diff --git a/CREDITS.txt b/CREDITS.txt index da2a9413c..8d764caac 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2052,3 +2052,6 @@ Robert Rubio Dennis G Miller Leonardo Garcia Osuna Antonio Carrasco Pastor +Musa Pinar +Jens Moder +Josef de Beer diff --git a/companion/src/datamodels/CMakeLists.txt b/companion/src/datamodels/CMakeLists.txt index beb7d4d2d..446f161b3 100644 --- a/companion/src/datamodels/CMakeLists.txt +++ b/companion/src/datamodels/CMakeLists.txt @@ -1,12 +1,12 @@ set(datamodels_SRCS - rawitemdatamodels.cpp - rawitemfilteredmodel.cpp + compounditemmodels.cpp + filtereditemmodels.cpp ) set(datamodels_HDRS - rawitemdatamodels.h - rawitemfilteredmodel.h + compounditemmodels.h + filtereditemmodels.h ) qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS}) diff --git a/companion/src/datamodels/compounditemmodels.cpp b/companion/src/datamodels/compounditemmodels.cpp new file mode 100644 index 000000000..039e90244 --- /dev/null +++ b/companion/src/datamodels/compounditemmodels.cpp @@ -0,0 +1,705 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "compounditemmodels.h" +#include "generalsettings.h" +#include "eeprominterface.h" +#include "modeldata.h" +#include "adjustmentreference.h" + +// static +QString AbstractItemModel::idToString(const int value) +{ + switch (value) { + case IMID_Unknown: + return "Unknown"; + case IMID_RawSource: + return "RawSource"; + case IMID_RawSwitch: + return "RawSwitch"; + case IMID_Curve: + return "Curve"; + case IMID_GVarRef: + return "GVarRef"; + case IMID_ThrSource: + return "ThrSource"; + case IMID_CustomFuncAction: + return "CustomFuncAction"; + case IMID_CustomFuncResetParam: + return "CustomFuncResetParam"; + case IMID_TeleSource: + return "TeleSource"; + case IMID_CurveRefType: + return "CurveRefType"; + case IMID_CurveRefFunc: + return "CurveRefFunc"; + default: + return "Custom"; + } +} + +// static +void AbstractItemModel::dumpItemModelContents(AbstractItemModel * itemModel) +{ + if (itemModel) { + qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName(); + + for (int i = 0; i < itemModel->rowCount(); ++i) { + qDebug() << "row:" << i + << "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString() + << "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt() + << "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool() + << "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt() + << "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt(); + } + } + else + qDebug() << "Error: model not of class AbstractItemModel"; +} + +// +// AbstractStaticItemModel +// + +void AbstractStaticItemModel::loadItemList() +{ + foreach (const ListItem *item, itemList) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(item->text); + modelItem->setData(item->id, IMDR_Id); + modelItem->setData(item->type, IMDR_Type); + modelItem->setData(item->flags, IMDR_Flags); + modelItem->setData(item->isAvailable, IMDR_Available); + appendRow(modelItem); + } + + itemList.clear(); +}; + +// +// RawSourceItemModel +// + +RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_RawSource); + setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts)); + + addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); + for (int i = 0; i < firmware->getCapability(LuaScripts); i++) + addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16); + addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs)); + addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs)); + addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, firmware->getCapability(RotaryEncoders)); + addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims)); + addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1); + addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches)); + addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches)); + addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC); + addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs)); + addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, firmware->getCapability(Outputs)); + addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5); + addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, firmware->getCapability(Sensors) * 3); + addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, firmware->getCapability(Gvars)); +} + +void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const +{ + item->setText(src.toString(modelData, generalSettings, boardType)); + item->setData(src.isAvailable(modelData, generalSettings, boardType), IMDR_Available); +} + +void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start) +{ + for (int i = start; i < start + count; i++) { + const RawSource src = RawSource(type, i); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(src.toValue(), IMDR_Id); + modelItem->setData(type, IMDR_Type); + modelItem->setData(group, IMDR_Flags); + setDynamicItemData(modelItem, src); + appendRow(modelItem); + } +} + +void RawSourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), RawSource(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// RawSwitchItemModel +// + +RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_RawSwitch); + setUpdateMask(IMUE_FlightModes | IMUE_LogicalSwitches | IMUE_TeleSensors); + + // Descending switch direction: NOT (!) switches + addItems(SWITCH_TYPE_ACT, -1); + addItems(SWITCH_TYPE_SENSOR, -firmware->getCapability(Sensors)); + addItems(SWITCH_TYPE_TELEMETRY, -1); + addItems(SWITCH_TYPE_FLIGHT_MODE, -firmware->getCapability(FlightModes)); + addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches)); + addItems(SWITCH_TYPE_ROTARY_ENCODER, -firmware->getCapability(RotaryEncoders)); + addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches)); + addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions))); + addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions)); + + // Ascending switch direction (including zero) + addItems(SWITCH_TYPE_TIMER_MODE, 5); + addItems(SWITCH_TYPE_NONE, 1); + addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions)); + addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)); + addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches)); + addItems(SWITCH_TYPE_ROTARY_ENCODER, firmware->getCapability(RotaryEncoders)); + addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches)); + addItems(SWITCH_TYPE_FLIGHT_MODE, firmware->getCapability(FlightModes)); + addItems(SWITCH_TYPE_TELEMETRY, 1); + addItems(SWITCH_TYPE_SENSOR, firmware->getCapability(Sensors)); + addItems(SWITCH_TYPE_ON, 1); + addItems(SWITCH_TYPE_ONE, 1); + addItems(SWITCH_TYPE_ACT, 1); +} + +void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const +{ + item->setText(rsw.toString(boardType, generalSettings, modelData)); + item->setData(rsw.isAvailable(modelData, generalSettings, boardType), IMDR_Available); +} + +void RawSwitchItemModel::addItems(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; + // handle exceptions in RawSwitch() index values + const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0; + + // determine cotext flags + int 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(); + modelItem->setData(rs.toValue(), IMDR_Id); + modelItem->setData(type, IMDR_Type); + modelItem->setData(context, IMDR_Flags); + setDynamicItemData(modelItem, rs); + appendRow(modelItem); + } +} + +void RawSwitchItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), RawSwitch(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// CurveItemModel +// + +CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_Curve); + + if (!modelData) + return; + + setUpdateMask(IMUE_Curves); + + const int count = firmware->getCapability(NumCurves); + + for (int i = -count ; i <= count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CurveItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, value); + item->setText(cr.toString(modelData, false)); + item->setData(cr.isAvailable(), IMDR_Available); +} + +void CurveItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// GVarReferenceItemModel +// + +GVarReferenceItemModel::GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_GVarRef); + + if (!modelData) + return; + + setUpdateMask(IMUE_GVars | IMUE_FlightModes | IMUE_LogicalSwitches); + + const int count = firmware->getCapability(Gvars); + + if (count > 0) { + addItems(-count); + addItems(count); + } +} + +void GVarReferenceItemModel::addItems(int count) +{ + int i = (count < 0 ? count : 1); + count = (i < 0 ? 0 : count + i); + for ( ; i < count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + AdjustmentReference ar(AdjustmentReference::ADJUST_REF_GVAR, i); + modelItem->setData(ar.toValue(), IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, ar); + appendRow(modelItem); + } +} + +void GVarReferenceItemModel::setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const +{ + item->setText(ar.toString(modelData, false)); + item->setData(ar.isAvailable(), IMDR_Available); +} + +void GVarReferenceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), AdjustmentReference(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// ThrottleSourceItemModel +// + +ThrottleSourceItemModel::ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_ThrSource); + + if (!modelData) + return; + + setUpdateMask(IMUE_Timers | IMUE_Inputs | IMUE_TeleSensors); + + for (int i = 0; i < modelData->thrTraceSrcCount(); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void ThrottleSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(modelData->thrTraceSrcToString(value)); + item->setData(modelData->isThrTraceSrcAvailable(generalSettings, value), IMDR_Available); +} + +void ThrottleSourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// CustomFuncActionItemModel +// + +CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CustomFuncAction); + setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts)); + + for (int i = 0; i < AssignFunc::FuncCount; i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CustomFunctionData::funcContext(i), IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(CustomFunctionData(AssignFunc(value)).funcToString(modelData)); + item->setData(CustomFunctionData::isFuncAvailable(value), IMDR_Available); +} + +void CustomFuncActionItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// CustomFuncResetParamItemModel +// + +CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CustomFuncResetParam); + setUpdateMask(IMUE_TeleSensors); + + for (int i = 0; i < CustomFunctionData::resetParamCount(modelData); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + CustomFunctionData cfd = CustomFunctionData(AssignFunc::FuncReset); + cfd.param = value; + item->setText(cfd.paramToString(modelData)); + item->setData(CustomFunctionData::isResetParamAvailable(modelData, value), IMDR_Available); +} + +void CustomFuncResetParamItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// TelemetrySourceItemModel +// + +TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_TeleSource); + + if (!modelData) + return; + + setUpdateMask(IMUE_TeleSensors); + const int count = firmware->getCapability(Sensors); + + for (int i = -count; i <= count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(SensorData::sourceToString(modelData, value)); + item->setData(SensorData::isSourceAvailable(modelData, value), IMDR_Available); +} + +void TelemetrySourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) { + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + } + + emit updateComplete(); + } +} + +// +// CurveRefTypeItemModel +// + +CurveRefTypeItemModel::CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CurveRefType); + + for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(CurveReference::typeToString((CurveReference::CurveRefType)i)); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CurveReference::isTypeAvailable((CurveReference::CurveRefType)i), IMDR_Available); + appendRow(modelItem); + } +} + +// +// CurveRefFuncItemModel +// + +CurveRefFuncItemModel::CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CurveRefFunc); + + for (int i = 1; i <= CurveReference::functionCount(); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(CurveReference::functionToString(i)); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CurveReference::isFunctionAvailable(i), IMDR_Available); + appendRow(modelItem); + } +} + +// +// PrecisionItemModel +// + +PrecisionItemModel::PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix, const bool placeholders) : + AbstractStaticItemModel() +{ + for (int i = minDecimals, j = maxDecimals; j >= 0; i++, j--) { + QString str = QString("0.%1").arg(QString(i, '0')); + if (placeholders) + str.append(QString(j, '_')); + if (!suffix.isEmpty()) + str.append(QString(" %1").arg(suffix)); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(str); + modelItem->setData(i, IMDR_Id); + modelItem->setData(true, IMDR_Available); + appendRow(modelItem); + } +} + +// +// CompoundItemModelFactory +// + +CompoundItemModelFactory::CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData) : + generalSettings(generalSettings), + modelData(modelData) +{ + firmware = getCurrentFirmware(); + board = new Boards(getCurrentBoard()); + boardType = getCurrentBoard(); +} + +CompoundItemModelFactory::~CompoundItemModelFactory() +{ + unregisterItemModels(); + delete board; +} + +void CompoundItemModelFactory::addItemModel(const int id) +{ + switch (id) { + case AbstractItemModel::IMID_RawSource: + registerItemModel(new RawSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_RawSwitch: + registerItemModel(new RawSwitchItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_Curve: + registerItemModel(new CurveItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_GVarRef: + registerItemModel(new GVarReferenceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_ThrSource: + registerItemModel(new ThrottleSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CustomFuncAction: + registerItemModel(new CustomFuncActionItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CustomFuncResetParam: + registerItemModel(new CustomFuncResetParamItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_TeleSource: + registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CurveRefType: + registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CurveRefFunc: + registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + default: + qDebug() << "Error: unknown item model: id"; + break; + } +} + +int CompoundItemModelFactory::registerItemModel(AbstractItemModel * itemModel) +{ + if (itemModel) { + if (!isItemModelRegistered(itemModel->getId())) { + setSourceId(itemModel); + registeredItemModels.append(itemModel); + return itemModel->getId(); + } + else + return itemModel->getId(); + } + return -1; +} + +void CompoundItemModelFactory::unregisterItemModels() +{ + foreach (AbstractItemModel *itemModel, registeredItemModels) { + delete itemModel; + } +} + +void CompoundItemModelFactory::unregisterItemModel(const int id) +{ + AbstractItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +AbstractItemModel * CompoundItemModelFactory::getItemModel(const int id) const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +bool CompoundItemModelFactory::isItemModelRegistered(const int id) const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return true; + } + + return false; +} + +void CompoundItemModelFactory::update(const int event) +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + itemModel->update(event); + } +} + +void CompoundItemModelFactory::dumpAllItemModelContents() const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + AbstractItemModel::dumpItemModelContents(itemModel); + } +} + +void CompoundItemModelFactory::setSourceId(AbstractItemModel * itemModel) +{ + if (itemModel && itemModel->getId() == AbstractItemModel::IMID_Unknown) + itemModel->setId(AbstractItemModel::IMID_ReservedCount + registeredItemModels.count()); +} diff --git a/companion/src/datamodels/compounditemmodels.h b/companion/src/datamodels/compounditemmodels.h new file mode 100644 index 000000000..de32fc902 --- /dev/null +++ b/companion/src/datamodels/compounditemmodels.h @@ -0,0 +1,365 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef COMPOUNDITEMMODELS_H +#define COMPOUNDITEMMODELS_H + +#include "rawsource.h" +#include "rawswitch.h" + +#include + +class GeneralSettings; +class ModelData; +class AdjustmentReference; + +class AbstractItemModel: public QStandardItemModel +{ + Q_OBJECT + public: + enum ItemModelId { + IMID_Unknown, + IMID_RawSource, + IMID_RawSwitch, + IMID_Curve, + IMID_GVarRef, + IMID_ThrSource, + IMID_CustomFuncAction, + IMID_CustomFuncResetParam, + IMID_TeleSource, + IMID_CurveRefType, + IMID_CurveRefFunc, + IMID_ReservedCount, + IMID_Custom + }; + Q_ENUM(ItemModelId) + + enum ItemModelDataRoles { + IMDR_Id = Qt::UserRole, + IMDR_Type, + IMDR_Flags, + IMDR_Available + }; + Q_ENUM(ItemModelDataRoles) + + enum ItemModelDataGroups { + IMDG_None = 0x01, + IMDG_Negative = 0x02, + IMDG_Positive = 0x04 + }; + Q_ENUM(ItemModelDataGroups) + + enum ItemModelUpdateEvent { + IMUE_None = 0, + IMUE_SystemRefresh = 1 << 0, + IMUE_Channels = 1 << 1, + IMUE_Curves = 1 << 2, + IMUE_FlightModes = 1 << 3, + IMUE_GVars = 1 << 4, + IMUE_Inputs = 1 << 5, + IMUE_LogicalSwitches = 1 << 6, + IMUE_Scripts = 1 << 7, + IMUE_TeleSensors = 1 << 8, + IMUE_Timers = 1 << 9, + IMUE_All = IMUE_SystemRefresh | IMUE_Channels | IMUE_Curves | IMUE_FlightModes | IMUE_GVars | IMUE_Inputs | + IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers + }; + Q_ENUM(ItemModelUpdateEvent) + + explicit AbstractItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + QStandardItemModel(nullptr), + generalSettings(generalSettings), + modelData(modelData), + firmware(firmware), + board(board), + boardType(boardType), + m_id(IMID_Unknown), + m_name(""), + m_updateMask(IMUE_None) + {} + + virtual ~AbstractItemModel() {} + + void setId(int id) { m_id = id; } + int getId () const { return m_id; } + bool isReservedModelId() const { return m_id > IMID_Unknown && m_id < IMID_ReservedCount; } + void setName(QString name) { m_name = name; } + QString getName() const { return isReservedModelId() ? idToString(m_id) : m_name; } + void setUpdateMask(const int mask) { m_updateMask = mask; } + int getUpdateMask() const { return m_updateMask; } + + inline bool doUpdate(const int event) const { return m_updateMask & event; } + + AbstractItemModel * getItemModel(const int id) const; + + static void dumpItemModelContents(AbstractItemModel * itemModel); + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) = 0; + + protected: + const GeneralSettings * generalSettings; + const ModelData * modelData; + Firmware * firmware; + const Boards * board; + const Board::Type boardType; + + private: + int m_id = IMID_Unknown; + QString m_name = ""; + int m_updateMask = IMUE_None; + + static QString idToString(const int value); +}; + +class AbstractStaticItemModel: public AbstractItemModel +{ + Q_OBJECT + public: + explicit AbstractStaticItemModel(const GeneralSettings * const generalSettings = nullptr, const ModelData * const modelData = nullptr, + Firmware * firmware = nullptr, const Boards * const board = nullptr, + const Board::Type boardType = Board::BOARD_UNKNOWN) : + AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {} + virtual ~AbstractStaticItemModel() {}; + + inline void appendToItemList(QString text, int id, bool isAvailable = true, int type = 0, int flags = 0) + { itemList.append(new ListItem(text, id, isAvailable, type, flags)); } + + void loadItemList(); + + public slots: + virtual void update(const int event) override final {} + + protected: + struct ListItem + { + QString text; + int id; + bool isAvailable; + int type; + int flags; + + ListItem() {} + ListItem(QString p_text, int p_id, bool p_isAvailable, int p_type, int p_flags) : + text(p_text), id(p_id), isAvailable(p_isAvailable), type(p_type), flags(p_flags) {} + }; + + QVector itemList; +}; + +class AbstractDynamicItemModel: public AbstractItemModel +{ + Q_OBJECT + public: + explicit AbstractDynamicItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {} + virtual ~AbstractDynamicItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) {} + + signals: + void aboutToBeUpdated(); + void updateComplete(); +}; + +class RawSourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~RawSourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const RawSource & src) const; + void addItems(const RawSourceType & type, const int group, const int count, const int start = 0); +}; + +class RawSwitchItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~RawSwitchItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; + void addItems(const RawSwitchType & type, int count); +}; + +class CurveItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class GVarReferenceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~GVarReferenceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const; + void addItems(int count); +}; + +class ThrottleSourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~ThrottleSourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CustomFuncActionItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CustomFuncActionItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CustomFuncResetParamItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CustomFuncResetParamItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class TelemetrySourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~TelemetrySourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CurveRefTypeItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveRefTypeItemModel() {}; +}; + +class CurveRefFuncItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveRefFuncItemModel() {}; +}; + +class PrecisionItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix = "", const bool placeholders = false); + virtual ~PrecisionItemModel() {}; +}; + +// +// CompoundItemModelFactory +// + +class CompoundItemModelFactory +{ + public: + CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData); + virtual ~CompoundItemModelFactory(); + + void addItemModel(const int id); + int registerItemModel(AbstractItemModel * itemModel); + void unregisterItemModels(); + void unregisterItemModel(const int id); + bool isItemModelRegistered(const int id) const; + AbstractItemModel * getItemModel(const int id) const; + void update(const int event = AbstractItemModel::IMUE_SystemRefresh); + void dumpAllItemModelContents() const; + + protected: + const GeneralSettings * generalSettings; + const ModelData * modelData; + Firmware * firmware; + Boards * board; + Board::Type boardType; + QVector registeredItemModels; + + private: + void setSourceId(AbstractItemModel * itemModel); +}; + +#endif // COMPOUNDITEMMODELS_H diff --git a/companion/src/datamodels/filtereditemmodels.cpp b/companion/src/datamodels/filtereditemmodels.cpp new file mode 100644 index 000000000..4f4e27262 --- /dev/null +++ b/companion/src/datamodels/filtereditemmodels.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "filtereditemmodels.h" + +FilteredItemModel::FilteredItemModel(AbstractItemModel * sourceModel, int flags) : + QSortFilterProxyModel(nullptr), + filterFlags(0), + m_id(0), + m_name("") +{ + setFilterRole(AbstractItemModel::IMDR_Available); + setFilterKeyColumn(0); + setFilterFlags(flags); + setDynamicSortFilter(true); + setSourceModel(sourceModel); + + AbstractDynamicItemModel * itemModel = qobject_cast(sourceModel); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &FilteredItemModel::onAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &FilteredItemModel::onUpdateComplete); + } +} + +void FilteredItemModel::setFilterFlags(int flags) +{ + if (filterFlags != flags) { + filterFlags = flags; + invalidateFilter(); + } +} + +bool FilteredItemModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const +{ + const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent); + if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool()) + return false; + + if (!filterFlags) + return true; + + bool ok; + const int flags = sourceModel()->data(srcIdx, AbstractItemModel::IMDR_Flags).toInt(&ok); + return (ok && (!flags || (filterFlags & flags))); +} + +void FilteredItemModel::update() const +{ + AbstractDynamicItemModel * itemModel = qobject_cast(sourceModel()); + if (itemModel) + itemModel->update(); +} + +void FilteredItemModel::onAboutToBeUpdated() +{ + emit aboutToBeUpdated(); +} + +void FilteredItemModel::onUpdateComplete() +{ + emit updateComplete(); +} + +// static +void FilteredItemModel::dumpItemModelContents(FilteredItemModel * itemModel) +{ + if (itemModel) { + qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName(); + + for (int i = 0; i < itemModel->rowCount(); ++i) { + qDebug() << "row:" << i + << "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString() + << "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt() + << "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool() + << "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt() + << "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt(); + } + } + else + qDebug() << "Error: model not of class FilteredItemModel"; +} + +// +// FilteredItemModelFactory +// + +FilteredItemModelFactory::FilteredItemModelFactory() +{ +} + +FilteredItemModelFactory::~FilteredItemModelFactory() +{ + unregisterItemModels(); +} + +int FilteredItemModelFactory::registerItemModel(FilteredItemModel * itemModel, const QString name, const int id) +{ + if (itemModel) { + if (isItemModelRegistered(name)) { + qDebug() << "Error: item model already registered with name:" << name; + return 0; + } + else if (id > -1 && isItemModelRegistered(id)) { + qDebug() << "Error: item model already registered with id:" << id; + return 0; + } + else { + int fid = id; + if (fid < 0) { + fid = registeredItemModels.count() + 1; + AbstractItemModel * mdl = qobject_cast(itemModel->sourceModel()); + if (mdl) { + fid += mdl->getId() * 128; + } + } + itemModel->setId(fid); + itemModel->setName(name); + registeredItemModels.append(itemModel); + return fid; + } + } + + qDebug() << "Error: invalid filtered item model pointer"; + return 0; +} + +void FilteredItemModelFactory::unregisterItemModels() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + delete itemModel; + } +} + +void FilteredItemModelFactory::unregisterItemModel(const int id) +{ + FilteredItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +bool FilteredItemModelFactory::isItemModelRegistered(const int id) const +{ + return getItemModel(id); +} + +bool FilteredItemModelFactory::isItemModelRegistered(const QString name) const +{ + return getItemModel(name); +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const int id) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const QString name) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getName() == name) + return itemModel; + } + + return nullptr; +} + +void FilteredItemModelFactory::update() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + itemModel->update(); + } +} + +void FilteredItemModelFactory::dumpItemModelContents(const int id) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(id)); +} + +void FilteredItemModelFactory::dumpItemModelContents(const QString name) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(name)); +} + +void FilteredItemModelFactory::dumpAllItemModelContents() const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + FilteredItemModel::dumpItemModelContents(itemModel); + } +} + +// +// CurveRefFilteredFactory +// + +CurveRefFilteredFactory::CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags, const int gvarRefFlags) +{ + if (!sharedItemModels) { + qDebug() << "Error: invalid compound item model factory pointer"; + return; + } + + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve), curveFlags), + fidToString(CRFIM_CURVE), CRFIM_CURVE); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef), gvarRefFlags), + fidToString(CRFIM_GVARREF), CRFIM_GVARREF); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefType)), + fidToString(CRFIM_TYPE), CRFIM_TYPE); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefFunc)), + fidToString(CRFIM_FUNC), CRFIM_FUNC); +} + +CurveRefFilteredFactory::~CurveRefFilteredFactory() +{ +} + +// static +QString CurveRefFilteredFactory::fidToString(const int value) +{ + switch(value) { + case CRFIM_CURVE: + return "Curves"; + case CRFIM_GVARREF: + return "Global Variables"; + case CRFIM_TYPE: + return "Types"; + case CRFIM_FUNC: + return "Functions"; + default: + return CPN_STR_UNKNOWN_ITEM; + } +} diff --git a/companion/src/datamodels/filtereditemmodels.h b/companion/src/datamodels/filtereditemmodels.h new file mode 100644 index 000000000..24668704d --- /dev/null +++ b/companion/src/datamodels/filtereditemmodels.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef FILTEREDITEMMODELS_H +#define FILTEREDITEMMODELS_H + +#include "compounditemmodels.h" + +#include +#include +#include + +class FilteredItemModel: public QSortFilterProxyModel +{ + Q_OBJECT + public: + enum DataFilters { + AllFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None | AbstractItemModel::IMDG_Positive, + AllExcludeNoneFilter = AllFilter &~ AbstractItemModel::IMDG_None, + NegativeFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None, + NegativeExcludeNoneFilter = AbstractItemModel::IMDG_Negative, + PositiveFilter = AbstractItemModel::IMDG_Positive | AbstractItemModel::IMDG_None, + PositiveExcludeNoneFilter = AbstractItemModel::IMDG_Positive + }; + Q_ENUM(DataFilters) + + explicit FilteredItemModel(AbstractItemModel * sourceModel, int flags); + explicit FilteredItemModel(AbstractItemModel * sourceModel) : + FilteredItemModel(sourceModel, 0) {} + virtual ~FilteredItemModel() {}; + + void setId(int id) { m_id = id; } + int getId() const { return m_id; }; + void setName(QString name) { m_name = name; } + QString getName() const { return m_name; } + + static void dumpItemModelContents(FilteredItemModel * itemModel); + + public slots: + void setFilterFlags(int flags); + void update() const; + void onAboutToBeUpdated(); + void onUpdateComplete(); + + signals: + void aboutToBeUpdated(); + void updateComplete(); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; + + int filterFlags; + + private: + int m_id = 0; + QString m_name = ""; +}; + +class FilteredItemModelFactory +{ + public: + explicit FilteredItemModelFactory(); + virtual ~FilteredItemModelFactory(); + + int registerItemModel(FilteredItemModel * itemModel, const QString name, const int id = -1); + void unregisterItemModels(); + void unregisterItemModel(const int id); + bool isItemModelRegistered(const int id) const; + bool isItemModelRegistered(const QString name) const; + FilteredItemModel * getItemModel(const int id) const; + FilteredItemModel * getItemModel(const QString name) const; + void update(); + + void dumpItemModelContents(const int id) const; + void dumpItemModelContents(const QString name) const; + void dumpAllItemModelContents() const; + + protected: + QVector registeredItemModels; +}; + +class CurveRefFilteredFactory : public FilteredItemModelFactory +{ + public: + enum FilteredItemModelId { + CRFIM_CURVE, + CRFIM_GVARREF, + CRFIM_TYPE, + CRFIM_FUNC + }; + + explicit CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags = 0, const int gvarRefFlags = 0); + virtual ~CurveRefFilteredFactory(); + + static QString fidToString(const int value); +}; + +#endif // FILTEREDITEMMODELS_H diff --git a/companion/src/datamodels/itemmodelfactory.cpp b/companion/src/datamodels/itemmodelfactory.cpp new file mode 100644 index 000000000..b5b341afd --- /dev/null +++ b/companion/src/datamodels/itemmodelfactory.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "itemmodelfactory.h" + +#include "compounditemmodels.h" +#include "filtereditemmodels.h" + +#include "eeprominterface.h" +#include "generalsettings.h" +#include "modeldata.h" + +ItemModelFactory::ItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData) : + generalSettings(generalSettings), + modelData(modelData) +{ + firmware = getCurrentFirmware(); + board = new Boards(getCurrentBoard()); + boardType = getCurrentBoard(); +} + +ItemModelFactory::~ItemModelFactory() +{ + unregisterItemModels(); + delete board; +} + +void ItemModelFactory::addItemModel(const AbstractItemModel::ItemModelId id) +{ + switch (id) { + case AbstractItemModel::RawSourceId: + registerItemModel(new RawSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::RawSwitchId: + registerItemModel(new RawSwitchItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::CurveId: + registerItemModel(new CurveItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::GVarRefId: + registerItemModel(new GVarReferenceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::ThrSourceId: + registerItemModel(new ThrottleSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::CustomFuncActionId: + registerItemModel(new CustomFuncActionItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::CustomFuncResetParamId: + registerItemModel(new CustomFuncResetParamItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::TeleSourceId: + registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::CurveRefTypeId: + registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::CurveRefFuncId: + registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + default: + qDebug() << "Error: unknown item model: id"; + break; + } +} + +void ItemModelFactory::registerItemModel(QAbstractItemModel * itemModel) +{ + if (itemModel && !getItemModel(itemModel->getId())) { + registeredItemModels.push_back(itemModel); + } +} + +void ItemModelFactory::unregisterItemModels() +{ + foreach (QAbstractItemModel *itemModel, registeredItemModels) { + delete itemModel; + } +} + +void ItemModelFactory::unregisterItemModel(const AbstractItemModel::ItemModelId id) +{ + QAbstractItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +QAbstractItemModel * CompoundItemModelFactory::getItemModel(const AbstractItemModel::ItemModelId id) const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +void ItemModelFactory::update(const AbstractItemModel::UpdateTrigger trigger) +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + itemModel->update(trigger); + } +} + +void ItemModelFactory::dumpAllItemModelContents() const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + AbstractItemModel::dumpItemModelContents(itemModel); + } +} + +// +// FilteredItemModelFactory +// + +FilteredItemModelFactory::FilteredItemModelFactory() +{ +} + +FilteredItemModelFactory::~FilteredItemModelFactory() +{ + unregisterItemModels(); +} + +int FilteredItemModelFactory::registerItemModel(FilteredItemModel * itemModel, QString name) +{ + if (itemModel) { + if (isItemModelRegistered(name)) + qDebug() << "Warning: item model already registered with name:" << name; + const int id = registeredItemModels.count(); + itemModel->setId(id); + itemModel->setName(name); + registeredItemModels.push_back(itemModel); + return id; + } + return 0; +} + +void FilteredItemModelFactory::unregisterItemModels() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + delete itemModel; + } +} + +void FilteredItemModelFactory::unregisterItemModel(const int id) +{ + FilteredItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +bool FilteredItemModelFactory::isItemModelRegistered(const int id) const +{ + return getItemModel(id); +} + +bool FilteredItemModelFactory::isItemModelRegistered(const QString name) const +{ + return getItemModel(name); +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const int id) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const QString name) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getName() == name) + return itemModel; + } + + return nullptr; +} + +void FilteredItemModelFactory::update() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + itemModel->update(); + } +} + +void FilteredItemModelFactory::dumpItemModelContents(const int id) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(id)); +} + +void FilteredItemModelFactory::dumpItemModelContents(const QString name) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(name)); +} + +void FilteredItemModelFactory::dumpAllItemModelContents() const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + FilteredItemModel::dumpItemModelContents(itemModel); + } +} + diff --git a/companion/src/datamodels/itemmodelfactory.h b/companion/src/datamodels/itemmodelfactory.h new file mode 100644 index 000000000..9f03b897b --- /dev/null +++ b/companion/src/datamodels/itemmodelfactory.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef ITEMMODELFACTORY_H +#define ITEMMODELFACTORY_H + +class GeneralSettings; +class ModelData; +class AbstractItemModel; +class FilteredItemModel; + +class ItemModelFactory +{ + public: + ItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData); + virtual ~ItemModelFactory(); + + void addItemModel(const AbstractItemModel::ItemModelId id); + void registerItemModel(AbstractItemModel * itemModel); + void unregisterItemModels(); + void unregisterItemModel(const AbstractItemModel::ItemModelId id); + AbstractItemModel * getItemModel(const AbstractItemModel::ItemModelId id) const; + void update(const AbstractItemModel::UpdateTrigger trigger = AbstractItemModel::SystemRefresh); + void dumpAllItemModelContents() const; + + protected: + const GeneralSettings * generalSettings; + const ModelData * modelData; + Firmware * firmware; + Boards * board; + Board::Type boardType; + QVector registeredItemModels; +}; + +class FilteredItemModelFactory +{ + public: + FilteredItemModelFactory(); + virtual ~FilteredItemModelFactory(); + + int registerItemModel(FilteredItemModel * itemModel, QString name); + void unregisterItemModels(); + void unregisterItemModel(const int id); + bool isItemModelRegistered(const int id) const; + bool isItemModelRegistered(const QString name) const; + FilteredItemModel * getItemModel(const int id) const; + FilteredItemModel * getItemModel(const QString name) const; + void update(); + + void dumpItemModelContents(const int id) const; + void dumpItemModelContents(const QString name) const; + void dumpAllItemModelContents() const; + + protected: + QVector registeredItemModels; +}; + +#endif // ITEMMODELFACTORY_H diff --git a/companion/src/datamodels/rawitemdatamodels.cpp b/companion/src/datamodels/rawitemdatamodels.cpp deleted file mode 100644 index 3805b98d6..000000000 --- a/companion/src/datamodels/rawitemdatamodels.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "rawitemdatamodels.h" -#include "generalsettings.h" -#include "eeprominterface.h" -#include "modeldata.h" -#include "adjustmentreference.h" - -RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - const Boards board = Boards(getCurrentBoard()); - Firmware * fw = getCurrentFirmware(); - - addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); - 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)); - addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders)); - addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims)); - addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1); - addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches)); - addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches)); - addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC); - addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs)); - addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs)); - addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5); - addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, fw->getCapability(Sensors) * 3); - addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars)); -} - -void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const -{ - Board::Type board = getCurrentBoard(); - item->setText(src.toString(modelData, generalSettings, board)); - item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole); -} - -void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start) -{ - for (int i = start; i < start + count; i++) { - const RawSource src = RawSource(type, i); - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(src.toValue(), ItemIdRole); - modelItem->setData(type, ItemTypeRole); - modelItem->setData(group, ItemFlagsRole); - setDynamicItemData(modelItem, src); - appendRow(modelItem); - } -} - -void RawSourceItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt())); - - emit dataUpdateComplete(); -} - - -// -// RawSwitchItemModel -// - -RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - Boards board = Boards(getCurrentBoard()); - Firmware * fw = getCurrentFirmware(); - - // Descending switch direction: NOT (!) switches - addItems(SWITCH_TYPE_ACT, -1); - addItems(SWITCH_TYPE_SENSOR, -fw->getCapability(Sensors)); - addItems(SWITCH_TYPE_TELEMETRY, -1); - addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes)); - addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches)); - addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders)); - addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches)); - addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions))); - addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions)); - - // Ascending switch direction (including zero) - addItems(SWITCH_TYPE_TIMER_MODE, 5); - addItems(SWITCH_TYPE_NONE, 1); - addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions)); - addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)); - addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches)); - addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders)); - addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches)); - addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes)); - addItems(SWITCH_TYPE_TELEMETRY, 1); - addItems(SWITCH_TYPE_SENSOR, fw->getCapability(Sensors)); - addItems(SWITCH_TYPE_ON, 1); - addItems(SWITCH_TYPE_ONE, 1); - addItems(SWITCH_TYPE_ACT, 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::addItems(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; - // handle exceptions in RawSwitch() index values - const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0; - - // determine cotext flags - int 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(); - modelItem->setData(rs.toValue(), ItemIdRole); - modelItem->setData(type, ItemTypeRole); - modelItem->setData(context, ItemFlagsRole); - setDynamicItemData(modelItem, rs); - appendRow(modelItem); - } -} - -void RawSwitchItemModel::update() -{ - 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) -{ - if (!modelData) - return; - - const int count = getCurrentFirmware()->getCapability(NumCurves); - - for (int i = -count ; i <= count; ++i) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - int flags = i < 0 ? DataGroups::NegativeGroup : DataGroups::PositiveGroup; - if (i == 0) - flags |= DataGroups::NoneGroup; - modelItem->setData(flags, ItemFlagsRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void CurveItemModel::setDynamicItemData(QStandardItem * item, const int index) const -{ - CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, index); - item->setText(cr.toString(modelData, false)); - item->setData(cr.isAvailable(), IsAvailableRole); -} - -void CurveItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - - -// -// GVarReferenceItemModel -// - -GVarReferenceItemModel::GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - if (!modelData) - return; - - const int count = getCurrentFirmware()->getCapability(Gvars); - if (count > 0) { - addItems(-count); - addItems(count); - } -} - -void GVarReferenceItemModel::addItems(int count) -{ - int i = (count < 0 ? count : 1); - count = (i < 0 ? 0 : count + i); - for ( ; i < count; ++i) { - QStandardItem * modelItem = new QStandardItem(); - AdjustmentReference ar(AdjustmentReference::ADJUST_REF_GVAR, i); - modelItem->setData(ar.toValue(), ItemIdRole); - modelItem->setData(i < 0 ? DataGroups::NegativeGroup : DataGroups::PositiveGroup, ItemFlagsRole); - setDynamicItemData(modelItem, ar); - appendRow(modelItem); - } -} - -void GVarReferenceItemModel::setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const -{ - item->setText(ar.toString(modelData, false)); - item->setData(ar.isAvailable(), IsAvailableRole); -} - -void GVarReferenceItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), AdjustmentReference(item(i)->data(ItemIdRole).toInt())); - - emit dataUpdateComplete(); -} - - -// -// ThrottleSourceItemModel -// - -ThrottleSourceItemModel::ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - if (!modelData) - return; - - for (int i = 0; i < modelData->thrTraceSrcCount(); i++) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void ThrottleSourceItemModel::setDynamicItemData(QStandardItem * item, const int index) const -{ - item->setText(modelData->thrTraceSrcToString(index)); - item->setData(modelData->isThrTraceSrcAvailable(generalSettings, index), IsAvailableRole); -} - -void ThrottleSourceItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - - -// -// CustomFuncActionItemModel -// - -CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - for (int i = 0; i < AssignFunc::FuncCount; i++) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - modelItem->setData(CustomFunctionData::funcContext(i), ItemFlagsRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int index) const -{ - item->setText(CustomFunctionData(AssignFunc(index)).funcToString(modelData)); - item->setData(CustomFunctionData::isFuncAvailable(index), IsAvailableRole); -} - -void CustomFuncActionItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - - -// -// CustomFuncResetParamItemModel -// - -CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - for (int i = 0; i < CustomFunctionData::resetParamCount(modelData); i++) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int index) const -{ - CustomFunctionData cfd = CustomFunctionData(AssignFunc::FuncReset); - cfd.param = index; - item->setText(cfd.paramToString(modelData)); - item->setData(CustomFunctionData::isResetParamAvailable(modelData, index), IsAvailableRole); -} - -void CustomFuncResetParamItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - - -// -// TelemetrySourceItemModel -// - -TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - if (!modelData) - return; - - const int count = getCurrentFirmware()->getCapability(Sensors); - - for (int i = -count + 1; i < count; ++i) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - int flags = i < 0 ? DataGroups::NegativeGroup : DataGroups::PositiveGroup; - if (i == 0) - flags |= DataGroups::NoneGroup; - modelItem->setData(flags, ItemFlagsRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int index) const -{ - item->setText(SensorData::sourceToString(modelData, index)); - item->setData(SensorData::isSourceAvailable(modelData, index), IsAvailableRole); -} - -void TelemetrySourceItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - - -// -// CommonItemModels TODO rename to DynamicDataModels -// - -CommonItemModels::CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - QObject(parent) -{ - m_rawSourceItemModel = new RawSourceItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("raw source"), qobject_cast(m_rawSourceItemModel)); - - m_rawSwitchItemModel = new RawSwitchItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("raw switch"), qobject_cast(m_rawSwitchItemModel)); - - m_curveItemModel = new CurveItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("curve"), qobject_cast(m_curveItemModel)); - - m_gvarReferenceItemModel = new GVarReferenceItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("gvar ref"), qobject_cast(m_gvarReferenceItemModel)); - - m_throttleSourceItemModel = new ThrottleSourceItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("thr source"), qobject_cast(m_throttleSourceItemModel)); - - m_customFuncActionItemModel = new CustomFuncActionItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("cf action"), qobject_cast(m_customFuncActionItemModel)); - - m_customFuncResetParamItemModel = new CustomFuncResetParamItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("cf reset param"), qobject_cast(m_customFuncResetParamItemModel)); - - m_telemetrySourceItemModel = new TelemetrySourceItemModel(generalSettings, modelData, parent); - //dumpModelContents(QString("tele source"), qobject_cast(m_telemetrySourceItemModel)); -} - -CommonItemModels::~CommonItemModels() -{ -} - -void CommonItemModels::update(const RadioModelObjects radioModelObjects) -{ - switch (radioModelObjects) { - case RMO_CHANNELS: - m_throttleSourceItemModel->update(); - // no break - case RMO_TIMERS: - m_customFuncActionItemModel->update(); - // no break - case RMO_INPUTS: - case RMO_TELEMETRY_SENSORS: - m_rawSourceItemModel->update(); - m_customFuncResetParamItemModel->update(); - m_telemetrySourceItemModel->update(); - break; - - case RMO_GLOBAL_VARIABLES: - m_gvarReferenceItemModel->update(); - m_customFuncActionItemModel->update(); - // no break - case RMO_FLIGHT_MODES: - case RMO_LOGICAL_SWITCHES: - m_rawSourceItemModel->update(); - m_rawSwitchItemModel->update(); - break; - - case RMO_CURVES: - m_curveItemModel->update(); - break; - - case RMO_SCRIPTS: - // no need to refresh - break; - - default: - qDebug() << "Unknown RadioModelObject:" << radioModelObjects; - } -} - - -void dumpModelContents(QString desc, AbstractRawItemDataModel * dataModel) -{ - if (dataModel) { - qDebug() << "model:" << desc << "rows:" << dataModel->rowCount(); - for (int i = 0; i < dataModel->rowCount(); ++i) { - qDebug() << "row:" << i << "text:" << dataModel->item(i)->data(Qt::DisplayRole).toString() - << "id:" << dataModel->item(i)->data(AbstractRawItemDataModel::ItemIdRole).toInt() - << "avail:" << dataModel->item(i)->data(AbstractRawItemDataModel::IsAvailableRole).toBool() - << "flags:" << dataModel->item(i)->data(AbstractRawItemDataModel::ItemFlagsRole).toInt() - << "type:" << dataModel->item(i)->data(AbstractRawItemDataModel::ItemTypeRole).toInt(); - } - } - else - qDebug() << "model:" << desc << "did not cast"; -} diff --git a/companion/src/datamodels/rawitemdatamodels.h b/companion/src/datamodels/rawitemdatamodels.h deleted file mode 100644 index fbcfe8be9..000000000 --- a/companion/src/datamodels/rawitemdatamodels.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef RAWITEMDATAMODELS_H -#define RAWITEMDATAMODELS_H - -#include "rawsource.h" -#include "rawswitch.h" - -#include - -class GeneralSettings; -class ModelData; -class AdjustmentReference; - -class AbstractRawItemDataModel: public QStandardItemModel -{ - Q_OBJECT - public: - 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), - modelData(modelData) - {} - - public slots: - virtual void update() = 0; - - signals: - void dataAboutToBeUpdated(); - void dataUpdateComplete(); - - protected: - const GeneralSettings * generalSettings; - const ModelData * modelData; -}; - - -class RawSourceItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const RawSource & src) const; - void addItems(const RawSourceType & type, const int group, const int count, const int start = 0); -}; - - -class RawSwitchItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; - void addItems(const RawSwitchType & type, int count); -}; - - -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, const int index) const; -}; - - -class GVarReferenceItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const; - void addItems(int count); -}; - - -class ThrottleSourceItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const int index) const; -}; - - -class CustomFuncActionItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const int index) const; -}; - - -class CustomFuncResetParamItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const int index) const; -}; - - -class TelemetrySourceItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const int index) const; -}; - - -class CommonItemModels: public QObject -{ - Q_OBJECT - public: - enum RadioModelObjects { - RMO_CHANNELS, - RMO_CURVES, - RMO_FLIGHT_MODES, - RMO_GLOBAL_VARIABLES, - RMO_INPUTS, - RMO_LOGICAL_SWITCHES, - RMO_SCRIPTS, - RMO_TELEMETRY_SENSORS, - RMO_TIMERS - }; - Q_ENUM(RadioModelObjects) - - explicit CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - ~CommonItemModels(); - - void update(const RadioModelObjects radioModelObjects); - RawSourceItemModel * rawSourceItemModel() const { return m_rawSourceItemModel; } - RawSwitchItemModel * rawSwitchItemModel() const { return m_rawSwitchItemModel; } - CurveItemModel * curveItemModel() const { return m_curveItemModel; } - GVarReferenceItemModel * gvarItemModel() const { return m_gvarReferenceItemModel; } - ThrottleSourceItemModel * throttleSourceItemModel() const { return m_throttleSourceItemModel; } - CustomFuncActionItemModel * customFuncActionItemModel() const { return m_customFuncActionItemModel; } - CustomFuncResetParamItemModel * customFuncResetParamItemModel() const { return m_customFuncResetParamItemModel; } - TelemetrySourceItemModel * telemetrySourceItemModel() const { return m_telemetrySourceItemModel; } - - private: - RawSourceItemModel *m_rawSourceItemModel; - RawSwitchItemModel *m_rawSwitchItemModel; - CurveItemModel *m_curveItemModel; - GVarReferenceItemModel *m_gvarReferenceItemModel; - ThrottleSourceItemModel *m_throttleSourceItemModel; - CustomFuncActionItemModel *m_customFuncActionItemModel; - CustomFuncResetParamItemModel *m_customFuncResetParamItemModel; - TelemetrySourceItemModel *m_telemetrySourceItemModel; -}; - -void dumpModelContents(QString desc, AbstractRawItemDataModel * dataModel); - -#endif // RAWITEMDATAMODELS_H diff --git a/companion/src/datamodels/rawitemfilteredmodel.cpp b/companion/src/datamodels/rawitemfilteredmodel.cpp deleted file mode 100644 index abe9ca08e..000000000 --- a/companion/src/datamodels/rawitemfilteredmodel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "rawitemfilteredmodel.h" - -RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) : - QSortFilterProxyModel(parent), - filterFlags(0) -{ - setFilterRole(AbstractRawItemDataModel::IsAvailableRole); - setFilterKeyColumn(0); - setFilterFlags(flags); - setDynamicSortFilter(true); - setSourceModel(sourceModel); - - AbstractRawItemDataModel * itemModel = qobject_cast(sourceModel); - if (itemModel) { - connect(itemModel, &AbstractRawItemDataModel::dataAboutToBeUpdated, this, &RawItemFilteredModel::onDataAboutToBeUpdated); - connect(itemModel, &AbstractRawItemDataModel::dataUpdateComplete, this, &RawItemFilteredModel::onDataUpdateComplete); - } -} - -void RawItemFilteredModel::setFilterFlags(int flags) -{ - if (filterFlags != flags) { - filterFlags = flags; - invalidateFilter(); - } -} - -bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const -{ - const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent); - if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool()) - return false; - - if (!filterFlags) - return true; - - bool ok; - const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok); - return (ok && (!flags || (filterFlags & flags))); -} - -void RawItemFilteredModel::update() const -{ - AbstractRawItemDataModel * itemModel = qobject_cast(sourceModel()); - if (itemModel) - itemModel->update(); -} - -void RawItemFilteredModel::onDataAboutToBeUpdated() -{ - emit dataAboutToBeUpdated(); -} - -void RawItemFilteredModel::onDataUpdateComplete() -{ - emit dataUpdateComplete(); -} diff --git a/companion/src/datamodels/rawitemfilteredmodel.h b/companion/src/datamodels/rawitemfilteredmodel.h deleted file mode 100644 index 3274460f7..000000000 --- a/companion/src/datamodels/rawitemfilteredmodel.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef RAWITEMFILTEREDMODEL_H -#define RAWITEMFILTEREDMODEL_H - -#include "rawitemdatamodels.h" - -#include - -class GeneralSettings; -class ModelData; - -class RawItemFilteredModel: public QSortFilterProxyModel -{ - Q_OBJECT - public: - enum DataFilters { - AllFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup, - AllExcludeNoneFilter = AllFilter &~ AbstractRawItemDataModel::NoneGroup, - NegativeFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup, - NegativeExcludeNoneFilter = AbstractRawItemDataModel::NegativeGroup, - PositiveFilter = AbstractRawItemDataModel::PositiveGroup | AbstractRawItemDataModel::NoneGroup, - PositiveExcludeNoneFilter = 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; -}; -#endif // RAWITEMFILTEREDMODEL_H diff --git a/companion/src/firmwares/curvereference.cpp b/companion/src/firmwares/curvereference.cpp index 6ee2e38c5..6ade9264e 100644 --- a/companion/src/firmwares/curvereference.cpp +++ b/companion/src/firmwares/curvereference.cpp @@ -22,7 +22,7 @@ #include "adjustmentreference.h" #include "helpers.h" #include "modeldata.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" const QString CurveReference::toString(const ModelData * model, bool verbose) const { @@ -91,8 +91,6 @@ QString CurveReference::typeToString(const CurveRefType type) return strl.at(idx); } -constexpr int MAX_CURVE_REF_FUNC { 6 }; - // static QString CurveReference::functionToString(const int value) { @@ -105,77 +103,65 @@ QString CurveReference::functionToString(const int value) return strl.at(idx); } -/* +// static +bool CurveReference::isTypeAvailable(const CurveRefType type) +{ + bool ret = false; + Firmware * fw = getCurrentFirmware(); + switch(type) { + case CURVE_REF_DIFF: + if (fw->getCapability(HasInputDiff)) + ret = true; + break; + case CURVE_REF_EXPO: + if (fw->getCapability(HasMixerExpo)) + ret = true; + break; + case CURVE_REF_FUNC: + case CURVE_REF_CUSTOM: + ret = true; + break; + } + + return ret; +} + +// static +bool CurveReference::isFunctionAvailable(const int value) +{ + return true; +} + +// static +int CurveReference::functionCount() +{ + return 6; +} + + +/* * CurveReferenceUIManager */ -constexpr int CURVE_REF_UI_HIDE_DIFF { 0x01 }; -constexpr int CURVE_REF_UI_HIDE_EXPO { 0x02 }; -constexpr int CURVE_REF_UI_HIDE_NEGATIVE_CURVES { 0x04 }; - -// static -bool CurveReferenceUIManager::firsttime { true }; -int CurveReferenceUIManager::flags { 0 }; -bool CurveReferenceUIManager::hasCapabilityGvars { false }; -int CurveReferenceUIManager::numCurves { 0 }; -RawItemFilteredModel * CurveReferenceUIManager::curveItemModel { nullptr }; -QStandardItemModel * CurveReferenceUIManager::tempModel { nullptr }; - -CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent) : - QObject(parent), - curveTypeCB(nullptr), - curveGVarCB(nullptr), - curveValueSB(nullptr), - curveValueCB(curveValueCB), - curve(curve), - model(model), - lock(false) -{ - init(curveItemModel); -} - CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB, - QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent) : + QComboBox * curveValueCB, CurveReference & curveRef, const ModelData & model, + CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) : QObject(parent), curveTypeCB(curveTypeCB), curveGVarCB(curveGVarCB), curveValueSB(curveValueSB), curveValueCB(curveValueCB), - curve(curve), + curveRef(curveRef), model(model), - lock(false) + lock(false), + filteredModelFactory(curveRefFilteredFactory) { - init(curveItemModel); -} - -CurveReferenceUIManager::~CurveReferenceUIManager() -{ - delete tempModel; -} - -void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel) -{ - tempModel = new QStandardItemModel(); - - if (firsttime) { - firsttime = false; - Firmware * fw = getCurrentFirmware(); - hasCapabilityGvars = fw->getCapability(Gvars); - numCurves = fw->getCapability(NumCurves); - curveItemModel = curveModel; - - if (!fw->getCapability(HasInputDiff)) - flags |= (CURVE_REF_UI_HIDE_DIFF | CURVE_REF_UI_HIDE_NEGATIVE_CURVES); - - if (!fw->getCapability(HasMixerExpo)) - flags |= CURVE_REF_UI_HIDE_EXPO; - } + hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars); if (curveTypeCB) { - populateTypeCB(curveTypeCB, curve); + curveTypeCB->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE)); + curveTypeCB->setCurrentIndex(curveTypeCB->findData((int)curveRef.type)); connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); } @@ -188,13 +174,20 @@ void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel) connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged())); } - curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); - curveValueCB->setMaxVisibleItems(10); - connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); + if (curveValueCB) { + curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + curveValueCB->setMaxVisibleItems(10); + connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); + } update(); } +CurveReferenceUIManager::~CurveReferenceUIManager() +{ + delete filteredModelFactory; +} + #define CURVE_REF_UI_GVAR_SHOW (1<<0) #define CURVE_REF_UI_VALUE_SHOW (1<<1) #define CURVE_REF_UI_REF_SHOW (1<<2) @@ -204,12 +197,12 @@ void CurveReferenceUIManager::update() lock = true; int widgetsMask = 0; - if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) { + if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) { if (hasCapabilityGvars) widgetsMask |= CURVE_REF_UI_GVAR_SHOW; - if (curve.isValueNumber()) { + if (curveRef.isValueNumber()) { curveGVarCB->setChecked(false); - curveValueSB->setValue(curve.value); + curveValueSB->setValue(curveRef.value); widgetsMask |= CURVE_REF_UI_VALUE_SHOW; } else { @@ -222,7 +215,7 @@ void CurveReferenceUIManager::update() } if(curveTypeCB) { - curveTypeCB->setCurrentIndex(curveTypeCB->findData(curve.type)); + curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type)); curveTypeCB->show(); } if(curveGVarCB) @@ -230,8 +223,8 @@ void CurveReferenceUIManager::update() if(curveValueSB) curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW); if(curveValueCB) { - if (curve.isValueReference()) - populateValueCB(curveValueCB, curve, &model); + if (curveRef.isValueReference()) + populateValueCB(curveValueCB); curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW); } @@ -241,7 +234,7 @@ void CurveReferenceUIManager::update() void CurveReferenceUIManager::gvarCBChanged(int state) { if (!lock) { - curve.value = CurveReference::getDefaultValue(curve.type, state); + curveRef.value = CurveReference::getDefaultValue(curveRef.type, state); update(); } } @@ -250,7 +243,7 @@ void CurveReferenceUIManager::typeChanged(int value) { if (!lock) { CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt(); - curve = CurveReference(type, CurveReference::getDefaultValue(type)); + curveRef = CurveReference(type, CurveReference::getDefaultValue(type)); update(); } } @@ -258,7 +251,7 @@ void CurveReferenceUIManager::typeChanged(int value) void CurveReferenceUIManager::valueSBChanged() { if (!lock) { - curve.value = curveValueSB->value(); + curveRef.value = curveValueSB->value(); update(); } } @@ -266,47 +259,24 @@ void CurveReferenceUIManager::valueSBChanged() void CurveReferenceUIManager::valueCBChanged() { if (!lock) { - curve.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); + curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); update(); } } -// static -void CurveReferenceUIManager::populateTypeCB(QComboBox * cb, const CurveReference & curveRef) +void CurveReferenceUIManager::populateValueCB(QComboBox * cb) { if (cb) { - cb->clear(); - for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) { - if ((curveRef.type == CurveReference::CURVE_REF_DIFF && !(flags & CURVE_REF_UI_HIDE_DIFF)) || - (curveRef.type == CurveReference::CURVE_REF_EXPO && !(flags & CURVE_REF_UI_HIDE_EXPO)) || - (curveRef.type != CurveReference::CURVE_REF_DIFF && curveRef.type != CurveReference::CURVE_REF_EXPO)) - cb->addItem(CurveReference::typeToString((CurveReference::CurveRefType)i), i); - } - - cb->setCurrentIndex(cb->findData((int)curveRef.type)); - } -} - -// static -void CurveReferenceUIManager::populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model) -{ - if (cb) { - cb->setModel(tempModel); // do not want to clear/alter the shared curves model and set to nullptr is invalid - switch (curveRef.type) { case CurveReference::CURVE_REF_DIFF: case CurveReference::CURVE_REF_EXPO: - cb->clear(); - Helpers::populateGVCB(*cb, curveRef.value, *model); + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_GVARREF)); break; case CurveReference::CURVE_REF_FUNC: - cb->clear(); - for (int i = 1; i <= MAX_CURVE_REF_FUNC; i++) { - cb->addItem(CurveReference::functionToString(i), i); - } + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_FUNC)); break; case CurveReference::CURVE_REF_CUSTOM: - cb->setModel(curveItemModel); + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE)); break; default: break; diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h index 018fb12aa..c4482c742 100644 --- a/companion/src/firmwares/curvereference.h +++ b/companion/src/firmwares/curvereference.h @@ -29,7 +29,7 @@ class ModelData; -class RawItemFilteredModel; +class CurveRefFilteredFactory; class CurveReference { @@ -79,6 +79,9 @@ class CurveReference { static int getDefaultValue(const CurveRefType type, const bool isGVar = false); static QString typeToString(const CurveRefType type); static QString functionToString(const int value); + static bool isTypeAvailable(const CurveRefType type); + static bool isFunctionAvailable(const int value); + static int functionCount(); }; class CurveReferenceUIManager : public QObject { @@ -86,38 +89,34 @@ class CurveReferenceUIManager : public QObject { Q_OBJECT public: - CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent = nullptr); - CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, - CurveReference & curve, const ModelData & model, RawItemFilteredModel * curveItemModel, QObject * parent = nullptr); + explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, + CurveReference & curve, const ModelData & model, CurveRefFilteredFactory * curveRefFilteredFactory, + QObject * parent = nullptr); + + explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, + CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) : + CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, curve, model, curveRefFilteredFactory, parent) {} + virtual ~CurveReferenceUIManager(); - void init(RawItemFilteredModel * curveModel); - void update(); protected slots: void gvarCBChanged(int); void typeChanged(int); void valueSBChanged(); void valueCBChanged(); + void update(); - protected: + private: QComboBox *curveTypeCB; QCheckBox *curveGVarCB; QSpinBox *curveValueSB; QComboBox *curveValueCB; - CurveReference & curve; + CurveReference & curveRef; const ModelData & model; bool lock; - - static bool firsttime; - static int flags; - static bool hasCapabilityGvars; - static int numCurves; - static RawItemFilteredModel * curveItemModel; - static QStandardItemModel * tempModel; - - static void populateTypeCB(QComboBox * cb, const CurveReference & curveRef); - static void populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model = nullptr); + bool hasCapabilityGvars; + CurveRefFilteredFactory *filteredModelFactory; + void populateValueCB(QComboBox * cb); }; #endif // CURVEREFERENCE_H diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index 2b01f2600..753d2eed0 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -23,6 +23,7 @@ #include "radiodata.h" #include "modeldata.h" #include "eeprominterface.h" +#include "compounditemmodels.h" void SensorData::updateUnit() { @@ -32,9 +33,18 @@ void SensorData::updateUnit() } } +// TODO depreciated QString SensorData::unitString() const { - switch (unit) { + return unitToString(unit); +} + +// static +QString SensorData::unitToString(const int value) +{ + switch (value) { + case UNIT_RAW: + return tr("Raw (-)"); case UNIT_VOLTS: return tr("V"); case UNIT_AMPS: @@ -92,7 +102,7 @@ QString SensorData::unitString() const case UNIT_US: return tr("uS"); default: - return ""; + return CPN_STR_UNKNOWN_ITEM; } } @@ -120,11 +130,71 @@ bool SensorData::isEmpty() const return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0); } +// static +QString SensorData::typeToString(const int value) +{ + switch(value) { + case TELEM_TYPE_CUSTOM: + return tr("Custom"); + case TELEM_TYPE_CALCULATED: + return tr("Calculated"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString SensorData::formulaToString(const int value) +{ + switch(value) { + case TELEM_FORMULA_ADD: + return tr("Add"); + case TELEM_FORMULA_AVERAGE: + return tr("Average"); + case TELEM_FORMULA_MIN: + return tr("Minimum"); + case TELEM_FORMULA_MAX: + return tr("Maximum"); + case TELEM_FORMULA_MULTIPLY: + return tr("Multiply"); + case TELEM_FORMULA_TOTALIZE: + return tr("Totalize"); + case TELEM_FORMULA_CELL: + return tr("Cell"); + case TELEM_FORMULA_CONSUMPTION: + return tr("Consumption"); + case TELEM_FORMULA_DIST: + return tr("Distance"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString SensorData::cellIndexToString(const int value) +{ + if (value == TELEM_CELL_INDEX_LOWEST) + return tr("Lowest"); + if (value > TELEM_CELL_INDEX_LOWEST && value < TELEM_CELL_INDEX_HIGHEST) + return tr("Cell %1").arg(value - TELEM_CELL_INDEX_LOWEST); + if (value== TELEM_CELL_INDEX_HIGHEST) + return tr("Highest"); + if (value == TELEM_CELL_INDEX_DELTA) + return tr("Delta"); + return CPN_STR_UNKNOWN_ITEM; +} + +// static +QString SensorData::precisionToString(const int value) +{ + return QString("0.%1").arg(QString(value, '0')); +} + // static QString SensorData::sourceToString(const ModelData * model, const int index, const bool sign) { if (model) { - const QString prfx = sign ? index < 0 ? "-" : "" : ""; + const QString prfx = sign ? index < 0 ? "-" : "+" : ""; if (abs(index) > 0) { const SensorData &sd = model->sensorData[abs(index) - 1]; @@ -136,23 +206,89 @@ QString SensorData::sourceToString(const ModelData * model, const int index, con else return CPN_STR_NONE_ITEM; } - else - return ""; + + return ""; } // static bool SensorData::isSourceAvailable(const ModelData * model, const int index) { - if (model) { - Firmware * firmware = getCurrentFirmware(); - const int i = abs(index); - if (i <= firmware->getCapability(Sensors)) { - if (i > 0) - return model->sensorData[i - 1].isAvailable(); - else - return true; - } + Firmware * firmware = getCurrentFirmware(); + const int sensorcnt = firmware->getCapability(Sensors); + const int i = abs(index); + + if (model && sensorcnt > 0 and i <= sensorcnt) { + if (i > 0) + return model->sensorData[i - 1].isAvailable(); + else + return true; } return false; } + +// static +AbstractStaticItemModel * SensorData::typeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.type"); + + for (int i = 0; i <= TELEM_TYPE_LAST; i++) { + mdl->appendToItemList(typeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::formulaItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.formula"); + + for (int i = 0; i <= TELEM_FORMULA_LAST; i++) { + mdl->appendToItemList(formulaToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::cellIndexItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.cellindex"); + + for (int i = 0; i <= TELEM_CELL_INDEX_LAST; i++) { + mdl->appendToItemList(cellIndexToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::unitItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.unit"); + + for (int i = 0; i <= UNIT_MAX; i++) { + QString str = unitToString(i); + if (str != CPN_STR_UNKNOWN_ITEM) + mdl->appendToItemList(str, i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +PrecisionItemModel * SensorData::precisionItemModel() +{ + PrecisionItemModel * mdl = new PrecisionItemModel(0, 2); + mdl->setName("sensordata.precision"); + return mdl; +} diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 200f6e889..afd9d7891 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -27,6 +27,8 @@ constexpr int CPN_MAX_SENSORS = 60; constexpr int SENSOR_LABEL_LEN = 4; class ModelData; +class AbstractStaticItemModel; +class PrecisionItemModel; class SensorData { Q_DECLARE_TR_FUNCTIONS(SensorData) @@ -36,7 +38,8 @@ class SensorData { enum { TELEM_TYPE_CUSTOM, - TELEM_TYPE_CALCULATED + TELEM_TYPE_CALCULATED, + TELEM_TYPE_LAST = TELEM_TYPE_CALCULATED }; enum @@ -63,6 +66,7 @@ class SensorData { TELEM_CELL_INDEX_6, TELEM_CELL_INDEX_HIGHEST, TELEM_CELL_INDEX_DELTA, + TELEM_CELL_INDEX_LAST = TELEM_CELL_INDEX_DELTA }; enum @@ -169,8 +173,19 @@ class SensorData { void clear() { memset(this, 0, sizeof(SensorData)); } bool isEmpty() const; - static QString sourceToString(const ModelData * model, const int index, const bool sign = true); + static QString sourceToString(const ModelData * model, const int index, const bool sign = false); static bool isSourceAvailable(const ModelData * model, const int index); + static QString typeToString(const int value); + static QString formulaToString(const int value); + static QString cellIndexToString(const int value); + static QString unitToString(const int value); + static QString precisionToString(const int value); + + static AbstractStaticItemModel * typeItemModel(); + static AbstractStaticItemModel * formulaItemModel(); + static AbstractStaticItemModel * cellIndexItemModel(); + static AbstractStaticItemModel * unitItemModel(); + static PrecisionItemModel * precisionItemModel(); }; #endif // SENSORDATA_H diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index bff9d3f83..e80038f9f 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -28,7 +28,7 @@ #include "hardware.h" #include "../modeledit/customfunctions.h" #include "verticalscrollarea.h" -#include "rawitemdatamodels.h" +#include "compounditemmodels.h" GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) : QDialog(parent), @@ -56,10 +56,14 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir } } - commonItemModels = new CommonItemModels(&generalSettings, nullptr, this); + sharedItemModels = new CompoundItemModelFactory(&generalSettings, nullptr); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); - addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, commonItemModels), tr("Global Functions")); + addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, sharedItemModels), 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")); @@ -70,6 +74,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir GeneralEdit::~GeneralEdit() { delete ui; + delete sharedItemModels; } void GeneralEdit::closeEvent(QCloseEvent *event) diff --git a/companion/src/generaledit/generaledit.h b/companion/src/generaledit/generaledit.h index 3f73a9e01..b2e6caa82 100644 --- a/companion/src/generaledit/generaledit.h +++ b/companion/src/generaledit/generaledit.h @@ -25,7 +25,7 @@ #include "eeprominterface.h" #include "genericpanel.h" -class CommonItemModels; +class CompoundItemModelFactory; namespace Ui { class GeneralEdit; @@ -73,7 +73,7 @@ class GeneralEdit : public QDialog QVector panels; void addTab(GenericPanel *panel, QString text); void closeEvent(QCloseEvent *event); - CommonItemModels *commonItemModels; + CompoundItemModelFactory *sharedItemModels; }; #endif // _GENERALEDIT_H_ diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index d2818368e..27374a8c4 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -20,7 +20,7 @@ #include "channels.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.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), @@ -96,16 +96,15 @@ void LimitsGroup::updateMinMax(int max) } } } -ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { chnCapability = firmware->getCapability(Outputs); int channelNameMaxLen = firmware->getCapability(ChannelsName); - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &ChannelsPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &ChannelsPanel::onModelDataUpdateComplete); + curveFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve)); + connectItemModelEvents(curveFilteredModel); QStringList headerLabels; headerLabels << "#"; @@ -214,6 +213,7 @@ ChannelsPanel::~ChannelsPanel() delete centerSB[i]; delete symlimitsChk[i]; } + delete curveFilteredModel; } void ChannelsPanel::symlimitsEdited() @@ -474,12 +474,18 @@ void ChannelsPanel::swapData(int idx1, int idx2) } } -void ChannelsPanel::onModelDataAboutToBeUpdated() +void ChannelsPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &ChannelsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &ChannelsPanel::onItemModelUpdateComplete); +} + +void ChannelsPanel::onItemModelAboutToBeUpdated() { lock = true; } -void ChannelsPanel::onModelDataUpdateComplete() +void ChannelsPanel::onItemModelUpdateComplete() { update(); lock = false; @@ -487,5 +493,5 @@ void ChannelsPanel::onModelDataUpdateComplete() void ChannelsPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_CHANNELS); + sharedItemModels->update(AbstractItemModel::IMUE_Channels); } diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index a481feec2..2a65f497a 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -26,8 +26,8 @@ #include -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel"; @@ -57,8 +57,8 @@ class ChannelsPanel : public ModelPanel Q_OBJECT public: - ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~ChannelsPanel(); + ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~ChannelsPanel(); public slots: void refreshExtendedLimits(); @@ -81,8 +81,8 @@ class ChannelsPanel : public ModelPanel void cmClear(bool prompt = true); void cmClearAll(); void onCustomContextMenuRequested(QPoint pos); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: bool hasClipboardData(QByteArray * data = nullptr) const; @@ -100,9 +100,10 @@ class ChannelsPanel : public ModelPanel QCheckBox *symlimitsChk[CPN_MAX_CHNOUT]; int selectedIndex; int chnCapability; - CommonItemModels * commonItemModels; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + FilteredItemModel *curveFilteredModel; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _CHANNELS_H_ diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 9e60f30c3..7f8b80219 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -23,7 +23,7 @@ #include "node.h" #include "edge.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #define GFX_MARGIN 16 @@ -109,11 +109,12 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax return y; } -CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Curves), currentCurve(0), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { ui->setupUi(this); @@ -812,7 +813,7 @@ void CurvesPanel::swapData(int idx1, int idx2) void CurvesPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_CURVES); + sharedItemModels->update(AbstractItemModel::IMUE_Curves); } CustomScene::CustomScene(QGraphicsView * view) : diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h index 8df3a8528..c66f79cb7 100644 --- a/companion/src/modeledit/curves.h +++ b/companion/src/modeledit/curves.h @@ -26,7 +26,7 @@ #include #include -class CommonItemModels; +class CompoundItemModelFactory; constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve"; @@ -61,7 +61,7 @@ class CurvesPanel : public ModelPanel Q_OBJECT public: - CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~CurvesPanel(); virtual void update(); @@ -121,7 +121,7 @@ class CurvesPanel : public ModelPanel bool moveDownAllowed() const; bool moveUpAllowed() const; void swapData(int idx1, int idx2); - CommonItemModels * commonItemModels; + CompoundItemModelFactory * sharedItemModels; void updateItemModels(); }; diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index c3ee895b7..5c15bd538 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -19,7 +19,7 @@ */ #include "customfunctions.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include "appdata.h" @@ -66,10 +66,10 @@ void RepeatComboBox::update() setCurrentIndex(value); } -CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): GenericPanel(parent, model, generalSettings, firmware), functions(model ? model->customFn : generalSettings.customFn), - commonItemModels(commonItemModels), mediaPlayerCurrent(-1), mediaPlayer(nullptr), modelsUpdateCnt(0) @@ -77,21 +77,18 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, lock = true; fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions); - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext); + connectItemModelEvents(rawSwitchFilteredModel); - rawSourceAllModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this); - connect(rawSourceAllModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceAllModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceAllModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)); + connectItemModelEvents(rawSourceAllModel); - rawSourceInputsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); - connect(rawSourceInputsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceInputsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceInputsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups); + connectItemModelEvents(rawSourceInputsModel); - rawSourceGVarsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::GVarsGroup, this); - connect(rawSourceGVarsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceGVarsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceGVarsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::GVarsGroup); + connectItemModelEvents(rawSourceGVarsModel); if (!firmware->getCapability(VoicesAsNumbers)) { tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength)); @@ -253,6 +250,10 @@ CustomFunctionsPanel::~CustomFunctionsPanel() { if (mediaPlayer) stopSound(mediaPlayerCurrent); + delete rawSwitchFilteredModel; + delete rawSourceAllModel; + delete rawSourceInputsModel; + delete rawSourceGVarsModel; } void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state) @@ -827,13 +828,19 @@ bool CustomFunctionsPanel::moveUpAllowed() const return selectedIndex > 0; } -void CustomFunctionsPanel::onModelDataAboutToBeUpdated() +void CustomFunctionsPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &CustomFunctionsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &CustomFunctionsPanel::onItemModelUpdateComplete); +} + +void CustomFunctionsPanel::onItemModelAboutToBeUpdated() { lock = true; modelsUpdateCnt++; } -void CustomFunctionsPanel::onModelDataUpdateComplete() +void CustomFunctionsPanel::onItemModelUpdateComplete() { modelsUpdateCnt--; if (modelsUpdateCnt < 1) { diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h index 9b3e3d238..e41baf672 100644 --- a/companion/src/modeledit/customfunctions.h +++ b/companion/src/modeledit/customfunctions.h @@ -26,8 +26,8 @@ #include -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class TimerEdit; constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function"; @@ -55,8 +55,8 @@ class CustomFunctionsPanel : public GenericPanel Q_OBJECT public: - CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~CustomFunctionsPanel(); + CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~CustomFunctionsPanel(); virtual void update(); @@ -83,8 +83,8 @@ class CustomFunctionsPanel : public GenericPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: void populateFuncCB(QComboBox *b, unsigned int value); @@ -96,11 +96,12 @@ class CustomFunctionsPanel : public GenericPanel bool moveUpAllowed() const; void swapData(int idx1, int idx2); void resetCBsAndRefresh(int idx); - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; - RawItemFilteredModel * rawSourceAllModel; - RawItemFilteredModel * rawSourceInputsModel; - RawItemFilteredModel * rawSourceGVarsModel; + void connectItemModelEvents(const FilteredItemModel * itemModel); + + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * rawSourceAllModel; + FilteredItemModel * rawSourceInputsModel; + FilteredItemModel * rawSourceGVarsModel; QSet tracksSet; QSet scriptsSet; diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index afebbeb27..808cff7ba 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -20,12 +20,11 @@ #include "expodialog.h" #include "ui_expodialog.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceModel, - RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) : + Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels) : QDialog(parent), ui(new Ui::ExpoDialog), model(model), @@ -38,6 +37,9 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G { ui->setupUi(this); + dialogFilteredItemModels = new FilteredItemModelFactory(); + int id; + 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; i < CPN_MAX_FLIGHT_MODES; i++) { @@ -50,9 +52,15 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100); gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, curveItemModel, this); - ui->switchesCB->setModel(rawSwitchModel); + curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, + firmware->getCapability(HasInputDiff) ? 0 : FilteredItemModel::PositiveFilter); + curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, + curveRefFilteredItemModels, this); + + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::MixesContext), "RawSwitch"); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->sideCB->setCurrentIndex(ed->mode - 1); @@ -83,7 +91,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G if (firmware->getCapability(VirtualInputs)) { ui->inputName->setMaxLength(firmware->getCapability(InputsLength)); - ui->sourceCB->setModel(rawSourceModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup)), + "RawSource"); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue())); ui->inputName->setValidator(new QRegExpValidator(rx, this)); ui->inputName->setText(inputName); @@ -135,9 +146,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G ExpoDialog::~ExpoDialog() { + delete ui; delete gvWeightGroup; delete gvOffsetGroup; - delete ui; + delete dialogFilteredItemModels; } void ExpoDialog::updateScale() diff --git a/companion/src/modeledit/expodialog.h b/companion/src/modeledit/expodialog.h index b77d55852..f4980d344 100644 --- a/companion/src/modeledit/expodialog.h +++ b/companion/src/modeledit/expodialog.h @@ -26,7 +26,9 @@ #include "modelprinter.h" class GVarGroup; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModelFactory; +class CurveRefFilteredFactory; class CurveReferenceUIManager; namespace Ui { @@ -37,9 +39,8 @@ class ExpoDialog : public QDialog { Q_OBJECT public: ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceItemModel, - RawItemFilteredModel * rawSwitchItemModel, RawItemFilteredModel * curveItemModel); - ~ExpoDialog(); + Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels); + virtual ~ExpoDialog(); protected: void updateScale(); @@ -65,6 +66,8 @@ class ExpoDialog : public QDialog { ModelPrinter modelPrinter; bool lock; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + FilteredItemModelFactory *dialogFilteredItemModels; + CurveRefFilteredFactory *curveRefFilteredItemModels; }; #endif // _EXPODIALOG_H_ diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 32188feea..224d69965 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -20,19 +20,19 @@ #include "flightmodes.h" #include "ui_flightmode.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include "customdebug.h" -FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel): +FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::FlightMode), phaseIdx(phaseIdx), phase(model.flightModeData[phaseIdx]) { ui->setupUi(this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &FlightModePanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &FlightModePanel::onModelDataUpdateComplete); + connectItemModelEvents(rawSwitchFilteredModel); ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu); ui->labelName->setToolTip(tr("Popup menu available")); @@ -1361,12 +1361,18 @@ void FlightModePanel::gvSwapData(int idx1, int idx2) } } -void FlightModePanel::onModelDataAboutToBeUpdated() +void FlightModePanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModePanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModePanel::onItemModelUpdateComplete); +} + +void FlightModePanel::onItemModelAboutToBeUpdated() { lock = true; } -void FlightModePanel::onModelDataUpdateComplete() +void FlightModePanel::onItemModelUpdateComplete() { update(); lock = false; @@ -1374,11 +1380,14 @@ void FlightModePanel::onModelDataUpdateComplete() /**********************************************************/ -FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext); + connectItemModelEvents(rawSwitchFilteredModel); + modesCount = firmware->getCapability(FlightModes); QGridLayout * gridLayout = new QGridLayout(this); @@ -1403,6 +1412,7 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS FlightModesPanel::~FlightModesPanel() { + delete rawSwitchFilteredModel; } QString FlightModesPanel::getTabName(int index) @@ -1431,10 +1441,24 @@ void FlightModesPanel::update() emit updated(); } +void FlightModesPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModesPanel::onItemModelUpdateComplete); +} + +void FlightModesPanel::onItemModelAboutToBeUpdated() +{ +} + +void FlightModesPanel::onItemModelUpdateComplete() +{ +} + void FlightModesPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_FLIGHT_MODES); - commonItemModels->update(CommonItemModels::RMO_GLOBAL_VARIABLES); + sharedItemModels->update(AbstractItemModel::IMUE_FlightModes); + sharedItemModels->update(AbstractItemModel::IMUE_GVars); } void FlightModesPanel::onTabIndexChanged(int index) diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h index ca3619c6c..33fd87e8a 100644 --- a/companion/src/modeledit/flightmodes.h +++ b/companion/src/modeledit/flightmodes.h @@ -24,8 +24,8 @@ #include "modeledit.h" #include "eeprominterface.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; @@ -41,7 +41,8 @@ class FlightModePanel : public ModelPanel Q_OBJECT public: - FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel); + FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel); virtual ~FlightModePanel(); virtual void update(); @@ -90,8 +91,8 @@ class FlightModePanel : public ModelPanel void gvCmPaste(); void gvCmMoveDown(); void gvCmMoveUp(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::FlightMode *ui; @@ -138,6 +139,7 @@ class FlightModePanel : public ModelPanel bool gvMoveDownAllowed() const; bool gvMoveUpAllowed() const; void gvSwapData(int idx1, int idx2); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class FlightModesPanel : public ModelPanel @@ -145,7 +147,7 @@ class FlightModesPanel : public ModelPanel Q_OBJECT public: - FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~FlightModesPanel(); public slots: @@ -157,16 +159,19 @@ class FlightModesPanel : public ModelPanel private slots: void onPhaseNameChanged(); void onTabIndexChanged(int index); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: QString getTabName(int index); int modesCount; QTabWidget *tabWidget; - CommonItemModels *commonItemModels; - RawItemFilteredModel *rawSwitchFilteredModel; + CompoundItemModelFactory *sharedItemModels; + FilteredItemModel *rawSwitchFilteredModel; QVector panels; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _FLIGHTMODES_H_ diff --git a/companion/src/modeledit/heli.cpp b/companion/src/modeledit/heli.cpp index 1b8607799..ef86c5793 100644 --- a/companion/src/modeledit/heli.cpp +++ b/companion/src/modeledit/heli.cpp @@ -21,18 +21,16 @@ #include "heli.h" #include "ui_heli.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - ui(new Ui::Heli), - commonItemModels(commonItemModels) + ui(new Ui::Heli) { ui->setupUi(this); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &HeliPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &HeliPanel::onModelDataUpdateComplete); + rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups); + connectItemModelEvents(rawSourceFilteredModel); connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited())); @@ -71,6 +69,7 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener HeliPanel::~HeliPanel() { delete ui; + delete rawSourceFilteredModel; } void HeliPanel::update() @@ -118,12 +117,18 @@ void HeliPanel::edited() } } -void HeliPanel::onModelDataAboutToBeUpdated() +void HeliPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &HeliPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &HeliPanel::onItemModelUpdateComplete); +} + +void HeliPanel::onItemModelAboutToBeUpdated() { lock = true; } -void HeliPanel::onModelDataUpdateComplete() +void HeliPanel::onItemModelUpdateComplete() { update(); lock = false; diff --git a/companion/src/modeledit/heli.h b/companion/src/modeledit/heli.h index ee9a3ac36..eb3c7d54e 100644 --- a/companion/src/modeledit/heli.h +++ b/companion/src/modeledit/heli.h @@ -23,8 +23,8 @@ #include "modeledit.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; namespace Ui { class Heli; @@ -35,19 +35,19 @@ class HeliPanel : public ModelPanel Q_OBJECT public: - HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~HeliPanel(); + HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~HeliPanel(); void update(); private slots: void edited(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Heli *ui; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSourceFilteredModel; + FilteredItemModel * rawSourceFilteredModel; + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _HELI_H_ diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp index ee2347aee..f48d7d916 100644 --- a/companion/src/modeledit/inputs.cpp +++ b/companion/src/modeledit/inputs.cpp @@ -21,25 +21,19 @@ #include "inputs.h" #include "expodialog.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), expoInserted(false), modelPrinter(firmware, generalSettings, model), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup), this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); - - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); - - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); + connectItemModelEvents(AbstractItemModel::IMID_RawSource); + connectItemModelEvents(AbstractItemModel::IMID_RawSwitch); + connectItemModelEvents(AbstractItemModel::IMID_Curve); + connectItemModelEvents(AbstractItemModel::IMID_GVarRef); inputsCount = firmware->getCapability(VirtualInputs); if (inputsCount == 0) @@ -194,7 +188,7 @@ void InputsPanel::gm_openExpo(int index) if (firmware->getCapability(VirtualInputs)) inputName = model->inputNames[ed.chn]; - ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); + ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, sharedItemModels); if (dlg->exec()) { model->expoData[index] = ed; if (firmware->getCapability(VirtualInputs)) @@ -730,18 +724,31 @@ int InputsPanel::getInputIndexFromSelected() return idx; } -void InputsPanel::onModelDataAboutToBeUpdated() +void InputsPanel::connectItemModelEvents(const int id) { - lock = true; + AbstractDynamicItemModel * itemModel = qobject_cast(sharedItemModels->getItemModel(id)); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &InputsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &InputsPanel::onItemModelUpdateComplete); + } } -void InputsPanel::onModelDataUpdateComplete() +void InputsPanel::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void InputsPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } void InputsPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_INPUTS); + sharedItemModels->update(AbstractItemModel::IMUE_Inputs); } diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index ea1243213..9b360ec19 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -25,8 +25,8 @@ #include "mixerslistwidget.h" #include "modelprinter.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo"; @@ -35,7 +35,7 @@ class InputsPanel : public ModelPanel Q_OBJECT public: - InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~InputsPanel(); virtual void update(); @@ -62,8 +62,8 @@ class InputsPanel : public ModelPanel void cmInputInsert(); void cmInputMoveDown(); void cmInputMoveUp(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: bool expoInserted; @@ -72,10 +72,8 @@ class InputsPanel : public ModelPanel ModelPrinter modelPrinter; int selectedIdx; int inputIdx; - CommonItemModels * commonItemModels; - RawItemFilteredModel *rawSourceFilteredModel; - RawItemFilteredModel *rawSwitchFilteredModel; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + int modelsUpdateCnt; int getExpoIndex(unsigned int dch); bool gm_insertExpo(int idx); @@ -97,6 +95,7 @@ class InputsPanel : public ModelPanel int getIndexFromSelected(); int getInputIndexFromSelected(); void updateItemModels(); + void connectItemModelEvents(const int id); }; #endif // _INPUTS_H_ diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index cacd5c6fd..499df9e49 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -19,25 +19,25 @@ */ #include "logicalswitches.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include -LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels), + sharedItemModels(sharedItemModels), selectedIndex(0), modelsUpdateCnt(0) { - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::LogicalSwitchesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::LogicalSwitchesContext); + connectItemModelEvents(rawSwitchFilteredModel); const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), srcGroups, this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); + rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), srcGroups); + connectItemModelEvents(rawSourceFilteredModel); lsCapability = firmware->getCapability(LogicalSwitches); lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt); @@ -161,6 +161,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, LogicalSwitchesPanel::~LogicalSwitchesPanel() { + delete rawSourceFilteredModel; + delete rawSwitchFilteredModel; } void LogicalSwitchesPanel::onFunctionChanged() @@ -644,16 +646,22 @@ void LogicalSwitchesPanel::swapData(int idx1, int idx2) void LogicalSwitchesPanel::updateItemModels() { lock = true; - commonItemModels->update(CommonItemModels::RMO_LOGICAL_SWITCHES); + sharedItemModels->update(AbstractItemModel::IMUE_LogicalSwitches); } -void LogicalSwitchesPanel::onModelDataAboutToBeUpdated() +void LogicalSwitchesPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &LogicalSwitchesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &LogicalSwitchesPanel::onItemModelUpdateComplete); +} + +void LogicalSwitchesPanel::onItemModelAboutToBeUpdated() { lock = true; modelsUpdateCnt++; } -void LogicalSwitchesPanel::onModelDataUpdateComplete() +void LogicalSwitchesPanel::onItemModelUpdateComplete() { modelsUpdateCnt--; if (modelsUpdateCnt < 1) { diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h index 87a360408..f1c2f8397 100644 --- a/companion/src/modeledit/logicalswitches.h +++ b/companion/src/modeledit/logicalswitches.h @@ -24,8 +24,8 @@ #include "modeledit.h" #include "radiodata.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class TimerEdit; constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch"; @@ -35,7 +35,7 @@ class LogicalSwitchesPanel : public ModelPanel Q_OBJECT public: - LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~LogicalSwitchesPanel(); virtual void update(); @@ -60,8 +60,8 @@ class LogicalSwitchesPanel : public ModelPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES]; @@ -74,9 +74,9 @@ class LogicalSwitchesPanel : public ModelPanel QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES]; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; - RawItemFilteredModel * rawSourceFilteredModel; + CompoundItemModelFactory * sharedItemModels; + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * rawSourceFilteredModel; int selectedIndex; void populateFunctionCB(QComboBox *b); void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0); @@ -89,6 +89,7 @@ class LogicalSwitchesPanel : public ModelPanel bool moveUpAllowed() const; int modelsUpdateCnt; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _LOGICALSWITCHES_H_ diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index 00d2badc8..67b01f8f6 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -21,11 +21,11 @@ #include "mixerdialog.h" #include "ui_mixerdialog.h" #include "radiodata.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware, - RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) : + CompoundItemModelFactory * sharedItemModels) : QDialog(parent), ui(new Ui::MixerDialog), model(model), @@ -36,6 +36,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, { ui->setupUi(this); + dialogFilteredItemModels = new FilteredItemModelFactory(); + int id; + 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 }; @@ -45,14 +48,20 @@ 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(rawSourceModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup)), + "RawSource"); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue())); int limit = firmware->getCapability(OffsetWeight); gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit); gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, curveItemModel, this); + curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, + firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter); + curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, + curveRefFilteredItemModels, this); ui->MixDR_CB->setChecked(md->noExpo == 0); @@ -104,7 +113,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, } } - ui->switchesCB->setModel(rawSwitchModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::MixesContext), "RawSwitch"); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue())); ui->warningCB->setCurrentIndex(md->mixWarn); ui->mltpxCB->setCurrentIndex(md->mltpx); @@ -150,6 +161,7 @@ MixerDialog::~MixerDialog() delete ui; delete gvWeightGroup; delete gvOffsetGroup; + delete dialogFilteredItemModels; } void MixerDialog::changeEvent(QEvent *e) diff --git a/companion/src/modeledit/mixerdialog.h b/companion/src/modeledit/mixerdialog.h index 6d2131de2..04ff1aeaf 100644 --- a/companion/src/modeledit/mixerdialog.h +++ b/companion/src/modeledit/mixerdialog.h @@ -25,7 +25,9 @@ #include "eeprominterface.h" class GVarGroup; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModelFactory; +class CurveRefFilteredFactory; class CurveReferenceUIManager; namespace Ui { @@ -36,7 +38,7 @@ class MixerDialog : public QDialog { Q_OBJECT public: MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware, - RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel); + CompoundItemModelFactory * sharedItemModels); ~MixerDialog(); protected: @@ -61,6 +63,8 @@ class MixerDialog : public QDialog { GVarGroup * gvOffsetGroup; CurveReferenceUIManager * curveGroup; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + FilteredItemModelFactory *dialogFilteredItemModels; + CurveRefFilteredFactory *curveRefFilteredItemModels; }; #endif // _MIXERDIALOG_H_ diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp index f02a57417..3d95bd04d 100644 --- a/companion/src/modeledit/mixes.cpp +++ b/companion/src/modeledit/mixes.cpp @@ -20,26 +20,20 @@ #include "mixes.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,CommonItemModels * commonItemModels): +MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), mixInserted(false), highlightedSource(0), modelPrinter(firmware, generalSettings, model), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup), this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); - - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); - - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); + connectItemModelEvents(AbstractItemModel::IMID_RawSource); + connectItemModelEvents(AbstractItemModel::IMID_RawSwitch); + connectItemModelEvents(AbstractItemModel::IMID_Curve); + connectItemModelEvents(AbstractItemModel::IMID_GVarRef); QGridLayout * mixesLayout = new QGridLayout(this); @@ -189,7 +183,7 @@ void MixesPanel::gm_openMix(int index) MixData mixd(model->mixData[index]); - MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); + MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, sharedItemModels); if(dlg->exec()) { model->mixData[index] = mixd; emit modified(); @@ -545,13 +539,26 @@ void MixesPanel::clearMixes() } } -void MixesPanel::onModelDataAboutToBeUpdated() +void MixesPanel::connectItemModelEvents(const int id) { - lock = true; + AbstractDynamicItemModel * itemModel = qobject_cast(sharedItemModels->getItemModel(id)); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &MixesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &MixesPanel::onItemModelUpdateComplete); + } } -void MixesPanel::onModelDataUpdateComplete() +void MixesPanel::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void MixesPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h index 014786b74..c298df11a 100644 --- a/companion/src/modeledit/mixes.h +++ b/companion/src/modeledit/mixes.h @@ -26,15 +26,15 @@ #include "mixerdialog.h" #include "modelprinter.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class MixesPanel : public ModelPanel { Q_OBJECT public: - MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~MixesPanel(); virtual void update(); @@ -60,18 +60,16 @@ class MixesPanel : public ModelPanel void mimeMixerDropped(int index, const QMimeData *data, Qt::DropAction action); void pasteMixerMimeData(const QMimeData * mimeData, int destIdx); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: MixersListWidget * mixersListWidget; bool mixInserted; unsigned int highlightedSource; ModelPrinter modelPrinter; - CommonItemModels * commonItemModels; - RawItemFilteredModel *rawSourceFilteredModel; - RawItemFilteredModel *rawSwitchFilteredModel; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + int modelsUpdateCnt; int getMixerIndex(unsigned int dch); bool gm_insertMix(int idx); @@ -83,6 +81,7 @@ class MixesPanel : public ModelPanel void setSelectedByMixList(QList list); void AddMixerLine(int dest); QString getMixerText(int dest, bool newChannel); + void connectItemModelEvents(const int id); }; #endif // _MIXES_H_ diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index 41989ba53..3577be7ae 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -33,7 +33,7 @@ #include "customfunctions.h" #include "telemetry.h" #include "appdata.h" -#include "rawitemdatamodels.h" +#include "compounditemmodels.h" ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmware * firmware) : QDialog(parent), @@ -53,42 +53,53 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw GeneralSettings &generalSettings = radioData.generalSettings; ModelData &model = radioData.models[modelId]; - commonItemModels = new CommonItemModels(&generalSettings, &model, this); + sharedItemModels = new CompoundItemModelFactory(&generalSettings, &model); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); + sharedItemModels->addItemModel(AbstractItemModel::IMID_Curve); + sharedItemModels->addItemModel(AbstractItemModel::IMID_GVarRef); + sharedItemModels->addItemModel(AbstractItemModel::IMID_ThrSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); + sharedItemModels->addItemModel(AbstractItemModel::IMID_TeleSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefType); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefFunc); + s1.report("Init"); - SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, commonItemModels); + SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, sharedItemModels); addTab(setupPanel, tr("Setup")); s1.report("Setup"); if (firmware->getCapability(Heli)) { - addTab(new HeliPanel(this, model, generalSettings, firmware, commonItemModels), tr("Heli")); + addTab(new HeliPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Heli")); s1.report("Heli"); } - addTab(new FlightModesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Flight Modes")); + addTab(new FlightModesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Flight Modes")); s1.report("Flight Modes"); - addTab(new InputsPanel(this, model, generalSettings, firmware, commonItemModels), tr("Inputs")); + addTab(new InputsPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Inputs")); s1.report("Inputs"); - addTab(new MixesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Mixes")); + addTab(new MixesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Mixes")); s1.report("Mixes"); - ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, commonItemModels); + ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, sharedItemModels); addTab(channelsPanel, tr("Outputs")); s1.report("Outputs"); - addTab(new CurvesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Curves")); + addTab(new CurvesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Curves")); s1.report("Curves"); - addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Logical Switches")); + addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Logical Switches")); s1.report("Logical Switches"); - addTab(new CustomFunctionsPanel(this, &model, generalSettings, firmware, commonItemModels), tr("Special Functions")); + addTab(new CustomFunctionsPanel(this, &model, generalSettings, firmware, sharedItemModels), tr("Special Functions")); s1.report("Special Functions"); if (firmware->getCapability(Telemetry)) { - addTab(new TelemetryPanel(this, model, generalSettings, firmware, commonItemModels), tr("Telemetry")); + addTab(new TelemetryPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Telemetry")); s1.report("Telemetry"); } @@ -104,6 +115,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw ModelEdit::~ModelEdit() { delete ui; + delete sharedItemModels; } void ModelEdit::closeEvent(QCloseEvent *event) diff --git a/companion/src/modeledit/modeledit.h b/companion/src/modeledit/modeledit.h index 9095101bf..0bd4af9d8 100644 --- a/companion/src/modeledit/modeledit.h +++ b/companion/src/modeledit/modeledit.h @@ -25,7 +25,7 @@ #include "genericpanel.h" class RadioData; -class CommonItemModels; +class CompoundItemModelFactory; namespace Ui { class ModelEdit; @@ -60,12 +60,12 @@ class ModelEdit : public QDialog private: Ui::ModelEdit *ui; int modelId; - RadioData & radioData; - Firmware * firmware; + RadioData &radioData; + Firmware *firmware; QVector panels; - CommonItemModels * commonItemModels; + CompoundItemModelFactory *sharedItemModels; - void addTab(GenericPanel *panel, QString text); + void addTab(GenericPanel * panel, QString text); void launchSimulation(); }; diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index e4f67178d..25cd576ec 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -22,7 +22,7 @@ #include "ui_setup.h" #include "ui_setup_timer.h" #include "ui_setup_module.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "appdata.h" #include "modelprinter.h" #include "multiprotocols.h" @@ -31,14 +31,14 @@ #include -TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawItemFilteredModel * rawSwitchFilteredModel): +TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, + QWidget * prevFocus, FilteredItemModel * rawSwitchFilteredModel): ModelPanel(parent, model, generalSettings, firmware), timer(timer), ui(new Ui::Timer) { ui->setupUi(this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TimerPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &TimerPanel::onModelDataUpdateComplete); + connectItemModelEvents(rawSwitchFilteredModel); lock = true; @@ -172,12 +172,18 @@ void TimerPanel::on_name_editingFinished() } } -void TimerPanel::onModelDataAboutToBeUpdated() +void TimerPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TimerPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TimerPanel::onItemModelUpdateComplete); +} + +void TimerPanel::onItemModelAboutToBeUpdated() { lock = true; } -void TimerPanel::onModelDataUpdateComplete() +void TimerPanel::onItemModelUpdateComplete() { update(); lock = false; @@ -991,13 +997,19 @@ void ModulePanel::onClearAccessRxClicked() /******************************************************************************/ -SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels) : ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Setup), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { ui->setupUi(this); - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::TimersContext, this); + + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::TimersContext); + connectItemModelEvents(rawSwitchFilteredModel); + + thrSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_ThrSource)); + connectItemModelEvents(thrSourceFilteredModel); Board::Type board = firmware->getBoard(); @@ -1248,6 +1260,8 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge SetupPanel::~SetupPanel() { delete ui; + delete rawSwitchFilteredModel; + delete thrSourceFilteredModel; } void SetupPanel::on_extendedLimits_toggled(bool checked) @@ -1750,7 +1764,21 @@ void SetupPanel::onTimerNameChanged() updateItemModels(); } +void SetupPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &SetupPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &SetupPanel::onItemModelUpdateComplete); +} + +void SetupPanel::onItemModelAboutToBeUpdated() +{ +} + +void SetupPanel::onItemModelUpdateComplete() +{ +} + void SetupPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_TIMERS); + sharedItemModels->update(AbstractItemModel::IMUE_Timers); } diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index c56e63ea1..c931f9dd7 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -26,8 +26,8 @@ constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer"; -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; namespace Ui { class Setup; @@ -40,7 +40,8 @@ class TimerPanel : public ModelPanel Q_OBJECT public: - TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawItemFilteredModel * switchModel); + TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, + QWidget *prevFocus, FilteredItemModel * switchModel); virtual ~TimerPanel(); virtual void update(); @@ -51,8 +52,8 @@ class TimerPanel : public ModelPanel void on_value_editingFinished(); void on_minuteBeep_toggled(bool checked); void on_name_editingFinished(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); signals: void nameChanged(); @@ -60,6 +61,7 @@ class TimerPanel : public ModelPanel private: TimerData & timer; Ui::Timer * ui; + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class ModulePanel : public ModelPanel @@ -131,7 +133,7 @@ class SetupPanel : public ModelPanel Q_OBJECT public: - SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~SetupPanel(); virtual void update(); @@ -170,6 +172,8 @@ class SetupPanel : public ModelPanel void cmTimerMoveDown(); void cmTimerMoveUp(); void onTimerNameChanged(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Setup *ui; @@ -191,9 +195,11 @@ class SetupPanel : public ModelPanel bool moveTimerDownAllowed() const; bool moveTimerUpAllowed() const; void swapTimerData(int idx1, int idx2); - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; + CompoundItemModelFactory * sharedItemModels; + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * thrSourceFilteredModel; void updateItemModels(); - }; + void connectItemModelEvents(const FilteredItemModel * itemModel); +}; #endif // _SETUP_H_ diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp index e980c3943..423e10e5d 100644 --- a/companion/src/modeledit/telemetry.cpp +++ b/companion/src/modeledit/telemetry.cpp @@ -24,24 +24,36 @@ #include "ui_telemetry_sensor.h" #include "helpers.h" #include "appdata.h" -#include "rawitemfilteredmodel.h" #include -TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel): +constexpr char FIM_RAWSOURCE[] {"Raw Source"}; +constexpr char FIM_TELEALLSRC[] {"Tele All Source"}; +constexpr char FIM_TELEPOSSRC[] {"Tele Pos Source"}; +constexpr char FIM_SENSORTYPE[] {"Sensor.Type"}; +constexpr char FIM_SENSORFORMULA[] {"Sensor.Formula"}; +constexpr char FIM_SENSORCELLINDEX[] {"Sensor.CellIndex"}; +constexpr char FIM_SENSORUNIT[] {"Sensor.Unit"}; +constexpr char FIM_SENSORPRECISION[] {"Sensor.Precision"}; + +TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, + Firmware * firmware, const bool & parentLock, FilteredItemModelFactory * panelFilteredItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetryCustomScreen), - screen(screen) + screen(screen), + modelsUpdateCnt(0), + parentLock(parentLock) { ui->setupUi(this); - connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TelemetryCustomScreen::onModelDataAboutToBeUpdated); - connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &TelemetryCustomScreen::onModelDataUpdateComplete); + + FilteredItemModel * rawSourceFilteredModel = panelFilteredItemModels->getItemModel(FIM_RAWSOURCE); + connectItemModelEvents(rawSourceFilteredModel); 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(rawSourceModel); + fieldsCB[l][c]->setModel(rawSourceFilteredModel); ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1); connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int))); } @@ -50,7 +62,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(rawSourceModel); + barsCB[l]->setModel(rawSourceFilteredModel); connect(barsCB[l], SIGNAL(activated(int)), this, SLOT(barSourceChanged(int))); ui->screenBarsLayout->addWidget(barsCB[l], l, 0, 1, 1); @@ -203,7 +215,7 @@ void TelemetryCustomScreen::updateBar(int line) void TelemetryCustomScreen::on_screenType_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { memset(reinterpret_cast(&screen.body), 0, sizeof(screen.body)); update(); emit modified(); @@ -212,7 +224,7 @@ void TelemetryCustomScreen::on_screenType_currentIndexChanged(int index) void TelemetryCustomScreen::scriptNameEdited() { - if (!lock) { + if (!isLocked()) { lock = true; Helpers::getFileComboBoxValue(ui->scriptName, screen.body.script.filename, 8); emit modified(); @@ -222,7 +234,7 @@ void TelemetryCustomScreen::scriptNameEdited() void TelemetryCustomScreen::customFieldChanged(int value) { - if (lock || !sender() || !qobject_cast(sender())) + if (isLocked() || !sender() || !qobject_cast(sender())) return; bool ok; @@ -238,7 +250,7 @@ void TelemetryCustomScreen::customFieldChanged(int value) void TelemetryCustomScreen::barSourceChanged(int value) { - if (lock || !sender() || !qobject_cast(sender())) + if (isLocked() || !sender() || !qobject_cast(sender())) return; bool ok; @@ -256,7 +268,7 @@ void TelemetryCustomScreen::barSourceChanged(int value) void TelemetryCustomScreen::barMinChanged(double value) { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); screen.body.bars[line].barMin = round(value / minSB[line]->singleStep()); // TODO set min (maxSB) @@ -266,7 +278,7 @@ void TelemetryCustomScreen::barMinChanged(double value) void TelemetryCustomScreen::barMaxChanged(double value) { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep()); // TODO set max (minSB) @@ -276,7 +288,7 @@ void TelemetryCustomScreen::barMaxChanged(double value) void TelemetryCustomScreen::barTimeChanged() { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); int & valRef = (sender()->property("type").toString() == "min" ? screen.body.bars[line].barMin : screen.body.bars[line].barMax); TimerEdit * te = qobject_cast(sender()); @@ -289,29 +301,51 @@ void TelemetryCustomScreen::barTimeChanged() } } -void TelemetryCustomScreen::onModelDataAboutToBeUpdated() +void TelemetryCustomScreen::connectItemModelEvents(const FilteredItemModel * itemModel) { - lock = true; + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetryCustomScreen::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetryCustomScreen::onItemModelUpdateComplete); } -void TelemetryCustomScreen::onModelDataUpdateComplete() +void TelemetryCustomScreen::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void TelemetryCustomScreen::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + // leave updating to parent + lock = false; + } } /******************************************************/ -TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, + GeneralSettings & generalSettings, Firmware * firmware, const bool & parentLock, + FilteredItemModelFactory * panelFilteredItemModels) : ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetrySensor), sensor(sensor), - lock(false), sensorIndex(sensorIndex), selectedIndex(0), - sensorCapability(sensorCapability) + sensorCapability(sensorCapability), + modelsUpdateCnt(0), + parentLock(parentLock) { + // TODO ui definition housekeeping + // - remove all predefined combobox lists leaving to code + // - use Auto types for consistency ui->setupUi(this); + FilteredItemModel * fltmdl; + + connectItemModelEvents(panelFilteredItemModels->getItemModel(FIM_TELEALLSRC)); + connectItemModelEvents(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); + + lock = true; ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1)); ui->numLabel->setProperty("index", sensorIndex); ui->numLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -326,6 +360,9 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, connect(ui->numLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_customContextMenuRequested(QPoint))); ui->id->setField(sensor.id, this); ui->instance->setField(sensor.instance, this); + ui->type->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORTYPE)); + ui->formula->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORFORMULA)); + ui->unit->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORUNIT)); ui->ratio->setField(sensor.ratio, this); ui->offset->setField(sensor.offset, this); ui->autoOffset->setField(sensor.autoOffset, this); @@ -333,21 +370,29 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ui->logs->setField(sensor.logs, this); ui->persistent->setField(sensor.persistent, this); ui->onlyPositive->setField(sensor.onlyPositive, this); + fltmdl = panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC); + ui->gpsSensor->setModel(fltmdl); ui->gpsSensor->setField(sensor.gps, this); + ui->altSensor->setModel(fltmdl); ui->altSensor->setField(sensor.alt, this); + ui->ampsSensor->setModel(fltmdl); ui->ampsSensor->setField(sensor.amps, this); + ui->cellsSensor->setModel(fltmdl); ui->cellsSensor->setField(sensor.source, this); - ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST); - for (int i = SensorData::TELEM_CELL_INDEX_LOWEST + 1; i < SensorData::TELEM_CELL_INDEX_HIGHEST; i++) - ui->cellsIndex->addItem(tr("Cell %1").arg(i), i); - ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST); - ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA); + ui->cellsIndex->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORCELLINDEX)); ui->cellsIndex->setField(sensor.index); + fltmdl = panelFilteredItemModels->getItemModel(FIM_TELEALLSRC); + ui->source1->setModel(fltmdl); ui->source1->setField(sensor.sources[0], this); + ui->source2->setModel(fltmdl); ui->source2->setField(sensor.sources[1], this); + ui->source3->setModel(fltmdl); ui->source3->setField(sensor.sources[2], this); + ui->source4->setModel(fltmdl); ui->source4->setField(sensor.sources[3], this); - ui->prec->setField(sensor.prec, 0, 2, false, "", this); + ui->prec->setField(sensor.prec, 0, 2, false, "", this); // TODO replace autoprecisioncombobox with autocombobox and filtereditemmodel + lock = false; + update(); } @@ -358,6 +403,7 @@ TelemetrySensorPanel::~TelemetrySensorPanel() void TelemetrySensorPanel::update() { + // TODO use bit mask bool isConfigurable = false; bool gpsFieldsDisplayed = false; bool cellsFieldsDisplayed = false; @@ -369,8 +415,8 @@ void TelemetrySensorPanel::update() lock = true; ui->name->setText(sensor.label); - ui->type->setCurrentIndex(sensor.type); - ui->unit->setCurrentIndex(sensor.unit); + ui->type->setCurrentIndex(ui->type->findData(sensor.type)); + ui->unit->setCurrentIndex(ui->unit->findData(sensor.unit)); ui->id->updateValue(); ui->instance->updateValue(); ui->ratio->updateValue(); @@ -396,7 +442,7 @@ void TelemetrySensorPanel::update() ui->originLabel->hide(); ui->origin->hide(); ui->formula->show(); - ui->formula->setCurrentIndex(sensor.formula); + ui->formula->setCurrentIndex(ui->formula->findData(sensor.formula)); isConfigurable = (sensor.formula < SensorData::TELEM_FORMULA_CELL); gpsFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_DIST); cellsFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_CELL); @@ -404,14 +450,10 @@ void TelemetrySensorPanel::update() sources12FieldsDisplayed = (sensor.formula <= SensorData::TELEM_FORMULA_MULTIPLY); sources34FieldsDisplayed = (sensor.formula < SensorData::TELEM_FORMULA_MULTIPLY); totalizeFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_TOTALIZE); - updateSourcesComboBox(ui->source1, true); - updateSourcesComboBox(ui->source2, true); - updateSourcesComboBox(ui->source3, true); - updateSourcesComboBox(ui->source4, true); - updateSourcesComboBox(ui->gpsSensor, false); - updateSourcesComboBox(ui->altSensor, false); - updateSourcesComboBox(ui->ampsSensor, false); - updateSourcesComboBox(ui->cellsSensor, false); + ui->source1->updateValue(); + ui->source2->updateValue(); + ui->source3->updateValue(); + ui->source4->updateValue(); } else { ui->idLabel->show(); @@ -483,40 +525,9 @@ void TelemetrySensorPanel::update() lock = false; } -void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model, bool negative) -{ - cb->clear(); - if (negative) { - for (int i = -CPN_MAX_SENSORS; i < 0; ++i) { - const SensorData& sensor = model->sensorData[-i - 1]; - if (sensor.isAvailable()) { - if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); - else - cb->addItem(QString("-%1").arg(sensor.label), i); - } - } - } - cb->addItem("---", 0); - for (unsigned i = 1; i <= CPN_MAX_SENSORS; ++i) { - const SensorData& sensor = model->sensorData[i-1]; - if (sensor.isAvailable()) { - if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); - else - cb->addItem(QString("%1").arg(sensor.label), i); - } - } -} - -void TelemetrySensorPanel::updateSourcesComboBox(AutoComboBox * cb, bool negative) -{ - populateTelemetrySourcesComboBox(cb, model, negative); -} - void TelemetrySensorPanel::on_name_editingFinished() { - if (!lock) { + if (!isLocked() && (sensor.label != ui->name->text().toLatin1())) { strcpy(sensor.label, ui->name->text().toLatin1()); emit dataModified(); } @@ -524,8 +535,8 @@ void TelemetrySensorPanel::on_name_editingFinished() void TelemetrySensorPanel::on_type_currentIndexChanged(int index) { - if (!lock) { - sensor.type = index; + if (!isLocked()) { + sensor.type = ui->type->itemData(index).toInt(); update(); emit modified(); } @@ -533,8 +544,8 @@ void TelemetrySensorPanel::on_type_currentIndexChanged(int index) void TelemetrySensorPanel::on_formula_currentIndexChanged(int index) { - if (!lock) { - sensor.formula = index; + if (!isLocked()) { + sensor.formula = ui->formula->itemData(index).toInt(); if (sensor.formula == SensorData::TELEM_FORMULA_CELL) { sensor.prec = 2; sensor.unit = SensorData::UNIT_VOLTS; @@ -553,8 +564,8 @@ void TelemetrySensorPanel::on_formula_currentIndexChanged(int index) void TelemetrySensorPanel::on_unit_currentIndexChanged(int index) { - if (!lock) { - sensor.unit = index; + if (!isLocked()) { + sensor.unit = ui->unit->itemData(index).toInt(); if (sensor.unit == SensorData::UNIT_FAHRENHEIT) { sensor.prec = 0; } @@ -565,7 +576,7 @@ void TelemetrySensorPanel::on_unit_currentIndexChanged(int index) void TelemetrySensorPanel::on_prec_valueChanged() { - if (!lock) { + if (!isLocked()) { update(); } } @@ -686,15 +697,69 @@ void TelemetrySensorPanel::cmMoveDown() emit moveDownSensor(selectedIndex); } +void TelemetrySensorPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetrySensorPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetrySensorPanel::onItemModelUpdateComplete); +} + +void TelemetrySensorPanel::onItemModelAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void TelemetrySensorPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + // leave updating to parent + lock = false; + } +} + /******************************************************/ -TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Telemetry), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { ui->setupUi(this); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this); + + panelItemModels = new CompoundItemModelFactory(&generalSettings, &model); + panelFilteredItemModels = new FilteredItemModelFactory(); + int id; + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)), + FIM_RAWSOURCE); + connectItemModelEvents(id); + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_TeleSource)), + FIM_TELEALLSRC); + connectItemModelEvents(id); + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_TeleSource), + FilteredItemModel::PositiveFilter), + FIM_TELEPOSSRC); + connectItemModelEvents(id); + + id = panelItemModels->registerItemModel(SensorData::typeItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORTYPE); + + id = panelItemModels->registerItemModel(SensorData::formulaItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORFORMULA); + + id = panelItemModels->registerItemModel(SensorData::cellIndexItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORCELLINDEX); + + id = panelItemModels->registerItemModel(SensorData::unitItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORUNIT); + + id = panelItemModels->registerItemModel(SensorData::precisionItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORPRECISION); sensorCapability = firmware->getCapability(Sensors); if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability @@ -704,13 +769,15 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin model.frsky.usrProto = 1; } + ui->varioSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->varioSource->setField(model.frsky.varioSource, this); 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); + TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, + firmware, lock, panelFilteredItemModels); ui->sensorsLayout->addWidget(panel); sensorPanels[i] = panel; connect(panel, SIGNAL(dataModified()), this, SLOT(on_dataModifiedSensor())); @@ -723,7 +790,9 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin } if (IS_TARANIS_X9(firmware->getBoard())) { + ui->voltsSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->voltsSource->setField(model.frsky.voltsSource, this); + ui->altitudeSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->altitudeSource->setField(model.frsky.altitudeSource, this); } else { @@ -731,7 +800,8 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin } for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { - TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, rawSourceFilteredModel); + TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, lock, + panelFilteredItemModels); ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1)); telemetryCustomScreens[i] = tab; connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified); @@ -745,10 +815,14 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin TelemetryPanel::~TelemetryPanel() { delete ui; + delete panelFilteredItemModels; + delete panelItemModels; } void TelemetryPanel::update() { + lock = true; + if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { if (model->moduleData[0].protocol == PULSES_OFF && model->moduleData[1].protocol == PULSES_PPM) { ui->telemetryProtocol->setEnabled(true); @@ -758,10 +832,10 @@ void TelemetryPanel::update() ui->telemetryProtocol->setCurrentIndex(0); } - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); - populateTelemetrySourcesComboBox(ui->voltsSource, model, false); - populateTelemetrySourcesComboBox(ui->altitudeSource, model, false); - populateTelemetrySourcesComboBox(ui->varioSource, model, false); + ui->rssiSourceCB->updateValue(); + ui->voltsSource->updateValue(); + ui->altitudeSource->updateValue(); + ui->varioSource->updateValue(); } for (int i = 0; i < sensorCapability; ++i) { @@ -771,6 +845,8 @@ void TelemetryPanel::update() for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { telemetryCustomScreens[i]->update(); } + + lock = false; } void TelemetryPanel::setup() @@ -792,9 +868,9 @@ void TelemetryPanel::setup() ui->rssiSourceLabel->show(); ui->rssiSourceLabel->setText(tr("Source")); + ui->rssiSourceCB->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->rssiSourceCB->setField(model->rssiSource, this); ui->rssiSourceCB->show(); - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); ui->rssiAlarmWarningCB->hide(); ui->rssiAlarmCriticalCB->hide(); @@ -842,44 +918,9 @@ void TelemetryPanel::setup() lock = false; } -void TelemetryPanel::populateVarioSource() -{ - AutoComboBox * cb = ui->varioSource; - cb->setField(model->frsky.varioSource, this); - cb->addItem(tr("Alti"), TELEMETRY_VARIO_SOURCE_ALTI); - cb->addItem(tr("Alti+"), TELEMETRY_VARIO_SOURCE_ALTI_PLUS); - cb->addItem(tr("VSpeed"), TELEMETRY_VARIO_SOURCE_VSPEED); - cb->addItem(tr("A1"), TELEMETRY_VARIO_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_VARIO_SOURCE_A2); -} - -void TelemetryPanel::populateVoltsSource() -{ - AutoComboBox * cb = ui->frskyVoltCB; - cb->setField(model->frsky.voltsSource, this); - cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2); - cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4); - cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS); - cb->addItem(tr("Cells"), TELEMETRY_VOLTS_SOURCE_CELLS); -} - -void TelemetryPanel::populateCurrentSource() -{ - AutoComboBox * cb = ui->frskyCurrentCB; - cb->setField(model->frsky.currentSource, this); - cb->addItem(tr("---"), TELEMETRY_CURRENT_SOURCE_NONE); - cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2); - cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4); - cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS); -} - void TelemetryPanel::on_telemetryProtocol_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { model->telemetryProtocol = index; emit modified(); } @@ -892,7 +933,7 @@ void TelemetryPanel::onModified() void TelemetryPanel::on_bladesCount_editingFinished() { - if (!lock) { + if (!isLocked()) { model->frsky.blades = ui->bladesCount->value(); emit modified(); } @@ -900,7 +941,7 @@ void TelemetryPanel::on_bladesCount_editingFinished() void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { model->frsky.usrProto = index; for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) telemetryCustomScreens[i]->update(); @@ -910,31 +951,39 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index) void TelemetryPanel::on_rssiAlarmWarningSB_editingFinished() { - model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); - emit modified(); + if (!isLocked()) { + model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); + emit modified(); + } } void TelemetryPanel::on_rssiAlarmCriticalSB_editingFinished() { - model->rssiAlarms.critical = ui->rssiAlarmCriticalSB->value(); - emit modified(); + if (!isLocked()) { + model->rssiAlarms.critical = ui->rssiAlarmCriticalSB->value(); + emit modified(); + } } void TelemetryPanel::on_varioLimitMin_DSB_editingFinished() { - model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10); - emit modified(); + if (!isLocked()) { + model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10); + emit modified(); + } } void TelemetryPanel::on_varioLimitMax_DSB_editingFinished() { - model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10); - emit modified(); + if (!isLocked()) { + model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10); + emit modified(); + } } void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() { - if (!lock) { + if (!isLocked()) { if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } @@ -945,7 +994,7 @@ void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() { - if (!lock) { + if (!isLocked()) { if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } @@ -956,21 +1005,27 @@ void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() void TelemetryPanel::on_fasOffset_DSB_editingFinished() { - model->frsky.fasOffset = ui->fasOffset_DSB->value() * 10; - emit modified(); + if (!isLocked()) { + model->frsky.fasOffset = ui->fasOffset_DSB->value() * 10; + emit modified(); + } } void TelemetryPanel::on_mahCount_SB_editingFinished() { - model->frsky.storedMah = ui->mahCount_SB->value(); - emit modified(); + if (!isLocked()) { + model->frsky.storedMah = ui->mahCount_SB->value(); + emit modified(); + } } void TelemetryPanel::on_mahCount_ChkB_toggled(bool checked) { - model->frsky.mAhPersistent = checked; - ui->mahCount_SB->setDisabled(!checked); - emit modified(); + if (!isLocked()) { + model->frsky.mAhPersistent = checked; + ui->mahCount_SB->setDisabled(!checked); + emit modified(); + } } void TelemetryPanel::on_clearAllSensors() @@ -980,9 +1035,7 @@ void TelemetryPanel::on_clearAllSensors() model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i); } - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_insertSensor(int selectedIndex) @@ -990,10 +1043,7 @@ void TelemetryPanel::on_insertSensor(int selectedIndex) memmove(&model->sensorData[selectedIndex + 1], &model->sensorData[selectedIndex], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); model->sensorData[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); - - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_deleteSensor(int selectedIndex) @@ -1004,10 +1054,7 @@ void TelemetryPanel::on_deleteSensor(int selectedIndex) memmove(&model->sensorData[selectedIndex], &model->sensorData[selectedIndex + 1], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); model->sensorData[CPN_MAX_SENSORS - 1].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); - - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_moveUpSensor(int selectedIndex) @@ -1029,20 +1076,34 @@ void TelemetryPanel::swapData(int idx1, int idx2) memcpy(sd2, sd1, sizeof(SensorData)); memcpy(sd1, &sdtmp, sizeof(SensorData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } } void TelemetryPanel::on_dataModifiedSensor() { - updateItemModels(); - update(); + sharedItemModels->update(AbstractItemModel::IMUE_TeleSensors); emit modified(); } -void TelemetryPanel::updateItemModels() +void TelemetryPanel::connectItemModelEvents(const int id) { - commonItemModels->update(CommonItemModels::RMO_TELEMETRY_SENSORS); + FilteredItemModel * itemModel = panelFilteredItemModels->getItemModel(id); + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetryPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetryPanel::onItemModelUpdateComplete); +} + +void TelemetryPanel::onItemModelAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void TelemetryPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h index 9719c7df6..224f88020 100644 --- a/companion/src/modeledit/telemetry.h +++ b/companion/src/modeledit/telemetry.h @@ -23,12 +23,11 @@ #include "modeledit.h" #include "eeprominterface.h" +#include "filtereditemmodels.h" -constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor"; +constexpr char MIMETYPE_TELE_SENSOR[] {"application/x-companion-tele-sensor"}; class AutoComboBox; -class CommonItemModels; -class RawItemFilteredModel; class TimerEdit; namespace Ui { @@ -42,7 +41,8 @@ class TelemetryCustomScreen: public ModelPanel Q_OBJECT public: - TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel); + TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, + const bool & parentLock, FilteredItemModelFactory * panelFilteredItemModels); ~TelemetryCustomScreen(); void update(); @@ -54,8 +54,8 @@ class TelemetryCustomScreen: public ModelPanel void barMinChanged(double value); void barMaxChanged(double value); void barTimeChanged(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: void updateBar(int line); @@ -67,6 +67,11 @@ class TelemetryCustomScreen: public ModelPanel QDoubleSpinBox * maxSB[4]; TimerEdit * minTime[4]; TimerEdit * maxTime[4]; + int modelsUpdateCnt; + const bool &parentLock; + + inline bool isLocked() { return lock | parentLock; } + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class TelemetrySensorPanel: public ModelPanel @@ -74,7 +79,9 @@ class TelemetrySensorPanel: public ModelPanel Q_OBJECT public: - TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, + GeneralSettings & generalSettings, Firmware * firmware, const bool & parentLock, + FilteredItemModelFactory * panelFilteredItemModels); ~TelemetrySensorPanel(); void update(); @@ -86,7 +93,6 @@ class TelemetrySensorPanel: public ModelPanel void moveUpSensor(int index); void moveDownSensor(int index); - protected slots: void on_name_editingFinished(); void on_type_currentIndexChanged(int index); @@ -104,20 +110,23 @@ class TelemetrySensorPanel: public ModelPanel void cmDelete(); void cmMoveUp(); void cmMoveDown(); - - protected: - void updateSourcesComboBox(AutoComboBox * cb, bool negative); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::TelemetrySensor * ui; SensorData & sensor; - bool lock = false; int sensorIndex = 0; int selectedIndex = 0; int sensorCapability; bool insertAllowed() const; bool moveDownAllowed() const; bool moveUpAllowed() const; + int modelsUpdateCnt; + const bool &parentLock; + + inline bool isLocked() { return lock | parentLock; } + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class TelemetryPanel : public ModelPanel @@ -125,7 +134,8 @@ class TelemetryPanel : public ModelPanel Q_OBJECT public: - TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels); virtual ~TelemetryPanel(); virtual void update(); @@ -152,22 +162,24 @@ class TelemetryPanel : public ModelPanel void on_moveUpSensor(int index); void on_moveDownSensor(int index); void on_dataModifiedSensor(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Telemetry *ui; - TelemetryCustomScreen * telemetryCustomScreens[4]; - TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS]; + TelemetryCustomScreen *telemetryCustomScreens[4]; + TelemetrySensorPanel *sensorPanels[CPN_MAX_SENSORS]; int sensorCapability; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSourceFilteredModel; + CompoundItemModelFactory *sharedItemModels; + CompoundItemModelFactory *panelItemModels; + FilteredItemModelFactory *panelFilteredItemModels; + int modelsUpdateCnt; void setup(); void telBarUpdate(); - void populateVoltsSource(); - void populateCurrentSource(); - void populateVarioSource(); void swapData(int idx1, int idx2); - void updateItemModels(); + void connectItemModelEvents(const int id); + inline bool isLocked() { return lock; } }; #endif // _TELEMETRY_H_ diff --git a/companion/src/shared/autocombobox.h b/companion/src/shared/autocombobox.h index fcb1845ac..158352f97 100644 --- a/companion/src/shared/autocombobox.h +++ b/companion/src/shared/autocombobox.h @@ -37,30 +37,37 @@ class AutoComboBox: public QComboBox void clear() { - lock = true; - QComboBox::clear(); - next = 0; - lock = false; + if (!hasModel) { + lock = true; + QComboBox::clear(); + next = 0; + lock = false; + } } virtual void insertItems(int index, const QStringList & items) { - foreach(QString item, items) { - addItem(item); + if (!hasModel) { + foreach(QString item, items) { + addItem(item); + } } } virtual void addItem(const QString & item) { - addItem(item, next++); + if (!hasModel) + addItem(item, next++); } virtual void addItem(const QString & item, int value) { - lock = true; - QComboBox::addItem(item, value); - lock = false; - updateValue(); + if (!hasModel) { + lock = true; + QComboBox::addItem(item, value); + lock = false; + updateValue(); + } } void setField(unsigned int & field, GenericPanel * panel=nullptr) @@ -77,11 +84,22 @@ class AutoComboBox: public QComboBox updateValue(); } + void setModel(QAbstractItemModel * model) + { + lock = true; + QComboBox::setModel(model); + lock = false; + hasModel = true; + updateValue(); + } + void setAutoIndexes() { - for (int i=0; imodified(); + if (panel && panel->lock) + return; + if (index > -1) { + const int val = itemData(index).toInt(); + if (field && !lock) { + *field = val; + if (panel) + emit panel->modified(); + } + emit currentDataChanged(val); } - emit currentDataChanged(val); } protected: @@ -113,6 +135,7 @@ class AutoComboBox: public QComboBox GenericPanel * panel = nullptr; int next = 0; bool lock = false; + bool hasModel = false; }; #endif // _AUTOCOMBOBOX_H_