Bsongis/issue 4400 (#4425)
[opentx.git] / companion / src / wizarddialog.cpp
blob829ab56a763f259ff8767e57e1408c7a206905cb
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "wizarddialog.h"
22 #include "wizarddata.h"
23 #include "helpers.h"
25 WizardDialog::WizardDialog(const GeneralSettings & settings, unsigned int modelId, QWidget *parent):
26 QWizard(parent),
27 mix(settings, modelId),
28 settings(settings)
30 setWindowIcon(CompanionIcon("wizard.png"));
31 setWindowTitle(tr("Model Wizard"));
33 setPage(Page_Models, new ModelSelectionPage(this, "models", tr("Model Type"), tr("Enter model name and model type.")));
34 setPage(Page_Throttle, new ThrottlePage(this, "throttle", tr("Throttle"), tr("Has your model got a motor or an engine?"), Page_Wingtypes));
35 setPage(Page_Wingtypes, new WingtypeSelectionPage(this, "wingtype", tr("Wing Type"), tr("Is your model a flying wing/deltawing or has it a standard wing configuration?")));
36 setPage(Page_Ailerons, new AileronsPage(this, "ailerons", tr("Ailerons"), tr("Has your model got ailerons?"), Page_Flaps));
37 setPage(Page_Flaps, new FlapsPage(this, "flaps", tr("Flaps"), tr("Has your model got flaps?"), Page_Airbrakes));
38 setPage(Page_Airbrakes, new AirbrakesPage(this, "airbrakes", tr("Airbrakes"), tr("Has your model got airbrakes?"), Page_Tails));
39 setPage(Page_Elevons, new ElevonsPage(this, "elevons", tr("Flying-wing / Delta-wing"), tr("Select the elevons channels"), Page_Rudder));
40 setPage(Page_Rudder, new RudderPage(this, "rudder", tr("Rudder"), tr("Does your model have a rudder?"), Page_Options));
41 setPage(Page_Tails, new TailSelectionPage(this, "tails", tr("Tail Type"), tr("Select which type of tail your model is equiped with.")));
42 setPage(Page_Tail, new TailPage(this, "tail", tr("Tail"), tr("Select channels for tail control."), Page_Options));
43 setPage(Page_Vtail, new VTailPage(this, "vtail", tr("V-Tail"), tr("Select channels for tail control."), Page_Options));
44 setPage(Page_Simpletail, new SimpleTailPage(this, "simpletail", tr("Tail"), tr("Select elevator channel."), Page_Options));
45 setPage(Page_Cyclic, new CyclicPage(this, "cyclic", tr("Cyclic"), tr("Which type of swash control is installed in your helicopter?"), Page_Gyro));
46 setPage(Page_Gyro, new GyroPage(this, "gyro", tr("Tail Gyro"), tr("Has your helicopter got an adjustable gyro for the tail?"), Page_Flybar));
47 setPage(Page_Flybar, new FlybarSelectionPage(this, "flybar", tr("Rotor Type"), tr("Has your helicopter got a flybar?")));
48 setPage(Page_Fblheli, new FblPage(this, "fblheli", tr("Helicopter"), tr("Select the controls for your helicopter"), Page_Options));
49 setPage(Page_Helictrl, new HeliPage(this, "helictrl", tr("Helicopter"), tr("Select the controls for your helicopter"), Page_Options));
50 setPage(Page_Multirotor, new MultirotorPage(this, "multirotor", tr("Multirotor"), tr("Select the control channels for your multirotor"), Page_Options));
51 setPage(Page_Options, new OptionsPage(this, "options", tr("Model Options"), tr("Select additional options"), Page_Conclusion));
52 setPage(Page_Conclusion, new ConclusionPage(this, "conclusion", tr("Save Changes"), tr(
53 "Manually check the direction of each control surface and reverse any channels that make controls move in the wrong direction. "
54 "Remove the propeller/propellers before you try to control your model for the first time.<br>"
55 "Please note that continuing removes all old model settings!"), -1));
56 setStartId(Page_Models);
58 // Workaround for Qt radio button rendering issue on Mac
59 Q_FOREACH(QAbstractButton * rb, findChildren<QAbstractButton *>()) {
60 rb->setAttribute(Qt::WA_LayoutUsesWidgetRect);
63 setWizardStyle(ModernStyle);
64 setOption(QWizard::NoCancelButton, false);
65 setOption(HaveHelpButton, true);
66 connect(this, SIGNAL(helpRequested()), this, SLOT(showHelp()));
69 void WizardDialog::showHelp()
71 QString message;
73 switch (currentId()) {
74 case Page_Models:
75 message = tr("Enter a name for your model and select model type.");
76 break;
77 case Page_Throttle:
78 message = tr("Select the receiver channel that is connected to your ESC or throttle servo.<br><br>"
79 "Throttle - Spektrum: CH1, Futaba: CH3");
80 break;
81 case Page_Wingtypes:
82 message = tr("Most aircraft have a main wing and a tail with control surfaces. Flying wings and delta winged aircraft only have a single wing. "
83 "The main control surface on a standard wing controls the roll of the aircraft. This surface is called an aileron.<br>"
84 "The control surface of a delta wing controls both roll and pitch. This surface is called an elevon. ");
85 break;
86 case Page_Ailerons:
87 message = tr("Models use one or two channels to control the ailerons.<br>"
88 "A so called Y-cable can be used to connect a single receiver channel to two separate aileron servos. "
89 "If your servos are connected by a Y-cable you should select the single-servo option.<br><br>"
90 "Aileron - Spektrum: CH2, Futaba: CH1");
91 break;
92 case Page_Flaps:
93 message = tr("This wizard assumes that your flaps are controlled by a switch. "
94 "If your flaps are controlled by a potentiometer you can change that manually later.");
95 break;
96 case Page_Airbrakes:
97 message = tr("Air brakes are used to reduce the speed of advanced sail planes.<br>"
98 "They are very uncommon on other types of planes.");
99 break;
100 case Page_Elevons:
101 message = tr("Models use two channels to control the elevons.<br>"
102 "Select these two channels");
103 break;
104 case Page_Rudder:
105 message = tr("Select the receiver channel that is connected to your rudder.<br><br>"
106 "Rudder - Spektrum: CH4, Futaba: CH4");
107 break;
108 case Page_Tails:
109 message = tr("Select the tail type of your plane.");
110 break;
111 case Page_Tail:
112 message = tr("Select the Rudder and Elevator channels.<br><br>"
113 "Rudder - Spektrum: CH4, Futaba: CH4<br>"
114 "Elevator - Spektrum: CH3, Futaba: CH2");
115 break;
116 case Page_Vtail:
117 message = tr("Select the Rudder and Elevator channels.<br><br>"
118 "Rudder - Spektrum: CH4, Futaba: CH4<br>"
119 "Elevator - Spektrum: CH3, Futaba: CH2");
120 break;
121 case Page_Simpletail:
122 message = tr("Select the Elevator channel.<br><br>"
123 "Elevator - Spektrum: CH3, Futaba: CH2");
124 break;
125 case Page_Flybar:
126 message = tr("TBD.");
127 break;
128 case Page_Cyclic:
129 message = tr("TBD.");
130 break;
131 case Page_Gyro:
132 message = tr("TBD.");
133 break;
134 case Page_Fblheli:
135 message = tr("TBD.");
136 break;
137 case Page_Helictrl:
138 message = tr("TBD.");
139 break;
140 case Page_Multirotor:
141 message = tr("Select the control channels for your multirotor.<br><br>"
142 "Throttle - Spektrum: CH1, Futaba: CH3<br>"
143 "Yaw - Spektrum: CH4, Futaba: CH4<br>"
144 "Pitch - Spektrum: CH3, Futaba: CH2<br>"
145 "Roll - Spektrum: CH2, Futaba: CH1");
146 break;
147 case Page_Options:
148 message = tr("TBD.");
149 break;
150 case Page_Conclusion:
151 message = tr("TBD.");
152 break;
153 default:
154 message = tr("There is no help available for the current page.");
157 QMessageBox::information(this, tr("Model Wizard Help"), message);
160 StandardPage::StandardPage(WizardPage currentPage, WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
161 QWizardPage(),
162 wizDlg(dlg),
163 pageCurrent(currentPage),
164 pageFollower(nextPage)
166 setTitle(title);
167 setPixmap(QWizard::WatermarkPixmap, QPixmap(QString(":/images/wizard/%1.png").arg(image)));
168 topLabel = new QLabel(text+"<br>");
169 topLabel->setWordWrap(true);
171 QVBoxLayout *layout = new QVBoxLayout;
172 layout->addWidget(topLabel);
173 setLayout(layout);
176 int StandardPage::getDefaultChannel(const Input input)
178 return wizDlg->settings.getDefaultChannel(input-1);
181 int StandardPage::nextFreeChannel(int channel)
183 for(int i=channel;i<8; i++)
184 if (wizDlg->mix.channel[i].page == Page_None)
185 return i;
186 return -1;
189 int StandardPage::totalChannelsAvailable()
191 int c = 0;
192 for(int i=0; i<WIZ_MAX_CHANNELS; i++)
193 if (wizDlg->mix.channel[i].page == Page_None)
194 c++;
196 return c;
199 void StandardPage::populateCB(QComboBox *cb, int preferred)
201 cb->clear();
203 // Add all unbooked channels and select the preferred one
204 for (int i=0; i<WIZ_MAX_CHANNELS; i++) {
205 if (wizDlg->mix.channel[i].page == Page_None) {
206 cb->addItem(tr("Channel %1").arg(i+1), i);
207 if (preferred == i) {
208 cb->setCurrentIndex(cb->count()-1);
212 // Avoid selecting prebooked channels
213 int channel = cb->itemData(cb->currentIndex()).toInt();
214 if (wizDlg->mix.channel[channel].prebooked) {
215 for (int i=cb->count()-1; i>=0; i--){
216 channel = cb->itemData(i).toInt();
217 if (!wizDlg->mix.channel[channel].prebooked) {
218 cb->setCurrentIndex(i);
219 break;
223 // Prebook the selected channel
224 channel = cb->itemData(cb->currentIndex()).toInt();
225 wizDlg->mix.channel[channel].prebooked = true;
228 bool StandardPage::bookChannel(QComboBox * cb, Input input1, int weight1, Input input2, int weight2 )
230 int channel = cb->itemData(cb->currentIndex()).toInt();
231 if (channel<0 || channel>=WIZ_MAX_CHANNELS)
232 return false;
233 if (wizDlg->mix.channel[channel].page != Page_None)
234 return false;
236 wizDlg->mix.channel[channel].page = pageCurrent;
237 wizDlg->mix.channel[channel].input1 = input1;
238 wizDlg->mix.channel[channel].input2 = input2;
239 wizDlg->mix.channel[channel].weight1 = weight1;
240 wizDlg->mix.channel[channel].weight2 = weight2;
242 return true;
245 void StandardPage::releaseBookings()
247 for (int i=0; i<WIZ_MAX_CHANNELS; i++) {
248 if (wizDlg->mix.channel[i].page == pageCurrent) {
249 wizDlg->mix.channel[i].clear();
254 void StandardPage::releasePreBookings()
256 for (int i=0; i<WIZ_MAX_CHANNELS; i++) {
257 wizDlg->mix.channel[i].prebooked = false;
261 void StandardPage::initializePage()
263 releasePreBookings(); // All prebookings are void after page has initialized
266 void StandardPage::cleanupPage()
268 releaseBookings();
271 int StandardPage::nextId() const
273 return pageFollower;
276 ModelSelectionPage::ModelSelectionPage(WizardDialog *dlg, QString image, QString title, QString text)
277 : StandardPage(Page_Models, dlg, image, title, text)
279 nameLineEdit = new QLineEdit;
280 planeRB = new QRadioButton(tr("Plane"));
281 planeRB->setChecked(true);
282 multirotorRB = new QRadioButton(tr("Multirotor"));
283 helicopterRB = new QRadioButton(tr("Helicopter"));
284 helicopterRB->setDisabled(true); //TODO REMOVE TO ENABLE HELICOPTERS
286 registerField("evaluate.name*", nameLineEdit);
288 QLayout *l = layout();
289 l->addWidget(new QLabel(tr("Model Name:")));
290 l->addWidget(nameLineEdit);
291 l->addWidget(new QLabel(""));
292 l->addWidget(new QLabel(tr("Model Type:")));
293 l->addWidget(planeRB);
294 l->addWidget(multirotorRB);
295 l->addWidget(helicopterRB);
298 bool ModelSelectionPage::validatePage()
300 //Filter and insert model name in mix data
301 QString newName(nameLineEdit->text());
302 newName = (newName.normalized(QString::NormalizationForm_D));
303 newName = newName.replace(QRegExp("[^ A-Za-z0-9_.-,\\s]"), "");
304 strncpy( wizDlg->mix.name, newName.toLatin1(), WIZ_MODEL_NAME_LENGTH);
305 wizDlg->mix.name[WIZ_MODEL_NAME_LENGTH] = 0;
307 if (multirotorRB->isChecked())
308 wizDlg->mix.vehicle = MULTICOPTER;
309 else if (helicopterRB->isChecked())
310 wizDlg->mix.vehicle = HELICOPTER;
311 else
312 wizDlg->mix.vehicle = PLANE;
313 return true;
316 int ModelSelectionPage::nextId() const
318 if (helicopterRB->isChecked())
319 return Page_Cyclic;
320 else if (multirotorRB->isChecked())
321 return Page_Multirotor;
322 else
323 return Page_Throttle;
326 WingtypeSelectionPage::WingtypeSelectionPage(WizardDialog *dlg, QString image, QString title, QString text)
327 : StandardPage(Page_Wingtypes, dlg, image, title, text)
329 standardWingRB = new QRadioButton(tr("Standard Wing"));
330 standardWingRB->setChecked(true);
331 deltaWingRB = new QRadioButton(tr("Flying Wing / Deltawing"));
333 QLayout *l = layout();
334 l->addWidget(standardWingRB);
335 l->addWidget(deltaWingRB);
338 int WingtypeSelectionPage::nextId() const
340 if (deltaWingRB->isChecked())
341 return Page_Elevons;
342 else
343 return Page_Ailerons;
346 TailSelectionPage::TailSelectionPage(WizardDialog *dlg, QString image, QString title, QString text)
347 : StandardPage(Page_Tails, dlg, image, title, text)
349 standardTailRB = new QRadioButton(tr("Elevator and Rudder"));
350 standardTailRB->setChecked(true);
351 simpleTailRB = new QRadioButton(tr("Only Elevator"));
352 vTailRB = new QRadioButton(tr("V-tail"));
354 QLayout *l = layout();
355 l->addWidget(new QLabel(tr("Tail Type:")));
356 l->addWidget(standardTailRB);
357 l->addWidget(simpleTailRB);
358 l->addWidget(vTailRB);
361 int TailSelectionPage::nextId() const
363 if (simpleTailRB->isChecked())
364 return Page_Simpletail;
365 else if (vTailRB->isChecked())
366 return Page_Vtail;
367 else
368 return Page_Tail;
371 FlybarSelectionPage::FlybarSelectionPage(WizardDialog *dlg, QString image, QString title, QString text)
372 : StandardPage(Page_Flybar, dlg, image, title, text)
374 flybarRB = new QRadioButton(tr("Has Flybar"));
375 flybarRB->setChecked(true);
376 noFlybarRB = new QRadioButton(tr("Flybarless"));
378 QLayout *l = layout();
379 l->addWidget(new QLabel(tr("Flybar:")));
380 l->addWidget(flybarRB);
381 l->addWidget(noFlybarRB);
384 int FlybarSelectionPage::nextId() const
386 if (flybarRB->isChecked())
387 return Page_Helictrl;
388 else
389 return Page_Fblheli;
392 ThrottlePage::ThrottlePage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage)
393 : StandardPage(Page_Throttle, dlg, image, title, text, nextPage)
395 motorRB = new QRadioButton(tr("Yes"));
396 noMotorRB = new QRadioButton(tr("No"));
397 motorRB->setChecked(true);
398 throttleCB = new QComboBox();
400 QLayout *l = layout();
401 l->addWidget(motorRB);
402 l->addWidget(noMotorRB);
403 l->addWidget(new QLabel(tr("<br>Throttle Channel:")));
404 l->addWidget(throttleCB);
406 connect(motorRB, SIGNAL(toggled(bool)), this, SLOT(onMotorStateChanged(bool)));
409 void ThrottlePage::initializePage()
411 populateCB(throttleCB, getDefaultChannel(THROTTLE_INPUT));
412 StandardPage::initializePage();
415 bool ThrottlePage::validatePage()
417 releaseBookings();
418 if (motorRB->isChecked())
419 return bookChannel(throttleCB, THROTTLE_INPUT, 100);
420 else
421 return true;
424 void ThrottlePage::onMotorStateChanged(bool toggled)
426 throttleCB->setEnabled(toggled);
429 AileronsPage::AileronsPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage)
430 : StandardPage(Page_Ailerons, dlg, image, title, text, nextPage)
432 noAileronsRB = new QRadioButton(tr("No"));
433 oneAileronRB = new QRadioButton(tr("Yes, controlled by a single channel"));
434 twoAileronsRB = new QRadioButton(tr("Yes, controlled by two channels"));
435 noAileronsRB->setChecked(true);
437 aileron1CB = new QComboBox();
438 aileron2CB = new QComboBox();
439 aileron1CB->setEnabled(false);
440 aileron2CB->setEnabled(false);
442 QLayout *l = layout();
443 l->addWidget(noAileronsRB);
444 l->addWidget(oneAileronRB);
445 l->addWidget(twoAileronsRB);
446 l->addWidget(new QLabel(tr("<br>First Aileron Channel:")));
447 l->addWidget(aileron1CB);
448 l->addWidget(new QLabel(tr("Second Aileron Channel:")));
449 l->addWidget(aileron2CB);
451 connect(noAileronsRB, SIGNAL(toggled(bool)), this, SLOT(noAileronChannel()));
452 connect(oneAileronRB, SIGNAL(toggled(bool)), this, SLOT(oneAileronChannel()));
453 connect(twoAileronsRB, SIGNAL(toggled(bool)), this, SLOT(twoAileronChannels()));
456 void AileronsPage::initializePage()
458 populateCB(aileron1CB, getDefaultChannel(AILERONS_INPUT));
459 populateCB(aileron2CB, nextFreeChannel(4));
460 StandardPage::initializePage();
463 bool AileronsPage::validatePage()
465 releaseBookings();
466 if (noAileronsRB->isChecked()) {
467 return true;
469 if (oneAileronRB->isChecked()) {
470 return (bookChannel(aileron1CB, AILERONS_INPUT, 100 ));
472 return( bookChannel(aileron1CB, AILERONS_INPUT, 100 ) &&
473 bookChannel(aileron2CB, AILERONS_INPUT, -100 ));
476 void AileronsPage::noAileronChannel()
478 aileron1CB->setEnabled(false);
479 aileron2CB->setEnabled(false);
482 void AileronsPage::oneAileronChannel()
484 aileron1CB->setEnabled(true);
485 aileron2CB->setEnabled(false);
488 void AileronsPage::twoAileronChannels()
490 aileron1CB->setEnabled(true);
491 aileron2CB->setEnabled(true);
494 FlapsPage::FlapsPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
495 StandardPage(Page_Flaps, dlg, image, title, text, nextPage)
497 noFlapsRB = new QRadioButton(tr("No"));
498 oneFlapRB = new QRadioButton(tr("Yes, controlled by a single channel"));
499 twoFlapsRB = new QRadioButton(tr("Yes, controlled by two channels"));
500 noFlapsRB->setChecked(true);
502 flap1CB = new QComboBox();
503 flap2CB = new QComboBox();
504 flap1CB->setEnabled(false);
505 flap2CB->setEnabled(false);
507 QLayout *l = layout();
508 l->addWidget(noFlapsRB);
509 l->addWidget(oneFlapRB);
510 l->addWidget(twoFlapsRB);
511 l->addWidget(new QLabel(tr("<br>First Flap Channel:")));
512 l->addWidget(flap1CB);
513 l->addWidget(new QLabel(tr("Second Flap Channel:")));
514 l->addWidget(flap2CB);
516 connect(noFlapsRB, SIGNAL(toggled(bool)), this, SLOT(noFlapChannel()));
517 connect(oneFlapRB, SIGNAL(toggled(bool)), this, SLOT(oneFlapChannel()));
518 connect(twoFlapsRB, SIGNAL(toggled(bool)), this, SLOT(twoFlapChannels()));
521 void FlapsPage::initializePage()
523 populateCB(flap1CB, nextFreeChannel(4));
524 populateCB(flap2CB, nextFreeChannel(4));
525 StandardPage::initializePage();
528 bool FlapsPage::validatePage() {
529 releaseBookings();
530 if (noFlapsRB->isChecked()) {
531 return true;
533 if (oneFlapRB->isChecked()) {
534 return (bookChannel(flap1CB, FLAPS_INPUT, 100 ));
536 return( bookChannel(flap1CB, FLAPS_INPUT, 100 ) &&
537 bookChannel(flap2CB, FLAPS_INPUT, 100 ));
540 void FlapsPage::noFlapChannel()
542 flap1CB->setEnabled(false);
543 flap2CB->setEnabled(false);
546 void FlapsPage::oneFlapChannel()
548 flap1CB->setEnabled(true);
549 flap2CB->setEnabled(false);
552 void FlapsPage::twoFlapChannels()
554 flap1CB->setEnabled(true);
555 flap2CB->setEnabled(true);
558 AirbrakesPage::AirbrakesPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
559 StandardPage(Page_Airbrakes, dlg, image, title, text, nextPage)
561 noAirbrakesRB = new QRadioButton(tr("No"));
562 oneAirbrakeRB = new QRadioButton(tr("Yes, controlled by a single channel"));
563 twoAirbrakesRB = new QRadioButton(tr("Yes, controlled by two channels"));
564 noAirbrakesRB->setChecked(true);
566 airbrake1CB = new QComboBox();
567 airbrake2CB = new QComboBox();
568 airbrake1CB->setEnabled(false);
569 airbrake2CB->setEnabled(false);
571 QLayout *l = layout();
572 l->addWidget(noAirbrakesRB);
573 l->addWidget(oneAirbrakeRB);
574 l->addWidget(twoAirbrakesRB);
575 l->addWidget(new QLabel(tr("<br>First Airbrake Channel:")));
576 l->addWidget(airbrake1CB);
577 l->addWidget(new QLabel(tr("Second Airbrake Channel:")));
578 l->addWidget(airbrake2CB);
580 connect(noAirbrakesRB, SIGNAL(toggled(bool)), this, SLOT(noAirbrakeChannel()));
581 connect(oneAirbrakeRB, SIGNAL(toggled(bool)), this, SLOT(oneAirbrakeChannel()));
582 connect(twoAirbrakesRB, SIGNAL(toggled(bool)), this, SLOT(twoAirbrakeChannels()));
585 void AirbrakesPage::initializePage()
587 populateCB(airbrake1CB, nextFreeChannel(4));
588 populateCB(airbrake2CB, nextFreeChannel(4));
589 StandardPage::initializePage();
592 bool AirbrakesPage::validatePage()
594 releaseBookings();
595 if (noAirbrakesRB->isChecked()) {
596 return true;
598 if (oneAirbrakeRB->isChecked()) {
599 return (bookChannel(airbrake1CB, AIRBRAKES_INPUT, 100 ));
601 return( bookChannel(airbrake1CB, AIRBRAKES_INPUT, 100 ) &&
602 bookChannel(airbrake2CB, AIRBRAKES_INPUT, 100 ));
605 void AirbrakesPage::noAirbrakeChannel()
607 airbrake1CB->setEnabled(false);
608 airbrake2CB->setEnabled(false);
611 void AirbrakesPage::oneAirbrakeChannel()
613 airbrake1CB->setEnabled(true);
614 airbrake2CB->setEnabled(false);
617 void AirbrakesPage::twoAirbrakeChannels()
619 airbrake1CB->setEnabled(true);
620 airbrake2CB->setEnabled(true);
623 ElevonsPage::ElevonsPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
624 StandardPage(Page_Elevons, dlg, image, title, text, nextPage)
626 elevon1CB = new QComboBox();
627 elevon2CB = new QComboBox();
629 QLayout *l = layout();
630 l->addWidget(new QLabel(tr("<br>First Elevon Channel:")));
631 l->addWidget(elevon1CB);
632 l->addWidget(new QLabel(tr("Second Elevon Channel:")));
633 l->addWidget(elevon2CB);
636 void ElevonsPage::initializePage()
638 populateCB(elevon1CB, getDefaultChannel(ELEVATOR_INPUT));
639 populateCB(elevon2CB, getDefaultChannel(AILERONS_INPUT));
640 StandardPage::initializePage();
643 bool ElevonsPage::validatePage()
645 releaseBookings();
646 return (bookChannel(elevon1CB, AILERONS_INPUT, 50, ELEVATOR_INPUT, 50) &&
647 bookChannel(elevon2CB, AILERONS_INPUT, -50, ELEVATOR_INPUT, 50));
650 RudderPage::RudderPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
651 StandardPage(Page_Rudder, dlg, image, title, text, nextPage)
653 noRudderRB = new QRadioButton(tr("No"));
654 hasRudderRB = new QRadioButton(tr("Yes"));
655 noRudderRB->setChecked(true);
657 rudderCB = new QComboBox();
658 rudderCB->setEnabled(false);
660 QLayout *l = layout();
661 l->addWidget(noRudderRB);
662 l->addWidget(hasRudderRB);
663 l->addWidget(new QLabel(tr("<br>Rudder Channel:")));
664 l->addWidget(rudderCB);
665 connect(noRudderRB, SIGNAL(toggled(bool)), this, SLOT(noRudder()));
666 connect(hasRudderRB, SIGNAL(toggled(bool)), this, SLOT(hasRudder()));
669 void RudderPage::initializePage()
671 populateCB(rudderCB, getDefaultChannel(RUDDER_INPUT));
672 StandardPage::initializePage();
675 bool RudderPage::validatePage() {
676 releaseBookings();
677 if (noRudderRB->isChecked())
678 return true;
680 return (bookChannel(rudderCB, RUDDER_INPUT, 100));
683 void RudderPage::noRudder()
685 rudderCB->setEnabled(false);
688 void RudderPage::hasRudder()
690 rudderCB->setEnabled(true);
693 VTailPage::VTailPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage)
694 : StandardPage(Page_Tail, dlg, image, title, text, nextPage)
696 tail1CB = new QComboBox();
697 tail2CB = new QComboBox();
699 QLayout *l = layout();
700 l->addWidget(new QLabel(tr("First Tail Channel:")));
701 l->addWidget(tail1CB);
702 l->addWidget(new QLabel(tr("Second Tail Channel:")));
703 l->addWidget(tail2CB);
706 void VTailPage::initializePage()
708 populateCB(tail1CB, getDefaultChannel(ELEVATOR_INPUT));
709 populateCB(tail2CB, getDefaultChannel(AILERONS_INPUT));
710 StandardPage::initializePage();
713 bool VTailPage::validatePage()
715 releaseBookings();
716 return (bookChannel(tail1CB, ELEVATOR_INPUT, 50, RUDDER_INPUT, 50) &&
717 bookChannel(tail2CB, ELEVATOR_INPUT, 50, RUDDER_INPUT, -50 ));
720 TailPage::TailPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
721 StandardPage(Page_Tail, dlg, image, title, text, nextPage)
723 elevatorCB = new QComboBox();
724 rudderCB = new QComboBox();
726 l = layout();
727 l->addWidget(new QLabel(tr("Rudder Channel:")));
728 l->addWidget(rudderCB);
729 l->addWidget(new QLabel(tr("Elevator Channel:")));
730 l->addWidget(elevatorCB);
732 errorMessage = NULL;
735 void TailPage::initializePage()
737 populateCB(elevatorCB, getDefaultChannel(ELEVATOR_INPUT));
738 populateCB(rudderCB, getDefaultChannel(RUDDER_INPUT));
739 StandardPage::initializePage();
741 if (totalChannelsAvailable() < 2) {
742 errorMessage = new QLabel(tr("Only one channel still available!<br>"
743 "You probably should configure your model without using the wizard."));
744 errorMessage->setStyleSheet("QLabel { color : red; }");
745 l->addWidget(errorMessage);
749 bool TailPage::validatePage()
751 releaseBookings();
752 return( bookChannel(elevatorCB, ELEVATOR_INPUT, 100) &&
753 bookChannel(rudderCB, RUDDER_INPUT, 100));
756 void TailPage::cleanupPage()
758 if (errorMessage)
760 l->removeWidget(errorMessage);
761 delete errorMessage;
762 errorMessage = NULL;
764 StandardPage::cleanupPage();
767 SimpleTailPage::SimpleTailPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage)
768 : StandardPage(Page_Simpletail, dlg, image, title, text, nextPage)
770 elevatorCB = new QComboBox();
772 QLayout *l = layout();
773 l->addWidget(new QLabel(tr("Elevator Channel:")));
774 l->addWidget(elevatorCB);
777 void SimpleTailPage::initializePage()
779 populateCB(elevatorCB, getDefaultChannel(ELEVATOR_INPUT));
780 StandardPage::initializePage();
783 bool SimpleTailPage::validatePage()
785 releaseBookings();
786 return( bookChannel(elevatorCB, ELEVATOR_INPUT, 100 ));
789 CyclicPage::CyclicPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
790 StandardPage(Page_Cyclic, dlg, image, title, text, nextPage)
792 cyclic90RB = new QRadioButton(tr("90"));
793 cyclic90RB->setChecked(true);
794 cyclic120RB = new QRadioButton(tr("120"));
795 cyclic120XRB = new QRadioButton(tr("120x"));
796 cyclic140RB = new QRadioButton(tr("140"));
798 QLayout *l = layout();
799 l->addWidget(cyclic90RB);
800 l->addWidget(cyclic120RB);
801 l->addWidget(cyclic120XRB);
802 l->addWidget(cyclic140RB);
805 void CyclicPage::initializePage()
807 StandardPage::initializePage();
810 bool CyclicPage::validatePage()
812 releaseBookings();
813 return true;
816 GyroPage::GyroPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
817 StandardPage(Page_Gyro, dlg, image, title, text, nextPage)
819 noGyroRB = new QRadioButton(tr("No"));
820 noGyroRB->setChecked(true);
821 switchGyroRB = new QRadioButton(tr("Yes, controled by a switch"));
822 potGyroRB = new QRadioButton(tr("Yes, controlled by a pot"));
824 QLayout *l = layout();
825 l->addWidget(noGyroRB);
826 l->addWidget(switchGyroRB);
827 l->addWidget(potGyroRB);
830 void GyroPage::initializePage()
832 StandardPage::initializePage();
835 bool GyroPage::validatePage() {
836 releaseBookings();
837 return true;
840 FblPage::FblPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
841 StandardPage(Page_Fblheli, dlg, image, title, text, nextPage)
843 throttleCB = new QComboBox();
844 yawCB = new QComboBox();
845 pitchCB = new QComboBox();
846 rollCB = new QComboBox();
848 QLayout *l = layout();
849 l->addWidget(new QLabel(tr("Throttle Channel:")));
850 l->addWidget(throttleCB);
851 l->addWidget(new QLabel(tr("Yaw Channel:")));
852 l->addWidget(yawCB);
853 l->addWidget(new QLabel(tr("Pitch Channel:")));
854 l->addWidget(pitchCB);
855 l->addWidget(new QLabel(tr("Roll Channel:")));
856 l->addWidget(rollCB);
859 void FblPage::initializePage()
861 populateCB(throttleCB, getDefaultChannel(THROTTLE_INPUT));
862 populateCB(yawCB, getDefaultChannel(RUDDER_INPUT));
863 populateCB(pitchCB, getDefaultChannel(ELEVATOR_INPUT));
864 populateCB(rollCB, getDefaultChannel(AILERONS_INPUT));
865 StandardPage::initializePage();
868 bool FblPage::validatePage()
870 releaseBookings();
871 return( bookChannel(throttleCB, THROTTLE_INPUT, 100 ) &&
872 bookChannel( yawCB, RUDDER_INPUT, 100 ) &&
873 bookChannel( pitchCB, ELEVATOR_INPUT, 100 ) &&
874 bookChannel( rollCB, AILERONS_INPUT, 100 ));
877 HeliPage::HeliPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
878 StandardPage(Page_Helictrl, dlg, image, title, text, nextPage)
880 throttleCB = new QComboBox();
881 yawCB = new QComboBox();
882 pitchCB = new QComboBox();
883 rollCB = new QComboBox();
885 QLayout *l = layout();
886 l->addWidget(new QLabel(tr("Throttle Channel:")));
887 l->addWidget(throttleCB);
888 l->addWidget(new QLabel(tr("Yaw Channel:")));
889 l->addWidget(yawCB);
890 l->addWidget(new QLabel(tr("Pitch Channel:")));
891 l->addWidget(pitchCB);
892 l->addWidget(new QLabel(tr("Roll Channel:")));
893 l->addWidget(rollCB);
896 void HeliPage::initializePage()
898 populateCB(throttleCB, getDefaultChannel(THROTTLE_INPUT));
899 populateCB(yawCB, getDefaultChannel(RUDDER_INPUT));
900 populateCB(pitchCB, getDefaultChannel(ELEVATOR_INPUT));
901 populateCB(rollCB, getDefaultChannel(AILERONS_INPUT));
902 StandardPage::initializePage();
905 bool HeliPage::validatePage()
907 releaseBookings();
908 return( bookChannel(throttleCB, THROTTLE_INPUT, 100 ) &&
909 bookChannel( yawCB, RUDDER_INPUT, 100 ) &&
910 bookChannel( pitchCB, ELEVATOR_INPUT, 100 ) &&
911 bookChannel( rollCB, AILERONS_INPUT, 100 ));
914 MultirotorPage::MultirotorPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
915 StandardPage(Page_Multirotor, dlg, image, title, text, nextPage)
917 throttleCB = new QComboBox();
918 yawCB = new QComboBox();
919 pitchCB = new QComboBox();
920 rollCB = new QComboBox();
922 QLayout *l = layout();
923 l->addWidget(new QLabel(tr("Throttle Channel:")));
924 l->addWidget(throttleCB);
925 l->addWidget(new QLabel(tr("Yaw Channel:")));
926 l->addWidget(yawCB);
927 l->addWidget(new QLabel(tr("Pitch Channel:")));
928 l->addWidget(pitchCB);
929 l->addWidget(new QLabel(tr("Roll Channel:")));
930 l->addWidget(rollCB);
933 void MultirotorPage::initializePage()
935 populateCB(throttleCB, getDefaultChannel(THROTTLE_INPUT));
936 populateCB(yawCB, getDefaultChannel(RUDDER_INPUT));
937 populateCB(pitchCB, getDefaultChannel(ELEVATOR_INPUT));
938 populateCB(rollCB, getDefaultChannel(AILERONS_INPUT));
939 StandardPage::initializePage();
942 bool MultirotorPage::validatePage()
944 releaseBookings();
945 return( bookChannel(throttleCB, THROTTLE_INPUT, 100 ) &&
946 bookChannel(yawCB, RUDDER_INPUT, 100 ) &&
947 bookChannel(pitchCB, ELEVATOR_INPUT, 100 ) &&
948 bookChannel(rollCB, AILERONS_INPUT, 100 ));
951 OptionsPage::OptionsPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage):
952 StandardPage(Page_Options, dlg, image, title, text, nextPage)
954 throttleCutRB = new QCheckBox(tr("Throttle Cut"));
955 throttleTimerRB = new QCheckBox(tr("Throttle Timer"));
956 flightTimerRB = new QCheckBox(tr("Flight Timer"));
958 QLayout *l = layout();
959 l->addWidget(throttleCutRB);
960 l->addWidget(throttleTimerRB);
961 l->addWidget(flightTimerRB);
964 void OptionsPage::initializePage(){
965 StandardPage::initializePage();
968 bool OptionsPage::validatePage(){
969 wizDlg->mix.options[THROTTLE_CUT_OPTION] = throttleCutRB->isChecked();
970 wizDlg->mix.options[THROTTLE_TIMER_OPTION] = throttleTimerRB->isChecked();
971 wizDlg->mix.options[FLIGHT_TIMER_OPTION] = flightTimerRB->isChecked();
972 return true;
975 ConclusionPage::ConclusionPage(WizardDialog *dlg, QString image, QString title, QString text, int nextPage)
976 : StandardPage(Page_Conclusion, dlg, image, title, text, nextPage)
978 textLabel = new QLabel();
979 proceedCB = new QCheckBox(tr("OK, I understand."));
980 registerField("evaluate.proceed*", proceedCB);
982 QLayout *l = layout();
983 l->addWidget(textLabel);
984 l->addWidget(proceedCB);
987 void ConclusionPage::initializePage()
989 WizardPrinter p(&wizDlg->mix);
990 textLabel->setText(p.print());
991 StandardPage::initializePage();
994 bool ConclusionPage::validatePage()
996 wizDlg->mix.complete = true;
997 return true;
1001 QString WizardPrinter::inputName(Input input)
1003 switch (input) {
1004 case THROTTLE_INPUT:
1005 return "THR";
1006 case RUDDER_INPUT:
1007 return "RUD";
1008 case ELEVATOR_INPUT:
1009 return "ELE";
1010 case AILERONS_INPUT:
1011 return "AIL";
1012 case FLAPS_INPUT:
1013 return "FLP";
1014 case AIRBRAKES_INPUT:
1015 return "AIR";
1016 default:
1017 return "---";
1021 QString WizardPrinter::vehicleName(Vehicle vehicle)
1023 switch (vehicle) {
1024 case PLANE:
1025 return tr("Plane");
1026 case MULTICOPTER:
1027 return tr("Multicopter");
1028 case HELICOPTER:
1029 return tr("Helicopter");
1030 default:
1031 return "---";
1035 WizardPrinter::WizardPrinter(WizMix *wizMix)
1037 mix = wizMix;
1040 QString WizardPrinter::printChannel( Input input1, int weight1, Input input2, int weight2 )
1042 QString str;
1043 str = QString("[%1, %2]").arg(inputName(input1)).arg(weight1);
1044 if ( input2 != NO_INPUT )
1045 str += QString("[%1, %2]").arg(inputName(input2)).arg(weight2);
1046 return str;
1049 QString WizardPrinter::print()
1051 QString str = tr("Model Name: ") + mix->name + "\n";
1052 str += tr("Model Type: ") + vehicleName(mix->vehicle) + "\n";
1054 str += tr("Options: ") + "[";
1055 for (int i=0; i<WIZ_MAX_OPTIONS; i++) {
1056 if (mix->options[i])
1057 str += "X";
1058 else
1059 str += "-";
1061 str += QString("]") + "\n";
1063 for (int i=0; i<WIZ_MAX_CHANNELS; i++) {
1064 if (mix->channel[i].page != Page_None) {
1065 Channel ch = mix->channel[i];
1066 str += tr("Channel %1: ").arg(i+1);
1067 str += printChannel(ch.input1, ch.weight1, ch.input2, ch.weight2 );
1068 str += QString("\n");
1071 return str;