From 7a0e6da706a57b633bdbf59b22b4379f99ddfa40 Mon Sep 17 00:00:00 2001 From: Kiara Navarro Date: Sat, 2 Jul 2022 10:01:43 -0500 Subject: [PATCH] mode/app: decouple mode creation from gui components Signed-off-by: Kiara Navarro --- Software/PC_Application/LibreVNA-GUI.pro | 7 ++ Software/PC_Application/appwindow.cpp | 104 +++++++--------- Software/PC_Application/appwindow.h | 3 +- Software/PC_Application/mode.cpp | 135 +-------------------- Software/PC_Application/mode.h | 9 +- Software/PC_Application/modehandler.cpp | 138 ++++++++++++++++++++++ Software/PC_Application/modehandler.h | 50 ++++++++ Software/PC_Application/modetabwidget.cpp | 14 +++ Software/PC_Application/modetabwidget.h | 18 +++ Software/PC_Application/modewindow.cpp | 99 ++++++++++++++++ Software/PC_Application/modewindow.h | 28 +++++ Software/PC_Application/modewindow.ui | 45 +++++++ 12 files changed, 454 insertions(+), 196 deletions(-) create mode 100644 Software/PC_Application/modehandler.cpp create mode 100644 Software/PC_Application/modehandler.h create mode 100644 Software/PC_Application/modetabwidget.cpp create mode 100644 Software/PC_Application/modetabwidget.h create mode 100644 Software/PC_Application/modewindow.cpp create mode 100644 Software/PC_Application/modewindow.h create mode 100644 Software/PC_Application/modewindow.ui diff --git a/Software/PC_Application/LibreVNA-GUI.pro b/Software/PC_Application/LibreVNA-GUI.pro index bd60738..5665ce2 100644 --- a/Software/PC_Application/LibreVNA-GUI.pro +++ b/Software/PC_Application/LibreVNA-GUI.pro @@ -123,7 +123,10 @@ HEADERS += \ averaging.h \ csv.h \ json.hpp \ + modehandler.h \ mode.h \ + modetabwidget.h \ + modewindow.h \ preferences.h \ savable.h \ scpi.h \ @@ -242,7 +245,10 @@ SOURCES += \ averaging.cpp \ csv.cpp \ main.cpp \ + modehandler.cpp \ mode.cpp \ + modetabwidget.cpp \ + modewindow.cpp \ preferences.cpp \ scpi.cpp \ tcpserver.cpp \ @@ -306,6 +312,7 @@ FORMS += \ VNA/s2pImportOptions.ui \ aboutdialog.ui \ main.ui \ + modewindow.ui \ preferencesdialog.ui DISTFILES += diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index 305960c..7cb3f28 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -27,12 +27,14 @@ #include "CustomWidgets/informationbox.h" #include "Util/app_common.h" #include "about.h" +#include "mode.h" +#include "modehandler.h" +#include "modewindow.h" #include #include #include #include -#include #include #include #include @@ -168,6 +170,7 @@ AppWindow::AppWindow(QWidget *parent) , appVersion(APP_VERSION) , appGitHash(APP_GIT_HASH) { + // qDebug().setVerbosity(0); qDebug() << "Application start"; @@ -186,6 +189,7 @@ AppWindow::AppWindow(QWidget *parent) Preferences::getInstance().load(); device = nullptr; + modeHandler = nullptr; if(parser.isSet("port")) { bool OK; @@ -222,12 +226,19 @@ AppWindow::AppWindow(QWidget *parent) ui->menuToolbars->addAction(t->toggleViewAction()); } - // Create GUI modes - central = new QStackedWidget; - setCentralWidget(central); - auto vna = new VNA(this); - auto generator = new Generator(this); - auto spectrumAnalyzer = new SpectrumAnalyzer(this); + modeHandler = new ModeHandler(this); + auto modeWindow = new ModeWindow(modeHandler, this); + + setCentralWidget(modeWindow); + modeHandler->createMode("Vector Network Analyzer", Mode::Type::VNA); + modeHandler->createMode("Spectrum Analyzer", Mode::Type::SA); + modeHandler->createMode("Signal Generator", Mode::Type::SG); + + auto setModeStatusbar = [=](const QString &msg) { + lModeInfo.setText(msg); + }; + + connect(modeHandler, &ModeHandler::StatusBarMessageChanged, setModeStatusbar); // UI connections connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList); @@ -271,32 +282,10 @@ AppWindow::AppWindow(QWidget *parent) } } - // averaging mode may have changed, update for all relevant modes - for (auto m : Mode::getModes()) - { - switch (m->getType()) - { - case Mode::Type::VNA: - if(p.Acquisition.useMedianAveraging) { - static_cast(m)->setAveragingMode(Averaging::Mode::Median); - } - else { - static_cast(m)->setAveragingMode(Averaging::Mode::Mean); - } - break; - case Mode::Type::SA: - if(p.Acquisition.useMedianAveraging) { - static_cast(m)->setAveragingMode(Averaging::Mode::Median); - } - else { - static_cast(m)->setAveragingMode(Averaging::Mode::Mean); - } - break; - case Mode::Type::SG: - case Mode::Type::Last: - default: - break; - } + if(p.Acquisition.useMedianAveraging) { + modeHandler->setAveragingMode(Averaging::Mode::Median); + } else { + modeHandler->setAveragingMode(Averaging::Mode::Mean); } // acquisition frequencies may have changed, update @@ -333,9 +322,6 @@ AppWindow::AppWindow(QWidget *parent) SetupSCPI(); - // Set default mode - vna->activate(); - auto pref = Preferences::getInstance(); if(pref.Startup.UseSetupFile) { LoadSetup(pref.Startup.SetupFile); @@ -351,7 +337,8 @@ AppWindow::AppWindow(QWidget *parent) LoadSetup(parser.value("setup")); } if(parser.isSet("cal")) { - vna->LoadCalibration(parser.value("cal")); + VNA* mode = static_cast(modeHandler->findFirstOfType(Mode::Type::VNA)); + mode->LoadCalibration(parser.value("cal")); } if(!parser.isSet("no-gui")) { InformationBox::setGUI(true); @@ -375,9 +362,7 @@ void AppWindow::closeEvent(QCloseEvent *event) if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) { SaveSetup(pref.Startup.SetupFile); } - for(auto m : Mode::getModes()) { - m->shutdown(); - } + modeHandler->shutdown(); QSettings settings; settings.setValue("geometry", saveGeometry()); // deactivate currently used mode (stores mode state in settings) @@ -385,6 +370,8 @@ void AppWindow::closeEvent(QCloseEvent *event) Mode::getActiveMode()->deactivate(); } delete device; + delete modeHandler; + modeHandler = nullptr; pref.store(); QMainWindow::closeEvent(event); } @@ -586,11 +573,11 @@ void AppWindow::SetupSCPI() } Mode *mode = nullptr; if (params[0] == "VNA") { - mode = Mode::findFirstOfType(Mode::Type::VNA); + mode = modeHandler->findFirstOfType(Mode::Type::VNA); } else if(params[0] == "GEN") { - mode = Mode::findFirstOfType(Mode::Type::SG); + mode = modeHandler->findFirstOfType(Mode::Type::SG); } else if(params[0] == "SA") { - mode = Mode::findFirstOfType(Mode::Type::SA); + mode = modeHandler->findFirstOfType(Mode::Type::SA); } else { return "INVALID MDOE"; } @@ -1082,7 +1069,7 @@ nlohmann::json AppWindow::SaveSetup() { nlohmann::json j; nlohmann::json jm; - for(auto m : Mode::getModes()) { + for(auto m : modeHandler->getModes()) { nlohmann::json jmode; jmode["type"] = Mode::TypeToName(m->getType()).toStdString(); jmode["name"] = m->getName().toStdString(); @@ -1138,28 +1125,31 @@ void AppWindow::LoadSetup(nlohmann::json j) toolbars.reference.type->setCurrentIndex(index); toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off"))); } - while(Mode::getModes().size() > 0) { - delete Mode::getModes()[0]; - } + + modeHandler->closeModes(); // old style VNA/Generator/Spectrum Analyzer settings if(j.contains("VNA")) { - auto vna = new VNA(this); + modeHandler->createMode("Vector Network Analyzer", Mode::Type::VNA); + auto * vna = static_cast(modeHandler->findFirstOfType(Mode::Type::VNA)); vna->fromJSON(j["VNA"]); } if(j.contains("Generator")) { - auto generator = new Generator(this); + modeHandler->createMode("Generator", Mode::Type::SG); + auto * generator = static_cast(modeHandler->findFirstOfType(Mode::Type::SG)); generator->fromJSON(j["Generator"]); } if(j.contains("SpectrumAnalyzer")) { - auto spectrumAnalyzer = new SpectrumAnalyzer(this); + modeHandler->createMode("Spectrum Analyzer", Mode::Type::SA); + auto * spectrumAnalyzer = static_cast(modeHandler->findFirstOfType(Mode::Type::SA)); spectrumAnalyzer->fromJSON(j["SpectrumAnalyzer"]); } if(j.contains("Modes")) { for(auto jm : j["Modes"]) { auto type = Mode::TypeFromName(QString::fromStdString(jm.value("type", "Invalid"))); if(type != Mode::Type::Last && jm.contains("settings")) { - auto m = Mode::createNew(this, QString::fromStdString(jm.value("name", "")), type); + modeHandler->createMode(QString::fromStdString(jm.value("name", "")), type); + auto m = modeHandler->getMode(modeHandler->getCurrentIndex()); m->fromJSON(jm["settings"]); } } @@ -1167,15 +1157,15 @@ void AppWindow::LoadSetup(nlohmann::json j) // activate the correct mode QString modeName = QString::fromStdString(j.value("activeMode", "")); - for(auto m : Mode::getModes()) { + for(auto m : modeHandler->getModes()) { if(m->getName() == modeName) { m->activate(); 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(!Mode::getActiveMode() && Mode::getModes().size() > 0) { - Mode::getModes()[0]->activate(); + if(!Mode::getActiveMode() && modeHandler->getModes().size() > 0) { + modeHandler->getModes()[0]->activate(); } } @@ -1184,11 +1174,6 @@ Device *&AppWindow::getDevice() return device; } -QStackedWidget *AppWindow::getCentral() const -{ - return central; -} - Ui::MainWindow *AppWindow::getUi() const { return ui; @@ -1268,3 +1253,4 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status) break; } } + diff --git a/Software/PC_Application/appwindow.h b/Software/PC_Application/appwindow.h index 90b18f2..d3ec2b1 100644 --- a/Software/PC_Application/appwindow.h +++ b/Software/PC_Application/appwindow.h @@ -31,6 +31,7 @@ class MainWindow; class VNA; class Generator; class SpectrumAnalyzer; +class ModeHandler; class AppWindow : public QMainWindow { @@ -40,7 +41,6 @@ public: ~AppWindow(); Ui::MainWindow *getUi() const; - QStackedWidget *getCentral() const; Device*&getDevice(); const QString& getAppVersion() const; @@ -98,6 +98,7 @@ private: } reference; } toolbars; + ModeHandler *modeHandler; Device *device; DeviceLog deviceLog; QString deviceSerial; diff --git a/Software/PC_Application/mode.cpp b/Software/PC_Application/mode.cpp index 163f203..787163f 100644 --- a/Software/PC_Application/mode.cpp +++ b/Software/PC_Application/mode.cpp @@ -13,10 +13,7 @@ #include #include -std::vector Mode::modes; Mode* Mode::activeMode = nullptr; -QTabBar* Mode::tabbar = nullptr; -QWidget* Mode::cornerWidget = nullptr; //QButtonGroup* Mode::modeButtonGroup = nullptr; Mode::Mode(AppWindow *window, QString name, QString SCPIname) @@ -26,80 +23,6 @@ Mode::Mode(AppWindow *window, QString name, QString SCPIname) name(name), 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); } @@ -109,16 +32,6 @@ Mode::~Mode() 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); - delete central; for(auto d : docks) { delete d; } @@ -151,7 +64,6 @@ void Mode::activate() } QSettings settings; - window->getCentral()->setCurrentWidget(central); // restore dock and toolbar positions window->restoreState(settings.value("windowState_"+name).toByteArray()); @@ -175,10 +87,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()) { initializeDevice(); @@ -268,21 +176,9 @@ Mode *Mode::createNew(AppWindow *window, QString name, Mode::Type t) } } -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) { central = centralWidget; - window->getCentral()->addWidget(central); // Set ObjectName for toolbars and docks for(auto d : docks) { d->setObjectName(d->windowTitle()+name); @@ -302,27 +198,6 @@ void Mode::finalize(QWidget *centralWidget) } } -int Mode::findTabIndex() -{ - auto it = std::find(modes.begin(), modes.end(), this); - return it - modes.begin(); -} - -std::vector 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) { statusbarMsg = msg; @@ -338,12 +213,7 @@ QString Mode::getName() const void Mode::setName(const QString &value) { - if(!nameAllowed(value)) { - // unable to use this name - return; - } name = value; - tabbar->setTabText(findTabIndex(), name); } void Mode::updateGraphColors() @@ -354,3 +224,8 @@ void Mode::updateGraphColors() } } } + +QWidget *Mode::getCentral() const +{ + return central; +} diff --git a/Software/PC_Application/mode.h b/Software/PC_Application/mode.h index 038cc53..a031d75 100644 --- a/Software/PC_Application/mode.h +++ b/Software/PC_Application/mode.h @@ -44,9 +44,8 @@ public: virtual void saveSreenshot(); static Mode *createNew(AppWindow *window, QString name, Type t); - static bool nameAllowed(QString name); - static std::vector getModes(); - static Mode* findFirstOfType(Type t); + + virtual QWidget *getCentral() const; signals: void statusbarMessage(QString msg); @@ -60,14 +59,12 @@ protected: std::set docks; private: - int findTabIndex(); static std::vector modes; static Mode *activeMode; - static QTabBar *tabbar; - static QWidget *cornerWidget; // static QButtonGroup *modeButtonGroup; QString name; QString statusbarMsg; + QWidget *central; }; diff --git a/Software/PC_Application/modehandler.cpp b/Software/PC_Application/modehandler.cpp new file mode 100644 index 0000000..61357c7 --- /dev/null +++ b/Software/PC_Application/modehandler.cpp @@ -0,0 +1,138 @@ +#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(); + } +} + +void ModeHandler::createMode(QString name, Mode::Type t) +{ + auto mode = Mode::createNew(aw, name, t); + createMode(mode); +} + +void ModeHandler::createMode(Mode *mode) +{ + modes.push_back(mode); + currentModeIndex = int(modes.size()); + connect(mode, &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged); + emit ModeCreated(currentModeIndex - 1); + +} + +Mode* ModeHandler::getMode(int index) +{ + return modes.at(index); +} + +std::vector ModeHandler::getModes() +{ + return modes; +} + +void ModeHandler::setCurrentIndex(int index) +{ + if ( (currentModeIndex != index) && (index >= 0)) { + currentModeIndex = index; + auto * mode = modes.at(currentModeIndex); + mode->activate(); + } +} + +int ModeHandler::getCurrentIndex() +{ + return currentModeIndex; +} + +void ModeHandler::closeMode(int index) +{ + disconnect(modes.at(index), &Mode::statusbarMessage, this, &ModeHandler::setStatusBarMessageChanged); + delete modes.at(index); + modes.erase(modes.begin() + index); + if (currentModeIndex > int(modes.size()) ) { + setCurrentIndex(currentModeIndex - 1); // Select bar before one deleted + auto vna = modes.at(currentModeIndex); + vna->activate(); + } + emit ModeClosed(index); +} + +void ModeHandler::closeModes() +{ + while(modes.size() > 0) { + closeMode(0); + } +} + +void ModeHandler::setStatusBarMessageChanged(const QString &msg) +{ + 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; +} + +Mode* ModeHandler::findFirstOfType(Mode::Type t) +{ + for(auto m : modes) { + if(m->getType() == t) { + return m; + } + } + return nullptr; +} + +void ModeHandler::setAveragingMode(Averaging::Mode value) +{ + + + // averaging mode may have changed, update for all relevant modes + for (auto m : getModes()) + { + switch (m->getType()) + { + case Mode::Type::VNA: + static_cast(m)->setAveragingMode(value); + break; + case Mode::Type::SA: + static_cast(m)->setAveragingMode(value); + break; + case Mode::Type::SG: + case Mode::Type::Last: + default: + break; + } + } + + for(auto m : modes) { + if (m->getType() == Mode::Type::SA) { + static_cast(m)->setAveragingMode(value); + } + else if (m->getType() == Mode::Type::VNA) { + static_cast(m)->setAveragingMode(value); + } + } +} diff --git a/Software/PC_Application/modehandler.h b/Software/PC_Application/modehandler.h new file mode 100644 index 0000000..b41c758 --- /dev/null +++ b/Software/PC_Application/modehandler.h @@ -0,0 +1,50 @@ +#ifndef MODEHANDLER_H +#define MODEHANDLER_H + +#include "mode.h" +#include "appwindow.h" + +#include +#include + +class ModeHandler: public QObject +{ + Q_OBJECT +public: + ModeHandler(AppWindow *window); + ~ModeHandler() = default; + + void shutdown(); + void createMode(QString name, Mode::Type t); + void closeMode(int index); + void closeModes(); + int getCurrentIndex(); + + Mode* getMode(int index); + std::vector getModes(); + + bool nameAllowed(const QString &name); + Mode* findFirstOfType(Mode::Type t); + + void setAveragingMode(Averaging::Mode m); + +signals: + void StatusBarMessageChanged(const QString &msg); + + void ModeCreated(int modeIndex); + void ModeClosed(int modeIndex); + +public slots: + void setCurrentIndex(int modeIndex); + +private: + std::vector modes; + int currentModeIndex; + void createMode(Mode *mode); + AppWindow *aw; + +private slots: + void setStatusBarMessageChanged(const QString &msg); +}; + +#endif // MODEHANDLER_H diff --git a/Software/PC_Application/modetabwidget.cpp b/Software/PC_Application/modetabwidget.cpp new file mode 100644 index 0000000..e2170b9 --- /dev/null +++ b/Software/PC_Application/modetabwidget.cpp @@ -0,0 +1,14 @@ +#include "modetabwidget.h" + +#include +#include + +ModeTabWidget::ModeTabWidget(QWidget* parent): + QTabWidget(parent) +{ + tabBar = new QTabBar; + tabBar->setStyleSheet("QTabBar::tab { height: " + QString::number(parent->height()) + "px;}"); + this->setTabBar(tabBar); + this->setTabsClosable(true); + this->setMovable(true); +} diff --git a/Software/PC_Application/modetabwidget.h b/Software/PC_Application/modetabwidget.h new file mode 100644 index 0000000..0e1e786 --- /dev/null +++ b/Software/PC_Application/modetabwidget.h @@ -0,0 +1,18 @@ +#ifndef MODETABWIDGET_H +#define MODETABWIDGET_H + +#include +#include + +class ModeTabWidget: public QTabWidget +{ + Q_OBJECT +public: + explicit ModeTabWidget(QWidget* parent = nullptr); + ~ModeTabWidget() = default; + +private: + QTabBar * tabBar = nullptr; +}; + +#endif // MODETABWIDGET_H diff --git a/Software/PC_Application/modewindow.cpp b/Software/PC_Application/modewindow.cpp new file mode 100644 index 0000000..cacbb38 --- /dev/null +++ b/Software/PC_Application/modewindow.cpp @@ -0,0 +1,99 @@ +#include "modewindow.h" + +#include "mode.h" +#include "ui_modewindow.h" +#include "appwindow.h" +#include "CustomWidgets/informationbox.h" + +#include +#include +#include + +ModeWindow::ModeWindow(ModeHandler* handler, AppWindow* aw, QWidget* parent): + QWidget(parent), + handler(handler), + aw(aw) +{ + ui = new Ui::ModeWindow; + ui->setupUi(this); + + SetupUi(); + + connect(handler, &ModeHandler::ModeCreated, this, &ModeWindow::ModeCreated); + connect(handler, &ModeHandler::ModeClosed, this, &ModeWindow::ModeClosed); + + connect(ui->tabwidgetModes, &ModeTabWidget::currentChanged, handler, &ModeHandler::setCurrentIndex); + connect(ui->tabwidgetModes, &ModeTabWidget::tabCloseRequested, handler, &ModeHandler::closeMode); + +} + +ModeWindow::~ModeWindow() +{ + delete ui; + ui = nullptr; +} + +void ModeWindow::SetupUi() +{ + ui->horizontalLayout->setSpacing(0); + ui->horizontalLayout->setMargin(0); + ui->horizontalLayout->setContentsMargins(0,0,0,0); + ui->tabwidgetModes->setUsesScrollButtons(true); + + 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(450); + 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); + aw->menuBar()->setCornerWidget(bAdd); +} + +void ModeWindow::ModeCreated(int modeIndex) +{ + auto mode = handler->getMode(modeIndex); + + if (mode) + { + const auto name = mode->getName(); + auto central = mode->getCentral(); + const auto tabIndex = ui->tabwidgetModes->insertTab(modeIndex, central, name); + ui->tabwidgetModes->setCurrentIndex(tabIndex); + } +} + +void ModeWindow::ModeClosed(int modeIndex) +{ + auto modeWidget = ui->tabwidgetModes->widget(modeIndex); + ui->tabwidgetModes->removeTab(modeIndex); + delete modeWidget; +} diff --git a/Software/PC_Application/modewindow.h b/Software/PC_Application/modewindow.h new file mode 100644 index 0000000..4a31286 --- /dev/null +++ b/Software/PC_Application/modewindow.h @@ -0,0 +1,28 @@ +#ifndef MODEWINDOW_H +#define MODEWINDOW_H + +#include "modehandler.h" + +namespace Ui { + class ModeWindow; +} + +class ModeWindow: public QWidget +{ + Q_OBJECT +public: + explicit ModeWindow(ModeHandler* handler, AppWindow* aw, QWidget *parent = nullptr); + ~ModeWindow(); + +private: + ModeHandler* handler; + Ui::ModeWindow *ui; + void SetupUi(); + AppWindow* aw; + +private slots: + void ModeCreated(int modeIndex); + void ModeClosed(int modeIndex); +}; + +#endif // MODEWINDOW_H diff --git a/Software/PC_Application/modewindow.ui b/Software/PC_Application/modewindow.ui new file mode 100644 index 0000000..4f9e2d3 --- /dev/null +++ b/Software/PC_Application/modewindow.ui @@ -0,0 +1,45 @@ + + + ModeWindow + + + + 0 + 0 + 22 + 29 + + + + Form + + + + + + Qt::LeftToRight + + + -1 + + + false + + + true + + + + + + + + ModeTabWidget + QTabWidget +
modetabwidget.h
+ 1 +
+
+ + +