fix(cpn): preserve current calibration when writing models and settings to radio (#6722)

This commit is contained in:
Neil Horne
2025-10-29 11:23:45 +10:00
committed by GitHub
parent dbab5745b6
commit edaba32e2b
10 changed files with 143 additions and 62 deletions
+4 -5
View File
@@ -1493,10 +1493,11 @@ int MdiChild::askQuestion(const QString & msg, QMessageBox::StandardButtons butt
return QMessageBox::question(this, CPN_STR_APP_NAME, msg, buttons, defaultButton);
}
void MdiChild::writeSettings(StatusDialog * status, bool toRadio) // write to Tx
void MdiChild::writeSettings(StatusDialog * status, bool toRadio)
{
// safeguard as the menu actions should be disabled
int cnt = radioData.invalidModels();
if (cnt) {
QMessageBox::critical(this, tr("Write Models and Settings"), tr("Operation aborted as %1 models have significant errors that may affect model operation.").arg(cnt));
return;
@@ -1522,8 +1523,7 @@ void MdiChild::writeSettings(StatusDialog * status, bool toRadio) // write to T
if (toRadio) {
radioPath = findMassStoragePath("RADIO", true);
qDebug() << "Searching for SD card, found" << radioPath;
}
else {
} else {
radioPath = g.currentProfile().sdPath();
if (!QFile(radioPath % "/RADIO").exists())
radioPath.clear();
@@ -1538,8 +1538,7 @@ void MdiChild::writeSettings(StatusDialog * status, bool toRadio) // write to T
if (saveFile(radioPath, false)) {
status->hide();
QMessageBox::information(this, CPN_STR_TTL_INFO, tr("Models and settings written"));
}
else {
} else {
status->hide();
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Error writing models and settings!"));
}
+1 -1
View File
@@ -49,7 +49,7 @@ bool EtxFormat::load(RadioData & radioData)
return result;
}
bool EtxFormat::write(const RadioData & radioData)
bool EtxFormat::write(RadioData & radioData)
{
qDebug() << "Saving to archive" << filename;
+1 -1
View File
@@ -37,7 +37,7 @@ class EtxFormat : public LabelsStorageFormat
virtual QString name() { return "etx"; }
virtual bool load(RadioData & radioData);
virtual bool write(const RadioData & radioData);
virtual bool write(RadioData & radioData);
protected:
virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false);
+53 -15
View File
@@ -57,21 +57,8 @@ bool LabelsStorageFormat::load(RadioData & radioData)
qDebug() << tr("Found %1").arg(filename);
}
QByteArray radioSettingsBuffer;
if (!loadFile(radioSettingsBuffer, "RADIO/radio.yml")) {
setError(tr("Cannot extract RADIO/radio.yml"));
if (!loadRadioSettings(radioData.generalSettings))
return false;
}
try {
if (!loadRadioSettingsFromYaml(radioData.generalSettings, radioSettingsBuffer)) {
setError(tr("Cannot load RADIO/radio.yml"));
return false;
}
} catch(const std::runtime_error& e) {
setError(tr("Cannot load RADIO/radio.yml") + ":\n" + QString(e.what()));
return false;
}
board = (Board::Type)radioData.generalSettings.variant;
@@ -187,8 +174,34 @@ bool LabelsStorageFormat::load(RadioData & radioData)
return true;
}
bool LabelsStorageFormat::write(const RadioData & radioData)
bool LabelsStorageFormat::write(RadioData & radioData)
{
// TODO
// move all unique radio settings to a separate file eg RADIO/hardware.yml.
// These settings/values should never be transferred to another radio.
// Also some are at a point in time eg calibration and
// therefore not restored to the radio from say an etx file
// may not exist on a new sd card or path
if (QFile(filename + "/RADIO/radio.yml").exists()) {
GeneralSettings gsCur;
if (loadRadioSettings(gsCur)) {
GeneralSettings & gsNew = radioData.generalSettings;
gsNew.txCurrentCalibration = gsCur.txCurrentCalibration;
gsNew.txVoltageCalibration = gsCur.txVoltageCalibration;
for (int i = 0; i < CPN_MAX_INPUTS; i++) {
gsNew.inputConfig[i].calib = gsCur.inputConfig[i].calib;
}
qDebug() << "Hardware specific settings preserved";
} else {
setError("Error reading current settings from radio");
return false;
}
}
QByteArray radioSettingsBuffer;
if (!writeRadioSettingsToYaml(radioData.generalSettings, radioSettingsBuffer))
return false;
@@ -280,3 +293,28 @@ bool LabelsStorageFormat::writeChecklist(const ModelData & model)
return true;
}
bool LabelsStorageFormat::loadRadioSettings(GeneralSettings & generalSettings)
{
QByteArray radioSettingsBuffer;
const QString file("RADIO/radio.yml");
const QString filePath(QDir::toNativeSeparators(filename + "/" + file));
if (!loadFile(radioSettingsBuffer, file)) {
setError(tr("Cannot extract %1").arg(filePath));
return false;
}
try {
if (!loadRadioSettingsFromYaml(generalSettings, radioSettingsBuffer)) {
setError(tr("Cannot load %1").arg(filePath));
return false;
}
} catch(const std::runtime_error& e) {
setError(tr("Cannot load %1").arg(filePath) + ":\n" + QString(e.what()));
return false;
}
return true;
}
+2 -1
View File
@@ -42,7 +42,7 @@ class LabelsStorageFormat : public StorageFormat
}
virtual bool load(RadioData & radioData);
virtual bool write(const RadioData & radioData);
virtual bool write(RadioData & radioData);
protected:
virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false) = 0;
@@ -54,4 +54,5 @@ class LabelsStorageFormat : public StorageFormat
bool loadChecklist(ModelData &model);
bool writeChecklist(const ModelData & model);
bool loadRadioSettings(GeneralSettings & generalSettings);
};
+1 -1
View File
@@ -23,7 +23,7 @@
#include <QFile>
#include <QDir>
bool SdcardFormat::write(const RadioData & radioData)
bool SdcardFormat::write(RadioData & radioData)
{
QDir dir(filename);
dir.mkdir("RADIO");
+1 -1
View File
@@ -36,7 +36,7 @@ class SdcardFormat : public LabelsStorageFormat
}
virtual QString name() { return "sdcard"; }
virtual bool write(const RadioData & radioData);
virtual bool write(RadioData & radioData);
protected:
virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false);
+70 -33
View File
@@ -62,57 +62,94 @@ void unregisterStorageFactories()
bool Storage::load(RadioData & radioData)
{
QFile file(filename);
if (!file.exists()) {
setError(tr("Unable to find file %1!").arg(filename));
if (!fileExists())
return false;
}
bool ret = false;
foreach (StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename)) {
StorageFormat * format = factory->instance(filename);
if (format->load(radioData)) {
board = format->getBoard();
setWarning(format->warning());
ret = true;
delete format;
break;
}
else {
setError(format->error());
}
delete format;
StorageFormat *format = getStorageFormat();
if (format) {
if (format->load(radioData)) {
board = format->getBoard();
setWarning(format->warning());
ret = true;
} else {
setError(format->error());
}
delete format;
}
return ret;
}
bool Storage::write(const RadioData & radioData)
bool Storage::write(RadioData & radioData)
{
bool ret = false;
foreach (StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename)) {
StorageFormat * format = factory->instance(filename);
ret = format->write(radioData);
delete format;
break;
}
StorageFormat *format = getStorageFormat();
if (format) {
ret = format->write(radioData);
delete format;
}
return ret;
}
bool Storage::writeModel(const RadioData & radioData, const int modelIndex)
{
bool ret = false;
foreach (StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename)) {
StorageFormat * format = factory->instance(filename);
ret = format->writeModel(radioData, modelIndex);
delete format;
break;
}
StorageFormat *format = getStorageFormat();
if (format) {
ret = format->writeModel(radioData, modelIndex);
delete format;
}
return ret;
}
bool Storage::fileExists()
{
QFile file(filename);
if (!file.exists()) {
setError(tr("Unable to find file %1!").arg(filename));
return false;
}
return true;
}
StorageFormat * Storage::getStorageFormat()
{
foreach (StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename))
return factory->instance(filename);
}
return nullptr;
}
bool Storage::load(GeneralSettings & generalSettings)
{
if (!fileExists())
return false;
bool ret = false;
StorageFormat *format = getStorageFormat();
if (format) {
if (format->load(generalSettings)) {
board = format->getBoard();
setWarning(format->warning());
ret = true;
}
else
setError(format->error());
delete format;
}
return ret;
}
+9 -3
View File
@@ -51,7 +51,8 @@ class StorageFormat
}
virtual ~StorageFormat() {}
virtual bool load(RadioData & radioData) = 0;
virtual bool write(const RadioData & radioData) = 0;
virtual bool load(GeneralSettings & generalSettings) { return false; }
virtual bool write(RadioData & radioData) = 0;
virtual bool writeModel(const RadioData & radioData, const int modelIndex) { return false; }
QString error() {
@@ -151,9 +152,14 @@ class Storage : public StorageFormat
_warning = warning;
}
virtual bool load(RadioData & radioData);
virtual bool write(const RadioData & radioData);
virtual bool load(RadioData & radioData) override;
virtual bool load(GeneralSettings & generalSettings) override;
virtual bool write(RadioData & radioData);
virtual bool writeModel(const RadioData & radioData, const int modelIndex);
protected:
bool fileExists();
StorageFormat * getStorageFormat();
};
void registerStorageFactories();
+1 -1
View File
@@ -37,7 +37,7 @@ class YamlFormat : public StorageFormat
virtual QString name() override { return "yml"; }
virtual bool load(RadioData & radioData) override;
virtual bool write(const RadioData & radioData) override { return false; }
virtual bool write(RadioData & radioData) override { return false; }
virtual bool writeModel(const RadioData & radioData, const int modelIndex) override;
protected: