#ifndef PREFERENCESDIALOG_H #define PREFERENCESDIALOG_H #include "Util/qpointervariant.h" #include "savable.h" #include "Traces/traceaxis.h" #include "CustomWidgets/siunitedit.h" #include "Device/LibreVNA/Compound/compounddevice.h" #include #include #include #include enum GraphDomainChangeBehavior { RemoveChangedTraces = 0, AdjustGraphs = 1, AdjustGrahpsIfOnlyTrace = 2, }; Q_DECLARE_METATYPE(GraphDomainChangeBehavior) enum GraphLimitIndication { DontShowAnything = 0, PassFailText = 1, Overlay = 2, }; Q_DECLARE_METATYPE(GraphLimitIndication) enum MarkerSortOrder { PrefMarkerSortXCoord = 0, PrefMarkerSortNumber = 1, PrefMarkerSortTimestamp = 2, }; Q_DECLARE_METATYPE(MarkerSortOrder) enum MarkerSymbolStyle { FilledNumberInside = 0, FilledNumberAbove = 1, EmptyNumberAbove = 2, }; Q_DECLARE_METATYPE(MarkerSymbolStyle); class Preferences : public QObject, public Savable { Q_OBJECT friend class PreferencesDialog; public: static Preferences& getInstance() { return instance; } Preferences(const Preferences&) = delete; ~Preferences(); void load(); void load(std::vector descr); void store(); void store(std::vector descr); void edit(); void setDefault(); void setDefault(std::vector descr); void manualTCPport() { TCPoverride = true; } static QFileDialog::Options QFileDialogOptions(QFileDialog::Options option = (QFileDialog::Options) 0x00000000); struct { bool ConnectToFirstDevice; bool RememberSweepSettings; bool UseSetupFile; bool AutosaveSetupFile; QString SetupFile; struct { QString type; double f_start; double f_stop; bool logSweep; double f_excitation; double dbm_start; double dbm_stop; double dbm_freq; int points; double bandwidth; int averaging; double dwellTime; } DefaultSweep; struct { double frequency; double level; } Generator; struct { double start; double stop; double RBW; int window; int detector; int averaging; } SA; } Startup; struct { // VNA settings bool alwaysExciteAllPorts; bool allowSegmentedSweep; bool allowUseOfUnstableLibreCALTemp; bool useMedianAveraging; // Full span settings bool fullSpanManual; double fullSpanStart; double fullSpanStop; bool fullSpanCalibratedRange; // Math settings bool limitDFT; double maxDFTrate; int groupDelaySamples; } Acquisition; struct { bool showUnits; struct { QColor background; QColor axis; struct { QColor divisions; struct { bool enabled; QColor background; } Background; } Ticks; } Color; GraphDomainChangeBehavior domainChangeBehavior; GraphLimitIndication limitIndication; bool limitNaNpasses; double lineWidth; int fontSizeTitle; int fontSizeAxis; int fontSizeMarkerData; int fontSizeTraceNames; int fontSizeCursorOverlay; bool enablePanAndZoom; double zoomFactor; bool enableMasterTicksForYAxis; struct { bool triangle; int triangleSize; bool line; bool hide; double hidePercent; } SweepIndicator; struct { QString transmission; QString reflection; } defaultGraphs; struct { double min[(int) YAxis::Type::Last]; double max[(int) YAxis::Type::Last]; } defaultAxisLimits; } Graphs; struct { struct { bool showDataOnGraphs; bool showdB, showdBm, showdBuV, showdBAngle, showRealImag, showImpedance, showVSWR, showResistance, showCapacitance, showInductance, showQualityFactor, showGroupDelay; bool showNoise, showPhasenoise, showCenterBandwidth, showCutoff, showInsertionLoss, showTOI, showAvgTone, showAvgModulation, showP1dB, showFlatness, showMaxDeltaNeg, showMaxDeltaPos; } defaultBehavior; bool interpolatePoints; MarkerSortOrder sortOrder; MarkerSymbolStyle symbolStyle; bool clipToYAxis; } Marker; struct { bool enabled; int port; } SCPIServer; struct { struct { bool enabled; int port; } VNARawData; struct { bool enabled; int port; } VNACalibratedData; struct { bool enabled; int port; } VNADeembeddedData; struct { bool enabled; int port; } SARawData; struct { bool enabled; int port; } SANormalizedData; } StreamingServers; struct { double USBlogSizeLimit; bool saveTraceData; bool useNativeDialogs; } Debug; struct { struct { unsigned int ports; unsigned int formatIndex; unsigned int unitIndex; QString exportedTraceNames; } TouchstoneExport; struct { QString setup; QString cal; QString calkit; QString data; QString image; QString vnacaldata; QString packetlog; QString limitLines; QString pref; QString firmware; } Paths; qsizetype saveImageFilterIndex; } UISettings; bool TCPoverride; // in case of manual port specification via command line void fromJSON(nlohmann::json j) override; nlohmann::json toJSON() override; bool set(QString name, QVariant value); QVariant get(QString name); signals: void updated(); private: Preferences() : TCPoverride(false) {} void nonTrivialParsing(); void nonTrivialWriting(); static Preferences instance; // TODO remove settings that have been moved to LibreVNADriver const std::vector descr = {{ {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, {&Startup.UseSetupFile, "Startup.UseSetupFile", false}, {&Startup.SetupFile, "Startup.SetupFile", ""}, {&Startup.AutosaveSetupFile, "Startup.AutosaveSetupFile", false}, {&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"}, {&Startup.DefaultSweep.f_start, "Startup.DefaultSweep.start", 1000000.0}, {&Startup.DefaultSweep.f_stop, "Startup.DefaultSweep.stop", 6000000000.0}, {&Startup.DefaultSweep.logSweep, "Startup.DefaultSweep.logSweep", false}, {&Startup.DefaultSweep.f_excitation, "Startup.DefaultSweep.excitation", -10.00}, {&Startup.DefaultSweep.dbm_start, "Startup.DefaultSweep.dbm_start", -30.00}, {&Startup.DefaultSweep.dbm_stop, "Startup.DefaultSweep.dbm_stop", -10.0}, {&Startup.DefaultSweep.dbm_freq, "Startup.DefaultSweep.dbm_freq", 1000000000.0}, {&Startup.DefaultSweep.points, "Startup.DefaultSweep.points", 501}, {&Startup.DefaultSweep.bandwidth, "Startup.DefaultSweep.bandwidth", 1000.0}, {&Startup.DefaultSweep.averaging, "Startup.DefaultSweep.averaging", 1}, {&Startup.DefaultSweep.dwellTime, "Startup.DefaultSweep.dwellTime", 0.0}, {&Startup.Generator.frequency, "Startup.Generator.frequency", 1000000000.0}, {&Startup.Generator.level, "Startup.Generator.level", -10.00}, {&Startup.SA.start, "Startup.SA.start", 950000000.0}, {&Startup.SA.stop, "Startup.SA.stop", 1050000000.0}, {&Startup.SA.RBW, "Startup.SA.RBW", 10000.0}, {&Startup.SA.window, "Startup.SA.window", 1}, {&Startup.SA.detector, "Startup.SA.detector", 0}, {&Startup.SA.averaging, "Startup.SA.averaging", 1}, {&Acquisition.alwaysExciteAllPorts, "Acquisition.alwaysExciteBothPorts", true}, {&Acquisition.allowSegmentedSweep, "Acquisition.allowSegmentedSweep", true}, {&Acquisition.allowUseOfUnstableLibreCALTemp, "Acquisition.allowUseOfUnstableLibreCALTemp", true}, {&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false}, {&Acquisition.fullSpanManual, "Acquisition.fullSpanManual", false}, {&Acquisition.fullSpanStart, "Acquisition.fullSpanStart", 0.0}, {&Acquisition.fullSpanStop, "Acquisition.fullSpanStop", 6000000000.0}, {&Acquisition.fullSpanCalibratedRange, "Acquisition.fullSpanCalibratedRange", false}, {&Acquisition.limitDFT, "Acquisition.limitDFT", true}, {&Acquisition.maxDFTrate, "Acquisition.maxDFTrate", 1.0}, {&Acquisition.groupDelaySamples, "Acquisition.groupDelaySamples", 5}, {&Graphs.showUnits, "Graphs.showUnits", true}, {&Graphs.Color.background, "Graphs.Color.background", QColor(Qt::black)}, {&Graphs.Color.axis, "Graphs.Color.axis", QColor(Qt::white)}, {&Graphs.Color.Ticks.Background.enabled, "Graphs.Color.Ticks.Background.enabled", true}, {&Graphs.Color.Ticks.Background.background, "Graphs.Color.Ticks.Background.background", QColor(20, 20, 20)}, {&Graphs.Color.Ticks.divisions, "Graphs.Color.Ticks.divisions", QColor(Qt::gray)}, {&Graphs.domainChangeBehavior, "Graphs.domainChangeBehavior", GraphDomainChangeBehavior::AdjustGraphs}, {&Graphs.limitIndication, "Graphs.limitIndication", GraphLimitIndication::PassFailText}, {&Graphs.limitNaNpasses, "Graphs.limitNaNpasses", false}, {&Graphs.lineWidth, "Graphs.lineWidth", 1.0}, {&Graphs.fontSizeTitle, "Graphs.fontSizeTitle", 18}, {&Graphs.fontSizeAxis, "Graphs.fontSizeAxis", 10}, {&Graphs.fontSizeCursorOverlay, "Graphs.fontSizeCursorOverlay", 12}, {&Graphs.fontSizeMarkerData, "Graphs.fontSizeMarkerData", 12}, {&Graphs.fontSizeTraceNames, "Graphs.fontSizeTraceNames", 12}, {&Graphs.enablePanAndZoom, "Graphs.enablePanAndZoom", true}, {&Graphs.zoomFactor, "Graphs.zoomFactor", 0.9}, {&Graphs.enableMasterTicksForYAxis, "Graphs.enableMasterTicksForYAxis", false}, {&Graphs.SweepIndicator.triangle, "Graphs.SweepIndicator.triangle", true}, {&Graphs.SweepIndicator.triangleSize, "Graphs.SweepIndicator.triangleSize", 5}, {&Graphs.SweepIndicator.line, "Graphs.SweepIndicator.line", false}, {&Graphs.SweepIndicator.hide, "Graphs.SweepIndicator.hide", false}, {&Graphs.SweepIndicator.hidePercent, "Graphs.SweepIndicator.hidePercent", 3.0}, {&Graphs.defaultGraphs.transmission, "Graphs.defaultGraphs.transmission", "XY Plot"}, {&Graphs.defaultGraphs.reflection, "Graphs.defaultGraphs.reflection", "Smith Chart"}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Magnitude], "Graphs.defaultAxisLimits.Magnitude.max", 20.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Magnitude], "Graphs.defaultAxisLimits.Magnitude.min", -120.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::MagnitudedBuV], "Graphs.defaultAxisLimits.MagnitudedBuV.max", 128.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::MagnitudedBuV], "Graphs.defaultAxisLimits.MagnitudedBuV.min", -13.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::MagnitudeLinear], "Graphs.defaultAxisLimits.MagnitudeLinear.max", 1.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::MagnitudeLinear], "Graphs.defaultAxisLimits.MagnitudeLinear.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Phase], "Graphs.defaultAxisLimits.Phase.max",180.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Phase], "Graphs.defaultAxisLimits.Phase.min", -180.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::UnwrappedPhase], "Graphs.defaultAxisLimits.UnwrappedPhase.max", 0.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::UnwrappedPhase], "Graphs.defaultAxisLimits.UnwrappedPhase.min", -360.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::VSWR], "Graphs.defaultAxisLimits.VSWR.max", 10.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::VSWR], "Graphs.defaultAxisLimits.VSWR.min", 1.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Real], "Graphs.defaultAxisLimits.Real.max", 1.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Real], "Graphs.defaultAxisLimits.Real.min", -1.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Imaginary], "Graphs.defaultAxisLimits.Imaginary.max", 1.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Imaginary], "Graphs.defaultAxisLimits.Imaginary.min", -1.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::AbsImpedance], "Graphs.defaultAxisLimits.AbsImpedance.max", 100.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::AbsImpedance], "Graphs.defaultAxisLimits.AbsImpedance.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::SeriesR], "Graphs.defaultAxisLimits.SeriesR.max", 100.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::SeriesR], "Graphs.defaultAxisLimits.SeriesR.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Reactance], "Graphs.defaultAxisLimits.Reactance.max", 100.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Reactance], "Graphs.defaultAxisLimits.Reactance.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Capacitance], "Graphs.defaultAxisLimits.Capacitance.max", 10e-6}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Capacitance], "Graphs.defaultAxisLimits.Capacitance.min", 0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Inductance], "Graphs.defaultAxisLimits.Inductance.max", 1e-3}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Inductance], "Graphs.defaultAxisLimits.Inductance.min", 0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::QualityFactor], "Graphs.defaultAxisLimits.QualityFactor.max", 100.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::QualityFactor], "Graphs.defaultAxisLimits.QualityFactor.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::GroupDelay], "Graphs.defaultAxisLimits.GroupDelay.max", 1e-6}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::GroupDelay], "Graphs.defaultAxisLimits.GroupDelay.min", 0.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::ImpulseReal], "Graphs.defaultAxisLimits.ImpulseReal.max", 1.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::ImpulseReal], "Graphs.defaultAxisLimits.ImpulseReal.min", -1.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::ImpulseMag], "Graphs.defaultAxisLimits.ImpulseMag.max", 0.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::ImpulseMag], "Graphs.defaultAxisLimits.ImpulseMag.min", -100.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Step], "Graphs.defaultAxisLimits.Step.max", 1.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Step], "Graphs.defaultAxisLimits.Step.min", -1.0}, {&Graphs.defaultAxisLimits.max[(int) YAxis::Type::Impedance], "Graphs.defaultAxisLimits.Impedance.max", 100.0}, {&Graphs.defaultAxisLimits.min[(int) YAxis::Type::Impedance], "Graphs.defaultAxisLimits.Impedance.min", 0.0}, {&Marker.defaultBehavior.showDataOnGraphs, "Marker.defaultBehavior.ShowDataOnGraphs", true}, {&Marker.defaultBehavior.showdB, "Marker.defaultBehavior.showdB", true}, {&Marker.defaultBehavior.showdBm, "Marker.defaultBehavior.showdBm", true}, {&Marker.defaultBehavior.showdBuV, "Marker.defaultBehavior.showdBuV", true}, {&Marker.defaultBehavior.showdBAngle, "Marker.defaultBehavior.showdBAngle", true}, {&Marker.defaultBehavior.showRealImag, "Marker.defaultBehavior.showRealImag", true}, {&Marker.defaultBehavior.showVSWR, "Marker.defaultBehavior.showVSWR", true}, {&Marker.defaultBehavior.showImpedance, "Marker.defaultBehavior.showImpedance", true}, {&Marker.defaultBehavior.showResistance, "Marker.defaultBehavior.showResistance", true}, {&Marker.defaultBehavior.showCapacitance, "Marker.defaultBehavior.showCapacitance", true}, {&Marker.defaultBehavior.showInductance, "Marker.defaultBehavior.showInductance", true}, {&Marker.defaultBehavior.showQualityFactor, "Marker.defaultBehavior.showQualityFactor", true}, {&Marker.defaultBehavior.showGroupDelay, "Marker.defaultBehavior.showGroupDelay", true}, {&Marker.defaultBehavior.showNoise, "Marker.defaultBehavior.showNoise", true}, {&Marker.defaultBehavior.showPhasenoise, "Marker.defaultBehavior.showPhasenoise", true}, {&Marker.defaultBehavior.showCenterBandwidth, "Marker.defaultBehavior.showCenterBandwidth", true}, {&Marker.defaultBehavior.showCutoff, "Marker.defaultBehavior.showCutoff", true}, {&Marker.defaultBehavior.showInsertionLoss, "Marker.defaultBehavior.showInsertionLoss", true}, {&Marker.defaultBehavior.showTOI, "Marker.defaultBehavior.showTOI", true}, {&Marker.defaultBehavior.showAvgTone, "Marker.defaultBehavior.showAvgTone", true}, {&Marker.defaultBehavior.showAvgModulation, "Marker.defaultBehavior.showAvgModulation", true}, {&Marker.defaultBehavior.showP1dB, "Marker.defaultBehavior.showP1dB", true}, {&Marker.defaultBehavior.showFlatness, "Marker.defaultBehavior.showNonUniformity", true}, {&Marker.defaultBehavior.showMaxDeltaNeg, "Marker.defaultBehavior.showMaxDeltaNeg", true}, {&Marker.defaultBehavior.showMaxDeltaPos, "Marker.defaultBehavior.showMaxDeltaPos", true}, {&Marker.interpolatePoints, "Marker.interpolatePoints", false}, {&Marker.sortOrder, "Marker.sortOrder", MarkerSortOrder::PrefMarkerSortXCoord}, {&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::FilledNumberAbove}, {&Marker.clipToYAxis, "Marker.clipToYAxis", true}, {&SCPIServer.enabled, "SCPIServer.enabled", true}, {&SCPIServer.port, "SCPIServer.port", 19542}, {&StreamingServers.VNARawData.enabled, "StreamingServers.VNARawData.enabled", false}, {&StreamingServers.VNARawData.port, "StreamingServers.VNARawData.port", 19000}, {&StreamingServers.VNACalibratedData.enabled, "StreamingServers.VNACalibratedData.enabled", false}, {&StreamingServers.VNACalibratedData.port, "StreamingServers.VNACalibratedData.port", 19001}, {&StreamingServers.VNADeembeddedData.enabled, "StreamingServers.VNADeembeddedData.enabled", false}, {&StreamingServers.VNADeembeddedData.port, "StreamingServers.VNADeembeddedData.port", 19002}, {&StreamingServers.SARawData.enabled, "StreamingServers.sARawData.enabled", false}, {&StreamingServers.SARawData.port, "StreamingServers.sARawData.port", 19100}, {&StreamingServers.SANormalizedData.enabled, "StreamingServers.SANormalizedData.enabled", false}, {&StreamingServers.SANormalizedData.port, "StreamingServers.SANormalizedData.port", 19101}, {&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0}, {&Debug.saveTraceData, "Debug.saveTraceData", false}, {&Debug.useNativeDialogs, "Debug.useNativeDialogs", true}, {&UISettings.TouchstoneExport.ports, "UISettings.TouchstoneExport.ports", 2}, {&UISettings.TouchstoneExport.formatIndex, "UISettings.TouchstoneExport.formatIndex", 2}, {&UISettings.TouchstoneExport.unitIndex, "UISettings.TouchstoneExport.unitIndex", 3}, {&UISettings.TouchstoneExport.exportedTraceNames, "UISettings.TouchstoneExport.exportedTraceNames", ""}, {&UISettings.Paths.setup, "UISettings.Paths.setup", ""}, {&UISettings.Paths.cal, "UISettings.Paths.cal", ""}, {&UISettings.Paths.calkit, "UISettings.Paths.calkit", ""}, {&UISettings.Paths.data, "UISettings.Paths.data", ""}, {&UISettings.Paths.image, "UISettings.Paths.image", ""}, {&UISettings.Paths.vnacaldata, "UISettings.Paths.vnacaldata", ""}, {&UISettings.Paths.packetlog, "UISettings.Paths.packetlog", ""}, {&UISettings.Paths.limitLines, "UISettings.Paths.limitLines", ""}, {&UISettings.Paths.pref, "UISettings.Paths.pref", ""}, {&UISettings.Paths.firmware, "UISettings.Paths.firmware", ""}, {&UISettings.saveImageFilterIndex, "UISettings.saveImageFilterIndex", 0}, }}; }; namespace Ui { class PreferencesDialog; } class PreferencesDialog : public QDialog { Q_OBJECT public: explicit PreferencesDialog(Preferences *pref, QWidget *parent = nullptr); ~PreferencesDialog(); private: void setInitialGUIState(); void updateFromGUI(); Ui::PreferencesDialog *ui; Preferences *p; std::map graphAxisLimitsMaxEntries; std::map graphAxisLimitsMinEntries; }; #endif // PREFERENCESDIALOG_H