WiP: start parsing YaML
This commit is contained in:
@@ -5,3 +5,6 @@
|
||||
[submodule "radio/src/thirdparty/AccessDenied"]
|
||||
path = radio/src/thirdparty/AccessDenied
|
||||
url = https://github.com/raphaelcoeffic/AccessDenied.git
|
||||
[submodule "companion/src/thirdparty/yaml-cpp"]
|
||||
path = companion/src/thirdparty/yaml-cpp
|
||||
url = https://github.com/jbeder/yaml-cpp.git
|
||||
|
||||
@@ -197,6 +197,7 @@ add_subdirectory(simulation)
|
||||
add_subdirectory(storage)
|
||||
add_subdirectory(thirdparty/qcustomplot)
|
||||
add_subdirectory(thirdparty/maxlibqt/src/widgets)
|
||||
add_subdirectory(thirdparty/yaml-cpp)
|
||||
|
||||
############# Companion ###############
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ set(firmwares_SRCS
|
||||
ersky9x/ersky9xinterface.cpp
|
||||
opentx/opentxeeprom.cpp
|
||||
opentx/opentxinterface.cpp
|
||||
edgetx/edgetxinterface.cpp
|
||||
datahelpers.cpp
|
||||
customisation_data.cpp
|
||||
)
|
||||
@@ -48,14 +49,19 @@ set(firmwares_QT
|
||||
qt5_wrap_cpp(firmwares_SRCS ${firmwares_QT})
|
||||
|
||||
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
|
||||
|
||||
target_link_libraries(firmwares ${CPN_COMMON_LIB} datamodels Qt5::Core Qt5::Xml Qt5::Widgets)
|
||||
target_link_libraries(firmwares yaml-cpp)
|
||||
|
||||
target_include_directories(firmwares
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/yaml-cpp/include
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/er9x"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ersky9x"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/opentx"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/edgetx"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "edgetxinterface.h"
|
||||
|
||||
#include "yaml_ops.h"
|
||||
#include "yaml_generalsettings.h"
|
||||
|
||||
static YAML::Node loadYamlFromByteArray(const QByteArray& data)
|
||||
{
|
||||
// TODO: use real streaming to avoid memory copies
|
||||
std::istringstream data_istream(data.toStdString());
|
||||
return YAML::Load(data_istream);
|
||||
}
|
||||
|
||||
bool loadModelFromYaml(ModelData& model, const QByteArray& data)
|
||||
{
|
||||
try {
|
||||
YAML::Node node = loadYamlFromByteArray(data);
|
||||
//model << node;
|
||||
} catch (const std::runtime_error& e) {
|
||||
qDebug() << "YAML::ParserException: " << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadRadioSettingsFromYaml(GeneralSettings& settings, const QByteArray& data)
|
||||
{
|
||||
try {
|
||||
YAML::Node node = loadYamlFromByteArray(data);
|
||||
node >> settings;
|
||||
} catch (const std::runtime_error& e) {
|
||||
qDebug() << "YAML::ParserException: " << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeModelToYaml(const ModelData& model, QByteArray& data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool writeRadioSettingsToYaml(const GeneralSettings& settings, QByteArray& data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "radiodata.h"
|
||||
#include <QByteArray>
|
||||
|
||||
bool loadModelFromYaml(ModelData& model, const QByteArray& data);
|
||||
bool loadRadioSettingsFromYaml(GeneralSettings& settings, const QByteArray& data);
|
||||
|
||||
bool writeModelToByteArray(const ModelData& model, QByteArray& data);
|
||||
bool writeRadioSettingsToByteArray(const GeneralSettings& settings, QByteArray& data);
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "yaml_ops.h"
|
||||
#include "generalsettings.h"
|
||||
#include "yaml_trainerdata.h"
|
||||
|
||||
namespace YAML {
|
||||
|
||||
template<>
|
||||
struct convert<GeneralSettings> {
|
||||
|
||||
// static YAML::Node encode(const GeneralSettings& rhs) {
|
||||
// Node node;
|
||||
// // TODO: convert struct into Node
|
||||
// return node;
|
||||
// }
|
||||
|
||||
static bool decode(const YAML::Node& node, GeneralSettings& rhs) {
|
||||
|
||||
node["version"] >> rhs.version;
|
||||
node["versionBla"] >> rhs.version;
|
||||
// // calib
|
||||
node["currModel"] >> rhs.currModelIndex;
|
||||
// // filename
|
||||
node["contrast"] >> rhs.contrast;
|
||||
node["vBatWarn"] >> rhs.vBatWarn;
|
||||
node["txVoltageCalibration"] >> rhs.txVoltageCalibration;
|
||||
node["vBatMin"] >> rhs.vBatMin;
|
||||
node["vBatMax"] >> rhs.vBatMax;
|
||||
|
||||
// TODO: lookup table
|
||||
//rhs.backlightMode = node["backlightMode"].as<std::string>(); // backlight_mode_all
|
||||
|
||||
node["trainer"] >> rhs.trainer;
|
||||
node["view"] >> rhs.view;
|
||||
node["fai"] >> rhs.fai;
|
||||
node["disableMemoryWarning"] >> rhs.disableMemoryWarning;
|
||||
//node["beepMode"] >> rhs.beeperMode; // TODO: string mapping
|
||||
node["disableAlarmWarning"] >> rhs.disableAlarmWarning;
|
||||
node["disableRssiPoweroffAlarm"] >> rhs.disableRssiPoweroffAlarm;
|
||||
node["USBMode"] >> rhs.usbMode;
|
||||
node["jackMode"] >> rhs.jackMode;
|
||||
//node["hapticMode"] >> rhs.hapticMode; // TODO: strin mapping
|
||||
node["stickMode"] >> rhs.stickMode;
|
||||
node["timezone"] >> rhs.timezone;
|
||||
node["adjustRTC"] >> rhs.adjustRTC;
|
||||
node["inactivityTimer"] >> rhs.inactivityTimer;
|
||||
node["telemetryBaudrate"] >> rhs.telemetryBaudrate; // TODO: conversion???
|
||||
node["splashMode"] >> rhs.splashMode; // TODO: B&W only
|
||||
node["templateSetup"] >> rhs.templateSetup;
|
||||
node["hapticLength"] >> rhs.hapticLength; // TODO: conversion???
|
||||
node["speakerPitch"] >> rhs.speakerPitch; // TODO: conversion???
|
||||
node["hapticStrength"] >> rhs.hapticStrength; // TODO: conversion???
|
||||
node["beepLength"] >> rhs.beeperLength; // TODO: conversion???
|
||||
node["gpsFormat"] >> rhs.gpsFormat;
|
||||
node["speakerVolume"] >> rhs.speakerVolume; // TODO: conversion???
|
||||
node["backlightBright"] >> rhs.backlightBright;
|
||||
node["switchesDelay"] >> rhs.switchesDelay;
|
||||
node["globalTimer"] >> rhs.globalTimer;
|
||||
node["bluetoothName"] >> rhs.bluetoothName;
|
||||
node["bluetoothBaudrate"] >> rhs.bluetoothBaudrate;
|
||||
node["bluetoothMode"] >> rhs.bluetoothMode;
|
||||
node["countryCode"] >> rhs.countryCode;
|
||||
node["jitterFilter"] >> rhs.jitterFilter;
|
||||
node["disableRtcWarning"] >> rhs.rtcCheckDisable; // TODO: verify
|
||||
node["keysBacklight"] >> rhs.keysBacklight;
|
||||
node["imperial"] >> rhs.imperial;
|
||||
node["ttsLanguage"] >> rhs.ttsLanguage;
|
||||
node["beepVolume"] >> rhs.beepVolume; // TODO: conversion???
|
||||
node["wavVolume"] >> rhs.wavVolume;
|
||||
node["varioVolume"] >> rhs.varioVolume;
|
||||
node["varioPitch"] >> rhs.varioPitch;
|
||||
node["varioRange"] >> rhs.varioRange;
|
||||
node["varioRepeat"] >> rhs.varioRepeat;
|
||||
node["backgroundVolume"] >> rhs.backgroundVolume;
|
||||
//node["auxSerialMode"] >> rhs.auxSerialMode;
|
||||
//node["aux2SerialMode"] >> rhs.aux2SerialMode;
|
||||
//node["antennaMode"] >> rhs.antennaMode;
|
||||
node["backlightColor"] >> rhs.backlightColor;
|
||||
|
||||
// if (node["customFn"]) {
|
||||
// const YAML::Node& cfn = node["customFn"];
|
||||
// for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) {
|
||||
// cfn[i] >> rhs.customFn[i];
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO:
|
||||
// char switchName[CPN_MAX_SWITCHES][HARDWARE_NAME_LEN + 1];
|
||||
// unsigned int switchConfig[CPN_MAX_SWITCHES];
|
||||
// char stickName[CPN_MAX_STICKS][HARDWARE_NAME_LEN + 1];
|
||||
// char potName[CPN_MAX_KNOBS][HARDWARE_NAME_LEN + 1];
|
||||
// unsigned int potConfig[CPN_MAX_KNOBS];
|
||||
// char sliderName[CPN_MAX_SLIDERS][HARDWARE_NAME_LEN + 1];
|
||||
// unsigned int sliderConfig[CPN_MAX_SLIDERS];
|
||||
// RadioTheme::ThemeData themeData;
|
||||
|
||||
node["ownerRegistrationID"] >> rhs.registrationId;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 <yaml-cpp/yaml.h>
|
||||
|
||||
template <typename T>
|
||||
void operator>>(const YAML::Node& node, T& value)
|
||||
{
|
||||
if (node) {
|
||||
value = node.as<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void operator>>(const YAML::Node& node, char (&value)[N])
|
||||
{
|
||||
if (node) {
|
||||
auto str = node.as<std::string>();
|
||||
str.copy(value, N-1);
|
||||
value[std::min(str.size(), N-1)] = '\0';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "yaml_ops.h"
|
||||
#include "generalsettings.h"
|
||||
|
||||
namespace YAML {
|
||||
|
||||
template<>
|
||||
struct convert<TrainerMix> {
|
||||
|
||||
// static YAML::Node encode(const TrainerMix& rhs) {
|
||||
// Node node;
|
||||
// // TODO: convert struct into Node
|
||||
// return node;
|
||||
// }
|
||||
|
||||
static bool decode(const YAML::Node& node, TrainerMix& rhs)
|
||||
{
|
||||
node["srcChn"] >> rhs.src;
|
||||
//node["mode"] >> rhs.mode; // TODO: string mapping
|
||||
node["studWeight"] >> rhs.weight;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<TrainerData> {
|
||||
|
||||
// static YAML::Node encode(const TrainerData& rhs) {
|
||||
// Node node;
|
||||
// // TODO: convert struct into Node
|
||||
// return node;
|
||||
// }
|
||||
|
||||
static bool decode(const YAML::Node& node, TrainerData& rhs)
|
||||
{
|
||||
if (node["calib"]) {
|
||||
const YAML::Node& calib = node["calib"];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
calib[i] >> rhs.calib[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (node["mix"]) {
|
||||
const YAML::Node& mix = node["mix"];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mix[i] >> rhs.mix[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "categorized.h"
|
||||
#include "firmwares/opentx/opentxinterface.h"
|
||||
#include "firmwares/edgetx/edgetxinterface.h"
|
||||
#include "miniz.c" // Can only be included once!
|
||||
|
||||
bool CategorizedStorageFormat::load(RadioData & radioData)
|
||||
@@ -217,8 +218,8 @@ bool CategorizedStorageFormat::loadYaml(RadioData & radioData)
|
||||
qDebug() << tr("Found %1").arg(filename);
|
||||
}
|
||||
|
||||
setError(tr("Error: Yaml format ignored - under development"));
|
||||
return false; // force failure until fully developed
|
||||
// setError(tr("Error: Yaml format ignored - under development"));
|
||||
// return false; // force failure until fully developed
|
||||
|
||||
/*
|
||||
This code a copy of loadBin with yaml file extensions ONLY
|
||||
@@ -229,88 +230,15 @@ bool CategorizedStorageFormat::loadYaml(RadioData & radioData)
|
||||
setError(tr("Can't extract RADIO/radio.yml"));
|
||||
return false;
|
||||
}
|
||||
|
||||
OpenTxEepromInterface * loadInterface = loadRadioSettingsFromByteArray(radioData.generalSettings, radioSettingsBuffer);
|
||||
if (!loadInterface) {
|
||||
|
||||
if (!loadRadioSettingsFromYaml(radioData.generalSettings, radioSettingsBuffer)) {
|
||||
setError(tr("Can't load RADIO/radio.yml"));
|
||||
return false;
|
||||
}
|
||||
|
||||
board = loadInterface->getBoard();
|
||||
// TODO: provide a simple text mapping
|
||||
board = Board::BOARD_RADIOMASTER_TX16S;
|
||||
|
||||
QByteArray modelsListBuffer;
|
||||
if (!loadFile(modelsListBuffer, "MODELS/models.yml")) {
|
||||
setError(tr("Can't extract MODELS/models.yml"));
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QByteArray> lines = modelsListBuffer.split('\n');
|
||||
int modelIndex = 0;
|
||||
int categoryIndex = -1;
|
||||
foreach (const QByteArray & lineArray, lines) {
|
||||
QString line = QString(lineArray).trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
// qDebug() << "parsing line" << line;
|
||||
|
||||
if (line.startsWith('[') && line.endsWith(']')) {
|
||||
// ignore categories for boards that do not support them
|
||||
if (getCurrentFirmware()->getCapability(HasModelCategories)) {
|
||||
QString name = line.mid(1, line.size() - 2);
|
||||
CategoryData category(qPrintable(name));
|
||||
radioData.categories.push_back(category);
|
||||
categoryIndex++;
|
||||
qDebug() << "added category" << name;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine if we have a model number
|
||||
QStringList parts = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
|
||||
if (parts.size() == 2) {
|
||||
// parse model number
|
||||
int modelNumber = parts[0].toInt();
|
||||
if (modelNumber > 0 && modelNumber > modelIndex && modelNumber < getCurrentFirmware()->getCapability(Models)) {
|
||||
modelIndex = modelNumber;
|
||||
qDebug() << "advanced model number to" << modelIndex;
|
||||
}
|
||||
else {
|
||||
if (modelNumber != modelIndex) qDebug() << "Invalid model number" << parts[0];
|
||||
}
|
||||
parts.removeFirst();
|
||||
}
|
||||
if (parts.size() == 1) {
|
||||
// parse model file name and load
|
||||
QString fileName = parts[0];
|
||||
qDebug() << "Loading model from file" << fileName << "into slot" << modelIndex;
|
||||
QByteArray modelBuffer;
|
||||
if (!loadFile(modelBuffer, QString("MODELS/%1").arg(fileName))) {
|
||||
setError(tr("Can't extract %1").arg(fileName));
|
||||
return false;
|
||||
}
|
||||
if ((int)radioData.models.size() <= modelIndex) {
|
||||
radioData.models.resize(modelIndex + 1);
|
||||
}
|
||||
if (!loadModelFromByteArray(radioData.models[modelIndex], modelBuffer)) {
|
||||
setError(tr("Error loading models"));
|
||||
return false;
|
||||
}
|
||||
strncpy(radioData.models[modelIndex].filename, qPrintable(fileName), sizeof(radioData.models[modelIndex].filename));
|
||||
if (IS_FAMILY_HORUS_OR_T16(board) && !strcmp(radioData.generalSettings.currModelFilename, qPrintable(fileName))) {
|
||||
radioData.generalSettings.currModelIndex = modelIndex;
|
||||
qDebug() << "currModelIndex =" << modelIndex;
|
||||
}
|
||||
if (getCurrentFirmware()->getCapability(HasModelCategories)) {
|
||||
radioData.models[modelIndex].category = categoryIndex;
|
||||
}
|
||||
radioData.models[modelIndex].used = true;
|
||||
modelIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// invalid line
|
||||
// TODO add to parsing report
|
||||
qDebug() << "Invalid line" <<line;
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -318,63 +246,4 @@ bool CategorizedStorageFormat::writeYaml(const RadioData & radioData)
|
||||
{
|
||||
setError("Error: Yaml format ignored - under development");
|
||||
return false; // force failure until fully developed
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This is a copy of writeBin with changed file yml extensions ONLY
|
||||
|
||||
*/
|
||||
|
||||
QByteArray modelsList; // models.txt
|
||||
QByteArray radioSettingsData; // radio.bin
|
||||
size_t numModels = radioData.models.size();
|
||||
size_t numCategories = radioData.categories.size();
|
||||
std::vector<std::vector<QString>> sortedModels(numCategories);
|
||||
|
||||
writeRadioSettingsToByteArray(radioData.generalSettings, radioSettingsData);
|
||||
if (!writeFile(radioSettingsData, "RADIO/radio.yml")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t m=0; m<numModels; m++) {
|
||||
const ModelData & model = radioData.models[m];
|
||||
if (model.isEmpty()) continue;
|
||||
|
||||
QString modelFilename = QString("MODELS/%1").arg(model.filename);
|
||||
QByteArray modelData;
|
||||
writeModelToByteArray(model, modelData);
|
||||
if (!writeFile(modelData, modelFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For firmware that doesn't support categories, we can just construct
|
||||
// models.txt as we iterate thru the models vector. For firmware that does
|
||||
// support categories, we have a bit of work to do in order to sort the
|
||||
// models first by category index, so we use the sortedModels data
|
||||
// structure to do that.
|
||||
if (!getCurrentFirmware()->getCapability(HasModelCategories)) {
|
||||
// Use format with model number and file name. This is needed because
|
||||
// radios without category support can have unused model slots
|
||||
modelsList.append(QString("%1 %2\n").arg(m).arg(model.filename));
|
||||
} else {
|
||||
sortedModels[model.category].push_back(QString("%1\n").arg(model.filename));
|
||||
}
|
||||
}
|
||||
|
||||
if (getCurrentFirmware()->getCapability(HasModelCategories)) {
|
||||
for (size_t c=0; c<numCategories; c++) {
|
||||
modelsList.append(QString().sprintf("[%s]\n", radioData.categories[c].name));
|
||||
numModels = sortedModels[c].size();
|
||||
for (size_t m=0; m<numModels; m++) {
|
||||
modelsList.append(sortedModels[c][m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!writeFile(modelsList, "MODELS/models.yml")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
Submodule companion/src/thirdparty/yaml-cpp added at 9a3624205e
Reference in New Issue
Block a user