diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index ae3ef3ef2..3b63779c2 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -168,6 +168,7 @@ set(companion_SRCS flashfirmwaredialog.cpp flasheepromdialog.cpp printdialog.cpp + modelprinter.cpp fusesdialog.cpp logsdialog.cpp downloaddialog.cpp diff --git a/companion/src/comparedialog.cpp b/companion/src/comparedialog.cpp index b6be51ce4..2e1325c2e 100644 --- a/companion/src/comparedialog.cpp +++ b/companion/src/comparedialog.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #if !defined WIN32 && defined __GNUC__ #include @@ -28,9 +29,11 @@ public: CompareDialog::CompareDialog(QWidget * parent, Firmware * firmware): QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), firmware(firmware), - model1(0), - model2(0), - ui(new Ui::CompareDialog) + model1Valid(false), + model2Valid(false), + ui(new Ui::CompareDialog), + modelPrinter1(firmware, &dummySettings, &g_model1), + modelPrinter2(firmware, &dummySettings, &g_model2) { ui->setupUi(this); @@ -38,10 +41,6 @@ CompareDialog::CompareDialog(QWidget * parent, Firmware * firmware): te = ui->textEdit; this->setAcceptDrops(true); - // TODO this is really horrible - g_model1=(ModelData *)malloc(sizeof(ModelData)); - g_model2=(ModelData *)malloc(sizeof(ModelData)); - modeltemp=(ModelData *)malloc(sizeof(ModelData)); //setDragDropOverwriteMode(true); //setDropIndicatorShown(true); @@ -77,85 +76,60 @@ void CompareDialog::dragLeaveEvent(QDragLeaveEvent *event) void CompareDialog::printDiff() { te->clear(); + curvefile1=generateProcessUniqueTempFileName("curve1.png"); + curvefile2=generateProcessUniqueTempFileName("curve2.png"); printSetup(); if (GetCurrentFirmware()->getCapability(FlightModes)) { printPhases(); } - curvefile1=generateProcessUniqueTempFileName("curve1.png"); - curvefile2=generateProcessUniqueTempFileName("curve2.png"); - printExpos(); + printInputs(); printMixers(); printLimits(); printCurves(); printGvars(); - printSwitches(); - printFSwitches(); + printLogicalSwitches(); + printCustomFunctions(); printFrSky(); te->scrollToAnchor("1"); } +bool CompareDialog::handleDroppedModel(const QMimeData * mimeData, ModelData * model, QLabel * label) +{ + if(mimeData->hasFormat("application/x-companion")) { + QByteArray gmData = mimeData->data("application/x-companion"); + DragDropHeader *header = (DragDropHeader *)gmData.data(); + if (!header->general_settings) { + char *gData = gmData.data()+sizeof(DragDropHeader); + if(gData[0] == 'M') { + ModelData * modeltemp = (ModelData *)(gData + 1); + if (modeltemp->used) { + memcpy(model, modeltemp, sizeof(ModelData)); + QString name(model->name); + if (!name.isEmpty()) { + label->setText(name); + } else { + label->setText(tr("No name")); + } + return true; + } + } + } + } + return false; +} + void CompareDialog::dropEvent(QDropEvent *event) { QLabel *child = qobject_cast(childAt(event->pos())); - const QMimeData *mimeData = event->mimeData(); - if (child) { - if (child->objectName().contains("label_1")) { - if(mimeData->hasFormat("application/x-companion")) { - QByteArray gmData = mimeData->data("application/x-companion"); - DragDropHeader *header = (DragDropHeader *)gmData.data(); - if (!header->general_settings) { - char *gData = gmData.data()+sizeof(DragDropHeader);//new char[gmData.size() + 1]; - char c = *gData; - gData++; - if(c=='M') { - memcpy(modeltemp,(ModelData *)gData,sizeof(ModelData)); - if (modeltemp->used) { - memcpy(g_model1,(ModelData *)gData,sizeof(ModelData)); - QString name; - name.append(g_model1->name); - if (!name.isEmpty()) { - ui->label_1->setText(name); - } else { - ui->label_1->setText(tr("No name")); - } - model1=1; - } - } - } - } - } - else if (child->objectName().contains("label_2")) { - if (mimeData->hasFormat("application/x-companion")) { - QByteArray gmData = mimeData->data("application/x-companion"); - DragDropHeader *header = (DragDropHeader *)gmData.data(); - if (!header->general_settings) { - char *gData = gmData.data()+sizeof(DragDropHeader);//new char[gmData.size() + 1]; - char c = *gData; - gData++; - if(c=='M') { - memcpy(modeltemp,(ModelData *)gData,sizeof(ModelData)); - if (modeltemp->used) { - memcpy(g_model2,(ModelData *)gData,sizeof(ModelData)); - QString name; - name.append(g_model2->name); - if (!name.isEmpty()) { - ui->label_2->setText(name); - } else { - ui->label_2->setText(tr("No name")); - } - model2=1; - } - } - } - } - } - } else { - return; + if (!child) return; + if (child->objectName().contains("label_1")) { + model1Valid = handleDroppedModel(event->mimeData(), &g_model1, ui->label_1); + } + else if (child->objectName().contains("label_2")) { + model2Valid = handleDroppedModel(event->mimeData(), &g_model2, ui->label_2); } event->accept(); - if ((model1==1) & (model2==1)) { - printDiff(); - } + if (model1Valid && model2Valid) printDiff(); } void CompareDialog::closeEvent(QCloseEvent *event) @@ -169,16 +143,6 @@ CompareDialog::~CompareDialog() delete ui; } -int CompareDialog::ModelHasExpo(ExpoData * ExpoArray, ExpoData expo, bool * expoused) -{ - for (int i=0; i< C9X_MAX_EXPOS; i++) { - if ((memcmp(&expo,&ExpoArray[i],sizeof(ExpoData))==0) && (expoused[i]==false)) { - return i; - } - } - return -1; -} - bool CompareDialog::ChannelHasExpo(ExpoData * expoArray, uint8_t destCh) { for (int i=0; i< C9X_MAX_EXPOS; i++) { @@ -189,16 +153,6 @@ bool CompareDialog::ChannelHasExpo(ExpoData * expoArray, uint8_t destCh) return false; } -int CompareDialog::ModelHasMix(MixData * mixArray, MixData mix, bool * mixused) -{ - for (int i=0; i< C9X_MAX_MIXERS; i++) { - if ((memcmp(&mix,&mixArray[i],sizeof(MixData))==0) && (mixused[i]==false)) { - return i; - } - } - return -1; -} - bool CompareDialog::ChannelHasMix(MixData * mixArray, uint8_t destCh) { for (int i=0; i< C9X_MAX_MIXERS; i++) { @@ -215,40 +169,64 @@ void CompareDialog::printSetup() QString str = ""; str.append(""); str.append(""); str.append("

"+tr("General Model Settings")+"

"); - color=getColor1(g_model1->name,g_model2->name); - str.append(fv(tr("Name"), g_model1->name, color)); - color=getColor1(GetEepromInterface()->getSize(*g_model1), GetEepromInterface()->getSize(*g_model2)); - str.append(""+tr("EEprom Size")+QString(": %1
").arg(GetEepromInterface()->getSize(*g_model1)).arg(color)); - color=getColor1(getTimerStr(g_model1->timers[0]), getTimerStr(g_model2->timers[0])); - str.append(fv(tr("Timer1"), getTimerStr(g_model1->timers[0]), color)); //value, mode, count up/down - color=getColor1(getTimerStr(g_model1->timers[1]), getTimerStr(g_model2->timers[1])); - str.append(fv(tr("Timer2"), getTimerStr(g_model1->timers[1]), color)); //value, mode, count up/down - color=getColor1(getProtocol(g_model1->moduleData[0]),getProtocol(g_model2->moduleData[0])); - str.append(fv(tr("Protocol"), getProtocol(g_model1->moduleData[0]), color)); //proto, numch, delay, - color=getColor1(g_model1->thrTrim,g_model2->thrTrim); - str.append(fv(tr("Throttle Trim"), g_model1->thrTrim ? tr("Enabled") : tr("Disabled"), color)); - color=getColor1(getTrimInc(g_model1),getTrimInc(g_model2)); - str.append(fv(tr("Trim Increment"), getTrimInc(g_model1),color)); - color = getColor1(getCenterBeepStr(g_model1), getCenterBeepStr(g_model2)); - str.append(fv(tr("Center Beep"), getCenterBeepStr(g_model1), color)); // specify which channels beep + color=getColor1(g_model1.name,g_model2.name); + str.append(fv(tr("Name"), g_model1.name, color)); + color=getColor1(GetEepromInterface()->getSize(g_model1), GetEepromInterface()->getSize(g_model2)); + str.append(""+tr("EEprom Size")+QString(": %1
").arg(GetEepromInterface()->getSize(g_model1)).arg(color)); + color=getColor1(getTimerStr(g_model1.timers[0]), getTimerStr(g_model2.timers[0])); + str.append(fv(tr("Timer1"), getTimerStr(g_model1.timers[0]), color)); //value, mode, count up/down + color=getColor1(getTimerStr(g_model1.timers[1]), getTimerStr(g_model2.timers[1])); + str.append(fv(tr("Timer2"), getTimerStr(g_model1.timers[1]), color)); //value, mode, count up/down + color=getColor1(getProtocol(g_model1.moduleData[0]),getProtocol(g_model2.moduleData[0])); + if (firmware->getCapability(NumModules)>1) { + str.append(""+(IS_TARANIS(firmware->getBoard()) ? tr("Internal Radio System") : tr("Radio System") )+"
  "); //proto, numch, delay, + } + str.append(fv(tr("Protocol"), getProtocol(g_model1.moduleData[0]),color)); + if (firmware->getCapability(NumModules)>1) { + color=getColor1(getProtocol(g_model1.moduleData[1]),getProtocol(g_model2.moduleData[1])); + str.append(""+(IS_TARANIS(firmware->getBoard()) ? tr("External Radio Module") : tr("Extra Radio System"))+"
  "); //proto, numch, delay, + str.append(fv(tr("Protocol"), getProtocol(g_model1.moduleData[1]),color)); + } + if (IS_TARANIS(firmware->getBoard())){ + color=getColor1(getTrainerMode(g_model1.trainerMode, g_model1.moduleData[2]),getTrainerMode(g_model2.trainerMode, g_model2.moduleData[2])); + str.append(fv(tr("Trainer port mode"), getTrainerMode(g_model1.trainerMode, g_model1.moduleData[2]),color)); + } + color=getColor1(g_model1.thrTrim,g_model2.thrTrim); + str.append(fv(tr("Throttle Trim"), g_model1.thrTrim ? tr("Enabled") : tr("Disabled"), color)); + color=getColor1(getTrimInc(&g_model1),getTrimInc(&g_model2)); + str.append(fv(tr("Trim Increment"), getTrimInc(&g_model1),color)); + color = getColor1(getCenterBeepStr(&g_model1), getCenterBeepStr(&g_model2)); + str.append(fv(tr("Center Beep"), getCenterBeepStr(&g_model1), color)); // specify which channels beep str.append("
"); - color=getColor2(g_model1->name,g_model2->name); - str.append(fv(tr("Name"), g_model2->name, color)); - color=getColor2(GetEepromInterface()->getSize(*g_model1), GetEepromInterface()->getSize(*g_model2)); - str.append(""+tr("EEprom Size")+QString(": %1
").arg(GetEepromInterface()->getSize(*g_model2)).arg(color)); - color=getColor2(getTimerStr(g_model1->timers[0]), getTimerStr(g_model2->timers[0])); - str.append(fv(tr("Timer1"), getTimerStr(g_model2->timers[0]),color)); //value, mode, count up/down - color=getColor2(getTimerStr(g_model1->timers[1]), getTimerStr(g_model2->timers[1])); - str.append(fv(tr("Timer2"), getTimerStr(g_model2->timers[1]),color)); //value, mode, count up/down - color=getColor2(getProtocol(g_model1->moduleData[0]),getProtocol(g_model2->moduleData[0])); - str.append(fv(tr("Protocol"), getProtocol(g_model2->moduleData[0]), color)); //proto, numch, delay, - color=getColor2(g_model1->thrTrim,g_model2->thrTrim); - str.append(fv(tr("Throttle Trim"), g_model2->thrTrim ? tr("Enabled") : tr("Disabled"), color)); - color=getColor2(getTrimInc(g_model1),getTrimInc(g_model2)); - str.append(fv(tr("Trim Increment"), getTrimInc(g_model2),color)); - color = getColor2(getCenterBeepStr(g_model1),getCenterBeepStr(g_model2)); - str.append(fv(tr("Center Beep"), getCenterBeepStr(g_model2), color)); // specify which channels beep + color=getColor2(g_model1.name,g_model2.name); + str.append(fv(tr("Name"), g_model2.name, color)); + color=getColor2(GetEepromInterface()->getSize(g_model1), GetEepromInterface()->getSize(g_model2)); + str.append(""+tr("EEprom Size")+QString(": %1
").arg(GetEepromInterface()->getSize(g_model2)).arg(color)); + color=getColor2(getTimerStr(g_model1.timers[0]), getTimerStr(g_model2.timers[0])); + str.append(fv(tr("Timer1"), getTimerStr(g_model2.timers[0]),color)); //value, mode, count up/down + color=getColor2(getTimerStr(g_model1.timers[1]), getTimerStr(g_model2.timers[1])); + str.append(fv(tr("Timer2"), getTimerStr(g_model2.timers[1]),color)); //value, mode, count up/down + color=getColor2(getProtocol(g_model1.moduleData[0]),getProtocol(g_model2.moduleData[0])); + if (firmware->getCapability(NumModules)>1) { + str.append(""+(IS_TARANIS(firmware->getBoard()) ? tr("Internal Radio System") : tr("Radio System") )+"
  "); //proto, numch, delay, + } + str.append(fv(tr("Protocol"), getProtocol(g_model2.moduleData[0]),color)); + if (firmware->getCapability(NumModules)>1) { + color=getColor2(getProtocol(g_model1.moduleData[1]),getProtocol(g_model2.moduleData[1])); + str.append(""+(IS_TARANIS(firmware->getBoard()) ? tr("External Radio Module") : tr("Extra Radio System"))+"
  "); //proto, numch, delay, + str.append(fv(tr("Protocol"), getProtocol(g_model2.moduleData[1]),color)); + } + if (IS_TARANIS(firmware->getBoard())){ + color=getColor2(getTrainerMode(g_model1.trainerMode, g_model1.moduleData[2]),getTrainerMode(g_model2.trainerMode, g_model2.moduleData[2])); + str.append(fv(tr("Trainer port mode"), getTrainerMode(g_model2.trainerMode, g_model2.moduleData[2]),color)); + } + color=getColor2(g_model1.thrTrim,g_model2.thrTrim); + str.append(fv(tr("Throttle Trim"), g_model2.thrTrim ? tr("Enabled") : tr("Disabled"), color)); + color=getColor2(getTrimInc(&g_model1),getTrimInc(&g_model2)); + str.append(fv(tr("Trim Increment"), getTrimInc(&g_model2),color)); + color = getColor2(getCenterBeepStr(&g_model1),getCenterBeepStr(&g_model2)); + str.append(fv(tr("Center Beep"), getCenterBeepStr(&g_model2), color)); // specify which channels beep str.append("
"); te->append(str); } @@ -265,12 +243,12 @@ void CompareDialog::printPhases() str.append(""+tr("Switch")+""+tr("Flight mode name")); str.append(""+tr("IN")+""+tr("OUT")+""); for (i=0; i<4; i++) { - str.append(QString("%1").arg(getInputStr(g_model1, i))); + str.append(QString("%1").arg(modelPrinter1.printInputName(i))); } str.append(""); for (i=0; igetCapability(FlightModes); i++) { - FlightModeData *pd1=&g_model1->flightModeData[i]; - FlightModeData *pd2=&g_model2->flightModeData[i]; + FlightModeData *pd1=&g_model1.flightModeData[i]; + FlightModeData *pd2=&g_model2.flightModeData[i]; str.append(""+tr("FM")+QString("%1 ").arg(i)); color=getColor1(pd1->name,pd2->name); str.append(QString("%1").arg(pd1->name).arg(color)); @@ -305,7 +283,7 @@ void CompareDialog::printPhases() str.append(""+tr("Flight mode name")+""); if (GetCurrentFirmware()->getCapability(GvarsFlightModes)) { for (i=0; iGV%1
%2").arg(i+1).arg(g_model1->gvars_names[i])); + str.append(QString("GV%1
%2").arg(i+1).arg(g_model1.gvars_names[i])); } } for (i=0; igetCapability(RotaryEncoders); i++) { @@ -313,8 +291,8 @@ void CompareDialog::printPhases() } str.append(""); for (i=0; igetCapability(FlightModes); i++) { - FlightModeData *pd1=&g_model1->flightModeData[i]; - FlightModeData *pd2=&g_model2->flightModeData[i]; + FlightModeData *pd1=&g_model1.flightModeData[i]; + FlightModeData *pd2=&g_model2.flightModeData[i]; str.append(""+tr("FM")+QString("%1 ").arg(i)); color=getColor1(pd1->name,pd2->name); str.append(QString("%1").arg(pd1->name).arg(color)); @@ -354,12 +332,12 @@ void CompareDialog::printPhases() str.append(""+tr("Switch")+""+tr("Flight mode name")); str.append(""+tr("IN")+""+tr("OUT")+""); for (i=0; i<4; i++) { - str.append(QString("%1").arg(getInputStr(g_model1, i))); + str.append(QString("%1").arg(modelPrinter2.printInputName(i))); } str.append(""); for (i=0; igetCapability(FlightModes); i++) { - FlightModeData *pd1=&g_model1->flightModeData[i]; - FlightModeData *pd2=&g_model2->flightModeData[i]; + FlightModeData *pd1=&g_model1.flightModeData[i]; + FlightModeData *pd2=&g_model2.flightModeData[i]; str.append(""+tr("FM")+QString("%1 ").arg(i)); color=getColor2(pd1->name,pd2->name); str.append(QString("%1").arg(pd2->name).arg(color)); @@ -394,7 +372,7 @@ void CompareDialog::printPhases() str.append(""+tr("Flight mode name")+""); if (GetCurrentFirmware()->getCapability(GvarsFlightModes)) { for (i=0; iGV%1
%2").arg(i+1).arg(g_model2->gvars_names[i])); + str.append(QString("GV%1
%2").arg(i+1).arg(g_model2.gvars_names[i])); } } for (i=0; igetCapability(RotaryEncoders); i++) { @@ -402,8 +380,8 @@ void CompareDialog::printPhases() } str.append(""); for (i=0; igetCapability(FlightModes); i++) { - FlightModeData *pd1=&g_model1->flightModeData[i]; - FlightModeData *pd2=&g_model2->flightModeData[i]; + FlightModeData *pd1=&g_model1.flightModeData[i]; + FlightModeData *pd2=&g_model2.flightModeData[i]; str.append(""+tr("FM")+QString("%1 ").arg(i)); color=getColor1(pd1->name,pd2->name); str.append(QString("%1").arg(pd2->name).arg(color)); @@ -453,8 +431,8 @@ void CompareDialog::printLimits() for(int i=0; igetCapability(Outputs); i++) { str.append(""); if (GetCurrentFirmware()->getCapability(HasChNames)) { - QString name1=g_model1->limitData[i].name; - QString name2=g_model2->limitData[i].name; + QString name1=g_model1.limitData[i].name; + QString name2=g_model2.limitData[i].name; color=getColor1(name1,name2); if (name1.trimmed().isEmpty()) { str.append(doTC(tr("CH")+QString(" %1").arg(i+1,2,10,QChar('0')),color,true)); @@ -464,14 +442,14 @@ void CompareDialog::printLimits() } else { str.append(doTC(tr("CH")+QString(" %1").arg(i+1,2,10,QChar('0')),"",true)); } - color=getColor1(g_model1->limitData[i].offset,g_model2->limitData[i].offset); - str.append(doTR(g_model1->limitData[i].offsetToString(), color)); - color=getColor1(g_model1->limitData[i].min,g_model2->limitData[i].min); - str.append(doTR(g_model1->limitData[i].minToString(), color)); - color=getColor1(g_model1->limitData[i].max,g_model2->limitData[i].max); - str.append(doTR(g_model1->limitData[i].maxToString(), color)); - color=getColor1(g_model1->limitData[i].revert,g_model2->limitData[i].revert); - str.append(doTR(QString(g_model1->limitData[i].revert ? tr("INV") : tr("NOR")),color)); + color=getColor1(g_model1.limitData[i].offset,g_model2.limitData[i].offset); + str.append(doTR(g_model1.limitData[i].offsetToString(), color)); + color=getColor1(g_model1.limitData[i].min,g_model2.limitData[i].min); + str.append(doTR(g_model1.limitData[i].minToString(), color)); + color=getColor1(g_model1.limitData[i].max,g_model2.limitData[i].max); + str.append(doTR(g_model1.limitData[i].maxToString(), color)); + color=getColor1(g_model1.limitData[i].revert,g_model2.limitData[i].revert); + str.append(doTR(QString(g_model1.limitData[i].revert ? tr("INV") : tr("NOR")),color)); str.append(""); } str.append(""); @@ -480,8 +458,8 @@ void CompareDialog::printLimits() for(int i=0; igetCapability(Outputs); i++) { str.append(""); if (GetCurrentFirmware()->getCapability(HasChNames)) { - QString name1=g_model1->limitData[i].name; - QString name2=g_model2->limitData[i].name; + QString name1=g_model1.limitData[i].name; + QString name2=g_model2.limitData[i].name; color=getColor2(name1,name2); if (name2.trimmed().isEmpty()) { str.append(doTC(tr("CH")+QString(" %1").arg(i+1,2,10,QChar('0')),color,true)); @@ -491,14 +469,14 @@ void CompareDialog::printLimits() } else { str.append(doTC(tr("CH")+QString(" %1").arg(i+1,2,10,QChar('0')),"",true)); } - color=getColor2(g_model1->limitData[i].offset,g_model2->limitData[i].offset); - str.append(doTR(g_model2->limitData[i].offsetToString(), color)); - color=getColor2(g_model1->limitData[i].min,g_model2->limitData[i].min); - str.append(doTR(g_model2->limitData[i].minToString(), color)); - color=getColor2(g_model1->limitData[i].max,g_model2->limitData[i].max); - str.append(doTR(g_model2->limitData[i].maxToString(), color)); - color=getColor2(g_model1->limitData[i].revert,g_model2->limitData[i].revert); - str.append(doTR(QString(g_model2->limitData[i].revert ? tr("INV") : tr("NOR")),color)); + color=getColor2(g_model1.limitData[i].offset,g_model2.limitData[i].offset); + str.append(doTR(g_model2.limitData[i].offsetToString(), color)); + color=getColor2(g_model1.limitData[i].min,g_model2.limitData[i].min); + str.append(doTR(g_model2.limitData[i].minToString(), color)); + color=getColor2(g_model1.limitData[i].max,g_model2.limitData[i].max); + str.append(doTR(g_model2.limitData[i].maxToString(), color)); + color=getColor2(g_model1.limitData[i].revert,g_model2.limitData[i].revert); + str.append(doTR(QString(g_model2.limitData[i].revert ? tr("INV") : tr("NOR")),color)); str.append(""); } str.append(""); @@ -515,8 +493,8 @@ void CompareDialog::printGvars() str.append("

"+tr("Global Variables")+"

"); str.append(""); str.append(""); - FlightModeData *pd1=&g_model1->flightModeData[0]; - FlightModeData *pd2=&g_model2->flightModeData[0]; + FlightModeData *pd1=&g_model1.flightModeData[0]; + FlightModeData *pd2=&g_model2.flightModeData[0]; int width = 100 / gvars; str.append(""); for (int i=0; i"; + if (!l2.isEmpty()) o2 += ""; + } +} + +void CompareDialog::printInputs() +{ QString str = "
" + l2 + "

"; - str.append(tr("Expo/Dr Settings")); - str.append("

"); + str += tr("Inputs"); + str += "
"; for(uint8_t i=0; igetCapability(Outputs); i++) { - if (ChannelHasExpo(g_model1->expoData, i) || ChannelHasExpo(g_model2->expoData, i)) { - str.append(""); - str.append(""); - str.append(""); - str.append(""); + QString diffLines1, diffLines2; + diffAndAssembleTableLines(lines1, lines2, diffLines1, diffLines2); + + str += ""; + str += ""; + str += ""; + str += ""; + str += ""; + str += ""; } } - str.append("
"); - str.append(""); - for (int j=0; jexpoData[j].chn==i){ - int expo=ModelHasExpo(g_model2->expoData, g_model1->expoData[j],expoused); - if (expo>-1) { - if (expoused[expo]==false) { - color="grey"; - expoused[expo]=true; - } else { - color="green"; - } - } else { - color="green"; - } - ExpoData *ed=&g_model1->expoData[j]; - if(ed->mode==0) - continue; - str.append(""; - } + QStringList lines1, lines2; + for (int j=0; jchn == i) && (ed1-> mode != 0)) lines1 << modelPrinter1.printInputLine(ed1); + if ((ed2->chn == i) && (ed2-> mode != 0)) lines2 << modelPrinter2.printInputLine(ed2); } - str.append("
"); - switch(ed->mode) { - case (1): - str += "<- "; - break; - case (2): - str += "-> "; - break; - default: - str += "   "; - break; - }; + if (ChannelHasExpo(g_model1.expoData, i) || ChannelHasExpo(g_model2.expoData, i)) { - str += tr("Weight") + QString("%1").arg(getGVarString(ed->weight)).rightJustified(6, ' '); - str += ed->curve.toString().replace("<", "<").replace(">", ">"); + QString name1, name2; + name1 = modelPrinter1.printInputName(i); + name2 = modelPrinter2.printInputName(i); + applyDiffFont(name1, name2); - if (GetCurrentFirmware()->getCapability(FlightModes)) { - if(ed->phases) { - if (ed->phases!=(unsigned int)(1<getCapability(FlightModes))-1) { - int mask=1; - int first=0; - for (int i=0; igetCapability(FlightModes);i++) { - if (!(ed->phases & mask)) { - first++; - } - mask <<=1; - } - if (first>1) { - str += " " + tr("Flight modes") + QString("("); - } else { - str += " " + tr("Flight mode") + QString("("); - } - mask=1; - first=1; - for (int j=0; jgetCapability(FlightModes);j++) { - if (!(ed->phases & mask)) { - FlightModeData *pd = &g_model1->flightModeData[j]; - if (!first) { - str += QString(", ")+ QString("%1").arg(getPhaseName(j+1, pd->name)); - } else { - str += QString("%1").arg(getPhaseName(j+1,pd->name)); - first=0; - } - } - mask <<=1; - } - str += QString(")"); - } - else { - str += tr("DISABLED")+QString(" !!!"); - } - } - } - if (ed->swtch.type) - str += " " + tr("Switch") + QString("(%1)").arg(ed->swtch.toString()); - str += "
"+getInputStr(g_model2, i)+""); - str.append(""); - for (int j=0; jexpoData[j].chn==i){ - int expo=ModelHasExpo(g_model1->expoData, g_model2->expoData[j], expoused2); - if (expo>-1) { - if (expoused2[expo]==false) { - color="grey"; - expoused2[expo]=true; - } else { - color="red"; - } - } else { - color="red"; - } - ExpoData *ed=&g_model2->expoData[j]; - if(ed->mode==0) - continue; - str.append(""; - } - } - str.append("
"); - switch(ed->mode) { - case (1): - str += "<- "; - break; - case (2): - str += "-> "; - break; - default: - str += "   "; - break; - } - str += tr("Weight") + QString("%1").arg(getGVarString(ed->weight)).rightJustified(6, ' '); - str += ed->curve.toString().replace("<", "<").replace(">", ">"); - - if (GetCurrentFirmware()->getCapability(FlightModes)) { - if(ed->phases) { - if (ed->phases!=(unsigned int)(1<getCapability(FlightModes))-1) { - int mask=1; - int first=0; - for (int i=0; igetCapability(FlightModes);i++) { - if (!(ed->phases & mask)) { - first++; - } - mask <<=1; - } - if (first>1) { - str += " " + tr("Flight modes") + QString("("); - } else { - str += " " + tr("Flight mode") + QString("("); - } - mask=1; - first=1; - for (int j=0; jgetCapability(FlightModes);j++) { - if (!(ed->phases & mask)) { - FlightModeData *pd = &g_model2->flightModeData[j]; - if (!first) { - str += QString(", ")+ QString("%1").arg(getPhaseName(j+1, pd->name)); - } else { - str += QString("%1").arg(getPhaseName(j+1,pd->name)); - first=0; - } - } - mask <<=1; - } - str += QString(")"); - } else { - str += tr("DISABLED")+QString(" !!!"); - } - } - } - if (ed->swtch.type) - str += " " + tr("Switch") + QString("(%1)").arg(ed->swtch.toString()); - - str += "
" + name1 + "" + diffLines1 + "
" + name2 + "" + diffLines2 + "
"); + str += "
"; te->append(str); + // debugHtml(str); } void CompareDialog::printMixers() { QString color; QString str = "

"; - str.append(tr("Mixers")); - str.append("

"); - float scale=GetCurrentFirmware()->getCapability(SlowScale); - bool mixused[64]={false}; - bool mixused2[64]={false}; + str += tr("Mixers"); + str += "
"; for(uint8_t i=1; i<=GetCurrentFirmware()->getCapability(Outputs); i++) { - if (ChannelHasMix(g_model1->mixData, i) || ChannelHasMix(g_model2->mixData, i)) { - str.append(""); - str.append(""); - str.append("").arg(i,2,10,QChar('0'))); - str.append(""); - str.append(""); + + QString diffLines1, diffLines2; + diffAndAssembleTableLines(lines1, lines2, diffLines1, diffLines2); + + str += ""; + str += ""; + str += "").arg(i,2,10,QChar('0')); + str += ""; + str += ""; } } - str.append("
"); - str.append(""); + if (ChannelHasMix(g_model1.mixData, i) || ChannelHasMix(g_model2.mixData, i)) { + + QStringList lines1, lines2; for (int j=0; jgetCapability(Mixes); j++) { - if (g_model1->mixData[j].destCh==i) { - int mix=ModelHasMix(g_model2->mixData, g_model1->mixData[j], mixused); - if (mix>-1) { - if (mixused[mix]==false) { - color="grey"; - mixused[mix]=true; - } else { - color="green"; - } - } else { - color="green"; - } - MixData *md = &g_model1->mixData[j]; - str.append(""); - } + MixData *md1 = &g_model1.mixData[j]; + MixData *md2 = &g_model2.mixData[j]; + if (md1->destCh == i) lines1 << modelPrinter1.printMixerLine(md1); + if (md2->destCh == i) lines2 << modelPrinter2.printMixerLine(md2); } - str.append("
"); - switch(md->mltpx) { - case (1): - str += " *"; - break; - case (2): - str += " R"; - break; - default: - str += "  "; - break; - }; - str += QString(" %1").arg(getGVarString(md->weight)).rightJustified(6, ' '); - str += md->srcRaw.toString(g_model1); - if (md->swtch.type) str += " " + tr("Switch") + QString("(%1)").arg(md->swtch.toString()); - if (md->carryTrim) str += " " + tr("noTrim"); - if (md->sOffset) str += " "+ tr("Offset") + QString(" (%1%)").arg(getGVarString(md->sOffset)); - if (md->curve.value) str += " " + Qt::escape(md->curve.toString()); - if (md->delayDown || md->delayUp) str += tr(" Delay(u%1:d%2)").arg(md->delayUp/scale).arg(md->delayDown/scale); - if (md->speedDown || md->speedUp) str += tr(" Slow(u%1:d%2)").arg(md->speedUp/scale).arg(md->speedDown/scale); - if (md->mixWarn) str += " "+tr("Warn")+QString("(%1)").arg(md->mixWarn); - if (GetCurrentFirmware()->getCapability(FlightModes)) { - if(md->phases) { - if (md->phases!=(unsigned int)(1<getCapability(FlightModes))-1) { - int mask=1; - int first=0; - for (int i=0; igetCapability(FlightModes);i++) { - if (!(md->phases & mask)) { - first++; - } - mask <<=1; - } - if (first>1) { - str += " " + tr("Flight modes") + QString("("); - } else { - str += " " + tr("Flight mode") + QString("("); - } - mask=1; - first=1; - for (int j=0; jgetCapability(FlightModes);j++) { - if (!(md->phases & mask)) { - FlightModeData *pd = &g_model1->flightModeData[j]; - if (!first) { - str += QString(", ")+ QString("%1").arg(getPhaseName(j+1, pd->name)); - } else { - str += QString("%1").arg(getPhaseName(j+1,pd->name)); - first=0; - } - } - mask <<=1; - } - str += QString(")"); - } else { - str += tr("DISABLED")+QString(" !!!"); - } - } - } - str.append("
"+tr("CH")+QString("%1"); - str.append(""); - for (int j=0; jgetCapability(Mixes); j++) { - if (g_model2->mixData[j].destCh==i) { - int mix=ModelHasMix(g_model1->mixData, g_model2->mixData[j],mixused2); - if (mix>-1) { - if (mixused2[mix]==false) { - color="grey"; - mixused2[mix]=true; - } else { - color="red"; - } - } else { - color="red"; - } - MixData *md = &g_model2->mixData[j]; - str.append(""); - } - } - str.append("
"); - switch(md->mltpx) { - case (1): - str += " *"; - break; - case (2): - str += " R"; - break; - default: - str += "  "; - break; - }; - str += QString(" %1").arg(getGVarString(md->weight)).rightJustified(6, ' '); - str += md->srcRaw.toString(g_model2); - if (md->swtch.type) str += " " + tr("Switch") + QString("(%1)").arg(md->swtch.toString()); - if (md->carryTrim) str += " " + tr("noTrim"); - if (md->sOffset) str += " "+ tr("Offset") + QString(" (%1%)").arg(getGVarString(md->sOffset)); - if (md->curve.value) str += " " + Qt::escape(md->curve.toString()); - if (md->delayDown || md->delayUp) str += tr(" Delay(u%1:d%2)").arg(md->delayUp/scale).arg(md->delayDown/scale); - if (md->speedDown || md->speedUp) str += tr(" Slow(u%1:d%2)").arg(md->speedUp/scale).arg(md->speedDown/scale); - if (md->mixWarn) str += " "+tr("Warn")+QString("(%1)").arg(md->mixWarn); - if (GetCurrentFirmware()->getCapability(FlightModes)) { - if(md->phases) { - if (md->phases!=(unsigned int)(1<getCapability(FlightModes))-1) { - int mask=1; - int first=0; - for (int i=0; igetCapability(FlightModes);i++) { - if (!(md->phases & mask)) { - first++; - } - mask <<=1; - } - if (first>1) { - str += " " + tr("Flight modes") + QString("("); - } else { - str += " " + tr("Flight mode") + QString("("); - } - mask=1; - first=1; - for (int j=0; jgetCapability(FlightModes);j++) { - if (!(md->phases & mask)) { - FlightModeData *pd = &g_model2->flightModeData[j]; - if (!first) { - str += QString(", ")+ QString("%1").arg(getPhaseName(j+1, pd->name)); - } else { - str += QString("%1").arg(getPhaseName(j+1,pd->name)); - first=0; - } - } - mask <<=1; - } - str += QString(")"); - } else { - str += tr("DISABLED")+QString(" !!!"); - } - } - } - str.append("
"+ diffLines1 + "
"+tr("CH")+QString("%1"+ diffLines2 + "
"); + str += "
"; te->append(str); + // debugHtml(str); } void CompareDialog::printCurves() @@ -923,17 +647,17 @@ void CompareDialog::printCurves() for(i=0; icurves[i].count; j++) { - if (g_model1->curves[i].points[j].y!=0) + for(int j=0; jcurves[i].count; j++) { - if (g_model2->curves[i].points[j].y!=0) + for(int j=0; j0) || (g_model1->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)|| (g_model1->curves[i].count !=5) || - (count2>0) || (g_model2->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)|| (g_model2->curves[i].count !=5)) { + if ((count1>0) || (g_model1.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)|| (g_model1.curves[i].count !=5) || + (count2>0) || (g_model2.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)|| (g_model2.curves[i].count !=5)) { pen.setColor(colors[usedcurves]); painter1.setPen(pen); painter2.setPen(pen); @@ -946,50 +670,50 @@ void CompareDialog::printCurves() c+=b; sprintf(buffer,"%06x",c); // curves are different in number of points or curve type so makes little sense to compare they are just different - if ((g_model1->curves[i].count!=g_model2->curves[i].count) || (g_model1->curves[i].type!=g_model2->curves[i].type)) { + if ((g_model1.curves[i].count!=g_model2.curves[i].count) || (g_model1.curves[i].type!=g_model2.curves[i].type)) { cm1y="["; cm1x="["; - for(int j=0; jcurves[i].count; j++) { - cm1y.append(QString("%1").arg(g_model1->curves[i].points[j].y)); - cm1x.append(QString("%1").arg(g_model1->curves[i].points[j].x)); - if (j<(g_model1->curves[i].count-1)) { + for(int j=0; jcurves[i].type == CurveData::CURVE_TYPE_CUSTOM) - painter1.drawLine(ISIZE/2+(ISIZE*g_model1->curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model1->curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model1->curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model1->curves[i].points[j].y)/200); + if (g_model1.curves[i].type == CurveData::CURVE_TYPE_CUSTOM) + painter1.drawLine(ISIZE/2+(ISIZE*g_model1.curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model1.curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model1.curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model1.curves[i].points[j].y)/200); else - painter1.drawLine(ISIZE*(j-1)/(g_model1->curves[i].count-1),ISIZE/2-(ISIZE*g_model1->curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model1->curves[i].count-1),ISIZE/2-(ISIZE*g_model1->curves[i].points[j].y)/200); + painter1.drawLine(ISIZE*(j-1)/(g_model1.curves[i].count-1),ISIZE/2-(ISIZE*g_model1.curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model1.curves[i].count-1),ISIZE/2-(ISIZE*g_model1.curves[i].points[j].y)/200); } cm1y.append("]"); cm1x.append("]"); cm2y="["; cm2x="["; - for(int j=0; jcurves[i].count; j++) { - cm2y.append(QString("%1").arg(g_model2->curves[i].points[j].y)); - cm2x.append(QString("%1").arg(g_model2->curves[i].points[j].x)); - if (j<(g_model2->curves[i].count-1)) { + for(int j=0; jcurves[i].type == CurveData::CURVE_TYPE_CUSTOM) - painter2.drawLine(ISIZE/2+(ISIZE*g_model2->curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model2->curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model2->curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model2->curves[i].points[j].y)/200); + if (g_model2.curves[i].type == CurveData::CURVE_TYPE_CUSTOM) + painter2.drawLine(ISIZE/2+(ISIZE*g_model2.curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model2.curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model2.curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model2.curves[i].points[j].y)/200); else - painter2.drawLine(ISIZE*(j-1)/(g_model2->curves[i].count-1),ISIZE/2-(ISIZE*g_model2->curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model2->curves[i].count-1),ISIZE/2-(ISIZE*g_model2->curves[i].points[j].y)/200); + painter2.drawLine(ISIZE*(j-1)/(g_model2.curves[i].count-1),ISIZE/2-(ISIZE*g_model2.curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model2.curves[i].count-1),ISIZE/2-(ISIZE*g_model2.curves[i].points[j].y)/200); } cm2y.append("]"); cm2x.append("]"); str.append(""); str.append(cm1y); - if ((g_model1->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { + if ((g_model1.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { str.append(QString("
")+cm1x+QString("
")); } str.append(QString("").arg(buffer)+tr("Curve")+QString(" %1").arg(i+1)); str.append(""); str.append(cm2y); - if ((g_model2->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { + if ((g_model2.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { str.append(QString("
")+cm2x+QString("
")); } } else { @@ -998,35 +722,35 @@ void CompareDialog::printCurves() cm1x="["; cm2y="["; cm2x="["; - for(int j=0; jcurves[i].count; j++) { - if (g_model1->curves[i].points[j].y!=g_model2->curves[i].points[j].y) { - cm1y.append(QString("%1").arg(g_model1->curves[i].points[j].y)); - cm2y.append(QString("%1").arg(g_model2->curves[i].points[j].y)); + for(int j=0; j%1").arg(g_model1.curves[i].points[j].y)); + cm2y.append(QString("%1").arg(g_model2.curves[i].points[j].y)); } else { - cm1y.append(QString("%1").arg(g_model1->curves[i].points[j].y)); - cm2y.append(QString("%1").arg(g_model2->curves[i].points[j].y)); + cm1y.append(QString("%1").arg(g_model1.curves[i].points[j].y)); + cm2y.append(QString("%1").arg(g_model2.curves[i].points[j].y)); } - if (g_model1->curves[i].points[j].x!=g_model2->curves[i].points[j].x) { - cm1x.append(QString("%1").arg(g_model1->curves[i].points[j].x)); - cm2x.append(QString("%1").arg(g_model2->curves[i].points[j].x)); + if (g_model1.curves[i].points[j].x!=g_model2.curves[i].points[j].x) { + cm1x.append(QString("%1").arg(g_model1.curves[i].points[j].x)); + cm2x.append(QString("%1").arg(g_model2.curves[i].points[j].x)); } else { - cm1x.append(QString("%1").arg(g_model1->curves[i].points[j].x)); - cm2x.append(QString("%1").arg(g_model2->curves[i].points[j].x)); + cm1x.append(QString("%1").arg(g_model1.curves[i].points[j].x)); + cm2x.append(QString("%1").arg(g_model2.curves[i].points[j].x)); } - if (j<(g_model1->curves[i].count-1)) { + if (j<(g_model1.curves[i].count-1)) { cm1y.append(","); cm1x.append(","); cm2y.append(","); cm2x.append(","); } - if (g_model1->curves[i].type == CurveData::CURVE_TYPE_CUSTOM) - painter1.drawLine(ISIZE/2+(ISIZE*g_model1->curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model1->curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model1->curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model1->curves[i].points[j].y)/200); + if (g_model1.curves[i].type == CurveData::CURVE_TYPE_CUSTOM) + painter1.drawLine(ISIZE/2+(ISIZE*g_model1.curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model1.curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model1.curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model1.curves[i].points[j].y)/200); else - painter1.drawLine(ISIZE*(j-1)/(g_model1->curves[i].count-1),ISIZE/2-(ISIZE*g_model1->curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model1->curves[i].count-1),ISIZE/2-(ISIZE*g_model1->curves[i].points[j].y)/200); - if (g_model2->curves[i].type == CurveData::CURVE_TYPE_CUSTOM) - painter2.drawLine(ISIZE/2+(ISIZE*g_model2->curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model2->curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model2->curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model2->curves[i].points[j].y)/200); + painter1.drawLine(ISIZE*(j-1)/(g_model1.curves[i].count-1),ISIZE/2-(ISIZE*g_model1.curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model1.curves[i].count-1),ISIZE/2-(ISIZE*g_model1.curves[i].points[j].y)/200); + if (g_model2.curves[i].type == CurveData::CURVE_TYPE_CUSTOM) + painter2.drawLine(ISIZE/2+(ISIZE*g_model2.curves[i].points[j-1].x)/200,ISIZE/2-(ISIZE*g_model2.curves[i].points[j-1].y)/200,ISIZE/2+(ISIZE*g_model2.curves[i].points[j].x)/200,ISIZE/2-(ISIZE*g_model2.curves[i].points[j].y)/200); else - painter2.drawLine(ISIZE*(j-1)/(g_model2->curves[i].count-1),ISIZE/2-(ISIZE*g_model2->curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model2->curves[i].count-1),ISIZE/2-(ISIZE*g_model2->curves[i].points[j].y)/200); + painter2.drawLine(ISIZE*(j-1)/(g_model2.curves[i].count-1),ISIZE/2-(ISIZE*g_model2.curves[i].points[j-1].y)/200,ISIZE*(j)/(g_model2.curves[i].count-1),ISIZE/2-(ISIZE*g_model2.curves[i].points[j].y)/200); } painter1.setPen(QColor(0,0,0)); painter2.setPen(QColor(0,0,0)); @@ -1047,13 +771,13 @@ void CompareDialog::printCurves() cm2x.append("]"); str.append(""); str.append(cm1y); - if ((g_model1->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { + if ((g_model1.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { str.append(QString("
")+cm1x+QString("")); } str.append(QString("").arg(buffer)+tr("Curve")+QString(" %1").arg(i+1)); str.append(""); str.append(cm2y); - if ((g_model2->curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { + if ((g_model2.curves[i].type == CurveData::CURVE_TYPE_CUSTOM)) { str.append(QString("
")+cm2x+QString("")); } } @@ -1069,110 +793,50 @@ void CompareDialog::printCurves() } } -void CompareDialog::printSwitches() +void CompareDialog::printLogicalSwitches() { - int sc=0; - QString color; - QString str = ""; - str.append(""); - str.append("

"+tr("Logical Switches")+"

"); - for (int i=0; igetCapability(LogicalSwitches); i++) { - GeneralSettings settings; - QString sw1 = g_model1->logicalSw[i].toString(*g_model1, settings); - QString sw2 = g_model2->logicalSw[i].toString(*g_model2, settings); - if (!(sw1.isEmpty() && sw2.isEmpty())) { - str.append(""); - color=getColor1(sw1,sw2); - str.append(QString(""); - str.append("")); - color=getColor2(sw1,sw2); - str.append(QString(""); - str.append(""); - sc++; - } + bool haveOutput = false; + QString str = "
").arg(color)+sw1+""+tr("L%1").arg(i+1)+QString("").arg(color)+sw2+"
"; + str += ""; + str += "

" + tr("Logical Switches") + "

"; + for (int i=0; igetCapability(LogicalSwitches); i++) { + QString l1 = modelPrinter1.printLogicalSwitchLine(i); + QString l2 = modelPrinter2.printLogicalSwitchLine(i); + if (!(l1.isEmpty() && l2.isEmpty())) { + applyDiffFont(l1, l2); + str += ""; + str += ""; + str += "").arg(i+1); + str += ""; + str += ""; + haveOutput = true; } - str.append("
"+ l1 + "" + tr("L") + QString("%1" + l2 + "
"); - if (sc>0) - te->append(str); + } + str += "
"; + if (haveOutput) te->append(str); } -void CompareDialog::printFSwitches() +void CompareDialog::printCustomFunctions() { - QString color1; - QString color2; - int sc=0; - QString str = ""; - str.append(""); - str.append("

"+tr("Special Functions")+"

"); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - str.append(""); - for(int i=0; igetCapability(CustomFunctions); i++) - { - if (g_model1->customFn[i].swtch.type || g_model2->customFn[i].swtch.type) { - if ((g_model1->customFn[i].swtch != g_model2->customFn[i].swtch) || (g_model1->customFn[i].func!=g_model2->customFn[i].func) || (g_model1->customFn[i].adjustMode!=g_model2->customFn[i].adjustMode) || (g_model1->customFn[i].param!=g_model2->customFn[i].param) || (g_model1->customFn[i].enabled != g_model2->customFn[i].enabled) || (g_model1->customFn[i].repeatParam != g_model2->customFn[i].repeatParam)) { - color1="green"; - color2="red"; - } else { - color1="grey"; - color2="grey"; - } - str.append(""); - if (g_model1->customFn[i].swtch.type) { - str.append(doTC(g_model1->customFn[i].swtch.toString(),color1)); - str.append(doTC(g_model1->customFn[i].funcToString(),color1)); - str.append(doTC(g_model1->customFn[i].paramToString(),color1)); - int index=g_model1->customFn[i].func; - if (index==FuncPlaySound || index==FuncPlayHaptic || index==FuncPlayValue || index==FuncPlayPrompt || index==FuncPlayBoth || index==FuncBackgroundMusic) { - str.append(doTC(QString("%1").arg(g_model1->customFn[i].repeatParam),color1)); - } else { - str.append(doTC( "---",color1)); - } - if ((index<=FuncInstantTrim) || (index>FuncBackgroundMusicPause)) { - str.append(doTC((g_model1->customFn[i].enabled ? "ON" : "OFF"),color1)); - } else { - str.append(doTC( "---",color1)); - } - } else { - str.append(""); - } - str.append(doTC(tr("SF")+QString("%1").arg(i+1),"",true)); - if (g_model2->customFn[i].swtch.type) { - str.append(doTC(g_model2->customFn[i].swtch.toString(),color2)); - str.append(doTC(g_model2->customFn[i].funcToString(),color2)); - str.append(doTC(g_model2->customFn[i].paramToString(),color2)); - int index=g_model2->customFn[i].func; - if (index==FuncPlaySound || index==FuncPlayHaptic || index==FuncPlayValue || index==FuncPlayPrompt || index==FuncPlayBoth || index==FuncBackgroundMusic) { - str.append(doTC(QString("%1").arg(g_model2->customFn[i].repeatParam),color2)); - } else { - str.append(doTC( "---",color2)); - } - if ((index<=FuncInstantTrim) || (index>FuncBackgroundMusicPause)) { - str.append(doTC((g_model2->customFn[i].enabled ? "ON" : "OFF"),color2)); - } else { - str.append(doTC( "---",color2)); - } - } - else { - str.append(""); - } - str.append(""); - sc++; + bool haveOutput = false; + QString str = "
"+tr("Switch")+""+tr("Function")+""+tr("Param")+""+tr("Repeat")+""+tr("Enable")+" "+tr("Switch")+""+tr("Function")+""+tr("Param")+""+tr("Repeat")+""+tr("Enable")+"
       
"; + str += ""; + str += "

" + tr("Special Functions") + "

"; + for (int i=0; igetCapability(CustomFunctions); i++) { + QString l1 = modelPrinter1.printCustomFunctionLine(i); + QString l2 = modelPrinter2.printCustomFunctionLine(i); + if (!(l1.isEmpty() && l2.isEmpty())) { + applyDiffFont(l1, l2); + str += ""; + str += ""; + str += "").arg(i+1); + str += ""; + str += ""; + haveOutput = true; } -} - str.append("
"+ l1 + "" + tr("SF") + QString("%1" + l2 + "
"); - str.append("
"); - if (sc!=0) - te->append(str); + } + str += "
"; + if (haveOutput) te->append(str); } void CompareDialog::printFrSky() @@ -1183,8 +847,8 @@ void CompareDialog::printFrSky() str.append("

"+tr("Telemetry Settings")+"

"); str.append(""); str.append(""); - FrSkyData *fd1=&g_model1->frsky; - FrSkyData *fd2=&g_model2->frsky; + FrSkyData *fd1=&g_model1.frsky; + FrSkyData *fd2=&g_model2.frsky; str.append(""); for (int i=0; i<2; i++) { str.append(""); diff --git a/companion/src/comparedialog.h b/companion/src/comparedialog.h index bfc170479..b8b15fc05 100644 --- a/companion/src/comparedialog.h +++ b/companion/src/comparedialog.h @@ -5,6 +5,7 @@ #include #include #include "eeprominterface.h" +#include "modelprinter.h" namespace Ui { class CompareDialog; @@ -21,11 +22,10 @@ class CompareDialog : public QDialog protected: GeneralSettings * settings; - ModelData * g_model1; - ModelData * g_model2; - ModelData * modeltemp; - int model1; - int model2; + ModelData g_model1; + ModelData g_model2; + bool model1Valid; + bool model2Valid; private: void closeEvent(QCloseEvent *event); @@ -55,15 +55,20 @@ class CompareDialog : public QDialog return "grey"; } - int ModelHasExpo(ExpoData * ExpoArray, ExpoData expo, bool * expoused); bool ChannelHasExpo(ExpoData * expoArray, uint8_t destCh); - int ModelHasMix(MixData * mixArray, MixData mix, bool * mixused); bool ChannelHasMix(MixData * mixArray, uint8_t destCh); + bool handleDroppedModel(const QMimeData * mimeData, ModelData * model, QLabel * label); + void applyDiffFont(QString & v1, QString & v2, const QString & font = "", bool eqGrey = false); + void diffAndAssembleTableLines(QStringList & i1, QStringList & i2, QString & o1, QString & o2); QTextEdit * te; QString curvefile1; QString curvefile2; QDir *qd; + + ModelPrinter modelPrinter1; + ModelPrinter modelPrinter2; + GeneralSettings dummySettings; private slots: void on_printButton_clicked(); @@ -78,13 +83,13 @@ protected: void printSetup(); void printPhases(); void printLimits(); - void printExpos(); + void printInputs(); void printMixers(); void printCurves(); void printGvars(); - void printSwitches(); + void printLogicalSwitches(); void printSafetySwitches(); - void printFSwitches(); + void printCustomFunctions(); void printFrSky(); }; diff --git a/companion/src/eeprominterface.cpp b/companion/src/eeprominterface.cpp index 3758c24c3..c6bc3f601 100644 --- a/companion/src/eeprominterface.cpp +++ b/companion/src/eeprominterface.cpp @@ -561,7 +561,7 @@ QString SwitchDn(const char sw) return QString::fromUtf8(result); } -QString RawSwitch::toString() +QString RawSwitch::toString() const { static const QString switches9X[] = { QString("THR"), QString("RUD"), QString("ELE"), @@ -659,7 +659,7 @@ QString RawSwitch::toString() } } -QString CurveReference::toString() +QString CurveReference::toString() const { if (value == 0) { return "----"; @@ -678,7 +678,7 @@ QString CurveReference::toString() } } -CSFunctionFamily LogicalSwitchData::getFunctionFamily() +CSFunctionFamily LogicalSwitchData::getFunctionFamily() const { if (func == LS_FN_EDGE) return LS_FAMILY_EDGE; @@ -694,7 +694,7 @@ CSFunctionFamily LogicalSwitchData::getFunctionFamily() return LS_FAMILY_VCOMP; } -unsigned int LogicalSwitchData::getRangeFlags() +unsigned int LogicalSwitchData::getRangeFlags() const { if (func == LS_FN_DPOS) return RANGE_DELTA_FUNCTION; @@ -704,7 +704,7 @@ unsigned int LogicalSwitchData::getRangeFlags() return 0; } -QString LogicalSwitchData::funcToString() +QString LogicalSwitchData::funcToString() const { switch (func) { case LS_FN_OFF: @@ -754,127 +754,6 @@ QString LogicalSwitchData::funcToString() } } -QString LogicalSwitchData::toString(const ModelData & model, const GeneralSettings & settings) -{ - QString result = ""; - - if (!func) - return result; - - if (andsw!=0) { - result +="( "; - } - switch (getFunctionFamily()) { - case LS_FAMILY_EDGE: - result += QObject::tr("Edge(%1, [%2:%3])").arg(RawSwitch(val1).toString()).arg(ValToTim(val2)).arg(ValToTim(val2+val3)); - break; - case LS_FAMILY_STICKY: - result += QObject::tr("Sticky(%1, %2)").arg(RawSwitch(val1).toString()).arg(RawSwitch(val2).toString()); - break; - case LS_FAMILY_TIMER: - result += QObject::tr("Timer(%1, %2)").arg(ValToTim(val1)).arg(ValToTim(val2)); - break; - case LS_FAMILY_VOFS: { - RawSource source = RawSource(val1); - RawSourceRange range = source.getRange(&model, settings); - QString res; - if (val1) - res += source.toString(&model); - else - res += "0"; - res.remove(" "); - if (func == LS_FN_APOS || func == LS_FN_ANEG) - res = "|" + res + "|"; - else if (func == LS_FN_DAPOS) - res = "|d(" + res + ")|"; - else if (func == LS_FN_DPOS) - res = "d(" + res + ")"; - result += res; - if (func == LS_FN_APOS || func == LS_FN_VPOS || func == LS_FN_DPOS || func == LS_FN_DAPOS) - result += " > "; - else if (func == LS_FN_EQUAL || func == LS_FN_VEQUAL) - result += " = "; - else if (func == LS_FN_NEQUAL) - result += " != "; - else if (func == LS_FN_ANEG || func == LS_FN_VNEG) - result += " < "; - else if (func == LS_FN_VALMOSTEQUAL) - result += " ~ "; - else - result += " missing"; - result += QString::number(range.step * (val2 /*TODO+ source.getRawOffset(model)*/) + range.offset); - break; - } - case LS_FAMILY_VBOOL: - result += RawSwitch(val1).toString(); - switch (func) { - case LS_FN_AND: - result += " AND "; - break; - case LS_FN_OR: - result += " OR "; - break; - case LS_FN_XOR: - result += " XOR "; - break; - default: - result += " bar "; - break; - } - result += RawSwitch(val2).toString(); - break; - - case LS_FAMILY_VCOMP: - if (val1) - result += RawSource(val1).toString(&model); - else - result += "0"; - switch (func) { - case LS_FN_EQUAL: - case LS_FN_VEQUAL: - result += " = "; - break; - case LS_FN_NEQUAL: - result += " != "; - break; - case LS_FN_GREATER: - result += " > "; - break; - case LS_FN_LESS: - result += " < "; - break; - case LS_FN_EGREATER: - result += " >= "; - break; - case LS_FN_ELESS: - result += " <= "; - break; - default: - result += " foo "; - break; - } - if (val2) - result += RawSource(val2).toString(&model); - else - result += "0"; - break; - } - - if (andsw!=0) { - result +=" ) AND "; - result += RawSwitch(andsw).toString(); - } - - if (GetCurrentFirmware()->getCapability(LogicalSwitchesExt)) { - if (duration) - result += QObject::tr(" Duration (%1s)").arg(duration/10.0); - if (delay) - result += QObject::tr(" Delay (%1s)").arg(delay/10.0); - } - - return result; -} - void CustomFunctionData::clear() { memset(this, 0, sizeof(CustomFunctionData)); @@ -883,7 +762,7 @@ void CustomFunctionData::clear() } } -QString CustomFunctionData::funcToString() +QString CustomFunctionData::funcToString() const { if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) return QObject::tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString()); @@ -936,36 +815,84 @@ QString CustomFunctionData::funcToString() } } -QString CustomFunctionData::paramToString() +void CustomFunctionData::populateResetParams(ModelData * model, QComboBox * b, unsigned int value = 0) +{ + int val = 0; + Firmware * firmware = GetCurrentFirmware(); + BoardEnum board = GetEepromInterface()->getBoard(); + + b->addItem(QObject::tr("Timer1"), val++); + b->addItem(QObject::tr("Timer2"), val++); + if (IS_ARM(board)) { + b->addItem( QObject::tr("Timer3"), val++); + } + b->addItem(QObject::tr("Flight"), val++); + b->addItem(QObject::tr("Telemetry"), val++); + int reCount = firmware->getCapability(RotaryEncoders); + if (reCount == 1) { + b->addItem(QObject::tr("Rotary Encoder"), val++); + } + else if (reCount == 2) { + b->addItem(QObject::tr("REa"), val++); + b->addItem(QObject::tr("REb"), val++); + } + if ((int)value < b->count()) { + b->setCurrentIndex(value); + } + if (model && IS_ARM(board)) { + for (int i=0; isensorData[i].isAvailable()) { + RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i); + b->addItem(item.toString(model), val+i); + if ((int)value == val+i) { + b->setCurrentIndex(b->count()-1); + } + } + } + } +} + +void CustomFunctionData::populatePlaySoundParams(QStringList & qs) +{ + qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ; + qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ; +} + +void CustomFunctionData::populateHapticParams(QStringList & qs) +{ + qs << "0" << "1" << "2" << "3"; +} + +QString CustomFunctionData::paramToString(ModelData * model) const { QStringList qs; if (func <= FuncInstantTrim) { return QString("%1").arg(param); } + else if (func==FuncLogs) { + return QString("%1").arg(param/10.0) + QObject::tr("s"); + } else if (func==FuncPlaySound) { - qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ; - qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ; + CustomFunctionData::populatePlaySoundParams(qs); if (param>=0 && param<(int)qs.count()) return qs.at(param); else return QObject::tr("Inconsistent parameter"); } else if (func==FuncPlayHaptic) { - qs << "0" << "1" << "2" << "3"; + CustomFunctionData::populateHapticParams(qs); if (param>=0 && param<(int)qs.count()) return qs.at(param); else return QObject::tr("Inconsistent parameter"); } else if (func==FuncReset) { - qs.append( QObject::tr("Timer1")); - qs.append( QObject::tr("Timer2")); - qs.append( QObject::tr("Timer3")); - qs.append( QObject::tr("All")); - qs.append( QObject::tr("Telemetry")); - if (param>=0 && param<(int)qs.count()) - return qs.at(param); - else + QComboBox cb; + CustomFunctionData::populateResetParams(model, &cb); + int pos = cb.findData(param); + if (pos >= 0) + return cb.itemText(pos); + else return QObject::tr("Inconsistent parameter"); } else if ((func==FuncVolume)|| (func==FuncPlayValue)) { @@ -980,43 +907,47 @@ QString CustomFunctionData::paramToString() return paramarm; } } - else if ((func>FuncBackgroundMusicPause) && (func=FuncAdjustGV1) && (funcgetBoard()) ? 5 : 10; - return QObject::tr("%1 sec").arg(step*repeatParam); + unsigned int step = IS_ARM(GetEepromInterface()->getBoard()) ? 1 : 10; + return QObject::tr("repeat") + QString("(%1").arg(step*repeatParam) + QObject::tr("s") + ")"; } } +QString CustomFunctionData::enabledToString() const +{ + if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) || + (func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) || + (func==FuncReset) || + (func>=FuncSetTimer1 && func<=FuncSetTimer2) || + (func==FuncVolume) || + (func <= FuncInstantTrim)) { + if (!enabled) { + return QObject::tr("DISABLED"); + } + } + return ""; +} + QString LimitData::minToString() { return QString::number((qreal)min/10); diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index ca4ad74d8..d925d07b5 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "constants.h" #include "simulatorinterface.h" @@ -390,7 +391,7 @@ class RawSwitch { return index >= 0 ? (type * 256 + index) : -(type * 256 - index); } - QString toString(); + QString toString() const; bool operator== ( const RawSwitch& other) { return (this->type == other.type) && (this->index == other.index); @@ -426,7 +427,7 @@ class CurveReference { CurveRefType type; int value; - QString toString(); + QString toString() const; }; enum InputMode { @@ -575,10 +576,9 @@ class LogicalSwitchData { // Logical Switches data unsigned int duration; int andsw; void clear() { memset(this, 0, sizeof(LogicalSwitchData)); } - CSFunctionFamily getFunctionFamily(); - unsigned int getRangeFlags(); - QString funcToString(); - QString toString(const ModelData & model, const GeneralSettings & settings); + CSFunctionFamily getFunctionFamily() const; + unsigned int getRangeFlags() const; + QString funcToString() const; }; enum AssignFunc { @@ -624,10 +624,15 @@ class CustomFunctionData { // Function Switches data unsigned int adjustMode; int repeatParam; void clear(); - QString funcToString(); - QString paramToString(); - QString repeatToString(); - QStringList toStringList(); + QString funcToString() const; + QString paramToString(ModelData * model) const; + QString repeatToString() const; + QString enabledToString() const; + + static void populateResetParams(ModelData * model, QComboBox * b, unsigned int value); + static void populatePlaySoundParams(QStringList & qs); + static void populateHapticParams(QStringList & qs); + }; class FlightModeData { diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 13378ec29..a30064571 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -65,26 +65,6 @@ QString getPhaseName(int val, const char * phasename) } } -QString getInputStr(ModelData * model, int index) -{ - QString result; - - if (GetCurrentFirmware()->getCapability(VirtualInputs)) { - if (strlen(model->inputNames[index]) > 0) { - result = QObject::tr("[I%1]").arg(index+1); - result += QString(model->inputNames[index]); - } - else { - result = QObject::tr("Input%1").arg(index+1, 2, 10, QChar('0')); - } - } - else { - result = RawSource(SOURCE_TYPE_STICK, index).toString(model); - } - - return result; -} - void populateGvSourceCB(QComboBox *b, int value) { QString strings[] = { QObject::tr("---"), QObject::tr("Rud Trim"), QObject::tr("Ele Trim"), QObject::tr("Thr Trim"), QObject::tr("Ail Trim"), QObject::tr("Rot Enc"), QObject::tr("Rud"), QObject::tr("Ele"), QObject::tr("Thr"), QObject::tr("Ail"), QObject::tr("P1"), QObject::tr("P2"), QObject::tr("P3")}; @@ -858,34 +838,6 @@ QString getTrainerMode(const int trainermode, ModuleData & module) return result; } -QString getPhasesStr(unsigned int phases, ModelData * model) -{ - int numphases = GetCurrentFirmware()->getCapability(FlightModes); - - if (numphases && phases) { - QString str; - int count = 0; - if (phases == (unsigned int)(1< 0) str += QString(", "); - str += getPhaseName(i+1, model->flightModeData[i].name); - } - } - } - if (count > 1) - return QObject::tr("Flight modes(%1)").arg(str); - else - return QObject::tr("Flight mode(%1)").arg(str); - } - else { - return ""; - } -} - QString getCenterBeepStr(ModelData * g_model) { QStringList strl; diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 5e3c40503..1c0535535 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -101,7 +101,6 @@ void populateSwitchCB(QComboBox *b, const RawSwitch & value, const GeneralSettin void populatePhasesCB(QComboBox *b, int value); void populateGvarUseCB(QComboBox *b, unsigned int phase); QString getProtocolStr(const int proto); -QString getPhasesStr(unsigned int phases, ModelData * model); #define POPULATE_NONE (1<<0) #define POPULATE_SOURCES (1<<1) @@ -120,7 +119,6 @@ QString getPhasesStr(unsigned int phases, ModelData * model); void populateGVCB(QComboBox *b, int value); void populateSourceCB(QComboBox *b, const RawSource &source, const GeneralSettings generalSettings, const ModelData * model, unsigned int flags); QString getPhaseName(int val, const char * phasename=NULL); -QString getInputStr(ModelData * model, int index); QString image2qstring(QImage image); int findmult(float value, float base); diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 5442f2e6b..031ae2a9c 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -636,47 +636,17 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi QStringList qs; b->clear(); if (function==FuncPlaySound) { - qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ; - qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ; + CustomFunctionData::populatePlaySoundParams(qs); b->addItems(qs); b->setCurrentIndex(value); } else if (function==FuncPlayHaptic) { - qs << "0" << "1" << "2" << "3"; + CustomFunctionData::populateHapticParams(qs); b->addItems(qs); b->setCurrentIndex(value); } else if (function==FuncReset) { - int val = 0; - b->addItem(tr("Timer1"), val++); - b->addItem(tr("Timer2"), val++); - if (IS_ARM(firmware->getBoard())) { - b->addItem( QObject::tr("Timer3"), val++); - } - b->addItem(tr("Flight"), val++); - b->addItem(tr("Telemetry"), val++); - int reCount = firmware->getCapability(RotaryEncoders); - if (reCount == 1) { - b->addItem(tr("Rotary Encoder"), val++); - } - else if (reCount == 2) { - b->addItem(tr("REa"), val++); - b->addItem(tr("REb"), val++); - } - if ((int)value < b->count()) { - b->setCurrentIndex(value); - } - if (model && IS_ARM(firmware->getBoard())) { - for (int i=0; isensorData[i].isAvailable()) { - RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i); - b->addItem(item.toString(model), val+i); - if ((int)value == val+i) { - b->setCurrentIndex(b->count()-1); - } - } - } - } + CustomFunctionData::populateResetParams(model, b, value); } else if (function==FuncVolume) { populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_NONE|POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS|POPULATE_SWITCHES); diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index 10007c394..b629ff16d 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -10,13 +10,14 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G generalSettings(generalSettings), firmware(firmware), ed(expoData), - inputName(inputName) + inputName(inputName), + modelPrinter(firmware, &generalSettings, &model) { ui->setupUi(this); QLabel * lb_fp[] = {ui->lb_FP0,ui->lb_FP1,ui->lb_FP2,ui->lb_FP3,ui->lb_FP4,ui->lb_FP5,ui->lb_FP6,ui->lb_FP7,ui->lb_FP8 }; QCheckBox * cb_fp[] = {ui->cb_FP0,ui->cb_FP1,ui->cb_FP2,ui->cb_FP3,ui->cb_FP4,ui->cb_FP5,ui->cb_FP6,ui->cb_FP7,ui->cb_FP8 }; - setWindowTitle(tr("Edit %1").arg(getInputStr(&model, ed->chn))); + setWindowTitle(tr("Edit %1").arg(modelPrinter.printInputName(ed->chn))); QRegExp rx(CHAR_FOR_NAMES_REGEX); if (IS_TARANIS(GetEepromInterface()->getBoard())) { diff --git a/companion/src/modeledit/expodialog.h b/companion/src/modeledit/expodialog.h index b4b40f803..9aff8f35d 100644 --- a/companion/src/modeledit/expodialog.h +++ b/companion/src/modeledit/expodialog.h @@ -3,6 +3,7 @@ #include #include "eeprominterface.h" +#include "modelprinter.h" class GVarGroup; class CurveGroup; @@ -35,6 +36,7 @@ class ExpoDialog : public QDialog { GVarGroup * gvWeightGroup; GVarGroup * gvOffsetGroup; CurveGroup * curveGroup; + ModelPrinter modelPrinter; }; #endif // EXPODIALOG_H diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp index 9d5580672..c9550ab60 100644 --- a/companion/src/modeledit/inputs.cpp +++ b/companion/src/modeledit/inputs.cpp @@ -5,7 +5,8 @@ InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): ModelPanel(parent, model, generalSettings, firmware), - expoInserted(false) + expoInserted(false), + modelPrinter(firmware, &generalSettings, &model) { inputsCount = firmware->getCapability(VirtualInputs); if (inputsCount == 0) @@ -135,7 +136,7 @@ QString InputsPanel::getInputText(int dest, bool * new_ch) QString str; if (new_ch) *new_ch = 0; if (dest < 0) { - str = getInputStr(model, -dest-1); + str = modelPrinter.printInputName(-dest-1); if (new_ch) *new_ch = 1; } else { @@ -144,9 +145,9 @@ QString InputsPanel::getInputText(int dest, bool * new_ch) if ((dest == 0) || (model->expoData[dest-1].chn != md->chn)) { if (new_ch) *new_ch = 1; if (firmware->getCapability(VirtualInputs)) - str = QString("%1").arg(getInputStr(model, md->chn), -10, ' '); + str += QString("%1").arg(modelPrinter.printInputName(md->chn), -10, ' '); else - str = getInputStr(model, md->chn); + str = modelPrinter.printInputName(md->chn); } else { if (firmware->getCapability(VirtualInputs)) @@ -154,39 +155,10 @@ QString InputsPanel::getInputText(int dest, bool * new_ch) else str = " "; } - - switch (md->mode) { - case (1): str += " <-"; break; - case (2): str += " ->"; break; - default: str += " "; break; - } - - str += " " + tr("Weight(%1)").arg(getGVarString(md->weight)); - if (md->offset) str += " " + tr("Offset(%1)").arg(getGVarString(md->offset)); - - if (firmware->getCapability(VirtualInputs)) { - str += " " + tr("Source(%1)").arg(md->srcRaw.toString(model)); - if (md->carryTrim>0) { - str += " " + tr("NoTrim"); - } - else if (md->carryTrim<0) { - str += " " + RawSource(SOURCE_TYPE_TRIM, (-(md->carryTrim)-1)).toString(model); - } - } - - if (md->curve.value) str += " " + md->curve.toString(); - - QString phasesStr = getPhasesStr(md->phases, model); - if (!phasesStr.isEmpty()) str += " " + phasesStr; - - if (md->swtch.type != SWITCH_TYPE_NONE) str += " " + tr("Switch(%1)").arg(md->swtch.toString()); - - if (firmware->getCapability(HasExpoNames)) { - QString expoName = md->name; - if (!expoName.isEmpty()) str += QString(" [%1]").arg(expoName); - } + str.replace(" ", " "); + str += modelPrinter.printInputLine(md); } - return Qt::escape(str).replace(" ", " "); + return str; } bool InputsPanel::gm_insertExpo(int idx) diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index 124ef22a5..173675d44 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -3,6 +3,7 @@ #include "modeledit.h" #include "mixerslist.h" +#include "modelprinter.h" class InputsPanel : public ModelPanel { @@ -35,6 +36,7 @@ class InputsPanel : public ModelPanel MixersList *ExposlistWidget; bool firstLine; int inputsCount; + ModelPrinter modelPrinter; int getExpoIndex(unsigned int dch); bool gm_insertExpo(int idx); diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp index 59e7ba28f..b368fabdb 100644 --- a/companion/src/modeledit/mixes.cpp +++ b/companion/src/modeledit/mixes.cpp @@ -6,7 +6,8 @@ MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): ModelPanel(parent, model, generalSettings, firmware), mixInserted(false), - highlightedSource(0) + highlightedSource(0), + modelPrinter(firmware, &generalSettings, &model) { QGridLayout * mixesLayout = new QGridLayout(this); @@ -43,23 +44,6 @@ MixesPanel::~MixesPanel() { } -QString MixesPanel::getChannelLabel(int curDest) -{ - QString str; - str = QObject::tr("CH%1").arg(curDest); - // TODO not nice, Qt brings a function for that, I don't remember right now - (str.length() < 4) ? str.append(" ") : str.append(" "); - if (firmware->getCapability(HasChNames)) { - QString name = model->limitData[curDest-1].name; - if (!name.isEmpty()) { - name = QString("(") + name + QString(")"); - } - name.append(" "); - str += name.left(8); - } - return Qt::escape(str); -} - void MixesPanel::update() { // curDest -> destination channel @@ -141,8 +125,8 @@ QString MixesPanel::getMixerText(int dest, bool * new_ch) QString str; if (new_ch) *new_ch = 0; if (dest < 0) { - str = getChannelLabel(-dest); - //highlight channell if needed + str = modelPrinter.printMixerName(-dest); + //highlight channel if needed if (-dest == (int)highlightedSource) { str = "" + str + ""; } @@ -151,11 +135,11 @@ QString MixesPanel::getMixerText(int dest, bool * new_ch) else { MixData *md = &model->mixData[dest]; //md->destCh from 1 to 32 - str = getChannelLabel(md->destCh); + str = modelPrinter.printMixerName(md->destCh); if ((dest == 0) || (model->mixData[dest-1].destCh != md->destCh)) { if (new_ch) *new_ch = 1; - //highlight channell if needed + //highlight channel if needed if (md->destCh == highlightedSource) { str = "" + str + ""; } @@ -164,53 +148,7 @@ QString MixesPanel::getMixerText(int dest, bool * new_ch) str.fill(' '); } - switch (md->mltpx) { - case (1): str += " *"; break; - case (2): str += " R"; break; - default: str += " "; break; - }; - - // highlight source if needed - if ( (md->srcRaw.type == SOURCE_TYPE_CH) && (md->srcRaw.index+1 == (int)highlightedSource) ) { - str += " " + Qt::escape(md->srcRaw.toString(model)) + ""; - } - else { - str += " " + Qt::escape(md->srcRaw.toString(model)); - } - - str += " " + Qt::escape(tr("Weight(%1)").arg(getGVarString(md->weight, true))); - - QString phasesStr = getPhasesStr(md->phases, model); - if (!phasesStr.isEmpty()) str += " " + Qt::escape(phasesStr); - - if (md->swtch.type != SWITCH_TYPE_NONE) { - str += " " + Qt::escape(tr("Switch(%1)").arg(md->swtch.toString())); - } - - if (md->carryTrim > 0) - str += " " + Qt::escape(tr("NoTrim")); - else if (md->carryTrim<0) - str += " " + RawSource(SOURCE_TYPE_TRIM, (-(md->carryTrim)-1)).toString(model); - - if (firmware->getCapability(HasNoExpo) && md->noExpo) str += " " + Qt::escape(tr("No DR/Expo")); - if (md->sOffset) str += " " + Qt::escape(tr("Offset(%1)").arg(getGVarString(md->sOffset))); - if (md->curve.value) str += " " + Qt::escape(md->curve.toString()); - - int scale = firmware->getCapability(SlowScale); - if (scale == 0) - scale = 1; - if (md->delayDown || md->delayUp) - str += Qt::escape(tr(" Delay(u%1:d%2)").arg((double)md->delayUp/scale).arg((double)md->delayDown/scale)); - if (md->speedDown || md->speedUp) - str += Qt::escape(tr(" Slow(u%1:d%2)").arg((double)md->speedUp/scale).arg((double)md->speedDown/scale)); - if (md->mixWarn) str += Qt::escape(tr(" Warn(%1)").arg(md->mixWarn)); - if (firmware->getCapability(HasMixerNames)) { - QString MixerName; - MixerName.append(md->name); - if (!MixerName.isEmpty()) { - str += " " + Qt::escape(QString("(%1)").arg(MixerName)); - } - } + str += modelPrinter.printMixerLine(md, highlightedSource); } return str.replace(" ", " "); } diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h index bb6a0e705..66b3605e3 100644 --- a/companion/src/modeledit/mixes.h +++ b/companion/src/modeledit/mixes.h @@ -4,6 +4,7 @@ #include "modeledit.h" #include "mixerslist.h" #include "mixerdialog.h" +#include "modelprinter.h" class MixesPanel : public ModelPanel { @@ -44,6 +45,7 @@ class MixesPanel : public ModelPanel bool mixInserted; unsigned int highlightedSource; bool firstLine; + ModelPrinter modelPrinter; int getMixerIndex(unsigned int dch); bool gm_insertMix(int idx); @@ -53,7 +55,6 @@ class MixesPanel : public ModelPanel void mixersDeleteList(QList list); QList createMixListFromSelected(); void setSelectedByMixList(QList list); - QString getChannelLabel(int curDest); bool AddMixerLine(int dest); QString getMixerText(int dest, bool * new_ch); }; diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp new file mode 100644 index 000000000..e11ea37a9 --- /dev/null +++ b/companion/src/modelprinter.cpp @@ -0,0 +1,317 @@ +#include "helpers.h" +#include "modelprinter.h" + +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, + GeneralSettings *gg, ModelData *gm) : + firmware(firmware), + g_eeGeneral(gg), + g_model(gm) +{ +} + +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::printInputName(int idx) +{ + QString result; + if (GetCurrentFirmware()->getCapability(VirtualInputs)) { + if (strlen(g_model->inputNames[idx]) > 0) { + result = QObject::tr("[I%1]").arg(idx+1); + result += QString(g_model->inputNames[idx]); + } + else { + result = QObject::tr("Input%1").arg(idx+1, 2, 10, QChar('0')); + } + } + else { + result = RawSource(SOURCE_TYPE_STICK, idx).toString(g_model); + } + return Qt::escape(result); +} + +QString ModelPrinter::printInputLine(const ExpoData * ed) +{ + QString str = " "; + + switch (ed->mode) { + case (1): str += "<- "; break; + case (2): str += "-> "; break; + default: str += "   "; break; + } + + if (firmware->getCapability(VirtualInputs)) { + str += Qt::escape(ed->srcRaw.toString(g_model)); + } + + str += " " + Qt::escape(QObject::tr("Weight")) + QString("(%1)").arg(getGVarString(ed->weight,true)); + if (ed->curve.value) str += " " + Qt::escape(ed->curve.toString()); + + QString phasesStr = getPhasesStr(ed->phases); + if (!phasesStr.isEmpty()) str += " " + Qt::escape(phasesStr); + + if (ed->swtch.type != SWITCH_TYPE_NONE) + str += " " + Qt::escape(QObject::tr("Switch") + QString("(%1)").arg(ed->swtch.toString())); + + + if (firmware->getCapability(VirtualInputs)) { + if (ed->carryTrim>0) str += " " + Qt::escape(QObject::tr("NoTrim")); + else if (ed->carryTrim<0) str += " " + Qt::escape(RawSource(SOURCE_TYPE_TRIM, (-(ed->carryTrim)-1)).toString(g_model)); + } + + if (firmware->getCapability(HasExpoNames) && ed->name[0]) + str += Qt::escape(QString(" [%1]").arg(ed->name)); + + return str; +} + +QString ModelPrinter::printMixerName(int curDest) +{ + QString str; + str = QObject::tr("CH%1").arg(curDest); + // TODO not nice, Qt brings a function for that, I don't remember right now + (str.length() < 4) ? str.append(" ") : str.append(" "); + if (firmware->getCapability(HasChNames)) { + QString name = g_model->limitData[curDest-1].name; + if (!name.isEmpty()) { + name = QString("(") + name + QString(")"); + } + name.append(" "); + str += name.left(8); + } + return Qt::escape(str); +} + +QString ModelPrinter::printMixerLine(const MixData * md, int highlightedSource) +{ + QString str = " "; + + switch(md->mltpx) { + case (1): str += "*"; break; + case (2): str += "R"; break; + default: str += " "; break; + }; + + // highlight source if needed + QString source = Qt::escape(md->srcRaw.toString(g_model)); + if ( (md->srcRaw.type == SOURCE_TYPE_CH) && (md->srcRaw.index+1 == (int)highlightedSource) ) { + source = "" + source + ""; + } + str += " " + source; + + str += " " + Qt::escape(QObject::tr("Weight")) + QString("(%1)").arg(getGVarString(md->weight, true)); + + QString phasesStr = getPhasesStr(md->phases); + if (!phasesStr.isEmpty()) str += " " + Qt::escape(phasesStr); + + if (md->swtch.type != SWITCH_TYPE_NONE) { + str += " " + Qt::escape(QObject::tr("Switch")) + QString("(%1)").arg(md->swtch.toString()); + } + + if (md->carryTrim>0) str += " " + Qt::escape(QObject::tr("NoTrim")); + else if (md->carryTrim<0) str += " " + RawSource(SOURCE_TYPE_TRIM, (-(md->carryTrim)-1)).toString(g_model); + + if (firmware->getCapability(HasNoExpo) && md->noExpo) str += " " + Qt::escape(QObject::tr("No DR/Expo")); + if (md->sOffset) str += " " + Qt::escape(QObject::tr("Offset")) + QString("(%1)").arg(getGVarString(md->sOffset)); + if (md->curve.value) str += " " + Qt::escape(md->curve.toString()); + + int scale = firmware->getCapability(SlowScale); + if (scale == 0) + scale = 1; + if (md->delayDown || md->delayUp) + str += " " + Qt::escape(QObject::tr("Delay")) + QString("(u%1:d%2)").arg((double)md->delayUp/scale).arg((double)md->delayDown/scale); + if (md->speedDown || md->speedUp) + str += " " + Qt::escape(QObject::tr("Slow")) + QString("(u%1:d%2)").arg((double)md->speedUp/scale).arg((double)md->speedDown/scale); + if (md->mixWarn) + // str += Qt::escape(QObject::tr(" Warn(%1)").arg(md->mixWarn)); + str += " " + Qt::escape(QObject::tr("Warn")) + QString("(%1)").arg(md->mixWarn); + if (firmware->getCapability(HasMixerNames) && md->name[0]) + str += Qt::escape(QString(" [%1]").arg(md->name)); + return str; +} + +QString ModelPrinter::getPhasesStr(unsigned int phases) +{ + int numphases = GetCurrentFirmware()->getCapability(FlightModes); + + if (numphases && phases) { + QString str; + int count = 0; + if (phases == (unsigned int)(1< 0) str += QString(", "); + str += getPhaseName(i+1, g_model->flightModeData[i].name); + } + } + // } + if (count > 1) + return QObject::tr("Flight modes") + QString("(%1)").arg(str); + else + return QObject::tr("Flight mode") + QString("(%1)").arg(str); + } + return ""; +} + +QString ModelPrinter::printLogicalSwitchLine(int idx) +{ + QString result = ""; + const LogicalSwitchData & ls = g_model->logicalSw[idx]; + + if (!ls.func) + return result; + + if (ls.andsw!=0) { + result +="( "; + } + switch (ls.getFunctionFamily()) { + case LS_FAMILY_EDGE: + result += QObject::tr("Edge(%1, [%2:%3])").arg(RawSwitch(ls.val1).toString()).arg(ValToTim(ls.val2)).arg(ValToTim(ls.val2+ls.val3)); + break; + case LS_FAMILY_STICKY: + result += QObject::tr("Sticky(%1, %2)").arg(RawSwitch(ls.val1).toString()).arg(RawSwitch(ls.val2).toString()); + break; + case LS_FAMILY_TIMER: + result += QObject::tr("Timer(%1, %2)").arg(ValToTim(ls.val1)).arg(ValToTim(ls.val2)); + break; + case LS_FAMILY_VOFS: { + RawSource source = RawSource(ls.val1); + RawSourceRange range = source.getRange(g_model, *g_eeGeneral); + QString res; + if (ls.val1) + res += source.toString(g_model); + else + res += "0"; + res.remove(" "); + if (ls.func == LS_FN_APOS || ls.func == LS_FN_ANEG) + res = "|" + res + "|"; + else if (ls.func == LS_FN_DAPOS) + res = "|d(" + res + ")|"; + else if (ls.func == LS_FN_DPOS) result = "d(" + res + ")"; + result += res; + + if (ls.func == LS_FN_APOS || ls.func == LS_FN_VPOS || ls.func == LS_FN_DPOS || ls.func == LS_FN_DAPOS) + result += " > "; + else if (ls.func == LS_FN_ANEG || ls.func == LS_FN_VNEG) + result += " < "; + else if (ls.func == LS_FN_VALMOSTEQUAL) + result += " ~ "; + else + result += " missing"; + result += QString::number(range.step * (ls.val2 /*TODO+ source.getRawOffset(model)*/) + range.offset); + break; + } + case LS_FAMILY_VBOOL: + result += RawSwitch(ls.val1).toString(); + switch (ls.func) { + case LS_FN_AND: + result += " AND "; + break; + case LS_FN_OR: + result += " OR "; + break; + case LS_FN_XOR: + result += " XOR "; + break; + default: + result += " bar "; + break; + } + result += RawSwitch(ls.val2).toString(); + break; + + case LS_FAMILY_VCOMP: + if (ls.val1) + result += RawSource(ls.val1).toString(g_model); + else + result += "0"; + switch (ls.func) { + case LS_FN_EQUAL: + case LS_FN_VEQUAL: + result += " = "; + break; + case LS_FN_NEQUAL: + result += " != "; + break; + case LS_FN_GREATER: + result += " > "; + break; + case LS_FN_LESS: + result += " < "; + break; + case LS_FN_EGREATER: + result += " >= "; + break; + case LS_FN_ELESS: + result += " <= "; + break; + default: + result += " foo "; + break; + } + if (ls.val2) + result += RawSource(ls.val2).toString(g_model); + else + result += "0"; + break; + } + + if (ls.andsw!=0) { + result +=" ) AND "; + result += RawSwitch(ls.andsw).toString(); + } + + if (GetCurrentFirmware()->getCapability(LogicalSwitchesExt)) { + if (ls.duration) + result += QObject::tr(" Duration (%1s)").arg(ls.duration/10.0); + if (ls.delay) + result += QObject::tr(" Delay (%1s)").arg(ls.delay/10.0); + } + + return result; +} + +QString ModelPrinter::printCustomFunctionLine(int idx) +{ + QString result; + const CustomFunctionData & cf = g_model->customFn[idx]; + if (cf.swtch.type == SWITCH_TYPE_NONE) return result; + + result += cf.swtch.toString() + " - "; + result += cf.funcToString() + "("; + result += cf.paramToString(g_model) + ")"; + if (!cf.repeatToString().isEmpty()) result += " " + cf.repeatToString(); + if (!cf.enabledToString().isEmpty()) result += " " + cf.enabledToString(); + return result; +} diff --git a/companion/src/modelprinter.h b/companion/src/modelprinter.h new file mode 100644 index 000000000..6c4da6751 --- /dev/null +++ b/companion/src/modelprinter.h @@ -0,0 +1,35 @@ +#ifndef MODELPRINTER_H +#define MODELPRINTER_H + +#include +#include "eeprominterface.h" + +QString changeColor(const QString & input, const QString & to, const QString & from = "grey"); + +QString addFont(const QString & input, const QString & color = "", const QString & size = "", const QString & face = ""); + +void debugHtml(const QString & html); + + +class ModelPrinter +{ +public: + ModelPrinter(Firmware * firmware, GeneralSettings *gg, ModelData *gm); + ~ModelPrinter() {}; + + QString printInputName(int idx); + QString printInputLine(const ExpoData * ed); + QString printMixerName(int curDest); + QString printMixerLine(const MixData * md, int highlightedSource = 0); + QString printLogicalSwitchLine(int idx); + QString printCustomFunctionLine(int idx); + +private: + Firmware * firmware; + GeneralSettings * g_eeGeneral; + ModelData * g_model; + + QString getPhasesStr(unsigned int phases); +}; + +#endif //#ifndef MODELPRINTER_H \ No newline at end of file diff --git a/companion/src/printdialog.cpp b/companion/src/printdialog.cpp index 53724fbe1..4e23c1e4a 100644 --- a/companion/src/printdialog.cpp +++ b/companion/src/printdialog.cpp @@ -3,6 +3,7 @@ #include "helpers.h" #include "helpers_html.h" #include "eeprominterface.h" +#include "modelprinter.h" #include #include #include @@ -22,7 +23,8 @@ PrintDialog::PrintDialog(QWidget *parent, Firmware * firmware, GeneralSettings * g_model(gm), printfilename(filename), ui(new Ui::PrintDialog), - gvars(firmware->getCapability(Gvars)) + gvars(firmware->getCapability(Gvars)), + modelPrinter(firmware, gg, gm) { ui->setupUi(this); setWindowIcon(CompanionIcon("print.png")); @@ -48,8 +50,8 @@ PrintDialog::PrintDialog(QWidget *parent, Firmware * firmware, GeneralSettings * printLimits(); printCurves(); printGvars(); - printSwitches(); - printFSwitches(); + printLogicalSwitches(); + printCustomFunctions(); printFrSky(); te->scrollToAnchor("1"); @@ -191,161 +193,55 @@ QString PrintDialog::printFlightModes() void PrintDialog::printInputs() { QString str = "
"+tr("Analog")+""+tr("Unit")+""+tr("Scale")+""+tr("Offset")+"

"; - str.append(tr("Inputs")); - str.append("

"); + str += tr("Inputs"); + str += "
"; int ec=0; unsigned int lastCHN = 255; for(int i=0; iexpoData[i]; - if(ed->mode==0) - continue; + if(ed->mode==0) continue; ec++; - str.append(""); - str.append(""; + str += ""; + + str += ""; + str += ""; } str += "
"); + + str += "
"; if(lastCHN!=ed->chn) { lastCHN=ed->chn; - str.append(""+getInputStr(g_model, ed->chn)+""); + str += addFont(""+modelPrinter.printInputName(ed->chn)+"", "", "+1", "Courier New"); } - str.append(""); - - switch(ed->mode) { - case (1): - str += "<-"; - break; - case (2): - str += "->"; - break; - default: - str += "  "; - break; - }; - - str += " " + tr("Weight") + QString("(%1)").arg(getGVarString(ed->weight,true)); - - if (firmware->getCapability(VirtualInputs)) { - str += " " + tr("Source") + QString("(%1)").arg(ed->srcRaw.toString(g_model)); - if (ed->carryTrim>0) str += " " + tr("NoTrim"); - else if (ed->carryTrim<0) str += " " + RawSource(SOURCE_TYPE_TRIM, (-(ed->carryTrim)-1)).toString(g_model); - } - if (ed->curve.value) str += " " + Qt::escape(ed->curve.toString()); - - if (firmware->getCapability(FlightModes)) { - if(ed->phases) { - if (ed->phases!=(unsigned int)(1<getCapability(FlightModes))-1) { - unsigned int mask=1; - bool first = true; - bool multiple = false; - QString strModes; - for (int j=0; jgetCapability(FlightModes);j++) { - if (!(ed->phases & mask)) { - //FlightModeData *pd = &g_model->flightModeData[j]; - const char * pdName = g_model->flightModeData[j].name; - if (first) { - strModes += Qt::escape(QString("%1").arg(getPhaseName(j+1,pdName))); - first = false; - } else { - strModes += Qt::escape(QString(", %1").arg(getPhaseName(j+1, pdName))); - multiple = true; - } - } - mask <<= 1; - } - if (!strModes.isEmpty()) { - str += " " + tr(multiple?"Flight modes":"Flight mode") + "(" + strModes + ")"; - } - } else { - str += tr("DISABLED")+QString(" !!!"); - } - } - } - if (ed->swtch.type) str += " " + tr("Switch") + QString("(%1)").arg(ed->swtch.toString()); - if (firmware->getCapability(HasExpoNames) && ed->name[0]) str += Qt::escape(QString(" [%1]").arg(ed->name)); - str += "
" + addFont(modelPrinter.printInputLine(ed), "green", "+1", "Courier New") + "

"; - if (ec>0) - te->append(str); + if (ec>0) te->append(str); + // debugHtml(str); } void PrintDialog::printMixes() { QString str = "

"; - str.append(tr("Mixers")); - str.append("

"); + str += tr("Mixers"); + str += "
"; unsigned int lastCHN = 255; for(int i=0; igetCapability(Mixes); i++) { MixData *md = &g_model->mixData[i]; if(!md->destCh || md->destCh>(unsigned int)firmware->getCapability(Outputs) ) break; - str.append(""); - str.append(""; - str += " " + md->srcRaw.toString(g_model); - str += " " + Qt::escape(tr("Weight(%1)").arg(getGVarString(md->weight, true))); - - QString phasesStr = getPhasesStr(md->phases, g_model); - if (!phasesStr.isEmpty()) str += " " + Qt::escape(phasesStr); - - if (md->swtch.type != SWITCH_TYPE_NONE) { - str += " " + Qt::escape(tr("Switch(%1)").arg(md->swtch.toString())); - } - - if (md->carryTrim>0) - str += " " + Qt::escape(tr("NoTrim")); - else if (md->carryTrim<0) - str += " " + RawSource(SOURCE_TYPE_TRIM, (-(md->carryTrim)-1)).toString(g_model); - - if (firmware->getCapability(HasNoExpo) && md->noExpo) str += " " + Qt::escape(tr("No DR/Expo")); - if (md->sOffset) str += " " + Qt::escape(tr("Offset(%1)").arg(getGVarString(md->sOffset))); - if (md->curve.value) str += " " + Qt::escape(md->curve.toString()); - - int scale = firmware->getCapability(SlowScale); - if (scale == 0) - scale = 1; - if (md->delayDown || md->delayUp) - str += Qt::escape(tr(" Delay(u%1:d%2)").arg((double)md->delayUp/scale).arg((double)md->delayDown/scale)); - if (md->speedDown || md->speedUp) - str += Qt::escape(tr(" Slow(u%1:d%2)").arg((double)md->speedUp/scale).arg((double)md->speedDown/scale)); - if (md->mixWarn) - str += Qt::escape(tr(" Warn(%1)").arg(md->mixWarn)); - if (firmware->getCapability(HasMixerNames)) { - QString MixerName; - MixerName.append(md->name); - if (!MixerName.isEmpty()) { - str += " " + Qt::escape(QString("(%1)").arg(MixerName)); - } - } - str.append(""); + str += ""; + str += ""; } - str.append("
"); + + str += "
"; if(lastCHN!=md->destCh) { lastCHN=md->destCh; - - QString chname = QObject::tr("CH%1").arg(lastCHN); - // TODO not nice, Qt brings a function for that, I don't remember right now - (chname.length() < 4) ? chname.append(" ") : chname.append(" "); - if (firmware->getCapability(HasChNames)) { - QString name = g_model->limitData[lastCHN-1].name; - if (!name.isEmpty()) { - name = QString("(") + name + QString(")"); - } - name.append(" "); - chname += name.left(8); - } - chname = Qt::escape(chname); - str.append(chname.replace(" ", " ")); + str += addFont(modelPrinter.printMixerName(md->destCh).replace(" ", " "), "", "+1", "Courier New"); } - else { - str.append(" "); - } - str.append(""); - switch(md->mltpx) { - case (1): str += " *"; break; - case (2): str += " R"; break; - default: str += "  "; break; - }; + str += "
" + addFont(modelPrinter.printMixerLine(md), "green", "+1", "Courier New") + "

"); + str += "

"; te->append(str); + // debugHtml(str); } void PrintDialog::printLimits() @@ -572,27 +468,25 @@ void PrintDialog::printCurves() } } -void PrintDialog::printSwitches() +void PrintDialog::printLogicalSwitches() { - int sc=0; - QString str = ""; - str.append(""); - str.append("

"+tr("Logical Switches")+"

"); - - for (int i=0; igetCapability(LogicalSwitches); i++) { - if (g_model->logicalSw[i].func) { - str.append(""); - str.append("").arg(i+1)); - QString tstr = g_model->logicalSw[i].toString(*g_model, *g_eeGeneral); - str.append(doTL(tstr,"green")); - str.append(""); - sc++; - } + bool haveOutput = false; + QString str = "
"+tr("L")+QString("%1
"; + str += ""; + str += "

" + tr("Logical Switches") + "

"; + for (int i=0; igetCapability(LogicalSwitches); i++) { + QString sw = modelPrinter.printLogicalSwitchLine(i); + if (!sw.isEmpty()) { + str += ""; + str += "").arg(i+1); + str += ""; + str += ""; + haveOutput = true; } - str.append("
"+ tr("L") + QString("%1" + addFont(sw, "green") + "
"); - str.append("
"); - if (sc!=0) - te->append(str); + } + str += "
"; + str += "
"; + if (haveOutput) te->append(str); } void PrintDialog::printGvars() @@ -619,52 +513,35 @@ void PrintDialog::printGvars() } } -void PrintDialog::printFSwitches() +void PrintDialog::printCustomFunctions() { - int sc=0; - QString str = ""; - str.append(""); - str.append("

"+tr("Special Functions")+"

"); - str.append(""); - str.append(doTL(tr("Switch"), "", true)); - str.append(doTL(tr("Function"), "", true)); - str.append(doTL(tr("Parameter"), "", true)); - str.append(doTL(tr("Repeat"), "", true)); - str.append(doTL(tr("Enabled"), "", true)); - str.append(""); - for(int i=0; igetCapability(CustomFunctions); i++) { - if (g_model->customFn[i].swtch.type!=SWITCH_TYPE_NONE) { - str.append(""); - str.append(doTL(tr("SF%1").arg(i+1),"", true)); - str.append(doTL(g_model->customFn[i].swtch.toString(),"green")); - str.append(doTL(g_model->customFn[i].funcToString(),"green")); - str.append(doTL(g_model->customFn[i].paramToString(),"green")); - int index=g_model->customFn[i].func; - if ((g_model->customFn[i].repeatParam>0) && - (index==FuncPlaySound || index==FuncPlayHaptic || index==FuncPlayValue || index==FuncPlayPrompt || index==FuncPlayBoth || index==FuncBackgroundMusic)) { - str.append(doTL(QString("%1").arg(g_model->customFn[i].repeatParam),"green")); - } else { - str.append(doTL( " ","green")); - } - if ((index<=FuncInstantTrim) || (index>FuncBackgroundMusicPause)) { - str.append(doTL((g_model->customFn[i].enabled ? "ON" : "OFF"),"green")); - } else { - str.append(doTL( "---","green")); - } - str.append(""); - sc++; - } + bool haveOutput = false; + QString str = "
#
"; + str += ""; + str += "

" + tr("Special Functions") + "

"; + for (int i=0; igetCapability(CustomFunctions); i++) { + QString cf = modelPrinter.printCustomFunctionLine(i); + if (!cf.isEmpty()) { + str += ""; + str += "").arg(i+1); + str += ""; + str += ""; + haveOutput = true; } - str.append("
"+ tr("SF") + QString("%1" + addFont(cf, "green") + "
"); - str.append("
"); - if (sc!=0) - te->append(str); + } + str += "
"; + str += "
"; + if (haveOutput) te->append(str); } void PrintDialog::printFrSky() { int tc=0; QString str = ""; + int analog=2; + if (IS_ARM(firmware->getBoard())) { + analog=4; + } if (IS_TARANIS(GetEepromInterface()->getBoard())) { str.append(""); @@ -675,7 +552,7 @@ void PrintDialog::printFrSky() str.append(""); FrSkyData *fd=&g_model->frsky; - for (int i=0; i<2; i++) { + for (int i=0; ichannels[i].ratio!=0) { tc++; float ratio=(fd->channels[i].ratio/(fd->channels[i].type==0 ?10.0:1)); @@ -725,7 +602,7 @@ void PrintDialog::printFrSky() str.append(""); str.append(""); FrSkyData *fd=&g_model->frsky; - for (int i=0; i<2; i++) { + for (int i=0; ichannels[i].ratio!=0) { tc++; float ratio=(fd->channels[i].ratio/(fd->channels[i].type==0 ?10.0:1)); @@ -749,7 +626,7 @@ void PrintDialog::printFrSky() str.append(""); str.append(""); str.append(""); - str.append(""); + str.append(""); str.append("

"+tr("Telemetry Settings")+"

"+tr("Type")+""+tr("Condition")+""+tr("Value")+""+tr("Type")+""+tr("Condition")+""+tr("Value")+"
"+getFrSkyAlarmType(fd->rssiAlarms[1].level)+"<"+QString::number(fd->rssiAlarms[1].value,10)+"
"+tr("Frsky serial protocol")+""+getFrSkyProtocol(fd->usrProto)+"
"+tr("Blades")+""+fd->blades+"
"+tr("Blades")+""+QString("%1").arg(fd->blades)+"
"); } #if 0 diff --git a/companion/src/printdialog.h b/companion/src/printdialog.h index 4f5ddecd5..9804cd078 100644 --- a/companion/src/printdialog.h +++ b/companion/src/printdialog.h @@ -5,6 +5,7 @@ #include #include #include "eeprominterface.h" +#include "modelprinter.h" namespace Ui { class PrintDialog; @@ -37,9 +38,9 @@ private: void printLimits(); void printCurves(); void printGvars(); - void printSwitches(); + void printLogicalSwitches(); void printSafetySwitches(); - void printFSwitches(); + void printCustomFunctions(); void printFrSky(); void printToFile(); @@ -47,6 +48,8 @@ private: QString curvefile5; QString curvefile9; QDir *qd; + + ModelPrinter modelPrinter; private slots: void on_printButton_clicked(); diff --git a/companion/src/simulation/simulatordialog.cpp b/companion/src/simulation/simulatordialog.cpp index 20f17990b..0b25e2a8e 100644 --- a/companion/src/simulation/simulatordialog.cpp +++ b/companion/src/simulation/simulatordialog.cpp @@ -1,1137 +1,1136 @@ -#include "simulatordialog.h" -#include "ui_simulatordialog-9x.h" -#include "ui_simulatordialog-taranis.h" -#include -#include "helpers.h" -#include "simulatorinterface.h" - -#define GBALL_SIZE 20 -#define RESX 1024 - -int SimulatorDialog::screenshotIdx = 0; -SimulatorDialog * traceCallbackInstance = 0; - -void traceCb(const char * text) -{ - // divert C callback into simulator instance - if (traceCallbackInstance) { - traceCallbackInstance->traceCallback(text); - } -} - -void SimulatorDialog::traceCallback(const char * text) -{ - // this function is called from other threads - traceMutex.lock(); - // limit the size of list - if (traceList.size() < 1000) { - traceList.append(QString(text)); - } - traceMutex.unlock(); -} - -void SimulatorDialog::updateDebugOutput() -{ - traceMutex.lock(); - while (!traceList.isEmpty()) { - QString text = traceList.takeFirst(); - traceBuffer.append(text); - // limit the size of traceBuffer - if (traceBuffer.size() > 10*1024) { - traceBuffer.remove(0, 1*1024); - } - if (DebugOut) { - DebugOut->traceCallback(QString(text)); - } - } - traceMutex.unlock(); -} - -SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - QDialog(parent), - flags(flags), - timer(NULL), - lightOn(false), - simulator(simulator), - lastPhase(-1), - beepVal(0), - TelemetrySimu(0), - TrainerSimu(0), - DebugOut(0), - buttonPressed(0), - trimPressed (TRIM_NONE), - middleButtonPressed(false) -{ - //shorcut for telemetry simulator - // new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_T), this, SLOT(openTelemetrySimulator())); - new QShortcut(QKeySequence(Qt::Key_F4), this, SLOT(openTelemetrySimulator())); - new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(openTrainerSimulator())); - new QShortcut(QKeySequence(Qt::Key_F6), this, SLOT(openDebugOutput())); - traceCallbackInstance = this; -} - -uint32_t SimulatorDialog9X::switchstatus = 0; - -SimulatorDialog9X::SimulatorDialog9X(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialog9X), - beepShow(0) -{ - lcdWidth = 128; - lcdHeight = 64; - lcdDepth = 1; - - initUi(ui); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - backLight = g.backLight(); - if (backLight > 4) backLight = 0; - switch (backLight) { - case 1: - ui->lcd->setBackgroundColor(166,247,159); - break; - case 2: - ui->lcd->setBackgroundColor(247,159,166); - break; - case 3: - ui->lcd->setBackgroundColor(255,195,151); - break; - case 4: - ui->lcd->setBackgroundColor(247,242,159); - break; - default: - ui->lcd->setBackgroundColor(159,165,247); - break; - } - - //restore switches - if (g.simuSW()) - restoreSwitches(); - - ui->trimHR_L->setText(QString::fromUtf8(leftArrow)); - ui->trimHR_R->setText(QString::fromUtf8(rightArrow)); - ui->trimVR_U->setText(QString::fromUtf8(upArrow)); - ui->trimVR_D->setText(QString::fromUtf8(downArrow)); - ui->trimHL_L->setText(QString::fromUtf8(leftArrow)); - ui->trimHL_R->setText(QString::fromUtf8(rightArrow)); - ui->trimVL_U->setText(QString::fromUtf8(upArrow)); - ui->trimVL_D->setText(QString::fromUtf8(downArrow)); - for (int i=0; isetProperty("index", i); - connect(pots[i], SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int))); - } - connect(ui->cursor, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->menu, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased())); -} - -SimulatorDialog9X::~SimulatorDialog9X() -{ - saveSwitches(); - delete ui; -} - -uint32_t SimulatorDialogTaranis::switchstatus = 0; - -SimulatorDialogTaranis::SimulatorDialogTaranis(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): - SimulatorDialog(parent, simulator, flags), - ui(new Ui::SimulatorDialogTaranis) -{ - lcdWidth = 212; - lcdHeight = 64; - lcdDepth = 4; - - initUi(ui); - - // install simulator TRACE hook - simulator->installTraceHook(traceCb); - - ui->lcd->setBackgroundColor(47, 123, 227); - - // restore switches - if (g.simuSW()) { - restoreSwitches(); - } - - for (int i=0; isetValue(-1024); - pots[i]->setSingleStep(2048/5); - pots[i]->setPageStep(2048/5); - } - else if (!(flags & (SIMULATOR_FLAGS_S1 << i))) { - pots[i]->hide(); - potLabels[i]->hide(); - } - } - - ui->trimHR_L->setText(QString::fromUtf8(leftArrow)); - ui->trimHR_R->setText(QString::fromUtf8(rightArrow)); - ui->trimVR_U->setText(QString::fromUtf8(upArrow)); - ui->trimVR_D->setText(QString::fromUtf8(downArrow)); - ui->trimHL_L->setText(QString::fromUtf8(leftArrow)); - ui->trimHL_R->setText(QString::fromUtf8(rightArrow)); - ui->trimVL_U->setText(QString::fromUtf8(upArrow)); - ui->trimVL_D->setText(QString::fromUtf8(downArrow)); - - connect(ui->cursor, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->menu, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); - connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); - connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased())); - connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased())); -} - -SimulatorDialogTaranis::~SimulatorDialogTaranis() -{ - saveSwitches(); - delete ui; -} - -SimulatorDialog::~SimulatorDialog() -{ - traceCallbackInstance = 0; - delete timer; - delete simulator; -} - -void SimulatorDialog::closeEvent (QCloseEvent *) -{ - simulator->stop(); - timer->stop(); -} - -void SimulatorDialog::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton) { - middleButtonPressed = true; - } -} - -void SimulatorDialog::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton) { - middleButtonPressed = false; - } -} - -void SimulatorDialog9X::dialChanged(int value) -{ - int index = sender()->property("index").toInt(); - potValues[index]->setText(QString("%1 %").arg((value*100)/1024)); -} - -void SimulatorDialog::wheelEvent (QWheelEvent *event) -{ - simulator->wheelEvent(event->delta() > 0 ? 1 : -1); -} - -void SimulatorDialog::onTrimPressed() -{ - if (sender()->objectName() == QString("trimHL_L")) - trimPressed = TRIM_LH_L; - else if (sender()->objectName() == QString("trimHL_R")) - trimPressed = TRIM_LH_R; - else if (sender()->objectName() == QString("trimVL_D")) - trimPressed = TRIM_LV_DN; - else if (sender()->objectName() == QString("trimVL_U")) - trimPressed = TRIM_LV_UP; - else if (sender()->objectName() == QString("trimVR_D")) - trimPressed = TRIM_RV_DN; - else if (sender()->objectName() == QString("trimVR_U")) - trimPressed = TRIM_RV_UP; - else if (sender()->objectName() == QString("trimHR_L")) - trimPressed = TRIM_RH_L; - else if (sender()->objectName() == QString("trimHR_R")) - trimPressed = TRIM_RH_R; -} - -void SimulatorDialog::onTrimReleased() -{ - trimPressed = TRIM_NONE; -} - -void SimulatorDialog::openTelemetrySimulator() -{ - // allow only one instance - if (TelemetrySimu == 0) { - TelemetrySimu = new TelemetrySimulator(this, simulator); - TelemetrySimu->show(); - } - else if (!TelemetrySimu->isVisible()) { - TelemetrySimu->show(); - } -} - -void SimulatorDialog::openTrainerSimulator() -{ - // allow only one instance - if (TrainerSimu == 0) { - TrainerSimu = new TrainerSimulator(this, simulator); - TrainerSimu->show(); - } - else if (!TrainerSimu->isVisible()) { - TrainerSimu->show(); - } -} - -void SimulatorDialog::openDebugOutput() -{ - // allow only one instance, but install signal handler to catch dialog destruction just in case - if (DebugOut == 0) { - DebugOut = new DebugOutput(this); - QObject::connect(DebugOut, SIGNAL(destroyed()), this, SLOT(onDebugOutputClose())); - DebugOut->traceCallback(traceBuffer); - DebugOut->show(); - } - else if (!DebugOut->isVisible()) { - DebugOut->show(); - } -} - -void SimulatorDialog::onDebugOutputClose() -{ - DebugOut = 0; -} - -void SimulatorDialog::keyPressEvent (QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - buttonPressed = Qt::Key_Enter; - break; - case Qt::Key_Escape: - case Qt::Key_Backspace: - buttonPressed = Qt::Key_Escape; - break; - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Right: - case Qt::Key_Left: - case Qt::Key_Minus: - case Qt::Key_Plus: - case Qt::Key_PageDown: - case Qt::Key_PageUp: - buttonPressed = event->key(); - break; - } -} - -void SimulatorDialog::keyReleaseEvent(QKeyEvent * event) -{ - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_Escape: - case Qt::Key_Backspace: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Right: - case Qt::Key_Left: - case Qt::Key_Plus: - case Qt::Key_Minus: - case Qt::Key_PageDown: - case Qt::Key_PageUp: - buttonPressed = 0; - break; - } -} - -void SimulatorDialog::setupTimer() -{ - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent())); - timer->start(10); -} - -template -void SimulatorDialog::initUi(T * ui) -{ - ui->setupUi(this); - - lcd = ui->lcd; - leftStick = ui->leftStick; - rightStick = ui->rightStick; - pots = findWidgets(this, "pot%1"); - potLabels = findWidgets(this, "potLabel%1"); - potValues = findWidgets(this, "potValue%1"); - sliders = findWidgets(this, "slider%1"); - - trimHLeft = ui->trimHLeft; - trimVLeft = ui->trimVLeft; - trimHRight = ui->trimHRight; - trimVRight = ui->trimVRight; - tabWidget = ui->tabWidget; - leftXPerc = ui->leftXPerc; - leftYPerc = ui->leftYPerc; - rightXPerc = ui->rightXPerc; - rightYPerc = ui->rightYPerc; - - setupSticks(); - - resize(0, 0); // to force min height, min width - setFixedSize(width(), height()); - -#ifdef JOYSTICKS - if (g.jsSupport()) { - int count=0; - for (int j=0; j<8; j++){ - int axe = g.joystick[j].stick_axe(); - if (axe>=0 && axe<8) { - jsmap[axe]=j+1; - jscal[axe][0] = g.joystick[j].stick_min(); - jscal[axe][1] = g.joystick[j].stick_med(); - jscal[axe][2] = g.joystick[j].stick_max(); - jscal[axe][3] = g.joystick[j].stick_inv(); - count++; - } - } - if (count<3) { - QMessageBox::critical(this, tr("Warning"), tr("Joystick enabled but not configured correctly")); - } - if (g.jsCtrl()!=-1) { - joystick = new Joystick(this); - if (joystick) { - if (joystick->open(g.jsCtrl())) { - int numAxes=std::min(joystick->numAxes,8); - for (int j=0; jsensitivities[j] = 0; - joystick->deadzones[j]=0; - } - nodeRight->setCenteringY(false); //mode 1,3 -> THR on right - ui->holdRightY->setChecked(true); - nodeRight->setCenteringX(false); //mode 1,3 -> THR on right - ui->holdRightX->setChecked(true); - nodeLeft->setCenteringY(false); //mode 1,3 -> THR on right - ui->holdLeftY->setChecked(true); - nodeLeft->setCenteringX(false); //mode 1,3 -> THR on right - ui->holdLeftX->setChecked(true); - connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int))); - } - else { - QMessageBox::critical(this, tr("Warning"), tr("Cannot open joystick, joystick disabled")); - } - } - } - } -#endif - - windowName = tr("Simulating Radio (%1)").arg(GetCurrentFirmware()->getName()); - setWindowTitle(windowName); - - simulator->setSdPath(g.profile[g.id()].sdPath()); - simulator->setVolumeGain(g.profile[g.id()].volumeGain()); - lcd->setData(simulator->getLcd(), lcdWidth, lcdHeight, lcdDepth); - - if (flags & SIMULATOR_FLAGS_STICK_MODE_LEFT) { - nodeLeft->setCenteringY(false); - ui->holdLeftY->setChecked(true); - } - else { - nodeRight->setCenteringY(false); - ui->holdRightY->setChecked(true); - } - - setTrims(); - - int outputs = std::min(32, GetCurrentFirmware()->getCapability(Outputs)); - if (outputs <= 16) { - // hide second Outputs tab - tabWidget->removeTab(tabWidget->indexOf(ui->outputs2)); - } - else { - tabWidget->setTabText(tabWidget->indexOf(ui->outputs), tr("Outputs") + QString(" 1-%1").arg(16)); - tabWidget->setTabText(tabWidget->indexOf(ui->outputs2), tr("Outputs") + QString(" 17-%1").arg(outputs)); - } - for (int i=0; ichannelsLayout; - int column = i / (std::min(16,outputs)/2); - int line = i % (std::min(16,outputs)/2); - if (i >= 16 ) { - outputTab = ui->channelsLayout2; - column = (i-16) / (std::min(16,outputs-16)/2); - line = (i-16) % (std::min(16,outputs-16)/2); - } - QLabel * label = new QLabel(tabWidget); - ModelData model; - label->setText(RawSource(SOURCE_TYPE_CH, i).toString(&model)); - outputTab->addWidget(label, line, column == 0 ? 0 : 5, 1, 1); - - QSlider * slider = new QSlider(tabWidget); - slider->setEnabled(false); - slider->setMaximumSize(QSize(16777215, 18)); - slider->setStyleSheet(QString::fromUtf8("QSlider::sub-page:horizontal:disabled {\n" - "border-color: #999;\n" - "}\n" - "\n" - "QSlider::add-page:horizontal:disabled {\n" - "border-color: #999;\n" - "}\n" - "\n" - "QSlider::handle:horizontal:disabled {\n" - "background: #0000CC;\n" - "border: 1px solid #aaa;\n" - "border-radius: 4px;\n" - "}")); - slider->setMinimum(-1024); - slider->setMaximum(1024); - slider->setPageStep(128); - slider->setTracking(false); - slider->setOrientation(Qt::Horizontal); - slider->setInvertedAppearance(false); - slider->setTickPosition(QSlider::TicksBelow); - channelSliders << slider; - outputTab->addWidget(slider, line, column == 0 ? 1 : 4, 1, 1); - - QLabel * value = new QLabel(tabWidget); - value->setMinimumSize(QSize(50, 0)); - value->setAlignment(Qt::AlignCenter); - channelValues << value; - outputTab->addWidget(value, line, column == 0 ? 2 : 3, 1, 1); - } - - int switches = GetCurrentFirmware()->getCapability(LogicalSwitches); - for (int i=0; ilogicalSwitchesLayout->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1); - if (outputs > 16) { - // repeat logical switches on second outputs tab - swtch = createLogicalSwitch(tabWidget, i, logicalSwitchLabels2); - ui->logicalSwitchesLayout2->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1); - } - } - - int fmodes = GetCurrentFirmware()->getCapability(FlightModes); - int gvars = GetCurrentFirmware()->getCapability(Gvars); - if (gvars>0) { - for (int fm=0; fmsetText(QString("FM%1").arg(fm)); - label->setAlignment(Qt::AlignCenter); - ui->gvarsLayout->addWidget(label, 0, fm+1); - } - for (int i=0; isetText(QString("GV%1").arg(i+1)); - label->setAutoFillBackground(true); - if ((i % 2) ==0 ) { - label->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }"); - } - ui->gvarsLayout->addWidget(label, i+1, 0); - for (int fm=0; fmsetAutoFillBackground(true); - value->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - if ((i % 2) ==0 ) { - value->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }"); - } - gvarValues << value; - ui->gvarsLayout->addWidget(value, i+1, fm+1); - } - } - } - - if (flags & SIMULATOR_FLAGS_NOTX) { - ui->tabWidget->setCurrentWidget(ui->outputs); - } - else { - ui->tabWidget->setCurrentWidget(ui->simu); - } -} - -QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels) -{ - QFrame * swtch = new QFrame(parent); - swtch->setAutoFillBackground(true); - swtch->setFrameShape(QFrame::Panel); - swtch->setFrameShadow(QFrame::Raised); - swtch->setLineWidth(2); - QVBoxLayout * layout = new QVBoxLayout(swtch); - layout->setContentsMargins(2, 2, 2, 2); - QLabel * label = new QLabel(swtch); - label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString()); - label->setAlignment(Qt::AlignCenter); - labels << label; - layout->addWidget(label); - return swtch; -} - -void SimulatorDialog::onButtonPressed(int value) -{ - if (value == Qt::Key_Print) { - QString fileName = ""; - if (!g.snapToClpbrd()) { - fileName = QString("screenshot-%1.png").arg(++screenshotIdx); - } - lcd->makeScreenshot(fileName); - } - else { - buttonPressed = value; - } -} - -void SimulatorDialog9X::setLightOn(bool enable) -{ - QString bg = ""; - if (enable) { - QStringList list; - list << "bl" << "gr" << "rd" << "or" << "yl"; - bg = QString("-") + list[backLight]; - } - ui->top->setStyleSheet(QString("background:url(:/images/9xdt%1.png);").arg(bg)); - ui->bottom->setStyleSheet(QString("background:url(:/images/9xdb%1.png);").arg(bg)); - ui->left->setStyleSheet(QString("background:url(:/images/9xdl%1.png);").arg(bg)); - ui->right->setStyleSheet(QString("background:url(:/images/9xdr%1.png);").arg(bg)); -} - -void SimulatorDialog9X::updateBeepButton() -{ - #define CBEEP_ON "QLabel { background-color: #FF364E }" - #define CBEEP_OFF "QLabel { }" - - if (beepVal) { - beepShow = 20; - } - - ui->label_beep->setStyleSheet(beepShow ? CBEEP_ON : CBEEP_OFF); - - if (beepShow) { - beepShow--; - } -} - -void SimulatorDialog::onTimerEvent() -{ - static unsigned int lcd_counter = 0; - if (!simulator->timer10ms()) { - QMessageBox::critical(this, "Companion", tr("Firmware %1 error: %2").arg(GetCurrentFirmware()->getName()).arg(simulator->getError())); - timer->stop(); - return; - } - - getValues(); - - if (tabWidget->currentIndex()==0) { - bool lightEnable; - if (simulator->lcdChanged(lightEnable)) { - lcd->onLcdChanged(lightEnable); - if (lightOn != lightEnable) { - setLightOn(lightEnable); - lightOn = lightEnable; - } - } - } - - // display current flight mode in window title - unsigned int currentPhase = simulator->getPhase(); - if (currentPhase != lastPhase) { - lastPhase = currentPhase; - const char * phase_name = simulator->getPhaseName(currentPhase); - if (phase_name && phase_name[0]) { - setWindowTitle(windowName + QString(" - Flight Mode %1").arg(QString(phase_name))); - } - else { - setWindowTitle(windowName + QString(" - Flight Mode %1").arg(simulator->getPhase())); - } - } - - if (!(lcd_counter++ % 5)) { - - setValues(); - - setTrims(); - - centerSticks(); - - updateBeepButton(); - - if (beepVal) { - beepVal = 0; - QApplication::beep(); - } - } - - updateDebugOutput(); -} - -void SimulatorDialog::centerSticks() -{ - if (leftStick->scene()) - nodeLeft->stepToCenter(); - - if (rightStick->scene()) - nodeRight->stepToCenter(); -} - -void SimulatorDialog::start(QByteArray & eeprom) -{ - lastPhase = -1; - numGvars = GetCurrentFirmware()->getCapability(Gvars); - numFlightModes = GetCurrentFirmware()->getCapability(FlightModes); - simulator->start(eeprom, (flags & SIMULATOR_FLAGS_NOTX) ? false : true); - getValues(); - setupTimer(); -} - -void SimulatorDialog::start(const char * filename) -{ - lastPhase = -1; - numGvars = GetCurrentFirmware()->getCapability(Gvars); - numFlightModes = GetCurrentFirmware()->getCapability(FlightModes); - simulator->start(filename); - getValues(); - setupTimer(); -} - -void SimulatorDialog::setTrims() -{ - Trims trims; - simulator->getTrims(trims); - - int trimMin = -125, trimMax = +125; - if (trims.extended) { - trimMin = -500; - trimMax = +500; - } - trimHLeft->setRange(trimMin, trimMax); trimHLeft->setValue(trims.values[0]); - trimVLeft->setRange(trimMin, trimMax); trimVLeft->setValue(trims.values[1]); - trimVRight->setRange(trimMin, trimMax); trimVRight->setValue(trims.values[2]); - trimHRight->setRange(trimMin, trimMax); trimHRight->setValue(trims.values[3]); -} - -void SimulatorDialog9X::getValues() -{ - TxInputs inputs = { - { - int(1024*nodeLeft->getX()), // LEFT HORZ - int(-1024*nodeLeft->getY()), // LEFT VERT - int(-1024*nodeRight->getY()), // RGHT VERT - int(1024*nodeRight->getX()) // RGHT HORZ - }, - - { - pots[0]->value(), - pots[1]->value(), - pots[2]->value() - }, - - { - ui->switchTHR->isChecked(), - ui->switchRUD->isChecked(), - ui->switchELE->isChecked(), - ui->switchID2->isChecked() ? 1 : (ui->switchID1->isChecked() ? 0 : -1), - ui->switchAIL->isChecked(), - ui->switchGEA->isChecked(), - ui->switchTRN->isDown(), - 0, 0, 0 - }, - - { - buttonPressed == Qt::Key_Enter, - buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Down, - buttonPressed == Qt::Key_Up, - buttonPressed == Qt::Key_Right, - buttonPressed == Qt::Key_Left, - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R - } - }; - - simulator->setValues(inputs); -} - -void SimulatorDialog9X::saveSwitches(void) -{ - // qDebug() << "SimulatorDialog9X::saveSwitches()"; - switchstatus=ui->switchTHR->isChecked(); - switchstatus<<=1; - switchstatus+=(ui->switchRUD->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID2->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID1->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchID0->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchGEA->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchELE->isChecked()&0x1); - switchstatus<<=1; - switchstatus+=(ui->switchAIL->isChecked()&0x1); -} - -void SimulatorDialog9X::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialog9X::restoreSwitches()"; - ui->switchAIL->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchELE->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchGEA->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID0->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID1->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchID2->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchRUD->setChecked(switchstatus & 0x1); - switchstatus >>=1; - ui->switchTHR->setChecked(switchstatus & 0x1); -} - -void SimulatorDialogTaranis::resetSH() -{ - ui->switchH->setValue(0); -} - -void SimulatorDialogTaranis::on_switchH_sliderReleased() -{ - QTimer::singleShot(400, this, SLOT(resetSH())); -} - -void SimulatorDialogTaranis::getValues() -{ - for (int i=0; ivalue()+1024)/(2048.0/5))*(2048.0/5)-1024; - pots[i]->setValue(s1); - } - } - - TxInputs inputs = { - { - int(1024*nodeLeft->getX()), // LEFT HORZ - int(-1024*nodeLeft->getY()), // LEFT VERT - int(-1024*nodeRight->getY()), // RGHT VERT - int(1024*nodeRight->getX()) // RGHT HORZ - }, - - { - -pots[0]->value(), - pots[1]->value(), - ((flags && SIMULATOR_FLAGS_S3) ? pots[2]->value() : 0), - -sliders[0]->value(), - sliders[1]->value() - }, - - { - ui->switchA->value() - 1, - ui->switchB->value() - 1, - ui->switchC->value() - 1, - ui->switchD->value() - 1, - ui->switchE->value() - 1, - ui->switchF->value(), - ui->switchG->value() - 1, - ui->switchH->value(), 0, 0 - }, - - { - buttonPressed == Qt::Key_PageUp, - buttonPressed == Qt::Key_Escape, - buttonPressed == Qt::Key_Enter, - buttonPressed == Qt::Key_PageDown, - buttonPressed == Qt::Key_Plus, - buttonPressed == Qt::Key_Minus - }, - - middleButtonPressed, - - { - trimPressed == TRIM_LH_L, - trimPressed == TRIM_LH_R, - trimPressed == TRIM_LV_DN, - trimPressed == TRIM_LV_UP, - trimPressed == TRIM_RV_DN, - trimPressed == TRIM_RV_UP, - trimPressed == TRIM_RH_L, - trimPressed == TRIM_RH_R - } - }; - - simulator->setValues(inputs); -} - -void SimulatorDialogTaranis::saveSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::saveSwitches()"; - switchstatus=ui->switchA->value(); - switchstatus<<=2; - switchstatus+=ui->switchB->value(); - switchstatus<<=2; - switchstatus+=ui->switchC->value(); - switchstatus<<=2; - switchstatus+=ui->switchD->value(); - switchstatus<<=2; - switchstatus+=ui->switchE->value(); - switchstatus<<=2; - switchstatus+=ui->switchF->value(); - switchstatus<<=2; - switchstatus+=ui->switchG->value(); - switchstatus<<=2; - switchstatus+=ui->switchH->value(); -} - -void SimulatorDialogTaranis::restoreSwitches(void) -{ - // qDebug() << "SimulatorDialogTaranis::restoreSwitches()"; - ui->switchH->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchG->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchF->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchE->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchD->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchC->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchB->setValue(switchstatus & 0x3); - switchstatus>>=2; - ui->switchA->setValue(switchstatus & 0x3); -} - -inline int chVal(int val) -{ - return qMin(1024, qMax(-1024, val)); -} - -void SimulatorDialog::on_trimHLeft_valueChanged(int value) -{ - simulator->setTrim(0, value); -} - -void SimulatorDialog::on_trimVLeft_valueChanged(int value) -{ - simulator->setTrim(1, value); -} - -void SimulatorDialog::on_trimVRight_valueChanged(int value) -{ - simulator->setTrim(2, value); -} - -void SimulatorDialog::on_trimHRight_valueChanged(int value) -{ - simulator->setTrim(3, value); -} - -void SimulatorDialog::setValues() -{ - TxOutputs outputs; - simulator->getValues(outputs); - Trims trims; - simulator->getTrims(trims); - - for (int i=0; igetCapability(Outputs); i++) { - if (i < channelSliders.size()) { - channelSliders[i]->setValue(chVal(outputs.chans[i])); - channelValues[i]->setText(QString("%1").arg((qreal)outputs.chans[i]*100/1024, 0, 'f', 1)); - } - } - - leftXPerc->setText(QString("X %1%").arg((qreal)nodeLeft->getX()*100+trims.values[0]/5, 2, 'f', 0)); - leftYPerc->setText(QString("Y %1%").arg((qreal)nodeLeft->getY()*-100+trims.values[1]/5, 2, 'f', 0)); - - rightXPerc->setText(QString("X %1%").arg((qreal)nodeRight->getX()*100+trims.values[3]/5, 2, 'f', 0)); - rightYPerc->setText(QString("Y %1%").arg((qreal)nodeRight->getY()*-100+trims.values[2]/5, 2, 'f', 0)); - - QString CSWITCH_ON = "QLabel { background-color: #4CC417 }"; - QString CSWITCH_OFF = "QLabel { }"; - - for (int i=0; igetCapability(LogicalSwitches); i++) { - logicalSwitchLabels[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); - if (!logicalSwitchLabels2.isEmpty()) { - logicalSwitchLabels2[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); - } - } - - for (unsigned int gv=0; gvsetText(QString((fm==lastPhase)?"%1":"%1").arg(outputs.gvars[fm][gv])); - } - } - - if (outputs.beep) { - beepVal = outputs.beep; - } -} - -void SimulatorDialog::setupSticks() -{ - QGraphicsScene *leftScene = new QGraphicsScene(leftStick); - leftScene->setItemIndexMethod(QGraphicsScene::NoIndex); - leftStick->setScene(leftScene); - - // leftStick->scene()->addLine(0,10,20,30); - - QGraphicsScene *rightScene = new QGraphicsScene(rightStick); - rightScene->setItemIndexMethod(QGraphicsScene::NoIndex); - rightStick->setScene(rightScene); - - // rightStick->scene()->addLine(0,10,20,30); - - nodeLeft = new Node(); - nodeLeft->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2); - nodeLeft->setBallSize(GBALL_SIZE); - leftScene->addItem(nodeLeft); - - nodeRight = new Node(); - nodeRight->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2); - nodeRight->setBallSize(GBALL_SIZE); - rightScene->addItem(nodeRight); -} - -void SimulatorDialog::resizeEvent(QResizeEvent *event) -{ - if (leftStick->scene()) { - QRect qr = leftStick->contentsRect(); - qreal w = (qreal)qr.width() - GBALL_SIZE; - qreal h = (qreal)qr.height() - GBALL_SIZE; - qreal cx = (qreal)qr.width()/2; - qreal cy = (qreal)qr.height()/2; - leftStick->scene()->setSceneRect(-cx,-cy,w,h); - - QPointF p = nodeLeft->pos(); - p.setX(qMin(cx, qMax(p.x(), -cx))); - p.setY(qMin(cy, qMax(p.y(), -cy))); - nodeLeft->setPos(p); - } - - if (rightStick->scene()) { - QRect qr = rightStick->contentsRect(); - qreal w = (qreal)qr.width() - GBALL_SIZE; - qreal h = (qreal)qr.height() - GBALL_SIZE; - qreal cx = (qreal)qr.width()/2; - qreal cy = (qreal)qr.height()/2; - rightStick->scene()->setSceneRect(-cx,-cy,w,h); - - QPointF p = nodeRight->pos(); - p.setX(qMin(cx, qMax(p.x(), -cx))); - p.setY(qMin(cy, qMax(p.y(), -cy))); - nodeRight->setPos(p); - } - QDialog::resizeEvent(event); -} - -void SimulatorDialog::on_holdLeftX_clicked(bool checked) -{ - nodeLeft->setCenteringX(!checked); -} - -void SimulatorDialog::on_holdLeftY_clicked(bool checked) -{ - nodeLeft->setCenteringY(!checked); -} - -void SimulatorDialog::on_holdRightX_clicked(bool checked) -{ - nodeRight->setCenteringX(!checked); -} - -void SimulatorDialog::on_holdRightY_clicked(bool checked) -{ - nodeRight->setCenteringY(!checked); -} - -void SimulatorDialog::on_FixLeftX_clicked(bool checked) -{ - nodeLeft->setFixedX(checked); -} - -void SimulatorDialog::on_FixLeftY_clicked(bool checked) -{ - nodeLeft->setFixedY(checked); -} - -void SimulatorDialog::on_FixRightX_clicked(bool checked) -{ - nodeRight->setFixedX(checked); -} - -void SimulatorDialog::on_FixRightY_clicked(bool checked) -{ - nodeRight->setFixedY(checked); -} - -#ifdef JOYSTICKS -void SimulatorDialog::onjoystickAxisValueChanged(int axis, int value) -{ - int stick; - if (axis>=0 && axis<=8) { - stick=jsmap[axis]; - int stickval; - if (value>jscal[axis][1]) { - if ((jscal[axis][2]-jscal[axis][1])==0) - return; - stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][2]-jscal[axis][1]); - } - else { - if ((jscal[axis][1]-jscal[axis][0])==0) - return; - stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][1]-jscal[axis][0]); - } - if (jscal[axis][3]==1) { - stickval*=-1; - } - if (stick==1 ) { - nodeRight->setY(-stickval/1024.0); - } - else if (stick==2) { - nodeRight->setX(stickval/1024.0); - } - else if (stick==3) { - nodeLeft->setY(-stickval/1024.0); - } - else if (stick==4) { - nodeLeft->setX(stickval/1024.0); - } - else if (stick >= 5 && stick < 5+pots.count()) { - pots[stick-5]->setValue(stickval); - } - } -} -#endif +#include "simulatordialog.h" +#include "ui_simulatordialog-9x.h" +#include "ui_simulatordialog-taranis.h" +#include +#include "helpers.h" +#include "simulatorinterface.h" + +#define GBALL_SIZE 20 +#define RESX 1024 + +int SimulatorDialog::screenshotIdx = 0; +SimulatorDialog * traceCallbackInstance = 0; + +void traceCb(const char * text) +{ + // divert C callback into simulator instance + if (traceCallbackInstance) { + traceCallbackInstance->traceCallback(text); + } +} + +void SimulatorDialog::traceCallback(const char * text) +{ + // this function is called from other threads + traceMutex.lock(); + // limit the size of list + if (traceList.size() < 1000) { + traceList.append(QString(text)); + } + traceMutex.unlock(); +} + +void SimulatorDialog::updateDebugOutput() +{ + traceMutex.lock(); + while (!traceList.isEmpty()) { + QString text = traceList.takeFirst(); + traceBuffer.append(text); + // limit the size of traceBuffer + if (traceBuffer.size() > 10*1024) { + traceBuffer.remove(0, 1*1024); + } + if (DebugOut) { + DebugOut->traceCallback(QString(text)); + } + } + traceMutex.unlock(); +} + +SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): + QDialog(parent), + flags(flags), + timer(NULL), + lightOn(false), + simulator(simulator), + lastPhase(-1), + beepVal(0), + TelemetrySimu(0), + TrainerSimu(0), + DebugOut(0), + buttonPressed(0), + trimPressed (TRIM_NONE), + middleButtonPressed(false) +{ + //shorcut for telemetry simulator + // new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_T), this, SLOT(openTelemetrySimulator())); + new QShortcut(QKeySequence(Qt::Key_F4), this, SLOT(openTelemetrySimulator())); + new QShortcut(QKeySequence(Qt::Key_F5), this, SLOT(openTrainerSimulator())); + new QShortcut(QKeySequence(Qt::Key_F6), this, SLOT(openDebugOutput())); + traceCallbackInstance = this; +} + +uint32_t SimulatorDialog9X::switchstatus = 0; + +SimulatorDialog9X::SimulatorDialog9X(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): + SimulatorDialog(parent, simulator, flags), + ui(new Ui::SimulatorDialog9X), + beepShow(0) +{ + lcdWidth = 128; + lcdHeight = 64; + lcdDepth = 1; + + initUi(ui); + + // install simulator TRACE hook + simulator->installTraceHook(traceCb); + + backLight = g.backLight(); + if (backLight > 4) backLight = 0; + switch (backLight) { + case 1: + ui->lcd->setBackgroundColor(166,247,159); + break; + case 2: + ui->lcd->setBackgroundColor(247,159,166); + break; + case 3: + ui->lcd->setBackgroundColor(255,195,151); + break; + case 4: + ui->lcd->setBackgroundColor(247,242,159); + break; + default: + ui->lcd->setBackgroundColor(159,165,247); + break; + } + + //restore switches + if (g.simuSW()) + restoreSwitches(); + + ui->trimHR_L->setText(QString::fromUtf8(leftArrow)); + ui->trimHR_R->setText(QString::fromUtf8(rightArrow)); + ui->trimVR_U->setText(QString::fromUtf8(upArrow)); + ui->trimVR_D->setText(QString::fromUtf8(downArrow)); + ui->trimHL_L->setText(QString::fromUtf8(leftArrow)); + ui->trimHL_R->setText(QString::fromUtf8(rightArrow)); + ui->trimVL_U->setText(QString::fromUtf8(upArrow)); + ui->trimVL_D->setText(QString::fromUtf8(downArrow)); + for (int i=0; isetProperty("index", i); + connect(pots[i], SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int))); + } + connect(ui->cursor, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); + connect(ui->menu, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); + connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased())); +} + +SimulatorDialog9X::~SimulatorDialog9X() +{ + saveSwitches(); + delete ui; +} + +uint32_t SimulatorDialogTaranis::switchstatus = 0; + +SimulatorDialogTaranis::SimulatorDialogTaranis(QWidget * parent, SimulatorInterface *simulator, unsigned int flags): + SimulatorDialog(parent, simulator, flags), + ui(new Ui::SimulatorDialogTaranis) +{ + lcdWidth = 212; + lcdHeight = 64; + lcdDepth = 4; + + initUi(ui); + + // install simulator TRACE hook + simulator->installTraceHook(traceCb); + + ui->lcd->setBackgroundColor(47, 123, 227); + + // restore switches + if (g.simuSW()) { + restoreSwitches(); + } + + for (int i=0; isetValue(-1024); + pots[i]->setSingleStep(2048/5); + pots[i]->setPageStep(2048/5); + } + else if (!(flags & (SIMULATOR_FLAGS_S1 << i))) { + pots[i]->hide(); + potLabels[i]->hide(); + } + } + + ui->trimHR_L->setText(QString::fromUtf8(leftArrow)); + ui->trimHR_R->setText(QString::fromUtf8(rightArrow)); + ui->trimVR_U->setText(QString::fromUtf8(upArrow)); + ui->trimVR_D->setText(QString::fromUtf8(downArrow)); + ui->trimHL_L->setText(QString::fromUtf8(leftArrow)); + ui->trimHL_R->setText(QString::fromUtf8(rightArrow)); + ui->trimVL_U->setText(QString::fromUtf8(upArrow)); + ui->trimVL_D->setText(QString::fromUtf8(downArrow)); + + connect(ui->cursor, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); + connect(ui->menu, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int))); + connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed())); + connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased())); + connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased())); +} + +SimulatorDialogTaranis::~SimulatorDialogTaranis() +{ + saveSwitches(); + delete ui; +} + +SimulatorDialog::~SimulatorDialog() +{ + traceCallbackInstance = 0; + delete timer; + delete simulator; +} + +void SimulatorDialog::closeEvent (QCloseEvent *) +{ + simulator->stop(); + timer->stop(); +} + +void SimulatorDialog::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::MidButton) { + middleButtonPressed = true; + } +} + +void SimulatorDialog::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::MidButton) { + middleButtonPressed = false; + } +} + +void SimulatorDialog9X::dialChanged(int value) +{ + int index = sender()->property("index").toInt(); + potValues[index]->setText(QString("%1 %").arg((value*100)/1024)); +} + +void SimulatorDialog::wheelEvent (QWheelEvent *event) +{ + simulator->wheelEvent(event->delta() > 0 ? 1 : -1); +} + +void SimulatorDialog::onTrimPressed() +{ + if (sender()->objectName() == QString("trimHL_L")) + trimPressed = TRIM_LH_L; + else if (sender()->objectName() == QString("trimHL_R")) + trimPressed = TRIM_LH_R; + else if (sender()->objectName() == QString("trimVL_D")) + trimPressed = TRIM_LV_DN; + else if (sender()->objectName() == QString("trimVL_U")) + trimPressed = TRIM_LV_UP; + else if (sender()->objectName() == QString("trimVR_D")) + trimPressed = TRIM_RV_DN; + else if (sender()->objectName() == QString("trimVR_U")) + trimPressed = TRIM_RV_UP; + else if (sender()->objectName() == QString("trimHR_L")) + trimPressed = TRIM_RH_L; + else if (sender()->objectName() == QString("trimHR_R")) + trimPressed = TRIM_RH_R; +} + +void SimulatorDialog::onTrimReleased() +{ + trimPressed = TRIM_NONE; +} + +void SimulatorDialog::openTelemetrySimulator() +{ + // allow only one instance + if (TelemetrySimu == 0) { + TelemetrySimu = new TelemetrySimulator(this, simulator); + TelemetrySimu->show(); + } + else if (!TelemetrySimu->isVisible()) { + TelemetrySimu->show(); + } +} + +void SimulatorDialog::openTrainerSimulator() +{ + // allow only one instance + if (TrainerSimu == 0) { + TrainerSimu = new TrainerSimulator(this, simulator); + TrainerSimu->show(); + } + else if (!TrainerSimu->isVisible()) { + TrainerSimu->show(); + } +} + +void SimulatorDialog::openDebugOutput() +{ + // allow only one instance, but install signal handler to catch dialog destruction just in case + if (DebugOut == 0) { + DebugOut = new DebugOutput(this); + QObject::connect(DebugOut, SIGNAL(destroyed()), this, SLOT(onDebugOutputClose())); + DebugOut->traceCallback(traceBuffer); + DebugOut->show(); + } + else if (!DebugOut->isVisible()) { + DebugOut->show(); + } +} + +void SimulatorDialog::onDebugOutputClose() +{ + DebugOut = 0; +} + +void SimulatorDialog::keyPressEvent (QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + buttonPressed = Qt::Key_Enter; + break; + case Qt::Key_Escape: + case Qt::Key_Backspace: + buttonPressed = Qt::Key_Escape; + break; + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Right: + case Qt::Key_Left: + case Qt::Key_Minus: + case Qt::Key_Plus: + case Qt::Key_PageDown: + case Qt::Key_PageUp: + buttonPressed = event->key(); + break; + } +} + +void SimulatorDialog::keyReleaseEvent(QKeyEvent * event) +{ + switch (event->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_Escape: + case Qt::Key_Backspace: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Right: + case Qt::Key_Left: + case Qt::Key_Plus: + case Qt::Key_Minus: + case Qt::Key_PageDown: + case Qt::Key_PageUp: + buttonPressed = 0; + break; + } +} + +void SimulatorDialog::setupTimer() +{ + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent())); + timer->start(10); +} + +template +void SimulatorDialog::initUi(T * ui) +{ + ui->setupUi(this); + + lcd = ui->lcd; + leftStick = ui->leftStick; + rightStick = ui->rightStick; + pots = findWidgets(this, "pot%1"); + potLabels = findWidgets(this, "potLabel%1"); + potValues = findWidgets(this, "potValue%1"); + sliders = findWidgets(this, "slider%1"); + + trimHLeft = ui->trimHLeft; + trimVLeft = ui->trimVLeft; + trimHRight = ui->trimHRight; + trimVRight = ui->trimVRight; + tabWidget = ui->tabWidget; + leftXPerc = ui->leftXPerc; + leftYPerc = ui->leftYPerc; + rightXPerc = ui->rightXPerc; + rightYPerc = ui->rightYPerc; + + setupSticks(); + + resize(0, 0); // to force min height, min width + setFixedSize(width(), height()); + +#ifdef JOYSTICKS + if (g.jsSupport()) { + int count=0; + for (int j=0; j<8; j++){ + int axe = g.joystick[j].stick_axe(); + if (axe>=0 && axe<8) { + jsmap[axe]=j+1; + jscal[axe][0] = g.joystick[j].stick_min(); + jscal[axe][1] = g.joystick[j].stick_med(); + jscal[axe][2] = g.joystick[j].stick_max(); + jscal[axe][3] = g.joystick[j].stick_inv(); + count++; + } + } + if (count<3) { + QMessageBox::critical(this, tr("Warning"), tr("Joystick enabled but not configured correctly")); + } + if (g.jsCtrl()!=-1) { + joystick = new Joystick(this); + if (joystick) { + if (joystick->open(g.jsCtrl())) { + int numAxes=std::min(joystick->numAxes,8); + for (int j=0; jsensitivities[j] = 0; + joystick->deadzones[j]=0; + } + nodeRight->setCenteringY(false); //mode 1,3 -> THR on right + ui->holdRightY->setChecked(true); + nodeRight->setCenteringX(false); //mode 1,3 -> THR on right + ui->holdRightX->setChecked(true); + nodeLeft->setCenteringY(false); //mode 1,3 -> THR on right + ui->holdLeftY->setChecked(true); + nodeLeft->setCenteringX(false); //mode 1,3 -> THR on right + ui->holdLeftX->setChecked(true); + connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int))); + } + else { + QMessageBox::critical(this, tr("Warning"), tr("Cannot open joystick, joystick disabled")); + } + } + } + } +#endif + + windowName = tr("Simulating Radio (%1)").arg(GetCurrentFirmware()->getName()); + setWindowTitle(windowName); + + simulator->setSdPath(g.profile[g.id()].sdPath()); + simulator->setVolumeGain(g.profile[g.id()].volumeGain()); + lcd->setData(simulator->getLcd(), lcdWidth, lcdHeight, lcdDepth); + + if (flags & SIMULATOR_FLAGS_STICK_MODE_LEFT) { + nodeLeft->setCenteringY(false); + ui->holdLeftY->setChecked(true); + } + else { + nodeRight->setCenteringY(false); + ui->holdRightY->setChecked(true); + } + + setTrims(); + + int outputs = std::min(32, GetCurrentFirmware()->getCapability(Outputs)); + if (outputs <= 16) { + // hide second Outputs tab + tabWidget->removeTab(tabWidget->indexOf(ui->outputs2)); + } + else { + tabWidget->setTabText(tabWidget->indexOf(ui->outputs), tr("Outputs") + QString(" 1-%1").arg(16)); + tabWidget->setTabText(tabWidget->indexOf(ui->outputs2), tr("Outputs") + QString(" 17-%1").arg(outputs)); + } + for (int i=0; ichannelsLayout; + int column = i / (std::min(16,outputs)/2); + int line = i % (std::min(16,outputs)/2); + if (i >= 16 ) { + outputTab = ui->channelsLayout2; + column = (i-16) / (std::min(16,outputs-16)/2); + line = (i-16) % (std::min(16,outputs-16)/2); + } + QLabel * label = new QLabel(tabWidget); + label->setText(RawSource(SOURCE_TYPE_CH, i).toString()); + outputTab->addWidget(label, line, column == 0 ? 0 : 5, 1, 1); + + QSlider * slider = new QSlider(tabWidget); + slider->setEnabled(false); + slider->setMaximumSize(QSize(16777215, 18)); + slider->setStyleSheet(QString::fromUtf8("QSlider::sub-page:horizontal:disabled {\n" + "border-color: #999;\n" + "}\n" + "\n" + "QSlider::add-page:horizontal:disabled {\n" + "border-color: #999;\n" + "}\n" + "\n" + "QSlider::handle:horizontal:disabled {\n" + "background: #0000CC;\n" + "border: 1px solid #aaa;\n" + "border-radius: 4px;\n" + "}")); + slider->setMinimum(-1024); + slider->setMaximum(1024); + slider->setPageStep(128); + slider->setTracking(false); + slider->setOrientation(Qt::Horizontal); + slider->setInvertedAppearance(false); + slider->setTickPosition(QSlider::TicksBelow); + channelSliders << slider; + outputTab->addWidget(slider, line, column == 0 ? 1 : 4, 1, 1); + + QLabel * value = new QLabel(tabWidget); + value->setMinimumSize(QSize(50, 0)); + value->setAlignment(Qt::AlignCenter); + channelValues << value; + outputTab->addWidget(value, line, column == 0 ? 2 : 3, 1, 1); + } + + int switches = GetCurrentFirmware()->getCapability(LogicalSwitches); + for (int i=0; ilogicalSwitchesLayout->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1); + if (outputs > 16) { + // repeat logical switches on second outputs tab + swtch = createLogicalSwitch(tabWidget, i, logicalSwitchLabels2); + ui->logicalSwitchesLayout2->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1); + } + } + + int fmodes = GetCurrentFirmware()->getCapability(FlightModes); + int gvars = GetCurrentFirmware()->getCapability(Gvars); + if (gvars>0) { + for (int fm=0; fmsetText(QString("FM%1").arg(fm)); + label->setAlignment(Qt::AlignCenter); + ui->gvarsLayout->addWidget(label, 0, fm+1); + } + for (int i=0; isetText(QString("GV%1").arg(i+1)); + label->setAutoFillBackground(true); + if ((i % 2) ==0 ) { + label->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }"); + } + ui->gvarsLayout->addWidget(label, i+1, 0); + for (int fm=0; fmsetAutoFillBackground(true); + value->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + if ((i % 2) ==0 ) { + value->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }"); + } + gvarValues << value; + ui->gvarsLayout->addWidget(value, i+1, fm+1); + } + } + } + + if (flags & SIMULATOR_FLAGS_NOTX) { + ui->tabWidget->setCurrentWidget(ui->outputs); + } + else { + ui->tabWidget->setCurrentWidget(ui->simu); + } +} + +QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QVector & labels) +{ + QFrame * swtch = new QFrame(parent); + swtch->setAutoFillBackground(true); + swtch->setFrameShape(QFrame::Panel); + swtch->setFrameShadow(QFrame::Raised); + swtch->setLineWidth(2); + QVBoxLayout * layout = new QVBoxLayout(swtch); + layout->setContentsMargins(2, 2, 2, 2); + QLabel * label = new QLabel(swtch); + label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString()); + label->setAlignment(Qt::AlignCenter); + labels << label; + layout->addWidget(label); + return swtch; +} + +void SimulatorDialog::onButtonPressed(int value) +{ + if (value == Qt::Key_Print) { + QString fileName = ""; + if (!g.snapToClpbrd()) { + fileName = QString("screenshot-%1.png").arg(++screenshotIdx); + } + lcd->makeScreenshot(fileName); + } + else { + buttonPressed = value; + } +} + +void SimulatorDialog9X::setLightOn(bool enable) +{ + QString bg = ""; + if (enable) { + QStringList list; + list << "bl" << "gr" << "rd" << "or" << "yl"; + bg = QString("-") + list[backLight]; + } + ui->top->setStyleSheet(QString("background:url(:/images/9xdt%1.png);").arg(bg)); + ui->bottom->setStyleSheet(QString("background:url(:/images/9xdb%1.png);").arg(bg)); + ui->left->setStyleSheet(QString("background:url(:/images/9xdl%1.png);").arg(bg)); + ui->right->setStyleSheet(QString("background:url(:/images/9xdr%1.png);").arg(bg)); +} + +void SimulatorDialog9X::updateBeepButton() +{ + #define CBEEP_ON "QLabel { background-color: #FF364E }" + #define CBEEP_OFF "QLabel { }" + + if (beepVal) { + beepShow = 20; + } + + ui->label_beep->setStyleSheet(beepShow ? CBEEP_ON : CBEEP_OFF); + + if (beepShow) { + beepShow--; + } +} + +void SimulatorDialog::onTimerEvent() +{ + static unsigned int lcd_counter = 0; + if (!simulator->timer10ms()) { + QMessageBox::critical(this, "Companion", tr("Firmware %1 error: %2").arg(GetCurrentFirmware()->getName()).arg(simulator->getError())); + timer->stop(); + return; + } + + getValues(); + + if (tabWidget->currentIndex()==0) { + bool lightEnable; + if (simulator->lcdChanged(lightEnable)) { + lcd->onLcdChanged(lightEnable); + if (lightOn != lightEnable) { + setLightOn(lightEnable); + lightOn = lightEnable; + } + } + } + + // display current flight mode in window title + unsigned int currentPhase = simulator->getPhase(); + if (currentPhase != lastPhase) { + lastPhase = currentPhase; + const char * phase_name = simulator->getPhaseName(currentPhase); + if (phase_name && phase_name[0]) { + setWindowTitle(windowName + QString(" - Flight Mode %1").arg(QString(phase_name))); + } + else { + setWindowTitle(windowName + QString(" - Flight Mode %1").arg(simulator->getPhase())); + } + } + + if (!(lcd_counter++ % 5)) { + + setValues(); + + setTrims(); + + centerSticks(); + + updateBeepButton(); + + if (beepVal) { + beepVal = 0; + QApplication::beep(); + } + } + + updateDebugOutput(); +} + +void SimulatorDialog::centerSticks() +{ + if (leftStick->scene()) + nodeLeft->stepToCenter(); + + if (rightStick->scene()) + nodeRight->stepToCenter(); +} + +void SimulatorDialog::start(QByteArray & eeprom) +{ + lastPhase = -1; + numGvars = GetCurrentFirmware()->getCapability(Gvars); + numFlightModes = GetCurrentFirmware()->getCapability(FlightModes); + simulator->start(eeprom, (flags & SIMULATOR_FLAGS_NOTX) ? false : true); + getValues(); + setupTimer(); +} + +void SimulatorDialog::start(const char * filename) +{ + lastPhase = -1; + numGvars = GetCurrentFirmware()->getCapability(Gvars); + numFlightModes = GetCurrentFirmware()->getCapability(FlightModes); + simulator->start(filename); + getValues(); + setupTimer(); +} + +void SimulatorDialog::setTrims() +{ + Trims trims; + simulator->getTrims(trims); + + int trimMin = -125, trimMax = +125; + if (trims.extended) { + trimMin = -500; + trimMax = +500; + } + trimHLeft->setRange(trimMin, trimMax); trimHLeft->setValue(trims.values[0]); + trimVLeft->setRange(trimMin, trimMax); trimVLeft->setValue(trims.values[1]); + trimVRight->setRange(trimMin, trimMax); trimVRight->setValue(trims.values[2]); + trimHRight->setRange(trimMin, trimMax); trimHRight->setValue(trims.values[3]); +} + +void SimulatorDialog9X::getValues() +{ + TxInputs inputs = { + { + int(1024*nodeLeft->getX()), // LEFT HORZ + int(-1024*nodeLeft->getY()), // LEFT VERT + int(-1024*nodeRight->getY()), // RGHT VERT + int(1024*nodeRight->getX()) // RGHT HORZ + }, + + { + pots[0]->value(), + pots[1]->value(), + pots[2]->value() + }, + + { + ui->switchTHR->isChecked(), + ui->switchRUD->isChecked(), + ui->switchELE->isChecked(), + ui->switchID2->isChecked() ? 1 : (ui->switchID1->isChecked() ? 0 : -1), + ui->switchAIL->isChecked(), + ui->switchGEA->isChecked(), + ui->switchTRN->isDown(), + 0, 0, 0 + }, + + { + buttonPressed == Qt::Key_Enter, + buttonPressed == Qt::Key_Escape, + buttonPressed == Qt::Key_Down, + buttonPressed == Qt::Key_Up, + buttonPressed == Qt::Key_Right, + buttonPressed == Qt::Key_Left, + }, + + middleButtonPressed, + + { + trimPressed == TRIM_LH_L, + trimPressed == TRIM_LH_R, + trimPressed == TRIM_LV_DN, + trimPressed == TRIM_LV_UP, + trimPressed == TRIM_RV_DN, + trimPressed == TRIM_RV_UP, + trimPressed == TRIM_RH_L, + trimPressed == TRIM_RH_R + } + }; + + simulator->setValues(inputs); +} + +void SimulatorDialog9X::saveSwitches(void) +{ + // qDebug() << "SimulatorDialog9X::saveSwitches()"; + switchstatus=ui->switchTHR->isChecked(); + switchstatus<<=1; + switchstatus+=(ui->switchRUD->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchID2->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchID1->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchID0->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchGEA->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchELE->isChecked()&0x1); + switchstatus<<=1; + switchstatus+=(ui->switchAIL->isChecked()&0x1); +} + +void SimulatorDialog9X::restoreSwitches(void) +{ + // qDebug() << "SimulatorDialog9X::restoreSwitches()"; + ui->switchAIL->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchELE->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchGEA->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchID0->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchID1->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchID2->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchRUD->setChecked(switchstatus & 0x1); + switchstatus >>=1; + ui->switchTHR->setChecked(switchstatus & 0x1); +} + +void SimulatorDialogTaranis::resetSH() +{ + ui->switchH->setValue(0); +} + +void SimulatorDialogTaranis::on_switchH_sliderReleased() +{ + QTimer::singleShot(400, this, SLOT(resetSH())); +} + +void SimulatorDialogTaranis::getValues() +{ + for (int i=0; ivalue()+1024)/(2048.0/5))*(2048.0/5)-1024; + pots[i]->setValue(s1); + } + } + + TxInputs inputs = { + { + int(1024*nodeLeft->getX()), // LEFT HORZ + int(-1024*nodeLeft->getY()), // LEFT VERT + int(-1024*nodeRight->getY()), // RGHT VERT + int(1024*nodeRight->getX()) // RGHT HORZ + }, + + { + -pots[0]->value(), + pots[1]->value(), + ((flags && SIMULATOR_FLAGS_S3) ? pots[2]->value() : 0), + -sliders[0]->value(), + sliders[1]->value() + }, + + { + ui->switchA->value() - 1, + ui->switchB->value() - 1, + ui->switchC->value() - 1, + ui->switchD->value() - 1, + ui->switchE->value() - 1, + ui->switchF->value(), + ui->switchG->value() - 1, + ui->switchH->value(), 0, 0 + }, + + { + buttonPressed == Qt::Key_PageUp, + buttonPressed == Qt::Key_Escape, + buttonPressed == Qt::Key_Enter, + buttonPressed == Qt::Key_PageDown, + buttonPressed == Qt::Key_Plus, + buttonPressed == Qt::Key_Minus + }, + + middleButtonPressed, + + { + trimPressed == TRIM_LH_L, + trimPressed == TRIM_LH_R, + trimPressed == TRIM_LV_DN, + trimPressed == TRIM_LV_UP, + trimPressed == TRIM_RV_DN, + trimPressed == TRIM_RV_UP, + trimPressed == TRIM_RH_L, + trimPressed == TRIM_RH_R + } + }; + + simulator->setValues(inputs); +} + +void SimulatorDialogTaranis::saveSwitches(void) +{ + // qDebug() << "SimulatorDialogTaranis::saveSwitches()"; + switchstatus=ui->switchA->value(); + switchstatus<<=2; + switchstatus+=ui->switchB->value(); + switchstatus<<=2; + switchstatus+=ui->switchC->value(); + switchstatus<<=2; + switchstatus+=ui->switchD->value(); + switchstatus<<=2; + switchstatus+=ui->switchE->value(); + switchstatus<<=2; + switchstatus+=ui->switchF->value(); + switchstatus<<=2; + switchstatus+=ui->switchG->value(); + switchstatus<<=2; + switchstatus+=ui->switchH->value(); +} + +void SimulatorDialogTaranis::restoreSwitches(void) +{ + // qDebug() << "SimulatorDialogTaranis::restoreSwitches()"; + ui->switchH->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchG->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchF->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchE->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchD->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchC->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchB->setValue(switchstatus & 0x3); + switchstatus>>=2; + ui->switchA->setValue(switchstatus & 0x3); +} + +inline int chVal(int val) +{ + return qMin(1024, qMax(-1024, val)); +} + +void SimulatorDialog::on_trimHLeft_valueChanged(int value) +{ + simulator->setTrim(0, value); +} + +void SimulatorDialog::on_trimVLeft_valueChanged(int value) +{ + simulator->setTrim(1, value); +} + +void SimulatorDialog::on_trimVRight_valueChanged(int value) +{ + simulator->setTrim(2, value); +} + +void SimulatorDialog::on_trimHRight_valueChanged(int value) +{ + simulator->setTrim(3, value); +} + +void SimulatorDialog::setValues() +{ + TxOutputs outputs; + simulator->getValues(outputs); + Trims trims; + simulator->getTrims(trims); + + for (int i=0; igetCapability(Outputs); i++) { + if (i < channelSliders.size()) { + channelSliders[i]->setValue(chVal(outputs.chans[i])); + channelValues[i]->setText(QString("%1").arg((qreal)outputs.chans[i]*100/1024, 0, 'f', 1)); + } + } + + leftXPerc->setText(QString("X %1%").arg((qreal)nodeLeft->getX()*100+trims.values[0]/5, 2, 'f', 0)); + leftYPerc->setText(QString("Y %1%").arg((qreal)nodeLeft->getY()*-100+trims.values[1]/5, 2, 'f', 0)); + + rightXPerc->setText(QString("X %1%").arg((qreal)nodeRight->getX()*100+trims.values[3]/5, 2, 'f', 0)); + rightYPerc->setText(QString("Y %1%").arg((qreal)nodeRight->getY()*-100+trims.values[2]/5, 2, 'f', 0)); + + QString CSWITCH_ON = "QLabel { background-color: #4CC417 }"; + QString CSWITCH_OFF = "QLabel { }"; + + for (int i=0; igetCapability(LogicalSwitches); i++) { + logicalSwitchLabels[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); + if (!logicalSwitchLabels2.isEmpty()) { + logicalSwitchLabels2[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF); + } + } + + for (unsigned int gv=0; gvsetText(QString((fm==lastPhase)?"%1":"%1").arg(outputs.gvars[fm][gv])); + } + } + + if (outputs.beep) { + beepVal = outputs.beep; + } +} + +void SimulatorDialog::setupSticks() +{ + QGraphicsScene *leftScene = new QGraphicsScene(leftStick); + leftScene->setItemIndexMethod(QGraphicsScene::NoIndex); + leftStick->setScene(leftScene); + + // leftStick->scene()->addLine(0,10,20,30); + + QGraphicsScene *rightScene = new QGraphicsScene(rightStick); + rightScene->setItemIndexMethod(QGraphicsScene::NoIndex); + rightStick->setScene(rightScene); + + // rightStick->scene()->addLine(0,10,20,30); + + nodeLeft = new Node(); + nodeLeft->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2); + nodeLeft->setBallSize(GBALL_SIZE); + leftScene->addItem(nodeLeft); + + nodeRight = new Node(); + nodeRight->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2); + nodeRight->setBallSize(GBALL_SIZE); + rightScene->addItem(nodeRight); +} + +void SimulatorDialog::resizeEvent(QResizeEvent *event) +{ + if (leftStick->scene()) { + QRect qr = leftStick->contentsRect(); + qreal w = (qreal)qr.width() - GBALL_SIZE; + qreal h = (qreal)qr.height() - GBALL_SIZE; + qreal cx = (qreal)qr.width()/2; + qreal cy = (qreal)qr.height()/2; + leftStick->scene()->setSceneRect(-cx,-cy,w,h); + + QPointF p = nodeLeft->pos(); + p.setX(qMin(cx, qMax(p.x(), -cx))); + p.setY(qMin(cy, qMax(p.y(), -cy))); + nodeLeft->setPos(p); + } + + if (rightStick->scene()) { + QRect qr = rightStick->contentsRect(); + qreal w = (qreal)qr.width() - GBALL_SIZE; + qreal h = (qreal)qr.height() - GBALL_SIZE; + qreal cx = (qreal)qr.width()/2; + qreal cy = (qreal)qr.height()/2; + rightStick->scene()->setSceneRect(-cx,-cy,w,h); + + QPointF p = nodeRight->pos(); + p.setX(qMin(cx, qMax(p.x(), -cx))); + p.setY(qMin(cy, qMax(p.y(), -cy))); + nodeRight->setPos(p); + } + QDialog::resizeEvent(event); +} + +void SimulatorDialog::on_holdLeftX_clicked(bool checked) +{ + nodeLeft->setCenteringX(!checked); +} + +void SimulatorDialog::on_holdLeftY_clicked(bool checked) +{ + nodeLeft->setCenteringY(!checked); +} + +void SimulatorDialog::on_holdRightX_clicked(bool checked) +{ + nodeRight->setCenteringX(!checked); +} + +void SimulatorDialog::on_holdRightY_clicked(bool checked) +{ + nodeRight->setCenteringY(!checked); +} + +void SimulatorDialog::on_FixLeftX_clicked(bool checked) +{ + nodeLeft->setFixedX(checked); +} + +void SimulatorDialog::on_FixLeftY_clicked(bool checked) +{ + nodeLeft->setFixedY(checked); +} + +void SimulatorDialog::on_FixRightX_clicked(bool checked) +{ + nodeRight->setFixedX(checked); +} + +void SimulatorDialog::on_FixRightY_clicked(bool checked) +{ + nodeRight->setFixedY(checked); +} + +#ifdef JOYSTICKS +void SimulatorDialog::onjoystickAxisValueChanged(int axis, int value) +{ + int stick; + if (axis>=0 && axis<=8) { + stick=jsmap[axis]; + int stickval; + if (value>jscal[axis][1]) { + if ((jscal[axis][2]-jscal[axis][1])==0) + return; + stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][2]-jscal[axis][1]); + } + else { + if ((jscal[axis][1]-jscal[axis][0])==0) + return; + stickval=(1024*(value-jscal[axis][1]))/(jscal[axis][1]-jscal[axis][0]); + } + if (jscal[axis][3]==1) { + stickval*=-1; + } + if (stick==1 ) { + nodeRight->setY(-stickval/1024.0); + } + else if (stick==2) { + nodeRight->setX(stickval/1024.0); + } + else if (stick==3) { + nodeLeft->setY(-stickval/1024.0); + } + else if (stick==4) { + nodeLeft->setX(stickval/1024.0); + } + else if (stick >= 5 && stick < 5+pots.count()) { + pots[stick-5]->setValue(stickval); + } + } +} +#endif