Bsongis/companion r9m fixes (#5914)
[opentx.git] / companion / src / modeledit / setup.cpp
blob8cf7928c7ddf99e2099a6d2e781e284e8f10c614
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 "setup.h"
22 #include "ui_setup.h"
23 #include "ui_setup_timer.h"
24 #include "ui_setup_module.h"
25 #include "switchitemmodel.h"
26 #include "appdata.h"
27 #include "modelprinter.h"
28 #include "multiprotocols.h"
29 #include "checklistdialog.h"
31 TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus):
32 ModelPanel(parent, model, generalSettings, firmware),
33 timer(timer),
34 ui(new Ui::Timer)
36 Board::Type board = firmware->getBoard();
38 ui->setupUi(this);
40 lock = true;
42 // Name
43 int length = firmware->getCapability(TimersName);
44 if (length == 0) {
45 ui->name->hide();
47 else {
48 ui->name->setMaxLength(length);
49 ui->name->setText(timer.name);
52 // Mode
53 rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, TimersContext);
54 ui->mode->setModel(rawSwitchItemModel);
55 ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue()));
57 if (!firmware->getCapability(PermTimers)) {
58 ui->persistent->hide();
59 ui->persistentValue->hide();
62 ui->countdownBeep->setField(timer.countdownBeep, this);
63 ui->countdownBeep->addItem(tr("Silent"), TimerData::COUNTDOWN_SILENT);
64 ui->countdownBeep->addItem(tr("Beeps"), TimerData::COUNTDOWN_BEEPS);
65 if (IS_ARM(board) || IS_2560(board)) {
66 ui->countdownBeep->addItem(tr("Voice"), TimerData::COUNTDOWN_VOICE);
67 ui->countdownBeep->addItem(tr("Haptic"), TimerData::COUNTDOWN_HAPTIC);
70 ui->value->setMaximumTime(firmware->getMaxTimerStart());
72 ui->persistent->setField(timer.persistent, this);
73 ui->persistent->addItem(tr("Not persistent"), 0);
74 ui->persistent->addItem(tr("Persistent (flight)"), 1);
75 ui->persistent->addItem(tr("Persistent (manual reset)"), 2);
77 disableMouseScrolling();
78 QWidget::setTabOrder(prevFocus, ui->name);
79 QWidget::setTabOrder(ui->name, ui->value);
80 QWidget::setTabOrder(ui->value, ui->mode);
81 QWidget::setTabOrder(ui->mode, ui->countdownBeep);
82 QWidget::setTabOrder(ui->countdownBeep, ui->minuteBeep);
83 QWidget::setTabOrder(ui->minuteBeep, ui->persistent);
85 lock = false;
88 TimerPanel::~TimerPanel()
90 delete ui;
93 void TimerPanel::update()
95 rawSwitchItemModel->update();
97 int hour = timer.val / 3600;
98 int min = (timer.val - (hour * 3600)) / 60;
99 int sec = (timer.val - (hour * 3600)) % 60;
101 ui->value->setTime(QTime(hour, min, sec));
103 if (firmware->getCapability(PermTimers)) {
104 int sign = 1;
105 int pvalue = timer.pvalue;
106 if (pvalue < 0) {
107 pvalue = -pvalue;
108 sign = -1;
110 int hours = pvalue / 3600;
111 pvalue -= hours * 3600;
112 int minutes = pvalue / 60;
113 int seconds = pvalue % 60;
114 ui->persistentValue->setText(QString(" %1(%2:%3:%4)").arg(sign<0 ? "-" :" ").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
117 ui->minuteBeep->setChecked(timer.minuteBeep);
120 QWidget * TimerPanel::getLastFocus()
122 return ui->persistent;
125 void TimerPanel::on_value_editingFinished()
127 unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
128 if (timer.val != val) {
129 timer.val = val;
130 emit modified();
134 void TimerPanel::on_mode_currentIndexChanged(int index)
136 if (!lock) {
137 timer.mode = RawSwitch(ui->mode->itemData(index).toInt());
138 emit modified();
142 void TimerPanel::on_minuteBeep_toggled(bool checked)
144 timer.minuteBeep = checked;
145 emit modified();
148 void TimerPanel::on_name_editingFinished()
150 if (QString(timer.name) != ui->name->text()) {
151 int length = ui->name->maxLength();
152 strncpy(timer.name, ui->name->text().toLatin1(), length);
153 emit modified();
157 /******************************************************************************/
159 #define FAILSAFE_CHANNEL_HOLD 2000
160 #define FAILSAFE_CHANNEL_NOPULSE 2001
162 #define MASK_PROTOCOL 1
163 #define MASK_CHANNELS_COUNT 2
164 #define MASK_RX_NUMBER 4
165 #define MASK_CHANNELS_RANGE 8
166 #define MASK_PPM_FIELDS 16
167 #define MASK_FAILSAFES 32
168 #define MASK_OPEN_DRAIN 64
169 #define MASK_MULTIMODULE 128
170 #define MASK_ANTENNA 256
171 #define MASK_MULTIOPTION 512
172 #define MASK_R9M 1024
173 #define MASK_SBUSPPM_FIELDS 2048
174 #define MASK_SUBTYPES 4096
176 quint8 ModulePanel::failsafesValueDisplayType = ModulePanel::FAILSAFE_DISPLAY_PERCENT;
178 ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & module, GeneralSettings & generalSettings, Firmware * firmware, int moduleIdx):
179 ModelPanel(parent, model, generalSettings, firmware),
180 module(module),
181 moduleIdx(moduleIdx),
182 ui(new Ui::Module)
184 lock = true;
186 ui->setupUi(this);
188 QString label;
189 if (moduleIdx < 0) {
190 label = tr("Trainer Port");
191 if (IS_HORUS(firmware->getBoard())) {
192 ui->trainerMode->setItemData(TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, 0, Qt::UserRole - 1);
193 ui->trainerMode->setItemData(TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, 0, Qt::UserRole - 1);
195 if (generalSettings.hw_uartMode != UART_MODE_SBUS_TRAINER) {
196 ui->trainerMode->setItemData(TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, 0, Qt::UserRole - 1);
198 ui->trainerMode->setCurrentIndex(model.trainerMode);
199 if (!IS_HORUS_OR_TARANIS(firmware->getBoard())) {
200 ui->label_trainerMode->hide();
201 ui->trainerMode->hide();
203 ui->formLayout_col1->setSpacing(0);
205 else {
206 ui->label_trainerMode->hide();
207 ui->trainerMode->hide();
208 if (firmware->getCapability(NumModules) > 1) {
209 if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
210 if (moduleIdx == 0)
211 label = tr("Internal Radio System");
212 else
213 label = tr("External Radio Module");
215 else {
216 if (moduleIdx == 0)
217 label = tr("Radio System");
218 else
219 label = tr("Extra Radio System");
222 else {
223 label = tr("Radio System");
226 ui->label_module->setText(label);
228 // The protocols available on this board
229 for (int i=0; i<PULSES_PROTOCOL_LAST; i++) {
230 if (firmware->isAvailable((PulsesProtocol) i, moduleIdx)) {
231 if (IS_TARANIS_XLITE(firmware->getBoard()) && i == PULSES_PXX_R9M) //TODO remove when mini are handled as a different module type
232 ui->protocol->addItem("FrSky R9M Mini", (QVariant) i);
233 else
234 ui->protocol->addItem(ModelPrinter::printModuleProtocol(i), (QVariant) i);
235 if (i == module.protocol)
236 ui->protocol->setCurrentIndex(ui->protocol->count()-1);
239 for (int i=0; i<=MM_RF_PROTO_LAST; i++) {
240 ui->multiProtocol->addItem(ModelPrinter::printMultiRfProtocol(i, false), (QVariant) i);
243 ui->btnGrpValueType->setId(ui->optPercent, FAILSAFE_DISPLAY_PERCENT);
244 ui->btnGrpValueType->setId(ui->optUs, FAILSAFE_DISPLAY_USEC);
245 ui->btnGrpValueType->button(failsafesValueDisplayType)->setChecked(true);
247 setupFailsafes();
249 disableMouseScrolling();
251 update();
253 connect(ui->protocol, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onProtocolChanged);
254 connect(ui->multiProtocol, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged);
255 connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes);
256 connect(ui->btnGrpValueType, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged);
258 lock = false;
262 ModulePanel::~ModulePanel()
264 delete ui;
267 bool ModulePanel::moduleHasFailsafes()
269 return (((PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_XJT_X16 || (PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_R9M)
270 && firmware->getCapability(HasFailsafe));;
273 void ModulePanel::setupFailsafes()
275 ChannelFailsafeWidgetsGroup grp;
276 const int start = module.channelsStart;
277 const int end = start + module.channelsCount;
278 const bool hasFailsafe = moduleHasFailsafes();
280 lock = true;
282 QMutableMapIterator<int, ChannelFailsafeWidgetsGroup> i(failsafeGroupsMap);
283 while (i.hasNext()) {
284 i.next();
285 grp = i.value();
286 ui->failsafesLayout->removeWidget(grp.label);
287 ui->failsafesLayout->removeWidget(grp.combo);
288 ui->failsafesLayout->removeWidget(grp.sbPercent);
289 ui->failsafesLayout->removeWidget(grp.sbUsec);
290 if (i.key() < start || i.key() >= end || !hasFailsafe) {
291 grp.label->deleteLater();
292 grp.combo->deleteLater();
293 grp.sbPercent->deleteLater();
294 grp.sbUsec->deleteLater();
295 i.remove();
299 if (!hasFailsafe)
300 return;
302 int row = 0;
303 int col = 0;
304 int channelMax = model->getChannelsMax();
305 int channelMaxUs = 512 * channelMax / 100 * 2;
307 for (int i = start; i < end; ++i) {
308 if (failsafeGroupsMap.contains(i)) {
309 grp = failsafeGroupsMap.value(i);
311 else {
312 QLabel * label = new QLabel(this);
313 label->setProperty("index", i);
314 label->setText(QString::number(i+1));
316 QComboBox * combo = new QComboBox(this);
317 combo->setProperty("index", i);
318 combo->addItem(tr("Value"), 0);
319 combo->addItem(tr("Hold"), FAILSAFE_CHANNEL_HOLD);
320 combo->addItem(tr("No Pulse"), FAILSAFE_CHANNEL_NOPULSE);
322 QDoubleSpinBox * sbDbl = new QDoubleSpinBox(this);
323 sbDbl->setProperty("index", i);
324 sbDbl->setMinimumSize(QSize(20, 0));
325 sbDbl->setRange(-channelMax, channelMax);
326 sbDbl->setSingleStep(0.1);
327 sbDbl->setDecimals(1);
329 QSpinBox * sbInt = new QSpinBox(this);
330 sbInt->setProperty("index", i);
331 sbInt->setMinimumSize(QSize(20, 0));
332 sbInt->setRange(-channelMaxUs, channelMaxUs);
333 sbInt->setSingleStep(1);
335 grp = ChannelFailsafeWidgetsGroup();
336 grp.combo = combo;
337 grp.sbPercent = sbDbl;
338 grp.sbUsec = sbInt;
339 grp.label = label;
340 failsafeGroupsMap.insert(i, grp);
342 connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onFailsafeComboIndexChanged(int)));
343 connect(sbInt, SIGNAL(valueChanged(int)), this, SLOT(onFailsafeUsecChanged(int)));
344 connect(sbDbl, SIGNAL(valueChanged(double)), this, SLOT(onFailsafePercentChanged(double)));
347 ui->failsafesLayout->addWidget(grp.label, row, col, Qt::AlignHCenter);
348 ui->failsafesLayout->addWidget(grp.combo, row + 1, col, Qt::AlignHCenter);
349 ui->failsafesLayout->addWidget(grp.sbPercent, row + 2, col, Qt::AlignHCenter);
350 ui->failsafesLayout->addWidget(grp.sbUsec, row + 3, col, Qt::AlignHCenter);
351 grp.sbPercent->setVisible(failsafesValueDisplayType == FAILSAFE_DISPLAY_PERCENT);
352 grp.sbUsec->setVisible(failsafesValueDisplayType == FAILSAFE_DISPLAY_USEC);
354 updateFailsafe(i);
356 if (++col > 7) {
357 row += 4;
358 col = 0;
362 lock = false;
365 void ModulePanel::update()
367 unsigned int mask = 0;
368 PulsesProtocol protocol = (PulsesProtocol)module.protocol;
369 unsigned int max_rx_num = 63;
371 if (moduleIdx >= 0) {
372 mask |= MASK_PROTOCOL;
373 switch (protocol) {
374 case PULSES_PXX_R9M:
375 mask |= MASK_R9M | MASK_SUBTYPES;
376 case PULSES_PXX_XJT_X16:
377 case PULSES_PXX_XJT_D8:
378 case PULSES_PXX_XJT_LR12:
379 case PULSES_PXX_DJT:
380 mask |= MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
381 if (protocol==PULSES_PXX_XJT_X16 || protocol==PULSES_PXX_XJT_LR12 || protocol==PULSES_PXX_R9M)
382 mask |= MASK_RX_NUMBER;
383 if ((IS_HORUS(firmware->getBoard()) || IS_TARANIS_XLITE(firmware->getBoard())) && moduleIdx==0)
384 mask |= MASK_ANTENNA;
385 break;
386 case PULSES_LP45:
387 case PULSES_DSM2:
388 case PULSES_DSMX:
389 mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER;
390 module.channelsCount = 6;
391 max_rx_num = 20;
392 break;
393 case PULSES_CROSSFIRE:
394 mask |= MASK_CHANNELS_RANGE;
395 module.channelsCount = 16;
396 break;
397 case PULSES_PPM:
398 mask |= MASK_PPM_FIELDS | MASK_SBUSPPM_FIELDS| MASK_CHANNELS_RANGE| MASK_CHANNELS_COUNT;
399 if (IS_9XRPRO(firmware->getBoard())) {
400 mask |= MASK_OPEN_DRAIN;
402 break;
403 case PULSES_SBUS:
404 module.channelsCount = 16;
405 mask |= MASK_SBUSPPM_FIELDS| MASK_CHANNELS_RANGE;
406 break;
407 case PULSES_MULTIMODULE:
408 mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER | MASK_MULTIMODULE | MASK_SUBTYPES;
409 max_rx_num = 15;
410 if (module.multi.rfProtocol == MM_RF_PROTO_DSM2)
411 mask |= MASK_CHANNELS_COUNT;
412 else
413 module.channelsCount = 16;
414 if (multiProtocols.getProtocol(module.multi.rfProtocol).optionsstr != nullptr)
415 mask |= MASK_MULTIOPTION;
416 if (multiProtocols.getProtocol(module.multi.rfProtocol).hasFailsafe)
417 mask |= MASK_FAILSAFES;
418 break;
419 case PULSES_OFF:
420 break;
421 default:
422 break;
425 else if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
426 if (model->trainerMode == TRAINER_SLAVE_JACK) {
427 mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
430 else if (model->trainerMode != TRAINER_MASTER_JACK) {
431 mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
434 if (moduleHasFailsafes()) {
435 mask |= MASK_FAILSAFES;
438 ui->label_protocol->setVisible(mask & MASK_PROTOCOL);
439 ui->protocol->setVisible(mask & MASK_PROTOCOL);
440 ui->label_rxNumber->setVisible(mask & MASK_RX_NUMBER);
441 ui->rxNumber->setVisible(mask & MASK_RX_NUMBER);
442 ui->rxNumber->setMaximum(max_rx_num);
443 ui->rxNumber->setValue(module.modelId);
444 ui->label_channelsStart->setVisible(mask & MASK_CHANNELS_RANGE);
445 ui->channelsStart->setVisible(mask & MASK_CHANNELS_RANGE);
446 ui->channelsStart->setValue(module.channelsStart+1);
447 ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
448 ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
449 ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT);
450 ui->channelsCount->setValue(module.channelsCount);
451 ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2);
453 // PPM settings fields
454 ui->label_ppmPolarity->setVisible(mask & MASK_SBUSPPM_FIELDS);
455 ui->ppmPolarity->setVisible(mask & MASK_SBUSPPM_FIELDS);
456 ui->ppmPolarity->setCurrentIndex(module.ppm.pulsePol);
457 ui->label_ppmOutputType->setVisible(mask & MASK_OPEN_DRAIN);
458 ui->ppmOutputType->setVisible(mask & MASK_OPEN_DRAIN);
459 ui->ppmOutputType->setCurrentIndex(module.ppm.outputType);
460 ui->label_ppmDelay->setVisible(mask & MASK_PPM_FIELDS);
461 ui->ppmDelay->setVisible(mask & MASK_PPM_FIELDS);
462 ui->ppmDelay->setValue(module.ppm.delay);
463 ui->label_ppmFrameLength->setVisible(mask & MASK_SBUSPPM_FIELDS);
464 ui->ppmFrameLength->setVisible(mask & MASK_SBUSPPM_FIELDS);
465 ui->ppmFrameLength->setMinimum(module.channelsCount*(model->extendedLimits ? 2.250 : 2)+3.5);
466 ui->ppmFrameLength->setMaximum(firmware->getCapability(PPMFrameLength));
467 ui->ppmFrameLength->setValue(22.5+((double)module.ppm.frameLength)*0.5);
469 // Antenna selection on Horus and xlite
470 ui->label_antenna->setVisible(mask & MASK_ANTENNA);
471 ui->antennaMode->setVisible(mask & MASK_ANTENNA);
472 if IS_HORUS_X12S(firmware->getBoard()) {
473 ui->antennaMode->setItemText(1,tr("Ext. + Int"));
475 else {
476 ui->antennaMode->setItemText(1,tr("External"));
478 ui->antennaMode->setCurrentIndex(module.pxx.external_antenna);
480 // R9M options
481 ui->r9mPower->setVisible(mask & MASK_R9M);
482 ui->label_r9mPower->setVisible(mask & MASK_R9M);
483 ui->warning_r9mPower->setVisible((mask & MASK_R9M) && module.subType == R9M_LBT);
485 if (mask & MASK_R9M) {
486 ui->r9mPower->clear();
487 Board::Type board = firmware->getBoard();
488 if (IS_TARANIS_XLITE(board)) {
489 if (module.subType == R9M_FCC) {
490 ui->r9mPower->addItem(tr("100 mW - 16CH"));
492 else {
493 ui->r9mPower->addItem(tr("25 mW - 8CH"));
494 ui->r9mPower->addItem(tr("25 mW - 16CH"));
495 ui->r9mPower->addItem(tr("100 mW - 16CH, no telemetry"));
498 else {
499 if (module.subType == R9M_FCC) {
500 ui->r9mPower->addItem(tr("10 mW - 16CH"));
501 ui->r9mPower->addItem(tr("100 mW - 16CH"));
502 ui->r9mPower->addItem(tr("500 mW - 16CH"));
503 ui->r9mPower->addItem(tr("1000 mW - 16CH"));
505 else {
506 ui->r9mPower->addItem(tr("25 mW - 8CH"));
507 ui->r9mPower->addItem(tr("25 mW - 16CH"));
508 ui->r9mPower->addItem(tr("200 mW - 16CH"));
509 ui->r9mPower->addItem(tr("500 mW - 16CH"));
512 ui->r9mPower->setCurrentIndex(module.pxx.power);
515 // module subtype
516 ui->label_multiSubType->setVisible(mask & MASK_SUBTYPES);
517 ui->multiSubType->setVisible(mask & MASK_SUBTYPES);
518 if (mask & MASK_SUBTYPES) {
519 unsigned numEntries = 2; // R9M FCC/EU
520 if (mask & MASK_MULTIMODULE)
521 numEntries = (module.multi.customProto ? 8 : multiProtocols.getProtocol(module.multi.rfProtocol).numSubytes());
523 bool blocker = ui->multiSubType->blockSignals(true);
524 ui->multiSubType->clear();
525 for (unsigned i=0; i < numEntries; i++)
526 ui->multiSubType->addItem(ModelPrinter::printModuleSubType(protocol, i, module.multi.rfProtocol, module.multi.customProto), i);
527 ui->multiSubType->setCurrentIndex(module.subType);
528 ui->multiSubType->blockSignals(blocker);
531 // Multi settings fields
532 ui->label_multiProtocol->setVisible(mask & MASK_MULTIMODULE);
533 ui->multiProtocol->setVisible(mask & MASK_MULTIMODULE);
534 ui->label_option->setVisible(mask & MASK_MULTIOPTION);
535 ui->optionValue->setVisible(mask & MASK_MULTIOPTION);
536 ui->autoBind->setVisible(mask & MASK_MULTIMODULE);
537 ui->lowPower->setVisible(mask & MASK_MULTIMODULE);
539 if (mask & MASK_MULTIMODULE) {
540 ui->multiProtocol->setCurrentIndex(module.multi.rfProtocol);
541 ui->autoBind->setChecked(module.multi.autoBindMode);
542 ui->lowPower->setChecked(module.multi.lowPowerMode);
545 if (mask & MASK_MULTIOPTION) {
546 auto pdef = multiProtocols.getProtocol(module.multi.rfProtocol);
547 ui->optionValue->setMinimum(pdef.getOptionMin());
548 ui->optionValue->setMaximum(pdef.getOptionMax());
549 ui->optionValue->setValue(module.multi.optionValue);
550 ui->label_option->setText(qApp->translate("Multiprotocols", qPrintable(pdef.optionsstr)));
553 // Failsafes
554 ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES);
555 ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
557 if ((mask & MASK_FAILSAFES) && module.failsafeMode == FAILSAFE_CUSTOM) {
558 if (ui->failsafesGroupBox->isHidden()) {
559 setupFailsafes();
560 ui->failsafesGroupBox->setVisible(true);
563 else {
564 ui->failsafesGroupBox->setVisible(false);
567 if (mask & MASK_FAILSAFES) {
568 ui->failsafeMode->setCurrentIndex(module.failsafeMode);
570 if (firmware->getCapability(ChannelsName)) {
571 int chan;
572 QString name;
573 QMapIterator<int, ChannelFailsafeWidgetsGroup> i(failsafeGroupsMap);
574 while (i.hasNext()) {
575 i.next();
576 chan = i.key();
577 name = QString(model->limitData[chan + module.channelsStart].name).trimmed();
578 if (name.isEmpty())
579 i.value().label->setText(QString::number(chan + 1));
580 else
581 i.value().label->setText(name);
586 if (mask & MASK_CHANNELS_RANGE) {
587 ui->channelsStart->setMaximum(33 - ui->channelsCount->value());
588 ui->channelsCount->setMaximum(qMin(16, 33-ui->channelsStart->value()));
592 void ModulePanel::on_trainerMode_currentIndexChanged(int index)
594 if (!lock) {
595 model->trainerMode = index;
596 update();
597 emit modified();
601 void ModulePanel::onProtocolChanged(int index)
603 if (!lock) {
604 module.protocol = ui->protocol->itemData(index).toInt();
605 update();
606 emit modified();
610 void ModulePanel::on_ppmPolarity_currentIndexChanged(int index)
612 module.ppm.pulsePol = index;
613 emit modified();
616 void ModulePanel::on_antennaMode_currentIndexChanged(int index)
618 module.pxx.external_antenna = index;
619 emit modified();
622 void ModulePanel::on_r9mPower_currentIndexChanged(int index)
624 module.pxx.power = index;
625 emit modified();
628 void ModulePanel::on_ppmOutputType_currentIndexChanged(int index)
630 module.ppm.outputType = index;
631 emit modified();
634 void ModulePanel::on_channelsCount_editingFinished()
636 if (!lock && module.channelsCount != ui->channelsCount->value()) {
637 module.channelsCount = ui->channelsCount->value();
638 update();
639 emit channelsRangeChanged();
640 emit modified();
644 void ModulePanel::on_channelsStart_editingFinished()
646 if (!lock && module.channelsStart != (unsigned)ui->channelsStart->value() - 1) {
647 module.channelsStart = (unsigned)ui->channelsStart->value() - 1;
648 update();
649 emit channelsRangeChanged();
650 emit modified();
654 void ModulePanel::on_ppmDelay_editingFinished()
656 if (!lock && module.ppm.delay != ui->ppmDelay->value()) {
657 // TODO only accept valid values
658 module.ppm.delay = ui->ppmDelay->value();
659 emit modified();
663 void ModulePanel::on_rxNumber_editingFinished()
665 if (module.modelId != (unsigned)ui->rxNumber->value()) {
666 module.modelId = (unsigned)ui->rxNumber->value();
667 emit modified();
671 void ModulePanel::on_ppmFrameLength_editingFinished()
673 int val = (ui->ppmFrameLength->value()-22.5) / 0.5;
674 if (module.ppm.frameLength != val) {
675 module.ppm.frameLength = val;
676 emit modified();
680 void ModulePanel::on_failsafeMode_currentIndexChanged(int value)
682 if (!lock) {
683 module.failsafeMode = value;
684 update();
685 emit modified();
689 void ModulePanel::onMultiProtocolChanged(int index)
691 if (!lock) {
692 lock=true;
693 module.multi.rfProtocol = (unsigned int) index;
694 unsigned int maxSubTypes = multiProtocols.getProtocol(index).numSubytes();
695 if (module.multi.customProto)
696 maxSubTypes=8;
697 module.subType = std::min(module.subType, maxSubTypes -1);
698 update();
699 emit modified();
700 lock = false;
704 void ModulePanel::on_optionValue_editingFinished()
706 if (module.multi.optionValue != ui->optionValue->value()) {
707 module.multi.optionValue = ui->optionValue->value();
708 emit modified();
712 void ModulePanel::on_multiSubType_currentIndexChanged(int index)
714 if (!lock) {
715 lock=true;
716 module.subType = index;
717 update();
718 emit modified();
719 lock = false;
723 void ModulePanel::on_autoBind_stateChanged(int state)
725 module.multi.autoBindMode = (state == Qt::Checked);
727 void ModulePanel::on_lowPower_stateChanged(int state)
729 module.multi.lowPowerMode = (state == Qt::Checked);
732 // updtSb (update spin box(es)): 0=none or bitmask of FailsafeValueDisplayTypes
733 void ModulePanel::setChannelFailsafeValue(const int channel, const int value, quint8 updtSb)
735 if (channel < 0 || channel >= CPN_MAX_CHNOUT)
736 return;
738 module.failsafeChannels[channel] = value;
739 double pctVal = divRoundClosest(value * 1000, 1024) / 10.0;
740 // qDebug() << value << pctVal;
742 if (failsafeGroupsMap.contains(channel)) {
743 const ChannelFailsafeWidgetsGroup & grp = failsafeGroupsMap.value(channel);
744 if ((updtSb & FAILSAFE_DISPLAY_PERCENT) && grp.sbPercent) {
745 grp.sbPercent->blockSignals(true);
746 grp.sbPercent->setValue(pctVal);
747 grp.sbPercent->blockSignals(false);
749 if ((updtSb & FAILSAFE_DISPLAY_USEC) && grp.sbUsec) {
750 grp.sbUsec->blockSignals(true);
751 grp.sbUsec->setValue(value);
752 grp.sbUsec->blockSignals(false);
755 if (!lock)
756 emit modified();
759 void ModulePanel::onFailsafeUsecChanged(int value)
761 if (!sender())
762 return;
764 bool ok = false;
765 int channel = sender()->property("index").toInt(&ok);
766 if (ok)
767 setChannelFailsafeValue(channel, value, FAILSAFE_DISPLAY_PERCENT);
770 void ModulePanel::onFailsafePercentChanged(double value)
772 if (!sender())
773 return;
775 bool ok = false;
776 int channel = sender()->property("index").toInt(&ok);
777 if (ok)
778 setChannelFailsafeValue(channel, divRoundClosest(int(value * 1024), 100), FAILSAFE_DISPLAY_USEC);
781 void ModulePanel::onFailsafeComboIndexChanged(int index)
783 if (!sender())
784 return;
786 QComboBox * cb = qobject_cast<QComboBox *>(sender());
788 if (cb && !lock) {
789 lock = true;
790 bool ok = false;
791 int channel = sender()->property("index").toInt(&ok);
792 if (ok) {
793 module.failsafeChannels[channel] = cb->itemData(index).toInt();
794 updateFailsafe(channel);
795 emit modified();
797 lock = false;
801 void ModulePanel::onFailsafesDisplayValueTypeChanged(int type)
803 if (failsafesValueDisplayType != type) {
804 failsafesValueDisplayType = type;
805 foreach (ChannelFailsafeWidgetsGroup grp, failsafeGroupsMap) {
806 if (grp.sbPercent)
807 grp.sbPercent->setVisible(type == FAILSAFE_DISPLAY_PERCENT);
808 if (grp.sbUsec)
809 grp.sbUsec->setVisible(type == FAILSAFE_DISPLAY_USEC);
814 void ModulePanel::onExtendedLimitsToggled()
816 double channelMaxPct = double(model->getChannelsMax());
817 int channelMaxUs = 512 * channelMaxPct / 100 * 2;
818 foreach (ChannelFailsafeWidgetsGroup grp, failsafeGroupsMap) {
819 if (grp.sbPercent)
820 grp.sbPercent->setRange(-channelMaxPct, channelMaxPct);
821 if (grp.sbUsec)
822 grp.sbUsec->setRange(-channelMaxUs, channelMaxUs);
826 void ModulePanel::updateFailsafe(int channel)
828 if (channel >= CPN_MAX_CHNOUT || !failsafeGroupsMap.contains(channel))
829 return;
831 const int failsafeValue = module.failsafeChannels[channel];
832 const ChannelFailsafeWidgetsGroup & grp = failsafeGroupsMap.value(channel);
833 const bool valDisable = (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE);
835 if (grp.combo)
836 grp.combo->setCurrentIndex(grp.combo->findData(valDisable ? failsafeValue : 0));
837 if (grp.sbPercent)
838 grp.sbPercent->setDisabled(valDisable);
839 if (grp.sbUsec)
840 grp.sbUsec->setDisabled(valDisable);
842 if (!valDisable)
843 setChannelFailsafeValue(channel, failsafeValue, (FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC));
846 /******************************************************************************/
848 SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
849 ModelPanel(parent, model, generalSettings, firmware),
850 ui(new Ui::Setup)
852 Board::Type board = firmware->getBoard();
854 lock = true;
856 memset(modules, 0, sizeof(modules));
858 ui->setupUi(this);
860 QRegExp rx(CHAR_FOR_NAMES_REGEX);
861 ui->name->setValidator(new QRegExpValidator(rx, this));
862 ui->name->setMaxLength(firmware->getCapability(ModelName));
864 if (firmware->getCapability(ModelImage)) {
865 QStringList items;
866 items.append("");
867 QString path = g.profile[g.id()].sdPath();
868 path.append("/IMAGES/");
869 QDir qd(path);
870 if (qd.exists()) {
871 QStringList filters;
872 if(IS_HORUS(board)) {
873 filters << "*.bmp" << "*.jpg" << "*.png";
874 foreach ( QString file, qd.entryList(filters, QDir::Files) ) {
875 QFileInfo fi(file);
876 QString temp = fi.fileName();
877 if (!items.contains(temp) && temp.length() <= 6+4) {
878 items.append(temp);
882 else {
883 filters << "*.bmp";
884 foreach (QString file, qd.entryList(filters, QDir::Files)) {
885 QFileInfo fi(file);
886 QString temp = fi.completeBaseName();
887 if (!items.contains(temp) && temp.length() <= 10+4) {
888 items.append(temp);
893 if (!items.contains(model.bitmap)) {
894 items.append(model.bitmap);
896 items.sort();
897 foreach (QString file, items) {
898 ui->image->addItem(file);
899 if (file == model.bitmap) {
900 ui->image->setCurrentIndex(ui->image->count()-1);
901 QString fileName = path;
902 fileName.append(model.bitmap);
903 if (!IS_HORUS(board))
904 fileName.append(".bmp");
905 QImage image(fileName);
906 if (image.isNull() && !IS_HORUS(board)) {
907 fileName = path;
908 fileName.append(model.bitmap);
909 fileName.append(".BMP");
910 image.load(fileName);
912 if (!image.isNull()) {
913 if (IS_HORUS(board)) {
914 ui->imagePreview->setFixedSize(QSize(192, 114));
915 ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(192, 114)));
917 else {
918 ui->imagePreview->setFixedSize(QSize(64, 32));
919 ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(64, 32)));
925 else {
926 ui->image->hide();
927 ui->modelImage_label->hide();
928 ui->imagePreview->hide();
931 QWidget * prevFocus = ui->image;
932 for (int i=0; i<CPN_MAX_TIMERS; i++) {
933 if (i<firmware->getCapability(Timers)) {
934 timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus);
935 ui->gridLayout->addWidget(timers[i], 1+i, 1);
936 connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
937 prevFocus = timers[i]->getLastFocus();
939 else {
940 foreach(QLabel *label, findChildren<QLabel *>(QRegExp(QString("label_timer%1").arg(i+1)))) {
941 label->hide();
946 if (firmware->getCapability(HasTopLcd)) {
947 ui->toplcdTimer->setField(model.toplcdTimer, this);
948 for (int i=0; i<CPN_MAX_TIMERS; i++) {
949 if (i<firmware->getCapability(Timers)) {
950 ui->toplcdTimer->addItem(tr("Timer %1").arg(i+1), i);
954 else {
955 ui->toplcdTimerLabel->hide();
956 ui->toplcdTimer->hide();
959 if (!firmware->getCapability(HasDisplayText)) {
960 ui->displayText->hide();
961 ui->editText->hide();
964 if (!firmware->getCapability(GlobalFunctions)) {
965 ui->gfEnabled->hide();
968 // Beep Center checkboxes
969 prevFocus = ui->trimsDisplay;
970 int analogs = CPN_MAX_STICKS + getBoardCapability(board, Board::Pots) + getBoardCapability(board, Board::Sliders);
971 int genAryIdx = 0;
972 for (int i=0; i < analogs + firmware->getCapability(RotaryEncoders); i++) {
973 RawSource src((i < analogs) ? SOURCE_TYPE_STICK : SOURCE_TYPE_ROTARY_ENCODER, (i < analogs) ? i : analogs - i);
974 QCheckBox * checkbox = new QCheckBox(this);
975 checkbox->setProperty("index", i);
976 checkbox->setText(src.toString(&model, &generalSettings));
977 ui->centerBeepLayout->addWidget(checkbox, 0, i+1);
978 connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(onBeepCenterToggled(bool)));
979 centerBeepCheckboxes << checkbox;
980 if (IS_HORUS_OR_TARANIS(board)) {
981 if (src.isPot(&genAryIdx) && !generalSettings.isPotAvailable(genAryIdx)) {
982 checkbox->hide();
984 else if (src.isSlider(&genAryIdx) && !generalSettings.isSliderAvailable(genAryIdx)) {
985 checkbox->hide();
988 QWidget::setTabOrder(prevFocus, checkbox);
989 prevFocus = checkbox;
992 // Startup switches warnings
993 for (int i=0; i<getBoardCapability(board, Board::Switches); i++) {
994 Board::SwitchInfo switchInfo = Boards::getSwitchInfo(board, i);
995 switchInfo.config = Board::SwitchType(generalSettings.switchConfig[i]);
996 if (switchInfo.config == Board::SWITCH_NOT_AVAILABLE || switchInfo.config == Board::SWITCH_TOGGLE) {
997 continue;
999 RawSource src(RawSourceType::SOURCE_TYPE_SWITCH, i);
1000 QLabel * label = new QLabel(this);
1001 QSlider * slider = new QSlider(this);
1002 QCheckBox * cb = new QCheckBox(this);
1003 slider->setProperty("index", i);
1004 slider->setOrientation(Qt::Vertical);
1005 slider->setMinimum(0);
1006 slider->setInvertedAppearance(true);
1007 slider->setInvertedControls(true);
1008 slider->setTickPosition(QSlider::TicksBothSides);
1009 slider->setMinimumSize(QSize(30, 50));
1010 slider->setMaximumSize(QSize(50, 50));
1011 slider->setSingleStep(1);
1012 slider->setPageStep(1);
1013 slider->setTickInterval(1);
1014 label->setText(src.toString(&model, &generalSettings));
1015 slider->setMaximum(switchInfo.config == Board::SWITCH_3POS ? 2 : 1);
1016 cb->setProperty("index", i);
1017 ui->switchesStartupLayout->addWidget(label, 0, i+1);
1018 ui->switchesStartupLayout->setAlignment(label, Qt::AlignCenter);
1019 ui->switchesStartupLayout->addWidget(slider, 1, i+1);
1020 ui->switchesStartupLayout->setAlignment(slider, Qt::AlignCenter);
1021 ui->switchesStartupLayout->addWidget(cb, 2, i+1);
1022 ui->switchesStartupLayout->setAlignment(cb, Qt::AlignCenter);
1023 connect(slider, SIGNAL(valueChanged(int)), this, SLOT(startupSwitchEdited(int)));
1024 connect(cb, SIGNAL(toggled(bool)), this, SLOT(startupSwitchToggled(bool)));
1025 startupSwitchesSliders << slider;
1026 startupSwitchesCheckboxes << cb;
1027 QWidget::setTabOrder(prevFocus, slider);
1028 QWidget::setTabOrder(slider, cb);
1029 prevFocus = cb;
1032 // Pot warnings
1033 prevFocus = ui->potWarningMode;
1034 if (IS_HORUS_OR_TARANIS(board)) {
1035 for (int i=0; i<getBoardCapability(board, Board::Pots)+getBoardCapability(board, Board::Sliders); i++) {
1036 RawSource src(SOURCE_TYPE_STICK, CPN_MAX_STICKS + i);
1037 QCheckBox * cb = new QCheckBox(this);
1038 cb->setProperty("index", i);
1039 cb->setText(src.toString(&model, &generalSettings));
1040 ui->potWarningLayout->addWidget(cb, 0, i+1);
1041 connect(cb, SIGNAL(toggled(bool)), this, SLOT(potWarningToggled(bool)));
1042 potWarningCheckboxes << cb;
1043 if (src.isPot(&genAryIdx) && !generalSettings.isPotAvailable(genAryIdx)) {
1044 cb->hide();
1046 else if (src.isSlider(&genAryIdx) && !generalSettings.isSliderAvailable(genAryIdx)) {
1047 cb->hide();
1049 QWidget::setTabOrder(prevFocus, cb);
1050 prevFocus = cb;
1053 else {
1054 ui->label_potWarning->hide();
1055 ui->potWarningMode->hide();
1058 if (IS_ARM(board)) {
1059 ui->trimsDisplay->setField(model.trimsDisplay, this);
1061 else {
1062 ui->labelTrimsDisplay->hide();
1063 ui->trimsDisplay->hide();
1066 for (int i=0; i<firmware->getCapability(NumModules); i++) {
1067 modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
1068 ui->modulesLayout->addWidget(modules[i]);
1069 connect(modules[i], &ModulePanel::modified, this, &SetupPanel::modified);
1070 connect(this, &SetupPanel::extendedLimitsToggled, modules[i], &ModulePanel::onExtendedLimitsToggled);
1073 if (firmware->getCapability(ModelTrainerEnable)) {
1074 modules[CPN_MAX_MODULES] = new ModulePanel(this, model, model.moduleData[CPN_MAX_MODULES], generalSettings, firmware, -1);
1075 ui->modulesLayout->addWidget(modules[CPN_MAX_MODULES]);
1076 connect(modules[CPN_MAX_MODULES], &ModulePanel::modified, this, &SetupPanel::modified);
1079 disableMouseScrolling();
1081 lock = false;
1084 SetupPanel::~SetupPanel()
1086 delete ui;
1089 void SetupPanel::on_extendedLimits_toggled(bool checked)
1091 model->extendedLimits = checked;
1092 emit extendedLimitsToggled();
1093 emit modified();
1096 void SetupPanel::on_throttleWarning_toggled(bool checked)
1098 model->disableThrottleWarning = !checked;
1099 emit modified();
1102 void SetupPanel::on_throttleReverse_toggled(bool checked)
1104 model->throttleReversed = checked;
1105 emit modified();
1108 void SetupPanel::on_extendedTrims_toggled(bool checked)
1110 model->extendedTrims = checked;
1111 emit modified();
1114 void SetupPanel::on_trimIncrement_currentIndexChanged(int index)
1116 model->trimInc = index-2;
1117 emit modified();
1120 void SetupPanel::on_throttleSource_currentIndexChanged(int index)
1122 if (!lock) {
1123 model->thrTraceSrc = index;
1124 emit modified();
1128 void SetupPanel::on_name_editingFinished()
1130 if (QString(model->name) != ui->name->text()) {
1131 int length = ui->name->maxLength();
1132 strncpy(model->name, ui->name->text().toLatin1(), length);
1133 emit modified();
1137 void SetupPanel::on_image_currentIndexChanged(int index)
1139 if (!lock) {
1140 Board::Type board = firmware->getBoard();
1141 strncpy(model->bitmap, ui->image->currentText().toLatin1(), 10);
1142 QString path = g.profile[g.id()].sdPath();
1143 path.append("/IMAGES/");
1144 QDir qd(path);
1145 if (qd.exists()) {
1146 QString fileName=path;
1147 fileName.append(model->bitmap);
1148 if (!IS_HORUS(board))
1149 fileName.append(".bmp");
1150 QImage image(fileName);
1151 if (image.isNull() && !IS_HORUS(board)) {
1152 fileName=path;
1153 fileName.append(model->bitmap);
1154 fileName.append(".BMP");
1155 image.load(fileName);
1157 if (!image.isNull()) {
1158 if (IS_HORUS(board)) {
1159 ui->imagePreview->setFixedSize(QSize(192, 114));
1160 ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(192, 114)));
1162 else {
1163 ui->imagePreview->setFixedSize(QSize(64, 32));
1164 ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(64, 32)));
1167 else {
1168 ui->imagePreview->clear();
1171 else {
1172 ui->imagePreview->clear();
1174 emit modified();
1178 void SetupPanel::populateThrottleSourceCB()
1180 Board::Type board = firmware->getBoard();
1181 lock = true;
1182 ui->throttleSource->clear();
1183 ui->throttleSource->addItem(tr("THR"));
1184 for (int i=0; i<getBoardCapability(board, Board::Pots)+getBoardCapability(board, Board::Sliders); i++) {
1185 ui->throttleSource->addItem(firmware->getAnalogInputName(4+i), i);
1187 for (int i=0; i<firmware->getCapability(Outputs); i++) {
1188 ui->throttleSource->addItem(RawSource(SOURCE_TYPE_CH, i).toString(model, &generalSettings));
1190 ui->throttleSource->setCurrentIndex(model->thrTraceSrc);
1191 lock = false;
1194 void SetupPanel::update()
1196 ui->name->setText(model->name);
1197 ui->throttleReverse->setChecked(model->throttleReversed);
1198 populateThrottleSourceCB();
1199 ui->throttleWarning->setChecked(!model->disableThrottleWarning);
1200 ui->trimIncrement->setCurrentIndex(model->trimInc+2);
1201 ui->throttleTrim->setChecked(model->thrTrim);
1202 ui->extendedLimits->setChecked(model->extendedLimits);
1203 ui->extendedTrims->setChecked(model->extendedTrims);
1204 ui->displayText->setChecked(model->displayChecklist);
1205 ui->gfEnabled->setChecked(!model->noGlobalFunctions);
1207 updateBeepCenter();
1208 updateStartupSwitches();
1210 if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
1211 updatePotWarnings();
1214 for (int i=0; i<firmware->getCapability(Timers); i++) {
1215 timers[i]->update();
1218 for (int i=0; i<CPN_MAX_MODULES+1; i++) {
1219 if (modules[i]) {
1220 modules[i]->update();
1225 void SetupPanel::updateBeepCenter()
1227 for (int i=0; i<centerBeepCheckboxes.size(); i++) {
1228 centerBeepCheckboxes[i]->setChecked(model->beepANACenter & (0x01 << i));
1232 void SetupPanel::updateStartupSwitches()
1234 lock = true;
1236 uint64_t switchStates = model->switchWarningStates;
1237 uint64_t value;
1239 for (int i=0; i<startupSwitchesSliders.size(); i++) {
1240 QSlider * slider = startupSwitchesSliders[i];
1241 QCheckBox * cb = startupSwitchesCheckboxes[i];
1242 int index = slider->property("index").toInt();
1243 bool enabled = !(model->switchWarningEnable & (1 << index));
1244 if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
1245 value = (switchStates >> (2*index)) & 0x03;
1246 if (generalSettings.switchConfig[index] != Board::SWITCH_3POS && value == 2) {
1247 value = 1;
1250 else {
1251 value = (i==0 ? switchStates & 0x3 : switchStates & 0x1);
1252 switchStates >>= (i==0 ? 2 : 1);
1254 slider->setValue(value);
1255 slider->setEnabled(enabled);
1256 cb->setChecked(enabled);
1259 lock = false;
1262 void SetupPanel::startupSwitchEdited(int value)
1264 if (!lock) {
1265 int shift = 0;
1266 uint64_t mask;
1267 int index = sender()->property("index").toInt();
1269 if (IS_HORUS_OR_TARANIS(firmware->getBoard())) {
1270 shift = index * 2;
1271 mask = 0x03ull << shift;
1273 else {
1274 if (index == 0) {
1275 mask = 0x03;
1277 else {
1278 shift = index+1;
1279 mask = 0x01ull << shift;
1283 model->switchWarningStates &= ~mask;
1285 if (IS_HORUS_OR_TARANIS(firmware->getBoard()) && generalSettings.switchConfig[index] != Board::SWITCH_3POS) {
1286 if (value == 1) {
1287 value = 2;
1291 if (value) {
1292 model->switchWarningStates |= ((uint64_t)value << shift);
1295 updateStartupSwitches();
1296 emit modified();
1300 void SetupPanel::startupSwitchToggled(bool checked)
1302 if (!lock) {
1303 int index = sender()->property("index").toInt();
1305 if (checked)
1306 model->switchWarningEnable &= ~(1 << index);
1307 else
1308 model->switchWarningEnable |= (1 << index);
1310 updateStartupSwitches();
1311 emit modified();
1315 void SetupPanel::updatePotWarnings()
1317 lock = true;
1318 ui->potWarningMode->setCurrentIndex(model->potsWarningMode);
1319 for (int i=0; i<potWarningCheckboxes.size(); i++) {
1320 QCheckBox *checkbox = potWarningCheckboxes[i];
1321 int index = checkbox->property("index").toInt();
1322 checkbox->setChecked(!model->potsWarningEnabled[index]);
1323 checkbox->setDisabled(model->potsWarningMode == 0);
1325 lock = false;
1328 void SetupPanel::potWarningToggled(bool checked)
1330 if (!lock) {
1331 int index = sender()->property("index").toInt();
1332 model->potsWarningEnabled[index] = !checked;
1333 updatePotWarnings();
1334 emit modified();
1338 void SetupPanel::on_potWarningMode_currentIndexChanged(int index)
1340 if (!lock) {
1341 model->potsWarningMode = index;
1342 updatePotWarnings();
1343 emit modified();
1347 void SetupPanel::on_displayText_toggled(bool checked)
1349 model->displayChecklist = checked;
1350 emit modified();
1353 void SetupPanel::on_gfEnabled_toggled(bool checked)
1355 model->noGlobalFunctions = !checked;
1356 emit modified();
1359 void SetupPanel::on_throttleTrim_toggled(bool checked)
1361 model->thrTrim = checked;
1362 emit modified();
1365 void SetupPanel::onBeepCenterToggled(bool checked)
1367 if (!lock) {
1368 int index = sender()->property("index").toInt();
1369 unsigned int mask = (0x01 << index);
1370 if (checked)
1371 model->beepANACenter |= mask;
1372 else
1373 model->beepANACenter &= ~mask;
1374 emit modified();
1378 void SetupPanel::on_editText_clicked()
1380 ChecklistDialog *g = new ChecklistDialog(this, ui->name->text());
1381 g->exec();