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