diff --git a/companion/src/datamodels/rawitemdatamodels.cpp b/companion/src/datamodels/rawitemdatamodels.cpp index 1cba1c180..4edd26c76 100644 --- a/companion/src/datamodels/rawitemdatamodels.cpp +++ b/companion/src/datamodels/rawitemdatamodels.cpp @@ -30,7 +30,7 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett Firmware * fw = getCurrentFirmware(); addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); - for (int i=0; i < fw->getCapability(LuaScripts); i++) + for (int i = 0; i < fw->getCapability(LuaScripts); i++) addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16); addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs)); addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board.getCapability(Board::MaxAnalogs)); @@ -67,10 +67,14 @@ void RawSourceItemModel::addItems(const RawSourceType & type, const int group, c } } -void RawSourceItemModel::update() const +void RawSourceItemModel::update() { - for (int i=0; i < rowCount(); ++i) + emit dataAboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt())); + + emit dataUpdateComplete(); } @@ -166,8 +170,53 @@ void RawSwitchItemModel::addItems(const RawSwitchType & type, int count) } } -void RawSwitchItemModel::update() const +void RawSwitchItemModel::update() { - for (int i=0; i < rowCount(); ++i) + emit dataAboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt())); + + emit dataUpdateComplete(); +} + +// +// CurveItemModel +// + +CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : + AbstractRawItemDataModel(generalSettings, modelData, parent) +{ + const int count = getCurrentFirmware()->getCapability(NumCurves); + + for (int i = -count ; i <= count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, ItemIdRole); + int flags; + if (i < 0) + flags = DataGroups::NegativeGroup; + else if (i > 0) + flags = DataGroups::PositiveGroup; + else + flags = DataGroups::NoneGroup; + modelItem->setData(flags, ItemFlagsRole); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CurveItemModel::setDynamicItemData(QStandardItem * item, int index) const +{ + item->setText(CurveReference(CurveReference::CURVE_REF_CUSTOM, index).toString(modelData, false)); + item->setData(true, IsAvailableRole); +} + +void CurveItemModel::update() +{ + emit dataAboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); + + emit dataUpdateComplete(); } diff --git a/companion/src/datamodels/rawitemdatamodels.h b/companion/src/datamodels/rawitemdatamodels.h index 59eb6025e..30a9b54e9 100644 --- a/companion/src/datamodels/rawitemdatamodels.h +++ b/companion/src/datamodels/rawitemdatamodels.h @@ -36,6 +36,13 @@ class AbstractRawItemDataModel: public QStandardItemModel enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole }; Q_ENUM(DataRoles) + enum DataGroups { + NoneGroup = 0x01, + NegativeGroup = 0x02, + PositiveGroup = 0x04 + }; + Q_ENUM(DataGroups) + explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) : QStandardItemModel(parent), generalSettings(generalSettings), @@ -43,7 +50,11 @@ class AbstractRawItemDataModel: public QStandardItemModel {} public slots: - virtual void update() const = 0; + virtual void update() = 0; + + signals: + void dataAboutToBeUpdated(); + void dataUpdateComplete(); protected: const GeneralSettings * generalSettings; @@ -58,7 +69,7 @@ class RawSourceItemModel: public AbstractRawItemDataModel explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); public slots: - void update() const override; + void update() override; protected: void setDynamicItemData(QStandardItem * item, const RawSource & src) const; @@ -73,7 +84,7 @@ class RawSwitchItemModel: public AbstractRawItemDataModel explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); public slots: - void update() const override; + void update() override; protected: void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; @@ -81,4 +92,17 @@ class RawSwitchItemModel: public AbstractRawItemDataModel }; +class CurveItemModel: public AbstractRawItemDataModel +{ + Q_OBJECT + public: + explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); + + public slots: + void update() override; + + protected: + void setDynamicItemData(QStandardItem * item, int index) const; +}; + #endif // RAWITEMDATAMODELS_H diff --git a/companion/src/datamodels/rawitemfilteredmodel.cpp b/companion/src/datamodels/rawitemfilteredmodel.cpp index 1de9e26b2..775b85fc4 100644 --- a/companion/src/datamodels/rawitemfilteredmodel.cpp +++ b/companion/src/datamodels/rawitemfilteredmodel.cpp @@ -30,6 +30,12 @@ RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int setFilterFlags(flags); setDynamicSortFilter(true); setSourceModel(sourceModel); + + AbstractRawItemDataModel * model = qobject_cast(sourceModel); + if (model) { + connect(model, &AbstractRawItemDataModel::dataAboutToBeUpdated, this, &RawItemFilteredModel::onDataAboutToBeUpdated); + connect(model, &AbstractRawItemDataModel::dataUpdateComplete, this, &RawItemFilteredModel::onDataUpdateComplete); + } } void RawItemFilteredModel::setFilterFlags(int flags) @@ -61,14 +67,12 @@ void RawItemFilteredModel::update() const model->update(); } - -RawSourceFilterItemModel::RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent) : - RawItemFilteredModel(new RawSourceItemModel(generalSettings, modelData, parent), flags, parent) +void RawItemFilteredModel::onDataAboutToBeUpdated() { + emit dataAboutToBeUpdated(); } - -RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent) : - RawItemFilteredModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent) +void RawItemFilteredModel::onDataUpdateComplete() { + emit dataUpdateComplete(); } diff --git a/companion/src/datamodels/rawitemfilteredmodel.h b/companion/src/datamodels/rawitemfilteredmodel.h index 2d95dff71..f8bf22c19 100644 --- a/companion/src/datamodels/rawitemfilteredmodel.h +++ b/companion/src/datamodels/rawitemfilteredmodel.h @@ -21,6 +21,8 @@ #ifndef RAWITEMFILTEREDMODEL_H #define RAWITEMFILTEREDMODEL_H +#include "rawitemdatamodels.h" + #include class GeneralSettings; @@ -32,43 +34,30 @@ class RawItemFilteredModel: public QSortFilterProxyModel { Q_OBJECT public: + enum DataFilters { + AllFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup, + HideNegativeFilter = AllFilter &~ AbstractRawItemDataModel::NegativeGroup, + NonePositiveFilter = AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup, + PositiveFilter = AbstractRawItemDataModel::PositiveGroup + }; + Q_ENUM(DataFilters) + explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr); explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {} public slots: void setFilterFlags(int flags); void update() const; + void onDataAboutToBeUpdated(); + void onDataUpdateComplete(); + + signals: + void dataAboutToBeUpdated(); + void dataUpdateComplete(); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; int filterFlags; }; - - -// The specialized "convenience" types below can go away once centralalized RawSource/RawSwitch item models are established. -// These proxy classes will automatically create a source model of the corresponding type. - -class RawSwitchFilterItemModel: public RawItemFilteredModel -{ - Q_OBJECT - public: - using RawItemFilteredModel::RawItemFilteredModel; - - explicit RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent = nullptr); -}; - - -class RawSourceFilterItemModel: public RawItemFilteredModel -{ - Q_OBJECT - public: - using RawItemFilteredModel::RawItemFilteredModel; - - explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent = nullptr); - - explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) : - RawSourceFilterItemModel(generalSettings, modelData, 0, parent) {} -}; - #endif // RAWITEMFILTEREDMODEL_H diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h index cb5be4e73..c6984d7ae 100644 --- a/companion/src/firmwares/curvereference.h +++ b/companion/src/firmwares/curvereference.h @@ -36,6 +36,15 @@ class CurveReference { CURVE_REF_CUSTOM }; + enum CurveRefGroups { + NoneGroup = 0x001, + NegativeGroup = 0x002, + PositiveGroup = 0x004, + + AllCurveRefGroups = NoneGroup | NegativeGroup | PositiveGroup, + PositiveCurveRefGroups = AllCurveRefGroups &~ NegativeGroup + }; + CurveReference() { clear(); } CurveReference(CurveRefType type, int value): @@ -51,6 +60,14 @@ class CurveReference { QString toString(const ModelData * model = NULL, bool verbose = true) const; bool isSet() const { return type != CURVE_REF_DIFF || value != 0; } + + bool operator == ( const CurveReference & other) const { + return (this->type == other.type) && (this->value == other.value); + } + + bool operator != ( const CurveReference & other) const { + return (this->type != other.type) || (this->value != other.value); + } }; #endif // CURVEREFERENCE_H diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 558b848df..51efcc333 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -321,7 +321,7 @@ class ModelData { void updateModuleFailsafes(ModuleData * md); inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType); } inline void updateSwitchRef(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1); } - inline void updateTimerMode(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1, false, (int)SWITCH_TYPE_TIMER_MODE, 0); } + inline void updateTimerMode(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1, false, (int)SWITCH_TYPE_TIMER_MODE, -1 /*adjusted by offset*/); } inline void updateSourceIntRef(int & value) { RawSource src = RawSource(value); diff --git a/companion/src/generaledit/CMakeLists.txt b/companion/src/generaledit/CMakeLists.txt index 827c37ddf..2c458c719 100644 --- a/companion/src/generaledit/CMakeLists.txt +++ b/companion/src/generaledit/CMakeLists.txt @@ -28,4 +28,4 @@ qt5_wrap_ui(generaledit_SRCS ${generaledit_UIS}) qt5_wrap_cpp(generaledit_SRCS ${generaledit_HDRS}) add_library(generaledit ${generaledit_SRCS}) -target_link_libraries(generaledit PRIVATE ${CPN_COMMON_LIB} Qt5::Multimedia) +target_link_libraries(generaledit PRIVATE datamodels ${CPN_COMMON_LIB} Qt5::Multimedia) diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index 34d090e65..a31fee359 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -28,6 +28,7 @@ #include "hardware.h" #include "../modeledit/customfunctions.h" #include "verticalscrollarea.h" +#include "rawitemdatamodels.h" GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) : QDialog(parent), @@ -55,8 +56,11 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir } } + RawSourceItemModel *rawSourceModel = new RawSourceItemModel(&generalSettings, nullptr, this); + RawSwitchItemModel *rawSwitchModel = new RawSwitchItemModel(&generalSettings, nullptr, this); + addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); - addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions")); + addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, rawSourceModel, rawSwitchModel), tr("Global Functions")); addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer")); addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index 6442cc2fb..1371d3fab 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -20,6 +20,7 @@ #include "channels.h" #include "helpers.h" +#include "rawitemfilteredmodel.h" LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel): firmware(firmware), @@ -95,15 +96,16 @@ void LimitsGroup::updateMinMax(int max) } } } - -Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CurveItemModel * curveItemModel): ModelPanel(parent, model, generalSettings, firmware) { - Stopwatch s1("Channels"); - chnCapability = firmware->getCapability(Outputs); int channelNameMaxLen = firmware->getCapability(ChannelsName); + curveModel = new RawItemFilteredModel(curveItemModel, RawItemFilteredModel::AllFilter, this); + connect(curveModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &ChannelsPanel::onModelDataAboutToBeUpdated); + connect(curveModel, &RawItemFilteredModel::dataUpdateComplete, this, &ChannelsPanel::onModelDataUpdateComplete); + QStringList headerLabels; headerLabels << "#"; if (channelNameMaxLen > 0) { @@ -118,8 +120,6 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera headerLabels << tr("Linear Subtrim"); TableLayout *tableLayout = new TableLayout(this, chnCapability, headerLabels); - s1.report("header"); - for (int i = 0; i < chnCapability; i++) { int col = 0; @@ -165,6 +165,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { curveCB[i] = new QComboBox(this); curveCB[i]->setProperty("index", i); + curveCB[i]->setModel(curveModel); connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited())); tableLayout->addWidget(i, col++, curveCB[i]); } @@ -193,15 +194,13 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera } } update(); - s1.report("add elements"); disableMouseScrolling(); tableLayout->resizeColumnsToContents(); tableLayout->pushRowsUp(chnCapability+1); - s1.report("end"); } -Channels::~Channels() +ChannelsPanel::~ChannelsPanel() { // compiler warning if delete[] for (int i = 0; i < CPN_MAX_CHNOUT; i++) { @@ -214,9 +213,10 @@ Channels::~Channels() delete centerSB[i]; delete symlimitsChk[i]; } + delete curveModel; } -void Channels::symlimitsEdited() +void ChannelsPanel::symlimitsEdited() { if (!lock) { QCheckBox *ckb = qobject_cast(sender()); @@ -226,17 +226,20 @@ void Channels::symlimitsEdited() } } -void Channels::nameEdited() +void ChannelsPanel::nameEdited() { if (!lock) { QLineEdit *le = qobject_cast(sender()); int index = le->property("index").toInt(); - strcpy(model->limitData[index].name, le->text().toLatin1()); - emit modified(); + if (model->limitData[index].name != le->text()) { + strcpy(model->limitData[index].name, le->text().toLatin1()); + emit updateDataModels(); + emit modified(); + } } } -void Channels::refreshExtendedLimits() +void ChannelsPanel::refreshExtendedLimits() { int channelMax = model->getChannelsMax(); @@ -248,7 +251,7 @@ void Channels::refreshExtendedLimits() emit modified(); } -void Channels::invEdited() +void ChannelsPanel::invEdited() { if (!lock) { QComboBox *cb = qobject_cast(sender()); @@ -258,17 +261,20 @@ void Channels::invEdited() } } -void Channels::curveEdited() +void ChannelsPanel::curveEdited() { if (!lock) { QComboBox *cb = qobject_cast(sender()); int index = cb->property("index").toInt(); - model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt()); - emit modified(); + // ignore unnecessary updates that could be triggered by updates to the data model + if (model->limitData[index].curve != CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt())) { + model->limitData[index].curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt()); + emit modified(); + } } } -void Channels::ppmcenterEdited() +void ChannelsPanel::ppmcenterEdited() { if (!lock) { QSpinBox *sb = qobject_cast(sender()); @@ -278,51 +284,49 @@ void Channels::ppmcenterEdited() } } -void Channels::update() +void ChannelsPanel::update() { for (int i = 0; i < chnCapability; i++) { updateLine(i); } } -void Channels::updateLine(int i) +void ChannelsPanel::updateLine(int i) { lock = true; + LimitData &chn = model->limitData[i]; + if (firmware->getCapability(ChannelsName) > 0) { - name[i]->setText(model->limitData[i].name); + name[i]->setText(chn.name); } - chnOffset[i]->setValue(model->limitData[i].offset); - chnMin[i]->setValue(model->limitData[i].min); - chnMax[i]->setValue(model->limitData[i].max); - invCB[i]->setCurrentIndex((model->limitData[i].revert) ? 1 : 0); + chnOffset[i]->setValue(chn.offset); + chnMin[i]->setValue(chn.min); + chnMax[i]->setValue(chn.max); + invCB[i]->setCurrentIndex((chn.revert) ? 1 : 0); if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { - int numcurves = firmware->getCapability(NumCurves); - curveCB[i]->clear(); - for (int j = -numcurves; j <= numcurves; j++) { - curveCB[i]->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(model, false), j); - } - curveCB[i]->setCurrentIndex(model->limitData[i].curve.value + numcurves); + curveCB[i]->setCurrentIndex(curveCB[i]->findData(chn.curve.value)); } if (firmware->getCapability(PPMCenter)) { - centerSB[i]->setValue(model->limitData[i].ppmCenter + 1500); + centerSB[i]->setValue(chn.ppmCenter + 1500); } if (firmware->getCapability(SYMLimits)) { - symlimitsChk[i]->setChecked(model->limitData[i].symetrical); + symlimitsChk[i]->setChecked(chn.symetrical); } lock = false; } -void Channels::cmPaste() +void ChannelsPanel::cmPaste() { QByteArray data; if (hasClipboardData(&data)) { memcpy(&model->limitData[selectedIndex], data.constData(), sizeof(LimitData)); updateLine(selectedIndex); + emit updateDataModels(); emit modified(); } } -void Channels::cmDelete() +void ChannelsPanel::cmDelete() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -335,10 +339,11 @@ void Channels::cmDelete() updateLine(i); } + emit updateDataModels(); emit modified(); } -void Channels::cmCopy() +void ChannelsPanel::cmCopy() { QByteArray data; data.append((char*)&model->limitData[selectedIndex], sizeof(LimitData)); @@ -347,7 +352,7 @@ void Channels::cmCopy() QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard); } -void Channels::cmCut() +void ChannelsPanel::cmCut() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -356,7 +361,7 @@ void Channels::cmCut() cmClear(false); } -void Channels::onCustomContextMenuRequested(QPoint pos) +void ChannelsPanel::onCustomContextMenuRequested(QPoint pos) { QLabel *label = (QLabel *)sender(); selectedIndex = label->property("index").toInt(); @@ -378,7 +383,7 @@ void Channels::onCustomContextMenuRequested(QPoint pos) contextMenu.exec(globalPos); } -bool Channels::hasClipboardData(QByteArray * data) const +bool ChannelsPanel::hasClipboardData(QByteArray * data) const { const QClipboard * clipboard = QApplication::clipboard(); const QMimeData * mimeData = clipboard->mimeData(); @@ -390,32 +395,32 @@ bool Channels::hasClipboardData(QByteArray * data) const return false; } -bool Channels::insertAllowed() const +bool ChannelsPanel::insertAllowed() const { return ((selectedIndex < chnCapability - 1) && (model->limitData[chnCapability - 1].isEmpty())); } -bool Channels::moveDownAllowed() const +bool ChannelsPanel::moveDownAllowed() const { return selectedIndex < chnCapability - 1; } -bool Channels::moveUpAllowed() const +bool ChannelsPanel::moveUpAllowed() const { return selectedIndex > 0; } -void Channels::cmMoveUp() +void ChannelsPanel::cmMoveUp() { swapData(selectedIndex, selectedIndex - 1); } -void Channels::cmMoveDown() +void ChannelsPanel::cmMoveDown() { swapData(selectedIndex, selectedIndex + 1); } -void Channels::cmClear(bool prompt) +void ChannelsPanel::cmClear(bool prompt) { if (prompt) { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Channel. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) @@ -425,10 +430,11 @@ void Channels::cmClear(bool prompt) model->limitData[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); updateLine(selectedIndex); + emit updateDataModels(); emit modified(); } -void Channels::cmClearAll() +void ChannelsPanel::cmClearAll() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Channels. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -438,19 +444,21 @@ void Channels::cmClearAll() model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_CLEAR, i); updateLine(i); } + emit updateDataModels(); emit modified(); } -void Channels::cmInsert() +void ChannelsPanel::cmInsert() { memmove(&model->limitData[selectedIndex + 1], &model->limitData[selectedIndex], (CPN_MAX_CHNOUT - (selectedIndex + 1)) * sizeof(LimitData)); model->limitData[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); update(); + emit updateDataModels(); emit modified(); } -void Channels::swapData(int idx1, int idx2) +void ChannelsPanel::swapData(int idx1, int idx2) { if ((idx1 != idx2) && (!model->limitData[idx1].isEmpty() || !model->limitData[idx2].isEmpty())) { LimitData chntmp = model->limitData[idx2]; @@ -461,6 +469,17 @@ void Channels::swapData(int idx1, int idx2) model->updateAllReferences(ModelData::REF_UPD_TYPE_CHANNEL, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); updateLine(idx1); updateLine(idx2); + emit updateDataModels(); emit modified(); } } + +void ChannelsPanel::onModelDataAboutToBeUpdated() +{ + lock = true; +} + +void ChannelsPanel::onModelDataUpdateComplete() +{ + update(); +} diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index d20923a35..0583b1d7c 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -26,6 +26,9 @@ #include +class CurveItemModel; +class RawItemFilteredModel; + constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel"; class GVarGroup; @@ -49,13 +52,13 @@ class LimitsGroup double displayStep; }; -class Channels : public ModelPanel +class ChannelsPanel : public ModelPanel { Q_OBJECT public: - Channels(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); - ~Channels(); + ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CurveItemModel * curveItemModel); + ~ChannelsPanel(); public slots: void refreshExtendedLimits(); @@ -78,6 +81,11 @@ class Channels : public ModelPanel void cmClear(bool prompt = true); void cmClearAll(); void onCustomContextMenuRequested(QPoint pos); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); + + signals: + void updateDataModels(); private: bool hasClipboardData(QByteArray * data = nullptr) const; @@ -95,6 +103,7 @@ class Channels : public ModelPanel QCheckBox *symlimitsChk[CPN_MAX_CHNOUT]; int selectedIndex; int chnCapability; + RawItemFilteredModel *curveModel; }; #endif // _CHANNELS_H_ diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 662dc61c4..81da85a02 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -108,7 +108,7 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax return y; } -Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Curves), currentCurve(0) @@ -230,12 +230,12 @@ Curves::Curves(QWidget * parent, ModelData & model, GeneralSettings & generalSet lock = false; } -Curves::~Curves() +CurvesPanel::~CurvesPanel() { delete ui; } -void Curves::editCurve() +void CurvesPanel::editCurve() { QPushButton *button = (QPushButton *)sender(); int index = button->property("index").toInt(); @@ -243,7 +243,7 @@ void Curves::editCurve() update(); } -void Curves::plotCurve(bool checked) +void CurvesPanel::plotCurve(bool checked) { QCheckBox *chk = (QCheckBox *)sender(); int index = chk->property("index").toInt(); @@ -251,7 +251,7 @@ void Curves::plotCurve(bool checked) updateCurve(); } -void Curves::update() +void CurvesPanel::update() { lock = true; @@ -266,12 +266,12 @@ void Curves::update() lock = false; } -void Curves::setCurrentCurve(int index) +void CurvesPanel::setCurrentCurve(int index) { currentCurve = index; } -void Curves::updateCurveType() +void CurvesPanel::updateCurveType() { lock = true; @@ -297,7 +297,7 @@ void Curves::updateCurveType() lock = false; } -void Curves::updateCurve() +void CurvesPanel::updateCurve() { lock = true; @@ -371,7 +371,7 @@ void Curves::updateCurve() lock = false; } -void Curves::updateCurvePoints() +void CurvesPanel::updateCurvePoints() { lock = true; @@ -405,7 +405,7 @@ void Curves::updateCurvePoints() lock = false; } -void Curves::onPointEdited() +void CurvesPanel::onPointEdited() { if (!lock) { int index = sender()->property("index").toInt(); @@ -416,7 +416,7 @@ void Curves::onPointEdited() } } -void Curves::onNodeMoved(int x, int y) +void CurvesPanel::onNodeMoved(int x, int y) { if (!lock) { lock = true; @@ -434,20 +434,20 @@ void Curves::onNodeMoved(int x, int y) } } -void Curves::onNodeFocus() +void CurvesPanel::onNodeFocus() { int index = sender()->property("index").toInt(); spny[index]->setFocus(); } -void Curves::onNodeUnfocus() +void CurvesPanel::onNodeUnfocus() { int index = sender()->property("index").toInt(); spny[index]->clearFocus(); updateCurve(); } -bool Curves::allowCurveType(int points, CurveData::CurveType type) +bool CurvesPanel::allowCurveType(int points, CurveData::CurveType type) { int totalpoints = 0; for (int i = 0; i < maxCurves; i++) { @@ -465,7 +465,7 @@ bool Curves::allowCurveType(int points, CurveData::CurveType type) } } -void Curves::on_curvePoints_currentIndexChanged(int index) +void CurvesPanel::on_curvePoints_currentIndexChanged(int index) { if (!lock) { int numpoints = ((QComboBox *)sender())->itemData(index).toInt(); @@ -488,7 +488,7 @@ void Curves::on_curvePoints_currentIndexChanged(int index) } } -void Curves::on_curveCustom_currentIndexChanged(int index) +void CurvesPanel::on_curveCustom_currentIndexChanged(int index) { if (!lock) { CurveData::CurveType type = (CurveData::CurveType)index; @@ -512,20 +512,23 @@ void Curves::on_curveCustom_currentIndexChanged(int index) } } -void Curves::on_curveSmooth_currentIndexChanged(int index) +void CurvesPanel::on_curveSmooth_currentIndexChanged(int index) { model->curves[currentCurve].smooth = index; update(); } -void Curves::on_curveName_editingFinished() +void CurvesPanel::on_curveName_editingFinished() { - memset(model->curves[currentCurve].name, 0, sizeof(model->curves[currentCurve].name)); - strcpy(model->curves[currentCurve].name, ui->curveName->text().toLatin1()); - emit modified(); + if (ui->curveName->text() != model->curves[currentCurve].name) { + memset(model->curves[currentCurve].name, 0, sizeof(model->curves[currentCurve].name)); + strcpy(model->curves[currentCurve].name, ui->curveName->text().toLatin1()); + emit updateDataModels(); + emit modified(); + } } -void Curves::resizeEvent(QResizeEvent *event) +void CurvesPanel::resizeEvent(QResizeEvent *event) { QRect qr = ui->curvePreview->contentsRect(); ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width() - GFX_MARGIN * 2, qr.height() - GFX_MARGIN * 2); @@ -533,7 +536,7 @@ void Curves::resizeEvent(QResizeEvent *event) ModelPanel::resizeEvent(event); } -void Curves::on_curveType_currentIndexChanged(int index) +void CurvesPanel::on_curveType_currentIndexChanged(int index) { unsigned int flags = templates[index].flags; ui->curveCoeffLabel->setVisible(flags & CURVE_COEFF_ENABLE); @@ -547,7 +550,7 @@ void Curves::on_curveType_currentIndexChanged(int index) ui->yMin->setValue(-100); } -void Curves::addTemplate(QString name, unsigned int flags, curveFunction function) +void CurvesPanel::addTemplate(QString name, unsigned int flags, curveFunction function) { CurveCreatorTemplate tmpl; tmpl.name = name; @@ -557,7 +560,7 @@ void Curves::addTemplate(QString name, unsigned int flags, curveFunction functio ui->curveType->addItem(name); } -void Curves::on_curveApply_clicked() +void CurvesPanel::on_curveApply_clicked() { int index = ui->curveType->currentIndex(); int numpoints = model->curves[currentCurve].count; @@ -594,14 +597,14 @@ void Curves::on_curveApply_clicked() emit modified(); } -void Curves::onPointSizeEdited() +void CurvesPanel::onPointSizeEdited() { if (!lock) { update(); } } -void Curves::onNodeDelete() +void CurvesPanel::onNodeDelete() { int index = sender()->property("index").toInt(); int numpoints = model->curves[currentCurve].count; @@ -619,7 +622,7 @@ void Curves::onNodeDelete() } } -void Curves::onSceneNewPoint(int x, int y) +void CurvesPanel::onSceneNewPoint(int x, int y) { if ((model->curves[currentCurve].type == CurveData::CURVE_TYPE_CUSTOM) && (model->curves[currentCurve].count < CPN_MAX_POINTS)) { int newidx = 0; @@ -650,7 +653,7 @@ void Curves::onSceneNewPoint(int x, int y) } } -void Curves::onCustomContextMenuRequested(QPoint pos) +void CurvesPanel::onCustomContextMenuRequested(QPoint pos) { QPushButton *button = (QPushButton *)sender(); selectedIndex = button->property("index").toInt(); @@ -672,7 +675,7 @@ void Curves::onCustomContextMenuRequested(QPoint pos) contextMenu.exec(globalPos); } -bool Curves::hasClipboardData(QByteArray * data) const +bool CurvesPanel::hasClipboardData(QByteArray * data) const { const QClipboard * clipboard = QApplication::clipboard(); const QMimeData * mimeData = clipboard->mimeData(); @@ -684,22 +687,22 @@ bool Curves::hasClipboardData(QByteArray * data) const return false; } -bool Curves::insertAllowed() const +bool CurvesPanel::insertAllowed() const { return ((selectedIndex < maxCurves - 1) && (model->curves[maxCurves - 1].isEmpty())); } -bool Curves::moveDownAllowed() const +bool CurvesPanel::moveDownAllowed() const { return selectedIndex < maxCurves - 1; } -bool Curves::moveUpAllowed() const +bool CurvesPanel::moveUpAllowed() const { return selectedIndex > 0; } -void Curves::cmClear(bool prompt) +void CurvesPanel::cmClear(bool prompt) { if (prompt) { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) @@ -709,10 +712,11 @@ void Curves::cmClear(bool prompt) model->curves[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); update(); + emit updateDataModels(); emit modified(); } -void Curves::cmClearAll() +void CurvesPanel::cmClearAll() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Curves. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -722,10 +726,11 @@ void Curves::cmClearAll() model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_CLEAR, i); } update(); + emit updateDataModels(); emit modified(); } -void Curves::cmCopy() +void CurvesPanel::cmCopy() { QByteArray data; data.append((char*)&model->curves[selectedIndex], sizeof(CurveData)); @@ -734,7 +739,7 @@ void Curves::cmCopy() QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard); } -void Curves::cmCut() +void CurvesPanel::cmCut() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -742,7 +747,7 @@ void Curves::cmCut() cmClear(false); } -void Curves::cmDelete() +void CurvesPanel::cmDelete() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Curve. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; @@ -751,40 +756,43 @@ void Curves::cmDelete() model->curves[maxCurves - 1].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); update(); + emit updateDataModels(); emit modified(); } -void Curves::cmInsert() +void CurvesPanel::cmInsert() { memmove(&model->curves[selectedIndex + 1], &model->curves[selectedIndex], (CPN_MAX_CURVES - (selectedIndex + 1)) * sizeof(CurveData)); model->curves[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); update(); + emit updateDataModels(); emit modified(); } -void Curves::cmMoveDown() +void CurvesPanel::cmMoveDown() { swapData(selectedIndex, selectedIndex + 1); } -void Curves::cmMoveUp() +void CurvesPanel::cmMoveUp() { swapData(selectedIndex, selectedIndex - 1); } -void Curves::cmPaste() +void CurvesPanel::cmPaste() { QByteArray data; if (hasClipboardData(&data)) { CurveData *cd = &model->curves[selectedIndex]; memcpy(cd, data.constData(), sizeof(CurveData)); update(); + emit updateDataModels(); emit modified(); } } -void Curves::swapData(int idx1, int idx2) +void CurvesPanel::swapData(int idx1, int idx2) { if ((idx1 != idx2) && (!model->curves[idx1].isEmpty() || !model->curves[idx2].isEmpty())) { CurveData cdtmp = model->curves[idx2]; @@ -794,6 +802,7 @@ void Curves::swapData(int idx1, int idx2) memcpy(cd1, &cdtmp, sizeof(CurveData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_CURVE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); update(); + emit updateDataModels(); emit modified(); } } diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h index 34d1a675e..2e08dbbd4 100644 --- a/companion/src/modeledit/curves.h +++ b/companion/src/modeledit/curves.h @@ -54,13 +54,13 @@ class CustomScene : public QGraphicsScene virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event) override; }; -class Curves : public ModelPanel +class CurvesPanel : public ModelPanel { Q_OBJECT public: - Curves(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); - virtual ~Curves(); + CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + virtual ~CurvesPanel(); virtual void update(); @@ -91,6 +91,9 @@ class Curves : public ModelPanel void cmMoveDown(); void cmMoveUp(); + signals: + void updateDataModels(); + protected: virtual void resizeEvent(QResizeEvent *event); void addTemplate(QString name, unsigned int flags, curveFunction function); diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 36dba9c97..ddbf724f0 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -41,7 +41,7 @@ RepeatComboBox::RepeatComboBox(QWidget *parent, int & repeatParam): addItem(tr("No repeat"), 0); - for (unsigned int i=step; i<=60; i+=step) { + for (unsigned int i = step; i <= 60; i += step) { addItem(tr("%1s").arg(i), i); } @@ -66,24 +66,36 @@ void RepeatComboBox::update() setCurrentIndex(value); } -CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware): +CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel): GenericPanel(parent, model, generalSettings, firmware), functions(model ? model->customFn : generalSettings.customFn), mediaPlayerCurrent(-1), - mediaPlayer(nullptr) + mediaPlayer(nullptr), + modelsUpdateCnt(0) { - Stopwatch s1("CustomFunctionsPanel - populate"); lock = true; fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions); - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, model, model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this); - rawSrcAllItemModel = new RawSourceFilterItemModel(&generalSettings, model, this); - rawSrcInputsItemModel = new RawSourceFilterItemModel(rawSrcAllItemModel->sourceModel(), RawSource::InputSourceGroups, this); - rawSrcGVarsItemModel = new RawSourceFilterItemModel(rawSrcAllItemModel->sourceModel(), RawSource::GVarsGroup, this); + rawSwitchModel = new RawItemFilteredModel(rawSwitchItemModel, model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext); + connect(rawSwitchModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); + connect(rawSwitchModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + + rawSrcAllModel = new RawItemFilteredModel(rawSourceItemModel); + connect(rawSrcAllModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); + connect(rawSrcAllModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + + rawSrcInputsModel = new RawItemFilteredModel(rawSourceItemModel, RawSource::InputSourceGroups); + connect(rawSrcInputsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); + connect(rawSrcInputsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + + rawSrcGVarsModel = new RawItemFilteredModel(rawSourceItemModel, RawSource::GVarsGroup); + connect(rawSrcGVarsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); + connect(rawSrcGVarsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); if (!firmware->getCapability(VoicesAsNumbers)) { tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength)); - for (int i=0; igetBoard())) { scriptsSet = getFilesSet(g.profile[g.id()].sdPath() + "/SCRIPTS/FUNCTIONS", QStringList() << "*.lua", firmware->getCapability(VoicesMaxLength)); - for (int i=0; isetContextMenuPolicy(Qt::CustomContextMenu); @@ -123,9 +132,9 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, label->setMouseTracking(true); label->setProperty("index", i); if (model) - label->setText(tr("SF%1").arg(i+1)); + label->setText(tr("SF%1").arg(i + 1)); else - label->setText(tr("GF%1").arg(i+1)); + label->setText(tr("GF%1").arg(i + 1)); label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenuRequested(QPoint))); tableLayout->addWidget(i, 0, label); @@ -133,7 +142,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, // The switch fswtchSwtch[i] = new QComboBox(this); - fswtchSwtch[i]->setModel(rawSwitchItemModel); + fswtchSwtch[i]->setModel(rawSwitchModel); fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue())); fswtchSwtch[i]->setProperty("index", i); fswtchSwtch[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum); @@ -198,7 +207,6 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, fswtchParamArmT[i]->setEditable(true); fswtchParamArmT[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents); paramLayout->addWidget(fswtchParamArmT[i]); - connect(fswtchParamArmT[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited())); connect(fswtchParamArmT[i], SIGNAL(editTextChanged ( const QString)), this, SLOT(customFunctionEdited())); @@ -221,46 +229,34 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, QHBoxLayout * repeatLayout = new QHBoxLayout(); tableLayout->addLayout(i, 4, repeatLayout); fswtchRepeat[i] = new RepeatComboBox(this, functions[i].repeatParam); - repeatLayout->addWidget(fswtchRepeat[i], i+1); - connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onChildModified())); + repeatLayout->addWidget(fswtchRepeat[i], i + 1); + connect(fswtchRepeat[i], SIGNAL(modified()), this, SLOT(onRepeatModified())); fswtchEnable[i] = new QCheckBox(this); fswtchEnable[i]->setProperty("index", i); fswtchEnable[i]->setText(tr("ON")); fswtchEnable[i]->setFixedWidth(200); - repeatLayout->addWidget(fswtchEnable[i], i+1); + repeatLayout->addWidget(fswtchEnable[i], i + 1); connect(fswtchEnable[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited())); } - s1.report("add items"); - disableMouseScrolling(); - s1.report("disableMouseScrolling"); - - lock = false; + tableLayout->resizeColumnsToContents(); + tableLayout->setColumnWidth(3, 300); + tableLayout->pushRowsUp(fswCapability + 1); update(); - s1.report("update"); - tableLayout->resizeColumnsToContents(); - s1.report("resizeColumnsToContents"); - tableLayout->setColumnWidth(3, 300); - tableLayout->pushRowsUp(fswCapability+1); - s1.report("end"); + lock = false; } CustomFunctionsPanel::~CustomFunctionsPanel() { if (mediaPlayer) stopSound(mediaPlayerCurrent); -} - -void CustomFunctionsPanel::updateDataModels() -{ - const bool oldLock = lock; - lock = true; - rawSwitchItemModel->update(); - rawSrcAllItemModel->update(); - lock = oldLock; + delete rawSwitchModel; + delete rawSrcAllModel; + delete rawSrcInputsModel; + delete rawSrcGVarsModel; } void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state) @@ -343,6 +339,7 @@ void CustomFunctionsPanel::toggleSound(bool play) #define CUSTOM_FUNCTION_BL_COLOR (1<<9) #define CUSTOM_FUNCTION_SHOW_FUNC (1<<10) + void CustomFunctionsPanel::customFunctionEdited() { if (!lock) { @@ -369,162 +366,151 @@ void CustomFunctionsPanel::functionEdited() } } -void CustomFunctionsPanel::onChildModified() +void CustomFunctionsPanel::onRepeatModified() { emit modified(); } void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) { - CustomFunctionData & cfn = functions[i]; - AssignFunc func = (AssignFunc)fswtchFunc[i]->currentData().toInt(); + CustomFunctionData & cfn = functions[i]; + AssignFunc func = (AssignFunc)fswtchFunc[i]->currentData().toInt(); - unsigned int widgetsMask = 0; - if (modified) { - cfn.swtch = RawSwitch(fswtchSwtch[i]->currentData().toInt()); - cfn.func = func; - cfn.enabled = fswtchEnable[i]->isChecked(); - } + unsigned int widgetsMask = 0; + if (modified) { + cfn.swtch = RawSwitch(fswtchSwtch[i]->currentData().toInt()); + cfn.func = func; + cfn.enabled = fswtchEnable[i]->isChecked(); + } - if (!cfn.isEmpty()) { - widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC; + if (!cfn.isEmpty()) { + widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC; - if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) { - if (model) { - int channelsMax = model->getChannelsMax(true); - fswtchParam[i]->setDecimals(0); - fswtchParam[i]->setSingleStep(1); - fswtchParam[i]->setMinimum(-channelsMax); - fswtchParam[i]->setMaximum(channelsMax); - if (modified) { - cfn.param = fswtchParam[i]->value(); - } - fswtchParam[i]->setValue(cfn.param); - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_ENABLE; + if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) { + if (model) { + int channelsMax = model->getChannelsMax(true); + fswtchParam[i]->setDecimals(0); + fswtchParam[i]->setSingleStep(1); + fswtchParam[i]->setMinimum(-channelsMax); + fswtchParam[i]->setMaximum(channelsMax); + if (modified) { + cfn.param = fswtchParam[i]->value(); } + fswtchParam[i]->setValue(cfn.param); + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_ENABLE; } - else if (func == FuncLogs) { - fswtchParam[i]->setDecimals(1); - fswtchParam[i]->setMinimum(0); - fswtchParam[i]->setMaximum(25.5); - fswtchParam[i]->setSingleStep(0.1); + } + else if (func == FuncLogs) { + fswtchParam[i]->setDecimals(1); + fswtchParam[i]->setMinimum(0); + fswtchParam[i]->setMaximum(25.5); + fswtchParam[i]->setSingleStep(0.1); + if (modified) + cfn.param = fswtchParam[i]->value() * 10.0; + fswtchParam[i]->setValue(cfn.param / 10.0); + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; + } + else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) { + int gvidx = func - FuncAdjustGV1; + if (modified) + cfn.adjustMode = fswtchGVmode[i]->currentIndex(); + fswtchGVmode[i]->setCurrentIndex(cfn.adjustMode); + widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE; + if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { if (modified) - cfn.param = fswtchParam[i]->value()*10.0; - fswtchParam[i]->setValue(cfn.param/10.0); - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; - } - else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) { - int gvidx = func - FuncAdjustGV1; - if (modified) - cfn.adjustMode = fswtchGVmode[i]->currentIndex(); - fswtchGVmode[i]->setCurrentIndex(cfn.adjustMode); - widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE; - if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { - if (modified) - cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet(); - fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec); - fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet()); - fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString()); - if (cfn.adjustMode==FUNC_ADJUST_GVAR_INCDEC) { - double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin()); - rng *= model->gvarData[gvidx].multiplierGet(); - fswtchParam[i]->setMinimum(-rng); - fswtchParam[i]->setMaximum(rng); - } - else { - fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec()); - fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec()); - } - fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet()); - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; + cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet(); + fswtchParam[i]->setDecimals(model->gvarData[gvidx].prec); + fswtchParam[i]->setSingleStep(model->gvarData[gvidx].multiplierGet()); + fswtchParam[i]->setSuffix(model->gvarData[gvidx].unitToString()); + if (cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { + double rng = abs(model->gvarData[gvidx].getMax() - model->gvarData[gvidx].getMin()); + rng *= model->gvarData[gvidx].multiplierGet(); + fswtchParam[i]->setMinimum(-rng); + fswtchParam[i]->setMaximum(rng); } else { - if (modified) - cfn.param = fswtchParamT[i]->currentData().toInt(); - populateFuncParamCB(fswtchParamT[i], func, cfn.param, cfn.adjustMode); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; + fswtchParam[i]->setMinimum(model->gvarData[gvidx].getMinPrec()); + fswtchParam[i]->setMaximum(model->gvarData[gvidx].getMaxPrec()); } + fswtchParam[i]->setValue(cfn.param * model->gvarData[gvidx].multiplierGet()); + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; } - else if (func == FuncReset) { + else { + if (modified) + cfn.param = fswtchParamT[i]->currentData().toInt(); + populateFuncParamCB(fswtchParamT[i], func, cfn.param, cfn.adjustMode); + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; + } + } + else if (func == FuncReset) { + if (modified) + cfn.param = fswtchParamT[i]->currentData().toInt(); + populateFuncParamCB(fswtchParamT[i], func, cfn.param); + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; + } + else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) { + if (modified) + cfn.param = fswtchParamTime[i]->timeInSeconds(); + RawSourceRange range = RawSource(SOURCE_TYPE_SPECIAL, func - FuncSetTimer1 + 2).getRange(model, generalSettings); + fswtchParamTime[i]->setTimeRange((int)range.min, (int)range.max); + fswtchParamTime[i]->setTime(cfn.param); + widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE; + } + else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) { + widgetsMask |= CUSTOM_FUNCTION_ENABLE; + } + else if (func == FuncVolume || func == FuncBacklight) { + if (modified) + cfn.param = fswtchParamT[i]->currentData().toInt(); + populateFuncParamCB(fswtchParamT[i], func, cfn.param); + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; + } + else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) { + if (func != FuncBackgroundMusic) { + widgetsMask |= CUSTOM_FUNCTION_REPEAT; + fswtchRepeat[i]->update(); + } + if (func == FuncPlayValue) { if (modified) cfn.param = fswtchParamT[i]->currentData().toInt(); populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_REPEAT; } - else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) { - if (modified) - cfn.param = fswtchParamTime[i]->timeInSeconds(); - RawSourceRange range = RawSource(SOURCE_TYPE_SPECIAL, func - FuncSetTimer1 + 2).getRange(model, generalSettings); - fswtchParamTime[i]->setTimeRange((int)range.min, (int)range.max); - fswtchParamTime[i]->setTime(cfn.param); - widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE; - } - else if (func >= FuncSetFailsafeInternalModule && func <= FuncBindExternalModule) { - widgetsMask |= CUSTOM_FUNCTION_ENABLE; - } - else if (func == FuncVolume || func == FuncBacklight) { - if (modified) - cfn.param = fswtchParamT[i]->currentData().toInt(); - populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; - } - else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic) { - if (func != FuncBackgroundMusic) { - widgetsMask |= CUSTOM_FUNCTION_REPEAT; - fswtchRepeat[i]->update(); - } - if (func == FuncPlayValue) { - if (modified) - cfn.param = fswtchParamT[i]->currentData().toInt(); - populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_REPEAT; - } - else if (func == FuncPlayPrompt || func == FuncPlayBoth) { - if (firmware->getCapability(VoicesAsNumbers)) { - fswtchParam[i]->setDecimals(0); - fswtchParam[i]->setSingleStep(1); - fswtchParam[i]->setMinimum(0); - if (func == FuncPlayPrompt) { - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT | CUSTOM_FUNCTION_GV_TOOGLE; - } - else { - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT; - fswtchParamGV[i]->setChecked(false); - } - fswtchParam[i]->setMaximum(func == FuncPlayBoth ? 254 : 255); - if (modified) { - if (fswtchParamGV[i]->isChecked()) { - fswtchParam[i]->setMinimum(1); - cfn.param = std::min(fswtchParam[i]->value(),5.0)+(fswtchParamGV[i]->isChecked() ? 250 : 0); - } - else { - cfn.param = fswtchParam[i]->value(); - } - } - if (cfn.param>250 && (func!=FuncPlayBoth)) { - fswtchParamGV[i]->setChecked(true); - fswtchParam[i]->setValue(cfn.param-250); - fswtchParam[i]->setMaximum(5); - } - else { - fswtchParamGV[i]->setChecked(false); - fswtchParam[i]->setValue(cfn.param); - } - if (cfn.param < 251) - widgetsMask |= CUSTOM_FUNCTION_PLAY; + else if (func == FuncPlayPrompt || func == FuncPlayBoth) { + if (firmware->getCapability(VoicesAsNumbers)) { + fswtchParam[i]->setDecimals(0); + fswtchParam[i]->setSingleStep(1); + fswtchParam[i]->setMinimum(0); + if (func == FuncPlayPrompt) { + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT | CUSTOM_FUNCTION_GV_TOOGLE; } else { - widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM; - if (modified) { - Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength)); + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT; + fswtchParamGV[i]->setChecked(false); + } + fswtchParam[i]->setMaximum(func == FuncPlayBoth ? 254 : 255); + if (modified) { + if (fswtchParamGV[i]->isChecked()) { + fswtchParam[i]->setMinimum(1); + cfn.param = std::min(fswtchParam[i]->value(),5.0)+(fswtchParamGV[i]->isChecked() ? 250 : 0); } - Helpers::populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm); - if (fswtchParamArmT[i]->currentText() != "----") { - widgetsMask |= CUSTOM_FUNCTION_PLAY; + else { + cfn.param = fswtchParam[i]->value(); } } + if (cfn.param > 250 && (func != FuncPlayBoth)) { + fswtchParamGV[i]->setChecked(true); + fswtchParam[i]->setValue(cfn.param - 250); + fswtchParam[i]->setMaximum(5); + } + else { + fswtchParamGV[i]->setChecked(false); + fswtchParam[i]->setValue(cfn.param); + } + if (cfn.param < 251) + widgetsMask |= CUSTOM_FUNCTION_PLAY; } - else if (func == FuncBackgroundMusic) { + else { widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM; if (modified) { Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength)); @@ -534,58 +520,68 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) widgetsMask |= CUSTOM_FUNCTION_PLAY; } } - else if (func == FuncPlaySound) { - if (modified) - cfn.param = (uint8_t)fswtchParamT[i]->currentIndex(); - populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; - } - else if (func == FuncPlayHaptic) { - if (modified) - cfn.param = (uint8_t)fswtchParamT[i]->currentIndex(); - populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; - } } - else if (func == FuncPlayScript) { + else if (func == FuncBackgroundMusic) { widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM; if (modified) { - Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8); + Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, firmware->getCapability(VoicesMaxLength)); + } + Helpers::populateFileComboBox(fswtchParamArmT[i], tracksSet, cfn.paramarm); + if (fswtchParamArmT[i]->currentText() != "----") { + widgetsMask |= CUSTOM_FUNCTION_PLAY; } - Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm); } - else { + else if (func == FuncPlaySound) { if (modified) - cfn.param = fswtchParam[i]->value(); - fswtchParam[i]->setDecimals(0); - fswtchParam[i]->setSingleStep(1); - fswtchParam[i]->setValue(cfn.param); - if (func <= FuncInstantTrim) { - widgetsMask |= CUSTOM_FUNCTION_ENABLE; - } + cfn.param = (uint8_t)fswtchParamT[i]->currentIndex(); + populateFuncParamCB(fswtchParamT[i], func, cfn.param); + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; + } + else if (func == FuncPlayHaptic) { + if (modified) + cfn.param = (uint8_t)fswtchParamT[i]->currentIndex(); + populateFuncParamCB(fswtchParamT[i], func, cfn.param); + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; } } + else if (func == FuncPlayScript) { + widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM; + if (modified) { + Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8); + } + Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm); + } + else { + if (modified) + cfn.param = fswtchParam[i]->value(); + fswtchParam[i]->setDecimals(0); + fswtchParam[i]->setSingleStep(1); + fswtchParam[i]->setValue(cfn.param); + if (func <= FuncInstantTrim) { + widgetsMask |= CUSTOM_FUNCTION_ENABLE; + } + } + } - fswtchFunc[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SHOW_FUNC); - fswtchParam[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_NUMERIC_PARAM); - fswtchParamTime[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_TIME_PARAM); - fswtchParamGV[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_TOOGLE); - fswtchParamT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SOURCE_PARAM); - fswtchParamArmT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_FILE_PARAM); - fswtchEnable[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_ENABLE); - if (widgetsMask & CUSTOM_FUNCTION_ENABLE) - fswtchEnable[i]->setChecked(cfn.enabled); - else - fswtchEnable[i]->setChecked(false); - fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT); - fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE); - fswtchBLcolor[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_BL_COLOR); - playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY); + fswtchFunc[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SHOW_FUNC); + fswtchParam[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_NUMERIC_PARAM); + fswtchParamTime[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_TIME_PARAM); + fswtchParamGV[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_TOOGLE); + fswtchParamT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SOURCE_PARAM); + fswtchParamArmT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_FILE_PARAM); + fswtchEnable[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_ENABLE); + if (widgetsMask & CUSTOM_FUNCTION_ENABLE) + fswtchEnable[i]->setChecked(cfn.enabled); + else + fswtchEnable[i]->setChecked(false); + fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT); + fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE); + fswtchBLcolor[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_BL_COLOR); + playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY); } void CustomFunctionsPanel::update() { - updateDataModels(); lock = true; for (int i = 0; i < fswCapability; i++) { refreshCustomFunction(i); @@ -660,16 +656,16 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value) { b->clear(); for (unsigned int i = 0; i < FuncCount; i++) { - if (((i>=FuncOverrideCH1 && i<=FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) || - ((i==FuncVolume || i==FuncBackgroundMusic || i==FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) || - ((i==FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) || - ((i==FuncPlayHaptic) && !firmware->getCapability(Haptic)) || - ((i==FuncPlayBoth) && !firmware->getCapability(HasBeeper)) || - ((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) || - ((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) || - ((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) || - ((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) || - ((i>=FuncAdjustGV1 && i<=FuncAdjustGVLast) && (!model || !firmware->getCapability(Gvars))) + if (((i >= FuncOverrideCH1 && i <= FuncOverrideCH32) && (!model || !firmware->getCapability(SafetyChannelCustomFunction))) || + ((i == FuncVolume || i == FuncBackgroundMusic || i == FuncBackgroundMusicPause) && !firmware->getCapability(HasVolume)) || + ((i == FuncPlayScript && !IS_HORUS_OR_TARANIS(firmware->getBoard()))) || + ((i == FuncPlayHaptic) && !firmware->getCapability(Haptic)) || + ((i == FuncPlayBoth) && !firmware->getCapability(HasBeeper)) || + ((i == FuncLogs) && !firmware->getCapability(HasSDLogs)) || + ((i == FuncSetTimer3) && firmware->getCapability(Timers) < 3) || + ((i == FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) || + ((i >= FuncRangeCheckInternalModule && i <= FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) || + ((i >= FuncAdjustGV1 && i <= FuncAdjustGVLast) && (!model || !firmware->getCapability(Gvars))) ) { // skipped continue; @@ -711,21 +707,21 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi CustomFunctionData::populateResetParams(model, b, value); } else if (function == FuncVolume || function == FuncBacklight) { - b->setModel(rawSrcInputsItemModel); + b->setModel(rawSrcInputsModel); b->setCurrentIndex(b->findData(value)); } else if (function == FuncPlayValue) { - b->setModel(rawSrcAllItemModel); + b->setModel(rawSrcAllModel); b->setCurrentIndex(b->findData(value)); } else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) { switch (adjustmode) { case 1: - b->setModel(rawSrcInputsItemModel); + b->setModel(rawSrcInputsModel); b->setCurrentIndex(b->findData(value)); break; case 2: - b->setModel(rawSrcGVarsItemModel); + b->setModel(rawSrcGVarsModel); b->setCurrentIndex(b->findData(value)); break; } @@ -830,3 +826,21 @@ bool CustomFunctionsPanel::moveUpAllowed() const { return selectedIndex > 0; } + +void CustomFunctionsPanel::onModelDataAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void CustomFunctionsPanel::onModelDataUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) + lock = true; + for (int i = 0; i < fswCapability; i++) { + fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(functions[i].swtch.toValue())); + fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(functions[i].func)); + } + update(); +} diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h index 54a83ddcf..98b173ee5 100644 --- a/companion/src/modeledit/customfunctions.h +++ b/companion/src/modeledit/customfunctions.h @@ -26,8 +26,9 @@ #include -class RawSourceFilterItemModel; -class RawSwitchFilterItemModel; +class RawSourceItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; class TimerEdit; constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function"; @@ -55,7 +56,8 @@ class CustomFunctionsPanel : public GenericPanel Q_OBJECT public: - CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware); + CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel); ~CustomFunctionsPanel(); virtual void update(); @@ -64,12 +66,11 @@ class CustomFunctionsPanel : public GenericPanel CustomFunctionData * functions; private slots: - void updateDataModels(); void customFunctionEdited(); void functionEdited(); void onCustomContextMenuRequested(QPoint pos); void refreshCustomFunction(int index, bool modified=false); - void onChildModified(); + void onRepeatModified(); bool playSound(int index); void stopSound(int index); void toggleSound(bool play); @@ -84,6 +85,8 @@ class CustomFunctionsPanel : public GenericPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); private: void populateFuncCB(QComboBox *b, unsigned int value); @@ -95,10 +98,10 @@ class CustomFunctionsPanel : public GenericPanel bool moveUpAllowed() const; void swapData(int idx1, int idx2); void resetCBsAndRefresh(int idx); - RawSwitchFilterItemModel * rawSwitchItemModel; - RawSourceFilterItemModel * rawSrcAllItemModel; - RawSourceFilterItemModel * rawSrcInputsItemModel; - RawSourceFilterItemModel * rawSrcGVarsItemModel; + RawItemFilteredModel * rawSwitchModel; + RawItemFilteredModel * rawSrcAllModel; + RawItemFilteredModel * rawSrcInputsModel; + RawItemFilteredModel * rawSrcGVarsModel; QSet tracksSet; QSet scriptsSet; @@ -119,7 +122,7 @@ class CustomFunctionsPanel : public GenericPanel int selectedIndex; int fswCapability; - + int modelsUpdateCnt; }; #endif // _CUSTOMFUNCTIONS_H_ diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index 95aaeca66..1df0ffaf0 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -24,7 +24,8 @@ #include "helpers.h" ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName) : + Firmware * firmware, QString & inputName, RawSourceItemModel * rawSourceItemModel, + RawSwitchItemModel * rawSwitchItemModel) : QDialog(parent), ui(new Ui::ExpoDialog), model(model), @@ -36,6 +37,9 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G lock(false) { ui->setupUi(this); + rawSourceModel = new RawItemFilteredModel(rawSourceItemModel, (RawSource::InputSourceGroups & ~RawSource::InputsGroup) | RawSource::TelemGroup, this); + rawSwitchModel = new RawItemFilteredModel(rawSwitchItemModel, RawSwitch::MixesContext, this); + QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0,ui->lb_FP1,ui->lb_FP2,ui->lb_FP3,ui->lb_FP4,ui->lb_FP5,ui->lb_FP6,ui->lb_FP7,ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0,ui->cb_FP1,ui->cb_FP2,ui->cb_FP3,ui->cb_FP4,ui->cb_FP5,ui->cb_FP6,ui->cb_FP7,ui->cb_FP8 }; for (int i=0; icurveTypeCB, ui->curveGVarCB, ui->curveValueCB, ui->curveValueSB, ed->curve, model, firmware->getCapability(HasInputDiff) ? 0 : (HIDE_DIFF | HIDE_NEGATIVE_CURVES)); - ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this)); + ui->switchesCB->setModel(rawSwitchModel); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->sideCB->setCurrentIndex(ed->mode-1); @@ -83,7 +87,7 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G if (firmware->getCapability(VirtualInputs)) { ui->inputName->setMaxLength(firmware->getCapability(InputsLength)); - ui->sourceCB->setModel(new RawSourceFilterItemModel(&generalSettings, &model, (RawSource::InputSourceGroups & ~RawSource::InputsGroup) | RawSource::TelemGroup, this)); + ui->sourceCB->setModel(rawSourceModel); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue())); ui->sourceCB->removeItem(0); ui->inputName->setValidator(new QRegExpValidator(rx, this)); diff --git a/companion/src/modeledit/expodialog.h b/companion/src/modeledit/expodialog.h index e1355e147..1a3cc26af 100644 --- a/companion/src/modeledit/expodialog.h +++ b/companion/src/modeledit/expodialog.h @@ -27,6 +27,9 @@ class GVarGroup; class CurveGroup; +class RawSourceItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; namespace Ui { class ExpoDialog; @@ -36,7 +39,8 @@ class ExpoDialog : public QDialog { Q_OBJECT public: ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName); + Firmware * firmware, QString & inputName, RawSourceItemModel * rawSourceItemModel, + RawSwitchItemModel * rawSwitchItemModel); ~ExpoDialog(); protected: @@ -63,6 +67,8 @@ class ExpoDialog : public QDialog { ModelPrinter modelPrinter; bool lock; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + RawItemFilteredModel * rawSourceModel; + RawItemFilteredModel * rawSwitchModel; }; #endif // _EXPODIALOG_H_ diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 12082091d..92d69e5e7 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -24,14 +24,15 @@ #include "helpers.h" #include "customdebug.h" -FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchFilterItemModel * switchModel): +FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * switchModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::FlightMode), phaseIdx(phaseIdx), - phase(model.flightModeData[phaseIdx]), - rawSwitchItemModel(NULL) + phase(model.flightModeData[phaseIdx]) { ui->setupUi(this); + connect(switchModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &FlightModePanel::onModelDataAboutToBeUpdated); + connect(switchModel, &RawItemFilteredModel::dataUpdateComplete, this, &FlightModePanel::onModelDataUpdateComplete); ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu); ui->labelName->setToolTip(tr("Popup menu available")); @@ -316,8 +317,6 @@ void FlightModePanel::update() for (int i = 0; i < reCount; i++) { updateRotaryEncoder(i); } - - emit nameModified(); } void FlightModePanel::updateGVar(int index) @@ -390,8 +389,8 @@ void FlightModePanel::phaseName_editingFinished() { QLineEdit *lineEdit = qobject_cast(sender()); strcpy(phase.name, lineEdit->text().toLatin1()); + emit phaseNameChanged(); emit modified(); - emit nameModified(); } void FlightModePanel::phaseSwitchChanged(int index) @@ -401,6 +400,8 @@ void FlightModePanel::phaseSwitchChanged(int index) const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok)); if (ok && phase.swtch.toValue() != rs.toValue()) { phase.swtch = rs; + if (!rs.isSet()) + emit phaseNoSwitchSet(); emit modified(); } } @@ -457,7 +458,7 @@ void FlightModePanel::phaseGVValue_editingFinished() QDoubleSpinBox *spinBox = qobject_cast(sender()); int gvar = spinBox->property("index").toInt(); phase.gvars[gvar] = spinBox->value() * model->gvarData[gvar].multiplierSet(); - emit datachanged(); + updateGVar(gvar); emit modified(); } } @@ -469,7 +470,7 @@ void FlightModePanel::GVName_editingFinished() int gvar = lineedit->property("index").toInt(); memset(&model->gvarData[gvar].name, 0, sizeof(model->gvarData[gvar].name)); strcpy(model->gvarData[gvar].name, lineedit->text().toLatin1()); - emit datachanged(); + emit gvNameChanged(); emit modified(); } } @@ -488,7 +489,7 @@ void FlightModePanel::phaseGVUse_currentIndexChanged(int index) } if (model->isGVarLinkedCircular(phaseIdx, gvar)) QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. Flight Mode 0 value used.")); - emit datachanged(); + updateGVar(gvar); emit modified(); lock = false; } @@ -500,7 +501,7 @@ void FlightModePanel::phaseGVUnit_currentIndexChanged(int index) QComboBox *comboBox = qobject_cast(sender()); int gvar = comboBox->property("index").toInt(); model->gvarData[gvar].unit = index; - emit datachanged(); + updateGVar(gvar); emit modified(); } } @@ -511,7 +512,7 @@ void FlightModePanel::phaseGVPrec_currentIndexChanged(int index) QComboBox *comboBox = qobject_cast(sender()); int gvar = comboBox->property("index").toInt(); model->gvarData[gvar].prec = index; - emit datachanged(); + updateGVar(gvar); emit modified(); } } @@ -534,7 +535,7 @@ void FlightModePanel::phaseGVMin_editingFinished() } } } - emit datachanged(); + updateGVar(gvar); emit modified(); } } @@ -557,7 +558,7 @@ void FlightModePanel::phaseGVMax_editingFinished() } } } - emit datachanged(); + updateGVar(gvar); emit modified(); } } @@ -741,7 +742,8 @@ void FlightModePanel::cmClear(bool prompt) model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, phaseIdx); - emit datachanged(); + update(); + emit phaseDataChanged(); emit modified(); } @@ -767,7 +769,7 @@ void FlightModePanel::cmClearAll() model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i); } - emit datachanged(); + emit phaseDataChanged(); emit modified(); } @@ -846,7 +848,7 @@ void FlightModePanel::cmDelete() model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, -1); - emit datachanged(); + emit phaseDataChanged(); emit modified(); } @@ -897,7 +899,7 @@ void FlightModePanel::cmInsert() model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, 1); - emit datachanged(); + emit phaseDataChanged(); emit modified(); } @@ -946,7 +948,7 @@ void FlightModePanel::cmPaste() } } - emit datachanged(); + emit phaseDataChanged(); emit modified(); } } @@ -1035,7 +1037,7 @@ void FlightModePanel::swapData(int idx1, int idx2) } model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - emit datachanged(); + emit phaseDataChanged(); emit modified(); } @@ -1162,7 +1164,8 @@ void FlightModePanel::gvCmClear(bool prompt) } phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx); } - emit datachanged(); + updateGVar(gvIdx); + emit gvNameChanged(); emit modified(); } @@ -1186,7 +1189,10 @@ void FlightModePanel::gvCmClearAll() phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx); } } - emit datachanged(); + for (int i = 0; i < gvCount; i++) { + updateGVar(i); + } + emit gvNameChanged(); emit modified(); } @@ -1261,8 +1267,13 @@ void FlightModePanel::gvCmDelete() for (int j = 0; j < fmCount; j++) { model->flightModeData[j].gvars[maxidx] = model->flightModeData[j].linkedGVarFlightModeZero(j); } + model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, -1); - emit datachanged(); + + for (int i = 0; i < gvCount; i++) { + updateGVar(i); + } + emit gvNameChanged(); emit modified(); } @@ -1279,7 +1290,10 @@ void FlightModePanel::gvCmInsert() model->flightModeData[j].gvars[gvIdx] = model->flightModeData[j].linkedGVarFlightModeZero(j); } model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, 1); - emit datachanged(); + for (int i = 0; i < gvCount; i++) { + updateGVar(i); + } + emit gvNameChanged(); emit modified(); } @@ -1322,7 +1336,8 @@ void FlightModePanel::gvCmPaste() else phase.gvars[gvIdx] = val; } - emit datachanged(); + updateGVar(gvIdx); + emit gvNameChanged(); emit modified(); } @@ -1340,37 +1355,57 @@ void FlightModePanel::gvSwapData(int idx1, int idx2) model->flightModeData[j].gvars[idx1] = valtmp; } model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - emit datachanged(); + updateGVar(idx1); + updateGVar(idx2); + emit gvNameChanged(); emit modified(); } } +void FlightModePanel::onModelDataAboutToBeUpdated() +{ + lock = true; +} + +void FlightModePanel::onModelDataUpdateComplete() +{ + update(); + lock = false; +} + /**********************************************************/ -FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): - ModelPanel(parent, model, generalSettings, firmware), - modesCount(firmware->getCapability(FlightModes)) +FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchItemModel * rawSwitchItemModel): + ModelPanel(parent, model, generalSettings, firmware) { - - RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this); - connect(this, &FlightModesPanel::updated, swModel, &RawSwitchFilterItemModel::update); + rawSwitchFilteredModel = new RawItemFilteredModel(rawSwitchItemModel, RawSwitch::MixesContext, this); + modesCount = firmware->getCapability(FlightModes); QGridLayout * gridLayout = new QGridLayout(this); tabWidget = new QTabWidget(this); for (int i = 0; i < modesCount; i++) { - FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, swModel); + FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel); tab->setProperty("index", i); - connect(tab, &FlightModePanel::datachanged, this, &FlightModesPanel::update); - connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified); - connect(tab, &FlightModePanel::nameModified, this, &FlightModesPanel::onPhaseNameChanged); - connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update); + connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified); + connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::onPhaseNameChanged); + connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::update); + connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::refreshDataModels); + connect(tab, &FlightModePanel::phaseNameChanged, this, &FlightModesPanel::onPhaseNameChanged); + connect(tab, &FlightModePanel::phaseNoSwitchSet, this, &FlightModesPanel::refreshDataModels); + connect(tab, &FlightModePanel::gvNameChanged, this, &FlightModesPanel::refreshDataModels); + + connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update); tabWidget->addTab(tab, getTabName(i)); + panels << tab; } + connect(tabWidget, &QTabWidget::currentChanged, this, &FlightModesPanel::onTabIndexChanged); gridLayout->addWidget(tabWidget, 0, 0, 1, 1); + onTabIndexChanged(0); } FlightModesPanel::~FlightModesPanel() { + delete rawSwitchFilteredModel; } QString FlightModesPanel::getTabName(int index) @@ -1397,3 +1432,14 @@ void FlightModesPanel::update() { emit updated(); } + +void FlightModesPanel::refreshDataModels() +{ + emit updateDataModels(); +} + +void FlightModesPanel::onTabIndexChanged(int index) +{ + if (index < panels.size()) + panels.at(index)->update(); +} diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h index 61e25c59a..2579538fc 100644 --- a/companion/src/modeledit/flightmodes.h +++ b/companion/src/modeledit/flightmodes.h @@ -24,7 +24,8 @@ #include "modeledit.h" #include "eeprominterface.h" -class RawSwitchFilterItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; @@ -40,14 +41,16 @@ class FlightModePanel : public ModelPanel Q_OBJECT public: - FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchFilterItemModel * switchModel); + FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * switchModel); virtual ~FlightModePanel(); virtual void update(); signals: - void nameModified(); - void datachanged(); + void gvNameChanged(); + void phaseDataChanged(); + void phaseNameChanged(); + void phaseNoSwitchSet(); private slots: void phaseName_editingFinished(); @@ -87,6 +90,8 @@ class FlightModePanel : public ModelPanel void gvCmPaste(); void gvCmMoveDown(); void gvCmMoveUp(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); private: Ui::FlightMode *ui; @@ -111,7 +116,6 @@ class FlightModePanel : public ModelPanel QVector trimsUse; QVector trimsValue; QVector trimsSlider; - RawSwitchFilterItemModel * rawSwitchItemModel; Board::Type board; void trimUpdate(unsigned int trim); @@ -141,24 +145,28 @@ class FlightModesPanel : public ModelPanel Q_OBJECT public: - FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchItemModel * rawSwitchItemModel); virtual ~FlightModesPanel(); public slots: virtual void update() override; signals: + void updateDataModels(); void updated(); private slots: void onPhaseNameChanged(); + void refreshDataModels(); + void onTabIndexChanged(int index); private: QString getTabName(int index); int modesCount; QTabWidget *tabWidget; - + RawItemFilteredModel *rawSwitchFilteredModel; + QVector panels; }; #endif // _FLIGHTMODES_H_ diff --git a/companion/src/modeledit/heli.cpp b/companion/src/modeledit/heli.cpp index c0a4e39d8..9574feeed 100644 --- a/companion/src/modeledit/heli.cpp +++ b/companion/src/modeledit/heli.cpp @@ -23,17 +23,20 @@ #include "helpers.h" #include "rawitemfilteredmodel.h" -HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSourceItemModel * rawSourceItemModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Heli) { ui->setupUi(this); - rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, RawSource::InputSourceGroups, this); + rawSourceModel = new RawItemFilteredModel(rawSourceItemModel, RawSource::InputSourceGroups, this); + connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &HeliPanel::onModelDataAboutToBeUpdated); + connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &HeliPanel::onModelDataUpdateComplete); connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited())); connect(ui->swashCollectiveSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); + if (firmware->getCapability(VirtualInputs)) { connect(ui->swashAileronSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); connect(ui->swashElevatorSource, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); @@ -63,30 +66,22 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener HeliPanel::~HeliPanel() { + delete rawSourceModel; delete ui; } -void HeliPanel::updateDataModels() -{ - const bool oldLock = lock; - lock = true; - rawSourceItemModel->update(); - lock = oldLock; -} - void HeliPanel::update() { lock = true; - updateDataModels(); ui->swashType->setCurrentIndex(model->swashRingData.type); - ui->swashCollectiveSource->setModel(rawSourceItemModel); + ui->swashCollectiveSource->setModel(rawSourceModel); ui->swashCollectiveSource->setCurrentIndex(ui->swashCollectiveSource->findData(model->swashRingData.collectiveSource.toValue())); ui->swashRingVal->setValue(model->swashRingData.value); if (firmware->getCapability(VirtualInputs)) { - ui->swashElevatorSource->setModel(rawSourceItemModel); + ui->swashElevatorSource->setModel(rawSourceModel); ui->swashElevatorSource->setCurrentIndex(ui->swashElevatorSource->findData(model->swashRingData.elevatorSource.toValue())); - ui->swashAileronSource->setModel(rawSourceItemModel); + ui->swashAileronSource->setModel(rawSourceModel); ui->swashAileronSource->setCurrentIndex(ui->swashAileronSource->findData(model->swashRingData.aileronSource.toValue())); ui->swashElevatorWeight->setValue(model->swashRingData.elevatorWeight); ui->swashAileronWeight->setValue(model->swashRingData.aileronWeight); @@ -122,3 +117,13 @@ void HeliPanel::edited() emit modified(); } } + +void HeliPanel::onModelDataAboutToBeUpdated() +{ + lock = true; +} + +void HeliPanel::onModelDataUpdateComplete() +{ + update(); +} diff --git a/companion/src/modeledit/heli.h b/companion/src/modeledit/heli.h index 5a27c7c26..97552778a 100644 --- a/companion/src/modeledit/heli.h +++ b/companion/src/modeledit/heli.h @@ -23,7 +23,8 @@ #include "modeledit.h" -class RawSourceFilterItemModel; +class RawSourceItemModel; +class RawItemFilteredModel; namespace Ui { class Heli; @@ -34,17 +35,18 @@ class HeliPanel : public ModelPanel Q_OBJECT public: - HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSourceItemModel * rawSourceItemModel); ~HeliPanel(); void update(); private slots: - void updateDataModels(); void edited(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); private: Ui::Heli *ui; - RawSourceFilterItemModel * rawSourceItemModel; + RawItemFilteredModel * rawSourceModel; }; #endif // _HELI_H_ diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp index 2e65c788c..624f1fdbd 100644 --- a/companion/src/modeledit/inputs.cpp +++ b/companion/src/modeledit/inputs.cpp @@ -22,10 +22,13 @@ #include "expodialog.h" #include "helpers.h" -InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel): ModelPanel(parent, model, generalSettings, firmware), expoInserted(false), - modelPrinter(firmware, generalSettings, model) + modelPrinter(firmware, generalSettings, model), + rawSourceItemModel(rawSourceItemModel), + rawSwitchItemModel(rawSwitchItemModel) { inputsCount = firmware->getCapability(VirtualInputs); if (inputsCount == 0) @@ -180,11 +183,12 @@ void InputsPanel::gm_openExpo(int index) if (firmware->getCapability(VirtualInputs)) inputName = model->inputNames[ed.chn]; - ExpoDialog *g = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName); + ExpoDialog *g = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, rawSourceItemModel, rawSwitchItemModel); if (g->exec()) { model->expoData[index] = ed; if (firmware->getCapability(VirtualInputs)) strncpy(model->inputNames[ed.chn], inputName.toLatin1().data(), INPUT_NAME_LEN); + emit updateDataModels(); emit modified(); update(); } diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index 9922f2873..0922305ce 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -24,6 +24,7 @@ #include "modeledit.h" #include "mixerslistwidget.h" #include "modelprinter.h" +#include "rawitemdatamodels.h" constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo"; @@ -32,7 +33,8 @@ class InputsPanel : public ModelPanel Q_OBJECT public: - InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel); virtual ~InputsPanel(); virtual void update(); @@ -60,6 +62,9 @@ class InputsPanel : public ModelPanel void cmInputMoveDown(); void cmInputMoveUp(); + signals: + void updateDataModels(); + private: bool expoInserted; MixersListWidget *ExposlistWidget; @@ -67,6 +72,8 @@ class InputsPanel : public ModelPanel ModelPrinter modelPrinter; int selectedIdx; int inputIdx; + RawSourceItemModel *rawSourceItemModel; + RawSwitchItemModel *rawSwitchItemModel; int getExpoIndex(unsigned int dch); bool gm_insertExpo(int idx); diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index e70d63568..109e09ecf 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -24,16 +24,20 @@ #include -LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel): ModelPanel(parent, model, generalSettings, firmware), - selectedIndex(0) + selectedIndex(0), + modelsUpdateCnt(0) { - Stopwatch s1("LogicalSwitchesPanel"); - - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::LogicalSwitchesContext, this); + rawSwitchModel = new RawItemFilteredModel(rawSwitchItemModel, RawSwitch::LogicalSwitchesContext); + connect(rawSwitchModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); + connect(rawSwitchModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup); - rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this); + rawSourceModel = new RawItemFilteredModel(rawSourceItemModel, srcGroups, this); + connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); + connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); lsCapability = firmware->getCapability(LogicalSwitches); lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt); @@ -45,16 +49,14 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, } TableLayout * tableLayout = new TableLayout(this, lsCapability, headerLabels); - s1.report("header"); - const int channelsMax = model.getChannelsMax(true); lock = true; - for (int i=0; isetProperty("index", i); - label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, i+1).toString()); + label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, i + 1).toString()); label->setContextMenuPolicy(Qt::CustomContextMenu); label->setToolTip(tr("Popup menu available")); label->setMouseTracking(true); @@ -123,7 +125,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, // AND cbAndSwitch[i] = new QComboBox(this); cbAndSwitch[i]->setProperty("index", i); - populateAndSwitchCB(cbAndSwitch[i]); + cbAndSwitch[i]->setModel(rawSwitchModel); + cbAndSwitch[i]->setVisible(true); connect(cbAndSwitch[i], SIGNAL(currentIndexChanged(int)), this, SLOT(onAndSwitchChanged(int))); tableLayout->addWidget(i, 4, cbAndSwitch[i]); @@ -152,27 +155,16 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, } } - s1.report("added elements"); - disableMouseScrolling(); lock = false; - update(); tableLayout->resizeColumnsToContents(); tableLayout->pushRowsUp(lsCapability+1); - s1.report("end"); } LogicalSwitchesPanel::~LogicalSwitchesPanel() { -} - -void LogicalSwitchesPanel::updateDataModels() -{ - const bool oldLock = lock; - lock = true; - rawSwitchItemModel->update(); - rawSourceItemModel->update(); - lock = oldLock; + delete rawSourceModel; + delete rawSwitchModel; } void LogicalSwitchesPanel::onFunctionChanged() @@ -199,8 +191,10 @@ void LogicalSwitchesPanel::onFunctionChanged() model->logicalSw[i].val2 = -129; } } - if (bool(oldFunc) != bool(newFunc)) + if (bool(oldFunc) != bool(newFunc)) { + emit updateDataModels(); update(); + } else updateLine(i); @@ -211,13 +205,15 @@ void LogicalSwitchesPanel::onV1Changed(int value) { if (!lock) { int i = sender()->property("index").toInt(); - model->logicalSw[i].val1 = cbSource1[i]->itemData(value).toInt(); - if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) { - if (!offsetChangedAt(i)) - updateLine(i); - } - else { - emit modified(); + if (model->logicalSw[i].val1 != cbSource1[i]->itemData(value).toInt()) { + model->logicalSw[i].val1 = cbSource1[i]->itemData(value).toInt(); + if (model->logicalSw[i].getFunctionFamily() == LS_FAMILY_VOFS) { + if (!offsetChangedAt(i)) + updateLine(i); + } + else { + emit modified(); + } } } } @@ -226,8 +222,10 @@ void LogicalSwitchesPanel::onV2Changed(int value) { if (!lock) { int i = sender()->property("index").toInt(); - model->logicalSw[i].val2 = cbSource2[i]->itemData(value).toInt(); - emit modified(); + if (model->logicalSw[i].val2 != cbSource2[i]->itemData(value).toInt()) { + model->logicalSw[i].val2 = cbSource2[i]->itemData(value).toInt(); + emit modified(); + } } } @@ -235,8 +233,10 @@ void LogicalSwitchesPanel::onAndSwitchChanged(int value) { if (!lock) { int index = sender()->property("index").toInt(); - model->logicalSw[index].andsw = cbAndSwitch[index]->itemData(value).toInt(); - emit modified(); + if (model->logicalSw[index].andsw != cbAndSwitch[index]->itemData(value).toInt()) { + model->logicalSw[index].andsw = cbAndSwitch[index]->itemData(value).toInt(); + emit modified(); + } } } @@ -244,7 +244,7 @@ void LogicalSwitchesPanel::onDurationChanged(double duration) { if (!lock) { int index = sender()->property("index").toInt(); - model->logicalSw[index].duration = (uint8_t)round(duration*10); + model->logicalSw[index].duration = (uint8_t)round(duration * 10); emit modified(); } } @@ -253,7 +253,7 @@ void LogicalSwitchesPanel::onDelayChanged(double delay) { if (!lock) { int index = sender()->property("index").toInt(); - model->logicalSw[index].delay = (uint8_t)round(delay*10); + model->logicalSw[index].delay = (uint8_t)round(delay * 10); emit modified(); } } @@ -326,9 +326,9 @@ void LogicalSwitchesPanel::updateTimerParam(QDoubleSpinBox *sb, int timer, doubl sb->setMinimum(minimum); sb->setMaximum(175); float value = ValToTim(timer); - if (value>=60) + if (value >= 60) sb->setSingleStep(1); - else if (value>=2) + else if (value >= 2) sb->setSingleStep(0.5); else sb->setSingleStep(0.1); @@ -367,7 +367,7 @@ void LogicalSwitchesPanel::updateLine(int i) RawSource source = RawSource(model->logicalSw[i].val1); RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[i].getRangeFlags()); double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/ - cbSource1[i]->setModel(rawSourceItemModel); + cbSource1[i]->setModel(rawSourceModel); cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(source.toValue())); if (source.isTimeBased()) { mask |= VALUE_TO_VISIBLE; @@ -396,16 +396,16 @@ void LogicalSwitchesPanel::updateLine(int i) case LS_FAMILY_STICKY: // no break case LS_FAMILY_VBOOL: mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE; - cbSource1[i]->setModel(rawSwitchItemModel); + cbSource1[i]->setModel(rawSwitchModel); cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1)); - cbSource2[i]->setModel(rawSwitchItemModel); + cbSource2[i]->setModel(rawSwitchModel); cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2)); break; case LS_FAMILY_EDGE: mask |= SOURCE1_VISIBLE | VALUE2_VISIBLE | VALUE3_VISIBLE; mask &= ~DELAY_ENABLED; - cbSource1[i]->setModel(rawSwitchItemModel); + cbSource1[i]->setModel(rawSwitchModel); cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1)); updateTimerParam(dsbOffset[i], model->logicalSw[i].val2, 0.0); updateTimerParam(dsbOffset2[i], model->logicalSw[i].val2+model->logicalSw[i].val3, ValToTim(TimToVal(dsbOffset[i]->value())-1)); @@ -414,9 +414,9 @@ void LogicalSwitchesPanel::updateLine(int i) case LS_FAMILY_VCOMP: mask |= SOURCE1_VISIBLE | SOURCE2_VISIBLE; - cbSource1[i]->setModel(rawSourceItemModel); + cbSource1[i]->setModel(rawSourceModel); cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(model->logicalSw[i].val1)); - cbSource2[i]->setModel(rawSourceItemModel); + cbSource2[i]->setModel(rawSourceModel); cbSource2[i]->setCurrentIndex(cbSource2[i]->findData(model->logicalSw[i].val2)); break; @@ -439,9 +439,9 @@ void LogicalSwitchesPanel::updateLine(int i) dsbDuration[i]->setVisible(mask & DURATION_ENABLED); dsbDelay[i]->setVisible(mask & DELAY_ENABLED); if (mask & DURATION_ENABLED) - dsbDuration[i]->setValue(model->logicalSw[i].duration/10.0); + dsbDuration[i]->setValue(model->logicalSw[i].duration / 10.0); if (mask & DELAY_ENABLED) - dsbDelay[i]->setValue(model->logicalSw[i].delay/10.0); + dsbDelay[i]->setValue(model->logicalSw[i].delay / 10.0); } lock = false; @@ -475,7 +475,7 @@ void LogicalSwitchesPanel::populateFunctionCB(QComboBox *b) }; b->clear(); - for (int i=0; isetMaxVisibleItems(10); } -void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b) -{ - b->setModel(rawSwitchItemModel); - b->setVisible(true); -} - void LogicalSwitchesPanel::update() { - updateDataModels(); - for (int i=0; ilogicalSw[selectedIndex], data.constData(), sizeof(LogicalSwitchData)); - updateDataModels(); + emit updateDataModels(); updateLine(selectedIndex); emit modified(); } @@ -518,6 +511,7 @@ void LogicalSwitchesPanel::cmDelete() model->logicalSw[lsCapability - 1].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); + emit updateDataModels(); update(); emit modified(); } @@ -609,6 +603,7 @@ void LogicalSwitchesPanel::cmClear(bool prompt) model->logicalSw[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, selectedIndex); update(); + emit updateDataModels(); emit modified(); } @@ -617,11 +612,12 @@ void LogicalSwitchesPanel::cmClearAll() if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Logical Switches. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; - for (int i=0; ilogicalSw[i].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_CLEAR, i); } update(); + emit updateDataModels(); emit modified(); } @@ -631,6 +627,7 @@ void LogicalSwitchesPanel::cmInsert() model->logicalSw[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); update(); + emit updateDataModels(); emit modified(); } @@ -644,6 +641,20 @@ void LogicalSwitchesPanel::swapData(int idx1, int idx2) memcpy(lsw1, &lstmp, sizeof(LogicalSwitchData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_LOGICAL_SWITCH, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); update(); + emit updateDataModels(); emit modified(); } } + +void LogicalSwitchesPanel::onModelDataAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void LogicalSwitchesPanel::onModelDataUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) + update(); +} diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h index 62aa69f30..b73bd8034 100644 --- a/companion/src/modeledit/logicalswitches.h +++ b/companion/src/modeledit/logicalswitches.h @@ -24,8 +24,9 @@ #include "modeledit.h" #include "radiodata.h" -class RawSwitchFilterItemModel; -class RawSourceFilterItemModel; +class RawSourceItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; class TimerEdit; constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch"; @@ -35,13 +36,13 @@ class LogicalSwitchesPanel : public ModelPanel Q_OBJECT public: - LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel); virtual ~LogicalSwitchesPanel(); virtual void update(); private slots: - void updateDataModels(); void onFunctionChanged(); void onV1Changed(int value); void onV2Changed(int value); @@ -61,6 +62,11 @@ class LogicalSwitchesPanel : public ModelPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); + + signals: + void updateDataModels(); private: QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES]; @@ -73,11 +79,10 @@ class LogicalSwitchesPanel : public ModelPanel QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES]; - RawSwitchFilterItemModel * rawSwitchItemModel; - RawSourceFilterItemModel * rawSourceItemModel; + RawItemFilteredModel * rawSwitchModel; + RawItemFilteredModel * rawSourceModel; int selectedIndex; void populateFunctionCB(QComboBox *b); - void populateAndSwitchCB(QComboBox *b); void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0); int lsCapability; int lsCapabilityExt; @@ -86,6 +91,7 @@ class LogicalSwitchesPanel : public ModelPanel bool insertAllowed() const; bool moveDownAllowed() const; bool moveUpAllowed() const; + int modelsUpdateCnt; }; #endif // _LOGICALSWITCHES_H_ diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index 1b17e9471..5727f2495 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -24,7 +24,8 @@ #include "rawitemfilteredmodel.h" #include "helpers.h" -MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware) : +MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel) : QDialog(parent), ui(new Ui::MixerDialog), model(model), @@ -34,6 +35,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, lock(false) { ui->setupUi(this); + rawSourceModel = new RawItemFilteredModel(rawSourceItemModel, RawSource::InputSourceGroups | RawSource::ScriptsGroup, this); + rawSwitchModel = new RawItemFilteredModel(rawSwitchItemModel, RawSwitch::MixesContext, this); + QRegExp rx(CHAR_FOR_NAMES_REGEX); QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0,ui->lb_FP1,ui->lb_FP2,ui->lb_FP3,ui->lb_FP4,ui->lb_FP5,ui->lb_FP6,ui->lb_FP7,ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0,ui->cb_FP1,ui->cb_FP2,ui->cb_FP3,ui->cb_FP4,ui->cb_FP5,ui->cb_FP6,ui->cb_FP7,ui->cb_FP8 }; @@ -43,7 +47,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh-1).toString(&model, &generalSettings))); - ui->sourceCB->setModel(new RawSourceFilterItemModel(&generalSettings, &model, RawSource::InputSourceGroups | RawSource::ScriptsGroup, this)); + ui->sourceCB->setModel(rawSourceModel); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue())); ui->sourceCB->removeItem(0); @@ -104,7 +108,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, } } - ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this)); + ui->switchesCB->setModel(rawSwitchModel); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue())); ui->warningCB->setCurrentIndex(md->mixWarn); ui->mltpxCB->setCurrentIndex(md->mltpx); diff --git a/companion/src/modeledit/mixerdialog.h b/companion/src/modeledit/mixerdialog.h index 93f061d0d..2b89cd00e 100644 --- a/companion/src/modeledit/mixerdialog.h +++ b/companion/src/modeledit/mixerdialog.h @@ -26,6 +26,9 @@ class GVarGroup; class CurveGroup; +class RawSourceItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; namespace Ui { class MixerDialog; @@ -34,7 +37,8 @@ namespace Ui { class MixerDialog : public QDialog { Q_OBJECT public: - MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware); + MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel); ~MixerDialog(); protected: @@ -59,6 +63,8 @@ class MixerDialog : public QDialog { GVarGroup * gvOffsetGroup; CurveGroup * curveGroup; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + RawItemFilteredModel * rawSourceModel; + RawItemFilteredModel * rawSwitchModel; }; #endif // _MIXERDIALOG_H_ diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp index 4d0f5f4cd..52f6ba51c 100644 --- a/companion/src/modeledit/mixes.cpp +++ b/companion/src/modeledit/mixes.cpp @@ -21,11 +21,14 @@ #include "mixes.h" #include "helpers.h" -MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel): ModelPanel(parent, model, generalSettings, firmware), mixInserted(false), highlightedSource(0), - modelPrinter(firmware, generalSettings, model) + modelPrinter(firmware, generalSettings, model), + rawSourceItemModel(rawSourceItemModel), + rawSwitchItemModel(rawSwitchItemModel) { QGridLayout * mixesLayout = new QGridLayout(this); @@ -175,7 +178,7 @@ void MixesPanel::gm_openMix(int index) MixData mixd(model->mixData[index]); - MixerDialog *g = new MixerDialog(this, *model, &mixd, generalSettings, firmware); + MixerDialog *g = new MixerDialog(this, *model, &mixd, generalSettings, firmware, rawSourceItemModel, rawSwitchItemModel); if(g->exec()) { model->mixData[index] = mixd; emit modified(); diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h index 95765465e..15cb0bd54 100644 --- a/companion/src/modeledit/mixes.h +++ b/companion/src/modeledit/mixes.h @@ -25,13 +25,15 @@ #include "mixerslistwidget.h" #include "mixerdialog.h" #include "modelprinter.h" +#include "rawitemdatamodels.h" class MixesPanel : public ModelPanel { Q_OBJECT public: - MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + RawSourceItemModel * rawSourceItemModel, RawSwitchItemModel * rawSwitchItemModel); virtual ~MixesPanel(); virtual void update(); @@ -63,6 +65,8 @@ class MixesPanel : public ModelPanel bool mixInserted; unsigned int highlightedSource; ModelPrinter modelPrinter; + RawSourceItemModel *rawSourceItemModel; + RawSwitchItemModel *rawSwitchItemModel; int getMixerIndex(unsigned int dch); bool gm_insertMix(int idx); diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index af3166c7f..9b6d1727c 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -33,6 +33,7 @@ #include "customfunctions.h" #include "telemetry.h" #include "appdata.h" +#include "rawitemdatamodels.h" ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmware * firmware) : QDialog(parent), @@ -48,38 +49,96 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw setWindowIcon(CompanionIcon("edit.png")); restoreGeometry(g.modelEditGeo()); ui->pushButton->setIcon(CompanionIcon("simulate.png")); - SetupPanel * setupPanel = new SetupPanel(this, radioData.models[modelId], radioData.generalSettings, firmware); + + GeneralSettings &generalSettings = radioData.generalSettings; + ModelData &model = radioData.models[modelId]; + + /* + Create reusable model specific ui datamodels here and pass pointers as needed + They should be referenced through filters in each use case + Code that updates the source for one or more ui datamodels should emit a SIGNAL that can be trapped (see below) and the datamodels refreshed + WARNING: beware of looping signals and slots and unnecessary data field updates from refreshing datamodels + where practical make signals granular to only those fields that affect datamodels thus needing to be refreshed + */ + rawSourceModel = new RawSourceItemModel(&generalSettings, &model, this); + rawSwitchModel = new RawSwitchItemModel(&generalSettings, &model, this); + curveModel = new CurveItemModel(&generalSettings, &model, this); + s1.report("Init"); + + SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, rawSwitchModel); addTab(setupPanel, tr("Setup")); - if (firmware->getCapability(Heli)) - addTab(new HeliPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Heli")); - addTab(new FlightModesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Flight Modes")); - addTab(new InputsPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Inputs")); - s1.report("inputs"); - addTab(new MixesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Mixes")); + s1.report("Setup"); + + if (firmware->getCapability(Heli)) { + HeliPanel * heliPanel = new HeliPanel(this, model, generalSettings, firmware, rawSourceModel); + addTab(heliPanel, tr("Heli")); + s1.report("Heli"); + } + + FlightModesPanel * flightModesPanel = new FlightModesPanel(this, model, generalSettings, firmware, rawSwitchModel); + addTab(flightModesPanel, tr("Flight Modes")); + s1.report("Flight Modes"); + + InputsPanel * inputsPanel = new InputsPanel(this, model, generalSettings, firmware, rawSourceModel, rawSwitchModel); + addTab(inputsPanel, tr("Inputs")); + s1.report("Inputs"); + + MixesPanel * mixesPanel = new MixesPanel(this, model, generalSettings, firmware, rawSourceModel, rawSwitchModel); + addTab(mixesPanel, tr("Mixes")); s1.report("Mixes"); - Channels * chnPanel = new Channels(this, radioData.models[modelId], radioData.generalSettings, firmware); - addTab(chnPanel, tr("Outputs")); + + ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, curveModel); + addTab(channelsPanel, tr("Outputs")); s1.report("Outputs"); - addTab(new Curves(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Curves")); - addTab(new LogicalSwitchesPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Logical Switches")); - s1.report("LS"); - addTab(new CustomFunctionsPanel(this, &radioData.models[modelId], radioData.generalSettings, firmware), tr("Special Functions")); - s1.report("CF"); - if (firmware->getCapability(Telemetry)) - addTab(new TelemetryPanel(this, radioData.models[modelId], radioData.generalSettings, firmware), tr("Telemetry")); - onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel + CurvesPanel * curvesPanel = new CurvesPanel(this, model, generalSettings, firmware); + addTab(curvesPanel, tr("Curves")); + s1.report("Curves"); + + LogicalSwitchesPanel * logicalSwitchesPanel = new LogicalSwitchesPanel(this, model, generalSettings, firmware, rawSourceModel, rawSwitchModel); + addTab(logicalSwitchesPanel, tr("Logical Switches")); + s1.report("Logical Switches"); + + CustomFunctionsPanel * customFunctionsPanel = new CustomFunctionsPanel(this, &model, generalSettings, firmware, rawSourceModel, rawSwitchModel); + addTab(customFunctionsPanel, tr("Special Functions")); + s1.report("Special Functions"); + + if (firmware->getCapability(Telemetry)) { + TelemetryPanel * telemetryPanel = new TelemetryPanel(this, model, generalSettings, firmware, rawSourceModel); + addTab(telemetryPanel, tr("Telemetry")); + connect(telemetryPanel, &TelemetryPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + s1.report("Telemetry"); + } + + connect(setupPanel, &SetupPanel::extendedLimitsToggled, channelsPanel, &ChannelsPanel::refreshExtendedLimits); + connect(setupPanel, &SetupPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + + connect(flightModesPanel, &FlightModesPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + connect(flightModesPanel, &FlightModesPanel::updateDataModels, rawSwitchModel, &RawSwitchItemModel::update); + + connect(inputsPanel, &InputsPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + + connect(channelsPanel, &ChannelsPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + + connect(curvesPanel, &CurvesPanel::updateDataModels, curveModel, &CurveItemModel::update); + + connect(logicalSwitchesPanel, &LogicalSwitchesPanel::updateDataModels, rawSourceModel, &RawSourceItemModel::update); + connect(logicalSwitchesPanel, &LogicalSwitchesPanel::updateDataModels, rawSwitchModel, &RawSwitchItemModel::update); - connect(setupPanel, &SetupPanel::extendedLimitsToggled, chnPanel, &Channels::refreshExtendedLimits); connect(ui->tabWidget, &QTabWidget::currentChanged, this, &ModelEdit::onTabIndexChanged); connect(ui->pushButton, &QPushButton::clicked, this, &ModelEdit::launchSimulation); - s1.report("end"); + onTabIndexChanged(ui->tabWidget->currentIndex()); // make sure to trigger update on default tab panel + + s1.report("Signals and Slots"); gStopwatch.report("ModelEdit end constructor"); } ModelEdit::~ModelEdit() { + delete rawSourceModel; + delete rawSwitchModel; + delete curveModel; delete ui; } diff --git a/companion/src/modeledit/modeledit.h b/companion/src/modeledit/modeledit.h index 969ae85d7..87c07759b 100644 --- a/companion/src/modeledit/modeledit.h +++ b/companion/src/modeledit/modeledit.h @@ -25,6 +25,9 @@ #include "genericpanel.h" class RadioData; +class RawSourceItemModel; +class RawSwitchItemModel; +class CurveItemModel; namespace Ui { class ModelEdit; @@ -62,6 +65,9 @@ class ModelEdit : public QDialog RadioData & radioData; Firmware * firmware; QVector panels; + RawSourceItemModel *rawSourceModel; + RawSwitchItemModel *rawSwitchModel; + CurveItemModel *curveModel; void addTab(GenericPanel *panel, QString text); void launchSimulation(); diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index dcbe4f101..a83aeff69 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -31,13 +31,15 @@ #include -TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawSwitchFilterItemModel * switchModel): +TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawItemFilteredModel * rawSwitchModel): ModelPanel(parent, model, generalSettings, firmware), timer(timer), ui(new Ui::Timer) { ui->setupUi(this); + connect(rawSwitchModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TimerPanel::onModelDataAboutToBeUpdated); + connect(rawSwitchModel, &RawItemFilteredModel::dataUpdateComplete, this, &TimerPanel::onModelDataUpdateComplete); lock = true; @@ -52,7 +54,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge } // Mode - ui->mode->setModel(switchModel); + ui->mode->setModel(rawSwitchModel); ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue())); connect(ui->mode, SIGNAL(activated(int)), this, SLOT(onModeChanged(int))); @@ -165,11 +167,22 @@ void TimerPanel::on_name_editingFinished() if (QString(timer.name) != ui->name->text()) { int length = ui->name->maxLength(); strncpy(timer.name, ui->name->text().toLatin1(), length); + emit nameChanged(); emit modified(); } } } +void TimerPanel::onModelDataAboutToBeUpdated() +{ + lock = true; +} + +void TimerPanel::onModelDataUpdateComplete() +{ + update(); +} + /******************************************************************************/ #define FAILSAFE_CHANNEL_HOLD 2000 @@ -978,7 +991,7 @@ void ModulePanel::onClearAccessRxClicked() /******************************************************************************/ -SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchItemModel * rawSwitchItemModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Setup) { @@ -1062,18 +1075,17 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge } QWidget * prevFocus = ui->image; - RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this); - connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update); + rawSwitchFilteredModel = new RawItemFilteredModel(rawSwitchItemModel, RawSwitch::TimersContext, this); timersCount = firmware->getCapability(Timers); for (int i = 0; i < CPN_MAX_TIMERS; i++) { if (i < timersCount) { - timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel); + timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, rawSwitchFilteredModel); ui->gridLayout->addWidget(timers[i], 1+i, 1); connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified); + connect(timers[i], &TimerPanel::nameChanged, this, &SetupPanel::onTimerNameChanged); connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update); - connect(this, &SetupPanel::timerUpdated, timers[i], &TimerPanel::update); prevFocus = timers[i]->getLastFocus(); // TODO more reliable method required QLabel *label = findChild(QString("label_timer%1").arg(i + 1)); @@ -1234,6 +1246,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge SetupPanel::~SetupPanel() { + delete rawSwitchFilteredModel; delete ui; } @@ -1601,7 +1614,7 @@ void SetupPanel::cmTimerClear(bool prompt) model->timers[selectedTimerIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex); - emit timerUpdated(); + emit updateDataModels(); emit modified(); } @@ -1614,7 +1627,7 @@ void SetupPanel::cmTimerClearAll() model->timers[i].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, i); } - emit timerUpdated(); + emit updateDataModels(); emit modified(); } @@ -1648,7 +1661,7 @@ void SetupPanel::cmTimerDelete() } model->timers[maxidx].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, -1); - emit timerUpdated(); + emit updateDataModels(); emit modified(); } @@ -1661,7 +1674,7 @@ void SetupPanel::cmTimerInsert() } model->timers[selectedTimerIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, 1); - emit timerUpdated(); + emit updateDataModels(); emit modified(); } @@ -1681,7 +1694,7 @@ void SetupPanel::cmTimerPaste() if (hasTimerClipboardData(&data)) { TimerData *td = &model->timers[selectedTimerIndex]; memcpy(td, data.constData(), sizeof(TimerData)); - emit timerUpdated(); + emit updateDataModels(); emit modified(); } } @@ -1695,7 +1708,12 @@ void SetupPanel::swapTimerData(int idx1, int idx2) memcpy(td2, td1, sizeof(TimerData)); memcpy(td1, &tdtmp, sizeof(TimerData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - emit timerUpdated(); + emit updateDataModels(); emit modified(); } } + +void SetupPanel::onTimerNameChanged() +{ + emit updateDataModels(); +} diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 0aa48ea76..6f4a95922 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -26,7 +26,8 @@ constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer"; -class RawSwitchFilterItemModel; +class RawSwitchItemModel; +class RawItemFilteredModel; namespace Ui { class Setup; @@ -39,7 +40,7 @@ class TimerPanel : public ModelPanel Q_OBJECT public: - TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawSwitchFilterItemModel * switchModel); + TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawItemFilteredModel * switchModel); virtual ~TimerPanel(); virtual void update(); @@ -50,6 +51,11 @@ class TimerPanel : public ModelPanel void on_value_editingFinished(); void on_minuteBeep_toggled(bool checked); void on_name_editingFinished(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); + + signals: + void nameChanged(); private: TimerData & timer; @@ -125,7 +131,7 @@ class SetupPanel : public ModelPanel Q_OBJECT public: - SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSwitchItemModel * rawSwitchItemModel); virtual ~SetupPanel(); virtual void update(); @@ -133,7 +139,7 @@ class SetupPanel : public ModelPanel signals: void extendedLimitsToggled(); void updated(); - void timerUpdated(); + void updateDataModels(); private slots: void on_name_editingFinished(); @@ -163,6 +169,7 @@ class SetupPanel : public ModelPanel void cmTimerPaste(); void cmTimerMoveDown(); void cmTimerMoveUp(); + void onTimerNameChanged(); private: Ui::Setup *ui; @@ -183,6 +190,7 @@ class SetupPanel : public ModelPanel bool moveTimerDownAllowed() const; bool moveTimerUpAllowed() const; void swapTimerData(int idx1, int idx2); -}; + RawItemFilteredModel * rawSwitchFilteredModel; + }; #endif // _SETUP_H_ diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp index b34caa89e..0b6ad58b7 100644 --- a/companion/src/modeledit/telemetry.cpp +++ b/companion/src/modeledit/telemetry.cpp @@ -28,18 +28,20 @@ #include -TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel): +TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetryCustomScreen), screen(screen) { ui->setupUi(this); + connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TelemetryCustomScreen::onModelDataAboutToBeUpdated); + connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &TelemetryCustomScreen::onModelDataUpdateComplete); for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) { for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { fieldsCB[l][c] = new QComboBox(this); fieldsCB[l][c]->setProperty("index", c + (l << 8)); - fieldsCB[l][c]->setModel(srcModel); + fieldsCB[l][c]->setModel(rawSourceModel); ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1); connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int))); } @@ -48,7 +50,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) { barsCB[l] = new QComboBox(this); barsCB[l]->setProperty("index", l); - barsCB[l]->setModel(srcModel); + barsCB[l]->setModel(rawSourceModel); connect(barsCB[l], SIGNAL(activated(int)), this, SLOT(barSourceChanged(int))); ui->screenBarsLayout->addWidget(barsCB[l], l, 0, 1, 1); @@ -287,6 +289,16 @@ void TelemetryCustomScreen::barTimeChanged() } } +void TelemetryCustomScreen::onModelDataAboutToBeUpdated() +{ + lock = true; +} + +void TelemetryCustomScreen::onModelDataUpdateComplete() +{ + update(); +} + /******************************************************/ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): @@ -678,11 +690,12 @@ void TelemetrySensorPanel::cmMoveDown() /******************************************************/ -TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSourceItemModel * rawSourceItemModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Telemetry) { ui->setupUi(this); + rawSourceModel = new RawItemFilteredModel(rawSourceItemModel, this); sensorCapability = firmware->getCapability(Sensors); if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability @@ -696,6 +709,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this); ui->A1GB->hide(); ui->A2GB->hide(); + for (int i = 0; i < sensorCapability; ++i) { TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, firmware); ui->sensorsLayout->addWidget(panel); @@ -717,15 +731,11 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin ui->topbarGB->hide(); } - RawSourceFilterItemModel * srcModel = (new RawSourceFilterItemModel(&generalSettings, &model, this)); - connect(this, &TelemetryPanel::updated, srcModel, &RawSourceFilterItemModel::update); - for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { - TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, srcModel); + TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, rawSourceModel); ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1)); telemetryCustomScreens[i] = tab; connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified); - connect(this, &TelemetryPanel::updated, tab, &TelemetryCustomScreen::update); } disableMouseScrolling(); @@ -735,6 +745,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin TelemetryPanel::~TelemetryPanel() { + delete rawSourceModel; delete ui; } @@ -759,79 +770,78 @@ void TelemetryPanel::update() sensorPanels[i]->update(); } - emit updated(); + for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { + telemetryCustomScreens[i]->update(); + } } void TelemetryPanel::setup() { - QString firmware_id = g.profile[g.id()].fwType(); + lock = true; - lock = true; + ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0); + ui->telemetryProtocol->addItem(tr("FrSky D"), 1); + if (IS_9XRPRO(firmware->getBoard()) || + (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) { + ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2); + } + ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol); + ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this); + ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled); - ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0); - ui->telemetryProtocol->addItem(tr("FrSky D"), 1); - if (IS_9XRPRO(firmware->getBoard()) || - (IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) { - ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2); - } - ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol); - ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this); - ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled); + ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning); + ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical); - ui->rssiAlarmWarningSB->setValue(model->rssiAlarms.warning); - ui->rssiAlarmCriticalSB->setValue(model->rssiAlarms.critical); + ui->rssiSourceLabel->show(); + ui->rssiSourceLabel->setText(tr("Source")); + ui->rssiSourceCB->setField(model->rssiSource, this); + ui->rssiSourceCB->show(); + populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); - ui->rssiSourceLabel->show(); - ui->rssiSourceLabel->setText(tr("Source")); - ui->rssiSourceCB->setField(model->rssiSource, this); - ui->rssiSourceCB->show(); - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); + ui->rssiAlarmWarningCB->hide(); + ui->rssiAlarmCriticalCB->hide(); + ui->rssiAlarmWarningLabel->setText(tr("Low Alarm")); + ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm")); - ui->rssiAlarmWarningCB->hide(); - ui->rssiAlarmCriticalCB->hide(); - ui->rssiAlarmWarningLabel->setText(tr("Low Alarm")); - ui->rssiAlarmCriticalLabel->setText(tr("Critical Alarm")); - - int varioCap = firmware->getCapability(HasVario); - if (!varioCap) { - ui->varioLimitMax_DSB->hide(); + if (!firmware->getCapability(HasVario)) { + ui->varioLimitMax_DSB->hide(); + ui->varioLimitMin_DSB->hide(); + ui->varioLimitCenterMin_DSB->hide(); + ui->varioLimitCenterMax_DSB->hide(); + ui->varioLimit_label->hide(); + ui->VarioLabel_1->hide(); + ui->VarioLabel_2->hide(); + ui->VarioLabel_3->hide(); + ui->VarioLabel_4->hide(); + ui->varioSource->hide(); + ui->varioSource_label->hide(); + } + else { + if (!firmware->getCapability(HasVarioSink)) { ui->varioLimitMin_DSB->hide(); ui->varioLimitCenterMin_DSB->hide(); - ui->varioLimitCenterMax_DSB->hide(); - ui->varioLimit_label->hide(); ui->VarioLabel_1->hide(); ui->VarioLabel_2->hide(); - ui->VarioLabel_3->hide(); - ui->VarioLabel_4->hide(); - ui->varioSource->hide(); - ui->varioSource_label->hide(); - } - else { - if (!firmware->getCapability(HasVarioSink)) { - ui->varioLimitMin_DSB->hide(); - ui->varioLimitCenterMin_DSB->hide(); - ui->VarioLabel_1->hide(); - ui->VarioLabel_2->hide(); - } - ui->varioLimitMin_DSB->setValue(model->frsky.varioMin - 10); - ui->varioLimitMax_DSB->setValue(model->frsky.varioMax + 10); - ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax / 10.0) + 0.5); - ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin / 10.0) - 0.5); } + ui->varioLimitMin_DSB->setValue(model->frsky.varioMin - 10); + ui->varioLimitMax_DSB->setValue(model->frsky.varioMax + 10); + ui->varioLimitCenterMax_DSB->setValue((model->frsky.varioCenterMax / 10.0) + 0.5); + ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin / 10.0) - 0.5); + } - ui->altimetryGB->setVisible(firmware->getCapability(HasVario)), - ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol)); + ui->altimetryGB->setVisible(firmware->getCapability(HasVario)), + ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol)); - if (firmware->getCapability(Telemetry)) { - ui->frskyProtoCB->addItem(tr("Winged Shadow How High")); - } - else { - ui->frskyProtoCB->addItem(tr("Winged Shadow How High (not supported)")); - } + if (firmware->getCapability(Telemetry)) { + ui->frskyProtoCB->addItem(tr("Winged Shadow How High")); + } + else { + ui->frskyProtoCB->addItem(tr("Winged Shadow How High (not supported)")); + } - ui->variousGB->hide(); + ui->variousGB->hide(); - lock = false; + lock = false; } void TelemetryPanel::populateVarioSource() @@ -973,6 +983,7 @@ void TelemetryPanel::on_clearAllSensors() } update(); + emit updateDataModels(); emit modified(); } @@ -983,6 +994,7 @@ void TelemetryPanel::on_insertSensor(int selectedIndex) model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); update(); + emit updateDataModels(); emit modified(); } @@ -996,6 +1008,7 @@ void TelemetryPanel::on_deleteSensor(int selectedIndex) model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); update(); + emit updateDataModels(); emit modified(); } @@ -1019,6 +1032,7 @@ void TelemetryPanel::swapData(int idx1, int idx2) memcpy(sd1, &sdtmp, sizeof(SensorData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); update(); + emit updateDataModels(); emit modified(); } } diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h index cddade217..758c0bc51 100644 --- a/companion/src/modeledit/telemetry.h +++ b/companion/src/modeledit/telemetry.h @@ -27,7 +27,8 @@ constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor"; class AutoComboBox; -class RawSourceFilterItemModel; +class RawSourceItemModel; +class RawItemFilteredModel; class TimerEdit; namespace Ui { @@ -41,7 +42,7 @@ class TelemetryCustomScreen: public ModelPanel Q_OBJECT public: - TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawSourceFilterItemModel * srcModel); + TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel); ~TelemetryCustomScreen(); void update(); @@ -53,6 +54,8 @@ class TelemetryCustomScreen: public ModelPanel void barMinChanged(double value); void barMaxChanged(double value); void barTimeChanged(); + void onModelDataAboutToBeUpdated(); + void onModelDataUpdateComplete(); private: void updateBar(int line); @@ -122,12 +125,14 @@ class TelemetryPanel : public ModelPanel Q_OBJECT public: - TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, RawSourceItemModel * rawSourceItemModel); virtual ~TelemetryPanel(); virtual void update(); signals: void updated(); + void updateDataModels(); + private slots: void on_telemetryProtocol_currentIndexChanged(int index); @@ -154,6 +159,7 @@ class TelemetryPanel : public ModelPanel TelemetryCustomScreen * telemetryCustomScreens[4]; TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS]; int sensorCapability; + RawItemFilteredModel * rawSourceModel; void setup(); void telBarUpdate();