fix(cpn): crash when creating a new model on Windows (#6869)

This commit is contained in:
philmoz
2025-12-13 12:21:35 +10:00
committed by GitHub
parent 2d1cf8e5a8
commit fb53b369d2
4 changed files with 35 additions and 43 deletions
+19 -23
View File
@@ -29,22 +29,23 @@
ZoneOptionValue::ZoneOptionValue()
{
memset((void*)this, 0, sizeof(ZoneOptionValue));
unsignedValue = 0;
signedValue = 0;
boolValue = 0;
stringValue.clear();
sourceValue.clear();
colorValue = 0;
}
bool ZoneOptionValue::isEmpty() const
{
return unsignedValue == 0 && signedValue == 0 && boolValue == 0 && colorValue == 0 &&
stringValue.empty() && sourceValue.toValue() == 0;
}
ZoneOptionValueTyped::ZoneOptionValueTyped()
{
memset((void*)this, 0, sizeof(ZoneOptionValueTyped));
}
WidgetPersistentData::WidgetPersistentData()
{
memset((void*)this, 0, sizeof(WidgetPersistentData));
}
ZonePersistentData::ZonePersistentData()
{
memset((void*)this, 0, sizeof(ZonePersistentData));
type = ZOV_Unsigned;
}
inline void setZoneOptionValue(ZoneOptionValue& zov, bool value)
@@ -57,9 +58,9 @@ inline void setZoneOptionValue(ZoneOptionValue& zov, int value)
zov.signedValue = value;
}
inline void setZoneOptionValue(ZoneOptionValue& zov, char value)
inline void setZoneOptionValue(ZoneOptionValue& zov, const char* value)
{
memset(&zov.stringValue, value, LEN_ZONE_OPTION_STRING);
zov.stringValue = value;
}
inline void setZoneOptionValue(ZoneOptionValue& zov, unsigned int value)
@@ -110,22 +111,17 @@ static const ZoneOptionValueTyped zero_widget_option = {};
bool ZoneOptionValueTyped::isEmpty() const
{
return !memcmp((void*)this, &zero_widget_option, sizeof(zero_widget_option));
return type == ZOV_Unsigned && value.isEmpty();
}
bool ZonePersistentData::isEmpty() const
{
return strlen(widgetName) == 0;
}
RadioLayout::CustomScreenData::CustomScreenData()
{
memset((void*)this, 0, sizeof(RadioLayout::CustomScreenData));
return widgetName.empty();
}
bool RadioLayout::CustomScreenData::isEmpty() const
{
return strlen(layoutId) == 0;
return layoutId.empty();
}
void RadioLayout::CustomScreens::clear()
@@ -141,7 +137,7 @@ void RadioLayout::init(const char* layoutId, CustomScreens& customScreens)
for (int i = 0; i < MAX_CUSTOM_SCREENS; i++) {
if (i == 0)
strncpy(customScreens.customScreenData[i].layoutId, layoutId, LAYOUT_ID_LEN);
customScreens.customScreenData[i].layoutId = layoutId;
LayoutPersistentData& persistentData =
customScreens.customScreenData[i].layoutPersistentData;
+8 -12
View File
@@ -33,14 +33,11 @@
constexpr int MAX_CUSTOM_SCREENS {10};
constexpr int MAX_THEME_OPTIONS {5};
constexpr int LEN_ZONE_OPTION_STRING {255}; // TODO: use std::string instead of fixed length char array
constexpr int MAX_LAYOUT_ZONES {10};
constexpr int MAX_LAYOUT_OPTIONS {10};
constexpr int WIDGET_NAME_LEN {255}; // TODO: use std::string instead of fixed length char array
constexpr int MAX_WIDGET_OPTIONS {50};
constexpr int MAX_TOPBAR_ZONES {7}; // 4 for portrait LCD, 6 for standard LCD, 7 for wide screen LCD
constexpr int MAX_TOPBAR_OPTIONS {1};
constexpr int LAYOUT_ID_LEN {255}; // TODO: use std::string instead of fixed length char array
// Common 'ZoneOptionValue's among all layouts
enum {
@@ -58,11 +55,12 @@ struct ZoneOptionValue // union in radio/src/datastructs.h
unsigned int unsignedValue;
int signedValue;
unsigned int boolValue;
char stringValue[LEN_ZONE_OPTION_STRING + 1];
std::string stringValue;
RawSource sourceValue;
unsigned int colorValue;
ZoneOptionValue();
bool isEmpty() const;
};
enum ZoneOptionValueEnum {
@@ -119,14 +117,14 @@ struct ZoneOptionValueTyped
struct WidgetPersistentData {
ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS];
WidgetPersistentData();
WidgetPersistentData() {}
};
struct ZonePersistentData {
char widgetName[WIDGET_NAME_LEN + 1];
std::string widgetName;
WidgetPersistentData widgetData;
ZonePersistentData();
ZonePersistentData() {}
bool isEmpty() const;
};
@@ -135,9 +133,7 @@ struct WidgetsContainerPersistentData {
ZonePersistentData zones[N];
ZoneOptionValueTyped options[O];
WidgetsContainerPersistentData() {
memset((void*)this, 0, sizeof(WidgetsContainerPersistentData));
}
WidgetsContainerPersistentData() {}
};
typedef WidgetsContainerPersistentData<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>
@@ -152,10 +148,10 @@ class RadioLayout
public:
struct CustomScreenData {
char layoutId[LAYOUT_ID_LEN + 1];
std::string layoutId;
LayoutPersistentData layoutPersistentData;
CustomScreenData();
CustomScreenData() {}
bool isEmpty() const;
};
@@ -43,7 +43,7 @@ struct convert<WidgetsContainerPersistentData<N,O> > {
{
Node node;
for (int i=0; i<N; i++) {
if (strlen(rhs.zones[i].widgetName) > 0) {
if (!rhs.zones[i].widgetName.empty()) {
node["zones"][std::to_string(i)] = rhs.zones[i];
}
}
@@ -149,7 +149,7 @@ UserInterfacePanel::UserInterfacePanel(QWidget * parent, ModelData & model, Gene
for (int i = 0; i < firmware->getCapability(TopBarZones); i++) {
ZonePersistentData & zpd = model.topBarData.zones[i];
QPushButton * btn = new QPushButton(zpd.widgetName, this);
QPushButton * btn = new QPushButton(zpd.widgetName.c_str(), this);
btn->setProperty("index", i);
btn->setFixedSize(QSize(180, 50));
widgetbtns.append(btn);
@@ -165,7 +165,7 @@ UserInterfacePanel::UserInterfacePanel(QWidget * parent, ModelData & model, Gene
optswidgets.append(wgt);
QGridLayout * layout = new QGridLayout(wgt); // must be owned by QWidget so visibility can be set
layout->addLayout(addOptionsLayout<WidgetPersistentData>(zpd.widgetData, MAX_WIDGET_OPTIONS, zpd.widgetName), 0, 0);
layout->addLayout(addOptionsLayout<WidgetPersistentData>(zpd.widgetData, MAX_WIDGET_OPTIONS, zpd.widgetName.c_str()), 0, 0);
optsgrids.append(layout);
connect(btn, &QPushButton::clicked, this, [&]() {
@@ -239,7 +239,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in
addGridLabel(grid, tr("Layout:"), row, col++);
// currently no point continuing if no layout but will change if editing becomes possible
if (model.customScreens.customScreenData[index].layoutId[0] == '\0') {
if (model.customScreens.customScreenData[index].layoutId.empty()) {
addGridLabel(grid, tr("None"), row, col);
addHSpring(grid, grid->columnCount(), 0);
addVSpring(grid, 0, grid->rowCount());
@@ -248,7 +248,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in
QLabel * img = new QLabel(this);
QString path(QString(":/layouts/mask_%1.png").arg(QString(scrns.customScreenData[index].layoutId).toLower()));
QString path(QString(":/layouts/mask_%1.png").arg(QString(scrns.customScreenData[index].layoutId.c_str()).toLower()));
QFile f(path);
if (f.exists()) {
@@ -278,7 +278,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in
for (int i = 0; i < MAX_LAYOUT_ZONES; i++) {
ZonePersistentData & zpd = lpd.zones[i];
QPushButton * btn = new QPushButton(zpd.widgetName, this);
QPushButton * btn = new QPushButton(zpd.widgetName.c_str(), this);
btn->setProperty("index", i);
btn->setFixedSize(QSize(180, 50));
widgetbtns.append(btn);
@@ -294,7 +294,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in
optswidgets.append(wgt);
QGridLayout * layout = new QGridLayout(wgt); // must be owned by QWidget so visibility can be set
layout->addLayout(addOptionsLayout<WidgetPersistentData>(zpd.widgetData, MAX_WIDGET_OPTIONS, zpd.widgetName), 0, 0, Qt::AlignTop);
layout->addLayout(addOptionsLayout<WidgetPersistentData>(zpd.widgetData, MAX_WIDGET_OPTIONS, zpd.widgetName.c_str()), 0, 0, Qt::AlignTop);
optsgrids.append(layout);
connect(btn, &QPushButton::clicked, this, [&]() {
@@ -369,7 +369,7 @@ CustomScreenPanel::CustomScreenPanel(QWidget * parent, ModelData & model, int in
break;
case ZOV_String:
lbl = new QLabel(this);
lbl->setText(lpd.options[i].value.stringValue);
lbl->setText(lpd.options[i].value.stringValue.c_str());
break;
default:
lbl = new QLabel(this);