diff --git a/companion/src/apppreferencesdialog.cpp b/companion/src/apppreferencesdialog.cpp index 4696cad10..85e553120 100644 --- a/companion/src/apppreferencesdialog.cpp +++ b/companion/src/apppreferencesdialog.cpp @@ -76,6 +76,7 @@ void AppPreferencesDialog::accept() Profile & profile = g.currentProfile(); g.showSplash(ui->showSplash->isChecked()); + g.sortProfiles(ui->sortProfiles->isChecked()); g.promptProfile(ui->chkPromptProfile->isChecked()); g.simuSW(ui->simuSW->isChecked()); g.disableJoystickWarning(ui->joystickWarningCB->isChecked()); @@ -232,6 +233,7 @@ void AppPreferencesDialog::initSettings() } ui->showSplash->setChecked(g.showSplash()); + ui->sortProfiles->setChecked(g.sortProfiles()); ui->chkPromptProfile->setChecked(g.promptProfile()); ui->historySize->setValue(g.historySize()); ui->backLightColor->setCurrentIndex(g.backLight()); diff --git a/companion/src/apppreferencesdialog.ui b/companion/src/apppreferencesdialog.ui index b69843db0..8813d7473 100644 --- a/companion/src/apppreferencesdialog.ui +++ b/companion/src/apppreferencesdialog.ui @@ -7,7 +7,7 @@ 0 0 865 - 692 + 703 @@ -45,7 +45,7 @@ - 0 + 1 @@ -748,10 +748,120 @@ Mode 4: 6 - - - - Qt::Horizontal + + + + + 0 + 0 + + + + Remember + + + + + + + Update + + + + + + + Prompt to run installer after update + + + + + + + + + true + + + + + + + + 0 + 0 + + + + Select Executable + + + + + + + + + + + <html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An EdgeTX developer may request this to help diagnose an issue.</p></body></html> + + + Application (Companion/Simulator) + + + + + + + <html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html> + + + Radio Firmware (in Simulator) + + + + + + + + + + 0 + 0 + + + + Google Earth Executable + + + + + + + + 0 + 0 + + + + Debug Output Logging + + + + + + + + + + + 0 + 0 + + + + Automatic Backup Folder @@ -779,97 +889,14 @@ Mode 4: - - - - - 0 - 0 - - - - Automatic Backup Folder + + + + Qt::Horizontal - - - - - - - - 0 - 0 - - - - Debug Output Logging - - - - - - - - 0 - 0 - - - - Google Earth Executable - - - - - - - - - <html><head/><body><p>Keep a log of all debugging messages generated by the desktop Companion/Simulator applications. An EdgeTX developer may request this to help diagnose an issue.</p></body></html> - - - Application (Companion/Simulator) - - - - - - - <html><head/><body><p>Keep a log of all messages generated by the radio firmware when running in Simulator. This is the same information one would also see in the Simulator <span style=" font-style:italic;">Debug Output</span> window.</p></body></html> - - - Radio Firmware (in Simulator) - - - - - - - - - - - true - - - - - - - - 0 - 0 - - - - Select Executable - - - - - - + Qt::Horizontal @@ -883,14 +910,14 @@ Mode 4: - + Qt::Horizontal - + @@ -913,14 +940,7 @@ Mode 4: - - - - Prompt for radio profile - - - - + @@ -940,43 +960,7 @@ Mode 4: - - - - <html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html> - - - Remove empty model slots when deleting models (only applies for radios w/out labels) - - - - - - - - 0 - 0 - - - - User Splash Screens - - - - - - - - 0 - 0 - - - - Action on New Model - - - - + @@ -1003,6 +987,52 @@ Mode 4: + + + + + 0 + 0 + + + + Action on New Model + + + + + + + + 0 + 0 + + + + User Splash Screens + + + + + + + + 0 + 0 + + + + Enable automatic backup before writing firmware + + + + + + + Prompt for radio profile + + + @@ -1039,7 +1069,7 @@ Mode 4: - + @@ -1065,14 +1095,24 @@ Mode 4: - + Qt::Horizontal - + + + + <html><head/><body><p>This option maintains the behaviour from older OpenTx versions where empty model slots are preserved when a model is deleted or moved. </p><p>When this option is de-selected, the other models may be re-arranged to fill the gap left by the removed model.</p></body></html> + + + Remove empty model slots when deleting models (only applies for radios w/out labels) + + + + @@ -1093,43 +1133,24 @@ Mode 4: - - - - - 0 - 0 - - + + - Enable automatic backup before writing firmware + Radio Profiles - - - - - 0 - 0 - - + + - Remember + Move selected Radio Profile to the top of the list - - - - Prompt to run installer after update - - - - - - - Update + + + + Qt::Horizontal diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 95d47bfa0..1725be789 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -1248,6 +1248,7 @@ void MainWindow::onChangeWindowAction(QAction * act) void MainWindow::onCurrentProfileChanged() { + g.moveCurrentProfileToTop(); Firmware::setCurrentVariant(Firmware::getFirmwareForId(g.currentProfile().fwType())); emit firmwareChanged(); QApplication::clipboard()->clear(); @@ -1259,8 +1260,10 @@ int MainWindow::newProfile(bool loadProfile) int i; for (i=0; i < MAX_PROFILES && g.profile[i].existsOnDisk(); i++) ; - if (i == MAX_PROFILES) //Failed to find free slot + if (i == MAX_PROFILES) { //Failed to find free slot + QMessageBox::warning(this, tr("Cannot add profile"), tr("There is no space left to add a new profile. Delete an exsting profile before adding a new one.")); return -1; + } Firmware *newfw = Firmware::getDefaultVariant(); g.profile[i].init(); @@ -1300,9 +1303,14 @@ void MainWindow::deleteProfile(const int pid) QMessageBox::warning(this, tr("Companion :: Open files warning"), tr("Please save or close modified file(s) before deleting the active profile.")); return; } + int newPid = 0; if (pid == 0) { - QMessageBox::warning(this, tr("Not possible to remove profile"), tr("The default profile can not be removed.")); - return; + // Find valid profile + for (newPid = 1; newPid < MAX_PROFILES && !g.profile[newPid].existsOnDisk(); newPid += 1); + if (newPid == MAX_PROFILES) { + QMessageBox::warning(this, tr("Not possible to remove profile"), tr("The default profile can not be removed.")); + return; + } } int ret = QMessageBox::question(this, tr("Confirm Delete Profile"), @@ -1311,7 +1319,8 @@ void MainWindow::deleteProfile(const int pid) return; g.getProfile(pid).resetAll(); - loadProfileId(0); + loadProfileId(newPid); + g.moveCurrentProfileToTop(); } void MainWindow::deleteCurrentProfile() diff --git a/companion/src/storage/appdata.cpp b/companion/src/storage/appdata.cpp index 9408cec28..45c21d590 100644 --- a/companion/src/storage/appdata.cpp +++ b/companion/src/storage/appdata.cpp @@ -304,6 +304,11 @@ Profile::Profile() : CompStoreObj(), index(-1) CompStoreObj::addObjectMapping(propertyGroup(), this); } +Profile::Profile(const Profile & rhs) : CompStoreObj(), index(-1) +{ + *this = rhs; +} + // The default copy operator can not be used since the index variable would be destroyed Profile & Profile::operator= (const Profile & rhs) { @@ -661,6 +666,18 @@ QMap AppData::getActiveProfiles() const return active; } +void AppData::moveCurrentProfileToTop() +{ + if (g.sortProfiles() && m_sessionId > 0) { + Profile tmpProfile(g.profile[m_sessionId]); + for (int i = m_sessionId; i > 0; i -= 1) { + g.profile[i] = g.profile[i - 1]; + } + g.profile[0] = tmpProfile; + id(0); + } +} + void AppData::convertSettings(QSettings & settings) { quint32 savedVer = settings.value(SETTINGS_VERSION_KEY, 0).toUInt(); diff --git a/companion/src/storage/appdata.h b/companion/src/storage/appdata.h index 37fcffa99..c544058b6 100644 --- a/companion/src/storage/appdata.h +++ b/companion/src/storage/appdata.h @@ -58,7 +58,7 @@ #define CPN_SETTINGS_INI_FILE QString(PRODUCT % " " % QCoreApplication::translate("Companion", "settings") % " %1.ini") #define CPN_SETTINGS_INI_PATH QString(CPN_SETTINGS_BACKUP_DIR % "/" % CPN_SETTINGS_INI_FILE) -#define MAX_PROFILES 20 +#define MAX_PROFILES 32 #define MAX_JS_AXES 10 #define MAX_JS_BUTTONS 32 #define MAX_COMPONENTS 10 @@ -472,6 +472,7 @@ class Profile: public CompStoreObj protected: explicit Profile(); + explicit Profile(const Profile & rhs); void setIndex(int idx) { index = idx; } inline QString propertyGroup() const override { return QStringLiteral("Profiles"); } inline QString settingsPath() const override { return QString("%1/profile%2/").arg(propertyGroup()).arg(index); } @@ -685,6 +686,8 @@ class AppData: public CompStoreObj const Profile & getProfile(int index) const; //! List of all active profiles mapped by index. QMap getActiveProfiles() const; + // Move the currently selected profile to the top of the list + void moveCurrentProfileToTop(); //! Get a modifiable (non-const) reference to the ComponentData at \a index. Returns component[0] if \a index is invalid. ComponentData & getComponent(int index); @@ -791,6 +794,7 @@ class AppData: public CompStoreObj PROPERTY4(bool, jsSupport, "js_support", false) PROPERTY4(bool, showSplash, "show_splash", true) + PROPERTY4(bool, sortProfiles, "sort_profiles", false) PROPERTY4(bool, snapToClpbrd, "snapshot_to_clipboard", false) PROPERTY(UpdateCheckFreq, updateCheckFreq, UPDATE_CHECK_MANUAL)