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"
28 #include <QApplication>
33 QString
changeColor(const QString
& input
, const QString
& to
, const QString
& from
)
35 QString result
= input
;
36 return result
.replace("color="+from
, "color="+to
);
39 ModelPrinter::ModelPrinter(Firmware
* firmware
, const GeneralSettings
& generalSettings
, const ModelData
& model
):
41 generalSettings(generalSettings
),
46 ModelPrinter::~ModelPrinter()
50 QString
formatTitle(const QString
& name
)
52 return QString("<b>" + name
+ "</b> ");
55 void debugHtml(const QString
& html
)
57 QFile
file("foo.html");
58 file
.open(QIODevice::Truncate
| QIODevice::WriteOnly
);
59 file
.write(html
.toUtf8());
63 QString
addFont(const QString
& input
, const QString
& color
, const QString
& size
, const QString
& face
)
66 if (!color
.isEmpty()) {
67 colorStr
= "color=" + color
;
70 if (!size
.isEmpty()) {
71 sizeStr
= "size=" + size
;
74 if (!face
.isEmpty()) {
75 faceStr
= "face='" + face
+ "'";
77 return "<font " + sizeStr
+ " " + faceStr
+ " " + colorStr
+ ">" + input
+ "</font>";
80 QString
ModelPrinter::printLabelValue(const QString
& lbl
, const QString
& val
, const bool sep
) {
81 return QString("<b>%1:</b> %2%3 ").arg(lbl
, val
, (sep
? ";" : ""));
84 QString
ModelPrinter::printLabelValues(const QString
& lbl
, const QStringList
& vals
, const bool sep
) {
88 for (int i
=0;i
<vals
.count();i
++) {
89 str
.append(vals
.at(i
));
90 if (i
<(vals
.count()-1))
96 return printLabelValue(lbl
, str
, sep
);
99 #define MASK_TIMEVALUE_HRSMINS 1
100 #define MASK_TIMEVALUE_ZEROHRS 2
101 #define MASK_TIMEVALUE_PADSIGN 3
103 QString
ModelPrinter::printTimeValue(const int value
, const unsigned int mask
)
112 result
= (sign
< 0 ? QString("-") : ((mask
& MASK_TIMEVALUE_PADSIGN
) ? QString(" ") : QString("")));
113 if (mask
& MASK_TIMEVALUE_HRSMINS
) {
114 int hours
= val
/ 3600;
115 if (hours
> 0 || (mask
& MASK_TIMEVALUE_ZEROHRS
)) {
117 result
.append(QString("%1:").arg(hours
, 2, 10, QLatin1Char('0')));
120 int minutes
= val
/ 60;
121 int seconds
= val
% 60;
122 result
.append(QString("%1:%2").arg(minutes
, 2, 10, QLatin1Char('0')).arg(seconds
, 2, 10, QLatin1Char('0')));
126 #define BOOLEAN_ENABLEDISABLE 1
127 #define BOOLEAN_TRUEFALSE 2
128 #define BOOLEAN_YESNO 3
130 #define BOOLEAN_ONOFF 5
132 QString
ModelPrinter::printBoolean(const bool val
, const int typ
)
135 case BOOLEAN_ENABLEDISABLE
:
136 return (val
? tr("Enable") : tr("Disable"));
137 case BOOLEAN_TRUEFALSE
:
138 return (val
? tr("True") : tr("False"));
140 return (val
? tr("Yes") : tr("No"));
142 return (val
? tr("Y") : tr("N"));
144 return (val
? tr("ON") : tr("OFF"));
150 QString
ModelPrinter::printEEpromSize()
152 return QString("%1 ").arg(getCurrentEEpromInterface()->getSize(model
)) + tr("bytes");
155 QString
ModelPrinter::printChannelName(int idx
)
157 QString str
= RawSource(SOURCE_TYPE_CH
, idx
).toString(&model
, &generalSettings
);
158 if (firmware
->getCapability(ChannelsName
)) {
159 str
= str
.leftJustified(firmware
->getCapability(ChannelsName
) + 5, ' ', false);
162 return str
.toHtmlEscaped();
165 QString
ModelPrinter::printTrimIncrementMode()
167 switch (model
.trimInc
) {
169 return tr("Exponential");
171 return tr("Extra Fine");
179 return tr("Unknown");
183 QString
ModelPrinter::printModuleProtocol(unsigned int protocol
)
185 static const char * strings
[] = {
188 "Silverlit A", "Silverlit B", "Silverlit C",
190 "LP45", "DSM2", "DSMX",
192 "FrSky XJT (D16)", "FrSky XJT (D8)", "FrSky XJT (LR12)", "FrSky DJT",
194 "DIY Multiprotocol Module",
196 "SBUS output at VBat"
199 return CHECK_IN_ARRAY(strings
, protocol
);
202 QString
ModelPrinter::printMultiRfProtocol(int rfProtocol
, bool custom
)
204 static const char * strings
[] = {
205 "FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
206 "Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","OLRS",
207 "FlySky AFHDS2A", "Q2x2", "Walkera", "Q303", "GW008", "DM002", "CABELL", "Esky 150", "H8 3D", "Corona", "CFlie"
210 return QObject::tr("Custom - proto %1)").arg(QString::number(rfProtocol
));
212 return CHECK_IN_ARRAY(strings
, rfProtocol
);
215 QString
ModelPrinter::printMultiSubType(unsigned rfProtocol
, bool custom
, unsigned int subType
) {
216 /* custom protocols */
219 rfProtocol
= MM_RF_CUSTOM_SELECTED
;
221 Multiprotocols::MultiProtocolDefinition pdef
= multiProtocols
.getProtocol(rfProtocol
);
223 if (subType
< (unsigned int) pdef
.subTypeStrings
.size())
224 return qApp
->translate("Multiprotocols", qPrintable(pdef
.subTypeStrings
[subType
]));
229 QString
ModelPrinter::printR9MPowerValue(unsigned subType
, unsigned val
, bool telem
)
234 if (IS_TARANIS_XLITE(firmware
->getBoard())) {
235 strFCC
= QStringList() << tr("100mW - 16CH");
236 strLBT
= QStringList() << tr("25mW - 8CH") << tr("25mW - 16CH") << tr("100mW 16CH");
239 strFCC
= QStringList() << tr("10mW") << tr("100mW") << tr("500mW") << tr("1W");
240 strLBT
= QStringList() << tr("25mW - 8CH") << tr("25mW - 16CH") << tr("200mW 16CH") << tr("500mW 16CH");
244 if (subType
== R9M_FCC
&& (int)val
< strFCC
.size())
245 return strFCC
.at(val
);
246 else if (subType
== R9M_LBT
)
247 return (telem
? strLBT
.at(0) : strLBT
.at(1));
252 QString
ModelPrinter::printModuleSubType(unsigned protocol
, unsigned subType
, unsigned rfProtocol
, bool custom
)
254 static const char * strings
[] = {
260 case PULSES_MULTIMODULE
:
261 return printMultiSubType(rfProtocol
, custom
, subType
);
264 return CHECK_IN_ARRAY(strings
, subType
);
271 QString
ModelPrinter::printModule(int idx
)
275 ModuleData module
= model
.moduleData
[(idx
<0 ? CPN_MAX_MODULES
: idx
)];
277 str
<< printLabelValue(tr("Mode"), printTrainerMode());
278 if (IS_HORUS_OR_TARANIS(firmware
->getBoard())) {
279 if (model
.trainerMode
== TRAINER_SLAVE_JACK
) {
280 str
<< printLabelValue(tr("Channels"), QString("%1-%2").arg(module
.channelsStart
+ 1).arg(module
.channelsStart
+ module
.channelsCount
));
281 str
<< printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module
.ppm
.frameLength
)));
282 str
<< printLabelValue(tr("PPM delay"), QString("%1us").arg(module
.ppm
.delay
));
283 str
<< printLabelValue(tr("Polarity"), module
.polarityToString());
286 result
= str
.join(" ");
289 str
<< printLabelValue(tr("Protocol"), printModuleProtocol(module
.protocol
));
290 if (module
.protocol
) {
291 str
<< printLabelValue(tr("Channels"), QString("%1-%2").arg(module
.channelsStart
+ 1).arg(module
.channelsStart
+ module
.channelsCount
));
292 if (module
.protocol
== PULSES_PPM
|| module
.protocol
== PULSES_SBUS
) {
293 str
<< printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module
.ppm
.frameLength
)));
294 str
<< printLabelValue(tr("Polarity"), module
.polarityToString());
295 if (module
.protocol
== PULSES_PPM
)
296 str
<< printLabelValue(tr("Delay"), QString("%1us").arg(module
.ppm
.delay
));
299 if (!(module
.protocol
== PULSES_PXX_XJT_D8
|| module
.protocol
== PULSES_CROSSFIRE
|| module
.protocol
== PULSES_SBUS
)) {
300 str
<< printLabelValue(tr("Receiver"), QString::number(module
.modelId
));
302 if (module
.protocol
== PULSES_MULTIMODULE
) {
303 str
<< printLabelValue(tr("Radio protocol"), printMultiRfProtocol(module
.multi
.rfProtocol
, module
.multi
.customProto
));
304 str
<< printLabelValue(tr("Subtype"), printMultiSubType(module
.multi
.rfProtocol
, module
.multi
.customProto
, module
.subType
));
305 str
<< printLabelValue(tr("Option value"), QString::number(module
.multi
.optionValue
));
307 if (module
.protocol
== PULSES_PXX_R9M
) {
308 str
<< printLabelValue(tr("Sub Type"), printModuleSubType(module
.protocol
, module
.subType
));
309 str
<< printLabelValue(tr("RF Output Power"), printR9MPowerValue(module
.subType
, module
.pxx
.power
, module
.pxx
.sport_out
));
310 str
<< printLabelValue(tr("Telemetry"), printBoolean(module
.pxx
.sport_out
, BOOLEAN_ENABLEDISABLE
));
314 result
= str
.join(" ");
315 if (((PulsesProtocol
)module
.protocol
== PulsesProtocol::PULSES_PXX_XJT_X16
|| (PulsesProtocol
)module
.protocol
== PulsesProtocol::PULSES_PXX_R9M
)
316 && firmware
->getCapability(HasFailsafe
))
317 result
.append("<br/>" + printFailsafe(idx
));
322 QString
ModelPrinter::printTrainerMode()
325 switch (model
.trainerMode
) {
326 case TRAINER_MASTER_JACK
:
327 result
= tr("Master/Jack");
329 case TRAINER_SLAVE_JACK
:
330 result
= tr("Slave/Jack");
332 case TRAINER_MASTER_SBUS_MODULE
:
333 result
= tr("Master/SBUS Module");
335 case TRAINER_MASTER_CPPM_MODULE
:
336 result
= tr("Master/CPPM Module");
338 case TRAINER_MASTER_SBUS_BATT_COMPARTMENT
:
339 result
= tr("Master/SBUS in battery compartment");
347 QString
ModelPrinter::printHeliSwashType ()
349 switch (model
.swashRingData
.type
) {
350 case HELI_SWASH_TYPE_90
:
352 case HELI_SWASH_TYPE_120
:
354 case HELI_SWASH_TYPE_120X
:
356 case HELI_SWASH_TYPE_140
:
358 case HELI_SWASH_TYPE_NONE
:
365 QString
ModelPrinter::printCenterBeep()
368 if (model
.beepANACenter
& 0x01)
369 strl
<< tr("Rudder");
370 if (model
.beepANACenter
& 0x02)
371 strl
<< tr("Elevator");
372 if (model
.beepANACenter
& 0x04)
373 strl
<< tr("Throttle");
374 if (model
.beepANACenter
& 0x08)
375 strl
<< tr("Aileron");
376 if (IS_HORUS(firmware
->getBoard())) {
378 qDebug() << "ModelPrinter::printCenterBeep() TODO";
380 else if (IS_TARANIS(firmware
->getBoard())) {
381 if (model
.beepANACenter
& 0x10)
383 if (model
.beepANACenter
& 0x20)
385 if (model
.beepANACenter
& 0x40)
387 if (model
.beepANACenter
& 0x80)
389 if (model
.beepANACenter
& 0x100)
393 if (model
.beepANACenter
& 0x10)
395 if (model
.beepANACenter
& 0x20)
397 if (model
.beepANACenter
& 0x40)
400 return (strl
.isEmpty() ? tr("None") : strl
.join(" "));
403 QString
ModelPrinter::printTimer(int idx
)
405 return printTimer(model
.timers
[idx
]);
408 QString
ModelPrinter::printTimer(const TimerData
& timer
)
411 if (firmware
->getCapability(TimersName
) && timer
.name
[0])
412 result
+= tr("Name") + QString("(%1)").arg(timer
.name
);
413 result
+= printTimeValue(timer
.val
, MASK_TIMEVALUE_HRSMINS
| MASK_TIMEVALUE_ZEROHRS
);
414 result
+= timer
.mode
.toString();
415 if (timer
.countdownBeep
)
416 result
+= tr("Countdown") + QString("(%1)").arg(printTimerCountdownBeep(timer
.countdownBeep
));
417 if (timer
.minuteBeep
)
418 result
+= tr("Minute call");
419 if (timer
.persistent
)
420 result
+= tr("Persistent") + QString("(%1)").arg(printTimerPersistent(timer
.persistent
));
421 return result
.join(", ");
424 QString
ModelPrinter::printTrim(int flightModeIndex
, int stickIndex
)
426 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
428 if (fm
.trimMode
[stickIndex
] == -1) {
432 if (fm
.trimRef
[stickIndex
] == flightModeIndex
) {
433 return QString("%1").arg(fm
.trim
[stickIndex
]);
436 if (fm
.trimMode
[stickIndex
] == 0) {
437 return tr("FM%1").arg(fm
.trimRef
[stickIndex
]);
440 if (fm
.trim
[stickIndex
] < 0)
441 return tr("FM%1%2").arg(fm
.trimRef
[stickIndex
]).arg(fm
.trim
[stickIndex
]);
443 return tr("FM%1+%2").arg(fm
.trimRef
[stickIndex
]).arg(fm
.trim
[stickIndex
]);
449 QString
ModelPrinter::printGlobalVar(int flightModeIndex
, int gvarIndex
)
451 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
453 if (fm
.gvars
[gvarIndex
] <= 1024) {
454 return QString("%1").arg(fm
.gvars
[gvarIndex
] * model
.gvarData
[gvarIndex
].multiplierGet());
457 int num
= fm
.gvars
[gvarIndex
] - 1025;
458 if (num
>= flightModeIndex
) num
++;
459 return tr("FM%1").arg(num
);
463 QString
ModelPrinter::printRotaryEncoder(int flightModeIndex
, int reIndex
)
465 const FlightModeData
& fm
= model
.flightModeData
[flightModeIndex
];
467 if (fm
.rotaryEncoders
[reIndex
] <= 1024) {
468 return QString("%1").arg(fm
.rotaryEncoders
[reIndex
]);
471 int num
= fm
.rotaryEncoders
[reIndex
] - 1025;
472 if (num
>= flightModeIndex
) num
++;
473 return tr("FM%1").arg(num
);
477 QString
ModelPrinter::printInputName(int idx
)
479 RawSourceType srcType
= (firmware
->getCapability(VirtualInputs
) ? SOURCE_TYPE_VIRTUAL_INPUT
: SOURCE_TYPE_STICK
);
480 return RawSource(srcType
, idx
).toString(&model
, &generalSettings
).toHtmlEscaped();
483 QString
ModelPrinter::printInputLine(int idx
)
485 return printInputLine(model
.expoData
[idx
]);
488 QString
ModelPrinter::printInputLine(const ExpoData
& input
)
490 QString str
= " ";
492 switch (input
.mode
) {
493 case (1): str
+= "<- "; break;
494 case (2): str
+= "-> "; break;
495 default: str
+= " "; break;
498 if (firmware
->getCapability(VirtualInputs
)) {
499 str
+= input
.srcRaw
.toString(&model
, &generalSettings
).toHtmlEscaped();
502 str
+= " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(Helpers::getAdjustmentString(input
.weight
, &model
, true).toHtmlEscaped());
503 if (input
.curve
.value
)
504 str
+= " " + input
.curve
.toString(&model
).toHtmlEscaped();
506 QString flightModesStr
= printFlightModes(input
.flightModes
);
507 if (!flightModesStr
.isEmpty())
508 str
+= " " + flightModesStr
.toHtmlEscaped();
510 if (input
.swtch
.type
!= SWITCH_TYPE_NONE
)
511 str
+= " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input
.swtch
.toString(getCurrentBoard(), &generalSettings
)).toHtmlEscaped();
514 if (firmware
->getCapability(VirtualInputs
)) {
515 if (input
.carryTrim
>0)
516 str
+= " " + tr("NoTrim").toHtmlEscaped();
517 else if (input
.carryTrim
<0)
518 str
+= " " + RawSource(SOURCE_TYPE_TRIM
, (-(input
.carryTrim
)-1)).toString(&model
, &generalSettings
).toHtmlEscaped();
522 str
+= " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(input
.offset
, &model
)).toHtmlEscaped();
524 if (firmware
->getCapability(HasExpoNames
) && input
.name
[0])
525 str
+= QString(" [%1]").arg(input
.name
).toHtmlEscaped();
530 QString
ModelPrinter::printMixerLine(const MixData
& mix
, bool showMultiplex
, int highlightedSource
)
532 QString str
= " ";
536 case (1): str
+= "*="; break;
537 case (2): str
+= ":="; break;
538 default: str
+= "+="; break;
542 str
+= " ";
544 // highlight source if needed
545 QString source
= mix
.srcRaw
.toString(&model
, &generalSettings
).toHtmlEscaped();
546 if ( (mix
.srcRaw
.type
== SOURCE_TYPE_CH
) && (mix
.srcRaw
.index
+1 == (int)highlightedSource
) ) {
547 source
= "<b>" + source
+ "</b>";
549 str
+= " " + source
;
551 if (mix
.mltpx
== MLTPX_MUL
&& !showMultiplex
)
552 str
+= " " + tr("MULT!").toHtmlEscaped();
554 str
+= " " + tr("Weight") + QString("(%1)").arg(Helpers::getAdjustmentString(mix
.weight
, &model
, true)).toHtmlEscaped();
556 QString flightModesStr
= printFlightModes(mix
.flightModes
);
557 if (!flightModesStr
.isEmpty())
558 str
+= " " + flightModesStr
.toHtmlEscaped();
560 if (mix
.swtch
.type
!= SWITCH_TYPE_NONE
)
561 str
+= " " + tr("Switch") + QString("(%1)").arg(mix
.swtch
.toString(getCurrentBoard(), &generalSettings
)).toHtmlEscaped();
563 if (mix
.carryTrim
> 0)
564 str
+= " " + tr("NoTrim").toHtmlEscaped();
565 else if (mix
.carryTrim
< 0)
566 str
+= " " + RawSource(SOURCE_TYPE_TRIM
, (-(mix
.carryTrim
)-1)).toString(&model
, &generalSettings
);
568 if (firmware
->getCapability(HasNoExpo
) && mix
.noExpo
)
569 str
+= " " + tr("No DR/Expo").toHtmlEscaped();
571 str
+= " " + tr("Offset") + QString("(%1)").arg(Helpers::getAdjustmentString(mix
.sOffset
, &model
)).toHtmlEscaped();
573 str
+= " " + mix
.curve
.toString(&model
).toHtmlEscaped();
574 int scale
= firmware
->getCapability(SlowScale
);
577 if (mix
.delayDown
|| mix
.delayUp
)
578 str
+= " " + tr("Delay") + QString("(u%1:d%2)").arg((double)mix
.delayUp
/scale
).arg((double)mix
.delayDown
/scale
).toHtmlEscaped();
579 if (mix
.speedDown
|| mix
.speedUp
)
580 str
+= " " + tr("Slow") + QString("(u%1:d%2)").arg((double)mix
.speedUp
/scale
).arg((double)mix
.speedDown
/scale
).toHtmlEscaped();
582 str
+= " " + tr("Warn") + QString("(%1)").arg(mix
.mixWarn
).toHtmlEscaped();
583 if (firmware
->getCapability(HasMixerNames
) && mix
.name
[0])
584 str
+= QString(" [%1]").arg(mix
.name
).toHtmlEscaped();
588 QString
ModelPrinter::printFlightModeSwitch(const RawSwitch
& swtch
)
590 return swtch
.toString(getCurrentBoard(), &generalSettings
);
593 QString
ModelPrinter::printFlightModeName(int index
)
595 return model
.flightModeData
[index
].nameToString(index
);
598 QString
ModelPrinter::printFlightModes(unsigned int flightModes
)
600 int numFlightModes
= firmware
->getCapability(FlightModes
);
601 if (numFlightModes
&& flightModes
) {
602 if (flightModes
== (unsigned int)(1<<numFlightModes
) - 1) {
603 return tr("Disabled in all flight modes");
607 for (int i
=0; i
<numFlightModes
; i
++) {
608 if (!(flightModes
& (1<<i
))) {
609 list
<< printFlightModeName(i
);
612 return (list
.size() > 1 ? tr("Flight modes") : tr("Flight mode")) + QString("(%1)").arg(list
.join(", "));
619 QString
ModelPrinter::printInputFlightModes(unsigned int flightModes
)
621 int numFlightModes
= firmware
->getCapability(FlightModes
);
622 if (numFlightModes
&& flightModes
) {
623 if (flightModes
== (unsigned int)(1<<numFlightModes
) - 1) {
628 for (int i
=0; i
<numFlightModes
; i
++) {
629 if (!(flightModes
& (1<<i
))) {
630 list
<< printFlightModeName(i
);
633 return QString("%1").arg(list
.join(" "));
640 QString
ModelPrinter::printLogicalSwitchLine(int idx
)
643 const LogicalSwitchData
& ls
= model
.logicalSw
[idx
];
644 const QString sw1Name
= RawSwitch(ls
.val1
).toString(getCurrentBoard(), &generalSettings
);
645 const QString sw2Name
= RawSwitch(ls
.val2
).toString(getCurrentBoard(), &generalSettings
);
653 switch (ls
.getFunctionFamily()) {
655 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
)));
657 case LS_FAMILY_STICKY
:
658 result
+= tr("Sticky") + QString("(%1, %2)").arg(sw1Name
).arg(sw2Name
);
660 case LS_FAMILY_TIMER
:
661 result
+= tr("Timer") + QString("(%1, %2)").arg(ValToTim(ls
.val1
)).arg(ValToTim(ls
.val2
));
663 case LS_FAMILY_VOFS
: {
664 RawSource source
= RawSource(ls
.val1
);
665 RawSourceRange range
= source
.getRange(&model
, generalSettings
);
668 res
+= source
.toString(&model
, &generalSettings
);
672 if (ls
.func
== LS_FN_APOS
|| ls
.func
== LS_FN_ANEG
)
673 res
= "|" + res
+ "|";
674 else if (ls
.func
== LS_FN_DAPOS
)
675 res
= "|d(" + res
+ ")|";
676 else if (ls
.func
== LS_FN_DPOS
)
677 result
= "d(" + res
+ ")";
679 if (ls
.func
== LS_FN_VEQUAL
)
681 else if (ls
.func
== LS_FN_APOS
|| ls
.func
== LS_FN_VPOS
|| ls
.func
== LS_FN_DPOS
|| ls
.func
== LS_FN_DAPOS
)
683 else if (ls
.func
== LS_FN_ANEG
|| ls
.func
== LS_FN_VNEG
)
685 else if (ls
.func
== LS_FN_VALMOSTEQUAL
)
688 result
+= tr(" missing");
689 result
+= QString::number(range
.step
* (ls
.val2
/*TODO+ source.getRawOffset(model)*/) + range
.offset
);
692 case LS_FAMILY_VBOOL
:
711 case LS_FAMILY_VCOMP
:
713 result
+= RawSource(ls
.val1
).toString(&model
, &generalSettings
);
741 result
+= RawSource(ls
.val2
).toString(&model
, &generalSettings
);
749 result
+= RawSwitch(ls
.andsw
).toString(getCurrentBoard(), &generalSettings
);
752 if (firmware
->getCapability(LogicalSwitchesExt
)) {
754 result
+= " " + tr("Duration") + QString("(%1s)").arg(ls
.duration
/10.0);
756 result
+= " " + tr("Delay") + QString("(%1s)").arg(ls
.delay
/10.0);
762 QString
ModelPrinter::printCustomFunctionLine(int idx
)
765 const CustomFunctionData
& cf
= model
.customFn
[idx
];
766 if (cf
.swtch
.type
== SWITCH_TYPE_NONE
)
769 result
+= cf
.swtch
.toString(getCurrentBoard(), &generalSettings
) + " - ";
770 result
+= cf
.funcToString(&model
) + " (";
771 result
+= cf
.paramToString(&model
) + ")";
772 if (!cf
.repeatToString().isEmpty())
773 result
+= " " + cf
.repeatToString();
774 if (!cf
.enabledToString().isEmpty())
775 result
+= " " + cf
.enabledToString();
779 QString
ModelPrinter::printCurveName(int idx
)
781 return model
.curves
[idx
].nameToString(idx
).toHtmlEscaped();
784 QString
ModelPrinter::printCurve(int idx
)
787 const CurveData
& curve
= model
.curves
[idx
];
788 result
+= (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
) ? tr("Custom") : tr("Standard");
790 if (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
) {
791 for (int j
=0; j
<curve
.count
; j
++) {
794 result
+= QString("(%1, %2)").arg(curve
.points
[j
].x
).arg(curve
.points
[j
].y
);
798 for (int j
=0; j
<curve
.count
; j
++) {
801 result
+= QString("%1").arg(curve
.points
[j
].y
);
808 CurveImage::CurveImage():
810 image(size
+1, size
+1, QImage::Format_RGB32
),
813 painter
.setBrush(QBrush("#FFFFFF"));
814 painter
.setPen(QColor(0, 0, 0));
815 painter
.drawRect(0, 0, size
, size
);
817 painter
.setPen(QColor(0, 0, 0));
818 painter
.drawLine(0, size
/2, size
, size
/2);
819 painter
.drawLine(size
/2, 0, size
/2, size
);
820 for (int i
=0; i
<21; i
++) {
821 painter
.drawLine(size
/2-5, (size
*i
)/(20), size
/2+5, (size
*i
)/(20));
822 painter
.drawLine((size
*i
)/(20), size
/2-5, (size
*i
)/(20), size
/2+5);
826 void CurveImage::drawCurve(const CurveData
& curve
, QColor color
)
828 painter
.setPen(QPen(color
, 2, Qt::SolidLine
));
829 for (int j
=1; j
<curve
.count
; j
++) {
830 if (curve
.type
== CurveData::CURVE_TYPE_CUSTOM
)
831 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);
833 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);
837 QString
ModelPrinter::createCurveImage(int idx
, QTextDocument
* document
)
840 image
.drawCurve(model
.curves
[idx
], colors
[idx
]);
841 QString filename
= QString("mydata://curve-%1-%2.png").arg((uint64_t)this).arg(idx
);
843 document
->addResource(QTextDocument::ImageResource
, QUrl(filename
), image
.get());
844 // qDebug() << "ModelPrinter::createCurveImage()" << idx << filename;
848 QString
ModelPrinter::printGlobalVarUnit(int idx
)
850 return model
.gvarData
[idx
].unitToString().toHtmlEscaped();
853 QString
ModelPrinter::printGlobalVarPrec(int idx
)
855 return model
.gvarData
[idx
].precToString().toHtmlEscaped();
858 QString
ModelPrinter::printGlobalVarMin(int idx
)
860 return QString::number(model
.gvarData
[idx
].getMinPrec());
863 QString
ModelPrinter::printGlobalVarMax(int idx
)
865 return QString::number(model
.gvarData
[idx
].getMaxPrec());
868 QString
ModelPrinter::printGlobalVarPopup(int idx
)
870 return printBoolean(model
.gvarData
[idx
].popup
, BOOLEAN_YN
);
873 QString
ModelPrinter::printOutputValueGVar(int val
)
876 if (abs(val
) > 10000) {
879 result
.append(RawSource(SOURCE_TYPE_GVAR
, abs(val
)-10001).toString(&model
));
884 result
.append(QString::number((qreal
)val
/10, 'f', 1) + "%");
889 QString
ModelPrinter::printOutputOffset(int idx
)
891 return printOutputValueGVar(model
.limitData
[idx
].offset
);
894 QString
ModelPrinter::printOutputMin(int idx
)
896 return printOutputValueGVar(model
.limitData
[idx
].min
);
899 QString
ModelPrinter::printOutputMax(int idx
)
901 return printOutputValueGVar(model
.limitData
[idx
].max
);
904 QString
ModelPrinter::printOutputRevert(int idx
)
906 return model
.limitData
[idx
].revertToString();
909 QString
ModelPrinter::printOutputPpmCenter(int idx
)
911 return QString::number(model
.limitData
[idx
].ppmCenter
+ 1500);
914 QString
ModelPrinter::printOutputCurve(int idx
)
916 return CurveReference(CurveReference::CURVE_REF_CUSTOM
, model
.limitData
[idx
].curve
.value
).toString(&model
, false);
919 QString
ModelPrinter::printOutputSymetrical(int idx
)
921 return printBoolean(model
.limitData
[idx
].symetrical
, BOOLEAN_YN
);
924 QString
ModelPrinter::printSettingsOther()
927 str
<< printLabelValue(tr("Extended Limits"), printBoolean(model
.extendedLimits
, BOOLEAN_YESNO
));
928 if (firmware
->getCapability(HasDisplayText
))
929 str
<< printLabelValue(tr("Display Checklist"), printBoolean(model
.displayChecklist
, BOOLEAN_YESNO
));
930 if (firmware
->getCapability(GlobalFunctions
))
931 str
<< printLabelValue(tr("Global Functions"), printBoolean(!model
.noGlobalFunctions
, BOOLEAN_YESNO
));
932 return str
.join(" ");
935 QString
ModelPrinter::printSwitchWarnings()
938 Boards board
= firmware
->getBoard();
939 uint64_t switchStates
= model
.switchWarningStates
;
942 for (int idx
=0; idx
<board
.getCapability(Board::Switches
); idx
++) {
943 Board::SwitchInfo switchInfo
= Boards::getSwitchInfo(board
.getBoardType(), idx
);
944 switchInfo
.config
= Board::SwitchType(generalSettings
.switchConfig
[idx
]);
945 if (switchInfo
.config
== Board::SWITCH_NOT_AVAILABLE
|| switchInfo
.config
== Board::SWITCH_TOGGLE
) {
948 if (!(model
.switchWarningEnable
& (1 << idx
))) {
949 if (IS_HORUS_OR_TARANIS(board
.getBoardType())) {
950 value
= (switchStates
>> (2*idx
)) & 0x03;
953 value
= (idx
==0 ? switchStates
& 0x3 : switchStates
& 0x1);
954 switchStates
>>= (idx
==0 ? 2 : 1);
956 str
+= RawSwitch(SWITCH_TYPE_SWITCH
, 1+idx
*3+value
).toString(board
.getBoardType(), &generalSettings
, &model
);
959 return (str
.isEmpty() ? tr("None") : str
.join(" ")) ;
962 QString
ModelPrinter::printPotWarnings()
966 Boards board
= firmware
->getBoard();
967 if (model
.potsWarningMode
) {
968 for (int i
=0; i
<board
.getCapability(Board::Pots
)+board
.getCapability(Board::Sliders
); i
++) {
969 RawSource
src(SOURCE_TYPE_STICK
, CPN_MAX_STICKS
+ i
);
970 if ((src
.isPot(&genAryIdx
) && generalSettings
.isPotAvailable(genAryIdx
)) || (src
.isSlider(&genAryIdx
) && generalSettings
.isSliderAvailable(genAryIdx
))) {
971 if (!model
.potsWarningEnabled
[i
])
972 str
+= src
.toString(&model
, &generalSettings
);
976 str
<< printLabelValue(tr("Mode"), printPotsWarningMode());
977 return str
.join(" ");
980 QString
ModelPrinter::printPotsWarningMode()
982 switch (model
.potsWarningMode
) {
994 QString
ModelPrinter::printFailsafe(int idx
)
997 ModuleData module
= model
.moduleData
[idx
];
998 strl
<< printLabelValue(tr("Failsafe Mode"), printFailsafeMode(module
.failsafeMode
));
999 if (module
.failsafeMode
== FAILSAFE_CUSTOM
) {
1000 for (int i
=0; i
<module
.channelsCount
; i
++) {
1001 //strl << QString("%1(%2)").arg(printChannelName(module.channelsStart + i).trimmed()).arg(printFailsafeValue(module.failsafeChannels[i]));
1002 strl
<< printLabelValue(printChannelName(module
.channelsStart
+ i
).trimmed(), printFailsafeValue(module
.failsafeChannels
[i
]));
1005 return strl
.join(" ");
1008 QString
ModelPrinter::printFailsafeValue(int val
)
1014 return tr("No Pulse");
1016 return QString("%1%").arg(QString::number(divRoundClosest(val
* 1000, 1024) / 10.0));
1020 QString
ModelPrinter::printFailsafeMode(unsigned int fsmode
)
1023 case FAILSAFE_NOT_SET
:
1024 return tr("Not set");
1027 case FAILSAFE_CUSTOM
:
1028 return tr("Custom");
1029 case FAILSAFE_NOPULSES
:
1030 return tr("No pulses");
1031 case FAILSAFE_RECEIVER
:
1032 return tr("Receiver");
1038 QString
ModelPrinter::printTimerCountdownBeep(unsigned int countdownBeep
)
1040 switch (countdownBeep
) {
1041 case TimerData::COUNTDOWN_SILENT
:
1042 return tr("Silent");
1043 case TimerData::COUNTDOWN_BEEPS
:
1045 case TimerData::COUNTDOWN_VOICE
:
1047 case TimerData::COUNTDOWN_HAPTIC
:
1048 return tr("Haptic");
1054 QString
ModelPrinter::printTimerPersistent(unsigned int persistent
)
1056 switch (persistent
) {
1060 return tr("Flight");
1062 return tr("Manual reset");
1068 QString
ModelPrinter::printSettingsTrim()
1071 str
<< printLabelValue(tr("Step"), printTrimIncrementMode());
1072 if (IS_ARM(firmware
->getBoard()))
1073 str
<< printLabelValue(tr("Display"), printTrimsDisplayMode());
1074 str
<< printLabelValue(tr("Extended"), printBoolean(model
.extendedTrims
, BOOLEAN_YESNO
));
1075 return str
.join(" ");
1078 QString
ModelPrinter::printThrottleSource(int idx
)
1080 Boards board
= firmware
->getBoard();
1081 int chnstart
= board
.getCapability(Board::Pots
)+board
.getCapability(Board::Sliders
);
1084 else if (idx
< (chnstart
+1))
1085 return firmware
->getAnalogInputName(idx
+board
.getCapability(Board::Sticks
)-1);
1087 return RawSource(SOURCE_TYPE_CH
, idx
-chnstart
-1).toString(&model
, &generalSettings
);
1090 QString
ModelPrinter::printTrimsDisplayMode()
1092 switch (model
.trimsDisplay
) {
1096 return tr("On Change");
1098 return tr("Always");
1104 QString
ModelPrinter::printModuleType(int idx
)
1107 return tr("Trainer Port");
1108 else if (firmware
->getCapability(NumModules
) > 1)
1109 if (IS_HORUS_OR_TARANIS(firmware
->getBoard()))
1111 return tr("Internal Radio System");
1113 return tr("External Radio Module");
1115 return tr("Radio System");
1117 return tr("Extra Radio System");
1119 return tr("Radio System");
1122 QString
ModelPrinter::printPxxPower(int power
)
1124 static const char *strings
[] = {
1125 "10mW", "100mW", "500mW", "3W"
1127 return CHECK_IN_ARRAY(strings
, power
);
1130 QString
ModelPrinter::printThrottle()
1133 result
<< printLabelValue(tr("Source"), printThrottleSource(model
.thrTraceSrc
));
1134 result
<< printLabelValue(tr("Trim idle only"), printBoolean(model
.thrTrim
, BOOLEAN_YESNO
));
1135 result
<< printLabelValue(tr("Warning"), printBoolean(!model
.disableThrottleWarning
, BOOLEAN_YESNO
));
1136 result
<< printLabelValue(tr("Reversed"), printBoolean(model
.throttleReversed
, BOOLEAN_YESNO
));
1137 return result
.join(" ");
1140 QString
ModelPrinter::printPPMFrameLength(int ppmFL
)
1142 double result
= (((double)ppmFL
* 5) + 225) / 10;
1143 return QString::number(result
);
1146 QString
ModelPrinter::printTimerName(int idx
)
1149 result
= tr("Tmr") + QString("%1").arg(idx
+1);
1150 if (firmware
->getCapability(TimersName
) && model
.timers
[idx
].name
[0])
1151 result
.append(":" + QString(model
.timers
[idx
].name
));
1156 QString
ModelPrinter::printTimerTimeValue(unsigned int val
)
1158 return printTimeValue(val
, MASK_TIMEVALUE_HRSMINS
| MASK_TIMEVALUE_ZEROHRS
);
1161 QString
ModelPrinter::printTimerMinuteBeep(bool mb
)
1163 return printBoolean(mb
, BOOLEAN_YESNO
);
1166 QString
ModelPrinter::printTelemetryProtocol(unsigned int val
)
1170 return tr("FrSky S.PORT");
1172 return tr("FrSky D");
1174 return tr("FrSky D (cable)");
1180 QString
ModelPrinter::printRssiAlarmsDisabled(bool mb
)
1182 return printBoolean(!mb
, BOOLEAN_ENABLEDISABLE
);
1185 QString
ModelPrinter::printTelemetrySource(int val
)
1187 QStringList strings
= QStringList() << tr("None");
1189 for (int i
=1; i
<=CPN_MAX_SENSORS
; ++i
) {
1190 strings
<< QString("%1").arg(model
.sensorData
[i
-1].label
);
1193 return QString("%1%2").arg((val
< 0 ? "-" : "")).arg(strings
.value(abs(val
)));
1196 QString
ModelPrinter::printVarioSource(unsigned int val
)
1199 case TELEMETRY_VARIO_SOURCE_ALTI
:
1201 case TELEMETRY_VARIO_SOURCE_ALTI_PLUS
:
1203 case TELEMETRY_VARIO_SOURCE_VSPEED
:
1204 return tr("VSpeed");
1205 case TELEMETRY_VARIO_SOURCE_A1
:
1207 case TELEMETRY_VARIO_SOURCE_A2
:
1214 QString
ModelPrinter::printVarioCenterSilent(bool mb
)
1216 return printBoolean(mb
, BOOLEAN_YESNO
);
1219 QString
ModelPrinter::printVoltsSource(unsigned int val
)
1222 case TELEMETRY_VOLTS_SOURCE_A1
:
1224 case TELEMETRY_VOLTS_SOURCE_A2
:
1226 case TELEMETRY_VOLTS_SOURCE_A3
:
1228 case TELEMETRY_VOLTS_SOURCE_A4
:
1230 case TELEMETRY_VOLTS_SOURCE_FAS
:
1232 case TELEMETRY_VOLTS_SOURCE_CELLS
:
1239 QString
ModelPrinter::printCurrentSource(unsigned int val
)
1242 case TELEMETRY_CURRENT_SOURCE_NONE
:
1244 case TELEMETRY_CURRENT_SOURCE_A1
:
1246 case TELEMETRY_CURRENT_SOURCE_A2
:
1248 case TELEMETRY_CURRENT_SOURCE_A3
:
1250 case TELEMETRY_CURRENT_SOURCE_A4
:
1252 case TELEMETRY_CURRENT_SOURCE_FAS
:
1259 QString
ModelPrinter::printMahPersistent(bool mb
)
1261 return printBoolean(mb
, BOOLEAN_YESNO
);
1264 QString
ModelPrinter::printIgnoreSensorIds(bool mb
)
1266 return printBoolean(mb
, BOOLEAN_ENABLEDISABLE
);
1269 QString
ModelPrinter::printSensorType(unsigned int val
)
1272 case SensorData::TELEM_TYPE_CUSTOM
:
1273 return tr("Custom");
1274 case SensorData::TELEM_TYPE_CALCULATED
:
1275 return tr("Calculated");
1281 QString
ModelPrinter::printSensorFormula(unsigned int val
)
1284 case SensorData::TELEM_FORMULA_ADD
:
1286 case SensorData::TELEM_FORMULA_AVERAGE
:
1287 return tr("Average");
1288 case SensorData::TELEM_FORMULA_MIN
:
1290 case SensorData::TELEM_FORMULA_MAX
:
1292 case SensorData::TELEM_FORMULA_MULTIPLY
:
1293 return tr("Multiply");
1294 case SensorData::TELEM_FORMULA_TOTALIZE
:
1295 return tr("Totalise");
1296 case SensorData::TELEM_FORMULA_CELL
:
1298 case SensorData::TELEM_FORMULA_CONSUMPTION
:
1299 return tr("Consumption");
1300 case SensorData::TELEM_FORMULA_DIST
:
1301 return tr("Distance");
1307 QString
ModelPrinter::printSensorCells(unsigned int val
)
1309 QStringList strings
;
1311 strings
<< tr("Lowest");
1312 for (int i
=1; i
<=6; i
++)
1313 strings
<< tr("Cell %1").arg(i
);
1314 strings
<< tr("Highest") << tr("Delta");
1316 return strings
.value(val
);
1319 QString
ModelPrinter::printSensorTypeCond(unsigned int idx
)
1321 if (!model
.sensorData
[idx
].isAvailable())
1324 return printSensorType(model
.sensorData
[idx
].type
);
1327 QString
ModelPrinter::printSensorDetails(unsigned int idx
)
1330 SensorData sensor
= model
.sensorData
[idx
];
1332 if (!sensor
.isAvailable())
1335 bool isConfigurable
= false;
1336 bool gpsFieldsPrinted
= false;
1337 bool cellsFieldsPrinted
= false;
1338 bool consFieldsPrinted
= false;
1339 bool ratioFieldsPrinted
= false;
1340 bool totalizeFieldsPrinted
= false;
1341 bool sources12FieldsPrinted
= false;
1342 bool sources34FieldsPrinted
= false;
1344 str
.append(doTableCell(printSensorTypeCond(idx
)));
1347 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
) {
1348 isConfigurable
= (sensor
.formula
< SensorData::TELEM_FORMULA_CELL
);
1349 gpsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
);
1350 cellsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
);
1351 consFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
);
1352 sources12FieldsPrinted
= (sensor
.formula
<= SensorData::TELEM_FORMULA_MULTIPLY
);
1353 sources34FieldsPrinted
= (sensor
.formula
< SensorData::TELEM_FORMULA_MULTIPLY
);
1354 totalizeFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
);
1356 tc
.append(printLabelValue(tr("Formula"), printSensorFormula(sensor
.formula
)));
1359 isConfigurable
= sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
;
1360 ratioFieldsPrinted
= (sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
);
1362 tc
.append(printLabelValue(tr("Id"), QString::number(sensor
.id
,16).toUpper()));
1363 tc
.append(printLabelValue(tr("Instance"), QString::number(sensor
.instance
)));
1365 if (cellsFieldsPrinted
) {
1366 tc
.append(printLabelValue(tr("Sensor"), QString("%1 > %2").arg(printTelemetrySource(sensor
.source
), false).arg(printSensorCells(sensor
.index
))));
1368 if (sources12FieldsPrinted
) {
1370 for (int i
=0;i
<4;i
++) {
1371 if (i
< 2 || sources34FieldsPrinted
) {
1372 srcs
<< printTelemetrySource(sensor
.sources
[i
]);
1375 tc
.append(printLabelValues(tr("Sources"), srcs
));
1377 if (consFieldsPrinted
|| totalizeFieldsPrinted
)
1378 tc
.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor
.amps
)));
1379 if (gpsFieldsPrinted
) {
1380 tc
.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor
.gps
)));
1381 tc
.append(printLabelValue(tr("Alt."), printTelemetrySource(sensor
.alt
)));
1383 if (ratioFieldsPrinted
&& sensor
.unit
== SensorData::UNIT_RPMS
) {
1384 tc
.append(printLabelValue(tr("Blades"), QString::number(sensor
.ratio
)));
1385 tc
.append(printLabelValue(tr("Multi."), QString::number(sensor
.offset
)));
1387 str
.append(doTableCell(tc
));
1389 tc
= sensor
.unitString();
1390 tc
= tc
.trimmed() == "" ? "-" : tc
;
1391 str
.append(doTableCell(tc
));
1393 if (isConfigurable
&& sensor
.unit
!= SensorData::UNIT_FAHRENHEIT
)
1394 tc
= QString::number(sensor
.prec
);
1397 str
.append(doTableCell(tc
));
1399 if (!ratioFieldsPrinted
) {
1400 str
.append(doTableCell(""));
1401 str
.append(doTableCell(""));
1403 else if (sensor
.unit
!= SensorData::UNIT_RPMS
) {
1404 int prec
= sensor
.prec
== 0 ? 1 : pow(10, sensor
.prec
);
1405 str
.append(doTableCell(QString::number((float)sensor
.ratio
/ prec
)));
1406 str
.append(doTableCell(QString::number((float)sensor
.offset
/ prec
)));
1409 if (sensor
.unit
!= SensorData::UNIT_RPMS
&& isConfigurable
)
1410 str
.append(doTableCell(printBoolean(sensor
.autoOffset
, BOOLEAN_YN
)));
1412 str
.append(doTableCell(""));
1415 str
.append(doTableCell(printBoolean(sensor
.filter
, BOOLEAN_YN
)));
1417 str
.append(doTableCell(""));
1419 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
)
1420 str
.append(doTableCell(printBoolean(sensor
.persistent
, BOOLEAN_YN
)));
1422 str
.append(doTableCell(""));
1424 str
.append(doTableCell(printBoolean(sensor
.onlyPositive
, BOOLEAN_YN
)));
1425 str
.append(doTableCell(printBoolean(sensor
.logs
, BOOLEAN_YN
), false));
1429 QString
ModelPrinter::printSensorParams(unsigned int idx
)
1432 SensorData sensor
= model
.sensorData
[idx
];
1434 if (!sensor
.isAvailable())
1437 bool isConfigurable
= false;
1438 bool gpsFieldsPrinted
= false;
1439 bool cellsFieldsPrinted
= false;
1440 bool consFieldsPrinted
= false;
1441 bool ratioFieldsPrinted
= false;
1442 bool totalizeFieldsPrinted
= false;
1443 bool sources12FieldsPrinted
= false;
1444 bool sources34FieldsPrinted
= false;
1446 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
) {
1447 isConfigurable
= (sensor
.formula
< SensorData::TELEM_FORMULA_CELL
);
1448 gpsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_DIST
);
1449 cellsFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CELL
);
1450 consFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_CONSUMPTION
);
1451 sources12FieldsPrinted
= (sensor
.formula
<= SensorData::TELEM_FORMULA_MULTIPLY
);
1452 sources34FieldsPrinted
= (sensor
.formula
< SensorData::TELEM_FORMULA_MULTIPLY
);
1453 totalizeFieldsPrinted
= (sensor
.formula
== SensorData::TELEM_FORMULA_TOTALIZE
);
1455 str
.append(printLabelValue(tr("F"), printSensorFormula(sensor
.formula
)));
1458 isConfigurable
= sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
;
1459 ratioFieldsPrinted
= (sensor
.unit
< SensorData::UNIT_FIRST_VIRTUAL
);
1461 str
.append(printLabelValue(tr("Id"), QString::number(sensor
.id
,16).toUpper()));
1462 str
.append(printLabelValue(tr("Inst"), QString::number(sensor
.instance
)));
1464 if (cellsFieldsPrinted
) {
1465 str
.append(printLabelValue(tr("Sensor"), QString("%1 %2").arg(printTelemetrySource(sensor
.source
), false).arg(printSensorCells(sensor
.index
))));
1467 if (sources12FieldsPrinted
) {
1469 for (int i
=0;i
<4;i
++) {
1470 if (i
< 2 || sources34FieldsPrinted
) {
1471 srcs
<< printTelemetrySource(sensor
.sources
[i
]);
1474 str
.append(printLabelValues(tr("Sources"), srcs
));
1476 if (consFieldsPrinted
|| totalizeFieldsPrinted
)
1477 str
.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor
.amps
)));
1478 if (gpsFieldsPrinted
) {
1479 str
.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor
.gps
)));
1480 str
.append(printLabelValue(tr("Alt"), printTelemetrySource(sensor
.alt
)));
1482 QString u
= sensor
.unitString();
1483 u
= u
.trimmed() == "" ? "-" : u
;
1484 str
.append(printLabelValue(tr("Unit"), u
));
1485 if (isConfigurable
&& sensor
.unit
!= SensorData::UNIT_FAHRENHEIT
)
1486 str
.append(printLabelValue(tr("Prec"), QString::number(sensor
.prec
)));
1487 if (ratioFieldsPrinted
) {
1488 if (sensor
.unit
!= SensorData::UNIT_RPMS
) {
1489 int prec
= sensor
.prec
== 0 ? 1 : pow(10, sensor
.prec
);
1490 str
.append(printLabelValue(tr("Ratio"), QString::number((float)sensor
.ratio
/ prec
)));
1491 str
.append(printLabelValue(tr("Offset"), QString::number((float)sensor
.offset
/ prec
)));
1493 else if (sensor
.unit
== SensorData::UNIT_RPMS
) {
1494 str
.append(printLabelValue(tr("Blades"), QString::number(sensor
.ratio
)));
1495 str
.append(printLabelValue(tr("Multi"), QString::number(sensor
.offset
)));
1498 if (sensor
.unit
!= SensorData::UNIT_RPMS
&& isConfigurable
)
1499 str
.append(printLabelValue(tr("A/Offset"), printBoolean(sensor
.autoOffset
, BOOLEAN_YN
)));
1501 str
.append(printLabelValue(tr("Filter"), printBoolean(sensor
.filter
, BOOLEAN_YN
)));
1502 if (sensor
.type
== SensorData::TELEM_TYPE_CALCULATED
)
1503 str
.append(printLabelValue(tr("Persist"), printBoolean(sensor
.persistent
, BOOLEAN_YN
)));
1504 str
.append(printLabelValue(tr("Positive"), printBoolean(sensor
.onlyPositive
, BOOLEAN_YN
)));
1505 str
.append(printLabelValue(tr("Log"), printBoolean(sensor
.logs
, BOOLEAN_YN
), false));
1509 QString
ModelPrinter::printTelemetryScreenType(unsigned int val
)
1512 case TelemetryScreenEnum::TELEMETRY_SCREEN_NONE
:
1514 case TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS
:
1515 return tr("Numbers");
1516 case TelemetryScreenEnum::TELEMETRY_SCREEN_BARS
:
1518 case TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT
:
1519 return tr("Script");
1525 QString
ModelPrinter::printTelemetryScreen(unsigned int idx
, unsigned int line
, unsigned int width
)
1529 FrSkyScreenData screen
= model
.frsky
.screens
[idx
];
1530 hd
<< ""; // blank 1st column
1532 if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS
) {
1534 for (int c
=0; c
<firmware
->getCapability(TelemetryCustomScreensFieldsPerLine
); c
++) {
1538 for (int c
=0; c
<firmware
->getCapability(TelemetryCustomScreensFieldsPerLine
); c
++) {
1539 RawSource source
= screen
.body
.lines
[line
].source
[c
];
1540 strl
<< source
.toString(&model
, &generalSettings
);
1543 else if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_BARS
) {
1545 hd
<< tr("Source") << tr("Min") << tr("Max");
1547 RawSource source
= screen
.body
.bars
[line
].source
;
1548 RawSourceRange range
= source
.getRange(&model
, generalSettings
);
1549 strl
<< source
.toString(&model
, &generalSettings
);
1553 if (source
.isTimeBased()){
1554 minstr
= printTimeValue((float)screen
.body
.bars
[line
].barMin
, MASK_TIMEVALUE_HRSMINS
);
1555 maxstr
= printTimeValue((float)screen
.body
.bars
[line
].barMax
, MASK_TIMEVALUE_HRSMINS
);
1558 minstr
= QString::number(range
.getValue(screen
.body
.bars
[line
].barMin
));
1559 maxstr
= QString::number(range
.getValue(screen
.body
.bars
[line
].barMax
));
1562 strl
<< QString("%1%2").arg(minstr
).arg(unit
);
1563 strl
<< QString("%1%2").arg(maxstr
).arg(unit
);
1565 else if (screen
.type
== TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT
&& line
== 0) {
1566 hd
<< tr("Filename");
1567 strl
<< QString("%1.lua").arg(screen
.body
.script
.filename
);
1569 return (hd
.count() > 1 ? doTableRow(hd
, width
/ hd
.count(), "left", "", true) : "" ) + doTableRow(strl
, width
/ strl
.count());