diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 2b4015650..b06e3c79d 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -2128,7 +2128,7 @@ void ModelData::validate() QStringList ModelData::errorsList() { - QStringList list; + QStringList list { "" }; for (int i = 0; i < CPN_MAX_INPUTS; i++) { if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) diff --git a/companion/src/firmwares/radiodata.cpp b/companion/src/firmwares/radiodata.cpp index ee96a86d4..a07496a12 100644 --- a/companion/src/firmwares/radiodata.cpp +++ b/companion/src/firmwares/radiodata.cpp @@ -358,3 +358,18 @@ int RadioData::invalidModels() return cnt; } + +QStringList RadioData::modelErrorsList() +{ + QStringList ret; + + for(auto &model: models) { + if (!model.isValid()) { + ret.append(""); + ret.append(model.name); + ret.append(model.errorsList()); + } + } + + return ret; +} diff --git a/companion/src/firmwares/radiodata.h b/companion/src/firmwares/radiodata.h index 4263092b1..12caf85ed 100644 --- a/companion/src/firmwares/radiodata.h +++ b/companion/src/firmwares/radiodata.h @@ -68,6 +68,7 @@ class RadioData { QString getNextModelFilename(); void validateModels(); int invalidModels(); + QStringList modelErrorsList(); static QString modelSortOrderToString(int value); static AbstractStaticItemModel * modelSortOrderItemModel(); diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index d64ccab66..3f44ff1fb 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -677,9 +677,9 @@ void MainWindow::updateMenus() saveAsAct->setEnabled(activeChild); closeAct->setEnabled(activeChild); compareAct->setEnabled(activeChild); - writeSettingsAct->setEnabled(activeChild && !activeMdiChild()->invalidModels()); + writeSettingsAct->setEnabled(activeChild); readSettingsAct->setEnabled(true); - writeSettingsSDPathAct->setEnabled(activeChild && isSDPathValid() && !activeMdiChild()->invalidModels()); + writeSettingsSDPathAct->setEnabled(activeChild && isSDPathValid()); readSettingsSDPathAct->setEnabled(isSDPathValid()); writeBUToRadioAct->setEnabled(false); readBUToFileAct->setEnabled(false); @@ -1518,12 +1518,22 @@ bool MainWindow::readSettingsFromSDPath(const QString & filename) void MainWindow::writeSettingsSDPath() { - StatusDialog *status = new StatusDialog(this, tr("Writing models and settings to SD path"), tr("In progress..."), 400); + if (activeMdiChild()) { + int cnt = activeMdiChild()->invalidModels(); - if (activeMdiChild()) + if (cnt) { + QMessageBox::critical(this, tr("Write Models and Settings to SD Path"), + tr("Operation aborted: %1 models have errors that may affect operation.\n%2") + .arg(cnt) + .arg(activeMdiChild()->modelErrorsList().join("\n"))); + + return; + } + + StatusDialog *status = new StatusDialog(this, tr("Writing models and settings to SD path"), tr("In progress..."), 400); activeMdiChild()->writeSettings(status, false); - - delete status; + delete status; + } } bool MainWindow::isSDPathValid() diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 8c0b80f95..e6b4d849d 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -38,6 +38,17 @@ #include #include + +void StatusBarIcon::mouseDoubleClickEvent(QMouseEvent * event) +{ + QLabel::mouseDoubleClickEvent(event); + emit doubleClicked(); +} + +/* + class MdiChild +*/ + MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f): QWidget(parent, f), ui(new Ui::MdiChild), @@ -352,7 +363,7 @@ void MdiChild::updateNavigation() cboModelSortOrder->setCurrentIndex(radioData.sortOrder); cboModelSortOrder->blockSignals(false); } - action[ACT_GEN_SIM]->setEnabled(!invalidModels()); + action[ACT_GEN_SIM]->setEnabled(true); action[ACT_GEN_SRT]->setVisible(hasLabels); action[ACT_MDL_DEL]->setEnabled(modelsSelected); @@ -375,7 +386,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 && !invalidModels()); + action[ACT_MDL_SIM]->setEnabled(singleModelSelected); action[ACT_MDL_ERR]->setEnabled(singleModelSelected && radioData.models[getCurrentModel()].modelErrors); emit navigationUpdated(); @@ -1285,12 +1296,35 @@ void MdiChild::setDefault() void MdiChild::radioSimulate() { + // safeguard as the menu actions are enabled + int cnt = radioData.invalidModels(); + + if (cnt) { + QMessageBox::critical(this, tr("Simulate Radio"), + tr("Operation aborted: %1 models have errors that may affect simulation.\n%2") + .arg(cnt) + .arg(radioData.modelErrorsList().join("\n"))); + return; + } + startSimulation(this, radioData, -1); } void MdiChild::modelSimulate() { - startSimulation(this, radioData, getCurrentModel()); + int currMdlIdx = getCurrentModel(); + + if (currMdlIdx > -1 && !radioData.models[currMdlIdx].isValid()) { + QMessageBox::critical(this, tr("Simulate Model"), + tr("Operation aborted: selected model has errors that may affect simulation.\n%1") + .arg(radioData.models[currMdlIdx].errorsList().join("\n"))); + return; + } + + if (currMdlIdx < 0) + radioSimulate(); + else + startSimulation(this, radioData, getCurrentModel()); } void MdiChild::newFile(bool useProfileSettings) @@ -1541,11 +1575,14 @@ int MdiChild::askQuestion(const QString & msg, QMessageBox::StandardButtons butt void MdiChild::writeSettings(StatusDialog * status, bool toRadio) { - // safeguard as the menu actions should be disabled + // safeguard as the menu actions are enabled 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)); + QMessageBox::critical(this, tr("Write Models and Settings"), + tr("Operation aborted as %1 models have significant errors that may affect model operation.\n%2") + .arg(cnt) + .arg(radioData.modelErrorsList().join("\n"))); return; } @@ -1915,9 +1952,14 @@ QAction * MdiChild::actionsSeparator() return act; } -bool MdiChild::invalidModels() +int MdiChild::invalidModels() { - return (bool)radioData.invalidModels(); + return radioData.invalidModels(); +} + +QStringList MdiChild::modelErrorsList() +{ + return radioData.modelErrorsList(); } void MdiChild::modelShowErrors() @@ -1938,7 +1980,7 @@ void MdiChild::setupStatusBar() ui->statusBarLayout->addWidget(statusBar); QLabel *lbl = new QLabel(tr("Models status")); statusBar->addPermanentWidget(lbl); - statusBarIcon = new QLabel(); + statusBarIcon = new StatusBarIcon(this); statusBar->addPermanentWidget(statusBarIcon); statusBarCount = new QLabel(); statusBar->addPermanentWidget(statusBarCount); @@ -1949,13 +1991,16 @@ void MdiChild::updateStatusBar() QPixmap p; QLabel cnt; int invalid = radioData.invalidModels(); + disconnect(statusBarIcon, &StatusBarIcon::doubleClicked, nullptr, nullptr); if (!invalidModels()) { statusBarIcon->setToolTip(tr("No errors")); p.load(":/images/png/tick-green.png"); - } - else { - statusBarIcon->setToolTip(tr("Errors")); + } else { + statusBarIcon->setToolTip(tr("Double click to display errors")); + connect(statusBarIcon, &StatusBarIcon::doubleClicked, [this] () { + QMessageBox::critical(this, tr("Models Status"), radioData.modelErrorsList().join("\n")); + }); p.load(":/images/png/cross-red.png"); cnt.setText(QString::number(invalid)); } @@ -2039,4 +2084,4 @@ void MdiChild::modelImport() refresh(); setModified(); } -} \ No newline at end of file +} diff --git a/companion/src/mdichild.h b/companion/src/mdichild.h index 541a40c9c..49c58abb9 100644 --- a/companion/src/mdichild.h +++ b/companion/src/mdichild.h @@ -44,6 +44,21 @@ class MdiChild; class LabelsDelegate; class LabelsProxy; +class StatusBarIcon : public QLabel +{ + Q_OBJECT + + public: + StatusBarIcon(QWidget * parent) : QLabel(parent) {} + virtual ~StatusBarIcon() {} + + signals: + void doubleClicked(); + + protected: + virtual void mouseDoubleClickEvent(QMouseEvent * event); +}; + class MdiChild : public QWidget { Q_OBJECT @@ -91,7 +106,8 @@ class MdiChild : public QWidget QList getModelActions(); QList getLabelsActions(); QAction * getAction(const Actions type); - bool invalidModels(); + int invalidModels(); + QStringList modelErrorsList(); public slots: void newFile(bool useProfileSettings = false); @@ -228,7 +244,7 @@ class MdiChild : public QWidget QToolBar * labelsToolbar; QLabel *lblLabels; QStatusBar *statusBar; - QLabel *statusBarIcon; + StatusBarIcon *statusBarIcon; QLabel *statusBarCount; Firmware * firmware; diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index 7f9f0ddf1..0c879cebe 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -168,5 +168,12 @@ void ModelEdit::onTabIndexChanged(int index) void ModelEdit::launchSimulation() { + if (!radioData.models[modelId].isValid()) { + QMessageBox::critical(this, tr("Simulate Model"), + tr("Operation aborted: model has errors that may affect simulation.\n%1") + .arg(radioData.models[modelId].errorsList().join("\n"))); + return; + } + startSimulation(this, radioData, modelId); }