diff --git a/Software/PC_Application/Application b/Software/PC_Application/Application index 8a1ce8c..7d5b462 100755 Binary files a/Software/PC_Application/Application and b/Software/PC_Application/Application differ diff --git a/Software/PC_Application/Application.pro b/Software/PC_Application/Application.pro index ebc92fb..d3be828 100644 --- a/Software/PC_Application/Application.pro +++ b/Software/PC_Application/Application.pro @@ -34,7 +34,9 @@ HEADERS += \ Traces/tracesmithchart.h \ Traces/tracewidget.h \ averaging.h \ + preferences.h \ qwtplotpiecewisecurve.h \ + signalgenerator.h \ touchstone.h \ unit.h \ valueinput.h \ @@ -77,7 +79,9 @@ SOURCES += \ Traces/tracewidget.cpp \ averaging.cpp \ main.cpp \ + preferences.cpp \ qwtplotpiecewisecurve.cpp \ + signalgenerator.cpp \ touchstone.cpp \ unit.cpp \ valueinput.cpp \ @@ -106,7 +110,9 @@ FORMS += \ Traces/traceexportdialog.ui \ Traces/traceimportdialog.ui \ Traces/tracewidget.ui \ - main.ui + main.ui \ + preferencesdialog.ui \ + signalgenerator.ui DISTFILES += diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp index fe5c30d..322a1a1 100644 --- a/Software/PC_Application/Device/device.cpp +++ b/Software/PC_Application/Device/device.cpp @@ -305,17 +305,26 @@ void Device::ReceivedData() do { handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet); dataBuffer->removeBytes(handled_len); - if(packet.type == Protocol::PacketType::Datapoint) { + switch(packet.type) { + case Protocol::PacketType::Datapoint: emit DatapointReceived(packet.datapoint); - } else if(packet.type == Protocol::PacketType::Status) { - qDebug() << "Got status"; + break; + case Protocol::PacketType::Status: emit ManualStatusReceived(packet.status); - } else if(packet.type == Protocol::PacketType::DeviceInfo) { + break; + case Protocol::PacketType::DeviceInfo: lastInfo = packet.info; lastInfoValid = true; emit DeviceInfoUpdated(); - } else if(packet.type == Protocol::PacketType::Ack) { + break; + case Protocol::PacketType::Ack: emit AckReceived(); + break; + case Protocol::PacketType::Nack: + emit NackReceived(); + break; + default: + break; } } while (handled_len > 0); } diff --git a/Software/PC_Application/Device/device.h b/Software/PC_Application/Device/device.h index fa68b4e..89fa5ae 100644 --- a/Software/PC_Application/Device/device.h +++ b/Software/PC_Application/Device/device.h @@ -62,6 +62,7 @@ signals: void DeviceInfoUpdated(); void ConnectionLost(); void AckReceived(); + void NackReceived(); void LogLineReceived(QString line); private slots: void ReceivedData(); diff --git a/Software/PC_Application/Device/firmwareupdatedialog.cpp b/Software/PC_Application/Device/firmwareupdatedialog.cpp index 6c0751d..9b0b897 100644 --- a/Software/PC_Application/Device/firmwareupdatedialog.cpp +++ b/Software/PC_Application/Device/firmwareupdatedialog.cpp @@ -58,6 +58,8 @@ void FirmwareUpdateDialog::on_bStart_clicked() return; } state = State::ErasingFLASH; + connect(dev, &Device::AckReceived, this, &FirmwareUpdateDialog::receivedAck); + connect(dev, &Device::NackReceived, this, &FirmwareUpdateDialog::receivedNack); addStatus("Erasing device memory..."); dev->SendCommandWithoutPayload(Protocol::PacketType::ClearFlash); timer.setSingleShot(true); @@ -71,6 +73,9 @@ void FirmwareUpdateDialog::addStatus(QString line) void FirmwareUpdateDialog::abortWithError(QString error) { + disconnect(dev, &Device::AckReceived, this, &FirmwareUpdateDialog::receivedAck); + disconnect(dev, &Device::NackReceived, this, &FirmwareUpdateDialog::receivedNack); + QTextCharFormat tf; tf = ui->status->currentCharFormat(); tf.setForeground(QBrush(Qt::red)); @@ -94,6 +99,9 @@ void FirmwareUpdateDialog::timerCallback() dev = new Device(serialnumber); addStatus("...device reattached, update complete"); timer.stop(); + ui->bStart->setEnabled(true); + disconnect(dev, &Device::AckReceived, this, &FirmwareUpdateDialog::receivedAck); + disconnect(dev, &Device::NackReceived, this, &FirmwareUpdateDialog::receivedNack); } } } @@ -139,6 +147,11 @@ void FirmwareUpdateDialog::receivedAck() } } +void FirmwareUpdateDialog::receivedNack() +{ + abortWithError("Nack received, device does not support firmware update"); +} + void FirmwareUpdateDialog::sendNextFirmwareChunk() { Protocol::FirmwarePacket fw; diff --git a/Software/PC_Application/Device/firmwareupdatedialog.h b/Software/PC_Application/Device/firmwareupdatedialog.h index 8f0978a..8404a62 100644 --- a/Software/PC_Application/Device/firmwareupdatedialog.h +++ b/Software/PC_Application/Device/firmwareupdatedialog.h @@ -29,11 +29,12 @@ private slots: void on_bFile_clicked(); void on_bStart_clicked(); void timerCallback(); + void receivedAck(); + void receivedNack(); private: void addStatus(QString line); void abortWithError(QString error); - void receivedAck(); void sendNextFirmwareChunk(); Ui::FirmwareUpdateDialog *ui; Device *&dev; diff --git a/Software/PC_Application/Traces/tracebodeplot.cpp b/Software/PC_Application/Traces/tracebodeplot.cpp index 857162f..05b648c 100644 --- a/Software/PC_Application/Traces/tracebodeplot.cpp +++ b/Software/PC_Application/Traces/tracebodeplot.cpp @@ -396,7 +396,7 @@ bool TraceBodePlot::supported(Trace *t, TraceBodePlot::YAxisType type) void TraceBodePlot::updateXAxis() { - if(XAxis.autorange) { + if(XAxis.autorange && sweep_fmax-sweep_fmin > 0) { QList tickList; for(double tick = sweep_fmin;tick <= sweep_fmax;tick+= (sweep_fmax-sweep_fmin)/10) { tickList.append(tick); diff --git a/Software/PC_Application/Traces/tracemarkermodel.cpp b/Software/PC_Application/Traces/tracemarkermodel.cpp index b594cd6..636b64c 100644 --- a/Software/PC_Application/Traces/tracemarkermodel.cpp +++ b/Software/PC_Application/Traces/tracemarkermodel.cpp @@ -47,6 +47,8 @@ void TraceMarkerModel::removeMarker(unsigned int index, bool delete_marker) if (index < markers.size()) { beginRemoveRows(QModelIndex(), index, index); if(delete_marker) { + // disconnect from deleted signal prior to deleting the marker. Otherwise a second (possibly non-existent) will be erased from the list + disconnect(markers[index], &TraceMarker::deleted, this, qOverload(&TraceMarkerModel::removeMarker)); delete markers[index]; } markers.erase(markers.begin() + index); diff --git a/Software/PC_Application/Traces/tracesmithchart.cpp b/Software/PC_Application/Traces/tracesmithchart.cpp index 5d56041..07a5828 100644 --- a/Software/PC_Application/Traces/tracesmithchart.cpp +++ b/Software/PC_Application/Traces/tracesmithchart.cpp @@ -63,6 +63,9 @@ void TraceSmithChart::mouseMoveEvent(QMouseEvent *event) auto t = selectedMarker->trace(); auto mouseS = pixelToPlot(event->pos()); auto samples = t->size(); + if(!samples) { + return; + } double closestDistance = numeric_limits::max(); unsigned int closestIndex = 0; for(unsigned int i=0;idrawLine(std::real(last), -std::imag(last), std::real(now), -std::imag(now)); } - auto markers = t.first->getMarkers(); - for(auto m : markers) { - auto coords = m->getData(); - coords *= smithCoordMax; - auto symbol = m->getSymbol(); - symbol = symbol.scaled(symbol.width()*width_factor, symbol.height()*width_factor); - painter->drawPixmap(coords.real() - symbol.width()/2, -coords.imag() - symbol.height(), symbol); + if(trace->size() > 0) { + // only draw markers if the trace has at least one point + auto markers = t.first->getMarkers(); + for(auto m : markers) { + auto coords = m->getData(); + coords *= smithCoordMax; + auto symbol = m->getSymbol(); + symbol = symbol.scaled(symbol.width()*width_factor, symbol.height()*width_factor); + painter->drawPixmap(coords.real() - symbol.width()/2, -coords.imag() - symbol.height(), symbol); + } } } } diff --git a/Software/PC_Application/Traces/tracewidget.ui b/Software/PC_Application/Traces/tracewidget.ui index e0ddffc..24a1ea8 100644 --- a/Software/PC_Application/Traces/tracewidget.ui +++ b/Software/PC_Application/Traces/tracewidget.ui @@ -92,7 +92,8 @@ - + + .. @@ -117,12 +118,19 @@ - + + .. + + + 0 + 0 + + Import @@ -137,6 +145,12 @@ + + + 0 + 0 + + Export @@ -164,7 +178,8 @@ - + + .. diff --git a/Software/PC_Application/main.ui b/Software/PC_Application/main.ui index d8b9f12..3642195 100644 --- a/Software/PC_Application/main.ui +++ b/Software/PC_Application/main.ui @@ -84,6 +84,7 @@ + @@ -206,6 +207,16 @@ Firmware Update + + + Preferences + + + + + Dummy + + diff --git a/Software/PC_Application/preferences.cpp b/Software/PC_Application/preferences.cpp new file mode 100644 index 0000000..ef43cc5 --- /dev/null +++ b/Software/PC_Application/preferences.cpp @@ -0,0 +1,128 @@ +#include "preferences.h" +#include "ui_preferencesdialog.h" +#include +#include +#include +#include + +using namespace std; + +PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) : + QDialog(parent), + ui(new Ui::PreferencesDialog), + p(pref) +{ + ui->setupUi(this); + + // Setup GUI connections and adjustments + // Startup page + connect(ui->StartupSweepLastUsed, &QPushButton::clicked, [=](){ + ui->StartupSweepStart->setEnabled(false); + ui->StartupSweepStop->setEnabled(false); + ui->StartupSweepPoints->setEnabled(false); + ui->StartupSweepLevel->setEnabled(false); + ui->StartupSweepBandwidth->setEnabled(false); + }); + connect(ui->StartupSweepDefault, &QPushButton::clicked, [=](){ + ui->StartupSweepStart->setEnabled(true); + ui->StartupSweepStop->setEnabled(true); + ui->StartupSweepPoints->setEnabled(true); + ui->StartupSweepLevel->setEnabled(true); + ui->StartupSweepBandwidth->setEnabled(true); + }); + ui->StartupSweepStart->setUnit("Hz"); + ui->StartupSweepStart->setPrefixes(" kMG"); + ui->StartupSweepStop->setUnit("Hz"); + ui->StartupSweepStop->setPrefixes(" kMG"); + ui->StartupSweepBandwidth->setUnit("Hz"); + ui->StartupSweepBandwidth->setPrefixes(" k"); + + // Page selection + connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) { + auto name = current->text(0); + for(int i=0;ipageWidget->count();i++) { + auto w = ui->pageWidget->widget(i); + if(name == w->objectName()) { + // found the correct page, set to front + ui->pageWidget->setCurrentWidget(w); + break; + } + } + }); + + // Reset and OK action + connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, [=](){ + if(QMessageBox::question(this, "Restore defaults?", "Do you really want to set all preferences to their default values?") == QMessageBox::StandardButton::Yes) { + p->setDefault(); + setInitialGUIState(); + } + }); + 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.start = ui->StartupSweepStart->value(); + p->Startup.DefaultSweep.stop = ui->StartupSweepStop->value(); + p->Startup.DefaultSweep.bandwidth = ui->StartupSweepBandwidth->value(); + p->Startup.DefaultSweep.points = ui->StartupSweepPoints->value(); + p->Startup.DefaultSweep.excitation = ui->StartupSweepLevel->value(); + accept(); + }); + + setInitialGUIState(); +} + +PreferencesDialog::~PreferencesDialog() +{ + delete ui; +} + +void PreferencesDialog::setInitialGUIState() +{ + ui->StartupAutoconnect->setChecked(p->Startup.ConnectToFirstDevice); + if(p->Startup.RememberSweepSettings) { + ui->StartupSweepLastUsed->click(); + } else { + ui->StartupSweepDefault->click(); + } + ui->StartupSweepStart->setValueQuiet(p->Startup.DefaultSweep.start); + ui->StartupSweepStop->setValueQuiet(p->Startup.DefaultSweep.stop); + ui->StartupSweepBandwidth->setValueQuiet(p->Startup.DefaultSweep.bandwidth); + ui->StartupSweepPoints->setValue(p->Startup.DefaultSweep.points); + ui->StartupSweepLevel->setValue(p->Startup.DefaultSweep.excitation); +} + +void Preferences::load() +{ + QSettings settings; + // load settings, using default values if not present + for(auto d : descr) { + try { + d.var.setValue(settings.value(d.name, d.def)); + } catch (const exception& e){ + d.var.setValue(d.def); + } + } +} + +void Preferences::store() +{ + QSettings settings; + // store settings + for(auto d : descr) { + settings.setValue(d.name, d.var.value()); + } +} + +void Preferences::edit() +{ + auto dialog = new PreferencesDialog(this); + dialog->exec(); +} + +void Preferences::setDefault() +{ + for(auto d : descr) { + d.var.setValue(d.def); + } +} diff --git a/Software/PC_Application/preferences.h b/Software/PC_Application/preferences.h new file mode 100644 index 0000000..b3539e3 --- /dev/null +++ b/Software/PC_Application/preferences.h @@ -0,0 +1,84 @@ +#ifndef PREFERENCESDIALOG_H +#define PREFERENCESDIALOG_H + +#include +#include +#include + +class QPointerVariant { +public: + template QPointerVariant(T *ptr) + : ptr(static_cast(ptr)), + variant(QVariant(*ptr)){}; + void setValue(const QVariant &value) { + auto destType = variant.type(); + if(!value.canConvert(destType)) { + throw std::runtime_error("Unable to convert QVariant to requested type"); + } + variant = value; + variant.convert(destType); + QMetaType mt(destType); + mt.construct(ptr, variant.constData()); + } + QVariant value() { + return QVariant(variant.type(), ptr); + } +private: + void *ptr; + QVariant variant; +}; + +class Preferences { +public: + void load(); + void store(); + void edit(); + void setDefault(); + + struct { + bool ConnectToFirstDevice; + bool RememberSweepSettings; + struct { + double start; + double stop; + int points; + double bandwidth; + double excitation; + } DefaultSweep; + } Startup; +private: + using SettingDescription = struct { + QPointerVariant var; + QString name; + QVariant def; + }; + const std::array descr = {{ + {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, + {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, + {&Startup.DefaultSweep.start, "Startup.DefaultSweep.start", 1000000.0}, + {&Startup.DefaultSweep.stop, "Startup.DefaultSweep.stop", 6000000000.0}, + {&Startup.DefaultSweep.points, "Startup.DefaultSweep.points", 501}, + {&Startup.DefaultSweep.bandwidth, "Startup.DefaultSweep.bandwidth", 1000.0}, + {&Startup.DefaultSweep.excitation, "Startup.DefaultSweep.excitation", -10.00}, + }}; +}; + +namespace Ui { +class PreferencesDialog; +} + +class PreferencesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PreferencesDialog(Preferences *pref, QWidget *parent = nullptr); + ~PreferencesDialog(); + +private: + void setInitialGUIState(); + Ui::PreferencesDialog *ui; + Preferences *p; +}; + +#endif // PREFERENCESDIALOG_H diff --git a/Software/PC_Application/preferencesdialog.ui b/Software/PC_Application/preferencesdialog.ui new file mode 100644 index 0000000..1d10a4a --- /dev/null +++ b/Software/PC_Application/preferencesdialog.ui @@ -0,0 +1,290 @@ + + + PreferencesDialog + + + + 0 + 0 + 646 + 543 + + + + Preferences + + + + + + + + + 0 + 0 + + + + + 180 + 16777215 + + + + true + + + false + + + + 1 + + + + + Startup + + + + + Acquisition + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + When starting the application... + + + + + + Autoconnect to the first device available + + + + + + + Set sweep settings to... + + + + + + + + + + + + + Last used + + + StartupSweepGroup + + + + + + + Default values + + + StartupSweepGroup + + + + + + + + + + + Start: + + + + + + + + + + Stop: + + + + + + + + + + Level: + + + + + + + dbm + + + -42.000000000000000 + + + -10.000000000000000 + + + 0.250000000000000 + + + + + + + Points: + + + + + + + 1 + + + 4501 + + + 501 + + + + + + + IF bandwitdh: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + <html><head/><body><p>If only S11/S21 or S22/S12 are enabled, faster sweeps are possible by only exciting one port. Checking this option forces the device to always excite both ports even when the measurements from one port will not be used.</p></body></html> + + + Always perform full 2-port measurement + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + false + + + + + + + + SIUnitEdit + QLineEdit +
CustomWidgets/siunitedit.h
+
+
+ + + + + +
diff --git a/Software/PC_Application/signalgenerator.cpp b/Software/PC_Application/signalgenerator.cpp new file mode 100644 index 0000000..bb44fac --- /dev/null +++ b/Software/PC_Application/signalgenerator.cpp @@ -0,0 +1,60 @@ +#include "signalgenerator.h" +#include "ui_signalgenerator.h" + +Signalgenerator::Signalgenerator(QWidget *parent) : + QWidget(parent), + ui(new Ui::Signalgenerator) +{ + ui->setupUi(this); + ui->frequency->setUnit("Hz"); + ui->frequency->setPrefixes(" kMG"); + + connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) { + // TODO centralize min/max values + if(newval < 9000) { + newval = 9000; + } else if (newval > 6000000000) { + newval = 6000000000; + } + ui->frequency->setValueQuiet(newval); + SettingsChanged(); + }); + connect(ui->levelSpin, qOverload(&QDoubleSpinBox::valueChanged), this, &Signalgenerator::setLevel); + connect(ui->levelSlider, &QSlider::valueChanged, [=](int value) { + setLevel((double) value / 100.0); + }); + connect(ui->EnablePort1, &QCheckBox::clicked, [=](){ + if(ui->EnablePort1->isChecked() && ui->EnablePort2->isChecked()) { + ui->EnablePort2->setCheckState(Qt::CheckState::Unchecked); + } + SettingsChanged(); + }); + connect(ui->EnablePort2, &QCheckBox::clicked, [=](){ + if(ui->EnablePort1->isChecked() && ui->EnablePort2->isChecked()) { + ui->EnablePort1->setCheckState(Qt::CheckState::Unchecked); + } + SettingsChanged(); + }); +} + +Signalgenerator::~Signalgenerator() +{ + delete ui; +} + +void Signalgenerator::setLevel(double level) +{ + // TODO constrain to frequency dependent levels + ui->levelSpin->blockSignals(true); + ui->levelSlider->blockSignals(true); + ui->levelSpin->setValue(level); + ui->levelSlider->setValue(level * 100.0); + ui->levelSpin->blockSignals(false); + ui->levelSlider->blockSignals(false); + SettingsChanged(); +} + +void Signalgenerator::SettingsChanged() +{ + // TODO compile manual settings packet and send +} diff --git a/Software/PC_Application/signalgenerator.h b/Software/PC_Application/signalgenerator.h new file mode 100644 index 0000000..444ffad --- /dev/null +++ b/Software/PC_Application/signalgenerator.h @@ -0,0 +1,29 @@ +#ifndef SIGNALGENERATOR_H +#define SIGNALGENERATOR_H + +#include +#include "Device/device.h" + +namespace Ui { +class Signalgenerator; +} + +class Signalgenerator : public QWidget +{ + Q_OBJECT + +public: + explicit Signalgenerator(QWidget *parent = nullptr); + ~Signalgenerator(); + +signals: + void NewManualState(Protocol::ManualStatus s); + +private slots: + void setLevel(double level); +private: + void SettingsChanged(); + Ui::Signalgenerator *ui; +}; + +#endif // SIGNALGENERATOR_H diff --git a/Software/PC_Application/signalgenerator.ui b/Software/PC_Application/signalgenerator.ui new file mode 100644 index 0000000..bfb6b74 --- /dev/null +++ b/Software/PC_Application/signalgenerator.ui @@ -0,0 +1,189 @@ + + + Signalgenerator + + + + 0 + 0 + 1093 + 594 + + + + + 0 + 0 + + + + Form + + + false + + + + + + Qt::Horizontal + + + + 197 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Generator + + + + + + Frequency: + + + + + + + + + + + + + Level Control + + + + + + dbm + + + -50.000000000000000 + + + 0.000000000000000 + + + 0.250000000000000 + + + -10.000000000000000 + + + + + + + -5000 + + + 0 + + + 25 + + + 500 + + + -1000 + + + Qt::Horizontal + + + + + + + + + + Enable + + + + + + Port 1 + + + + + + + Port 2 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 196 + 20 + + + + + + + + + SIUnitEdit + QLineEdit +
CustomWidgets/siunitedit.h
+
+
+ + +
diff --git a/Software/PC_Application/vna.cpp b/Software/PC_Application/vna.cpp index 8e6965c..ea5a534 100644 --- a/Software/PC_Application/vna.cpp +++ b/Software/PC_Application/vna.cpp @@ -39,6 +39,10 @@ #include "Calibration/calibrationtracedialog.h" #include "ui_main.h" #include "Device/firmwareupdatedialog.h" +#include "preferences.h" +#include "signalgenerator.h" +#include +#include using namespace std; @@ -50,9 +54,10 @@ VNA::VNA(QWidget *parent) , ui(new Ui::MainWindow) { QCoreApplication::setOrganizationName("VNA"); - QCoreApplication::setOrganizationName("Application"); + QCoreApplication::setApplicationName("Application"); + + pref.load(); - settings = defaultSweep; averages = 1; calValid = false; calMeasuring = false; @@ -70,6 +75,48 @@ VNA::VNA(QWidget *parent) ui->statusbar->addWidget(new QLabel, 1); //ui->statusbar->setStyleSheet("QStatusBar::item { border: 1px solid black; };"); + // Create default traces + auto tS11 = new Trace("S11", Qt::yellow); + tS11->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S11); + traceModel.addTrace(tS11); + auto tS12 = new Trace("S12", Qt::blue); + tS12->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S12); + traceModel.addTrace(tS12); + auto tS21 = new Trace("S21", Qt::green); + tS21->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S21); + traceModel.addTrace(tS21); + auto tS22 = new Trace("S22", Qt::red); + tS22->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S22); + traceModel.addTrace(tS22); + + auto tracesmith1 = new TraceSmithChart(traceModel); + tracesmith1->enableTrace(tS11, true); + auto tracesmith2 = new TraceSmithChart(traceModel); + tracesmith2->enableTrace(tS22, true); + + auto tracebode1 = new TraceBodePlot(traceModel); + tracebode1->enableTrace(tS12, true); + auto tracebode2 = new TraceBodePlot(traceModel); + tracebode2->enableTrace(tS21, true); + + auto tiles = new TileWidget(traceModel); + tiles->splitVertically(); + tiles->Child1()->splitHorizontally(); + tiles->Child2()->splitHorizontally(); + tiles->Child1()->Child1()->setPlot(tracesmith1); + tiles->Child1()->Child2()->setPlot(tracebode1); + tiles->Child2()->Child1()->setPlot(tracebode2); + tiles->Child2()->Child2()->setPlot(tracesmith2); + + // Create GUI modes + central = new QStackedWidget; + setCentralWidget(central); + modeVNA = new GUIMode(this, "Vector Network Analyzer", tiles); + auto signalGenWidget = new Signalgenerator; + modeSGen = new GUIMode(this, "Signal Generator", signalGenWidget); + modeSGen->addHiddenElement(ui->menuTools->menuAction()); + modeSGen->addHiddenElement(ui->menuCalibration->menuAction()); + CreateToolbars(); // UI connections connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &VNA::UpdateDeviceList); @@ -113,6 +160,9 @@ VNA::VNA(QWidget *parent) fw_update->exec(); } }); + connect(ui->actionPreferences, &QAction::triggered, [=](){ + pref.edit(); + }); setWindowTitle("VNA"); @@ -194,312 +244,73 @@ VNA::VNA(QWidget *parent) } statusLayout->addStretch(); - auto tw = new TraceWidget(traceModel); - // Create default traces - auto tS11 = new Trace("S11", Qt::yellow); - tS11->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S11); - traceModel.addTrace(tS11); - auto tS12 = new Trace("S12", Qt::blue); - tS12->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S12); - traceModel.addTrace(tS12); - auto tS21 = new Trace("S21", Qt::green); - tS21->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S21); - traceModel.addTrace(tS21); - auto tS22 = new Trace("S22", Qt::red); - tS22->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S22); - traceModel.addTrace(tS22); - - auto tracesmith1 = new TraceSmithChart(traceModel); - tracesmith1->enableTrace(tS11, true); - auto tracesmith2 = new TraceSmithChart(traceModel); - tracesmith2->enableTrace(tS22, true); - - auto tracebode1 = new TraceBodePlot(traceModel); - tracebode1->enableTrace(tS12, true); - auto tracebode2 = new TraceBodePlot(traceModel); - tracebode2->enableTrace(tS21, true); - - auto tiles = new TileWidget(traceModel); - tiles->splitVertically(); - tiles->Child1()->splitHorizontally(); - tiles->Child2()->splitHorizontally(); - tiles->Child1()->Child1()->setPlot(tracesmith1); - tiles->Child1()->Child2()->setPlot(tracebode1); - tiles->Child2()->Child1()->setPlot(tracebode2); - tiles->Child2()->Child2()->setPlot(tracesmith2); - - auto menuLayout = new QStackedLayout; - auto mMain = new Menu(*menuLayout); - - auto mFrequency = new Menu(*menuLayout, "Frequency"); - auto mCenter = new MenuValue("Center Frequency", (settings.f_start + settings.f_stop)/2, "Hz", " kMG", 6); - mFrequency->addItem(mCenter); - auto mStart = new MenuValue("Start Frequency", settings.f_start, "Hz", " kMG", 6); - mFrequency->addItem(mStart); - auto mStop = new MenuValue("Stop Frequency", settings.f_stop, "Hz", " kMG", 6); - mFrequency->addItem(mStop); - mFrequency->finalize(); - mMain->addMenu(mFrequency); - - auto mSpan = new Menu(*menuLayout, "Span"); - auto mSpanWidth = new MenuValue("Span", settings.f_stop - settings.f_start, "Hz", " kMG", 6); - mSpan->addItem(mSpanWidth); - auto mSpanZoomIn = new MenuAction("Zoom in"); - mSpan->addItem(mSpanZoomIn); - auto mSpanZoomOut = new MenuAction("Zoom out"); - mSpan->addItem(mSpanZoomOut); - auto mSpanFull = new MenuAction("Full span"); - mSpan->addItem(mSpanFull); - mSpan->finalize(); - mMain->addMenu(mSpan); - - auto mAcquisition = new Menu(*menuLayout, "Acquisition"); - auto mdbm = new MenuValue("Source Level", -10, "dbm", " "); - mAcquisition->addItem(mdbm); - auto mPoints = new MenuValue("Points", settings.points, "", " "); - mAcquisition->addItem(mPoints); - auto mBandwidth = new MenuValue("IF Bandwidth", settings.if_bandwidth, "Hz", " k", 3); - mAcquisition->addItem(mBandwidth); - auto mAverages = new MenuValue("Averages", averages); - mAcquisition->addItem(mAverages); - mAcquisition->finalize(); - mMain->addMenu(mAcquisition); - - auto mCalibration = new Menu(*menuLayout, "Calibration"); - auto mCalPort1 = new Menu(*menuLayout, "Port 1"); - auto mCalPort1Open = new MenuAction("Port 1 Open"); - auto mCalPort1Short = new MenuAction("Port 1 Short"); - auto mCalPort1Load = new MenuAction("Port 1 Load"); - mCalPort1->addItem(mCalPort1Short); - mCalPort1->addItem(mCalPort1Open); - mCalPort1->addItem(mCalPort1Load); - mCalPort1->finalize(); - mCalibration->addMenu(mCalPort1); - auto mCalPort2 = new Menu(*menuLayout, "Port 2"); - auto mCalPort2Open = new MenuAction("Port 2 Open"); - auto mCalPort2Short = new MenuAction("Port 2 Short"); - auto mCalPort2Load = new MenuAction("Port 2 Load"); - mCalPort2->addItem(mCalPort2Short); - mCalPort2->addItem(mCalPort2Open); - mCalPort2->addItem(mCalPort2Load); - mCalPort2->finalize(); - mCalibration->addMenu(mCalPort2); - auto mCalThrough = new MenuAction("Through"); - auto mCalIsolation = new MenuAction("Isolation"); - mCalibration->addItem(mCalThrough); - mCalibration->addItem(mCalIsolation); - - mCalSOL1 = new MenuAction("Apply Port 1 SOL"); - mCalibration->addItem(mCalSOL1); - mCalSOL1->setDisabled(true); - - mCalSOL2 = new MenuAction("Apply Port 2 SOL"); - mCalibration->addItem(mCalSOL2); - mCalSOL2->setDisabled(true); - - mCalFullSOLT = new MenuAction("Apply full SOLT"); - mCalibration->addItem(mCalFullSOLT); - mCalFullSOLT->setDisabled(true); - - auto mCalSave = new MenuAction("Save to file"); - mCalibration->addItem(mCalSave); - - auto mCalLoad = new MenuAction("Load from file"); - mCalibration->addItem(mCalLoad); - - auto mEditKit = new MenuAction("Edit CalKit"); - mCalibration->addItem(mEditKit); - - mCalibration->finalize(); - mMain->addMenu(mCalibration); - - auto mSystem = new Menu(*menuLayout, "System"); - auto aManual = new MenuAction("Manual Control"); - auto aMatchDialog = new MenuAction("Impedance Matching"); - mSystem->addItem(aManual); - mSystem->addItem(aMatchDialog); - mSystem->finalize(); - mMain->addMenu(mSystem); - - mMain->finalize(); - - // Frequency and span connections - // setting values - connect(mCenter, &MenuValue::valueChanged, this, &VNA::SetCenterFreq); - connect(mStart, &MenuValue::valueChanged, this, &VNA::SetStartFreq); - connect(mStop, &MenuValue::valueChanged, this, &VNA::SetStopFreq); - connect(mSpanWidth, &MenuValue::valueChanged, this, &VNA::SetSpan); - connect(mSpanZoomIn, &MenuAction::triggered, this, &VNA::SpanZoomIn); - connect(mSpanZoomOut, &MenuAction::triggered, this, &VNA::SpanZoomOut); - connect(mSpanFull, &MenuAction::triggered, this, &VNA::SetFullSpan); - // readback and update line edits - connect(this, &VNA::startFreqChanged, mStart, &MenuValue::setValueQuiet); - connect(this, &VNA::stopFreqChanged, mStop, &MenuValue::setValueQuiet); - connect(this, &VNA::centerFreqChanged, mCenter, &MenuValue::setValueQuiet); - connect(this, &VNA::spanChanged, mSpanWidth, &MenuValue::setValueQuiet); - - // Acquisition connections - // setting values - connect(mPoints, &MenuValue::valueChanged, [=](double newval){ - SetPoints(newval); - }); - connect(mdbm, &MenuValue::valueChanged, this, &VNA::SetSourceLevel); - connect(mBandwidth, &MenuValue::valueChanged, this, &VNA::SetIFBandwidth); - connect(mAverages, &MenuValue::valueChanged, [=](double newval){ - SetAveraging(newval); - }); - // readback and update line edits - connect(this, &VNA::sourceLevelChanged, mdbm, &MenuValue::setValueQuiet); - connect(this, &VNA::pointsChanged, [=](int newval) { - mPoints->setValueQuiet(newval); - }); - connect(this, &VNA::IFBandwidthChanged, mBandwidth, &MenuValue::setValueQuiet); - connect(this, &VNA::averagingChanged, [=](int newval) { - mAverages->setValueQuiet(newval); - }); - - connect(mCalPort1Open, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port1Open); - }); - connect(mCalPort1Short, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port1Short); - }); - connect(mCalPort1Load, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port1Load); - }); - connect(mCalPort2Open, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port2Open); - }); - connect(mCalPort2Short, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port2Short); - }); - connect(mCalPort2Load, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Port2Load); - }); - connect(mCalThrough, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Through); - }); - connect(mCalIsolation, &MenuAction::triggered, [=](){ - StartCalibrationMeasurement(Calibration::Measurement::Isolation); - }); - connect(mCalSOL1, &MenuAction::triggered, [=](){ - ApplyCalibration(Calibration::Type::Port1SOL); - }); - connect(mCalSOL2, &MenuAction::triggered, [=](){ - ApplyCalibration(Calibration::Type::Port2SOL); - }); - connect(mCalFullSOLT, &MenuAction::triggered, [=](){ - ApplyCalibration(Calibration::Type::FullSOLT); - }); - - connect(mCalSave, &MenuAction::triggered, [=](){ - cal.saveToFile(); - }); - - connect(mCalLoad, &MenuAction::triggered, [=](){ - if(cal.openFromFile()) { - // Check if applying calibration is available - if(cal.calculationPossible(Calibration::Type::Port1SOL)) { - mCalSOL1->setEnabled(true); - } - if(cal.calculationPossible(Calibration::Type::Port2SOL)) { - mCalSOL2->setEnabled(true); - } - if(cal.calculationPossible(Calibration::Type::FullSOLT)) { - mCalFullSOLT->setEnabled(true); - } - } - }); - - connect(mEditKit, &MenuAction::triggered, [=](){ - cal.getCalibrationKit().edit(); - }); - - // Manual control trigger - connect(aManual, &MenuAction::triggered, this, &VNA::StartManualControl); - connect(aMatchDialog, &MenuAction::triggered, this, &VNA::StartImpedanceMatching); - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - auto mainWidget = new QWidget; - auto mainLayout = new QHBoxLayout; - mainWidget->setLayout(mainLayout); auto statusWidget = new QWidget; statusWidget->setLayout(statusLayout); // statusWidget->setFixedWidth(150); auto statusDock = new QDockWidget("Status"); statusDock->setWidget(statusWidget); -// statusDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); addDockWidget(Qt::LeftDockWidgetArea, statusDock); auto tracesDock = new QDockWidget("Traces"); - tracesDock->setWidget(tw); -// tracesDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + tracesDock->setWidget(new TraceWidget(traceModel)); addDockWidget(Qt::LeftDockWidgetArea, tracesDock); -// mainLayout->addWidget(statusWidget); - mainLayout->addWidget(tiles); - auto menuWidget = new QWidget; - menuWidget->setLayout(menuLayout); -// menuWidget->setFixedWidth(180); - auto menuDock = new QDockWidget("Menu"); - menuDock->setWidget(menuWidget); -// menuDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); - addDockWidget(Qt::RightDockWidgetArea, menuDock); -// mainLayout->addWidget(menuWidget); auto markerWidget = new MarkerWidget(*markerModel); auto markerDock = new QDockWidget("Marker"); markerDock->setWidget(markerWidget); -// markerDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); addDockWidget(Qt::BottomDockWidgetArea, markerDock); auto logDock = new QDockWidget("Device Log"); logDock->setWidget(&deviceLog); addDockWidget(Qt::BottomDockWidgetArea, logDock); - setCentralWidget(mainWidget); + modeSGen->addHiddenElement(markerDock); + modeSGen->addHiddenElement(tracesDock); + modeSGen->addHiddenElement(statusDock); // status and menu dock hidden by default - menuDock->close(); statusDock->close(); - // fill dock/toolbar hide/show menu and set initial state if available - QSettings settings; - ui->menuDocks->clear(); - for(auto d : findChildren()) { - ui->menuDocks->addAction(d->toggleViewAction()); - bool hidden = settings.value("dock_"+d->windowTitle(), d->isHidden()).toBool(); - if(hidden) { - d->close(); - } else { - d->show(); - } - } - ui->menuToolbars->clear(); - for(auto t : findChildren()) { - ui->menuToolbars->addAction(t->toggleViewAction()); - bool hidden = settings.value("toolbar_"+t->windowTitle(), t->isHidden()).toBool(); - if(hidden) { - t->close(); - } else { - t->show(); - } + { + QSettings settings; + restoreGeometry(settings.value("geometry").toByteArray()); } - restoreGeometry(settings.value("geometry").toByteArray()); - restoreState(settings.value("windowState").toByteArray()); + // Set ObjectName for toolbars and docks + for(auto d : findChildren()) { + d->setObjectName(d->windowTitle()); + } + for(auto t : findChildren()) { + t->setObjectName(t->windowTitle()); + } + + // Set default mode + modeVNA->activate(); qRegisterMetaType("Datapoint"); - ConstrainAndUpdateFrequencies(); + + // Set initial sweep settings + if(pref.Startup.RememberSweepSettings) { + LoadSweepSettings(); + } else { + settings.f_start = pref.Startup.DefaultSweep.start; + settings.f_stop = pref.Startup.DefaultSweep.stop; + ConstrainAndUpdateFrequencies(); + SetSourceLevel(pref.Startup.DefaultSweep.excitation); + SetIFBandwidth(pref.Startup.DefaultSweep.bandwidth); + SetPoints(pref.Startup.DefaultSweep.points); + } // List available devices - if(UpdateDeviceList()) { + if(UpdateDeviceList() && pref.Startup.ConnectToFirstDevice) { // at least one device available ConnectToDevice(); } @@ -508,16 +319,11 @@ VNA::VNA(QWidget *parent) void VNA::closeEvent(QCloseEvent *event) { QSettings settings; - // save dock/toolbar visibility - for(auto d : findChildren()) { - settings.setValue("dock_"+d->windowTitle(), d->isHidden()); - } - ui->menuToolbars->clear(); - for(auto t : findChildren()) { - settings.setValue("toolbar_"+t->windowTitle(), t->isHidden()); - } settings.setValue("geometry", saveGeometry()); - settings.setValue("windowState", saveState()); + // deactivate currently used mode (stores mode state in settings) + GUIMode::getActiveMode()->deactivate(); + StoreSweepSettings(); + pref.store(); QMainWindow::closeEvent(event); } @@ -530,16 +336,6 @@ void VNA::NewDatapoint(Protocol::Datapoint d) if(d.pointNum == settings.points - 1) { calMeasuring = false; emit CalibrationMeasurementComplete(calMeasurement); - // Check if applying calibration is available - if(cal.calculationPossible(Calibration::Type::Port1SOL)) { - mCalSOL1->setEnabled(true); - } - if(cal.calculationPossible(Calibration::Type::Port2SOL)) { - mCalSOL2->setEnabled(true); - } - if(cal.calculationPossible(Calibration::Type::FullSOLT)) { - mCalFullSOLT->setEnabled(true); - } } calDialog.setValue(d.pointNum + 1); } @@ -715,6 +511,7 @@ void VNA::CreateToolbars() tb_sweep->addWidget(bZoomOut); addToolBar(tb_sweep); + modeSGen->addHiddenElement(tb_sweep); // Acquisition toolbar auto tb_acq = new QToolBar("Acquisition", this); @@ -751,6 +548,7 @@ void VNA::CreateToolbars() tb_acq->addWidget(eBandwidth); addToolBar(tb_acq); + modeSGen->addHiddenElement(tb_acq); // Reference toolbar auto tb_reference = new QToolBar("Reference", this); @@ -840,6 +638,7 @@ void VNA::CreateToolbars() tb_cal->addWidget(cbType); addToolBar(tb_cal); + modeSGen->addHiddenElement(tb_cal); } int VNA::UpdateDeviceList() @@ -1075,3 +874,144 @@ void VNA::ConstrainAndUpdateFrequencies() emit centerFreqChanged((settings.f_stop + settings.f_start)/2); SettingsChanged(); } + +void VNA::LoadSweepSettings() +{ + QSettings s; + settings.f_start = s.value("SweepStart", pref.Startup.DefaultSweep.start).toULongLong(); + settings.f_stop = s.value("SweepStop", pref.Startup.DefaultSweep.stop).toULongLong(); + ConstrainAndUpdateFrequencies(); + SetIFBandwidth(s.value("SweepBandwidth", pref.Startup.DefaultSweep.bandwidth).toUInt()); + SetPoints(s.value("SweepPoints", pref.Startup.DefaultSweep.points).toInt()); + SetSourceLevel(s.value("SweepLevel", pref.Startup.DefaultSweep.excitation).toDouble()); +} + +void VNA::StoreSweepSettings() +{ + QSettings s; + s.setValue("SweepStart", static_cast(settings.f_start)); + s.setValue("SweepStop", static_cast(settings.f_stop)); + s.setValue("SweepBandwidth", settings.if_bandwidth); + s.setValue("SweepPoints", settings.points); + s.setValue("SweepLevel", (double) settings.cdbm_excitation / 100.0); +} + +VNA::GUIMode* VNA::GUIMode::activeMode = nullptr; +QWidget* VNA::GUIMode::cornerWidget = nullptr; +QButtonGroup* VNA::GUIMode::modeButtonGroup = nullptr; + +VNA::GUIMode::GUIMode(VNA *vna, QString name, QWidget *centralWidget) + : vna(vna), + name(name), + central(centralWidget) +{ + vna->central->addWidget(central); + // Create mode switch button + auto modeSwitch = new QPushButton(name); + modeSwitch->setCheckable(true); + modeSwitch->setMaximumHeight(vna->ui->menubar->height()); + if(!cornerWidget) { + // this is the first created mode, initialize corner widget and set this mode as active + modeSwitch->setChecked(true); + cornerWidget = new QWidget; + cornerWidget->setLayout(new QHBoxLayout); + cornerWidget->layout()->setSpacing(0); + cornerWidget->layout()->setMargin(0); + cornerWidget->layout()->setContentsMargins(0,0,0,0); + vna->menuBar()->setCornerWidget(cornerWidget); + modeButtonGroup = new QButtonGroup; + vna->ui->menubar->setMaximumHeight(vna->ui->menubar->height()); + } + cornerWidget->layout()->addWidget(modeSwitch); + modeButtonGroup->addButton(modeSwitch); + + connect(modeSwitch, &QPushButton::clicked, [=](){ + activate(); + }); +} + +void VNA::GUIMode::activate() +{ + if(activeMode == this) { + // already active; + return; + } else if(activeMode) { + activeMode->deactivate(); + } + QSettings settings; + // hide menu actions that are not applicable to this mode + for(auto a : hiddenActions) { + a->setVisible(false); + } + + vna->central->setCurrentWidget(central); + + // restore dock and toolbar positions +// vna->restoreGeometry(settings.value("geometry_"+name).toByteArray()); + vna->restoreState(settings.value("windowState_"+name).toByteArray()); + + // restore visibility of toolbars and docks + vna->ui->menuDocks->clear(); + for(auto d : vna->findChildren()) { + if(hiddenDocks.count(d)) { + // this dock is not applicable for the current state, hide and don't add menu entry + d->hide(); + continue; + } + vna->ui->menuDocks->addAction(d->toggleViewAction()); + bool hidden = settings.value("dock_"+name+"_"+d->windowTitle(), d->isHidden()).toBool(); + if(hidden) { + d->hide(); + } else { + d->show(); + } + } + vna->ui->menuToolbars->clear(); + for(auto t : vna->findChildren()) { + if(hiddenToolbars.count(t)) { + // this toolbar is not applicable for the current state, hide and don't add menu entry + t->hide(); + continue; + } + vna->ui->menuToolbars->addAction(t->toggleViewAction()); + bool hidden = settings.value("toolbar_"+name+"_"+t->windowTitle(), t->isHidden()).toBool(); + if(hidden) { + t->hide(); + } else { + t->show(); + } + } + + activeMode = this; +} + +void VNA::GUIMode::deactivate() +{ + QSettings settings; + // save dock/toolbar visibility + for(auto d : vna->findChildren()) { + settings.setValue("dock_"+name+"_"+d->windowTitle(), d->isHidden()); + } + for(auto t : vna->findChildren()) { + settings.setValue("toolbar_"+name+"_"+t->windowTitle(), t->isHidden()); + } +// settings.setValue("geometry_"+name, vna->saveGeometry()); + settings.setValue("windowState_"+name, vna->saveState()); + + // restore hidden items + for(auto a : hiddenActions) { + a->setVisible(true); + } + + activeMode = nullptr; +} + +VNA::GUIMode *VNA::GUIMode::getActiveMode() +{ + return activeMode; +} + +QString VNA::GUIMode::getName() const +{ + return name; +} diff --git a/Software/PC_Application/vna.h b/Software/PC_Application/vna.h index 23e2ab5..02d1925 100644 --- a/Software/PC_Application/vna.h +++ b/Software/PC_Application/vna.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "Device/device.h" #include "Traces/traceplot.h" #include "Calibration/calibration.h" @@ -14,6 +15,8 @@ #include "Traces/tracemarkermodel.h" #include "averaging.h" #include "Device/devicelog.h" +#include "preferences.h" +#include namespace Ui { class MainWindow; @@ -70,11 +73,48 @@ private: void DeviceConnectionLost(); void CreateToolbars(); void ConstrainAndUpdateFrequencies(); + void LoadSweepSettings(); + void StoreSweepSettings(); + + class GUIMode { + friend class VNA; + public: + GUIMode(VNA *vna, QString name, QWidget *centralWidget);; + void addHiddenElement(QAction* a) { + hiddenActions.insert(a); + } + void addHiddenElement(QToolBar* a) { + hiddenToolbars.insert(a); + } + void addHiddenElement(QDockWidget* a) { + hiddenDocks.insert(a); + } + void activate(); + void deactivate(); + QString getName() const; + static GUIMode *getActiveMode(); + + private: + static GUIMode *activeMode; + static QWidget *cornerWidget; + static QButtonGroup *modeButtonGroup; + std::set hiddenActions; + std::set hiddenToolbars; + std::set hiddenDocks; + VNA *vna; + const QString name; + QWidget *central; + }; + GUIMode *modeVNA, *modeSGen; + + QStackedWidget *central; struct { QComboBox *referenceType; } toolbars; + Preferences pref; + Device *device; DeviceLog deviceLog; QString deviceSerial; @@ -93,9 +133,6 @@ private: bool calWaitFirst; QProgressDialog calDialog; - // Calibration menu - MenuAction *mCalSOL1, *mCalSOL2, *mCalFullSOLT; - // Status Labels QLabel lStart, lCenter, lStop, lSpan, lPoints, lBandwidth; QLabel lCalibration;