fix(cpn): inputs and mixes must have source (#5798)

This commit is contained in:
Neil Horne
2025-02-06 12:05:31 +10:00
committed by GitHub
parent 0325bd776b
commit ec3c5bf188
19 changed files with 481 additions and 21 deletions
+3
View File
@@ -10,6 +10,9 @@
<file>images/track.png</file>
<file>images/track0.png</file>
<file>images/taranison.png</file>
<file>images/svg/circle-green.svg</file>
<file>images/svg/circle-orange.svg</file>
<file>images/svg/circle-red.svg</file>
<file>images/simulator/icons/svg/arrow_click.svg</file>
<file>images/simulator/icons/svg/camera.svg</file>
<file>images/simulator/icons/svg/camera-active.svg</file>
+60
View File
@@ -29,6 +29,8 @@
#include "adjustmentreference.h"
#include "compounditemmodels.h"
#include <QMessageBox>
ModelData::ModelData()
{
clear();
@@ -1924,3 +1926,61 @@ int ModelData::getCustomScreensCount() const
return cnt;
}
void ModelData::validate()
{
modelErrors = false;
for (int i = 0; i < CPN_MAX_INPUTS; i++) {
if (!expoData[i].isEmpty() && expoData[i].srcRaw == SOURCE_TYPE_NONE) {
modelErrors = true;
return;
}
}
for (int i = 0; i < CPN_MAX_MIXERS; i++) {
if (!mixData[i].isEmpty() && mixData[i].srcRaw == SOURCE_TYPE_NONE) {
modelErrors = true;
return;
}
}
}
QStringList ModelData::errorsList()
{
QStringList list;
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")));
}
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")));
}
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;
}
+8
View File
@@ -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,11 +367,18 @@ class ModelData {
static AbstractStaticItemModel * funcSwitchStartItemModel();
int getCustomScreensCount() const;
bool hasErrors() { return modelErrors; }
bool isValid() { return !hasErrors(); }
void validate();
QStringList errorsList();
protected:
void removeGlobalVar(int & var);
private:
int getMixLine(int index) const;
int getInputLine(int index) const;
QVector<UpdateReferenceParams> *updRefList = nullptr;
struct UpdateReferenceInfo
+16
View File
@@ -343,3 +343,19 @@ AbstractStaticItemModel * RadioData::modelSortOrderItemModel()
mdl->loadItemList();
return mdl;
}
void RadioData::validateModels()
{
for(auto &model: models)
model.validate();
}
int RadioData::invalidModels()
{
int cnt = 0;
for(auto &model: models)
cnt += model.isValid() ? 0 : 1;
return cnt;
}
+2
View File
@@ -66,6 +66,8 @@ class RadioData {
void setCurrentModel(unsigned int index);
void fixModelFilenames();
QString getNextModelFilename();
void validateModels();
int invalidModels();
static QString modelSortOrderToString(int value);
static AbstractStaticItemModel * modelSortOrderItemModel();
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-green.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#14ff14;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-orange.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#ff8000;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572;fill-opacity:1"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-red.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#ff0000;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572;fill-opacity:1"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-green.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#14ff14;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-orange.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#ff8000;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572;fill-opacity:1"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48mm"
height="48mm"
viewBox="0 0 48 48"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="circle-red.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.5197952"
inkscape:cx="153.96812"
inkscape:cy="139.82147"
inkscape:window-width="1920"
inkscape:window-height="1055"
inkscape:window-x="-7"
inkscape:window-y="-7"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#ff0000;stroke:#ffffff;stroke-width:0.204744;stroke-linejoin:round;stroke-opacity:0.99572;fill-opacity:1"
id="path1"
cx="24"
cy="24"
r="21.897629" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+2 -4
View File
@@ -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);
@@ -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);
+76 -7
View File
@@ -63,6 +63,7 @@ MdiChild::MdiChild(QWidget * parent, QWidget * parentWin, Qt::WindowFlags f):
if (parentWindow)
parentWindow->setWindowIcon(windowIcon());
setupStatusBar();
setupNavigation();
initModelsList();
@@ -227,11 +228,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);
@@ -349,6 +351,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 +372,8 @@ 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());
action[ACT_MDL_ERR]->setEnabled(singleModelSelected && radioData.models[getCurrentModel()].modelErrors);
}
void MdiChild::retranslateUi()
@@ -399,6 +403,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"));
@@ -444,6 +449,7 @@ QList<QAction *> 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;
}
@@ -603,6 +609,7 @@ void MdiChild::refresh()
}
updateNavigation();
updateTitle();
updateStatusBar();
}
void MdiChild::onItemActivated(const QModelIndex index)
@@ -1204,6 +1211,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();
@@ -1298,6 +1306,9 @@ bool MdiChild::loadFile(const QString & filename, bool resetCurrentFile)
refresh();
}
radioData.validateModels();
updateStatusBar();
return true;
}
@@ -1344,8 +1355,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();
@@ -1486,6 +1499,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."));
@@ -1854,3 +1874,52 @@ QAction * MdiChild::actionsSeparator()
act->setSeparator(true);
return act;
}
bool MdiChild::invalidModels()
{
return (bool)radioData.invalidModels();
}
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();
}
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();
statusBar->addPermanentWidget(statusBarCount);
}
void MdiChild::updateStatusBar()
{
QPixmap p;
QLabel cnt;
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));
}
statusBarIcon->setPixmap(p.scaled(QSize(16, 16)));
statusBarCount->setText(cnt.text());
}
+12 -4
View File
@@ -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"
@@ -33,6 +32,7 @@
#include <QWidget>
#include <QStyledItemDelegate>
#include <QListWidget>
#include <QStatusBar>
class QToolBar;
class StatusDialog;
@@ -70,6 +70,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
@@ -89,6 +90,7 @@ class MdiChild : public QWidget
QList<QAction *> getModelActions();
QList<QAction *> getLabelsActions();
QAction * getAction(const Actions type);
bool invalidModels();
public slots:
void newFile(bool createDefaults = true);
@@ -130,6 +132,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();
@@ -153,6 +156,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);
@@ -201,6 +205,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<QDialog *> * getChildrenDialogsList(QRegularExpression & regexp);
@@ -219,6 +224,9 @@ class MdiChild : public QWidget
QToolBar * modelsToolbar;
QToolBar * labelsToolbar;
QLabel *lblLabels;
QStatusBar *statusBar;
QLabel *statusBarIcon;
QLabel *statusBarCount;
Firmware * firmware;
RadioData radioData;
@@ -232,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.
@@ -262,5 +272,3 @@ class ItemViewProxyStyle: public QProxyStyle
}
}
};
#endif // _MDICHILD_H_
+3
View File
@@ -51,6 +51,9 @@
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="statusBarLayout"/>
</item>
</layout>
</widget>
<resources/>
+2 -1
View File
@@ -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)
+2 -4
View File
@@ -19,8 +19,7 @@
* GNU General Public License for more details.
*/
#ifndef _MODELEDIT_H_
#define _MODELEDIT_H_
#pragma once
#include <QtWidgets>
#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_
+6
View File
@@ -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 --;