Updated French Translation (#5484)
[opentx.git] / companion / src / apppreferencesdialog.cpp
blob5b5d4fb3a94b2e39b067ecf5f2e98018282cca2d
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 "apppreferencesdialog.h"
22 #include "ui_apppreferencesdialog.h"
23 #include "mainwindow.h"
24 #include "appdata.h"
25 #include "helpers.h"
26 #if defined(JOYSTICKS)
27 #include "joystick.h"
28 #include "joystickdialog.h"
29 #endif
31 AppPreferencesDialog::AppPreferencesDialog(QWidget * parent) :
32 QDialog(parent),
33 ui(new Ui::AppPreferencesDialog)
35 ui->setupUi(this);
36 updateLock=false;
37 setWindowIcon(CompanionIcon("apppreferences.png"));
39 initSettings();
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();
50 ui->label_11->hide();
51 #endif
53 shrink();
56 AppPreferencesDialog::~AppPreferencesDialog()
58 delete ui;
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());
86 else {
87 g.jsSupport(false);
88 g.jsCtrl(0);
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"));
102 else
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?
138 #endif
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());
165 else {
166 ui->backupEnable->setDisabled(true);
169 else {
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);
188 if ( joystick ) {
189 if ( joystick->joystickNames.count() > 0 ) {
190 joystickNames = joystick->joystickNames;
191 ui->joystickCB->setEnabled(true);
192 ui->joystickcalButton->setEnabled(true);
194 joystick->close();
196 ui->joystickCB->clear();
197 ui->joystickCB->insertItems(0, joystickNames);
198 ui->joystickCB->setCurrentIndex(g.jsCtrl());
200 else {
201 ui->joystickCB->clear();
202 ui->joystickCB->setDisabled(true);
203 ui->joystickcalButton->setDisabled(true);
205 #endif
206 // Profile Tab Inits
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());
216 } else {
217 ui->pbackupEnable->setDisabled(true);
220 else {
221 ui->pbackupEnable->setDisabled(true);
224 ui->profileNameLE->setText(g.profile[g.id()].name());
226 QString hwSettings;
227 if (g.profile[g.id()].stickPotCalib() == "" ) {
228 hwSettings = tr("EMPTY: No radio settings stored in profile");
230 else {
231 QString str = g.profile[g.id()].timeStamp();
232 if (str.isEmpty())
233 hwSettings = tr("AVAILABLE: Radio settings of unknown age");
234 else
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()) {
254 g.libDir(fileName);
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);
266 else {
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);
319 if ( joystick ) {
320 if ( joystick->joystickNames.count() > 0 ) {
321 joystickNames = joystick->joystickNames;
322 ui->joystickCB->setEnabled(true);
323 ui->joystickcalButton->setEnabled(true);
325 joystick->close();
327 ui->joystickCB->clear();
328 ui->joystickCB->insertItems(0, joystickNames);
330 else {
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());
339 jd->exec();
341 #endif
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())
359 return false;
361 QImage image(fileName);
362 if (image.isNull())
363 return false;
365 ui->imageLabel->setPixmap(makePixMap(image));
366 ui->imageLabel->setFixedSize(getCurrentFirmware()->getCapability(LcdWidth), getCurrentFirmware()->getCapability(LcdHeight));
367 return true;
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);
408 break;
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());
445 if (cb == voice) {
446 showVoice(voice->isChecked());
448 Firmware * firmware=NULL;
449 if (cb && state) {
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);
465 return;
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();
486 updateLock = true;
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
499 int index = 0;
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)));
508 if (prevFocus) {
509 QWidget::setTabOrder(prevFocus, checkbox);
513 QCheckBox *cb = optionsCheckBoxes.at(index++);
514 if (cb) {
515 cb->show();
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")) {
520 voice = cb;
522 prevFocus = cb;
527 for (; index<optionsCheckBoxes.size(); index++) {
528 QCheckBox *cb = optionsCheckBoxes.at(index);
529 cb->hide();
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("");
549 else {
550 ui->widget_splashImage->show();
551 ui->SplashFileName->setText(g.profile[g.id()].splashFile());
552 displayImage(g.profile[g.id()].splashFile());
555 updateLock = false;
556 QTimer::singleShot(50, this, SLOT(shrink()));
559 void AppPreferencesDialog::shrink()
561 adjustSize();