From 3b87323475b7f471fa7dcc399d09d2549c91111c Mon Sep 17 00:00:00 2001 From: Giacomo Caironi <giacomo.caironi@skywarder.eu> Date: Sat, 25 Nov 2023 12:00:46 +0000 Subject: [PATCH] Simplified windows and modules management --- .gitignore | 3 +- .vscode/settings.json | 3 +- CMakeLists.txt | 8 +- SkywardHub.pro | 30 +- src/entrypoints/groundstation/main.cpp | 13 +- src/shared/Components/ErrorDisplayer/Error.h | 5 +- .../ModulesPicker/ModulesPicker.cpp | 146 +++----- .../Components/ModulesPicker/ModulesPicker.h | 46 ++- .../Components/ModulesPicker/ModulesPicker.ui | 267 --------------- src/shared/Core/EventHandler/EventHandler.cpp | 21 -- src/shared/Core/EventHandler/EventHandler.h | 38 --- .../Core/MessageBroker/MessageBroker.cpp | 12 +- src/shared/Core/MessageBroker/MessageBroker.h | 8 + src/shared/Core/Module/Module.cpp | 25 -- src/shared/Core/Module/Module.h | 48 --- .../Core/ModulesManager/ModulesManager.cpp | 312 ------------------ .../Core/ModulesManager/ModulesManager.h | 84 ----- src/shared/Core/SkywardHubCore.cpp | 207 +++++++----- src/shared/Core/SkywardHubCore.h | 51 ++- src/shared/Core/Window/Window.cpp | 66 ++++ .../MainWindow => Core/Window}/Window.h | 38 +-- src/shared/Modules/CommandPad/CommandPad.cpp | 25 +- src/shared/Modules/CommandPad/CommandPad.h | 8 +- .../CompactCommandPad/CommandSelector.cpp | 3 +- .../CompactCommandPad/CommandSelector.h | 6 +- .../CompactCommandPad/CompactCommandPad.cpp | 19 +- .../CompactCommandPad/CompactCommandPad.h | 10 +- .../Modules/DefaultModule/DefaultModule.cpp | 154 --------- src/shared/Modules/Empty/EmptyModule.cpp | 42 +-- src/shared/Modules/Empty/EmptyModule.h | 30 +- src/shared/Modules/Empty/EmptyModule.ui | 95 ------ .../Modules/FileStream/FileStreamModule.cpp | 37 +-- .../Modules/FileStream/FileStreamModule.h | 8 +- src/shared/Modules/Graph/Graph.cpp | 99 +++--- src/shared/Modules/Graph/Graph.h | 12 +- .../IncomingMessagesViewerModule.cpp | 26 +- .../IncomingMessagesViewerModule.h | 12 +- .../MainStateViewer/MainStateViewer.cpp | 29 +- .../Modules/MainStateViewer/MainStateViewer.h | 11 +- .../MainWindow/SkywardHubMainWindow.cpp | 70 ---- .../Modules/MainWindow/SkywardHubMainWindow.h | 40 --- src/shared/Modules/MainWindow/Window.cpp | 104 ------ src/shared/Modules/MainWindow/Window.ui | 43 --- .../Modules/Mavlink/BaseMavlinkModule.cpp | 15 +- .../Modules/Mavlink/BaseMavlinkModule.h | 9 +- .../Modules/Mavlink/SerialMavlinkModule.cpp | 6 +- .../Modules/Mavlink/SerialMavlinkModule.h | 2 +- .../Modules/Mavlink/UdpMavlinkModule.cpp | 6 +- src/shared/Modules/Mavlink/UdpMavlinkModule.h | 2 +- src/shared/Modules/Module.cpp | 121 +++++++ .../DefaultModule.h => Module.h} | 61 ++-- src/shared/Modules/ModuleInfo.cpp | 42 +-- src/shared/Modules/ModuleInfo.h | 72 ++-- src/shared/Modules/ModulesList.cpp | 311 +++++++++-------- src/shared/Modules/ModulesList.h | 21 +- .../OrientationVisualizer.cpp | 27 +- .../OrientationVisualizer.h | 28 +- .../OutgoingMessagesViewerModule.cpp | 24 +- .../OutgoingMessagesViewerModule.h | 12 +- .../PayloadStateViewer/PayloadStateViewer.cpp | 27 +- .../PayloadStateViewer/PayloadStateViewer.h | 10 +- src/shared/Modules/SkywardHubStrings.h | 9 +- src/shared/Modules/Splitter/Splitter.cpp | 125 ++++--- src/shared/Modules/Splitter/Splitter.h | 15 +- src/shared/Modules/Tabs/TabsModule.cpp | 137 ++++---- src/shared/Modules/Tabs/TabsModule.h | 30 +- src/shared/Modules/Test/TestModule.cpp | 32 +- src/shared/Modules/Test/TestModule.h | 12 +- .../TimerController/TimerControllerModule.cpp | 17 +- .../TimerController/TimerControllerModule.h | 13 +- .../ValuesConverterViewerModule.cpp | 51 ++- .../ValuesConverterViewerModule.h | 12 +- .../Modules/ValvesViewer/ValvesViewer.cpp | 25 +- .../Modules/ValvesViewer/ValvesViewer.h | 10 +- 74 files changed, 1170 insertions(+), 2428 deletions(-) delete mode 100644 src/shared/Components/ModulesPicker/ModulesPicker.ui delete mode 100644 src/shared/Core/EventHandler/EventHandler.cpp delete mode 100644 src/shared/Core/EventHandler/EventHandler.h delete mode 100644 src/shared/Core/Module/Module.cpp delete mode 100644 src/shared/Core/Module/Module.h delete mode 100644 src/shared/Core/ModulesManager/ModulesManager.cpp delete mode 100644 src/shared/Core/ModulesManager/ModulesManager.h create mode 100644 src/shared/Core/Window/Window.cpp rename src/shared/{Modules/MainWindow => Core/Window}/Window.h (63%) delete mode 100644 src/shared/Modules/DefaultModule/DefaultModule.cpp delete mode 100644 src/shared/Modules/Empty/EmptyModule.ui delete mode 100644 src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp delete mode 100644 src/shared/Modules/MainWindow/SkywardHubMainWindow.h delete mode 100644 src/shared/Modules/MainWindow/Window.cpp delete mode 100644 src/shared/Modules/MainWindow/Window.ui create mode 100644 src/shared/Modules/Module.cpp rename src/shared/Modules/{DefaultModule/DefaultModule.h => Module.h} (56%) diff --git a/.gitignore b/.gitignore index c6fa6bf9..5925c9a2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ SkywardHub.pro.user SkywardHub.pro.user.* build/** **/.DS_Store -Deploy/* \ No newline at end of file +Deploy/* +.cache \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index ab0ffa7b..9dcff53c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -166,7 +166,8 @@ "qtsvg": "cpp", "qtvirtualkeyboard": "cpp", "qabstractbutton": "cpp", - "qmetatype": "cpp" + "qmetatype": "cpp", + "qmainwindow": "cpp" }, "editor.defaultFormatter": "ms-vscode.cpptools", "[xml]": { diff --git a/CMakeLists.txt b/CMakeLists.txt index 338f66c1..84737575 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,15 +47,13 @@ add_executable(groundstation src/shared/Components/ErrorDisplayer/Error.cpp src/shared/Components/ErrorDisplayer/ErrorDisplayer.cpp src/shared/Components/FilterSelector/FilterSelector.cpp - src/shared/Core/EventHandler/EventHandler.cpp src/shared/Core/Message/Field.cpp src/shared/Core/Message/Filter.cpp src/shared/Core/Message/Message.cpp src/shared/Core/Message/Topic.cpp src/shared/Core/MessageBroker/MessageBroker.cpp - src/shared/Core/Module/Module.cpp - src/shared/Core/ModulesManager/ModulesManager.cpp src/shared/Core/QCustomPlot/QCustomPlot.cpp + src/shared/Core/Window/Window.cpp src/shared/Core/SkywardHubCore.cpp src/shared/Core/XmlObject.cpp src/shared/Modules/CommandPad/CommandPad.cpp @@ -63,13 +61,10 @@ add_executable(groundstation src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp src/shared/Modules/CompactCommandPad/CommandSelector.cpp src/shared/Modules/CompactCommandPad/SendThread.cpp - src/shared/Modules/DefaultModule/DefaultModule.cpp src/shared/Modules/Empty/EmptyModule.cpp src/shared/Modules/FileStream/FileStreamModule.cpp src/shared/Modules/Graph/Graph.cpp src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp - src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp - src/shared/Modules/MainWindow/Window.cpp src/shared/Modules/Mavlink/Ports/MavlinkPort.cpp src/shared/Modules/Mavlink/Ports/SerialPort.cpp src/shared/Modules/Mavlink/Ports/UdpPort.cpp @@ -91,6 +86,7 @@ add_executable(groundstation src/shared/Modules/ModuleInfo.cpp src/shared/Modules/ModulesList.cpp src/shared/Modules/ValvesViewer/ValvesViewer.cpp + src/shared/Modules/Module.cpp src/entrypoints/groundstation/application.qrc src/entrypoints/groundstation/main.cpp ) diff --git a/SkywardHub.pro b/SkywardHub.pro index 75586e3a..04ba882c 100644 --- a/SkywardHub.pro +++ b/SkywardHub.pro @@ -1,13 +1,8 @@ -QT += core gui 3dcore 3drender 3dinput 3dlogic 3dextras 3danimation - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport serialport network +QT += core gui widgets printsupport serialport +QT += 3dcore 3drender 3dinput 3dlogic 3dextras 3danimation CONFIG += c++11 -# You can make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - # MacOs app icon ICON = src/entrypoints/groundstation/assets/icons/SkywardHub.icns @@ -33,12 +28,10 @@ SOURCES += \ src/shared/Modules/Graph/Graph.cpp \ src/shared/Modules/Test/TestModule.cpp \ src/shared/Modules/ModulesList.cpp \ + src/shared/Modules/Module.cpp \ src/shared/Modules/Splitter/Splitter.cpp \ - src/shared/Modules/DefaultModule/DefaultModule.cpp \ src/shared/Modules/CommandPad/CommandPad.cpp \ src/shared/Modules/CommandPad/MessageFormElement.cpp \ - src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp \ - src/shared/Modules/MainWindow/Window.cpp \ src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp \ src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp \ src/shared/Modules/CompactCommandPad/SendThread.cpp \ @@ -53,18 +46,15 @@ SOURCES += \ src/shared/Modules/Mavlink/SerialMavlinkModule.cpp \ src/shared/Modules/Mavlink/UdpMavlinkModule.cpp \ src/shared/Modules/ValvesViewer/ValvesViewer.cpp \ - src/shared/Core/EventHandler/EventHandler.cpp \ src/shared/Core/XmlObject.cpp \ src/shared/Core/QCustomPlot/QCustomPlot.cpp \ src/shared/Core/MessageBroker/MessageBroker.cpp \ - src/shared/Core/Module/Module.cpp \ - src/shared/Core/CrashLogger.h \ src/shared/Core/SkywardHubCore.cpp \ src/shared/Core/Message/Filter.cpp \ src/shared/Core/Message/Field.cpp \ src/shared/Core/Message/Topic.cpp \ src/shared/Core/Message/Message.cpp \ - src/shared/Core/ModulesManager/ModulesManager.cpp \ + src/shared/Core/Window/Window.cpp \ src/shared/Components/FilterSelector/FilterSelector.cpp \ src/shared/Components/ModulesPicker/ModulesPicker.cpp \ src/shared/Components/SaveConfigurationDialog/SaveConfigurationDialog.cpp \ @@ -92,12 +82,9 @@ HEADERS += \ src/shared/Modules/Test/TestModule.h \ src/shared/Modules/SkywardHubStrings.h \ src/shared/Modules/Splitter/Splitter.h \ - src/shared/Modules/DefaultModule/DefaultModule.h \ src/shared/Modules/CommandPad/MessageFormElement.h \ src/shared/Modules/CommandPad/CommandPad.h \ src/shared/Modules/CommandPad/MessagesList.h \ - src/shared/Modules/MainWindow/SkywardHubMainWindow.h \ - src/shared/Modules/MainWindow/Window.h \ src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h \ src/shared/Modules/CompactCommandPad/CompactCommandPad.h \ src/shared/Modules/CompactCommandPad/CommandSelector.h \ @@ -114,17 +101,17 @@ HEADERS += \ src/shared/Modules/ModulesList.h \ src/shared/Modules/ValvesViewer/ValvesViewer.h \ src/shared/Modules/ValvesViewer/ValvesList.h \ - src/shared/Core/EventHandler/EventHandler.h \ + src/shared/Modules/Module.h \ src/shared/Core/QCustomPlot/QCustomPlot.h \ src/shared/Core/MessageBroker/MessageBroker.h \ src/shared/Core/SkywardHubCore.h \ - src/shared/Core/Module/Module.h \ src/shared/Core/XmlObject.h \ src/shared/Core/Message/Message.h \ src/shared/Core/Message/Filter.h \ src/shared/Core/Message/Field.h \ src/shared/Core/Message/Topic.h \ - src/shared/Core/ModulesManager/ModulesManager.h \ + src/shared/Core/Window/Window.h \ + src/shared/Core/CrashLogger.h \ src/shared/Components/FilterSelector/FilterSelector.h \ src/shared/Components/ModulesPicker/ModulesPicker.h \ src/shared/Components/SaveConfigurationDialog/SaveConfigurationDialog.h \ @@ -134,15 +121,12 @@ HEADERS += \ src/shared/Components/SubscriptionsPanel/SubscriptionsPanel.h \ FORMS += \ - src/shared/Modules/Empty/EmptyModule.ui \ src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.ui \ src/shared/Modules/ValuesConverterViewer/ValuesViewerConfigPanel.ui \ src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.ui \ src/shared/Modules/TimerController/TimerControllerModule.ui \ src/shared/Modules/FileStream/FileStreamModule.ui \ src/shared/Modules/Test/TestModule.ui \ - src/shared/Modules/MainWindow/Window.ui \ - src/shared/Components/ModulesPicker/ModulesPicker.ui \ src/shared/Components/SaveConfigurationDialog/SaveConfigurationDialog.ui \ # Default rules for deployment. diff --git a/src/entrypoints/groundstation/main.cpp b/src/entrypoints/groundstation/main.cpp index f4da481e..590a72e2 100644 --- a/src/entrypoints/groundstation/main.cpp +++ b/src/entrypoints/groundstation/main.cpp @@ -16,19 +16,24 @@ * */ +#include <Core/SkywardHubCore.h> + #include <QApplication> +#include <QFile> #include "Core/CrashLogger.h" -#include "Modules/MainWindow/SkywardHubMainWindow.h" int main(int argc, char *argv[]) { QApplication application(argc, argv); - SkywardHubMainWindow skywardHub; - application.setStyleSheet(skywardHub.styleSheet()); - skywardHub.show(); + // Set application theme + QFile styleSheet(":/assets/styles/global.qss"); + styleSheet.open(QFile::ReadOnly); + application.setStyleSheet(styleSheet.readAll()); + // Start and run + SkywardHubCore::getInstance().init(); application.exec(); return 0; diff --git a/src/shared/Components/ErrorDisplayer/Error.h b/src/shared/Components/ErrorDisplayer/Error.h index bc6a4788..f86a3998 100644 --- a/src/shared/Components/ErrorDisplayer/Error.h +++ b/src/shared/Components/ErrorDisplayer/Error.h @@ -20,7 +20,6 @@ #include <Core/Message/Message.h> #include <Core/MessageBroker/MessageBroker.h> -#include <Core/SkywardHubCore.h> #include <QGridLayout> #include <QLabel> @@ -30,6 +29,8 @@ #include <QWidget> #include <QtWidgets> +class ErrorDisplayer; + enum ErrorType { ET_ERROR, @@ -37,8 +38,6 @@ enum ErrorType ET_INFO, }; -class ErrorDisplayer; - class Error : public QWidget { Q_OBJECT diff --git a/src/shared/Components/ModulesPicker/ModulesPicker.cpp b/src/shared/Components/ModulesPicker/ModulesPicker.cpp index 730290a6..a6235d13 100644 --- a/src/shared/Components/ModulesPicker/ModulesPicker.cpp +++ b/src/shared/Components/ModulesPicker/ModulesPicker.cpp @@ -18,61 +18,74 @@ #include "ModulesPicker.h" -#include <Core/ModulesManager/ModulesManager.h> #include <Modules/Splitter/Splitter.h> #include <QDebug> #include <QPushButton> -#include "ui_ModulesPicker.h" - -ModulesPicker::ModulesPicker() : QDialog(), ui(new Ui::ModulesPicker) +ModulesPicker::ModulesPicker() { - ui->setupUi(this); - createAndConnectUI(); - - setAttribute(Qt::WA_DeleteOnClose, - true); // WA_DeleteOnClose is set to true, so this - // widget will be deleted on close + setupUi(); + setAttribute(Qt::WA_DeleteOnClose, true); } -ModulesPicker::~ModulesPicker() { delete ui; } - -void ModulesPicker::createAndConnectUI() +void ModulesPicker::setupUi() { - connect(ui->button_createModule, &QPushButton::clicked, this, - &ModulesPicker::onCreateModuleButtonClick); - - connect(ui->pushButton_horizontal, &QPushButton::clicked, this, - [=]() { createSplitter(Qt::Horizontal); }); - connect(ui->pushButton_vertical, &QPushButton::clicked, this, - [=]() { createSplitter(Qt::Vertical); }); - - /* Important: - * The text of this buttons is set to be the name of the module to load - * onclick - */ - for (ModuleInfo moduleInfo : ModulesManager::getModulesInfo()) + mainLayout = new QGridLayout; + setLayout(mainLayout); + + dataVisualizationGroupBox = new QGroupBox("Data Visualization"); + mainLayout->addWidget(dataVisualizationGroupBox, 0, 0); + dataVisualizationList = new QVBoxLayout(); + dataVisualizationList->addStretch(); + dataVisualizationGroupBox->setLayout(dataVisualizationList); + + dataSourcesGroupBox = new QGroupBox("Data Sources"); + mainLayout->addWidget(dataSourcesGroupBox, 1, 0); + dataSourcesList = new QVBoxLayout(); + dataSourcesList->addStretch(); + dataSourcesGroupBox->setLayout(dataSourcesList); + + utilitiesGroupBox = new QGroupBox("Utilities"); + mainLayout->addWidget(utilitiesGroupBox, 0, 1); + utilitiesList = new QVBoxLayout(); + utilitiesList->addStretch(); + utilitiesGroupBox->setLayout(utilitiesList); + + organizationGroupBox = new QGroupBox("Organization"); + mainLayout->addWidget(organizationGroupBox, 1, 1); + organizationList = new QVBoxLayout(); + organizationList->addStretch(); + organizationGroupBox->setLayout(organizationList); + + testingGroupBox = new QGroupBox("Testing"); + mainLayout->addWidget(testingGroupBox, 0, 2); + testingList = new QVBoxLayout(); + testingList->addStretch(); + testingGroupBox->setLayout(testingList); + + for (ModuleInfo moduleInfo : ModulesList::getInstance().getModulesInfo()) { switch (moduleInfo.getModuleCategory()) { - case ModuleCategory::DEFAULT: - ui->comboBox_modulesList->addItem(moduleInfo.getModuleName()); + case ModuleCategory::DATA_VISUALIZATION: + dataVisualizationList->insertWidget( + 0, createButton(moduleInfo.getModuleName())); break; - case ModuleCategory::DATASOURCE: - ui->data_source_layout->insertWidget( + case ModuleCategory::DATA_SOURCES: + dataSourcesList->insertWidget( 0, createButton(moduleInfo.getModuleName())); break; - case ModuleCategory::DATAVISUAL: - ui->data_visual_layout->insertWidget( + case ModuleCategory::UTILITIES: + utilitiesList->insertWidget( 0, createButton(moduleInfo.getModuleName())); break; - case ModuleCategory::UTILITY: - ui->utility_layout->insertWidget( + case ModuleCategory::ORGANIZATION: + organizationList->insertWidget( 0, createButton(moduleInfo.getModuleName())); break; - case ModuleCategory::HOME: - ui->home_layout->insertWidget( + case ModuleCategory::TESTING: + testingList->insertWidget( 0, createButton(moduleInfo.getModuleName())); break; default: @@ -81,71 +94,20 @@ void ModulesPicker::createAndConnectUI() } } -void ModulesPicker::connectSlot(QPushButton* button) -{ - connect(button, &QPushButton::clicked, this, - [this, button]() - { - Module* module = - ModulesManager::instantiateModuleByName(button->text()); - if (module != nullptr) - { - onModuleSelected(module); - } - }); -} - -void ModulesPicker::onCreateModuleButtonClick() -{ - QString moduleName = ui->comboBox_modulesList->currentText(); - onModuleSelected(moduleName); -} - -void ModulesPicker::createSplitter(Qt::Orientation orientation) -{ - Splitter* module = qobject_cast<Splitter*>( - ModulesManager::instantiateModuleById(ModuleId::SPLITTER)); - if (module) - { - module->setOrientation(orientation); - onModuleSelected(module); - } -} - QPushButton* ModulesPicker::createButton(const QString& name) { QPushButton* button = new QPushButton(name); connect(button, &QPushButton::clicked, this, [this, button]() { - if (button != nullptr) + ModuleId id; + if (ModulesList::getInstance().getModuleId(button->text(), id)) { - onModuleSelected(button->text()); + emit onModuleSelected(id); } + + close(); }); return button; } - -void ModulesPicker::onModuleSelected(const QString& mName) -{ - Module* module = ModulesManager::instantiateModuleByName(mName); - if (module != nullptr) - onModuleSelected(module); -} - -void ModulesPicker::onModuleSelected(Module* module) -{ - *selectedModule = module; - emit moduleSelected(module); - this->close(); -} - -Module* ModulesPicker::start() -{ - Module* mSelected = nullptr; - // cppcheck-suppress danglingLifetime - selectedModule = &mSelected; - this->exec(); - return mSelected; -} diff --git a/src/shared/Components/ModulesPicker/ModulesPicker.h b/src/shared/Components/ModulesPicker/ModulesPicker.h index b0822d95..420f7791 100644 --- a/src/shared/Components/ModulesPicker/ModulesPicker.h +++ b/src/shared/Components/ModulesPicker/ModulesPicker.h @@ -18,47 +18,43 @@ #pragma once -#include <Core/Module/Module.h> - +#include <QBoxLayout> #include <QDialog> +#include <QGroupBox> #include <QPushButton> -#include <QSharedPointer> -#include <QWidget> -namespace Ui -{ -class ModulesPicker; -} +#include "Modules/ModulesList.h" class ModulesPicker : public QDialog { Q_OBJECT public: - explicit ModulesPicker(); - ~ModulesPicker() override; + ModulesPicker(); void addModule(const QString& txt); - void onModuleSelected(Module* module); - void onModuleSelected(const QString& mName); - Module* start(); - - // QWidget* toWidget() override; - // XmlObject toXmlObject() override; - // void fromXmlObject(const XmlObject &xmlObject) override; - -signals: - void moduleSelected(Module* selectedModule); protected: - void createAndConnectUI(); - void connectSlot(QPushButton* button); - void onCreateModuleButtonClick(); + void setupUi(); QPushButton* createButton(const QString& name); +signals: + void onModuleSelected(ModuleId id); + private: void createSplitter(Qt::Orientation orientation); - Ui::ModulesPicker* ui; - Module** selectedModule = nullptr; + Module* selectedModule = nullptr; + + QGridLayout* mainLayout; + QGroupBox* dataVisualizationGroupBox; + QVBoxLayout* dataVisualizationList; + QGroupBox* dataSourcesGroupBox; + QVBoxLayout* dataSourcesList; + QGroupBox* utilitiesGroupBox; + QVBoxLayout* utilitiesList; + QGroupBox* organizationGroupBox; + QVBoxLayout* organizationList; + QGroupBox* testingGroupBox; + QVBoxLayout* testingList; }; diff --git a/src/shared/Components/ModulesPicker/ModulesPicker.ui b/src/shared/Components/ModulesPicker/ModulesPicker.ui deleted file mode 100644 index 10916cb3..00000000 --- a/src/shared/Components/ModulesPicker/ModulesPicker.ui +++ /dev/null @@ -1,267 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ModulesPicker</class> - <widget class="QWidget" name="ModulesPicker"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>996</width> - <height>689</height> - </rect> - </property> - <property name="windowTitle"> - <string>Modules Picker</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1"> - <item> - <layout class="QHBoxLayout" name="home_layout" stretch="1,0"> - <item> - <widget class="QComboBox" name="comboBox_modulesList" /> - </item> - <item> - <widget class="QPushButton" name="button_createModule"> - <property name="text"> - <string>Create</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="1"> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0"> - <item> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>Utility</string> - </property> - <layout class="QVBoxLayout" name="group_utility"> - <item> - <widget class="QScrollArea" name="scrollArea_2"> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents_2"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>457</width> - <height>502</height> - </rect> - </property> - <layout class="QVBoxLayout" name="utility_layout"> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>463</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="whatsThis"> - <string /> - </property> - <property name="title"> - <string>Splitter</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_vertical"> - <property name="text"> - <string /> - </property> - <property name="icon"> - <iconset resource="../../application.qrc"> - <normaloff>:/assets/icons/splitter_vertical.png</normaloff> - :/assets/icons/splitter_horizontal.png - </iconset> - </property> - <property name="iconSize"> - <size> - <width>25</width> - <height>25</height> - </size> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_horizontal"> - <property name="text"> - <string /> - </property> - <property name="icon"> - <iconset resource="../../application.qrc"> - <normaloff>:/assets/icons/splitter_horizontal.png</normaloff> - :/assets/icons/splitter_vertical.png - </iconset> - </property> - <property name="iconSize"> - <size> - <width>25</width> - <height>25</height> - </size> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </item> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Data Visualization</string> - </property> - <layout class="QVBoxLayout" name="ver_lay_3"> - <item> - <widget class="QScrollArea" name="scrollArea"> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>459</width> - <height>277</height> - </rect> - </property> - <layout class="QVBoxLayout" name="data_visual_layout"> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>278</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QGroupBox" name="groupBox_4"> - <property name="title"> - <string>Data Source</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <widget class="QScrollArea" name="scrollArea_3"> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents_4"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>435</width> - <height>232</height> - </rect> - </property> - <layout class="QVBoxLayout" name="data_source_layout"> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>211</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources> - <include location="../../application.qrc" /> - </resources> - <connections /> -</ui> \ No newline at end of file diff --git a/src/shared/Core/EventHandler/EventHandler.cpp b/src/shared/Core/EventHandler/EventHandler.cpp deleted file mode 100644 index ecdf2267..00000000 --- a/src/shared/Core/EventHandler/EventHandler.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "EventHandler.h" - -EventHandler::EventHandler() {} \ No newline at end of file diff --git a/src/shared/Core/EventHandler/EventHandler.h b/src/shared/Core/EventHandler/EventHandler.h deleted file mode 100644 index 1866b2ce..00000000 --- a/src/shared/Core/EventHandler/EventHandler.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <QMenu> -#include <QObject> - -class Module; - -class EventHandler : public QObject -{ - Q_OBJECT - -public: - EventHandler(); - -signals: - void beforeDelete(Module *module); - void replaceMeWith(Module *sender, Module *newModule); - void replaceMeWithModules(QList<Module *> module); - void contextMenuRequest(QMenu &menu, const QPoint &p); -}; diff --git a/src/shared/Core/MessageBroker/MessageBroker.cpp b/src/shared/Core/MessageBroker/MessageBroker.cpp index ba0a26e8..ba9f82bf 100644 --- a/src/shared/Core/MessageBroker/MessageBroker.cpp +++ b/src/shared/Core/MessageBroker/MessageBroker.cpp @@ -18,7 +18,13 @@ #include "MessageBroker.h" -#include <Core/Module/Module.h> +#include <Modules/Module.h> + +MessageBroker& MessageBroker::getInstance() +{ + static MessageBroker instance; + return instance; +} void MessageBroker::subscribe(Filter filter, Module* observer, Callback callback) @@ -27,8 +33,8 @@ void MessageBroker::subscribe(Filter filter, Module* observer, // Register the beforeDelete slot of the module to automatically // remove the subscriber - connect(observer->getEventHandler(), &EventHandler::beforeDelete, this, - &MessageBroker::onModuleDeleted); + // connect(observer, &Module::closeMe, this, + // &MessageBroker::onModuleDeleted); } void MessageBroker::unsubscribe(Filter filter, Module* module) diff --git a/src/shared/Core/MessageBroker/MessageBroker.h b/src/shared/Core/MessageBroker/MessageBroker.h index 686ee576..19471425 100644 --- a/src/shared/Core/MessageBroker/MessageBroker.h +++ b/src/shared/Core/MessageBroker/MessageBroker.h @@ -32,6 +32,8 @@ class MessageBroker : public QObject public: using Callback = std::function<void(const Message&, const Filter&)>; + static MessageBroker& getInstance(); + void subscribe(Filter filter, Module* observer, Callback callback); /** @@ -45,8 +47,14 @@ public: void publish(const Message& message); private: + MessageBroker() {} + QMultiMap<Filter, QPair<Module*, Callback*>> observers; private slots: void onModuleDeleted(Module* module); + + // public: + // MessageBroker(const MessageBroker&) = delete; + // MessageBroker& operator=(const MessageBroker&) = delete; }; diff --git a/src/shared/Core/Module/Module.cpp b/src/shared/Core/Module/Module.cpp deleted file mode 100644 index cd2ada76..00000000 --- a/src/shared/Core/Module/Module.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "Module.h" - -Module::Module(QWidget *parent) : QWidget(parent) {} - -EventHandler *Module::getEventHandler() { return &eventsHandler; } - -SkywardHubCoreProxy &Module::getCore() { return coreProxy; } diff --git a/src/shared/Core/Module/Module.h b/src/shared/Core/Module/Module.h deleted file mode 100644 index dc53bc1b..00000000 --- a/src/shared/Core/Module/Module.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <Core/EventHandler/EventHandler.h> -#include <Core/SkywardHubCore.h> -#include <Core/XmlObject.h> - -#include <QWidget> - -class Module : public QWidget -{ - Q_OBJECT - -public: - Module(QWidget* parent = nullptr); - - virtual QWidget* toWidget() = 0; - virtual XmlObject toXmlObject() = 0; - virtual void fromXmlObject(const XmlObject& xmlObject) = 0; - - // ModulesManagerProxy& getModuleManager(); - SkywardHubCoreProxy& getCore(); - EventHandler* getEventHandler(); - -protected: - // virtual void onManagerSetted(ModulesManager *manager); - -private: - SkywardHubCoreProxy coreProxy; - EventHandler eventsHandler; -}; diff --git a/src/shared/Core/ModulesManager/ModulesManager.cpp b/src/shared/Core/ModulesManager/ModulesManager.cpp deleted file mode 100644 index c4f4e1c8..00000000 --- a/src/shared/Core/ModulesManager/ModulesManager.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "ModulesManager.h" - -#include <Components/ModulesPicker/ModulesPicker.h> -#include <Components/SaveConfigurationDialog/SaveConfigurationDialog.h> -#include <Core/Module/Module.h> -#include <Core/XmlObject.h> -#include <Modules/SkywardHubStrings.h> - -#include <QDebug> -#include <QDir> -#include <QInputDialog> -#include <QMessageBox> -#include <QStandardPaths> - -ModulesList ModulesManager::modulesListHandler; - -ModulesManager::ModulesManager() {} - -ModulesManager::~ModulesManager() -{ - clearPages(); - for (int i = 0; i < menuActions.count(); i++) - { - delete menuActions[i]; - } - menuActions.clear(); -} - -QString ModulesManager::getModuleName(ModuleId id) -{ - if (ModulesManager::modulesListHandler.containsId(id)) - return ModulesManager::modulesListHandler.getModuleName(id); - - return ""; -} - -Module* ModulesManager::instantiateModuleById(ModuleId id) -{ - if (ModulesManager::modulesListHandler.containsId(id)) - return ModulesManager::modulesListHandler.getFactory(id)(); - - return nullptr; -} - -Module* ModulesManager::instantiateModuleByName(const QString& moduleName) -{ - return ModulesManager::modulesListHandler.findFactoryByModuleName( - moduleName)(); -} - -QList<Module*> ModulesManager::loadModuleFromXml(XmlObject& xml) -{ - QList<Module*> windows; - - for (int i = 0; i < xml.childCount(); i++) - { - XmlObject* child = xml.getChild(i); - QString moduleName = child->getObjectName(); - - Module* module = ModulesManager::instantiateModuleByName(moduleName); - - if (module != nullptr) - { - module->fromXmlObject(*child); - windows.append(module); - } - } - - return windows; -} - -void ModulesManager::setModules(QList<Module*> modules) -{ - int i; - for (i = 0; i < pages.count() && i < modules.count(); i++) - { - Module* old = pages[i]; - emit pages[i]->getEventHandler()->replaceMeWith(old, modules[i]); - } - if (i < pages.count()) - { - for (int c = pages.count() - 1; c > i; c--) - { - delete pages[c]; - } - } - for (; i < modules.count(); i++) - { - addPage(modules[i]); - } -} - -void ModulesManager::addModules(QList<Module*> modules) -{ - for (int i = 0; i < modules.count(); i++) - { - addPage(modules[i]); - } -} - -void ModulesManager::addPage(Module* module) -{ - pages.append(module); - connectModule(module); - emit pageAdded(pages.indexOf(module)); -} - -void ModulesManager::removePage(Module* module) -{ - int index = pages.indexOf(module); - if (index >= 0) - { - pages.removeAt(index); - disconnectModule(module); - } -} - -Module* ModulesManager::instantiateDefaultModule() -{ - return ModulesManager::instantiateModuleById(ModuleId::EMPTY); -} - -Module* ModulesManager::invokeModulesPickerService() -{ - ModulesPicker* p = new ModulesPicker(); - return p->start(); -} - -QList<QString> ModulesManager::getModulesNamesList() -{ - return ModulesManager::modulesListHandler.getModulesNamesList(); -} - -void ModulesManager::connectModule(Module* module) -{ - if (module) - { - connect(module->getEventHandler(), &EventHandler::contextMenuRequest, - this, &ModulesManager::onContextMenuRequest); - connect(module->getEventHandler(), &EventHandler::beforeDelete, this, - &ModulesManager::onModuleDeleted); - connect(module->getEventHandler(), &EventHandler::replaceMeWith, this, - &ModulesManager::onReplaceMeWith); - } - - // connect(module->getEventHandler(),&EventHandler::replaceMeWithModules,this,&ModulesManager::openWindows); -} - -void ModulesManager::disconnectModule(Module* module) -{ - if (module) - { - disconnect(module->getEventHandler(), &EventHandler::contextMenuRequest, - this, &ModulesManager::onContextMenuRequest); - disconnect(module->getEventHandler(), &EventHandler::beforeDelete, this, - &ModulesManager::onModuleDeleted); - disconnect(module->getEventHandler(), &EventHandler::replaceMeWith, - this, &ModulesManager::onReplaceMeWith); - } -} - -void ModulesManager::onModuleDeleted(Module* deletedModule) -{ - emit deletedModule->getEventHandler()->replaceMeWith( - deletedModule, instantiateDefaultModule()); -} - -void ModulesManager::openNewEmptyWindow() -{ - addPage(ModulesManager::instantiateDefaultModule()); -} - -Module* ModulesManager::getModuleAt(int index) -{ - if (index >= 0 && index < pages.count()) - { - return pages.at(index); - } - return nullptr; -} - -int ModulesManager::getModuleCount() { return pages.count(); } - -void ModulesManager::clearPages() -{ - for (int i = pages.count() - 1; i >= 0; i--) - { - delete pages[i]; - } - pages.clear(); -} - -void ModulesManager::onReplaceMeWith(Module* sender, Module* newModule) -{ - if (sender != nullptr && newModule != nullptr) - { - int index = pages.indexOf(sender); - if (index >= 0) - { - pages[index] = newModule; - connectModule(newModule); - disconnectModule(sender); - } - } -} - -void ModulesManager::onContextMenuRequest(QMenu& menu, const QPoint& p) -{ - QMenu hubMenu("Global menu"); - hubMenu.addActions(getHubMenuActions()); - menu.addMenu(&hubMenu); - emit contextMenuRequest(menu, p); -} - -QList<QAction*> ModulesManager::getHubMenuActions() -{ - if (menuActions.count() == 0) - { - QAction* save = new QAction("Save"); - menuActions.append(save); - connect(save, &QAction::triggered, this, - &ModulesManager::openConfigurationWindow); - - QAction* openWindows = new QAction("New Window"); - menuActions.append(openWindows); - connect(openWindows, &QAction::triggered, this, - &ModulesManager::openNewEmptyWindow); - } - - return menuActions; -} - -QList<ModuleInfo> ModulesManager::getModulesInfo() -{ - return modulesListHandler.getModulesInfo(); -} - -void ModulesManager::openConfigurationWindow() -{ - if (pages.isEmpty()) - { - QMessageBox errorMsg; - errorMsg.setText("No module to be saved found"); - errorMsg.exec(); - return; - } - - // Ask configuration data to the user - SaveConfigurationDialog* saveDialog = new SaveConfigurationDialog(); - saveDialog->setConfigName(SkywardHubStrings::defaultConfigurationFileName); - saveDialog->setConfigIconPath( - SkywardHubStrings::defaultConfigurationIconPath); - QString configName; - QString configIconPath; - QString description; - saveDialog->pickConfigData(&configName, &configIconPath, &description); - - XmlObject xml(SkywardHubStrings::configurationNameValue); - xml.addAttribute(SkywardHubStrings::configurationIconPathAttribute, - configIconPath); - xml.addAttribute(SkywardHubStrings::configurationDescriptionAttribute, - description); - - if (!configName.isEmpty()) - { - configName = configName.replace(".xml", ""); - xml.addAttribute(SkywardHubStrings::configurationNameAttribute, - configName); - if (configName.indexOf(".xml") < 0) - { - configName.append(".xml"); - } - - if (!QDir(SkywardHubStrings::defaultPrefabsFolder).exists()) - { - QDir().mkpath(SkywardHubStrings::defaultPrefabsFolder); - } - - for (Module* module : pages) - { - xml.addChild(module->toXmlObject()); - } - - QString resultTxt = "Impossible to save"; - if (xml.writeToFile(SkywardHubStrings::defaultPrefabsFolder + - configName)) - { - resultTxt = "The configuration has been saved in " + configName; - } - QMessageBox resultMsg; - resultMsg.setText(resultTxt); - resultMsg.exec(); - } -} diff --git a/src/shared/Core/ModulesManager/ModulesManager.h b/src/shared/Core/ModulesManager/ModulesManager.h deleted file mode 100644 index 689bd7f8..00000000 --- a/src/shared/Core/ModulesManager/ModulesManager.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <QMap> -#include <QMenu> -#include <QObject> -#include <QString> - -#include "Modules/ModulesList.h" - -class Module; -class SaveConfigurationDialog; -class XmlObject; - -class ModulesManager : public QObject -{ - Q_OBJECT - -public: - ModulesManager(); - ~ModulesManager(); - - static Module *instantiateDefaultModule(); - static Module *invokeModulesPickerService(); - - static QList<QString> getModulesNamesList(); - static QString getModuleName(ModuleId id); - static Module *instantiateModuleById(ModuleId id); - - static Module *instantiateModuleByName(const QString &moduleName); - static QList<Module *> loadModuleFromXml(XmlObject &xml); - static QList<ModuleInfo> getModulesInfo(); - - void setModules(QList<Module *> modules); - void addModules(QList<Module *> modules); - void addPage(Module *module); - void removePage(Module *module); - - Module *getModuleAt(int index); - int getModuleCount(); - void clearPages(); - - QList<QAction *> getHubMenuActions(); - -public slots: - void openNewEmptyWindow(); - void openConfigurationWindow(); - -signals: - void contextMenuRequest(QMenu &menu, const QPoint &p); - void pageAdded(int index); - -protected: - void connectModule(Module *module); - void disconnectModule(Module *module); - -protected slots: - void onContextMenuRequest(QMenu &menu, const QPoint &p); - void onModuleDeleted(Module *deletedModule); - void onReplaceMeWith(Module *sender, Module *newModule); - -private: - static ModulesList modulesListHandler; - - QList<Module *> pages; - QList<QAction *> menuActions; -}; diff --git a/src/shared/Core/SkywardHubCore.cpp b/src/shared/Core/SkywardHubCore.cpp index 9f794514..bccda021 100644 --- a/src/shared/Core/SkywardHubCore.cpp +++ b/src/shared/Core/SkywardHubCore.cpp @@ -18,53 +18,57 @@ #include "SkywardHubCore.h" -#include <Core/EventHandler/EventHandler.h> +#include <Components/SaveConfigurationDialog/SaveConfigurationDialog.h> #include <Core/MessageBroker/MessageBroker.h> -#include <Core/Module/Module.h> -#include <Core/ModulesManager/ModulesManager.h> +#include <Core/Window/Window.h> +#include <Modules/Module.h> +#include <Modules/ModulesList.h> #include <Modules/SkywardHubStrings.h> +#include <QCloseEvent> #include <QDir> #include <QMessageBox> -SkywardHubCore::SkywardHubCore() +SkywardHubCore& SkywardHubCore::getInstance() { - modulesManager = new ModulesManager(); - moduleEventHandler = new EventHandler(); - moduleMessageBroker = new MessageBroker(); + static SkywardHubCore instance; + return instance; } -SkywardHubCore::~SkywardHubCore() +void SkywardHubCore::init() { - if (modulesManager) - { - delete modulesManager; - } - if (moduleEventHandler) - { - delete moduleEventHandler; - } - if (moduleMessageBroker) + XmlObject settings; + settings.loadFromFile(SkywardHubStrings::defaultSettingsFilePath); + + QString settingsName = + settings.getChildObjectValue(SkywardHubStrings::skywardHubInitFileTag); + + if (!settingsName.isEmpty()) { - delete moduleMessageBroker; + XmlObject configuration; + if (configuration.loadFromFile(SkywardHubStrings::defaultPrefabsFolder + + settingsName)) + { + + loadConfigurationFromXmlObject(configuration); + return; + } } + + addNewWindow(); + saveConfiguration(SkywardHubStrings::defaultConfigurationFileName, + SkywardHubStrings::defaultConfigurationIconPath, ""); } -void SkywardHubCore::init() +QList<QAction*> SkywardHubCore::getHubMenuActions() { - if (!settings.loadFromFile(SkywardHubStrings::defaultSettingsFilePath)) - { - // Settings file not found or loaded incorrectly - settings.reset(); - settings.setObjectName(SkywardHubStrings::settingsObjectName); - XmlObject defaultConfig(SkywardHubStrings::skywardHubInitFileTag); - defaultConfig.setTextValue( - SkywardHubStrings::defaultConfigurationFileName); - settings.addChild(defaultConfig); - } + return hubMenuActionsList; +} +SkywardHubCore::SkywardHubCore() +{ checkDefaultFolders(); - loadFirstPage(); + buildHubMenuActions(); } void SkywardHubCore::checkDefaultFolders() @@ -77,69 +81,124 @@ void SkywardHubCore::checkDefaultFolders() { QDir().mkdir(SkywardHubStrings::defaultConfigurationFolder); } - - if (!QFile(SkywardHubStrings::defaultSettingsFilePath).exists()) - { - saveSettings(); - } } -void SkywardHubCore::saveSettings() +void SkywardHubCore::buildHubMenuActions() { - if (settings.writeToFile(SkywardHubStrings::defaultSettingsFilePath)) - { - QMessageBox confirmMsg; - confirmMsg.setMinimumSize(256, 256); - confirmMsg.setText(SkywardHubStrings::settingsSavedCorrectlyMsg); - confirmMsg.exec(); - } + QAction* save = new QAction("Save configuration"); + hubMenuActionsList.append(save); + connect(save, &QAction::triggered, this, + [this]() { saveConfigurationPrompt(); }); + + QAction* newWindow = new QAction("New Window"); + hubMenuActionsList.append(newWindow); + connect(newWindow, &QAction::triggered, this, + &SkywardHubCore::addNewWindow); } -void SkywardHubCore::loadFirstPage() +void SkywardHubCore::loadConfigurationFromXmlObject(XmlObject configuration) { - QString pageToLoadName = - settings.getChildObjectValue(SkywardHubStrings::skywardHubInitFileTag); + XmlObject windows; + windows = configuration.childAt(0); - if (!pageToLoadName.isEmpty()) + for (int i = 0; i < windows.childCount(); i++) { - XmlObject pageToLoad; - if (pageToLoad.loadFromFile(SkywardHubStrings::defaultPrefabsFolder + - pageToLoadName)) - { - modulesManager->setModules( - modulesManager->loadModuleFromXml(pageToLoad)); - return; - } + addWindowFromXml(windows.childAt(i)); } +} - // If first page not found, init with empty module - modulesManager->openNewEmptyWindow(); +void SkywardHubCore::addNewWindow() +{ + Module* empty = + ModulesList::getInstance().instantiateModule(ModuleId::EMPTY); + return addWindowFromXml(empty->toXmlObject()); } -MessageBroker *SkywardHubCore::getMessageBroker() +void SkywardHubCore::addWindowFromXml(XmlObject settings) { - return moduleMessageBroker; + Window* newWindow = new Window(settings); + newWindow->show(); + newWindow->activateWindow(); + windowsList.push_back(newWindow); + + connect(newWindow, &Window::onWindowClosed, this, + [this, newWindow]() + { + windowsList.removeAt(windowsList.indexOf(newWindow)); + delete newWindow; + }); } -EventHandler *SkywardHubCore::getEventHandler() { return moduleEventHandler; } +void SkywardHubCore::saveConfigurationPrompt() +{ + // Ask configuration data to the user + SaveConfigurationDialog* saveDialog = new SaveConfigurationDialog(); + saveDialog->setConfigName(SkywardHubStrings::defaultConfigurationFileName); + saveDialog->setConfigIconPath( + SkywardHubStrings::defaultConfigurationIconPath); + QString configName; + QString configIconPath; + QString description; + saveDialog->pickConfigData(&configName, &configIconPath, &description); + + QString resultTxt; + resultTxt = saveConfiguration(configName, configIconPath, description); + + QMessageBox resultMsg; + resultMsg.setText(resultTxt); + resultMsg.exec(); +} -ModulesManager *SkywardHubCore::getModulesManager() { return modulesManager; } +QString SkywardHubCore::saveConfiguration(QString configName, + QString configIconPath, + QString description) +{ -//_________________ SkywardHubCoreProxy -//____________________________________________________________ + XmlObject configuration(SkywardHubStrings::configurationNameValue); + configuration.addAttribute( + SkywardHubStrings::configurationIconPathAttribute, configIconPath); + configuration.addAttribute( + SkywardHubStrings::configurationDescriptionAttribute, description); -SkywardHubCore *SkywardHubCoreProxy::core = nullptr; + QString resultTxt = "Impossible to save"; -SkywardHubCore *SkywardHubCoreProxy::getCore() -{ - if (SkywardHubCoreProxy::core == nullptr) + if (!configName.isEmpty()) { - SkywardHubCoreProxy::core = new SkywardHubCore(); - } - return SkywardHubCoreProxy::core; -} + configName = configName.replace(".xml", ""); + configuration.addAttribute( + SkywardHubStrings::configurationNameAttribute, configName); + if (configName.indexOf(".xml") < 0) + { + configName.append(".xml"); + } -//_________________ ModulesManagerProxy -//____________________________________________________________ + if (!QDir(SkywardHubStrings::defaultPrefabsFolder).exists()) + { + QDir().mkpath(SkywardHubStrings::defaultPrefabsFolder); + } + + XmlObject windows("windows"); + + // Retrieve the setting of each window and save them in the file + for (int i = 0; i < windowsList.size(); i++) + { + windows.addChild(windowsList[i]->toXmlObject()); + } -XmlObject SkywardHubCore::getSettings() const { return settings; } + configuration.addChild(windows); + + if (configuration.writeToFile(SkywardHubStrings::defaultPrefabsFolder + + configName)) + { + resultTxt = "The configuration has been saved in " + configName; + XmlObject settings; + settings.setObjectName(SkywardHubStrings::settingsObjectName); + XmlObject defaultConfig(SkywardHubStrings::skywardHubInitFileTag); + defaultConfig.setTextValue(configName); + settings.addChild(defaultConfig); + settings.writeToFile(SkywardHubStrings::defaultSettingsFilePath); + } + } + + return resultTxt; +} diff --git a/src/shared/Core/SkywardHubCore.h b/src/shared/Core/SkywardHubCore.h index d5378fa2..d59100e0 100644 --- a/src/shared/Core/SkywardHubCore.h +++ b/src/shared/Core/SkywardHubCore.h @@ -18,13 +18,13 @@ #pragma once -#include <QObject> +#include <Core/Window/Window.h> + +#include <QAction> +#include <QList> #include "XmlObject.h" -class ModulesManager; -class EventHandler; -class MessageBroker; class Module; class SkywardHubCore : public QObject @@ -32,42 +32,31 @@ class SkywardHubCore : public QObject Q_OBJECT public: - SkywardHubCore(); - ~SkywardHubCore(); + static SkywardHubCore &getInstance(); void init(); - ModulesManager *getModulesManager(); - EventHandler *getEventHandler(); - MessageBroker *getMessageBroker(); - - XmlObject getSettings() const; + QList<QAction *> getHubMenuActions(); -signals: - void centralModuleChanged(Module *newModule); - -protected: - void checkDefaultFolders(); - void saveSettings(); - void loadFirstPage(); +public slots: + void addNewWindow(); + void addWindowFromXml(XmlObject settings); private: - ModulesManager *modulesManager = nullptr; - EventHandler *moduleEventHandler = nullptr; - MessageBroker *moduleMessageBroker = nullptr; + SkywardHubCore(); - XmlObject settings; -}; + void checkDefaultFolders(); + void buildHubMenuActions(); + void loadConfigurationFromXmlObject(XmlObject settings); -// Singleton instance of SkywardHubCore + void saveConfigurationPrompt(); + QString saveConfiguration(QString configName, QString configIconPath, + QString description); -class SkywardHubCoreProxy -{ + QList<Window *> windowsList; + QList<QAction *> hubMenuActionsList; public: - static SkywardHubCore *getCore(); - SkywardHubCore *operator->() { return getCore(); } - -private: - static SkywardHubCore *core; + SkywardHubCore(const SkywardHubCore &) = delete; + SkywardHubCore &operator=(const SkywardHubCore &) = delete; }; diff --git a/src/shared/Core/Window/Window.cpp b/src/shared/Core/Window/Window.cpp new file mode 100644 index 00000000..9cce6468 --- /dev/null +++ b/src/shared/Core/Window/Window.cpp @@ -0,0 +1,66 @@ +/* + * This file is part of Skyward Hub. + * + * Skyward Hub is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "Window.h" + +#include <Modules/Empty/EmptyModule.h> +#include <Modules/ModulesList.h> + +Window::Window(XmlObject configuration) +{ + errorDisplayer = new ErrorDisplayer(this); + Module *module = ModulesList::getInstance().instantiateModule( + configuration.getObjectName()); + + if (module) + { + module->fromXmlObject(configuration); + setChild(module); + } +} + +void Window::setChild(Module *module) +{ + setCentralWidget(module); + module->lower(); + + connect(module, &Module::replaceMe, this, &Window::replaceChild); + connect(module, &Module::closeMe, this, &Window::closeChild); +} + +void Window::replaceChild(Module *oldModule, Module *newModule) +{ + // Set the new module + setChild(newModule); + + // Delete the old child + delete oldModule; +} + +void Window::closeChild(Module *module) { close(); } + +XmlObject Window::toXmlObject() +{ + return ((Module *)centralWidget())->toXmlObject(); +} + +void Window::closeEvent(QCloseEvent *event) +{ + emit onWindowClosed(); + event->accept(); +} \ No newline at end of file diff --git a/src/shared/Modules/MainWindow/Window.h b/src/shared/Core/Window/Window.h similarity index 63% rename from src/shared/Modules/MainWindow/Window.h rename to src/shared/Core/Window/Window.h index c9736f12..6a061e54 100644 --- a/src/shared/Modules/MainWindow/Window.h +++ b/src/shared/Core/Window/Window.h @@ -18,41 +18,35 @@ #pragma once +#include <Core/XmlObject.h> +#include <Modules/Module.h> + +#include <QCloseEvent> +#include <QMainWindow> #include <QMenu> -#include <QWidget> -#include "Components/ErrorDisplayer/Error.h" #include "Components/ErrorDisplayer/ErrorDisplayer.h" -class Module; - -namespace Ui -{ -class Window; -} - -class Window : public QWidget +class Window : public QMainWindow { Q_OBJECT public: - explicit Window(QWidget *parent = nullptr); - ~Window(); + explicit Window(XmlObject configuration); - void updateModule(Module *m); - Module *getCentralModule() const; - - void setCentralModule(Module *value); + XmlObject toXmlObject(); ErrorDisplayer *errorDisplayer; -protected: void closeEvent(QCloseEvent *event) override; - void onWidgetDestroyed(); - void onReplaceRequested(Module *sender, Module *newModule); - void resizeEvent(QResizeEvent *) override; + +signals: + void onWindowClosed(); private: - Ui::Window *ui; - Module *centralModule = nullptr; + void setChild(Module *module); + +private slots: + void replaceChild(Module *oldModule, Module *newModule); + void closeChild(Module *module); }; diff --git a/src/shared/Modules/CommandPad/CommandPad.cpp b/src/shared/Modules/CommandPad/CommandPad.cpp index 19981754..85e8d638 100644 --- a/src/shared/Modules/CommandPad/CommandPad.cpp +++ b/src/shared/Modules/CommandPad/CommandPad.cpp @@ -22,11 +22,7 @@ #include <QVBoxLayout> -CommandPad::CommandPad(QWidget *parent) : DefaultModule(parent) -{ - setupUi(); - defaultContextMenuSetup(); -} +CommandPad::CommandPad() : Module(ModuleId::COMMAND_PAD) { setupUi(); } CommandPad::~CommandPad() { @@ -35,11 +31,9 @@ CommandPad::~CommandPad() delete formElements[key]; } -QWidget *CommandPad::toWidget() { return this; } - XmlObject CommandPad::toXmlObject() { - XmlObject obj = XmlObject(getName(ModuleId::COMMANDPAD)); + XmlObject obj = Module::toXmlObject(); auto key = messagesListComboBox->currentText(); if (formElements.contains(key)) @@ -53,15 +47,12 @@ XmlObject CommandPad::toXmlObject() void CommandPad::fromXmlObject(const XmlObject &obj) { - if (obj.getObjectName() == getName(ModuleId::COMMANDPAD)) - { - auto key = obj.getAttribute("message_id"); + auto key = obj.getAttribute("message_id"); - if (formElements.contains(key)) - { - formElements[key]->fromXmlObject(obj); - messagesListComboBox->setCurrentText(key); - } + if (formElements.contains(key)) + { + formElements[key]->fromXmlObject(obj); + messagesListComboBox->setCurrentText(key); } } @@ -109,7 +100,7 @@ void CommandPad::setupUi() if (formElements.contains(key)) { auto message = formElements[key]->prepareMessage(key); - getCore()->getMessageBroker()->publish(message); + MessageBroker::getInstance().publish(message); } }); } diff --git a/src/shared/Modules/CommandPad/CommandPad.h b/src/shared/Modules/CommandPad/CommandPad.h index 07723754..ec9e2450 100644 --- a/src/shared/Modules/CommandPad/CommandPad.h +++ b/src/shared/Modules/CommandPad/CommandPad.h @@ -19,20 +19,18 @@ #pragma once #include <Modules/CommandPad/MessageFormElement.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <tuple> -class CommandPad : public DefaultModule +class CommandPad : public Module { Q_OBJECT public: - explicit CommandPad(QWidget* parent = nullptr); + CommandPad(); ~CommandPad(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; diff --git a/src/shared/Modules/CompactCommandPad/CommandSelector.cpp b/src/shared/Modules/CompactCommandPad/CommandSelector.cpp index babb1b2c..24497f54 100644 --- a/src/shared/Modules/CompactCommandPad/CommandSelector.cpp +++ b/src/shared/Modules/CompactCommandPad/CommandSelector.cpp @@ -22,8 +22,7 @@ #include <QDebug> -CommandSelector::CommandSelector(DefaultModule* _parent) - : QDialog(), parent(_parent) +CommandSelector::CommandSelector(Module* parent) : QDialog(), parent(parent) { setupUi(); } diff --git a/src/shared/Modules/CompactCommandPad/CommandSelector.h b/src/shared/Modules/CompactCommandPad/CommandSelector.h index f5c27d38..e15477ad 100644 --- a/src/shared/Modules/CompactCommandPad/CommandSelector.h +++ b/src/shared/Modules/CompactCommandPad/CommandSelector.h @@ -20,7 +20,7 @@ #include <Core/XmlObject.h> #include <Modules/CommandPad/MessageFormElement.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QBoxLayout> #include <QCheckBox> @@ -37,7 +37,7 @@ class CommandSelector : public QDialog Q_OBJECT public: - explicit CommandSelector(DefaultModule* _parent); + explicit CommandSelector(Module* parent); ~CommandSelector(); XmlObject toXmlObject(XmlObject& obj); @@ -62,5 +62,5 @@ private: QString selectedLabel; Message selectedMessage; - DefaultModule* parent; + Module* parent; }; diff --git a/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp b/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp index 7b700188..95f600a5 100644 --- a/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp +++ b/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp @@ -18,20 +18,21 @@ #include "CompactCommandPad.h" -CompactCommandPad::CompactCommandPad(QWidget* parent) - : DefaultModule(parent), timer(nullptr), continuosSendTimeout(false) +#include <QAction> + +CompactCommandPad::CompactCommandPad() + : Module(ModuleId::COMPACT_COMMAND_PAD), timer(nullptr), + continuosSendTimeout(false) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } CompactCommandPad::~CompactCommandPad() { delete selector; } -QWidget* CompactCommandPad::toWidget() { return this; } - XmlObject CompactCommandPad::toXmlObject() { - XmlObject obj = XmlObject("compact_command_pad"); + XmlObject obj = Module::toXmlObject(); selector->toXmlObject(obj); return obj; } @@ -122,13 +123,13 @@ void CompactCommandPad::setupUi() void CompactCommandPad::send() { - getCore()->getMessageBroker()->publish(selectedMessage); + MessageBroker::getInstance().publish(selectedMessage); } -void CompactCommandPad::addCustomActionsToMenu() +void CompactCommandPad::customContextMenuActionSetup() { QAction* edit = new QAction("Edit button", this); - addActionToMenu(edit); connect(edit, &QAction::triggered, this, &CompactCommandPad::buttonEditActionTriggered); + customContextMenuActions.append(edit); } diff --git a/src/shared/Modules/CompactCommandPad/CompactCommandPad.h b/src/shared/Modules/CompactCommandPad/CompactCommandPad.h index e06e24cb..7df617b1 100644 --- a/src/shared/Modules/CompactCommandPad/CompactCommandPad.h +++ b/src/shared/Modules/CompactCommandPad/CompactCommandPad.h @@ -19,20 +19,18 @@ #pragma once #include <Modules/CompactCommandPad/CommandSelector.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QTimer> -class CompactCommandPad : public DefaultModule +class CompactCommandPad : public Module { Q_OBJECT public: - explicit CompactCommandPad(QWidget* parent = nullptr); + CompactCommandPad(); ~CompactCommandPad(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& obj) override; @@ -42,7 +40,7 @@ private slots: private: void setupUi(); - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); CommandSelector* selector; QPushButton* button; diff --git a/src/shared/Modules/DefaultModule/DefaultModule.cpp b/src/shared/Modules/DefaultModule/DefaultModule.cpp deleted file mode 100644 index e779bb24..00000000 --- a/src/shared/Modules/DefaultModule/DefaultModule.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "DefaultModule.h" - -#include <Core/ModulesManager/ModulesManager.h> - -#include <QCloseEvent> - -DefaultModule::DefaultModule(QWidget* parent) : Module(parent) {} - -DefaultModule::~DefaultModule() -{ - for (int i = 0; i < menuActions.count(); i++) - { - delete menuActions[i]; - } - menuActions.clear(); -} - -void DefaultModule::defaultContextMenuSetup() -{ - if (areDefaultSettingsDone) - return; - - areDefaultSettingsDone = true; - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, &DefaultModule::customContextMenuRequested, this, - &DefaultModule::onCustomContextMenuRequested); - addDefaultActionsToMenu(); - addCustomActionsToMenu(); -} - -void DefaultModule::addCustomActionsToMenu() {} - -void DefaultModule::onSkywardHubContextMenuRequested(QMenu& menu, - const QPoint& pos) -{ - QMenu newMenu(menuName); - if (!menuName.isEmpty()) - { - newMenu.addActions(menuActions); - menu.addMenu(&newMenu); - } - else - menu.addActions(menuActions); - - menu.addSeparator(); - - emit getEventHandler()->contextMenuRequest(menu, pos); -} - -SkywardHubCoreProxy& DefaultModule::getCore() { return proxyCore; } - -void DefaultModule::onCustomContextMenuRequested(const QPoint& pos) -{ - QMenu menu; - onSkywardHubContextMenuRequested(menu, mapToGlobal(pos)); -} - -QString DefaultModule::getName(const ModuleId id) -{ - return getCore()->getModulesManager()->getModuleName(id); -} - -Window* DefaultModule::getWindow() -{ - QObject* parent = this; - while (dynamic_cast<Window*>(parent) == NULL) - { - parent = parent->parent(); - } - return dynamic_cast<Window*>(parent); -} - -void DefaultModule::error(QString title, QString description, int msecDuration) -{ - getWindow()->errorDisplayer->createError(title, description, - ErrorType::ET_ERROR, msecDuration); -} - -void DefaultModule::warning(QString title, QString description, - int msecDuration) -{ - getWindow()->errorDisplayer->createError( - title, description, ErrorType::ET_WARNING, msecDuration); -} - -void DefaultModule::info(QString title, QString description, int msecDuration) -{ - getWindow()->errorDisplayer->createError(title, description, - ErrorType::ET_INFO, msecDuration); -} - -void DefaultModule::closeEvent(QCloseEvent* event) -{ - if (event->spontaneous()) - { - emit getEventHandler()->beforeDelete(this); - QWidget::closeEvent(event); - } - else - { - QWidget::closeEvent(event); - } -} - -void DefaultModule::addDefaultActionsToMenu() -{ - QAction* close = new QAction("Close"); - connect(close, &QAction::triggered, this, &DefaultModule::onCloseClicked); - - QAction* replace = new QAction("Replace"); - connect(replace, &QAction::triggered, this, - &DefaultModule::onReplaceClicked); - - addActionToMenu(close); - addActionToMenu(replace); -} - -void DefaultModule::addActionToMenu(QAction* action) -{ - menuActions.append(action); -} - -void DefaultModule::showMenuActionsInSeparatedMenu(const QString& menuName) -{ - this->menuName = menuName; -} - -void DefaultModule::onReplaceClicked() -{ - Module* newModule = - getCore()->getModulesManager()->invokeModulesPickerService(); - if (newModule != nullptr) - emit getEventHandler()->replaceMeWith(this, newModule); -} - -void DefaultModule::onCloseClicked() { close(); } diff --git a/src/shared/Modules/Empty/EmptyModule.cpp b/src/shared/Modules/Empty/EmptyModule.cpp index ed9230ec..f70c05ce 100644 --- a/src/shared/Modules/Empty/EmptyModule.cpp +++ b/src/shared/Modules/Empty/EmptyModule.cpp @@ -18,39 +18,25 @@ #include "EmptyModule.h" -#include <Core/ModulesManager/ModulesManager.h> +#include <QBoxLayout> +#include <QPushButton> -#include <QAction> -#include <QMessageBox> -#include <QPoint> +EmptyModule::EmptyModule() : Module(ModuleId::EMPTY) { setupUi(); } -#include "ui_EmptyModule.h" - -EmptyModule::EmptyModule() : DefaultModule(), ui(new Ui::EmptyModule) +void EmptyModule::setupUi() { - ui->setupUi(this); - defaultContextMenuSetup(); - connectUiSlots(); -} - -EmptyModule::~EmptyModule() { delete ui; } + QVBoxLayout *layout1 = new QVBoxLayout; + QHBoxLayout *layout2 = new QHBoxLayout; + layout1->addLayout(layout2); -void EmptyModule::connectUiSlots() -{ - connect(ui->selectPanel_button, &QPushButton::clicked, this, - &EmptyModule::onSelectPanelClick); -} + QPushButton *button = new QPushButton; + button->setText("Select a module"); -void EmptyModule::onSelectPanelClick() { onReplaceClicked(); } + layout2->addStretch(); + layout2->addWidget(button); + layout2->addStretch(); -QWidget* EmptyModule::toWidget() { return this; } + connect(button, &QPushButton::clicked, this, &Module::onReplaceMe); -XmlObject EmptyModule::toXmlObject() -{ - return XmlObject(getName(ModuleId::EMPTY)); -} - -void EmptyModule::fromXmlObject(const XmlObject& xmlObject) -{ - Q_UNUSED(xmlObject); + setLayout(layout1); } diff --git a/src/shared/Modules/Empty/EmptyModule.h b/src/shared/Modules/Empty/EmptyModule.h index ee1a6a5b..2b85d813 100644 --- a/src/shared/Modules/Empty/EmptyModule.h +++ b/src/shared/Modules/Empty/EmptyModule.h @@ -18,37 +18,15 @@ #pragma once -#include <Core/Module/Module.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> -#include <QMenu> -#include <QSharedPointer> -#include <QWidget> - -namespace Ui -{ -class EmptyModule; -} - -class EmptyModule : public DefaultModule +class EmptyModule : public Module { Q_OBJECT public: - explicit EmptyModule(); - ~EmptyModule() override; - - QWidget* toWidget() override; - - XmlObject toXmlObject() override; - void fromXmlObject(const XmlObject& xmlObject) override; - -protected: - void connectUiSlots(); - -protected slots: - void onSelectPanelClick(); + EmptyModule(); private: - Ui::EmptyModule* ui; + void setupUi(); }; diff --git a/src/shared/Modules/Empty/EmptyModule.ui b/src/shared/Modules/Empty/EmptyModule.ui deleted file mode 100644 index d8c8b669..00000000 --- a/src/shared/Modules/Empty/EmptyModule.ui +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>EmptyModule</class> - <widget class="QWidget" name="EmptyModule"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>448</width> - <height>233</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>This is an Empty panel. -In order to select a panel click the following button</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="3" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="selectPanel_button"> - <property name="text"> - <string>Select Panel</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="0" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="4" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/shared/Modules/FileStream/FileStreamModule.cpp b/src/shared/Modules/FileStream/FileStreamModule.cpp index a1fcf669..e0226af6 100644 --- a/src/shared/Modules/FileStream/FileStreamModule.cpp +++ b/src/shared/Modules/FileStream/FileStreamModule.cpp @@ -11,11 +11,10 @@ #include "Modules/SkywardHubStrings.h" #include "ui_FileStreamModule.h" -FileStreamModule::FileStreamModule(QWidget* parent) - : DefaultModule(parent), ui(new Ui::FileStreamModule) +FileStreamModule::FileStreamModule() + : Module(ModuleId::FILE_STREAM), ui(new Ui::FileStreamModule) { ui->setupUi(this); - defaultContextMenuSetup(); connectUI(); ui->filePath_lineEdit->setText(SkywardHubStrings::defaultStreamFile); @@ -29,11 +28,9 @@ FileStreamModule::~FileStreamModule() delete ui; } -QWidget* FileStreamModule::toWidget() { return this; } - XmlObject FileStreamModule::toXmlObject() { - XmlObject obj(getName(ModuleId::FILESTREAM)); + XmlObject obj = Module::toXmlObject(); if (getFilePath() != "") obj.addAttribute("FilePath", getFilePath()); @@ -49,22 +46,18 @@ XmlObject FileStreamModule::toXmlObject() void FileStreamModule::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::FILESTREAM)) + if (xmlObject.hasAttribute("FilePath")) { + ui->filePath_lineEdit->setText(xmlObject.getAttribute("FilePath")); + } - if (xmlObject.hasAttribute("FilePath")) - { - ui->filePath_lineEdit->setText(xmlObject.getAttribute("FilePath")); - } - - for (int i = 0; i < xmlObject.childCount(); i++) + for (int i = 0; i < xmlObject.childCount(); i++) + { + XmlObject child = xmlObject.childAt(i); + if (child.getObjectName() == "Subscription" && + child.getTextValue() != "") { - XmlObject child = xmlObject.childAt(i); - if (child.getObjectName() == "Subscription" && - child.getTextValue() != "") - { - addTopic(child.getTextValue()); - } + addTopic(child.getTextValue()); } } } @@ -132,7 +125,7 @@ void FileStreamModule::onStartClicked() disableOnStartElement(); for (int i = 0; i < topicViewsList.count(); i++) { - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(topicViewsList[i]->text().trimmed()), this, [this](const Message& message, const Filter& filter) { onMsgReceived(message); }); @@ -148,7 +141,7 @@ void FileStreamModule::onStopClicked() for (int i = 0; i < topicViewsList.count(); i++) { - getCore()->getMessageBroker()->unsubscribe( + MessageBroker::getInstance().unsubscribe( Filter::fromString(topicViewsList[i]->text().trimmed()), this); topicViewsList[i]->setEnabled(true); } @@ -219,7 +212,7 @@ void FileStreamModule::deleteAllTopicViews() { for (int i = 0; i < topicViewsList.count(); i++) { - getCore()->getMessageBroker()->unsubscribe( + MessageBroker::getInstance().unsubscribe( Filter::fromString(topicViewsList[i]->text().trimmed()), this); ui->topics_layout->removeWidget(topicViewsList[i]); topicViewsList[i]->deleteLater(); diff --git a/src/shared/Modules/FileStream/FileStreamModule.h b/src/shared/Modules/FileStream/FileStreamModule.h index 1e778559..4c430554 100644 --- a/src/shared/Modules/FileStream/FileStreamModule.h +++ b/src/shared/Modules/FileStream/FileStreamModule.h @@ -1,7 +1,7 @@ #pragma once #include <Core/Message/Message.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QFile> #include <QLineEdit> @@ -12,16 +12,14 @@ namespace Ui class FileStreamModule; } -class FileStreamModule : public DefaultModule +class FileStreamModule : public Module { Q_OBJECT public: - explicit FileStreamModule(QWidget* parent = nullptr); + FileStreamModule(); ~FileStreamModule(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; diff --git a/src/shared/Modules/Graph/Graph.cpp b/src/shared/Modules/Graph/Graph.cpp index 3b10efda..2a9f40ac 100644 --- a/src/shared/Modules/Graph/Graph.cpp +++ b/src/shared/Modules/Graph/Graph.cpp @@ -24,21 +24,19 @@ #include <QTimer> #include <algorithm> -Graph::Graph(QWidget* parent) : DefaultModule(parent) +Graph::Graph() : Module(ModuleId::GRAPH) { setupUi(); - customContextMenuSetup(); + customContextMenuActionSetup(); connect(&updaterTimer, &QTimer::timeout, this, &Graph::onUpdateTimerTick); updaterTimer.setSingleShot(false); updaterTimer.start(updatePeriod); } -QWidget* Graph::toWidget() { return this; } - XmlObject Graph::toXmlObject() { - XmlObject obj(getName(ModuleId::GRAPH)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("stopped", stopped ? 1 : 0); obj.addAttribute("following", following ? 1 : 0); @@ -59,31 +57,28 @@ XmlObject Graph::toXmlObject() void Graph::fromXmlObject(const XmlObject& obj) { - if (obj.getObjectName() == getName(ModuleId::GRAPH)) + int tmp; + obj.getAttribute("stopped", tmp); + stopped = (tmp == 1); + obj.getAttribute("following", tmp); + following = (tmp == 1); + + float lowerRange, upperRange; + obj.getAttribute("y_lower_range", lowerRange); + obj.getAttribute("y_upper_range", upperRange); + plot->yAxis->setRange(lowerRange, upperRange); + obj.getAttribute("x_lower_range", lowerRange); + obj.getAttribute("x_upper_range", upperRange); + plot->xAxis->setRange(lowerRange, upperRange); + + for (int i = 0; i < obj.childCount(); i++) { - int tmp; - obj.getAttribute("stopped", tmp); - stopped = (tmp == 1); - obj.getAttribute("following", tmp); - following = (tmp == 1); - - float lowerRange, upperRange; - obj.getAttribute("y_lower_range", lowerRange); - obj.getAttribute("y_upper_range", upperRange); - plot->yAxis->setRange(lowerRange, upperRange); - obj.getAttribute("x_lower_range", lowerRange); - obj.getAttribute("x_upper_range", upperRange); - plot->xAxis->setRange(lowerRange, upperRange); - - for (int i = 0; i < obj.childCount(); i++) - { - XmlObject child = obj.childAt(i); + XmlObject child = obj.childAt(i); - if (child.getObjectName() == "subscription") - { - auto filter = Filter::fromString(child.getAttribute("filter")); - onFilterAdded(filter); - } + if (child.getObjectName() == "subscription") + { + auto filter = Filter::fromString(child.getAttribute("filter")); + onFilterAdded(filter); } } } @@ -110,9 +105,10 @@ void Graph::onClearClicked() plot->replot(); } -void Graph::onStopClicked(bool checked) +void Graph::onStopClicked(QAction* action, bool checked) { stopped = checked; + action->setChecked(stopped); if (stopped) updaterTimer.stop(); @@ -148,7 +144,7 @@ void Graph::onFilterAdded(const Filter& filter) } plot->replot(); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( filter, this, [&](const Message& message, const Filter& filter) { @@ -273,48 +269,37 @@ void Graph::setupUi() // select graphs by clicking: plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables); -} -void Graph::customContextMenuSetup() -{ - setContextMenuPolicy(Qt::CustomContextMenu); - - // Redirect event from the plot to the widget plot->setContextMenuPolicy(Qt::CustomContextMenu); connect(plot, &QCustomPlot::customContextMenuRequested, this, - &Graph::onCustomContextMenuRequested); + &QWidget::customContextMenuRequested); } -void Graph::onCustomContextMenuRequested(const QPoint& pos) +void Graph::customContextMenuActionSetup() { - QMenu menu; - - // Subscribe -> Edit graph series - QAction* subscribe = new QAction("Manage subscriptions"); - connect(subscribe, &QAction::triggered, this, &Graph::onSubscribeClicked); - menu.addAction(subscribe); + QAction* subscriptions = new QAction("Manage subscriptions"); + subscriptions->setToolTip("Edit graph series"); + connect(subscriptions, &QAction::triggered, this, + &Graph::onSubscribeClicked); + customContextMenuActions.append(subscriptions); - // Clear -> Removes all data currently on the plot QAction* clear = new QAction("Clear"); + clear->setToolTip("Removes all data currently on the plot"); connect(clear, &QAction::triggered, this, &Graph::onClearClicked); - menu.addAction(clear); + customContextMenuActions.append(clear); - // Stop -> Pauses the graph QAction* stop = new QAction("Stop"); stop->setCheckable(true); stop->setChecked(stopped); - connect(stop, &QAction::triggered, this, &Graph::onStopClicked); - menu.addAction(stop); + stop->setToolTip("Pauses the graph"); + connect(stop, &QAction::triggered, this, + [this, stop](bool checked) { onStopClicked(stop, checked); }); + customContextMenuActions.append(stop); - // Follow -> Automatically move the graph to follow new data QAction* follow = new QAction("Follow"); follow->setCheckable(true); follow->setChecked(following); + follow->setToolTip("Automatically move the graph to follow new data"); connect(follow, &QAction::triggered, this, &Graph::onFollowClicked); - menu.addAction(follow); - - // Add a separator - menu.addSeparator(); - - emit getEventHandler()->contextMenuRequest(menu, mapToGlobal(pos)); -} \ No newline at end of file + customContextMenuActions.append(follow); +} diff --git a/src/shared/Modules/Graph/Graph.h b/src/shared/Modules/Graph/Graph.h index 2b1c64e0..099583f4 100644 --- a/src/shared/Modules/Graph/Graph.h +++ b/src/shared/Modules/Graph/Graph.h @@ -20,29 +20,28 @@ #include <Core/Message/Filter.h> #include <Core/QCustomPlot/QCustomPlot.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QList> #include <QTimer> #include <QWidget> -class Graph : public DefaultModule +class Graph : public Module { Q_OBJECT static constexpr int MAX_DATA_AGE = 30 * 60; // [s] public: - explicit Graph(QWidget* parent = nullptr); + Graph(); - QWidget* toWidget() override; XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; private slots: void onSubscribeClicked(); void onClearClicked(); - void onStopClicked(bool checked); + void onStopClicked(QAction* action, bool checked); void onFollowClicked(bool checked); void onFilterAdded(const Filter& filter); @@ -52,8 +51,7 @@ private slots: private: void setupUi(); - void customContextMenuSetup(); - void onCustomContextMenuRequested(const QPoint& pos) override; + void customContextMenuActionSetup(); QCustomPlot* plot; diff --git a/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp b/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp index 6c7a2961..02399ade 100644 --- a/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp +++ b/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.cpp @@ -22,24 +22,22 @@ #include "Components/SubscriptionsPanel/SubscriptionsPanel.h" -IncomingMessagesViewerModule::IncomingMessagesViewerModule(QWidget* parent) - : DefaultModule(parent) +IncomingMessagesViewerModule::IncomingMessagesViewerModule() + : Module(ModuleId::INCOMING_MESSAGES_VIEWER) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } IncomingMessagesViewerModule::~IncomingMessagesViewerModule() { for (auto filter : filters) - getCore()->getMessageBroker()->unsubscribe(filter, this); + MessageBroker::getInstance().unsubscribe(filter, this); } -QWidget* IncomingMessagesViewerModule::toWidget() { return this; } - XmlObject IncomingMessagesViewerModule::toXmlObject() { - XmlObject obj(getName(ModuleId::INCOMINGMESSAGESVIEWER)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("keepOnlyLastMessage", keepOnlyLastMessage ? "1" : "0"); obj.addAttribute("useTimestamp", useTimestamp ? "1" : "0"); @@ -84,7 +82,7 @@ void IncomingMessagesViewerModule::onFilterAdded(const Filter& filter) { filters.append(filter); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( filter, this, [&](const Message& message, const Filter& filter) { @@ -117,7 +115,7 @@ void IncomingMessagesViewerModule::onFilterAdded(const Filter& filter) void IncomingMessagesViewerModule::onFilterRemoved(const Filter& filter) { filters.removeAll(filter); - getCore()->getMessageBroker()->unsubscribe(filter, this); + MessageBroker::getInstance().unsubscribe(filter, this); } void IncomingMessagesViewerModule::setupUi() @@ -132,26 +130,26 @@ void IncomingMessagesViewerModule::setupUi() setLayout(layout); } -void IncomingMessagesViewerModule::addCustomActionsToMenu() +void IncomingMessagesViewerModule::customContextMenuActionSetup() { QAction* clear = new QAction("Clear"); connect(clear, &QAction::triggered, this, [this]() { edit->clear(); }); - addActionToMenu(clear); + customContextMenuActions.append(clear); QAction* subscriptions = new QAction("Manage subscriptions"); connect(subscriptions, &QAction::triggered, this, &IncomingMessagesViewerModule::onSubscribeClicked); - addActionToMenu(subscriptions); + customContextMenuActions.append(subscriptions); keepOnlyLastMessageAction = new QAction("Keep only last message"); keepOnlyLastMessageAction->setCheckable(true); connect(keepOnlyLastMessageAction, &QAction::toggled, this, [=](bool value) { keepOnlyLastMessage = value; }); - addActionToMenu(keepOnlyLastMessageAction); + customContextMenuActions.append(keepOnlyLastMessageAction); useTimestampAction = new QAction("Use timestamp"); useTimestampAction->setCheckable(true); connect(useTimestampAction, &QAction::toggled, this, [=](bool value) { useTimestamp = value; }); - addActionToMenu(useTimestampAction); + customContextMenuActions.append(useTimestampAction); } diff --git a/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h b/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h index e0671639..ad22e590 100644 --- a/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h +++ b/src/shared/Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h @@ -19,18 +19,18 @@ #pragma once #include <Core/Message/Filter.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> -class IncomingMessagesViewerModule : public DefaultModule +#include <QTextEdit> + +class IncomingMessagesViewerModule : public Module { Q_OBJECT public: - explicit IncomingMessagesViewerModule(QWidget* parent = nullptr); + IncomingMessagesViewerModule(); ~IncomingMessagesViewerModule(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; @@ -42,7 +42,7 @@ private slots: private: QTextEdit* edit; void setupUi(); - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); QList<Filter> filters; diff --git a/src/shared/Modules/MainStateViewer/MainStateViewer.cpp b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp index c9648a23..17841307 100644 --- a/src/shared/Modules/MainStateViewer/MainStateViewer.cpp +++ b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp @@ -21,23 +21,23 @@ #include <Components/FilterSelector/FilterSelector.h> #include <Core/MessageBroker/MessageBroker.h> -MainStateViewerModule::MainStateViewerModule(QWidget* parent) - : DefaultModule(parent) +#include <QAction> + +MainStateViewerModule::MainStateViewerModule() + : Module(ModuleId::MAIN_STATE_VIEWER) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } MainStateViewerModule::~MainStateViewerModule() { - getCore()->getMessageBroker()->unsubscribe(filter, this); + MessageBroker::getInstance().unsubscribe(filter, this); } -QWidget* MainStateViewerModule::toWidget() { return this; } - XmlObject MainStateViewerModule::toXmlObject() { - XmlObject obj(getName(ModuleId::MAINSTATEVIEWER)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("filter", filter.toString()); @@ -46,11 +46,8 @@ XmlObject MainStateViewerModule::toXmlObject() void MainStateViewerModule::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::MAINSTATEVIEWER)) - { - auto filter = Filter::fromString(xmlObject.getAttribute("filter")); - setFilter(filter); - } + auto filter = Filter::fromString(xmlObject.getAttribute("filter")); + setFilter(filter); } void MainStateViewerModule::setupUi() @@ -71,13 +68,13 @@ void MainStateViewerModule::setupUi() setLayout(outerLayout); } -void MainStateViewerModule::addCustomActionsToMenu() +void MainStateViewerModule::customContextMenuActionSetup() { QAction* action = new QAction("Choose topic and field"); connect(action, &QAction::triggered, this, &MainStateViewerModule::onConfigureClicked); - addActionToMenu(action); + customContextMenuActions.append(action); } void MainStateViewerModule::onConfigureClicked() @@ -88,8 +85,8 @@ void MainStateViewerModule::onConfigureClicked() void MainStateViewerModule::setFilter(const Filter& newFilter) { - getCore()->getMessageBroker()->unsubscribe(filter, this); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().unsubscribe(filter, this); + MessageBroker::getInstance().subscribe( newFilter, this, [this](const Message& message, const Filter& filter) { onMsgReceived(message); }); diff --git a/src/shared/Modules/MainStateViewer/MainStateViewer.h b/src/shared/Modules/MainStateViewer/MainStateViewer.h index 20d85b68..3c427839 100644 --- a/src/shared/Modules/MainStateViewer/MainStateViewer.h +++ b/src/shared/Modules/MainStateViewer/MainStateViewer.h @@ -20,29 +20,28 @@ #include <Core/Message/Filter.h> #include <Core/Message/Message.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Core/XmlObject.h> +#include <Modules/Module.h> #include <QLabel> #include <QWidget> #include "MainStatesList.h" -class MainStateViewerModule : public DefaultModule +class MainStateViewerModule : public Module { Q_OBJECT public: - explicit MainStateViewerModule(QWidget* parent = nullptr); + MainStateViewerModule(); ~MainStateViewerModule(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; private: void setupUi(); - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); void onConfigureClicked(); void setFilter(const Filter& filter); void onMsgReceived(const Message& msg); diff --git a/src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp b/src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp deleted file mode 100644 index 22872363..00000000 --- a/src/shared/Modules/MainWindow/SkywardHubMainWindow.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "SkywardHubMainWindow.h" - -#include <Core/Module/Module.h> -#include <Core/ModulesManager/ModulesManager.h> - -#include <QFile> -#include <QMenu> - -SkywardHubMainWindow::SkywardHubMainWindow(QWidget* parent) - : QMainWindow(parent) -{ - QFile styleSheet(":/assets/styles/global.qss"); - styleSheet.open(QFile::ReadOnly); - setStyleSheet(styleSheet.readAll()); - - mainWindow = new Window(); - mainWindow->setWindowTitle("Skyward Hub - 1"); - setCentralWidget(mainWindow); - - connect(core->getModulesManager(), &ModulesManager::contextMenuRequest, - this, &SkywardHubMainWindow::onContextMenuRequest); - connect(core->getModulesManager(), &ModulesManager::pageAdded, this, - &SkywardHubMainWindow::onPageAdded); - - core->init(); -} - -void SkywardHubMainWindow::onContextMenuRequest(QMenu& menu, const QPoint& pos) -{ - menu.exec(pos); -} - -void SkywardHubMainWindow::onPageAdded(int index) -{ - Module* module = core->getModulesManager()->getModuleAt(index); - - if (module != nullptr) - { - if (index == 0) - { - mainWindow->updateModule(module); - } - else - { - Window* window = new Window(); - window->setWindowTitle("Skyward Hub - " + - QString::number(index + 1)); - window->setCentralModule(module); - window->show(); - } - } -} diff --git a/src/shared/Modules/MainWindow/SkywardHubMainWindow.h b/src/shared/Modules/MainWindow/SkywardHubMainWindow.h deleted file mode 100644 index fe0c699f..00000000 --- a/src/shared/Modules/MainWindow/SkywardHubMainWindow.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <QMainWindow> - -#include "Core/SkywardHubCore.h" -#include "Window.h" - -class SkywardHubMainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit SkywardHubMainWindow(QWidget *parent = nullptr); - -protected slots: - void onPageAdded(int index); - void onContextMenuRequest(QMenu &menu, const QPoint &p); - -private: - SkywardHubCoreProxy core; - Window *mainWindow; -}; diff --git a/src/shared/Modules/MainWindow/Window.cpp b/src/shared/Modules/MainWindow/Window.cpp deleted file mode 100644 index 8eb7a1a5..00000000 --- a/src/shared/Modules/MainWindow/Window.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of Skyward Hub. - * - * Skyward Hub is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. - * - */ - -#include "Window.h" - -#include <Core/Module/Module.h> -#include <Core/ModulesManager/ModulesManager.h> - -#include <QVBoxLayout> - -#include "ui_Window.h" - -Window::Window(QWidget* parent) : QWidget(parent), ui(new Ui::Window) -{ - ui->setupUi(this); - errorDisplayer = new ErrorDisplayer(this); -} - -Window::~Window() -{ - delete ui; - delete errorDisplayer; -} - -void Window::updateModule(Module* m) -{ - if (m != nullptr) - { - if (centralModule == nullptr || centralModule != m) - { - setCentralModule(m); - } - } -} - -Module* Window::getCentralModule() const { return centralModule; } - -void Window::setCentralModule(Module* value) -{ - if (centralModule != nullptr) - { - // ui->mainLayout->removeWidget(centralModule->toWidget()); - disconnect(centralModule->getEventHandler(), &QWidget::destroyed, this, - &Window::onWidgetDestroyed); - disconnect(centralModule->getEventHandler(), - &EventHandler::replaceMeWith, this, - &Window::onReplaceRequested); - } - centralModule = value; - ui->mainLayout->addWidget(value->toWidget()); - connect(value->getEventHandler(), &QWidget::destroyed, this, - &Window::onWidgetDestroyed); - connect(value->getEventHandler(), &EventHandler::replaceMeWith, this, - &Window::onReplaceRequested); - - value->toWidget()->lower(); -} - -void Window::closeEvent(QCloseEvent* event) -{ - if (centralModule != nullptr) - delete centralModule; - - QWidget::closeEvent(event); - - deleteLater(); -} - -void Window::onWidgetDestroyed() -{ - centralModule = nullptr; - close(); - this->deleteLater(); -} - -void Window::onReplaceRequested(Module* sender, Module* newModule) -{ - if (newModule != nullptr && sender != nullptr) - { - setCentralModule(newModule); - delete sender; - } -} - -void Window::resizeEvent(QResizeEvent* event) -{ - Q_UNUSED(event); - errorDisplayer->reposition(); -} diff --git a/src/shared/Modules/MainWindow/Window.ui b/src/shared/Modules/MainWindow/Window.ui deleted file mode 100644 index a4db8fed..00000000 --- a/src/shared/Modules/MainWindow/Window.ui +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Window</class> - <widget class="QWidget" name="Window"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <layout class="QVBoxLayout" name="mainLayout"> - <property name="spacing"> - <number>0</number> - </property> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/shared/Modules/Mavlink/BaseMavlinkModule.cpp b/src/shared/Modules/Mavlink/BaseMavlinkModule.cpp index 0c5b4b28..b9e9bcfa 100644 --- a/src/shared/Modules/Mavlink/BaseMavlinkModule.cpp +++ b/src/shared/Modules/Mavlink/BaseMavlinkModule.cpp @@ -22,18 +22,17 @@ int BaseMavlinkModule::ACTIVE_MAVLINK_MODULES = 0; -BaseMavlinkModule::BaseMavlinkModule(MavlinkPort *port, QWidget *parent) - : DefaultModule(parent), port(port), mavlinkCodec(port, this) +BaseMavlinkModule::BaseMavlinkModule(MavlinkPort *port, ModuleId id) + : Module(id), port(port), mavlinkCodec(port, this) { setupUi(); - defaultContextMenuSetup(); connect(&mavlinkCodec, &MavlinkCodec::msgReceived, this, &BaseMavlinkModule::onMsgReceived); connect(&linkQualityTimer, &QTimer::timeout, this, &BaseMavlinkModule::onLinkQualityTimerTick); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(SkywardHubStrings::commandsTopic + "/*"), this, [this](const Message &message, const Filter &filter) { onCommandReceived(message); }); @@ -44,12 +43,10 @@ BaseMavlinkModule::~BaseMavlinkModule() if (startToggleButton->state()) stop(); - getCore()->getMessageBroker()->unsubscribe( + MessageBroker::getInstance().unsubscribe( Filter::fromString(SkywardHubStrings::commandsTopic + "/*"), this); } -QWidget *BaseMavlinkModule::toWidget() { return this; } - XmlObject BaseMavlinkModule::toXmlObject() { XmlObject obj = childToXmlObject(); @@ -70,7 +67,7 @@ void BaseMavlinkModule::fromXmlObject(const XmlObject &obj) void BaseMavlinkModule::onMsgReceived(const Message &msg) { msgArrived++; - getCore()->getMessageBroker()->publish(msg); + MessageBroker::getInstance().publish(msg); } void BaseMavlinkModule::onLinkQualityTimerTick() @@ -162,7 +159,7 @@ void BaseMavlinkModule::onCommandReceived(const Message &msg) auto seqField = Field((uint64_t)mav_msg.seq); confirmationMsg.setField("sequence_number", seqField); - getCore()->getMessageBroker()->publish(confirmationMsg); + MessageBroker::getInstance().publish(confirmationMsg); } void BaseMavlinkModule::onOpenLogFolderClick() diff --git a/src/shared/Modules/Mavlink/BaseMavlinkModule.h b/src/shared/Modules/Mavlink/BaseMavlinkModule.h index 3cf58309..d7911d10 100644 --- a/src/shared/Modules/Mavlink/BaseMavlinkModule.h +++ b/src/shared/Modules/Mavlink/BaseMavlinkModule.h @@ -20,8 +20,7 @@ #include <Components/ToggleButton/ToggleButton.h> #include <Core/Message/Message.h> -#include <Core/Module/Module.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QTimer> #include <QWidget> @@ -36,15 +35,13 @@ namespace Ui class BaseMavlinkModule; } -class BaseMavlinkModule : public DefaultModule +class BaseMavlinkModule : public Module { Q_OBJECT public: - BaseMavlinkModule(MavlinkPort *port, QWidget *parent = nullptr); + BaseMavlinkModule(MavlinkPort *port, ModuleId id); ~BaseMavlinkModule(); - QWidget *toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject &obj) override; diff --git a/src/shared/Modules/Mavlink/SerialMavlinkModule.cpp b/src/shared/Modules/Mavlink/SerialMavlinkModule.cpp index 45780226..b3225395 100644 --- a/src/shared/Modules/Mavlink/SerialMavlinkModule.cpp +++ b/src/shared/Modules/Mavlink/SerialMavlinkModule.cpp @@ -20,8 +20,8 @@ #include <QSerialPortInfo> -SerialMavlinkModule::SerialMavlinkModule(QWidget *parent) - : BaseMavlinkModule(&serial, parent), serial(this) +SerialMavlinkModule::SerialMavlinkModule() + : BaseMavlinkModule(&serial, ModuleId::SERIAL_MAVLINK), serial(this) { childSetupUi(); } @@ -30,7 +30,7 @@ void SerialMavlinkModule::onRefreshClicked() { fillPortsComboBox(); } XmlObject SerialMavlinkModule::childToXmlObject() { - XmlObject obj(getName(ModuleId::SERIAL_MAVLINK)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("serial_port", portsComboBox->currentText()); obj.addAttribute("baudrate", baudrateComboBox->currentData().toInt()); diff --git a/src/shared/Modules/Mavlink/SerialMavlinkModule.h b/src/shared/Modules/Mavlink/SerialMavlinkModule.h index 68a2a7e6..6ae11c16 100644 --- a/src/shared/Modules/Mavlink/SerialMavlinkModule.h +++ b/src/shared/Modules/Mavlink/SerialMavlinkModule.h @@ -25,7 +25,7 @@ class SerialMavlinkModule : public BaseMavlinkModule { Q_OBJECT public: - explicit SerialMavlinkModule(QWidget *parent = nullptr); + explicit SerialMavlinkModule(); private slots: void onRefreshClicked(); diff --git a/src/shared/Modules/Mavlink/UdpMavlinkModule.cpp b/src/shared/Modules/Mavlink/UdpMavlinkModule.cpp index fd2a60f7..b529334b 100644 --- a/src/shared/Modules/Mavlink/UdpMavlinkModule.cpp +++ b/src/shared/Modules/Mavlink/UdpMavlinkModule.cpp @@ -18,15 +18,15 @@ #include "UdpMavlinkModule.h" -UdpMavlinkModule::UdpMavlinkModule(QWidget *parent) - : BaseMavlinkModule(&udp, parent), udp(this) +UdpMavlinkModule::UdpMavlinkModule() + : BaseMavlinkModule(&udp, ModuleId::UDP_MAVLINK), udp(this) { childSetupUi(); } XmlObject UdpMavlinkModule::childToXmlObject() { - XmlObject obj(getName(ModuleId::UDP_MAVLINK)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("recv_port", recvPort->text().toInt()); obj.addAttribute("send_port", sendPort->text().toInt()); diff --git a/src/shared/Modules/Mavlink/UdpMavlinkModule.h b/src/shared/Modules/Mavlink/UdpMavlinkModule.h index e0a92fd3..58a657aa 100644 --- a/src/shared/Modules/Mavlink/UdpMavlinkModule.h +++ b/src/shared/Modules/Mavlink/UdpMavlinkModule.h @@ -25,7 +25,7 @@ class UdpMavlinkModule : public BaseMavlinkModule { Q_OBJECT public: - explicit UdpMavlinkModule(QWidget *parent = nullptr); + explicit UdpMavlinkModule(); private: void childSetupUi(); diff --git a/src/shared/Modules/Module.cpp b/src/shared/Modules/Module.cpp new file mode 100644 index 00000000..1e759785 --- /dev/null +++ b/src/shared/Modules/Module.cpp @@ -0,0 +1,121 @@ +/* + * This file is part of Skyward Hub. + * + * Skyward Hub is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * Skyward Hub. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "Module.h" +// #include <Components/ErrorDisplayer/Error.h> + +#include <Components/ModulesPicker/ModulesPicker.h> +#include <Core/SkywardHubCore.h> +#include <Modules/ModulesList.h> + +#include <QAction> + +Module::Module(ModuleId id) : id(id) +{ + // Setup context menu + { + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &QWidget::customContextMenuRequested, this, + [&](const QPoint &pos) + { + QMenu menu("App"); + + QAction *close = new QAction("Close"); + connect(close, &QAction::triggered, this, + [this]() { emit closeMe(this); }); + menu.addAction(close); + + QAction *replace = new QAction("Replace"); + connect(replace, &QAction::triggered, this, + &Module::onReplaceMe); + menu.addAction(replace); + + // Load custom actions + if (customContextMenuActions.size() > 0) + { + menu.addSeparator(); + menu.addActions(customContextMenuActions); + } + + // Load hub actions + menu.addSeparator(); + menu.addActions( + SkywardHubCore::getInstance().getHubMenuActions()); + + menu.exec(mapToGlobal(pos)); + }); + } +} + +ModuleId Module::getId() const { return id; } + +QString Module::getModuleName() const +{ + return ModulesList::getInstance().getModuleName(id); +}; + +QString Module::getXmlName(const ModuleId id) const +{ + return ModulesList::getInstance().getXmlName(id); +}; + +XmlObject Module::toXmlObject() { return XmlObject(getXmlName(id)); } + +void Module::fromXmlObject(const XmlObject &xmlObject) {} + +void Module::onReplaceMe() +{ + ModulesPicker *picker = new ModulesPicker(); + + connect(picker, &ModulesPicker::onModuleSelected, this, + [this](ModuleId id) { + emit replaceMe( + this, ModulesList::getInstance().instantiateModule(id)); + }); + + // Launch the modules picker + picker->exec(); +} + +Window *Module::getWindow() +{ + QObject *parent = this; + while (dynamic_cast<Window *>(parent) == NULL) + { + parent = parent->parent(); + } + return dynamic_cast<Window *>(parent); +} + +void Module::error(QString title, QString description, int msecDuration) +{ + getWindow()->errorDisplayer->createError(title, description, + ErrorType::ET_ERROR, msecDuration); +} + +void Module::warning(QString title, QString description, int msecDuration) +{ + getWindow()->errorDisplayer->createError( + title, description, ErrorType::ET_WARNING, msecDuration); +} + +void Module::info(QString title, QString description, int msecDuration) +{ + getWindow()->errorDisplayer->createError(title, description, + ErrorType::ET_INFO, msecDuration); +} diff --git a/src/shared/Modules/DefaultModule/DefaultModule.h b/src/shared/Modules/Module.h similarity index 56% rename from src/shared/Modules/DefaultModule/DefaultModule.h rename to src/shared/Modules/Module.h index f1bfec30..279383b9 100644 --- a/src/shared/Modules/DefaultModule/DefaultModule.h +++ b/src/shared/Modules/Module.h @@ -18,35 +18,33 @@ #pragma once -#include <Components/ErrorDisplayer/ErrorDisplayer.h> -#include <Core/Module/Module.h> -#include <Core/SkywardHubCore.h> -#include <Modules/MainWindow/Window.h> +#include <Core/Window/Window.h> +#include <Core/XmlObject.h> #include <Modules/ModuleInfo.h> -class DefaultModule : public Module +#include <QAction> +#include <QWidget> + +class Window; + +class Module : public QWidget { Q_OBJECT public: - static constexpr int LONG_ERROR_DURATION = 1500; - static constexpr int MEDIUM_ERROR_DURATION = 10000; - static constexpr int SHORT_ERROR_DURATION = 5000; - - DefaultModule(QWidget* parent = nullptr); - ~DefaultModule(); - - virtual void defaultContextMenuSetup(); - virtual void addCustomActionsToMenu(); - virtual void onSkywardHubContextMenuRequested(QMenu& menu, const QPoint& p); - - SkywardHubCoreProxy& getCore(); - virtual void onCustomContextMenuRequested(const QPoint& p); - - QString getName(const ModuleId id); + explicit Module(ModuleId id); + ModuleId getId() const; + QString getModuleName() const; + QString getXmlName(const ModuleId id) const; Window* getWindow(); + virtual XmlObject toXmlObject(); // TODO: Make const + virtual void fromXmlObject(const XmlObject& xmlObject); + + static constexpr int LONG_ERROR_DURATION = 1500; + static constexpr int MEDIUM_ERROR_DURATION = 10000; + static constexpr int SHORT_ERROR_DURATION = 5000; void error(QString title, QString description, int duration = MEDIUM_ERROR_DURATION); void warning(QString title, QString description, @@ -54,20 +52,15 @@ public: void info(QString title, QString description, int duration = MEDIUM_ERROR_DURATION); -protected: - void closeEvent(QCloseEvent* event) override; - - void addDefaultActionsToMenu(); - void addActionToMenu(QAction* action); +public slots: + void onReplaceMe(); + // void onCloseMe(); - void showMenuActionsInSeparatedMenu(const QString& menuName); - virtual void onReplaceClicked(); - virtual void onCloseClicked(); +signals: + void replaceMe(Module* oldModule, Module* newModule); + void closeMe(Module* thisModule); -private: - SkywardHubCoreProxy proxyCore; - QList<QAction*> menuActions; - - QString menuName; - bool areDefaultSettingsDone = false; +protected: + ModuleId id; + QList<QAction*> customContextMenuActions; }; diff --git a/src/shared/Modules/ModuleInfo.cpp b/src/shared/Modules/ModuleInfo.cpp index 751dc24d..147f9917 100644 --- a/src/shared/Modules/ModuleInfo.cpp +++ b/src/shared/Modules/ModuleInfo.cpp @@ -23,11 +23,9 @@ ModuleInfo::ModuleInfo() {} ModuleInfo::ModuleInfo(const ModuleId &id, const QString &name) { setId(id); - setModuleName(name); + setName(name); } -ModuleInfo::ModuleInfo(const ModuleInfo &other) { copy(other); } - ModuleInfo::ModuleInfo(const ModuleId &id, const QString &name, ModuleCategory category) : ModuleInfo(id, name) @@ -35,42 +33,24 @@ ModuleInfo::ModuleInfo(const ModuleId &id, const QString &name, setCategory(category); } -ModuleId ModuleInfo::getId() const { return moduleId; } - -void ModuleInfo::setId(const ModuleId &value) { moduleId = value; } - -QString ModuleInfo::getModuleName() const { return moduleName; } +ModuleId ModuleInfo::getId() const { return id; } -void ModuleInfo::setModuleName(const QString &value) { moduleName = value; } +void ModuleInfo::setId(const ModuleId &value) { id = value; } -std::function<Module *()> ModuleInfo::getFactory() const { return factory; } +QString ModuleInfo::getModuleName() const { return name; } -void ModuleInfo::setFactory(const std::function<Module *()> &value) -{ - factory = value; -} +void ModuleInfo::setName(const QString &value) { name = value; } -QStringList ModuleInfo::getModuleSourceFiles() const +std::function<Module *()> ModuleInfo::getFactoryMethod() const { - return moduleSourceFiles; + return factoryMethod; } -void ModuleInfo::addModuleSourceFiles(const QString &value) -{ - moduleSourceFiles.append(value); -} - -void ModuleInfo::operator=(const ModuleInfo &other) { copy(other); } - -void ModuleInfo::copy(const ModuleInfo &other) +void ModuleInfo::setFactoryMethod(const std::function<Module *()> &value) { - setId(other.getId()); - setCategory(other.getModuleCategory()); - setModuleName(other.getModuleName()); - setFactory(other.getFactory()); - moduleSourceFiles = other.getModuleSourceFiles(); + factoryMethod = value; } -ModuleCategory ModuleInfo::getModuleCategory() const { return mCategory; } +ModuleCategory ModuleInfo::getModuleCategory() const { return category; } -void ModuleInfo::setCategory(const ModuleCategory &value) { mCategory = value; } +void ModuleInfo::setCategory(const ModuleCategory &value) { category = value; } diff --git a/src/shared/Modules/ModuleInfo.h b/src/shared/Modules/ModuleInfo.h index c28dad47..08362667 100644 --- a/src/shared/Modules/ModuleInfo.h +++ b/src/shared/Modules/ModuleInfo.h @@ -25,42 +25,51 @@ class Module; enum ModuleId { EMPTY, - SPLITTER, - COMMANDPAD, - COMPACT_COMMAND_PAD, - BROKERTEST, + + // Data visualization GRAPH, - OUTCOMINGMESSAGEVIEWER, - INCOMINGMESSAGESVIEWER, + OUTGOING_MESSAGES_VIEWER, + INCOMING_MESSAGES_VIEWER, + MAIN_STATE_VIEWER, + PAYLOAD_STATE_VIEWER, + ORIENTATION_VISUALIZER, + VALVES_VIEWER, + + // Data sources SERIAL_MAVLINK, UDP_MAVLINK, - FILESTREAM, - ORIENTATION_VISUALIZER, - MAINSTATEVIEWER, - PAYLOADSTATEVIEWER, - VALUESCONVERTERVIEWER, + FILE_STREAM, + + // Utilities + COMMAND_PAD, + COMPACT_COMMAND_PAD, + VALUES_CONVERTER_VIEWER, TIMER_CONTROLLER, - MODULETEST, + + // Organization TABS, - FILTER_SELECTOR, - VALVESVIEWER, + VERTICAL_SPLITTER, + HORIZONTAL_SPLITTER, + + // Testing + BROKER_TEST + }; enum ModuleCategory { HIDDEN, - DEFAULT, - UTILITY, - DATAVISUAL, - DATASOURCE, - HOME + DATA_VISUALIZATION, + DATA_SOURCES, + UTILITIES, + ORGANIZATION, + TESTING }; class ModuleInfo { public: ModuleInfo(); - ModuleInfo(const ModuleInfo& other); ModuleInfo(const ModuleId& id, const QString& name); ModuleInfo(const ModuleId& id, const QString& name, ModuleCategory category); @@ -69,26 +78,17 @@ public: void setId(const ModuleId& value); QString getModuleName() const; - void setModuleName(const QString& value); + void setName(const QString& value); - std::function<Module*()> getFactory() const; - void setFactory(const std::function<Module*()>& value); - - QStringList getModuleSourceFiles() const; - void addModuleSourceFiles(const QString& value); - - void operator=(const ModuleInfo& other); + std::function<Module*()> getFactoryMethod() const; + void setFactoryMethod(const std::function<Module*()>& value); ModuleCategory getModuleCategory() const; void setCategory(const ModuleCategory& value); -protected: - void copy(const ModuleInfo& other); - private: - ModuleId moduleId; - ModuleCategory mCategory = ModuleCategory::DEFAULT; - QString moduleName; - std::function<Module*()> factory; - QStringList moduleSourceFiles; + ModuleId id; + ModuleCategory category = ModuleCategory::HIDDEN; + QString name; + std::function<Module*()> factoryMethod; }; diff --git a/src/shared/Modules/ModulesList.cpp b/src/shared/Modules/ModulesList.cpp index 90442806..2a9abc8a 100644 --- a/src/shared/Modules/ModulesList.cpp +++ b/src/shared/Modules/ModulesList.cpp @@ -39,166 +39,207 @@ #include <Modules/ValuesConverterViewer/ValuesConverterViewerModule.h> #include <Modules/ValvesViewer/ValvesViewer.h> -void ModulesList::createModuleList() +ModulesList& ModulesList::getInstance() { - /** - * addModule(MODULE UNIQUE ID, MODULE UNIQUE NAME, a function that - * instantiate your module) If you are creating a new Module, please add - * it's id in the ModuleId enum (you can find it in moduleslist.h) - * - * WARNING! - * - Each ID must be unique - * - Each ModuleName must be unique and WITHOUT spaces - * - A Module must NOT include a file outside its folder - * - The ModuleSourceFiles allow you to specify which files will be included - * (all the files that match the strings you provide will be included) - */ - - ModuleInfo empty(ModuleId::EMPTY, "EmptyModule"); - empty.setFactory([]() { return new EmptyModule(); }); - addModuleInfo(empty); - - ModuleInfo commandPad(ModuleId::COMMANDPAD, "CommandPad", - ModuleCategory::UTILITY); - commandPad.setFactory([]() { return new CommandPad(); }); - addModuleInfo(commandPad); - - ModuleInfo compactCommandPad(ModuleId::COMPACT_COMMAND_PAD, - "compact_command_pad", - ModuleCategory::UTILITY); - compactCommandPad.setFactory([]() { return new CompactCommandPad(); }); - addModuleInfo(compactCommandPad); - - ModuleInfo splitter(ModuleId::SPLITTER, "Splitter"); - splitter.setFactory([]() { return new Splitter(); }); - addModuleInfo(splitter); - - ModuleInfo testModule(ModuleId::BROKERTEST, "TestBroker", - ModuleCategory::DEFAULT); - testModule.setFactory([]() { return new TestModule(); }); - addModuleInfo(testModule); - - ModuleInfo graphModule(ModuleId::GRAPH, "Graph", - ModuleCategory::DATAVISUAL); - graphModule.setFactory([]() { return new Graph(); }); - addModuleInfo(graphModule); - - ModuleInfo outMsgViewer(ModuleId::OUTCOMINGMESSAGEVIEWER, - "OutgoingMessagesViewer", - ModuleCategory::DATAVISUAL); - outMsgViewer.setFactory([]() - { return new OutgoingMessagesViewerModule(); }); - addModuleInfo(outMsgViewer); - - ModuleInfo inMsgViewer(ModuleId::INCOMINGMESSAGESVIEWER, - "IncomingMessagesViewer", - ModuleCategory::DATAVISUAL); - inMsgViewer.setFactory([]() { return new IncomingMessagesViewerModule(); }); - addModuleInfo(inMsgViewer); - - ModuleInfo serialMavlink(ModuleId::SERIAL_MAVLINK, "SerialMavlink", - ModuleCategory::DATASOURCE); - serialMavlink.setFactory([]() { return new SerialMavlinkModule(); }); - addModuleInfo(serialMavlink); - - ModuleInfo udpMavlink(ModuleId::UDP_MAVLINK, "UdpMavlink", - ModuleCategory::DATASOURCE); - udpMavlink.setFactory([]() { return new UdpMavlinkModule(); }); - addModuleInfo(udpMavlink); - - ModuleInfo fileStream(ModuleId::FILESTREAM, "FileStream", - ModuleCategory::DATASOURCE); - fileStream.setFactory([]() { return new FileStreamModule(); }); - addModuleInfo(fileStream); - - ModuleInfo mainStateViewer(ModuleId::MAINSTATEVIEWER, "MainStateViewer", - ModuleCategory::DATAVISUAL); - mainStateViewer.setFactory([]() { return new MainStateViewerModule(); }); - addModuleInfo(mainStateViewer); - - ModuleInfo payloadStateViewer(ModuleId::PAYLOADSTATEVIEWER, - "PayloadStateViewer", - ModuleCategory::DATAVISUAL); - payloadStateViewer.setFactory([]() - { return new PayloadStateViewerModule(); }); - addModuleInfo(payloadStateViewer); - - ModuleInfo valuesConverterViewer(ModuleId::VALUESCONVERTERVIEWER, - "ValuesConverterViewer", - ModuleCategory::UTILITY); - valuesConverterViewer.setFactory( - []() { return new ValuesConverterViewerModule(); }); - addModuleInfo(valuesConverterViewer); - - ModuleInfo orientationVisualizer(ModuleId::ORIENTATION_VISUALIZER, - "OrientationVisualizer", - ModuleCategory::UTILITY); - orientationVisualizer.setFactory([]() - { return new OrientationVisualizer(); }); - addModuleInfo(orientationVisualizer); - - ModuleInfo timerController(ModuleId::TIMER_CONTROLLER, "TimerController", - ModuleCategory::UTILITY); - timerController.setFactory([]() { return new TimerControllerModule(); }); - addModuleInfo(timerController); - - ModuleInfo tabs(ModuleId::TABS, "Tabs", ModuleCategory::UTILITY); - tabs.setFactory([]() { return new TabsModule(); }); - addModuleInfo(tabs); - - ModuleInfo valvesViewer(ModuleId::VALVESVIEWER, "ValvesViewer", - ModuleCategory::DATAVISUAL); - valvesViewer.setFactory([]() { return new ValvesViewer(); }); - valvesViewer.addModuleSourceFiles("Modules/ValvesViewer/"); - addModuleInfo(valvesViewer); + static ModulesList instance; + return instance; } -// ____________________________________________________________________________________________ +ModulesList::ModulesList() +{ -ModulesList::ModulesList() { createModuleList(); } + // If you are creating a new Module, please add it's id in the ModuleId enum + // (you can find it in moduleslist.h) -bool ModulesList::containsId(ModuleId id) -{ - for (int i = 0; i < modulesInfo.count(); i++) + // Hidden { - if (modulesInfo[i].getId() == id) - return true; + ModuleInfo emptyModule(ModuleId::EMPTY, "Empty", + ModuleCategory::HIDDEN); + emptyModule.setFactoryMethod([]() { return new EmptyModule(); }); + modulesInfo.append(emptyModule); } - return false; -} -void ModulesList::addModuleInfo(const ModuleInfo& info) -{ - modulesInfo.append(info); + // Data visualization widgets + { + ModuleInfo graphModule(ModuleId::GRAPH, "Graph", + ModuleCategory::DATA_VISUALIZATION); + graphModule.setFactoryMethod([]() { return new Graph(); }); + modulesInfo.append(graphModule); + + ModuleInfo outMsgViewer(ModuleId::OUTGOING_MESSAGES_VIEWER, + "Outgoing Messages Viewer", + ModuleCategory::DATA_VISUALIZATION); + outMsgViewer.setFactoryMethod( + []() { return new OutgoingMessagesViewerModule(); }); + modulesInfo.append(outMsgViewer); + + ModuleInfo inMsgViewer(ModuleId::INCOMING_MESSAGES_VIEWER, + "Incoming Messages Viewer", + ModuleCategory::DATA_VISUALIZATION); + inMsgViewer.setFactoryMethod( + []() { return new IncomingMessagesViewerModule(); }); + modulesInfo.append(inMsgViewer); + + ModuleInfo mainStateViewer(ModuleId::MAIN_STATE_VIEWER, + "Main State Viewer", + ModuleCategory::DATA_VISUALIZATION); + mainStateViewer.setFactoryMethod( + []() { return new MainStateViewerModule(); }); + modulesInfo.append(mainStateViewer); + + ModuleInfo payloadStateViewer(ModuleId::PAYLOAD_STATE_VIEWER, + "Payload State Viewer", + ModuleCategory::DATA_VISUALIZATION); + payloadStateViewer.setFactoryMethod( + []() { return new PayloadStateViewerModule(); }); + modulesInfo.append(payloadStateViewer); + + ModuleInfo orientationVisualizer(ModuleId::ORIENTATION_VISUALIZER, + "Orientation Visualizer", + ModuleCategory::DATA_VISUALIZATION); + orientationVisualizer.setFactoryMethod( + []() { return new OrientationVisualizer(); }); + modulesInfo.append(orientationVisualizer); + + ModuleInfo valvesViewer(ModuleId::VALVES_VIEWER, "ValvesViewer", + ModuleCategory::DATA_VISUALIZATION); + valvesViewer.setFactoryMethod([]() { return new ValvesViewer(); }); + modulesInfo.append(valvesViewer); + } + + // Data sources + { + ModuleInfo serialMavlink(ModuleId::SERIAL_MAVLINK, "SerialMavlink", + ModuleCategory::DATA_SOURCES); + serialMavlink.setFactoryMethod([]() + { return new SerialMavlinkModule(); }); + modulesInfo.append(serialMavlink); + + ModuleInfo udpMavlink(ModuleId::UDP_MAVLINK, "UdpMavlink", + ModuleCategory::DATA_SOURCES); + udpMavlink.setFactoryMethod([]() { return new UdpMavlinkModule(); }); + modulesInfo.append(udpMavlink); + + ModuleInfo fileStream(ModuleId::FILE_STREAM, "File Stream", + ModuleCategory::DATA_SOURCES); + fileStream.setFactoryMethod([]() { return new FileStreamModule(); }); + modulesInfo.append(fileStream); + } + + // Utilities + { + ModuleInfo commandPad(ModuleId::COMMAND_PAD, "Command Pad", + ModuleCategory::UTILITIES); + commandPad.setFactoryMethod([]() { return new CommandPad(); }); + modulesInfo.append(commandPad); + + ModuleInfo compactCommandPad(ModuleId::COMPACT_COMMAND_PAD, + "Compact Command Pad", + ModuleCategory::UTILITIES); + compactCommandPad.setFactoryMethod([]() + { return new CompactCommandPad(); }); + modulesInfo.append(compactCommandPad); + + ModuleInfo valuesConverterViewer(ModuleId::VALUES_CONVERTER_VIEWER, + "Values Converter Viewer", + ModuleCategory::UTILITIES); + valuesConverterViewer.setFactoryMethod( + []() { return new ValuesConverterViewerModule(); }); + modulesInfo.append(valuesConverterViewer); + + ModuleInfo timerController(ModuleId::TIMER_CONTROLLER, + "Timer Controller", + ModuleCategory::UTILITIES); + timerController.setFactoryMethod( + []() { return new TimerControllerModule(); }); + modulesInfo.append(timerController); + } + + // Organization + { + ModuleInfo tabs(ModuleId::TABS, "Tabs", ModuleCategory::ORGANIZATION); + tabs.setFactoryMethod([]() { return new TabsModule(); }); + modulesInfo.append(tabs); + + ModuleInfo verticalSplitter(ModuleId::VERTICAL_SPLITTER, + "Vertical Splitter", + ModuleCategory::ORGANIZATION); + verticalSplitter.setFactoryMethod( + []() { + return new Splitter(Qt::Vertical, ModuleId::VERTICAL_SPLITTER); + }); + modulesInfo.append(verticalSplitter); + + ModuleInfo horizontalSplitter(ModuleId::HORIZONTAL_SPLITTER, + "Horiziontal Splitter", + ModuleCategory::ORGANIZATION); + horizontalSplitter.setFactoryMethod( + []() { + return new Splitter(Qt::Horizontal, + ModuleId::HORIZONTAL_SPLITTER); + }); + modulesInfo.append(horizontalSplitter); + } + + // Testing + { + ModuleInfo testModule(ModuleId::BROKER_TEST, "TestBroker", + ModuleCategory::TESTING); + testModule.setFactoryMethod([]() { return new TestModule(); }); + modulesInfo.append(testModule); + } } -QString ModulesList::getModuleName(ModuleId id) const +QString ModulesList::getModuleName(ModuleId id) { for (int i = 0; i < modulesInfo.count(); i++) { if (modulesInfo[i].getId() == id) return modulesInfo[i].getModuleName(); } + return ""; } -std::function<Module*()> ModulesList::getFactory(ModuleId id) const +bool ModulesList::getModuleId(QString name, ModuleId& id) +{ + for (int i = 0; i < modulesInfo.count(); i++) + { + if (modulesInfo[i].getModuleName().toLower().replace(' ', '_') == + name.toLower().replace(' ', '_')) + { + id = modulesInfo[i].getId(); + return true; + } + } + + return false; +} + +QString ModulesList::getXmlName(ModuleId id) +{ + QString name = getModuleName(id); + name = name.toLower().replace(' ', '_'); + return name; +} + +std::function<Module*()> ModulesList::getFactoryMethod(ModuleId id) { for (int i = 0; i < modulesInfo.count(); i++) { if (modulesInfo[i].getId() == id) - return modulesInfo[i].getFactory(); + return modulesInfo[i].getFactoryMethod(); } return []() { return nullptr; }; } -std::function<Module*()> ModulesList::findFactoryByModuleName( - const QString& name) +std::function<Module*()> ModulesList::getFactoryMethod(const QString& name) { for (int i = 0; i < modulesInfo.count(); i++) { - if (modulesInfo[i].getModuleName() == name) - return modulesInfo[i].getFactory(); + if (modulesInfo[i].getModuleName().toLower().replace(' ', '_') == + name.toLower().replace(' ', '_')) + return modulesInfo[i].getFactoryMethod(); } return []() { return nullptr; }; } @@ -214,3 +255,13 @@ QList<QString> ModulesList::getModulesNamesList() } QList<ModuleInfo> ModulesList::getModulesInfo() { return modulesInfo; } + +Module* ModulesList::instantiateModule(ModuleId id) +{ + return getFactoryMethod(id)(); +} + +Module* ModulesList::instantiateModule(const QString& name) +{ + return getFactoryMethod(name)(); +} diff --git a/src/shared/Modules/ModulesList.h b/src/shared/Modules/ModulesList.h index c948f09a..65ef7099 100644 --- a/src/shared/Modules/ModulesList.h +++ b/src/shared/Modules/ModulesList.h @@ -25,21 +25,24 @@ class ModulesList { public: - ModulesList(); - - void createModuleList(); + static ModulesList &getInstance(); + ModulesList(const ModulesList &) = delete; + ModulesList &operator=(const ModulesList &) = delete; - bool containsId(ModuleId id); - void addModuleInfo(const ModuleInfo &info); + QString getModuleName(ModuleId id); + QString getXmlName(ModuleId id); - QString getModuleName(ModuleId id) const; - std::function<Module *()> getFactory(ModuleId id) const; + std::function<Module *()> getFactoryMethod(ModuleId id); + std::function<Module *()> getFactoryMethod(const QString &name); - std::function<Module *()> findFactoryByModuleName(const QString &name); QList<QString> getModulesNamesList(); - + bool getModuleId(QString name, ModuleId &id); QList<ModuleInfo> getModulesInfo(); + Module *instantiateModule(ModuleId id); + Module *instantiateModule(const QString &name); + private: + ModulesList(); QList<ModuleInfo> modulesInfo; }; diff --git a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp index a9196fd9..aac94aa2 100644 --- a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp +++ b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp @@ -18,16 +18,23 @@ #include "OrientationVisualizer.h" -OrientationVisualizer::OrientationVisualizer(QWidget *parent) - : DefaultModule(parent) +#include <QBoxLayout> +#include <Qt3DExtras/QConeMesh> +#include <Qt3DExtras/QPhongMaterial> +#include <Qt3DExtras/Qt3DWindow> +#include <Qt3DRender/QAttribute> +#include <Qt3DRender/QBuffer> +#include <Qt3DRender/QCamera> + +OrientationVisualizer::OrientationVisualizer() + : Module(ModuleId::ORIENTATION_VISUALIZER) { setupUi(); - defaultContextMenuSetup(); updateOrientation(0, 0, 0, 1); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString("Mav/ROCKET_FLIGHT_TM"), this, [this](const Message &message, const Filter &filter) { @@ -36,7 +43,7 @@ OrientationVisualizer::OrientationVisualizer(QWidget *parent) message.getField("nas_qz").getDouble(), message.getField("nas_qw").getDouble()); }); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString("Mav/PAYLOAD_FLIGHT_TM"), this, [this](const Message &message, const Filter &filter) { @@ -47,16 +54,6 @@ OrientationVisualizer::OrientationVisualizer(QWidget *parent) }); } -QWidget *OrientationVisualizer::toWidget() { return this; } - -XmlObject OrientationVisualizer::toXmlObject() -{ - XmlObject obj(getName(ModuleId::ORIENTATION_VISUALIZER)); - return obj; -} - -void OrientationVisualizer::fromXmlObject(const XmlObject &xmlObject) {} - void OrientationVisualizer::updateOrientation(double qx, double qy, double qz, double qw) { diff --git a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h index a24455b1..e95a7fa5 100644 --- a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h +++ b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h @@ -18,42 +18,20 @@ #pragma once -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <Qt3DRender/qpointlight.h> #include <QSizePolicy> #include <Qt3DCore/QAspectEngine> #include <Qt3DCore/QEntity> #include <Qt3DCore/QTransform> -#include <Qt3DExtras/QConeMesh> -#include <Qt3DExtras/QCuboidMesh> -#include <Qt3DExtras/QFirstPersonCameraController> -#include <Qt3DExtras/QForwardRenderer> -#include <Qt3DExtras/QOrbitCameraController> -#include <Qt3DExtras/QPhongMaterial> -#include <Qt3DExtras/QSphereMesh> -#include <Qt3DExtras/QTorusMesh> -#include <Qt3DExtras/Qt3DWindow> -#include <Qt3DInput/QInputAspect> -#include <Qt3DRender/QAttribute> -#include <Qt3DRender/QBuffer> -#include <Qt3DRender/QCamera> -#include <Qt3DRender/QCameraLens> -#include <Qt3DRender/QGeometry> -#include <Qt3DRender/QGeometryRenderer> -#include <Qt3DRender/QRenderAspect> -class OrientationVisualizer : public DefaultModule +class OrientationVisualizer : public Module { Q_OBJECT public: - explicit OrientationVisualizer(QWidget *parent = nullptr); - - QWidget *toWidget() override; - - XmlObject toXmlObject() override; - void fromXmlObject(const XmlObject &xmlObject) override; + OrientationVisualizer(); private: QLabel *rollLabel, *pitchLabel, *yawLabel; diff --git a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp index 4d90ae27..28a67fd8 100644 --- a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp +++ b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp @@ -25,23 +25,23 @@ #include "Modules/SkywardHubStrings.h" #include "ui_OutgoingMessagesViewerModule.h" -OutgoingMessagesViewerModule::OutgoingMessagesViewerModule(QWidget* parent) - : DefaultModule(parent), ui(new Ui::OutgoingMessagesViewerModule) +OutgoingMessagesViewerModule::OutgoingMessagesViewerModule() + : Module(ModuleId::OUTGOING_MESSAGES_VIEWER), + ui(new Ui::OutgoingMessagesViewerModule) { ui->setupUi(this); - defaultContextMenuSetup(); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(SkywardHubStrings::logCommandsTopic), this, [this](const Message& message, const Filter& filter) { addMsgSent(message); }); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(SkywardHubStrings::mavlink_received_msg_ACK_topic), this, [this](const Message& message, const Filter& filter) { handleAck(message); }); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(SkywardHubStrings::mavlink_received_msg_NACK_topic), this, [this](const Message& message, const Filter& filter) @@ -50,18 +50,6 @@ OutgoingMessagesViewerModule::OutgoingMessagesViewerModule(QWidget* parent) OutgoingMessagesViewerModule::~OutgoingMessagesViewerModule() { delete ui; } -QWidget* OutgoingMessagesViewerModule::toWidget() { return this; } - -XmlObject OutgoingMessagesViewerModule::toXmlObject() -{ - return XmlObject(getName(ModuleId::OUTCOMINGMESSAGEVIEWER)); -} - -void OutgoingMessagesViewerModule::fromXmlObject(const XmlObject& xmlObject) -{ - Q_UNUSED(xmlObject); -} - void OutgoingMessagesViewerModule::addMsgSent(const Message& msg) { int row = updateVerticalHeaders(msg); diff --git a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h index 4fe8f8f9..c5159212 100644 --- a/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h +++ b/src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h @@ -19,8 +19,7 @@ #pragma once #include <Core/Message/Message.h> -#include <Core/Module/Module.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QWidget> @@ -48,19 +47,14 @@ namespace Ui class OutgoingMessagesViewerModule; } -class OutgoingMessagesViewerModule : public DefaultModule +class OutgoingMessagesViewerModule : public Module { Q_OBJECT public: - explicit OutgoingMessagesViewerModule(QWidget* parent = nullptr); + OutgoingMessagesViewerModule(); ~OutgoingMessagesViewerModule(); - QWidget* toWidget() override; - - XmlObject toXmlObject() override; - void fromXmlObject(const XmlObject& xmlObject) override; - void addMsgSent(const Message& msg); void handleAck(const Message& ack); void handleNack(const Message& nack); diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp index 8202a497..0653564e 100644 --- a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp +++ b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp @@ -21,23 +21,21 @@ #include <Components/FilterSelector/FilterSelector.h> #include <Core/MessageBroker/MessageBroker.h> -PayloadStateViewerModule::PayloadStateViewerModule(QWidget* parent) - : DefaultModule(parent) +PayloadStateViewerModule::PayloadStateViewerModule() + : Module(ModuleId::PAYLOAD_STATE_VIEWER) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } PayloadStateViewerModule::~PayloadStateViewerModule() { - getCore()->getMessageBroker()->unsubscribe(filter, this); + MessageBroker::getInstance().unsubscribe(filter, this); } -QWidget* PayloadStateViewerModule::toWidget() { return this; } - XmlObject PayloadStateViewerModule::toXmlObject() { - XmlObject obj(getName(ModuleId::PAYLOADSTATEVIEWER)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("filter", filter.toString()); @@ -46,11 +44,8 @@ XmlObject PayloadStateViewerModule::toXmlObject() void PayloadStateViewerModule::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::PAYLOADSTATEVIEWER)) - { - auto filter = Filter::fromString(xmlObject.getAttribute("filter")); - setFilter(filter); - } + auto filter = Filter::fromString(xmlObject.getAttribute("filter")); + setFilter(filter); } void PayloadStateViewerModule::setupUi() @@ -71,13 +66,13 @@ void PayloadStateViewerModule::setupUi() setLayout(outerLayout); } -void PayloadStateViewerModule::addCustomActionsToMenu() +void PayloadStateViewerModule::customContextMenuActionSetup() { QAction* action = new QAction("Choose topic and field"); connect(action, &QAction::triggered, this, &PayloadStateViewerModule::onConfigureClicked); - addActionToMenu(action); + customContextMenuActions.append(action); } void PayloadStateViewerModule::onConfigureClicked() @@ -88,8 +83,8 @@ void PayloadStateViewerModule::onConfigureClicked() void PayloadStateViewerModule::setFilter(const Filter& newFilter) { - getCore()->getMessageBroker()->unsubscribe(filter, this); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().unsubscribe(filter, this); + MessageBroker::getInstance().subscribe( newFilter, this, [this](const Message& message, const Filter& filter) { onMsgReceived(message); }); diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h index 790387f9..5c2b81af 100644 --- a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h +++ b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h @@ -20,29 +20,27 @@ #include <Core/Message/Filter.h> #include <Core/Message/Message.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QLabel> #include <QWidget> #include "PayloadStatesList.h" -class PayloadStateViewerModule : public DefaultModule +class PayloadStateViewerModule : public Module { Q_OBJECT public: - explicit PayloadStateViewerModule(QWidget* parent = nullptr); + PayloadStateViewerModule(); ~PayloadStateViewerModule(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; private: void setupUi(); - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); void onConfigureClicked(); void setFilter(const Filter& filter); void onMsgReceived(const Message& msg); diff --git a/src/shared/Modules/SkywardHubStrings.h b/src/shared/Modules/SkywardHubStrings.h index 4c8ff5b1..0575fc49 100644 --- a/src/shared/Modules/SkywardHubStrings.h +++ b/src/shared/Modules/SkywardHubStrings.h @@ -29,13 +29,12 @@ static const QString defaultConfigurationFolder = "/" + "SkywardHub"; static const QString defaultSettingsFilePath = defaultConfigurationFolder + "/" + "settings.xml"; -static const QString defaultPrefabsFolderName = "Profiles"; static const QString defaultLogsFolder = defaultConfigurationFolder + "/" + "Logs"; static const QString defaultStreamFile = defaultConfigurationFolder + "/" + "StreamFile.txt"; static const QString defaultPrefabsFolder = - defaultConfigurationFolder + "/" + defaultPrefabsFolderName + "/"; + defaultConfigurationFolder + "/" + "Profiles" + "/"; static const QString defaultConfigurationFileName = "default.xml"; static const QString defaultConfigurationIconPath = defaultConfigurationFolder + "/" + "defaultConfigIcon.svg"; @@ -44,9 +43,9 @@ static const QString defaultConfigurationIconPath = static const QString skywardHubInitFileTag = "LoadOnLaunch"; static const QString settingsObjectName = "Settings"; static const QString configurationNameAttribute = "name"; -static const QString configurationNameValue = "Configuration"; -static const QString configurationIconPathAttribute = "ConfigurationIcon"; -static const QString configurationDescriptionAttribute = "Description"; +static const QString configurationNameValue = "configuration"; +static const QString configurationIconPathAttribute = "configuration_icon"; +static const QString configurationDescriptionAttribute = "description"; // Output Messages static const QString settingsSavedCorrectlyMsg = "Settings saved"; diff --git a/src/shared/Modules/Splitter/Splitter.cpp b/src/shared/Modules/Splitter/Splitter.cpp index 3dfa5ed6..a93c2002 100644 --- a/src/shared/Modules/Splitter/Splitter.cpp +++ b/src/shared/Modules/Splitter/Splitter.cpp @@ -18,29 +18,19 @@ #include "Splitter.h" -#include <Core/ModulesManager/ModulesManager.h> +#include <Modules/ModulesList.h> -#include <QDebug> -#include <QLabel> +#include <QBoxLayout> -Splitter::Splitter(Qt::Orientation orientation, QWidget* parent) - : DefaultModule(parent) +Splitter::Splitter(Qt::Orientation orientation, ModuleId id) : Module(id) { setupUi(orientation); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } -QWidget* Splitter::toWidget() { return this; } - XmlObject Splitter::toXmlObject() { - XmlObject obj(getName(ModuleId::SPLITTER)); - - // Orientation - if (splitter->orientation() == Qt::Horizontal) - obj.addAttribute("orientation", "horizontal"); - else - obj.addAttribute("orientation", "vertical"); + auto obj = Module::toXmlObject(); QString sizes; for (int i = 0; i < splitter->sizes().size(); i++) @@ -55,11 +45,8 @@ XmlObject Splitter::toXmlObject() for (int i = 0; i < splitter->count(); i++) { - DefaultModule* module = - qobject_cast<DefaultModule*>(splitter->widget(i)); - - if (module) - obj.addChild(module->toXmlObject()); + Module* module = qobject_cast<Module*>(splitter->widget(i)); + obj.addChild(module->toXmlObject()); } return obj; @@ -67,11 +54,6 @@ XmlObject Splitter::toXmlObject() void Splitter::fromXmlObject(const XmlObject& obj) { - QString orientation = obj.getAttribute("orientation"); - if (orientation == "vertical") - splitter->setOrientation(Qt::Vertical); - else - splitter->setOrientation(Qt::Horizontal); QList<int> intSizes; for (QString size : obj.getAttribute("sizes").split(",")) intSizes.append(size.toInt()); @@ -79,16 +61,18 @@ void Splitter::fromXmlObject(const XmlObject& obj) for (int i = 0; i < obj.childCount(); i++) { XmlObject xmlChild = obj.childAt(i); - Module* module = - getCore()->getModulesManager()->instantiateModuleByName( + Module* module = ModulesList::getInstance().instantiateModule( xmlChild.getObjectName()); if (module) + { module->fromXmlObject(xmlChild); + addModule(module, i); + } else - module = getCore()->getModulesManager()->instantiateDefaultModule(); - - addModule(module, i); + { + // TODO: what should we do? + } } splitter->setSizes(intSizes); @@ -96,27 +80,66 @@ void Splitter::fromXmlObject(const XmlObject& obj) void Splitter::addModule(Module* module) { - int count = splitter->count(); - addModule(module, count); + addModule(module, splitter->count()); } void Splitter::addModule(Module* module, int position) { - connect(module->getEventHandler(), &EventHandler::replaceMeWith, this, - &Splitter::replace); - connect(module->getEventHandler(), &EventHandler::contextMenuRequest, this, - &Splitter::onSkywardHubContextMenuRequested); + connect(module, &Module::replaceMe, this, &Splitter::replaceChild); + connect(module, &Module::closeMe, this, &Splitter::closeChild); - if (position < splitter->count()) + // Replace the module if there is already one + if (position >= 0 && position < splitter->count()) delete splitter->widget(position); splitter->insertWidget(position, qobject_cast<QWidget*>(module)); } -void Splitter::replace(Module* oldModule, Module* newModule) +void Splitter::replaceChild(Module* oldModule, Module* newModule) { - if (oldModule && newModule) - addModule(newModule, splitter->indexOf(oldModule->toWidget())); + // Check if the modules are valid + if (!oldModule || !newModule) + return; + + // Check if we are trying to replace a module with itself + if (oldModule == newModule) + return; + + auto index = splitter->indexOf(oldModule); + + // Check if the old module is a child + if (index == -1) + return; + + addModule(newModule, index); +} + +void Splitter::closeChild(Module* module) +{ + // Check if the given module is a child + if (splitter->indexOf(module) == -1) + return; + + // If there is only one child, then we have to delete the whole splitter + if (splitter->count() == 1) + { + emit closeMe(this); + return; + } + + // If there is only two children, then the remaining one will replace the + // whole splitter + if (splitter->count() == 2) + { + Module* currentChild = (Module*)splitter->widget(0); + + // REmove the children parent. This is essential otherwise when the + // splitter will be deleted, also the child will be + currentChild->setParent(nullptr); + + // Replace the splitter with the only left children + emit replaceMe(this, currentChild); + } } Qt::Orientation Splitter::getOrientation() const @@ -132,27 +155,31 @@ void Splitter::setOrientation(Qt::Orientation orientation) void Splitter::swapOrientation() { if (getOrientation() == Qt::Horizontal) + { + id = ModuleId::VERTICAL_SPLITTER; splitter->setOrientation(Qt::Vertical); + } else + { + id = ModuleId::HORIZONTAL_SPLITTER; splitter->setOrientation(Qt::Horizontal); + } } -void Splitter::addCustomActionsToMenu() +void Splitter::customContextMenuActionSetup() { - showMenuActionsInSeparatedMenu("Splitter"); QAction* split = new QAction("Split"); connect(split, &QAction::triggered, this, [this]() { - addModule( - getCore()->getModulesManager()->instantiateDefaultModule()); + addModule(ModulesList::getInstance().instantiateModule( + ModuleId::EMPTY)); }); + customContextMenuActions.append(split); QAction* changeOrientation = new QAction("Swap Orientation"); connect(changeOrientation, &QAction::triggered, this, [this]() { this->swapOrientation(); }); - - addActionToMenu(split); - addActionToMenu(changeOrientation); + customContextMenuActions.append(changeOrientation); } void Splitter::setupUi(Qt::Orientation orientation) @@ -167,8 +194,8 @@ void Splitter::setupUi(Qt::Orientation orientation) outerLayout->addWidget(splitter); // By default add two default modules - addModule(getCore()->getModulesManager()->instantiateDefaultModule()); - addModule(getCore()->getModulesManager()->instantiateDefaultModule()); + addModule(ModulesList::getInstance().instantiateModule(ModuleId::EMPTY)); + addModule(ModulesList::getInstance().instantiateModule(ModuleId::EMPTY)); setLayout(outerLayout); } diff --git a/src/shared/Modules/Splitter/Splitter.h b/src/shared/Modules/Splitter/Splitter.h index 02d75550..0fbb477d 100644 --- a/src/shared/Modules/Splitter/Splitter.h +++ b/src/shared/Modules/Splitter/Splitter.h @@ -18,21 +18,17 @@ #pragma once -#include <Core/Module/Module.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QSplitter> #include <QWidget> -class Splitter : public DefaultModule +class Splitter : public Module { Q_OBJECT public: - explicit Splitter(Qt::Orientation orientation = Qt::Horizontal, - QWidget *parent = nullptr); - - QWidget *toWidget() override; + explicit Splitter(Qt::Orientation orientation, ModuleId id); XmlObject toXmlObject() override; void fromXmlObject(const XmlObject &obj) override; @@ -45,10 +41,11 @@ public: void swapOrientation(); public slots: - void replace(Module *oldModule, Module *newModule); + void replaceChild(Module *oldModule, Module *newModule); + void closeChild(Module *module); private: - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); void setupUi(Qt::Orientation orientation = Qt::Horizontal); QSplitter *splitter; diff --git a/src/shared/Modules/Tabs/TabsModule.cpp b/src/shared/Modules/Tabs/TabsModule.cpp index 9f5e1535..53d3c3c2 100644 --- a/src/shared/Modules/Tabs/TabsModule.cpp +++ b/src/shared/Modules/Tabs/TabsModule.cpp @@ -18,16 +18,16 @@ #include "TabsModule.h" -#include <Core/ModulesManager/ModulesManager.h> +#include <Modules/ModulesList.h> #include <QBoxLayout> #include <QDebug> #include <QLabel> -TabsModule::TabsModule(QWidget* parent) : DefaultModule{parent} +TabsModule::TabsModule() : Module(ModuleId::TABS) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); QObject::connect(tabNames, &QListWidget::currentRowChanged, tabContents, &QStackedWidget::setCurrentIndex); @@ -35,28 +35,17 @@ TabsModule::TabsModule(QWidget* parent) : DefaultModule{parent} &TabsModule::onDoubleClickedItem); // Automatically add first tab - addTab(generateUniqueTabName(), SkywardHubCoreProxy::getCore() - ->getModulesManager() - ->instantiateDefaultModule()); -} - -TabsModule::~TabsModule() -{ - while (!contentModules.isEmpty()) - { - delete contentModules.takeFirst(); - } + addTab(generateUniqueTabName(), + ModulesList::getInstance().instantiateModule(ModuleId::EMPTY)); } -QWidget* TabsModule::toWidget() { return this; } - XmlObject TabsModule::toXmlObject() { - XmlObject obj(getName(ModuleId::TABS)); + XmlObject obj = Module::toXmlObject(); for (int i = 0; i != contentModules.size(); i++) { - XmlObject tab("Tab"); + XmlObject tab("tab"); tab.addAttribute("name", tabNames->item(i)->text()); tab.addChild(contentModules.at(i)->toXmlObject()); obj.addChild(tab); @@ -67,7 +56,7 @@ XmlObject TabsModule::toXmlObject() void TabsModule::fromXmlObject(const XmlObject& xmlObject) { - /* Discard previous content */ + // Discard previous content tabNames->clear(); for (int i = contentModules.size() - 1; i >= 0; i--) { @@ -77,113 +66,108 @@ void TabsModule::fromXmlObject(const XmlObject& xmlObject) delete module; } - totalTabs = 0; for (int i = 0; i < xmlObject.childCount(); ++i) { XmlObject tabNode = xmlObject.childAt(i); - if (tabNode.getObjectName() != "Tab" || tabNode.childCount() == 0) + if (tabNode.getObjectName() != "tab" || tabNode.childCount() == 0) continue; XmlObject xmlChild = tabNode.childAt(0); - Module* module = - getCore()->getModulesManager()->instantiateModuleByName( - xmlChild.getObjectName()); + Module* module = ModulesList::getInstance().instantiateModule( + xmlChild.getObjectName()); if (module != nullptr) { module->fromXmlObject(xmlChild); + addTab(tabNode.getAttribute("name", generateUniqueTabName()), + module); } else { - module = getCore()->getModulesManager()->instantiateDefaultModule(); + // TODO: what should we do? } - - addTab(tabNode.getAttribute("name", generateUniqueTabName()), module); } + // If the tabs are left empty, add a single tab with an empty module if (contentModules.size() == 0) addTab(generateUniqueTabName(), - getCore()->getModulesManager()->instantiateDefaultModule()); + ModulesList::getInstance().instantiateModule(ModuleId::EMPTY)); tabNames->setCurrentItem(tabNames->item(0)); } void TabsModule::addTab(const QString& tabName, Module* module) { - connect(module->getEventHandler(), &EventHandler::replaceMeWith, this, - &TabsModule::replaceTabContent); - connect(module->getEventHandler(), &EventHandler::contextMenuRequest, this, - &TabsModule::onSkywardHubContextMenuRequested); - connect(module->getEventHandler(), &EventHandler::beforeDelete, this, - &TabsModule::onTabDeleted); + connect(module, &Module::replaceMe, this, &TabsModule::replaceTab); + connect(module, &Module::closeMe, this, &TabsModule::closeTab); auto* listItem = new QListWidgetItem(); listItem->setText(tabName); listItem->setTextAlignment(Qt::AlignCenter); tabNames->addItem(listItem); - tabContents->addWidget(module->toWidget()); + tabContents->addWidget(module); contentModules.append(module); - /* We set the correct tabName after the widget is added */ + // We set the correct tabName after the widget is added tabNames->setCurrentItem(listItem); } QString TabsModule::generateUniqueTabName() { - return QString("Tab #%1").arg(++totalTabs); + return QString("Tab %1").arg(tabNames->count()); } -void TabsModule::replaceTabContent(Module* from, Module* to) +void TabsModule::replaceTab(Module* oldModule, Module* newModule) { - int index = contentModules.indexOf(from); + // Check if the modules are valid + if (!oldModule || !newModule) + return; + + // Check if we are trying to replace a module with itself + if (oldModule == newModule) + return; + + int index = contentModules.indexOf(oldModule); + // Check if the old module is a child if (index == -1) return; // Can replace only current tab tabNames->setCurrentItem(tabNames->item(index)); - contentModules.replace(index, to); - tabContents->insertWidget(index, to->toWidget()); - tabContents->removeWidget(from->toWidget()); - tabContents->setCurrentWidget(to->toWidget()); - - // Connect the module to the slots - connect(to->getEventHandler(), &EventHandler::replaceMeWith, this, - &TabsModule::replaceTabContent); - connect(to->getEventHandler(), &EventHandler::contextMenuRequest, this, - &TabsModule::onSkywardHubContextMenuRequested); - connect(to->getEventHandler(), &EventHandler::beforeDelete, this, - &TabsModule::onTabDeleted); - - // forces UI update + contentModules.replace(index, newModule); + tabContents->insertWidget(index, newModule); + tabContents->removeWidget(oldModule); + tabContents->setCurrentWidget(newModule); tabContents->update(); - delete from; + connect(newModule, &Module::replaceMe, this, &TabsModule::replaceTab); + connect(newModule, &Module::closeMe, this, &TabsModule::closeTab); + + delete oldModule; } -void TabsModule::onTabDeleted(Module* module) +void TabsModule::closeTab(Module* module) { int index = contentModules.indexOf(module); + // Check if the given module is a child if (index == -1) return; + // If there is only one child, then close the entire tabs module + if (contentModules.count() == 1) + { + emit closeMe(this); + return; + } + contentModules.removeAt(index); tabContents->removeWidget(tabContents->widget(index)); tabNames->takeItem(index); - - if (contentModules.isEmpty()) - { - emit getEventHandler()->replaceMeWith( - this, getCore()->getModulesManager()->instantiateDefaultModule()); - this->deleteLater(); - } - else - { - tabNames->setCurrentItem(tabNames->item(index == 0 ? 0 : index - 1)); - } + tabNames->setCurrentItem(tabNames->item(index == 0 ? 0 : index - 1)); } void TabsModule::onDoubleClickedItem(QListWidgetItem* item) @@ -193,28 +177,27 @@ void TabsModule::onDoubleClickedItem(QListWidgetItem* item) tabNames->editItem(item); } -void TabsModule::addCustomActionsToMenu() +void TabsModule::customContextMenuActionSetup() { - auto* newTab = new QAction("New Tab"); - auto* deleteTab = new QAction("Delete Tab"); - auto* renameTab = new QAction("Rename Tab"); - + auto* newTab = new QAction("New Tab"); connect(newTab, &QAction::triggered, this, &TabsModule::onMenuNewTabClick); + customContextMenuActions.append(newTab); + + auto* deleteTab = new QAction("Delete Tab"); connect(deleteTab, &QAction::triggered, this, &TabsModule::onMenuDeleteTabClick); + customContextMenuActions.append(deleteTab); + + auto* renameTab = new QAction("Rename Tab"); connect(renameTab, &QAction::triggered, this, &TabsModule::onMenuRenameTabClick); - - showMenuActionsInSeparatedMenu("Tabs"); - addActionToMenu(newTab); - addActionToMenu(deleteTab); - addActionToMenu(renameTab); + customContextMenuActions.append(renameTab); } void TabsModule::onMenuNewTabClick() { addTab(generateUniqueTabName(), - getCore()->getModulesManager()->instantiateDefaultModule()); + ModulesList::getInstance().instantiateModule(ModuleId::EMPTY)); } void TabsModule::onMenuDeleteTabClick() diff --git a/src/shared/Modules/Tabs/TabsModule.h b/src/shared/Modules/Tabs/TabsModule.h index 1c25b002..d06ba6c8 100644 --- a/src/shared/Modules/Tabs/TabsModule.h +++ b/src/shared/Modules/Tabs/TabsModule.h @@ -18,31 +18,27 @@ #pragma once +#include <Modules/Module.h> + #include <QListWidget> #include <QStackedWidget> #include <QWidget> -#include "Modules/DefaultModule/DefaultModule.h" - -class TabsModule : public DefaultModule +class TabsModule : public Module { Q_OBJECT + public: - TabsModule(QWidget* parent = nullptr); - ~TabsModule(); + TabsModule(); void addTab(const QString& tabName, Module* module); - QString generateUniqueTabName(); - - void addCustomActionsToMenu() override; - QWidget* toWidget() override; XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; -protected slots: - void onTabDeleted(Module* module); - void replaceTabContent(Module* from, Module* to); +private slots: + void replaceTab(Module* oldModule, Module* newModule); + void closeTab(Module* module); void onDoubleClickedItem(QListWidgetItem* item); void onMenuNewTabClick(); @@ -50,12 +46,12 @@ protected slots: void onMenuRenameTabClick(); private: + void setupUi(); + void customContextMenuActionSetup(); + + QString generateUniqueTabName(); + QListWidget* tabNames; QStackedWidget* tabContents; QList<Module*> contentModules; - - /* number of tabs ever created (used for names) */ - unsigned totalTabs = 0; - - void setupUi(); }; diff --git a/src/shared/Modules/Test/TestModule.cpp b/src/shared/Modules/Test/TestModule.cpp index 7bc640b6..fc71da85 100644 --- a/src/shared/Modules/Test/TestModule.cpp +++ b/src/shared/Modules/Test/TestModule.cpp @@ -19,15 +19,12 @@ #include "TestModule.h" #include <Core/MessageBroker/MessageBroker.h> -#include <Core/ModulesManager/ModulesManager.h> #include "ui_TestModule.h" -TestModule::TestModule(QWidget* parent) - : DefaultModule(parent), ui(new Ui::TestModule) +TestModule::TestModule() : Module(ModuleId::BROKER_TEST), ui(new Ui::TestModule) { ui->setupUi(this); - defaultContextMenuSetup(); maxChar = ui->maxChar_spinBox->value(); connect(ui->maxChar_spinBox, SIGNAL(valueChanged(int)), this, @@ -36,17 +33,16 @@ TestModule::TestModule(QWidget* parent) TestModule::~TestModule() { delete ui; } -QWidget* TestModule::toWidget() { return this; } - -XmlObject TestModule::toXmlObject() -{ - return XmlObject(getName(ModuleId::BROKERTEST)); -} - -void TestModule::fromXmlObject(const XmlObject& xmlObject) -{ - Q_UNUSED(xmlObject); -} +// TODO: get subscriptions from xml +// XmlObject TestModule::toXmlObject() +// { +// XmlObject obj = Module::toXmlObject(); +// return obj +// } +// void TestModule::fromXmlObject(const XmlObject& xmlObject) +// { +// Q_UNUSED(xmlObject); +// } void TestModule::on_publish_button_clicked() { @@ -58,12 +54,12 @@ void TestModule::on_publish_button_clicked() auto timestampField = Field((uint64_t)QTime::currentTime().msecsSinceStartOfDay()); message.setField("timestamp", timestampField); - getCore()->getMessageBroker()->publish(message); + MessageBroker::getInstance().publish(message); } void TestModule::on_subscribe_button_clicked() { - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString(ui->subscribe_lineEdit->text().trimmed()), this, [this](const Message& message, const Filter& filter) { @@ -78,7 +74,7 @@ void TestModule::on_subscribe_button_clicked() void TestModule::on_unsubscribe_button_clicked() { - getCore()->getMessageBroker()->unsubscribe( + MessageBroker::getInstance().unsubscribe( Filter::fromString(ui->subscribe_lineEdit->text().trimmed()), this); } diff --git a/src/shared/Modules/Test/TestModule.h b/src/shared/Modules/Test/TestModule.h index 9a67f6d0..499c719c 100644 --- a/src/shared/Modules/Test/TestModule.h +++ b/src/shared/Modules/Test/TestModule.h @@ -18,27 +18,23 @@ #pragma once -#include <QWidget> +#include <Modules/Module.h> -#include "Modules/DefaultModule/DefaultModule.h" +#include <QWidget> namespace Ui { class TestModule; } -class TestModule : public DefaultModule +class TestModule : public Module { Q_OBJECT public: - explicit TestModule(QWidget *parent = nullptr); + TestModule(); ~TestModule(); - QWidget *toWidget() override; - XmlObject toXmlObject() override; - void fromXmlObject(const XmlObject &xmlObject) override; - private slots: void on_publish_button_clicked(); diff --git a/src/shared/Modules/TimerController/TimerControllerModule.cpp b/src/shared/Modules/TimerController/TimerControllerModule.cpp index 573c0c29..cf278cea 100644 --- a/src/shared/Modules/TimerController/TimerControllerModule.cpp +++ b/src/shared/Modules/TimerController/TimerControllerModule.cpp @@ -23,11 +23,10 @@ #include "ui_TimerControllerModule.h" -TimerControllerModule::TimerControllerModule(QWidget *parent) - : DefaultModule(parent), ui(new Ui::TimerControllerModule) +TimerControllerModule::TimerControllerModule() + : Module(ModuleId::TIMER_CONTROLLER), ui(new Ui::TimerControllerModule) { ui->setupUi(this); - defaultContextMenuSetup(); connect(ui->setTimer_pushButton, &QPushButton::clicked, this, &TimerControllerModule::onSetTimerClicked); @@ -47,18 +46,6 @@ TimerControllerModule::TimerControllerModule(QWidget *parent) TimerControllerModule::~TimerControllerModule() { delete ui; } -QWidget *TimerControllerModule::toWidget() { return this; } - -XmlObject TimerControllerModule::toXmlObject() -{ - return XmlObject(getName(ModuleId::TIMER_CONTROLLER)); -} - -void TimerControllerModule::fromXmlObject(const XmlObject &xmlObject) -{ - Q_UNUSED(xmlObject); -} - void TimerControllerModule::onSetTimerClicked() { initCurrentTime(); } void TimerControllerModule::onStartTimerClicked() diff --git a/src/shared/Modules/TimerController/TimerControllerModule.h b/src/shared/Modules/TimerController/TimerControllerModule.h index 7e79a8c7..58b9ba4a 100644 --- a/src/shared/Modules/TimerController/TimerControllerModule.h +++ b/src/shared/Modules/TimerController/TimerControllerModule.h @@ -18,29 +18,24 @@ #pragma once +#include <Modules/Module.h> + #include <QTime> #include <QTimer> -#include "Modules/DefaultModule/DefaultModule.h" - namespace Ui { class TimerControllerModule; } -class TimerControllerModule : public DefaultModule +class TimerControllerModule : public Module { Q_OBJECT public: - explicit TimerControllerModule(QWidget *parent = nullptr); + TimerControllerModule(); ~TimerControllerModule(); - QWidget *toWidget() override; - - XmlObject toXmlObject() override; - void fromXmlObject(const XmlObject &xmlObject) override; - protected: void onSetTimerClicked(); void onStartTimerClicked(); diff --git a/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.cpp b/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.cpp index 1bea3e2b..33fa9d0a 100644 --- a/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.cpp +++ b/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.cpp @@ -20,17 +20,20 @@ #include <Core/MessageBroker/MessageBroker.h> +#include <QAction> + #include "Core/Message/Filter.h" #include "ValuesViewerConfigPanel.h" #include "ui_ValuesConverterViewerModule.h" -ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent) - : DefaultModule(parent), ui(new Ui::ValuesConverterViewerModule) +ValuesConverterViewerModule::ValuesConverterViewerModule() + : Module(ModuleId::VALUES_CONVERTER_VIEWER), + ui(new Ui::ValuesConverterViewerModule) { ui->setupUi(this); - defaultContextMenuSetup(); + customContextMenuActionSetup(); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().subscribe( Filter::fromString("*"), this, [this](const Message& message, const Filter& filter) { onMsgReceived(message); }); @@ -39,15 +42,13 @@ ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent) ValuesConverterViewerModule::~ValuesConverterViewerModule() { clearLabels(); - getCore()->getMessageBroker()->unsubscribe(Filter::fromString("*"), this); + MessageBroker::getInstance().unsubscribe(Filter::fromString("*"), this); delete ui; } -QWidget* ValuesConverterViewerModule::toWidget() { return this; } - XmlObject ValuesConverterViewerModule::toXmlObject() { - XmlObject obj(getName(ModuleId::VALUESCONVERTERVIEWER)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("Columns", QString::number(columns)); @@ -60,26 +61,22 @@ XmlObject ValuesConverterViewerModule::toXmlObject() void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::VALUESCONVERTERVIEWER)) + int col; + if (xmlObject.getAttribute("Columns", col)) { + columns = col; + } - int col; - if (xmlObject.getAttribute("Columns", col)) - { - columns = col; - } - - for (int i = 0; i < xmlObject.childCount(); i++) + for (int i = 0; i < xmlObject.childCount(); i++) + { + XmlObject child = xmlObject.childAt(i); + ValueElement el; + if (el.fromXmlObject(child)) { - XmlObject child = xmlObject.childAt(i); - ValueElement el; - if (el.fromXmlObject(child)) - { - addRule(el); - } + addRule(el); } - createLabels(); } + createLabels(); } void ValuesConverterViewerModule::onConfigureClicked() @@ -101,12 +98,12 @@ void ValuesConverterViewerModule::onConfigurationSaved( createLabels(); } -void ValuesConverterViewerModule::addCustomActionsToMenu() +void ValuesConverterViewerModule::customContextMenuActionSetup() { QAction* configure = new QAction("Configure"); connect(configure, &QAction::triggered, this, &ValuesConverterViewerModule::onConfigureClicked); - addActionToMenu(configure); + customContextMenuActions.append(configure); } QLabel* ValuesConverterViewerModule::createView(const ValueElement& el) const @@ -209,7 +206,7 @@ void ValuesConverterViewerModule::onMsgReceived(const Message& msg) // auto valueField = Field(rules[i].getCurrentValue()); // convertedMsg.setField("value", valueField); // convertedMsg.setTopic(Topic(rules[i].getOutputTopic())); - // getCore()->getMessageBroker()->publish(convertedMsg); + // MessageBroker::getInstance().publish(convertedMsg); // } // } // } @@ -222,7 +219,7 @@ void ValuesConverterViewerModule::clearRules() { if (rules[i].getTopic() != "") { - getCore()->getMessageBroker()->unsubscribe( + MessageBroker::getInstance().unsubscribe( Filter::fromString(rules[i].getTopic()), this); } } diff --git a/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.h b/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.h index 1b573e08..ecd1614c 100644 --- a/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.h +++ b/src/shared/Modules/ValuesConverterViewer/ValuesConverterViewerModule.h @@ -18,11 +18,12 @@ #pragma once +#include <Modules/Module.h> + #include <QLabel> #include <QWidget> #include "Core/Message/Message.h" -#include "Modules/DefaultModule/DefaultModule.h" #include "ValueElement.h" class ValuesViewerConfigPanel; @@ -32,23 +33,22 @@ namespace Ui class ValuesConverterViewerModule; } -class ValuesConverterViewerModule : public DefaultModule +class ValuesConverterViewerModule : public Module { Q_OBJECT public: - explicit ValuesConverterViewerModule(QWidget* parent = nullptr); + ValuesConverterViewerModule(); ~ValuesConverterViewerModule(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; protected: + void customContextMenuActionSetup(); + void onConfigureClicked(); void onConfigurationSaved(ValuesViewerConfigPanel* sPanel); - void addCustomActionsToMenu() override; QLabel* createView(const ValueElement& el) const; void clearLabels(); void createLabels(); diff --git a/src/shared/Modules/ValvesViewer/ValvesViewer.cpp b/src/shared/Modules/ValvesViewer/ValvesViewer.cpp index 71169955..7b68f3a6 100644 --- a/src/shared/Modules/ValvesViewer/ValvesViewer.cpp +++ b/src/shared/Modules/ValvesViewer/ValvesViewer.cpp @@ -21,22 +21,20 @@ #include <Components/FilterSelector/FilterSelector.h> #include <Core/MessageBroker/MessageBroker.h> -ValvesViewer::ValvesViewer(QWidget* parent) : DefaultModule(parent) +ValvesViewer::ValvesViewer() : Module(ModuleId::VALVES_VIEWER) { setupUi(); - defaultContextMenuSetup(); + customContextMenuActionSetup(); } ValvesViewer::~ValvesViewer() { - getCore()->getMessageBroker()->unsubscribe(filter, this); + MessageBroker::getInstance().unsubscribe(filter, this); } -QWidget* ValvesViewer::toWidget() { return this; } - XmlObject ValvesViewer::toXmlObject() { - XmlObject obj(getName(ModuleId::VALVESVIEWER)); + XmlObject obj = Module::toXmlObject(); obj.addAttribute("filter", filter.toString()); @@ -45,11 +43,8 @@ XmlObject ValvesViewer::toXmlObject() void ValvesViewer::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::VALVESVIEWER)) - { - auto filter = Filter::fromString(xmlObject.getAttribute("filter")); - setFilter(filter); - } + auto filter = Filter::fromString(xmlObject.getAttribute("filter")); + setFilter(filter); } void ValvesViewer::setupUi() @@ -70,13 +65,13 @@ void ValvesViewer::setupUi() setLayout(outerLayout); } -void ValvesViewer::addCustomActionsToMenu() +void ValvesViewer::customContextMenuActionSetup() { QAction* action = new QAction("Choose topic and field"); connect(action, &QAction::triggered, this, &ValvesViewer::onConfigureClicked); - addActionToMenu(action); + customContextMenuActions.append(action); } void ValvesViewer::onConfigureClicked() @@ -87,8 +82,8 @@ void ValvesViewer::onConfigureClicked() void ValvesViewer::setFilter(const Filter& newFilter) { - getCore()->getMessageBroker()->unsubscribe(filter, this); - getCore()->getMessageBroker()->subscribe( + MessageBroker::getInstance().unsubscribe(filter, this); + MessageBroker::getInstance().subscribe( newFilter, this, [this](const Message& message, const Filter& filter) { onMsgReceived(message); }); diff --git a/src/shared/Modules/ValvesViewer/ValvesViewer.h b/src/shared/Modules/ValvesViewer/ValvesViewer.h index 89fa9e7a..5c0b4efd 100644 --- a/src/shared/Modules/ValvesViewer/ValvesViewer.h +++ b/src/shared/Modules/ValvesViewer/ValvesViewer.h @@ -20,29 +20,27 @@ #include <Core/Message/Filter.h> #include <Core/Message/Message.h> -#include <Modules/DefaultModule/DefaultModule.h> +#include <Modules/Module.h> #include <QLabel> #include <QWidget> #include "ValvesList.h" -class ValvesViewer : public DefaultModule +class ValvesViewer : public Module { Q_OBJECT public: - explicit ValvesViewer(QWidget* parent = nullptr); + ValvesViewer(); ~ValvesViewer(); - QWidget* toWidget() override; - XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; private: void setupUi(); - void addCustomActionsToMenu() override; + void customContextMenuActionSetup(); void onConfigureClicked(); void setFilter(const Filter& filter); void onMsgReceived(const Message& msg); -- GitLab