feat(cpn): reorganise and refactor Edit Settings (Profile/Application/Simulator/Update) dialog  (#7623)

This commit is contained in:
Neil Horne
2026-09-14 07:38:48 +10:00
committed by GitHub
parent 244aab8919
commit 6ebd3b9834
88 changed files with 5171 additions and 3489 deletions
+2 -1
View File
@@ -207,6 +207,7 @@ add_subdirectory(generaledit)
add_subdirectory(modeledit)
add_subdirectory(print)
add_subdirectory(progress)
add_subdirectory(prefsedit)
add_subdirectory(shared)
add_subdirectory(simulation)
add_subdirectory(storage)
@@ -219,7 +220,6 @@ add_subdirectory(wizard)
include_directories(${maxLibQt_SOURCE_DIR}/widgets)
set(companion_NAMES
apppreferencesdialog
helpers_html
labels
logsdialog
@@ -268,6 +268,7 @@ target_link_libraries(${COMPANION_NAME} PRIVATE
flash
wizard
print
prefsedit
)
PrintTargetReport("${COMPANION_NAME}")
-959
View File
@@ -1,959 +0,0 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "apppreferencesdialog.h"
#include "ui_apppreferencesdialog.h"
#include "mainwindow.h"
#include "helpers.h"
#include "storage.h"
#if defined(USE_SDL)
#include "joystick.h"
#include "joystickdialog.h"
#endif
#include "moduledata.h"
#include "filtereditemmodels.h"
#include "updates/updatefactories.h"
#include "updates/updateoptionsdialog.h"
#include <QPalette>
#include <QColorDialog>
constexpr char FIM_TEMPLATESETUP[] {"Template Setup"};
AppPreferencesDialog::AppPreferencesDialog(QWidget * parent, UpdateFactories * factories) :
QDialog(parent),
ui(new Ui::AppPreferencesDialog),
updateLock(false),
mainWinHasDirtyChild(false),
factories(factories),
panelItemModels(nullptr)
{
ui->setupUi(this);
setWindowIcon(CompanionIcon("apppreferences.png"));
ui->tabWidget->setCurrentIndex(0);
panelItemModels = new FilteredItemModelFactory();
panelItemModels->registerItemModel(new FilteredItemModel(GeneralSettings::templateSetupItemModel()), FIM_TEMPLATESETUP);
initSettings();
connect(ui->boardCB, SIGNAL(currentIndexChanged(int)), this, SLOT(onBaseFirmwareChanged()));
connect(ui->opt_appDebugLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
connect(ui->opt_fwTraceLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
connect(ui->backupPath, &QLineEdit::editingFinished, this, &AppPreferencesDialog::onBackupPathEditingFinished);
connect(ui->backupPathButton, &QPushButton::clicked, this, &AppPreferencesDialog::onBackupPathButtonClicked);
connect(ui->profileBackupPath, &QLineEdit::editingFinished, this, &AppPreferencesDialog::onProfileBackupPathEditingFinished);
connect(ui->profileBackupPathButton, &QPushButton::clicked, this, &AppPreferencesDialog::onProfileBackupPathButtonClicked);
#if !defined(USE_SDL)
ui->joystickCB->hide();
ui->joystickCB->setDisabled(true);
ui->joystickcalButton->hide();
ui->joystickChkB->hide();
ui->label_11->hide();
#endif
shrink();
}
AppPreferencesDialog::~AppPreferencesDialog()
{
delete ui;
delete panelItemModels;
}
void AppPreferencesDialog::setMainWinHasDirtyChild(bool value)
{
mainWinHasDirtyChild = value;
}
void AppPreferencesDialog::accept()
{
Profile & profile = g.currentProfile();
g.showSplash(ui->showSplash->isChecked());
g.sortProfiles(ui->sortProfiles->isChecked());
g.promptProfile(ui->chkPromptProfile->isChecked());
g.removeModelSlots(ui->opt_removeBlankSlots->isChecked());
g.newModelAction((AppData::NewModelAction)ui->cboNewModelAction->currentIndex());
g.historySize(ui->historySize->value());
profile.volumeGain(round(ui->volumeGain->value() * 10.0));
g.libDir(ui->libraryPath->text());
g.gePath(ui->ge_lineedit->text());
g.embedSplashes(ui->splashincludeCB->currentIndex());
g.enableBackup(ui->backupEnable->isChecked());
g.appDebugLog(ui->opt_appDebugLog->isChecked());
g.fwTraceLog(ui->opt_fwTraceLog->isChecked());
g.appLogsDir(ui->appLogsDir->text());
g.runAppInstaller(ui->chkPromptInstall->isChecked());
g.useSavedSettings(ui->chkUseSavedSettingsApp->isChecked());
// Simulator tab
g.simuSW(ui->simuSW->isChecked());
g.backLight(ui->backLightColor->currentIndex());
g.simuGenericKeysPos((AppData::SimuGenericKeysPos)ui->cboSimuGenericKeysPos->currentIndex());
g.simuScrollButtons(ui->chkSimuScrollButtons->isChecked());
g.disableJoystickWarning(ui->joystickWarningCB->isChecked());
if (ui->joystickChkB ->isChecked()) {
g.jsSupport(ui->joystickChkB ->isChecked());
// Don't overwrite selected joystick if not connected. Avoid surprising the user.
if (ui->joystickCB->isEnabled()) {
profile.jsName(ui->joystickCB->currentText());
g.loadNamedJS();
}
}
else {
g.jsSupport(false);
}
// Updates tab
if (ui->leDownloadDir->text().isEmpty()) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Download folder path missing!"));
return;
}
if (ui->leDecompressDir->text().isEmpty()) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Decompress folder path missing!"));
return;
}
if (ui->leUpdateDir->text().isEmpty()) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Update folder path missing!"));
return;
}
if (!ui->chkDecompressDirUseDwnld->isChecked() &&
ui->leDecompressDir->text().trimmed() == ui->leDownloadDir->text().trimmed()) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Decompress and download folders have the same path!"));
return;
}
g.updateCheckFreq(AppData::UpdateCheckFreq(ui->cboUpdateCheckFreq->currentIndex()));
g.downloadDir(ui->leDownloadDir->text());
g.decompressDirUseDwnld(ui->chkDecompressDirUseDwnld->isChecked());
g.decompressDir(ui->leDecompressDir->text());
g.updateDirUseSD(ui->chkUpdateDirUseSD->isChecked());
g.updateDir(ui->leUpdateDir->text());
g.updDelDownloads(ui->chkDelDownloads->isChecked());
g.updDelDecompress(ui->chkDelDecompress->isChecked());
g.updLogLevel(ui->cboLogLevel->currentIndex());
QMapIterator<QString, int> it(factories->sortedComponentsList());
while (it.hasNext()) {
it.next();
int i = it.value();
g.component[i].checkForUpdate(chkCheckForUpdate[i]->isChecked());
g.component[i].releaseChannel((ComponentData::ReleaseChannel)cboReleaseChannel[i]->currentIndex());
}
profile.defaultInternalModule(ui->defaultInternalModuleCB->currentData().toInt());
profile.externalModuleSize(ui->externalModuleSizeCB->currentData().toInt());
profile.channelOrder(ui->channelorderCB->currentData().toInt());
profile.defaultMode(ui->stickmodeCB->currentData().toInt());
profile.burnFirmware(ui->burnFirmware->isChecked());
profile.sdPath(ui->sdPath->text());
profile.pBackupDir(ui->profileBackupPath->text());
profile.penableBackup(ui->profileBackupEnable->isChecked());
profile.splashFile(ui->SplashFileName->text());
profile.runSDSync(ui->chkPromptSDSync->isChecked());
profile.radioSimCaseColor(ui->lblRadioColorSample->palette().button().color());
profile.simBtnClickedUseOSTheme(ui->chkSimBtnClickedUseOSTheme->isChecked());
profile.simBtnClickedColor(ui->lblSimBtnClickedColorSample->palette().button().color());
profile.useSavedSettings(ui->chkUseSavedSettingsProfile->isChecked());
// The profile name may NEVER be empty
if (ui->profileNameLE->text().isEmpty())
profile.name(tr("My Radio"));
else
profile.name(ui->profileNameLE->text());
bool fwchange = false;
Firmware * newFw = getFirmwareVariant(); // always !null
// If a new fw type has been choosen, several things need to reset
if (Firmware::getCurrentVariant()->getId() != newFw->getId()) {
// check if we're going to be converting to a new radio type and there are unsaved files in the main window
if (mainWinHasDirtyChild && !Boards::isBoardCompatible(Firmware::getCurrentVariant()->getBoard(), newFw->getBoard())) {
QString q = tr("<p><b>You cannot switch Radio Type or change Build Options while there are unsaved file changes. What do you wish to do?</b></p> <ul>" \
"<li><i>Save All</i> - Save any open file(s) before saving Settings.<li>" \
"<li><i>Reset</i> - Revert to the previous Radio Type and Build Options before saving Settings.</li>" \
"<li><i>Cancel</i> - Return to the Settings editor dialog.</li></ul>");
int resp = QMessageBox::question(this, windowTitle(), q, (QMessageBox::SaveAll | QMessageBox::Reset | QMessageBox::Cancel), QMessageBox::Cancel);
if (resp == QMessageBox::SaveAll) {
// signal main window to save files, need to do this before the fw actually changes
emit firmwareProfileAboutToChange();
}
else if (resp == QMessageBox::Reset) {
// bail out early before saving the radio type & firmware options
QDialog::accept();
return;
}
else {
// we do not accept the dialog close
return;
}
}
Firmware::setCurrentVariant(newFw);
profile.fwName("");
profile.fwType(newFw->getId());
fwchange = true;
}
QDialog::accept();
if (fwchange)
emit firmwareProfileChanged(); // important to do this after the accepted() signal
}
void AppPreferencesDialog::on_snapshotPathButton_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this, tr("Select your snapshot folder"), g.snapshotDir());
if (!fileName.isEmpty()) {
g.snapshotDir(fileName);
g.snapToClpbrd(false);
ui->snapshotPath->setText(fileName);
}
}
void AppPreferencesDialog::on_btnRadioColor_clicked()
{
Profile & profile = g.currentProfile();
QColorDialog *dlg = new QColorDialog(this);
QColor color = dlg->getColor(profile.radioSimCaseColor(), this);
ui->lblRadioColorSample->setPalette(QPalette(color));
ui->lblRadioColorSample->repaint();
}
void AppPreferencesDialog::initSettings()
{
Profile & profile = g.currentProfile();
ui->burnFirmware->setChecked(profile.burnFirmware());
ui->showSplash->setChecked(g.showSplash());
ui->sortProfiles->setChecked(g.sortProfiles());
ui->chkPromptProfile->setChecked(g.promptProfile());
ui->historySize->setValue(g.historySize());
ui->opt_removeBlankSlots->setChecked(g.removeModelSlots());
ui->cboNewModelAction->addItems(AppData::newModelActionsList());
ui->cboNewModelAction->setCurrentIndex(g.newModelAction());
ui->libraryPath->setText(g.libDir());
ui->ge_lineedit->setText(g.gePath());
ui->backupPath->setText(g.backupDir());
if (!ui->backupPath->text().isEmpty() && QDir(ui->backupPath->text()).exists()) {
ui->backupEnable->setEnabled(true);
ui->backupEnable->setChecked(g.enableBackup());
} else {
ui->backupEnable->setChecked(false);
ui->backupEnable->setEnabled(false);
}
ui->splashincludeCB->setCurrentIndex(g.embedSplashes());
ui->opt_appDebugLog->setChecked(g.appDebugLog());
ui->opt_fwTraceLog->setChecked(g.fwTraceLog());
ui->appLogsDir->setText(g.appLogsDir());
toggleAppLogSettings();
ui->chkPromptInstall->setChecked(g.runAppInstaller());
// Simulator tab
ui->snapshotPath->setText(g.snapshotDir());
ui->snapshotPath->setReadOnly(true);
ui->snapshotClipboardCKB->setChecked(g.snapToClpbrd());
if (ui->snapshotClipboardCKB->isChecked()) {
ui->snapshotPath->setDisabled(true);
ui->snapshotPathButton->setDisabled(true);
}
ui->simuSW->setChecked(g.simuSW());
ui->backLightColor->setCurrentIndex(g.backLight());
if (!Boards::getCapability(getCurrentBoard(), Board::HasBacklightColor))
ui->backLightColor->setEnabled(false);
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
ui->cboSimuGenericKeysPos->addItems(AppData::simuGenericKeysPosList());
ui->cboSimuGenericKeysPos->setCurrentIndex(g.simuGenericKeysPos());
ui->chkSimuScrollButtons->setChecked(g.simuScrollButtons());
ui->joystickWarningCB->setChecked(g.disableJoystickWarning());
ui->chkUseSavedSettingsApp->setChecked(g.useSavedSettings());
#if defined(USE_SDL)
ui->joystickChkB->setChecked(g.jsSupport());
if (ui->joystickChkB->isChecked()) {
QStringList joystickNames;
joystickNames << tr("No joysticks found");
joystick = new Joystick(0,0,false,0);
ui->joystickcalButton->setDisabled(true);
ui->joystickCB->setDisabled(true);
if ( joystick ) {
if ( joystick->joystickNames.count() > 0 ) {
joystickNames = joystick->joystickNames;
ui->joystickCB->setEnabled(true);
ui->joystickcalButton->setEnabled(true);
}
joystick->close();
}
ui->joystickCB->clear();
ui->joystickCB->insertItems(0, joystickNames);
int stick = joystick->findCurrent(g.currentProfile().jsName());
ui->joystickCB->setCurrentIndex(stick);
}
else {
ui->joystickCB->clear();
ui->joystickCB->setDisabled(true);
ui->joystickcalButton->setDisabled(true);
}
#endif
// Profile Tab Inits
ui->defaultInternalModuleCB->setModel(ModuleData::internalModuleItemModel());
ui->defaultInternalModuleCB->setCurrentIndex(ui->defaultInternalModuleCB->findData(profile.defaultInternalModule()));
ui->externalModuleSizeCB->setModel(Boards::externalModuleSizeItemModel());
ui->externalModuleSizeCB->setCurrentIndex(ui->externalModuleSizeCB->findData(profile.externalModuleSize()));
panelItemModels->getItemModel(FIM_TEMPLATESETUP)->setFilterFlags(Boards::isAir() ? GeneralSettings::RadioTypeContextAir :
GeneralSettings::RadioTypeContextSurface);
ui->sdPath->setText(profile.sdPath());
ui->profileBackupPath->setText(profile.pBackupDir());
if (!ui->profileBackupPath->text().isEmpty()) {
if (QDir(ui->profileBackupPath->text()).exists()) {
ui->profileBackupEnable->setEnabled(true);
ui->profileBackupEnable->setChecked(profile.penableBackup());
} else {
ui->profileBackupEnable->setChecked(false);
ui->profileBackupEnable->setEnabled(false);
}
} else if (!ui->backupPath->text().isEmpty() && QDir(ui->backupPath->text()).exists()) {
ui->profileBackupEnable->setEnabled(true);
ui->profileBackupEnable->setChecked(profile.penableBackup());
} else {
ui->profileBackupEnable->setChecked(false);
ui->profileBackupEnable->setEnabled(false);
}
ui->profileNameLE->setText(profile.name());
QString hwSettings;
if (profile.generalSettings().isEmpty()) {
hwSettings = tr("No backup available for this profile");
}
else {
QString str = profile.timeStamp();
if (str.isEmpty())
hwSettings = tr("Backup available of unknown age");
else
hwSettings = tr("Backup available dated %1").arg(str);
}
ui->stickmodeCB->setModel(GeneralSettings::stickModeItemModel());
ui->stickmodeCB->setCurrentIndex(ui->stickmodeCB->findData(profile.defaultMode()));
if (Boards::isSurface()) {
ui->stickmodeLabel->hide();
ui->stickmodeCB->hide();
}
ui->channelorderCB->setModel(panelItemModels->getItemModel(FIM_TEMPLATESETUP));
ui->channelorderCB->setCurrentIndex(ui->channelorderCB->findData(profile.channelOrder()));
ui->chkUseSavedSettingsProfile->setChecked(profile.useSavedSettings());
ui->lblGeneralSettings->setText(hwSettings);
on_chkUseSavedSettingsProfile_stateChanged();
ui->chkPromptSDSync->setChecked(profile.runSDSync());
ui->lblRadioColorSample->setPalette(QPalette(profile.radioSimCaseColor()));
ui->chkSimBtnClickedUseOSTheme->setChecked(profile.simBtnClickedUseOSTheme());
ui->lblSimBtnClickedColorSample->setPalette(QPalette(profile.simBtnClickedColor()));
if (ui->chkSimBtnClickedUseOSTheme->isChecked()) {
ui->lblSimBtnClickedColorSample->setVisible(false);
ui->btnSimBtnClickedColor->setEnabled(false);
} else {
ui->lblSimBtnClickedColorSample->setVisible(true);
ui->btnSimBtnClickedColor->setEnabled(true);
}
QString currType = QStringList(profile.fwType().split('-').mid(0, 2)).join('-');
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
ui->boardCB->addItem(firmware->getName(), firmware->getId());
if (currType == firmware->getId()) {
ui->boardCB->setCurrentIndex(ui->boardCB->count() - 1);
}
}
populateFirmwareOptions(getBaseFirmware());
// Updates tab
ui->cboUpdateCheckFreq->addItems(AppData::updateCheckFreqsList());
connect(ui->btnResetUpdatesToDefaults, &QPushButton::clicked, [=]() {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Reset all update settings to defaults. Are you sure?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
g.resetUpdatesSettings();
QMessageBox::warning(this, CPN_STR_APP_NAME,
tr("Update settings have been reset. Please close and restart Companion to avoid unexpected behaviour!"));
loadUpdatesTab();
}
});
connect(ui->chkDecompressDirUseDwnld, &QCheckBox::toggled, [=](const bool checked) {
if (!checked) {
ui->leDecompressDir->setText(g.decompressDir());
ui->leDecompressDir->setEnabled(true);
ui->btnDecompressSelect->setEnabled(true);
ui->chkDelDownloads->setEnabled(true);
}
else {
ui->leDecompressDir->setText(g.downloadDir());
ui->leDecompressDir->setEnabled(false);
ui->btnDecompressSelect->setEnabled(false);
if (ui->chkDelDecompress->isChecked()) {
ui->chkDelDownloads->setEnabled(true);
}
else {
ui->chkDelDownloads->setEnabled(false);
ui->chkDelDownloads->setChecked(false);
}
}
});
connect(ui->chkUpdateDirUseSD, &QCheckBox::toggled, [=](const bool checked) {
if (!checked) {
ui->leUpdateDir->setText(g.updateDir());
ui->leUpdateDir->setEnabled(true);
ui->btnUpdateSelect->setEnabled(true);
}
else {
ui->leUpdateDir->setText(g.currentProfile().sdPath());
ui->leUpdateDir->setEnabled(false);
ui->btnUpdateSelect->setEnabled(false);
}
});
connect(ui->btnDownloadSelect, &QPushButton::clicked, [=]() {
QString dirPath = QFileDialog::getExistingDirectory(this,tr("Select your download folder"), g.downloadDir());
if (!dirPath.isEmpty()) {
ui->leDownloadDir->setText(dirPath);
}
});
connect(ui->btnDecompressSelect, &QPushButton::clicked, [=]() {
QString dirPath = QFileDialog::getExistingDirectory(this,tr("Select your decompress folder"), g.decompressDir());
if (!dirPath.isEmpty()) {
ui->leDecompressDir->setText(dirPath);
}
});
connect(ui->btnUpdateSelect, &QPushButton::clicked, [=]() {
QString dirPath = QFileDialog::getExistingDirectory(this,tr("Select your update destination folder"), g.updateDir());
if (!dirPath.isEmpty()) {
ui->leUpdateDir->setText(dirPath);
}
});
connect(ui->chkDelDecompress, &QCheckBox::checkStateChanged, [=](const int checked) {
if (!checked) {
if (ui->chkDecompressDirUseDwnld->isChecked()) {
ui->chkDelDownloads->setEnabled(false);
ui->chkDelDownloads->setChecked(false);
}
}
else {
ui->chkDelDownloads->setEnabled(true);
}
});
int row = 0;
int col = 0;
QGridLayout *grid = new QGridLayout();
col++; // leave col 0 blank
QLabel *h1 = new QLabel(tr("Check"));
grid->addWidget(h1, row, col++);
QLabel *h2 = new QLabel(tr("Release channel"));
grid->addWidget(h2, row, col++);
col++; // options button
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
grid->addItem(spacer, row, col++);
QMapIterator<QString, int> it(factories->sortedComponentsList());
while (it.hasNext()) {
it.next();
int i = it.value();
row++;
col = 0;
lblName[i] = new QLabel();
grid->addWidget(lblName[i], row, col++);
chkCheckForUpdate[i] = new QCheckBox();
chkCheckForUpdate[i]->setStyleSheet("spacing: 10px"); // workaround Qt 6.9.0 Qt::AlignHCenter causes text to overlap checkbox rhs
grid->addWidget(chkCheckForUpdate[i], row, col++);
grid->setAlignment(chkCheckForUpdate[i], Qt::AlignHCenter);
cboReleaseChannel[i] = new QComboBox();
cboReleaseChannel[i]->addItems(ComponentData::releaseChannelsList());
grid->addWidget(cboReleaseChannel[i], row, col++);
btnComponentOptions[i] = new QPushButton(tr("Options"));
connect(btnComponentOptions[i], &QPushButton::clicked, [=]() {
UpdateOptionsDialog *dlg = new UpdateOptionsDialog(this, factories->instance(i), i, false);
dlg->exec();
dlg->deleteLater();
});
grid->addWidget(btnComponentOptions[i], row, col++);
}
ui->grpComponents->setLayout(grid);
ui->cboLogLevel->addItems(AppData::updateLogLevelsList());
loadUpdatesTab();
}
void AppPreferencesDialog::loadUpdatesTab()
{
ui->cboUpdateCheckFreq->setCurrentIndex(g.updateCheckFreq());
ui->chkDelDownloads->setChecked(g.updDelDownloads());
ui->chkDelDecompress->setChecked(g.updDelDecompress());
ui->leDownloadDir->setText(g.downloadDir());
// trigger toggled signal by changing design value and then setting to saved value
ui->chkDecompressDirUseDwnld->setChecked(!ui->chkDecompressDirUseDwnld->isChecked());
ui->chkDecompressDirUseDwnld->setChecked(g.decompressDirUseDwnld());
if (g.currentProfile().sdPath().trimmed().isEmpty())
ui->chkUpdateDirUseSD->setEnabled(false);
else
ui->chkUpdateDirUseSD->setEnabled(true);
if (g.updateDirUseSD() && g.currentProfile().sdPath().trimmed().isEmpty()) {
g.updateDirUseSD(false);
g.updateDirReset();
}
if (g.updateDirUseSD()) {
// trigger toggled signal by changing design value and then setting to saved value
ui->chkUpdateDirUseSD->setChecked(!ui->chkUpdateDirUseSD->isChecked());
ui->chkUpdateDirUseSD->setChecked(g.updateDirUseSD());
}
else
ui->chkUpdateDirUseSD->setChecked(false);
ui->chkDelDownloads->setChecked(g.updDelDownloads());
ui->cboLogLevel->setCurrentIndex(g.updLogLevel());
QMapIterator<QString, int> it(factories->sortedComponentsList());
while (it.hasNext()) {
it.next();
int i = it.value();
lblName[i]->setText(it.key());
chkCheckForUpdate[i]->setChecked(g.component[i].checkForUpdate());
cboReleaseChannel[i]->setCurrentIndex(g.component[i].releaseChannel());
}
}
void AppPreferencesDialog::on_libraryPathButton_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your library folder"), g.libDir());
if (!fileName.isEmpty()) {
g.libDir(fileName);
ui->libraryPath->setText(fileName);
}
}
void AppPreferencesDialog::on_snapshotClipboardCKB_clicked()
{
if (ui->snapshotClipboardCKB->isChecked()) {
ui->snapshotPath->setDisabled(true);
ui->snapshotPathButton->setDisabled(true);
g.snapToClpbrd(true);
}
else {
ui->snapshotPath->setEnabled(true);
ui->snapshotPath->setReadOnly(true);
ui->snapshotPathButton->setEnabled(true);
g.snapToClpbrd(false);
}
}
void AppPreferencesDialog::onBackupPathButtonClicked()
{
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your global backup folder"), g.backupDir());
if (!fileName.isEmpty()) {
g.backupDir(fileName);
ui->backupPath->setText(fileName);
ui->backupEnable->setEnabled(true);
ui->profileBackupEnable->setEnabled(true);
} else {
ui->backupEnable->setEnabled(false);
if (!g.currentProfile().pBackupDir().isEmpty() && QFileInfo(g.currentProfile().pBackupDir()).exists()) {
ui->profileBackupEnable->setEnabled(true);
} else {
ui->profileBackupEnable->setEnabled(false);
}
}
}
void AppPreferencesDialog::onProfileBackupPathButtonClicked()
{
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select your profile backup folder"), g.backupDir());
if (!fileName.isEmpty()) {
ui->profileBackupPath->setText(fileName);
ui->profileBackupEnable->setEnabled(true);
}
}
void AppPreferencesDialog::on_btn_appLogsDir_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this, tr("Select a folder for application logs"), ui->appLogsDir->text());
if (!fileName.isEmpty()) {
ui->appLogsDir->setText(fileName);
}
}
void AppPreferencesDialog::on_ge_pathButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Google Earth executable"),ui->ge_lineedit->text());
if (!fileName.isEmpty()) {
ui->ge_lineedit->setText(fileName);
}
}
void AppPreferencesDialog::on_btnClearPos_clicked()
{
SimulatorOptions opts = g.profile[g.sessionId()].simulatorOptions();
opts.controlsState.clear();
g.profile[g.sessionId()].simulatorOptions(opts);
}
#if defined(USE_SDL)
void AppPreferencesDialog::on_joystickChkB_clicked() {
if (ui->joystickChkB->isChecked()) {
QStringList joystickNames;
joystickNames << tr("No joysticks found");
joystick = new Joystick(0,0,false,0);
ui->joystickcalButton->setDisabled(true);
ui->joystickCB->setDisabled(true);
if ( joystick ) {
if ( joystick->joystickNames.count() > 0 ) {
joystickNames = joystick->joystickNames;
ui->joystickCB->setEnabled(true);
ui->joystickcalButton->setEnabled(true);
}
joystick->close();
}
ui->joystickCB->clear();
ui->joystickCB->insertItems(0, joystickNames);
}
else {
ui->joystickCB->clear();
ui->joystickCB->setDisabled(true);
ui->joystickcalButton->setDisabled(true);
}
}
void AppPreferencesDialog::on_joystickcalButton_clicked() {
g.currentProfile().jsName(ui->joystickCB->currentText());
joystickDialog * jd = new joystickDialog(this);
jd->exec();
}
#endif
// ******** Profile tab functions
void AppPreferencesDialog::on_sdPathButton_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g.currentProfile().sdPath());
if (!fileName.isEmpty()) {
ui->sdPath->setText(fileName);
}
}
bool AppPreferencesDialog::displayImage(const QString & fileName)
{
// Start by clearing the label
ui->imageLabel->clear();
if (fileName.isEmpty())
return false;
QImage image(fileName);
if (image.isNull())
return false;
ui->imageLabel->setPixmap(makePixMap(image));
ui->imageLabel->setFixedSize(Boards::getCapability(getCurrentBoard(), Board::LcdWidth),
Boards::getCapability(getCurrentBoard(), Board::LcdHeight));
return true;
}
void AppPreferencesDialog::on_SplashSelect_clicked()
{
QString supportedImageFormats;
for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
supportedImageFormats += QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex];
}
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Image to load"), g.imagesDir(), tr("Images (%1)").arg(supportedImageFormats));
if (!fileName.isEmpty()){
g.imagesDir(QFileInfo(fileName).dir().absolutePath());
displayImage(fileName);
ui->SplashFileName->setText(fileName);
}
}
void AppPreferencesDialog::on_clearImageButton_clicked()
{
ui->imageLabel->clear();
ui->SplashFileName->clear();
}
void AppPreferencesDialog::onBaseFirmwareChanged()
{
populateFirmwareOptions(getBaseFirmware());
Firmware *newfw = getFirmwareVariant();
Profile & profile = g.currentProfile();
profile.defaultInternalModule(Boards::getDefaultInternalModules(newfw->getBoard()));
ui->defaultInternalModuleCB->setModel(ModuleData::internalModuleItemModel(newfw->getBoard()));
ui->defaultInternalModuleCB->setCurrentIndex(ui->defaultInternalModuleCB->findData(profile.defaultInternalModule()));
profile.externalModuleSize(Boards::getDefaultExternalModuleSize(newfw->getBoard()));
ui->externalModuleSizeCB->setModel(Boards::externalModuleSizeItemModel());
ui->externalModuleSizeCB->setCurrentIndex(ui->externalModuleSizeCB->findData(profile.externalModuleSize()));
if (Boards::isSurface()) {
profile.defaultMode(1);
ui->stickmodeLabel->hide();
ui->stickmodeCB->hide();
profile.channelOrder(0);
}
ui->stickmodeCB->setCurrentIndex(ui->stickmodeCB->findData(profile.defaultMode()));
panelItemModels->getItemModel(FIM_TEMPLATESETUP)->setFilterFlags(Boards::isAir() ? GeneralSettings::RadioTypeContextAir :
GeneralSettings::RadioTypeContextSurface);
ui->channelorderCB->setCurrentIndex(ui->channelorderCB->findData(profile.channelOrder()));
}
Firmware *AppPreferencesDialog::getBaseFirmware() const
{
return Firmware::getFirmwareForId(ui->boardCB->currentData().toString());
}
Firmware * AppPreferencesDialog::getFirmwareVariant() const
{
QString id = ui->boardCB->currentData().toString();
foreach(QCheckBox *cb, optionsCheckBoxes.values()) {
if (cb->isChecked())
id += "-" + cb->text();
}
if (ui->langCombo->count())
id += "-" + ui->langCombo->currentText();
return Firmware::getFirmwareForId(id);
}
void AppPreferencesDialog::onFirmwareOptionChanged(bool state)
{
QCheckBox *cb = qobject_cast<QCheckBox*>(sender());
if (!(cb && state))
return;
// This de-selects any mutually exlusive options (that is, members of the same QList<Option> list).
const Firmware::OptionsList & fwOpts = getBaseFirmware()->optionGroups();
for (const Firmware::OptionsGroup & optGrp : fwOpts) {
for (const Firmware::Option & opt : optGrp) {
if (cb->text() == opt.name) {
QCheckBox *ocb = nullptr;
foreach(const Firmware::Option & other, optGrp)
if (other.name != opt.name && (ocb = optionsCheckBoxes.value(other.name, nullptr)))
ocb->setChecked(false);
return;
}
}
}
}
void AppPreferencesDialog::toggleAppLogSettings()
{
bool vis = (ui->opt_appDebugLog->isChecked() || ui->opt_fwTraceLog->isChecked());
ui->appLogsDir->setVisible(vis);
ui->lbl_appLogsDir->setVisible(vis);
ui->btn_appLogsDir->setVisible(vis);
}
void AppPreferencesDialog::populateFirmwareOptions(const Firmware * firmware)
{
const Firmware * baseFw = firmware->getFirmwareBase();
QStringList currVariant = Firmware::getCurrentVariant()->getId().split('-');
QString fwLang = Firmware::getCurrentVariant()->getLanguage();
if (fwLang.isEmpty()) // try to detect os language
fwLang = QLocale::languageToString(QLocale().language()).split("_").first();
const QString currLang = ui->langCombo->count() ? ui->langCombo->currentText() : fwLang;
updateLock = true;
ui->langCombo->clear();
for (const char *lang : baseFw->languageList()) {
ui->langCombo->addItem(lang);
if (currLang == lang) {
ui->langCombo->setCurrentIndex(ui->langCombo->count() - 1);
}
}
if (optionsCheckBoxes.size()) {
currVariant.clear();
QMutableMapIterator<QString, QCheckBox *> it(optionsCheckBoxes);
while (it.hasNext()) {
it.next();
QCheckBox * cb = it.value();
if (cb->isChecked())
currVariant.append(it.key()); // keep previous selections
ui->optionsLayout->removeWidget(cb);
cb->deleteLater();
it.remove();
}
}
int index = 0;
QWidget * prevFocus = ui->langCombo;
for (const Firmware::OptionsGroup &optGrp : baseFw->optionGroups()) {
for (const Firmware::Option &opt : optGrp) {
QCheckBox * cb = new QCheckBox(ui->profileTab);
cb->setText(opt.name);
cb->setToolTip(opt.tooltip);
cb->setChecked(currVariant.contains(opt.name));
ui->optionsLayout->addWidget(cb, index / 4, index % 4);
QWidget::setTabOrder(prevFocus, cb);
// connect to duplicates check handler if this option is part of a group
if (optGrp.size() > 1)
connect(cb, &QCheckBox::toggled, this, &AppPreferencesDialog::onFirmwareOptionChanged);
optionsCheckBoxes.insert(opt.name, cb);
prevFocus = cb;
++index;
}
}
if (Boards::getCapability(baseFw->getBoard(), Board::HasColorLcd)) {
ui->widget_splashImage->hide();
ui->SplashFileName->setText("");
}
else {
ui->widget_splashImage->show();
ui->SplashFileName->setText(g.currentProfile().splashFile());
displayImage(g.currentProfile().splashFile());
}
updateLock = false;
QTimer::singleShot(50, this, &AppPreferencesDialog::shrink);
}
void AppPreferencesDialog::shrink()
{
adjustSize();
}
void AppPreferencesDialog::onBackupPathEditingFinished()
{
if(!ui->backupPath->text().isEmpty() && QFileInfo(ui->backupPath->text()).exists()) {
ui->backupEnable->setEnabled(true);
} else {
ui->backupEnable->setChecked(false);
ui->backupEnable->setEnabled(false);
}
onProfileBackupPathEditingFinished();
}
void AppPreferencesDialog::onProfileBackupPathEditingFinished()
{
if (!ui->profileBackupPath->text().isEmpty()) {
if (QDir(ui->profileBackupPath->text()).exists()) {
ui->profileBackupEnable->setEnabled(true);
} else {
ui->profileBackupEnable->setChecked(false);
ui->profileBackupEnable->setEnabled(false);
}
} else if (!ui->backupPath->text().isEmpty() && QDir(ui->backupPath->text()).exists()) {
ui->profileBackupEnable->setEnabled(true);
} else {
ui->profileBackupEnable->setChecked(false);
ui->profileBackupEnable->setEnabled(false);
}
}
void AppPreferencesDialog::on_chkSimBtnClickedUseOSTheme_stateChanged()
{
if (ui->chkSimBtnClickedUseOSTheme->isChecked()) {
ui->lblSimBtnClickedColorSample->setVisible(false);
ui->btnSimBtnClickedColor->setEnabled(false);
} else {
ui->lblSimBtnClickedColorSample->setVisible(true);
ui->btnSimBtnClickedColor->setEnabled(true);
}
}
void AppPreferencesDialog::on_btnSimBtnClickedColor_clicked()
{
QColorDialog *dlg = new QColorDialog(this);
QColor color = dlg->getColor(g.currentProfile().simBtnClickedColor(), this);
ui->lblSimBtnClickedColorSample->setPalette(QPalette(color));
ui->lblSimBtnClickedColorSample->repaint();
}
void AppPreferencesDialog::on_chkUseSavedSettingsProfile_stateChanged()
{
if (ui->chkUseSavedSettingsProfile->isChecked() && !g.currentProfile().generalSettings().isEmpty()) {
ui->stickmodeLabel->setEnabled(false);
ui->stickmodeCB->setEnabled(false);
ui->channelorderLabel->setEnabled(false);
ui->channelorderCB->setEnabled(false);
} else {
ui->stickmodeLabel->setEnabled(true);
ui->stickmodeCB->setEnabled(true);
ui->channelorderLabel->setEnabled(true);
ui->channelorderCB->setEnabled(true);
}
}
-111
View File
@@ -1,111 +0,0 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "eeprominterface.h"
#include "appdata.h"
#include <QDialog>
#include <QCheckBox>
#include <QComboBox>
class FilteredItemModelFactory;
namespace Ui {
class AppPreferencesDialog;
}
class Joystick;
class UpdateFactories;
class AppPreferencesDialog : public QDialog
{
Q_OBJECT
public:
explicit AppPreferencesDialog(QWidget * parent, UpdateFactories * factories);
~AppPreferencesDialog();
Joystick * joystick;
public slots:
void accept() Q_DECL_OVERRIDE;
void setMainWinHasDirtyChild(bool value);
signals:
void firmwareProfileChanged();
void firmwareProfileAboutToChange(bool saveFiles = true);
protected slots:
void shrink();
void onBaseFirmwareChanged();
void onFirmwareOptionChanged(bool state);
void toggleAppLogSettings();
void on_libraryPathButton_clicked();
void on_snapshotPathButton_clicked();
void on_snapshotClipboardCKB_clicked();
void onBackupPathButtonClicked();
void onProfileBackupPathButtonClicked();
void on_ge_pathButton_clicked();
void on_sdPathButton_clicked();
void on_SplashSelect_clicked();
void on_clearImageButton_clicked();
void on_btn_appLogsDir_clicked();
void on_btnClearPos_clicked();
#if defined(USE_SDL)
void on_joystickChkB_clicked();
void on_joystickcalButton_clicked();
#endif
void on_btnRadioColor_clicked();
void on_chkSimBtnClickedUseOSTheme_stateChanged();
void on_btnSimBtnClickedColor_clicked();
void onBackupPathEditingFinished();
void onProfileBackupPathEditingFinished();
void on_chkUseSavedSettingsProfile_stateChanged();
private:
void initSettings();
void populateFirmwareOptions(const Firmware *);
Firmware * getBaseFirmware() const;
Firmware * getFirmwareVariant() const;
bool displayImage(const QString & fileName);
Ui::AppPreferencesDialog *ui;
QMap<QString, QCheckBox *> optionsCheckBoxes;
bool updateLock;
bool mainWinHasDirtyChild;
UpdateFactories *factories;
QLabel *lblName[MAX_COMPONENTS];
QCheckBox *chkCheckForUpdate[MAX_COMPONENTS];
QComboBox *cboReleaseChannel[MAX_COMPONENTS];
QPushButton *btnComponentOptions[MAX_COMPONENTS];
FilteredItemModelFactory *panelItemModels;
void loadUpdatesTab();
};
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -169,11 +169,11 @@ int main(int argc, char *argv[])
bool doReset = args.contains("--defaults");
if (doExport)
Helpers::exportAppSettings();
Helpers::exportPreferences();
if (doReset) {
char ok;
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Reset ALL application settings to default values and remove radio profiles, are you sure?").toUtf8().constData());
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Reset ALL application preferences to default values and remove radio profiles, are you sure?").toUtf8().constData());
std::cin >> ok;
if (ok != 'Y' && ok != 'y')
exit(0);
@@ -181,11 +181,11 @@ int main(int argc, char *argv[])
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Would you like to perform a backup first?").toUtf8().constData());
std::cin >> ok;
if (ok == 'Y' || ok == 'y')
Helpers::exportAppSettings();
Helpers::exportPreferences();
}
g.resetAllSettings();
g.storeAllSettings();
std::cout << QCoreApplication::translate("Companion", "Application settings were reset and saved.").toUtf8().constData() << std::endl;
std::cout << QCoreApplication::translate("Companion", "Application preferences were reset and saved.").toUtf8().constData() << std::endl;
}
if (doImport)
@@ -252,7 +252,8 @@ int main(int argc, char *argv[])
profile.fwName("");
}
Firmware::setCurrentVariant(Firmware::getFirmwareForId(g.profile[g.id()].fwType()));
// force the Board definition to load by appending "-xxx"
Firmware::setCurrentVariant(Firmware::getFirmwareForId(g.profile[g.id()].fwType() % "-xxx"));
MainWindow *mainWin = new MainWindow();
mainWin->show();
+72
View File
@@ -1252,3 +1252,75 @@ QString Boards::getCapabilityStr(Board::Type board, Board::Capability capability
{
return getBoardJson(board)->getCapabilityStr(capability);
}
QString Boards::getManufacturer(Board::Type board)
{
switch (board) {
case BOARD_BETAFPV_LR3PRO:
return "BETAFPV";
case BOARD_FATFISH_F16:
return "Fatfish";
case BOARD_FLYSKY_NV14:
case BOARD_FLYSKY_EL18:
case BOARD_FLYSKY_PA01:
case BOARD_FLYSKY_PL18:
case BOARD_FLYSKY_PL18EV:
case BOARD_FLYSKY_PL18U:
case BOARD_FLYSKY_NB4P:
case BOARD_FLYSKY_ST16:
return "FlySky";
case BOARD_TARANIS_X7:
case BOARD_TARANIS_X7_ACCESS:
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_XLITES:
case BOARD_TARANIS_X9D:
case BOARD_TARANIS_X9DP:
case BOARD_TARANIS_X9DP_2019:
case BOARD_TARANIS_X9E:
case BOARD_TARANIS_X9LITE:
case BOARD_TARANIS_X9LITES:
case BOARD_HORUS_X12S:
case BOARD_X10:
case BOARD_X10_EXPRESS:
return "FrSky";
case BOARD_HELLORADIOSKY_V16:
case BOARD_HELLORADIOSKY_V12:
case BOARD_HELLORADIOSKY_V14:
case BOARD_HELLORADIOSKY_V14LCD:
return "HelloRadioSky";
case BOARD_IFLIGHT_COMMANDO8:
case BOARD_IFLIGHT_COMMANDO14:
return "iFlight";
case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
case BOARD_JUMPER_TLITE_F4:
case BOARD_JUMPER_TPRO:
case BOARD_JUMPER_TPROV2:
case BOARD_JUMPER_TPROS:
case BOARD_JUMPER_T12MAX:
case BOARD_JUMPER_BUMBLEBEE:
case BOARD_JUMPER_T14:
case BOARD_JUMPER_T15:
case BOARD_JUMPER_T15PRO:
case BOARD_JUMPER_T22:
case BOARD_JUMPER_T16:
case BOARD_JUMPER_T18:
case BOARD_JUMPER_T20:
case BOARD_JUMPER_T20V2:
return "Jumper";
case BOARD_RADIOMASTER_BOXER:
case BOARD_RADIOMASTER_POCKET:
case BOARD_RADIOMASTER_MT12:
case BOARD_RADIOMASTER_T8:
case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_TX12_MK2:
case BOARD_RADIOMASTER_TX16S:
case BOARD_RADIOMASTER_TX16SMK3:
case BOARD_RADIOMASTER_TX15:
case BOARD_RADIOMASTER_ZORRO:
case BOARD_RADIOMASTER_GX12:
return "Radiomaster";
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
+1
View File
@@ -419,6 +419,7 @@ class Boards
const QString getCapabilityStr(Board::Capability capability) const { return getCapabilityStr(m_boardType, capability); }
const bool isBoardCompatible(Board::Type board2) const { return isBoardCompatible(m_boardType, board2); }
static QString getManufacturer(Board::Type board);
static uint32_t getFourCC(Board::Type board);
static int getEEpromSize(Board::Type board);
static int getFlashSize(Board::Type board);
+14 -4
View File
@@ -155,10 +155,10 @@ class Firmware
virtual ~Firmware() { }
inline const Firmware * getFirmwareBase() const
{
return base ? base : this;
}
// const
inline const Firmware * getFirmwareBase() const { return base ? base : this; }
inline const bool isBase() const { return base ? false : true; }
virtual Firmware * getFirmwareVariant(const QString & id) { return NULL; }
@@ -186,6 +186,16 @@ class Firmware
}
QString getName() const
{
return Boards::getManufacturer(board) % " " % name;
}
QString getFullName() const
{
return getName();
}
QString getShortName() const
{
return name;
}
@@ -46,13 +46,15 @@ Firmware * OpenTxFirmware::getFirmwareVariant(const QString &id)
if (id == getId()) {
return this;
}
// when registering the base firmware we do not load the linked boards to save unnecessary processing
// so create a child instance to force the linked board to be loaded
else if (id.contains(getId() + "-") || (!id.contains("-") && id.contains(getId()))) {
Firmware * result = new OpenTxFirmware(id, this);
// TODO result.variant = firmware->getVariant(id);
return result;
}
else {
return NULL;
return nullptr;
}
}
@@ -344,7 +346,7 @@ void registerOpenTxFirmwares()
static const Firmware::Option opt_internal_gps("internalgps", Firmware::tr("Support internal GPS"));
/* BETAFPV LR3PRO board */
firmware = new OpenTxFirmware(FIRMWAREID("lr3pro"), QCoreApplication::translate("Firmware", "BETAFPV LiteRadio3 Pro"), BOARD_BETAFPV_LR3PRO);
firmware = new OpenTxFirmware(FIRMWAREID("lr3pro"), Firmware::tr("LiteRadio3 Pro"), BOARD_BETAFPV_LR3PRO);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -354,7 +356,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Fatfish F16 board */
firmware = new OpenTxFirmware(FIRMWAREID("f16"), Firmware::tr("Fatfish F16"), BOARD_FATFISH_F16);
firmware = new OpenTxFirmware(FIRMWAREID("f16"), Firmware::tr("F16"), BOARD_FATFISH_F16);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
@@ -362,68 +364,68 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
/* FlySky NV14 board */
firmware = new OpenTxFirmware(FIRMWAREID("nv14"), QCoreApplication::translate("Firmware", "FlySky NV14"), BOARD_FLYSKY_NV14);
firmware = new OpenTxFirmware(FIRMWAREID("nv14"), Firmware::tr("NV14"), BOARD_FLYSKY_NV14);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky EL18 board */
firmware = new OpenTxFirmware(FIRMWAREID("el18"), QCoreApplication::translate("Firmware", "FlySky EL18"), BOARD_FLYSKY_EL18);
firmware = new OpenTxFirmware(FIRMWAREID("el18"), Firmware::tr("EL18"), BOARD_FLYSKY_EL18);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky PA01 board */
firmware = new OpenTxFirmware(FIRMWAREID("pa01"), Firmware::tr("FlySky PA01"), BOARD_FLYSKY_PA01);
firmware = new OpenTxFirmware(FIRMWAREID("pa01"), Firmware::tr("PA01"), BOARD_FLYSKY_PA01);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky PL18 board */
firmware = new OpenTxFirmware(FIRMWAREID("pl18"), Firmware::tr("FlySky PL18"), BOARD_FLYSKY_PL18);
firmware = new OpenTxFirmware(FIRMWAREID("pl18"), Firmware::tr("PL18"), BOARD_FLYSKY_PL18);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky PL18EV board */
firmware = new OpenTxFirmware(FIRMWAREID("pl18ev"), Firmware::tr("FlySky PL18EV"), BOARD_FLYSKY_PL18EV);
firmware = new OpenTxFirmware(FIRMWAREID("pl18ev"), Firmware::tr("PL18EV"), BOARD_FLYSKY_PL18EV);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky PL18U board */
firmware = new OpenTxFirmware(FIRMWAREID("pl18u"), Firmware::tr("FlySky PL18U"), BOARD_FLYSKY_PL18U);
firmware = new OpenTxFirmware(FIRMWAREID("pl18u"), Firmware::tr("PL18U"), BOARD_FLYSKY_PL18U);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FlySky ST16 board */
firmware = new OpenTxFirmware(FIRMWAREID("st16"), Firmware::tr("FlySky ST16"), BOARD_FLYSKY_ST16);
firmware = new OpenTxFirmware(FIRMWAREID("st16"), Firmware::tr("ST16"), BOARD_FLYSKY_ST16);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FrSky Horus X10 board */
firmware = new OpenTxFirmware(FIRMWAREID("x10"), Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10);
firmware = new OpenTxFirmware(FIRMWAREID("x10"), Firmware::tr("Horus X10 / X10S"), BOARD_X10);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky Horus X10 Express board */
firmware = new OpenTxFirmware(FIRMWAREID("x10express"), Firmware::tr("FrSky Horus X10 Express / X10S Express"), BOARD_X10_EXPRESS, "x10express");
firmware = new OpenTxFirmware(FIRMWAREID("x10express"), Firmware::tr("Horus X10 Express / X10S Express"), BOARD_X10_EXPRESS, "x10express");
addOpenTxFrskyOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Horus X12 board */
firmware = new OpenTxFirmware(FIRMWAREID("x12s"), Firmware::tr("FrSky Horus X12S"), BOARD_HORUS_X12S);
firmware = new OpenTxFirmware(FIRMWAREID("x12s"), Firmware::tr("Horus X12S"), BOARD_HORUS_X12S);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
firmware->addOption("pcbdev", Firmware::tr("Use ONLY with first DEV pcb version"));
@@ -431,44 +433,44 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky Taranis X7 board */
firmware = new OpenTxFirmware(FIRMWAREID("x7"), Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
firmware = new OpenTxFirmware(FIRMWAREID("x7"), Firmware::tr("Taranis X7 / X7S"), BOARD_TARANIS_X7);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky Taranis X7 Access board */
firmware = new OpenTxFirmware(FIRMWAREID("x7access"), Firmware::tr("FrSky Taranis X7 / X7S Access"), BOARD_TARANIS_X7_ACCESS, "x7access");
firmware = new OpenTxFirmware(FIRMWAREID("x7access"), Firmware::tr("Taranis X7 / X7S Access"), BOARD_TARANIS_X7_ACCESS, "x7access");
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X-Lite board */
firmware = new OpenTxFirmware(FIRMWAREID("xlite"), Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
firmware = new OpenTxFirmware(FIRMWAREID("xlite"), Firmware::tr("Taranis X-Lite"), BOARD_TARANIS_XLITE);
// firmware->addOption("stdr9m", Firmware::tr("Use JR-sized R9M module"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky Taranis X-Lite S/PRO board */
firmware = new OpenTxFirmware(FIRMWAREID("xlites"), Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
firmware = new OpenTxFirmware(FIRMWAREID("xlites"), Firmware::tr("Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X9-Lite board */
firmware = new OpenTxFirmware(FIRMWAREID("x9lite"), Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE);
firmware = new OpenTxFirmware(FIRMWAREID("x9lite"), Firmware::tr("Taranis X9-Lite"), BOARD_TARANIS_X9LITE);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X9-LiteS board */
firmware = new OpenTxFirmware(FIRMWAREID("x9lites"), Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES);
firmware = new OpenTxFirmware(FIRMWAREID("x9lites"), Firmware::tr("Taranis X9-Lite S"), BOARD_TARANIS_X9LITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X9D board */
firmware = new OpenTxFirmware(FIRMWAREID("x9d"), Firmware::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
firmware = new OpenTxFirmware(FIRMWAREID("x9d"), Firmware::tr("Taranis X9D"), BOARD_TARANIS_X9D);
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
addOpenTxTaranisOptions(firmware);
@@ -476,20 +478,20 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, EU + FLEX + AFHDS2A + AFHDS3);
/* FrSky Taranis X9D+ board */
firmware = new OpenTxFirmware(FIRMWAREID("x9d+"), Firmware::tr("FrSky Taranis X9D+"), BOARD_TARANIS_X9DP, "x9dp");
firmware = new OpenTxFirmware(FIRMWAREID("x9d+"), Firmware::tr("Taranis X9D+"), BOARD_TARANIS_X9DP, "x9dp");
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX + AFHDS2A + AFHDS3);
/* FrSky Taranis X9D+ 2019 board */
firmware = new OpenTxFirmware(FIRMWAREID("x9d+2019"), Firmware::tr("FrSky Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019, "x9dp2019");
firmware = new OpenTxFirmware(FIRMWAREID("x9d+2019"), Firmware::tr("Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019, "x9dp2019");
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky Taranis X9E board */
firmware = new OpenTxFirmware(FIRMWAREID("x9e"), Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E);
firmware = new OpenTxFirmware(FIRMWAREID("x9e"), Firmware::tr("Taranis X9E"), BOARD_TARANIS_X9E);
firmware->addOption("shutdownconfirm", Firmware::tr("Confirmation before radio shutdown"));
firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware);
@@ -497,35 +499,35 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, EU + FLEX);
/* HelloRadioSky V12 board */
firmware = new OpenTxFirmware(FIRMWAREID("v12"), Firmware::tr("HelloRadioSky V12"), BOARD_HELLORADIOSKY_V12);
firmware = new OpenTxFirmware(FIRMWAREID("v12"), Firmware::tr("V12"), BOARD_HELLORADIOSKY_V12);
addOpenTxCommonOptions(firmware);
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* HelloRadioSky V14 board */
firmware = new OpenTxFirmware(FIRMWAREID("v14"), Firmware::tr("HelloRadioSky V14"), BOARD_HELLORADIOSKY_V14);
firmware = new OpenTxFirmware(FIRMWAREID("v14"), Firmware::tr("V14"), BOARD_HELLORADIOSKY_V14);
addOpenTxCommonOptions(firmware);
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* HelloRadioSky V14LCD board */
firmware = new OpenTxFirmware(FIRMWAREID("v14lcd"), Firmware::tr("HelloRadioSky V14LCD"), BOARD_HELLORADIOSKY_V14LCD);
firmware = new OpenTxFirmware(FIRMWAREID("v14lcd"), Firmware::tr("V14LCD"), BOARD_HELLORADIOSKY_V14LCD);
addOpenTxCommonOptions(firmware);
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* HelloRadioSky V16 board */
firmware = new OpenTxFirmware(FIRMWAREID("v16"), Firmware::tr("HelloRadioSky V16"), BOARD_HELLORADIOSKY_V16);
firmware = new OpenTxFirmware(FIRMWAREID("v16"), Firmware::tr("V16"), BOARD_HELLORADIOSKY_V16);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
registerOpenTxFirmware(firmware);
/* iFlight Commando8 board */
firmware = new OpenTxFirmware(FIRMWAREID("commando8"), QCoreApplication::translate("Firmware", "iFlight Commando 8"), BOARD_IFLIGHT_COMMANDO8);
firmware = new OpenTxFirmware(FIRMWAREID("commando8"), Firmware::tr("Commando 8"), BOARD_IFLIGHT_COMMANDO8);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -535,13 +537,13 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, NONE);
/* iFlight Commando 14 board */
firmware = new OpenTxFirmware(FIRMWAREID("c14"), Firmware::tr("iFlight Commando 14"), BOARD_IFLIGHT_COMMANDO14);
firmware = new OpenTxFirmware(FIRMWAREID("c14"), Firmware::tr("Commando 14"), BOARD_IFLIGHT_COMMANDO14);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
/* Jumper T-Lite board */
firmware = new OpenTxFirmware(FIRMWAREID("tlite"), QCoreApplication::translate("Firmware", "Jumper T-Lite"), BOARD_JUMPER_TLITE);
firmware = new OpenTxFirmware(FIRMWAREID("tlite"), Firmware::tr("T-Lite"), BOARD_JUMPER_TLITE);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -551,7 +553,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T-Pro board */
firmware = new OpenTxFirmware(FIRMWAREID("tpro"), QCoreApplication::translate("Firmware", "Jumper T-Pro"), BOARD_JUMPER_TPRO);
firmware = new OpenTxFirmware(FIRMWAREID("tpro"), Firmware::tr("T-Pro"), BOARD_JUMPER_TPRO);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -561,7 +563,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T-Pro V2 board */
firmware = new OpenTxFirmware(FIRMWAREID("tprov2"), QCoreApplication::translate("Firmware", "Jumper T-Pro V2"), BOARD_JUMPER_TPROV2);
firmware = new OpenTxFirmware(FIRMWAREID("tprov2"), Firmware::tr("T-Pro V2"), BOARD_JUMPER_TPROV2);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -571,7 +573,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T-Pro S board */
firmware = new OpenTxFirmware(FIRMWAREID("tpros"), QCoreApplication::translate("Firmware", "Jumper T-Pro S"), BOARD_JUMPER_TPROS);
firmware = new OpenTxFirmware(FIRMWAREID("tpros"), Firmware::tr("T-Pro S"), BOARD_JUMPER_TPROS);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -581,7 +583,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper Bumblebee board */
firmware = new OpenTxFirmware(FIRMWAREID("bumblebee"), QCoreApplication::translate("Firmware", "Jumper Bumblebee"), BOARD_JUMPER_BUMBLEBEE);
firmware = new OpenTxFirmware(FIRMWAREID("bumblebee"), Firmware::tr("Bumblebee"), BOARD_JUMPER_BUMBLEBEE);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -591,7 +593,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T12 board */
firmware = new OpenTxFirmware(FIRMWAREID("t12"), QCoreApplication::translate("Firmware", "Jumper T12 / T12 Pro"), BOARD_JUMPER_T12);
firmware = new OpenTxFirmware(FIRMWAREID("t12"), Firmware::tr("T12 / T12 Pro"), BOARD_JUMPER_T12);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -602,39 +604,39 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T12 MAX board */
firmware = new OpenTxFirmware(FIRMWAREID("t12max"), Firmware::tr("Jumper T12 MAX"), BOARD_JUMPER_T12MAX);
firmware = new OpenTxFirmware(FIRMWAREID("t12max"), Firmware::tr("T12 MAX"), BOARD_JUMPER_T12MAX);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalelrs", Firmware::tr("Select if internal ELRS module is installed"));
addOpenTxRfOptions(firmware, NONE);
registerOpenTxFirmware(firmware);
/* Jumper T14 board */
firmware = new OpenTxFirmware(FIRMWAREID("t14"), Firmware::tr("Jumper T14"), BOARD_JUMPER_T14);
firmware = new OpenTxFirmware(FIRMWAREID("t14"), Firmware::tr("T14"), BOARD_JUMPER_T14);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalelrs", Firmware::tr("Select if internal ELRS module is installed"));
addOpenTxRfOptions(firmware, NONE);
registerOpenTxFirmware(firmware);
/* Jumper T15 board */
firmware = new OpenTxFirmware(FIRMWAREID("t15"), Firmware::tr("Jumper T15"), BOARD_JUMPER_T15);
firmware = new OpenTxFirmware(FIRMWAREID("t15"), Firmware::tr("T15"), BOARD_JUMPER_T15);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
/* Jumper T15 Pro board */
firmware = new OpenTxFirmware(FIRMWAREID("t15pro"), Firmware::tr("Jumper T15 Pro"), BOARD_JUMPER_T15PRO);
firmware = new OpenTxFirmware(FIRMWAREID("t15pro"), Firmware::tr("T15 Pro"), BOARD_JUMPER_T15PRO);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
/* Jumper T22 board */
firmware = new OpenTxFirmware(FIRMWAREID("t22"), Firmware::tr("Jumper T22"), BOARD_JUMPER_T22);
firmware = new OpenTxFirmware(FIRMWAREID("t22"), Firmware::tr("T22"), BOARD_JUMPER_T22);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
/* Jumper T16 board */
firmware = new OpenTxFirmware(FIRMWAREID("t16"), Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
firmware = new OpenTxFirmware(FIRMWAREID("t16"), Firmware::tr("T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
firmware->addOption(opt_bt);
@@ -642,28 +644,28 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
/* Jumper T18 board */
firmware = new OpenTxFirmware(FIRMWAREID("t18"), Firmware::tr("Jumper T18"), BOARD_JUMPER_T18);
firmware = new OpenTxFirmware(FIRMWAREID("t18"), Firmware::tr("T18"), BOARD_JUMPER_T18);
addOpenTxFrskyOptions(firmware);
firmware->addOption(opt_bt);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T20 board */
firmware = new OpenTxFirmware(FIRMWAREID("t20"), Firmware::tr("Jumper T20"), BOARD_JUMPER_T20);
firmware = new OpenTxFirmware(FIRMWAREID("t20"), Firmware::tr("T20"), BOARD_JUMPER_T20);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalelrs", Firmware::tr("Select if internal ELRS module is installed"));
addOpenTxRfOptions(firmware, NONE);
registerOpenTxFirmware(firmware);
/* Jumper T20 V2 board */
firmware = new OpenTxFirmware(FIRMWAREID("t20v2"), Firmware::tr("Jumper T20 V2"), BOARD_JUMPER_T20V2);
firmware = new OpenTxFirmware(FIRMWAREID("t20v2"), Firmware::tr("T20 V2"), BOARD_JUMPER_T20V2);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalelrs", Firmware::tr("Select if internal ELRS module is installed"));
addOpenTxRfOptions(firmware, NONE);
registerOpenTxFirmware(firmware);
/* Radiomaster Boxer board */
firmware = new OpenTxFirmware(FIRMWAREID("boxer"), QCoreApplication::translate("Firmware", "Radiomaster Boxer"), Board::BOARD_RADIOMASTER_BOXER);
firmware = new OpenTxFirmware(FIRMWAREID("boxer"), Firmware::tr("Boxer"), Board::BOARD_RADIOMASTER_BOXER);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -673,7 +675,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
/* Radiomaster Pocket board */
firmware = new OpenTxFirmware(FIRMWAREID("pocket"), QCoreApplication::translate("Firmware", "Radiomaster Pocket"), Board::BOARD_RADIOMASTER_POCKET);
firmware = new OpenTxFirmware(FIRMWAREID("pocket"), Firmware::tr("Pocket"), Board::BOARD_RADIOMASTER_POCKET);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -683,7 +685,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
/* Radiomaster MT12 board */
firmware = new OpenTxFirmware(FIRMWAREID("mt12"), QCoreApplication::translate("Firmware", "Radiomaster MT12"), Board::BOARD_RADIOMASTER_MT12);
firmware = new OpenTxFirmware(FIRMWAREID("mt12"), Firmware::tr("MT12"), Board::BOARD_RADIOMASTER_MT12);
addOpenTxCommonOptions(firmware);
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
@@ -692,7 +694,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, NONE);
/* Radiomaster T8 board */
firmware = new OpenTxFirmware(FIRMWAREID("t8"), QCoreApplication::translate("Firmware", "Radiomaster T8"), BOARD_RADIOMASTER_T8);
firmware = new OpenTxFirmware(FIRMWAREID("t8"), Firmware::tr("T8"), BOARD_RADIOMASTER_T8);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -703,7 +705,7 @@ void registerOpenTxFirmwares()
firmware->addOption("bindkey", Firmware::tr("Allow bind using bind key"));
/* Radiomaster TX12 board */
firmware = new OpenTxFirmware(FIRMWAREID("tx12"), QCoreApplication::translate("Firmware", "Radiomaster TX12"), BOARD_RADIOMASTER_TX12);
firmware = new OpenTxFirmware(FIRMWAREID("tx12"), Firmware::tr("TX12"), BOARD_RADIOMASTER_TX12);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -713,7 +715,7 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Radiomaster TX12 Mark II board */
firmware = new OpenTxFirmware(FIRMWAREID("tx12mk2"), QCoreApplication::translate("Firmware", "Radiomaster TX12 Mark II"), BOARD_RADIOMASTER_TX12_MK2);
firmware = new OpenTxFirmware(FIRMWAREID("tx12mk2"), Firmware::tr("TX12 Mark II"), BOARD_RADIOMASTER_TX12_MK2);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -723,14 +725,14 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX);
/* Radiomaster GX12 board */
firmware = new OpenTxFirmware(FIRMWAREID("gx12"), QCoreApplication::translate("Firmware", "Radiomaster GX12"), BOARD_RADIOMASTER_GX12);
firmware = new OpenTxFirmware(FIRMWAREID("gx12"), Firmware::tr("GX12"), BOARD_RADIOMASTER_GX12);
addOpenTxCommonOptions(firmware);
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* Radiomaster TX15 board */
firmware = new OpenTxFirmware(FIRMWAREID("tx15"), Firmware::tr("Radiomaster TX15"), BOARD_RADIOMASTER_TX15);
firmware = new OpenTxFirmware(FIRMWAREID("tx15"), Firmware::tr("TX15"), BOARD_RADIOMASTER_TX15);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
@@ -744,7 +746,7 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
/* Radiomaster TX16S board */
firmware = new OpenTxFirmware(FIRMWAREID("tx16s"), Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S);
firmware = new OpenTxFirmware(FIRMWAREID("tx16s"), Firmware::tr("TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
@@ -752,14 +754,14 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
/* Radiomaster TX16SMK3 board */
firmware = new OpenTxFirmware(FIRMWAREID("tx16smk3"), Firmware::tr("Radiomaster TX16S MK3"), BOARD_RADIOMASTER_TX16SMK3);
firmware = new OpenTxFirmware(FIRMWAREID("tx16smk3"), Firmware::tr("TX16S MK3"), BOARD_RADIOMASTER_TX16SMK3);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
registerOpenTxFirmware(firmware);
/* Radiomaster Zorro board */
firmware = new OpenTxFirmware(FIRMWAREID("zorro"), QCoreApplication::translate("Firmware", "Radiomaster Zorro"), Board::BOARD_RADIOMASTER_ZORRO);
firmware = new OpenTxFirmware(FIRMWAREID("zorro"), Firmware::tr("Zorro"), Board::BOARD_RADIOMASTER_ZORRO);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
@@ -31,7 +31,7 @@ class OpenTxFirmware: public Firmware
public:
OpenTxFirmware(const QString & id, OpenTxFirmware * parent):
Firmware(parent, id, parent->getName(), parent->getBoard(),
Firmware(parent, id, parent->getShortName(), parent->getBoard(),
parent->getDownloadId(), parent->getSimulatorId(), parent->getHwDefnId())
{
}
+1 -1
View File
@@ -33,7 +33,7 @@
#include <QTimer>
FlashFirmwareDialog::FlashFirmwareDialog(QWidget *parent) :
FlashFirmwareDialog::FlashFirmwareDialog(QWidget * parent) :
QDialog(parent),
ui(new Ui::FlashFirmwareDialog),
fwName(g.profile[g.id()].fwName()),
+1 -1
View File
@@ -33,7 +33,7 @@ class FlashFirmwareDialog : public QDialog
Q_OBJECT
public:
FlashFirmwareDialog(QWidget *parent = 0);
FlashFirmwareDialog(QWidget * parent = nullptr);
~FlashFirmwareDialog();
private slots:
+3 -3
View File
@@ -266,10 +266,10 @@ void Helpers::getFileComboBoxValue(QComboBox * b, char * dest, int length)
}
}
void Helpers::exportAppSettings(QWidget * dlgParent)
void Helpers::exportPreferences(QWidget * dlgParent)
{
static QString lastExpFile = CPN_SETTINGS_INI_PATH.arg(QDateTime::currentDateTime().toString("dd-MMM-yy"));
const QString expFile = QFileDialog::getSaveFileName(dlgParent, QCoreApplication::translate("Companion", "Select or create a file for exported Settings:"), lastExpFile, CPN_STR_APP_SETTINGS_FILTER);
const QString expFile = QFileDialog::getSaveFileName(dlgParent, QCoreApplication::translate("Companion", "Select or create a file for exported Preferences:"), lastExpFile, CPN_STR_APP_SETTINGS_FILTER);
if (expFile.isEmpty())
return;
@@ -281,7 +281,7 @@ void Helpers::exportAppSettings(QWidget * dlgParent)
}
resultMsg.append("\n" % QCoreApplication::translate("Companion", "Press the 'Retry' button to choose another file."));
if (QMessageBox::warning(dlgParent, CPN_STR_APP_NAME, resultMsg, QMessageBox::Cancel, QMessageBox::Retry) == QMessageBox::Retry)
exportAppSettings(dlgParent);
exportPreferences(dlgParent);
}
unsigned int Helpers::getBitmappedValue(const unsigned int & field, const unsigned int index, const unsigned int numbits, const unsigned int offset)
+1 -1
View File
@@ -109,7 +109,7 @@ namespace Helpers
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
void exportAppSettings(QWidget * dlgParent = nullptr);
void exportPreferences(QWidget * dlgParent = nullptr);
QString removeAccents(const QString & str);
unsigned int getBitmappedValue(const unsigned int & field, const unsigned int index = 0, const unsigned int numbits = 1, const unsigned int offset = 0);
+33 -35
View File
@@ -23,7 +23,7 @@
#include "mdichild.h"
#include "comparedialog.h"
#include "logsdialog.h"
#include "apppreferencesdialog.h"
#include "prefs_edit.h"
#include "firmwareinterface.h"
#include "printdialog.h"
#include "version.h"
@@ -451,15 +451,13 @@ void MainWindow::loadProfile()
}
}
void MainWindow::editAppSettings()
void MainWindow::editPreferences()
{
AppPreferencesDialog * dialog = new AppPreferencesDialog(this, updateFactories);
dialog->setMainWinHasDirtyChild(anyChildrenDirty());
connect(dialog, &AppPreferencesDialog::firmwareProfileAboutToChange, this, &MainWindow::saveAll);
connect(dialog, &AppPreferencesDialog::firmwareProfileChanged, this, &MainWindow::onCurrentProfileChanged);
dialog->exec();
dialog->deleteLater();
updateMenus();
PrefsEditDialog * dlg = new PrefsEditDialog(this, updateFactories);
dlg->setMainWinHasDirtyChild(anyChildrenDirty());
connect(dlg, &PrefsEditDialog::profileFirmwareAboutToChange, this, &MainWindow::saveAll);
connect(dlg, &PrefsEditDialog::profileFirmwareChanged, this, &MainWindow::onCurrentProfileChanged);
dlg->exec();
}
void MainWindow::sdsync(bool postUpdate)
@@ -815,9 +813,9 @@ void MainWindow::retranslateUi(bool showMsg)
trAct(readSettingsSDPathAct, tr("Read Models and Settings from SD Path"), tr("Read Models and Settings from SD Path"));
trAct(exitAct, tr("Exit"), tr("Exit the application"));
trAct(editAppSettingsAct, tr("Edit Settings..."), tr("Edit %1 and Simulator settings (including radio profiles) settings").arg(CPN_STR_APP_NAME));
trAct(exportAppSettingsAct, tr("Export Settings..."), tr("Save all the current %1 and Simulator settings (including radio profiles) to a file.").arg(CPN_STR_APP_NAME));
trAct(importAppSettingsAct, tr("Import Settings..."), tr("Load %1 and Simulator settings from a prevously exported settings file.").arg(CPN_STR_APP_NAME));
trAct(editPreferencesAct, tr("Edit Preferences..."), tr("Edit %1 and Simulator preferences (including radio profiles) settings").arg(CPN_STR_APP_NAME));
trAct(exportPreferencesAct, tr("Export Settings..."), tr("Save all the current %1 and Simulator preferences (including radio profiles) to a file.").arg(CPN_STR_APP_NAME));
trAct(importPreferencesAct, tr("Import Settings..."), tr("Load %1 and Simulator preferences from a prevously exported settings file.").arg(CPN_STR_APP_NAME));
trAct(editSplashAct, tr("Edit Radio Splash Image..."), tr("Edit the splash image of your Radio"));
trAct(readFlashAct, tr("Read Firmware from Radio"), tr("Read firmware from Radio"));
@@ -889,9 +887,9 @@ void MainWindow::createActions()
readSettingsSDPathAct = addAct("folder-tree-read.png", SLOT(readSettingsSDPath()));
exitAct = addAct("exit.png", SLOT(closeAllWindows()), QKeySequence::Quit, qApp);
editAppSettingsAct = addAct("apppreferences.png", SLOT(editAppSettings()), QKeySequence::Preferences);
exportAppSettingsAct = addAct("saveas.png", SLOT(exportAppSettings()));
importAppSettingsAct = addAct("open.png", SLOT(importAppSettings()));
editPreferencesAct = addAct("apppreferences.png", SLOT(editPreferences()), QKeySequence::Preferences);
exportPreferencesAct = addAct("saveas.png", SLOT(exportPreferences()));
importPreferencesAct = addAct("open.png", SLOT(importPreferences()));
radioGetDevicesAct = addAct("configure.png", SLOT(radioGetDevices()));
compareAct = addAct("compare.png", SLOT(compare()), tr("Ctrl+Alt+R"));
@@ -929,7 +927,7 @@ void MainWindow::createActions()
exitAct->setMenuRole(QAction::QuitRole);
aboutAct->setMenuRole(QAction::AboutRole);
editAppSettingsAct->setMenuRole(QAction::PreferencesRole);
editPreferencesAct->setMenuRole(QAction::PreferencesRole);
changelogAct->setMenuRole(QAction::ApplicationSpecificRole);
compareAct->setEnabled(false);
@@ -1001,9 +999,9 @@ void MainWindow::createMenus()
radioMenu->addAction(radioGetDevicesAct);
settingsMenu = menuBar()->addMenu("");
settingsMenu->addAction(editAppSettingsAct);
settingsMenu->addAction(exportAppSettingsAct);
settingsMenu->addAction(importAppSettingsAct);
settingsMenu->addAction(editPreferencesAct);
settingsMenu->addAction(exportPreferencesAct);
settingsMenu->addAction(importPreferencesAct);
settingsMenu->addSeparator();
settingsMenu->addAction(profilesMenuAct);
@@ -1087,7 +1085,7 @@ void MainWindow::createToolBars()
settingsToolBar = addToolBar("");
settingsToolBar->setObjectName("Settings");
settingsToolBar->addAction(editAppSettingsAct);
settingsToolBar->addAction(editPreferencesAct);
settingsToolBar->addAction(profilesMenuAct);
if ((btn = qobject_cast<QToolButton *>(settingsToolBar->widgetForAction(profilesMenuAct))))
@@ -1325,7 +1323,7 @@ int MainWindow::newProfile(bool loadProfile)
if (loadProfile) {
if (loadProfileId(i))
editAppSettings();
editPreferences();
}
return i;
@@ -1344,7 +1342,7 @@ void MainWindow::copyProfile()
g.profile[newId] = g.profile[g.id()];
g.profile[newId].name(g.profile[newId].name() + tr(" - Copy"));
if (loadProfileId(newId))
editAppSettings();
editPreferences();
}
}
@@ -1379,26 +1377,26 @@ void MainWindow::deleteCurrentProfile()
deleteProfile(g.id());
}
void MainWindow::exportAppSettings()
void MainWindow::exportPreferences()
{
Helpers::exportAppSettings();
Helpers::exportPreferences();
}
void MainWindow::importAppSettings()
void MainWindow::importPreferences()
{
if (anyChildrenDirty()) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Please save or close all modified files before importing settings"));
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Please save or close all modified files before importing preferences"));
return;
}
QString resultMsg = tr("<html>" \
"<p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. " \
"This will replace current settings with any settings found in the file.</p>" \
"<p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p>" \
"<p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p>" \
"<p>%1 and Simulator preferences can be imported (restored) from a previosly saved export (backup) file. " \
"This will replace current preferences with any preferences found in the file.</p>" \
"<p>An automatic backup of the current preferences will be attempted. But if the current preferences are useful then it is recommended that you make a manual backup first.</p>" \
"<p>For best results when importing preferences, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p>" \
"<p>Do you wish to continue?</p>" \
"</html>").arg(CPN_STR_APP_NAME);
int ret = QMessageBox::question(this, tr("Confirm Settings Import"), resultMsg);
int ret = QMessageBox::question(this, tr("Confirm Preferences Import"), resultMsg);
if (ret != QMessageBox::Yes)
return;
@@ -1420,17 +1418,17 @@ void MainWindow::importAppSettings()
// Do the import
QSettings fromSettings(impFile, QSettings::IniFormat);
if (!g.importSettings(&fromSettings)) {
QMessageBox::critical(this, CPN_STR_APP_NAME, tr("The settings could not be imported."), QMessageBox::Ok);
QMessageBox::critical(this, CPN_STR_APP_NAME, tr("The preferences could not be imported."), QMessageBox::Ok);
return;
}
resultMsg = tr("<html>" \
"<p>New settings have been imported from:<br> %1.</p>" \
"<p>New preferences have been imported from:<br> %1.</p>" \
"<p>%2 will now re-initialize.</p>" \
"<p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p>" \
"<p>Note that you may need to close and restart %2 before some preferences like language and icon theme take effect.</p>" \
).arg(impFile).arg(CPN_STR_APP_NAME);
if (!expFile.isEmpty())
resultMsg.append(tr("<p>The previous settings were backed up to:<br> %1</p>").arg(expFile));
resultMsg.append(tr("<p>The previous preferences were backed up to:<br> %1</p>").arg(expFile));
resultMsg.append("</html>");
QMessageBox::information(this, CPN_STR_APP_NAME, resultMsg);
+6 -6
View File
@@ -104,9 +104,9 @@ class MainWindow : public QMainWindow
void copyProfile();
void deleteProfile(const int pid);
void deleteCurrentProfile();
void editAppSettings();
void exportAppSettings();
void importAppSettings();
void editPreferences();
void exportPreferences();
void importPreferences();
void autoClose();
void chooseProfile();
void autoCheckForUpdates();
@@ -199,7 +199,7 @@ class MainWindow : public QMainWindow
QAction *closeAct;
QAction *recentFilesAct;
QAction *exitAct;
QAction *editAppSettingsAct;
QAction *editPreferencesAct;
QAction *updatesAct;
QAction *manualChkForUpdAct;
QAction *sdsyncAct;
@@ -219,8 +219,8 @@ class MainWindow : public QMainWindow
QAction *createProfileAct;
QAction *copyProfileAct;
QAction *deleteProfileAct;
QAction *exportAppSettingsAct;
QAction *importAppSettingsAct;
QAction *exportPreferencesAct;
QAction *importPreferencesAct;
QAction *tabbedWindowsAct;
QAction *tileWindowsAct;
QAction *cascadeWindowsAct;
+31
View File
@@ -0,0 +1,31 @@
project(prefsedit)
set(${PROJECT_NAME}_NAMES
prefs_panel
prefs_edit
prefs_app
prefs_profile
prefs_simu
prefs_update
)
AddHeadersSources()
add_library(${PROJECT_NAME}
${${PROJECT_NAME}_HDRS}
${${PROJECT_NAME}_SRCS}
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
${CPN_COMMON_LIB}
)
target_include_directories(${PROJECT_NAME}
PRIVATE
"${CMAKE_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}"
)
+294
View File
@@ -0,0 +1,294 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_app.h"
#include "ui_prefs_app.h"
#include "appdata.h"
PrefsAppPanel::PrefsAppPanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof) :
PrefsPanel(parent, fw, bd, prof),
ui(new Ui::PrefsApp)
{
lock = true;
ui->setupUi(this);
sectionGeneral();
sectionRadioProfiles();
sectionFolders();
sectionLogging();
sectionGoogleEarth();
sectionSplashScreens();
update();
shrink();
lock = false;
}
PrefsAppPanel::~PrefsAppPanel()
{
delete ui;
}
void PrefsAppPanel::save()
{
AbstractPanel::save();
}
void PrefsAppPanel::sectionFolders()
{
QGridLayout *layFolders = ui->csectFolders->start(tr("Folders"));
row = col = 0;
AutoLabel *lblBackupsPath = new AutoLabel(this, tr("Backups"));
layFolders->addWidget(lblBackupsPath, row, col++);
leBackupsPath = newPathWidget(this);
leBackupsPath->setValue(g.backupDir());
leBackupsPath->setBindSave([this] {
g.backupDir(this->leBackupsPath->text());
});
layFolders->addWidget(leBackupsPath, row, col++);
AutoDirectorySelectButton *btnBackupsPath = new AutoDirectorySelectButton(this);
btnBackupsPath->setup(tr("Select backups folder"), g.backupDir(), leBackupsPath);;
layFolders->addWidget(btnBackupsPath, row, col++);
++row; col = 0;
AutoLabel *lblLogsPath = new AutoLabel(this, tr("Logs"));
layFolders->addWidget(lblLogsPath, row, col++);
leLogsPath = newPathWidget(this);
leLogsPath->setValue(g.logDir());
leLogsPath->setBindSave([this] {
g.logDir(this->leLogsPath->text());
});
layFolders->addWidget(leLogsPath, row, col++);
AutoDirectorySelectButton *btnLogsPath = new AutoDirectorySelectButton(this);
btnLogsPath->setup(tr("Select logs folder"), g.logDir(), leLogsPath);;
layFolders->addWidget(btnLogsPath, row, col++);
/* TODO implement
++row; col = 0;
AutoLabel *lblSDPath = new AutoLabel(this, tr("Models"));
layFolders->addWidget(lblSDPath, row, col++);
leModelsPath = newPathWidget(this);
leModelsPath->setValue(g.modelsDir());
leModelsPath->setBindSave([this] {
g.modelsDir(this->leModelsPath->text());
});
layFolders->addWidget(leModelsPath, row, col++);
AutoDirectorySelectButton *btnModelsPath = new AutoDirectorySelectButton(this);
btnModelsPath->setup(tr("Select models folder"), g.modelsDir(), leModelsPath);;
layFolders->addWidget(btnModelsPath, row, col++);
*/
ui->csectFolders->finish(-1, -1, [this] { this->shrink(); });
}
void PrefsAppPanel::sectionGeneral()
{
QGridLayout *layGeneral = ui->csectGeneral->start(tr("General"));
row = col = 0;
AutoLabel *lblShowSplash = new AutoLabel(this, tr("Show splash screen"));
layGeneral->addWidget(lblShowSplash, row, col++);
chkSplash = new AutoCheckBox(this);
chkSplash->setValue(g.showSplash());
chkSplash->setBindSave([this] {
g.showSplash(this->chkSplash->isChecked());
});
layGeneral->addWidget(chkSplash, row, col++);
++row; col = 0;
AutoLabel *lblProfPrmpt = new AutoLabel(this, tr("Prompt for radio profile on startup"));
layGeneral->addWidget(lblProfPrmpt, row, col++);
chkProfPrmpt = new AutoCheckBox(this);
chkProfPrmpt->setValue(g.promptProfile());
chkProfPrmpt->setBindSave([this] {
g.promptProfile(this->chkProfPrmpt->isChecked());
});
layGeneral->addWidget(chkProfPrmpt, row, col++);
++row; col = 0;
AutoLabel *lblRecentFiles = new AutoLabel(this, tr("Most recently used files"));
layGeneral->addWidget(lblRecentFiles, row, col++);
sbxRecentFiles = new AutoSpinBox(this);
sbxRecentFiles->setRange(1, 50);
sbxRecentFiles->setValue(g.historySize());
sbxRecentFiles->setBindSave([this] {
g.historySize(this->sbxRecentFiles->value());
});
layGeneral->addWidget(sbxRecentFiles, row, col++);
++row; col = 0;
AutoLabel *lblModelNew = new AutoLabel(this, tr("New models action"));
layGeneral->addWidget(lblModelNew, row, col++);
cboModelNew = new AutoComboBox(this);
cboModelNew->addItems(AppData::newModelActionsList());
cboModelNew->setValue((int)g.newModelAction());
cboModelNew->setBindSave([this] {
g.newModelAction((AppData::NewModelAction)this->cboModelNew->currentData().toInt());
});
layGeneral->addWidget(cboModelNew, row, col++);
// TODO implement profile level setting as override
++row; col = 0;
AutoLabel *lblModelDelete = new AutoLabel(this, tr("B&W remove empty slot on delete)"));
layGeneral->addWidget(lblModelDelete, row, col++);
chkModelDelete = new AutoCheckBox(this);
chkModelDelete->setValue(g.removeModelSlots());
chkModelDelete->setBindSave([this] {
g.removeModelSlots(this->chkModelDelete->isChecked());
});
layGeneral->addWidget(chkModelDelete, row, col++);
ui->csectGeneral->finish(row, col, [this] { this->shrink(); }, true);
}
void PrefsAppPanel::sectionGoogleEarth()
{
QGridLayout *layGoogle = ui->csectGoogleEarth->start(tr("Google Earth"));
row = col = 0;
AutoLabel *lblGoogleExe = new AutoLabel(this, tr("Executable"));
layGoogle->addWidget(lblGoogleExe, row, col++);
leGoogleExe = newPathWidget(this);
leGoogleExe->setValue(g.gePath());
leGoogleExe->setBindSave([this] {
g.gePath(this->leGoogleExe->text());
});
layGoogle->addWidget(leGoogleExe, row, col++);
AutoFileSelectButton *btnGoogleExe = new AutoFileSelectButton(this);
btnGoogleExe->setup(tr("Select Google Earth executable"), g.gePath(), "", leGoogleExe);;
layGoogle->addWidget(btnGoogleExe, row, col++);
ui->csectGoogleEarth->finish(-1, -1, [this] { this->shrink(); });
}
void PrefsAppPanel::sectionLogging()
{
QGridLayout *layLogging = ui->csectLogging->start(tr("Logging"));
row = col = 0;
AutoLabel *lblLogApp = new AutoLabel(this, tr("Application (Companion/Simulator)"));
layLogging->addWidget(lblLogApp, row, col++);
chkLogApp = new AutoCheckBox(this);
chkLogApp->setValue(g.appDebugLog());
chkLogApp->setBindSave([this] {
g.appDebugLog(this->chkLogApp->isChecked());
});
layLogging->addWidget(chkLogApp, row, col++);
++row; col = 0;
AutoLabel *lblLogFW = new AutoLabel(this, tr("Radio Firmware (in Simulator)"));
layLogging->addWidget(lblLogFW, row, col++);
chkLogFW = new AutoCheckBox(this);
chkLogFW->setValue(g.fwTraceLog());
chkLogFW->setBindSave([this] {
g.fwTraceLog(this->chkLogFW->isChecked());
});
layLogging->addWidget(chkLogFW, row, col++);
ui->csectLogging->finish(row, col, [this] { this->shrink(); });
}
void PrefsAppPanel::sectionRadioProfiles()
{
QGridLayout *layProfiles = ui->csectProfiles->start(tr("Radio Profiles"));
row = col = 0;
chkProfileTop = new AutoCheckBox(this, tr("Move selected profile to the top of the list"));
chkProfileTop->setValue(g.sortProfiles());
chkProfileTop->setBindSave([this] {
g.sortProfiles(this->chkProfileTop->isChecked());
});
layProfiles->addWidget(chkProfileTop, row, col++);
++row; col = 0;
chkBackupFirmware = new AutoCheckBox(this, tr("Prompt to backup current firmware before flashing new firmware"));
chkBackupFirmware->setValue(g.enableBackup());
chkBackupFirmware->setBindSave([this] {
g.enableBackup(this->chkBackupFirmware->isChecked());
});
layProfiles->addWidget(chkBackupFirmware, row, col++);
++row; col = 0;
chkUseSavedSettings = new AutoCheckBox(this, tr("Use radio settings backup for new models and settings files"));
chkUseSavedSettings->setValue(g.useSavedSettings());
chkUseSavedSettings->setBindSave([this] {
g.useSavedSettings(this->chkUseSavedSettings->isChecked());
});
layProfiles->addWidget(chkUseSavedSettings, row, col++);
++row; col = 0;
chkConfirmDeleteWrite = new AutoCheckBox(this, tr("Do not prompt to delete exisiting models on write to radio or SD path"));
chkConfirmDeleteWrite->setValue(g.confirmWriteModelsAndSettings());
chkConfirmDeleteWrite->setBindSave([this] {
g.confirmWriteModelsAndSettings(this->chkConfirmDeleteWrite->isChecked());
});
layProfiles->addWidget(chkConfirmDeleteWrite, row, col++);
ui->csectProfiles->finish(row, col, [this] { this->shrink(); });
}
void PrefsAppPanel::sectionSplashScreens()
{
QGridLayout *laySplash = ui->csectSplash->start(tr("Splash Screens (B&&W radios)"));
row = col = 0;
AutoLabel *lblSplashLibraries = new AutoLabel(this, tr("Libraries"));
laySplash->addWidget(lblSplashLibraries, row, col++);
cboSplashLibraries = new AutoComboBox(this);
cboSplashLibraries->addItems(AppData::splashLibsList());
cboSplashLibraries->setValue(g.embedSplashes());
cboSplashLibraries->setBindSave([this] {
g.embedSplashes(this->cboSplashLibraries->currentData().toInt());
});
laySplash->addWidget(cboSplashLibraries, row, col++);
++row; col = 0;
AutoLabel *lblSplashUserPath = new AutoLabel(this, tr("User folder"));
laySplash->addWidget(lblSplashUserPath, row, col++);
leSplashUserPath = newPathWidget(this);
leSplashUserPath->setValue(g.libDir());
leSplashUserPath->setBindSave([this] {
g.libDir(this->leSplashUserPath->text());
});
laySplash->addWidget(leSplashUserPath, row, col++);
AutoDirectorySelectButton *btnSplashUser = new AutoDirectorySelectButton(this);
btnSplashUser->setup(tr("Select user splash folder"), g.libDir(), leSplashUserPath);;
laySplash->addWidget(btnSplashUser, row, col++);
ui->csectSplash->finish(-1, -1, [this] { this->shrink(); });
}
void PrefsAppPanel::update()
{
AbstractPanel::update();
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "prefs_edit.h"
namespace Ui {
class PrefsApp;
}
class PrefsAppPanel : public PrefsPanel
{
Q_OBJECT
public:
PrefsAppPanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof);
virtual ~PrefsAppPanel();
virtual void save() override;
virtual void update() override;
private:
Ui::PrefsApp * ui;
AutoCheckBox *chkSplash;
AutoCheckBox *chkProfPrmpt;
AutoSpinBox *sbxRecentFiles;
AutoComboBox *cboModelNew;
AutoCheckBox *chkModelDelete;
AutoCheckBox *chkProfileTop;
AutoCheckBox *chkBackupFirmware;
AutoCheckBox *chkUseSavedSettings;
AutoCheckBox *chkConfirmDeleteWrite;
AutoLineEdit *leModelsPath;
AutoLineEdit *leBackupsPath;
AutoLineEdit *leLogsPath;
AutoCheckBox *chkLogApp;
AutoCheckBox *chkLogFW;
AutoComboBox *cboLogLevel;
AutoCheckBox *chkLogVerbose;
AutoLineEdit *leGoogleExe;
AutoComboBox *cboSplashLibraries;
AutoLineEdit *leSplashUserPath;
void sectionFolders();
void sectionGeneral();
void sectionGoogleEarth();
void sectionLogging();
void sectionRadioProfiles();
void sectionSplashScreens();
};
+60
View File
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefsApp</class>
<widget class="QWidget" name="PrefsApp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>648</width>
<height>132</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="AutoCollapsibleSection" name="csectGeneral" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectProfiles" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectFolders" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectLogging" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectGoogleEarth" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectSplash" native="true"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoCollapsibleSection</class>
<extends>QWidget</extends>
<header>autocollapsiblesection.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+208
View File
@@ -0,0 +1,208 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_edit.h"
#include "prefs_profile.h"
#include "prefs_app.h"
#include "prefs_simu.h"
#include "prefs_update.h"
#include "ui_prefs_edit.h"
#include "helpers.h"
#include <QMessageBox>
PrefsEditDialog::PrefsEditDialog(QWidget * parent, UpdateFactories * factories) :
QDialog(parent),
ui(new Ui::PrefsEdit),
mainWinHasDirtyChild(false),
firmware(getCurrentFirmware()),
board(getCurrentBoard()),
profile(g.currentProfile()),
dirty(false)
{
ui->setupUi(this);
setWindowIcon(CompanionIcon("apppreferences.png"));
setAttribute(Qt::WA_DeleteOnClose);
PrefsProfilePanel *prefsProfPanel = new PrefsProfilePanel(this, firmware, board, profile);
addTab(prefsProfPanel, tr("Radio Profile"));
connect(prefsProfPanel, &PrefsProfilePanel::radioChanged, this, &PrefsEditDialog::onRadioChanged);
addTab(new PrefsAppPanel(this, firmware, board, profile), tr("Application"));
addTab(new PrefsSimuPanel(this, firmware, board, profile), tr("Simulator"));
PrefsUpdatePanel *prefsUpdatePanel = new PrefsUpdatePanel(this, firmware, board, profile, factories);
addTab(prefsUpdatePanel, tr("Update"));
connect(prefsProfPanel, &PrefsProfilePanel::sdPathChanged, prefsUpdatePanel, &PrefsUpdatePanel::onSDPathChanged);
bool hasSavedGeo = restoreGeometry(g.prefsEditGeo());
if (!hasSavedGeo)
shrink();
ui->tabWidget->setCurrentIndex(0);
}
PrefsEditDialog::~PrefsEditDialog()
{
delete ui;
}
void PrefsEditDialog::accept()
{
if (!save())
return;
QDialog::accept();
}
void PrefsEditDialog::closeEvent(QCloseEvent *event)
{
if (!maybeSave())
return;
QDialog::closeEvent(event);
}
void PrefsEditDialog::reject()
{
if (!maybeSave())
return;
QDialog::reject();
}
PrefsPanel * PrefsEditDialog::addTab(PrefsPanel * panel, QString text)
{
panels << panel;
PrefsScrollArea *scrollArea = new PrefsScrollArea(ui->tabWidget, panel);
ui->tabWidget->addTab(scrollArea, text);
connect(panel, &PrefsPanel::modified, this, [this] { this->dirty = true; });
return panel;
}
void PrefsEditDialog::done(int r)
{
if (!isMaximized())
g.prefsEditGeo(saveGeometry());
QDialog::done(r);
}
bool PrefsEditDialog::maybeSave()
{
if (dirty) {
int ret = QMessageBox::question(this, tr("Edit Preferences"),
tr("Preferences have been modified.\nDo you want to save your changes?"),
(QMessageBox::Save | QMessageBox::Discard), QMessageBox::Save);
if (ret == QMessageBox::Save)
return save();
}
return true;
}
bool PrefsEditDialog::save()
{
if (dirty) {
bool fwchange = false;
// If a new fw type has been choosen, several things need to reset
if (getCurrentFirmware()->getFirmwareBase()->getId() != firmware->getFirmwareBase()->getId()) {
// check if we're going to be converting to a new radio type and there are unsaved files in the main window
if (mainWinHasDirtyChild && !Boards::isBoardCompatible(getCurrentBoard(), firmware->getBoard())) {
QString q = tr("<p><b>You cannot change Radio Types while there are unsaved model file changes. What do you wish to do?</b></p> <ul>" \
"<li><i>Save All</i> - save all open model file(s) before saving preferences.<li>" \
"<li><i>Reset</i> - revert Radio Type and Build Options before saving all other preferences.</li>" \
"<li><i>Cancel</i> - return to the editing preferences.</li></ul>");
int resp = QMessageBox::question(this, windowTitle(), q, (QMessageBox::SaveAll | QMessageBox::Reset | QMessageBox::Cancel), QMessageBox::Cancel);
if (resp == QMessageBox::SaveAll) {
// signal main window to save files
// need to do this before the current firmware actually changes
emit profileFirmwareAboutToChange();
fwchange = true;
} else if (resp == QMessageBox::Reset) {
// reset firmware to that at time of dialog ctor
onRadioChanged(getCurrentFirmware());
} else {
// we do not accept the dialog close
return false;
}
} else {
fwchange = true;
}
}
// save preferences for every tab
for (const auto panel : panels)
panel->save();
// prevent re-prompting
dirty = false;
hide();
if (fwchange) {
// do not keep incompatible backup settings
profile.generalSettings(QByteArray());
profile.timeStamp(QString());
// used by flash firmware so no longer applicable
profile.fwName(QString());
emit profileFirmwareChanged();
}
}
return true;
}
void PrefsEditDialog::setMainWinHasDirtyChild(bool value)
{
mainWinHasDirtyChild = value;
}
void PrefsEditDialog::shrink()
{
// adjustSize() only accounts for the currently visible tab, since
// QStackedWidget doesn't lay out hidden pages. Walk every tab once so
// each panel reports its real size hint, and size the dialog to fit
// the largest one so switching tabs later doesn't resize the window.
QSize maxHint;
const int current = ui->tabWidget->currentIndex();
for (int i = 0; i < ui->tabWidget->count(); i++) {
ui->tabWidget->setCurrentIndex(i);
ui->tabWidget->currentWidget()->adjustSize();
maxHint = maxHint.expandedTo(ui->tabWidget->currentWidget()->sizeHint());
}
ui->tabWidget->setCurrentIndex(current);
adjustSize();
resize(maxHint.expandedTo(size()));
}
void PrefsEditDialog::onRadioChanged(Firmware * newFirmware)
{
firmware = newFirmware;
for (const auto panel : panels)
panel->onRadioChanged(firmware);
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "prefs_panel.h"
#include "eeprominterface.h"
#include <QDialog>
class Firmware;
class UpdateFactories;
namespace Ui {
class PrefsEdit;
}
class PrefsEditDialog : public QDialog
{
Q_OBJECT
public:
explicit PrefsEditDialog(QWidget * parent, UpdateFactories * factories);
virtual ~PrefsEditDialog();
public slots:
void setMainWinHasDirtyChild(bool value);
signals:
void profileFirmwareChanged();
void profileFirmwareAboutToChange(bool saveFiles = true);
void resetFirmware();
protected slots:
void accept() Q_DECL_OVERRIDE;
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
void done(int r) Q_DECL_OVERRIDE;
void reject() Q_DECL_OVERRIDE;
void onRadioChanged(Firmware * firmware);
private:
Ui::PrefsEdit *ui;
bool mainWinHasDirtyChild;
Firmware *firmware;
Board::Type board;
Profile &profile;
QList<PrefsPanel *> panels;
bool dirty;
PrefsPanel * addTab(PrefsPanel * panel, QString text);
bool maybeSave();
bool save();
void shrink();
};
+71
View File
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefsEdit</class>
<widget class="QDialog" name="PrefsEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PrefsEdit</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PrefsEdit</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_panel.h"
PrefsPanel::PrefsPanel(QWidget * parent, Firmware * firmware, Board::Type & board, Profile & profile):
AbstractPanel(parent),
firmware(firmware),
board(board),
profile(profile),
row(0),
col(0)
{
}
PrefsPanel::~PrefsPanel()
{
}
AutoLineEdit * PrefsPanel::newPathWidget(QWidget * parent)
{
AutoLineEditPath *wgt = new AutoLineEditPath(parent, true);
setPathWidget(wgt);
return wgt;
}
void PrefsPanel::setPathWidget(AutoLineEdit * wgt)
{
wgt->setMinimumWidth(PATH_MIN_WIDTH);
wgt->setSizePolicy(PATH_SIZE_POLICY);
wgt->setEditSignal(true);
wgt->setClearButtonEnabled(true);
}
void PrefsPanel::onRadioChanged(Firmware * firmware, bool deferUpdate)
{
this->firmware = firmware;
board = this->firmware->getBoard();
if (!deferUpdate)
update();
}
/*
PrefsScrollArea
*/
PrefsScrollArea::PrefsScrollArea(QWidget * parent, PrefsPanel * panel):
QScrollArea(parent),
panel(panel)
{
setWidgetResizable(true);
setWidget(panel);
panel->installEventFilter(this);
}
bool PrefsScrollArea::eventFilter(QObject * o, QEvent * e)
{
if (o == panel && e->type() == QEvent::Resize)
setMinimumWidth(panel->minimumSizeHint().width());
return false;
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "appdata.h"
#include "abstractpanel.h"
#include "eeprominterface.h"
#include "gridlayout.h"
#include <QScrollArea>
class PrefsEditDialog;
// use to help Qt formatting
constexpr int PATH_MIN_WIDTH {250};
constexpr QSizePolicy PATH_SIZE_POLICY {QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed)};
class PrefsPanel : public AbstractPanel
{
Q_OBJECT
public:
friend class PrefsEditDialog;
explicit PrefsPanel(QWidget * parent, Firmware * firmware, Board::Type & board, Profile & profile) ;
virtual ~PrefsPanel();
virtual void save() override {};
signals:
void radioChanged(Firmware * firmware);
protected slots:
virtual void onRadioChanged(Firmware * firmware, bool deferUpdate = false);
protected:
Firmware *firmware;
Board::Type board;
Profile &profile;
int row;
int col;
AutoLineEdit * newPathWidget(QWidget * parent);
void setPathWidget(AutoLineEdit * wgt);
};
class PrefsScrollArea : public QScrollArea
{
Q_OBJECT
public:
explicit PrefsScrollArea(QWidget * parent, PrefsPanel * panel);
protected:
virtual bool eventFilter(QObject * o, QEvent * e);
private:
PrefsPanel * panel;
};
+508
View File
@@ -0,0 +1,508 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_profile.h"
#include "ui_prefs_profile.h"
#include "eeprominterface.h"
#include "moduledata.h"
#include "firmwarepicker.h"
#include "firmwarepicker.h"
#include <QAbstractItemView>
#include <QFileInfo>
#include <QImageReader>
#include <QStandardItemModel>
constexpr char FIM_TEMPLATESETUP[] {"Template Setup"};
PrefsProfilePanel::PrefsProfilePanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof) :
PrefsPanel(parent, fw, bd, prof),
ui(new Ui::PrefsProfile)
{
lock = true;
ui->setupUi(this);
panelItemModels->registerItemModel(new FilteredItemModel(GeneralSettings::templateSetupItemModel()), FIM_TEMPLATESETUP);
panelItemModels->getItemModel(FIM_TEMPLATESETUP)->setFilterFlags(Boards::isAir() ? GeneralSettings::RadioTypeContextAir :
GeneralSettings::RadioTypeContextSurface);
// name
// The profile name may NEVER be empty
if (profile.name().isEmpty())
profile.name(tr("My Radio"));
ui->leName->setValue(profile.name(), this);
ui->leName->setEditSignal(true);
ui->leName->setBindSave([this] {
profile.name(ui->leName->text());
if (profile.name().isEmpty())
profile.name(tr("My Radio"));
});
// radio
// this widget is for data management
fwTypeData = new AutoLineEdit(this, true);
fwTypeData->setHidden(true);
fwTypeData->setValue(profile.fwType());
fwTypeData->setBindSave([this] {
this->profile.fwType(this->fwTypeData->text());
});
fwTypeData->setBindPostChanged([this] {
// appending "-xxx" forces the associated Board definition to be loaded if not already loaded
// TODO fix as part of refactoring Firmware and Boards
Firmware *fw = Firmware::getFirmwareForId(this->fwTypeData->text() % "-xxx");
// this will be trapped by PrefsEditDialog which will trigger onRadioChanged for each panel
// including this panel which has an override onRadioChanged function
emit radioChanged(fw);
});
// this widget displays the firmware full name
ui->leFirmwareType->setReadOnly(true);
ui->leFirmwareType->setBindText([this] {
return Firmware::getFirmwareForId(this->fwTypeData->text())->getFullName();
});
ui->leFirmwareType->setMinimumWidth(PATH_MIN_WIDTH);
ui->leFirmwareType->setSizePolicy(PATH_SIZE_POLICY);
connect(ui->btnFirmwareType, &QPushButton::pressed, this, &PrefsProfilePanel::onFirmwareTypePressed);
sectionNewFile();
sectionFolders();
sectionFirmwareOpts();
sectionSplash();
update();
shrink();
lock = false;
}
PrefsProfilePanel::~PrefsProfilePanel()
{
delete ui;
}
void PrefsProfilePanel::onFirmwareTypePressed()
{
FirmwarePicker * picker = new FirmwarePicker(this, fwTypeData->text());
connect(picker, &FirmwarePicker::firmwareTypeChanged, this, [this] (const QString newType) {
this->fwTypeData->setText(newType);
this->update();
});
picker->exec();
picker->deleteLater();
}
QString PrefsProfilePanel::getLanguage()
{
return !profile.fwLanguage().isEmpty() ?
profile.fwLanguage() :
QLocale::languageToString(QLocale().language()).split("_").first();
}
QStringList PrefsProfilePanel::getSelectedOptions()
{
QStringList opts;
if (chkFirmwareBuildOpts.size()) {
QMutableMapIterator<QString, AutoCheckBox *> it(chkFirmwareBuildOpts);
while (it.hasNext()) {
it.next();
AutoCheckBox * chk = it.value();
if (chk->isChecked())
opts.append(it.key());
}
}
return opts;
}
QString PrefsProfilePanel::getSplashFileFilter()
{
QString fmts;
for (int idx = 0; idx < QImageReader::supportedImageFormats().count(); idx++) {
fmts += QLatin1String(" *.") + QImageReader::supportedImageFormats()[idx];
}
return fmts;
}
QAbstractItemModel * PrefsProfilePanel::languageModel()
{
QStandardItemModel * mdl = new QStandardItemModel(this);
for (const char *lang : firmware->getFirmwareBase()->languageList()) {
QStandardItem * item = new QStandardItem();
item->setText(lang);
item->setData(lang, Qt::UserRole);
mdl->appendRow(item);
}
QSortFilterProxyModel *smdl = new QSortFilterProxyModel(this);
smdl->setSourceModel(mdl);
smdl->setSortCaseSensitivity(Qt::CaseInsensitive);
smdl->sort(0);
return smdl;
}
void PrefsProfilePanel::onOptionChanged(QString name)
{
AutoCheckBox *chk = chkFirmwareBuildOpts.value(name, nullptr);
if (!(chk && chk->isChecked())) return;
const Firmware::OptionsList & fwOpts = firmware->getFirmwareBase()->optionGroups();
// This de-selects any mutually exlusive options (that is, members of the same QList<Option> list).
for (const Firmware::OptionsGroup & optGrp : fwOpts) {
for (const Firmware::Option & opt : optGrp) {
if (name == opt.name) {
AutoCheckBox *ochk = nullptr;
foreach(const Firmware::Option & other, optGrp) {
if (other.name != opt.name && (ochk = chkFirmwareBuildOpts.value(other.name, nullptr)))
ochk->setValue(false);
}
return;
}
}
}
}
void PrefsProfilePanel::populateFirmwareOptions(QStringList opts)
{
QStringList currOpts = opts;
if (!opts.size() && chkFirmwareBuildOpts.size()) {
currOpts.clear();
QMutableMapIterator<QString, AutoCheckBox *> it(chkFirmwareBuildOpts);
while (it.hasNext()) {
it.next();
QCheckBox * chk = it.value();
if (chk->isChecked())
currOpts.append(it.key()); // keep previous selections
layFirmwareBuildOpts->removeWidget(chk);
chk->deleteLater();
it.remove();
}
}
int index = 0;
QWidget * prevFocus = cboFirmwareLanguage;
for (const Firmware::OptionsGroup &optGrp : firmware->getFirmwareBase()->optionGroups()) {
for (const Firmware::Option &opt : optGrp) {
AutoCheckBox * chk = new AutoCheckBox(this, opt.name);
chk->setValue(currOpts.contains(opt.name));
chk->setToolTip(opt.tooltip);
// connect to duplicates check handler if this option is part of a group
if (optGrp.size() > 1)
chk->setBindPostChanged([=] { this->onOptionChanged(opt.name); });
layFirmwareBuildOpts->addWidget(chk, index / 4, index % 4);
chkFirmwareBuildOpts.insert(opt.name, chk);
QWidget::setTabOrder(prevFocus, chk);
prevFocus = chk;
++index;
}
}
shrink();
}
void PrefsProfilePanel::save()
{
profile.fwOptions(getSelectedOptions().join("-"));
AbstractPanel::save();
}
// options TODO split into those supported by Cloud Build and others
void PrefsProfilePanel::sectionFirmwareOpts()
{
QGridLayout *layFirmwareOpts = ui->csectFirmwareOpts->start(tr("Firmware Options"));
row = col = 0;
// language
QLabel *lblFirmwareLanguage = new QLabel(tr("Language"), this);
layFirmwareOpts->addWidget(lblFirmwareLanguage, row, col++);
QHBoxLayout *layLanguage = new QHBoxLayout();
cboFirmwareLanguage = new AutoComboBox(this);
cboFirmwareLanguage->setModel(languageModel());
cboFirmwareLanguage->setValue(profile.fwLanguage());
cboFirmwareLanguage->setBindSave([this] {
this->profile.fwLanguage(this->cboFirmwareLanguage->currentData().toString());
});
layLanguage->addWidget(cboFirmwareLanguage);
QLabel *spacerLanguage = new QLabel();
spacerLanguage->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
layLanguage->addWidget(spacerLanguage);
layFirmwareOpts->addLayout(layLanguage, row, col++);
// other options
++row; col = 0;
AutoLabel *lblFirmwareOptions = new AutoLabel(this, tr("Build"));
layFirmwareOpts->addWidget(lblFirmwareOptions, row, col++, Qt::AlignTop);
layFirmwareBuildOpts = new QGridLayout();
layFirmwareOpts->addLayout(layFirmwareBuildOpts, row, col++);
populateFirmwareOptions(profile.fwOptions().split("-", Qt::SkipEmptyParts));
// flashing
++row; col = 0;
AutoLabel *lblBackupBeforeFlash = new AutoLabel(this, tr("Flashing"));
layFirmwareOpts->addWidget(lblBackupBeforeFlash, row, col++, Qt::AlignTop);
chkBackupBeforeFlash = new AutoCheckBox(this, tr("prompt to backup current firmware before flashing"));
chkBackupBeforeFlash->setValue(profile.penableBackup());
chkBackupBeforeFlash->setBindSave([this] {
this->profile.penableBackup(this->chkBackupBeforeFlash->isChecked());
});
layFirmwareOpts->addWidget(chkBackupBeforeFlash, row, col++);
ui->csectFirmwareOpts->finish(row, col, [this] { this->shrink(); });
}
void PrefsProfilePanel::sectionFolders()
{
QGridLayout *layFolders = ui->csectFolders->start(tr("Folders"));
row = col = 0;
AutoLabel *lblSDPath = new AutoLabel(this, tr("SD Path"));
layFolders->addWidget(lblSDPath, row, col++);
leSDPath = newPathWidget(this);
leSDPath->setValue(profile.sdPath());
leSDPath->setBindSave([this] {
this->profile.sdPath(this->leSDPath->text());
});
leSDPath->setBindPostChanged([this] {
// alert other tabs eg Updates
emit this->sdPathChanged(this->leSDPath->text());
});
layFolders->addWidget(leSDPath, row, col++);
AutoDirectorySelectButton *btnSDPath = new AutoDirectorySelectButton(this);
btnSDPath->setup(tr("Select SD path folder"), profile.sdPath(), leSDPath);;
layFolders->addWidget(btnSDPath, row, col++);
// Backups path
++row; col = 0;
AutoLabel *lblBackupsPath = new AutoLabel(this, tr("Backups"));
layFolders->addWidget(lblBackupsPath, row, col++);
leBackupsPath = newPathWidget(this);
leBackupsPath->setValue(profile.pBackupDir());
leBackupsPath->setBindSave([this] {
this->profile.pBackupDir(this->leBackupsPath->text());
});
layFolders->addWidget(leBackupsPath, row, col++);
AutoDirectorySelectButton *btnBackupsPath = new AutoDirectorySelectButton(this);
btnBackupsPath->setup(tr("Select backups folder"), profile.pBackupDir(), leBackupsPath);;
layFolders->addWidget(btnBackupsPath, row, col++);
/* TODO implement
++row; col = 0;
AutoLabel *lblModelsPath = new AutoLabel(this, tr("Models"));
layFolders->addWidget(lblModelsPath, row, col++);
leModelsPath = newPathWidget(this);
leModelsPath->setValue(profile.modelsDir());
leModelsPath->setBindSave([this] {
this->profile.modelsDir(this->leModelsPath->text());
});
layFolders->addWidget(leModelsPath, row, col++);
AutoDirectorySelectButton *btnModelsPath = new AutoDirectorySelectButton(this);
btnModelsPath->setup(tr("Select models folder"), profile.modelsDir(), leModelsPath);;
layFolders->addWidget(btnModelsPath, row, col++);
*/
ui->csectFolders->finish(-1, -1, [this] { this->shrink(); });
}
void PrefsProfilePanel::sectionNewFile()
{
QGridLayout *layNewFile = ui->csectNewFile->start(tr("New Models and Settings Files"));
row = col = 0;
AutoLabel *lblUseSettingsBackup = new AutoLabel(this, tr("Use backup settings"));
layNewFile->addWidget(lblUseSettingsBackup, row, col++);
chkUseSettingsBackup = new AutoCheckBox(this, " ");
chkUseSettingsBackup->setValue(profile.useSavedSettings());
chkUseSettingsBackup->setBindSave([this] {
this->profile.useSavedSettings(this->chkUseSettingsBackup->isChecked());
});
chkUseSettingsBackup->setBindPostChanged([this] { this->update(); });
layNewFile->addWidget(chkUseSettingsBackup, row, col++);
++row; col = 0;
lblSettingsBackup = new AutoLabel(this);
lblSettingsBackup->setBindText([this] (){
if (profile.generalSettings().isEmpty()) {
return tr("No backup available for this profile");
} else {
QString str = profile.timeStamp();
if (str.isEmpty())
return tr("Backup available of unknown age");
else
return tr("Backup available dated %1").arg(str);
}
});
layNewFile->addWidget(lblSettingsBackup, row, 1);
// Stick Mode
++row; col = 0;
AutoLabel *lblStickMode = new AutoLabel(this, tr("Default Stick Mode"));
lblStickMode->setBindEnabled([this] {
return (!this->chkUseSettingsBackup->isChecked() ||
(this->chkUseSettingsBackup->isChecked() &&
this->profile.generalSettings().isEmpty()));
});
lblStickMode->setBindVisible([this] { return Boards::isAir(); });
layNewFile->addWidget(lblStickMode, row, col++);
cboStickMode = new AutoComboBox(this);
cboStickMode->setModel(GeneralSettings::stickModeItemModel());
cboStickMode->setValue(profile.defaultMode());
cboStickMode->setBindSave([this] {
this->profile.defaultMode(this->cboStickMode->currentData().toInt());
});
cboStickMode->setBindEnabled([this] {
return (!this->chkUseSettingsBackup->isChecked() ||
(this->chkUseSettingsBackup->isChecked() &&
this->profile.generalSettings().isEmpty()));
});
cboStickMode->setBindVisible([this] { return Boards::isAir(); });
layNewFile->addWidget(cboStickMode, row, col++);
// Channel Order
++row; col = 0;
AutoLabel *lblChannelOrder = new AutoLabel(this, tr("Default Channel Order"));
lblChannelOrder->setBindEnabled([this] {
return (!this->chkUseSettingsBackup->isChecked() ||
(this->chkUseSettingsBackup->isChecked() &&
this->profile.generalSettings().isEmpty()));
});
layNewFile->addWidget(lblChannelOrder, row, col++);
cboChannelOrder = new AutoComboBox(this);
cboChannelOrder->setModel(panelItemModels->getItemModel(FIM_TEMPLATESETUP));
cboChannelOrder->setValue(profile.channelOrder());
cboChannelOrder->setBindSave([this] {
this->profile.channelOrder(this->cboChannelOrder->currentData().toInt());
});
cboChannelOrder->setBindEnabled([this] {
return (!this->chkUseSettingsBackup->isChecked() ||
(this->chkUseSettingsBackup->isChecked() &&
this->profile.generalSettings().isEmpty()));
});
layNewFile->addWidget(cboChannelOrder, row, col++);
// Internal Module
++row; col = 0;
AutoLabel *lblModuleInternal = new AutoLabel(this, tr("Default Internal Module"));
layNewFile->addWidget(lblModuleInternal, row, col++);
cboModuleInternal = new AutoComboBox(this);
cboModuleInternal->setModel(ModuleData::internalModuleItemModel());
cboModuleInternal->setValue(profile.defaultInternalModule());
cboModuleInternal->setBindSave([this] {
profile.defaultInternalModule(this->cboModuleInternal->currentData().toInt());
});
layNewFile->addWidget(cboModuleInternal, row, col++);
// External Module
++row; col = 0;
AutoLabel *lblModuleExternal = new AutoLabel(this, tr("External Module Size"));
layNewFile->addWidget(lblModuleExternal, row, col++);
cboModuleExternal = new AutoComboBox(this);
cboModuleExternal->setModel(Boards::externalModuleSizeItemModel());
cboModuleExternal->setValue(profile.externalModuleSize());
cboModuleExternal->setBindSave([this] {
this->profile.externalModuleSize(this->cboModuleExternal->currentData().toInt());
});
layNewFile->addWidget(cboModuleExternal, row, col++);
ui->csectNewFile->finish(row, col, [this] { this->shrink(); });
}
void PrefsProfilePanel::sectionSplash()
{
QGridLayout *laySplash = ui->csectSplash->start(tr("Splash Screen"));
ui->csectSplash->setBindVisible([this] {
return !Boards::getCapability(this->board, Board::HasColorLcd);
});
row = col = 0;
leSplashPath = newPathWidget(this);
leSplashPath->setValue(profile.splashFile());
leSplashPath->setBindSave([this] {
this->profile.splashFile(this->leSplashPath->text());
});
laySplash->addWidget(leSplashPath, row, col++);
// Splash folder select
AutoFileSelectButton *btnSplashSelect = new AutoFileSelectButton(this);
btnSplashSelect->setup(tr("Open Image to load"), g.imagesDir(),
tr("Images (%1)").arg(getSplashFileFilter()), leSplashPath);
btnSplashSelect->setBindPostChanged([this] {
if (!this->leSplashPath->text().isEmpty()){
g.imagesDir(QFileInfo(this->leSplashPath->text()).dir().absolutePath());
}
});
laySplash->addWidget(btnSplashSelect, row, col++);
// Splash image
++row; col = 0;
imgSplash = new AutoImage(this, leSplashPath->text());
// change of firmware and thus board can effect the image
imgSplash->setBindPreUpdate([this] {
imgSplash->setDimensions(Boards::getCapability(this->board, Board::LcdWidth),
Boards::getCapability(this->board, Board::LcdHeight),
Boards::getCapability(this->board, Board::LcdDepth));
});
laySplash->addWidget(imgSplash, row, col++);
// Splash clear
AutoPushButton *btnSplashClear = new AutoPushButton(this, tr("Clear"));
btnSplashClear->setBindClicked([this] {
this->imgSplash->clear();
this->leSplashPath->clear();
});
laySplash->addWidget(btnSplashClear, row, col++);
ui->csectSplash->finish(row, col, [this] { this->shrink(); });
}
// called directly by PrefsEditDialog
// slot not used due to risk of Qt events not being processed in required sequence
void PrefsProfilePanel::onRadioChanged(Firmware * firmware, bool deferUpdate)
{
PrefsPanel::onRadioChanged(firmware, true);
fwTypeData->setText(firmware->getFirmwareBase()->getId());
populateFirmwareOptions(profile.fwOptions().split("-"));
update();
}
void PrefsProfilePanel::update()
{
AbstractPanel::update();
}
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "prefs_edit.h"
namespace Ui {
class PrefsProfile;
}
class Firmware;
class PrefsProfilePanel : public PrefsPanel
{
Q_OBJECT
public:
PrefsProfilePanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof);
virtual ~PrefsProfilePanel();
virtual void save() override;
virtual void update() override;
signals:
void sdPathChanged(QString path);
public slots:
void onOptionChanged(QString name);
void onFirmwareTypePressed();
protected slots:
virtual void onRadioChanged(Firmware * firmware, bool deferUpdate = true) override;
private:
Ui::PrefsProfile * ui;
AutoLineEdit *fwTypeData;
AutoCheckBox *chkUseSettingsBackup;
AutoLabel *lblSettingsBackup;
AutoComboBox *cboStickMode;
AutoComboBox *cboChannelOrder;
AutoComboBox *cboModuleInternal;
AutoComboBox *cboModuleExternal;
AutoLineEdit *leSDPath;
AutoLineEdit *leModelsPath;
AutoLineEdit *leBackupsPath;
AutoComboBox *cboFirmwareLanguage;
AutoImage *imgSplash;
AutoLineEdit *leSplashPath;
QStringList strlBuildOpts;
QGridLayout *layFirmwareBuildOpts;
QMap<QString, AutoCheckBox *> chkFirmwareBuildOpts;
AutoCheckBox *chkBackupBeforeFlash;
QString getLanguage();
QStringList getSelectedOptions();
QString getSplashFileFilter();
QAbstractItemModel *languageModel();
void populateFirmwareOptions(QStringList opts = QStringList());
void sectionFirmwareOpts();
void sectionFolders();
void sectionNewFile();
void sectionSplash();
};
+182
View File
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefsProfile</class>
<widget class="QWidget" name="PrefsProfile">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>710</width>
<height>184</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>70</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>544</width>
<height>52</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="lblFirmwareType">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Firmware Type</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="btnFirmwareType">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="AutoLineEdit" name="leName">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="AutoLineEdit" name="leFirmwareType"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectFirmwareOpts" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectFolders" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectNewFile" native="true"/>
</item>
<item>
<widget class="AutoCollapsibleSection" name="csectSplash" native="true"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoCollapsibleSection</class>
<extends>QWidget</extends>
<header>autocollapsiblesection.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>AutoLineEdit</class>
<extends>QLineEdit</extends>
<header>autolineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+171
View File
@@ -0,0 +1,171 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_simu.h"
#include "ui_prefs_simu.h"
#include "eeprominterface.h"
#if defined(USE_SDL)
#include "joystick.h"
#include "joystickdialog.h"
#endif
PrefsSimuPanel::PrefsSimuPanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof) :
PrefsPanel(parent, fw, bd, prof),
ui(new Ui::PrefsSimu)
{
lock = true;
ui->setupUi(this);
// fix ups TODO move to Appdata load
if (g.snapshotDir().isEmpty() && !g.snapToClpbrd())
g.snapToClpbrd(true);
ui->chkScrnshotClipbd->setValue(g.snapToClpbrd(), this);
ui->chkScrnshotClipbd->setBindSave([this] { g.snapToClpbrd(ui->chkScrnshotClipbd->isChecked()); });
ui->chkScrnshotClipbd->setBindPostChanged([this] { this->update(); });
setPathWidget(ui->leScrnshotPath);
ui->leScrnshotPath->setValue(g.snapshotDir(), this);
ui->leScrnshotPath->setBindSave([this] { g.snapshotDir(ui->leScrnshotPath->text()); });
ui->leScrnshotPath->setBindEnabled([this] { return !ui->chkScrnshotClipbd->isChecked(); });
ui->leScrnshotPath->setBindPostChanged([this] {
if (ui->leScrnshotPath->text().isEmpty()) {
ui->chkScrnshotClipbd->setChecked(true);
update();
}
});
ui->btnScrnshotFldr->setup(tr("Select snapshot folder"), g.snapshotDir(), ui->leScrnshotPath);
ui->btnScrnshotFldr->addBuddyParentWidget(ui->leScrnshotPath);
ui->btnClearSavedPosn->setBindClicked([this] {
SimulatorOptions opts = this->profile.simulatorOptions();
opts.controlsState.clear();
this->profile.simulatorOptions(opts);
});
ui->chkSaveControls->setValue(g.simuSW(), this);
ui->chkSaveControls->setBindSave([this] { g.simuSW(ui->chkSaveControls->isChecked()); });
ui->chkJoystickWarning->setValue(g.disableJoystickWarning(), this);
ui->chkJoystickWarning->setBindSave([this] { g.disableJoystickWarning(ui->chkJoystickWarning->isChecked()); });
ui->chkScrollButtons->setValue(g.simuScrollButtons(), this);
ui->chkScrollButtons->setBindSave([this] { g.simuScrollButtons(ui->chkScrollButtons->isChecked()); });
ui->cboGenericKeysPos->addItems(AppData::simuGenericKeysPosList());
ui->cboGenericKeysPos->setValue((int)g.simuGenericKeysPos(), this);
ui->cboGenericKeysPos->setBindSave([this] {
g.simuGenericKeysPos((AppData::SimuGenericKeysPos)ui->cboGenericKeysPos->currentIndex());
});
ui->dsbVolumeGain->setValue(profile.volumeGain() / 10.0, this);
ui->dsbVolumeGain->setBindSave([this] { this->profile.volumeGain(ui->dsbVolumeGain->value() * 10.0); });
ui->lblBackLightColor->setBindVisible([this] { return Boards::getCapability(board, Board::HasBacklightColor); });
ui->cboBackLightColor->addItems(AppData::simuBackLightColorList());
ui->cboBackLightColor->setValue((int)g.backLight(), this);
ui->cboBackLightColor->setBindSave([this] { g.backLight(ui->cboBackLightColor->currentIndex()); });
ui->cboBackLightColor->setBindVisible([this] { return Boards::getCapability(board, Board::HasBacklightColor); });
ui->lblCaseColorSample->setBindSave([this] {
this->profile.radioSimCaseColor(ui->lblCaseColorSample->palette().button().color());
});
ui->lblCaseColorSample->setPalette(profile.radioSimCaseColor());
ui->btnCaseColor->setup(ui->lblCaseColorSample->palette().button().color(), ui->lblCaseColorSample);
ui->chkBtnClkUseOSTheme->setValue(profile.simBtnClickedUseOSTheme(), this);
ui->chkBtnClkUseOSTheme->setBindSave([this] {
return this->profile.simBtnClickedUseOSTheme(ui->chkBtnClkUseOSTheme->isChecked());
});
ui->chkBtnClkUseOSTheme->setBindPostChanged([this] { this->update(); });
ui->lblBtnClkColorSample->setPalette(profile.simBtnClickedColor());
ui->lblBtnClkColorSample->setBindSave([this] {
return this->profile.simBtnClickedColor(ui->lblBtnClkColorSample->palette().button().color());
});
ui->lblBtnClkColorSample->setBindEnabled([this] { return !ui->chkBtnClkUseOSTheme->isChecked(); });
ui->lblBtnClkColorSample->setBindVisible([this] { return !ui->chkBtnClkUseOSTheme->isChecked(); });
ui->btnBtnClkColor->setup(ui->lblBtnClkColorSample->palette().button().color(), ui->lblBtnClkColorSample);
ui->btnBtnClkColor->setBindEnabled([this] { return !ui->chkBtnClkUseOSTheme->isChecked(); });
ui->btnBtnClkColor->setBindVisible([this] { return !ui->chkBtnClkUseOSTheme->isChecked(); });
#if defined(USE_SDL)
ui->chkJoystickEnable->setValue(g.jsSupport(), this);
ui->chkJoystickEnable->setBindSave([this] { g.jsSupport(ui->chkJoystickEnable->isChecked()); });
ui->cboJoystick->addItems(joysticksList());
ui->cboJoystick->setValue(profile.jsName(), this, false);
ui->cboJoystick->setBindEnabled([this] { return ui->chkJoystickEnable->isChecked();} );
ui->cboJoystick->setBindSave([this] {
if (ui->cboJoystick->isEnabled()) {
this->profile.jsName(ui->cboJoystick->currentText());
g.loadNamedJS();
}
});
ui->btnJoystickCalib->setBindEnabled([this] { return ui->chkJoystickEnable->isChecked();} );
ui->btnJoystickCalib->setBindClicked([this] {
this->profile.jsName(ui->cboJoystick->currentText());
joystickDialog *jd = new joystickDialog(this);
jd->exec();
delete jd;
});
#endif
update();
lock = false;
}
PrefsSimuPanel::~PrefsSimuPanel()
{
delete ui;
}
void PrefsSimuPanel::save()
{
AbstractPanel::save();
}
void PrefsSimuPanel::update()
{
AbstractPanel::update();
}
#if defined(USE_SDL)
QStringList PrefsSimuPanel::joysticksList() {
QStringList lst;
Joystick *joystick = new Joystick(nullptr, 0, false, 0);
if ( joystick && joystick->joystickNames.count() > 0 ) {
lst = joystick->joystickNames;
joystick->close();
} else {
lst << tr("No joysticks found");
}
return lst;
}
#endif
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "prefs_panel.h"
namespace Ui {
class PrefsSimu;
}
class PrefsSimuPanel : public PrefsPanel
{
Q_OBJECT
public:
explicit PrefsSimuPanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof);
virtual ~PrefsSimuPanel();
virtual void update() override;
virtual void save() override;
private:
Ui::PrefsSimu * ui;
#if defined(USE_SDL)
QStringList joysticksList();
#endif
};
+450
View File
@@ -0,0 +1,450 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefsSimu</class>
<widget class="QWidget" name="PrefsSimu">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>617</width>
<height>322</height>
</rect>
</property>
<property name="windowTitle">
<string>Simulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="AutoLabel" name="lblScrnshotCap">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Screenshot Capture</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="AutoCheckBox" name="chkScrnshotClipbd">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Only to clipboard</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="AutoLineEdit" name="leScrnshotPath">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<widget class="AutoDirectorySelectButton" name="btnScrnshotFldr">
<property name="text">
<string>Folder...</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="AutoLabel" name="lblControls">
<property name="text">
<string>Controls</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="AutoCheckBox" name="chkSaveControls">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save switch and pot positions on exit</string>
</property>
</widget>
</item>
<item row="2" column="3" colspan="2">
<widget class="AutoPushButton" name="btnClearSavedPosn">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="2" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1" colspan="2">
<widget class="AutoCheckBox" name="chkJoystickWarning">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Disable 'Cannot open joystick, joystick disabled' warning</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="AutoCheckBox" name="chkScrollButtons">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Display Scroll Buttons (mouse without scroll wheel)</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="AutoLabel" name="lblKeys">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Keys</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="cboGenericKeysPos">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblPad0">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="AutoLabel" name="lblVolumeGain">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Volume Gain</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="AutoDoubleSpinBox" name="dsbVolumeGain">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>3.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="AutoLabel" name="lblBackLightColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>BackLight Colour</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="AutoComboBox" name="cboBackLightColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="8" column="0" rowspan="2">
<widget class="AutoLabel" name="lblCaseColor">
<property name="text">
<string>Case Colour</string>
</property>
</widget>
</item>
<item row="8" column="1" rowspan="2">
<widget class="AutoLabel" name="lblCaseColorSample">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Box</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="3" rowspan="2" colspan="2">
<widget class="AutoColorSelectButton" name="btnCaseColor">
<property name="text">
<string>Colour...</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="AutoLabel" name="lblBtnClkColor">
<property name="text">
<string>Button Clicked Colour</string>
</property>
</widget>
</item>
<item row="10" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="AutoCheckBox" name="chkBtnClkUseOSTheme">
<property name="text">
<string>Operating System theme</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="AutoLabel" name="lblBtnClkColorSample">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Box</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="3" colspan="2">
<widget class="AutoColorSelectButton" name="btnBtnClkColor">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Colour...</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="AutoLabel" name="lblJoystick">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Joystick</string>
</property>
</widget>
</item>
<item row="11" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<item>
<widget class="AutoCheckBox" name="chkJoystickEnable">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="cboJoystick">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblPad1">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="11" column="3" colspan="2">
<widget class="AutoPushButton" name="btnJoystickCalib">
<property name="text">
<string>Calibrate...</string>
</property>
</widget>
</item>
<item row="12" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoCheckBox</class>
<extends>QCheckBox</extends>
<header>autocheckbox.h</header>
</customwidget>
<customwidget>
<class>AutoLineEdit</class>
<extends>QLineEdit</extends>
<header>autolineedit.h</header>
</customwidget>
<customwidget>
<class>AutoLabel</class>
<extends>QLabel</extends>
<header>autolabel.h</header>
</customwidget>
<customwidget>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>autocombobox.h</header>
</customwidget>
<customwidget>
<class>AutoDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>autodoublespinbox.h</header>
</customwidget>
<customwidget>
<class>AutoPushButton</class>
<extends>QPushButton</extends>
<header>autopushbutton.h</header>
</customwidget>
<customwidget>
<class>AutoColorSelectButton</class>
<extends>QPushButton</extends>
<header>autocolorselectbutton.h</header>
</customwidget>
<customwidget>
<class>AutoDirectorySelectButton</class>
<extends>QPushButton</extends>
<header>autodirectoryselectbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+395
View File
@@ -0,0 +1,395 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "prefs_update.h"
#include "ui_prefs_update.h"
#include "updates/updatefactories.h"
#include "updates/updateoptionsdialog.h"
#include <QMessageBox>
PrefsUpdatePanel::PrefsUpdatePanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof, UpdateFactories * factories):
PrefsPanel(parent, fw, bd, prof),
ui(new Ui::PrefsUpdate),
factories(factories)
{
lock = true;
ui->setupUi(this);
// need to track latest value in editor so
// save before changed in profile preferences ui
// updated by onSDPathChanged;
profileSDPath = profile.sdPath().trimmed();
ui->cboCheckFreq->addItems(AppData::updateCheckFreqsList());
ui->cboCheckFreq->setPanel(this);
ui->cboCheckFreq->setBindSave([this] {
g.updateCheckFreq((AppData::UpdateCheckFreq)this->ui->cboCheckFreq->currentData().toInt());
});
ui->btnResetToDefaults->setBindClicked([this] {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Reset ALL update settings to defaults. Are you sure?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
g.resetUpdatesSettings();
this->setValuesFromSettings();
emit this->modified();
QMessageBox::warning(this, CPN_STR_APP_NAME,
tr("Please save changed preferences.\nThen close and restart Companion to avoid unexpected behaviour!"));
}
});
sectionFolders();
sectionComponents();
sectionOptions();
sectionPostUpdate();
setValuesFromSettings();
shrink();
lock = false;
}
PrefsUpdatePanel::~PrefsUpdatePanel()
{
delete ui;
}
void PrefsUpdatePanel::onSDPathChanged(QString path)
{
profileSDPath = path.trimmed();
if (profileSDPath.isEmpty())
chkUpdateDirUseSD->setValue(false);
else if (chkUpdateDirUseSD->isChecked())
leUpdateDir->setValue(path);
update();
}
void PrefsUpdatePanel::save()
{
QStringList msgs;
if (leDownloadDir->text().trimmed().isEmpty())
msgs.append(tr("Download folder path missing!"));
if (leDecompressDir->text().trimmed().isEmpty())
msgs.append(tr("Decompress folder path missing!"));
if (leUpdateDir->text().trimmed().isEmpty())
msgs.append(tr("Update folder path missing!"));
if (!chkDecompressDirUseDwnld->isChecked() &&
leDecompressDir->text().trimmed() == leDownloadDir->text().trimmed())
msgs.append(tr("Decompress and download folders have the same path!"));
if (msgs.count() > 0) {
QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Preferences:\n%1").arg(msgs.join("\n")));
}
AbstractPanel::save();
}
void PrefsUpdatePanel::sectionComponents()
{
QGridLayout *layComponents = ui->csectComponents->start(tr("Components"));
row = 0; col = 1; // leave col 0 blank
QLabel *lblCheck = new QLabel(tr("Check"));
layComponents->addWidget(lblCheck, row, col++);
QLabel *lblReleaseChannel = new QLabel(tr("Release channel"));
layComponents->addWidget(lblReleaseChannel, row, col++);
col++; // options button
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
layComponents->addItem(spacer, row, col++);
QMapIterator<QString, int> it(factories->sortedComponentsList());
while (it.hasNext()) {
it.next();
int i = it.value();
row++; col = 0;
lblName[i] = new AutoLabel();
layComponents->addWidget(lblName[i], row, col++);
chkCheckForUpdate[i] = new AutoCheckBox(this);
// workaround Qt 6.9.0 Qt::AlignHCenter causes text to overlap checkbox rhs
chkCheckForUpdate[i]->setStyleSheet("spacing: 10px");
chkCheckForUpdate[i]->setBindSave([this, i] {
g.component[i].checkForUpdate(this->chkCheckForUpdate[i]->isChecked());
});
layComponents->addWidget(chkCheckForUpdate[i], row, col++);
layComponents->setAlignment(chkCheckForUpdate[i], Qt::AlignHCenter);
cboReleaseChannel[i] = new AutoComboBox(this);
cboReleaseChannel[i]->addItems(ComponentData::releaseChannelsList());
cboReleaseChannel[i]->setBindSave([this, i] {
g.component[i].releaseChannel((ComponentData::ReleaseChannel)this->cboReleaseChannel[i]->currentData().toInt());
});
layComponents->addWidget(cboReleaseChannel[i], row, col++);
btnComponentOptions[i] = new AutoPushButton(this, tr("Options"));
connect(btnComponentOptions[i], &QPushButton::clicked, [=]() {
UpdateOptionsDialog *dlg = new UpdateOptionsDialog(this, factories->instance(i), i, false);
dlg->exec();
dlg->deleteLater();
});
layComponents->addWidget(btnComponentOptions[i], row, col++);
}
ui->csectComponents->finish(row, col, [this] { this->shrink(); });
while (it.hasNext()) {
it.next();
int i = it.value();
g.component[i].checkForUpdate(chkCheckForUpdate[i]->isChecked());
g.component[i].releaseChannel((ComponentData::ReleaseChannel)cboReleaseChannel[i]->currentIndex());
}
}
void PrefsUpdatePanel::sectionFolders()
{
QGridLayout *layFolders = ui->csectFolders->start(tr("Folders"));
row = col = 0;
AutoLabel *lblDownloadDir = new AutoLabel(this, tr("Download"));
layFolders->addWidget(lblDownloadDir, row, col++);
leDownloadDir = newPathWidget(this);
leDownloadDir->setBindSave([this] {
g.downloadDir(this->leDownloadDir->text().trimmed());
});
leDownloadDir->setBindPostChanged([this] {
if (this->chkDecompressDirUseDwnld->isChecked()) {
this->leDecompressDir->setValue(this->leDownloadDir->text().trimmed());
if (this->leDownloadDir->text().trimmed().isEmpty())
this->chkDecompressDirUseDwnld->setValue(false);
}
this->update();
});
layFolders->addWidget(leDownloadDir, row, col++);
AutoDirectorySelectButton *btnDownloadDir = new AutoDirectorySelectButton(this);
btnDownloadDir->setup(tr("Select download folder"), g.downloadDir(), leDownloadDir);
btnDownloadDir->addBuddyParentWidget(leDownloadDir);
layFolders->addWidget(btnDownloadDir, row, col++);
++row; col = 0;
AutoLabel *lblDecompressDir = new AutoLabel(this, tr("Decompress"));
layFolders->addWidget(lblDecompressDir, row, col++);
chkDecompressDirUseDwnld = new AutoCheckBox(this, tr("create sub-folders in Download folder"));
chkDecompressDirUseDwnld->setBindSave([this] {
g.decompressDirUseDwnld(this->chkDecompressDirUseDwnld->isChecked());
});
chkDecompressDirUseDwnld->setBindEnabled([this] {
return !this->leDownloadDir->text().trimmed().isEmpty();
});
chkDecompressDirUseDwnld->setBindPostChanged([this] {
if (chkDecompressDirUseDwnld->isChecked())
this->leDecompressDir->setValue(this->leDownloadDir->text());
this->update();
});
layFolders->addWidget(chkDecompressDirUseDwnld, row, col++);
++row; col = 1; // skip col 0
leDecompressDir = newPathWidget(this);
leDecompressDir->setBindEnabled([this] {
return (!this->chkDecompressDirUseDwnld->isChecked() ||
this->leDownloadDir->text().trimmed().isEmpty());
});
leDecompressDir->setBindSave([this] {
g.decompressDir(this->leDecompressDir->text().trimmed());
});
layFolders->addWidget(leDecompressDir, row, col++);
AutoDirectorySelectButton *btnDecompressDir = new AutoDirectorySelectButton(this);
btnDecompressDir->setup(tr("Select decompression folder"), g.decompressDir(), leDecompressDir);;
btnDecompressDir->addBuddyParentWidget(leDecompressDir);
layFolders->addWidget(btnDecompressDir, row, col++);
++row; col = 0;
AutoLabel *lblUpdateDir = new AutoLabel(this, tr("Update"));
layFolders->addWidget(lblUpdateDir, row, col++);
chkUpdateDirUseSD = new AutoCheckBox(this, tr("use Radio Profile SD path"));
chkUpdateDirUseSD->setBindEnabled([this] {
return !this->profileSDPath.isEmpty();
});
chkUpdateDirUseSD->setBindSave([this] {
g.updateDirUseSD(this->chkUpdateDirUseSD->isChecked());
});
chkUpdateDirUseSD->setBindPostChanged([this] {
if (this->chkUpdateDirUseSD->isChecked()) {
this->leUpdateDir->setValue(profileSDPath);
}
this->update();
});
layFolders->addWidget(chkUpdateDirUseSD, row, col++);
++row; col = 1; // skip col 0
leUpdateDir = newPathWidget(this);
leUpdateDir->setBindEnabled([this] {
return !this->chkUpdateDirUseSD->isChecked() ||
this->profileSDPath.isEmpty();
});
leUpdateDir->setBindSave([this] {
g.updateDir(this->leUpdateDir->text().trimmed());
});
layFolders->addWidget(leUpdateDir, row, col++);
AutoDirectorySelectButton *btnUpdateDir = new AutoDirectorySelectButton(this);
btnUpdateDir->setup(tr("Select update folder"), g.updateDir(), leUpdateDir);;
btnUpdateDir->addBuddyParentWidget(leUpdateDir);
layFolders->addWidget(btnUpdateDir, row, col++);
ui->csectFolders->finish(-1, -1, [this] { this->shrink(); });
}
void PrefsUpdatePanel::sectionOptions()
{
QGridLayout *layOptions = ui->csectOptions->start(tr("Options"));
row = col = 0;
AutoLabel *lblDelDownloads = new AutoLabel(this, tr("Delete downloads"));
layOptions->addWidget(lblDelDownloads, row, col++);
chkDelDownloads = new AutoCheckBox(this);
chkDelDownloads->setBindSave([this] {
g.updDelDownloads(this->chkDelDownloads->isChecked());
});
chkDelDownloads->setBindEnabled([this] {
return !this->chkDecompressDirUseDwnld->isChecked() ||
this->chkDelDecompress->isChecked();
});
layOptions->addWidget(chkDelDownloads, row, col++);
row++; col = 0;
AutoLabel *lblDelDecompress = new AutoLabel(this, tr("Delete decompressions"));
layOptions->addWidget(lblDelDecompress, row, col++);
chkDelDecompress = new AutoCheckBox(this);
chkDelDecompress->setBindSave([this] {
g.updDelDecompress(this->chkDelDecompress->isChecked());
});
chkDelDecompress->setBindPostChanged([this] {
if (!this->chkDelDecompress->isChecked()) {
if (this->chkDecompressDirUseDwnld->isChecked()) {
this->chkDelDownloads->setValue(false);
}
} else {
this->chkDelDownloads->setEnabled(true);
}
update();
});
layOptions->addWidget(chkDelDecompress, row, col++);
row++; col = 0;
QLabel *lblLogLevel = new QLabel(tr("Log level"), this);
layOptions->addWidget(lblLogLevel, row, col++);
cboLogLevel = new AutoComboBox(this);
cboLogLevel->addItems(AppData::updateLogLevelsList());
cboLogLevel->setBindSave([this] {
g.updLogLevel(this->cboLogLevel->currentData().toInt());
});
layOptions->addWidget(cboLogLevel, row, col++);
ui->csectOptions->finish(row, col, [this] { this->shrink(); });
}
void PrefsUpdatePanel::sectionPostUpdate()
{
QGridLayout *layPostUpdate = ui->csectPostUpdate->start(tr("Post Update"));
row = col = 0;
chkPrmptFlash = new AutoCheckBox(this, tr("Prompt to flash firmware"));
chkPrmptFlash->setBindSave([this] {
profile.burnFirmware(this->chkPrmptFlash->isChecked());
});
layPostUpdate->addWidget(chkPrmptFlash, row, col++);
row++; col = 0;
chkPrmptSDSync = new AutoCheckBox(this, tr("Prompt to run SD Sync"));
chkPrmptSDSync->setBindSave([this] {
profile.runSDSync(this->chkPrmptSDSync->isChecked());
});
layPostUpdate->addWidget(chkPrmptSDSync, row, col++);
row++; col = 0;
chkPrmptCpnInstall = new AutoCheckBox(this, tr("Prompt to run Companion installer"));
chkPrmptCpnInstall->setBindSave([this] {
g.runAppInstaller(this->chkPrmptCpnInstall->isChecked());
});
layPostUpdate->addWidget(chkPrmptCpnInstall, row, col++);
ui->csectPostUpdate->finish(row, col, [this] { this->shrink(); });
}
void PrefsUpdatePanel::setValuesFromSettings()
{
lock = true;
ui->cboCheckFreq->setValue(g.updateCheckFreq());
// folders
leDownloadDir->setValue(g.downloadDir());
chkDecompressDirUseDwnld->setValue(g.decompressDirUseDwnld());
leDecompressDir->setValue(g.decompressDir());
chkUpdateDirUseSD->setValue(g.updateDirUseSD());
leUpdateDir->setValue(g.updateDir());
// components
QMapIterator<QString, int> it(factories->sortedComponentsList());
while (it.hasNext()) {
it.next();
int i = it.value();
lblName[i]->setText(it.key());
chkCheckForUpdate[i]->setValue(g.component[i].checkForUpdate());
cboReleaseChannel[i]->setValue(g.component[i].releaseChannel());
}
// options
chkDelDownloads->setValue(g.updDelDownloads());
chkDelDecompress->setValue(g.updDelDecompress());
cboLogLevel->setValue(g.updLogLevel());
// post update
chkPrmptFlash->setValue(profile.burnFirmware());
chkPrmptSDSync->setValue(profile.runSDSync());
chkPrmptCpnInstall->setValue(g.runAppInstaller());
update();
lock = false;
}
void PrefsUpdatePanel::update()
{
AbstractPanel::update();
}
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "prefs_edit.h"
namespace Ui {
class PrefsUpdate;
}
class UpdateFactories;
class PrefsUpdatePanel : public PrefsPanel
{
Q_OBJECT
public:
PrefsUpdatePanel(QWidget * parent, Firmware * fw, Board::Type & bd, Profile & prof, UpdateFactories * factories);
virtual ~PrefsUpdatePanel();
virtual void save() override;
virtual void update() override;
public slots:
void onSDPathChanged(QString path);
private:
Ui::PrefsUpdate *ui;
UpdateFactories *factories;
// general
// folders
AutoLineEdit *leDownloadDir;
AutoCheckBox *chkDecompressDirUseDwnld;
AutoLineEdit *leDecompressDir;
AutoCheckBox *chkUpdateDirUseSD;
AutoLineEdit *leUpdateDir;
//components
AutoLabel *lblName[MAX_COMPONENTS];
AutoCheckBox *chkCheckForUpdate[MAX_COMPONENTS];
AutoComboBox *cboReleaseChannel[MAX_COMPONENTS];
AutoPushButton *btnComponentOptions[MAX_COMPONENTS];
// options
AutoCheckBox *chkDelDownloads;
AutoCheckBox *chkDelDecompress;
AutoComboBox *cboLogLevel;
// post update
AutoCheckBox *chkPrmptFlash;
AutoCheckBox *chkPrmptSDSync;
AutoCheckBox *chkPrmptCpnInstall;
QString profileSDPath;
void sectionFolders();
void sectionComponents();
void sectionOptions();
void sectionPostUpdate();
void setValuesFromSettings();
};
+143
View File
@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefsUpdate</class>
<widget class="QWidget" name="PrefsUpdate">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>156</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="AutoCollapsibleSection" name="csectOptions" native="true"/>
</item>
<item row="4" column="0">
<widget class="AutoCollapsibleSection" name="csectPostUpdate" native="true"/>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="AutoCollapsibleSection" name="csectComponents" native="true"/>
</item>
<item row="1" column="0">
<widget class="AutoCollapsibleSection" name="csectFolders" native="true"/>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>591</width>
<height>24</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="AutoLabel" name="lblCheckFreq">
<property name="text">
<string>Check frequency</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="cboCheckFreq"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="AutoPushButton" name="btnResetToDefaults">
<property name="text">
<string>Reset to Defaults</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoCollapsibleSection</class>
<extends>QWidget</extends>
<header>autocollapsiblesection.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>AutoPushButton</class>
<extends>QPushButton</extends>
<header>autopushbutton.h</header>
</customwidget>
<customwidget>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>autocombobox.h</header>
</customwidget>
<customwidget>
<class>AutoLabel</class>
<extends>QLabel</extends>
<header>autolabel.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+13 -3
View File
@@ -7,22 +7,30 @@ set(${PROJECT_NAME}_NAMES
autobitsetcheckbox
autocheckbox
autocollapsiblesection
autocolorselectbutton
autocombobox
autodoublespinbox
autofileselectbutton
autodirectoryselectbutton
autohexspinbox
autoimage
autolabel
autolineedit
autolineeditpath
autoprecisioncombobox
autopushbutton
autoslider
autospinbox
autotimeedit
curveimagewidget
curvedialog
genericpanel
exclusivecombogroup
gridlayout
scrollarea
textvalidator
exclusivecombogroup
widgetbindings
abstractpanel
genericpanel
firmwarepicker
)
AddHeadersSources()
@@ -48,6 +56,8 @@ set(${PROJECT_NAME}_SRCS
curveimage.cpp
semanticversion.h
semanticversion.cpp
widgetbindings.h
widgetbindings.cpp
)
add_library(${PROJECT_NAME}
+181
View File
@@ -0,0 +1,181 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "abstractpanel.h"
#include "autowidget.h"
#include "widgetbindings.h"
#include <TimerEdit>
#include <QComboBox>
#include <QEvent>
#include <QLabel>
#include <QGridLayout>
#include <QSpacerItem>
AbstractPanel::AbstractPanel(QWidget * parent):
QWidget(parent),
lock(false),
panelItemModels(new FilteredItemModelFactory()),
m_bindings(nullptr)
{
}
AbstractPanel::~AbstractPanel()
{
delete panelItemModels;
}
void AbstractPanel::addLabel(QGridLayout *gridLayout, const QString &text, int col, bool minimize)
{
QLabel *label = new QLabel(this);
label->setFrameShape(QFrame::Panel);
label->setFrameShadow(QFrame::Raised);
label->setMidLineWidth(0);
label->setAlignment(Qt::AlignCenter);
label->setMargin(5);
label->setText(text);
if (!minimize)
label->setMinimumWidth(100);
gridLayout->addWidget(label, 0, col, 1, 1);
}
void AbstractPanel::addEmptyLabel(QGridLayout * gridLayout, int col)
{
QLabel *label = new QLabel(this);
label->setText("");
gridLayout->addWidget(label, 0, col, 1, 1);
}
void AbstractPanel::addHSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
gridLayout->addItem(spacer, row, col);
}
void AbstractPanel::addVSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
void AbstractPanel::addDoubleSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
bool AbstractPanel::eventFilter(QObject *object, QEvent * event)
{
QWidget * widget = qobject_cast<QWidget*>(object);
if (widget) {
if (event->type() == QEvent::Wheel) {
if (widget->focusPolicy() == Qt::WheelFocus) {
event->accept();
return false;
}
else {
event->ignore();
return true;
}
}
else if (event->type() == QEvent::FocusIn) {
widget->setFocusPolicy(Qt::WheelFocus);
}
else if (event->type() == QEvent::FocusOut) {
widget->setFocusPolicy(Qt::StrongFocus);
}
}
return QWidget::eventFilter(object, event);
}
void AbstractPanel::setFocusFilter(QWidget * w)
{
w->installEventFilter(this);
w->setFocusPolicy(Qt::StrongFocus);
}
void AbstractPanel::disableMouseScrolling()
{
foreach(QWidget * cb, findChildren<QComboBox*>())
setFocusFilter(cb);
foreach(QWidget * sb, findChildren<QAbstractSpinBox*>())
setFocusFilter(sb);
foreach(QWidget * slider, findChildren<QSlider*>())
setFocusFilter(slider);
foreach(QWidget * te, findChildren<TimerEdit*>())
setFocusFilter(te);
}
void AbstractPanel::save()
{
saveAutoWidgets();
}
void AbstractPanel::saveAutoWidgets()
{
foreach(QWidget *wdgt, findChildren<QWidget *>()) {
AutoWidget *autowdgt = dynamic_cast<AutoWidget *>(wdgt);
if (autowdgt) {
autowdgt->saveValue();
}
}
}
void AbstractPanel::update()
{
lock = true;
updateAutoWidgets();
lock = false;
}
void AbstractPanel::updateAutoWidgets()
{
foreach(QWidget *wdgt, findChildren<QWidget *>()) {
AutoWidget *autowdgt = dynamic_cast<AutoWidget *>(wdgt);
if (autowdgt) {
autowdgt->runPreUpdate();
autowdgt->updateValue();
autowdgt->applyBindings();
}
}
}
WidgetBindings *AbstractPanel::bindings()
{
if (!m_bindings)
m_bindings = std::make_unique<WidgetBindings>();
return m_bindings.get();
}
void AbstractPanel::applyBindings()
{
if (m_bindings)
m_bindings->applyAll();
}
void AbstractPanel::shrink()
{
this->adjustSize();
this->resize(0, 0);
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "filtereditemmodels.h"
#include <QWidget>
#include <memory>
class QGridLayout;
class QString;
class WidgetBindings;
class AbstractPanel : public QWidget
{
Q_OBJECT
friend class GVarGroup;
friend class AutoWidget;
public:
explicit AbstractPanel(QWidget *parent);
virtual ~AbstractPanel();
signals:
void modified();
public slots:
virtual void save();
virtual void update();
protected:
bool lock; // TODO for consistency move to private and add protected getter and setter
FilteredItemModelFactory *panelItemModels;
void addLabel(QGridLayout * gridLayout, const QString &text, int col, bool mimimize=false);
void addEmptyLabel(QGridLayout * gridLayout, int col);
void addHSpring(QGridLayout *, int col, int row);
void addVSpring(QGridLayout *, int col, int row);
void addDoubleSpring(QGridLayout *, int col, int row);
virtual bool eventFilter(QObject *obj, QEvent *event);
void setFocusFilter(QWidget * w);
void disableMouseScrolling();
void updateAutoWidgets();
void saveAutoWidgets();
WidgetBindings *bindings();
void applyBindings();
void shrink();
//bool lock(); TODO
//void setLock(bool val); TODO
private:
//bool m_lock; TODO
std::unique_ptr<WidgetBindings> m_bindings;
};
@@ -23,7 +23,7 @@
AutoBitMappedCheckBox::AutoBitMappedCheckBox(QWidget * parent):
QCheckBox(parent),
AutoWidget(),
AutoWidget(parent),
m_field(nullptr),
m_invert(false)
{
@@ -35,7 +35,7 @@ AutoBitMappedCheckBox::~AutoBitMappedCheckBox()
{
}
void AutoBitMappedCheckBox::setField(int & field, GenericPanel * panel, bool invert)
void AutoBitMappedCheckBox::setField(int & field, AbstractPanel * panel, bool invert)
{
m_field = &field;
m_invert = invert;
@@ -43,7 +43,7 @@ void AutoBitMappedCheckBox::setField(int & field, GenericPanel * panel, bool inv
updateValue();
}
void AutoBitMappedCheckBox::setField(unsigned int & field, GenericPanel * panel, bool invert)
void AutoBitMappedCheckBox::setField(unsigned int & field, AbstractPanel * panel, bool invert)
{
m_field = (int *)&field;
m_invert = invert;
+2 -2
View File
@@ -36,8 +36,8 @@ class AutoBitMappedCheckBox : public QCheckBox, public AutoWidget
virtual void updateValue() override;
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setField(int & field, GenericPanel * panel = nullptr, bool invert = false);
void setField(unsigned int & field, GenericPanel * panel = nullptr, bool invert = false);
void setField(int & field, AbstractPanel * panel = nullptr, bool invert = false);
void setField(unsigned int & field, AbstractPanel * panel = nullptr, bool invert = false);
void setInvert(bool invert);
void setBits(const unsigned int numBits = 1, const unsigned int offsetBits = 0, const unsigned int index = 0,
const unsigned int indexBits = 1);
@@ -23,7 +23,7 @@
AutoBitMappedComboBox::AutoBitMappedComboBox(QWidget * parent):
QComboBox(parent),
AutoWidget(),
AutoWidget(parent),
m_field(nullptr),
m_next(0),
m_hasModel(false),
@@ -83,7 +83,7 @@ void AutoBitMappedComboBox::setAutoModel(QAbstractItemModel * model)
AutoBitMappedComboBox::setModel(model);
}
void AutoBitMappedComboBox::setField(unsigned int & field, GenericPanel * panel)
void AutoBitMappedComboBox::setField(unsigned int & field, AbstractPanel * panel)
{
m_field = (int *)&field;
m_rawSource = nullptr;
@@ -91,7 +91,7 @@ void AutoBitMappedComboBox::setField(unsigned int & field, GenericPanel * panel)
setFieldInit(panel);
}
void AutoBitMappedComboBox::setField(int & field, GenericPanel * panel)
void AutoBitMappedComboBox::setField(int & field, AbstractPanel * panel)
{
m_field = &field;
m_rawSource = nullptr;
@@ -99,7 +99,7 @@ void AutoBitMappedComboBox::setField(int & field, GenericPanel * panel)
setFieldInit(panel);
}
void AutoBitMappedComboBox::setField(RawSource & field, GenericPanel * panel)
void AutoBitMappedComboBox::setField(RawSource & field, AbstractPanel * panel)
{
m_rawSource = &field;
m_rawSwitch = nullptr;
@@ -107,7 +107,7 @@ void AutoBitMappedComboBox::setField(RawSource & field, GenericPanel * panel)
setFieldInit(panel);
}
void AutoBitMappedComboBox::setField(RawSwitch & field, GenericPanel * panel)
void AutoBitMappedComboBox::setField(RawSwitch & field, AbstractPanel * panel)
{
m_rawSwitch = &field;
m_rawSource = nullptr;
@@ -115,7 +115,7 @@ void AutoBitMappedComboBox::setField(RawSwitch & field, GenericPanel * panel)
setFieldInit(panel);
}
void AutoBitMappedComboBox::setFieldInit(GenericPanel * panel)
void AutoBitMappedComboBox::setFieldInit(AbstractPanel * panel)
{
setPanel(panel);
updateValue();
+5 -5
View File
@@ -48,10 +48,10 @@ class AutoBitMappedComboBox : public QComboBox, public AutoWidget
void setBits(const unsigned int numBits = 1, const unsigned int offsetBits = 0, const unsigned int index = 0,
const unsigned int indexBits = 1);
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(int & field, GenericPanel * panel = nullptr);
void setField(RawSource & field, GenericPanel * panel = nullptr);
void setField(RawSwitch & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
void setField(int & field, AbstractPanel * panel = nullptr);
void setField(RawSource & field, AbstractPanel * panel = nullptr);
void setField(RawSwitch & field, AbstractPanel * panel = nullptr);
void setAutoIndexes();
void setModel(QAbstractItemModel * model) override;
@@ -76,5 +76,5 @@ class AutoBitMappedComboBox : public QComboBox, public AutoWidget
unsigned int shiftbits();
unsigned int bitmask();
void setFieldInit(GenericPanel * panel);
void setFieldInit(AbstractPanel * panel);
};
+1 -1
View File
@@ -28,7 +28,7 @@ AutoBitsetCheckBox::AutoBitsetCheckBox(QWidget * parent) :
AutoBitsetCheckBox::AutoBitsetCheckBox(const QString & text, QWidget * parent) :
QCheckBox(text, parent),
AutoWidget()
AutoWidget(parent)
{
init();
}
+43 -15
View File
@@ -21,12 +21,14 @@
#include "autocheckbox.h"
AutoCheckBox::AutoCheckBox(QWidget * parent):
AutoCheckBox::AutoCheckBox(QWidget * parent, const QString & text):
QCheckBox(parent),
AutoWidget(),
AutoWidget(parent),
m_field(nullptr),
m_invert(false)
m_invert(false),
m_value(false)
{
QCheckBox::setText(text);
connect(this, &QCheckBox::toggled, this, &AutoCheckBox::onToggled);
}
@@ -36,19 +38,36 @@ AutoCheckBox::~AutoCheckBox()
void AutoCheckBox::onToggled(bool checked)
{
if (m_field && !lock()) {
const bool val = m_invert ? !checked : checked;
*m_field = val;
emit currentDataChanged(val);
if (!lock()) {
m_value = m_invert ? !checked : checked;
if (m_field)
*m_field = m_value;
emit currentDataChanged(m_value);
runPostChanged();
}
}
void AutoCheckBox::setField(bool & field, GenericPanel * panel, bool invert)
void AutoCheckBox::setAutoText(QString text)
{
QCheckBox::setText(text);
}
void AutoCheckBox::setField(bool & field, AbstractPanel * panel, bool invert)
{
m_field = &field;
m_invert = invert;
setPanel(panel);
m_value = *m_field;
updateValue();
}
void AutoCheckBox::setFieldInit(AbstractPanel * panel, bool invert)
{
setPanel(panel);
setInvert(invert);
updateValue();
}
@@ -58,16 +77,25 @@ void AutoCheckBox::setInvert(bool invert)
updateValue();
}
void AutoCheckBox::setAutoText(QString text)
void AutoCheckBox::setValue(bool value)
{
QCheckBox::setText(text);
if (!m_field) {
m_value = value;
updateValue();
}
}
void AutoCheckBox::setValue(bool value, AbstractPanel * panel, bool invert)
{
if (!m_field) {
m_value = value;
setFieldInit(panel, invert);
}
}
void AutoCheckBox::updateValue()
{
if (m_field) {
setLock(true);
setChecked(m_invert ? !(*m_field) : *m_field);
setLock(false);
}
setLock(true);
setChecked(m_invert ? !m_value : m_value);
setLock(false);
}
+11 -2
View File
@@ -30,14 +30,20 @@ class AutoCheckBox : public QCheckBox, public AutoWidget
Q_OBJECT
public:
explicit AutoCheckBox(QWidget * parent = nullptr);
explicit AutoCheckBox(QWidget * parent = nullptr, const QString & text = QString());
virtual ~AutoCheckBox();
virtual void updateValue() override;
// not applicable to this widget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setField(bool & field, GenericPanel * panel = nullptr, bool invert = false);
void setField(bool & field, AbstractPanel * panel = nullptr, bool invert = false);
void setInvert(bool invert);
// use for widget not bound to a memory address
void setValue(bool value, AbstractPanel * panel, bool invert = false);
// use after initialised
void setValue(bool value);
signals:
void currentDataChanged(bool value);
@@ -51,4 +57,7 @@ class AutoCheckBox : public QCheckBox, public AutoWidget
private:
bool *m_field;
bool m_invert;
bool m_value;
void setFieldInit(AbstractPanel * panel, bool invert);
};
@@ -44,12 +44,15 @@
#include <QPropertyAnimation>
AutoCollapsibleSection::AutoCollapsibleSection(QWidget * parent) :
QWidget(parent)
QWidget(parent),
AutoWidget(parent),
fnResize(nullptr)
{
toggleButton = new QToolButton(this);
headerLine = new QFrame(this);
toggleAnimation = new QParallelAnimationGroup(this);
contentArea = new QScrollArea(this);
contentAreaLayout = new QGridLayout();
mainLayout = new QGridLayout(this);
toggleButton->setStyleSheet("QToolButton {border: none;}");
@@ -64,6 +67,7 @@ AutoCollapsibleSection::AutoCollapsibleSection(QWidget * parent) :
headerLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
contentArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
contentArea->setFrameStyle(QFrame::NoFrame);
// start out collapsed
contentArea->setMaximumHeight(0);
@@ -84,7 +88,30 @@ AutoCollapsibleSection::AutoCollapsibleSection(QWidget * parent) :
setLayout(mainLayout);
connect(toggleButton, &QToolButton::toggled, this, &AutoCollapsibleSection::toggle);
connect(toggleAnimation, &QParallelAnimationGroup::finished, [this] () { emit resized(); });
connect(toggleAnimation, &QParallelAnimationGroup::finished, [this] ()
{
if (fnResize) fnResize();
emit resized();
});
}
QGridLayout * AutoCollapsibleSection::start(const QString & title)
{
setTitle(title);
return contentAreaLayout;
}
void AutoCollapsibleSection::finish(int springRow, int springCol, std::function<void()> fnResize, bool expand)
{
if (springRow >= 0 && springCol >= 0) {
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
contentAreaLayout->addItem(spacer, springRow, springCol);
}
// attach after constructed for better sizing
setContentLayout(*contentAreaLayout);
setBindResize(fnResize);
toggleButton->setChecked(expand);
}
void AutoCollapsibleSection::setAnimationDuration(const int duration)
@@ -92,6 +119,11 @@ void AutoCollapsibleSection::setAnimationDuration(const int duration)
animationDuration = duration;
}
void AutoCollapsibleSection::setBindResize(std::function<void()> fn)
{
fnResize = std::move(fn);
}
void AutoCollapsibleSection::setContentLayout(QLayout & contentLayout)
{
delete contentArea->layout();
+13 -3
View File
@@ -41,26 +41,34 @@
#pragma once
#include "autowidget.h"
#include <QDialog>
#include <QFrame>
#include <QGridLayout>
#include <QParallelAnimationGroup>
#include <QScrollArea>
#include <QToolButton>
#include <QWidget>
class AutoCollapsibleSection : public QWidget
class AutoCollapsibleSection : public QWidget, public AutoWidget
{
Q_OBJECT
public:
static const int DEFAULT_DURATION = 0;
static const int DEFAULT_DURATION = 300;
explicit AutoCollapsibleSection(QWidget * parent = nullptr);
virtual ~AutoCollapsibleSection() {}
virtual void updateValue() override {}
QGridLayout * start(const QString & title);
void finish(int row = -1, int col = -1, std::function<void()> fnResize = nullptr, bool expand = false);
// setters
void setAnimationDuration(const int duration);
void setContentLayout(QLayout & contentLayout);
void setTitle(const QString & title);
void setBindResize(std::function<void()> fn);
// getters
const int getAnimationDuration() { return animationDuration; }
@@ -80,8 +88,10 @@ class AutoCollapsibleSection : public QWidget
QFrame *headerLine;
QParallelAnimationGroup *toggleAnimation;
QScrollArea *contentArea;
QGridLayout *contentAreaLayout;
int animationDuration = DEFAULT_DURATION;
int collapsedHeight;
bool isExpanded = false;
QString title;
std::function<void()> fnResize;
};
@@ -0,0 +1,53 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autocolorselectbutton.h"
AutoColorSelectButton::AutoColorSelectButton(QWidget * parent) :
AutoPushButton(parent),
m_sample(nullptr)
{
connect(this, &QPushButton::released, [&] ()
{
QColor color = QColorDialog::getColor(m_color, this);
if (color.isValid() && color != m_color) {
m_color = color;
if (m_sample) {
m_sample->setPalette(QPalette(m_color));
m_sample->repaint();
}
emit colorChanged(m_color);
}
});
}
AutoColorSelectButton::~AutoColorSelectButton()
{
}
void AutoColorSelectButton::setup(QColor color, QWidget * sampleWidget)
{
m_color = color;
m_sample = sampleWidget;
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autopushbutton.h"
#include <QColorDialog>
class AutoColorSelectButton : public AutoPushButton
{
Q_OBJECT
public:
explicit AutoColorSelectButton(QWidget * parent = nullptr);
virtual ~AutoColorSelectButton();
virtual void updateValue() override {}
void setup(QColor color, QWidget * sample = nullptr);
signals:
void colorChanged(QColor color);
private:
QWidget *m_sample;
QColor m_color;
};
+86 -42
View File
@@ -23,12 +23,15 @@
AutoComboBox::AutoComboBox(QWidget * parent):
QComboBox(parent),
AutoWidget(),
AutoWidget(parent),
m_next(0),
m_hasModel(false)
m_hasModel(false),
m_useFindData(true)
{
initField();
connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AutoComboBox::onCurrentIndexChanged);
setSizeAdjustPolicy(QComboBox::AdjustToContents);
connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AutoComboBox::onCurrentIndexChanged);
}
AutoComboBox::~AutoComboBox()
@@ -37,7 +40,7 @@ AutoComboBox::~AutoComboBox()
void AutoComboBox::initField()
{
m_field = nullptr;
m_int = nullptr;
m_rawSource = nullptr;
m_rawSwitch = nullptr;
m_curveType = nullptr;
@@ -45,6 +48,8 @@ void AutoComboBox::initField()
m_switchType = nullptr;
m_qString = nullptr;
m_stdString = nullptr;
m_value = 0;
}
void AutoComboBox::clear()
@@ -82,75 +87,88 @@ void AutoComboBox::addItem(const QString & item, int value)
}
}
void AutoComboBox::addItems(const QStringList & items)
{
if (!m_hasModel) {
setLock(true);
foreach(QString item, items)
QComboBox::addItem(item, m_next++);
setLock(false);
updateValue();
}
}
void AutoComboBox::setAutoModel(QAbstractItemModel * model)
{
AutoComboBox::setModel(model);
}
void AutoComboBox::setField(unsigned int & field, GenericPanel * panel)
void AutoComboBox::setField(unsigned int & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_field = (int *)&field;
m_int = (int *)&field;
updateValue();
}
void AutoComboBox::setField(int & field, GenericPanel * panel)
void AutoComboBox::setField(int & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_field = &field;
m_int = &field;
updateValue();
}
void AutoComboBox::setField(RawSource & field, GenericPanel * panel)
void AutoComboBox::setField(RawSource & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_rawSource = &field;
updateValue();
}
void AutoComboBox::setField(RawSwitch & field, GenericPanel * panel)
void AutoComboBox::setField(RawSwitch & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_rawSwitch = &field;
updateValue();
}
void AutoComboBox::setField(CurveData::CurveType & field, GenericPanel * panel)
void AutoComboBox::setField(CurveData::CurveType & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_curveType = &field;
updateValue();
}
void AutoComboBox::setField(Board::FlexType & field, GenericPanel * panel)
void AutoComboBox::setField(Board::FlexType & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_flexType = &field;
updateValue();
}
void AutoComboBox::setField(Board::SwitchType & field, GenericPanel * panel)
void AutoComboBox::setField(Board::SwitchType & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_switchType = &field;
updateValue();
}
void AutoComboBox::setField(QString & field, GenericPanel * panel)
void AutoComboBox::setField(QString & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_qString = &field;
updateValue();
}
void AutoComboBox::setField(std::string & field, GenericPanel * panel)
void AutoComboBox::setField(std::string & field, AbstractPanel * panel)
{
setFieldInit(panel);
m_stdString = &field;
updateValue();
}
void AutoComboBox::setFieldInit(GenericPanel * panel)
void AutoComboBox::setFieldInit(AbstractPanel * panel)
{
initField();
setPanel(panel);
@@ -167,6 +185,20 @@ void AutoComboBox::setModel(QAbstractItemModel * model)
}
}
void AutoComboBox::setValue(QVariant value)
{
m_value = value;
updateValue();
}
void AutoComboBox::setValue(QVariant value, AbstractPanel * panel, bool useFindData)
{
setFieldInit(panel);
m_value = value;
m_useFindData = useFindData;
updateValue();
}
void AutoComboBox::setAutoIndexes()
{
if (!m_hasModel) {
@@ -181,8 +213,8 @@ void AutoComboBox::updateValue()
{
setLock(true);
if (m_field)
setCurrentIndex(findData(*m_field));
if (m_int)
setCurrentIndex(findData(*m_int));
else if (m_rawSource)
setCurrentIndex(findData(m_rawSource->toValue()));
else if (m_rawSwitch)
@@ -197,6 +229,11 @@ void AutoComboBox::updateValue()
setCurrentIndex(findText(*m_qString));
else if (m_stdString)
setCurrentIndex(findText(QString(m_stdString->c_str())));
// default using m_value
else if (m_useFindData)
setCurrentIndex(findData(m_value));
else
setCurrentIndex(findText(m_value.toString()));
setLock(false);
}
@@ -207,37 +244,44 @@ void AutoComboBox::onCurrentIndexChanged(int index)
return;
bool ok;
int val = 0;
QString str;
int ival = 0;
QString sval;
if (m_qString || m_stdString) {
str = itemText(index);
if (m_qString || m_stdString || m_value.typeId() != QMetaType::Int) {
ok = true;
if (m_useFindData)
sval = itemData(index).toString();
else
sval = itemText(index);
} else {
val = itemData(index).toInt(&ok);
ival = itemData(index).toInt(&ok);
}
if (ok) {
if (m_field && *m_field != val)
*m_field = val;
else if (m_rawSource && m_rawSource->toValue() != val)
*m_rawSource = RawSource(val);
else if (m_rawSwitch && m_rawSwitch->toValue() != val)
*m_rawSwitch = RawSwitch(val);
else if (m_curveType && *m_curveType != val)
*m_curveType = (CurveData::CurveType)val;
else if (m_flexType && *m_flexType != val)
*m_flexType = (Board::FlexType)val;
else if (m_switchType && *m_switchType != val)
*m_switchType = (Board::SwitchType)val;
else if (m_qString && *m_qString != str)
*m_qString = str;
else if (m_stdString && *m_stdString != str.toStdString())
*m_stdString = str.toStdString();
else
return;
if (m_int && *m_int != ival) {
*m_int = ival;
} else if (m_rawSource && m_rawSource->toValue() != ival) {
*m_rawSource = RawSource(ival);
} else if (m_rawSwitch && m_rawSwitch->toValue() != ival) {
*m_rawSwitch = RawSwitch(ival);
} else if (m_curveType && *m_curveType != ival) {
*m_curveType = (CurveData::CurveType)ival;
} else if (m_flexType && *m_flexType != ival) {
*m_flexType = (Board::FlexType)ival;
} else if (m_switchType && *m_switchType != ival) {
*m_switchType = (Board::SwitchType)ival;
} else if (m_qString && *m_qString != sval) {
*m_qString = sval;
} else if (m_stdString && *m_stdString != sval.toStdString()) {
*m_stdString = sval.toStdString();
// default using m_value
} else if (m_value.typeId() == QMetaType::Int && m_value.toInt() != ival) {
m_value = ival;
} else if (m_value.typeId() != QMetaType::Int && m_value.toString() != sval) {
m_value = sval;
}
emit currentDataChanged(val);
emit currentDataChanged(ival); // TODO change to QVariant
runPostChanged();
}
}
+21 -11
View File
@@ -46,27 +46,35 @@ class AutoComboBox : public QComboBox, public AutoWidget
// QComboBox
virtual void addItem(const QString & item);
virtual void addItem(const QString & item, int value);
virtual void addItems(const QStringList & items);
virtual void insertItems(int index, const QStringList & items);
// AutoWidget
virtual void updateValue() override;
void setAutoModel(QAbstractItemModel * model) override;
// not applicable to this widget
void setBindText(std::function<QString()> fn) = delete;
void clear();
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(int & field, GenericPanel * panel = nullptr);
void setField(RawSource & field, GenericPanel * panel = nullptr);
void setField(RawSwitch & field, GenericPanel * panel = nullptr);
void setField(CurveData::CurveType & field, GenericPanel * panel = nullptr);
void setField(Board::FlexType & field, GenericPanel * panel = nullptr);
void setField(Board::SwitchType & field, GenericPanel * panel = nullptr);
void setField(QString & field, GenericPanel * panel = nullptr);
void setField(std::string & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
void setField(int & field, AbstractPanel * panel = nullptr);
void setField(RawSource & field, AbstractPanel * panel = nullptr);
void setField(RawSwitch & field, AbstractPanel * panel = nullptr);
void setField(CurveData::CurveType & field, AbstractPanel * panel = nullptr);
void setField(Board::FlexType & field, AbstractPanel * panel = nullptr);
void setField(Board::SwitchType & field, AbstractPanel * panel = nullptr);
void setField(QString & field, AbstractPanel * panel = nullptr);
void setField(std::string & field, AbstractPanel * panel = nullptr);
void setAutoIndexes();
void setModel(QAbstractItemModel * model) override;
// use for widget not bound to a memory address
void setValue(QVariant value, AbstractPanel * panel, bool useFindData = true);
void setValue(QVariant value);
signals:
void currentDataChanged(int value);
@@ -76,7 +84,7 @@ class AutoComboBox : public QComboBox, public AutoWidget
private:
int m_next;
bool m_hasModel;
int *m_field;
int *m_int;
RawSource *m_rawSource;
RawSwitch *m_rawSwitch;
CurveData::CurveType *m_curveType;
@@ -84,7 +92,9 @@ class AutoComboBox : public QComboBox, public AutoWidget
Board::SwitchType *m_switchType;
QString *m_qString;
std::string *m_stdString;
QVariant m_value;
bool m_useFindData;
void initField();
void setFieldInit(GenericPanel * panel);
void setFieldInit(AbstractPanel * panel);
};
@@ -0,0 +1,74 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autodirectoryselectbutton.h"
#include <QLabel>
#include <QLineEdit>
AutoDirectorySelectButton::AutoDirectorySelectButton(QWidget * parent, const QString & buttonText) :
AutoPushButton(parent, buttonText),
m_caption(""),
m_dir(""),
m_displayDir(nullptr),
m_options(QFileDialog::ShowDirsOnly)
{
connect(this, &QPushButton::released, [&] ()
{
QString dir = QFileDialog::getExistingDirectory(this, m_caption, m_dir, m_options);
if (!dir.isEmpty()) {
m_dir = dir;
if (m_displayDir) {
QLabel *lbl = dynamic_cast<QLabel *>(m_displayDir);
if (lbl) {
lbl->setText(m_dir);
} else {
QLineEdit *le = dynamic_cast<QLineEdit *>(m_displayDir);
if (le) {
le->setText(m_dir);
le->setCursorPosition(0);
}
}
}
emit directoryChanged(m_dir);
runPostChanged();
}
});
}
AutoDirectorySelectButton::~AutoDirectorySelectButton()
{
}
void AutoDirectorySelectButton::setup(QString dlgCaption, QString dir,
QWidget * displayDir, QFileDialog::Options options)
{
m_caption = dlgCaption;
m_dir = dir;
m_displayDir = displayDir;
m_options = options;
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autopushbutton.h"
#include <QFileDialog>
class AutoDirectorySelectButton : public AutoPushButton
{
Q_OBJECT
public:
explicit AutoDirectorySelectButton(QWidget * parent = nullptr, const QString & buttonText = tr("Select..."));
virtual ~AutoDirectorySelectButton();
virtual void updateValue() override {}
void setup(QString dlgCaption, QString dir, QWidget * displayDir = nullptr,
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
signals:
void directoryChanged(QString dir);
private:
QString m_caption;
QString m_dir;
QWidget *m_displayDir;
QFileDialog::Options m_options;
};
+26 -9
View File
@@ -23,9 +23,10 @@
AutoDoubleSpinBox::AutoDoubleSpinBox(QWidget * parent):
QDoubleSpinBox(parent),
AutoWidget(),
AutoWidget(parent),
m_field(nullptr),
m_offset(0)
m_offset(0),
m_value(0)
{
connect(this, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AutoDoubleSpinBox::onValueChanged);
}
@@ -34,14 +35,14 @@ AutoDoubleSpinBox::~AutoDoubleSpinBox()
{
}
void AutoDoubleSpinBox::setField(int & field, GenericPanel * panel)
void AutoDoubleSpinBox::setField(int & field, AbstractPanel * panel)
{
m_field = &field;
setPanel(panel);
updateValue();
}
void AutoDoubleSpinBox::setField(unsigned int & field, GenericPanel * panel)
void AutoDoubleSpinBox::setField(unsigned int & field, AbstractPanel * panel)
{
m_field = (int *)&field;
setPanel(panel);
@@ -62,11 +63,14 @@ void AutoDoubleSpinBox::setOffset(int offset)
void AutoDoubleSpinBox::updateValue()
{
if (m_field) {
setLock(true);
setValue(float(*m_field + m_offset) / multiplier());
setLock(false);
}
setLock(true);
if (m_field)
QDoubleSpinBox::setValue(float(*m_field + m_offset) / multiplier());
else
QDoubleSpinBox::setValue(float(m_value + m_offset) / multiplier());
setLock(false);
}
int AutoDoubleSpinBox::multiplier()
@@ -91,3 +95,16 @@ void AutoDoubleSpinBox::onValueChanged(double value)
runPostChanged();
}
}
void AutoDoubleSpinBox::setValue(int val, AbstractPanel * panel)
{
m_value = val;
setPanel(panel);
updateValue();
}
void AutoDoubleSpinBox::setValue(int val)
{
m_value = val;
updateValue();
}
+6 -2
View File
@@ -41,10 +41,13 @@ class AutoDoubleSpinBox : public QDoubleSpinBox, public AutoWidget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(int & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(int & field, AbstractPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
void setDecimals(int prec);
void setOffset(int offset);
// use for widget not bound to a memory address
void setValue(int val, AbstractPanel * panel);
void setValue(int val);
signals:
void currentDataChanged(double value);
@@ -55,6 +58,7 @@ class AutoDoubleSpinBox : public QDoubleSpinBox, public AutoWidget
private:
int *m_field;
int m_offset;
int m_value;
int multiplier();
};
@@ -0,0 +1,74 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autofileselectbutton.h"
#include <QLabel>
#include <QLineEdit>
AutoFileSelectButton::AutoFileSelectButton(QWidget * parent, const QString & buttonText) :
AutoPushButton(parent, buttonText),
m_caption(""),
m_dir(""),
m_filter(""),
m_displayFile(nullptr),
m_options(QFileDialog::Options())
{
connect(this, &QPushButton::released, [&] ()
{
QString file = QFileDialog::getOpenFileName(this, m_caption, m_dir, m_filter, nullptr, m_options);
if (!file.isEmpty()) {
m_file = file;
if (m_displayFile) {
QLabel *lbl = dynamic_cast<QLabel *>(m_displayFile);
if (lbl) {
lbl->setText(m_file);
} else {
QLineEdit *le = dynamic_cast<QLineEdit *>(m_displayFile);
if (le)
le->setText(m_file);
}
}
emit fileChanged(m_file);
runPostChanged();
}
});
}
AutoFileSelectButton::~AutoFileSelectButton()
{
}
void AutoFileSelectButton::setup(const QString dlgCaption, const QString dir,
const QString filter, QWidget * displayFile,
QFileDialog::Options options)
{
m_caption = dlgCaption;
m_dir = dir;
m_filter = filter;
m_displayFile = displayFile;
m_options = options;
}
@@ -0,0 +1,52 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autopushbutton.h"
#include <QFileDialog>
class AutoFileSelectButton : public AutoPushButton
{
Q_OBJECT
public:
explicit AutoFileSelectButton(QWidget * parent = nullptr, const QString & buttonText = tr("Select..."));
virtual ~AutoFileSelectButton();
virtual void updateValue() override {}
void setup(const QString dlgCaption = QString(), const QString dir = QString(),
const QString filter = QString(), QWidget * displayFile = nullptr,
QFileDialog::Options options = QFileDialog::Options());
signals:
void fileChanged(QString file);
private:
QString m_caption;
QString m_dir;
QString m_filter;
QWidget *m_displayFile;
QFileDialog::Options m_options;
QString m_file;
};
+33 -13
View File
@@ -24,8 +24,9 @@
AutoHexSpinBox::AutoHexSpinBox(QWidget * parent):
QSpinBox(parent),
AutoWidget(),
m_field(nullptr)
AutoWidget(parent),
m_field(nullptr),
m_value(0)
{
setRange(0, AUTOHEXSPINBOX_MAX_VALUE);
connect(this, QOverload<int>::of(&QSpinBox::valueChanged), this, &AutoHexSpinBox::onValueChanged);
@@ -35,7 +36,7 @@ AutoHexSpinBox::~AutoHexSpinBox()
{
}
void AutoHexSpinBox::setField(unsigned int & field, const unsigned int min, const unsigned int max, GenericPanel * panel)
void AutoHexSpinBox::setField(unsigned int & field, const unsigned int min, const unsigned int max, AbstractPanel * panel)
{
m_field = &field;
setRange(min, max);
@@ -43,7 +44,7 @@ void AutoHexSpinBox::setField(unsigned int & field, const unsigned int min, cons
updateValue();
}
void AutoHexSpinBox::setField(unsigned int & field, GenericPanel * panel)
void AutoHexSpinBox::setField(unsigned int & field, AbstractPanel * panel)
{
m_field = &field;
setRange(0, AUTOHEXSPINBOX_MAX_VALUE);
@@ -60,23 +61,42 @@ void AutoHexSpinBox::setRange(const unsigned int min, const unsigned int max)
m_validator = new QRegularExpressionValidator(QRegularExpression(QString("[0-9A-Fa-f]{1,%1}").arg(m_length)), this);
}
void AutoHexSpinBox::setValue(int val, AbstractPanel * panel)
{
m_value = val;
setRange(0, AUTOHEXSPINBOX_MAX_VALUE);
setPanel(panel);
updateValue();
}
void AutoHexSpinBox::setValue(int val)
{
setRange(0, AUTOHEXSPINBOX_MAX_VALUE);
updateValue();
}
void AutoHexSpinBox::updateValue()
{
if (m_field) {
setLock(true);
setValue(*m_field);
setLock(false);
}
setLock(true);
if (m_field)
QSpinBox::setValue(*m_field);
else
QSpinBox::setValue(m_value);
setLock(false);
}
void AutoHexSpinBox::onValueChanged(int value)
{
if (m_field && !lock()) {
if (*m_field != (unsigned)value) {
if (*m_field != (unsigned)value)
*m_field = (unsigned)value;
emit currentDataChanged(value);
runPostChanged();
}
else if (m_value != (unsigned)value)
m_value = (unsigned)value;
emit currentDataChanged(value);
runPostChanged();
}
}
+6 -2
View File
@@ -42,9 +42,12 @@ class AutoHexSpinBox : public QSpinBox, public AutoWidget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(unsigned int & field, const unsigned int min = 0, const unsigned int max = AUTOHEXSPINBOX_MAX_VALUE, GenericPanel * panel = nullptr);
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, const unsigned int min = 0, const unsigned int max = AUTOHEXSPINBOX_MAX_VALUE, AbstractPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
void setRange(unsigned int min = 0, unsigned int max = AUTOHEXSPINBOX_MAX_VALUE);
// use for widget not bound to a memory address
void setValue(int val, AbstractPanel * panel);
void setValue(int val);
protected:
QValidator::State validate(QString &text, int &pos) const;
@@ -61,4 +64,5 @@ class AutoHexSpinBox : public QSpinBox, public AutoWidget
unsigned int *m_field;
QRegularExpressionValidator *m_validator;
unsigned int m_length;
unsigned int m_value;
};
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autoimage.h"
AutoImage::AutoImage(QWidget * parent, const QString & filename, int width, int height, int depth) :
QLabel(parent),
AutoWidget(parent)
{
setup(filename, width, height, depth);
}
AutoImage::~AutoImage()
{
}
void AutoImage::setup(const QString & filename, int width, int height, int depth)
{
m_filename = filename;
setDimensions(width, height, depth);
}
void AutoImage::setDimensions(int width, int height, int depth)
{
m_width = width;
m_height = height;
m_depth = depth;
setFixedSize(m_width, m_height);
}
void AutoImage::updateValue()
{
setLock(true);
clear();
if (!m_filename.isEmpty()) {
QImage image(m_filename);
if (!image.isNull()) {
QImage result = image.scaled(m_width, m_height);
if (m_depth == 4) {
result = result.convertToFormat(QImage::Format_RGB32);
for (int i = 0; i < result.width(); ++i) {
for (int j = 0; j < result.height(); ++j) {
QRgb col = result.pixel(i, j);
int gray = qGray(col);
result.setPixel(i, j, qRgb(gray, gray, gray));
}
}
} else {
result = result.convertToFormat(QImage::Format_Mono);
}
setPixmap(QPixmap::fromImage(result));
}
}
setLock(false);
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autowidget.h"
#include <QLabel>
class AutoImage: public QLabel, public AutoWidget
{
Q_OBJECT
public:
explicit AutoImage(QWidget * parent = nullptr, const QString & filename = QString(), int width = 100, int height = 100, int depth = 4);
virtual ~AutoImage();
virtual void updateValue() override;
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setup(const QString & filename, int width, int height, int depth);
void setDimensions(int width, int height, int depth);
protected:
private:
QString m_filename;
int m_depth;
int m_height;
int m_width;
};
+5 -4
View File
@@ -23,26 +23,27 @@
#include <QFontMetrics>
AutoLabel::AutoLabel(QWidget * parent):
AutoLabel::AutoLabel(QWidget * parent, const QString & text) :
QLabel(parent),
AutoWidget(),
AutoWidget(parent),
m_charField(NULL),
m_strField(nullptr)
{
setText(text);
}
AutoLabel::~AutoLabel()
{
}
void AutoLabel::setField(char * field, GenericPanel * panel)
void AutoLabel::setField(char * field, AbstractPanel * panel)
{
m_charField = field;
setPanel(panel);
updateValue();
}
void AutoLabel::setField(QString & field, GenericPanel * panel)
void AutoLabel::setField(QString & field, AbstractPanel * panel)
{
m_strField = &field;
setPanel(panel);
+3 -3
View File
@@ -30,14 +30,14 @@ class AutoLabel: public QLabel, public AutoWidget
Q_OBJECT
public:
explicit AutoLabel(QWidget * parent = nullptr);
explicit AutoLabel(QWidget * parent = nullptr, const QString & text = QString());
virtual ~AutoLabel();
virtual void updateValue() override;
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setField(char * field, GenericPanel * panel = nullptr);
void setField(QString & field, GenericPanel * panel = nullptr);
void setField(char * field, AbstractPanel * panel = nullptr);
void setField(QString & field, AbstractPanel * panel = nullptr);
void setWidth(int numChars);
protected:
+60 -13
View File
@@ -23,47 +23,64 @@
AutoLineEdit::AutoLineEdit(QWidget * parent, bool updateOnChange):
QLineEdit(parent),
AutoWidget(),
AutoWidget(parent),
m_charField(NULL),
m_strField(nullptr)
m_strField(nullptr),
m_value("")
{
if (updateOnChange)
connect(this, &QLineEdit::textChanged, this, &AutoLineEdit::onEdited);
else
connect(this, &QLineEdit::editingFinished, this, &AutoLineEdit::onEdited);
setEditSignal(updateOnChange);
}
AutoLineEdit::~AutoLineEdit()
{
}
void AutoLineEdit::setField(char * field, int len, GenericPanel * panel)
void AutoLineEdit::setField(char * field, int len, AbstractPanel * panel)
{
m_charField = field;
setFieldInit(len, panel);
}
void AutoLineEdit::setField(QString & field, int len, GenericPanel * panel)
void AutoLineEdit::setField(QString & field, int len, AbstractPanel * panel)
{
m_strField = &field;
setFieldInit(len, panel);
}
void AutoLineEdit::setFieldInit(int len, GenericPanel * panel)
void AutoLineEdit::setFieldInit(int len, AbstractPanel * panel)
{
setPanel(panel);
if (len)
setMaxLength(len);
setLength(len);
updateValue();
}
void AutoLineEdit::setLength(int len)
{
if (len) setMaxLength(len);
}
void AutoLineEdit::setEditSignal(bool onChange)
{
disconnect(this, &QLineEdit::textChanged, this, &AutoLineEdit::onEdited);
disconnect(this, &QLineEdit::editingFinished, this, &AutoLineEdit::onEdited);
if (onChange)
connect(this, &QLineEdit::textChanged, this, &AutoLineEdit::onEdited);
else
connect(this, &QLineEdit::editingFinished, this, &AutoLineEdit::onEdited);
}
void AutoLineEdit::updateValue()
{
setLock(true);
if (m_strField)
QLineEdit::setText(*m_strField);
setText(*m_strField);
else if (m_charField)
QLineEdit::setText(m_charField);
setText(m_charField);
else
setText(m_value);
setLock(false);
}
@@ -76,6 +93,8 @@ void AutoLineEdit::onEdited()
*m_strField = text();
else if (m_charField && strcmp(m_charField, text().toLatin1()))
strcpy(m_charField, text().toLatin1());
else if (m_value != text())
m_value = text();
else
return;
@@ -89,3 +108,31 @@ void AutoLineEdit::setAutoText(QString text)
QLineEdit::setText(text);
setLock(false);
}
void AutoLineEdit::setValue(QString text)
{
if (!m_strField && !m_charField) {
m_value = text;
updateValue();
}
}
void AutoLineEdit::setValue(QString text, AbstractPanel * panel, int len)
{
if (!m_strField && !m_charField) {
m_value = text;
setFieldInit(len, panel);
}
}
// virtual default
void AutoLineEdit::setText(const QString & text)
{
QLineEdit::setText(text);
}
// virtual default
QString AutoLineEdit::text() const
{
return QLineEdit::text();
}
+15 -4
View File
@@ -33,13 +33,23 @@ class AutoLineEdit: public QLineEdit, public AutoWidget
explicit AutoLineEdit(QWidget * parent = nullptr, bool updateOnChange = false);
virtual ~AutoLineEdit();
virtual void updateValue() override;
virtual void setText(const QString & text);
virtual QString text() const;
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setField(char * field, int len, GenericPanel * panel = nullptr);
void setField(QString & field, int len = 0, GenericPanel * panel = nullptr);
void setField(char * field, int len, AbstractPanel * panel = nullptr);
void setField(QString & field, int len = 0, AbstractPanel * panel = nullptr);
signals:
void setLength(int len);
void setEditSignal(bool onChange);
// use for widget not bound to a memory address
void setValue(QString text, AbstractPanel * panel, int len = 0);
void setValue(QString text);
signals:
void currentDataChanged();
protected slots:
@@ -51,6 +61,7 @@ class AutoLineEdit: public QLineEdit, public AutoWidget
private:
char *m_charField;
QString *m_strField;
QString m_value;
void setFieldInit(int len, GenericPanel * panel);
void setFieldInit(int len, AbstractPanel * panel);
};
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autolineeditpath.h"
#include <QDir>
AutoLineEditPath::AutoLineEditPath(QWidget * parent, bool updateOnChange):
AutoLineEdit(parent, updateOnChange)
{
}
AutoLineEditPath::~AutoLineEditPath()
{
}
void AutoLineEditPath::setText(const QString & path)
{
QLineEdit::setText(QDir::toNativeSeparators(path));
}
QString AutoLineEditPath::text() const
{
return QDir::fromNativeSeparators(QLineEdit::text());
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autolineedit.h"
// encapsulates calls to and from native separators
class AutoLineEditPath : public AutoLineEdit
{
Q_OBJECT
public:
explicit AutoLineEditPath(QWidget * parent = nullptr, bool updateOnChange = false);
virtual ~AutoLineEditPath();
virtual void setText(const QString & path) override;
virtual QString text() const override;
protected:
private:
};
@@ -26,13 +26,13 @@ constexpr unsigned int APCB_DECIMALS_MAX {6};
AutoPrecisionComboBox::AutoPrecisionComboBox(QWidget * parent):
QComboBox(parent),
AutoWidget()
AutoWidget(parent)
{
setFieldInit();
init();
}
AutoPrecisionComboBox::AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, GenericPanel * panel):
AutoPrecisionComboBox::AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, AbstractPanel * panel):
QComboBox(parent),
AutoWidget()
{
@@ -41,7 +41,7 @@ AutoPrecisionComboBox::AutoPrecisionComboBox(unsigned int & field, unsigned int
init();
}
AutoPrecisionComboBox::AutoPrecisionComboBox(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, GenericPanel * panel):
AutoPrecisionComboBox::AutoPrecisionComboBox(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, AbstractPanel * panel):
QComboBox(parent),
AutoWidget()
{
@@ -54,14 +54,14 @@ AutoPrecisionComboBox::~AutoPrecisionComboBox()
{
}
void AutoPrecisionComboBox::setField(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel)
void AutoPrecisionComboBox::setField(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, AbstractPanel * panel)
{
m_field = (unsigned int *)&field;
setFieldInit(minDecimals, maxDecimals, padding, suffix, panel);
setPanel(panel);
}
void AutoPrecisionComboBox::setField(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel)
void AutoPrecisionComboBox::setField(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, AbstractPanel * panel)
{
m_field = &field;
setFieldInit(minDecimals, maxDecimals, padding, suffix, panel);
@@ -161,7 +161,7 @@ void AutoPrecisionComboBox::init()
connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AutoPrecisionComboBox::onCurrentIndexChanged);
}
void AutoPrecisionComboBox::setFieldInit(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel)
void AutoPrecisionComboBox::setFieldInit(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, AbstractPanel * panel)
{
setLock(true);
setMinDecimals(minDecimals);
+5 -5
View File
@@ -32,16 +32,16 @@ class AutoPrecisionComboBox : public QComboBox, public AutoWidget
public:
explicit AutoPrecisionComboBox(QWidget * parent = nullptr);
explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr);
explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr);
explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, AbstractPanel * panel = nullptr);
explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, AbstractPanel * panel = nullptr);
virtual ~AutoPrecisionComboBox();
virtual void updateValue() override;
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr);
void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr);
void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", AbstractPanel * panel = nullptr);
void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", AbstractPanel * panel = nullptr);
void setMinDecimals(unsigned int minDecimals);
void setMaxDecimals(unsigned int maxDecimals);
void setDecimalsRange(unsigned int min, unsigned int max);
@@ -65,7 +65,7 @@ class AutoPrecisionComboBox : public QComboBox, public AutoWidget
QString m_suffix = "";
void init();
void setFieldInit(unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr);
void setFieldInit(unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", AbstractPanel * panel = nullptr);
bool isValidDecimals(unsigned int value);
unsigned int rangecheckDecimals(unsigned int decimals);
void updateList();
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "autopushbutton.h"
AutoPushButton::AutoPushButton(QWidget * parent, const QString & text):
QPushButton(parent),
AutoWidget(parent)
{
setText(text);
connect(this, &QPushButton::clicked, this, [this] () {
if (this->m_clicked) this->m_clicked();
});
}
AutoPushButton::~AutoPushButton()
{
}
void AutoPushButton::setBindClicked(std::function<void()> fn)
{
m_clicked = std::move(fn);
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autowidget.h"
#include <QPushButton>
class AutoPushButton: public QPushButton, public AutoWidget
{
Q_OBJECT
public:
explicit AutoPushButton(QWidget * parent = nullptr, const QString & text = "...");
virtual ~AutoPushButton();
virtual void updateValue() override {}
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindClicked(std::function<void()> fn);
protected:
private:
std::function<void()> m_clicked;
};
+31 -13
View File
@@ -23,7 +23,9 @@
AutoSlider::AutoSlider(QWidget * parent):
QSlider(parent),
AutoWidget()
AutoWidget(parent),
m_field(nullptr),
m_value(0)
{
init();
}
@@ -39,13 +41,13 @@ AutoSlider::~AutoSlider()
{
}
void AutoSlider::setField(int & field, int min, int max, GenericPanel * panel)
void AutoSlider::setField(int & field, int min, int max, AbstractPanel * panel)
{
m_field = &field;
setFieldInit(min, max, panel);
}
void AutoSlider::setField(unsigned int & field, int min, int max, GenericPanel * panel)
void AutoSlider::setField(unsigned int & field, int min, int max, AbstractPanel * panel)
{
m_field = (int *)&field;
setFieldInit(min, max, panel);
@@ -57,13 +59,27 @@ void AutoSlider::setTick(int interval, QSlider::TickPosition position)
setTickPosition(position);
}
void AutoSlider::setValue(int val, int min, int max, AbstractPanel * panel)
{
m_value = val;
setFieldInit(min, max, panel);
}
void AutoSlider::setValue(int val)
{
m_value = val;
updateValue();
}
void AutoSlider::updateValue()
{
if (m_field) {
setLock(true);
setValue(*m_field);
setLock(false);
}
setLock(true);
if (m_field)
QSlider::setValue(*m_field);
else
QSlider::setValue(m_value);
setLock(false);
}
void AutoSlider::init()
@@ -71,7 +87,7 @@ void AutoSlider::init()
connect(this, &QSlider::valueChanged, this, &AutoSlider::onValueChanged);
}
void AutoSlider::setFieldInit(int min, int max, GenericPanel * panel)
void AutoSlider::setFieldInit(int min, int max, AbstractPanel * panel)
{
setPanel(panel);
setRange(min, max);
@@ -81,10 +97,12 @@ void AutoSlider::setFieldInit(int min, int max, GenericPanel * panel)
void AutoSlider::onValueChanged(int value)
{
if (m_field && !lock()) {
if (*m_field != value) {
if (*m_field != value)
*m_field = value;
emit currentDataChanged(value);
runPostChanged();
}
else if (m_value != value)
m_value = value;
emit currentDataChanged(value);
runPostChanged();
}
}
+8 -4
View File
@@ -38,9 +38,12 @@ class AutoSlider : public QSlider, public AutoWidget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(int & field, int min, int max, GenericPanel * panel = nullptr);
void setField(unsigned int & field, int min, int max, GenericPanel * panel = nullptr);
void setField(int & field, int min, int max, AbstractPanel * panel = nullptr);
void setField(unsigned int & field, int min, int max, AbstractPanel * panel = nullptr);
void setTick(int interval, QSlider::TickPosition position);
// use for widget not bound to a memory address
void setValue(int val, int min, int max, AbstractPanel * panel);
void setValue(int val);
signals:
void currentDataChanged(int value);
@@ -49,8 +52,9 @@ class AutoSlider : public QSlider, public AutoWidget
void onValueChanged(int value);
private:
int *m_field = nullptr;
int *m_field;
int m_value;
void init();
void setFieldInit(int min, int max, GenericPanel * panel);
void setFieldInit(int min, int max, AbstractPanel * panel);
};
+33 -15
View File
@@ -23,8 +23,9 @@
AutoSpinBox::AutoSpinBox(QWidget * parent):
QSpinBox(parent),
AutoWidget(),
m_field(nullptr)
AutoWidget(parent),
m_field(nullptr),
m_value(0)
{
connect(this, QOverload<int>::of(&QSpinBox::valueChanged), this, &AutoSpinBox::onValueChanged);
}
@@ -33,40 +34,57 @@ AutoSpinBox::~AutoSpinBox()
{
}
void AutoSpinBox::setField(int & field, GenericPanel * panel)
void AutoSpinBox::setField(int & field, AbstractPanel * panel)
{
m_field = &field;
setFieldInit(panel);
}
void AutoSpinBox::setField(unsigned int & field, GenericPanel * panel)
void AutoSpinBox::setField(unsigned int & field, AbstractPanel * panel)
{
m_field = (int *)&field;
setFieldInit(panel);
}
void AutoSpinBox::setFieldInit(GenericPanel * panel)
void AutoSpinBox::setFieldInit(AbstractPanel * panel)
{
setPanel(panel);
updateValue();
}
void AutoSpinBox::setValue(int val, AbstractPanel * panel)
{
m_value = val;
setFieldInit(panel);
}
void AutoSpinBox::setValue(int val)
{
m_value = val;
updateValue();
}
void AutoSpinBox::updateValue()
{
if (m_field) {
setLock(true);
setValue(*m_field);
setLock(false);
}
setLock(true);
if (m_field)
QSpinBox::setValue(*m_field);
else
QSpinBox::setValue(m_value);
setLock(false);
}
void AutoSpinBox::onValueChanged(int value)
{
if (m_field && !lock()) {
if (*m_field != value) {
if (!lock()) {
if (m_field && *m_field != value)
*m_field = value;
emit currentDataChanged(value);
runPostChanged();
}
else if (m_value != value)
m_value = value;
emit currentDataChanged(value);
runPostChanged();
}
}
+7 -3
View File
@@ -37,8 +37,11 @@ class AutoSpinBox : public QSpinBox, public AutoWidget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(int & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(int & field, AbstractPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
// use for widget not bound to a memory address
void setValue(int val, AbstractPanel * panel);
void setValue(int val);
signals:
void currentDataChanged(int value);
@@ -48,6 +51,7 @@ class AutoSpinBox : public QSpinBox, public AutoWidget
private:
int *m_field;
int m_value;
void setFieldInit(GenericPanel * panel);
void setFieldInit(AbstractPanel * panel);
};
+2 -2
View File
@@ -23,7 +23,7 @@
AutoTimeEdit::AutoTimeEdit(QWidget * parent):
QTimeEdit(parent),
AutoWidget(),
AutoWidget(parent),
m_field(nullptr)
{
connect(this, &QTimeEdit::timeChanged, this, &AutoTimeEdit::onTimeChanged);
@@ -33,7 +33,7 @@ AutoTimeEdit::~AutoTimeEdit()
{
}
void AutoTimeEdit::setField(unsigned int & field, GenericPanel * panel)
void AutoTimeEdit::setField(unsigned int & field, AbstractPanel * panel)
{
m_field = &field;
setPanel(panel);
+1 -1
View File
@@ -37,7 +37,7 @@ class AutoTimeEdit : public QTimeEdit, public AutoWidget
void setBindModel(std::function<QAbstractItemModel*()> fn) = delete;
void setBindText(std::function<QString()> fn) = delete;
void setField(unsigned int & field, GenericPanel * panel = nullptr);
void setField(unsigned int & field, AbstractPanel * panel = nullptr);
void setTimeRange(const QTime min, const QTime max);
signals:
+70 -34
View File
@@ -20,28 +20,42 @@
*/
#include "autowidget.h"
#include "genericpanel.h"
#include "abstractpanel.h"
#include <memory>
AutoWidget::AutoWidget():
AutoWidget::AutoWidget(QWidget * parent):
m_panel(nullptr),
m_lock(false),
m_buddyWidgets(QList<AutoWidget *> {nullptr}),
m_parentBuddyWidget(nullptr),
m_enabled(nullptr),
m_model(nullptr),
m_text(nullptr),
m_visible(nullptr)
m_visible(nullptr),
m_preUpdate(nullptr),
m_postChanged(nullptr),
m_save(nullptr)
{
if (parent) {
AbstractPanel * panel = dynamic_cast<AbstractPanel *>(parent);
if (panel) m_panel = panel;
}
}
AutoWidget::~AutoWidget()
{
}
AutoWidget::~AutoWidget() = default;
void AutoWidget::addBuddyParentWidget(AutoWidget * wgt)
{
if (wgt) wgt->addBuddyWidget(this);
}
void AutoWidget::addBuddyWidget(AutoWidget * wgt)
{
if (wgt) {
m_buddyWidgets.append(wgt);
// just in case set as we want parent to control
clearBuddyBinds(wgt);
}
}
@@ -55,7 +69,7 @@ void AutoWidget::addBuddyWidgets(QList<AutoWidget *> wgts)
}
}
// Apply bindings to this AutoWidget also enabled and visible to all buddy AutoWidgets
// Apply bindings to this AutoWidget and selective to all buddy AutoWidgets
void AutoWidget::applyBindings()
{
if (m_enabled) {
@@ -80,17 +94,13 @@ void AutoWidget::applyBindings()
}
}
if (m_text) {
// makes no sense to apply parent bind to buddies
// leave it to each buddy to apply when it is updated
setAutoText(m_text());
}
// makes no sense to apply parent bind to buddies
// leave it to each buddy to apply when it is updated
if (m_text) setAutoText(m_text());
if (m_model) {
// makes no sense to apply parent bind to buddies
// leave it to each buddy to apply when it is updated
setAutoModel(m_model());
}
// makes no sense to apply parent bind to buddies
// leave it to each buddy to apply when it is updated
if (m_model) setAutoModel(m_model());
}
void AutoWidget::clearBindEnabled()
@@ -108,26 +118,14 @@ void AutoWidget::clearBuddyBinds(AutoWidget * wgt)
if (wgt) {
wgt->clearBindEnabled();
wgt->clearBindVisible();
// needed for wgt dtor to remove itself from controlling widget
wgt->setParentBuddyWidget(this);
}
}
void AutoWidget::clearBuddyWidget(AutoWidget * wgt)
{
if (wgt) {
if (!m_buddyWidgets.removeOne(wgt))
qDebug() << "Warning: widget not removed from list";
}
}
void AutoWidget::clearBuddyWidgets()
{
m_buddyWidgets.clear();
}
void AutoWidget::dataChanged()
{
if (m_panel)
emit m_panel->modified();
if (m_panel) emit m_panel->modified();
}
bool AutoWidget::lock()
@@ -140,12 +138,34 @@ bool AutoWidget::panelLock()
return m_panel ? m_panel->lock : false;
}
void AutoWidget::removeBuddyWidget(AutoWidget * wgt)
{
if (wgt) {
if (!m_buddyWidgets.removeOne(wgt))
qDebug() << "Warning: widget not removed from list";
}
}
void AutoWidget::removeBuddyWidgets()
{
m_buddyWidgets.clear();
}
void AutoWidget::runPreUpdate()
{
if (m_preUpdate) m_preUpdate();
}
void AutoWidget::runPostChanged()
{
dataChanged();
if (m_postChanged)
m_postChanged();
if (m_postChanged) m_postChanged();
}
void AutoWidget::saveValue()
{
if (m_save) m_save();
}
void AutoWidget::setAutoEnabled(bool enabled)
@@ -165,11 +185,21 @@ void AutoWidget::setBindEnabled(std::function<bool()> pred)
m_enabled = std::move(pred);
}
void AutoWidget::setBindSave(std::function<void()> fn)
{
m_save = std::move(fn);
}
void AutoWidget::setBindModel(std::function<QAbstractItemModel*()> fn)
{
m_model = std::move(fn);
}
void AutoWidget::setBindPreUpdate(std::function<void()> fn)
{
m_preUpdate = std::move(fn);
}
void AutoWidget::setBindPostChanged(std::function<void()> fn)
{
m_postChanged = std::move(fn);
@@ -190,7 +220,13 @@ void AutoWidget::setLock(bool lock)
m_lock = lock;
}
void AutoWidget::setPanel(GenericPanel * panel)
void AutoWidget::setPanel(AbstractPanel * panel)
{
m_panel = panel;
}
void AutoWidget::setParentBuddyWidget(AutoWidget * wgt)
{
m_parentBuddyWidget = wgt;
}
+20 -10
View File
@@ -28,63 +28,73 @@
#include <QList>
#include <QAbstractItemModel>
class GenericPanel;
class AbstractPanel;
// Base class for all Auto name prefixed widgets
// Note: ths class cannot be a Qt object as it will trigger a compile time ambiguity in the inheriting class
// Note: this class cannot be a Qt object as it will trigger a compile time ambiguity in the inheriting class
class AutoWidget
{
friend class GenericPanel;
friend class AbstractPanel;
public:
explicit AutoWidget();
explicit AutoWidget(QWidget * parent = nullptr);
~AutoWidget();
// buddy Auto widgets have their bindings mirroring the parent
// example buddies are AutoLabel and AutoComboBox
void addBuddyWidget(AutoWidget * wgt);
void addBuddyWidgets(QList<AutoWidget *> wgts);
void clearBuddyWidget(AutoWidget * wgt);
void clearBuddyWidgets();
void removeBuddyWidget(AutoWidget * wgt);
void removeBuddyWidgets();
void addBuddyParentWidget(AutoWidget * wgt);
// mark those unsupported by the base Qt widget as deleted in the child widget
// mark those unsupported as deleted in the child widget
// these are not marked as virtual to support deletion
void setBindEnabled(std::function<bool()> pred);
void setBindModel(std::function<QAbstractItemModel*()> fn);
void setBindPreUpdate(std::function<void()> fn);
void setBindPostChanged(std::function<void()> fn);
void setBindSave(std::function<void()> fn);
void setBindText(std::function<QString()> fn);
void setBindVisible(std::function<bool()> pred);
void setPanel(AbstractPanel * panel);
protected:
virtual void setAutoModel(QAbstractItemModel * model) {};
virtual void setAutoText(QString text) {};
virtual void saveValue();
virtual void updateValue() = 0;
void applyBindings();
void clearBindEnabled();
void clearBindVisible();
void clearBuddyBinds(AutoWidget * wgt);
void setParentBuddyWidget(AutoWidget * wgt);
bool lock();
bool panelLock();
void runPreUpdate();
void runPostChanged();
void setAutoEnabled(bool enabled);
void setAutoVisible(bool visible);
void setLock(bool lock);
void setPanel(GenericPanel * panel);
private:
GenericPanel *m_panel;
AbstractPanel *m_panel;
bool m_lock;
QList<AutoWidget *> m_buddyWidgets;
AutoWidget *m_parentBuddyWidget;
std::function<bool()> m_enabled;
std::function<QAbstractItemModel*()> m_model;
std::function<QString()> m_text;
std::function<bool()> m_visible;
std::function<void()> m_preUpdate;
std::function<void()> m_postChanged;
std::function<void()> m_save;
void dataChanged();
};
+10 -2
View File
@@ -21,15 +21,23 @@
#pragma once
#include "autobitmappedcheckbox.h"
#include "autobitmappedcombobox.h"
#include "autobitsetcheckbox.h"
#include "autocheckbox.h"
#include "autocollapsiblesection.h"
#include "autocolorselectbutton.h"
#include "autocombobox.h"
#include "autodoublespinbox.h"
#include "autofileselectbutton.h"
#include "autodirectoryselectbutton.h"
#include "autohexspinbox.h"
#include "autoimage.h"
#include "autolabel.h"
#include "autolineedit.h"
#include "autolineeditpath.h"
#include "autoprecisioncombobox.h"
#include "autopushbutton.h"
#include "autoslider.h"
#include "autospinbox.h"
#include "autotimeedit.h"
#include "autobitmappedcheckbox.h"
#include "autobitmappedcombobox.h"
+123
View File
@@ -0,0 +1,123 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "firmwarepicker.h"
#include "ui_firmwarepicker.h"
#include "eeprominterface.h"
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <algorithm>
FirmwarePicker::FirmwarePicker(QWidget * parent, const QString & type) :
QDialog(parent),
ui(new Ui::FirmwarePicker),
m_oldtype(type),
m_currentItem(nullptr)
{
ui->setupUi(this);
ui->treeWidget->header()->hide();
ui->treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
QList<QStringList> list;
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
if (firmware->isBase()) {
QStringList item;
item.append(firmware->getFullName());
item.append(Boards::getManufacturer(firmware->getBoard()));
item.append(firmware->getShortName());
item.append(firmware->getId());
list.append(item);
}
}
// sort by full name
std::sort(list.begin(), list.end(), [] (const QStringList &a, const QStringList &b)
{
return QString::compare(a.at(0), b.at(0), Qt::CaseInsensitive) < 0;
});
ui->treeWidget->setColumnCount(1);
ui->treeWidget->header()->hide();
ui->treeWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QTreeWidgetItem *lastManu = nullptr;
for (int i = 0; i < list.count(); i++) {
if (!lastManu || lastManu->text(0) != list.at(i).at(1)) {
QTreeWidgetItem * manu = new QTreeWidgetItem();
manu->setText(0, list.at(i).at(1));
manu->setFlags(manu->flags() &~ Qt::ItemIsSelectable);
ui->treeWidget->addTopLevelItem(manu);
lastManu = manu;
}
QTreeWidgetItem * item = new QTreeWidgetItem();
item->setText(0, list.at(i).at(2)); // short name
item->setData(0, Qt::UserRole, list.at(i).at(3)); // id
lastManu->addChild(item);
if (m_oldtype == list.at(i).at(3))
m_currentItem = item;
}
if (m_currentItem) {
QTreeWidgetItem *parentItem = m_currentItem->parent();
while (parentItem != nullptr) {
parentItem->setExpanded(true);
parentItem = parentItem->parent();
}
}
// running adjustSize inline does not give enogh time for widgets to have updated their geometry
QTimer::singleShot(0, this, &FirmwarePicker::adjustSize);
// need to allow time for adjustSize to complete otherwise this has no effect
// this is an abitary delay through trial and error
QTimer::singleShot(100, this, [this] () {
if (m_currentItem) {
ui->treeWidget->scrollToItem(m_currentItem, QAbstractItemView::PositionAtCenter);
ui->treeWidget->setCurrentItem(m_currentItem);
}
});
}
FirmwarePicker::~FirmwarePicker()
{
delete ui;
}
void FirmwarePicker::accept()
{
if (ui->treeWidget->selectedItems().count() > 0) {
m_currentItem = ui->treeWidget->selectedItems().first();
QString newtype = m_currentItem->data(0, Qt::UserRole).toString();
if (newtype != m_oldtype)
emit firmwareTypeChanged(newtype);
}
QDialog::accept();
}
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <QDialog>
class QTreeWidget;
class QTreeWidgetItem;
namespace Ui {
class FirmwarePicker;
}
class FirmwarePicker : public QDialog
{
Q_OBJECT
public:
FirmwarePicker(QWidget * parent, const QString & currentType);
virtual ~FirmwarePicker();
public slots:
virtual void accept() Q_DECL_OVERRIDE;
signals:
void firmwareTypeChanged(const QString newType);
private:
Ui::FirmwarePicker *ui;
const QString &m_oldtype;
QTreeWidgetItem *m_currentItem;
};
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FirmwarePicker</class>
<widget class="QDialog" name="FirmwarePicker">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Available Firmware</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="treeWidget">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FirmwarePicker</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FirmwarePicker</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+3 -124
View File
@@ -20,136 +20,15 @@
*/
#include "genericpanel.h"
#include "autowidget.h"
#include "widgetbindings.h"
#include <TimerEdit>
#include <QComboBox>
#include <QEvent>
#include <QLabel>
#include <QGridLayout>
#include <QSpacerItem>
#include "eeprominterface.h"
GenericPanel::GenericPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware):
QWidget(parent),
AbstractPanel(parent),
model(model),
generalSettings(generalSettings),
firmware(firmware),
firmware(firmware)
//board(firmware->getBoard()), TODO: as part of capabilities refactor
lock(false)
{
}
GenericPanel::~GenericPanel() = default;
void GenericPanel::update()
{
}
void GenericPanel::addLabel(QGridLayout *gridLayout, const QString &text, int col, bool minimize)
{
QLabel *label = new QLabel(this);
label->setFrameShape(QFrame::Panel);
label->setFrameShadow(QFrame::Raised);
label->setMidLineWidth(0);
label->setAlignment(Qt::AlignCenter);
label->setMargin(5);
label->setText(text);
if (!minimize)
label->setMinimumWidth(100);
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addEmptyLabel(QGridLayout * gridLayout, int col)
{
QLabel *label = new QLabel(this);
label->setText("");
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addHSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addVSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addDoubleSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
bool GenericPanel::eventFilter(QObject *object, QEvent * event)
{
QWidget * widget = qobject_cast<QWidget*>(object);
if (widget) {
if (event->type() == QEvent::Wheel) {
if (widget->focusPolicy() == Qt::WheelFocus) {
event->accept();
return false;
}
else {
event->ignore();
return true;
}
}
else if (event->type() == QEvent::FocusIn) {
widget->setFocusPolicy(Qt::WheelFocus);
}
else if (event->type() == QEvent::FocusOut) {
widget->setFocusPolicy(Qt::StrongFocus);
}
}
return QWidget::eventFilter(object, event);
}
void GenericPanel::setFocusFilter(QWidget * w)
{
w->installEventFilter(this);
w->setFocusPolicy(Qt::StrongFocus);
}
void GenericPanel::disableMouseScrolling()
{
foreach(QWidget * cb, findChildren<QComboBox*>())
setFocusFilter(cb);
foreach(QWidget * sb, findChildren<QAbstractSpinBox*>())
setFocusFilter(sb);
foreach(QWidget * slider, findChildren<QSlider*>())
setFocusFilter(slider);
foreach(QWidget * te, findChildren<TimerEdit*>())
setFocusFilter(te);
}
void GenericPanel::updateAutoWidgets()
{
foreach(QWidget *wdgt, findChildren<QWidget *>()) {
AutoWidget *autowdgt = dynamic_cast<AutoWidget *>(wdgt);
if (autowdgt) {
autowdgt->updateValue();
autowdgt->applyBindings();
}
}
}
WidgetBindings *GenericPanel::bindings()
{
if (!m_bindings)
m_bindings = std::make_unique<WidgetBindings>();
return m_bindings.get();
}
void GenericPanel::applyBindings()
{
if (m_bindings)
m_bindings->applyAll();
}
+4 -29
View File
@@ -21,53 +21,28 @@
#pragma once
#include <QWidget>
#include <memory>
#include "abstractpanel.h"
class ModelData;
class GeneralSettings;
class Firmware;
class QGridLayout;
class QString;
class WidgetBindings;
class GenericPanel : public QWidget
class GenericPanel : public AbstractPanel
{
Q_OBJECT
friend class GVarGroup;
friend class AutoWidget;
public:
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware);
virtual ~GenericPanel();
signals:
void modified();
public slots:
virtual void update();
virtual void save() override {};
virtual void update() override {};
protected:
ModelData * model;
GeneralSettings & generalSettings;
Firmware * firmware;
//Board::Type board; TODO: as part of refactor to move physical capabilities from Firmware to Boards
bool lock;
void addLabel(QGridLayout * gridLayout, const QString &text, int col, bool mimimize=false);
void addEmptyLabel(QGridLayout * gridLayout, int col);
void addHSpring(QGridLayout *, int col, int row);
void addVSpring(QGridLayout *, int col, int row);
void addDoubleSpring(QGridLayout *, int col, int row);
virtual bool eventFilter(QObject *obj, QEvent *event);
void setFocusFilter(QWidget * w);
void disableMouseScrolling();
void updateAutoWidgets();
WidgetBindings *bindings();
void applyBindings();
private:
std::unique_ptr<WidgetBindings> m_bindings;
};
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "gridlayout.h"
#include <QFrame>
GridLayout::GridLayout(QWidget * parent) :
QGridLayout(parent),
m_lastRow(0),
m_lastCol(0)
{
}
GridLayout::~GridLayout()
{
}
gridIndex GridLayout::addLabel(QString & text, int col, int colSpan, int row, int rowSpan)
{
QLabel *label = new QLabel(text);
setIndexes(col, row);
addWidget(label, col, colSpan, row, rowSpan);
return { m_lastRow, m_lastCol };
}
gridIndex GridLayout::addLine(int col, int colSpan, int row)
{
QFrame *line = new QFrame();
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
line->setLineWidth(1);
line->setMidLineWidth(0);
setIndexes(col, row);
QGridLayout::addWidget(line, m_lastRow, m_lastCol, 1, (colSpan > 0 ? colSpan : columnCount()));
return { m_lastRow, m_lastCol };
}
gridIndex GridLayout::addLayout(QLayout * layout, int col, int colSpan, int row, int rowSpan)
{
setIndexes(col, row);
QGridLayout::addLayout(layout, m_lastRow, m_lastCol, rowSpan, colSpan);
return { m_lastRow, m_lastCol };
}
gridIndex GridLayout::addWidget(QWidget * wgt, int col, int colSpan, int row, int rowSpan)
{
setIndexes(col, row);
QGridLayout::addWidget(wgt, m_lastRow, m_lastCol, rowSpan, colSpan);
return { m_lastRow, m_lastCol };
}
gridIndex GridLayout::addSection(QString & text, int col, int row)
{
QString str(QString("<b>%1</b>").arg(text));
return addLabel(str, col, row);
}
gridIndex GridLayout::newRow()
{
return { ++m_lastRow, (m_lastCol = 0) };
}
void GridLayout::setIndexes(int col, int row)
{
m_lastCol = (col = -1 ? m_lastCol + 1 : col);
// do not auto increment row
m_lastRow = (row = -1 ? m_lastRow : row);
}
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "autowidgets.h"
#include <QGridLayout>
struct gridIndex {
int row;
int col;
};
class GridLayout : public QGridLayout
{
Q_OBJECT
public:
explicit GridLayout(QWidget * parent = nullptr);
virtual ~GridLayout();
// creates and adds a label
gridIndex addLabel(QString & text, int col = -1, int colSpan = 1, int row = -1, int rowSpan = 1);
// creates and adds a horizontal line
gridIndex addLine(int col = -1, int colSpan = -1, int row = -1);
// adds a layout
gridIndex addLayout(QLayout * layout, int col = -1, int colSpan = 1, int row = -1, int rowSpan = 1);
// adds a fixed or collapsible section
gridIndex addSection(QString & text, int col = -1, int row = -1);
// adds a widget
gridIndex addWidget(QWidget * wgt, int col = -1, int colSpan = 1, int row = -1, int rowSpan = 1);
// increments the current row
gridIndex newRow();
// increments the current column
gridIndex skipCol();
private:
int m_lastRow;
int m_lastCol;
void setIndexes(int col, int row);
};
+37 -2
View File
@@ -621,7 +621,6 @@ void AppData::initAll()
void AppData::resetAllSettings()
{
resetAll();
fwRev.resetAll();
for (int i = 0; i < MAX_PROFILES; i++) {
profile[i].resetAll();
@@ -766,6 +765,7 @@ void AppData::convertSettings(QSettings & settings)
// We only want to remove old/deprecated settngs if the {major}{minor} part of the settings version number has changed.
// This preserves backwards compatiblity within minor version releases (where only revision number changes).
const unsigned savedMajMin = (savedVer >> 16);
const unsigned savedRevision = (savedVer & 0x0F);
const unsigned currMajMin = (CPN_SETTINGS_VERSION >> 16);
const bool removeUnused = (savedMajMin < currMajMin);
@@ -938,6 +938,40 @@ void AppData::convertSettings(QSettings & settings)
}
}
if (savedMajMin <= 0x300 && savedRevision < CPN_SETTINGS_REVISION) {
// split out profile fwType options and language into separate fields
qInfo().noquote() << "Converting profiles firmware type";
static const QString profilePath = QStringLiteral("Profiles/profile%1");
static const QString profileFwTypePath = QStringLiteral("Profiles/profile%1/fwType");
for (int i = 0; i < MAX_PROFILES; i++) {
if (settings.contains(profileFwTypePath.arg(i))) {
const QVariant oldValue = settings.value(profileFwTypePath.arg(i));
if (oldValue.isValid()) {
const QStringList oldparts = settings.value(profileFwTypePath.arg(i)).toString().split("-");
QString newfwType;
QString newfwOpts;
QString newfwLang;
if (oldparts.count() > 1) {
newfwType = oldparts.mid(0, 2).join("-");
settings.setValue(profileFwTypePath.arg(i), newfwType);
}
if (oldparts.count() > 2) {
newfwLang = oldparts.last();
settings.setValue(profilePath.arg(i) % "/fwLanguage", newfwLang);
}
if (oldparts.count() > 3) {
newfwOpts = oldparts.mid(2, oldparts.count() - 3).join("-");
settings.setValue(profilePath.arg(i) % "/fwOptions", newfwOpts);
}
qInfo().noquote() << "Converted entry" << profileFwTypePath.arg(i)
<< "from (" << oldValue << ")"
<< "to (type:" << newfwType << "opts:" << newfwOpts << "lang:" << newfwLang << ")";
}
}
}
}
if (removeUnused)
clearUnusedSettings(settings);
@@ -1108,8 +1142,9 @@ void AppData::resetUpdatesSettings()
decompressDirUseDwnldReset();
updateDirReset();
updateDirUseSDReset();
updDelDownloadsReset();
updLogLevelReset();
updDelDownloadsReset();
updDelDecompressReset();
for (int i = 0; i < MAX_COMPONENTS; i++) {
component[i].resetAll();
+21 -31
View File
@@ -41,7 +41,7 @@
//! CPN_SETTINGS_REVISION is used to track settings changes independently of EdgeTX version. It should be reset to zero whenever settings are migrated to new COMPANY or PRODUCT.
//! \note !! Increment this value if properties are removed or refactored. It will trigger a conversion/cleanup of any stored settings. \sa AppData::convertSettings()
#define CPN_SETTINGS_REVISION 3 // Note: bumped for changes during 3.0 dev
#define CPN_SETTINGS_REVISION 4 // Note: bumped for multiple changes during 3.0 dev
//! CPN_SETTINGS_VERSION is used for settings data version tracking.
#define CPN_SETTINGS_VERSION ((VERSION_NUMBER << 8) | CPN_SETTINGS_REVISION)
@@ -310,23 +310,6 @@ class CompStoreObj: public QObject
class AppData;
//! \brief FwRevision class stores data about downloaded firmware binaries. It uses dynamic key names and does not have any properties.
class FwRevision: public CompStoreObj
{
Q_OBJECT
public slots:
inline int get(const QString & fwType) const { return m_settings.value(settingsPath() % fwType, 0).toInt(); }
inline void set(const QString & fwType, const int fwRevision) const { store(QString("%1").arg(fwRevision), fwType); }
inline void remove(const QString & tag) const { clear(tag); }
inline void resetAll() override { clear(propertyGroup(), ""); }
protected:
explicit FwRevision() : CompStoreObj() { CompStoreObj::addDynamicPropertyGroup(propertyGroup()); }
QString propertyGroup() const override { return QStringLiteral("FwRevisions"); }
friend class AppData;
};
//! \brief JStickData class stores properties related to each joystick axis (calibration/assignment/direction).
class JStickData: public CompStoreObj
{
@@ -519,28 +502,31 @@ class Profile: public CompStoreObj
PROPERTYSTR2(name, "Name")
PROPERTYSTR2(splashFile, "SplashFileName")
PROPERTYSTR(fwName)
PROPERTYSTR(fwType)
PROPERTYSTR(fwType) // converted 3.0 split out options and language to own fields
PROPERTYSTR(fwOptions) // added 3.0
PROPERTYSTR(fwLanguage) // added 3.0
PROPERTYSTR(sdPath)
PROPERTYSTR(pBackupDir)
PROPERTYSTR(modelsDir) // added 3.0
PROPERTY (int, defaultInternalModule, 0)
PROPERTY (int, externalModuleSize, 1) // added 2.9 - Board::EXTMODSIZE_STD used for existing profiles
PROPERTY4(int, channelOrder, "default_channel_order", 0)
PROPERTY4(int, defaultMode, "default_mode", 1)
PROPERTY (int, volumeGain, 10)
PROPERTY (int, externalModuleSize, 1) // added 2.9 - Board::EXTMODSIZE_STD used for existing profiles
PROPERTY4(int, channelOrder, "default_channel_order", 0)
PROPERTY4(int, defaultMode, "default_mode", 1)
PROPERTY (int, volumeGain, 10) // divided by 10
PROPERTY (bool, burnFirmware, false)
PROPERTY (bool, penableBackup, false)
PROPERTY (bool, runSDSync, false)
// Simulator variables
PROPERTY(SimulatorOptions, simulatorOptions, SimulatorOptions())
PROPERTY(bool, telemSimEnabled, false)
PROPERTY(bool, telemSimPauseOnHide, true)
PROPERTY(bool, telemSimResetRssiOnStop, false)
PROPERTY(QColor, radioSimCaseColor, QColor(Qt::black))
PROPERTY(bool, simBtnClickedUseOSTheme, true)
PROPERTY(QColor, simBtnClickedColor, QColor(Qt::red))
PROPERTY(SimulatorOptions, simulatorOptions, SimulatorOptions())
PROPERTY(bool, telemSimEnabled, false)
PROPERTY(bool, telemSimPauseOnHide, true)
PROPERTY(bool, telemSimResetRssiOnStop, false)
PROPERTY(QColor, radioSimCaseColor, QColor(Qt::black))
PROPERTY(bool, simBtnClickedUseOSTheme, true)
PROPERTY(QColor, simBtnClickedColor, QColor(Qt::red))
// General settings
PROPERTYQBA(generalSettings)
@@ -672,6 +658,8 @@ class AppData: public CompStoreObj
// refer enum QtMsgType
static QStringList updateLogLevelsList() { return { tr("Debug"), tr("Warning"), tr("Critical"), tr("Fatal"), tr("Information") } ; }
static QStringList simuGenericKeysPosList() { return { tr("Default"), tr("Left"), tr("Right") } ; }
static QStringList simuBackLightColorList() { return { tr("Blue"), tr("Green"), tr("Red"), tr("Orange"), tr("Yellow") } ; }
static QStringList splashLibsList() { return { tr("Only show user splash images"), tr("Show user and companion splash images") } ; }
explicit AppData();
void init() override;
@@ -728,7 +716,6 @@ class AppData: public CompStoreObj
JStickData joystick[MAX_JS_AXES];
JButtonData jsButton[MAX_JS_BUTTONS];
NamedJSData namedJS[MAX_NAMED_JOYSTICKS];
FwRevision fwRev;
ComponentData component[MAX_COMPONENTS];
void clearJSData() {
@@ -760,6 +747,7 @@ class AppData: public CompStoreObj
PROPERTYQBA2(mainWinGeo, "mainWindowGeometry")
PROPERTYQBA2(mainWinState, "mainWindowState")
PROPERTYQBA2(modelEditGeo, "modelEditGeometry")
PROPERTYQBA2(prefsEditGeo, "prefsEditGeometry") // added 3.0
PROPERTYQBA (mdiWinGeo)
PROPERTYQBA (mdiWinState)
PROPERTYQBA (compareWinGeo)
@@ -775,6 +763,7 @@ class AppData: public CompStoreObj
PROPERTYSTRD(downloadDir, CPN_DOCUMENTS_LOCATION % "/downloads")
PROPERTYSTRD(decompressDir, CPN_DOCUMENTS_LOCATION % "/decompress")
PROPERTYSTRD(updateDir, CPN_DOCUMENTS_LOCATION % "/updates")
PROPERTYSTRD(modelsDir, CPN_DOCUMENTS_LOCATION % "/models") // added 3.0
PROPERTY (bool, decompressDirUseDwnld, true)
PROPERTY (bool, updateDirUseSD, true)
PROPERTY (bool, runAppInstaller, false)
@@ -782,6 +771,7 @@ class AppData: public CompStoreObj
PROPERTY (bool, updDelDownloads, false)
PROPERTY (bool, updDelDecompress, false)
PROPERTYSTR (lastUpdateDir)
PROPERTY (bool, logVerbose, false)
PROPERTYSTR (locale)
PROPERTYSTR (gePath)