diff --git a/companion/src/datamodels/rawitemdatamodels.cpp b/companion/src/datamodels/rawitemdatamodels.cpp index d7c1b6682..3805b98d6 100644 --- a/companion/src/datamodels/rawitemdatamodels.cpp +++ b/companion/src/datamodels/rawitemdatamodels.cpp @@ -22,6 +22,7 @@ #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) @@ -187,28 +188,28 @@ void RawSwitchItemModel::update() 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; - if (i < 0) - flags = DataGroups::NegativeGroup; - else if (i > 0) - flags = DataGroups::PositiveGroup; - else - flags = DataGroups::NoneGroup; + 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, int index) const +void CurveItemModel::setDynamicItemData(QStandardItem * item, const int index) const { - item->setText(CurveReference(CurveReference::CURVE_REF_CUSTOM, index).toString(modelData, false)); - item->setData(true, IsAvailableRole); + CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, index); + item->setText(cr.toString(modelData, false)); + item->setData(cr.isAvailable(), IsAvailableRole); } void CurveItemModel::update() @@ -221,16 +222,228 @@ void CurveItemModel::update() emit dataUpdateComplete(); } + // -// CommonItemModels +// 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() @@ -241,24 +454,54 @@ 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: - case RMO_TIMERS: m_rawSourceItemModel->update(); + m_customFuncResetParamItemModel->update(); + m_telemetrySourceItemModel->update(); break; - case RMO_FLIGHT_MODES: + 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 index 48cb55fd2..fbcfe8be9 100644 --- a/companion/src/datamodels/rawitemdatamodels.h +++ b/companion/src/datamodels/rawitemdatamodels.h @@ -28,6 +28,7 @@ class GeneralSettings; class ModelData; +class AdjustmentReference; class AbstractRawItemDataModel: public QStandardItemModel { @@ -102,7 +103,78 @@ class CurveItemModel: public AbstractRawItemDataModel void update() override; protected: - void setDynamicItemData(QStandardItem * item, int index) const; + 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; }; @@ -130,11 +202,23 @@ class CommonItemModels: public QObject 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/firmwares/adjustmentreference.cpp b/companion/src/firmwares/adjustmentreference.cpp index 7181e15dd..ae487effa 100644 --- a/companion/src/firmwares/adjustmentreference.cpp +++ b/companion/src/firmwares/adjustmentreference.cpp @@ -19,7 +19,7 @@ */ #include "adjustmentreference.h" -#include "radiodata.h" // for ModelData +#include "modeldata.h" AdjustmentReference::AdjustmentReference(int value) { @@ -76,3 +76,8 @@ QString AdjustmentReference::toString(const ModelData * model, const bool sign) } return ret; } + +const bool AdjustmentReference::isAvailable() const +{ + return true; +} diff --git a/companion/src/firmwares/adjustmentreference.h b/companion/src/firmwares/adjustmentreference.h index 2a7b7e141..9377cd5e8 100644 --- a/companion/src/firmwares/adjustmentreference.h +++ b/companion/src/firmwares/adjustmentreference.h @@ -45,6 +45,7 @@ class AdjustmentReference { bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; } bool isValid(const int value) const; QString toString(const ModelData * model = nullptr, const bool sign = false) const; + const bool isAvailable() const; inline const int toValue() const { diff --git a/companion/src/firmwares/curvereference.cpp b/companion/src/firmwares/curvereference.cpp index 449dc0266..6ee2e38c5 100644 --- a/companion/src/firmwares/curvereference.cpp +++ b/companion/src/firmwares/curvereference.cpp @@ -63,6 +63,11 @@ const bool CurveReference::isValueNumber() const return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE; } +const bool CurveReference::isAvailable() const +{ + return true; +} + // static int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar) { @@ -101,6 +106,7 @@ QString CurveReference::functionToString(const int value) } /* + * CurveReferenceUIManager */ diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h index 0a1c7a180..018fb12aa 100644 --- a/companion/src/firmwares/curvereference.h +++ b/companion/src/firmwares/curvereference.h @@ -63,6 +63,7 @@ class CurveReference { const bool isValueNumber() const; const bool isValueReference() const { return !isValueNumber(); } const QString toString(const ModelData * model = nullptr, bool verbose = true) const; + const bool isAvailable() const; CurveRefType type; int value; diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index d6918e27c..d4942c60c 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -38,12 +38,12 @@ bool CustomFunctionData::isEmpty() const QString CustomFunctionData::nameToString(int index, bool globalContext) const { - return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true); + return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index + 1, 0, true); } QString CustomFunctionData::funcToString(const ModelData * model) const { - if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) + if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); else if (func == FuncTrainer) return tr("Trainer Sticks"); @@ -65,8 +65,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const return tr("Haptic"); else if (func == FuncReset) return tr("Reset"); - else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) - return tr("Set Timer %1").arg(func-FuncSetTimer1+1); + else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast) + return tr("Set %1").arg(RawSource(SOURCE_TYPE_SPECIAL, SOURCE_TYPE_SPECIAL_TIMER1_IDX + func - FuncSetTimer1).toString(model)); else if (func == FuncVario) return tr("Vario"); else if (func == FuncPlayPrompt) @@ -90,7 +90,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const else if (func == FuncBackgroundMusicPause) return tr("Background Music Pause"); else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) - return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model)); + return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1).toString(model)); else if (func == FuncSetFailsafe) return tr("Set Failsafe"); else if (func == FuncRangeCheckInternalModule) @@ -102,7 +102,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const else if (func == FuncBindExternalModule) return tr("Bind Ext. Module"); else { - return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is) + return QString(CPN_STR_UNKNOWN_ITEM); } } @@ -111,11 +111,16 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox int val = 0; Firmware * firmware = Firmware::getCurrentVariant(); - b->addItem(tr("Timer1"), val++); - b->addItem(tr("Timer2"), val++); - b->addItem( tr("Timer3"), val++); + for (int i = 0; i < CPN_MAX_TIMERS; i++, val++) { + if (i < firmware->getCapability(Timers)) { + RawSource item = RawSource(SOURCE_TYPE_SPECIAL, i + SOURCE_TYPE_SPECIAL_TIMER1_IDX); + b->addItem(item.toString(model), val); + } + } + b->addItem(tr("Flight"), val++); b->addItem(tr("Telemetry"), val++); + int reCount = firmware->getCapability(RotaryEncoders); if (reCount == 1) { b->addItem(tr("Rotary Encoder"), val++); @@ -124,6 +129,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox b->addItem(tr("REa"), val++); b->addItem(tr("REb"), val++); } + if (model) { for (int i = 0; i < firmware->getCapability(Sensors); ++i) { if (model->sensorData[i].isAvailable()) { @@ -132,6 +138,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox } } } + b->setCurrentIndex(b->findData(value)); } @@ -153,18 +160,18 @@ QString CustomFunctionData::paramToString(const ModelData * model) const return QString("%1").arg(param); } else if (func == FuncLogs) { - return QString("%1").arg(param/10.0) + tr("s"); + return QString("%1").arg(param / 10.0) + tr("s"); } else if (func == FuncPlaySound) { CustomFunctionData::populatePlaySoundParams(qs); - if (param>=0 && param<(int)qs.count()) + if (param >= 0 && param < (int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); } else if (func == FuncPlayHaptic) { CustomFunctionData::populateHapticParams(qs); - if (param>=0 && param<(int)qs.count()) + if (param >= 0 && param < (int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); @@ -193,7 +200,7 @@ QString CustomFunctionData::paramToString(const ModelData * model) const else if (func >= FuncAdjustGV1 && func < FuncCount) { switch (adjustMode) { case FUNC_ADJUST_GVAR_CONSTANT: - return tr("Value ")+QString("%1").arg(param); + return tr("Value ") + QString("%1").arg(param); case FUNC_ADJUST_GVAR_SOURCE: case FUNC_ADJUST_GVAR_GVAR: return RawSource(param).toString(); @@ -218,16 +225,16 @@ QString CustomFunctionData::repeatToString() const } else { unsigned int step = 1; - return tr("repeat(%1s)").arg(step*repeatParam); + return tr("repeat(%1s)").arg(step * repeatParam); } } QString CustomFunctionData::enabledToString() const { - if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) || + if ((func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) || (func == FuncReset) || - (func >= FuncSetTimer1 && func <= FuncSetTimer2) || + (func >= FuncSetTimer1 && func <= FuncSetTimerLast) || (func == FuncVolume) || (func == FuncBacklight) || (func <= FuncInstantTrim)) { @@ -238,6 +245,64 @@ QString CustomFunctionData::enabledToString() const return ""; } +// static +bool CustomFunctionData::isFuncAvailable(int index) +{ + Firmware * fw = getCurrentFirmware(); + + bool ret = (((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) && !fw->getCapability(SafetyChannelCustomFunction)) || + ((index == FuncVolume || index == FuncBackgroundMusic || index == FuncBackgroundMusicPause) && !fw->getCapability(HasVolume)) || + ((index == FuncPlayScript && !IS_HORUS_OR_TARANIS(fw->getBoard()))) || + ((index == FuncPlayHaptic) && !fw->getCapability(Haptic)) || + ((index == FuncPlayBoth) && !fw->getCapability(HasBeeper)) || + ((index == FuncLogs) && !fw->getCapability(HasSDLogs)) || + ((index >= FuncSetTimer1 && index <= FuncSetTimerLast) && index > FuncSetTimer1 + fw->getCapability(Timers)) || + ((index == FuncScreenshot) && !IS_HORUS_OR_TARANIS(fw->getBoard())) || + ((index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) && !fw->getCapability(DangerousFunctions)) || + ((index >= FuncAdjustGV1 && index <= FuncAdjustGVLast) && !fw->getCapability(Gvars)) + ); + return !ret; +} + +// static +int CustomFunctionData::funcContext(int index) +{ + int ret = AllFunctionContexts; + + if ((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) || + (index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) || + (index >= FuncAdjustGV1 && index <= FuncAdjustGVLast)) + ret &= ~GlobalFunctionsContext; + + return ret; +} +// static +int CustomFunctionData::resetParamCount(const ModelData * model) +{ + QComboBox cb; + CustomFunctionData::populateResetParams(model, &cb); + return cb.count(); +} + +// static +bool CustomFunctionData::isResetParamAvailable(const ModelData * model, int index) +{ + Firmware * firmware = getCurrentFirmware(); + + if (index < CPN_MAX_TIMERS) { + if (index < firmware->getCapability(Timers)) + return true; + else + return false; + } + else if (index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders)) + return true; + else if (model && index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders) + firmware->getCapability(Sensors)) + return model->sensorData[index - CPN_MAX_TIMERS - firmware->getCapability(RotaryEncoders)].isAvailable(); + + return false; +} + void CustomFunctionData::convert(RadioDataConversionState & cstate) { cstate.setComponent(tr("CFN"), 8); diff --git a/companion/src/firmwares/customfunctiondata.h b/companion/src/firmwares/customfunctiondata.h index 93f9969e8..9e597441f 100644 --- a/companion/src/firmwares/customfunctiondata.h +++ b/companion/src/firmwares/customfunctiondata.h @@ -35,7 +35,8 @@ class RadioDataConversionState; enum AssignFunc { FuncOverrideCH1 = 0, - FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1, + FuncOverrideCHLast = FuncOverrideCH1 + CPN_MAX_CHNOUT - 1, + FuncOverrideCH32 = FuncOverrideCHLast, // TODO remove FuncTrainer, FuncTrainerRUD, FuncTrainerELE, @@ -47,8 +48,9 @@ enum AssignFunc { FuncPlayHaptic, FuncReset, FuncSetTimer1, - FuncSetTimer2, - FuncSetTimer3, + FuncSetTimer2, // TODO remove + FuncSetTimer3, // TODO remove + FuncSetTimerLast = FuncSetTimer1 + CPN_MAX_TIMERS - 1, FuncVario, FuncPlayPrompt, FuncPlayBoth, @@ -61,7 +63,7 @@ enum AssignFunc { FuncBackgroundMusic, FuncBackgroundMusicPause, FuncAdjustGV1, - FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1, + FuncAdjustGVLast = FuncAdjustGV1 + CPN_MAX_GVARS - 1, FuncSetFailsafe, FuncRangeCheckInternalModule, FuncRangeCheckExternalModule, @@ -83,7 +85,15 @@ class CustomFunctionData { Q_DECLARE_TR_FUNCTIONS(CustomFunctionData) public: - CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; } + enum CustomFunctionContext + { + GlobalFunctionsContext = 0x01, + SpecialFunctionsContext = 0x02, + + AllFunctionContexts = GlobalFunctionsContext | SpecialFunctionsContext + }; + + CustomFunctionData(AssignFunc func = FuncOverrideCH1) { clear(); this->func = func; } RawSwitch swtch; AssignFunc func; int param; @@ -95,7 +105,7 @@ class CustomFunctionData { void clear(); bool isEmpty() const; QString nameToString(int index, bool globalContext = false) const; - QString funcToString(const ModelData * model = NULL) const; + QString funcToString(const ModelData * model = nullptr) const; QString paramToString(const ModelData * model) const; QString repeatToString() const; QString enabledToString() const; @@ -103,6 +113,10 @@ class CustomFunctionData { static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value); static void populatePlaySoundParams(QStringList & qs); static void populateHapticParams(QStringList & qs); + static bool isFuncAvailable(int index); + static int funcContext(int index); + static int resetParamCount(const ModelData * model); + static bool isResetParamAvailable(const ModelData * model, int index); void convert(RadioDataConversionState & cstate); diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 930df092c..7657e2798 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1439,3 +1439,42 @@ void ModelData::updateResetParam(CustomFunctionData * cfd) updRefInfo.updcnt++; } } + +QString ModelData::thrTraceSrcToString() const +{ + return thrTraceSrcToString((int)thrTraceSrc); +} + +QString ModelData::thrTraceSrcToString(const int index) const +{ + Firmware * firmware = getCurrentFirmware(); + const Boards board = Boards(getCurrentBoard()); + const int pscnt = board.getCapability(Board::Pots) + board.getCapability(Board::Sliders); + + if (index == 0) + return tr("THR"); + else if (index <= pscnt) + return board.getAnalogInputName(index + board.getCapability(Board::Sticks) - 1); + else if (index <= pscnt + firmware->getCapability(Outputs)) + return RawSource(SOURCE_TYPE_CH, index - pscnt - 1).toString(this); + + return QString(CPN_STR_UNKNOWN_ITEM); +} + +int ModelData::thrTraceSrcCount() const +{ + const Boards board = Boards(getCurrentBoard()); + Firmware * firmware = getCurrentFirmware(); + + return 1 + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + firmware->getCapability(Outputs); +} + +bool ModelData::isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const +{ + const Boards board = Boards(getCurrentBoard()); + + if (index > 0 && index <= board.getCapability(Board::Pots) + board.getCapability(Board::Sliders)) + return RawSource(SOURCE_TYPE_STICK, index + board.getCapability(Board::Sticks) - 1).isAvailable(this, generalSettings, board.getBoardType()); + else + return true; +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 7eacdc26d..2b277568f 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -283,6 +283,10 @@ class ModelData { bool hasExpoChildren(const int index); bool hasExpoSiblings(const int index); void removeMix(const int idx); + QString thrTraceSrcToString() const; + QString thrTraceSrcToString(const int index) const; + int thrTraceSrcCount() const; + bool isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const; protected: void removeGlobalVar(int & var); diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 67a640c33..67ad743b6 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -143,14 +143,14 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con static const QString rotary[] = { tr("REa"), tr("REb") }; if (index<0) { - return tr("???"); + return QString(CPN_STR_UNKNOWN_ITEM); } QString result; int genAryIdx = 0; switch (type) { case SOURCE_TYPE_NONE: - return tr("----"); + return QString(CPN_STR_NONE_ITEM); case SOURCE_TYPE_VIRTUAL_INPUT: { @@ -161,7 +161,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con } case SOURCE_TYPE_LUA_OUTPUT: - return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16)); + return tr("LUA%1%2").arg(index / 16 + 1).arg(QChar('a' + index % 16)); case SOURCE_TYPE_STICK: if (generalSettings) { @@ -193,10 +193,10 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return result; case SOURCE_TYPE_CUSTOM_SWITCH: - return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString(); + return RawSwitch(SWITCH_TYPE_VIRTUAL, index + 1).toString(); case SOURCE_TYPE_CYC: - return tr("CYC%1").arg(index+1); + return tr("CYC%1").arg(index + 1); case SOURCE_TYPE_PPM: return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1); @@ -208,18 +208,15 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return LimitData().nameToString(index); case SOURCE_TYPE_SPECIAL: - result = CHECK_IN_ARRAY(special, index); - // TODO refactor timers into own source type - if (result.startsWith("Timer")) { - bool ok; - int n = result.right(1).toInt(&ok); - if (ok) { - if (model) - result = model->timers[n - 1].nameToString(n - 1); - else - result = TimerData().nameToString(n - 1); - } + if (index >= SOURCE_TYPE_SPECIAL_TIMER1_IDX && index <= SOURCE_TYPE_SPECIAL_TIMER1_IDX + CPN_MAX_TIMERS - 1) { + if (model) + result = model->timers[index - SOURCE_TYPE_SPECIAL_TIMER1_IDX].nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX); + else + result = TimerData().nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX); } + else + result = CHECK_IN_ARRAY(special, index); + return result; case SOURCE_TYPE_TELEMETRY: @@ -241,7 +238,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return GVarData().nameToString(index); default: - return tr("???"); + return QString(CPN_STR_UNKNOWN_ITEM); } } @@ -409,4 +406,3 @@ QStringList RawSource::getSwitchList(Boards board) const } return ret; } - diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index 9d0b19450..a7d293173 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -178,6 +178,9 @@ enum RawSourceType { MAX_SOURCE_TYPE }; +constexpr int SOURCE_TYPE_STICK_THR_IDX { 3 }; // TODO is there a function to determine index? +constexpr int SOURCE_TYPE_SPECIAL_TIMER1_IDX { 2 }; // TODO temp const until Timers own source type + class RawSourceRange { Q_DECLARE_TR_FUNCTIONS(RawSourceRange) diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index a9b8d7640..2b01f2600 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -22,6 +22,7 @@ #include "radiodata.h" #include "modeldata.h" +#include "eeprominterface.h" void SensorData::updateUnit() { @@ -118,3 +119,40 @@ 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::sourceToString(const ModelData * model, const int index, const bool sign) +{ + if (model) { + const QString prfx = sign ? index < 0 ? "-" : "" : ""; + + if (abs(index) > 0) { + const SensorData &sd = model->sensorData[abs(index) - 1]; + if (sd.type == SensorData::TELEM_TYPE_CUSTOM) + return QString("%1%2 (%3)").arg(prfx).arg(sd.label).arg(sd.getOrigin(model)); + else + return QString("%1%2").arg(prfx).arg(sd.label); + } + else + return CPN_STR_NONE_ITEM; + } + else + 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; + } + } + + return false; +} diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index a2b993bcc..200f6e889 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -168,6 +168,9 @@ class SensorData { QString getOrigin(const ModelData* model) const; void clear() { memset(this, 0, sizeof(SensorData)); } bool isEmpty() const; + + static QString sourceToString(const ModelData * model, const int index, const bool sign = true); + static bool isSourceAvailable(const ModelData * model, const int index); }; #endif // SENSORDATA_H