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 #if defined(JOYSTICKS)
28 #include "joystickdialog.h"
31 AppPreferencesDialog::AppPreferencesDialog(QWidget
* parent
) :
33 ui(new Ui::AppPreferencesDialog
)
37 setWindowIcon(CompanionIcon("apppreferences.png"));
40 connect(ui
->downloadVerCB
, SIGNAL(currentIndexChanged(int)), this, SLOT(baseFirmwareChanged()));
41 connect(ui
->opt_appDebugLog
, &QCheckBox::toggled
, this, &AppPreferencesDialog::toggleAppLogSettings
);
42 connect(ui
->opt_fwTraceLog
, &QCheckBox::toggled
, this, &AppPreferencesDialog::toggleAppLogSettings
);
43 connect(this, SIGNAL(accepted()), this, SLOT(writeValues()));
45 #if !defined(JOYSTICKS)
46 ui
->joystickCB
->hide();
47 ui
->joystickCB
->setDisabled(true);
48 ui
->joystickcalButton
->hide();
49 ui
->joystickChkB
->hide();
56 AppPreferencesDialog::~AppPreferencesDialog()
61 void AppPreferencesDialog::writeValues()
63 g
.autoCheckApp(ui
->autoCheckCompanion
->isChecked());
64 g
.OpenTxBranch(DownloadBranchType(ui
->OpenTxBranch
->currentIndex()));
65 g
.autoCheckFw(ui
->autoCheckFirmware
->isChecked());
66 g
.showSplash(ui
->showSplash
->isChecked());
67 g
.simuSW(ui
->simuSW
->isChecked());
68 g
.removeModelSlots(ui
->opt_removeBlankSlots
->isChecked());
69 g
.newModelAction(ui
->opt_newMdl_useWizard
->isChecked() ? 1 : ui
->opt_newMdl_useEditor
->isChecked() ? 2 : 0);
70 g
.historySize(ui
->historySize
->value());
71 g
.backLight(ui
->backLightColor
->currentIndex());
72 g
.profile
[g
.id()].volumeGain(round(ui
->volumeGain
->value() * 10.0));
73 g
.libDir(ui
->libraryPath
->text());
74 g
.gePath(ui
->ge_lineedit
->text());
75 g
.embedSplashes(ui
->splashincludeCB
->currentIndex());
76 g
.enableBackup(ui
->backupEnable
->isChecked());
78 g
.appDebugLog(ui
->opt_appDebugLog
->isChecked());
79 g
.fwTraceLog(ui
->opt_fwTraceLog
->isChecked());
80 g
.appLogsDir(ui
->appLogsDir
->text());
82 if (ui
->joystickChkB
->isChecked() && ui
->joystickCB
->isEnabled()) {
83 g
.jsSupport(ui
->joystickChkB
->isChecked());
84 g
.jsCtrl(ui
->joystickCB
->currentIndex());
90 g
.profile
[g
.id()].channelOrder(ui
->channelorderCB
->currentIndex());
91 g
.profile
[g
.id()].defaultMode(ui
->stickmodeCB
->currentIndex());
92 g
.profile
[g
.id()].renameFwFiles(ui
->renameFirmware
->isChecked());
93 g
.profile
[g
.id()].burnFirmware(ui
->burnFirmware
->isChecked());
94 g
.profile
[g
.id()].sdPath(ui
->sdPath
->text());
95 g
.profile
[g
.id()].pBackupDir(ui
->profilebackupPath
->text());
96 g
.profile
[g
.id()].penableBackup(ui
->pbackupEnable
->isChecked());
97 g
.profile
[g
.id()].splashFile(ui
->SplashFileName
->text());
99 // The profile name may NEVER be empty
100 if (ui
->profileNameLE
->text().isEmpty())
101 g
.profile
[g
.id()].name(tr("My Radio"));
103 g
.profile
[g
.id()].name(ui
->profileNameLE
->text());
105 // If a new fw type has been choosen, several things need to reset
106 Firmware::setCurrentVariant(getFirmwareVariant());
107 QString id
= Firmware::getCurrentVariant()->getId();
108 if (g
.profile
[g
.id()].fwType() != id
) {
109 g
.profile
[g
.id()].fwName("");
110 g
.profile
[g
.id()].initFwVariables();
111 g
.profile
[g
.id()].fwType(id
);
112 emit
firmwareProfileChanged(g
.id());
116 void AppPreferencesDialog::on_snapshotPathButton_clicked()
118 QString fileName
= QFileDialog::getExistingDirectory(this, tr("Select your snapshot folder"), g
.snapshotDir());
119 if (!fileName
.isEmpty()) {
120 g
.snapshotDir(fileName
);
121 g
.snapToClpbrd(false);
122 ui
->snapshotPath
->setText(fileName
);
126 void AppPreferencesDialog::initSettings()
128 ui
->snapshotClipboardCKB
->setChecked(g
.snapToClpbrd());
129 ui
->burnFirmware
->setChecked(g
.profile
[g
.id()].burnFirmware());
130 ui
->snapshotPath
->setText(g
.snapshotDir());
131 ui
->snapshotPath
->setReadOnly(true);
132 if (ui
->snapshotClipboardCKB
->isChecked()) {
133 ui
->snapshotPath
->setDisabled(true);
134 ui
->snapshotPathButton
->setDisabled(true);
136 #if !defined(ALLOW_NIGHTLY_BUILDS)
137 // TODO should we gray out nightly builds here?
139 ui
->OpenTxBranch
->setCurrentIndex(g
.OpenTxBranch());
140 ui
->autoCheckCompanion
->setChecked(g
.autoCheckApp());
141 ui
->autoCheckFirmware
->setChecked(g
.autoCheckFw());
142 ui
->showSplash
->setChecked(g
.showSplash());
143 ui
->historySize
->setValue(g
.historySize());
144 ui
->backLightColor
->setCurrentIndex(g
.backLight());
145 ui
->volumeGain
->setValue(g
.profile
[g
.id()].volumeGain() / 10.0);
147 if (IS_TARANIS(getCurrentBoard())) {
148 ui
->backLightColor
->setEnabled(false);
151 ui
->simuSW
->setChecked(g
.simuSW());
152 ui
->opt_removeBlankSlots
->setChecked(g
.removeModelSlots());
153 ui
->opt_newMdl_useNone
->setChecked(g
.newModelAction() == 0);
154 ui
->opt_newMdl_useWizard
->setChecked(g
.newModelAction() == 1);
155 ui
->opt_newMdl_useEditor
->setChecked(g
.newModelAction() == 2);
156 ui
->libraryPath
->setText(g
.libDir());
157 ui
->ge_lineedit
->setText(g
.gePath());
159 if (!g
.backupDir().isEmpty()) {
160 if (QDir(g
.backupDir()).exists()) {
161 ui
->backupPath
->setText(g
.backupDir());
162 ui
->backupEnable
->setEnabled(true);
163 ui
->backupEnable
->setChecked(g
.enableBackup());
166 ui
->backupEnable
->setDisabled(true);
170 ui
->backupEnable
->setDisabled(true);
172 ui
->splashincludeCB
->setCurrentIndex(g
.embedSplashes());
174 ui
->opt_appDebugLog
->setChecked(g
.appDebugLog());
175 ui
->opt_fwTraceLog
->setChecked(g
.fwTraceLog());
176 ui
->appLogsDir
->setText(g
.appLogsDir());
177 toggleAppLogSettings();
179 #if defined(JOYSTICKS)
180 ui
->joystickChkB
->setChecked(g
.jsSupport());
181 if (ui
->joystickChkB
->isChecked()) {
182 QStringList joystickNames
;
183 joystickNames
<< tr("No joysticks found");
184 joystick
= new Joystick(0,false,0,0);
185 ui
->joystickcalButton
->setDisabled(true);
186 ui
->joystickCB
->setDisabled(true);
189 if ( joystick
->joystickNames
.count() > 0 ) {
190 joystickNames
= joystick
->joystickNames
;
191 ui
->joystickCB
->setEnabled(true);
192 ui
->joystickcalButton
->setEnabled(true);
196 ui
->joystickCB
->clear();
197 ui
->joystickCB
->insertItems(0, joystickNames
);
198 ui
->joystickCB
->setCurrentIndex(g
.jsCtrl());
201 ui
->joystickCB
->clear();
202 ui
->joystickCB
->setDisabled(true);
203 ui
->joystickcalButton
->setDisabled(true);
207 ui
->channelorderCB
->setCurrentIndex(g
.profile
[g
.id()].channelOrder());
208 ui
->stickmodeCB
->setCurrentIndex(g
.profile
[g
.id()].defaultMode());
209 ui
->renameFirmware
->setChecked(g
.profile
[g
.id()].renameFwFiles());
210 ui
->sdPath
->setText(g
.profile
[g
.id()].sdPath());
211 if (!g
.profile
[g
.id()].pBackupDir().isEmpty()) {
212 if (QDir(g
.profile
[g
.id()].pBackupDir()).exists()) {
213 ui
->profilebackupPath
->setText(g
.profile
[g
.id()].pBackupDir());
214 ui
->pbackupEnable
->setEnabled(true);
215 ui
->pbackupEnable
->setChecked(g
.profile
[g
.id()].penableBackup());
217 ui
->pbackupEnable
->setDisabled(true);
221 ui
->pbackupEnable
->setDisabled(true);
224 ui
->profileNameLE
->setText(g
.profile
[g
.id()].name());
227 if (g
.profile
[g
.id()].stickPotCalib() == "" ) {
228 hwSettings
= tr("EMPTY: No radio settings stored in profile");
231 QString str
= g
.profile
[g
.id()].timeStamp();
233 hwSettings
= tr("AVAILABLE: Radio settings of unknown age");
235 hwSettings
= tr("AVAILABLE: Radio settings stored %1").arg(str
);
237 ui
->lblGeneralSettings
->setText(hwSettings
);
239 QString currType
= QStringList(g
.profile
[g
.id()].fwType().split('-').mid(0, 2)).join('-');
240 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
241 ui
->downloadVerCB
->addItem(firmware
->getName(), firmware
->getId());
242 if (currType
== firmware
->getId()) {
243 ui
->downloadVerCB
->setCurrentIndex(ui
->downloadVerCB
->count() - 1);
247 baseFirmwareChanged();
250 void AppPreferencesDialog::on_libraryPathButton_clicked()
252 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your library folder"), g
.libDir());
253 if (!fileName
.isEmpty()) {
255 ui
->libraryPath
->setText(fileName
);
259 void AppPreferencesDialog::on_snapshotClipboardCKB_clicked()
261 if (ui
->snapshotClipboardCKB
->isChecked()) {
262 ui
->snapshotPath
->setDisabled(true);
263 ui
->snapshotPathButton
->setDisabled(true);
264 g
.snapToClpbrd(true);
267 ui
->snapshotPath
->setEnabled(true);
268 ui
->snapshotPath
->setReadOnly(true);
269 ui
->snapshotPathButton
->setEnabled(true);
270 g
.snapToClpbrd(false);
274 void AppPreferencesDialog::on_backupPathButton_clicked()
276 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g
.backupDir());
277 if (!fileName
.isEmpty()) {
278 g
.backupDir(fileName
);
279 ui
->backupPath
->setText(fileName
);
280 ui
->backupEnable
->setEnabled(true);
284 void AppPreferencesDialog::on_ProfilebackupPathButton_clicked()
286 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select your Models and Settings backup folder"), g
.backupDir());
287 if (!fileName
.isEmpty()) {
288 ui
->profilebackupPath
->setText(fileName
);
289 ui
->pbackupEnable
->setEnabled(true);
294 void AppPreferencesDialog::on_btn_appLogsDir_clicked()
296 QString fileName
= QFileDialog::getExistingDirectory(this, tr("Select a folder for application logs"), ui
->appLogsDir
->text());
297 if (!fileName
.isEmpty()) {
298 ui
->appLogsDir
->setText(fileName
);
302 void AppPreferencesDialog::on_ge_pathButton_clicked()
304 QString fileName
= QFileDialog::getOpenFileName(this, tr("Select Google Earth executable"),ui
->ge_lineedit
->text());
305 if (!fileName
.isEmpty()) {
306 ui
->ge_lineedit
->setText(fileName
);
310 #if defined(JOYSTICKS)
311 void AppPreferencesDialog::on_joystickChkB_clicked() {
312 if (ui
->joystickChkB
->isChecked()) {
313 QStringList joystickNames
;
314 joystickNames
<< tr("No joysticks found");
315 joystick
= new Joystick(0,false,0,0);
316 ui
->joystickcalButton
->setDisabled(true);
317 ui
->joystickCB
->setDisabled(true);
320 if ( joystick
->joystickNames
.count() > 0 ) {
321 joystickNames
= joystick
->joystickNames
;
322 ui
->joystickCB
->setEnabled(true);
323 ui
->joystickcalButton
->setEnabled(true);
327 ui
->joystickCB
->clear();
328 ui
->joystickCB
->insertItems(0, joystickNames
);
331 ui
->joystickCB
->clear();
332 ui
->joystickCB
->setDisabled(true);
333 ui
->joystickcalButton
->setDisabled(true);
337 void AppPreferencesDialog::on_joystickcalButton_clicked() {
338 joystickDialog
* jd
=new joystickDialog(this, ui
->joystickCB
->currentIndex());
343 // ******** Profile tab functions
345 void AppPreferencesDialog::on_sdPathButton_clicked()
347 QString fileName
= QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g
.profile
[g
.id()].sdPath());
348 if (!fileName
.isEmpty()) {
349 ui
->sdPath
->setText(fileName
);
353 bool AppPreferencesDialog::displayImage(const QString
& fileName
)
355 // Start by clearing the label
356 ui
->imageLabel
->clear();
358 if (fileName
.isEmpty())
361 QImage
image(fileName
);
365 ui
->imageLabel
->setPixmap(makePixMap(image
));
366 ui
->imageLabel
->setFixedSize(getCurrentFirmware()->getCapability(LcdWidth
), getCurrentFirmware()->getCapability(LcdHeight
));
370 void AppPreferencesDialog::on_SplashSelect_clicked()
372 QString supportedImageFormats
;
373 for (int formatIndex
= 0; formatIndex
< QImageReader::supportedImageFormats().count(); formatIndex
++) {
374 supportedImageFormats
+= QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex
];
377 QString fileName
= QFileDialog::getOpenFileName(this,
378 tr("Open Image to load"), g
.imagesDir(), tr("Images (%1)").arg(supportedImageFormats
));
380 if (!fileName
.isEmpty()){
381 g
.imagesDir(QFileInfo(fileName
).dir().absolutePath());
383 displayImage(fileName
);
384 ui
->SplashFileName
->setText(fileName
);
388 void AppPreferencesDialog::on_clearImageButton_clicked()
390 ui
->imageLabel
->clear();
391 ui
->SplashFileName
->clear();
395 void AppPreferencesDialog::showVoice(bool show
)
397 ui
->voiceLabel
->setVisible(show
);
398 ui
->voiceCombo
->setVisible(show
);
401 void AppPreferencesDialog::baseFirmwareChanged()
403 QString selected_firmware
= ui
->downloadVerCB
->currentData().toString();
405 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
406 if (firmware
->getId() == selected_firmware
) {
407 populateFirmwareOptions(firmware
);
413 Firmware
* AppPreferencesDialog::getFirmwareVariant()
415 QString selected_firmware
= ui
->downloadVerCB
->currentData().toString();
417 foreach(Firmware
* firmware
, Firmware::getRegisteredFirmwares()) {
418 QString id
= firmware
->getId();
419 if (id
== selected_firmware
) {
420 foreach(QCheckBox
*cb
, optionsCheckBoxes
) {
421 if (cb
->isChecked()) {
422 id
+= "-" + cb
->text();
426 if (voice
&& voice
->isChecked()) {
427 id
+= "-tts" + ui
->voiceCombo
->currentText();
430 if (ui
->langCombo
->count()) {
431 id
+= "-" + ui
->langCombo
->currentText();
434 return Firmware::getFirmwareForId(id
);
438 // Should never occur...
439 return Firmware::getDefaultVariant();
442 void AppPreferencesDialog::firmwareOptionChanged(bool state
)
444 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(sender());
446 showVoice(voice
->isChecked());
448 Firmware
* firmware
=NULL
;
450 QVariant selected_firmware
= ui
->downloadVerCB
->currentData();
451 foreach(firmware
, Firmware::getRegisteredFirmwares()) {
452 if (firmware
->getId() == selected_firmware
) {
453 foreach(QList
<Option
> opts
, firmware
->opts
) {
454 foreach(Option opt
, opts
) {
455 if (cb
->text() == opt
.name
) {
456 foreach(Option other
, opts
) {
457 if (other
.name
!= opt
.name
) {
458 foreach(QCheckBox
*ocb
, optionsCheckBoxes
) {
459 if (ocb
->text() == other
.name
) {
460 ocb
->setChecked(false);
474 void AppPreferencesDialog::toggleAppLogSettings()
476 bool vis
= (ui
->opt_appDebugLog
->isChecked() || ui
->opt_fwTraceLog
->isChecked());
477 ui
->appLogsDir
->setVisible(vis
);
478 ui
->lbl_appLogsDir
->setVisible(vis
);
479 ui
->btn_appLogsDir
->setVisible(vis
);
482 void AppPreferencesDialog::populateFirmwareOptions(const Firmware
* firmware
)
484 const Firmware
* parent
= firmware
->getFirmwareBase();
488 QString id
= Firmware::getCurrentVariant()->getId();
489 ui
->langCombo
->clear();
490 foreach(const char *lang
, parent
->languages
) {
491 ui
->langCombo
->addItem(lang
);
492 if (id
.endsWith(lang
)) {
493 ui
->langCombo
->setCurrentIndex(ui
->langCombo
->count() - 1);
497 voice
= NULL
; // we will search for a voice checkbox
500 QWidget
* prevFocus
= ui
->voiceCombo
;
501 foreach(QList
<Option
> opts
, parent
->opts
) {
502 foreach(Option opt
, opts
) {
503 if (index
>= optionsCheckBoxes
.size()) {
504 QCheckBox
* checkbox
= new QCheckBox(ui
->profileTab
);
505 ui
->optionsLayout
->addWidget(checkbox
, optionsCheckBoxes
.count()/4, optionsCheckBoxes
.count()%4, 1, 1);
506 optionsCheckBoxes
.push_back(checkbox
);
507 connect(checkbox
, SIGNAL(toggled(bool)), this, SLOT(firmwareOptionChanged(bool)));
509 QWidget::setTabOrder(prevFocus
, checkbox
);
513 QCheckBox
*cb
= optionsCheckBoxes
.at(index
++);
516 cb
->setText(opt
.name
);
517 cb
->setToolTip(opt
.tooltip
);
518 cb
->setCheckState(id
.contains(opt
.name
) ? Qt::Checked
: Qt::Unchecked
);
519 if (opt
.name
== QString("voice")) {
527 for (; index
<optionsCheckBoxes
.size(); index
++) {
528 QCheckBox
*cb
= optionsCheckBoxes
.at(index
);
530 cb
->setCheckState(Qt::Unchecked
);
533 ui
->voiceCombo
->clear();
534 foreach(const char *lang
, parent
->ttslanguages
) {
535 ui
->voiceCombo
->addItem(lang
);
536 if (id
.contains(QString("-tts%1").arg(lang
))) {
537 ui
->voiceCombo
->setCurrentIndex(ui
->voiceCombo
->count() - 1);
541 showVoice(voice
&& voice
->isChecked());
543 // TODO: Remove once splash replacement supported on Horus
544 // NOTE: 480x272 image causes issues on screens <800px high, needs a solution like scrolling once reinstated
545 if (IS_HORUS(parent
->getBoard())) {
546 ui
->widget_splashImage
->hide();
547 ui
->SplashFileName
->setText("");
550 ui
->widget_splashImage
->show();
551 ui
->SplashFileName
->setText(g
.profile
[g
.id()].splashFile());
552 displayImage(g
.profile
[g
.id()].splashFile());
556 QTimer::singleShot(50, this, SLOT(shrink()));
559 void AppPreferencesDialog::shrink()