/* * Copyright (C) OpenTX * * Based on code named * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "helpers.h" #include "modelprinter.h" #include "multiprotocols.h" #include "boards.h" #include "helpers_html.h" #include "multiprotocols.h" #include "appdata.h" #include #include #include #include #include extern AppData g; QString changeColor(const QString & input, const QString & to, const QString & from) { QString result = input; return result.replace("color="+from, "color="+to); } ModelPrinter::ModelPrinter(Firmware * firmware, const GeneralSettings & generalSettings, const ModelData & model): firmware(firmware), generalSettings(generalSettings), model(model) { } ModelPrinter::~ModelPrinter() { } QString formatTitle(const QString & name) { return QString("" + name + " "); } void debugHtml(const QString & html) { QFile file("foo.html"); file.open(QIODevice::Truncate | QIODevice::WriteOnly); file.write(html.toUtf8()); file.close(); } QString addFont(const QString & input, const QString & color, const QString & size, const QString & face) { QString colorStr; if (!color.isEmpty()) { colorStr = "color=" + color; } QString sizeStr; if (!size.isEmpty()) { sizeStr = "size=" + size; } QString faceStr; if (!face.isEmpty()) { faceStr = "face='" + face + "'"; } return "" + input + ""; } QString ModelPrinter::printLabelValue(const QString & lbl, const QString & val, const bool sep) { return QString("%1: %2%3 ").arg(lbl, val, (sep ? ";" : "")); } QString ModelPrinter::printLabelValues(const QString & lbl, const QStringList & vals, const bool sep) { QString str; if (vals.count() > 1) str.append("("); for (int i=0;i 1) str.append(")"); return printLabelValue(lbl, str, sep); } #define MASK_TIMEVALUE_HRSMINS 1 #define MASK_TIMEVALUE_ZEROHRS 2 #define MASK_TIMEVALUE_PADSIGN 3 QString ModelPrinter::printTimeValue(const int value, const unsigned int mask) { QString result; int sign = 1; int val = value; if (val < 0) { val = -val; sign = -1; } result = (sign < 0 ? QString("-") : ((mask & MASK_TIMEVALUE_PADSIGN) ? QString(" ") : QString(""))); if (mask & MASK_TIMEVALUE_HRSMINS) { int hours = val / 3600; if (hours > 0 || (mask & MASK_TIMEVALUE_ZEROHRS)) { val -= hours * 3600; result.append(QString("%1:").arg(hours, 2, 10, QLatin1Char('0'))); } } int minutes = val / 60; int seconds = val % 60; result.append(QString("%1:%2").arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0'))); return result; } #define BOOLEAN_ENABLEDISABLE 1 #define BOOLEAN_TRUEFALSE 2 #define BOOLEAN_YESNO 3 #define BOOLEAN_YN 4 #define BOOLEAN_ONOFF 5 QString ModelPrinter::printBoolean(const bool val, const int typ) { switch (typ) { case BOOLEAN_ENABLEDISABLE: return (val ? tr("Enable") : tr("Disable")); case BOOLEAN_TRUEFALSE: return (val ? tr("True") : tr("False")); case BOOLEAN_YESNO: return (val ? tr("Yes") : tr("No")); case BOOLEAN_YN: return (val ? tr("Y") : tr("N")); case BOOLEAN_ONOFF: return (val ? tr("ON") : tr("OFF")); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printEEpromSize() { return QString("%1 ").arg(getCurrentEEpromInterface()->getSize(model)) + tr("bytes"); } QString ModelPrinter::printChannelName(int idx) { QString str = RawSource(SOURCE_TYPE_CH, idx).toString(&model, &generalSettings); if (firmware->getCapability(ChannelsName)) { str = str.leftJustified(firmware->getCapability(ChannelsName) + 5, ' ', false); } str.append(' '); return str.toHtmlEscaped(); } QString ModelPrinter::printTrimIncrementMode() { switch (model.trimInc) { case -2: return tr("Exponential"); case -1: return tr("Extra Fine"); case 0: return tr("Fine"); case 1: return tr("Medium"); case 2: return tr("Coarse"); default: return tr("Unknown"); } } QString ModelPrinter::printModule(int idx) { QStringList str; QString result; ModuleData module = model.moduleData[(idx<0 ? CPN_MAX_MODULES : idx)]; if (idx < 0) { str << printLabelValue(tr("Mode"), printTrainerMode()); if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { if (model.trainerMode == TRAINER_SLAVE_JACK) { str << printLabelValue(tr("Channels"), QString("%1-%2").arg(module.channelsStart + 1).arg(module.channelsStart + module.channelsCount)); str << printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module.ppm.frameLength))); str << printLabelValue(tr("PPM delay"), QString("%1us").arg(module.ppm.delay)); str << printLabelValue(tr("Polarity"), module.polarityToString()); } } result = str.join(" "); } else { str << printLabelValue(tr("Protocol"), ModuleData::protocolToString(module.protocol)); if (module.protocol) { str << printLabelValue(tr("Channels"), QString("%1-%2").arg(module.channelsStart + 1).arg(module.channelsStart + module.channelsCount)); if (module.protocol == PULSES_PPM || module.protocol == PULSES_SBUS) { str << printLabelValue(tr("Frame length"), QString("%1ms").arg(printPPMFrameLength(module.ppm.frameLength))); str << printLabelValue(tr("Polarity"), module.polarityToString()); if (module.protocol == PULSES_PPM) str << printLabelValue(tr("Delay"), QString("%1us").arg(module.ppm.delay)); } else { if (!(module.protocol == PULSES_PXX_XJT_D8 || module.protocol == PULSES_CROSSFIRE || module.protocol == PULSES_SBUS)) { str << printLabelValue(tr("Receiver"), QString::number(module.modelId)); } if (module.protocol == PULSES_MULTIMODULE) { str << printLabelValue(tr("Radio protocol"), module.rfProtocolToString()); str << printLabelValue(tr("Subtype"), module.subTypeToString()); str << printLabelValue(tr("Option value"), QString::number(module.multi.optionValue)); } if (module.protocol == PULSES_PXX_R9M) { str << printLabelValue(tr("Sub Type"), module.subTypeToString()); str << printLabelValue(tr("RF Output Power"), module.powerValueToString(firmware)); } } } result = str.join(" "); if (((PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_XJT_X16 || (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_R9M) && firmware->getCapability(HasFailsafe)) result.append("
" + printFailsafe(idx)); } return result; } QString ModelPrinter::printTrainerMode() { QString result; switch (model.trainerMode) { case TRAINER_MASTER_JACK: result = tr("Master/Jack"); break; case TRAINER_SLAVE_JACK: result = tr("Slave/Jack"); break; case TRAINER_MASTER_SBUS_MODULE: result = tr("Master/SBUS Module"); break; case TRAINER_MASTER_CPPM_MODULE: result = tr("Master/CPPM Module"); break; case TRAINER_MASTER_SBUS_BATT_COMPARTMENT: result = tr("Master/SBUS in battery compartment"); break; default: result = CPN_STR_UNKNOWN_ITEM; } return result; } QString ModelPrinter::printHeliSwashType () { switch (model.swashRingData.type) { case HELI_SWASH_TYPE_90: return tr("90"); case HELI_SWASH_TYPE_120: return tr("120"); case HELI_SWASH_TYPE_120X: return tr("120X"); case HELI_SWASH_TYPE_140: return tr("140"); case HELI_SWASH_TYPE_NONE: return tr("Off"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printCenterBeep() { QStringList strl; Board::Type board = firmware->getBoard(); int analogs = CPN_MAX_STICKS + getBoardCapability(board, Board::Pots) + getBoardCapability(board, Board::Sliders); for (int i=0; i < analogs + firmware->getCapability(RotaryEncoders); i++) { RawSource src((i < analogs) ? SOURCE_TYPE_STICK : SOURCE_TYPE_ROTARY_ENCODER, (i < analogs) ? i : analogs - i); if (model.beepANACenter & (0x01 << i)) { strl << src.toString(&model, &generalSettings); } } return (strl.isEmpty() ? tr("None") : strl.join(" ")); } QString ModelPrinter::printTimer(int idx) { return printTimer(model.timers[idx]); } QString ModelPrinter::printTimer(const TimerData & timer) { QStringList result; if (firmware->getCapability(TimersName) && timer.name[0]) result += tr("Name") + QString("(%1)").arg(timer.name); result += printTimeValue(timer.val, MASK_TIMEVALUE_HRSMINS | MASK_TIMEVALUE_ZEROHRS); result += timer.mode.toString(); if (timer.countdownBeep) result += tr("Countdown") + QString("(%1)").arg(printTimerCountdownBeep(timer.countdownBeep)); if (timer.minuteBeep) result += tr("Minute call"); if (timer.persistent) result += tr("Persistent") + QString("(%1)").arg(printTimerPersistent(timer.persistent)); return result.join(", "); } QString ModelPrinter::printTrim(int flightModeIndex, int stickIndex) { const FlightModeData & fm = model.flightModeData[flightModeIndex]; if (fm.trimMode[stickIndex] == -1) { return tr("OFF"); } else { if (fm.trimRef[stickIndex] == flightModeIndex) { return QString("%1").arg(fm.trim[stickIndex]); } else { if (fm.trimMode[stickIndex] == 0) { return tr("FM%1").arg(fm.trimRef[stickIndex]); } else { if (fm.trim[stickIndex] < 0) return tr("FM%1%2").arg(fm.trimRef[stickIndex]).arg(fm.trim[stickIndex]); else return tr("FM%1+%2").arg(fm.trimRef[stickIndex]).arg(fm.trim[stickIndex]); } } } } QString ModelPrinter::printGlobalVar(int flightModeIndex, int gvarIndex) { const FlightModeData & fm = model.flightModeData[flightModeIndex]; if (fm.gvars[gvarIndex] <= 1024) { return QString("%1").arg(fm.gvars[gvarIndex] * model.gvarData[gvarIndex].multiplierGet()); } else { int num = fm.gvars[gvarIndex] - 1025; if (num >= flightModeIndex) num++; return tr("FM%1").arg(num); } } QString ModelPrinter::printRotaryEncoder(int flightModeIndex, int reIndex) { const FlightModeData & fm = model.flightModeData[flightModeIndex]; if (fm.rotaryEncoders[reIndex] <= 1024) { return QString("%1").arg(fm.rotaryEncoders[reIndex]); } else { int num = fm.rotaryEncoders[reIndex] - 1025; if (num >= flightModeIndex) num++; return tr("FM%1").arg(num); } } QString ModelPrinter::printInputName(int idx) { RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_STICK); return RawSource(srcType, idx).toString(&model, &generalSettings).toHtmlEscaped(); } QString ModelPrinter::printInputLine(int idx) { return printInputLine(model.expoData[idx]); } QString ModelPrinter::printInputLine(const ExpoData & input) { QString str = " "; switch (input.mode) { case (1): str += "<- "; break; case (2): str += "-> "; break; default: str += "   "; break; } if (firmware->getCapability(VirtualInputs)) { str += input.srcRaw.toString(&model, &generalSettings).toHtmlEscaped(); } str += " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(Helpers::getAdjustmentString(input.weight, &model, true).toHtmlEscaped()); if (input.curve.value) str += " " + input.curve.toString(&model).toHtmlEscaped(); QString flightModesStr = printFlightModes(input.flightModes); if (!flightModesStr.isEmpty()) str += " " + flightModesStr.toHtmlEscaped(); if (input.swtch.type != SWITCH_TYPE_NONE) str += " " + tr("Switch").toHtmlEscaped() + QString("(%1)").arg(input.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped(); if (firmware->getCapability(VirtualInputs)) { if (input.carryTrim>0) str += " " + tr("NoTrim").toHtmlEscaped(); else if (input.carryTrim<0) str += " " + RawSource(SOURCE_TYPE_TRIM, (-(input.carryTrim)-1)).toString(&model, &generalSettings).toHtmlEscaped(); } if (input.offset) str += " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(input.offset, &model)).toHtmlEscaped(); if (firmware->getCapability(HasExpoNames) && input.name[0]) str += QString(" [%1]").arg(input.name).toHtmlEscaped(); return str; } QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, int highlightedSource) { QString str = " "; if (showMultiplex) { switch(mix.mltpx) { case (1): str += "*="; break; case (2): str += ":="; break; default: str += "+="; break; } } else { str += "  "; } // highlight source if needed QString source = mix.srcRaw.toString(&model, &generalSettings).toHtmlEscaped(); if ( (mix.srcRaw.type == SOURCE_TYPE_CH) && (mix.srcRaw.index+1 == (int)highlightedSource) ) { source = "" + source + ""; } str += " " + source; if (mix.mltpx == MLTPX_MUL && !showMultiplex) str += " " + tr("MULT!").toHtmlEscaped(); else str += " " + tr("Weight") + QString("(%1)").arg(Helpers::getAdjustmentString(mix.weight, &model, true)).toHtmlEscaped(); QString flightModesStr = printFlightModes(mix.flightModes); if (!flightModesStr.isEmpty()) str += " " + flightModesStr.toHtmlEscaped(); if (mix.swtch.type != SWITCH_TYPE_NONE) str += " " + tr("Switch") + QString("(%1)").arg(mix.swtch.toString(getCurrentBoard(), &generalSettings)).toHtmlEscaped(); if (mix.carryTrim > 0) str += " " + tr("NoTrim").toHtmlEscaped(); else if (mix.carryTrim < 0) str += " " + RawSource(SOURCE_TYPE_TRIM, (-(mix.carryTrim)-1)).toString(&model, &generalSettings); if (firmware->getCapability(HasNoExpo) && mix.noExpo) str += " " + tr("No DR/Expo").toHtmlEscaped(); if (mix.sOffset) str += " " + tr("Offset") + QString("(%1)").arg(Helpers::getAdjustmentString(mix.sOffset, &model)).toHtmlEscaped(); if (mix.curve.value) str += " " + mix.curve.toString(&model).toHtmlEscaped(); int scale = firmware->getCapability(SlowScale); if (scale == 0) scale = 1; if (mix.delayDown || mix.delayUp) str += " " + tr("Delay") + QString("(u%1:d%2)").arg((double)mix.delayUp/scale).arg((double)mix.delayDown/scale).toHtmlEscaped(); if (mix.speedDown || mix.speedUp) str += " " + tr("Slow") + QString("(u%1:d%2)").arg((double)mix.speedUp/scale).arg((double)mix.speedDown/scale).toHtmlEscaped(); if (mix.mixWarn) str += " " + tr("Warn") + QString("(%1)").arg(mix.mixWarn).toHtmlEscaped(); if (firmware->getCapability(HasMixerNames) && mix.name[0]) str += QString(" [%1]").arg(mix.name).toHtmlEscaped(); return str; } QString ModelPrinter::printFlightModeSwitch(const RawSwitch & swtch) { return swtch.toString(getCurrentBoard(), &generalSettings); } QString ModelPrinter::printFlightModeName(int index) { return model.flightModeData[index].nameToString(index); } QString ModelPrinter::printFlightModes(unsigned int flightModes) { int numFlightModes = firmware->getCapability(FlightModes); if (numFlightModes && flightModes) { if (flightModes == (unsigned int)(1< 1 ? tr("Flight modes") : tr("Flight mode")) + QString("(%1)").arg(list.join(", ")); } } else return ""; } QString ModelPrinter::printInputFlightModes(unsigned int flightModes) { int numFlightModes = firmware->getCapability(FlightModes); if (numFlightModes && flightModes) { if (flightModes == (unsigned int)(1<getCapability(LogicalSwitchesExt)) { if (ls.duration) result += " " + tr("Duration") + QString("(%1s)").arg(ls.duration/10.0); if (ls.delay) result += " " + tr("Delay") + QString("(%1s)").arg(ls.delay/10.0); } return result; } QString ModelPrinter::printCustomFunctionLine(int idx, bool gfunc) { QString result; CustomFunctionData cf; if (gfunc) { if (model.noGlobalFunctions) return result; cf = generalSettings.customFn[idx]; } else cf = model.customFn[idx]; if (cf.swtch.type == SWITCH_TYPE_NONE) return result; result += cf.swtch.toString(getCurrentBoard(), &generalSettings) + " - "; result += cf.funcToString(&model) + " ("; result += cf.paramToString(&model) + ")"; if (!cf.repeatToString().isEmpty()) result += " " + cf.repeatToString(); if (!cf.enabledToString().isEmpty()) result += " " + cf.enabledToString(); return result; } QString ModelPrinter::printCurveName(int idx) { return model.curves[idx].nameToString(idx).toHtmlEscaped(); } QString ModelPrinter::printCurve(int idx) { QString result; const CurveData & curve = model.curves[idx]; result += (curve.type == CurveData::CURVE_TYPE_CUSTOM) ? tr("Custom") : tr("Standard"); result += ", ["; if (curve.type == CurveData::CURVE_TYPE_CUSTOM) { for (int j=0; jaddResource(QTextDocument::ImageResource, QUrl(filename), image.get()); // qDebug() << "ModelPrinter::createCurveImage()" << idx << filename; return filename; } QString ModelPrinter::printGlobalVarUnit(int idx) { return model.gvarData[idx].unitToString().toHtmlEscaped(); } QString ModelPrinter::printGlobalVarPrec(int idx) { return model.gvarData[idx].precToString().toHtmlEscaped(); } QString ModelPrinter::printGlobalVarMin(int idx) { return QString::number(model.gvarData[idx].getMinPrec()); } QString ModelPrinter::printGlobalVarMax(int idx) { return QString::number(model.gvarData[idx].getMaxPrec()); } QString ModelPrinter::printGlobalVarPopup(int idx) { return printBoolean(model.gvarData[idx].popup, BOOLEAN_YN); } QString ModelPrinter::printOutputValueGVar(int val) { QString result = ""; if (abs(val) > 10000) { if (val < 0) result = "-"; result.append(RawSource(SOURCE_TYPE_GVAR, abs(val)-10001).toString(&model)); } else { if (val >= 0) result = "+"; result.append(QString::number((qreal)val/10, 'f', 1) + "%"); } return result; } QString ModelPrinter::printOutputOffset(int idx) { return printOutputValueGVar(model.limitData[idx].offset); } QString ModelPrinter::printOutputMin(int idx) { return printOutputValueGVar(model.limitData[idx].min); } QString ModelPrinter::printOutputMax(int idx) { return printOutputValueGVar(model.limitData[idx].max); } QString ModelPrinter::printOutputRevert(int idx) { return model.limitData[idx].revertToString(); } QString ModelPrinter::printOutputPpmCenter(int idx) { return QString::number(model.limitData[idx].ppmCenter + 1500); } QString ModelPrinter::printOutputCurve(int idx) { return CurveReference(CurveReference::CURVE_REF_CUSTOM, model.limitData[idx].curve.value).toString(&model, false); } QString ModelPrinter::printOutputSymetrical(int idx) { return printBoolean(model.limitData[idx].symetrical, BOOLEAN_YN); } QString ModelPrinter::printSettingsOther() { QStringList str; str << printLabelValue(tr("Extended Limits"), printBoolean(model.extendedLimits, BOOLEAN_YESNO)); if (firmware->getCapability(HasDisplayText)) str << printLabelValue(tr("Display Checklist"), printBoolean(model.displayChecklist, BOOLEAN_YESNO)); if (firmware->getCapability(GlobalFunctions)) str << printLabelValue(tr("Global Functions"), printBoolean(!model.noGlobalFunctions, BOOLEAN_YESNO)); return str.join(" "); } QString ModelPrinter::printSwitchWarnings() { QStringList str; Boards board = firmware->getBoard(); uint64_t switchStates = model.switchWarningStates; uint64_t value; for (int idx=0; idx> (2*idx)) & 0x03; } else { value = (idx==0 ? switchStates & 0x3 : switchStates & 0x1); switchStates >>= (idx==0 ? 2 : 1); } str += RawSwitch(SWITCH_TYPE_SWITCH, 1+idx*3+value).toString(board.getBoardType(), &generalSettings, &model); } } return (str.isEmpty() ? tr("None") : str.join(" ")) ; } QString ModelPrinter::printPotWarnings() { QStringList str; int genAryIdx = 0; Boards board = firmware->getBoard(); if (model.potsWarningMode) { for (int i=0; igetBoard())) str << printLabelValue(tr("Display"), printTrimsDisplayMode()); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO)); return str.join(" "); } QString ModelPrinter::printThrottleSource(int idx) { Boards board = firmware->getBoard(); int chnstart = board.getCapability(Board::Pots)+board.getCapability(Board::Sliders); if (idx == 0) return "THR"; else if (idx < (chnstart+1)) return firmware->getAnalogInputName(idx+board.getCapability(Board::Sticks)-1); else return RawSource(SOURCE_TYPE_CH, idx-chnstart-1).toString(&model, &generalSettings); } QString ModelPrinter::printTrimsDisplayMode() { switch (model.trimsDisplay) { case 0: return tr("Never"); case 1: return tr("On Change"); case 2: return tr("Always"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printModuleType(int idx) { return ModuleData::indexToString(idx, firmware); } QString ModelPrinter::printPxxPower(int power) { static const char *strings[] = { "10mW", "100mW", "500mW", "3W" }; return CHECK_IN_ARRAY(strings, power); } QString ModelPrinter::printThrottle() { QStringList result; result << printLabelValue(tr("Source"), printThrottleSource(model.thrTraceSrc)); result << printLabelValue(tr("Trim idle only"), printBoolean(model.thrTrim, BOOLEAN_YESNO)); result << printLabelValue(tr("Warning"), printBoolean(!model.disableThrottleWarning, BOOLEAN_YESNO)); result << printLabelValue(tr("Reversed"), printBoolean(model.throttleReversed, BOOLEAN_YESNO)); return result.join(" "); } QString ModelPrinter::printPPMFrameLength(int ppmFL) { double result = (((double)ppmFL * 5) + 225) / 10; return QString::number(result); } QString ModelPrinter::printTimerName(int idx) { QString result; result = tr("Tmr") + QString("%1").arg(idx+1); if (firmware->getCapability(TimersName) && model.timers[idx].name[0]) result.append(":" + QString(model.timers[idx].name)); return result; } QString ModelPrinter::printTimerTimeValue(unsigned int val) { return printTimeValue(val, MASK_TIMEVALUE_HRSMINS | MASK_TIMEVALUE_ZEROHRS); } QString ModelPrinter::printTimerMinuteBeep(bool mb) { return printBoolean(mb, BOOLEAN_YESNO); } QString ModelPrinter::printTelemetryProtocol(unsigned int val) { switch (val) { case 0: return tr("FrSky S.PORT"); case 1: return tr("FrSky D"); case 2: return tr("FrSky D (cable)"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printRssiAlarmsDisabled(bool mb) { return printBoolean(!mb, BOOLEAN_ENABLEDISABLE); } QString ModelPrinter::printTelemetrySource(int val) { QStringList strings = QStringList() << tr("None"); for (unsigned i=1; i<=CPN_MAX_SENSORS; ++i) { strings << QString("%1").arg(model.sensorData[i-1].label); } return QString("%1%2").arg((val < 0 ? "-" : "")).arg(strings.value(abs(val))); } QString ModelPrinter::printVarioSource(unsigned int val) { switch (val) { case TELEMETRY_VARIO_SOURCE_ALTI: return tr("Alti"); case TELEMETRY_VARIO_SOURCE_ALTI_PLUS: return tr("Alti+"); case TELEMETRY_VARIO_SOURCE_VSPEED: return tr("VSpeed"); case TELEMETRY_VARIO_SOURCE_A1: return tr("A1"); case TELEMETRY_VARIO_SOURCE_A2: return tr("A2"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printVarioCenterSilent(bool mb) { return printBoolean(mb, BOOLEAN_YESNO); } QString ModelPrinter::printVoltsSource(unsigned int val) { switch (val) { case TELEMETRY_VOLTS_SOURCE_A1: return tr("A1"); case TELEMETRY_VOLTS_SOURCE_A2: return tr("A2"); case TELEMETRY_VOLTS_SOURCE_A3: return tr("A3"); case TELEMETRY_VOLTS_SOURCE_A4: return tr("A4"); case TELEMETRY_VOLTS_SOURCE_FAS: return tr("FAS"); case TELEMETRY_VOLTS_SOURCE_CELLS: return tr("Cells"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printCurrentSource(unsigned int val) { switch (val) { case TELEMETRY_CURRENT_SOURCE_NONE: return tr("None"); case TELEMETRY_CURRENT_SOURCE_A1: return tr("A1"); case TELEMETRY_CURRENT_SOURCE_A2: return tr("A2"); case TELEMETRY_CURRENT_SOURCE_A3: return tr("A3"); case TELEMETRY_CURRENT_SOURCE_A4: return tr("A4"); case TELEMETRY_CURRENT_SOURCE_FAS: return tr("FAS"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printMahPersistent(bool mb) { return printBoolean(mb, BOOLEAN_YESNO); } QString ModelPrinter::printIgnoreSensorIds(bool mb) { return printBoolean(mb, BOOLEAN_ENABLEDISABLE); } QString ModelPrinter::printSensorType(unsigned int val) { switch (val) { case SensorData::TELEM_TYPE_CUSTOM: return tr("Custom"); case SensorData::TELEM_TYPE_CALCULATED: return tr("Calculated"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printSensorFormula(unsigned int val) { switch (val) { case SensorData::TELEM_FORMULA_ADD: return tr("Add"); case SensorData::TELEM_FORMULA_AVERAGE: return tr("Average"); case SensorData::TELEM_FORMULA_MIN: return tr("Min"); case SensorData::TELEM_FORMULA_MAX: return tr("Max"); case SensorData::TELEM_FORMULA_MULTIPLY: return tr("Multiply"); case SensorData::TELEM_FORMULA_TOTALIZE: return tr("Totalise"); case SensorData::TELEM_FORMULA_CELL: return tr("Cell"); case SensorData::TELEM_FORMULA_CONSUMPTION: return tr("Consumption"); case SensorData::TELEM_FORMULA_DIST: return tr("Distance"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printSensorCells(unsigned int val) { QStringList strings; strings << tr("Lowest"); for (int i=1; i<=6; i++) strings << tr("Cell %1").arg(i); strings << tr("Highest") << tr("Delta"); return strings.value(val); } QString ModelPrinter::printSensorTypeCond(unsigned int idx) { if (!model.sensorData[idx].isAvailable()) return ""; else return printSensorType(model.sensorData[idx].type); } QString ModelPrinter::printSensorDetails(unsigned int idx) { QString str = ""; SensorData sensor = model.sensorData[idx]; if (!sensor.isAvailable()) return str; bool isConfigurable = false; bool gpsFieldsPrinted = false; bool cellsFieldsPrinted = false; bool consFieldsPrinted = false; bool ratioFieldsPrinted = false; bool totalizeFieldsPrinted = false; bool sources12FieldsPrinted = false; bool sources34FieldsPrinted = false; str.append(doTableCell(printSensorTypeCond(idx))); QString tc = ""; if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) { isConfigurable = (sensor.formula < SensorData::TELEM_FORMULA_CELL); gpsFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_DIST); cellsFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_CELL); consFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_CONSUMPTION); sources12FieldsPrinted = (sensor.formula <= SensorData::TELEM_FORMULA_MULTIPLY); sources34FieldsPrinted = (sensor.formula < SensorData::TELEM_FORMULA_MULTIPLY); totalizeFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_TOTALIZE); tc.append(printLabelValue(tr("Formula"), printSensorFormula(sensor.formula))); } else { isConfigurable = sensor.unit < SensorData::UNIT_FIRST_VIRTUAL; ratioFieldsPrinted = (sensor.unit < SensorData::UNIT_FIRST_VIRTUAL); tc.append(printLabelValue(tr("Id"), QString::number(sensor.id,16).toUpper())); tc.append(printLabelValue(tr("Instance"), QString::number(sensor.instance))); } if (cellsFieldsPrinted) { tc.append(printLabelValue(tr("Sensor"), QString("%1 > %2").arg(printTelemetrySource(sensor.source), false).arg(printSensorCells(sensor.index)))); } if (sources12FieldsPrinted) { QStringList srcs; for (int i=0;i<4;i++) { if (i < 2 || sources34FieldsPrinted) { srcs << printTelemetrySource(sensor.sources[i]); } } tc.append(printLabelValues(tr("Sources"), srcs)); } if (consFieldsPrinted || totalizeFieldsPrinted) tc.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor.amps))); if (gpsFieldsPrinted) { tc.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor.gps))); tc.append(printLabelValue(tr("Alt."), printTelemetrySource(sensor.alt))); } if (ratioFieldsPrinted && sensor.unit == SensorData::UNIT_RPMS) { tc.append(printLabelValue(tr("Blades"), QString::number(sensor.ratio))); tc.append(printLabelValue(tr("Multi."), QString::number(sensor.offset))); } str.append(doTableCell(tc)); tc = sensor.unitString(); tc = tc.trimmed() == "" ? "-" : tc; str.append(doTableCell(tc)); if (isConfigurable && sensor.unit != SensorData::UNIT_FAHRENHEIT) tc = QString::number(sensor.prec); else tc = ""; str.append(doTableCell(tc)); if (!ratioFieldsPrinted) { str.append(doTableCell("")); str.append(doTableCell("")); } else if (sensor.unit != SensorData::UNIT_RPMS) { int prec = sensor.prec == 0 ? 1 : pow(10, sensor.prec); str.append(doTableCell(QString::number((float)sensor.ratio / prec))); str.append(doTableCell(QString::number((float)sensor.offset / prec))); } if (sensor.unit != SensorData::UNIT_RPMS && isConfigurable) str.append(doTableCell(printBoolean(sensor.autoOffset, BOOLEAN_YN))); else str.append(doTableCell("")); if (isConfigurable) str.append(doTableCell(printBoolean(sensor.filter, BOOLEAN_YN))); else str.append(doTableCell("")); if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) str.append(doTableCell(printBoolean(sensor.persistent, BOOLEAN_YN))); else str.append(doTableCell("")); str.append(doTableCell(printBoolean(sensor.onlyPositive, BOOLEAN_YN))); str.append(doTableCell(printBoolean(sensor.logs, BOOLEAN_YN), false)); return str; } QString ModelPrinter::printSensorParams(unsigned int idx) { QString str = ""; SensorData sensor = model.sensorData[idx]; if (!sensor.isAvailable()) return str; bool isConfigurable = false; bool gpsFieldsPrinted = false; bool cellsFieldsPrinted = false; bool consFieldsPrinted = false; bool ratioFieldsPrinted = false; bool totalizeFieldsPrinted = false; bool sources12FieldsPrinted = false; bool sources34FieldsPrinted = false; if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) { isConfigurable = (sensor.formula < SensorData::TELEM_FORMULA_CELL); gpsFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_DIST); cellsFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_CELL); consFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_CONSUMPTION); sources12FieldsPrinted = (sensor.formula <= SensorData::TELEM_FORMULA_MULTIPLY); sources34FieldsPrinted = (sensor.formula < SensorData::TELEM_FORMULA_MULTIPLY); totalizeFieldsPrinted = (sensor.formula == SensorData::TELEM_FORMULA_TOTALIZE); str.append(printLabelValue(tr("F"), printSensorFormula(sensor.formula))); } else { isConfigurable = sensor.unit < SensorData::UNIT_FIRST_VIRTUAL; ratioFieldsPrinted = (sensor.unit < SensorData::UNIT_FIRST_VIRTUAL); str.append(printLabelValue(tr("Id"), QString::number(sensor.id,16).toUpper())); str.append(printLabelValue(tr("Inst"), QString::number(sensor.instance))); } if (cellsFieldsPrinted) { str.append(printLabelValue(tr("Sensor"), QString("%1 %2").arg(printTelemetrySource(sensor.source), false).arg(printSensorCells(sensor.index)))); } if (sources12FieldsPrinted) { QStringList srcs; for (int i=0;i<4;i++) { if (i < 2 || sources34FieldsPrinted) { srcs << printTelemetrySource(sensor.sources[i]); } } str.append(printLabelValues(tr("Sources"), srcs)); } if (consFieldsPrinted || totalizeFieldsPrinted) str.append(printLabelValue(tr("Sensor"), printTelemetrySource(sensor.amps))); if (gpsFieldsPrinted) { str.append(printLabelValue(tr("GPS"), printTelemetrySource(sensor.gps))); str.append(printLabelValue(tr("Alt"), printTelemetrySource(sensor.alt))); } QString u = sensor.unitString(); u = u.trimmed() == "" ? "-" : u; str.append(printLabelValue(tr("Unit"), u)); if (isConfigurable && sensor.unit != SensorData::UNIT_FAHRENHEIT) str.append(printLabelValue(tr("Prec"), QString::number(sensor.prec))); if (ratioFieldsPrinted) { if (sensor.unit != SensorData::UNIT_RPMS) { int prec = sensor.prec == 0 ? 1 : pow(10, sensor.prec); str.append(printLabelValue(tr("Ratio"), QString::number((float)sensor.ratio / prec))); str.append(printLabelValue(tr("Offset"), QString::number((float)sensor.offset / prec))); } else if (sensor.unit == SensorData::UNIT_RPMS) { str.append(printLabelValue(tr("Blades"), QString::number(sensor.ratio))); str.append(printLabelValue(tr("Multi"), QString::number(sensor.offset))); } } if (sensor.unit != SensorData::UNIT_RPMS && isConfigurable) str.append(printLabelValue(tr("A/Offset"), printBoolean(sensor.autoOffset, BOOLEAN_YN))); if (isConfigurable) str.append(printLabelValue(tr("Filter"), printBoolean(sensor.filter, BOOLEAN_YN))); if (sensor.type == SensorData::TELEM_TYPE_CALCULATED) str.append(printLabelValue(tr("Persist"), printBoolean(sensor.persistent, BOOLEAN_YN))); str.append(printLabelValue(tr("Positive"), printBoolean(sensor.onlyPositive, BOOLEAN_YN))); str.append(printLabelValue(tr("Log"), printBoolean(sensor.logs, BOOLEAN_YN), false)); return str; } QString ModelPrinter::printTelemetryScreenType(unsigned int val) { switch (val) { case TelemetryScreenEnum::TELEMETRY_SCREEN_NONE: return tr("None"); case TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS: return tr("Numbers"); case TelemetryScreenEnum::TELEMETRY_SCREEN_BARS: return tr("Bars"); case TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT: return tr("Script"); default: return CPN_STR_UNKNOWN_ITEM; } } QString ModelPrinter::printTelemetryScreen(unsigned int idx, unsigned int line, unsigned int width) { QStringList strl; QStringList hd; FrSkyScreenData screen = model.frsky.screens[idx]; hd << ""; // blank 1st column strl << ""; if (screen.type == TelemetryScreenEnum::TELEMETRY_SCREEN_NUMBERS) { if (line == 0) { for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) { hd << tr("Source"); } } for (int c=0; cgetCapability(TelemetryCustomScreensFieldsPerLine); c++) { RawSource source = screen.body.lines[line].source[c]; strl << source.toString(&model, &generalSettings); } } else if (screen.type == TelemetryScreenEnum::TELEMETRY_SCREEN_BARS) { if (line == 0) { hd << tr("Source") << tr("Min") << tr("Max"); } RawSource source = screen.body.bars[line].source; RawSourceRange range = source.getRange(&model, generalSettings); strl << source.toString(&model, &generalSettings); QString unit; QString minstr; QString maxstr; if (source.isTimeBased()){ minstr = printTimeValue((float)screen.body.bars[line].barMin, MASK_TIMEVALUE_HRSMINS); maxstr = printTimeValue((float)screen.body.bars[line].barMax, MASK_TIMEVALUE_HRSMINS); } else { minstr = QString::number(range.getValue(screen.body.bars[line].barMin)); maxstr = QString::number(range.getValue(screen.body.bars[line].barMax)); unit = range.unit; } strl << QString("%1%2").arg(minstr).arg(unit); strl << QString("%1%2").arg(maxstr).arg(unit); } else if (screen.type == TelemetryScreenEnum::TELEMETRY_SCREEN_SCRIPT && line == 0) { hd << tr("Filename"); strl << QString("%1.lua").arg(screen.body.script.filename); } return (hd.count() > 1 ? doTableRow(hd, width / hd.count(), "left", "", true) : "" ) + doTableRow(strl, width / strl.count()); } QString ModelPrinter::printChecklist() { if (!model.displayChecklist) return ""; QString str = tr("Error: Unable to open or read file!"); QFile file(Helpers::getChecklistFilePath(&model)); if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream in(&file); if (in.status() == QTextStream::Ok) { str = in.readAll(); str.replace("\n", "
"); str.remove("\r"); } file.close(); } return str; }