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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user