Merge branch 'mode-handler'

This commit is contained in:
Jan Käberich 2022-07-17 15:33:00 +02:00
commit 2a4850caf6
23 changed files with 529 additions and 251 deletions

View File

@ -17,15 +17,16 @@
using namespace std; using namespace std;
using namespace nlohmann; using namespace nlohmann;
AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, QWidget *parent) : AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, ModeHandler *handler, QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::AmplitudeCalDialog), ui(new Ui::AmplitudeCalDialog),
dev(dev), dev(dev),
modeHandler(handler),
model(this), model(this),
mode(CalibrationMode::BothPorts) mode(CalibrationMode::BothPorts)
{ {
activeMode = Mode::getActiveMode(); auto activeMode = modeHandler->getActiveMode();
activeMode->deactivate(); modeHandler->deactivate(activeMode);
dev->SetIdle(); dev->SetIdle();
ui->setupUi(this); ui->setupUi(this);
ui->view->setModel(&model); ui->view->setModel(&model);
@ -137,7 +138,8 @@ AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, QWidget *parent) :
AmplitudeCalDialog::~AmplitudeCalDialog() AmplitudeCalDialog::~AmplitudeCalDialog()
{ {
delete ui; delete ui;
activeMode->activate(); auto activeMode = modeHandler->getActiveMode();
modeHandler->activate(activeMode);
} }
void AmplitudeCalDialog::reject() void AmplitudeCalDialog::reject()

View File

@ -2,6 +2,7 @@
#define AMPLITUDECALDIALOG_H #define AMPLITUDECALDIALOG_H
#include "mode.h" #include "mode.h"
#include "modehandler.h"
#include "Device/device.h" #include "Device/device.h"
#include <QDialog> #include <QDialog>
@ -42,7 +43,7 @@ class AmplitudeCalDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit AmplitudeCalDialog(Device *dev, QWidget *parent = nullptr); explicit AmplitudeCalDialog(Device *dev, ModeHandler *handler, QWidget *parent = nullptr);
~AmplitudeCalDialog(); ~AmplitudeCalDialog();
void reject() override; void reject() override;
@ -100,7 +101,7 @@ protected:
std::vector<CorrectionPoint> points; std::vector<CorrectionPoint> points;
Ui::AmplitudeCalDialog *ui; Ui::AmplitudeCalDialog *ui;
Device *dev; Device *dev;
Mode *activeMode; ModeHandler *modeHandler;
AmplitudeModel model; AmplitudeModel model;
bool edited; bool edited;
CalibrationMode mode; CalibrationMode mode;

View File

@ -2,7 +2,7 @@
#include "ui_frequencycaldialog.h" #include "ui_frequencycaldialog.h"
FrequencyCalDialog::FrequencyCalDialog(Device *dev, QWidget *parent) : FrequencyCalDialog::FrequencyCalDialog(Device *dev, ModeHandler *handler, QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::FrequencyCalDialog), ui(new Ui::FrequencyCalDialog),
dev(dev) dev(dev)
@ -22,9 +22,9 @@ FrequencyCalDialog::FrequencyCalDialog(Device *dev, QWidget *parent) :
p.frequencyCorrection.ppm = ui->ppm->value(); p.frequencyCorrection.ppm = ui->ppm->value();
dev->SendPacket(p); dev->SendPacket(p);
// force restart of current mode for setting to take effect // force restart of current mode for setting to take effect
auto activeMode = Mode::getActiveMode(); auto activeMode = handler->getActiveMode();
activeMode->deactivate(); handler->deactivate(activeMode);
activeMode->activate(); handler->activate(activeMode);
accept(); accept();
delete this; delete this;
}); });

View File

@ -2,6 +2,7 @@
#define FREQUENCYCALDIALOG_H #define FREQUENCYCALDIALOG_H
#include "Device/device.h" #include "Device/device.h"
#include "modehandler.h"
#include "mode.h" #include "mode.h"
#include <QDialog> #include <QDialog>
@ -15,7 +16,7 @@ class FrequencyCalDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit FrequencyCalDialog(Device *dev, QWidget *parent = nullptr); explicit FrequencyCalDialog(Device *dev, ModeHandler *handler, QWidget *parent = nullptr);
~FrequencyCalDialog(); ~FrequencyCalDialog();
private: private:

View File

@ -1,7 +1,7 @@
#include "receivercaldialog.h" #include "receivercaldialog.h"
ReceiverCalDialog::ReceiverCalDialog(Device *dev) ReceiverCalDialog::ReceiverCalDialog(Device *dev, ModeHandler *handler)
: AmplitudeCalDialog(dev) : AmplitudeCalDialog(dev, handler)
{ {
setWindowTitle("Receiver Calibration Dialog"); setWindowTitle("Receiver Calibration Dialog");
LoadFromDevice(); LoadFromDevice();

View File

@ -2,12 +2,13 @@
#define RECEIVERCALDIALOG_H #define RECEIVERCALDIALOG_H
#include "amplitudecaldialog.h" #include "amplitudecaldialog.h"
#include "modehandler.h"
class ReceiverCalDialog : public AmplitudeCalDialog class ReceiverCalDialog : public AmplitudeCalDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
ReceiverCalDialog(Device *dev); ReceiverCalDialog(Device *dev, ModeHandler *handler);
protected: protected:
Protocol::PacketType requestCommand() override { return Protocol::PacketType::RequestReceiverCal; } Protocol::PacketType requestCommand() override { return Protocol::PacketType::RequestReceiverCal; }
Protocol::PacketType pointType() override { return Protocol::PacketType::ReceiverCalPoint; } Protocol::PacketType pointType() override { return Protocol::PacketType::ReceiverCalPoint; }

View File

@ -2,8 +2,8 @@
#include <QDebug> #include <QDebug>
SourceCalDialog::SourceCalDialog(Device *dev) SourceCalDialog::SourceCalDialog(Device *dev, ModeHandler *handler)
: AmplitudeCalDialog(dev) : AmplitudeCalDialog(dev, handler)
{ {
setWindowTitle("Source Calibration Dialog"); setWindowTitle("Source Calibration Dialog");
LoadFromDevice(); LoadFromDevice();

View File

@ -2,6 +2,7 @@
#define SOURCECALDIALOG_H #define SOURCECALDIALOG_H
#include "amplitudecaldialog.h" #include "amplitudecaldialog.h"
#include "modehandler.h"
#include <QObject> #include <QObject>
@ -9,7 +10,7 @@ class SourceCalDialog : public AmplitudeCalDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
SourceCalDialog(Device *dev); SourceCalDialog(Device *dev, ModeHandler *handler);
protected: protected:
Protocol::PacketType requestCommand() override { return Protocol::PacketType::RequestSourceCal; } Protocol::PacketType requestCommand() override { return Protocol::PacketType::RequestSourceCal; }
Protocol::PacketType pointType() override { return Protocol::PacketType::SourceCalPoint; } Protocol::PacketType pointType() override { return Protocol::PacketType::SourceCalPoint; }

View File

@ -55,7 +55,7 @@ void Generator::fromJSON(nlohmann::json j)
void Generator::updateDevice() void Generator::updateDevice()
{ {
if(!window->getDevice() || Mode::getActiveMode() != this) { if(!window->getDevice() || isActive != true) {
// can't update if not connected // can't update if not connected
return; return;
} }

View File

@ -18,6 +18,8 @@ public:
virtual nlohmann::json toJSON() override; virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
void setAveragingMode(Averaging::Mode mode) override {Q_UNUSED(mode)};
private slots: private slots:
void updateDevice(); void updateDevice();

View File

@ -123,7 +123,9 @@ HEADERS += \
averaging.h \ averaging.h \
csv.h \ csv.h \
json.hpp \ json.hpp \
modehandler.h \
mode.h \ mode.h \
modewindow.h \
preferences.h \ preferences.h \
savable.h \ savable.h \
scpi.h \ scpi.h \
@ -242,7 +244,9 @@ SOURCES += \
averaging.cpp \ averaging.cpp \
csv.cpp \ csv.cpp \
main.cpp \ main.cpp \
modehandler.cpp \
mode.cpp \ mode.cpp \
modewindow.cpp \
preferences.cpp \ preferences.cpp \
scpi.cpp \ scpi.cpp \
tcpserver.cpp \ tcpserver.cpp \

View File

@ -433,7 +433,7 @@ using namespace std;
void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d) void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
{ {
if(Mode::getActiveMode() != this) { if(isActive != true) {
return; return;
} }
@ -570,7 +570,7 @@ void SpectrumAnalyzer::SettingsChanged()
} }
} }
if(window->getDevice() && Mode::getActiveMode() == this) { if(window->getDevice() && isActive) {
window->getDevice()->Configure(settings, [=](Device::TransmissionResult res){ window->getDevice()->Configure(settings, [=](Device::TransmissionResult res){
// device received command // device received command
changingSettings = false; changingSettings = false;

View File

@ -28,7 +28,7 @@ public:
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
void updateGraphColors(); void updateGraphColors();
void setAveragingMode(Averaging::Mode mode); void setAveragingMode(Averaging::Mode mode) override;
private: private:

View File

@ -801,7 +801,7 @@ using namespace std;
void VNA::NewDatapoint(Protocol::Datapoint d) void VNA::NewDatapoint(Protocol::Datapoint d)
{ {
if(Mode::getActiveMode() != this) { if(isActive != true) {
// ignore // ignore
return; return;
} }
@ -972,7 +972,7 @@ void VNA::SettingsChanged(bool resetTraces, std::function<void (Device::Transmis
s.cdbm_excitation_stop = stop * 100; s.cdbm_excitation_stop = stop * 100;
s.logSweep = false; s.logSweep = false;
} }
if(window->getDevice() && Mode::getActiveMode() == this) { if(window->getDevice() && isActive) {
if(s.excitePort1 == 0 && s.excitePort2 == 0) { if(s.excitePort1 == 0 && s.excitePort2 == 0) {
// no signal at either port, just set the device to idle // no signal at either port, just set the device to idle
window->getDevice()->SetIdle(); window->getDevice()->SetIdle();
@ -1486,7 +1486,7 @@ void VNA::SetupSCPI()
return ret; return ret;
})); }));
scpi_cal->add(new SCPICommand("MEASure", [=](QStringList params) -> QString { scpi_cal->add(new SCPICommand("MEASure", [=](QStringList params) -> QString {
if(params.size() != 1 || CalibrationMeasurementActive() || !window->getDevice() || Mode::getActiveMode() != this) { if(params.size() != 1 || CalibrationMeasurementActive() || !window->getDevice() || isActive != true) {
// no measurement specified, still busy or invalid mode // no measurement specified, still busy or invalid mode
return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
} else { } else {

View File

@ -31,7 +31,7 @@ public:
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
void updateGraphColors(); void updateGraphColors();
void setAveragingMode(Averaging::Mode mode); void setAveragingMode(Averaging::Mode mode) override;
enum class SweepType { enum class SweepType {
Frequency = 0, Frequency = 0,

View File

@ -27,12 +27,14 @@
#include "CustomWidgets/informationbox.h" #include "CustomWidgets/informationbox.h"
#include "Util/app_common.h" #include "Util/app_common.h"
#include "about.h" #include "about.h"
#include "mode.h"
#include "modehandler.h"
#include "modewindow.h"
#include <QDockWidget> #include <QDockWidget>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QApplication> #include <QApplication>
#include <QActionGroup> #include <QActionGroup>
#include <mode.h>
#include <QDebug> #include <QDebug>
#include <QGridLayout> #include <QGridLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
@ -168,6 +170,7 @@ AppWindow::AppWindow(QWidget *parent)
, appVersion(APP_VERSION) , appVersion(APP_VERSION)
, appGitHash(APP_GIT_HASH) , appGitHash(APP_GIT_HASH)
{ {
// qDebug().setVerbosity(0); // qDebug().setVerbosity(0);
qDebug() << "Application start"; qDebug() << "Application start";
@ -191,6 +194,7 @@ AppWindow::AppWindow(QWidget *parent)
Preferences::getInstance().load(); Preferences::getInstance().load();
} }
device = nullptr; device = nullptr;
modeHandler = nullptr;
if(parser.isSet("port")) { if(parser.isSet("port")) {
bool OK; bool OK;
@ -227,12 +231,22 @@ AppWindow::AppWindow(QWidget *parent)
ui->menuToolbars->addAction(t->toggleViewAction()); ui->menuToolbars->addAction(t->toggleViewAction());
} }
// Create GUI modes modeHandler = new ModeHandler(this);
new ModeWindow(modeHandler, this);
central = new QStackedWidget; central = new QStackedWidget;
setCentralWidget(central); setCentralWidget(central);
auto vna = new VNA(this);
auto generator = new Generator(this); auto vnaIndex = modeHandler->createMode("Vector Network Analyzer", Mode::Type::VNA);
auto spectrumAnalyzer = new SpectrumAnalyzer(this); modeHandler->createMode("Spectrum Analyzer", Mode::Type::SA);
modeHandler->createMode("Signal Generator", Mode::Type::SG);
modeHandler->setCurrentIndex(vnaIndex);
auto setModeStatusbar = [=](const QString &msg) {
lModeInfo.setText(msg);
};
connect(modeHandler, &ModeHandler::StatusBarMessageChanged, setModeStatusbar);
// UI connections // UI connections
connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList); connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList);
@ -255,7 +269,7 @@ AppWindow::AppWindow(QWidget *parent)
LoadSetup(filename); LoadSetup(filename);
}); });
connect(ui->actionSave_image, &QAction::triggered, [=](){ connect(ui->actionSave_image, &QAction::triggered, [=](){
Mode::getActiveMode()->saveSreenshot(); modeHandler->getActiveMode()->saveSreenshot();
}); });
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl); connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
@ -275,26 +289,18 @@ AppWindow::AppWindow(QWidget *parent)
StartTCPServer(p.SCPIServer.port); StartTCPServer(p.SCPIServer.port);
} }
} }
// averaging mode may have changed, update for all relevant modes // averaging mode may have changed, update for all relevant modes
for (auto m : Mode::getModes()) for (auto m : modeHandler->getModes())
{ {
switch (m->getType()) switch (m->getType())
{ {
case Mode::Type::VNA: case Mode::Type::VNA:
if(p.Acquisition.useMedianAveraging) {
static_cast<VNA*>(m)->setAveragingMode(Averaging::Mode::Median);
}
else {
static_cast<VNA*>(m)->setAveragingMode(Averaging::Mode::Mean);
}
break;
case Mode::Type::SA: case Mode::Type::SA:
if(p.Acquisition.useMedianAveraging) { if(p.Acquisition.useMedianAveraging) {
static_cast<SpectrumAnalyzer*>(m)->setAveragingMode(Averaging::Mode::Median); m->setAveragingMode(Averaging::Mode::Median);
} }
else { else {
static_cast<SpectrumAnalyzer*>(m)->setAveragingMode(Averaging::Mode::Mean); m->setAveragingMode(Averaging::Mode::Mean);
} }
break; break;
case Mode::Type::SG: case Mode::Type::SG:
@ -307,7 +313,7 @@ AppWindow::AppWindow(QWidget *parent)
// acquisition frequencies may have changed, update // acquisition frequencies may have changed, update
UpdateAcquisitionFrequencies(); UpdateAcquisitionFrequencies();
auto active = Mode::getActiveMode(); auto active = modeHandler->getActiveMode();
if (active) if (active)
{ {
active->updateGraphColors(); active->updateGraphColors();
@ -338,9 +344,6 @@ AppWindow::AppWindow(QWidget *parent)
SetupSCPI(); SetupSCPI();
// Set default mode
vna->activate();
auto pref = Preferences::getInstance(); auto pref = Preferences::getInstance();
if(pref.Startup.UseSetupFile) { if(pref.Startup.UseSetupFile) {
LoadSetup(pref.Startup.SetupFile); LoadSetup(pref.Startup.SetupFile);
@ -356,7 +359,8 @@ AppWindow::AppWindow(QWidget *parent)
LoadSetup(parser.value("setup")); LoadSetup(parser.value("setup"));
} }
if(parser.isSet("cal")) { if(parser.isSet("cal")) {
vna->LoadCalibration(parser.value("cal")); VNA* mode = static_cast<VNA*>(modeHandler->findFirstOfType(Mode::Type::VNA));
mode->LoadCalibration(parser.value("cal"));
} }
if(!parser.isSet("no-gui")) { if(!parser.isSet("no-gui")) {
InformationBox::setGUI(true); InformationBox::setGUI(true);
@ -380,16 +384,16 @@ void AppWindow::closeEvent(QCloseEvent *event)
if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) { if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) {
SaveSetup(pref.Startup.SetupFile); SaveSetup(pref.Startup.SetupFile);
} }
for(auto m : Mode::getModes()) { modeHandler->shutdown();
m->shutdown();
}
QSettings settings; QSettings settings;
settings.setValue("geometry", saveGeometry()); settings.setValue("geometry", saveGeometry());
// deactivate currently used mode (stores mode state in settings) // deactivate currently used mode (stores mode state in settings)
if(Mode::getActiveMode()) { if(modeHandler->getActiveMode()) {
Mode::getActiveMode()->deactivate(); modeHandler->deactivate(modeHandler->getActiveMode());
} }
delete device; delete device;
delete modeHandler;
modeHandler = nullptr;
pref.store(); pref.store();
QMainWindow::closeEvent(event); QMainWindow::closeEvent(event);
} }
@ -421,8 +425,8 @@ bool AppWindow::ConnectToDevice(QString serial)
ui->actionFrequency_Calibration->setEnabled(true); ui->actionFrequency_Calibration->setEnabled(true);
UpdateAcquisitionFrequencies(); UpdateAcquisitionFrequencies();
if (Mode::getActiveMode()) { if (modeHandler->getActiveMode()) {
Mode::getActiveMode()->initializeDevice(); modeHandler->getActiveMode()->initializeDevice();
} }
UpdateReference(); UpdateReference();
@ -460,8 +464,8 @@ void AppWindow::DisconnectDevice()
deviceActionGroup->checkedAction()->setChecked(false); deviceActionGroup->checkedAction()->setChecked(false);
} }
UpdateStatusBar(DeviceStatusBar::Disconnected); UpdateStatusBar(DeviceStatusBar::Disconnected);
if(Mode::getActiveMode()) { if(modeHandler->getActiveMode()) {
Mode::getActiveMode()->deviceDisconnected(); modeHandler->getActiveMode()->deviceDisconnected();
} }
qDebug() << "Disconnected device"; qDebug() << "Disconnected device";
} }
@ -591,22 +595,23 @@ void AppWindow::SetupSCPI()
} }
Mode *mode = nullptr; Mode *mode = nullptr;
if (params[0] == "VNA") { if (params[0] == "VNA") {
mode = Mode::findFirstOfType(Mode::Type::VNA); mode = modeHandler->findFirstOfType(Mode::Type::VNA);
} else if(params[0] == "GEN") { } else if(params[0] == "GEN") {
mode = Mode::findFirstOfType(Mode::Type::SG); mode = modeHandler->findFirstOfType(Mode::Type::SG);
} else if(params[0] == "SA") { } else if(params[0] == "SA") {
mode = Mode::findFirstOfType(Mode::Type::SA); mode = modeHandler->findFirstOfType(Mode::Type::SA);
} else { } else {
return "INVALID MDOE"; return "INVALID MDOE";
} }
if(mode) { if(mode) {
mode->activate(); int index = modeHandler->findIndex(mode);
modeHandler->setCurrentIndex(index);
return SCPI::getResultName(SCPI::Result::Empty); return SCPI::getResultName(SCPI::Result::Empty);
} else { } else {
return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
} }
}, [=](QStringList) -> QString { }, [=](QStringList) -> QString {
auto active = Mode::getActiveMode(); auto active = modeHandler->getActiveMode();
if(active) { if(active) {
switch(active->getType()) { switch(active->getType()) {
case Mode::Type::VNA: return "VNA"; case Mode::Type::VNA: return "VNA";
@ -968,7 +973,7 @@ void AppWindow::StartManualControl()
connect(manual, &QDialog::finished, [=](){ connect(manual, &QDialog::finished, [=](){
manual = nullptr; manual = nullptr;
if(device) { if(device) {
Mode::getActiveMode()->initializeDevice(); modeHandler->getActiveMode()->initializeDevice();
} }
}); });
if(AppWindow::showGUI()) { if(AppWindow::showGUI()) {
@ -1048,7 +1053,7 @@ void AppWindow::DeviceStatusUpdated()
void AppWindow::SourceCalibrationDialog() void AppWindow::SourceCalibrationDialog()
{ {
auto d = new SourceCalDialog(device); auto d = new SourceCalDialog(device, modeHandler);
if(AppWindow::showGUI()) { if(AppWindow::showGUI()) {
d->exec(); d->exec();
} }
@ -1056,7 +1061,7 @@ void AppWindow::SourceCalibrationDialog()
void AppWindow::ReceiverCalibrationDialog() void AppWindow::ReceiverCalibrationDialog()
{ {
auto d = new ReceiverCalDialog(device); auto d = new ReceiverCalDialog(device, modeHandler);
if(AppWindow::showGUI()) { if(AppWindow::showGUI()) {
d->exec(); d->exec();
} }
@ -1064,7 +1069,7 @@ void AppWindow::ReceiverCalibrationDialog()
void AppWindow::FrequencyCalibrationDialog() void AppWindow::FrequencyCalibrationDialog()
{ {
auto d = new FrequencyCalDialog(device); auto d = new FrequencyCalDialog(device, modeHandler);
if(AppWindow::showGUI()) { if(AppWindow::showGUI()) {
d->exec(); d->exec();
} }
@ -1087,7 +1092,7 @@ nlohmann::json AppWindow::SaveSetup()
{ {
nlohmann::json j; nlohmann::json j;
nlohmann::json jm; nlohmann::json jm;
for(auto m : Mode::getModes()) { for(auto m : modeHandler->getModes()) {
nlohmann::json jmode; nlohmann::json jmode;
jmode["type"] = Mode::TypeToName(m->getType()).toStdString(); jmode["type"] = Mode::TypeToName(m->getType()).toStdString();
jmode["name"] = m->getName().toStdString(); jmode["name"] = m->getName().toStdString();
@ -1095,8 +1100,8 @@ nlohmann::json AppWindow::SaveSetup()
jm.push_back(jmode); jm.push_back(jmode);
} }
j["Modes"] = jm; j["Modes"] = jm;
if(Mode::getActiveMode()) { if(modeHandler->getActiveMode()) {
j["activeMode"] = Mode::getActiveMode()->getName().toStdString(); j["activeMode"] = modeHandler->getActiveMode()->getName().toStdString();
} }
nlohmann::json ref; nlohmann::json ref;
@ -1143,28 +1148,32 @@ void AppWindow::LoadSetup(nlohmann::json j)
toolbars.reference.type->setCurrentIndex(index); toolbars.reference.type->setCurrentIndex(index);
toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off"))); toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off")));
} }
while(Mode::getModes().size() > 0) {
delete Mode::getModes()[0];
}
// old style VNA/Generator/Spectrum Analyzer settings modeHandler->closeModes();
/* old style VNA/Generator/Spectrum Analyzer settings,
* no more than one instance in each mode running */
if(j.contains("VNA")) { if(j.contains("VNA")) {
auto vna = new VNA(this); auto vnaIndex = modeHandler->createMode("Vector Network Analyzer", Mode::Type::VNA);
auto *vna = static_cast<VNA*>(modeHandler->getMode(vnaIndex));
vna->fromJSON(j["VNA"]); vna->fromJSON(j["VNA"]);
} }
if(j.contains("Generator")) { if(j.contains("Generator")) {
auto generator = new Generator(this); auto sgIndex = modeHandler->createMode("Generator", Mode::Type::SG);
auto *generator = static_cast<Generator*>(modeHandler->getMode(sgIndex));
generator->fromJSON(j["Generator"]); generator->fromJSON(j["Generator"]);
} }
if(j.contains("SpectrumAnalyzer")) { if(j.contains("SpectrumAnalyzer")) {
auto spectrumAnalyzer = new SpectrumAnalyzer(this); auto saIndex = modeHandler->createMode("Spectrum Analyzer", Mode::Type::SA);
auto *spectrumAnalyzer = static_cast<SpectrumAnalyzer*>(modeHandler->getMode(saIndex));
spectrumAnalyzer->fromJSON(j["SpectrumAnalyzer"]); spectrumAnalyzer->fromJSON(j["SpectrumAnalyzer"]);
} }
if(j.contains("Modes")) { if(j.contains("Modes")) {
for(auto jm : j["Modes"]) { for(auto jm : j["Modes"]) {
auto type = Mode::TypeFromName(QString::fromStdString(jm.value("type", "Invalid"))); auto type = Mode::TypeFromName(QString::fromStdString(jm.value("type", "Invalid")));
if(type != Mode::Type::Last && jm.contains("settings")) { if(type != Mode::Type::Last && jm.contains("settings")) {
auto m = Mode::createNew(this, QString::fromStdString(jm.value("name", "")), type); auto index = modeHandler->createMode(QString::fromStdString(jm.value("name", "")), type);
auto m = modeHandler->getMode(index);
m->fromJSON(jm["settings"]); m->fromJSON(jm["settings"]);
} }
} }
@ -1172,15 +1181,16 @@ void AppWindow::LoadSetup(nlohmann::json j)
// activate the correct mode // activate the correct mode
QString modeName = QString::fromStdString(j.value("activeMode", "")); QString modeName = QString::fromStdString(j.value("activeMode", ""));
for(auto m : Mode::getModes()) { for(auto m : modeHandler->getModes()) {
if(m->getName() == modeName) { if(m->getName() == modeName) {
m->activate(); auto index = modeHandler->findIndex(m);
modeHandler->setCurrentIndex(index);
break; break;
} }
} }
// if no mode is activated, there might have been a problem with the setup file. Activate the first mode anyway, to prevent invalid GUI state // if no mode is activated, there might have been a problem with the setup file. Activate the first mode anyway, to prevent invalid GUI state
if(!Mode::getActiveMode() && Mode::getModes().size() > 0) { if(!modeHandler->getActiveMode() && modeHandler->getModes().size() > 0) {
Mode::getModes()[0]->activate(); modeHandler->activate(modeHandler->getModes()[0]);
} }
} }
@ -1194,6 +1204,12 @@ QStackedWidget *AppWindow::getCentral() const
return central; return central;
} }
ModeHandler* AppWindow::getModeHandler() const
{
return modeHandler;
}
Ui::MainWindow *AppWindow::getUi() const Ui::MainWindow *AppWindow::getUi() const
{ {
return ui; return ui;
@ -1273,3 +1289,4 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status)
break; break;
} }
} }

View File

@ -31,6 +31,7 @@ class MainWindow;
class VNA; class VNA;
class Generator; class Generator;
class SpectrumAnalyzer; class SpectrumAnalyzer;
class ModeHandler;
class AppWindow : public QMainWindow class AppWindow : public QMainWindow
{ {
@ -41,6 +42,7 @@ public:
Ui::MainWindow *getUi() const; Ui::MainWindow *getUi() const;
QStackedWidget *getCentral() const; QStackedWidget *getCentral() const;
ModeHandler* getModeHandler() const;
Device*&getDevice(); Device*&getDevice();
const QString& getAppVersion() const; const QString& getAppVersion() const;
@ -98,6 +100,7 @@ private:
} reference; } reference;
} toolbars; } toolbars;
ModeHandler *modeHandler;
Device *device; Device *device;
DeviceLog deviceLog; DeviceLog deviceLog;
QString deviceSerial; QString deviceSerial;

View File

@ -13,110 +13,22 @@
#include <QFileDialog> #include <QFileDialog>
#include <QInputDialog> #include <QInputDialog>
std::vector<Mode*> Mode::modes;
Mode* Mode::activeMode = nullptr;
QTabBar* Mode::tabbar = nullptr;
QWidget* Mode::cornerWidget = nullptr;
//QButtonGroup* Mode::modeButtonGroup = nullptr; //QButtonGroup* Mode::modeButtonGroup = nullptr;
Mode::Mode(AppWindow *window, QString name, QString SCPIname) Mode::Mode(AppWindow *window, QString name, QString SCPIname)
: QObject(window), : QObject(window),
SCPINode(SCPIname), SCPINode(SCPIname),
window(window), window(window),
isActive(false),
name(name), name(name),
central(nullptr) central(nullptr)
{ {
if(!nameAllowed(name)) {
throw std::runtime_error("Unable to create mode, name already taken");
}
// Create mode switch button
if(!cornerWidget) {
// this is the first created mode, initialize corner widget and set this mode as active
cornerWidget = new QWidget();
cornerWidget->setLayout(new QHBoxLayout);
cornerWidget->layout()->setSpacing(0);
cornerWidget->layout()->setMargin(0);
cornerWidget->layout()->setContentsMargins(0,0,0,0);
cornerWidget->setMaximumHeight(window->menuBar()->height());
tabbar = new QTabBar;
tabbar->setTabsClosable(true);
tabbar->setStyleSheet("QTabBar::tab { height: "+QString::number(window->menuBar()->height())+"px;}");
cornerWidget->layout()->addWidget(tabbar);
auto bAdd = new QPushButton();
QIcon icon;
QString iconThemeName = QString::fromUtf8("list-add");
if (QIcon::hasThemeIcon(iconThemeName)) {
icon = QIcon::fromTheme(iconThemeName);
} else {
icon.addFile(QString::fromUtf8(":/icons/add.png"), QSize(), QIcon::Normal, QIcon::Off);
}
bAdd->setIcon(icon);
auto mAdd = new QMenu();
for(unsigned int i=0;i<(int) Type::Last;i++) {
auto type = (Type) i;
auto action = new QAction(TypeToName(type));
mAdd->addAction(action);
connect(action, &QAction::triggered, [=](){
bool ok;
QString text = QInputDialog::getText(window, "Create new "+TypeToName(type)+" tab",
"Name:", QLineEdit::Normal,
TypeToName(type), &ok);
if(ok) {
if(!nameAllowed(text)) {
InformationBox::ShowError("Name collision", "Unable to create tab, no duplicate names allowed");
} else {
auto mode = Mode::createNew(window, text, type);
mode->activate();
}
}
});
}
bAdd->setMenu(mAdd);
bAdd->setMaximumHeight(window->menuBar()->height());
bAdd->setMaximumWidth(40);
cornerWidget->layout()->addWidget(bAdd);
window->menuBar()->setCornerWidget(cornerWidget);
connect(tabbar, &QTabBar::currentChanged, [=](int index){
modes[index]->activate();
});
connect(tabbar, &QTabBar::tabCloseRequested, [=](int index){
delete modes[index];
});
connect(tabbar, &QTabBar::tabMoved, [=](int from, int to){
auto modeFrom = modes.at(from);
auto modeTo = modes.at(to);
modes[from] = modeTo;
modes[to] = modeFrom;
});
}
connect(this, &Mode::statusbarMessage, window, &AppWindow::setModeStatus);
modes.push_back(this);
tabbar->blockSignals(true);
tabbar->insertTab(tabbar->count(), name);
tabbar->blockSignals(false);
tabbar->setMovable(true);
window->getSCPI()->add(this); window->getSCPI()->add(this);
} }
Mode::~Mode() Mode::~Mode()
{ {
window->getSCPI()->remove(this); window->getSCPI()->remove(this);
if(activeMode == this) {
deactivate();
}
auto index = findTabIndex();
tabbar->blockSignals(true);
tabbar->removeTab(index);
tabbar->blockSignals(false);
modes.erase(modes.begin() + index);
if(modes.size() > 0) {
modes[tabbar->currentIndex()]->activate();
}
window->getCentral()->removeWidget(central); window->getCentral()->removeWidget(central);
delete central; delete central;
for(auto d : docks) { for(auto d : docks) {
@ -129,13 +41,7 @@ Mode::~Mode()
void Mode::activate() void Mode::activate()
{ {
if(activeMode == this) { isActive = true;
// already active;
return;
} else if(activeMode) {
activeMode->deactivate();
}
qDebug() << "Activating mode" << name; qDebug() << "Activating mode" << name;
// show all mode specific GUI elements // show all mode specific GUI elements
for(auto t : toolbars) { for(auto t : toolbars) {
@ -152,7 +58,6 @@ void Mode::activate()
QSettings settings; QSettings settings;
window->getCentral()->setCurrentWidget(central); window->getCentral()->setCurrentWidget(central);
// restore dock and toolbar positions // restore dock and toolbar positions
window->restoreState(settings.value("windowState_"+name).toByteArray()); window->restoreState(settings.value("windowState_"+name).toByteArray());
@ -174,12 +79,6 @@ void Mode::activate()
} }
} }
activeMode = this;
// force activation of correct tab in case the mode switch was done via script/setup load.
// This will trigger a second activation of this mode in the signal of the tab bar, but since it is
// already the active mode, this function will just return -> no recursion
tabbar->setCurrentIndex(findTabIndex());
if(window->getDevice()) { if(window->getDevice()) {
initializeDevice(); initializeDevice();
} }
@ -189,6 +88,7 @@ void Mode::activate()
void Mode::deactivate() void Mode::deactivate()
{ {
isActive = false;
QSettings settings; QSettings settings;
// save dock/toolbar visibility // save dock/toolbar visibility
for(auto d : docks) { for(auto d : docks) {
@ -213,15 +113,10 @@ void Mode::deactivate()
} }
qDebug() << "Deactivated mode" << name; qDebug() << "Deactivated mode" << name;
if(window->getDevice()) { if(window->getDevice()) {
window->getDevice()->SetIdle(); window->getDevice()->SetIdle();
} }
activeMode = nullptr;
}
Mode *Mode::getActiveMode()
{
return activeMode;
} }
QString Mode::TypeToName(Mode::Type t) QString Mode::TypeToName(Mode::Type t)
@ -258,27 +153,6 @@ void Mode::saveSreenshot()
central->grab().save(filename); central->grab().save(filename);
} }
Mode *Mode::createNew(AppWindow *window, QString name, Mode::Type t)
{
switch(t) {
case Type::VNA: return new VNA(window, name);
case Type::SG: return new Generator(window, name);
case Type::SA: return new SpectrumAnalyzer(window, name);
default: return nullptr;
}
}
bool Mode::nameAllowed(QString name)
{
for(auto m : modes) {
if(m->getName() == name) {
// name already taken, no duplicates allowed
return false;
}
}
return true;
}
void Mode::finalize(QWidget *centralWidget) void Mode::finalize(QWidget *centralWidget)
{ {
central = centralWidget; central = centralWidget;
@ -302,33 +176,10 @@ void Mode::finalize(QWidget *centralWidget)
} }
} }
int Mode::findTabIndex()
{
auto it = std::find(modes.begin(), modes.end(), this);
return it - modes.begin();
}
std::vector<Mode *> Mode::getModes()
{
return modes;
}
Mode *Mode::findFirstOfType(Mode::Type t)
{
for(auto m : modes) {
if(m->getType() == t) {
return m;
}
}
return nullptr;
}
void Mode::setStatusbarMessage(QString msg) void Mode::setStatusbarMessage(QString msg)
{ {
statusbarMsg = msg; statusbarMsg = msg;
if(this == activeMode) { emit statusbarMessage(msg);
emit statusbarMessage(msg);
}
} }
QString Mode::getName() const QString Mode::getName() const
@ -338,12 +189,7 @@ QString Mode::getName() const
void Mode::setName(const QString &value) void Mode::setName(const QString &value)
{ {
if(!nameAllowed(value)) {
// unable to use this name
return;
}
name = value; name = value;
tabbar->setTabText(findTabIndex(), name);
} }
void Mode::updateGraphColors() void Mode::updateGraphColors()

View File

@ -16,6 +16,7 @@
class Mode : public QObject, public Savable, public SCPINode class Mode : public QObject, public Savable, public SCPINode
{ {
Q_OBJECT Q_OBJECT
friend class ModeHandler;
public: public:
enum class Type { enum class Type {
VNA, VNA,
@ -27,13 +28,10 @@ public:
Mode(AppWindow *window, QString name, QString SCPIname); Mode(AppWindow *window, QString name, QString SCPIname);
~Mode(); ~Mode();
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 virtual void shutdown(){}; // called when the application is about to exit
QString getName() const; QString getName() const;
void setName(const QString &value); void setName(const QString &value);
void updateGraphColors(); void updateGraphColors();
static Mode *getActiveMode();
static QString TypeToName(Type t); static QString TypeToName(Type t);
static Type TypeFromName(QString s); static Type TypeFromName(QString s);
virtual Type getType() = 0; virtual Type getType() = 0;
@ -43,14 +41,16 @@ public:
virtual void saveSreenshot(); virtual void saveSreenshot();
static Mode *createNew(AppWindow *window, QString name, Type t); virtual void setAveragingMode(Averaging::Mode mode) = 0;
static bool nameAllowed(QString name);
static std::vector<Mode *> getModes();
static Mode* findFirstOfType(Type t);
signals: signals:
void statusbarMessage(QString msg); void statusbarMessage(QString msg);
protected: protected:
virtual void activate(); // derived classes must call Mode::activate before doing anything
virtual void deactivate(); // derived classes must call Mode::deactivate before returning
bool isActive;
void setStatusbarMessage(QString msg); void setStatusbarMessage(QString msg);
// call once the derived class is fully initialized // call once the derived class is fully initialized
void finalize(QWidget *centralWidget); void finalize(QWidget *centralWidget);
@ -60,14 +60,10 @@ protected:
std::set<QDockWidget*> docks; std::set<QDockWidget*> docks;
private: private:
int findTabIndex();
static std::vector<Mode*> modes;
static Mode *activeMode;
static QTabBar *tabbar;
static QWidget *cornerWidget;
// static QButtonGroup *modeButtonGroup; // static QButtonGroup *modeButtonGroup;
QString name; QString name;
QString statusbarMsg; QString statusbarMsg;
QWidget *central; QWidget *central;
}; };

View File

@ -0,0 +1,204 @@
#include "modehandler.h"
#include "VNA/vna.h"
#include "SpectrumAnalyzer/spectrumanalyzer.h"
#include "Generator/generator.h"
#include "mode.h"
#include "averaging.h"
ModeHandler::ModeHandler(AppWindow *aw):
QObject(),
aw(aw)
{}
void ModeHandler::shutdown()
{
for(auto m : modes) {
m->shutdown();
}
}
int ModeHandler::createMode(QString name, Mode::Type t)
{
auto mode = createNew(aw, name, t);
return createMode(mode);
}
int ModeHandler::createMode(Mode *mode)
{
modes.push_back(mode);
currentModeIndex = int(modes.size()) - 1;
connect(mode, &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged);
auto m = getMode(currentModeIndex);
activate(m);
emit ModeCreated(currentModeIndex);
return (currentModeIndex);
}
Mode *ModeHandler::createNew(AppWindow *aw, QString name, Mode::Type t)
{
switch(t) {
case Mode::Type::VNA: return new VNA(aw, name);
case Mode::Type::SG: return new Generator(aw, name);
case Mode::Type::SA: return new SpectrumAnalyzer(aw, name);
default: return nullptr;
}
}
Mode* ModeHandler::getActiveMode()
{
return activeMode;
}
Mode* ModeHandler::getMode(int index)
{
return modes.at(index);
}
void ModeHandler::activate(Mode * mode)
{
if (getActiveMode() == mode) {
// Already active
return;
}
else if (getActiveMode()) {
deactivate(getActiveMode());
}
activeMode = mode;
mode->activate();
}
void ModeHandler::deactivate(Mode* mode)
{
mode->deactivate();
activeMode = nullptr;
}
std::vector<Mode*> ModeHandler::getModes()
{
return modes;
}
void ModeHandler::setCurrentIndex(int index)
{
if (index >= 0) {
currentModeIndex = index;
auto m = getMode(getCurrentIndex());
activate(m);
emit CurrentModeChanged(getCurrentIndex());
}
}
void ModeHandler::currentModeMoved(int from, int to)
{
auto modeFrom = modes.at(from);
auto modeTo = modes.at(to);
modes[from] = modeTo;
modes[to] = modeFrom;
}
int ModeHandler::getCurrentIndex()
{
return currentModeIndex;
}
void ModeHandler::closeMode(int index)
{
disconnect(modes.at(index), &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged);
std::vector<int> idx;
for(int i=0; i < int(modes.size()); i++)
{
idx.push_back(i);
}
auto left = std::find(idx.begin(), idx.end(), getCurrentIndex()-1);
auto right = std::find(idx.begin(), idx.end(), getCurrentIndex()+1);
auto foundLeft = false;
auto foundRight = false;
if ( left != idx.end() )
{
foundLeft = true;
}
if ( right != idx.end() )
{
foundRight = true;
}
auto lastIndex = getCurrentIndex();
if (int(modes.size()) > 0) {
if (getCurrentIndex() == index)
{
if (foundLeft)
{
setCurrentIndex(getCurrentIndex()-1);
}
else if (foundRight)
{
setCurrentIndex(getCurrentIndex()+1);
}
}
}
if (getActiveMode() == modes.at(index)) {
deactivate(getActiveMode());
}
delete modes.at(index);
modes.erase(modes.begin() + index);
if (getCurrentIndex() == 1 && lastIndex == 0) {
setCurrentIndex(0);
}
emit ModeClosed(index);
}
void ModeHandler::closeModes()
{
while(modes.size() > 0) {
closeMode(0);
}
}
void ModeHandler::setStatusBarMessageChanged(const QString &msg)
{
QObject* mode = sender();
if ( getActiveMode() == mode) {
emit StatusBarMessageChanged(msg);
}
}
bool ModeHandler::nameAllowed(const QString &name)
{
for(auto m : modes) {
if(m->getName() == name) {
/* name already taken, no duplicates allowed
* when importing, name is used as value
*/
return false;
}
}
return true;
}
int ModeHandler::findIndex(Mode *targetMode)
{
auto it = std::find(modes.begin(), modes.end(), targetMode);
return it - modes.begin();
}
Mode* ModeHandler::findFirstOfType(Mode::Type t)
{
for(auto m : modes) {
if(m->getType() == t) {
return m;
}
}
return nullptr;
}

View File

@ -0,0 +1,58 @@
#ifndef MODEHANDLER_H
#define MODEHANDLER_H
#include "mode.h"
#include "appwindow.h"
#include <vector>
#include <QObject>
class ModeHandler: public QObject
{
Q_OBJECT
public:
ModeHandler(AppWindow *window);
~ModeHandler() = default;
void shutdown();
int createMode(QString name, Mode::Type t);
void closeMode(int index);
void currentModeMoved(int from, int to);
void closeModes();
int getCurrentIndex();
Mode* getActiveMode();
void activate(Mode * mode);
void deactivate(Mode* mode);
Mode* getMode(int index);
std::vector<Mode*> getModes();
bool nameAllowed(const QString &name);
int findIndex(Mode *targetMode);
Mode* findFirstOfType(Mode::Type t);
signals:
void StatusBarMessageChanged(const QString &msg);
void ModeCreated(int modeIndex);
void ModeClosed(int modeIndex);
void CurrentModeChanged(int modeIndex);
public slots:
void setCurrentIndex(int modeIndex);
private:
std::vector<Mode*> modes;
int currentModeIndex;
int createMode(Mode *mode);
Mode *createNew(AppWindow *window, QString name, Mode::Type t);
AppWindow *aw;
Mode *activeMode = nullptr;
private slots:
void setStatusBarMessageChanged(const QString &msg);
};
#endif // MODEHANDLER_H

View File

@ -0,0 +1,117 @@
#include "modewindow.h"
#include "mode.h"
#include "appwindow.h"
#include "CustomWidgets/informationbox.h"
#include <QInputDialog>
#include <QPushButton>
#include <QMenuBar>
ModeWindow::ModeWindow(ModeHandler* handler, AppWindow* aw, QWidget* parent):
QWidget(parent),
handler(handler),
aw(aw)
{
SetupUi();
connect(handler, &ModeHandler::ModeCreated, this, &ModeWindow::ModeCreated);
connect(handler, &ModeHandler::ModeClosed, this, &ModeWindow::ModeClosed);
connect(handler, &ModeHandler::CurrentModeChanged, this, &ModeWindow::CurrentModeChanged);
connect(tabBar, &QTabBar::currentChanged, handler, &ModeHandler::setCurrentIndex);
connect(tabBar, &QTabBar::tabCloseRequested, handler, &ModeHandler::closeMode);
connect(tabBar, &QTabBar::tabMoved, handler, &ModeHandler::currentModeMoved);
}
ModeWindow::~ModeWindow()
{
}
void ModeWindow::SetupUi()
{
auto cornerWidget = new QWidget();
cornerWidget->setLayout(new QHBoxLayout);
cornerWidget->layout()->setSpacing(0);
cornerWidget->layout()->setMargin(0);
cornerWidget->layout()->setContentsMargins(0,0,0,0);
cornerWidget->setMaximumHeight(aw->menuBar()->height());
tabBar = new QTabBar;
tabBar->setStyleSheet("QTabBar::tab { height: " + QString::number(aw->menuBar()->height()) + "px;}");
tabBar->setTabsClosable(true);
cornerWidget->layout()->addWidget(tabBar);
auto bAdd = new QPushButton();
QIcon icon;
QString iconThemeName = QString::fromUtf8("list-add");
if (QIcon::hasThemeIcon(iconThemeName))
icon = QIcon::fromTheme(iconThemeName);
else
icon.addFile(QString::fromUtf8(":/icons/add.png"), QSize(), QIcon::Normal, QIcon::Off);
bAdd->setIcon(icon);
bAdd->setMaximumHeight(aw->menuBar()->height());
bAdd->setMaximumWidth(40);
auto mAdd = new QMenu();
for(unsigned int i=0;i<(int) Mode::Type::Last;i++) {
auto type = (Mode::Type) i;
auto action = new QAction(Mode::TypeToName(type));
mAdd->addAction(action);
connect(action, &QAction::triggered, [=](){
bool ok;
QString text = QInputDialog::getText(this,
"Create new "+Mode::TypeToName(type)+" tab",
"Name:", QLineEdit::Normal,
Mode::TypeToName(type), &ok);
if(ok) {
if(!handler->nameAllowed(text)) {
InformationBox::ShowError("Name collision", "Unable to create tab, " \
"no duplicate names allowed");
} else {
handler->createMode(text, type);
}
}
});
}
bAdd->setMenu(mAdd);
cornerWidget->layout()->addWidget(bAdd);
aw->menuBar()->setCornerWidget(cornerWidget);
}
void ModeWindow::ModeCreated(int modeIndex)
{
auto mode = handler->getMode(modeIndex);
if (mode)
{
const auto name = mode->getName();
tabBar->blockSignals(true);
tabBar->insertTab(modeIndex, name);
tabBar->blockSignals(false);
tabBar->setMovable(true);
tabBar->setCurrentIndex(modeIndex);
}
}
void ModeWindow::ModeClosed(int modeIndex)
{
tabBar->blockSignals(true);
tabBar->removeTab(modeIndex);
tabBar->blockSignals(false);
}
void ModeWindow::CurrentModeChanged(int modeIndex)
{
if (modeIndex != tabBar->currentIndex())
{
tabBar->setCurrentIndex(modeIndex);
}
}

View File

@ -0,0 +1,25 @@
#ifndef MODEWINDOW_H
#define MODEWINDOW_H
#include "modehandler.h"
class ModeWindow: public QWidget
{
Q_OBJECT
public:
explicit ModeWindow(ModeHandler* handler, AppWindow* aw, QWidget *parent = nullptr);
~ModeWindow();
private:
ModeHandler* handler;
void SetupUi();
AppWindow* aw;
QTabBar* tabBar;
private slots:
void ModeCreated(int modeIndex);
void ModeClosed(int modeIndex);
void CurrentModeChanged(int modeIndex);
};
#endif // MODEWINDOW_H