From e3e4a511d390d5a4076a1826f6a5b80d0ab15ab7 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 17 Jan 2025 22:28:48 +1100 Subject: [PATCH 01/16] fix(cpn): inputs and mixes must have source --- .../src/firmwares/edgetx/yaml_modeldata.cpp | 4 +-- companion/src/mdichild.cpp | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index f0ceeeb1841..3f32c78c4fa 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -1014,7 +1014,7 @@ Node convert::encode(const ModelData& rhs) for (int i = 0; i < CPN_MAX_MIXERS; i++) { const MixData& mix = rhs.mixData[i]; - if (!mix.isEmpty()) { + if (!mix.isEmpty() && mix.srcRaw != SOURCE_TYPE_NONE) { node["mixData"].push_back(Node(mix)); } } @@ -1029,7 +1029,7 @@ Node convert::encode(const ModelData& rhs) std::set inputs; for (int i = 0; i < CPN_MAX_EXPOS; i++) { const ExpoData& expo = rhs.expoData[i]; - if (!expo.isEmpty()) { + if (!expo.isEmpty() && expo.srcRaw != SOURCE_TYPE_NONE) { Node expoNode; expoNode = expo; node["expoData"].push_back(expoNode); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index ab13be5d3e0..b5b7856fb4b 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1334,6 +1334,35 @@ bool MdiChild::saveAs(bool isNew) bool MdiChild::saveFile(const QString & filename, bool setCurrent) { + int cnt = 0; + + for (int i = 0; i < (int)radioData.models.size(); i++) { + if (!radioData.models[i].isEmpty()) { + for (int j = 0; j < CPN_MAX_INPUTS; j++) { + if (!radioData.models[i].expoData[j].isEmpty() && radioData.models[i].expoData[j].srcRaw == SOURCE_TYPE_NONE) + cnt++; + } + + if (cnt > 0) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Model %1 has %2 inputs with no source and these inputs will not be saved. Continue?").arg(radioData.models[i].name).arg(cnt), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) + return false; + } + + cnt = 0; + for (int j = 0; j < CPN_MAX_MIXERS; j++) { + if (!radioData.models[i].mixData[j].isEmpty() && radioData.models[i].mixData[j].srcRaw == SOURCE_TYPE_NONE) + cnt++; + } + + if (cnt > 0) { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Model %1 has %2 mixes with no source and these mixes will not be saved. Continue?").arg(radioData.models[i].name).arg(cnt), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) + return false; + } + } + } + radioData.fixModelFilenames(); Storage storage(filename); bool result = storage.write(radioData); From ac86af08509339a1233d8fa2f5491219cee96930 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 17 Jan 2025 22:36:23 +1100 Subject: [PATCH 02/16] Reset counter for each model --- companion/src/mdichild.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index b5b7856fb4b..9cac31faab8 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1334,9 +1334,9 @@ bool MdiChild::saveAs(bool isNew) bool MdiChild::saveFile(const QString & filename, bool setCurrent) { - int cnt = 0; - for (int i = 0; i < (int)radioData.models.size(); i++) { + int cnt = 0; + if (!radioData.models[i].isEmpty()) { for (int j = 0; j < CPN_MAX_INPUTS; j++) { if (!radioData.models[i].expoData[j].isEmpty() && radioData.models[i].expoData[j].srcRaw == SOURCE_TYPE_NONE) From cbdf5afaca91a5dae2e2fd4378ed5fa4d7d3591d Mon Sep 17 00:00:00 2001 From: elecpower Date: Sun, 19 Jan 2025 22:03:37 +1100 Subject: [PATCH 03/16] Move checks and fix to data classes --- companion/src/firmwares/modeldata.cpp | 47 +++++++++++++++++++++++++++ companion/src/firmwares/modeldata.h | 2 ++ companion/src/firmwares/radiodata.cpp | 16 +++++++++ companion/src/firmwares/radiodata.h | 2 ++ companion/src/mdichild.cpp | 35 +++++--------------- companion/src/mdichild.h | 6 ++-- 6 files changed, 78 insertions(+), 30 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 5f8ee4fc280..e338b7575a0 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -29,6 +29,8 @@ #include "adjustmentreference.h" #include "compounditemmodels.h" +#include + ModelData::ModelData() { clear(); @@ -1924,3 +1926,48 @@ int ModelData::getCustomScreensCount() const return cnt; } + +bool ModelData::isValid(QWidget * parent) +{ + int inputerrors = 0; + for (int i = 0; i < CPN_MAX_INPUTS; i++) { + if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) + inputerrors++; + } + + int mixerrors = 0; + for (int i = 0; i < CPN_MAX_MIXERS; i++) { + if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) + mixerrors++; + } + + if (inputerrors > 0 || mixerrors > 0) { + QString msg = tr("Model %1 has the following errors:").arg(name) % "\n\n"; + if (inputerrors > 0) + msg.append(tr("- %1 inputs with no source").arg(inputerrors) % "\n"); + if (mixerrors > 0) + msg.append(tr("- %1 mixes with no source").arg(mixerrors)); + + QMessageBox::information(parent, CPN_STR_APP_NAME, msg); + return false; + } + + return true; +} + +void ModelData::fixErrors() +{ + for (int i = 0; i < CPN_MAX_INPUTS; i++) { + if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) { + // delete input line and fix up anything else then update refs + //updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, REF_UPD_ACT_CLEAR, i); + } + } + + for (int i = 0; i < CPN_MAX_MIXERS; i++) { + if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) { + // delete mixer line and fix up anything like numbering?? + } + } + +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 6ad033398a9..bd0767b2e3f 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -366,6 +366,8 @@ class ModelData { static AbstractStaticItemModel * funcSwitchStartItemModel(); int getCustomScreensCount() const; + bool isValid(QWidget * parent = nullptr); + void fixErrors(); protected: void removeGlobalVar(int & var); diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp index be7f3eeb074..0fac9e4c361 100644 --- a/companion/src/firmwares/radiodata.cpp +++ b/companion/src/firmwares/radiodata.cpp @@ -343,3 +343,19 @@ AbstractStaticItemModel * RadioData::modelSortOrderItemModel() mdl->loadItemList(); return mdl; } + +int RadioData::invalidModels(QWidget * parent) +{ + int cnt = 0; + + for(auto &model: models) + cnt += model.isValid(parent) ? 0 : 1; + + return cnt; +} + +void RadioData::fixInvalidModels() +{ + for(auto &model: models) + model.fixErrors(); +} diff --git a/companion/src/firmwares/radiodata.h b/companion/src/firmwares/radiodata.h index d8612b602f5..fb678c48ead 100644 --- a/companion/src/firmwares/radiodata.h +++ b/companion/src/firmwares/radiodata.h @@ -66,6 +66,8 @@ class RadioData { void setCurrentModel(unsigned int index); void fixModelFilenames(); QString getNextModelFilename(); + int invalidModels(QWidget * parent = nullptr); + void fixInvalidModels(); static QString modelSortOrderToString(int value); static AbstractStaticItemModel * modelSortOrderItemModel(); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 9cac31faab8..72daa2a55e5 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1334,33 +1334,16 @@ bool MdiChild::saveAs(bool isNew) bool MdiChild::saveFile(const QString & filename, bool setCurrent) { - for (int i = 0; i < (int)radioData.models.size(); i++) { - int cnt = 0; - - if (!radioData.models[i].isEmpty()) { - for (int j = 0; j < CPN_MAX_INPUTS; j++) { - if (!radioData.models[i].expoData[j].isEmpty() && radioData.models[i].expoData[j].srcRaw == SOURCE_TYPE_NONE) - cnt++; - } - - if (cnt > 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Model %1 has %2 inputs with no source and these inputs will not be saved. Continue?").arg(radioData.models[i].name).arg(cnt), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) - return false; - } - - cnt = 0; - for (int j = 0; j < CPN_MAX_MIXERS; j++) { - if (!radioData.models[i].mixData[j].isEmpty() && radioData.models[i].mixData[j].srcRaw == SOURCE_TYPE_NONE) - cnt++; - } - - if (cnt > 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Model %1 has %2 mixes with no source and these mixes will not be saved. Continue?").arg(radioData.models[i].name).arg(cnt), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) - return false; - } + int cnt = radioData.invalidModels(this); + if (cnt) { + if (askQuestion(tr("%1 models have errors. Repair?").arg(cnt), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Yes) { + radioData.fixInvalidModels(); + // NOW NEED TO REFRESH GUI if Model Edit open !!!!!!! + // refresh inputs and mixes lists + // update any data models } + else + return false; } radioData.fixModelFilenames(); diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 49f4cbc346c..4d823235770 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _MDICHILD_H_ -#define _MDICHILD_H_ +#pragma once #include "eeprominterface.h" #include "modelslist.h" @@ -201,6 +200,7 @@ class MdiChild : public QWidget bool convertStorage(Board::Type from, Board::Type to, bool newFile = false); void showWarning(const QString & msg); int askQuestion(const QString & msg, QMessageBox::StandardButtons buttons = (QMessageBox::Yes | QMessageBox::No), QMessageBox::StandardButton defaultButton = QMessageBox::No); + QDialog * getChildDialog(QRegularExpression & regexp); QDialog * getModelEditDialog(int row); QList * getChildrenDialogsList(QRegularExpression & regexp); @@ -262,5 +262,3 @@ class ItemViewProxyStyle: public QProxyStyle } } }; - -#endif // _MDICHILD_H_ From a33a934aaa819e8cfb6bede1640b63ec3e182de9 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 08:39:07 +1100 Subject: [PATCH 04/16] Modify validation functions and when called --- companion/src/firmwares/modeldata.cpp | 28 ++++++++++----------------- companion/src/firmwares/modeldata.h | 5 ++++- companion/src/firmwares/radiodata.cpp | 10 ++++++++-- companion/src/firmwares/radiodata.h | 3 ++- companion/src/mdichild.cpp | 9 +++++++-- companion/src/modelslist.cpp | 6 ++++++ 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index e338b7575a0..d89f4bfe42a 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1927,36 +1927,29 @@ int ModelData::getCustomScreensCount() const return cnt; } -bool ModelData::isValid(QWidget * parent) +void ModelData::validate() { - int inputerrors = 0; + modelErrors = false; + for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) - inputerrors++; + modelErrors = true; + return; } int mixerrors = 0; for (int i = 0; i < CPN_MAX_MIXERS; i++) { if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) - mixerrors++; - } - - if (inputerrors > 0 || mixerrors > 0) { - QString msg = tr("Model %1 has the following errors:").arg(name) % "\n\n"; - if (inputerrors > 0) - msg.append(tr("- %1 inputs with no source").arg(inputerrors) % "\n"); - if (mixerrors > 0) - msg.append(tr("- %1 mixes with no source").arg(mixerrors)); - - QMessageBox::information(parent, CPN_STR_APP_NAME, msg); - return false; + modelErrors = true; + return; } - - return true; } void ModelData::fixErrors() { + if (!modelErrors) + return; + for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) { // delete input line and fix up anything else then update refs @@ -1969,5 +1962,4 @@ void ModelData::fixErrors() // delete mixer line and fix up anything like numbering?? } } - } diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index bd0767b2e3f..01c3e4cdd8c 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -140,6 +140,7 @@ class ModelData { char labels[100]; int modelIndex; // Companion only, temporary index position managed by data model. bool modelUpdated; // Companion only, used to highlight if changed in models list + bool modelErrors; // Companion only, used to highlight if data errors in models list TimerData timers[CPN_MAX_TIMERS]; bool noGlobalFunctions; @@ -366,8 +367,10 @@ class ModelData { static AbstractStaticItemModel * funcSwitchStartItemModel(); int getCustomScreensCount() const; - bool isValid(QWidget * parent = nullptr); void fixErrors(); + bool hasErrors() { return modelErrors; } + bool isValid() { return !hasErrors(); } + void validate(); protected: void removeGlobalVar(int & var); diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp index 0fac9e4c361..b2ac99d2500 100644 --- a/companion/src/firmwares/radiodata.cpp +++ b/companion/src/firmwares/radiodata.cpp @@ -344,12 +344,18 @@ AbstractStaticItemModel * RadioData::modelSortOrderItemModel() return mdl; } -int RadioData::invalidModels(QWidget * parent) +void RadioData::validateModels() +{ + for(auto &model: models) + model.validate(); +} + +int RadioData::invalidModels() { int cnt = 0; for(auto &model: models) - cnt += model.isValid(parent) ? 0 : 1; + cnt += model.isValid() ? 0 : 1; return cnt; } diff --git a/companion/src/firmwares/radiodata.h b/companion/src/firmwares/radiodata.h index fb678c48ead..77566c352e7 100644 --- a/companion/src/firmwares/radiodata.h +++ b/companion/src/firmwares/radiodata.h @@ -66,7 +66,8 @@ class RadioData { void setCurrentModel(unsigned int index); void fixModelFilenames(); QString getNextModelFilename(); - int invalidModels(QWidget * parent = nullptr); + void validateModels(); + int invalidModels(); void fixInvalidModels(); static QString modelSortOrderToString(int value); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 72daa2a55e5..ed5236c265d 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1298,6 +1298,8 @@ bool MdiChild::loadFile(const QString & filename, bool resetCurrentFile) refresh(); } + radioData.validateModels(); + return true; } @@ -1334,7 +1336,8 @@ bool MdiChild::saveAs(bool isNew) bool MdiChild::saveFile(const QString & filename, bool setCurrent) { - int cnt = radioData.invalidModels(this); + // do not check for etx files as we accept errors + int cnt = radioData.invalidModels(); if (cnt) { if (askQuestion(tr("%1 models have errors. Repair?").arg(cnt), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Yes) { radioData.fixInvalidModels(); @@ -1356,8 +1359,10 @@ bool MdiChild::saveFile(const QString & filename, bool setCurrent) g.eepromDir(QFileInfo(filename).dir().absolutePath()); for (int i = 0; i < (int)radioData.models.size(); i++) { - if (!radioData.models[i].isEmpty()) + if (!radioData.models[i].isEmpty()) { radioData.models[i].modelUpdated = false; + radioData.models[i].validate(); + } } refresh(); diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp index 5bb14f5ce56..bea7df78a62 100644 --- a/companion/src/modelslist.cpp +++ b/companion/src/modelslist.cpp @@ -186,6 +186,12 @@ QVariant ModelsListModel::data(const QModelIndex & index, int role) const } if (role == Qt::ForegroundRole && item->isModel()) { + if (index.column() == (hasLabels ? 0 : 1) && radioData->models[item->getModelIndex()].modelErrors) { + QBrush brush; + brush.setColor(Qt::red); + return brush; + } + int col = item->columnCount() - 1; if(hasLabels) col --; From e6377256765afa7fc550bfe0f7512085b54d47d2 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 09:14:37 +1100 Subject: [PATCH 05/16] Remove unused functions and error check on etx save --- companion/src/firmwares/modeldata.cpp | 26 +++++++++++++------------- companion/src/firmwares/modeldata.h | 2 +- companion/src/firmwares/radiodata.cpp | 6 ------ companion/src/firmwares/radiodata.h | 1 - companion/src/mdichild.cpp | 13 ------------- 5 files changed, 14 insertions(+), 34 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index d89f4bfe42a..a3d34451874 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1932,34 +1932,34 @@ void ModelData::validate() modelErrors = false; for (int i = 0; i < CPN_MAX_INPUTS; i++) { - if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) + if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) { modelErrors = true; return; + } } - int mixerrors = 0; for (int i = 0; i < CPN_MAX_MIXERS; i++) { - if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) + if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) { modelErrors = true; return; + } } } -void ModelData::fixErrors() +QList ModelData::errorsList() { - if (!modelErrors) - return; + QList list; for (int i = 0; i < CPN_MAX_INPUTS; i++) { - if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) { - // delete input line and fix up anything else then update refs - //updateAllReferences(ModelData::REF_UPD_TYPE_INPUT, REF_UPD_ACT_CLEAR, i); - } + if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) + list.append(tr("Input: %1 Error: %2").arg(i + 1).arg(tr("has no source"))); } for (int i = 0; i < CPN_MAX_MIXERS; i++) { - if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) { - // delete mixer line and fix up anything like numbering?? - } + // fix line # wrong !!!!!! + if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) + list.append(tr("Mix: %1 Line: %2 Error: %3").arg(mixData[i].destCh).arg(i + 1).arg(tr("has no source"))); } + + return list; } diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 01c3e4cdd8c..09660560bee 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -367,10 +367,10 @@ class ModelData { static AbstractStaticItemModel * funcSwitchStartItemModel(); int getCustomScreensCount() const; - void fixErrors(); bool hasErrors() { return modelErrors; } bool isValid() { return !hasErrors(); } void validate(); + QList errorsList(); protected: void removeGlobalVar(int & var); diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp index b2ac99d2500..f5e10958346 100644 --- a/companion/src/firmwares/radiodata.cpp +++ b/companion/src/firmwares/radiodata.cpp @@ -359,9 +359,3 @@ int RadioData::invalidModels() return cnt; } - -void RadioData::fixInvalidModels() -{ - for(auto &model: models) - model.fixErrors(); -} diff --git a/companion/src/firmwares/radiodata.h b/companion/src/firmwares/radiodata.h index 77566c352e7..4263092b16b 100644 --- a/companion/src/firmwares/radiodata.h +++ b/companion/src/firmwares/radiodata.h @@ -68,7 +68,6 @@ class RadioData { QString getNextModelFilename(); void validateModels(); int invalidModels(); - void fixInvalidModels(); static QString modelSortOrderToString(int value); static AbstractStaticItemModel * modelSortOrderItemModel(); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index ed5236c265d..e729c901af5 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1336,19 +1336,6 @@ bool MdiChild::saveAs(bool isNew) bool MdiChild::saveFile(const QString & filename, bool setCurrent) { - // do not check for etx files as we accept errors - int cnt = radioData.invalidModels(); - if (cnt) { - if (askQuestion(tr("%1 models have errors. Repair?").arg(cnt), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Yes) { - radioData.fixInvalidModels(); - // NOW NEED TO REFRESH GUI if Model Edit open !!!!!!! - // refresh inputs and mixes lists - // update any data models - } - else - return false; - } - radioData.fixModelFilenames(); Storage storage(filename); bool result = storage.write(radioData); From 15009c63938f4e6ab8950e72de2aad643d8c0fc7 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 16:44:29 +1100 Subject: [PATCH 06/16] Remove comment --- companion/src/mainwindow.cpp | 2 -- radio/src/thirdparty/FreeRTOS | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 362bed8378e..40860a26178 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -889,10 +889,8 @@ void MainWindow::createActions() // assigned menus in createMenus() recentFilesAct = addAct("recentdocument.png"); closeAct = addAct("clear.png", SLOT(closeFile()) /*, QKeySequence::Close*/); // setting/showing this shortcut interferes with the system one (Ctrl+W/Ctrl-F4) - // TODO change to more appropriate icon sets and uncomment toolbar actions writeSettingsSDPathAct = addAct("folder-tree-write.png", SLOT(writeSettingsSDPath())); readSettingsSDPathAct = addAct("folder-tree-read.png", SLOT(readSettingsSDPath())); - // end TODO exitAct = addAct("exit.png", SLOT(closeAllWindows()), QKeySequence::Quit, qApp); editAppSettingsAct = addAct("apppreferences.png", SLOT(editAppSettings()), QKeySequence::Preferences); diff --git a/radio/src/thirdparty/FreeRTOS b/radio/src/thirdparty/FreeRTOS index dbf70559b27..a4b28e35103 160000 --- a/radio/src/thirdparty/FreeRTOS +++ b/radio/src/thirdparty/FreeRTOS @@ -1 +1 @@ -Subproject commit dbf70559b27d39c1fdb68dfb9a32140b6a6777a0 +Subproject commit a4b28e35103d699edf074dfff4835921b481b301 From a8d090e912166ee29924d8f169e698b5f3cb758f Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 17:28:25 +1100 Subject: [PATCH 07/16] Prevent saving except to etx --- companion/src/mainwindow.cpp | 4 ++-- companion/src/mdichild.cpp | 15 ++++++++++++++- companion/src/mdichild.h | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 40860a26178..7b7c73082ff 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -676,9 +676,9 @@ void MainWindow::updateMenus() saveAsAct->setEnabled(activeChild); closeAct->setEnabled(activeChild); compareAct->setEnabled(activeChild); - writeSettingsAct->setEnabled(activeChild); + writeSettingsAct->setEnabled(activeChild && !activeMdiChild()->invalidModels()); readSettingsAct->setEnabled(true); - writeSettingsSDPathAct->setEnabled(activeChild && isSDPathValid()); + writeSettingsSDPathAct->setEnabled(activeChild && isSDPathValid() && !activeMdiChild()->invalidModels()); readSettingsSDPathAct->setEnabled(isSDPathValid()); writeBUToRadioAct->setEnabled(false); readBUToFileAct->setEnabled(false); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index e729c901af5..e3332bbfb12 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -349,6 +349,7 @@ void MdiChild::updateNavigation() cboModelSortOrder->setCurrentIndex(radioData.sortOrder); cboModelSortOrder->blockSignals(false); } + action[ACT_GEN_SIM]->setEnabled(!invalidModels()); action[ACT_GEN_SRT]->setVisible(hasLabels); action[ACT_MDL_DEL]->setEnabled(modelsSelected); @@ -369,7 +370,7 @@ void MdiChild::updateNavigation() action[ACT_MDL_WIZ]->setEnabled(singleModelSelected); action[ACT_MDL_DFT]->setEnabled(singleModelSelected && getCurrentModel() != (int)radioData.generalSettings.currModelIndex); action[ACT_MDL_PRT]->setEnabled(singleModelSelected); - action[ACT_MDL_SIM]->setEnabled(singleModelSelected); + action[ACT_MDL_SIM]->setEnabled(singleModelSelected && !invalidModels()); } void MdiChild::retranslateUi() @@ -1490,6 +1491,13 @@ int MdiChild::askQuestion(const QString & msg, QMessageBox::StandardButtons butt void MdiChild::writeSettings(StatusDialog * status, bool toRadio) // write to Tx { + // safeguard as the menu actions should be disabled + int cnt = radioData.invalidModels(); + if (cnt) { + QMessageBox::critical(this, tr("Write Models and Settings"), tr("Operation aborted as %1 models have significant errors that may affect model operation.").arg(cnt)); + return; + } + if (g.confirmWriteModelsAndSettings()) { QMessageBox msgbox; msgbox.setText(tr("You are about to overwrite ALL models.")); @@ -1858,3 +1866,8 @@ QAction * MdiChild::actionsSeparator() act->setSeparator(true); return act; } + +bool MdiChild::invalidModels() +{ + return (bool)radioData.invalidModels(); +} diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 4d823235770..168d2b70eef 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -88,6 +88,7 @@ class MdiChild : public QWidget QList getModelActions(); QList getLabelsActions(); QAction * getAction(const Actions type); + bool invalidModels(); public slots: void newFile(bool createDefaults = true); From 479bfde7cf8e287e8838c9cb6380904244166e01 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 23:07:56 +1100 Subject: [PATCH 08/16] Add model error info action to main menu toolbar and context menu --- companion/src/firmwares/modeldata.cpp | 29 +++++++++++++++++++++++---- companion/src/firmwares/modeldata.h | 4 +++- companion/src/mdichild.cpp | 20 +++++++++++++----- companion/src/mdichild.h | 2 ++ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index a3d34451874..e1d6d2e0062 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1946,20 +1946,41 @@ void ModelData::validate() } } -QList ModelData::errorsList() +QStringList ModelData::errorsList() { - QList list; + QStringList list; for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) - list.append(tr("Input: %1 Error: %2").arg(i + 1).arg(tr("has no source"))); + list.append(tr("Error - Input: %1 Line: %2 %3").arg(i + 1).arg(getInputLine(i)).arg(tr("has no source"))); } for (int i = 0; i < CPN_MAX_MIXERS; i++) { // fix line # wrong !!!!!! if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) - list.append(tr("Mix: %1 Line: %2 Error: %3").arg(mixData[i].destCh).arg(i + 1).arg(tr("has no source"))); + list.append(tr("Error - Mix: %1 Line: %2 %3").arg(mixData[i].destCh).arg(getMixLine(i)).arg(tr("has no source"))); } return list; } + +int ModelData::getMixLine(int index) const +{ + int cnt = 1; + + for (int i = index - 1; i >= 0 && mixData[i].destCh == mixData[index].destCh; i--) + cnt++; + + return cnt; +} + +int ModelData::getInputLine(int index) const +{ + int cnt = 1; + + for (int i = 0; i < index; i++) + if (expoData[i].chn == expoData[index].chn) + cnt++; + + return cnt; +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 09660560bee..240ad339d17 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -370,7 +370,7 @@ class ModelData { bool hasErrors() { return modelErrors; } bool isValid() { return !hasErrors(); } void validate(); - QList errorsList(); + QStringList errorsList(); protected: void removeGlobalVar(int & var); @@ -426,4 +426,6 @@ class ModelData { value = swtch.toValue(); } void updateResetParam(CustomFunctionData * cfd); + int getMixLine(int index) const; + int getInputLine(int index) const; }; diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index e3332bbfb12..688efec33c4 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -227,11 +227,12 @@ void MdiChild::setupNavigation() addAct(ACT_MDL_SIM, "simulate.png", SLOT(modelSimulate()), tr("Alt+S")); addAct(ACT_MDL_DUP, "duplicate.png", SLOT(modelDuplicate()), QKeySequence::Underline); - addAct(ACT_MDL_CUT, "cut.png", SLOT(cut()), QKeySequence::Cut); - addAct(ACT_MDL_CPY, "copy.png", SLOT(copy()), QKeySequence::Copy); - addAct(ACT_MDL_PST, "paste.png", SLOT(paste()), QKeySequence::Paste); - addAct(ACT_MDL_INS, "list.png", SLOT(insert()), QKeySequence::Italic); - addAct(ACT_MDL_EXP, "save.png", SLOT(modelExport()), tr("Ctrl+Alt+S")); + addAct(ACT_MDL_CUT, "cut.png", SLOT(cut()), QKeySequence::Cut); + addAct(ACT_MDL_CPY, "copy.png", SLOT(copy()), QKeySequence::Copy); + addAct(ACT_MDL_PST, "paste.png", SLOT(paste()), QKeySequence::Paste); + addAct(ACT_MDL_INS, "list.png", SLOT(insert()), QKeySequence::Italic); + addAct(ACT_MDL_EXP, "save.png", SLOT(modelExport()), tr("Ctrl+Alt+S")); + addAct(ACT_MDL_ERR, "information.png", SLOT(modelShowErrors()), tr("Ctrl+Alt+E")); addAct(ACT_MDL_MOV, "arrow-right.png"); QMenu * catsMenu = new QMenu(this); @@ -371,6 +372,7 @@ void MdiChild::updateNavigation() action[ACT_MDL_DFT]->setEnabled(singleModelSelected && getCurrentModel() != (int)radioData.generalSettings.currModelIndex); action[ACT_MDL_PRT]->setEnabled(singleModelSelected); action[ACT_MDL_SIM]->setEnabled(singleModelSelected && !invalidModels()); + action[ACT_MDL_ERR]->setEnabled(singleModelSelected && radioData.models[getCurrentModel()].modelErrors); } void MdiChild::retranslateUi() @@ -400,6 +402,7 @@ void MdiChild::retranslateUi() action[ACT_MDL_PRT]->setText(tr("Print Model")); action[ACT_MDL_SIM]->setText(tr("Simulate Model")); action[ACT_MDL_DUP]->setText(tr("Duplicate Model")); + action[ACT_MDL_ERR]->setText(tr("Show Model Errors")); radioToolbar->setWindowTitle(tr("Show Radio Actions Toolbar")); modelsToolbar->setWindowTitle(tr("Show Model Actions Toolbar")); @@ -445,6 +448,7 @@ QList MdiChild::getModelActions() //actGrp.append(getAction(ACT_MDL_RTR)); actGrp.append(getAction(ACT_MDL_PRT)); actGrp.append(getAction(ACT_MDL_SIM)); + actGrp.append(getAction(ACT_MDL_ERR)); return actGrp; } @@ -1871,3 +1875,9 @@ bool MdiChild::invalidModels() { return (bool)radioData.invalidModels(); } + +void MdiChild::modelShowErrors() +{ + ModelData &mdl = radioData.models[getCurrentModel()]; + QMessageBox::information(this, tr("Model: %1 Information").arg(mdl.name), mdl.errorsList().join("\n")); +} \ No newline at end of file diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 168d2b70eef..c6f2516f8bc 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -69,6 +69,7 @@ class MdiChild : public QWidget ACT_MDL_DFT, // set as DeFaulT ACT_MDL_PRT, // print ACT_MDL_SIM, + ACT_MDL_ERR, ACT_LBL_ADD, // label actions.. ACT_LBL_DEL, ACT_LBL_MVU, // Move up @@ -153,6 +154,7 @@ class MdiChild : public QWidget void labelsFault(QString msg); void wizardEdit(); void modelDuplicate(); + void modelShowErrors(); void openModelWizard(int row = -1); void openModelEditWindow(int row = -1); From 02ffe2ca416c25bcc1bbc6e3d2649b844e41946a Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 23:15:18 +1100 Subject: [PATCH 09/16] Revert not writing inputs and mixes with no source --- companion/src/firmwares/edgetx/yaml_modeldata.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 3f32c78c4fa..f0ceeeb1841 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -1014,7 +1014,7 @@ Node convert::encode(const ModelData& rhs) for (int i = 0; i < CPN_MAX_MIXERS; i++) { const MixData& mix = rhs.mixData[i]; - if (!mix.isEmpty() && mix.srcRaw != SOURCE_TYPE_NONE) { + if (!mix.isEmpty()) { node["mixData"].push_back(Node(mix)); } } @@ -1029,7 +1029,7 @@ Node convert::encode(const ModelData& rhs) std::set inputs; for (int i = 0; i < CPN_MAX_EXPOS; i++) { const ExpoData& expo = rhs.expoData[i]; - if (!expo.isEmpty() && expo.srcRaw != SOURCE_TYPE_NONE) { + if (!expo.isEmpty()) { Node expoNode; expoNode = expo; node["expoData"].push_back(expoNode); From b7ea5e0c9228a2cc3c0c556994aefe5ea2658b74 Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 24 Jan 2025 23:28:14 +1100 Subject: [PATCH 10/16] Fix input error reference --- companion/src/firmwares/modeldata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index e1d6d2e0062..13ade072684 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1952,7 +1952,7 @@ QStringList ModelData::errorsList() for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) - list.append(tr("Error - Input: %1 Line: %2 %3").arg(i + 1).arg(getInputLine(i)).arg(tr("has no source"))); + list.append(tr("Error - Input: %1 Line: %2 %3").arg(expoData[i].chn + 1).arg(getInputLine(i)).arg(tr("has no source"))); } for (int i = 0; i < CPN_MAX_MIXERS; i++) { From aa1ebabec7b74770a0148d9a80ca0b44e36ad8f9 Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 25 Jan 2025 07:01:30 +1100 Subject: [PATCH 11/16] Housekeeping --- companion/src/firmwares/modeldata.cpp | 4 ++-- companion/src/firmwares/modeldata.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 13ade072684..7d853b508cd 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1956,7 +1956,6 @@ QStringList ModelData::errorsList() } for (int i = 0; i < CPN_MAX_MIXERS; i++) { - // fix line # wrong !!!!!! if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) list.append(tr("Error - Mix: %1 Line: %2 %3").arg(mixData[i].destCh).arg(getMixLine(i)).arg(tr("has no source"))); } @@ -1978,9 +1977,10 @@ int ModelData::getInputLine(int index) const { int cnt = 1; - for (int i = 0; i < index; i++) + for (int i = 0; i < index; i++) { if (expoData[i].chn == expoData[index].chn) cnt++; + } return cnt; } diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 240ad339d17..d4af9c1e1a8 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -376,6 +376,9 @@ class ModelData { void removeGlobalVar(int & var); private: + int getMixLine(int index) const; + int getInputLine(int index) const; + QVector *updRefList = nullptr; struct UpdateReferenceInfo @@ -426,6 +429,4 @@ class ModelData { value = swtch.toValue(); } void updateResetParam(CustomFunctionData * cfd); - int getMixLine(int index) const; - int getInputLine(int index) const; }; From 7eeed6fb3bed26bbe0aa3f0872252fc58d513b2b Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 25 Jan 2025 16:24:26 +1100 Subject: [PATCH 12/16] Change msg icon and title --- companion/src/mdichild.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 688efec33c4..dcc5c7ba7ff 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1879,5 +1879,5 @@ bool MdiChild::invalidModels() void MdiChild::modelShowErrors() { ModelData &mdl = radioData.models[getCurrentModel()]; - QMessageBox::information(this, tr("Model: %1 Information").arg(mdl.name), mdl.errorsList().join("\n")); -} \ No newline at end of file + QMessageBox::critical(this, QString("%1").arg(mdl.name), mdl.errorsList().join("\n")); +} From 9b12f10762cba85cc1d44462c9a5a9cd4c266848 Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 25 Jan 2025 17:27:43 +1100 Subject: [PATCH 13/16] Fix validation after model edit close --- companion/src/mdichild.cpp | 7 +++++++ companion/src/mdichild.h | 1 + companion/src/modeledit/modeledit.cpp | 3 ++- companion/src/modeledit/modeledit.h | 6 ++---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index dcc5c7ba7ff..19f01fb9a57 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1209,6 +1209,7 @@ void MdiChild::openModelEditWindow(int row) gStopwatch.report("ModelEdit created"); t->setWindowTitle(tr("Editing model %1: ").arg(row+1) + QString(model.name) + QString(" (%1)").arg(userFriendlyCurrentFile())); connect(t, &ModelEdit::modified, this, &MdiChild::setCurrentModelModified); + connect(t, &ModelEdit::closed, this, &MdiChild::onModelEditClosed); gStopwatch.report("STARTING MODEL EDIT"); t->show(); QApplication::restoreOverrideCursor(); @@ -1881,3 +1882,9 @@ void MdiChild::modelShowErrors() ModelData &mdl = radioData.models[getCurrentModel()]; QMessageBox::critical(this, QString("%1").arg(mdl.name), mdl.errorsList().join("\n")); } + +void MdiChild::onModelEditClosed(int id) +{ + radioData.models[id].validate(); + refresh(); +} diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index c6f2516f8bc..8a57a8b9c74 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -131,6 +131,7 @@ class MdiChild : public QWidget void onCurrentItemChanged(const QModelIndex &, const QModelIndex &); void onDataChanged(const QModelIndex & index); void onInternalModuleChanged(); + void onModelEditClosed(int id); void generalEdit(); void copyGeneralSettings(); diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index deb753d45dc..49a73d300e7 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -140,7 +140,8 @@ ModelEdit::~ModelEdit() void ModelEdit::closeEvent(QCloseEvent *event) { - g.modelEditGeo( saveGeometry() ); + g.modelEditGeo(saveGeometry()); + emit closed(modelId); } void ModelEdit::addTab(GenericPanel *panel, QString text) diff --git a/companion/src/modeledit/modeledit.h b/companion/src/modeledit/modeledit.h index 13c27dce586..f3211bd4a54 100644 --- a/companion/src/modeledit/modeledit.h +++ b/companion/src/modeledit/modeledit.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _MODELEDIT_H_ -#define _MODELEDIT_H_ +#pragma once #include #include "genericpanel.h" @@ -56,6 +55,7 @@ class ModelEdit : public QDialog signals: void modified(); + void closed(int id); private slots: void onTabIndexChanged(int index); @@ -72,5 +72,3 @@ class ModelEdit : public QDialog void launchSimulation(); }; - -#endif // _MODELEDIT_H_ From c17f78610952e95a52b2c0e344298c5261664d49 Mon Sep 17 00:00:00 2001 From: elecpower Date: Mon, 27 Jan 2025 09:16:51 +1100 Subject: [PATCH 14/16] Add status bar to models and settings dialog --- companion/src/companion.qrc | 3 ++ .../src/images/originals/circle-green.svg | 48 +++++++++++++++++++ .../src/images/originals/circle-orange.svg | 48 +++++++++++++++++++ companion/src/images/originals/circle-red.svg | 48 +++++++++++++++++++ companion/src/images/svg/circle-green.svg | 48 +++++++++++++++++++ companion/src/images/svg/circle-orange.svg | 48 +++++++++++++++++++ companion/src/images/svg/circle-red.svg | 48 +++++++++++++++++++ companion/src/mdichild.cpp | 31 ++++++++++++ companion/src/mdichild.h | 6 +++ companion/src/mdichild.ui | 3 ++ 10 files changed, 331 insertions(+) create mode 100644 companion/src/images/originals/circle-green.svg create mode 100644 companion/src/images/originals/circle-orange.svg create mode 100644 companion/src/images/originals/circle-red.svg create mode 100644 companion/src/images/svg/circle-green.svg create mode 100644 companion/src/images/svg/circle-orange.svg create mode 100644 companion/src/images/svg/circle-red.svg diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index bd395a44389..8712699d382 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -10,6 +10,9 @@ images/track.png images/track0.png images/taranison.png + images/svg/circle-green.svg + images/svg/circle-orange.svg + images/svg/circle-red.svg images/simulator/icons/svg/arrow_click.svg images/simulator/icons/svg/camera.svg images/simulator/icons/svg/camera-active.svg diff --git a/companion/src/images/originals/circle-green.svg b/companion/src/images/originals/circle-green.svg new file mode 100644 index 00000000000..e8e8c790ae7 --- /dev/null +++ b/companion/src/images/originals/circle-green.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/images/originals/circle-orange.svg b/companion/src/images/originals/circle-orange.svg new file mode 100644 index 00000000000..f23aaa15c54 --- /dev/null +++ b/companion/src/images/originals/circle-orange.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/images/originals/circle-red.svg b/companion/src/images/originals/circle-red.svg new file mode 100644 index 00000000000..7080708e0ad --- /dev/null +++ b/companion/src/images/originals/circle-red.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/images/svg/circle-green.svg b/companion/src/images/svg/circle-green.svg new file mode 100644 index 00000000000..e8e8c790ae7 --- /dev/null +++ b/companion/src/images/svg/circle-green.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/images/svg/circle-orange.svg b/companion/src/images/svg/circle-orange.svg new file mode 100644 index 00000000000..f23aaa15c54 --- /dev/null +++ b/companion/src/images/svg/circle-orange.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/images/svg/circle-red.svg b/companion/src/images/svg/circle-red.svg new file mode 100644 index 00000000000..7080708e0ad --- /dev/null +++ b/companion/src/images/svg/circle-red.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 19f01fb9a57..bcb79b42c04 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -63,6 +63,7 @@ MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f): if (parentWindow) parentWindow->setWindowIcon(windowIcon()); + setupStatusBar(); setupNavigation(); initModelsList(); @@ -608,6 +609,7 @@ void MdiChild::refresh() } updateNavigation(); updateTitle(); + updateStatusBar(); } void MdiChild::onItemActivated(const QModelIndex index) @@ -1305,6 +1307,7 @@ bool MdiChild::loadFile(const QString & filename, bool resetCurrentFile) } radioData.validateModels(); + updateStatusBar(); return true; } @@ -1888,3 +1891,31 @@ void MdiChild::onModelEditClosed(int id) radioData.models[id].validate(); refresh(); } + +void MdiChild::setupStatusBar() +{ + statusBar = new QStatusBar(); + ui->statusBarLayout->addWidget(statusBar); + statusBarIcon = new QLabel(); + statusBar->addPermanentWidget(statusBarIcon); + statusBarCount = new QLabel(); + statusBar->addPermanentWidget(statusBarCount); +} + +void MdiChild::updateStatusBar() +{ + QPixmap p; + QLabel cnt; + int invalid = radioData.invalidModels(); + + if (!invalidModels()) { + p.load(":/images/svg/circle-green.svg"); + } + else { + p.load(":/images/svg/circle-red.svg"); + cnt.setText(QString::number(invalid)); + } + + statusBarIcon->setPixmap(p.scaled(QSize(16, 16))); + statusBarCount->setText(cnt.text()); +} diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 8a57a8b9c74..65e4ec9761b 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -32,6 +32,7 @@ #include #include #include +#include class QToolBar; class StatusDialog; @@ -223,6 +224,9 @@ class MdiChild : public QWidget QToolBar * modelsToolbar; QToolBar * labelsToolbar; QLabel *lblLabels; + QStatusBar *statusBar; + QLabel *statusBarIcon; + QLabel *statusBarCount; Firmware * firmware; RadioData radioData; @@ -236,6 +240,8 @@ class MdiChild : public QWidget QComboBox* cboModelSortOrder; void setModelModified(const int modelIndex, bool cascade = true); QAction * actionsSeparator(); + void setupStatusBar(); + void updateStatusBar(); }; // This will draw the drop indicator across all columns of a model View (vs. in just one column), and lets us make the indicator more obvious. diff --git a/companion/src/mdichild.ui b/companion/src/mdichild.ui index 7ba95757fa0..439caa168b8 100644 --- a/companion/src/mdichild.ui +++ b/companion/src/mdichild.ui @@ -51,6 +51,9 @@ + + + From 961f8ba9bc9805909dc272dfb48e69e62fb16e84 Mon Sep 17 00:00:00 2001 From: elecpower Date: Wed, 5 Feb 2025 21:45:17 +1100 Subject: [PATCH 15/16] Add traffic light label and tooltip --- companion/src/mdichild.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index bcb79b42c04..28464f5b458 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1896,6 +1896,8 @@ void MdiChild::setupStatusBar() { statusBar = new QStatusBar(); ui->statusBarLayout->addWidget(statusBar); + QLabel *lbl = new QLabel(tr("Models status")); + statusBar->addPermanentWidget(lbl); statusBarIcon = new QLabel(); statusBar->addPermanentWidget(statusBarIcon); statusBarCount = new QLabel(); @@ -1909,9 +1911,11 @@ void MdiChild::updateStatusBar() int invalid = radioData.invalidModels(); if (!invalidModels()) { + statusBarIcon->setToolTip(tr("No errors")); p.load(":/images/svg/circle-green.svg"); } else { + statusBarIcon->setToolTip(tr("Errors")); p.load(":/images/svg/circle-red.svg"); cnt.setText(QString::number(invalid)); } From df17fe8e9ac839699e76c247b7e0c7d131abf132 Mon Sep 17 00:00:00 2001 From: elecpower Date: Thu, 6 Feb 2025 08:24:35 +1100 Subject: [PATCH 16/16] Tweak errors messages --- companion/src/firmwares/modeldata.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 7d853b508cd..8bfac936a8e 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1952,12 +1952,12 @@ QStringList ModelData::errorsList() for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) - list.append(tr("Error - Input: %1 Line: %2 %3").arg(expoData[i].chn + 1).arg(getInputLine(i)).arg(tr("has no source"))); + list.append(tr("Error - Input %1 Line %2 %3").arg(expoData[i].chn + 1).arg(getInputLine(i)).arg(tr("has no source"))); } for (int i = 0; i < CPN_MAX_MIXERS; i++) { if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) - list.append(tr("Error - Mix: %1 Line: %2 %3").arg(mixData[i].destCh).arg(getMixLine(i)).arg(tr("has no source"))); + list.append(tr("Error - Mix %1 Line %2 %3").arg(mixData[i].destCh).arg(getMixLine(i)).arg(tr("has no source"))); } return list;