[Companion] Refactor RawSwitchItemModel and RawSwitchFilterItemModel for better efficiency, does not invalidate whole model on updates (structure is almost identical to the RawSource variants).

This commit is contained in:
Max Paperno
2018-07-12 13:20:07 -04:00
parent b76a0a8789
commit 81c33b6432
11 changed files with 130 additions and 78 deletions
+1 -1
View File
@@ -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();
+14 -1
View File
@@ -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);
+1
View File
@@ -29,6 +29,7 @@ set(modeledit_SRCS
)
set(modeledit_HDRS
switchitemmodel.h
flightmodes.h
inputs.h
mixes.h
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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)));
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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()));
+83 -50
View File
@@ -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<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << 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; i<rowCount(); i++) {
QStandardItem * modelItem = item(i, 0);
RawSwitch swtch(modelItem->data(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<RawSwitchItemModel *>(sourceModel());
if (model)
model->update();
}
+25 -20
View File
@@ -20,39 +20,44 @@
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#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;
};