5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
22 #include "modelprinter.h"
23 #include "multiprotocols.h"
25 #include "helpers_html.h"
26 #include "multiprotocols.h"
29 #include <QApplication>
33 #include <QTextStream>
37 QString
changeColor(const QString
& input
, const QString
& to
, const QString
& from
)
39 QString result
= input
;
40 return result
.replace("color="+from
, "color="+to
);
43 ModelPrinter::ModelPrinter(Firmware
* firmware
, const GeneralSettings
& generalSettings
, const ModelData
& model
):
45 generalSettings(generalSettings
),
50 ModelPrinter::~ModelPrinter()
54 QString
formatTitle(const QString
& name
)
56 return QString("<b>" + name
+ "</b> ");
59 void debugHtml(const QString
& html
)
61 QFile
file("foo.html");
62 file
.open(QIODevice::Truncate
| QIODevice::WriteOnly
);
63 file
.write(html
.toUtf8());
67 QString
addFont(const QString
& input
, const QString
& color
, const QString
& size
, const QString
& face
)
70 if (!color
.isEmpty()) {
71 colorStr
= "color=" + color
;
74 if (!size
.isEmpty()) {
75 sizeStr
= "size=" + size
;
78 if (!face
.isEmpty()) {
79 faceStr
= "face='" + face
+ "'";
81 return "<font " + sizeStr
+ " " + faceStr
+ " " + colorStr
+ ">" + input
+ "</font>";
84 QString
ModelPrinter::printLabelValue(const QString
& lbl
, const QString
& val
, const bool sep
) {
85 return QString("<b>%1:</b> %2%3 ").arg(lbl
, val
, (sep
? ";" : ""));
88 QString
ModelPrinter::printLabelValues(const QString
& lbl
, const QStringList
& vals
, const bool sep
) {
92 for (int i
=0;i
<vals
.count();i
++) {
93 str
.append(vals
.at(i
));
94 if (i
<(vals
.count()-1))
100 return printLabelValue(lbl
, str
, sep
);
103 #define MASK_TIMEVALUE_HRSMINS 1
104 #define MASK_TIMEVALUE_ZEROHRS 2
105 #define MASK_TIMEVALUE_PADSIGN 3
107 QString
ModelPrinter::printTimeValue(const int value
, const unsigned int mask
)
116 result
= (sign
< 0 ? QString("-") : ((mask
& MASK_TIMEVALUE_PADSIGN
) ? QString(" ") : QString("")));
117 if (mask
& MASK_TIMEVALUE_HRSMINS
) {
118 int hours
= val
/ 3600;
119 if (hours
> 0 || (mask
& MASK_TIMEVALUE_ZEROHRS
)) {
121 result
.append(QString("%1:").arg(hours
, 2, 10, QLatin1Char('0')));
124 int minutes
= val
/ 60;
125 int seconds
= val
% 60;
126 result
.append(QString("%1:%2").arg(minutes
, 2, 10, QLatin1Char('0')).arg(seconds
, 2, 10, QLatin1Char('0')));
130 #define BOOLEAN_ENABLEDISABLE 1
131 #define BOOLEAN_TRUEFALSE 2
132 #define BOOLEAN_YESNO 3
134 #define BOOLEAN_ONOFF 5
136 QString
ModelPrinter::printBoolean(const bool val
, const int typ
)
139 case BOOLEAN_ENABLEDISABLE
:
140 return (val
? tr("Enable") : tr("Disable"));
141 case BOOLEAN_TRUEFALSE
:
142 return (val
? tr("True") : tr("False"));
144 return (val
? tr("Yes") : tr("No"));
146 return (val
? tr("Y") : tr("N"));
148 return (val
? tr("ON") : tr("OFF"));
150 return CPN_STR_UNKNOWN_ITEM
;
154 QString
ModelPrinter::printEEpromSize()
156 return QString("%1 ").arg(getCurrentEEpromInterface()->getSize(model
)) + tr("bytes");
159 QString
ModelPrinter::printChannelName(int idx
)
161 QString str
= RawSource(SOURCE_TYPE_CH
, idx
).toString(&model
, &generalSettings
);
162 if (firmware
->getCapability(ChannelsName
)) {
163 str
= str
.leftJustified(firmware
->getCapability(ChannelsName
) + 5, ' ', false);
166 return str
.toHtmlEscaped();
169 QString
ModelPrinter::printTrimIncrementMode()
171 switch (model
.trimInc
) {
173 return tr("Exponential");
175 return tr("Extra Fine");
183 return tr("Unknown");
187 QString
ModelPrinter::printModule(int idx
)
191 ModuleData module
= model
.moduleData
[(idx
<0 ? CPN_MAX_MODULES
: idx
)];
193 str
<< printLabelValue(tr("Mode"), printTrainerMode());
194 if (IS_HORUS_OR_TARANIS(firmware
->getBoard())) {
195 if (model
.trainerMode
== TRAINER_SLAVE_JACK
) {
196 str
<< printLabelValue(tr("Channels"), QString("%1-%2").arg(module
.channelsStart
+ 1).arg(module
.channelsStart
+ module
.channelsCount
));
197 str
<< printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module
.ppm
.frameLength
)));
198 str
<< printLabelValue(tr("PPM delay"), QString("%1us").arg(module
.ppm
.delay
));
199 str
<< printLabelValue(tr("Polarity"), module
.polarityToString());
202 result
= str
.join(" ");
205 str
<< printLabelValue(tr("Protocol"), ModuleData::protocolToString(module
.protocol
));
206 if (module
.protocol
) {
207 str
<< printLabelValue(tr("Channels"), QString("%1-%2").arg(module
.channelsStart
+ 1).arg(module
.channelsStart
+ module
.channelsCount
));
208 if (module
.protocol
== PULSES_PPM
|| module
.protocol
== PULSES_SBUS
) {
209 str
<< printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module
.ppm
.frameLength
)));
210 str
<< printLabelValue(tr("Polarity"), module
.polarityToString());
211 if (module
.protocol
== PULSES_PPM
)
212 str
<< printLabelValue(tr("Delay"), QString("%1us").arg(module
.ppm
.delay
));
215 if (!(module
.protocol
== PULSES_PXX_XJT_D8
|| module
.protocol
== PULSES_CROSSFIRE
|| module
.protocol
== PULSES_SBUS
)) {
216 str
<< printLabelValue(tr("Receiver"), QString::number(module
.modelId
));
218 if (module
.protocol
== PULSES_MULTIMODULE
) {
219 str
<< printLabelValue(tr("Radio protocol"), module
.rfProtocolToString());
220 str
<< printLabelValue(tr("Subtype"), module
.subTypeToString());
221 str
<< printLabelValue(tr("Option value"), QString::number(module
.multi
.optionValue
));
223 if (module
.protocol
== PULSES_PXX_R9M
) {
224 str
<< printLabelValue(tr("Sub Type"), module
.subTypeToString());
225 str
<< printLabelValue(tr("RF Output Power"), module
.powerValueToString(firmware
));
229 result
= str
.join(" ");
230 if (((PulsesProtocol
)module
.protocol
== PulsesProtocol::PULSES_PXX_XJT_X16
|| (PulsesProtocol
)module
.protocol
== PulsesProtocol::PULSES_PXX_R9M
)
231 && firmware
->getCapability(HasFailsafe
))
232 result
.append("<br/>" + printFailsafe(idx
));
237 QString
ModelPrinter::printTrainerMode()
240 switch (model
.trainerMode
) {
241 case TRAINER_MASTER_JACK
:
242 result
= tr("Master/Jack");
244 case TRAINER_SLAVE_JACK
:
245 result
= tr("Slave/Jack");
247 case TRAINER_MASTER_SBUS_MODULE
:
248 result
= tr("Master/SBUS Module");
250 case TRAINER_MASTER_CPPM_MODULE
:
251 result
= tr("Master/CPPM Module");
253 case TRAINER_MASTER_SBUS_BATT_COMPARTMENT
:
254 result
= tr("Master/SBUS in battery compartment");
257 result
= CPN_STR_UNKNOWN_ITEM
;
262 QString
ModelPrinter::printHeliSwashType ()
264 switch (model
.swashRingData
.type
) {
265 case HELI_SWASH_TYPE_90
:
267 case HELI_SWASH_TYPE_120
:
269 case HELI_SWASH_TYPE_120X
:
271 case HELI_SWASH_TYPE_140
:
273 case HELI_SWASH_TYPE_NONE
:
276 return CPN_STR_UNKNOWN_ITEM
;
280 QString
ModelPrinter::printCenterBeep()
283 Board::Type board
= firmware
->getBoard();
284 int analogs
= CPN_MAX_STICKS
+ getBoardCapability(board
, Board::Pots
) + getBoardCapability(board
, Board::Sliders
);
286 for (int i
=0; i
< analogs
+ firmware
->getCapability(RotaryEncoders
); i
++) {
287 RawSource
src((i
< analogs
) ? SOURCE_TYPE_STICK
: SOURCE_TYPE_ROTARY_ENCODER
, (i
< analogs
) ? i
: analogs
- i
);
288 if (model
.beepANACenter
& (0x01 << i
)) {
289 strl
<< src
.toString(&model
, &generalSettings
);
293 return (strl
.isEmpty() ? tr("None") : strl
.join(" "));
296 QString
ModelPrinter::printTimer(int idx
)
298 return printTimer(model
.timers
[idx
]);
301 QString
ModelPrinter::printTimer(const TimerData
& timer
)
304 if (firmware
->getCapability(TimersName
) && timer
.name
[0])
305 result
+= tr("Name") + QString("(%1)").arg(timer
.name
);
306 result
+= printTimeValue(timer
.val
, MASK_TIMEVALUE_HRSMINS
| MASK_TIMEVALUE_ZEROHRS
);
307 result
+= timer
.mode
.toString();
308 if (timer
.countdownBeep
)
309 result
+= tr("Countdown") + QString("(%1)").arg(printTimerCountdownBeep(timer
.countdownBeep
));
310 if (timer
.minuteBeep
)
311 result
+= tr("Minute call");
312 if (timer
.persistent
)
313 result
+= tr("Persistent") + QString("(%1)").arg(printTimerPersistent(timer
.persistent
));
314 return result
.join(", ");
317 QString
ModelPrinter::printTrim(int flightModeIndex
, int stickIndex
)
319 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
321 if (fm
.trimMode
[stickIndex
] == -1) {
325 if (fm
.trimRef
[stickIndex
] == flightModeIndex
) {
326 return QString("%1").arg(fm
.trim
[stickIndex
]);
329 if (fm
.trimMode
[stickIndex
] == 0) {
330 return tr("FM%1").arg(fm
.trimRef
[stickIndex
]);
333 if (fm
.trim
[stickIndex
] < 0)
334 return tr("FM%1%2").arg(fm
.trimRef
[stickIndex
]).arg(fm
.trim
[stickIndex
]);
336 return tr("FM%1+%2").arg(fm
.trimRef
[stickIndex
]).arg(fm
.trim
[stickIndex
]);
342 QString
ModelPrinter::printGlobalVar(int flightModeIndex
, int gvarIndex
)
344 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
346 if (fm
.gvars
[gvarIndex
] <= 1024) {
347 return QString("%1").arg(fm
.gvars
[gvarIndex
] * model
.gvarData
[gvarIndex
].multiplierGet());
350 int num
= fm
.gvars
[gvarIndex
] - 1025;
351 if (num
>= flightModeIndex
) num
++;
352 return tr("FM%1").arg(num
);
356 QString
ModelPrinter::printRotaryEncoder(int flightModeIndex
, int reIndex
)
358 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
360 if (fm
.rotaryEncoders
[reIndex
] <= 1024) {
361 return QString("%1").arg(fm
.rotaryEncoders
[reIndex
]);
364 int num
= fm
.rotaryEncoders
[reIndex
] - 1025;
365 if (num
>= flightModeIndex
) num
++;
366 return tr("FM%1").arg(num
);
370 QString
ModelPrinter::printInputName(int idx
)
372 RawSourceType srcType
= (firmware
->getCapability(VirtualInputs
) ? SOURCE_TYPE_VIRTUAL_INPUT
: SOURCE_TYPE_STICK
);
373 return RawSource(srcType
, idx
).toString(&model
, &generalSettings
).toHtmlEscaped();
376 QString
ModelPrinter::printInputLine(int idx
)
378 return printInputLine(model
.expoData
[idx
]);
381 QString
ModelPrinter::printInputLine(const ExpoData
& input
)
383 QString str
= " ";
385 switch (input
.mode
) {
386 case (1): str
+= "<- "; break;
387 case (2): str
+= "-> "; break;
388 default: str
+= " "; break;
391 if (firmware
->getCapability(VirtualInputs
)) {
392 str
+= input
.srcRaw
.toString(&model
, &generalSettings
).toHtmlEscaped();
395 str
+= " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(Helpers::getAdjustmentString(input
.weight
, &model
, true).toHtmlEscaped());
396 if (input
.curve
.value
)
397 str
+= " " + input
.curve
.toString(&model
).toHtmlEscaped();
399 QString flightModesStr
= printFlightModes(input
.flightModes
);
400 if (!flightModesStr
.isEmpty())
401 str
+= " " + flightModesStr
.toHtmlEscaped();
403 if (input
.swtch
.type
!= SWITCH_TYPE_NONE
)
404 str
+= " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input
.swtch
.toString(getCurrentBoard(), &generalSettings
)).toHtmlEscaped();
407 if (firmware
->getCapability(VirtualInputs
)) {
408 if (input
.carryTrim
>0)
409 str
+= " " + tr("NoTrim").toHtmlEscaped();
410 else if (input
.carryTrim
<0)
411 str
+= " " + RawSource(SOURCE_TYPE_TRIM
, (-(input
.carryTrim
)-1)).toString(&model
, &generalSettings
).toHtmlEscaped();
415 str
+= " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(input
.offset
, &model
)).toHtmlEscaped();
417 if (firmware
->getCapability(HasExpoNames
) && input
.name
[0])
418 str
+= QString(" [%1]").arg(input
.name
).toHtmlEscaped();
423 QString
ModelPrinter::printMixerLine(const MixData
& mix
, bool showMultiplex
, int highlightedSource
)
425 QString str
= " ";
429 case (1): str
+= "*="; break;
430 case (2): str
+= ":="; break;
431 default: str
+= "+="; break;
435 str
+= " ";
437 // highlight source if needed
438 QString source
= mix
.srcRaw
.toString(&model
, &generalSettings
).toHtmlEscaped();
439 if ( (mix
.srcRaw
.type
== SOURCE_TYPE_CH
) && (mix
.srcRaw
.index
+1 == (int)highlightedSource
) ) {
440 source
= "<b>" + source
+ "</b>";
442 str
+= " " + source
;
444 if (mix
.mltpx
== MLTPX_MUL
&& !showMultiplex
)
445 str
+= " " + tr("MULT!").toHtmlEscaped();
447 str
+= " " + tr("Weight") + QString("(%1)").arg(Helpers::getAdjustmentString(mix
.weight
, &model
, true)).toHtmlEscaped();
449 QString flightModesStr
= printFlightModes(mix
.flightModes
);
450 if (!flightModesStr
.isEmpty())
451 str
+= " " + flightModesStr
.toHtmlEscaped();
453 if (mix
.swtch
.type
!= SWITCH_TYPE_NONE
)
454 str
+= " " + tr("Switch") + QString("(%1)").arg(mix
.swtch
.toString(getCurrentBoard(), &generalSettings
)).toHtmlEscaped();
456 if (mix
.carryTrim
> 0)
457 str
+= " " + tr("NoTrim").toHtmlEscaped();
458 else if (mix
.carryTrim
< 0)
459 str
+= " " + RawSource(SOURCE_TYPE_TRIM
, (-(mix
.carryTrim
)-1)).toString(&model
, &generalSettings
);
461 if (firmware
->getCapability(HasNoExpo
) && mix
.noExpo
)
462 str
+= " " + tr("No DR/Expo").toHtmlEscaped();
464 str
+= " " + tr("Offset") + QString("(%1)").arg(Helpers::getAdjustmentString(mix
.sOffset
, &model
)).toHtmlEscaped();
466 str
+= " " + mix
.curve
.toString(&model
).toHtmlEscaped();
467 int scale
= firmware
->getCapability(SlowScale
);
470 if (mix
.delayDown
|| mix
.delayUp
)
471 str
+= " " + tr("Delay") + QString("(u%1:d%2)").arg((double)mix
.delayUp
/scale
).arg((double)mix
.delayDown
/scale
).toHtmlEscaped();
472 if (mix
.speedDown
|| mix
.speedUp
)
473 str
+= " " + tr("Slow") + QString("(u%1:d%2)").arg((double)mix
.speedUp
/scale
).arg((double)mix
.speedDown
/scale
).toHtmlEscaped();
475 str
+= " " + tr("Warn") + QString("(%1)").arg(mix
.mixWarn
).toHtmlEscaped();
476 if (firmware
->getCapability(HasMixerNames
) && mix
.name
[0])
477 str
+= QString(" [%1]").arg(mix
.name
).toHtmlEscaped();
481 QString
ModelPrinter::printFlightModeSwitch(const RawSwitch
& swtch
)
483 return swtch
.toString(getCurrentBoard(), &generalSettings
);
486 QString
ModelPrinter::printFlightModeName(int index
)
488 return model
.flightModeData
[index
].nameToString(index
);
491 QString
ModelPrinter::printFlightModes(unsigned int flightModes
)
493 int numFlightModes
= firmware
->getCapability(FlightModes
);
494 if (numFlightModes
&& flightModes
) {
495 if (flightModes
== (unsigned int)(1<<numFlightModes
) - 1) {
496 return tr("Disabled in all flight modes");
500 for (int i
=0; i
<numFlightModes
; i
++) {
501 if (!(flightModes
& (1<<i
))) {
502 list
<< printFlightModeName(i
);
505 return (list
.size() > 1 ? tr("Flight modes") : tr("Flight mode")) + QString("(%1)").arg(list
.join(", "));
512 QString
ModelPrinter::printInputFlightModes(unsigned int flightModes
)
514 int numFlightModes
= firmware
->getCapability(FlightModes
);
515 if (numFlightModes
&& flightModes
) {
516 if (flightModes
== (unsigned int)(1<<numFlightModes
) - 1) {
521 for (int i
=0; i
<numFlightModes
; i
++) {
522 if (!(flightModes
& (1<<i
))) {
523 list
<< printFlightModeName(i
);
526 return QString("%1").arg(list
.join(" "));
533 QString
ModelPrinter::printLogicalSwitchLine(int idx
)
536 const LogicalSwitchData
& ls
= model
.logicalSw
[idx
];
537 const QString sw1Name
= RawSwitch(ls
.val1
).toString(getCurrentBoard(), &generalSettings
);
538 const QString sw2Name
= RawSwitch(ls
.val2
).toString(getCurrentBoard(), &generalSettings
);
546 switch (ls
.getFunctionFamily()) {
548 result
+= tr("Edge") + QString("(%1, [%2:%3])").arg(sw1Name
).arg(ValToTim(ls
.val2
)).arg(ls
.val3
<0 ? tr("instant") : QString("%1").arg(ValToTim(ls
.val2
+ls
.val3
)));
550 case LS_FAMILY_STICKY
:
551 result
+= tr("Sticky") + QString("(%1, %2)").arg(sw1Name
).arg(sw2Name
);
553 case LS_FAMILY_TIMER
:
554 result
+= tr("Timer") + QString("(%1, %2)").arg(ValToTim(ls
.val1
)).arg(ValToTim(ls
.val2
));
556 case LS_FAMILY_VOFS
: {
557 RawSource source
= RawSource(ls
.val1
);
558 RawSourceRange range
= source
.getRange(&model
, generalSettings
);
561 res
+= source
.toString(&model
, &generalSettings
);
565 if (ls
.func
== LS_FN_APOS
|| ls
.func
== LS_FN_ANEG
)
566 res
= "|" + res
+ "|";
567 else if (ls
.func
== LS_FN_DAPOS
)
568 res
= "|d(" + res
+ ")|";
569 else if (ls
.func
== LS_FN_DPOS
)
570 result
= "d(" + res
+ ")";
572 if (ls
.func
== LS_FN_VEQUAL
)
574 else if (ls
.func
== LS_FN_APOS
|| ls
.func
== LS_FN_VPOS
|| ls
.func
== LS_FN_DPOS
|| ls
.func
== LS_FN_DAPOS
)
576 else if (ls
.func
== LS_FN_ANEG
|| ls
.func
== LS_FN_VNEG
)
578 else if (ls
.func
== LS_FN_VALMOSTEQUAL
)
581 result
+= tr(" missing");
582 result
+= QString::number(range
.step
* (ls
.val2
/*TODO+ source.getRawOffset(model)*/) + range
.offset
);
585 case LS_FAMILY_VBOOL
:
604 case LS_FAMILY_VCOMP
:
606 result
+= RawSource(ls
.val1
).toString(&model
, &generalSettings
);
634 result
+= RawSource(ls
.val2
).toString(&model
, &generalSettings
);
642 result
+= RawSwitch(ls
.andsw
).toString(getCurrentBoard(), &generalSettings
);
645 if (firmware
->getCapability(LogicalSwitchesExt
)) {
647 result
+= " " + tr("Duration") + QString("(%1s)").arg(ls
.duration
/10.0);
649 result
+= " " + tr("Delay") + QString("(%1s)").arg(ls
.delay
/10.0);
655 QString
ModelPrinter::printCustomFunctionLine(int idx
, bool gfunc
)
658 CustomFunctionData cf
;
660 if (model
.noGlobalFunctions
)
662 cf
= generalSettings
.customFn
[idx
];
665 cf
= model
.customFn
[idx
];
666 if (cf
.swtch
.type
== SWITCH_TYPE_NONE
)
669 result
+= cf
.swtch
.toString(getCurrentBoard(), &generalSettings
) + " - ";
670 result
+= cf
.funcToString(&model
) + " (";
671 result
+= cf
.paramToString(&model
) + ")";
672 if (!cf
.repeatToString().isEmpty())
673 result
+= " " + cf
.repeatToString();
674 if (!cf
.enabledToString().isEmpty())
675 result
+= " " + cf
.enabledToString();
679 QString
ModelPrinter::printCurveName(int idx
)
681 return model
.curves
[idx
].nameToString(idx
).toHtmlEscaped();
684 QString
ModelPrinter::printCurve(int idx
)
687 const CurveData
& curve
= model
.curves
[idx
];
688 result
+= (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
) ? tr("Custom") : tr("Standard");
690 if (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
) {
691 for (int j
=0; j
<curve
.count
; j
++) {
694 result
+= QString("(%1, %2)").arg(curve
.points
[j
].x
).arg(curve
.points
[j
].y
);
698 for (int j
=0; j
<curve
.count
; j
++) {
701 result
+= QString("%1").arg(curve
.points
[j
].y
);
708 CurveImage::CurveImage():
710 image(size
+1, size
+1, QImage::Format_RGB32
),
713 painter
.setBrush(QBrush("#FFFFFF"));
714 painter
.setPen(QColor(0, 0, 0));
715 painter
.drawRect(0, 0, size
, size
);
717 painter
.setPen(QColor(0, 0, 0));
718 painter
.drawLine(0, size
/2, size
, size
/2);
719 painter
.drawLine(size
/2, 0, size
/2, size
);
720 for (int i
=0; i
<21; i
++) {
721 painter
.drawLine(size
/2-5, (size
*i
)/(20), size
/2+5, (size
*i
)/(20));
722 painter
.drawLine((size
*i
)/(20), size
/2-5, (size
*i
)/(20), size
/2+5);
726 void CurveImage::drawCurve(const CurveData
& curve
, QColor color
)
728 painter
.setPen(QPen(color
, 2, Qt::SolidLine
));
729 for (int j
=1; j
<curve
.count
; j
++) {
730 if (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
)
731 painter
.drawLine(size
/2+(size
*curve
.points
[j
-1].x
)/200, size
/2-(size
*curve
.points
[j
-1].y
)/200, size
/2+(size
*curve
.points
[j
].x
)/200, size
/2-(size
*curve
.points
[j
].y
)/200);
733 painter
.drawLine(size
*(j
-1)/(curve
.count
-1), size
/2-(size
*curve
.points
[j
-1].y
)/200, size
*(j
)/(curve
.count
-1), size
/2-(size
*curve
.points
[j
].y
)/200);
737 QString
ModelPrinter::createCurveImage(int idx
, QTextDocument
* document
)
740 image
.drawCurve(model
.curves
[idx
], colors
[idx
]);
741 QString filename
= QString("mydata://curve-%1-%2.png").arg((uint64_t)this).arg(idx
);
743 document
->addResource(QTextDocument::ImageResource
, QUrl(filename
), image
.get());
744 // qDebug() << "ModelPrinter::createCurveImage()" << idx << filename;
748 QString
ModelPrinter::printGlobalVarUnit(int idx
)
750 return model
.gvarData
[idx
].unitToString().toHtmlEscaped();
753 QString
ModelPrinter::printGlobalVarPrec(int idx
)
755 return model
.gvarData
[idx
].precToString().toHtmlEscaped();
758 QString
ModelPrinter::printGlobalVarMin(int idx
)
760 return QString::number(model
.gvarData
[idx
].getMinPrec());
763 QString
ModelPrinter::printGlobalVarMax(int idx
)
765 return QString::number(model
.gvarData
[idx
].getMaxPrec());
768 QString
ModelPrinter::printGlobalVarPopup(int idx
)
770 return printBoolean(model
.gvarData
[idx
].popup
, BOOLEAN_YN
);
773 QString
ModelPrinter::printOutputValueGVar(int val
)
776 if (abs(val
) > 10000) {
779 result
.append(RawSource(SOURCE_TYPE_GVAR
, abs(val
)-10001).toString(&model
));
784 result
.append(QString::number((qreal
)val
/10, 'f', 1) + "%");
789 QString
ModelPrinter::printOutputOffset(int idx
)
791 return printOutputValueGVar(model
.limitData
[idx
].offset
);
794 QString
ModelPrinter::printOutputMin(int idx
)
796 return printOutputValueGVar(model
.limitData
[idx
].min
);
799 QString
ModelPrinter::printOutputMax(int idx
)
801 return printOutputValueGVar(model
.limitData
[idx
].max
);
804 QString
ModelPrinter::printOutputRevert(int idx
)
806 return model
.limitData
[idx
].revertToString();
809 QString
ModelPrinter::printOutputPpmCenter(int idx
)
811 return QString::number(model
.limitData
[idx
].ppmCenter
+ 1500);
814 QString
ModelPrinter::printOutputCurve(int idx
)
816 return CurveReference(CurveReference::CURVE_REF_CUSTOM
, model
.limitData
[idx
].curve
.value
).toString(&model
, false);
819 QString
ModelPrinter::printOutputSymetrical(int idx
)
821 return printBoolean(model
.limitData
[idx
].symetrical
, BOOLEAN_YN
);
824 QString
ModelPrinter::printSettingsOther()
827 str
<< printLabelValue(tr("Extended Limits"), printBoolean(model
.extendedLimits
, BOOLEAN_YESNO
));
828 if (firmware
->getCapability(HasDisplayText
))
829 str
<< printLabelValue(tr("Display Checklist"), printBoolean(model
.displayChecklist
, BOOLEAN_YESNO
));
830 if (firmware
->getCapability(GlobalFunctions
))
831 str
<< printLabelValue(tr("Global Functions"), printBoolean(!model
.noGlobalFunctions
, BOOLEAN_YESNO
));
832 return str
.join(" ");
835 QString
ModelPrinter::printSwitchWarnings()
838 Boards board
= firmware
->getBoard();
839 uint64_t switchStates
= model
.switchWarningStates
;
842 for (int idx
=0; idx
<board
.getCapability(Board::Switches
); idx
++) {
843 Board::SwitchInfo switchInfo
= Boards::getSwitchInfo(board
.getBoardType(), idx
);
844 switchInfo
.config
= Board::SwitchType(generalSettings
.switchConfig
[idx
]);
845 if (switchInfo
.config
== Board::SWITCH_NOT_AVAILABLE
|| switchInfo
.config
== Board::SWITCH_TOGGLE
) {
848 if (!(model
.switchWarningEnable
& (1 << idx
))) {
849 if (IS_HORUS_OR_TARANIS(board
.getBoardType())) {
850 value
= (switchStates
>> (2*idx
)) & 0x03;
853 value
= (idx
==0 ? switchStates
& 0x3 : switchStates
& 0x1);
854 switchStates
>>= (idx
==0 ? 2 : 1);
856 str
+= RawSwitch(SWITCH_TYPE_SWITCH
, 1+idx
*3+value
).toString(board
.getBoardType(), &generalSettings
, &model
);
859 return (str
.isEmpty() ? tr("None") : str
.join(" ")) ;
862 QString
ModelPrinter::printPotWarnings()
866 Boards board
= firmware
->getBoard();
867 if (model
.potsWarningMode
) {
868 for (int i
=0; i
<board
.getCapability(Board::Pots
)+board
.getCapability(Board::Sliders
); i
++) {
869 RawSource
src(SOURCE_TYPE_STICK
, CPN_MAX_STICKS
+ i
);
870 if ((src
.isPot(&genAryIdx
) && generalSettings
.isPotAvailable(genAryIdx
)) || (src
.isSlider(&genAryIdx
) && generalSettings
.isSliderAvailable(genAryIdx
))) {
871 if (!model
.potsWarnEnabled
[i
])
872 str
+= src
.toString(&model
, &generalSettings
);
876 str
<< printLabelValue(tr("Mode"), printPotsWarningMode());
877 return str
.join(" ");
880 QString
ModelPrinter::printPotsWarningMode()
882 switch (model
.potsWarningMode
) {
890 return CPN_STR_UNKNOWN_ITEM
;
894 QString
ModelPrinter::printFailsafe(int idx
)
897 ModuleData module
= model
.moduleData
[idx
];
898 strl
<< printLabelValue(tr("Failsafe Mode"), printFailsafeMode(module
.failsafeMode
));
899 if (module
.failsafeMode
== FAILSAFE_CUSTOM
) {
900 for (int i
=0; i
<module
.channelsCount
; i
++) {
901 //strl << QString("%1(%2)").arg(printChannelName(module.channelsStart + i).trimmed()).arg(printFailsafeValue(module.failsafeChannels[i]));
902 strl
<< printLabelValue(printChannelName(module
.channelsStart
+ i
).trimmed(), printFailsafeValue(module
.failsafeChannels
[i
]));
905 return strl
.join(" ");
908 QString
ModelPrinter::printFailsafeValue(int val
)
914 return tr("No Pulse");
916 return QString("%1%").arg(QString::number(divRoundClosest(val
* 1000, 1024) / 10.0));
920 QString
ModelPrinter::printFailsafeMode(unsigned int fsmode
)
923 case FAILSAFE_NOT_SET
:
924 return tr("Not set");
927 case FAILSAFE_CUSTOM
:
929 case FAILSAFE_NOPULSES
:
930 return tr("No pulses");
931 case FAILSAFE_RECEIVER
:
932 return tr("Receiver");
934 return CPN_STR_UNKNOWN_ITEM
;
938 QString
ModelPrinter::printTimerCountdownBeep(unsigned int countdownBeep
)
940 switch (countdownBeep
) {
941 case TimerData::COUNTDOWN_SILENT
:
943 case TimerData::COUNTDOWN_BEEPS
:
945 case TimerData::COUNTDOWN_VOICE
:
947 case TimerData::COUNTDOWN_HAPTIC
:
950 return CPN_STR_UNKNOWN_ITEM
;
954 QString
ModelPrinter::printTimerPersistent(unsigned int persistent
)
956 switch (persistent
) {
962 return tr("Manual reset");
964 return CPN_STR_UNKNOWN_ITEM
;
968 QString
ModelPrinter::printSettingsTrim()
971 str
<< printLabelValue(tr("Step"), printTrimIncrementMode());
972 if (IS_ARM(firmware
->getBoard()))
973 str
<< printLabelValue(tr("Display"), printTrimsDisplayMode());
974 str
<< printLabelValue(tr("Extended"), printBoolean(model
.extendedTrims
, BOOLEAN_YESNO
));
975 return str
.join(" ");
978 QString
ModelPrinter::printThrottleSource(int idx
)
980 Boards board
= firmware
->getBoard();
981 int chnstart
= board
.getCapability(Board::Pots
)+board
.getCapability(Board::Sliders
);
984 else if (idx
< (chnstart
+1))
985 return firmware
->getAnalogInputName(idx
+board
.getCapability(Board::Sticks
)-1);
987 return RawSource(SOURCE_TYPE_CH
, idx
-chnstart
-1).toString(&model
, &generalSettings
);
990 QString
ModelPrinter::printTrimsDisplayMode()
992 switch (model
.trimsDisplay
) {
996 return tr("On Change");
1000 return CPN_STR_UNKNOWN_ITEM
;
1004 QString
ModelPrinter::printModuleType(int idx
)
1006 return ModuleData::indexToString(idx
, firmware
);
1009 QString
ModelPrinter::printPxxPower(int power
)
1011 static const char *strings
[] = {
1012 "10mW", "100mW", "500mW", "3W"
1014 return CHECK_IN_ARRAY(strings
, power
);
1017 QString
ModelPrinter::printThrottle()
1020 result
<< printLabelValue(tr("Source"), printThrottleSource(model
.thrTraceSrc
));
1021 result
<< printLabelValue(tr("Trim idle only"), printBoolean(model
.thrTrim
, BOOLEAN_YESNO
));
1022 result
<< printLabelValue(tr("Warning"), printBoolean(!model
.disableThrottleWarning
, BOOLEAN_YESNO
));
1023 result
<< printLabelValue(tr("Reversed"), printBoolean(model
.throttleReversed
, BOOLEAN_YESNO
));
1024 return result
.join(" ");
1027 QString
ModelPrinter::printPPMFrameLength(int ppmFL
)
1029 double result
= (((double)ppmFL
* 5) + 225) / 10;
1030 return QString::number(result
);
1033 QString
ModelPrinter::printTimerName(int idx
)
1036 result
= tr("Tmr") + QString("%1").arg(idx
+1);
1037 if (firmware
->getCapability(TimersName
) && model
.timers
[idx
].name
[0])
1038 result
.append(":" + QString(model
.timers
[idx
].name
));
1043 QString
ModelPrinter::printTimerTimeValue(unsigned int val
)
1045 return printTimeValue(val
, MASK_TIMEVALUE_HRSMINS
| MASK_TIMEVALUE_ZEROHRS
);
1048 QString
ModelPrinter::printTimerMinuteBeep(bool mb
)
1050 return printBoolean(mb
, BOOLEAN_YESNO
);
1053 QString
ModelPrinter::printTelemetryProtocol(unsigned int val
)
1057 return tr("FrSky S.PORT");
1059 return tr("FrSky D");
1061 return tr("FrSky D (cable)");
1063 return CPN_STR_UNKNOWN_ITEM
;
1067 QString
ModelPrinter::printRssiAlarmsDisabled(bool mb
)
1069 return printBoolean(!mb
, BOOLEAN_ENABLEDISABLE
);
1072 QString
ModelPrinter::printTelemetrySource(int val
)
1074 QStringList strings
= QStringList() << tr("None");
1076 for (unsigned i
=1; i
<=CPN_MAX_SENSORS
; ++i
) {
1077 strings
<< QString("%1").arg(model
.sensorData
[i
-1].label
);
1080 return QString("%1%2").arg((val
< 0 ? "-" : "")).arg(strings
.value(abs(val
)));
1083 QString
ModelPrinter::printVarioSource(unsigned int val
)
1086 case TELEMETRY_VARIO_SOURCE_ALTI
:
1088 case TELEMETRY_VARIO_SOURCE_ALTI_PLUS
:
1090 case TELEMETRY_VARIO_SOURCE_VSPEED
:
1091 return tr("VSpeed");
1092 case TELEMETRY_VARIO_SOURCE_A1
:
1094 case TELEMETRY_VARIO_SOURCE_A2
:
1097 return CPN_STR_UNKNOWN_ITEM
;
1101 QString
ModelPrinter::printVarioCenterSilent(bool mb
)
1103 return printBoolean(mb
, BOOLEAN_YESNO
);
1106 QString
ModelPrinter::printVoltsSource(unsigned int val
)
1109 case TELEMETRY_VOLTS_SOURCE_A1
:
1111 case TELEMETRY_VOLTS_SOURCE_A2
:
1113 case TELEMETRY_VOLTS_SOURCE_A3
:
1115 case TELEMETRY_VOLTS_SOURCE_A4
:
1117 case TELEMETRY_VOLTS_SOURCE_FAS
:
1119 case TELEMETRY_VOLTS_SOURCE_CELLS
:
1122 return CPN_STR_UNKNOWN_ITEM
;
1126 QString
ModelPrinter::printCurrentSource(unsigned int val
)
1129 case TELEMETRY_CURRENT_SOURCE_NONE
:
1131 case TELEMETRY_CURRENT_SOURCE_A1
:
1133 case TELEMETRY_CURRENT_SOURCE_A2
:
1135 case TELEMETRY_CURRENT_SOURCE_A3
:
1137 case TELEMETRY_CURRENT_SOURCE_A4
:
1139 case TELEMETRY_CURRENT_SOURCE_FAS
:
1142 return CPN_STR_UNKNOWN_ITEM
;
1146 QString
ModelPrinter::printMahPersistent(bool mb
)
1148 return printBoolean(mb
, BOOLEAN_YESNO
);
1151 QString
ModelPrinter::printIgnoreSensorIds(bool mb
)
1153 return printBoolean(mb
, BOOLEAN_ENABLEDISABLE
);
1156 QString
ModelPrinter::printSensorType(unsigned int val
)
1159 case SensorData::TELEM_TYPE_CUSTOM
:
1160 return tr("Custom");
1161 case SensorData::TELEM_TYPE_CALCULATED
:
1162 return tr("Calculated");
1164 return CPN_STR_UNKNOWN_ITEM
;
1168 QString
ModelPrinter::printSensorFormula(unsigned int val
)
1171 case SensorData::TELEM_FORMULA_ADD
:
1173 case SensorData::TELEM_FORMULA_AVERAGE
:
1174 return tr("Average");
1175 case SensorData::TELEM_FORMULA_MIN
:
1177 case SensorData::TELEM_FORMULA_MAX
:
1179 case SensorData::TELEM_FORMULA_MULTIPLY
:
1180 return tr("Multiply");
1181 case SensorData::TELEM_FORMULA_TOTALIZE
:
1182 return tr("Totalise");
1183 case SensorData::TELEM_FORMULA_CELL
:
1185 case SensorData::TELEM_FORMULA_CONSUMPTION
:
1186 return tr("Consumption");
1187 case SensorData::TELEM_FORMULA_DIST
:
1188 return tr("Distance");
1190 return CPN_STR_UNKNOWN_ITEM
;
1194 QString
ModelPrinter::printSensorCells(unsigned int val
)
1196 QStringList strings
;
1198 strings
<< tr("Lowest");
1199 for (int i
=1; i
<=6; i
++)
1200 strings
<< tr("Cell %1").arg(i
);
1201 strings
<< tr("Highest") << tr("Delta");
1203 return strings
.value(val
);
1206 QString
ModelPrinter::printSensorTypeCond(unsigned int idx
)
1208 if (!model
.sensorData
[idx
].isAvailable())
1211 return printSensorType(model
.sensorData
[idx
].type
);
1214 QString
ModelPrinter::printSensorDetails(unsigned int idx
)
1217 SensorData sensor
= model
.sensorData
[idx
];
1219 if (!sensor
.isAvailable())
1222 bool isConfigurable
= false;
1223 bool gpsFieldsPrinted
= false;
1224 bool cellsFieldsPrinted
= false;
1225 bool consFieldsPrinted
= false;
1226 bool ratioFieldsPrinted
= false;
1227 bool totalizeFieldsPrinted
= false;
1228 bool sources12FieldsPrinted
= false;
1229 bool sources34FieldsPrinted
= false;
1231 str
.append(doTableCell(printSensorTypeCond(idx
)));
1234 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
) {
1235 isConfigurable
= (sensor
.formula
< SensorData::TELEM_FORMULA_CELL
);
1236 gpsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
);
1237 cellsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
);
1238 consFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
);
1239 sources12FieldsPrinted
= (sensor
.formula
<= SensorData::TELEM_FORMULA_MULTIPLY
);
1240 sources34FieldsPrinted
= (sensor
.formula
< SensorData::TELEM_FORMULA_MULTIPLY
);
1241 totalizeFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
);
1243 tc
.append(printLabelValue(tr("Formula"), printSensorFormula(sensor
.formula
)));
1246 isConfigurable
= sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
;
1247 ratioFieldsPrinted
= (sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
);
1249 tc
.append(printLabelValue(tr("Id"), QString::number(sensor
.id
,16).toUpper()));
1250 tc
.append(printLabelValue(tr("Instance"), QString::number(sensor
.instance
)));
1252 if (cellsFieldsPrinted
) {
1253 tc
.append(printLabelValue(tr("Sensor"), QString("%1 > %2").arg(printTelemetrySource(sensor
.source
), false).arg(printSensorCells(sensor
.index
))));
1255 if (sources12FieldsPrinted
) {
1257 for (int i
=0;i
<4;i
++) {
1258 if (i
< 2 || sources34FieldsPrinted
) {
1259 srcs
<< printTelemetrySource(sensor
.sources
[i
]);
1262 tc
.append(printLabelValues(tr("Sources"), srcs
));
1264 if (consFieldsPrinted
|| totalizeFieldsPrinted
)
1265 tc
.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor
.amps
)));
1266 if (gpsFieldsPrinted
) {
1267 tc
.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor
.gps
)));
1268 tc
.append(printLabelValue(tr("Alt."), printTelemetrySource(sensor
.alt
)));
1270 if (ratioFieldsPrinted
&& sensor
.unit
== SensorData::UNIT_RPMS
) {
1271 tc
.append(printLabelValue(tr("Blades"), QString::number(sensor
.ratio
)));
1272 tc
.append(printLabelValue(tr("Multi."), QString::number(sensor
.offset
)));
1274 str
.append(doTableCell(tc
));
1276 tc
= sensor
.unitString();
1277 tc
= tc
.trimmed() == "" ? "-" : tc
;
1278 str
.append(doTableCell(tc
));
1280 if (isConfigurable
&& sensor
.unit
!= SensorData::UNIT_FAHRENHEIT
)
1281 tc
= QString::number(sensor
.prec
);
1284 str
.append(doTableCell(tc
));
1286 if (!ratioFieldsPrinted
) {
1287 str
.append(doTableCell(""));
1288 str
.append(doTableCell(""));
1290 else if (sensor
.unit
!= SensorData::UNIT_RPMS
) {
1291 int prec
= sensor
.prec
== 0 ? 1 : pow(10, sensor
.prec
);
1292 str
.append(doTableCell(QString::number((float)sensor
.ratio
/ prec
)));
1293 str
.append(doTableCell(QString::number((float)sensor
.offset
/ prec
)));
1296 if (sensor
.unit
!= SensorData::UNIT_RPMS
&& isConfigurable
)
1297 str
.append(doTableCell(printBoolean(sensor
.autoOffset
, BOOLEAN_YN
)));
1299 str
.append(doTableCell(""));
1302 str
.append(doTableCell(printBoolean(sensor
.filter
, BOOLEAN_YN
)));
1304 str
.append(doTableCell(""));
1306 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
)
1307 str
.append(doTableCell(printBoolean(sensor
.persistent
, BOOLEAN_YN
)));
1309 str
.append(doTableCell(""));
1311 str
.append(doTableCell(printBoolean(sensor
.onlyPositive
, BOOLEAN_YN
)));
1312 str
.append(doTableCell(printBoolean(sensor
.logs
, BOOLEAN_YN
), false));
1316 QString
ModelPrinter::printSensorParams(unsigned int idx
)
1319 SensorData sensor
= model
.sensorData
[idx
];
1321 if (!sensor
.isAvailable())
1324 bool isConfigurable
= false;
1325 bool gpsFieldsPrinted
= false;
1326 bool cellsFieldsPrinted
= false;
1327 bool consFieldsPrinted
= false;
1328 bool ratioFieldsPrinted
= false;
1329 bool totalizeFieldsPrinted
= false;
1330 bool sources12FieldsPrinted
= false;
1331 bool sources34FieldsPrinted
= false;
1333 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
) {
1334 isConfigurable
= (sensor
.formula
< SensorData::TELEM_FORMULA_CELL
);
1335 gpsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
);
1336 cellsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
);
1337 consFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
);
1338 sources12FieldsPrinted
= (sensor
.formula
<= SensorData::TELEM_FORMULA_MULTIPLY
);
1339 sources34FieldsPrinted
= (sensor
.formula
< SensorData::TELEM_FORMULA_MULTIPLY
);
1340 totalizeFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
);
1342 str
.append(printLabelValue(tr("F"), printSensorFormula(sensor
.formula
)));
1345 isConfigurable
= sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
;
1346 ratioFieldsPrinted
= (sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
);
1348 str
.append(printLabelValue(tr("Id"), QString::number(sensor
.id
,16).toUpper()));
1349 str
.append(printLabelValue(tr("Inst"), QString::number(sensor
.instance
)));
1351 if (cellsFieldsPrinted
) {
1352 str
.append(printLabelValue(tr("Sensor"), QString("%1 %2").arg(printTelemetrySource(sensor
.source
), false).arg(printSensorCells(sensor
.index
))));
1354 if (sources12FieldsPrinted
) {
1356 for (int i
=0;i
<4;i
++) {
1357 if (i
< 2 || sources34FieldsPrinted
) {
1358 srcs
<< printTelemetrySource(sensor
.sources
[i
]);
1361 str
.append(printLabelValues(tr("Sources"), srcs
));
1363 if (consFieldsPrinted
|| totalizeFieldsPrinted
)
1364 str
.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor
.amps
)));
1365 if (gpsFieldsPrinted
) {
1366 str
.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor
.gps
)));
1367 str
.append(printLabelValue(tr("Alt"), printTelemetrySource(sensor
.alt
)));
1369 QString u
= sensor
.unitString();
1370 u
= u
.trimmed() == "" ? "-" : u
;
1371 str
.append(printLabelValue(tr("Unit"), u
));
1372 if (isConfigurable
&& sensor
.unit
!= SensorData::UNIT_FAHRENHEIT
)
1373 str
.append(printLabelValue(tr("Prec"), QString::number(sensor
.prec
)));
1374 if (ratioFieldsPrinted
) {
1375 if (sensor
.unit
!= SensorData::UNIT_RPMS
) {
1376 int prec
= sensor
.prec
== 0 ? 1 : pow(10, sensor
.prec
);
1377 str
.append(printLabelValue(tr("Ratio"), QString::number((float)sensor
.ratio
/ prec
)));
1378 str
.append(printLabelValue(tr("Offset"), QString::number((float)sensor
.offset
/ prec
)));
1380 else if (sensor
.unit
== SensorData::UNIT_RPMS
) {
1381 str
.append(printLabelValue(tr("Blades"), QString::number(sensor
.ratio
)));
1382 str
.append(printLabelValue(tr("Multi"), QString::number(sensor
.offset
)));
1385 if (sensor
.unit
!= SensorData::UNIT_RPMS
&& isConfigurable
)
1386 str
.append(printLabelValue(tr("A/Offset"), printBoolean(sensor
.autoOffset
, BOOLEAN_YN
)));
1388 str
.append(printLabelValue(tr("Filter"), printBoolean(sensor
.filter
, BOOLEAN_YN
)));
1389 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
)
1390 str
.append(printLabelValue(tr("Persist"), printBoolean(sensor
.persistent
, BOOLEAN_YN
)));
1391 str
.append(printLabelValue(tr("Positive"), printBoolean(sensor
.onlyPositive
, BOOLEAN_YN
)));
1392 str
.append(printLabelValue(tr("Log"), printBoolean(sensor
.logs
, BOOLEAN_YN
), false));
1396 QString
ModelPrinter::printTelemetryScreenType(unsigned int val
)
1399 case TelemetryScreenEnum::TELEMETRY_SCREEN_NONE
:
1401 case TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS
:
1402 return tr("Numbers");
1403 case TelemetryScreenEnum::TELEMETRY_SCREEN_BARS
:
1405 case TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT
:
1406 return tr("Script");
1408 return CPN_STR_UNKNOWN_ITEM
;
1412 QString
ModelPrinter::printTelemetryScreen(unsigned int idx
, unsigned int line
, unsigned int width
)
1416 FrSkyScreenData screen
= model
.frsky
.screens
[idx
];
1417 hd
<< ""; // blank 1st column
1419 if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS
) {
1421 for (int c
=0; c
<firmware
->getCapability(TelemetryCustomScreensFieldsPerLine
); c
++) {
1425 for (int c
=0; c
<firmware
->getCapability(TelemetryCustomScreensFieldsPerLine
); c
++) {
1426 RawSource source
= screen
.body
.lines
[line
].source
[c
];
1427 strl
<< source
.toString(&model
, &generalSettings
);
1430 else if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_BARS
) {
1432 hd
<< tr("Source") << tr("Min") << tr("Max");
1434 RawSource source
= screen
.body
.bars
[line
].source
;
1435 RawSourceRange range
= source
.getRange(&model
, generalSettings
);
1436 strl
<< source
.toString(&model
, &generalSettings
);
1440 if (source
.isTimeBased()){
1441 minstr
= printTimeValue((float)screen
.body
.bars
[line
].barMin
, MASK_TIMEVALUE_HRSMINS
);
1442 maxstr
= printTimeValue((float)screen
.body
.bars
[line
].barMax
, MASK_TIMEVALUE_HRSMINS
);
1445 minstr
= QString::number(range
.getValue(screen
.body
.bars
[line
].barMin
));
1446 maxstr
= QString::number(range
.getValue(screen
.body
.bars
[line
].barMax
));
1449 strl
<< QString("%1%2").arg(minstr
).arg(unit
);
1450 strl
<< QString("%1%2").arg(maxstr
).arg(unit
);
1452 else if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT
&& line
== 0) {
1453 hd
<< tr("Filename");
1454 strl
<< QString("%1.lua").arg(screen
.body
.script
.filename
);
1456 return (hd
.count() > 1 ? doTableRow(hd
, width
/ hd
.count(), "left", "", true) : "" ) + doTableRow(strl
, width
/ strl
.count());
1459 QString
ModelPrinter::printChecklist()
1461 if (!model
.displayChecklist
)
1463 QString str
= tr("Error: Unable to open or read file!");
1464 QFile
file(Helpers::getChecklistFilePath(&model
));
1465 if (file
.open(QFile::ReadOnly
| QFile::Text
)) {
1466 QTextStream
in(&file
);
1467 if (in
.status() == QTextStream::Ok
) {
1469 str
.replace("\n", "<br />");