Save/open preferences
This commit is contained in:
parent
5d8efd4336
commit
fa481e2062
@ -25,7 +25,7 @@ Calkit::Calkit()
|
||||
{
|
||||
|
||||
// set default values
|
||||
for(auto e : json_descr) {
|
||||
for(auto e : descr) {
|
||||
e.var.setValue(e.def);
|
||||
}
|
||||
}
|
||||
@ -40,24 +40,7 @@ void Calkit::toFile(QString filename)
|
||||
|
||||
TransformPathsToRelative(filename);
|
||||
|
||||
json j;
|
||||
for(auto e : json_descr) {
|
||||
auto list = e.name.split("/");
|
||||
auto *json_entry = &j;
|
||||
while(list.size() > 0) {
|
||||
json_entry = &(*json_entry)[list.takeFirst().toStdString()];
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: *json_entry = val.toDouble(); break;
|
||||
case QMetaType::Int: *json_entry = val.toInt(); break;
|
||||
case QMetaType::Bool: *json_entry = val.toBool(); break;
|
||||
case QMetaType::QString: *json_entry = val.toString().toStdString(); break;
|
||||
default:
|
||||
throw runtime_error("Unimplemented metatype");
|
||||
}
|
||||
}
|
||||
json j = Savable::createJSON(descr);
|
||||
ofstream file;
|
||||
file.open(filename.toStdString());
|
||||
file << setw(4) << j << endl;
|
||||
@ -90,58 +73,19 @@ Calkit Calkit::fromFile(QString filename)
|
||||
throw runtime_error("JSON parsing error: " + string(e.what()));
|
||||
}
|
||||
if(j.contains("SOLT")) {
|
||||
// older file versions specify Z0 for resistance. If resistance entry is missing,
|
||||
// set it to Z0 later
|
||||
bool loadResistanceMissing_m = false;
|
||||
bool loadResistanceMissing_f = false;
|
||||
// older file versions specify Z0 for resistance. Set resistance to Nan to detect missing values later
|
||||
c.SOLT.load_m.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
c.SOLT.load_f.resistance = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
qDebug() << "JSON format detected";
|
||||
// calkit file uses json format, parse
|
||||
for(auto e : c.json_descr) {
|
||||
auto list = e.name.split("/");
|
||||
auto *json_entry = &j;
|
||||
bool entry_exists = true;
|
||||
while(list.size() > 0) {
|
||||
auto key = list.takeFirst().toStdString();
|
||||
if((*json_entry).contains(key)) {
|
||||
json_entry = &(*json_entry)[key];
|
||||
} else {
|
||||
entry_exists = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!entry_exists) {
|
||||
// missing entry in json file, nothing to do (default values already set in constructor)
|
||||
qWarning() << "Entry" << e.name << "not present in file, assuming default value";
|
||||
if(e.name == "SOLT/Load/Param/Resistance") {
|
||||
loadResistanceMissing_m = true;
|
||||
} else if(e.name == "SOLT/Load/Param/Resistance_Female") {
|
||||
loadResistanceMissing_f = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: e.var.setValue((*json_entry).get<double>()); break;
|
||||
case QMetaType::Int: e.var.setValue((*json_entry).get<int>()); break;
|
||||
case QMetaType::Bool: e.var.setValue((*json_entry).get<bool>()); break;
|
||||
case QMetaType::QString: {
|
||||
auto s = QString::fromStdString((*json_entry).get<string>());
|
||||
e.var.setValue(s);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Unimplemented metatype");
|
||||
}
|
||||
}
|
||||
// adjust Z0/resistance in case of older calkit file version
|
||||
if(loadResistanceMissing_f) {
|
||||
Savable::parseJSON(j, c.descr);
|
||||
// adjust Z0/resistance in case of older calkit file version with missing resistance entries
|
||||
if(isnan(c.SOLT.load_f.resistance)) {
|
||||
c.SOLT.load_f.resistance = c.SOLT.load_f.Z0;
|
||||
c.SOLT.load_f.Z0 = 50.0;
|
||||
}
|
||||
if(loadResistanceMissing_m) {
|
||||
if(isnan(c.SOLT.load_m.resistance)) {
|
||||
c.SOLT.load_m.resistance = c.SOLT.load_m.Z0;
|
||||
c.SOLT.load_m.Z0 = 50.0;
|
||||
}
|
||||
|
@ -105,90 +105,85 @@ private:
|
||||
Touchstone *ts_through;
|
||||
bool ts_cached;
|
||||
|
||||
using JSONDescription = struct _jsondescr {
|
||||
QPointerVariant var;
|
||||
QString name;
|
||||
QVariant def;
|
||||
};
|
||||
const std::array<JSONDescription, 73> json_descr = {{
|
||||
const std::vector<Savable::SettingDescription> descr = {{
|
||||
{&manufacturer, "Manufacturer", ""},
|
||||
{&serialnumber, "Serialnumber", ""},
|
||||
{&description, "Description", ""},
|
||||
|
||||
{&SOLT.open_m.Z0, "SOLT/Open/Param/Z0", 50.0},
|
||||
{&SOLT.open_m.delay, "SOLT/Open/Param/Delay", 0.0},
|
||||
{&SOLT.open_m.loss, "SOLT/Open/Param/Loss", 0.0},
|
||||
{&SOLT.open_m.C0, "SOLT/Open/Param/C0", 0.0},
|
||||
{&SOLT.open_m.C1, "SOLT/Open/Param/C1", 0.0},
|
||||
{&SOLT.open_m.C2, "SOLT/Open/Param/C2", 0.0},
|
||||
{&SOLT.open_m.C3, "SOLT/Open/Param/C3", 0.0},
|
||||
{&SOLT.open_m.useMeasurements, "SOLT/Open/Measurements/Use", false},
|
||||
{&SOLT.open_m.file, "SOLT/Open/Measurements/File", ""},
|
||||
{&SOLT.open_m.Sparam, "SOLT/Open/Measurements/Port", 0},
|
||||
{&SOLT.open_f.Z0, "SOLT/Open/Param/Z0_Female", 50.0},
|
||||
{&SOLT.open_f.delay, "SOLT/Open/Param/Delay_Female", 0.0},
|
||||
{&SOLT.open_f.loss, "SOLT/Open/Param/Loss_Female", 0.0},
|
||||
{&SOLT.open_f.C0, "SOLT/Open/Param/C0_Female", 0.0},
|
||||
{&SOLT.open_f.C1, "SOLT/Open/Param/C1_Female", 0.0},
|
||||
{&SOLT.open_f.C2, "SOLT/Open/Param/C2_Female", 0.0},
|
||||
{&SOLT.open_f.C3, "SOLT/Open/Param/C3_Female", 0.0},
|
||||
{&SOLT.open_f.useMeasurements, "SOLT/Open/Measurements/Use_Female", false},
|
||||
{&SOLT.open_f.file, "SOLT/Open/Measurements/File_Female", ""},
|
||||
{&SOLT.open_f.Sparam, "SOLT/Open/Measurements/Port_Female", 0},
|
||||
{&SOLT.open_m.Z0, "SOLT.Open.Param.Z0", 50.0},
|
||||
{&SOLT.open_m.delay, "SOLT.Open.Param.Delay", 0.0},
|
||||
{&SOLT.open_m.loss, "SOLT.Open.Param.Loss", 0.0},
|
||||
{&SOLT.open_m.C0, "SOLT.Open.Param.C0", 0.0},
|
||||
{&SOLT.open_m.C1, "SOLT.Open.Param.C1", 0.0},
|
||||
{&SOLT.open_m.C2, "SOLT.Open.Param.C2", 0.0},
|
||||
{&SOLT.open_m.C3, "SOLT.Open.Param.C3", 0.0},
|
||||
{&SOLT.open_m.useMeasurements, "SOLT.Open.Measurements.Use", false},
|
||||
{&SOLT.open_m.file, "SOLT.Open.Measurements.File", ""},
|
||||
{&SOLT.open_m.Sparam, "SOLT.Open.Measurements.Port", 0},
|
||||
{&SOLT.open_f.Z0, "SOLT.Open.Param.Z0_Female", 50.0},
|
||||
{&SOLT.open_f.delay, "SOLT.Open.Param.Delay_Female", 0.0},
|
||||
{&SOLT.open_f.loss, "SOLT.Open.Param.Loss_Female", 0.0},
|
||||
{&SOLT.open_f.C0, "SOLT.Open.Param.C0_Female", 0.0},
|
||||
{&SOLT.open_f.C1, "SOLT.Open.Param.C1_Female", 0.0},
|
||||
{&SOLT.open_f.C2, "SOLT.Open.Param.C2_Female", 0.0},
|
||||
{&SOLT.open_f.C3, "SOLT.Open.Param.C3_Female", 0.0},
|
||||
{&SOLT.open_f.useMeasurements, "SOLT.Open.Measurements.Use_Female", false},
|
||||
{&SOLT.open_f.file, "SOLT.Open.Measurements.File_Female", ""},
|
||||
{&SOLT.open_f.Sparam, "SOLT.Open.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.short_m.Z0, "SOLT/Short/Param/Z0", 50.0},
|
||||
{&SOLT.short_m.delay, "SOLT/Short/Param/Delay", 0.0},
|
||||
{&SOLT.short_m.loss, "SOLT/Short/Param/Loss", 0.0},
|
||||
{&SOLT.short_m.L0, "SOLT/Short/Param/L0", 0.0},
|
||||
{&SOLT.short_m.L1, "SOLT/Short/Param/L1", 0.0},
|
||||
{&SOLT.short_m.L2, "SOLT/Short/Param/L2", 0.0},
|
||||
{&SOLT.short_m.L3, "SOLT/Short/Param/L3", 0.0},
|
||||
{&SOLT.short_m.useMeasurements, "SOLT/Short/Measurements/Use", false},
|
||||
{&SOLT.short_m.file, "SOLT/Short/Measurements/File", ""},
|
||||
{&SOLT.short_m.Sparam, "SOLT/Short/Measurements/Port", 0},
|
||||
{&SOLT.short_f.Z0, "SOLT/Short/Param/Z0_Female", 50.0},
|
||||
{&SOLT.short_f.delay, "SOLT/Short/Param/Delay_Female", 0.0},
|
||||
{&SOLT.short_f.loss, "SOLT/Short/Param/Loss_Female", 0.0},
|
||||
{&SOLT.short_f.L0, "SOLT/Short/Param/L0_Female", 0.0},
|
||||
{&SOLT.short_f.L1, "SOLT/Short/Param/L1_Female", 0.0},
|
||||
{&SOLT.short_f.L2, "SOLT/Short/Param/L2_Female", 0.0},
|
||||
{&SOLT.short_f.L3, "SOLT/Short/Param/L3_Female", 0.0},
|
||||
{&SOLT.short_f.useMeasurements, "SOLT/Short/Measurements/Use_Female", false},
|
||||
{&SOLT.short_f.file, "SOLT/Short/Measurements/File_Female", ""},
|
||||
{&SOLT.short_f.Sparam, "SOLT/Short/Measurements/Port_Female", 0},
|
||||
{&SOLT.short_m.Z0, "SOLT.Short.Param.Z0", 50.0},
|
||||
{&SOLT.short_m.delay, "SOLT.Short.Param.Delay", 0.0},
|
||||
{&SOLT.short_m.loss, "SOLT.Short.Param.Loss", 0.0},
|
||||
{&SOLT.short_m.L0, "SOLT.Short.Param.L0", 0.0},
|
||||
{&SOLT.short_m.L1, "SOLT.Short.Param.L1", 0.0},
|
||||
{&SOLT.short_m.L2, "SOLT.Short.Param.L2", 0.0},
|
||||
{&SOLT.short_m.L3, "SOLT.Short.Param.L3", 0.0},
|
||||
{&SOLT.short_m.useMeasurements, "SOLT.Short.Measurements.Use", false},
|
||||
{&SOLT.short_m.file, "SOLT.Short.Measurements.File", ""},
|
||||
{&SOLT.short_m.Sparam, "SOLT.Short.Measurements.Port", 0},
|
||||
{&SOLT.short_f.Z0, "SOLT.Short.Param.Z0_Female", 50.0},
|
||||
{&SOLT.short_f.delay, "SOLT.Short.Param.Delay_Female", 0.0},
|
||||
{&SOLT.short_f.loss, "SOLT.Short.Param.Loss_Female", 0.0},
|
||||
{&SOLT.short_f.L0, "SOLT.Short.Param.L0_Female", 0.0},
|
||||
{&SOLT.short_f.L1, "SOLT.Short.Param.L1_Female", 0.0},
|
||||
{&SOLT.short_f.L2, "SOLT.Short.Param.L2_Female", 0.0},
|
||||
{&SOLT.short_f.L3, "SOLT.Short.Param.L3_Female", 0.0},
|
||||
{&SOLT.short_f.useMeasurements, "SOLT.Short.Measurements.Use_Female", false},
|
||||
{&SOLT.short_f.file, "SOLT.Short.Measurements.File_Female", ""},
|
||||
{&SOLT.short_f.Sparam, "SOLT.Short.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.load_m.resistance, "SOLT/Load/Param/Resistance", 50.0},
|
||||
{&SOLT.load_m.Z0, "SOLT/Load/Param/Z0", 50.0},
|
||||
{&SOLT.load_m.delay, "SOLT/Load/Param/Delay", 0.0},
|
||||
{&SOLT.load_m.Cparallel, "SOLT/Load/Param/C", 0.0},
|
||||
{&SOLT.load_m.Lseries, "SOLT/Load/Param/L", 0.0},
|
||||
{&SOLT.load_m.useMeasurements, "SOLT/Load/Measurements/Use", false},
|
||||
{&SOLT.load_m.file, "SOLT/Load/Measurements/File", ""},
|
||||
{&SOLT.load_m.Sparam, "SOLT/Load/Measurements/Port", 0},
|
||||
{&SOLT.load_f.resistance, "SOLT/Load/Param/Resistance_Female", 50.0},
|
||||
{&SOLT.load_f.Z0, "SOLT/Load/Param/Z0_Female", 50.0},
|
||||
{&SOLT.load_f.delay, "SOLT/Load/Param/Delay_Female", 0.0},
|
||||
{&SOLT.load_f.Cparallel, "SOLT/Load/Param/C_Female", 0.0},
|
||||
{&SOLT.load_f.Lseries, "SOLT/Load/Param/L_Female", 0.0},
|
||||
{&SOLT.load_f.useMeasurements, "SOLT/Load/Measurements/Use_Female", false},
|
||||
{&SOLT.load_f.file, "SOLT/Load/Measurements/File_Female", ""},
|
||||
{&SOLT.load_f.Sparam, "SOLT/Load/Measurements/Port_Female", 0},
|
||||
{&SOLT.load_m.resistance, "SOLT.Load.Param.Resistance", 50.0},
|
||||
{&SOLT.load_m.Z0, "SOLT.Load.Param.Z0", 50.0},
|
||||
{&SOLT.load_m.delay, "SOLT.Load.Param.Delay", 0.0},
|
||||
{&SOLT.load_m.Cparallel, "SOLT.Load.Param.C", 0.0},
|
||||
{&SOLT.load_m.Lseries, "SOLT.Load.Param.L", 0.0},
|
||||
{&SOLT.load_m.useMeasurements, "SOLT.Load.Measurements.Use", false},
|
||||
{&SOLT.load_m.file, "SOLT.Load.Measurements.File", ""},
|
||||
{&SOLT.load_m.Sparam, "SOLT.Load.Measurements.Port", 0},
|
||||
{&SOLT.load_f.resistance, "SOLT.Load.Param.Resistance_Female", 50.0},
|
||||
{&SOLT.load_f.Z0, "SOLT.Load.Param.Z0_Female", 50.0},
|
||||
{&SOLT.load_f.delay, "SOLT.Load.Param.Delay_Female", 0.0},
|
||||
{&SOLT.load_f.Cparallel, "SOLT.Load.Param.C_Female", 0.0},
|
||||
{&SOLT.load_f.Lseries, "SOLT.Load.Param.L_Female", 0.0},
|
||||
{&SOLT.load_f.useMeasurements, "SOLT.Load.Measurements.Use_Female", false},
|
||||
{&SOLT.load_f.file, "SOLT.Load.Measurements.File_Female", ""},
|
||||
{&SOLT.load_f.Sparam, "SOLT.Load.Measurements.Port_Female", 0},
|
||||
|
||||
{&SOLT.Through.Z0, "SOLT/Through/Param/Z0", 50.0},
|
||||
{&SOLT.Through.delay, "SOLT/Through/Param/Delay", 0.0},
|
||||
{&SOLT.Through.loss, "SOLT/Through/Param/Loss", 0.0},
|
||||
{&SOLT.Through.useMeasurements, "SOLT/Through/Measurements/Use", false},
|
||||
{&SOLT.Through.file, "SOLT/Through/Measurements/File", ""},
|
||||
{&SOLT.Through.Sparam1, "SOLT/Through/Measurements/Port1", 0},
|
||||
{&SOLT.Through.Sparam2, "SOLT/Through/Measurements/Port2", 1},
|
||||
{&SOLT.Through.Z0, "SOLT.Through.Param.Z0", 50.0},
|
||||
{&SOLT.Through.delay, "SOLT.Through.Param.Delay", 0.0},
|
||||
{&SOLT.Through.loss, "SOLT.Through.Param.Loss", 0.0},
|
||||
{&SOLT.Through.useMeasurements, "SOLT.Through.Measurements.Use", false},
|
||||
{&SOLT.Through.file, "SOLT.Through.Measurements.File", ""},
|
||||
{&SOLT.Through.Sparam1, "SOLT.Through.Measurements.Port1", 0},
|
||||
{&SOLT.Through.Sparam2, "SOLT.Through.Measurements.Port2", 1},
|
||||
|
||||
{&SOLT.separate_male_female, "SOLT/SeparateMaleFemale", false},
|
||||
{&SOLT.separate_male_female, "SOLT.SeparateMaleFemale", false},
|
||||
|
||||
{&TRL.Through.Z0, "TRL/Through/Z0", 50.0},
|
||||
{&TRL.Reflection.isShort, "TRL/Reflect/isShort", false},
|
||||
{&TRL.Line.delay, "TRL/Line/Delay", 74.0},
|
||||
{&TRL.Line.minFreq, "TRL/Line/minFreq", 751000000.0},
|
||||
{&TRL.Line.maxFreq, "TRL/Line/maxFreq", 6000000000.0},
|
||||
{&TRL.Through.Z0, "TRL.Through.Z0", 50.0},
|
||||
{&TRL.Reflection.isShort, "TRL.Reflect.isShort", false},
|
||||
{&TRL.Line.delay, "TRL.Line.Delay", 74.0},
|
||||
{&TRL.Line.minFreq, "TRL.Line.minFreq", 751000000.0},
|
||||
{&TRL.Line.maxFreq, "TRL.Line.maxFreq", 6000000000.0},
|
||||
|
||||
{&startDialogWithSOLT, "StartDialogWithSOLT", true}
|
||||
}};
|
||||
|
@ -6,8 +6,12 @@
|
||||
#include <QSettings>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <map>
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -128,55 +132,34 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [=](){
|
||||
// apply GUI state to settings
|
||||
p->Startup.ConnectToFirstDevice = ui->StartupAutoconnect->isChecked();
|
||||
p->Startup.RememberSweepSettings = ui->StartupSweepLastUsed->isChecked();
|
||||
p->Startup.DefaultSweep.type = ui->StartupSweepType->currentText();
|
||||
p->Startup.DefaultSweep.f_start = ui->StartupSweepStart->value();
|
||||
p->Startup.DefaultSweep.f_stop = ui->StartupSweepStop->value();
|
||||
p->Startup.DefaultSweep.f_excitation = ui->StartupSweepLevel->value();
|
||||
p->Startup.DefaultSweep.dbm_start = ui->StartupSweepPowerStart->value();
|
||||
p->Startup.DefaultSweep.dbm_stop = ui->StartupSweepPowerStop->value();
|
||||
p->Startup.DefaultSweep.dbm_freq = ui->StartupSweepPowerFrequency->value();
|
||||
p->Startup.DefaultSweep.bandwidth = ui->StartupSweepBandwidth->value();
|
||||
p->Startup.DefaultSweep.points = ui->StartupSweepPoints->value();
|
||||
p->Startup.DefaultSweep.averaging = ui->StartupSweepAveraging->value();
|
||||
p->Startup.Generator.frequency = ui->StartupGeneratorFrequency->value();
|
||||
p->Startup.Generator.level = ui->StartupGeneratorLevel->value();
|
||||
p->Startup.SA.start = ui->StartupSAStart->value();
|
||||
p->Startup.SA.stop = ui->StartupSAStop->value();
|
||||
p->Startup.SA.RBW = ui->StartupSARBW->value();
|
||||
p->Startup.SA.window = ui->StartupSAWindow->currentIndex();
|
||||
p->Startup.SA.detector = ui->StartupSADetector->currentIndex();
|
||||
p->Startup.SA.signalID = ui->StartupSASignalID->isChecked();
|
||||
|
||||
p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
|
||||
p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked();
|
||||
p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked();
|
||||
p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked();
|
||||
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
|
||||
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
|
||||
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
||||
p->Acquisition.IF1 = ui->AcquisitionIF1->value();
|
||||
p->Acquisition.ADCprescaler = ui->AcquisitionADCpresc->value();
|
||||
p->Acquisition.DFTPhaseInc = ui->AcquisitionADCphaseInc->value();
|
||||
|
||||
p->Graphs.showUnits = ui->GraphsShowUnit->isChecked();
|
||||
p->Graphs.Color.background = ui->GraphsColorBackground->getColor();
|
||||
p->Graphs.Color.axis = ui->GraphsColorAxis->getColor();
|
||||
p->Graphs.Color.Ticks.Background.enabled = ui->GraphsColorTicksBackgroundEnabled->isChecked();
|
||||
p->Graphs.Color.Ticks.Background.background = ui->GraphsColorTicksBackground->getColor();
|
||||
p->Graphs.Color.Ticks.divisions = ui->GraphsColorTicksDivisions->getColor();
|
||||
p->Graphs.domainChangeBehavior = (GraphDomainChangeBehavior) ui->GraphsDomainChangeBehavior->currentIndex();
|
||||
p->Graphs.lineWidth = ui->GraphsLineWidth->value();
|
||||
|
||||
p->Marker.defaultBehavior.showDataOnGraphs = ui->MarkerShowMarkerData->isChecked();
|
||||
p->Marker.defaultBehavior.showAllData = ui->MarkerShowAllMarkerData->isChecked();
|
||||
p->Marker.interpolatePoints = ui->MarkerInterpolate->currentIndex() == 1;
|
||||
|
||||
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
|
||||
p->SCPIServer.port = ui->SCPIServerPort->value();
|
||||
updateFromGUI();
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save preferences", "", "LibreVNA preferences files (*.vnapref)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(filename.length() > 0) {
|
||||
if(!filename.toLower().endsWith(".vnapref")) {
|
||||
filename.append(".vnapref");
|
||||
}
|
||||
ofstream file;
|
||||
file.open(filename.toStdString());
|
||||
updateFromGUI();
|
||||
file << setw(1) << p->toJSON();
|
||||
file.close();
|
||||
}
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Load preferences", "", "LibreVNA preferences files (*.vnapref)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(filename.length() > 0) {
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
nlohmann::json j;
|
||||
file >> j;
|
||||
file.close();
|
||||
p->fromJSON(j);
|
||||
setInitialGUIState();
|
||||
}
|
||||
});
|
||||
|
||||
setInitialGUIState();
|
||||
updateADCRate();
|
||||
@ -259,6 +242,57 @@ void PreferencesDialog::setInitialGUIState()
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::updateFromGUI()
|
||||
{
|
||||
p->Startup.ConnectToFirstDevice = ui->StartupAutoconnect->isChecked();
|
||||
p->Startup.RememberSweepSettings = ui->StartupSweepLastUsed->isChecked();
|
||||
p->Startup.DefaultSweep.type = ui->StartupSweepType->currentText();
|
||||
p->Startup.DefaultSweep.f_start = ui->StartupSweepStart->value();
|
||||
p->Startup.DefaultSweep.f_stop = ui->StartupSweepStop->value();
|
||||
p->Startup.DefaultSweep.f_excitation = ui->StartupSweepLevel->value();
|
||||
p->Startup.DefaultSweep.dbm_start = ui->StartupSweepPowerStart->value();
|
||||
p->Startup.DefaultSweep.dbm_stop = ui->StartupSweepPowerStop->value();
|
||||
p->Startup.DefaultSweep.dbm_freq = ui->StartupSweepPowerFrequency->value();
|
||||
p->Startup.DefaultSweep.bandwidth = ui->StartupSweepBandwidth->value();
|
||||
p->Startup.DefaultSweep.points = ui->StartupSweepPoints->value();
|
||||
p->Startup.DefaultSweep.averaging = ui->StartupSweepAveraging->value();
|
||||
p->Startup.Generator.frequency = ui->StartupGeneratorFrequency->value();
|
||||
p->Startup.Generator.level = ui->StartupGeneratorLevel->value();
|
||||
p->Startup.SA.start = ui->StartupSAStart->value();
|
||||
p->Startup.SA.stop = ui->StartupSAStop->value();
|
||||
p->Startup.SA.RBW = ui->StartupSARBW->value();
|
||||
p->Startup.SA.window = ui->StartupSAWindow->currentIndex();
|
||||
p->Startup.SA.detector = ui->StartupSADetector->currentIndex();
|
||||
p->Startup.SA.signalID = ui->StartupSASignalID->isChecked();
|
||||
|
||||
p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
|
||||
p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked();
|
||||
p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked();
|
||||
p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked();
|
||||
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
|
||||
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
|
||||
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
||||
p->Acquisition.IF1 = ui->AcquisitionIF1->value();
|
||||
p->Acquisition.ADCprescaler = ui->AcquisitionADCpresc->value();
|
||||
p->Acquisition.DFTPhaseInc = ui->AcquisitionADCphaseInc->value();
|
||||
|
||||
p->Graphs.showUnits = ui->GraphsShowUnit->isChecked();
|
||||
p->Graphs.Color.background = ui->GraphsColorBackground->getColor();
|
||||
p->Graphs.Color.axis = ui->GraphsColorAxis->getColor();
|
||||
p->Graphs.Color.Ticks.Background.enabled = ui->GraphsColorTicksBackgroundEnabled->isChecked();
|
||||
p->Graphs.Color.Ticks.Background.background = ui->GraphsColorTicksBackground->getColor();
|
||||
p->Graphs.Color.Ticks.divisions = ui->GraphsColorTicksDivisions->getColor();
|
||||
p->Graphs.domainChangeBehavior = (GraphDomainChangeBehavior) ui->GraphsDomainChangeBehavior->currentIndex();
|
||||
p->Graphs.lineWidth = ui->GraphsLineWidth->value();
|
||||
|
||||
p->Marker.defaultBehavior.showDataOnGraphs = ui->MarkerShowMarkerData->isChecked();
|
||||
p->Marker.defaultBehavior.showAllData = ui->MarkerShowAllMarkerData->isChecked();
|
||||
p->Marker.interpolatePoints = ui->MarkerInterpolate->currentIndex() == 1;
|
||||
|
||||
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
|
||||
p->SCPIServer.port = ui->SCPIServerPort->value();
|
||||
}
|
||||
|
||||
void Preferences::load()
|
||||
{
|
||||
QSettings settings;
|
||||
@ -296,3 +330,13 @@ void Preferences::setDefault()
|
||||
d.var.setValue(d.def);
|
||||
}
|
||||
}
|
||||
|
||||
void Preferences::fromJSON(nlohmann::json j)
|
||||
{
|
||||
parseJSON(j, descr);
|
||||
}
|
||||
|
||||
nlohmann::json Preferences::toJSON()
|
||||
{
|
||||
return createJSON(descr);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define PREFERENCESDIALOG_H
|
||||
|
||||
#include "Util/qpointervariant.h"
|
||||
#include "savable.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QVariant>
|
||||
@ -16,7 +17,7 @@ enum GraphDomainChangeBehavior {
|
||||
Q_DECLARE_METATYPE(GraphDomainChangeBehavior);
|
||||
|
||||
|
||||
class Preferences {
|
||||
class Preferences : public Savable {
|
||||
public:
|
||||
static Preferences& getInstance() {
|
||||
return instance;
|
||||
@ -104,16 +105,16 @@ public:
|
||||
} SCPIServer;
|
||||
|
||||
bool TCPoverride; // in case of manual port specification via command line
|
||||
|
||||
void fromJSON(nlohmann::json j) override;
|
||||
nlohmann::json toJSON() override;
|
||||
|
||||
private:
|
||||
Preferences() :
|
||||
TCPoverride(false) {};
|
||||
static Preferences instance;
|
||||
using SettingDescription = struct {
|
||||
QPointerVariant var;
|
||||
QString name;
|
||||
QVariant def;
|
||||
};
|
||||
const std::array<SettingDescription, 45> descr = {{
|
||||
|
||||
const std::vector<Savable::SettingDescription> descr = {{
|
||||
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
||||
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
||||
{&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"},
|
||||
@ -176,6 +177,7 @@ public:
|
||||
|
||||
private:
|
||||
void setInitialGUIState();
|
||||
void updateFromGUI();
|
||||
Ui::PreferencesDialog *ui;
|
||||
Preferences *p;
|
||||
};
|
||||
|
@ -1144,7 +1144,7 @@
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
|
||||
<set>QDialogButtonBox::Ok|QDialogButtonBox::Open|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
|
@ -2,11 +2,87 @@
|
||||
#define SAVABLE_H
|
||||
|
||||
#include "json.hpp"
|
||||
#include "Util/qpointervariant.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QColor>
|
||||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
|
||||
class Savable {
|
||||
public:
|
||||
virtual nlohmann::json toJSON() = 0;
|
||||
virtual void fromJSON(nlohmann::json j) = 0;
|
||||
|
||||
using SettingDescription = struct {
|
||||
QPointerVariant var;
|
||||
QString name;
|
||||
QVariant def;
|
||||
};
|
||||
static void parseJSON(nlohmann::json j, std::vector<SettingDescription> descr) {
|
||||
for(auto e : descr) {
|
||||
auto list = e.name.split(".");
|
||||
auto *json_entry = &j;
|
||||
bool entry_exists = true;
|
||||
while(list.size() > 0) {
|
||||
auto key = list.takeFirst().toStdString();
|
||||
if((*json_entry).contains(key)) {
|
||||
json_entry = &(*json_entry)[key];
|
||||
} else {
|
||||
entry_exists = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!entry_exists) {
|
||||
// missing entry in json file, nothing to do (default values already set in constructor)
|
||||
qWarning() << "Entry" << e.name << "not present in file";
|
||||
continue;
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: e.var.setValue((*json_entry).get<double>()); break;
|
||||
case QMetaType::Int: e.var.setValue((*json_entry).get<int>()); break;
|
||||
case QMetaType::Bool: e.var.setValue((*json_entry).get<bool>()); break;
|
||||
case QMetaType::QString: {
|
||||
auto s = QString::fromStdString((*json_entry).get<std::string>());
|
||||
e.var.setValue(s);
|
||||
}
|
||||
break;
|
||||
case QMetaType::QColor: {
|
||||
auto s = QString::fromStdString((*json_entry).get<std::string>());
|
||||
e.var.setValue(QColor(s));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unimplemented metatype:"+std::string(val.typeName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
static nlohmann::json createJSON(std::vector<SettingDescription> descr) {
|
||||
nlohmann::json j;
|
||||
for(auto e : descr) {
|
||||
auto list = e.name.split(".");
|
||||
auto *json_entry = &j;
|
||||
while(list.size() > 0) {
|
||||
json_entry = &(*json_entry)[list.takeFirst().toStdString()];
|
||||
}
|
||||
// json library does not now about QVariant, handle used cases
|
||||
auto val = e.var.value();
|
||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||
case QMetaType::Double: *json_entry = val.toDouble(); break;
|
||||
case QMetaType::Int: *json_entry = val.toInt(); break;
|
||||
case QMetaType::Bool: *json_entry = val.toBool(); break;
|
||||
case QMetaType::QString: *json_entry = val.toString().toStdString(); break;
|
||||
case QMetaType::QColor: *json_entry = val.value<QColor>().name().toStdString(); break;
|
||||
default:
|
||||
throw std::runtime_error("Unimplemented metatype:"+std::string(val.typeName()));
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SAVABLE_H
|
||||
|
Loading…
Reference in New Issue
Block a user