diff --git a/companion/src/firmwares/customisation_data.cpp b/companion/src/firmwares/customisation_data.cpp index deda4a21c..d5bea24b2 100644 --- a/companion/src/firmwares/customisation_data.cpp +++ b/companion/src/firmwares/customisation_data.cpp @@ -20,6 +20,8 @@ */ #include "customisation_data.h" +#include "eeprominterface.h" +#include "helpers.h" // cannot use QColor so use formula from libopenui_defines.h #define RADIO_RGB(r, g, b) \ @@ -27,6 +29,22 @@ #define WHITE RADIO_RGB(0xFF, 0xFF, 0xFF) #define RED RADIO_RGB(229, 32, 30) +// based on radio/src/gui/colorlcd/libui/etx_lv_theme.h +int layoutValueScaled(int value) +{ + Firmware *firmware = getCurrentFirmware(); + Board::Type board = firmware->getBoard(); + + if (firmware->getCapability(IsLandscape)) { + if (Boards::getCapability(board, Board::LcdWidth) == 320) + return ((value * 8 + 5) / 10); + else if (Boards::getCapability(board, Board::LcdWidth) == 800) + return ((value * 11 + 4) / 8); + } + + return value; +} + ZoneOptionValue::ZoneOptionValue() { clear(); @@ -262,3 +280,14 @@ void RadioLayout::init(const std::string layoutId, CustomScreens& customScreens) setZoneOptionValue(persistentData.options[j++].value, (bool)false); } } + +// based on radio/src/gui/colorlcd/mainview/datastructs_screen.h +int RadioLayout::topBarZones() +{ + Firmware *firmware = getCurrentFirmware(); + Board::Type board = firmware->getBoard(); + const int menuHeaderButtonsLeft = layoutValueScaled(47); + const int topBarZoneWidth = layoutValueScaled((firmware->getCapability(IsWideLayout) ? 74 : 70)); + return rangeCheck(((Boards::getCapability(board, Board::LcdWidth) - menuHeaderButtonsLeft - 1 + + topBarZoneWidth / 2) / topBarZoneWidth), 0, MAX_TOPBAR_ZONES, 0); +} diff --git a/companion/src/firmwares/customisation_data.h b/companion/src/firmwares/customisation_data.h index 2d01653b4..4c01db981 100644 --- a/companion/src/firmwares/customisation_data.h +++ b/companion/src/firmwares/customisation_data.h @@ -191,4 +191,5 @@ class RadioLayout }; static void init(const std::string layoutId, CustomScreens & customScreens); + static int topBarZones(); }; diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 1c76b52da..490cc0c0e 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -1029,7 +1029,8 @@ Node convert::encode(const ModelData& rhs) modelSettingsVersion = SemanticVersion(VERSION); Node node; - auto board = getCurrentBoard(); + auto firmware = getCurrentFirmware(); + auto board = firmware->getBoard(); bool hasColorLcd = Boards::getCapability(board, Board::HasColorLcd); @@ -1242,8 +1243,8 @@ Node convert::encode(const ModelData& rhs) node["toplcdTimer"] = rhs.toplcdTimer; } - if (IS_FAMILY_HORUS_OR_T16(board)) { - for (int i=0; i::encode(const ModelData& rhs) if (topbarData && topbarData.IsMap()) { node["topbarData"] = topbarData; } - for (int i = 0; i < MAX_TOPBAR_ZONES; i++) - if (rhs.topbarWidgetWidth[i] > 0) + for (int i = 0; i < firmware->getCapability(TopBarZones); i++) { + if (rhs.topbarWidgetWidth[i] > 0) { node["topbarWidgetWidth"][std::to_string(i)]["val"] = (int)rhs.topbarWidgetWidth[i]; + } + } node["view"] = rhs.view; } @@ -1311,7 +1314,8 @@ bool convert::decode(const Node& node, ModelData& rhs) { if (!node.IsMap()) return false; - Board::Type board = getCurrentBoard(); + auto firmware = getCurrentFirmware(); + auto board = firmware->getBoard(); unsigned int modelIds[CPN_MAX_MODULES]; memset(modelIds, 0, sizeof(modelIds)); @@ -1663,6 +1667,22 @@ bool convert::decode(const Node& node, ModelData& rhs) YamlValidateLabelsNames(rhs, board); rhs.sortMixes(); // critical for Companion and radio that mix lines are in sequence + // TODO move to model conversion so any changes reported + if (Boards::getCapability(board, Board::HasColorLcd)) { + // total width of topbar widgets cannot exceed firmware topbar zones + const int fwzones = firmware->getCapability(TopBarZones); + int usedzones = 0; + + for (int i = 0; i < MAX_TOPBAR_ZONES; i++) { + usedzones += rhs.topbarWidgetWidth[i]; + + if (usedzones > fwzones) { + rhs.topbarWidgetWidth[i] = 0; + rhs.topBarData.zones[i].clear(); + } + } + } + return true; } diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h index 6a14530ab..347c40272 100644 --- a/companion/src/firmwares/eeprominterface.h +++ b/companion/src/firmwares/eeprominterface.h @@ -76,6 +76,10 @@ enum Capability { HasVarioSink, Heli, InputsLength, + IsLandscape, + IsNarrowLayout, + IsPortrait, + IsWideLayout, KeyShortcuts, LogicalSwitches, LuaInputsPerScript, diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 7926905c8..67ee20b2e 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -312,7 +312,7 @@ void ModelData::clear() topBarData.clear(); for (int i = 0; i < MAX_TOPBAR_ZONES; i++) - topbarWidgetWidth[i] = 0; + topbarWidgetWidth[i] = 1; view = 0; memset(®istrationId, 0, sizeof(registrationId)); @@ -414,9 +414,11 @@ void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settin clear(); used = true; sprintf(name, "MODEL%02d", id + 1); + for (int i = 0; i < CPN_MAX_MODULES; i++) { moduleData[i].modelId = id + 1; } + setDefaultMixes(settings); setDefaultFunctionSwitches(Boards::getCapability(getCurrentFirmware()->getBoard(), Board::FunctionSwitches)); } diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 513767455..aa3ca0bcb 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -22,6 +22,7 @@ #include "opentxinterface.h" #include "appdata.h" #include "constants.h" +#include "customisation_data.h" #include #include @@ -130,6 +131,16 @@ int OpenTxFirmware::getCapability(::Capability capability) return !id.contains("noheli"); case InputsLength: return HAS_LARGE_LCD(board) ? 4 : 3; + case IsLandscape: + return Boards::getCapability(board, Board::LcdWidth) > Boards::getCapability(board, Board::LcdHeight); + case IsNarrowLayout: + // based on radio/src/gui/colorlcd/libui/etx_lv_theme.h + return (getCapability(IsPortrait) && Boards::getCapability(board, Board::LcdWidth) == 320); + case IsPortrait: + return !getCapability(IsLandscape); + case IsWideLayout: + // based on radio/src/gui/colorlcd/libui/etx_lv_theme.h + return (!getCapability(IsNarrowLayout) && Boards::getCapability(board, Board::LcdWidth) >= 800); case KeyShortcuts: return VERSION_MAJOR > 2 && Boards::getCapability(board, Board::HasColorLcd) ? MAX_KEYSHORTCUTS : 0; case LogicalSwitches: @@ -207,7 +218,7 @@ int OpenTxFirmware::getCapability(::Capability capability) else return 3; case TopBarZones: - return Boards::getCapability(board, Board::LcdWidth) > Boards::getCapability(board, Board::LcdHeight) ? 4 : 2; + return Boards::getCapability(board, Board::HasColorLcd) ? RadioLayout::topBarZones() : 0; case TrainerInputs: return 16; case TrimsRange: diff --git a/companion/src/helpers.h b/companion/src/helpers.h index b59a86d85..56552b085 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -268,3 +268,11 @@ class StatusDialog: public QDialog private: QLabel *msg; }; + +template +T rangeCheck(T value, T min, T max, T defaultValue) { + if (value < min || value > max) { + return defaultValue; + } + return value; +} diff --git a/companion/src/modeledit/colorcustomscreens.cpp b/companion/src/modeledit/colorcustomscreens.cpp index 3b6a94c21..0a356a078 100644 --- a/companion/src/modeledit/colorcustomscreens.cpp +++ b/companion/src/modeledit/colorcustomscreens.cpp @@ -147,7 +147,12 @@ UserInterfacePanel::UserInterfacePanel(QWidget * parent, ModelData & model, Gene QGridLayout * tbgrid = new QGridLayout(); - for (int i = 0; i < firmware->getCapability(TopBarZones); i++) { + const int zones = firmware->getCapability(TopBarZones); + int usedzones = 0; + + for (int i = 0; i < zones; i++) { + if (usedzones >= zones) break; + usedzones += model.topbarWidgetWidth[i]; ZonePersistentData & zpd = model.topBarData.zones[i]; QPushButton * btn = new QPushButton(zpd.widgetName.c_str(), this); btn->setProperty("index", i);