fix(cpn): ModelData usage due to introduction of non-trivial data types (#6877)

Co-authored-by: philmoz <phil.a.mitchell@gmail.com>
This commit is contained in:
Neil Horne
2025-12-22 20:13:13 +10:00
committed by GitHub
co-authored by philmoz
parent 9725c948a7
commit 41c08b86d1
9 changed files with 414 additions and 75 deletions
+2 -2
View File
@@ -22,10 +22,10 @@
#include "boards.h"
#include "macros.h"
#include "compounditemmodels.h"
#include "moduledata.h"
#include "helpers.h"
#include "boardfactories.h"
#include "generalsettings.h"
#include "modeldata.h"
// TODO remove all those constants
// Update: These are now all only used within this class.
@@ -330,7 +330,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case FunctionSwitchGroups:
if (getCapability(board, FunctionSwitches)) {
return IS_RADIOMASTER_GX12(board) ? 4 : 3;
return IS_RADIOMASTER_GX12(board) ? CPN_MAX_CUSTOMSWITCH_GROUPS : 3;
}
return 0;
+112 -14
View File
@@ -29,12 +29,28 @@
ZoneOptionValue::ZoneOptionValue()
{
unsignedValue = 0;
signedValue = 0;
boolValue = 0;
stringValue.clear();
sourceValue.clear();
colorValue = 0;
clear();
}
ZoneOptionValue::ZoneOptionValue(const ZoneOptionValue & src)
{
copy(src);
}
ZoneOptionValue & ZoneOptionValue::operator=(const ZoneOptionValue & src)
{
copy(src);
return *this;
}
void ZoneOptionValue::copy(const ZoneOptionValue & src)
{
unsignedValue = src.unsignedValue;
signedValue = src.signedValue;
boolValue = src.boolValue;
stringValue = src.stringValue;
sourceValue = src.sourceValue;
colorValue = src.colorValue;
}
bool ZoneOptionValue::isEmpty() const
@@ -43,9 +59,14 @@ bool ZoneOptionValue::isEmpty() const
stringValue.empty() && sourceValue.toValue() == 0;
}
ZoneOptionValueTyped::ZoneOptionValueTyped()
void ZoneOptionValue::clear()
{
type = ZOV_Unsigned;
unsignedValue = 0;
signedValue = 0;
boolValue = 0;
stringValue.clear();
sourceValue.clear();
colorValue = 0;
}
inline void setZoneOptionValue(ZoneOptionValue& zov, bool value)
@@ -107,31 +128,108 @@ inline const char * zoneOptionValueEnumToString(ZoneOptionValueEnum zovenum) {
}
}
static const ZoneOptionValueTyped zero_widget_option = {};
ZoneOptionValueTyped::ZoneOptionValueTyped()
{
clear();
}
bool ZoneOptionValueTyped::isEmpty() const
{
return type == ZOV_Unsigned && value.isEmpty();
}
void ZoneOptionValueTyped::clear()
{
type = ZOV_Unsigned;
value.clear();
}
void WidgetPersistentData::clear()
{
for (int i = 0; i < MAX_WIDGET_OPTIONS; i += 1)
options[i].clear();
}
ZonePersistentData::ZonePersistentData(const ZonePersistentData & src)
{
copy(src);
}
ZonePersistentData & ZonePersistentData::operator=(const ZonePersistentData & src)
{
copy(src);
return *this;
}
void ZonePersistentData::copy(const ZonePersistentData & src)
{
widgetName = src.widgetName;
widgetData = src.widgetData;
}
bool ZonePersistentData::isEmpty() const
{
return widgetName.empty();
}
void ZonePersistentData::clear()
{
widgetName.clear();
widgetData.clear();
}
RadioLayout::CustomScreenData::CustomScreenData(const RadioLayout::CustomScreenData & src)
{
copy(src);
}
RadioLayout::CustomScreenData & RadioLayout::CustomScreenData::operator=(const RadioLayout::CustomScreenData & src)
{
copy(src);
return *this;
}
void RadioLayout::CustomScreenData::copy(const RadioLayout::CustomScreenData & src)
{
layoutId = src.layoutId;
layoutPersistentData = src.layoutPersistentData;
}
bool RadioLayout::CustomScreenData::isEmpty() const
{
return layoutId.empty();
}
void RadioLayout::CustomScreens::clear()
void RadioLayout::CustomScreenData::clear()
{
for (int i = 0; i < MAX_CUSTOM_SCREENS; i++) {
customScreenData[i] = CustomScreenData();
}
layoutId.clear();
layoutPersistentData.clear();
}
void RadioLayout::init(const char* layoutId, CustomScreens& customScreens)
RadioLayout::CustomScreens::CustomScreens(const RadioLayout::CustomScreens & src)
{
copy(src);
}
RadioLayout::CustomScreens & RadioLayout::CustomScreens::operator=(const RadioLayout::CustomScreens & src)
{
copy(src);
return *this;
}
void RadioLayout::CustomScreens::copy(const RadioLayout::CustomScreens & src)
{
for (int i = 0; i < MAX_CUSTOM_SCREENS; i++)
customScreenData[i] = src.customScreenData[i];
}
void RadioLayout::CustomScreens::clear()
{
for (int i = 0; i < MAX_CUSTOM_SCREENS; i++)
customScreenData[i].clear();
}
void RadioLayout::init(const std::string layoutId, CustomScreens& customScreens)
{
customScreens.clear();
+30 -1
View File
@@ -60,6 +60,11 @@ struct ZoneOptionValue // union in radio/src/datastructs.h
unsigned int colorValue;
ZoneOptionValue();
ZoneOptionValue(const ZoneOptionValue & src);
ZoneOptionValue & operator=(const ZoneOptionValue & src);
void clear();
void copy(const ZoneOptionValue & src);
bool isEmpty() const;
};
@@ -111,6 +116,7 @@ struct ZoneOptionValueTyped
ZoneOptionValue value;
ZoneOptionValueTyped();
void clear();
bool isEmpty() const;
};
@@ -118,6 +124,7 @@ struct WidgetPersistentData {
ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS];
WidgetPersistentData() {}
void clear();
};
struct ZonePersistentData {
@@ -125,6 +132,10 @@ struct ZonePersistentData {
WidgetPersistentData widgetData;
ZonePersistentData() {}
ZonePersistentData(const ZonePersistentData & src);
ZonePersistentData & operator=(const ZonePersistentData & src);
void clear();
void copy(const ZonePersistentData & src);
bool isEmpty() const;
};
@@ -134,6 +145,14 @@ struct WidgetsContainerPersistentData {
ZoneOptionValueTyped options[O];
WidgetsContainerPersistentData() {}
void clear() {
for (int i = 0; i < N; i++) {
zones[i].clear();
}
for (int i = 0; i < O; i++) {
options[i].clear();
}
}
};
typedef WidgetsContainerPersistentData<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>
@@ -152,14 +171,24 @@ class RadioLayout
LayoutPersistentData layoutPersistentData;
CustomScreenData() {}
CustomScreenData(const CustomScreenData & src);
CustomScreenData & operator=(const CustomScreenData & src);
void clear();
void copy(const CustomScreenData & src);
bool isEmpty() const;
};
struct CustomScreens {
CustomScreenData customScreenData[MAX_CUSTOM_SCREENS];
CustomScreens() {}
CustomScreens(const CustomScreens & src);
CustomScreens & operator=(const CustomScreens & src);
void clear();
void copy(const CustomScreens & src);
};
static void init(const char * layoutId, CustomScreens & customScreens);
static void init(const std::string layoutId, CustomScreens & customScreens);
};
@@ -984,12 +984,12 @@ struct convert<FrSkyScreenData> {
};
template <>
struct convert<customSwitch> {
static Node encode(const customSwitch& rhs);
static bool decode(const Node& node, customSwitch& rhs);
struct convert<CustomSwitchData> {
static Node encode(const CustomSwitchData& rhs);
static bool decode(const Node& node, CustomSwitchData& rhs);
};
Node convert<customSwitch>::encode(const customSwitch& rhs)
Node convert<CustomSwitchData>::encode(const CustomSwitchData& rhs)
{
Node node;
node["type"] = cfsSwitchConfig << rhs.type;
@@ -1006,7 +1006,7 @@ Node convert<customSwitch>::encode(const customSwitch& rhs)
return node;
}
bool convert<customSwitch>::decode(const Node& node, customSwitch& rhs)
bool convert<CustomSwitchData>::decode(const Node& node, CustomSwitchData& rhs)
{
if (!node.IsMap()) return false;
@@ -1254,7 +1254,7 @@ Node convert<ModelData>::encode(const ModelData& rhs)
if (topbarData && topbarData.IsMap()) {
node["topbarData"] = topbarData;
}
for (int i = 0; i < MAX_TOPBAR_ZONES; i += 1)
for (int i = 0; i < MAX_TOPBAR_ZONES; i++)
if (rhs.topbarWidgetWidth[i] > 0)
node["topbarWidgetWidth"][std::to_string(i)]["val"] = (int)rhs.topbarWidgetWidth[i];
node["view"] = rhs.view;
@@ -1265,14 +1265,17 @@ Node convert<ModelData>::encode(const ModelData& rhs)
int funcSwCnt = Boards::getCapability(board, Board::FunctionSwitches);
if (funcSwCnt) {
for (int i = 0; i < funcSwCnt; i += 1) {
for (int i = 0; i < funcSwCnt; i++) {
int sw = Boards::getSwitchIndexForCFS(i);
std::string tag = Boards::getSwitchYamlName(sw, BoardJson::YLT_CONFIG).toStdString();
node["customSwitches"][tag] = rhs.customSwitches[i];
}
for (int i = 1; i < 4; i += 1) {
node["cfsGroupOn"][std::to_string(i)]["v"] = rhs.cfsGroupOn[i];
int funcSwGrps = Boards::getCapability(board, Board::FunctionSwitchGroups);
if (funcSwGrps) {
for (int i = 1; i <= funcSwGrps; i++) {
node["cfsGroupOn"][std::to_string(i)]["v"] = rhs.cfsGroupOn[i];
}
}
}
@@ -1559,7 +1562,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
rhs.customSwitches[i].group = v & 3;
v >>= 2;
}
for (int i = 0; i < 4; i += 1) {
for (int i = 0; i < CPN_MAX_CUSTOMSWITCH_GROUPS; i += 1) {
rhs.cfsGroupOn[i] = v & 1;
v >>= 1;
}
@@ -1601,8 +1604,8 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
}
}
}
int funcSwCnt = Boards::getCapability(board, Board::FunctionSwitches);
if (node["customSwitches"]) {
int funcSwCnt = Boards::getCapability(board, Board::FunctionSwitches);
for (int i = 0; i < funcSwCnt; i += 1) {
int sw = Boards::getSwitchIndexForCFS(i);
std::string tag = Boards::getSwitchYamlName(sw, BoardJson::YLT_CONFIG).toStdString();
@@ -1610,7 +1613,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
}
}
if (node["cfsGroupOn"]) {
for (int i = 1; i < 4; i += 1) {
for (int i = 1; i < CPN_MAX_CUSTOMSWITCH_GROUPS; i += 1) {
if (node["cfsGroupOn"][std::to_string(i)]) {
node["cfsGroupOn"][std::to_string(i)]["v"] >> rhs.cfsGroupOn[i];
}
+186 -22
View File
@@ -39,15 +39,96 @@ ModelData::ModelData()
ModelData::ModelData(const ModelData & src)
{
*this = src;
copy(src);
}
ModelData & ModelData::operator = (const ModelData & src)
ModelData & ModelData::operator=(const ModelData & src)
{
memcpy(reinterpret_cast<void *>(this), &src, sizeof(ModelData));
copy(src);
return *this;
}
void ModelData::copy(const ModelData & src)
{
memcpy(&semver, &src.semver, sizeof(semver));
used = src.used;
memcpy(&name, &src.name, sizeof(name));
memcpy(&filename, &src.filename, sizeof(filename));
memcpy(&labels, &src.labels, sizeof(labels));
modelIndex = src.modelIndex;
modelUpdated = src.modelUpdated;
modelErrors = src.modelErrors;
memcpy(&timers[0], &src.timers[0], sizeof(timers[0]) * CPN_MAX_TIMERS);
noGlobalFunctions = src.noGlobalFunctions;
thrTrim = src.thrTrim;
trimInc = src.trimInc;
trimsDisplay = src.trimsDisplay;
disableThrottleWarning = src.disableThrottleWarning;
enableCustomThrottleWarning = src.enableCustomThrottleWarning;
customThrottleWarningPosition = src.customThrottleWarningPosition;
jitterFilter = src.jitterFilter;
beepANACenter = src.beepANACenter;
extendedLimits = src.extendedLimits;
extendedTrims = src.extendedTrims;
throttleReversed = src.throttleReversed;
checklistInteractive = src.checklistInteractive;
memcpy(&flightModeData[0], &src.flightModeData[0], sizeof(flightModeData[0]) * CPN_MAX_FLIGHT_MODES);
memcpy(&mixData[0], &src.mixData[0], sizeof(mixData[0]) * CPN_MAX_MIXERS);
memcpy(&limitData[0], &src.limitData[0], sizeof(limitData[0]) * CPN_MAX_CHNOUT);
memcpy(&inputNames, &src.inputNames, sizeof(inputNames));
memcpy(&expoData[0], &src.expoData[0], sizeof(expoData[0]) * CPN_MAX_EXPOS);
memcpy(&curves[0], &src.curves[0], sizeof(curves[0]) * CPN_MAX_CURVES);
memcpy(&logicalSw[0], &src.logicalSw[0], sizeof(logicalSw[0]) * CPN_MAX_LOGICAL_SWITCHES);
memcpy(&customFn[0], &src.customFn[0], sizeof(customFn[0]) * CPN_MAX_SPECIAL_FUNCTIONS);
swashRingData = src.swashRingData;
thrTraceSrc = src.thrTraceSrc;
switchWarningStates = src.switchWarningStates;
thrTrimSwitch = src.thrTrimSwitch;
potsWarningMode = src.potsWarningMode;
memcpy(&potsWarnEnabled[0], &src.potsWarnEnabled[0], sizeof(potsWarnEnabled[0]) * CPN_MAX_INPUTS);
memcpy(&potsWarnPosition[0], &src.potsWarnPosition[0], sizeof(potsWarnPosition[0]) * CPN_MAX_INPUTS);
displayChecklist = src.displayChecklist;
memcpy(&gvarData[0], &src.gvarData[0], sizeof(gvarData[0]) * CPN_MAX_GVARS);
mavlink = src.mavlink;
telemetryProtocol = src.telemetryProtocol;
frsky = src.frsky;
rssiSource = src.rssiSource;
rssiAlarms = src.rssiAlarms;
showInstanceIds = src.showInstanceIds;
memcpy(&bitmap, &src.bitmap, sizeof(bitmap));
trainerMode = src.trainerMode;
memcpy(&moduleData[0], &src.moduleData[0], sizeof(moduleData[0]) * (CPN_MAX_MODULES + 1));
memcpy(&scriptData[0], &src.scriptData[0], sizeof(scriptData[0]) * CPN_MAX_SCRIPTS);
memcpy(&sensorData[0], &src.sensorData[0], sizeof(sensorData[0]) * CPN_MAX_SENSORS);
toplcdTimer = src.toplcdTimer;
customScreens = src.customScreens;
topBarData = src.topBarData;
memcpy(&topbarWidgetWidth[0], &src.topbarWidgetWidth[0], sizeof(topbarWidgetWidth[0]) * MAX_TOPBAR_ZONES);
view = src.view;
memcpy(&registrationId, &src.registrationId, sizeof(registrationId));
hatsMode = src.hatsMode;
radioThemesDisabled = src.radioThemesDisabled;
radioGFDisabled = src.radioGFDisabled;
radioTrainerDisabled = src.radioTrainerDisabled;
modelHeliDisabled = src.modelHeliDisabled;
modelFMDisabled = src.modelFMDisabled;
modelCurvesDisabled = src.modelCurvesDisabled;
modelGVDisabled = src.modelGVDisabled;
modelLSDisabled = src.modelLSDisabled;
modelSFDisabled = src.modelSFDisabled;
modelCustomScriptsDisabled = src.modelCustomScriptsDisabled;
modelTelemetryDisabled = src.modelTelemetryDisabled;
memcpy(&customSwitches[0], &src.customSwitches[0], sizeof(customSwitches[0]) * CPN_MAX_SWITCHES_FUNCTION);
memcpy(&cfsGroupOn[0], &src.cfsGroupOn[0], sizeof(cfsGroupOn[0]) * CPN_MAX_CUSTOMSWITCH_GROUPS);
usbJoystickExtMode = src.usbJoystickExtMode;
usbJoystickIfMode = src.usbJoystickIfMode;
usbJoystickCircularCut = src.usbJoystickCircularCut;
memcpy(&usbJoystickCh[0], &src.usbJoystickCh[0], sizeof(usbJoystickCh[0]) * CPN_USBJ_MAX_JOYSTICK_CHANNELS);
checklistData = src.checklistData;
updRefList = nullptr;
memset(&updRefInfo, 0, sizeof(updRefInfo));
}
ExpoData * ModelData::insertInput(const int idx)
{
memmove(&expoData[idx + 1], &expoData[idx], (CPN_MAX_EXPOS - (idx + 1)) * sizeof(ExpoData));
@@ -145,48 +226,130 @@ void ModelData::clearMixes()
void ModelData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(ModelData));
// IMPORTANT: DO NOT USE
// memset(reinterpret_cast<void *>(this), 0, sizeof(ModelData));
// as struct contains complex data types eg std::string
memset(&semver, 0, sizeof(semver));
used = false;
memset(&name, 0, sizeof(name));
memset(&filename, 0, sizeof(filename));
memset(&labels, 0, sizeof(labels));
modelIndex = -1; // an invalid index, this is managed by the TreeView data model
moduleData[0].protocol = PULSES_OFF;
moduleData[1].protocol = PULSES_OFF;
moduleData[0].channelsCount = 8;
moduleData[1].channelsStart = 0;
moduleData[1].channelsCount = 8;
moduleData[0].ppm.delay = 300;
moduleData[1].ppm.delay = 300;
moduleData[2].ppm.delay = 300; //Trainer PPM
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
modelUpdated = false;
modelErrors = false;
noGlobalFunctions = false;
thrTrim = false;
trimInc = 0;
trimsDisplay = 0;
disableThrottleWarning = false;
enableCustomThrottleWarning = false;
customThrottleWarningPosition = 0;
jitterFilter = 0;
beepANACenter = 0;
extendedLimits = false;
extendedTrims = false;
throttleReversed = false;
checklistInteractive = false;
memset(&inputNames, 0, sizeof(inputNames));
thrTraceSrc = 0;
switchWarningStates = 0;
thrTrimSwitch = 0;
potsWarningMode = 0;
mavlink.clear();
telemetryProtocol = 0;
frsky.clear();
rssiSource = 0;
rssiAlarms.clear();
showInstanceIds = false;
memset(&bitmap, 0, sizeof(bitmap));
trainerMode = TRAINER_MODE_OFF;
for (int i = 0; i < CPN_MAX_INPUTS; i++)
potsWarnEnabled[i] = false;
for (int i = 0; i < CPN_MAX_INPUTS; i++)
potsWarnPosition[i] = 0;
displayChecklist = false;
for (int i = 0; i < CPN_MAX_MODULES + 1/*Trainer*/; i++) // + 1
moduleData[i].clear();
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++)
flightModeData[i].clear(i);
}
for (int i = 0; i < CPN_MAX_GVARS; i++) {
for (int i = 0; i < CPN_MAX_GVARS; i++)
gvarData[i].clear();
}
clearInputs();
clearMixes();
for (int i = 0; i < CPN_MAX_CHNOUT; i++)
limitData[i].clear();
for (int i = 0; i < CPN_MAX_STICKS; i++)
expoData[i].clear();
for (int i = 0; i < CPN_MAX_LOGICAL_SWITCHES; i++)
logicalSw[i].clear();
for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++)
customFn[i].clear();
for (int i = 0; i < CPN_MAX_CURVES; i++)
curves[i].clear();
for (int i = 0; i < CPN_MAX_TIMERS; i++)
timers[i].clear();
swashRingData.clear();
frsky.clear();
rssiAlarms.clear();
for (unsigned i = 0; i < CPN_MAX_SENSORS; i++)
sensorData[i].clear();
trainerMode = TRAINER_MODE_OFF;
toplcdTimer = 0;
RadioLayout::init("Layout2P1", customScreens);
topBarData.clear();
const char * layoutId = "Layout2P1"; // currently all using same default though might change for NV14
RadioLayout::init(layoutId, customScreens);
for (int i = 0; i < MAX_TOPBAR_ZONES; i++)
topbarWidgetWidth[i] = 0;
view = 0;
memset(&registrationId, 0, sizeof(registrationId));
hatsMode = GeneralSettings::HATSMODE_GLOBAL;
radioThemesDisabled = 0;
radioGFDisabled = 0;
radioTrainerDisabled = 0;
modelHeliDisabled = 0;
modelFMDisabled = 0;
modelCurvesDisabled = 0;
modelGVDisabled = 0;
modelLSDisabled = 0;
modelSFDisabled = 0;
modelCustomScriptsDisabled = 0;
modelTelemetryDisabled = 0;
for (int i = 0; i < CPN_MAX_SWITCHES_FUNCTION; i++)
customSwitches[i].clear();
for (int i = 0; i < CPN_MAX_CUSTOMSWITCH_GROUPS; i++)
cfsGroupOn[i] = 0;
usbJoystickExtMode = 0;
usbJoystickIfMode = 0;
usbJoystickCircularCut = 0;
for (int i = 0; i < CPN_USBJ_MAX_JOYSTICK_CHANNELS; i++)
usbJoystickCh[i].clear();
checklistData.clear();
if (updRefList)
delete updRefList;
updRefList = nullptr;
memset(&updRefInfo, 0, sizeof(updRefInfo));
}
bool ModelData::isEmpty() const
@@ -242,6 +405,7 @@ void ModelData::setDefaultFunctionSwitches(int functionSwitchCount)
customSwitches[i].onColor.setColor(255, 255, 255);
customSwitches[i].offColor.setColor(0, 0, 0);
}
cfsGroupOn[1] = 1;
}
@@ -249,7 +413,7 @@ void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settin
{
clear();
used = true;
sprintf(name, "MODEL%02d", id+1);
sprintf(name, "MODEL%02d", id + 1);
for (int i = 0; i < CPN_MAX_MODULES; i++) {
moduleData[i].modelId = id + 1;
}
+10 -7
View File
@@ -105,9 +105,11 @@ class USBJoystickChData {
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(USBJoystickChData)); }
};
class customSwitch {
#define CPN_MAX_CUSTOMSWITCH_GROUPS 4
class CustomSwitchData {
public:
customSwitch() { clear(); }
CustomSwitchData() { clear(); }
Board::SwitchType type;
unsigned int group;
unsigned int start;
@@ -117,7 +119,7 @@ class customSwitch {
unsigned int offColorLuaOverride;
RGBLedColor onColor;
RGBLedColor offColor;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(customSwitch)); }
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(CustomSwitchData)); }
};
class ModelData {
@@ -181,7 +183,7 @@ class ModelData {
char bitmap[CPN_MAX_BITMAP_LEN + 1];
unsigned int trainerMode; // TrainerMode
unsigned int trainerMode;
ModuleData moduleData[CPN_MAX_MODULES + 1/*trainer*/];
@@ -222,8 +224,8 @@ class ModelData {
};
// Function switches
customSwitch customSwitches[CPN_MAX_SWITCHES_FUNCTION];
unsigned int cfsGroupOn[4];
CustomSwitchData customSwitches[CPN_MAX_SWITCHES_FUNCTION];
unsigned int cfsGroupOn[CPN_MAX_CUSTOMSWITCH_GROUPS];
// Custom USB joytsick mapping
unsigned int usbJoystickExtMode;
@@ -233,7 +235,7 @@ class ModelData {
QByteArray checklistData;
ModelData & operator = (const ModelData & src);
ModelData & operator=(const ModelData & src);
void convert(RadioDataConversionState & cstate);
@@ -248,6 +250,7 @@ class ModelData {
QVector<const MixData *> mixes(int channel) const;
void clear();
void copy(const ModelData & src);
bool isEmpty() const;
void setDefaultInputs(const GeneralSettings & settings);
void setDefaultMixes(const GeneralSettings & settings);
+8
View File
@@ -65,6 +65,14 @@ void ModuleData::convert(RadioDataConversionState & cstate)
}
}
void ModuleData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(ModuleData));
protocol = PULSES_OFF;
channelsCount = 8;
ppm.delay = 300;
}
// moved from OpenTxFirmware EdgeTX v2.9
// only called by ModuleData::convert
// TODO: merge with ModuleData::isProtocolAvailable as share much of the same logic
+1 -1
View File
@@ -215,7 +215,7 @@ class ModuleData {
unsigned int flags;
} dsmp;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ModuleData)); }
void clear();
void convert(RadioDataConversionState & cstate);
bool isPxx2Module() const;
bool supportRxNum() const;
+50 -16
View File
@@ -20,6 +20,7 @@
*/
#include "modelslist.h"
#include "edgetxinterface.h"
ModelListItem::ModelListItem(const QVector<QVariant> & itemData):
itemData(itemData),
@@ -460,10 +461,28 @@ bool ModelsListModel::hasOwnMimeData(const QMimeData * mimeData) const
void ModelsListModel::encodeModelsData(const QModelIndexList & indexes, QByteArray * data) const
{
int mdlCnt = 0;
foreach (const QModelIndex &index, indexes) {
if (index.isValid() && index.column() == 0)
mdlCnt++;
}
if (mdlCnt < 1)
return;
QDataStream out(data, QIODevice::WriteOnly);
Board::Type board = getCurrentBoard();
out << board;
out << mdlCnt;
foreach (const QModelIndex &index, indexes) {
if (index.isValid() && index.column() == 0) {
data->append('M');
data->append((char *)&radioData->models[getModelIndex(index)], sizeof(ModelData));
ModelData &modelData = radioData->models[getModelIndex(index)];
QByteArray yaml;
if (writeModelToYaml(modelData, yaml))
out << yaml << modelData.checklistData.data();
}
}
}
@@ -520,18 +539,29 @@ bool ModelsListModel::decodeMimeData(const QMimeData * mimeData, QVector<ModelDa
*hasGenSet = false;
if (models && mimeData->hasFormat("application/x-companion-modeldata")) {
QByteArray mdlData = mimeData->data("application/x-companion-modeldata");
gData = mdlData.data();
int size = 0;
while (size < mdlData.size()) {
char c = *gData++;
if (c != 'M')
break;
ModelData model(*((ModelData *)gData));
models->append(model);
gData += sizeof(ModelData);
size += sizeof(ModelData) + 1;
ret = true;
QByteArray data = mimeData->data("application/x-companion-modeldata");
QDataStream in(&data, QIODevice::ReadOnly);
Board::Type board;
int mdlCnt;
in >> board >> mdlCnt;
for (int i = 1; i <= mdlCnt; i++) {
QByteArray buffer;
in >> buffer;
if (buffer.size() > 0) {
ModelData model;
if (loadModelFromYaml(model, buffer)) {
model.used = true;
QByteArray chklst;
in >> chklst;
model.checklistData = chklst;
models->append(model);
ret = true;
}
}
}
}
@@ -555,10 +585,14 @@ bool ModelsListModel::decodeMimeData(const QMimeData * mimeData, QVector<ModelDa
int ModelsListModel::countModelsInMimeData(const QMimeData * mimeData)
{
int ret = 0;
if (mimeData->hasFormat("application/x-companion-modeldata")) {
QByteArray mdlData = mimeData->data("application/x-companion-modeldata");
ret = mdlData.size() / (sizeof(ModelData) + 1);
QByteArray data = mimeData->data("application/x-companion-modeldata");
QDataStream in(&data, QIODevice::ReadOnly);
Board::Type board;
in >> board >> ret;
}
return ret;
}