From 81c33b6432198a77409cc79adc9af3973174cc08 Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Wed, 11 Jul 2018 06:38:10 -0400 Subject: [PATCH] [Companion] Refactor RawSwitchItemModel and RawSwitchFilterItemModel for better efficiency, does not invalidate whole model on updates (structure is almost identical to the RawSource variants). --- companion/src/firmwares/rawswitch.cpp | 2 +- companion/src/firmwares/rawswitch.h | 15 ++- companion/src/modeledit/CMakeLists.txt | 1 + companion/src/modeledit/customfunctions.cpp | 2 +- companion/src/modeledit/expodialog.cpp | 2 +- companion/src/modeledit/flightmodes.cpp | 2 +- companion/src/modeledit/logicalswitches.cpp | 2 +- companion/src/modeledit/mixerdialog.cpp | 2 +- companion/src/modeledit/setup.cpp | 2 +- companion/src/modeledit/switchitemmodel.cpp | 133 ++++++++++++-------- companion/src/modeledit/switchitemmodel.h | 45 ++++--- 11 files changed, 130 insertions(+), 78 deletions(-) diff --git a/companion/src/firmwares/rawswitch.cpp b/companion/src/firmwares/rawswitch.cpp index 497da9051..66b4fc6e3 100644 --- a/companion/src/firmwares/rawswitch.cpp +++ b/companion/src/firmwares/rawswitch.cpp @@ -142,7 +142,7 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen } } -bool RawSwitch::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) +bool RawSwitch::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const { if (board == Board::BOARD_UNKNOWN) board = getCurrentBoard(); diff --git a/companion/src/firmwares/rawswitch.h b/companion/src/firmwares/rawswitch.h index b05ed4eae..f3f4a9aad 100644 --- a/companion/src/firmwares/rawswitch.h +++ b/companion/src/firmwares/rawswitch.h @@ -52,6 +52,19 @@ class RawSwitch { Q_DECLARE_TR_FUNCTIONS(RawSwitch) public: + enum SwitchContext + { + NoSwitchContext = 0, + LogicalSwitchesContext = 0x01, + SpecialFunctionsContext = 0x02, + GlobalFunctionsContext = 0x04, + TimersContext = 0x08, + MixesContext = 0x10, + + AllModelContexts = SpecialFunctionsContext | LogicalSwitchesContext | TimersContext | MixesContext, + AllSwitchContexts = AllModelContexts | GlobalFunctionsContext + }; + RawSwitch(): type(SWITCH_TYPE_NONE), index(0) @@ -77,7 +90,7 @@ class RawSwitch { RawSwitch convert(RadioDataConversionState & cstate); QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL) const; - bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN); + bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const; bool operator== ( const RawSwitch& other) { return (this->type == other.type) && (this->index == other.index); diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt index a69127b31..1ecdc2c48 100644 --- a/companion/src/modeledit/CMakeLists.txt +++ b/companion/src/modeledit/CMakeLists.txt @@ -29,6 +29,7 @@ set(modeledit_SRCS ) set(modeledit_HDRS + switchitemmodel.h flightmodes.h inputs.h mixes.h diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 113403787..e5510c656 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -77,7 +77,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, lock = true; int num_fsw = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions); - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, model, model ? SpecialFunctionsContext : GlobalFunctionsContext); + 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); diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index 6e2a41ce8..1b087d28e 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -63,7 +63,7 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G curveGroup = new CurveGroup(ui->curveTypeCB, 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, MixesContext)); + ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->sideCB->setCurrentIndex(ed->mode-1); diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index e084e0351..10b3488ee 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -53,7 +53,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI // Phase switch if (phaseIdx > 0) { - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, MixesContext); + rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this); ui->swtch->setModel(rawSwitchItemModel); ui->swtch->setCurrentIndex(ui->swtch->findData(phase.swtch.toValue())); connect(ui->swtch, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseSwitch_currentIndexChanged(int))); diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index c060cfb95..84594466c 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -31,7 +31,7 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, { Stopwatch s1("LogicalSwitchesPanel"); - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, LogicalSwitchesContext); + rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::LogicalSwitchesContext, this); const unsigned srcGroups = firmware->getCapability(GvarsInCS) ? RawSource::AllSourceGroups : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup); rawSourceItemModel = new RawSourceFilterItemModel(&generalSettings, &model, srcGroups, this); diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index 0a424087f..7ff917a43 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -105,7 +105,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, } } - ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, MixesContext)); + ui->switchesCB->setModel(new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::MixesContext, this)); 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/setup.cpp b/companion/src/modeledit/setup.cpp index 911ffb01d..e2b48cb8f 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -50,7 +50,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge } // Mode - rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, TimersContext); + rawSwitchItemModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this); ui->mode->setModel(rawSwitchItemModel); ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue())); diff --git a/companion/src/modeledit/switchitemmodel.cpp b/companion/src/modeledit/switchitemmodel.cpp index 3220ea0c7..183cc20cf 100644 --- a/companion/src/modeledit/switchitemmodel.cpp +++ b/companion/src/modeledit/switchitemmodel.cpp @@ -21,7 +21,8 @@ #include "switchitemmodel.h" #include "eeprominterface.h" -RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData): +RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : + QStandardItemModel(parent), generalSettings(generalSettings), modelData(modelData) { @@ -58,78 +59,110 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett add(SWITCH_TYPE_ONE, 1); } +void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const +{ + const Board::Type board = getCurrentBoard(); + item->setText(rsw.toString(board, generalSettings, modelData)); + item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole); +} + void RawSwitchItemModel::add(const RawSwitchType & type, int count) { // Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule: const static QVector rawSwitchIndexBaseZeroTypes = QVector() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE; - int rawIdxAdj = 0; - const Board::Type board = getCurrentBoard(); - int i = (count < 0 ? count : 1); - const int maxCount = (i < 0 ? 0 : count + i); - // handle exceptions in RawSwitch() index values - if (rawSwitchIndexBaseZeroTypes.contains(type)) - rawIdxAdj = -1; + const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0; - for ( ; i < maxCount; ++i) { + // determine cotext flags + unsigned context = RawSwitch::AllSwitchContexts; + switch (type) { + case SWITCH_TYPE_FLIGHT_MODE: + context &= ~RawSwitch::MixesContext; + // fallthrough + case SWITCH_TYPE_VIRTUAL: + case SWITCH_TYPE_SENSOR: + context &= ~RawSwitch::GlobalFunctionsContext; + break; + + case SWITCH_TYPE_TIMER_MODE: + context = RawSwitch::TimersContext; + break; + + case SWITCH_TYPE_NONE: + context &= ~RawSwitch::TimersContext; + break; + + case SWITCH_TYPE_ON: + case SWITCH_TYPE_ONE: + context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext; + break; + + default: + break; + } + + int i = (count < 0 ? count : 1); + count = (i < 0 ? 0 : count + i); + for ( ; i < count; ++i) { RawSwitch rs(type, i + rawIdxAdj); - QStandardItem * modelItem = new QStandardItem(rs.toString(board, generalSettings, modelData)); - modelItem->setData(rs.toValue(), Qt::UserRole); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(rs.toValue(), ItemIdRole); + modelItem->setData(type, ItemTypeRole); + modelItem->setData(context, ContextRole); + setDynamicItemData(modelItem, rs); appendRow(modelItem); } } -void RawSwitchItemModel::update() +void RawSwitchItemModel::update() const { - for (int i=0; idata(Qt::UserRole).toInt()); - modelItem->setText(swtch.toString(getCurrentBoard(), generalSettings, modelData)); - } + for (int i=0; i < rowCount(); ++i) + setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt())); } -RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, SwitchContext context): - generalSettings(generalSettings), - modelData(modelData), - context(context), - parent(new RawSwitchItemModel(generalSettings, modelData)) + +// +// RawSwitchFilterItemModel +// + +RawSwitchFilterItemModel::RawSwitchFilterItemModel(QAbstractItemModel * sourceModel, RawSwitch::SwitchContext context, QObject * parent) : + QSortFilterProxyModel(parent) { - setSourceModel(parent); - setDynamicSortFilter(false); + setFilterRole(RawSwitchItemModel::IsAvailableRole); + setFilterKeyColumn(0); + setSwitchContext(context); + setDynamicSortFilter(true); + setSourceModel(sourceModel); +} + +RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, RawSwitch::SwitchContext context, QObject * parent): + RawSwitchFilterItemModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent) +{ +} + +void RawSwitchFilterItemModel::setSwitchContext(RawSwitch::SwitchContext ctxt) +{ + if (ctxt != context) { + context = ctxt; + invalidateFilter(); + } } bool RawSwitchFilterItemModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const { - QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - RawSwitch swtch(sourceModel()->data(index, Qt::UserRole).toInt()); - - if (swtch.type == SWITCH_TYPE_FLIGHT_MODE && (context == MixesContext || context == GlobalFunctionsContext)) + const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent); + if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool()) return false; - if (swtch.type == SWITCH_TYPE_VIRTUAL && context == GlobalFunctionsContext) - return false; - - if (swtch.type == SWITCH_TYPE_TIMER_MODE && context != TimersContext) - return false; - - if (swtch.type == SWITCH_TYPE_NONE && context == TimersContext) - return false; - - if (swtch.type == SWITCH_TYPE_SENSOR && context == GlobalFunctionsContext) - return false; - - if ((swtch.type == SWITCH_TYPE_ON || swtch.type == SWITCH_TYPE_ONE) && (context != SpecialFunctionsContext && context != GlobalFunctionsContext)) - return false; - - if (!swtch.isAvailable(modelData, generalSettings, getCurrentBoard())) - return false; - - return true; + bool ok; + const RawSwitch::SwitchContext ctxt = RawSwitch::SwitchContext(sourceModel()->data(srcIdx, RawSwitchItemModel::ContextRole).toUInt(&ok)); + return (ok && (ctxt == RawSwitch::AllSwitchContexts || context != RawSwitch::NoSwitchContext || (context & ctxt))); } -void RawSwitchFilterItemModel::update() +void RawSwitchFilterItemModel::update() const { - parent->update(); - invalidate(); + RawSwitchItemModel * model = qobject_cast(sourceModel()); + if (model) + model->update(); } diff --git a/companion/src/modeledit/switchitemmodel.h b/companion/src/modeledit/switchitemmodel.h index 4ac53b910..b9c78008c 100644 --- a/companion/src/modeledit/switchitemmodel.h +++ b/companion/src/modeledit/switchitemmodel.h @@ -20,39 +20,44 @@ #include #include -#include "radiodata.h" +#include "rawswitch.h" -enum SwitchContext +class GeneralSettings; +class ModelData; + +class RawSwitchItemModel: public QStandardItemModel { - LogicalSwitchesContext, - SpecialFunctionsContext, - GlobalFunctionsContext, - TimersContext, - MixesContext -}; - -class RawSwitchItemModel: public QStandardItemModel { + Q_OBJECT public: - RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData); - void update(); + enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ContextRole, IsAvailableRole }; + Q_ENUM(DataRoles) + + RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); + + public slots: + void update() const; protected: + void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; void add(const RawSwitchType & type, int count); const GeneralSettings * generalSettings; const ModelData * modelData; }; -class RawSwitchFilterItemModel: public QSortFilterProxyModel { +class RawSwitchFilterItemModel: public QSortFilterProxyModel +{ + Q_OBJECT public: - RawSwitchFilterItemModel(const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL, SwitchContext context = LogicalSwitchesContext); - void update(); + RawSwitchFilterItemModel(QAbstractItemModel * sourceModel, RawSwitch::SwitchContext context, QObject * parent = nullptr); + RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, RawSwitch::SwitchContext context, QObject * parent = nullptr); + + public slots: + void setSwitchContext(RawSwitch::SwitchContext ctxt); + void update() const; protected: - const GeneralSettings * generalSettings; - const ModelData * modelData; - SwitchContext context; - RawSwitchItemModel * parent; - bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; + + RawSwitch::SwitchContext context = RawSwitch::NoSwitchContext; };