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 "apppreferencesdialog.h"
22 #include "ui_apppreferencesdialog.h"
23 #include "mainwindow.h"
26 #include "firmwareinterface.h"
29 #include "joystickdialog.h"
31 #include <QDesktopServices>
34 AppPreferencesDialog::AppPreferencesDialog(QWidget
* parent
) :
36 ui(new Ui::AppPreferencesDialog
)
40 setWindowIcon(CompanionIcon("apppreferences.png"));
43 connect(ui
->downloadVerCB
, SIGNAL(currentIndexChanged(int)), this, SLOT(baseFirmwareChanged()));
44 connect(ui
->opt_appDebugLog
, &QCheckBox::toggled
, this, &AppPreferencesDialog::toggleAppLogSettings
);
45 connect(ui
->opt_fwTraceLog
, &QCheckBox::toggled
, this, &AppPreferencesDialog::toggleAppLogSettings
);
46 connect(this, SIGNAL(accepted()), this, SLOT(writeValues()));
48 #if !defined(JOYSTICKS)
49 ui
->joystickCB
->hide();
50 ui
->joystickCB
->setDisabled(true);
51 ui
->joystickcalButton
->hide();
52 ui
->joystickChkB
->hide();
59 AppPreferencesDialog::~AppPreferencesDialog()
64 void AppPreferencesDialog::writeValues()
66 g
.useCompanionNightlyBuilds(ui
->useCompanionNightlyBuilds
->isChecked());
67 g
.autoCheckApp(ui
->autoCheckCompanion
->isChecked());
68 g
.useFirmwareNightlyBuilds(ui
->useFirmwareNightlyBuilds
->isChecked());
69 g
.autoCheckFw(ui
->autoCheckFirmware
->isChecked());
70 g
.showSplash(ui
->showSplash
->isChecked());
71 g
.simuSW(ui
->simuSW
->isChecked());
72 g
.removeModelSlots(ui
->opt_removeBlankSlots
->isChecked());
73 g
.newModelAction(ui
->opt_newMdl_useWizard
->isChecked() ? 1 : ui
->opt_newMdl_useEditor
->isChecked() ? 2 : 0);
74 g
.historySize(ui
->historySize
->value());
75 g
.backLight(ui
->backLightColor
->currentIndex());
76 g
.profile
[g
.id()].volumeGain(round(ui
->volumeGain
->value() * 10.0));
77 g
.libDir(ui
->libraryPath
->text());
78 g
.gePath(ui
->ge_lineedit
->text());
79 g
.embedSplashes(ui
->splashincludeCB
->currentIndex());
80 g
.enableBackup(ui
->backupEnable
->isChecked());
82 g
.appDebugLog(ui
->opt_appDebugLog
->isChecked());
83 g
.fwTraceLog(ui
->opt_fwTraceLog
->isChecked());
84 g
.appLogsDir(ui
->appLogsDir
->text());
86 if (ui
->joystickChkB
->isChecked() && ui
->joystickCB
->isEnabled()) {
87 g
.jsSupport(ui
->joystickChkB
->isChecked());
88 g
.jsCtrl(ui
->joystickCB
->currentIndex());
94 g
.profile
[g
.id()].channelOrder(ui
->channelorderCB
->currentIndex());
95 g
.profile
[g
.id()].defaultMode(ui
->stickmodeCB
->currentIndex());
96 g
.profile
[g
.id()].renameFwFiles(ui
->renameFirmware
->isChecked());
97 g
.profile
[g
.id()].burnFirmware(ui
->burnFirmware
->isChecked());
98 g
.profile
[g
.id()].sdPath(ui
->sdPath
->text());
99 g
.profile
[g
.id()].pBackupDir(ui
->profilebackupPath
->text());
100 g
.profile
[g
.id()].penableBackup(ui
->pbackupEnable
->isChecked());
101 g
.profile
[g
.id()].splashFile(ui
->SplashFileName
->text());
103 // The profile name may NEVER be empty
104 if (ui
->profileNameLE
->text().isEmpty())
105 g
.profile
[g
.id()].name(tr("My Radio"));
107 g
.profile
[g
.id()].name(ui
->profileNameLE
->text());
109 // If a new fw type has been choosen, several things need to reset
110 Firmware::setCurrentVariant(getFirmwareVariant());
111 QString id
= Firmware::getCurrentVariant()->getId();
112 if (g
.profile
[g
.id()].fwType() != id
) {
113 g
.profile
[g
.id()].fwName("");
114 g
.profile
[g
.id()].initFwVariables();
115 g
.profile
[g
.id()].fwType(id
);
116 emit
firmwareProfileChanged(g
.id());
120 void AppPreferencesDialog::on_snapshotPathButton_clicked()
122 QString fileName
= QFileDialog::getExistingDirectory(this, tr("Select your snapshot folder"), g
.snapshotDir());
123 if (!fileName
.isEmpty()) {
124 g
.snapshotDir(fileName
);
125 g
.snapToClpbrd(false);
126 ui
->snapshotPath
->setText(fileName
);
130 void AppPreferencesDialog::initSettings()
132 ui
->snapshotClipboardCKB
->setChecked(g
.snapToClpbrd());
133 ui
->burnFirmware
->setChecked(g
.profile
[g
.id()].burnFirmware());
134 ui
->snapshotPath
->setText(g
.snapshotDir());
135 ui
->snapshotPath
->setReadOnly(true);
136 if (ui
->snapshotClipboardCKB
->isChecked()) {
137 ui
->snapshotPath
->setDisabled(true);
138 ui
->snapshotPathButton
->setDisabled(true);
140 #if defined(ALLOW_NIGHTLY_BUILDS)
141 ui
->useCompanionNightlyBuilds
->setChecked(g
.useCompanionNightlyBuilds());
142 ui
->useFirmwareNightlyBuilds
->setChecked(g
.useFirmwareNightlyBuilds());
144 ui
->useCompanionNightlyBuilds
->hide();
145 ui
->useFirmwareNightlyBuilds
->hide();
147 ui
->autoCheckCompanion
->setChecked(g
.autoCheckApp());
148 ui
->autoCheckFirmware
->setChecked(g
.autoCheckFw());
149 ui
->showSplash
->setChecked(g
.showSplash());
150 ui
->historySize
->setValue(g
.historySize());
151 ui
->backLightColor
->setCurrentIndex(g
.backLight());
152 ui
->volumeGain
->setValue(g
.profile
[g
.id()].volumeGain() / 10.0);
154 if (IS_TARANIS(getCurrentBoard())) {
155 ui
->backLightColor
->setEnabled(false);
158 ui
->simuSW
->setChecked(g
.simuSW());
159 ui
->opt_removeBlankSlots
->setChecked(g
.removeModelSlots());
160 ui
->opt_newMdl_useNone
->setChecked(g
.newModelAction() == 0);
161 ui
->opt_newMdl_useWizard
->setChecked(g
.newModelAction() == 1);
162 ui
->opt_newMdl_useEditor
->setChecked(g
.newModelAction() == 2);
163 ui
->libraryPath
->setText(g
.libDir());
164 ui
->ge_lineedit
->setText(g
.gePath());
166 if (!g
.backupDir().isEmpty()) {
167 if (QDir(g
.backupDir()).exists()) {
168 ui
->backupPath
->setText(g
.backupDir());
169 ui
->backupEnable
->setEnabled(true);
170 ui
->backupEnable
->setChecked(g
.enableBackup());
173 ui
->backupEnable
->setDisabled(true);
177 ui
->backupEnable
->setDisabled(true);
179 ui
->splashincludeCB
->setCurrentIndex(g
.embedSplashes());
181 ui
->opt_appDebugLog
->setChecked(g
.appDebugLog());
182 ui
->opt_fwTraceLog
->setChecked(g
.fwTraceLog());
183 ui
->appLogsDir
->setText(g
.appLogsDir());
184 toggleAppLogSettings();
186 #if defined(JOYSTICKS)
187 ui
->joystickChkB
->setChecked(g
.jsSupport());
188 if (ui
->joystickChkB
->isChecked()) {
189 QStringList joystickNames
;
190 joystickNames
<< tr("No joysticks found");
191 joystick
= new Joystick(0,false,0,0);
192 ui
->joystickcalButton
->setDisabled(true);
193 ui
->joystickCB
->setDisabled(true);
196 if ( joystick
->joystickNames
.count() > 0 ) {
197 joystickNames
= joystick
->joystickNames
;
198 ui
->joystickCB
->setEnabled(true);
199 ui
->joystickcalButton
->setEnabled(true);
203 ui
->joystickCB
->clear();
204 ui
->joystickCB
->insertItems(0, joystickNames
);
205 ui
->joystickCB
->setCurrentIndex(g
.jsCtrl());
208 ui
->joystickCB
->clear();
209 ui
->joystickCB
->setDisabled(true);
210 ui
->joystickcalButton
->setDisabled(true);
214 ui
->channelorderCB
->setCurrentIndex(g
.profile
[g
.id()].channelOrder());
215 ui
->stickmodeCB
->setCurrentIndex(g
.profile
[g
.id()].defaultMode());
216 ui
->renameFirmware
->setChecked(g
.profile
[g
.id()].renameFwFiles());
217 ui
->sdPath
->setText(g
.profile
[g
.id()].sdPath());
218 if (!g
.profile
[g
.id()].pBackupDir().isEmpty()) {
219 if (QDir(g
.profile
[g
.id()].pBackupDir()).exists()) {
220 ui
->profilebackupPath
->setText(g
.profile
[g
.id()].pBackupDir());
221 ui
->pbackupEnable
->setEnabled(true);
222 ui
->pbackupEnable
->setChecked(g
.profile
[g
.id()].penableBackup());
224 ui
->pbackupEnable
->setDisabled(true);
228 ui
->pbackupEnable
->setDisabled(true);
231 ui
->profileNameLE
->setText(g
.profile
[g
.id()].name());
234 if (g
.profile
[g
.id()].stickPotCalib() == "" ) {
235 hwSettings
= tr("EMPTY: No radio settings stored in profile");
238 QString str
= g
.profile
[g
.id()].timeStamp();
240 hwSettings
= tr("AVAILABLE: Radio settings of unknown age");
242 hwSettings
= tr("AVAILABLE: Radio settings stored %1").arg(str
);
244 ui
->lblGeneralSettings
->setText(hwSettings
);
246 QString currType
= QStringList(g
.profile
[g
.id()].fwType().split('-').mid(0, 2)).join('-');
247 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
248 ui
->downloadVerCB
->addItem(firmware
->getName(), firmware
->getId());
249 if (currType
== firmware
->getId()) {
250 ui
->downloadVerCB
->setCurrentIndex(ui
->downloadVerCB
->count() - 1);
254 baseFirmwareChanged();
257 void AppPreferencesDialog::on_libraryPathButton_clicked()
259 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your library folder"), g
.libDir());
260 if (!fileName
.isEmpty()) {
262 ui
->libraryPath
->setText(fileName
);
266 void AppPreferencesDialog::on_snapshotClipboardCKB_clicked()
268 if (ui
->snapshotClipboardCKB
->isChecked()) {
269 ui
->snapshotPath
->setDisabled(true);
270 ui
->snapshotPathButton
->setDisabled(true);
271 g
.snapToClpbrd(true);
274 ui
->snapshotPath
->setEnabled(true);
275 ui
->snapshotPath
->setReadOnly(true);
276 ui
->snapshotPathButton
->setEnabled(true);
277 g
.snapToClpbrd(false);
281 void AppPreferencesDialog::on_backupPathButton_clicked()
283 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g
.backupDir());
284 if (!fileName
.isEmpty()) {
285 g
.backupDir(fileName
);
286 ui
->backupPath
->setText(fileName
);
287 ui
->backupEnable
->setEnabled(true);
291 void AppPreferencesDialog::on_ProfilebackupPathButton_clicked()
293 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g
.backupDir());
294 if (!fileName
.isEmpty()) {
295 ui
->profilebackupPath
->setText(fileName
);
296 ui
->pbackupEnable
->setEnabled(true);
301 void AppPreferencesDialog::on_btn_appLogsDir_clicked()
303 QString fileName
= QFileDialog::getExistingDirectory(this, tr("Select a folder for application logs"), ui
->appLogsDir
->text());
304 if (!fileName
.isEmpty()) {
305 ui
->appLogsDir
->setText(fileName
);
309 void AppPreferencesDialog::on_ge_pathButton_clicked()
311 QString fileName
= QFileDialog::getOpenFileName(this, tr("Select Google Earth executable"),ui
->ge_lineedit
->text());
312 if (!fileName
.isEmpty()) {
313 ui
->ge_lineedit
->setText(fileName
);
317 #if defined(JOYSTICKS)
318 void AppPreferencesDialog::on_joystickChkB_clicked() {
319 if (ui
->joystickChkB
->isChecked()) {
320 QStringList joystickNames
;
321 joystickNames
<< tr("No joysticks found");
322 joystick
= new Joystick(0,false,0,0);
323 ui
->joystickcalButton
->setDisabled(true);
324 ui
->joystickCB
->setDisabled(true);
327 if ( joystick
->joystickNames
.count() > 0 ) {
328 joystickNames
= joystick
->joystickNames
;
329 ui
->joystickCB
->setEnabled(true);
330 ui
->joystickcalButton
->setEnabled(true);
334 ui
->joystickCB
->clear();
335 ui
->joystickCB
->insertItems(0, joystickNames
);
338 ui
->joystickCB
->clear();
339 ui
->joystickCB
->setDisabled(true);
340 ui
->joystickcalButton
->setDisabled(true);
344 void AppPreferencesDialog::on_joystickcalButton_clicked() {
345 joystickDialog
* jd
=new joystickDialog(this, ui
->joystickCB
->currentIndex());
350 // ******** Profile tab functions
352 void AppPreferencesDialog::on_sdPathButton_clicked()
354 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g
.profile
[g
.id()].sdPath());
355 if (!fileName
.isEmpty()) {
356 ui
->sdPath
->setText(fileName
);
360 bool AppPreferencesDialog::displayImage(const QString
& fileName
)
362 // Start by clearing the label
363 ui
->imageLabel
->clear();
365 if (fileName
.isEmpty())
368 QImage
image(fileName
);
372 ui
->imageLabel
->setPixmap(makePixMap(image
));
373 ui
->imageLabel
->setFixedSize(getCurrentFirmware()->getCapability(LcdWidth
), getCurrentFirmware()->getCapability(LcdHeight
));
377 void AppPreferencesDialog::on_SplashSelect_clicked()
379 QString supportedImageFormats
;
380 for (int formatIndex
= 0; formatIndex
< QImageReader::supportedImageFormats().count(); formatIndex
++) {
381 supportedImageFormats
+= QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex
];
384 QString fileName
= QFileDialog::getOpenFileName(this,
385 tr("Open Image to load"), g
.imagesDir(), tr("Images (%1)").arg(supportedImageFormats
));
387 if (!fileName
.isEmpty()){
388 g
.imagesDir(QFileInfo(fileName
).dir().absolutePath());
390 displayImage(fileName
);
391 ui
->SplashFileName
->setText(fileName
);
395 void AppPreferencesDialog::on_clearImageButton_clicked()
397 ui
->imageLabel
->clear();
398 ui
->SplashFileName
->clear();
402 void AppPreferencesDialog::showVoice(bool show
)
404 ui
->voiceLabel
->setVisible(show
);
405 ui
->voiceCombo
->setVisible(show
);
408 void AppPreferencesDialog::baseFirmwareChanged()
410 QString selected_firmware
= ui
->downloadVerCB
->currentData().toString();
412 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
413 if (firmware
->getId() == selected_firmware
) {
414 populateFirmwareOptions(firmware
);
420 Firmware
* AppPreferencesDialog::getFirmwareVariant()
422 QString selected_firmware
= ui
->downloadVerCB
->currentData().toString();
424 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
425 QString id
= firmware
->getId();
426 if (id
== selected_firmware
) {
427 foreach(QCheckBox
*cb
, optionsCheckBoxes
) {
428 if (cb
->isChecked()) {
429 id
+= "-" + cb
->text();
433 if (voice
&& voice
->isChecked()) {
434 id
+= "-tts" + ui
->voiceCombo
->currentText();
437 if (ui
->langCombo
->count()) {
438 id
+= "-" + ui
->langCombo
->currentText();
441 return Firmware::getFirmwareForId(id
);
445 // Should never occur...
446 return Firmware::getDefaultVariant();
449 void AppPreferencesDialog::firmwareOptionChanged(bool state
)
451 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(sender());
453 showVoice(voice
->isChecked());
455 Firmware
* firmware
=NULL
;
457 QVariant selected_firmware
= ui
->downloadVerCB
->currentData();
458 foreach(firmware
, Firmware::getRegisteredFirmwares()) {
459 if (firmware
->getId() == selected_firmware
) {
460 foreach(QList
<Option
> opts
, firmware
->opts
) {
461 foreach(Option opt
, opts
) {
462 if (cb
->text() == opt
.name
) {
463 foreach(Option other
, opts
) {
464 if (other
.name
!= opt
.name
) {
465 foreach(QCheckBox
*ocb
, optionsCheckBoxes
) {
466 if (ocb
->text() == other
.name
) {
467 ocb
->setChecked(false);
481 void AppPreferencesDialog::toggleAppLogSettings()
483 bool vis
= (ui
->opt_appDebugLog
->isChecked() || ui
->opt_fwTraceLog
->isChecked());
484 ui
->appLogsDir
->setVisible(vis
);
485 ui
->lbl_appLogsDir
->setVisible(vis
);
486 ui
->btn_appLogsDir
->setVisible(vis
);
489 void AppPreferencesDialog::populateFirmwareOptions(const Firmware
* firmware
)
491 const Firmware
* parent
= firmware
->getFirmwareBase();
495 QString id
= Firmware::getCurrentVariant()->getId();
496 ui
->langCombo
->clear();
497 foreach(const char *lang
, parent
->languages
) {
498 ui
->langCombo
->addItem(lang
);
499 if (id
.endsWith(lang
)) {
500 ui
->langCombo
->setCurrentIndex(ui
->langCombo
->count() - 1);
504 voice
= NULL
; // we will search for a voice checkbox
507 QWidget
* prevFocus
= ui
->voiceCombo
;
508 foreach(QList
<Option
> opts
, parent
->opts
) {
509 foreach(Option opt
, opts
) {
510 if (index
>= optionsCheckBoxes
.size()) {
511 QCheckBox
* checkbox
= new QCheckBox(ui
->profileTab
);
512 ui
->optionsLayout
->addWidget(checkbox
, optionsCheckBoxes
.count()/4, optionsCheckBoxes
.count()%4, 1, 1);
513 optionsCheckBoxes
.push_back(checkbox
);
514 connect(checkbox
, SIGNAL(toggled(bool)), this, SLOT(firmwareOptionChanged(bool)));
516 QWidget::setTabOrder(prevFocus
, checkbox
);
520 QCheckBox
*cb
= optionsCheckBoxes
.at(index
++);
523 cb
->setText(opt
.name
);
524 cb
->setToolTip(opt
.tooltip
);
525 cb
->setCheckState(id
.contains(opt
.name
) ? Qt::Checked
: Qt::Unchecked
);
526 if (opt
.name
== QString("voice")) {
534 for (; index
<optionsCheckBoxes
.size(); index
++) {
535 QCheckBox
*cb
= optionsCheckBoxes
.at(index
);
537 cb
->setCheckState(Qt::Unchecked
);
540 ui
->voiceCombo
->clear();
541 foreach(const char *lang
, parent
->ttslanguages
) {
542 ui
->voiceCombo
->addItem(lang
);
543 if (id
.contains(QString("-tts%1").arg(lang
))) {
544 ui
->voiceCombo
->setCurrentIndex(ui
->voiceCombo
->count() - 1);
548 showVoice(voice
&& voice
->isChecked());
550 // TODO: Remove once splash replacement supported on Horus
551 // NOTE: 480x272 image causes issues on screens <800px high, needs a solution like scrolling once reinstated
552 if (IS_HORUS(parent
->getBoard())) {
553 ui
->widget_splashImage
->hide();
554 ui
->SplashFileName
->setText("");
557 ui
->widget_splashImage
->show();
558 ui
->SplashFileName
->setText(g
.profile
[g
.id()].splashFile());
559 displayImage(g
.profile
[g
.id()].splashFile());
563 QTimer::singleShot(50, this, SLOT(shrink()));
566 void AppPreferencesDialog::shrink()