feat(color): New label based Model Selector (#1374)
* Model Labels Selector * Portrait Layout * Receiver ID Check * Fix Labels .yml format * Companion Initial Commit commit 967ddf3979b4954402fe62c858faba4b7a416bba Author: dlktdr <cblackburn320@gmail.com> Date: Mon Aug 29 01:49:15 2022 -0700 Fix Labels .yml format commit 534221cad9e01146c47a9ac1080a655e04f1f6c8 Author: dlktdr <cblackburn320@gmail.com> Date: Mon Aug 29 01:20:57 2022 -0700 Receiver ID Check commit f32c0939d44e9ae60bc0705a9176354c23fec198 Author: dlktdr <cblackburn320@gmail.com> Date: Sun Aug 28 23:13:25 2022 -0700 Portrait Layout commit 961181217c7841ff3f21299ac6aa419b810f80e9 Author: dlktdr <cblackburn320@gmail.com> Date: Sat Dec 11 16:56:13 2021 -0800 Model Labels Selector commitdc99dd40d2Author: David PHAM-VAN <1387855+DavBfr@users.noreply.github.com> Date: Fri Aug 26 03:04:34 2022 -0300 feat: Allow Lua widget to override built-in widget with same name (#2208) * Allow CPP Widgets Override with LUA * Reset a widget option it the type differs commit4b747caff9Author: eshifri <46511024+eshifri@users.noreply.github.com> Date: Thu Aug 25 19:47:53 2022 -0700 fix: Write model name into models.yml when duplicating model (#2224) * Update model name in the models.yml file (#2214) * Fix the length of the name. commite97f23a305Author: eshifri <46511024+eshifri@users.noreply.github.com> Date: Wed Aug 24 21:19:52 2022 -0700 fix(cpn): Fix full path to model notes for Simulator (#2223) * Correct Highlighted Column * labels .yml indentation * Update da.h New defines translated to Danish * Update dataconstants.h Omit warnings due to difference of LEN_MODEL_FILENAME and LEN_MODEL_NAME in modellist.cpp * Update modelslist.cpp Wonder if this are the right file in PR #1374 (?), seems a lot are changed to the better in #1374 * Update dataconstants.h Restore #define for LEN_MODEL_FILENAME to 16 * Rebase, Correct Issues Delete now deletes instead of select New model stores correct information Duplicate save all information in cell Rework items to use cell over button Reword function variables * CMPN: Add context menu Fix output not functional. Removed Yaml::null at some point :) Fix some compiler warnings * CMPN: Compiler warning, replace ,->_ in list * FW: Various Changes Change view to a grid Don't allow comma in label name Add scroll indicators Save sort order Co-authored-by: HThuren <99370924+HThuren@users.noreply.github.com>
This commit is contained in:
@@ -105,56 +105,37 @@ void convertBinRadioData(const char * path, int version)
|
||||
#endif
|
||||
|
||||
const char* error = nullptr;
|
||||
for (auto category_ptr : modelslist.getCategories()) {
|
||||
for(auto model_it = modelslist.begin(); model_it != modelslist.end(); ++model_it) {
|
||||
uint8_t model_version = 0;
|
||||
auto* model_ptr = *model_it;
|
||||
char* filename = model_ptr->modelFilename;
|
||||
|
||||
auto model_it = category_ptr->begin();
|
||||
TRACE("converting '%s' (%d/%d)", filename, converted, to_convert);
|
||||
drawProgressScreen(filename, converted, to_convert);
|
||||
|
||||
while(model_it != category_ptr->end()) {
|
||||
// read only the version number (size=0)
|
||||
error = readModelBin(filename, nullptr, 0, &model_version);
|
||||
if (!error) {
|
||||
// TODO: error handling
|
||||
error = convertBinModelData(filename, model_version);
|
||||
|
||||
uint8_t model_version = 0;
|
||||
auto* model_ptr = *model_it;
|
||||
char* filename = model_ptr->modelFilename;
|
||||
|
||||
TRACE("converting '%s' (%d/%d)", filename, converted, to_convert);
|
||||
drawProgressScreen(filename, converted, to_convert);
|
||||
|
||||
// read only the version number (size=0)
|
||||
error = readModelBin(filename, nullptr, 0, &model_version);
|
||||
if (!error) {
|
||||
// TODO: error handling
|
||||
error = convertBinModelData(filename, model_version);
|
||||
++model_it;
|
||||
|
||||
if (error) {
|
||||
TRACE("ERROR converting '%s': %s", filename, error);
|
||||
category_ptr->removeModel(model_ptr);
|
||||
} else {
|
||||
PartialModel partial;
|
||||
memclear(&partial, sizeof(PartialModel));
|
||||
|
||||
readModelYaml(filename, reinterpret_cast<uint8_t*>(&partial), sizeof(partial));
|
||||
model_ptr->setModelName(partial.header.name);
|
||||
}
|
||||
} else {
|
||||
TRACE("ERROR reading '%s': %s", filename, error);
|
||||
|
||||
// remove that file from the models list
|
||||
++model_it;
|
||||
category_ptr->removeModel(model_ptr);
|
||||
if (error) {
|
||||
TRACE("ERROR converting '%s': %s", filename, error);
|
||||
}
|
||||
} else {
|
||||
TRACE("ERROR reading '%s': %s", filename, error);
|
||||
}
|
||||
|
||||
converted++;
|
||||
converted++;
|
||||
|
||||
#if defined(SIMU)
|
||||
RTOS_WAIT_MS(200);
|
||||
RTOS_WAIT_MS(200);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SDCARD_YAML) || defined(STORAGE_MODELSLIST)
|
||||
modelslist.save();
|
||||
// trigger models list reload
|
||||
modelslist.clear();
|
||||
modelslist.load();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -179,7 +160,7 @@ const char* convertBinModelData(char* filename, int version)
|
||||
memcpy(path, MODELS_PATH, sizeof(MODELS_PATH)-1);
|
||||
path[sizeof(MODELS_PATH)-1] = '/';
|
||||
strcpy(&path[sizeof(MODELS_PATH)], filename);
|
||||
|
||||
|
||||
#if STORAGE_CONVERSIONS < 220
|
||||
if (version == 219) {
|
||||
const char* error = convertModelData_219_to_220(path);
|
||||
@@ -206,7 +187,7 @@ const char* convertBinModelData(char* filename, int version)
|
||||
void eeConvertModel(int id, int version)
|
||||
{
|
||||
TRACE("eeConvertModel(%d,%d)", id, version);
|
||||
|
||||
|
||||
#if STORAGE_CONVERSIONS < 220
|
||||
if (version == 219) {
|
||||
convertModelData_219_to_220(id);
|
||||
@@ -269,7 +250,7 @@ bool eeConvert(uint8_t start_version)
|
||||
#if defined(STORAGE_MODELSLIST)
|
||||
modelslist.clear();
|
||||
#endif
|
||||
|
||||
|
||||
#if LCD_W >= 212
|
||||
lcdDrawRect(60, 6*FH+4, 132, 3);
|
||||
#else
|
||||
|
||||
+1118
-380
File diff suppressed because it is too large
Load Diff
+172
-88
@@ -23,86 +23,189 @@
|
||||
#define _MODELSLIST_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "sdcard.h"
|
||||
|
||||
#if !defined(SDCARD_YAML)
|
||||
#include "sdcard_raw.h"
|
||||
#endif
|
||||
|
||||
#include "dataconstants.h"
|
||||
|
||||
// #define MODELCELL_WIDTH 172
|
||||
// #define MODELCELL_HEIGHT 59
|
||||
#include "rtc.h"
|
||||
|
||||
// modelXXXXXXX.bin F,FF F,3F,FF\r\n
|
||||
#define LEN_MODELS_IDX_LINE (LEN_MODEL_FILENAME + sizeof(" F,FF F,3F,FF\r\n")-1)
|
||||
#define LEN_MODELS_IDX_LINE \
|
||||
(LEN_MODEL_FILENAME + sizeof(" F,FF F,3F,FF\r\n") - 1)
|
||||
|
||||
#define DEFAULT_MODEL_SORT NAME_ASC
|
||||
|
||||
struct ModelData;
|
||||
struct ModuleData;
|
||||
|
||||
struct SimpleModuleData
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t subType;
|
||||
struct SimpleModuleData {
|
||||
uint8_t type = 0;
|
||||
uint8_t subType = 0;
|
||||
};
|
||||
|
||||
typedef struct PACKED {
|
||||
FSIZE_t fsize; /* File size */
|
||||
WORD fdate; /* Modified date */
|
||||
WORD ftime; /* Modified time */
|
||||
} FInfoH;
|
||||
|
||||
#define FILE_HASH_LENGTH (sizeof(FInfoH) * 2) // Hex string output
|
||||
|
||||
class ModelCell
|
||||
{
|
||||
public:
|
||||
char modelFilename[LEN_MODEL_FILENAME + 1];
|
||||
char modelName[LEN_MODEL_NAME + 1] = {};
|
||||
public:
|
||||
char modelFilename[LEN_MODEL_FILENAME + 1] = "";
|
||||
char modelName[LEN_MODEL_NAME + 1] = "";
|
||||
char modelFinfoHash[FILE_HASH_LENGTH + 1] = "";
|
||||
#if LEN_BITMAP_NAME > 0
|
||||
char modelBitmap[LEN_BITMAP_NAME] = "";
|
||||
#endif
|
||||
gtime_t lastOpened = 0;
|
||||
bool _isDirty = true;
|
||||
|
||||
bool valid_rfData;
|
||||
uint8_t modelId[NUM_MODULES];
|
||||
SimpleModuleData moduleData[NUM_MODULES];
|
||||
bool valid_rfData;
|
||||
uint8_t modelId[NUM_MODULES] = {0, 0};
|
||||
SimpleModuleData moduleData[NUM_MODULES];
|
||||
|
||||
explicit ModelCell(const char * name);
|
||||
explicit ModelCell(const char * name, uint8_t len);
|
||||
~ModelCell();
|
||||
explicit ModelCell(const char *fileName);
|
||||
explicit ModelCell(const char *fileName, uint8_t len);
|
||||
|
||||
void save(FIL * file);
|
||||
void setModelName(char *name);
|
||||
void setModelName(char *name, uint8_t len);
|
||||
void setRfData(ModelData *model);
|
||||
|
||||
void setModelName(char * name);
|
||||
void setModelName(char* name, uint8_t len);
|
||||
void setRfData(ModelData * model);
|
||||
|
||||
void setModelId(uint8_t moduleIdx, uint8_t id);
|
||||
void setRfModuleData(uint8_t moduleIdx, ModuleData* modData);
|
||||
|
||||
bool fetchRfData();
|
||||
void setModelId(uint8_t moduleIdx, uint8_t id);
|
||||
void setRfModuleData(uint8_t moduleIdx, ModuleData *modData);
|
||||
bool fetchRfData();
|
||||
};
|
||||
|
||||
class ModelsCategory: public std::list<ModelCell *>
|
||||
typedef struct {
|
||||
std::string icon;
|
||||
// Anything else?
|
||||
} SLabelDetail;
|
||||
|
||||
typedef std::vector<std::pair<uint16_t, ModelCell *>> ModelLabelsVector;
|
||||
typedef std::vector<std::string> LabelsVector;
|
||||
typedef std::vector<ModelCell *> ModelsVector;
|
||||
typedef enum {
|
||||
NO_SORT,
|
||||
NAME_ASC,
|
||||
NAME_DES,
|
||||
DATE_ASC,
|
||||
DATE_DES,
|
||||
SORT_COUNT
|
||||
} ModelsSortBy;
|
||||
|
||||
/**
|
||||
* @brief ModelMap is a multimap of all models and their cooresponding
|
||||
* labels. Lables are referenced by index, stored in var labels
|
||||
*/
|
||||
|
||||
class ModelMap : protected std::multimap<uint16_t, ModelCell *>
|
||||
{
|
||||
public:
|
||||
char name[LEN_MODEL_FILENAME + 1];
|
||||
public:
|
||||
ModelsVector getUnlabeledModels();
|
||||
ModelsVector getAllModels();
|
||||
ModelsVector getModelsByLabel(const std::string &);
|
||||
ModelsVector getModelsByLabels(const LabelsVector &);
|
||||
ModelsVector getModelsInLabels(const LabelsVector &lbls);
|
||||
LabelsVector getLabelsByModel(ModelCell *);
|
||||
std::map<std::string, bool> getSelectedLabels(ModelCell *);
|
||||
bool isLabelSelected(const std::string &, ModelCell *);
|
||||
LabelsVector getLabels();
|
||||
int addLabel(std::string lbl);
|
||||
bool addLabelToModel(const std::string &, ModelCell *, bool update = false);
|
||||
bool removeLabelFromModel(const std::string &label, ModelCell *,
|
||||
bool update = false);
|
||||
bool removeLabel(
|
||||
const std::string &,
|
||||
std::function<void(const char *file, int progress)> progress = nullptr);
|
||||
bool moveLabelTo(unsigned current, unsigned newind);
|
||||
bool renameLabel(
|
||||
const std::string &from, const std::string &to,
|
||||
std::function<void(const char *file, int progress)> progress = nullptr);
|
||||
std::string getCurrentLabel() { return currentlabel; };
|
||||
void setCurrentLabel(const std::string &lbl)
|
||||
{
|
||||
currentlabel = lbl;
|
||||
setDirty();
|
||||
}
|
||||
std::string getLabelString(ModelCell *, const char *noresults = "");
|
||||
void setDirty(bool save = false);
|
||||
bool isDirty() { return _isDirty; }
|
||||
|
||||
explicit ModelsCategory(const char * name);
|
||||
explicit ModelsCategory(const char * name, uint8_t len);
|
||||
~ModelsCategory();
|
||||
// Currently selected labels in the GUI
|
||||
void setFilteredLabels(std::set<uint32_t> filtlbls)
|
||||
{
|
||||
this->filtlbls = std::move(filtlbls);
|
||||
}
|
||||
void addFilteredLabel(const std::string &lbl);
|
||||
bool isLabelFiltered(const std::string &lbl);
|
||||
std::set<uint32_t> filteredLabels() { return filtlbls; }
|
||||
|
||||
ModelCell* addModel(const char* fileName, const char* modelName = nullptr);
|
||||
void removeModel(ModelCell * model);
|
||||
void moveModel(ModelCell * model, int8_t step);
|
||||
void setSortOrder(ModelsSortBy sortby);
|
||||
ModelsSortBy sortOrder() {return _sortOrder;}
|
||||
|
||||
int getModelIndex(const ModelCell* model);
|
||||
protected:
|
||||
ModelsSortBy _sortOrder = DEFAULT_MODEL_SORT;
|
||||
bool _isDirty = true;
|
||||
std::set<uint32_t> filtlbls;
|
||||
std::string currentlabel = "";
|
||||
|
||||
void save(FIL * file);
|
||||
void updateModelCell(ModelCell *);
|
||||
bool removeModels(
|
||||
ModelCell *); // Should only be called from ModelsList remove model
|
||||
bool updateModelFile(ModelCell *);
|
||||
void sortModelsBy(ModelsVector &mv, ModelsSortBy sortby);
|
||||
|
||||
void clear()
|
||||
{
|
||||
_isDirty = true;
|
||||
labels.clear();
|
||||
std::multimap<uint16_t, ModelCell *>::clear();
|
||||
}
|
||||
|
||||
int getIndexByLabel(const std::string &str)
|
||||
{
|
||||
auto a = std::find(labels.begin(), labels.end(), str);
|
||||
return a == labels.end() ? -1 : a - labels.begin();
|
||||
}
|
||||
|
||||
std::string getLabelByIndex(uint16_t index)
|
||||
{
|
||||
if (index < (uint16_t)labels.size())
|
||||
return labels.at(index);
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
friend class ModelsList;
|
||||
|
||||
private:
|
||||
LabelsVector labels; // Storage space for discovered labels
|
||||
};
|
||||
|
||||
class ModelsList
|
||||
class ModelsList : public ModelsVector
|
||||
{
|
||||
bool loaded;
|
||||
std::list<ModelsCategory *> categories;
|
||||
ModelsCategory * currentCategory;
|
||||
ModelCell * currentModel;
|
||||
unsigned int modelsCount;
|
||||
|
||||
ModelCell *currentModel;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
enum class Format {
|
||||
txt,
|
||||
#if defined(SDCARD_YAML)
|
||||
@@ -113,73 +216,54 @@ public:
|
||||
load_default = txt,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
ModelsList();
|
||||
~ModelsList();
|
||||
|
||||
bool load(Format fmt = Format::load_default);
|
||||
void save();
|
||||
const char *save(LabelsVector newOrder=LabelsVector());
|
||||
void clear();
|
||||
|
||||
const std::list<ModelsCategory *> & getCategories() const
|
||||
{
|
||||
return categories;
|
||||
}
|
||||
|
||||
std::list<ModelsCategory *>& getCategories()
|
||||
{
|
||||
return categories;
|
||||
}
|
||||
void setCurrentModel(ModelCell *cell);
|
||||
void updateCurrentModelCell();
|
||||
|
||||
void setCurrentCategory(ModelsCategory * cat);
|
||||
|
||||
ModelsCategory * getCurrentCategory() const
|
||||
{
|
||||
return currentCategory;
|
||||
}
|
||||
int getCurrentCategoryIdx() const;
|
||||
|
||||
void setCurrentModel(ModelCell * cell);
|
||||
|
||||
ModelCell * getCurrentModel() const
|
||||
{
|
||||
return currentModel;
|
||||
}
|
||||
|
||||
void incModelsCount() {
|
||||
modelsCount++;
|
||||
}
|
||||
ModelCell *getCurrentModel() const { return currentModel; }
|
||||
|
||||
unsigned int getModelsCount() const
|
||||
{
|
||||
return modelsCount;
|
||||
return std::vector<ModelCell *>::size();
|
||||
}
|
||||
|
||||
bool readNextLine(char * line, int maxlen);
|
||||
bool readNextLine(char *line, int maxlen);
|
||||
|
||||
ModelsCategory * createCategory(bool save=true);
|
||||
ModelsCategory * createCategory(const char * name, bool save=true);
|
||||
void removeCategory(ModelsCategory * category);
|
||||
ModelCell *addModel(const char *name, bool save = true, ModelCell *copyCell = nullptr);
|
||||
bool removeModel(ModelCell *model);
|
||||
bool moveModelTo(unsigned curindex, unsigned toindex);
|
||||
|
||||
ModelCell * addModel(ModelsCategory * category, const char * name, const char* modelName = nullptr, bool save=true);
|
||||
void removeModel(ModelsCategory * category, ModelCell * model);
|
||||
void moveModel(ModelsCategory * category, ModelCell * model, int8_t step);
|
||||
void moveModel(ModelCell * model, ModelsCategory * previous_category, ModelsCategory * new_category);
|
||||
|
||||
bool isModelIdUnique(uint8_t moduleIdx, char* warn_buf, size_t warn_buf_len);
|
||||
bool isModelIdUnique(uint8_t moduleIdx, char *warn_buf, size_t warn_buf_len);
|
||||
uint8_t findNextUnusedModelId(uint8_t moduleIdx);
|
||||
|
||||
void onNewModelCreated(ModelCell* cell, ModelData* model);
|
||||
typedef struct {
|
||||
std::string name;
|
||||
char hash[FILE_HASH_LENGTH + 1];
|
||||
bool curmodel = false;
|
||||
bool celladded = false;
|
||||
} filedat;
|
||||
std::vector<filedat> fileHashInfo;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
FIL file;
|
||||
|
||||
bool loadTxt();
|
||||
#if defined(SDCARD_YAML)
|
||||
bool loadYaml();
|
||||
bool loadYamlDirScanner();
|
||||
#endif
|
||||
};
|
||||
|
||||
extern ModelsList modelslist;
|
||||
ModelLabelsVector getUniqueLabels();
|
||||
|
||||
#endif // _MODELSLIST_H_
|
||||
extern ModelsList modelslist;
|
||||
extern ModelMap modelslabels;
|
||||
|
||||
#endif // _MODELSLIST_H_
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
#include "conversions/conversions.h"
|
||||
#include "model_init.h"
|
||||
|
||||
// defined either in sdcard_raw.cpp or sdcard_yaml.cpp
|
||||
void storageCreateModelsList();
|
||||
|
||||
void getModelPath(char * path, const char * filename, const char* pathName)
|
||||
{
|
||||
unsigned int len = strlen(pathName);
|
||||
@@ -71,9 +68,6 @@ void storageFormat()
|
||||
sdCheckAndCreateDirectory(MODELS_PATH);
|
||||
generalDefault();
|
||||
setModelDefaults();
|
||||
#if defined(STORAGE_MODELSLIST)
|
||||
storageCreateModelsList();
|
||||
#endif
|
||||
}
|
||||
|
||||
void storageCheck(bool immediately)
|
||||
@@ -87,10 +81,24 @@ void storageCheck(bool immediately)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(STORAGE_MODELSLIST)
|
||||
if (storageDirtyMsk & EE_LABELS) {
|
||||
TRACE("SD card write labels");
|
||||
storageDirtyMsk &= ~EE_LABELS;
|
||||
const char * error = modelslist.save();
|
||||
if (error) {
|
||||
TRACE("writeLabels error=%s", error);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (storageDirtyMsk & EE_MODEL) {
|
||||
TRACE("eeprom write model");
|
||||
storageDirtyMsk &= ~EE_MODEL;
|
||||
const char * error = writeModel();
|
||||
#if defined(STORAGE_MODELSLIST)
|
||||
modelslist.updateCurrentModelCell();
|
||||
#endif
|
||||
if (error) {
|
||||
TRACE("writeModel error=%s", error);
|
||||
}
|
||||
@@ -206,14 +214,14 @@ void storageReadAll()
|
||||
storageDirty(EE_GENERAL);
|
||||
storageCheck(true);
|
||||
}
|
||||
|
||||
|
||||
if (loadModel(g_eeGeneral.currModelFilename, false) != nullptr) {
|
||||
TRACE("No current model or SD card error");
|
||||
}
|
||||
#else
|
||||
if (loadModel(g_eeGeneral.currModel, false) != nullptr) {
|
||||
TRACE("No current model or SD card error");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "ff.h"
|
||||
#include "translations.h"
|
||||
|
||||
#define DEFAULT_CATEGORY "Models"
|
||||
|
||||
#define MODEL_FILENAME_PREFIX "model"
|
||||
#if defined(SDCARD_RAW)
|
||||
#define MODEL_FILENAME_SUFFIX ".bin"
|
||||
|
||||
@@ -191,15 +191,3 @@ const char * writeGeneralSettingsBin()
|
||||
return writeFileBin(RADIO_SETTINGS_PATH, (uint8_t *)&g_eeGeneral, sizeof(g_eeGeneral));
|
||||
}
|
||||
|
||||
#if !defined(SDCARD_YAML)
|
||||
void storageCreateModelsList()
|
||||
{
|
||||
FIL file;
|
||||
|
||||
FRESULT result = f_open(&file, RADIO_MODELSLIST_PATH, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (result == FR_OK) {
|
||||
f_puts("[" DEFAULT_CATEGORY "]\n" DEFAULT_MODEL_FILENAME "\n", &file);
|
||||
f_close(&file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -122,27 +122,6 @@ const char * readYamlFile(const char* fullpath, const YamlParserCalls* calls, vo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Generic storage interface
|
||||
//
|
||||
|
||||
#if defined(STORAGE_MODELSLIST)
|
||||
void storageCreateModelsList()
|
||||
{
|
||||
modelslist.clear();
|
||||
ModelsCategory* cat = modelslist.createCategory(DEFAULT_CATEGORY, false);
|
||||
ModelCell* model = nullptr;
|
||||
if (g_eeGeneral.currModelFilename[0] != '\0') {
|
||||
model = modelslist.addModel(cat, g_eeGeneral.currModelFilename, nullptr, false);
|
||||
} else {
|
||||
model = modelslist.addModel(cat, DEFAULT_MODEL_FILENAME, nullptr, false);
|
||||
}
|
||||
model->setModelName(g_model.header.name);
|
||||
modelslist.save();
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// SDCARD storage interface
|
||||
//
|
||||
@@ -224,12 +203,16 @@ const char * loadRadioSettings()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEFAULT_INTERNAL_MODULE)
|
||||
g_eeGeneral.internalModule = DEFAULT_INTERNAL_MODULE;
|
||||
#endif
|
||||
|
||||
const char* error = loadRadioSettingsYaml();
|
||||
if (!error) {
|
||||
g_eeGeneral.chkSum = evalChkSum();
|
||||
}
|
||||
postRadioSettingsLoad();
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -345,7 +328,7 @@ const char * writeGeneralSettings()
|
||||
return p;
|
||||
}
|
||||
f_unlink(RADIO_SETTINGS_YAML_PATH);
|
||||
|
||||
|
||||
FRESULT result = f_rename(RADIO_SETTINGS_TMPFILE_YAML_PATH, RADIO_SETTINGS_YAML_PATH);
|
||||
if(result != FR_OK)
|
||||
return SDCARD_ERROR(result);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
enum class ChecksumResult {Success, Failed, None};
|
||||
#include "sdcard_common.h" // TODO CHECK REQUIRED
|
||||
|
||||
constexpr uint8_t MODELIDX_STRLEN = sizeof(MODEL_FILENAME_PREFIX "00");
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ set(SRC ${SRC} storage/yaml/yaml_tree_walker.cpp
|
||||
storage/yaml/yaml_datastructs.cpp)
|
||||
|
||||
if(STORAGE_MODELSLIST)
|
||||
set(SRC ${SRC} storage/yaml/yaml_modelslist.cpp)
|
||||
set(SRC ${SRC} storage/yaml/yaml_labelslist.cpp)
|
||||
add_definitions(-DSTORAGE_MODELSLIST)
|
||||
endif()
|
||||
|
||||
|
||||
# Warning: this file must be kept in sync with 'yaml_datastructs.cpp'
|
||||
# in the same directory.
|
||||
|
||||
|
||||
@@ -455,6 +455,7 @@ static const struct YamlNode struct_ModelHeader[] = {
|
||||
YAML_STRING("name", 15),
|
||||
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
|
||||
YAML_STRING("bitmap", 14),
|
||||
YAML_STRING("labels", 100),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TimerData[] = {
|
||||
@@ -837,7 +838,7 @@ static const struct YamlNode struct_TopBarPersistentData[] = {
|
||||
};
|
||||
static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_CUSTOM("semver",nullptr,w_semver),
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_UNSIGNED( "telemetryProtocol", 3 ),
|
||||
YAML_UNSIGNED( "thrTrim", 1 ),
|
||||
@@ -889,7 +890,7 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_PartialModel[] = {
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
@@ -480,6 +480,7 @@ static const struct YamlNode struct_ModelHeader[] = {
|
||||
YAML_STRING("name", 15),
|
||||
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
|
||||
YAML_STRING("bitmap", 14),
|
||||
YAML_STRING("labels", 100),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TimerData[] = {
|
||||
@@ -862,7 +863,7 @@ static const struct YamlNode struct_TopBarPersistentData[] = {
|
||||
};
|
||||
static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_CUSTOM("semver",nullptr,w_semver),
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_UNSIGNED( "telemetryProtocol", 3 ),
|
||||
YAML_UNSIGNED( "thrTrim", 1 ),
|
||||
@@ -914,7 +915,7 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_PartialModel[] = {
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
@@ -478,6 +478,7 @@ static const struct YamlNode struct_ModelHeader[] = {
|
||||
YAML_STRING("name", 15),
|
||||
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
|
||||
YAML_STRING("bitmap", 14),
|
||||
YAML_STRING("labels", 100),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TimerData[] = {
|
||||
@@ -860,7 +861,7 @@ static const struct YamlNode struct_TopBarPersistentData[] = {
|
||||
};
|
||||
static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_CUSTOM("semver",nullptr,w_semver),
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_UNSIGNED( "telemetryProtocol", 3 ),
|
||||
YAML_UNSIGNED( "thrTrim", 1 ),
|
||||
@@ -912,7 +913,7 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_PartialModel[] = {
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* 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_labelslist.h"
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "storage/modelslist.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef DEBUG_LABELS
|
||||
#define TRACE_LABELS_YAML(...) TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE_LABELS_YAML(...)
|
||||
#endif
|
||||
|
||||
using std::list;
|
||||
|
||||
struct labelslist_iter
|
||||
{
|
||||
enum ItemData {
|
||||
Root=0,
|
||||
ModelsRoot=1,
|
||||
ModelName=2,
|
||||
ModelData=3,
|
||||
LabelsRoot=4,
|
||||
LabelName=5,
|
||||
LabelData=6,
|
||||
SortRoot=7,
|
||||
};
|
||||
|
||||
ModelCell *curmodel;
|
||||
bool modeldatavalid; // Used to determine if reading yaml values is necessary
|
||||
uint8_t level;
|
||||
char current_attr[LABEL_LENGTH+1]; // set after find_node()
|
||||
char current_label[LABEL_LENGTH+1]; // set after find_node()
|
||||
};
|
||||
|
||||
static labelslist_iter __labelslist_iter_inst;
|
||||
|
||||
void* get_labelslist_iter()
|
||||
{
|
||||
// Thoughts... record the time here.
|
||||
// If time > xxx while parsing models. pop up a window showing updating?
|
||||
|
||||
__labelslist_iter_inst.modeldatavalid = false;
|
||||
__labelslist_iter_inst.curmodel = NULL;
|
||||
__labelslist_iter_inst.level = 0;
|
||||
|
||||
TRACE_LABELS_YAML("YAML Label Reader Start %u", 0);
|
||||
|
||||
return &__labelslist_iter_inst;
|
||||
}
|
||||
|
||||
static bool to_parent(void* ctx)
|
||||
{
|
||||
labelslist_iter* mi = (labelslist_iter*)ctx;
|
||||
|
||||
if (mi->level == labelslist_iter::Root)
|
||||
return false;
|
||||
|
||||
if(mi->level == labelslist_iter::ModelName ||
|
||||
mi->level == labelslist_iter::LabelName) {
|
||||
mi->level = labelslist_iter::Root;
|
||||
}
|
||||
else
|
||||
mi->level--;
|
||||
|
||||
TRACE_LABELS_YAML("YAML To Parent %u", mi->level);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_child(void* ctx)
|
||||
{
|
||||
labelslist_iter* mi = (labelslist_iter*)ctx;
|
||||
|
||||
mi->level++;
|
||||
|
||||
TRACE_LABELS_YAML("YAML To Child");
|
||||
TRACE_LABELS_YAML("YAML Level %u", mi->level);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_next_elmt(void* ctx)
|
||||
{
|
||||
labelslist_iter* mi = (labelslist_iter*)ctx;
|
||||
if (mi->level == labelslist_iter::Root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TRACE_LABELS_YAML("YAML To Next Element");
|
||||
TRACE_LABELS_YAML("YAML Current Level %u", mi->level);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool find_node(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
labelslist_iter* mi = (labelslist_iter*)ctx;
|
||||
|
||||
memcpy(mi->current_attr, buf, len);
|
||||
mi->current_attr[len] = '\0';
|
||||
|
||||
TRACE_LABELS_YAML("YAML On Node %s", mi->current_attr);
|
||||
TRACE_LABELS_YAML("YAML Current Level %u", mi->level);
|
||||
|
||||
// If in the labels node, force to labelsroot enum
|
||||
if(mi->level == labelslist_iter::Root && strcasecmp(mi->current_attr,"labels") == 0) {
|
||||
TRACE_LABELS_YAML("Forced root");
|
||||
mi->level = labelslist_iter::LabelsRoot;
|
||||
TRACE_LABELS_YAML("YAML New Level %u", mi->level);
|
||||
}
|
||||
|
||||
if(mi->level == labelslist_iter::Root && strcasecmp(mi->current_attr,"models") == 0) {
|
||||
TRACE_LABELS_YAML("Forced root");
|
||||
mi->level = labelslist_iter::ModelsRoot;
|
||||
TRACE_LABELS_YAML("YAML New Level %u", mi->level);
|
||||
}
|
||||
|
||||
if(mi->level == labelslist_iter::Root && strcasecmp(mi->current_attr,"sort") == 0) {
|
||||
TRACE_LABELS_YAML("Forced root");
|
||||
mi->level = labelslist_iter::SortRoot;
|
||||
TRACE_LABELS_YAML("YAML New Level %u", mi->level);
|
||||
}
|
||||
|
||||
// Model List
|
||||
if(mi->level == labelslist_iter::ModelName) {
|
||||
bool found=false;
|
||||
for(auto &filehash : modelslist.fileHashInfo) {
|
||||
if(filehash.name == mi->current_attr) {
|
||||
TRACE_LABELS_YAML(" Model %s has a real file, creating a modelcell");
|
||||
ModelCell *model = new ModelCell(mi->current_attr);
|
||||
strcpy(model->modelFinfoHash, filehash.hash);
|
||||
modelslist.push_back(model);
|
||||
filehash.celladded = true;
|
||||
if(filehash.curmodel == true)
|
||||
modelslist.setCurrentModel(model);
|
||||
mi->curmodel = model;
|
||||
mi->modeldatavalid = false;
|
||||
mi->curmodel->_isDirty = true;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
mi->curmodel = NULL;
|
||||
TRACE_LABELS_YAML("File does not exist in /MODELS");
|
||||
}
|
||||
}
|
||||
|
||||
// Labels List
|
||||
if(mi->level == labelslist_iter::LabelName) {
|
||||
TRACE_LABELS_YAML("Label Found -- %s", mi->current_attr);
|
||||
modelslabels.addLabel(mi->current_attr);
|
||||
strncpy(mi->current_label,mi->current_attr, LABEL_LENGTH);
|
||||
mi->current_label[LABEL_LENGTH] = '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_attr(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
char value[40];
|
||||
memcpy(value, buf, len);
|
||||
value[len] = '\0';
|
||||
|
||||
labelslist_iter* mi = (labelslist_iter*)ctx;
|
||||
TRACE_LABELS_YAML("YAML Attr Level %u, %s = %s", mi->level, mi->current_attr, value);
|
||||
|
||||
// Model Section
|
||||
if(mi->level == labelslist_iter::ModelData) {
|
||||
|
||||
// File Hash
|
||||
if(!strcasecmp(mi->current_attr, "hash")) {
|
||||
if(mi->curmodel != NULL) {
|
||||
if(!strcmp(mi->curmodel->modelFinfoHash, value)) {
|
||||
TRACE_LABELS_YAML("FILE HASH MATCHES, No need to scan this model, just load the settings");
|
||||
mi->modeldatavalid = true;
|
||||
mi->curmodel->valid_rfData = true;
|
||||
mi->curmodel->_isDirty = false;
|
||||
} else {
|
||||
TRACE_LABELS_YAML("FILE HASH Does not Match, Open model and rebuild modelcell");
|
||||
mi->modeldatavalid = false;
|
||||
mi->curmodel->_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Model Name
|
||||
} else if(mi->modeldatavalid && !strcasecmp(mi->current_attr, "name")) {
|
||||
if(mi->curmodel != NULL) {
|
||||
mi->curmodel->setModelName(value);
|
||||
TRACE_LABELS_YAML("Set the models name");
|
||||
}
|
||||
|
||||
// Last Opened
|
||||
} else if(mi->modeldatavalid && !strcasecmp(mi->current_attr, "lastopen")) {
|
||||
if(mi->curmodel != NULL) {
|
||||
mi->curmodel->lastOpened = (gtime_t)strtol(value, NULL, 0);
|
||||
TRACE_LABELS_YAML("Last Opened %lu", value);
|
||||
}
|
||||
|
||||
// Model Bitmap
|
||||
#if LEN_BITMAP_NAME > 0
|
||||
} else if(mi->modeldatavalid && !strcasecmp(mi->current_attr, "bitmap")) {
|
||||
if(mi->curmodel != NULL) {
|
||||
// TODO Check if it exists ?
|
||||
strcpy(mi->curmodel->modelBitmap, value);
|
||||
TRACE_LABELS_YAML("Set the models bitmap");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Model Labels
|
||||
} else if(mi->modeldatavalid && !strcasecmp(mi->current_attr, "labels")) {
|
||||
if(mi->curmodel != NULL) {
|
||||
char *cma;
|
||||
cma = strtok(value, ",");
|
||||
int numTokens = 0;
|
||||
while(cma != NULL) {
|
||||
modelslabels.addLabelToModel(cma,mi->curmodel);
|
||||
TRACE_LABELS_YAML(" Adding the label - %s", cma);
|
||||
cma = strtok(NULL, ",");
|
||||
numTokens++;
|
||||
}
|
||||
}
|
||||
|
||||
// RF Module Data
|
||||
} else {
|
||||
char cmp[15];
|
||||
for(int i=0; i < NUM_MODULES; i++) {
|
||||
snprintf(cmp, sizeof(cmp), MODULE_ID_STR, i);
|
||||
cmp[sizeof(cmp)-1] = '\0';
|
||||
if(mi->curmodel != NULL && mi->modeldatavalid && !strcasecmp(mi->current_attr, cmp)) {
|
||||
mi->curmodel->modelId[i] = strtol(value,NULL,10);
|
||||
TRACE_LABELS_YAML("Set the module %d rfId to %s", i, value);
|
||||
}
|
||||
snprintf(cmp, sizeof(cmp), MODULE_TYPE_STR, i);
|
||||
cmp[sizeof(cmp)-1] = '\0';
|
||||
if(mi->curmodel != NULL && mi->modeldatavalid && !strcasecmp(mi->current_attr, cmp)) {
|
||||
mi->curmodel->moduleData[i].type = strtol(value,NULL,10);
|
||||
TRACE_LABELS_YAML("Set the module %d rfType to %s", i, value);
|
||||
}
|
||||
snprintf(cmp, sizeof(cmp), MODULE_RFPROTOCOL_STR, i);
|
||||
cmp[sizeof(cmp)-1] = '\0';
|
||||
if(mi->curmodel != NULL && mi->modeldatavalid && !strcasecmp(mi->current_attr, cmp)) {
|
||||
mi->curmodel->moduleData[i].subType = strtol(value,NULL,10);
|
||||
TRACE_LABELS_YAML("Set the module %d rfProtocol to %s", i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Label Section
|
||||
} else if(mi->level == labelslist_iter::LabelData) {
|
||||
if(!strcasecmp(mi->current_attr, "icon")) {
|
||||
TRACE_LABELS_YAML("Label Icon - %s", value);
|
||||
// TODO - Check icon exists, or ignore it.
|
||||
} else if(!strcasecmp(mi->current_attr, "selected")) {
|
||||
TRACE("FOUND %s Label is selected", mi->current_label);
|
||||
modelslabels.addFilteredLabel(mi->current_label);
|
||||
}
|
||||
|
||||
// Sort Order
|
||||
} else if (mi->level == labelslist_iter::SortRoot) {
|
||||
TRACE("Sort Order Found -- %s", mi->current_attr);
|
||||
mi->level = labelslist_iter::Root;
|
||||
modelslabels.setSortOrder((ModelsSortBy)strtol(value,NULL,10));
|
||||
}
|
||||
}
|
||||
|
||||
static const YamlParserCalls labelslistCalls = {
|
||||
to_parent,
|
||||
to_child,
|
||||
to_next_elmt,
|
||||
find_node,
|
||||
set_attr
|
||||
};
|
||||
|
||||
const YamlParserCalls* get_labelslist_parser_calls()
|
||||
{
|
||||
return &labelslistCalls;
|
||||
}
|
||||
@@ -19,12 +19,16 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _YAML_MODELSLIST_H_
|
||||
#define _YAML_MODELSLIST_H_
|
||||
#ifndef _YAML_LABELSLIST_H_
|
||||
#define _YAML_LABELSLIST_H_
|
||||
|
||||
#define MODULE_ID_STR "mod%did"
|
||||
#define MODULE_TYPE_STR "mod%dtype"
|
||||
#define MODULE_RFPROTOCOL_STR "mod%drf"
|
||||
|
||||
struct YamlParserCalls;
|
||||
|
||||
void* get_modelslist_iter(const char* currentModel, unsigned currentModel_len);
|
||||
const YamlParserCalls* get_modelslist_parser_calls();
|
||||
void* get_labelslist_iter();
|
||||
const YamlParserCalls* get_labelslist_parser_calls();
|
||||
|
||||
#endif
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* 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_modelslist.h"
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#include "storage/modelslist.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using std::list;
|
||||
|
||||
struct modelslist_iter
|
||||
{
|
||||
enum Level {
|
||||
Root=0,
|
||||
Category=1,
|
||||
Model=2
|
||||
};
|
||||
|
||||
ModelsList* root;
|
||||
const char* currentModel;
|
||||
unsigned currentModel_len;
|
||||
uint8_t level;
|
||||
char current_attr[16]; // set after find_node()
|
||||
};
|
||||
|
||||
static modelslist_iter __modelslist_iter_inst;
|
||||
|
||||
void* get_modelslist_iter(const char* currentModel, unsigned currentModel_len)
|
||||
{
|
||||
__modelslist_iter_inst.root = &modelslist;
|
||||
__modelslist_iter_inst.currentModel = currentModel;
|
||||
__modelslist_iter_inst.currentModel_len = currentModel_len;
|
||||
__modelslist_iter_inst.level = 0;
|
||||
|
||||
return &__modelslist_iter_inst;
|
||||
}
|
||||
|
||||
static bool to_parent(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mi->level--;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_child(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mi->level++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_next_elmt(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Root) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool find_node(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
|
||||
if (len > sizeof(modelslist_iter::current_attr)-1)
|
||||
len = sizeof(modelslist_iter::current_attr)-1;
|
||||
|
||||
memcpy(mi->current_attr, buf, len);
|
||||
mi->current_attr[len] = '\0';
|
||||
|
||||
list<ModelsCategory *>& cats = mi->root->getCategories();
|
||||
if (mi->level == modelslist_iter::Category) {
|
||||
ModelsCategory* cat = new ModelsCategory(buf,len);
|
||||
cats.push_back(cat);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_attr(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
auto ml = mi->root;
|
||||
list<ModelsCategory*>& cats = ml->getCategories();
|
||||
|
||||
switch (mi->level) {
|
||||
case modelslist_iter::Model:
|
||||
if (!strcmp(mi->current_attr, "filename")) {
|
||||
if (!cats.empty()) {
|
||||
ModelCell* model = new ModelCell(buf, len);
|
||||
auto cat = cats.back();
|
||||
cat->push_back(model);
|
||||
ml->incModelsCount();
|
||||
|
||||
if (!strncmp(model->modelFilename, mi->currentModel,
|
||||
mi->currentModel_len)) {
|
||||
ml->setCurrentCategory(cat);
|
||||
ml->setCurrentModel(model);
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(mi->current_attr, "name")) {
|
||||
if (!cats.empty()) {
|
||||
auto cat = cats.back();
|
||||
if (!cat->empty()) {
|
||||
auto model = cat->back();
|
||||
model->setModelName(buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const YamlParserCalls modelslistCalls = {
|
||||
to_parent,
|
||||
to_child,
|
||||
to_next_elmt,
|
||||
find_node,
|
||||
set_attr
|
||||
};
|
||||
|
||||
const YamlParserCalls* get_modelslist_parser_calls()
|
||||
{
|
||||
return &modelslistCalls;
|
||||
}
|
||||
Reference in New Issue
Block a user