diff --git a/Software/PC_Application/CustomWidgets/informationbox.cpp b/Software/PC_Application/CustomWidgets/informationbox.cpp index 20a4882..0713a06 100644 --- a/Software/PC_Application/CustomWidgets/informationbox.cpp +++ b/Software/PC_Application/CustomWidgets/informationbox.cpp @@ -20,6 +20,32 @@ void InformationBox::ShowMessage(QString title, QString message, QString message } } +bool InformationBox::AskQuestion(QString title, QString question, bool defaultAnswer, QString messageID) +{ + // check if the user still wants to see this message + unsigned int hash; + if(messageID.isEmpty()) { + hash = qHash(question); + } else { + hash = qHash(messageID); + } + + QSettings s; + if(!s.contains(hashToSettingsKey(hash))) { + auto box = new InformationBox(title, question, hash, nullptr); + box->setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int ret = box->exec(); + if(ret == QMessageBox::Yes) { + return true; + } else { + return false; + } + } else { + // don't show this question anymore + return defaultAnswer; + } +} + InformationBox::InformationBox(QString title, QString message, unsigned int hash, QWidget *parent) : QMessageBox(parent), hash(hash) diff --git a/Software/PC_Application/CustomWidgets/informationbox.h b/Software/PC_Application/CustomWidgets/informationbox.h index 0b06ca8..45f897f 100644 --- a/Software/PC_Application/CustomWidgets/informationbox.h +++ b/Software/PC_Application/CustomWidgets/informationbox.h @@ -8,6 +8,8 @@ class InformationBox : public QMessageBox Q_OBJECT public: static void ShowMessage(QString title, QString message, QString messageID = QString()); + // Display a dialog with yes/no buttons. Returns true if yes is clicked, false otherwise. If the user has selected to never see this message again, defaultAnswer is returned instead + static bool AskQuestion(QString title, QString question, bool defaultAnswer, QString messageID = QString()); private: InformationBox(QString title, QString message, unsigned int hash, QWidget *parent); ~InformationBox(); diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index fbd58b6..647814a 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -153,9 +153,9 @@ void TraceXYPlot::fromJSON(nlohmann::json j) auto xtype = jX.value("type", XAxisType::Frequency); auto xmode = jX.value("mode", XAxisMode::UseSpan); // auto xlog = jX.value("log", false); - auto xmin = jX.value("min", 0); - auto xmax = jX.value("max", 6000000000); - auto xdiv = jX.value("div", 600000000); + auto xmin = jX.value("min", 0.0); + auto xmax = jX.value("max", 6000000000.0); + auto xdiv = jX.value("div", 600000000.0); setXAxis(xtype, xmode, xmin, xmax, xdiv); nlohmann::json jY[2] = {j["YPrimary"], j["YSecondary"]}; for(unsigned int i=0;i<2;i++) { diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 393c708..6422a73 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -53,6 +53,7 @@ VNA::VNA(AppWindow *window) calValid = false; calMeasuring = false; calDialog.reset(); + calEdited = false; // Create default traces auto tS11 = new Trace("S11", Qt::yellow); @@ -104,10 +105,13 @@ VNA::VNA(AppWindow *window) } else { ApplyCalibration(cal.getType()); } + calEdited = false; }); connect(saveCal, &QAction::triggered, [=](){ - cal.saveToFile(); + if(cal.saveToFile()) { + calEdited = false; + } }); auto calDisable = calMenu->addAction("Disabled"); @@ -508,6 +512,16 @@ void VNA::deviceDisconnected() defaultCalMenu->setEnabled(false); } +void VNA::shutdown() +{ + if(calEdited && calValid) { + auto save = InformationBox::AskQuestion("Save calibration?", "The calibration contains data that has not been saved yet. Do you want to save it before exiting?", false); + if(save) { + cal.saveToFile(); + } + } +} + nlohmann::json VNA::toJSON() { nlohmann::json j; @@ -798,6 +812,7 @@ void VNA::StartCalibrationMeasurement(Calibration::Measurement m) // enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed) calMeasuring = true; }); + calEdited = true; } void VNA::ConstrainAndUpdateFrequencies() diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index e0968dc..e5d67ec 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -19,6 +19,7 @@ public: void deactivate() override; void initializeDevice() override; void deviceDisconnected() override; + void shutdown() override; // Only save/load user changeable stuff, no need to save the widgets/mode name etc. virtual nlohmann::json toJSON() override; @@ -67,6 +68,7 @@ private: // Calibration Calibration cal; bool calValid; + bool calEdited; Calibration::Measurement calMeasurement; bool calMeasuring; bool calWaitFirst; diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index 8d0a635..ccee4f9 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -184,6 +184,9 @@ AppWindow::~AppWindow() void AppWindow::closeEvent(QCloseEvent *event) { + vna->shutdown(); + generator->shutdown(); + spectrumAnalyzer->shutdown(); delete device; QSettings settings; settings.setValue("geometry", saveGeometry()); diff --git a/Software/PC_Application/mode.h b/Software/PC_Application/mode.h index 0aa4f08..931c5ae 100644 --- a/Software/PC_Application/mode.h +++ b/Software/PC_Application/mode.h @@ -17,6 +17,7 @@ public: virtual void activate(); // derived classes must call Mode::activate before doing anything virtual void deactivate(); // derived classes must call Mode::deactivate before returning + virtual void shutdown(){}; // called when the application is about to exit QString getName() const; static Mode *getActiveMode();