fix(cpn): topbar zones count and initialisation (#7147)

This commit is contained in:
Neil Horne
2026-03-15 13:18:03 +10:00
committed by GitHub
parent cef0a87971
commit 8a9b52bd97
8 changed files with 89 additions and 9 deletions
@@ -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);
}
@@ -191,4 +191,5 @@ class RadioLayout
};
static void init(const std::string layoutId, CustomScreens & customScreens);
static int topBarZones();
};
@@ -1029,7 +1029,8 @@ Node convert<ModelData>::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<ModelData>::encode(const ModelData& rhs)
node["toplcdTimer"] = rhs.toplcdTimer;
}
if (IS_FAMILY_HORUS_OR_T16(board)) {
for (int i=0; i<MAX_CUSTOM_SCREENS; i++) {
if (Boards::getCapability(board, Board::HasColorLcd)) {
for (int i = 0; i < MAX_CUSTOM_SCREENS; i++) {
const auto& csd = rhs.customScreens.customScreenData[i];
if (!csd.isEmpty()) {
node["screenData"][std::to_string(i)] = csd;
@@ -1254,9 +1255,11 @@ Node convert<ModelData>::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<ModelData>::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<ModelData>::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;
}
@@ -76,6 +76,10 @@ enum Capability {
HasVarioSink,
Heli,
InputsLength,
IsLandscape,
IsNarrowLayout,
IsPortrait,
IsWideLayout,
KeyShortcuts,
LogicalSwitches,
LuaInputsPerScript,
+3 -1
View File
@@ -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(&registrationId, 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));
}
@@ -22,6 +22,7 @@
#include "opentxinterface.h"
#include "appdata.h"
#include "constants.h"
#include "customisation_data.h"
#include <bitset>
#include <QMessageBox>
@@ -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:
+8
View File
@@ -268,3 +268,11 @@ class StatusDialog: public QDialog
private:
QLabel *msg;
};
template <typename T>
T rangeCheck(T value, T min, T max, T defaultValue) {
if (value < min || value > max) {
return defaultValue;
}
return value;
}
@@ -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);