fix(cpn): Preserve sort order and selected labels (#3580)

* fix(cpn): read/write models Sort Order (based on work by dlktdr)

* fix(cpn): read and write labels and selected
This commit is contained in:
Neil Horne
2023-05-23 13:41:41 +10:00
committed by GitHub
parent 48e5d141aa
commit ad5d8e190e
6 changed files with 96 additions and 34 deletions
@@ -89,18 +89,37 @@ static void writeYamlToByteArray(const YAML::Node& node, QByteArray& data, bool
qDebug() << data.toStdString().c_str();
}
bool loadLabelsListFromYaml(QStringList& labels,
bool loadLabelsListFromYaml(RadioData::ModelLabels& labels,
int& sortOrder,
EtxModelfiles& modelFiles,
const QByteArray& data)
{
sortOrder = 0;
labels.clear();
if (data.size() == 0)
return true;
YAML::Node node = loadYamlFromByteArray(data);
if (!node.IsMap()) return false; // Root Map (Labels, Models)
for (const auto& lbl : node["Labels"]) {
labels.append(QString::fromStdString(lbl.first.as<std::string>()));
}
if (!node.IsMap()) return false; // Root Map (Labels, Sort, Models)
if (node["Sort"].IsScalar()) {
bool ok = false;
sortOrder = QString::fromStdString(node["Sort"].Scalar()).toUInt(&ok);
if (!ok)
sortOrder = 0;
}
YAML::Node lbls = node["Labels"];
if (lbls.IsMap()) {
for (YAML::const_iterator it=lbls.begin(); it!=lbls.end(); ++it) {
std::string lbl = it->first.as<std::string>();
RadioData::LabelData ld;
ld.name = QString::fromStdString(lbl);
if (lbls[lbl]["selected"])
ld.selected = lbls[lbl]["selected"].as<bool>();
else
ld.selected = false;
labels.append(ld);
}
}
return true;
}
@@ -155,9 +174,12 @@ bool loadRadioSettingsFromYaml(GeneralSettings& settings, const QByteArray& data
bool writeLabelsListToYaml(const RadioData &radioData, QByteArray& data)
{
YAML::Node node;
foreach(QString label, radioData.labels) {
node["Labels"][label.toStdString()] = YAML::Null;
foreach(RadioData::LabelData label, radioData.labels) {
node["Labels"][label.name.toStdString()] = YAML::Null;
if (label.selected)
node["Labels"][label.name.toStdString()]["selected"] = true;
}
node["Sort"] = radioData.sortOrder;
writeYamlToByteArray(node, data);
return true;
}
@@ -37,7 +37,8 @@ struct EtxModelMetadata {
typedef std::list<EtxModelMetadata> EtxModelfiles;
bool loadLabelsListFromYaml(QStringList& labels,
bool loadLabelsListFromYaml(RadioData::ModelLabels& labels,
int& sortOrder,
EtxModelfiles& modelFiles,
const QByteArray& data);
+29 -9
View File
@@ -22,7 +22,8 @@
#include "radiodataconversionstate.h"
#include "eeprominterface.h"
RadioData::RadioData()
RadioData::RadioData() :
sortOrder(0)
{
models.resize(getCurrentFirmware()->getCapability(Models));
}
@@ -120,8 +121,11 @@ void RadioData::addLabel(QString label)
output.truncate(truncateAt);
}
label = QString(output);
if (labels.indexOf(label) == -1)
labels.append(label);
if (indexOfLabel(label) < 0) {
LabelData ld = { label, false };
labels.append(ld);
}
}
bool RadioData::deleteLabel(QString label)
@@ -139,7 +143,9 @@ bool RadioData::deleteLabel(QString label)
}
// Remove the label from the global list
labels.removeAll(label);
int index = indexOfLabel(label);
if (index > -1)
labels.remove(index);
// If no labels remain, add a Favorites one
if (!labels.size()) {
@@ -151,7 +157,7 @@ bool RadioData::deleteLabel(QString label)
bool RadioData::deleteLabel(int index)
{
if (index >= labels.size()) return false;
QString modelLabel = labels.at(index);
QString modelLabel = labels.at(index).name;
return deleteLabel(modelLabel);
}
@@ -188,9 +194,9 @@ bool RadioData::renameLabel(QString from, QString to)
}
}
}
int ind = labels.indexOf(from);
int ind = indexOfLabel(from);
if (ind != -1) {
labels.replace(ind, to);
labels[ind].name = to;
}
}
return success;
@@ -199,7 +205,7 @@ bool RadioData::renameLabel(QString from, QString to)
bool RadioData::renameLabel(int index, QString to)
{
if (index >= labels.size()) return false;
QString from = labels.at(index);
QString from = labels.at(index).name;
return renameLabel(from, to);
}
@@ -211,7 +217,7 @@ void RadioData::swapLabel(int indFrom, int indTo)
indFrom < 0 ||
indTo < 0)
return;
QString tmplbl = labels.at(indFrom);
LabelData tmplbl = labels.at(indFrom);
labels.replace(indFrom, labels.at(indTo));
labels.replace(indTo, tmplbl);
}
@@ -258,6 +264,20 @@ void RadioData::addLabelsFromModels()
}
}
int RadioData::indexOfLabel(QString & label) const
{
int index = -1;
for (int i = 0; i < labels.size(); i++) {
if (labels.at(i).name == label) {
index = i;
break;
}
}
return index;
}
QStringList RadioData::fromCSV(const QString &csv)
{
QStringList lbls = QString(csv).split(',',QString::SkipEmptyParts);
+12 -1
View File
@@ -17,7 +17,17 @@ class RadioData {
RadioData();
GeneralSettings generalSettings;
QStringList labels;
struct LabelData {
QString name;
bool selected;
};
typedef QVector<LabelData> ModelLabels;
ModelLabels labels;
int sortOrder;
std::vector<ModelData> models;
void convert(RadioDataConversionState & cstate);
@@ -31,6 +41,7 @@ class RadioData {
bool addLabelToModel(int index, QString label);
bool removeLabelFromModel(int index, QString label);
void addLabelsFromModels();
int indexOfLabel(QString & label) const;
static QStringList fromCSV(const QString &csv);
static QString toCSV(QStringList lbls);
+13 -12
View File
@@ -41,15 +41,15 @@ bool LabelsModel::setData(const QModelIndex &index, const QVariant &value, int r
if (role == Qt::CheckStateRole) {
if (value==Qt::Unchecked && selectedModel != -1) {
if (radioData->removeLabelFromModel(selectedModel, radioData->labels.at(index.row())))
if (radioData->removeLabelFromModel(selectedModel, radioData->labels.at(index.row()).name))
emit modelChanged(selectedModel);
} else {
try{
if (radioData->addLabelToModel(selectedModel, radioData->labels.at(index.row())))
if (radioData->addLabelToModel(selectedModel, radioData->labels.at(index.row()).name))
emit modelChanged(selectedModel);
} catch(const std::length_error& le) {
emit labelsFault(tr("Unable to add label \"%1\" to model \"%2\" not enough room")\
.arg(radioData->labels.at(index.row())).arg(le.what()));
.arg(radioData->labels.at(index.row()).name).arg(le.what()));
}
}
emit dataChanged(this->index(index.row(), 0),
@@ -60,10 +60,10 @@ bool LabelsModel::setData(const QModelIndex &index, const QVariant &value, int r
QString replTo = value.toString();
if (replFrom == replTo) // User exits edit without changing
return true;
if (radioData->labels.indexOf(replTo) == -1) { // Don't allow duplicates
if (radioData->indexOfLabel(replTo) == -1) { // Don't allow duplicates
bool modelsChanged = false;
try{
modelsChanged = radioData->renameLabel(replFrom,replTo);
modelsChanged = radioData->renameLabel(replFrom, replTo);
} catch(const std::length_error& le) {
emit labelsFault(tr("Unable to rename \"%1\" to \"%2\" not enough room in model %3")\
.arg(replFrom).arg(replTo).arg(le.what()));
@@ -88,7 +88,7 @@ QVariant LabelsModel::data(const QModelIndex &index, int role) const
if (index.row() >= labels.size() || !index.isValid() )
return QVariant();
QString label = radioData->labels.at(index.row());
QString label = radioData->labels.at(index.row()).name;
if (role == Qt::DisplayRole || role == Qt::EditRole) {
if (index.column() == 0) {
@@ -125,7 +125,7 @@ QModelIndex LabelsModel::parent(const QModelIndex &index) const
int LabelsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
Q_UNUSED(parent);
return labels.size();
}
@@ -158,9 +158,10 @@ bool LabelsModel::insertRows(int row, int count, const QModelIndex &parent)
if (newNo == 0)
newStr = QString(tr("New"));
newNo++;
} while(radioData->labels.indexOf(newStr) >= 0);
} while(radioData->indexOfLabel(newStr) >= 0);
// Add it to radioData
radioData->labels.insert(row+i, newStr);
RadioData::LabelData ld = { newStr , false };
radioData->labels.insert(row + i, ld);
}
buildLabelsList();
return true;
@@ -188,10 +189,10 @@ void LabelsModel::buildLabelsList()
{
labels.clear();
int i=0;
foreach(QString lbl, radioData->labels) {
int i = 0;
foreach(RadioData::LabelData ld, radioData->labels) {
LabelItem itm;
itm.label = lbl;
itm.label = ld.name;
itm.radioLabelIndex = i++;
labels.append(itm);
}
+11 -4
View File
@@ -140,7 +140,8 @@ bool LabelsStorageFormat::loadBin(RadioData & radioData)
// Add a Favorites label
if(getCurrentFirmware()->getCapability(HasModelLabels)) {
radioData.labels.append(tr("Favorites"));
RadioData::LabelData ld = { tr("Favorites"), false };
radioData.labels.append(ld);
}
return true;
}
@@ -218,9 +219,10 @@ bool LabelsStorageFormat::loadYaml(RadioData & radioData)
// - Update possible labels with all found in models too
QByteArray labelslistBuffer;
int sortOrder = 0;
if (loadFile(labelslistBuffer, "MODELS/labels.yml")) {
try {
if (!loadLabelsListFromYaml(radioData.labels, modelFiles, labelslistBuffer)) {
if (!loadLabelsListFromYaml(radioData.labels, sortOrder, modelFiles, labelslistBuffer)) {
setError(tr("Can't load MODELS/labels.yml"));
}
} catch(const std::runtime_error& e) {
@@ -228,6 +230,9 @@ bool LabelsStorageFormat::loadYaml(RadioData & radioData)
}
}
// Save Sort Order
radioData.sortOrder = sortOrder;
// Scan for all models
std::list<std::string> filelist;
if (!getFileList(filelist)) {
@@ -308,8 +313,10 @@ bool LabelsStorageFormat::loadYaml(RadioData & radioData)
radioData.addLabelsFromModels();
// If no labels, add a Favorites
if(!radioData.labels.size())
radioData.labels.append(tr("Favorites"));
if(!radioData.labels.size()) {
RadioData::LabelData ld = { tr("Favorites"), false };
radioData.labels.append(ld);
}
}
return true;