From c6668071ea56aeb502d66fd763549377b938058f Mon Sep 17 00:00:00 2001 From: Neil Horne <15316949+elecpower@users.noreply.github.com> Date: Sat, 11 Oct 2025 08:53:25 +1100 Subject: [PATCH] chore(cpn): move global variables from flight/drive modes tab to own tab (#6624) --- companion/src/constants.h | 1 - companion/src/firmwares/boards.cpp | 2 +- companion/src/firmwares/boards.h | 2 +- companion/src/firmwares/eeprominterface.h | 1 - companion/src/firmwares/flightmodedata.cpp | 50 +- companion/src/firmwares/flightmodedata.h | 13 +- companion/src/firmwares/gvardata.cpp | 57 +- companion/src/firmwares/gvardata.h | 22 +- companion/src/firmwares/modeldata.cpp | 167 +++- companion/src/firmwares/modeldata.h | 13 +- .../src/firmwares/opentx/opentxinterface.cpp | 2 - companion/src/firmwares/rawsource.cpp | 3 - companion/src/firmwares/rawsource.h | 1 - companion/src/generaledit/generaledit.cpp | 4 +- companion/src/generaledit/generaloptions.cpp | 2 +- companion/src/generaledit/generalsetup.cpp | 62 -- companion/src/generaledit/generalsetup.h | 9 +- companion/src/generaledit/generalsetup.ui | 926 +++++++++--------- companion/src/helpers.cpp | 43 +- companion/src/helpers.h | 3 +- companion/src/modeledit/CMakeLists.txt | 1 + .../src/modeledit/colorcustomscreens.cpp | 2 +- companion/src/modeledit/flightmode.ui | 127 ++- companion/src/modeledit/flightmodes.cpp | 881 ++--------------- companion/src/modeledit/flightmodes.h | 67 +- companion/src/modeledit/gvars.cpp | 620 ++++++++++++ companion/src/modeledit/gvars.h | 102 ++ companion/src/modeledit/modeledit.cpp | 19 +- companion/src/modeledit/modeloptions.cpp | 2 +- companion/src/modeledit/setup.cpp | 4 +- companion/src/print/modelprinter.cpp | 18 +- companion/src/print/modelprinter.h | 1 - companion/src/print/multimodelprinter.cpp | 12 +- companion/src/shared/CMakeLists.txt | 2 +- ...{verticalscrollarea.cpp => scrollarea.cpp} | 9 +- .../{verticalscrollarea.h => scrollarea.h} | 4 +- 36 files changed, 1623 insertions(+), 1631 deletions(-) create mode 100644 companion/src/modeledit/gvars.cpp create mode 100644 companion/src/modeledit/gvars.h rename companion/src/shared/{verticalscrollarea.cpp => scrollarea.cpp} (76%) rename companion/src/shared/{verticalscrollarea.h => scrollarea.h} (89%) diff --git a/companion/src/constants.h b/companion/src/constants.h index b46395efa..6898636a0 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -31,7 +31,6 @@ #define CPN_MAX_CURVES 32 #define CPN_MAX_POINTS 17 #define CPN_MAX_GVARS 15 // 0, 9, 15 -#define CPN_MAX_ENCODERS 2 // rotary encoders #define CPN_MAX_CHNOUT 32 // number of real output channels #define CPN_MAX_LOGICAL_SWITCHES 64 // number of custom switches #define CPN_MAX_SPECIAL_FUNCTIONS 64 // number of functions assigned to switches diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index f0d8bbea4..97570dfbc 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -1182,7 +1182,7 @@ bool Boards::isSwitchFunc(int index, Board::Type board) return getBoardJson(board)->isSwitchFunc(index); } -QString Boards::getRadioTypeString(Board::Type board) +QString Boards::getRadioModeString(Board::Type board) { return getCapability(board == Board::BOARD_UNKNOWN ? getCurrentBoard() : board, Board::Air) ? tr("Flight") : tr("Drive"); } diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 6ad445293..79447a0b9 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -465,7 +465,7 @@ class Boards static AbstractStaticItemModel * flexTypeItemModel(); static std::string getLegacyAnalogMappedInputTag(const char * legacytag, Board::Type board = Board::BOARD_UNKNOWN); - static QString getRadioTypeString(Board::Type board = Board::BOARD_UNKNOWN); + static QString getRadioModeString(Board::Type board = Board::BOARD_UNKNOWN); static bool isAir(Board::Type board = Board::BOARD_UNKNOWN); static bool isSurface(Board::Type board = Board::BOARD_UNKNOWN); diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h index 669ee1085..412dbdde0 100644 --- a/companion/src/firmwares/eeprominterface.h +++ b/companion/src/firmwares/eeprominterface.h @@ -69,7 +69,6 @@ enum Capability { CustomAndSwitches, HasNegAndSwitches, LogicalSwitchesExt, - RotaryEncoders, Outputs, ChannelsName, ExtraInputs, diff --git a/companion/src/firmwares/flightmodedata.cpp b/companion/src/firmwares/flightmodedata.cpp index b13a73fc7..fe15c30d0 100644 --- a/companion/src/firmwares/flightmodedata.cpp +++ b/companion/src/firmwares/flightmodedata.cpp @@ -22,6 +22,8 @@ #include "flightmodedata.h" #include "radiodata.h" #include "radiodataconversionstate.h" +#include "compounditemmodels.h" +#include "eeprominterface.h" void FlightModeData::convert(RadioDataConversionState & cstate) { @@ -33,35 +35,44 @@ void FlightModeData::convert(RadioDataConversionState & cstate) void FlightModeData::clear(const int phaseIdx) { memset(reinterpret_cast(this), 0, sizeof(FlightModeData)); + for (int i = 0; i < CPN_MAX_GVARS; i++) { gvars[i] = linkedGVarFlightModeZero(phaseIdx); } - for (int i = 0; i < CPN_MAX_ENCODERS; i++) { - rotaryEncoders[i] = linkedREncFlightModeZero(phaseIdx); - } } QString FlightModeData::nameToString(int phaseIdx) const { - return RadioData::getElementName(Boards::isAir() ? tr("FM") : tr("DM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc + return RadioData::getElementName(tr("%1M").arg(modeAbbrev()), phaseIdx, name); // names are zero-based, FM0, FM1, etc +} + +// static +QString FlightModeData::modeAbbrev() +{ + return Boards::isAir() ? tr("F") : tr("D"); +} + +// static +QString FlightModeData::modeName() +{ + return Boards::isAir() ? tr("Flight") : tr("Drive"); } bool FlightModeData::isEmpty(int phaseIdx) const { if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0) return false; + for (int i = 0; i < CPN_MAX_TRIMS; i++) { if (trim[i] != 0 || trimRef[i] != 0 || trimMode[i] != 0) return false; } + for (int i = 0; i < CPN_MAX_GVARS; i++) { if (!isGVarEmpty(phaseIdx, i)) return false; } - for (int i = 0; i < CPN_MAX_ENCODERS; i++) { - if (!isREncEmpty(phaseIdx, i)) - return false; - } + return true; } @@ -69,13 +80,7 @@ bool FlightModeData::isGVarEmpty(int phaseIdx, int gvIdx) const { if ((phaseIdx == 0 && gvars[gvIdx] == 0) || (phaseIdx != 0 && gvars[gvIdx] == linkedGVarFlightModeZero(phaseIdx))) return true; - return false; -} -bool FlightModeData::isREncEmpty(int phaseIdx, int reIdx) const -{ - if ((phaseIdx == 0 && rotaryEncoders[reIdx] == 0) || (phaseIdx != 0 && rotaryEncoders[reIdx] == linkedREncFlightModeZero(phaseIdx))) - return true; return false; } @@ -83,6 +88,7 @@ int FlightModeData::linkedFlightModeZero(int phaseIdx, int maxOwnValue) const { if (phaseIdx == 0) return 0; + return maxOwnValue + 1; } @@ -91,7 +97,19 @@ int FlightModeData::linkedGVarFlightModeZero(int phaseIdx) const return linkedFlightModeZero(phaseIdx, GVAR_MAX_VALUE); } -int FlightModeData::linkedREncFlightModeZero(int phaseIdx) const +// static +AbstractStaticItemModel * FlightModeData::gvarModesItemModel(int excludeMode) { - return linkedFlightModeZero(phaseIdx, RENC_MAX_VALUE); + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_FLIGHTMODEDATA_GVARFM); + int modes = getCurrentFirmware()->getCapability(FlightModes); + + for (int i = 0; i < modes; i++) { + if (i != excludeMode) + mdl->appendToItemList(tr("%1M%2").arg(modeAbbrev()).arg(i), + GVAR_MAX_VALUE + 1 + i - (i > excludeMode ? 1 : 0)); + } + + mdl->loadItemList(); + return mdl; } diff --git a/companion/src/firmwares/flightmodedata.h b/companion/src/firmwares/flightmodedata.h index 3e06322b5..d95688475 100644 --- a/companion/src/firmwares/flightmodedata.h +++ b/companion/src/firmwares/flightmodedata.h @@ -25,12 +25,15 @@ #include "rawswitch.h" #include +#include class RadioDataConversionState; +class AbstractStaticItemModel; +class Firmware; #define FLIGHTMODE_NAME_LEN 10 -#define RENC_MAX_VALUE 1024 -#define RENC_MIN_VALUE -RENC_MAX_VALUE + +constexpr char AIM_FLIGHTMODEDATA_GVARFM[] {"flightmodedata.gvarfm"}; class FlightModeData { Q_DECLARE_TR_FUNCTIONS(FlightModeData) @@ -45,7 +48,6 @@ class FlightModeData { char name[FLIGHTMODE_NAME_LEN + 1]; unsigned int fadeIn; unsigned int fadeOut; - int rotaryEncoders[CPN_MAX_ENCODERS]; int gvars[CPN_MAX_GVARS]; void convert(RadioDataConversionState & cstate); @@ -53,8 +55,9 @@ class FlightModeData { bool isEmpty(int phaseIdx) const; QString nameToString(int phaseIdx) const; bool isGVarEmpty(int phaseIdx, int gvIdx) const; - bool isREncEmpty(int phaseIdx, int reIdx) const; int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const; int linkedGVarFlightModeZero(int phaseIdx) const; - int linkedREncFlightModeZero(int phaseIdx) const; + static AbstractStaticItemModel * gvarModesItemModel(int excludeMode); + static QString modeAbbrev(); + static QString modeName(); }; diff --git a/companion/src/firmwares/gvardata.cpp b/companion/src/firmwares/gvardata.cpp index 8c4f2c60c..34aec7bdc 100644 --- a/companion/src/firmwares/gvardata.cpp +++ b/companion/src/firmwares/gvardata.cpp @@ -20,12 +20,17 @@ */ #include "gvardata.h" - #include "radiodata.h" +#include "compounditemmodels.h" QString GVarData::unitToString() const { - switch (unit) { + return unitToString(unit); +} + +QString GVarData::unitToString(int val) +{ + switch (val) { case GVAR_UNIT_NUMBER: return tr(""); case GVAR_UNIT_PERCENT: @@ -37,7 +42,12 @@ QString GVarData::unitToString() const QString GVarData::precToString() const { - switch (prec) { + return precToString(prec); +} + +QString GVarData::precToString(int val) +{ + switch (val) { case GVAR_PREC_MUL10: return tr("0._"); case GVAR_PREC_MUL1: @@ -96,3 +106,44 @@ bool GVarData::isEmpty() const { return (name[0] == '\0' && min == 0 && max == 0 && (!popup) && prec == 0 && unit == 0); } + +AbstractStaticItemModel * GVarData::precItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GVARDATA_UNIT); + + for (int i = 0; i < GVAR_PREC_COUNT; i++) { + mdl->appendToItemList(precToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +AbstractStaticItemModel * GVarData::unitItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GVARDATA_UNIT); + + for (int i = 0; i < GVAR_UNIT_COUNT; i++) { + mdl->appendToItemList(unitToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +QDataStream &operator<<(QDataStream &out, const GVarData &data) { + QByteArray name(data.name); + name.resize(sizeof(data.name)); + out << name << data.min << data.max << data.prec << data.unit; + return out; +} + +QDataStream &operator>>(QDataStream &in, GVarData &data) { + QByteArray name; + name.resize(sizeof(data.name)); + in >> name >> data.min >> data.max >> data.prec >> data.unit; + memcpy(data.name, name.constData(), sizeof(data.name)); + return in; +} diff --git a/companion/src/firmwares/gvardata.h b/companion/src/firmwares/gvardata.h index 1279a8b01..b44a916e7 100644 --- a/companion/src/firmwares/gvardata.h +++ b/companion/src/firmwares/gvardata.h @@ -19,15 +19,19 @@ * GNU General Public License for more details. */ -#ifndef GVARDATA_H -#define GVARDATA_H +#pragma once #include +constexpr char AIM_GVARDATA_PREC[] {"gvardata.prec"}; +constexpr char AIM_GVARDATA_UNIT[] {"gvardata.unit"}; + #define GVAR_NAME_LEN 3 #define GVAR_MAX_VALUE 1024 #define GVAR_MIN_VALUE -GVAR_MAX_VALUE +class AbstractStaticItemModel; + class GVarData { Q_DECLARE_TR_FUNCTIONS(GVarData) @@ -36,12 +40,14 @@ class GVarData { enum { GVAR_UNIT_NUMBER, - GVAR_UNIT_PERCENT + GVAR_UNIT_PERCENT, + GVAR_UNIT_COUNT }; enum { GVAR_PREC_MUL10, - GVAR_PREC_MUL1 + GVAR_PREC_MUL1, + GVAR_PREC_COUNT }; char name[GVAR_NAME_LEN + 1]; @@ -53,7 +59,9 @@ class GVarData { void clear() {memset(this, 0, sizeof(GVarData)); } QString unitToString() const; + static QString unitToString(int val); QString precToString() const; + static QString precToString(int val); QString nameToString(int index) const; int multiplierSet(); float multiplierGet() const; @@ -64,7 +72,9 @@ class GVarData { float getMinPrec() const; float getMaxPrec() const; bool isEmpty() const; + static AbstractStaticItemModel * unitItemModel(); + static AbstractStaticItemModel * precItemModel(); }; - -#endif // GVARDATA_H +QDataStream &operator<<(QDataStream &out, const GVarData &obj); +QDataStream &operator>>(QDataStream &in, GVarData &obj); diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 9d5422114..d27211728 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -304,39 +304,6 @@ int ModelData::getGVarValue(int phaseIdx, int gvarIdx) return flightModeData[0].gvars[gvarIdx]; // circular linked so return FM0 value } -bool ModelData::isREncLinked(int phaseIdx, int reIdx) -{ - return flightModeData[phaseIdx].rotaryEncoders[reIdx] > RENC_MAX_VALUE; -} - -bool ModelData::isREncLinkedCircular(int phaseIdx, int reIdx) -{ - for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { - int val = flightModeData[phaseIdx].rotaryEncoders[reIdx]; - if (phaseIdx == 0 || val <= RENC_MAX_VALUE) - return false; - int nextPhase = val - (RENC_MAX_VALUE + 1); - if (nextPhase >= phaseIdx) - nextPhase += 1; - phaseIdx = nextPhase; - } - return true; -} - -int ModelData::getREncValue(int phaseIdx, int reIdx) -{ - for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { - int val = flightModeData[phaseIdx].rotaryEncoders[reIdx]; - if (phaseIdx == 0 || val <= RENC_MAX_VALUE) - return val; - int nextPhase = val - (RENC_MAX_VALUE + 1); - if (nextPhase >= phaseIdx) - nextPhase += 1; - phaseIdx = nextPhase; - } - return flightModeData[0].rotaryEncoders[reIdx]; // circular linked so return FM0 value -} - void ModelData::setTrimValue(int phaseIdx, int trimIdx, int value) { for (uint8_t i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { @@ -1346,18 +1313,6 @@ void ModelData::setGVarFlightModeIndexToValue(const int phaseIdx, const int gvar flightModeData[phaseIdx].gvars[gvarIdx] = linkedFlightModeIndexToValue(phaseIdx, useFmIdx, GVAR_MAX_VALUE); } -int ModelData::getREncFlightModeIndex(const int phaseIdx, const int reIdx) -{ - if (!isREncLinked(phaseIdx, reIdx)) - return -1; - return (linkedFlightModeValueToIndex(phaseIdx, flightModeData[phaseIdx].rotaryEncoders[reIdx], RENC_MAX_VALUE)); -} - -void ModelData::setREncFlightModeIndexToValue(const int phaseIdx, const int reIdx, const int useFmIdx) -{ - flightModeData[phaseIdx].rotaryEncoders[reIdx] = linkedFlightModeIndexToValue(phaseIdx, useFmIdx, RENC_MAX_VALUE); -} - bool ModelData::isExpoParent(const int index) { const ExpoData &ed = expoData[index]; @@ -1494,7 +1449,7 @@ void ModelData::updateResetParam(CustomFunctionData * cfd) idxAdj = -2; // reverse earlier offset required for rawsource break; case REF_UPD_TYPE_SENSOR: - idxAdj = 5/*3 Timers + Flight + Telemetery*/ + firmware->getCapability(RotaryEncoders); + idxAdj = 5/*3 Timers + Flight + Telemetery*/; if (cfd->param < idxAdj || cfd->param > (idxAdj + firmware->getCapability(Sensors))) return; break; @@ -2051,3 +2006,123 @@ QString ModelData::getChecklistFilename() const { return QString(name).replace(" ", "_").append(".txt").toLower(); } + +void ModelData::gvarClear(const int index, bool updateRefs) +{ + gvarData[index].clear(); + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + FlightModeData &fm = flightModeData[i]; + fm.gvars[index] = fm.linkedGVarFlightModeZero(i); + } + + if (updateRefs) { + updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, + ModelData::REF_UPD_ACT_CLEAR, index); + } +} + +void ModelData::gvarSetMax(const int index, const float value) +{ + gvarData[index].setMax(value); + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + if (!isGVarLinked(i, index)) { + if (flightModeData[i].gvars[index] > gvarData[index].getMax()) { + flightModeData[i].gvars[index] = gvarData[index].getMax(); + } + } + } +} + +void ModelData::gvarSetMin(const int index, const float value) +{ + gvarData[index].setMin(value); + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + if (!isGVarLinked(i, index)) { + if (flightModeData[i].gvars[index] < gvarData[index].getMin()) { + flightModeData[i].gvars[index] = gvarData[index].getMin(); + } + } + } +} + +void ModelData::gvarSwap(const int index1, const int index2) +{ + if (index1 != index2) { + GVarData gvtmp = gvarData[index2]; + GVarData *gv1 = &gvarData[index1]; + GVarData *gv2 = &gvarData[index2]; + memcpy(gv2, gv1, sizeof(GVarData)); + memcpy(gv1, &gvtmp, sizeof(GVarData)); + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + FlightModeData &fm = flightModeData[i]; + int gvar = fm.gvars[index2]; + fm.gvars[index2] = fm.gvars[index1]; + fm.gvars[index1] = gvar; + } + + updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, + ModelData::REF_UPD_ACT_SWAP, index1, index2); + } +} + +void ModelData::gvarDelete(const int index) +{ + memmove(&gvarData[index], &gvarData[index + 1], + (CPN_MAX_GVARS - (index + 1)) * sizeof(GVarData)); + gvarData[CPN_MAX_GVARS - 1].clear(); + + for (int j = 0; j < CPN_MAX_FLIGHT_MODES; j++) { + for (int i = index; i < (CPN_MAX_GVARS - 1); i++) { + flightModeData[j].gvars[i] = flightModeData[j].gvars[i + 1]; + } + } + + for (int j = 0; j < CPN_MAX_FLIGHT_MODES; j++) { + flightModeData[j].gvars[CPN_MAX_GVARS - 1] = flightModeData[j].linkedGVarFlightModeZero(j); + } + + updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, + ModelData::REF_UPD_ACT_SHIFT, index, 0, -1); +} + +void ModelData::gvarInsert(const int index) +{ + memmove(&gvarData[index + 1], &gvarData[index], + (CPN_MAX_GVARS - (index + 1)) * sizeof(GVarData)); + gvarData[index].clear(); + + for (int j = 0; j < CPN_MAX_FLIGHT_MODES; j++) { + for (int i = (CPN_MAX_GVARS - 1); i > index; i--) { + flightModeData[j].gvars[i] = flightModeData[j].gvars[i - 1]; + } + } + + for (int j = 0; j < CPN_MAX_FLIGHT_MODES; j++) { + flightModeData[j].gvars[index] = flightModeData[j].linkedGVarFlightModeZero(j); + } + + updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, + ModelData::REF_UPD_ACT_SHIFT, index, 0, 1); +} + +bool ModelData::gvarInsertAllowed(const int index) +{ + bool ret = true; + int gvars = getCurrentFirmware()->getCapability(Gvars); + + if (index == (gvars - 1) || !gvarData[gvars - 1].isEmpty()) + ret = false; + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + if (flightModeData[i].gvars[gvars - 1] != + flightModeData[i].linkedGVarFlightModeZero(i)) + ret = false; + } + + return ret; + +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 080b3d9fb..bbced7a3d 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -262,12 +262,13 @@ class ModelData { float getGVarValuePrec(int phaseIdx, int gvarIdx); int getGVarFlightModeIndex(const int phaseIdx, const int gvarIdx); void setGVarFlightModeIndexToValue(const int phaseIdx, const int gvarIdx, const int useFmIdx); - - bool isREncLinked(int phaseIdx, int reIdx); - bool isREncLinkedCircular(int phaseIdx, int reIdx); - int getREncValue(int phaseIdx, int reIdx); - int getREncFlightModeIndex(const int phaseIdx, const int reIdx); - void setREncFlightModeIndexToValue(const int phaseIdx, const int reIdx, const int useFmIdx); + void gvarClear(const int index, bool updateRefs = true); + void gvarSetMax(const int index, const float value); + void gvarSetMin(const int index, const float value); + void gvarSwap(const int index1, const int index2); + void gvarDelete(const int index); + void gvarInsert(const int index); + bool gvarInsertAllowed(const int index); ModelData removeGlobalVars(); diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index cfe992c15..7b716793a 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -138,8 +138,6 @@ int OpenTxFirmware::getCapability(::Capability capability) return getCapability(LogicalSwitches); case LogicalSwitchesExt: return true; - case RotaryEncoders: - return 0; case Outputs: return 32; case NumCurvePoints: diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 68f699bd9..c784bafb6 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -188,9 +188,6 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con (Boards::isAir(board) ? CHECK_IN_ARRAY(trimsAir, index) : CHECK_IN_ARRAY(trimsSurface, index))); - case SOURCE_TYPE_ROTARY_ENCODER: - return CHECK_IN_ARRAY(rotary, index); - case SOURCE_TYPE_MIN: return tr("MIN"); diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index 9c2fe8376..ba00c7b02 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -167,7 +167,6 @@ enum RawSourceType { SOURCE_TYPE_VIRTUAL_INPUT, SOURCE_TYPE_LUA_OUTPUT, SOURCE_TYPE_INPUT, - SOURCE_TYPE_ROTARY_ENCODER, SOURCE_TYPE_TRIM, SOURCE_TYPE_MIN, SOURCE_TYPE_MAX, diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index cfcc06e10..c97efc4ee 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -29,7 +29,7 @@ #include "hardware.h" #include "../modeledit/customfunctions.h" #include "generaloptions.h" -#include "verticalscrollarea.h" +#include "scrollarea.h" #include "compounditemmodels.h" GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) : @@ -96,7 +96,7 @@ void GeneralEdit::addTab(GenericPanel *panel, QString text) panels << panel; QWidget * widget = new QWidget(ui->tabWidget); QVBoxLayout *baseLayout = new QVBoxLayout(widget); - VerticalScrollArea * area = new VerticalScrollArea(widget, panel); + ScrollArea * area = new ScrollArea(widget, panel); baseLayout->addWidget(area); ui->tabWidget->addTab(widget, text); connect(panel, &GenericPanel::modified, this, &GeneralEdit::onTabModified); diff --git a/companion/src/generaledit/generaloptions.cpp b/companion/src/generaledit/generaloptions.cpp index 57347a8a4..51d57334d 100644 --- a/companion/src/generaledit/generaloptions.cpp +++ b/companion/src/generaledit/generaloptions.cpp @@ -68,7 +68,7 @@ GeneralOptionsPanel::GeneralOptionsPanel(QWidget * parent, GeneralSettings & gen addParams(); } - addLabel(tr("%1 Modes").arg(Boards::getRadioTypeString(board))); + addLabel(tr("%1 Modes").arg(Boards::getRadioModeString(board))); AutoCheckBox *fmDisable = new AutoCheckBox(this); fmDisable->setField(generalSettings.modelFMDisabled, this, true); params->append(fmDisable); diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index da6ec4994..96078c238 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -145,14 +145,6 @@ ui(new Ui::GeneralSetup) ui->faimode_CB->setChecked(generalSettings.fai); } - if (!firmware->getCapability(RotaryEncoderNavigation)) { - ui->rotEncMode_CB->hide(); - ui->rotEncMode_label->hide(); - } - else { - populateRotEncModeCB(); - } - if (!firmware->getCapability(HasPxxCountry)) { ui->countrycode_label->hide(); ui->countrycode_CB->hide(); @@ -260,15 +252,6 @@ ui(new Ui::GeneralSetup) ui->hapticmodeCB->setDisabled(true); } - int reCount = firmware->getCapability(RotaryEncoders); - if (reCount == 0) { - ui->re_label->hide(); - ui->re_CB->hide(); - } - else { - populateRotEncCB(reCount); - } - if (Boards::getCapability(firmware->getBoard(), Board::HasColorLcd)) { ui->backlightautoSB->setMinimum(5); } @@ -505,18 +488,6 @@ void GeneralSetupPanel::updateVarioPitchRange() ui->varioPMax_SB->setMinimum(700 + (generalSettings.varioPitch * 10) + 1000 - 800); } -void GeneralSetupPanel::populateRotEncCB(int reCount) -{ - QString strings[] = { tr("No"), tr("RotEnc A"), tr("Rot Enc B"), tr("Rot Enc C"), tr("Rot Enc D"), tr("Rot Enc E")}; - QComboBox * b = ui->re_CB; - - b->clear(); - for (int i = 0; i <= reCount; i++) { - b->addItem(strings[i]); - } - b->setCurrentIndex(generalSettings.reNavigation); -} - int pwrDelayFromYaml(int delay) { static int8_t vals[] = { 1, 4, 3, 2, 0 }; @@ -631,31 +602,6 @@ void GeneralSetupPanel::on_faimode_CB_stateChanged(int) } } -void GeneralSetupPanel::populateRotEncModeCB() -{ - QComboBox * b = ui->rotEncMode_CB; - QString strings[] = { tr("Normal"), tr("Inverted"), tr("Vertical Inverted, Horizontal Normal"), tr("Vertical Inverted, Horizontal Alternate"), tr("Normal, Edit Inverted") }; - int itemCount = 5; - - if (Boards::getCapability(firmware->getBoard(), Board::HasColorLcd)) { - itemCount = 2; - } - - b->clear(); - for (int i = 0; i < itemCount; i++) { - b->addItem(strings[i], 0); - } - b->setCurrentIndex(generalSettings.rotEncMode); -} - -void GeneralSetupPanel::on_rotEncMode_CB_currentIndexChanged(int index) -{ - if (!lock) { - generalSettings.rotEncMode = index; - emit modified(); - } -} - void GeneralSetupPanel::on_speakerPitchSB_editingFinished() { if (!lock) { @@ -835,14 +781,6 @@ void GeneralSetupPanel::on_vBatMaxDSB_editingFinished() } } -void GeneralSetupPanel::on_re_CB_currentIndexChanged(int index) -{ - if (!lock) { - generalSettings.reNavigation = ui->re_CB->currentIndex(); - emit modified(); - } -} - void GeneralSetupPanel::on_countrycode_CB_currentIndexChanged(int index) { if (!lock) { diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h index 2f09e4778..9672eaf3b 100644 --- a/companion/src/generaledit/generalsetup.h +++ b/companion/src/generaledit/generalsetup.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _GENERALSETUP_H_ -#define _GENERALSETUP_H_ +#pragma once #include "generaledit.h" #include "eeprominterface.h" @@ -48,12 +47,10 @@ class GeneralSetupPanel : public GeneralPanel void on_displayTypeCB_currentIndexChanged(int index); void on_BLBright_SB_editingFinished(); void on_OFFBright_SB_editingFinished(); - void on_re_CB_currentIndexChanged(int index); void on_countrycode_CB_currentIndexChanged(int index); void on_units_CB_currentIndexChanged(int index); void on_ppm_units_CB_currentIndexChanged(int index); void on_faimode_CB_stateChanged(int ); - void on_rotEncMode_CB_currentIndexChanged(int index); void on_speakerPitchSB_editingFinished(); void on_timezoneLE_textEdited(const QString &text); void on_adjustRTC_stateChanged(int); @@ -116,9 +113,5 @@ class GeneralSetupPanel : public GeneralPanel void setValues(); void populateBacklightCB(); void populateVoiceLangCB(); - void populateRotEncCB(int reCount); - void populateRotEncModeCB(); void updateVarioPitchRange(); }; - -#endif // _GENERALSETUP_H_ diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index 68a30ddd2..fbabc39e3 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -24,7 +24,7 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint 0 @@ -81,7 +81,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -140,7 +140,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -183,7 +183,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -226,7 +226,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -269,7 +269,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -312,7 +312,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -355,7 +355,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -466,7 +466,7 @@ true - QSlider::NoTicks + QSlider::TickPosition::NoTicks 1 @@ -489,7 +489,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -503,16 +503,6 @@ - - - - Vario volume - - - - - - @@ -520,128 +510,7 @@ - - - - Label matching - - - - - - - America - - - - - Japan - - - - - Europe - - - - - - - - Speaker Pitch (spkr only) - - - - - - - Backlight flash on alarm - - - - - - - -2 - - - 2 - - - 1 - - - Qt::Horizontal - - - - - - - Backlight Switch - - - - - - - -2 - - - 2 - - - 1 - - - Qt::Horizontal - - - - - - - - - Color 1 - - - - - - - 20 - - - 5 - - - - - - - Color 2 - - - - - - - - - Favorites matching - - - - - - - Country Code - - - - @@ -652,7 +521,7 @@ Automatically adjust the radio's clock if a GPS is connected to telemetry. - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight Adjust RTC @@ -661,30 +530,14 @@ - - + + - Sound Mode + Backlight Auto OFF after - - - - -2 - - - 2 - - - 1 - - - Qt::Horizontal - - - - + @@ -716,38 +569,181 @@ - - - - - Must match - - - - - Optional match - - - - - - - - 8 + + + + Wav volume - - + + + + + Match all + + + + + Match any + + + + + + + + Enable this to quickly change model on the model select page (a long press can then be used to open the model edit menu). + - Backlight Auto OFF after + + + + + + + + Keys Backlight + + + + + + + Background volume + + + + + + + Vario repeat at zero + + + + + + + Owner Registration ID - + - Manage Models layout + Label selection mode + + + + + + + 23 + + + 5 + + + 0 + + + Qt::Orientation::Horizontal + + + + + + + 100 + + + + + + + Label matching + + + + + + + -2 + + + 2 + + + 1 + + + Qt::Orientation::Horizontal + + + + + + + FAI Mode + + + + + + + + Multi select + + + + + Single select + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Backlight OFF Brightness + + + + + + + + + + + + + This is the switch selectrion for turning on the backlight (if installed). + + + + + -1 @@ -770,151 +766,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Multi select - - - - - Single select - - - - - - - - - Match all - - - - - Match any - - - - - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html> - - - 1 - - - 20 - - - 1 - - - - - - - Backlight OFF Brightness - - - - - - - Vario pitch at zero - - - - - - - Wav volume - - - - - - - - - - - - - This is the switch selectrion for turning on the backlight (if installed). - - - - - -1 - - - - - - - Owner Registration ID - - - - - - - Timeshift from UTC - - - - - - - Model quick select - - - - - - - - - - - - - - FAI Mode - - - - - - @@ -927,70 +778,93 @@ p, li { white-space: pre-wrap; } 1 - Qt::Horizontal + Qt::Orientation::Horizontal - - + + - Enable this to quickly change model on the model select page (a long press can then be used to open the model edit menu). + If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. - - - - Background volume + + + + Hz - - - - - 5 + 1300 - 100 + 2900 + + + 10 + + + 1700 - - - - Rotary Encoder Mode - + + + + + Large image (2 columns) + + + + + Small image (3 columns) + + + + + Name only (2 columns) + + + + + Name only (1 column) + + - - - - Voice Language - - + + + + + + Color 1 + + + + + + + 20 + + + 5 + + + + + + + Color 2 + + + + - - - - 100 - - - - - - - - 0 - 0 - - - - Stick reverse - - + + @@ -1016,20 +890,68 @@ p, li { white-space: pre-wrap; } - - - - If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. - + + - + Vario volume - - + + + + 8 + + + + + - Keys Backlight + Country Code + + + + + + + Voice Language + + + + + + + Speaker Pitch (spkr only) + + + + + + + Vario pitch at zero + + + + + + + 5 + + + 100 + + + + + + + + 0 + 0 + + + + Stick reverse @@ -1052,36 +974,72 @@ p, li { white-space: pre-wrap; } - - - - Speaker Volume - - - - - - - 23 - - - 5 - - - 0 - - - Qt::Horizontal - - - - - + + + + + + + + + + Must match + + + + + Optional match + + + + + + + + Sound Mode + + + + + + + Timeshift from UTC + + + + + + + Backlight color + + + + + + + Beep volume + + + + + + + Backlight flash on alarm + + + + + + + Backlight Switch + + + @@ -1110,41 +1068,109 @@ p, li { white-space: pre-wrap; } - - + + - Large image (2 columns) + America - Small image (3 columns) + Japan - Name only (2 columns) - - - - - Name only (1 column) + Europe - - + + - Vario repeat at zero + Manage Models layout - - + + + + -2 + + + 2 + + + 1 + + + Qt::Orientation::Horizontal + + + + + - Label selection mode + Rotary Encoder Mode + + + + + + + -2 + + + 2 + + + 1 + + + Qt::Orientation::Horizontal + + + + + + + Model quick select + + + + + + + Speaker Volume + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html> + + + 1 + + + 20 + + + 1 @@ -1155,55 +1181,19 @@ p, li { white-space: pre-wrap; } - - + + - Backlight color + Favorites matching - - - - Beep volume - - - - - - - Hz - - - 1300 - - - 2900 - - - 10 - - - 1700 - - - - - - - RotEnc Navigation - - - - - - - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -2326,7 +2316,7 @@ p, li { white-space: pre-wrap; } - Qt::Vertical + Qt::Orientation::Vertical @@ -2367,7 +2357,7 @@ p, li { white-space: pre-wrap; } 1 - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2535,7 +2525,7 @@ p, li { white-space: pre-wrap; } - Qt::Vertical + Qt::Orientation::Vertical @@ -2548,7 +2538,7 @@ p, li { white-space: pre-wrap; } - Qt::Vertical + Qt::Orientation::Vertical diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 1dbeb6c4d..831336915 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -626,16 +626,7 @@ TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & hea int col = 0; foreach(QString text, headerLabels) { - QLabel *label = new QLabel(); - label->setFrameShape(QFrame::Panel); - label->setFrameShadow(QFrame::Raised); - label->setMidLineWidth(0); - label->setAlignment(Qt::AlignCenter); - label->setMargin(5); - label->setText(text); - // if (!minimize) - // label->setMinimumWidth(100); - gridWidget->addWidget(label, 0, col++); + addColumnHead(text, col++); } #endif } @@ -718,6 +709,38 @@ void TableLayout::setColumnStretch(int col, int stretch) #endif } +void TableLayout::addColumnHead(QString text, int col, int colSpan) +{ + QLabel *label = new QLabel(); + label->setFrameShape(QFrame::Panel); + label->setFrameShadow(QFrame::Raised); + label->setMidLineWidth(0); + label->setAlignment(Qt::AlignCenter); + label->setMargin(2); + label->setText(text); + // if (!minimize) + // label->setMinimumWidth(100); + gridWidget->addWidget(label, 0, col, 1, colSpan); +} + +void TableLayout::updateColumnHeading(int col, QString &text) +{ +#if defined(TABLE_LAYOUT) +#else + QLayoutItem *item = gridWidget->itemAtPosition(0, col); + + if (item) { + QWidget *widget = item->widget(); + if (widget) { + QLabel *lbl = qobject_cast(widget); + if (lbl) { + lbl->setText(text); + } + } + } +#endif +} + QString Helpers::removeAccents(const QString & str) { // UTF-8 ASCII Table diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 5b8009531..f0020f062 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -118,7 +118,6 @@ namespace Helpers QString concatPath(const QString & str1, const QString & str2, bool onlyonesep = true); QString concatPath(const QString & str1, QString & str2, bool onlyonesep = true); QString concatPath(QString & str1, const QString & str2, bool onlyonesep = true); - } // namespace Helpers // TODO : move globals to Helpers namespace @@ -205,6 +204,8 @@ public: void pushRowsUp(int row); void pushColumnsLeft(int col); void setColumnStretch(int col, int stretch); + void addColumnHead(QString text, int col, int colSpan = 1); + void updateColumnHeading(int col, QString &text); private: #if defined(TABLE_LAYOUT) diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt index c8e13e388..a1a2cafa3 100644 --- a/companion/src/modeledit/CMakeLists.txt +++ b/companion/src/modeledit/CMakeLists.txt @@ -9,6 +9,7 @@ set(${PROJECT_NAME}_NAMES customfunctions expodialog flightmodes + gvars inputs heli logicalswitches diff --git a/companion/src/modeledit/colorcustomscreens.cpp b/companion/src/modeledit/colorcustomscreens.cpp index e4de09c4e..d772b1bd5 100644 --- a/companion/src/modeledit/colorcustomscreens.cpp +++ b/companion/src/modeledit/colorcustomscreens.cpp @@ -333,7 +333,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in str = tr("Top bar"); break; case LAYOUT_OPTION_FM: - str = tr("%1 mode").arg(Boards::getRadioTypeString(firmware->getBoard())); + str = tr("%1 mode").arg(Boards::getRadioModeString(firmware->getBoard())); break; case LAYOUT_OPTION_SLIDERS: str = tr("Sliders"); diff --git a/companion/src/modeledit/flightmode.ui b/companion/src/modeledit/flightmode.ui index 4e69ebd41..ed1b32923 100644 --- a/companion/src/modeledit/flightmode.ui +++ b/companion/src/modeledit/flightmode.ui @@ -7,7 +7,7 @@ 0 0 610 - 499 + 593 @@ -61,7 +61,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -88,7 +88,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -101,10 +101,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -114,7 +114,7 @@ - Qt::Vertical + Qt::Orientation::Vertical false @@ -123,7 +123,7 @@ false - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -133,10 +133,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -146,7 +146,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -162,7 +162,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -178,7 +178,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -195,7 +195,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -211,7 +211,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -227,7 +227,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -245,7 +245,7 @@ trim2 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -255,7 +255,7 @@ trim1 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -273,10 +273,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -292,10 +292,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -305,10 +305,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -319,7 +319,7 @@ trim4 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -328,7 +328,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -344,7 +344,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -360,7 +360,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -377,7 +377,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -393,7 +393,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -409,7 +409,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -427,7 +427,7 @@ trim3 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -444,7 +444,7 @@ trim6 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -456,7 +456,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -474,10 +474,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Minimum + QSizePolicy::Policy::Minimum @@ -492,10 +492,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -510,7 +510,7 @@ trim8 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -522,7 +522,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -540,10 +540,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Minimum + QSizePolicy::Policy::Minimum @@ -558,10 +558,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -571,10 +571,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -589,7 +589,7 @@ trim5 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -601,7 +601,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -619,10 +619,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Minimum + QSizePolicy::Policy::Minimum @@ -637,10 +637,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSlider::TicksBothSides + QSlider::TickPosition::TicksBothSides 25 @@ -655,7 +655,7 @@ trim7 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -667,7 +667,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -685,10 +685,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::Minimum + QSizePolicy::Policy::Minimum @@ -702,23 +702,6 @@ - - - - Qt::Horizontal - - - - - - - - - - - - - diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 23f92f92e..c024bd412 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -26,13 +26,16 @@ #include "customdebug.h" #include "namevalidator.h" -FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, - FilteredItemModel * rawSwitchFilteredModel, QString radioType): +FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, + GeneralSettings & generalSettings, + Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel, + QString radioMode): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::FlightMode), phaseIdx(phaseIdx), phase(model.flightModeData[phaseIdx]), - radioType(radioType) + radioMode(radioMode) { ui->setupUi(this); connectItemModelEvents(rawSwitchFilteredModel); @@ -43,19 +46,12 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI board = firmware->getBoard(); fmCount = firmware->getCapability(FlightModes); - gvCount = firmware->getCapability(Gvars); - reCount = firmware->getCapability(RotaryEncoders); trimCount = Boards::getCapability(board, Board::NumTrims); + gvCount = firmware->getCapability(Gvars); - // Flight mode name - if (fmCount) { - ui->name->setValidator(new NameValidator(board, this)); - ui->name->setMaxLength(firmware->getCapability(FlightModesName)); - connect(ui->name, SIGNAL(editingFinished()), this, SLOT(phaseName_editingFinished())); - } - else { - ui->name->setDisabled(true); - } + ui->name->setValidator(new NameValidator(board, this)); + ui->name->setMaxLength(firmware->getCapability(FlightModesName)); + connect(ui->name, SIGNAL(editingFinished()), this, SLOT(phaseName_editingFinished())); // Flight mode switch if (phaseIdx > 0) { @@ -111,21 +107,21 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI trimsLabel[i]->setText(labels[Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1]); QComboBox * cb = trimsUse[i]; cb->setProperty("index", i); - if (IS_HORUS_OR_TARANIS(board)) { - cb->addItem(tr("Trim disabled"), -1); - cb->addItem(tr("3POS toggle switch"), TRIM_MODE_3POS); - } + cb->addItem(tr("Trim disabled"), -1); + cb->addItem(tr("3POS toggle switch"), TRIM_MODE_3POS); + for (int m = 0; m < fmCount; m++) { if (m == phaseIdx) { cb->addItem(tr("Own Trim"), m * 2); } else if (phaseIdx > 0) { - cb->addItem(tr("Use Trim from %1 Mode %2").arg(radioType).arg(m), m * 2); + cb->addItem(tr("Use Trim from %1 Mode %2").arg(radioMode).arg(m), m * 2); if (IS_HORUS_OR_TARANIS(board)) { - cb->addItem(tr("Use Trim from %1 Mode %2 + Own Trim as an offset").arg(radioType).arg(m), m * 2 + 1); + cb->addItem(tr("Use Trim from %1 Mode %2 + Own Trim as an offset").arg(radioMode).arg(m), m * 2 + 1); } } } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseTrimUse_currentIndexChanged(int))); int trimsMax = firmware->getCapability(ExtendedTrimsRange); @@ -140,161 +136,14 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI trimsSlider[i]->setProperty("index", i); trimsSlider[i]->setRange(-trimsMax, +trimsMax); int chn = Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1; + if (model.throttleReversed && ((Boards::isAir(board) && chn == 2/*TODO constant*/) || (Boards::isSurface(board) && chn == 1/*TODO constant*/))) trimsSlider[i]->setInvertedAppearance(true); + connect(trimsSlider[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrimSlider_valueChanged())); } - // Rotary encoders - if (reCount > 0) { - QGridLayout *reLayout = new QGridLayout(ui->reGB); - for (int i = 0; i < reCount; i++) { - // RE label - QLabel *label = new QLabel(ui->reGB); - label->setText(tr("Rotary Encoder %1").arg(i + 1)); - reLayout->addWidget(label, i, 0, 1, 1); - if (phaseIdx > 0) { - // RE link to another RE - reUse[i] = new QComboBox(ui->reGB); - reUse[i]->setProperty("index", i); - populateGvarUseCB(reUse[i], phaseIdx); - connect(reUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseREUse_currentIndexChanged(int))); - reLayout->addWidget(reUse[i], i, 1, 1, 1); - } - // RE value - reValues[i] = new QSpinBox(ui->reGB); - reValues[i]->setProperty("index", i); - reValues[i]->setMinimum(RENC_MIN_VALUE); - reValues[i]->setMaximum(RENC_MAX_VALUE); - connect(reValues[i], SIGNAL(editingFinished()), this, SLOT(phaseREValue_editingFinished())); - reLayout->addWidget(reValues[i], i, 2, 1, 1); - } - } - else { - ui->reGB->hide(); - } - - // GVars - if (gvCount > 0 && (firmware->getCapability(GvarsFlightModes) || phaseIdx == 0) ) { - QGridLayout *gvLayout = new QGridLayout(ui->gvGB); - - // Column headers - int headerCol = 1; - - if (firmware->getCapability(GvarsName)) { - QLabel *nameLabel = new QLabel(ui->gvGB); - nameLabel->setText(tr("Name")); - gvLayout->addWidget(nameLabel, 0, headerCol++, 1, 1); - } - - if (phaseIdx > 0) { - QLabel *sourceLabel = new QLabel(ui->gvGB); - sourceLabel->setText(tr("Value source")); - gvLayout->addWidget(sourceLabel, 0, headerCol++, 1, 1); - } - - QLabel *valueLabel = new QLabel(ui->gvGB); - valueLabel->setText(tr("Value")); - gvLayout->addWidget(valueLabel, 0, headerCol++, 1, 1); - - if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) { - QLabel *unitLabel = new QLabel(ui->gvGB); - unitLabel->setText(tr("Unit")); - gvLayout->addWidget(unitLabel, 0, headerCol++, 1, 1); - - QLabel *precLabel = new QLabel(ui->gvGB); - precLabel->setText(tr("Prec")); - gvLayout->addWidget(precLabel, 0, headerCol++, 1, 1); - - QLabel *minLabel = new QLabel(ui->gvGB); - minLabel->setText(tr("Min")); - gvLayout->addWidget(minLabel, 0, headerCol++, 1, 1); - - QLabel *maxLabel = new QLabel(ui->gvGB); - maxLabel->setText(tr("Max")); - gvLayout->addWidget(maxLabel, 0, headerCol++, 1, 1); - - QLabel *popupLabel = new QLabel(ui->gvGB); - popupLabel->setText(tr("Popup enabled")); - gvLayout->addWidget(popupLabel, 0, headerCol++, 1, 1); - } - - for (int i = 0; i < gvCount; i++) { - int col = 0; - // GVar label - QLabel *label = new QLabel(ui->gvGB); - label->setText(tr("GV%1").arg(i + 1)); - label->setProperty("index", i); - label->setContextMenuPolicy(Qt::CustomContextMenu); - label->setToolTip(tr("Popup menu available")); - connect(label, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(gvOnCustomContextMenuRequested(const QPoint &))); - gvLayout->addWidget(label, i + 1, col++, 1, 1); - // GVar name - int nameLen = firmware->getCapability(GvarsName); - if (nameLen > 0) { - gvNames[i] = new QLineEdit(ui->gvGB); - gvNames[i]->setProperty("index", i); - gvNames[i]->setValidator(new NameValidator(board, this)); - gvNames[i]->setMaxLength(nameLen); - connect(gvNames[i], SIGNAL(editingFinished()), this, SLOT(GVName_editingFinished())); - gvLayout->addWidget(gvNames[i], i + 1, col++, 1, 1); - } - if (phaseIdx > 0) { - // GVar link to another GVar - gvUse[i] = new QComboBox(ui->gvGB); - gvUse[i]->setProperty("index", i); - populateGvarUseCB(gvUse[i], phaseIdx); - connect(gvUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUse_currentIndexChanged(int))); - gvLayout->addWidget(gvUse[i], i + 1, col++, 1, 1); - } - // GVar value - gvValues[i] = new QDoubleSpinBox(ui->gvGB); - gvValues[i]->setProperty("index", i); - connect(gvValues[i], SIGNAL(editingFinished()), this, SLOT(phaseGVValue_editingFinished())); - gvLayout->addWidget(gvValues[i], i + 1, col++, 1, 1); - - if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) { - // GVar unit - gvUnit[i] = new QComboBox(ui->gvGB); - gvUnit[i]->setProperty("index", i); - populateGvarUnitCB(gvUnit[i]); - connect(gvUnit[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUnit_currentIndexChanged(int))); - gvLayout->addWidget(gvUnit[i], i + 1, col++, 1, 1); - - // GVar precision - gvPrec[i] = new QComboBox(ui->gvGB); - gvPrec[i]->setProperty("index", i); - populateGvarPrecCB(gvPrec[i]); - connect(gvPrec[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVPrec_currentIndexChanged(int))); - gvLayout->addWidget(gvPrec[i], i + 1, col++, 1, 1); - - // GVar min - gvMin[i] = new QDoubleSpinBox(ui->gvGB); - gvMin[i]->setProperty("index", i); - connect(gvMin[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMin_editingFinished())); - gvLayout->addWidget(gvMin[i], i + 1, col++, 1, 1); - - // GVar max - gvMax[i] = new QDoubleSpinBox(ui->gvGB); - gvMax[i]->setProperty("index", i); - connect(gvMax[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMax_editingFinished())); - gvLayout->addWidget(gvMax[i], i + 1, col++, 1, 1); - - // Popups - gvPopups[i] = new QCheckBox(ui->gvGB); - gvPopups[i]->setProperty("index", i); - //gvPopups[i]->setText(tr("Popup enabled")); - connect(gvPopups[i], SIGNAL(toggled(bool)), this, SLOT(phaseGVPopupToggled(bool))); - gvLayout->addWidget(gvPopups[i], i + 1, col++, 1, 1); - } - } - } - else { - ui->gvGB->hide(); - gvCount = 0; - } - disableMouseScrolling(); update(); @@ -317,90 +166,6 @@ void FlightModePanel::update() for (int i = 0; i < getBoardCapability(firmware->getBoard(), Board::NumTrims); i++) { trimUpdate(i); } - - for (int i = 0; i < gvCount; i++) { - updateGVar(i); - } - - for (int i = 0; i < reCount; i++) { - updateRotaryEncoder(i); - } -} - -void FlightModePanel::updateGVar(int index) -{ - lock = true; - if (firmware->getCapability(GvarsName) > 0) { - gvNames[index]->setText(model->gvarData[index].name); - } - if (phaseIdx > 0) { - if (model->isGVarLinked(phaseIdx, index)) - gvUse[index]->setCurrentIndex(phase.gvars[index] - GVAR_MAX_VALUE); - else - gvUse[index]->setCurrentIndex(0); - } - gvValues[index]->setDisabled(model->isGVarLinked(phaseIdx, index)); - setGVSB(gvValues[index], model->gvarData[index].getMin(), model->gvarData[index].getMax(), model->getGVarValue(phaseIdx, index)); - if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) { - gvUnit[index]->setCurrentIndex(model->gvarData[index].unit); - gvPrec[index]->setCurrentIndex(model->gvarData[index].prec); - setGVSB(gvMin[index], GVAR_MIN_VALUE, model->gvarData[index].getMax(), model->gvarData[index].getMin()); - setGVSB(gvMax[index], model->gvarData[index].getMin(), GVAR_MAX_VALUE, model->gvarData[index].getMax()); - gvPopups[index]->setChecked(model->gvarData[index].popup); - } - lock = false; -} - -void FlightModePanel::populateGvarUseCB(QComboBox * b, unsigned int phase) -{ - b->addItem(tr("Own value")); - for (int i = 0; i < getCurrentFirmware()->getCapability(FlightModes); i++) { - if (i != (int)phase) { - b->addItem(tr("%1 Mode %2 value").arg(radioType).arg(i)); - } - } -} - -void FlightModePanel::setGVSB(QDoubleSpinBox * sb, int min, int max, int val) -{ - int idx = sb->property("index").toInt(); - float mul = model->gvarData[idx].multiplierGet(); - sb->setDecimals(model->gvarData[idx].prec); - sb->setSingleStep(mul); - sb->setSuffix(model->gvarData[idx].unitToString()); - sb->setMinimum(min * mul); - sb->setMaximum(max * mul); - sb->setValue(val * mul); -} - -void FlightModePanel::updateRotaryEncoder(int index) -{ - lock = true; - if (phaseIdx > 0) { - if (model->isREncLinked(phaseIdx, index)) - reUse[index]->setCurrentIndex(phase.rotaryEncoders[index] - RENC_MAX_VALUE); - else - reUse[index]->setCurrentIndex(0); - } - reValues[index]->setDisabled(model->isREncLinked(phaseIdx, index)); - reValues[index]->setValue(model->getREncValue(phaseIdx, index)); - lock = false; -} - -// TODO: pull units from GVarData -void FlightModePanel::populateGvarUnitCB(QComboBox * cb) -{ - cb->clear(); - cb->addItem(""); - cb->addItem("%"); -} - -// TODO: pull precision string from GVarData -void FlightModePanel::populateGvarPrecCB(QComboBox * cb) -{ - cb->clear(); - cb->addItem(tr("0._")); - cb->addItem(tr("0.0")); } void FlightModePanel::phaseName_editingFinished() @@ -416,6 +181,7 @@ void FlightModePanel::phaseSwitch_currentIndexChanged(int index) if (!lock) { bool ok; const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok)); + if (ok && phase.swtch.toValue() != rs.toValue()) { phase.swtch = rs; emit phaseSwitchChanged(); @@ -447,6 +213,7 @@ void FlightModePanel::trimUpdate(unsigned int trim) int value = model->getTrimValue(phaseIdx, chn); trimsSlider[trim]->setValue(value); trimsValue[trim]->setValue(value); + if (phase.trimMode[chn] < 0) { trimsUse[trim]->setCurrentIndex(0); trimsValue[trim]->setEnabled(false); @@ -457,10 +224,8 @@ void FlightModePanel::trimUpdate(unsigned int trim) trimsSlider[trim]->setEnabled(false); } else { - if (IS_HORUS_OR_TARANIS(board)) - trimsUse[trim]->setCurrentIndex(2 + 2 * phase.trimRef[chn] + phase.trimMode[chn] - (phase.trimRef[chn] > phaseIdx ? 1 : 0)); - else - trimsUse[trim]->setCurrentIndex(phase.trimRef[chn]); + trimsUse[trim]->setCurrentIndex(2 + 2 * phase.trimRef[chn] + phase.trimMode[chn] - (phase.trimRef[chn] > phaseIdx ? 1 : 0)); + if (phaseIdx == 0 || phase.trimRef[chn] == phaseIdx || (IS_HORUS_OR_TARANIS(board) && phase.trimMode[chn] != 0)) { trimsValue[trim]->setEnabled(true); trimsSlider[trim]->setEnabled(true); @@ -473,157 +238,6 @@ void FlightModePanel::trimUpdate(unsigned int trim) lock = false; } -void FlightModePanel::phaseGVValue_editingFinished() -{ - if (!lock) { - QDoubleSpinBox *spinBox = qobject_cast(sender()); - int gvar = spinBox->property("index").toInt(); - phase.gvars[gvar] = spinBox->value() * model->gvarData[gvar].multiplierSet(); - updateGVar(gvar); - emit modified(); - } -} - -void FlightModePanel::GVName_editingFinished() -{ - if (!lock) { - QLineEdit *lineedit = qobject_cast(sender()); - int gvar = lineedit->property("index").toInt(); - memset(&model->gvarData[gvar].name, 0, sizeof(model->gvarData[gvar].name)); - strcpy(model->gvarData[gvar].name, lineedit->text().toLatin1()); - emit gvNameChanged(); - emit modified(); - } -} - -void FlightModePanel::phaseGVUse_currentIndexChanged(int index) -{ - if (!lock) { - lock = true; - QComboBox *comboBox = qobject_cast(sender()); - int gvar = comboBox->property("index").toInt(); - if (index == 0) { - phase.gvars[gvar] = 0; - } - else { - phase.gvars[gvar] = GVAR_MAX_VALUE + index; - } - if (model->isGVarLinkedCircular(phaseIdx, gvar)) - QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. %1 Mode 0 value used.").arg(radioType)); - updateGVar(gvar); - emit modified(); - lock = false; - } -} - -void FlightModePanel::phaseGVUnit_currentIndexChanged(int index) -{ - if (!lock) { - QComboBox *comboBox = qobject_cast(sender()); - int gvar = comboBox->property("index").toInt(); - model->gvarData[gvar].unit = index; - updateGVar(gvar); - emit modified(); - } -} - -void FlightModePanel::phaseGVPrec_currentIndexChanged(int index) -{ - if (!lock) { - QComboBox *comboBox = qobject_cast(sender()); - int gvar = comboBox->property("index").toInt(); - model->gvarData[gvar].prec = index; - updateGVar(gvar); - emit modified(); - } -} - -void FlightModePanel::phaseGVMin_editingFinished() -{ - if (!lock) { - QDoubleSpinBox *spinBox = qobject_cast(sender()); - int gvar = spinBox->property("index").toInt(); - model->gvarData[gvar].setMin(spinBox->value()); - if (!model->isGVarLinked(phaseIdx, gvar)) { - if (model->getGVarValuePrec(phaseIdx, gvar) < spinBox->value()) { - phase.gvars[gvar] = model->gvarData[gvar].getMin(); - } - } - for (int x = 1; x < fmCount; x++) { - if (!model->isGVarLinked(x, gvar)) { - if (model->flightModeData[x].gvars[gvar] < model->gvarData[gvar].getMin()) { - model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMin(); - } - } - } - updateGVar(gvar); - emit modified(); - } -} - -void FlightModePanel::phaseGVMax_editingFinished() -{ - if (!lock) { - QDoubleSpinBox *spinBox = qobject_cast(sender()); - int gvar = spinBox->property("index").toInt(); - model->gvarData[gvar].setMax(spinBox->value()); - if (!model->isGVarLinked(phaseIdx, gvar)) { - if (model->getGVarValuePrec(phaseIdx, gvar) > spinBox->value()) { - phase.gvars[gvar] = model->gvarData[gvar].getMax(); - } - } - for (int x = 1; x < fmCount; x++) { - if (!model->isGVarLinked(x, gvar)) { - if (model->flightModeData[x].gvars[gvar] > model->gvarData[gvar].getMax()) { - model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMax(); - } - } - } - updateGVar(gvar); - emit modified(); - } -} - -void FlightModePanel::phaseGVPopupToggled(bool checked) -{ - if (!lock) { - QCheckBox *cb = qobject_cast(sender()); - int gvar = cb->property("index").toInt(); - model->gvarData[gvar].popup = checked; - emit modified(); - } -} - -void FlightModePanel::phaseREValue_editingFinished() -{ - if (!lock) { - QSpinBox *spinBox = qobject_cast(sender()); - int re = spinBox->property("index").toInt(); - phase.rotaryEncoders[re] = spinBox->value(); - emit modified(); - } -} - -void FlightModePanel::phaseREUse_currentIndexChanged(int index) -{ - if (!lock) { - lock = true; - QComboBox *comboBox = qobject_cast(sender()); - int re = comboBox->property("index").toInt(); - if (index == 0) { - phase.rotaryEncoders[re] = 0; - } - else { - phase.rotaryEncoders[re] = RENC_MAX_VALUE + index; ; - } - update(); - if (model->isREncLinkedCircular(phaseIdx, re)) - QMessageBox::warning(this, "Companion", tr("Warning: Rotary encoder links back to itself. %1 Mode 0 value used.").arg(radioType)); - emit modified(); - lock = false; - } -} - void FlightModePanel::phaseTrimUse_currentIndexChanged(int index) { if (!lock) { @@ -631,6 +245,7 @@ void FlightModePanel::phaseTrimUse_currentIndexChanged(int index) int trim = comboBox->property("index").toInt(); int chn = Boards::isAir(board) ? CONVERT_AIRMODE(trim + 1) - 1 : CONVERT_SURFACEMODE(trim + 1) - 1; int data = comboBox->itemData(index).toInt(); + if (data < 0) { phase.trimMode[chn] = -1; phase.trimRef[chn] = 0; @@ -639,18 +254,12 @@ void FlightModePanel::phaseTrimUse_currentIndexChanged(int index) phase.trimMode[chn] = TRIM_MODE_3POS; phase.trimRef[chn] = 0; phase.trim[chn] = 0; - } - else { - if (IS_HORUS_OR_TARANIS(board)) { - phase.trimMode[chn] = data % 2; - phase.trimRef[chn] = data / 2; - } - else { - phase.trimMode[chn] = 0; - phase.trimRef[chn] = data / 2; - } + } else { + phase.trimMode[chn] = data % 2; + phase.trimRef[chn] = data / 2; phase.trim[chn] = 0; } + trimUpdate(trim); emit modified(); } @@ -711,11 +320,13 @@ bool FlightModePanel::hasClipboardData(QByteArray * data) const { const QClipboard * clipboard = QApplication::clipboard(); const QMimeData * mimeData = clipboard->mimeData(); + if (mimeData->hasFormat(MIMETYPE_FLIGHTMODE)) { if (data) data->append(mimeData->data(MIMETYPE_FLIGHTMODE)); return true; } + return false; } @@ -737,7 +348,7 @@ bool FlightModePanel::moveUpAllowed() const void FlightModePanel::cmClear(bool prompt) { if (prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear %1 Mode. Are you sure?").arg(radioMode), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; } @@ -746,23 +357,22 @@ void FlightModePanel::cmClear(bool prompt) if (phaseIdx == 0) { for (int i = 0; i < gvCount; i++) { model->gvarData[i].clear(); + for (int j = 0; j < fmCount; j++) { FlightModeData *fm = &model->flightModeData[j]; fm->gvars[i] = fm->linkedGVarFlightModeZero(j); } + model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i); } - } - else { + } else { QComboBox * pswtch = ui->swtch; RawSwitch item = RawSwitch(SWITCH_TYPE_NONE); pswtch->setCurrentIndex(pswtch->findText(item.toString())); + for (int i = 0; i < gvCount; i++) { phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx); } - for (int i = 0; i < reCount; i++) { - phase.rotaryEncoders[i] = phase.linkedREncFlightModeZero(phaseIdx); - } } model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, phaseIdx); @@ -774,18 +384,17 @@ void FlightModePanel::cmClear(bool prompt) void FlightModePanel::cmClearAll() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all %1 Modes. Are you sure?").arg(radioMode), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; for (int j = 0; j < fmCount; j++) { FlightModeData *fm = &model->flightModeData[j]; fm->clear(j); + for (int i = 0; i < gvCount; i++) { fm->gvars[i] = fm->linkedGVarFlightModeZero(j); } - for (int i = 0; i < reCount; i++) { - fm->rotaryEncoders[i] = fm->linkedREncFlightModeZero(j); - } + model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, j); } @@ -809,15 +418,18 @@ void FlightModePanel::cmCopy() void FlightModePanel::cmCut() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut %1 Mode. Are you sure?").arg(radioMode), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; + cmCopy(); cmClear(false); } void FlightModePanel::cmDelete() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete %1 Mode. Are you sure?").arg(radioMode), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; const int maxidx = fmCount - 1; @@ -858,17 +470,6 @@ void FlightModePanel::cmDelete() } } - for (int i = 0; i < reCount; i++) { - if (model->isREncLinked(j, i)) { - int idx = model->getREncFlightModeIndex(j, i); - if (phaseIdx == 0 && j == 0) - model->setREncFlightModeIndexToValue(j, i, j); - else if (idx > phaseIdx) - model->setREncFlightModeIndexToValue(j, i, idx - 1); - else if (idx == phaseIdx) - model->setREncFlightModeIndexToValue(j, i, 0); - } - } } model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, -1); @@ -881,19 +482,20 @@ void FlightModePanel::cmInsert() { const int maxidx = fmCount - 1; - memmove(&model->flightModeData[phaseIdx + 1], &model->flightModeData[phaseIdx], (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData)); + memmove(&model->flightModeData[phaseIdx + 1], &model->flightModeData[phaseIdx], + (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData)); model->flightModeData[phaseIdx].clear(phaseIdx); for (int j = maxidx; j > 0; j--) { FlightModeData *fm = &model->flightModeData[j]; for (int i = 0; i < trimCount; i++) { - if (phaseIdx == 0 && j == 1) + if (phaseIdx == 0 && j == 1) { fm->trimRef[i] = j; - else if (fm->trimRef[i] >= phaseIdx) { - if (fm->trimRef[i] < maxidx) + } else if (fm->trimRef[i] >= phaseIdx) { + if (fm->trimRef[i] < maxidx) { fm->trimRef[i]++; - else { + } else { fm->trimMode[i] = 0; fm->trimRef[i] = 0; fm->trim[i] = 0; @@ -910,16 +512,6 @@ void FlightModePanel::cmInsert() model->setGVarFlightModeIndexToValue(j, i, idx + 1); } } - - for (int i = 0; i < reCount; i++) { - if (model->isREncLinked(j, i)) { - int idx = model->getREncFlightModeIndex(j, i); - if (phaseIdx == 0 && j == 1) - model->setREncFlightModeIndexToValue(j, i, j); - else if (idx >= phaseIdx) - model->setREncFlightModeIndexToValue(j, i, idx + 1); - } - } } model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, 1); @@ -941,6 +533,7 @@ void FlightModePanel::cmMoveUp() void FlightModePanel::cmPaste() { QByteArray data; + if (hasClipboardData(&data)) { FlightModeData *fm = &model->flightModeData[phaseIdx]; memcpy(fm, data.constData(), sizeof(FlightModeData)); @@ -959,20 +552,12 @@ void FlightModePanel::cmPaste() for (int i = 0; i < gvCount; i++) { if (model->isGVarLinked(phaseIdx, i)) { int linkedidx = model->getGVarFlightModeIndex(phaseIdx, i); + if (phaseIdx == 0 || linkedidx == phaseIdx) model->setGVarFlightModeIndexToValue(phaseIdx, i, phaseIdx); } } - // TODO fix up linked REs but need to know source FM index to make adjustments - for (int i = 0; i < reCount; i++) { - if (model->isREncLinked(phaseIdx, i)) { - int linkedidx = model->getREncFlightModeIndex(phaseIdx, i); - if (phaseIdx == 0 || linkedidx == phaseIdx) - model->setREncFlightModeIndexToValue(phaseIdx, i, phaseIdx); - } - } - emit phaseDataChanged(); emit modified(); } @@ -1010,8 +595,7 @@ void FlightModePanel::swapData(int idx1, int idx2) if (idx1 == 0) { fmd1->trimMode[i] = 0; fmd1->trimRef[i] = 0; - } - else if (idx2 == 0) { + } else if (idx2 == 0) { fmd2->trimMode[i] = 0; fmd2->trimRef[i] = 0; } @@ -1020,6 +604,7 @@ void FlightModePanel::swapData(int idx1, int idx2) for (int i = 0; i < gvCount; i++) { if (model->isGVarLinked(idx1, i)) { int linkedidx = model->getGVarFlightModeIndex(idx1, i); + if (linkedidx == idx1) model->setGVarFlightModeIndexToValue(idx1, i, idx2 - shift); else if (linkedidx == idx2) @@ -1030,6 +615,7 @@ void FlightModePanel::swapData(int idx1, int idx2) if (model->isGVarLinked(idx2, i)) { int linkedidx = model->getGVarFlightModeIndex(idx2, i); + if (linkedidx == idx1) model->setGVarFlightModeIndexToValue(idx2, i, idx2 - shift); else if (linkedidx == idx2) @@ -1039,354 +625,11 @@ void FlightModePanel::swapData(int idx1, int idx2) } } - for (int i = 0; i < reCount; i++) { - if (model->isREncLinked(idx1, i)) { - int linkedidx = model->getREncFlightModeIndex(idx1, i); - if (linkedidx == idx1) - model->setREncFlightModeIndexToValue(idx1, i, idx2 - shift); - else if (linkedidx == idx2) - model->setREncFlightModeIndexToValue(idx1, i, idx1 + shift); - else - model->setREncFlightModeIndexToValue(idx1, i, linkedidx); - } - - if (model->isREncLinked(idx2, i)) { - int linkedidx = model->getREncFlightModeIndex(idx2, i); - if (linkedidx == idx1) - model->setREncFlightModeIndexToValue(idx2, i, idx2 - shift); - else if (linkedidx == idx2) - model->setREncFlightModeIndexToValue(idx2, i, idx1 + shift); - else - model->setREncFlightModeIndexToValue(idx2, i, linkedidx); - } - } - model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); emit phaseDataChanged(); emit modified(); } -void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos) -{ - QLabel *label = (QLabel *)sender(); - gvIdx = label->property("index").toInt(); - QPoint globalPos = label->mapToGlobal(pos); - - QMenu contextMenu; - contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(gvCmCopy())); - contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(gvCmCut())); - contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(gvCmPaste()))->setEnabled(gvHasClipboardData()); - contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(gvCmClear())); - contextMenu.addSeparator(); - contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(gvCmInsert()))->setEnabled(gvInsertAllowed()); - contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(gvCmDelete()))->setEnabled(gvDeleteAllowed()); - contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(gvCmMoveUp()))->setEnabled(gvMoveUpAllowed()); - contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(gvCmMoveDown()))->setEnabled(gvMoveDownAllowed()); - contextMenu.addSeparator(); - contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(gvCmClearAll())); - - contextMenu.exec(globalPos); -} - -bool FlightModePanel::gvHasClipboardData() const -{ - if ((phaseIdx == 0 && gvHasDefnClipboardData() && gvHasAllValuesClipboardData()) || (phaseIdx > 0 && gvHasValueClipboardData())) - return true; - return false; -} - -bool FlightModePanel::gvHasDefnClipboardData(QByteArray * data) const -{ - const QClipboard * clipboard = QApplication::clipboard(); - const QMimeData * mimeData = clipboard->mimeData(); - if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_PARAMS)) { - if (data) { - data->clear(); - data->append(mimeData->data(MIMETYPE_GVAR_PARAMS)); - } - return true; - } - return false; -} - -bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const -{ - const QClipboard * clipboard = QApplication::clipboard(); - const QMimeData * mimeData = clipboard->mimeData(); - if (mimeData->hasFormat(MIMETYPE_GVAR_VALUE)) { - if (data) { - data->clear(); - data->append(mimeData->data(MIMETYPE_GVAR_VALUE)); - } - return true; - } - return false; -} - -bool FlightModePanel::gvHasAllValuesClipboardData(QByteArray * data) const -{ - const QClipboard * clipboard = QApplication::clipboard(); - const QMimeData * mimeData = clipboard->mimeData(); - if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_ALL_VALUES)) { - if (data) { - data->clear(); - data->append(mimeData->data(MIMETYPE_GVAR_ALL_VALUES)); - } - return true; - } - return false; -} - -bool FlightModePanel::gvDeleteAllowed() const -{ - return phaseIdx == 0; -} - -bool FlightModePanel::gvInsertAllowed() const -{ - bool ret = true; - if (phaseIdx == 0) { - if (!model->gvarData[gvCount - 1].isEmpty()) - ret = false; - for (int i = 0; i < fmCount; i++) { - if (model->flightModeData[i].gvars[gvCount - 1] != phase.linkedGVarFlightModeZero(i)) - ret = false; - } - } - else - ret = false; - - return ret; -} - -bool FlightModePanel::gvMoveDownAllowed() const -{ - return (phaseIdx == 0 && gvIdx < gvCount - 1); -} - -bool FlightModePanel::gvMoveUpAllowed() const -{ - return (phaseIdx == 0 && gvIdx > 0); -} - -void FlightModePanel::gvCmClear(bool prompt) -{ - if (phaseIdx == 0) { - if (prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - } - model->gvarData[gvIdx].clear(); - for (int i = 0; i < fmCount; i++) { - model->flightModeData[i].gvars[gvIdx] = model->flightModeData[i].linkedGVarFlightModeZero(i); - } - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx); - } - else { - if (prompt) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - } - phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx); - } - updateGVar(gvIdx); - emit gvNameChanged(); - emit modified(); -} - -void FlightModePanel::gvCmClearAll() -{ - if (phaseIdx == 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - for (int i = 0; i < gvCount; i++) { - model->gvarData[i].clear(); - for (int j = 0; j < fmCount; j++) { - model->flightModeData[j].gvars[i] = model->flightModeData[j].linkedGVarFlightModeZero(j); - } - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i); - } - } - else { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for this %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - for (int i = 0; i < gvCount; i++) { - phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx); - } - } - for (int i = 0; i < gvCount; i++) { - updateGVar(i); - } - emit gvNameChanged(); - emit modified(); -} - -void FlightModePanel::gvCmCopy() -{ - QMimeData *mimeData = new QMimeData; - QByteArray data; - if (phaseIdx == 0) { - data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData)); - mimeData->setData(MIMETYPE_GVAR_PARAMS, data); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - - data.clear(); - for (int j = 0; j < fmCount; j++) { - data.append((char*)&model->flightModeData[j].gvars[gvIdx], sizeof(phase.gvars[0])); - } - mimeData->setData(MIMETYPE_GVAR_ALL_VALUES, data); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - - mimeData->removeFormat(MIMETYPE_GVAR_VALUE); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - } - else { - mimeData->removeFormat(MIMETYPE_GVAR_PARAMS); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - - mimeData->removeFormat(MIMETYPE_GVAR_ALL_VALUES); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - - data.clear(); - int val = phase.gvars[gvIdx]; - if (model->isGVarLinked(phaseIdx, gvIdx)) - val = GVAR_MAX_VALUE + 1 + model->getGVarFlightModeIndex(phaseIdx, gvIdx); // store index in case paste is to another flight mode - data.setNum(val); - mimeData->setData(MIMETYPE_GVAR_VALUE, data); - QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); - } -} - -void FlightModePanel::gvCmCut() -{ - if (phaseIdx == 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - } - else { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - } - - gvCmCopy(); - gvCmClear(false); -} - -void FlightModePanel::gvCmDelete() -{ - if (phaseIdx > 0) - return; - - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - - int maxidx = gvCount - 1; - for (int i = gvIdx; i < maxidx; i++) { - memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData)); - for (int j = 0; j < fmCount; j++) { - model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i + 1]; - } - } - - model->gvarData[maxidx].clear(); - for (int j = 0; j < fmCount; j++) { - model->flightModeData[j].gvars[maxidx] = model->flightModeData[j].linkedGVarFlightModeZero(j); - } - - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, -1); - - for (int i = 0; i < gvCount; i++) { - updateGVar(i); - } - emit gvNameChanged(); - emit modified(); -} - -void FlightModePanel::gvCmInsert() -{ - for (int i = (gvCount - 1); i > gvIdx; i--) { - memcpy(&model->gvarData[i], &model->gvarData[i - 1], sizeof(GVarData)); - for (int j = 0; j < fmCount; j++) { - model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i - 1]; - } - } - model->gvarData[gvIdx].clear(); - for (int j = 0; j < fmCount; j++) { - model->flightModeData[j].gvars[gvIdx] = model->flightModeData[j].linkedGVarFlightModeZero(j); - } - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, 1); - for (int i = 0; i < gvCount; i++) { - updateGVar(i); - } - emit gvNameChanged(); - emit modified(); -} - -void FlightModePanel::gvCmMoveDown() -{ - if (phaseIdx == 0) - gvSwapData(gvIdx, gvIdx + 1); -} - -void FlightModePanel::gvCmMoveUp() -{ - if (phaseIdx == 0) - gvSwapData(gvIdx, gvIdx - 1); -} - -void FlightModePanel::gvCmPaste() -{ - QByteArray data; - if (phaseIdx == 0) { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Paste to selected Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - return; - if (gvHasDefnClipboardData(&data)) { - memcpy(&model->gvarData[gvIdx], data.constData(), sizeof(GVarData)); - } - if (gvHasAllValuesClipboardData(&data)) { - for (int j = 0; j < fmCount; j++) { - int *gvar = &model->flightModeData[j].gvars[gvIdx]; - memcpy(gvar, data.mid(j * sizeof(phase.gvars[0]), sizeof(phase.gvars[0])).constData(), sizeof(phase.gvars[0])); - } - } - } - else if (gvHasValueClipboardData(&data)) { - int val = data.toInt(); - if (val > GVAR_MAX_VALUE) { - if (phaseIdx > 0) - model->setGVarFlightModeIndexToValue(phaseIdx, gvIdx, val - (GVAR_MAX_VALUE + 1)); // index stored in clipboard - else - phase.gvars[gvIdx] = 0; - } - else - phase.gvars[gvIdx] = val; - } - updateGVar(gvIdx); - emit gvNameChanged(); - emit modified(); -} - -void FlightModePanel::gvSwapData(int idx1, int idx2) -{ - if (phaseIdx == 0 && idx1 != idx2) { - GVarData datatmp = model->gvarData[idx2]; - GVarData *data1 = &model->gvarData[idx1]; - GVarData *data2 = &model->gvarData[idx2]; - memcpy(data2, data1, sizeof(GVarData)); - memcpy(data1, &datatmp, sizeof(GVarData)); - for (int j = 0; j < fmCount; j++) { - int valtmp = model->flightModeData[j].gvars[idx2]; - model->flightModeData[j].gvars[idx2] = model->flightModeData[j].gvars[idx1]; - model->flightModeData[j].gvars[idx1] = valtmp; - } - model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - updateGVar(idx1); - updateGVar(idx2); - emit gvNameChanged(); - emit modified(); - } -} - void FlightModePanel::connectItemModelEvents(const FilteredItemModel * itemModel) { connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModePanel::onItemModelAboutToBeUpdated); @@ -1408,6 +651,7 @@ void FlightModePanel::onThrottleReverseChanged() { for (int i = 0; i < CPN_MAX_TRIMS; i++) { int chn = Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1; + if (model->throttleReversed && ((Boards::isAir(board) && chn == 2/*TODO constant*/) || (Boards::isSurface(board) && chn == 1/*TODO constant*/))) trimsSlider[i]->setInvertedAppearance(true); @@ -1418,28 +662,30 @@ void FlightModePanel::onThrottleReverseChanged() /**********************************************************/ -FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, - CompoundItemModelFactory * sharedItemModels): +FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, + GeneralSettings & generalSettings, + Firmware * firmware, + CompoundItemModelFactory * sharedItemModels, + QString radioMode): ModelPanel(parent, model, generalSettings, firmware), - sharedItemModels(sharedItemModels) + sharedItemModels(sharedItemModels), + radioMode(radioMode) { rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext); connectItemModelEvents(rawSwitchFilteredModel); modesCount = firmware->getCapability(FlightModes); - radioType = Boards::getRadioTypeString(firmware->getBoard()); QGridLayout * gridLayout = new QGridLayout(this); tabWidget = new QTabWidget(this); for (int i = 0; i < modesCount; i++) { - FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel, radioType); + FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel, radioMode); tab->setProperty("index", i); connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified); connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::onPhaseNameChanged); connect(tab, &FlightModePanel::phaseNameChanged, this, &FlightModesPanel::onPhaseNameChanged); connect(tab, &FlightModePanel::phaseSwitchChanged, this, &FlightModesPanel::updateItemModels); - connect(tab, &FlightModePanel::gvNameChanged, this, &FlightModesPanel::updateItemModels); connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update); connect(this, &FlightModesPanel::refreshThrottleTrim, tab, &FlightModePanel::onThrottleReverseChanged); @@ -1459,7 +705,7 @@ FlightModesPanel::~FlightModesPanel() QString FlightModesPanel::getTabName(int index) { - QString result = tr("%1 Mode %2").arg(radioType).arg(index); + QString result = tr("%1 Mode %2").arg(radioMode).arg(index); const char *name = model->flightModeData[index].name; if (firmware->getCapability(FlightModesName) && strlen(name) > 0) { result += tr(" (%1)").arg(name); @@ -1500,7 +746,6 @@ void FlightModesPanel::onItemModelUpdateComplete() void FlightModesPanel::updateItemModels() { 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 11e7d5afe..c21a790cc 100644 --- a/companion/src/modeledit/flightmodes.h +++ b/companion/src/modeledit/flightmodes.h @@ -41,14 +41,16 @@ class FlightModePanel : public ModelPanel Q_OBJECT public: - FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, - FilteredItemModel * rawSwitchFilteredModel, QString radioType); + FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, + GeneralSettings & generalSettings, + Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel, + QString radioMode); virtual ~FlightModePanel(); virtual void update(); signals: - void gvNameChanged(); void phaseDataChanged(); void phaseNameChanged(); void phaseSwitchChanged(); @@ -64,16 +66,6 @@ class FlightModePanel : public ModelPanel void phaseTrimUse_currentIndexChanged(int index); void phaseTrim_valueChanged(); void phaseTrimSlider_valueChanged(); - void GVName_editingFinished(); - void phaseGVValue_editingFinished(); - void phaseGVUse_currentIndexChanged(int index); - void phaseGVPopupToggled(bool checked); - void phaseGVUnit_currentIndexChanged(int index); - void phaseGVPrec_currentIndexChanged(int index); - void phaseGVMin_editingFinished(); - void phaseGVMax_editingFinished(); - void phaseREValue_editingFinished(); - void phaseREUse_currentIndexChanged(int index); void onCustomContextMenuRequested(QPoint pos); void cmClear(bool prompt = true); void cmClearAll(); @@ -84,16 +76,6 @@ class FlightModePanel : public ModelPanel void cmPaste(); void cmMoveDown(); void cmMoveUp(); - void gvOnCustomContextMenuRequested(QPoint pos); - void gvCmClear(bool prompt = true); - void gvCmClearAll(); - void gvCmCopy(); - void gvCmCut(); - void gvCmDelete(); - void gvCmInsert(); - void gvCmPaste(); - void gvCmMoveDown(); - void gvCmMoveUp(); void onItemModelAboutToBeUpdated(); void onItemModelUpdateComplete(); @@ -102,49 +84,22 @@ class FlightModePanel : public ModelPanel int phaseIdx; FlightModeData & phase; int fmCount; - int reCount; - int gvCount; - int gvIdx; int trimCount; + int gvCount; QVector trimsLabel; - QLineEdit * gvNames[CPN_MAX_GVARS]; - QDoubleSpinBox * gvValues[CPN_MAX_GVARS]; - QCheckBox * gvPopups[CPN_MAX_GVARS]; - QComboBox * gvUse[CPN_MAX_GVARS]; - QComboBox * gvUnit[CPN_MAX_GVARS]; - QComboBox * gvPrec[CPN_MAX_GVARS]; - QDoubleSpinBox * gvMin[CPN_MAX_GVARS]; - QDoubleSpinBox * gvMax[CPN_MAX_GVARS]; - QSpinBox * reValues[CPN_MAX_ENCODERS]; - QComboBox * reUse[CPN_MAX_ENCODERS]; QVector trimsUse; QVector trimsValue; QVector trimsSlider; Board::Type board; - QString radioType; + QString radioMode; void trimUpdate(unsigned int trim); - void updateGVar(int index); - void updateRotaryEncoder(int index); - void setGVSB(QDoubleSpinBox * spinBox, int min, int max, int val); - void populateGvarUnitCB(QComboBox * cb); - void populateGvarPrecCB(QComboBox * cb); bool hasClipboardData(QByteArray * data = nullptr) const; bool insertAllowed() const; bool moveDownAllowed() const; bool moveUpAllowed() const; void swapData(int idx1, int idx2); - bool gvHasClipboardData() const; - bool gvHasDefnClipboardData(QByteArray * data = nullptr) const; - bool gvHasValueClipboardData(QByteArray * data = nullptr) const; - bool gvHasAllValuesClipboardData(QByteArray * data = nullptr) const; - bool gvDeleteAllowed() const; - bool gvInsertAllowed() const; - bool gvMoveDownAllowed() const; - bool gvMoveUpAllowed() const; - void gvSwapData(int idx1, int idx2); void connectItemModelEvents(const FilteredItemModel * itemModel); - void populateGvarUseCB(QComboBox *b, unsigned int phase); }; class FlightModesPanel : public ModelPanel @@ -152,7 +107,11 @@ class FlightModesPanel : public ModelPanel Q_OBJECT public: - FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + FlightModesPanel(QWidget *parent, ModelData & model, + GeneralSettings & generalSettings, + Firmware * firmware, + CompoundItemModelFactory * sharedItemModels, + QString radioModes); virtual ~FlightModesPanel(); public slots: @@ -177,7 +136,7 @@ class FlightModesPanel : public ModelPanel CompoundItemModelFactory *sharedItemModels; FilteredItemModel *rawSwitchFilteredModel; QVector panels; - QString radioType; + QString radioMode; void updateItemModels(); void connectItemModelEvents(const FilteredItemModel * itemModel); diff --git a/companion/src/modeledit/gvars.cpp b/companion/src/modeledit/gvars.cpp new file mode 100644 index 000000000..4680cf715 --- /dev/null +++ b/companion/src/modeledit/gvars.cpp @@ -0,0 +1,620 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * 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 "gvars.h" +#include "gvardata.h" +#include "flightmodedata.h" +#include "filtereditemmodels.h" +#include "eeprominterface.h" +#include "helpers.h" +#include "namevalidator.h" + +GlobalVariablesPanel::GlobalVariablesPanel(QWidget * parent, ModelData & model, + GeneralSettings & generalSettings, + Firmware * firmware, + CompoundItemModelFactory * sharedItemModels) : + ModelPanel(parent, model, generalSettings, firmware), + sharedItemModels(sharedItemModels), + selectedIndex(0), + modelsUpdateCnt(0), + gvars(firmware->getCapability(Gvars)), + modes(firmware->getCapability(FlightModes)), + modeName(FlightModeData::modeName()), + modePrefix(FlightModeData::modeAbbrev()) +{ + AbstractStaticItemModel *unitItemModel = GVarData::unitItemModel(); + AbstractStaticItemModel *precItemModel = GVarData::precItemModel(); + CompoundItemModelFactory *gvarModesIMF = new CompoundItemModelFactory(&generalSettings, &model); + + int firstmidx = 0; + for (int i = 0; i < modes; i++) { + int id = gvarModesIMF->registerItemModel(FlightModeData::gvarModesItemModel(i)); + if (i == 0) + firstmidx = id; + } + + // add mode headers post table construction as they span columns + QStringList headerLabels; + headerLabels << "#" << tr("Name") << tr("Unit") << tr("Prec") << tr("Min") + << tr("Max") << tr("Popup"); + + tableLayout = new TableLayout(this, gvars, headerLabels); + + for (int i = 0; i < gvars; i++) { + int col = 0; + // label + QLabel *label = new QLabel(this); + label->setText(tr("GV%1").arg(i + 1)); + label->setProperty("index", i); + label->setContextMenuPolicy(Qt::CustomContextMenu); + label->setToolTip(tr("Popup menu available")); + label->setMouseTracking(true); + label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + connect(label, &QWidget::customContextMenuRequested, this, + &GlobalVariablesPanel::onCustomContextMenuRequested); + tableLayout->addWidget(i, col++, label); + + // name + leName[i] = new QLineEdit(this); + QLineEdit *name = leName[i]; + name->setProperty("index", i); + name->setValidator(new NameValidator(firmware->getBoard(), this)); + name->setMaxLength(firmware->getCapability(GvarsName)); + connect(name, &QLineEdit::editingFinished, this, &GlobalVariablesPanel::nameEditingFinished); + tableLayout->addWidget(i, col++, name); + + // unit + cboUnit[i] = new QComboBox(this); + QComboBox *unit = cboUnit[i]; + unit->setProperty("index", i); + unit->setModel(unitItemModel); + connect(unit, &QComboBox::currentIndexChanged, this, &GlobalVariablesPanel::unitCurrentIndexChanged); + tableLayout->addWidget(i, col++, unit); + + // precision + cboPrec[i] = new QComboBox(this); + QComboBox *prec = cboPrec[i]; + prec->setProperty("index", i); + prec->setModel(precItemModel); + connect(prec, &QComboBox::currentIndexChanged, this, &GlobalVariablesPanel::precCurrentIndexChanged); + tableLayout->addWidget(i, col++, prec); + + // min + dsbMin[i] = new QDoubleSpinBox(this); + QDoubleSpinBox *min = dsbMin[i]; + min->setProperty("index", i); + connect(min, &QDoubleSpinBox::editingFinished, this, &GlobalVariablesPanel::minEditingFinished); + tableLayout->addWidget(i, col++, min); + + // max + dsbMax[i] = new QDoubleSpinBox(this); + QDoubleSpinBox *max = dsbMax[i]; + max->setProperty("index", i); + connect(max, &QDoubleSpinBox::editingFinished, this, &GlobalVariablesPanel::maxEditingFinished); + tableLayout->addWidget(i, col++, max); + + // popup + chkPopup[i] = new QCheckBox(this); + QCheckBox *popup = chkPopup[i]; + popup->setProperty("index", i); + connect(popup, &QCheckBox::toggled, this, &GlobalVariablesPanel::popupToggled); + tableLayout->addWidget(i, col++, popup, Qt::AlignHCenter); + + // radio modes (drive/flight) + for (int j = 0; j < modes; j++) { + if (j > 0) { + // use mode + chkUseMode[i][j] = new QCheckBox(tr("%1M").arg(modePrefix),this); + QCheckBox *usemode = chkUseMode[i][j]; + setIndexes(usemode, i, j); + connect(usemode, &QCheckBox::toggled, this, &GlobalVariablesPanel::useModeToggled); + tableLayout->addWidget(i, col++, usemode, Qt::AlignHCenter); + + // mode + cboMode[i][j] = new QComboBox(this); + QComboBox *mode = cboMode[i][j]; + setIndexes(mode, i, j); + mode->setModel(gvarModesIMF->getItemModel(firstmidx + j)); + connect(mode, &QComboBox::currentIndexChanged, this, &GlobalVariablesPanel::modeCurrentIndexChanged); + tableLayout->addWidget(i, col, mode); // do not increment col as either cboMode or dsbValue visible + } + + // value + dsbValue[i][j] = new QDoubleSpinBox(this); + QDoubleSpinBox *value = dsbValue[i][j]; + setIndexes(value, i, j); + connect(value, &QDoubleSpinBox::editingFinished, this, &GlobalVariablesPanel::valueEditingFinished); + tableLayout->addWidget(i, col++, value); + } + } + + int col = headerLabels.size(); + + for (int i = 0; i < modes; i++) { + int colspan = i > 0 ? 2 : 1; + tableLayout->addColumnHead(model.flightModeData[i].nameToString(i), col, colspan); + col += colspan; + } + + disableMouseScrolling(); + tableLayout->resizeColumnsToContents(); + tableLayout->pushRowsUp(gvars + 1); + tableLayout->pushColumnsLeft(col); +} + +GlobalVariablesPanel::~GlobalVariablesPanel() +{ +} + +void GlobalVariablesPanel::cmClear(bool prompt) +{ + if (prompt) { + if (QMessageBox::question(this, tr("Edit Global Variables"), + tr("Clear global variable #%1. Are you sure?").arg(selectedIndex + 1), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + } + + model->gvarClear(selectedIndex); + updateLine(selectedIndex); + updateItemModels(); + emit modified(); +} + +void GlobalVariablesPanel::cmClearAll() +{ + if (QMessageBox::question(this, tr("Edit Global Variables"), + tr("Clear all global variables. Are you sure?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + + for (int i = 0; i < gvars; i++) { + model->gvarClear(i); + } + + update(); + updateItemModels(); + emit modified(); +} + +void GlobalVariablesPanel::cmCopy() +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << model->gvarData[selectedIndex]; + + for (int j = 0; j < modes; j++) { + stream << model->flightModeData[j].gvars[selectedIndex]; + } + + QMimeData *mimeData = new QMimeData; + mimeData->setData(MIMETYPE_GLOBAL_VARIABLE, data); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); +} + +void GlobalVariablesPanel::cmCut() +{ + if (QMessageBox::question(this, tr("Edit Global Variables"), + tr("Cut global variable #%1. Are you sure?").arg(selectedIndex + 1), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + + cmCopy(); + cmClear(false); +} + +void GlobalVariablesPanel::cmDelete() +{ + if (QMessageBox::question(this, tr("Edit Global Variables"), + tr("Delete global variable #%1. Are you sure?").arg(selectedIndex + 1), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + return; + + model->gvarDelete(selectedIndex); + + for (int i = selectedIndex; i < gvars; i++) { + updateLine(i); + } + + updateItemModels(); + emit modified(); +} + +void GlobalVariablesPanel::cmInsert() +{ + model->gvarInsert(selectedIndex); + + for (int i = selectedIndex; i < gvars; i++) { + updateLine(i); + } + + updateItemModels(); + emit modified(); +} + +void GlobalVariablesPanel::cmMoveDown() +{ + swapData(selectedIndex, selectedIndex + 1); +} + +void GlobalVariablesPanel::cmMoveUp() +{ + swapData(selectedIndex, selectedIndex - 1); +} + +void GlobalVariablesPanel::cmPaste() +{ + QByteArray data; + if (hasClipboardData(&data)) { + QDataStream stream(&data, QIODevice::ReadOnly); + stream >> model->gvarData[selectedIndex]; + + for (int j = 0; j < modes; j++) { + stream >> model->flightModeData[j].gvars[selectedIndex]; + } + + updateLine(selectedIndex); + updateItemModels(); + emit modified(); + } +} + +void GlobalVariablesPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, + &GlobalVariablesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, + &GlobalVariablesPanel::onItemModelUpdateComplete); +} + +bool GlobalVariablesPanel::deleteAllowed() const +{ + return selectedIndex < gvars - 1; +} + +bool GlobalVariablesPanel::getIndexes(QWidget * widget, int &gvarIdx, int &modeIdx) { + bool ok = false; + unsigned int i = (unsigned int)widget->property("index").toInt(&ok); + + if (!ok) + return false; + + modeIdx = (int)Helpers::getBitmappedValue(i, 0, 8); + gvarIdx = (int)Helpers::getBitmappedValue(i, 1, 8); + return true; +} + +bool GlobalVariablesPanel::hasClipboardData(QByteArray * data) const +{ + const QClipboard * clipboard = QApplication::clipboard(); + const QMimeData * mimeData = clipboard->mimeData(); + + if (mimeData->hasFormat(MIMETYPE_GLOBAL_VARIABLE)) { + if (data) { + data->append(mimeData->data(MIMETYPE_GLOBAL_VARIABLE)); + } + + return true; + } + + return false; +} + +void GlobalVariablesPanel::maxEditingFinished() +{ + if (!lock) { + QDoubleSpinBox *dsb = qobject_cast(sender()); + bool ok; + int gidx = dsb->property("index").toInt(&ok); + + if (ok) { + model->gvarSetMax(gidx, dsb->value()); + updateLine(gidx); + emit modified(); + } + } +} + +void GlobalVariablesPanel::minEditingFinished() +{ + if (!lock) { + QDoubleSpinBox *dsb = qobject_cast(sender()); + bool ok; + int gidx = dsb->property("index").toInt(&ok); + + if (ok) { + model->gvarSetMin(gidx, dsb->value()); + updateLine(gidx); + emit modified(); + } + } +} + +void GlobalVariablesPanel::modeCurrentIndexChanged(int index) +{ + if (!lock) { + QComboBox *cbo = qobject_cast(sender()); + int gidx = 0; + int midx = 0; + + if (getIndexes(cbo, gidx, midx)) { + model->flightModeData[midx].gvars[gidx] = cbo->currentData().toInt(); + + if (model->isGVarLinkedCircular(midx, gidx)) { + QMessageBox::warning(this, tr("Edit Global Variables"), + tr("Warning: Global variable links back to itself, %1M0 used.") + .arg(modePrefix)); + model->flightModeData[midx].gvars[gidx] = + model->flightModeData->linkedGVarFlightModeZero(midx); + } + + updateLine(gidx); + emit modified(); + } + } +} + +bool GlobalVariablesPanel::moveDownAllowed() const +{ + return selectedIndex < gvars - 1; +} + +bool GlobalVariablesPanel::moveUpAllowed() const +{ + return selectedIndex > 0; +} + +void GlobalVariablesPanel::nameEditingFinished() +{ + if (!lock) { + QLineEdit *lineedit = qobject_cast(sender()); + bool ok; + int gidx = lineedit->property("index").toInt(&ok); + + if (ok) { + memset(&model->gvarData[gidx].name, 0, sizeof(model->gvarData[gidx].name)); + strcpy(model->gvarData[gidx].name, lineedit->text().toLatin1()); + updateItemModels(); + emit modified(); + } + } +} + +void GlobalVariablesPanel::onCustomContextMenuRequested(QPoint pos) +{ + QLabel *label = (QLabel *)sender(); + selectedIndex = label->property("index").toInt(); + QPoint globalPos = label->mapToGlobal(pos); + + QMenu contextMenu; + contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, + SLOT(cmCopy())); + contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, + SLOT(cmCut())); + contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, + SLOT(cmPaste()))->setEnabled(hasClipboardData()); + contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, + SLOT(cmClear())); + contextMenu.addSeparator(); + contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, + SLOT(cmInsert()))->setEnabled(model->gvarInsertAllowed(selectedIndex)); + contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, + SLOT(cmDelete()))->setEnabled(deleteAllowed()); + contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, + SLOT(cmMoveUp()))->setEnabled(moveUpAllowed()); + contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, + SLOT(cmMoveDown()))->setEnabled(moveDownAllowed()); + contextMenu.addSeparator(); + contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, + SLOT(cmClearAll())); + contextMenu.exec(globalPos); +} + +void GlobalVariablesPanel::onItemModelAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void GlobalVariablesPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } +} + +void GlobalVariablesPanel::popupToggled(bool checked) +{ + if (!lock) { + QCheckBox *chk = qobject_cast(sender()); + bool ok; + int gidx = chk->property("index").toInt(&ok); + + if (ok) { + model->gvarData[gidx].popup = checked; + emit modified(); + } + } +} + +void GlobalVariablesPanel::precCurrentIndexChanged(int index) +{ + if (!lock) { + QComboBox *comboBox = qobject_cast(sender()); + int gidx = comboBox->property("index").toInt(); + model->gvarData[gidx].prec = index; + updateLine(gidx); + emit modified(); + } +} + +void GlobalVariablesPanel::setIndexes(QWidget * widget, int gvarIdx, int modeIdx) { + unsigned int i = 0; + Helpers::setBitmappedValue(i, modeIdx, 0, 8); + Helpers::setBitmappedValue(i, gvarIdx, 1, 8); + widget->setProperty("index", i); +} + +void GlobalVariablesPanel::setMinMax(QDoubleSpinBox * dsb, int min, int max, int val) +{ + bool ok; + int gidx = dsb->property("index").toInt(&ok); + + if (ok) { + float mul = model->gvarData[gidx].multiplierGet(); + dsb->setDecimals(model->gvarData[gidx].prec); + dsb->setSingleStep(mul); + dsb->setSuffix(model->gvarData[gidx].unitToString()); + dsb->setMinimum(min * mul); + dsb->setMaximum(max * mul); + dsb->setValue(val * mul); + } +} + +void GlobalVariablesPanel::setValue(QDoubleSpinBox * dsb, int val) +{ + int gidx = 0; + int midx = 0; + + if (getIndexes(dsb, gidx, midx)) { + float mul = model->gvarData[gidx].multiplierGet(); + dsb->setDecimals(model->gvarData[gidx].prec); + dsb->setSingleStep(mul); + dsb->setSuffix(model->gvarData[gidx].unitToString()); + dsb->setMinimum(model->gvarData[gidx].getMinPrec()); + dsb->setMaximum(model->gvarData[gidx].getMaxPrec()); + dsb->setValue(val * mul); + } +} + +void GlobalVariablesPanel::swapData(int index1, int index2) +{ + if ((index1 != index2)) { + model->gvarSwap(index1, index2); + updateLine(index1); + updateLine(index2); + updateItemModels(); + emit modified(); + } +} + +void GlobalVariablesPanel::unitCurrentIndexChanged(int index) +{ + if (!lock) { + QComboBox *comboBox = qobject_cast(sender()); + int gidx = comboBox->property("index").toInt(); + model->gvarData[gidx].unit = index; + updateLine(gidx); + emit modified(); + } +} + +void GlobalVariablesPanel::update() +{ + int col = 7; + + for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { + QString text(model->flightModeData[i].nameToString(i)); + tableLayout->updateColumnHeading(col, text); + i == 0 ? col++ : col += 2; + } + + for (int i = 0; i < gvars; i++) { + updateLine(i); + } +} + +void GlobalVariablesPanel::updateLine(int index) +{ + if (index < 0 || index >= gvars) + return; + + lock = true; + leName[index]->setText(model->gvarData[index].name); + cboUnit[index]->setCurrentIndex(model->gvarData[index].unit); + cboPrec[index]->setCurrentIndex(model->gvarData[index].prec); + setMinMax(dsbMin[index], GVAR_MIN_VALUE, model->gvarData[index].getMax(), + model->gvarData[index].getMin()); + setMinMax(dsbMax[index], model->gvarData[index].getMin(), GVAR_MAX_VALUE, + model->gvarData[index].getMax()); + chkPopup[index]->setChecked(model->gvarData[index].popup); + + for (int j = 0; j < modes; j++) { + if (!model->isGVarLinked(j, index)) { + if (j > 0) { + chkUseMode[index][j]->setChecked(false); + cboMode[index][j]->setCurrentIndex(0); + cboMode[index][j]->setVisible(false); + } + + dsbValue[index][j]->setVisible(true); + setValue(dsbValue[index][j], model->getGVarValue(j, index)); + } else { + chkUseMode[index][j]->setChecked(true); + cboMode[index][j]->setVisible(true); + cboMode[index][j]->setCurrentIndex(cboMode[index][j]->findData(model->flightModeData[j].gvars[index])); + dsbValue[index][j]->setValue(0); + dsbValue[index][j]->setVisible(false); + } + } + + lock = false; +} + +void GlobalVariablesPanel::updateItemModels() +{ + sharedItemModels->update(AbstractItemModel::IMUE_GVars); +} + +void GlobalVariablesPanel::useModeToggled(bool checked) +{ + if (!lock) { + QCheckBox *chk = qobject_cast(sender()); + int gidx = 0; + int midx = 0; + + if (getIndexes(chk, gidx, midx)) { + int val = checked ? model->flightModeData->linkedGVarFlightModeZero(midx) : 0; + model->flightModeData[midx].gvars[gidx] = val; + updateLine(gidx); + emit modified(); + } + } +} + +void GlobalVariablesPanel::valueEditingFinished() +{ + if (!lock) { + QDoubleSpinBox *dsb = qobject_cast(sender()); + int gidx = 0; + int midx = 0; + + if (getIndexes(dsb, gidx, midx)) { + model->flightModeData[midx].gvars[gidx] = dsb->value() * + model->gvarData[gidx].multiplierSet(); + updateLine(gidx); + emit modified(); + } + } +} diff --git a/companion/src/modeledit/gvars.h b/companion/src/modeledit/gvars.h new file mode 100644 index 000000000..53bfd7d24 --- /dev/null +++ b/companion/src/modeledit/gvars.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * 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. + */ + +#pragma once + +#include "modeledit.h" +#include "constants.h" +#include "boards.h" + +class CompoundItemModelFactory; +class FilteredItemModel; +class TableLayout; + +constexpr char MIMETYPE_GLOBAL_VARIABLE[] = "application/x-companion-global-variable"; + +class GlobalVariablesPanel : public ModelPanel +{ + Q_OBJECT + + public: + GlobalVariablesPanel(QWidget *parent, ModelData & model, + GeneralSettings & generalSettings, + Firmware * firmware, + CompoundItemModelFactory * sharedItemModels); + virtual ~GlobalVariablesPanel(); + + virtual void update(); + + private slots: + void cmClear(bool prompt = true); + void cmClearAll(); + void cmCopy(); + void cmCut(); + void cmDelete(); + void cmInsert(); + void cmMoveDown(); + void cmMoveUp(); + void cmPaste(); + void maxEditingFinished(); + void minEditingFinished(); + void modeCurrentIndexChanged(int index); + void nameEditingFinished(); + void onCustomContextMenuRequested(QPoint pos); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); + void popupToggled(bool checked); + void precCurrentIndexChanged(int index); + void unitCurrentIndexChanged(int index); + void useModeToggled(bool checked); + void valueEditingFinished(); + + private: + CompoundItemModelFactory *sharedItemModels; + int selectedIndex; + int modelsUpdateCnt; + int gvars; + int modes; + QString modeName; + QString modePrefix; + + TableLayout *tableLayout; + QLineEdit *leName[CPN_MAX_GVARS]; + QComboBox *cboUnit[CPN_MAX_GVARS]; + QComboBox *cboPrec[CPN_MAX_GVARS]; + QDoubleSpinBox *dsbMin[CPN_MAX_GVARS]; + QDoubleSpinBox *dsbMax[CPN_MAX_GVARS]; + QCheckBox *chkPopup[CPN_MAX_GVARS]; + QCheckBox *chkUseMode[CPN_MAX_GVARS][CPN_MAX_FLIGHT_MODES]; + QComboBox *cboMode[CPN_MAX_GVARS][CPN_MAX_FLIGHT_MODES]; + QDoubleSpinBox *dsbValue[CPN_MAX_GVARS][CPN_MAX_FLIGHT_MODES]; + + void connectItemModelEvents(const FilteredItemModel * itemModel); + bool deleteAllowed() const; + bool getIndexes(QWidget * widget, int &gvarIdx, int &modeIdx); + bool hasClipboardData(QByteArray * data = nullptr) const; + bool moveDownAllowed() const; + bool moveUpAllowed() const; + void setIndexes(QWidget * widget, int gvarIdx, int modeIdx); + void setValue(QDoubleSpinBox * spinBox, int val); + void setMinMax(QDoubleSpinBox * spinBox, int min, int max, int val); + void swapData(int index1, int index2); + void updateLine(const int index); + void updateItemModels(); +}; diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index 2a0b59a15..66585016f 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -29,7 +29,7 @@ #include "mixes.h" #include "channels.h" #include "curves.h" -#include "verticalscrollarea.h" +#include "scrollarea.h" #include "logicalswitches.h" #include "customfunctions.h" #include "telemetry.h" @@ -38,6 +38,7 @@ #include "modeloptions.h" #include "appdata.h" #include "compounditemmodels.h" +#include "gvars.h" ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmware * firmware) : QDialog(parent), @@ -57,6 +58,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw GeneralSettings &generalSettings = radioData.generalSettings; ModelData &model = radioData.models[modelId]; + QString radioMode = Boards::getRadioModeString(firmware->getBoard()); sharedItemModels = new CompoundItemModelFactory(&generalSettings, &model); sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); @@ -81,10 +83,10 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw s1.report("Heli"); } - QString radioType = QString(tr("%1 Modes").arg(Boards::getRadioTypeString(firmware->getBoard()))); - FlightModesPanel *flightModesPanel = new FlightModesPanel(this, model, generalSettings, firmware, sharedItemModels); - addTab(flightModesPanel, radioType); - s1.report(radioType); + QString tabTitle = QString(tr("%1 Modes").arg(Boards::getRadioModeString(firmware->getBoard()))); + FlightModesPanel *flightModesPanel = new FlightModesPanel(this, model, generalSettings, firmware, sharedItemModels, radioMode); + addTab(flightModesPanel, tabTitle); + s1.report(tabTitle); addTab(new InputsPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Inputs")); s1.report("Inputs"); @@ -99,6 +101,11 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw addTab(new CurvesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Curves")); s1.report("Curves"); + if (firmware->getCapability(Gvars)) { + addTab(new GlobalVariablesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Global Variables")); + s1.report("Global Variables"); + } + addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Logical Switches")); s1.report("Logical Switches"); @@ -149,7 +156,7 @@ void ModelEdit::addTab(GenericPanel *panel, QString text) panels << panel; QWidget * widget = new QWidget(ui->tabWidget); QVBoxLayout *baseLayout = new QVBoxLayout(widget); - VerticalScrollArea * area = new VerticalScrollArea(widget, panel); + ScrollArea * area = new ScrollArea(widget, panel); baseLayout->addWidget(area); ui->tabWidget->addTab(widget, text); connect(panel, &GenericPanel::modified, this, &ModelEdit::modified); diff --git a/companion/src/modeledit/modeloptions.cpp b/companion/src/modeledit/modeloptions.cpp index 5029cdcc4..3a0253ebd 100644 --- a/companion/src/modeledit/modeloptions.cpp +++ b/companion/src/modeledit/modeloptions.cpp @@ -82,7 +82,7 @@ ModelOptionsPanel::ModelOptionsPanel(QWidget * parent, ModelData & model, Genera addParams(); } - addLabel(tr("%1 Modes").arg(Boards::getRadioTypeString(firmware->getBoard()))); + addLabel(tr("%1 Modes").arg(Boards::getRadioModeString(firmware->getBoard()))); AutoComboBox *fmDisable = new AutoComboBox(this); fmDisable->setModel(mdl); fmDisable->setField(model.modelFMDisabled, this); diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 23e72e198..3307211e7 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -199,8 +199,8 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge const int ttlFlexInputs = Boards::getBoardCapability(board, Board::FlexInputs); const int ttlInputs = ttlSticks + ttlFlexInputs; - for (int i = 0; i < ttlInputs + firmware->getCapability(RotaryEncoders); i++) { - RawSource src((i < ttlInputs) ? SOURCE_TYPE_INPUT : SOURCE_TYPE_ROTARY_ENCODER, (i < ttlInputs) ? i + 1 : i - ttlInputs); + for (int i = 0; i < ttlInputs; i++) { + RawSource src(SOURCE_TYPE_INPUT, i + 1); QCheckBox * checkbox = new QCheckBox(this); checkbox->setProperty("index", i); checkbox->setText(src.toString(&model, &generalSettings)); diff --git a/companion/src/print/modelprinter.cpp b/companion/src/print/modelprinter.cpp index 4df6abd12..227d0607b 100644 --- a/companion/src/print/modelprinter.cpp +++ b/companion/src/print/modelprinter.cpp @@ -274,9 +274,9 @@ QString ModelPrinter::printCenterBeep() Board::Type board = getCurrentBoard(); int inputs = Boards::getBoardCapability(board, Board::Inputs); - for (int i = 0; i < inputs + firmware->getCapability(RotaryEncoders); i++) { + for (int i = 0; i < inputs; i++) { if (model.beepANACenter & (0x01 << i)) { - RawSource src((i < inputs) ? SOURCE_TYPE_INPUT : SOURCE_TYPE_ROTARY_ENCODER, (i < inputs) ? i : inputs - i); + RawSource src(SOURCE_TYPE_INPUT, i + 1); strl << src.toString(&model, &generalSettings); } } @@ -325,20 +325,6 @@ QString ModelPrinter::printGlobalVar(int flightModeIndex, int gvarIndex) } } -QString ModelPrinter::printRotaryEncoder(int flightModeIndex, int reIndex) -{ - const FlightModeData & fm = model.flightModeData[flightModeIndex]; - - if (fm.rotaryEncoders[reIndex] <= 1024) { - return QString("%1").arg(fm.rotaryEncoders[reIndex]); - } - else { - int num = fm.rotaryEncoders[reIndex] - 1025; - if (num >= flightModeIndex) num++; - return tr("FM%1").arg(num); - } -} - QString ModelPrinter::printInputName(int idx) { RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_INPUT); diff --git a/companion/src/print/modelprinter.h b/companion/src/print/modelprinter.h index 7f9143a82..702e5c2d0 100644 --- a/companion/src/print/modelprinter.h +++ b/companion/src/print/modelprinter.h @@ -52,7 +52,6 @@ class ModelPrinter: public QObject QString printHeliSwashType(); QString printTrim(int flightModeIndex, int stickIndex); QString printGlobalVar(int flightModeIndex, int gvarIndex); - QString printRotaryEncoder(int flightModeIndex, int reIndex); QString printInputName(int idx); QString printInputLine(int idx); QString printInputLine(const ExpoData & ed); diff --git a/companion/src/print/multimodelprinter.cpp b/companion/src/print/multimodelprinter.cpp index fc9ec3ef1..ef3205ef3 100644 --- a/companion/src/print/multimodelprinter.cpp +++ b/companion/src/print/multimodelprinter.cpp @@ -460,9 +460,10 @@ QString MultiModelPrinter::printFlightModes() str.append(columns.print()); } - // GVars and Rotary Encoders + // GVars int gvars = firmware->getCapability(Gvars); - if ((gvars && firmware->getCapability(GvarsFlightModes)) || firmware->getCapability(RotaryEncoders)) { + + if (gvars && firmware->getCapability(GvarsFlightModes)) { MultiColumns columns(modelPrinterMap.size()); columns.appendSectionTableStart(); QStringList hd = QStringList() << tr("Global vars"); @@ -471,9 +472,6 @@ QString MultiModelPrinter::printFlightModes() hd << tr("GV%1").arg(i + 1); } } - for (int i=0; igetCapability(RotaryEncoders); i++) { - hd << tr("RE%1").arg(i + 1); - } columns.appendRowHeader(hd); int wd = 80 / gvars; if (firmware->getCapability(GvarsFlightModes)) { @@ -524,9 +522,7 @@ QString MultiModelPrinter::printFlightModes() COMPARECELL(modelPrinter->printGlobalVar(i, k)); } } - for (int k = 0; k < firmware->getCapability(RotaryEncoders); k++) { - COMPARECELL(modelPrinter->printRotaryEncoder(i, k)); - } + columns.appendRowEnd(); } columns.appendTableEnd(); diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index 0b284cd96..6fc3015ad 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -18,7 +18,7 @@ set(${PROJECT_NAME}_NAMES curveimagewidget curvedialog genericpanel - verticalscrollarea + scrollarea textvalidator ) diff --git a/companion/src/shared/verticalscrollarea.cpp b/companion/src/shared/scrollarea.cpp similarity index 76% rename from companion/src/shared/verticalscrollarea.cpp rename to companion/src/shared/scrollarea.cpp index 9d1b2d995..de89d6818 100644 --- a/companion/src/shared/verticalscrollarea.cpp +++ b/companion/src/shared/scrollarea.cpp @@ -19,25 +19,24 @@ * GNU General Public License for more details. */ -#include "verticalscrollarea.h" +#include "scrollarea.h" #include "genericpanel.h" #include #include -VerticalScrollArea::VerticalScrollArea(QWidget * parent, GenericPanel * panel): +ScrollArea::ScrollArea(QWidget * parent, GenericPanel * panel): QScrollArea(parent), panel(panel) { setWidgetResizable(true); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setWidget(panel); panel->installEventFilter(this); } -bool VerticalScrollArea::eventFilter(QObject * o, QEvent * e) +bool ScrollArea::eventFilter(QObject * o, QEvent * e) { if (o == panel && e->type() == QEvent::Resize) { - setMinimumWidth(panel->minimumSizeHint().width() + verticalScrollBar()->width()); + setMinimumWidth(panel->minimumSizeHint().width() * 0.75); } return false; } diff --git a/companion/src/shared/verticalscrollarea.h b/companion/src/shared/scrollarea.h similarity index 89% rename from companion/src/shared/verticalscrollarea.h rename to companion/src/shared/scrollarea.h index 7c16f00b9..ddd6ca254 100644 --- a/companion/src/shared/verticalscrollarea.h +++ b/companion/src/shared/scrollarea.h @@ -25,12 +25,12 @@ class GenericPanel; -class VerticalScrollArea : public QScrollArea +class ScrollArea : public QScrollArea { Q_OBJECT public: - VerticalScrollArea(QWidget * parent, GenericPanel * panel); + ScrollArea(QWidget * parent, GenericPanel * panel); protected: virtual bool eventFilter(QObject * o, QEvent * e);