From 3e18af4a8ebbc75c10e9ad8706e37c695da16e04 Mon Sep 17 00:00:00 2001
From: Malte Laurin Matthey <malte.matthey@student.kit.edu>
Date: Wed, 18 Dec 2024 10:23:31 -0300
Subject: [PATCH] move UI logic out of TaskManager and LearnEnvironment, adjust
 resource location

---
 .devcontainer/devcontainer.json               |   2 +-
 .../src/learn_environment/CMakeLists.txt      |   2 +-
 .../folder_structure_constants.hpp            |  18 +++
 .../learn_environment/learn_environment.hpp   |  13 --
 .../learn_environment/subtask_item.hpp        |   1 +
 .../learn_environment/task_manager.hpp        |  38 +++---
 .../include/learn_environment/task_ui.hpp     |  50 ++++++-
 .../resource/learn_environment.ui             |   4 +-
 .../learn_environment/resource/resources.qrc  |  17 +++
 catkin_ws/src/learn_environment/resources.qrc |  17 ---
 .../src/learn_environment.cpp                 |  52 ++------
 .../learn_environment/src/subtask_item.cpp    |  14 +-
 .../learn_environment/src/task_manager.cpp    |  95 ++------------
 .../src/learn_environment/src/task_ui.cpp     | 124 ++++++++++++++++--
 14 files changed, 245 insertions(+), 202 deletions(-)
 create mode 100644 catkin_ws/src/learn_environment/resource/resources.qrc
 delete mode 100644 catkin_ws/src/learn_environment/resources.qrc

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 21caed4..6a760ec 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -34,7 +34,7 @@
 				"ms-vscode.cmake-tools",
 				"ms-python.python",
 
-				// remove to not show cell tags in editor
+				// remove VS Code plugin to not show cell tags in editor
 				"-ms-toolsai.vscode-jupyter-cell-tags"
 			]
 		}
diff --git a/catkin_ws/src/learn_environment/CMakeLists.txt b/catkin_ws/src/learn_environment/CMakeLists.txt
index 31ba730..bac241f 100644
--- a/catkin_ws/src/learn_environment/CMakeLists.txt
+++ b/catkin_ws/src/learn_environment/CMakeLists.txt
@@ -80,7 +80,7 @@ set(${PROJECT_NAME}_UIS
 )
 
 set(${PROJECT_NAME}_QRC
-  resources.qrc
+  resource/resources.qrc
 )
 
 # Create header from ui file (uic)
diff --git a/catkin_ws/src/learn_environment/include/learn_environment/folder_structure_constants.hpp b/catkin_ws/src/learn_environment/include/learn_environment/folder_structure_constants.hpp
index 2ab3417..73d8029 100644
--- a/catkin_ws/src/learn_environment/include/learn_environment/folder_structure_constants.hpp
+++ b/catkin_ws/src/learn_environment/include/learn_environment/folder_structure_constants.hpp
@@ -26,6 +26,24 @@ namespace FolderStructureConstants {
      */
     inline const QString RESET_ROBOT_SCRIPT_PATH = "/task_pool/reset_robot.py";
 
+    /**
+     * @var FolderStructureConstants::TASK_DEFINITIONS_PATH
+     * @brief Path to the task definitions json.
+     */
+    inline const QString TASK_DEFINITIONS_PATH = ":/task_pool/task_definitions.json";
+
+    /**
+     * @var FolderStructureConstants::TOPIC_DEFINITIONS_PATH
+     * @brief Path to the topic definitions json.
+     */
+    inline const QString TOPIC_DEFINITIONS_PATH = ":/task_pool/topic_definitions.json";
+
+    /**
+     * @var FolderStructureConstants::TOPIC_DEFINITIONS_PATH
+     * @brief Path to the difficulty definitions json.
+     */
+    inline const QString DIFFICULTY_LEVELS_DEFINITION_PATH = ":/task_pool/difficulty_levels.json";
+
     /**
      * @var FolderStructureConstants::SOLUTION_SCRIPTS_SOURCE_PATH
      * @brief Path to the solution scripts source directory.
diff --git a/catkin_ws/src/learn_environment/include/learn_environment/learn_environment.hpp b/catkin_ws/src/learn_environment/include/learn_environment/learn_environment.hpp
index c10c46e..a1af02a 100644
--- a/catkin_ws/src/learn_environment/include/learn_environment/learn_environment.hpp
+++ b/catkin_ws/src/learn_environment/include/learn_environment/learn_environment.hpp
@@ -3,7 +3,6 @@
 
 #include <rviz/panel.h>
 #include <ui_learn_environment.h>
-#include "sidebar.hpp"
 #include "task_manager.hpp"
 #include "task_ui.hpp"
 #include "notebook_converter.hpp"
@@ -54,15 +53,8 @@ public:
      */
     virtual void save(rviz::Config config) const override;
 
-private Q_SLOTS:
-    /**
-     * @brief Toggles the visibility of the sidebar.
-     */
-    void toggleSidebarVisibility();
-
 private:
     Ui::LearnEnvironment *ui; ///< Pointer to the UI object.
-    Sidebar *sidebar; ///< Pointer to the Sidebar object.
     TaskManager *taskManager; ///< Pointer to the TaskManager object.
     TaskUI *taskUI; ///< Pointer to the TaskUI object.
     QProcess *process; ///< Pointer to the QProcess object.
@@ -74,11 +66,6 @@ private:
      * @brief Initializes the UI and the startup logic.
      */
     void initialize();
-
-    /**
-     * @brief Sets up the splitter and layout for the main window.
-     */
-    void setupSplitterAndLayout();
 };
 
 #endif // LEARN_ENVIRONMENT_HPP
\ No newline at end of file
diff --git a/catkin_ws/src/learn_environment/include/learn_environment/subtask_item.hpp b/catkin_ws/src/learn_environment/include/learn_environment/subtask_item.hpp
index 4010fbd..139b144 100644
--- a/catkin_ws/src/learn_environment/include/learn_environment/subtask_item.hpp
+++ b/catkin_ws/src/learn_environment/include/learn_environment/subtask_item.hpp
@@ -3,6 +3,7 @@
 
 #include "task.hpp"
 #include "task_manager.hpp"
+#include "execute_frame.hpp"
 
 #include <QWidget>
 #include <QPushButton>
diff --git a/catkin_ws/src/learn_environment/include/learn_environment/task_manager.hpp b/catkin_ws/src/learn_environment/include/learn_environment/task_manager.hpp
index 2c441c3..78d4ae3 100644
--- a/catkin_ws/src/learn_environment/include/learn_environment/task_manager.hpp
+++ b/catkin_ws/src/learn_environment/include/learn_environment/task_manager.hpp
@@ -3,11 +3,8 @@
 
 #include "task.hpp"
 #include "task_executor.hpp"
-#include "execute_frame.hpp"
 
 #include <QObject>
-#include <QPushButton>
-#include <QFrame>
 #include <QVector>
 #include <QSharedPointer>
 
@@ -28,11 +25,9 @@ public:
     /**
      * @brief Constructs a TaskManager object.
      * @param taskUI Pointer to the TaskUI object.
-     * @param nextButton Pointer to the next button.
-     * @param previousButton Pointer to the previous button.
      * @param parent Pointer to the parent QObject.
      */
-    TaskManager(TaskUI *taskUI, QPushButton *nextButton, QPushButton *previousButton, QFrame *resetRobotFrame, QObject *parent = nullptr);
+    TaskManager(TaskUI *taskUI, QObject *parent = nullptr);
 
     /**
      * @brief Starts or stops a subtask.
@@ -49,32 +44,33 @@ public:
 
 public Q_SLOTS:
     /**
-     * @brief Starts or stops a subtask.
-     * @param subtask Reference to the subtask to be started or stopped.
+     * @brief Slot for changing to the next task.
      */
-    void startStopSubtask(const Subtask &subtask);
+    void nextTask();
 
     /**
-     * @brief Forces the reset of the robot to its initial state.
+     * @brief Slot for changing to the previous task.
      */
-    void forceResetRobot();
+    void previousTask();
 
-private Q_SLOTS:
     /**
-     * @brief Slot for handling the next button click event.
+     * @brief Selects a task by its index.
+     * @param index The index of the task to be selected.
      */
-    void onNextButtonClicked();
+    void selectTask(int index);
 
     /**
-     * @brief Slot for handling the previous button click event.
+     * @brief Starts or stops a subtask.
+     * @param subtask Reference to the subtask to be started or stopped.
      */
-    void onPreviousButtonClicked();
+    void startStopSubtask(const Subtask &subtask);
 
     /**
-     * @brief Selects a task by its index.
-     * @param index The index of the task to be selected.
+     * @brief Forces the reset of the robot to its initial state.
      */
-    void selectTask(int index);
+    void forceResetRobot();
+
+private Q_SLOTS:
 
     /**
      * @brief Slot for handling the task execution started event.
@@ -111,10 +107,6 @@ private Q_SLOTS:
 private:
     TaskUI *taskUI; ///< Pointer to the TaskUI object.
     TaskExecutor *taskExecutor; ///< Pointer to the TaskExecutor object.
-    QPushButton *nextButton; ///< Pointer to the next button.
-    QPushButton *previousButton; ///< Pointer to the previous button.
-    QFrame *resetRobotFrame; ///< Pointer to the reset robot frame.
-    ExecuteFrame *executeResetRobotFrame; ///< Pointer to the execute reset robot frame.
     QVector<QSharedPointer<Task>> tasks; ///< Vector of tasks.
     QVector<Subtask*> queued_and_running_subtasks; ///< Vector of queued and running subtasks.
     int currentQueueStartSolution = false; ///< Flag indicating whether to start the solution or the users script.
diff --git a/catkin_ws/src/learn_environment/include/learn_environment/task_ui.hpp b/catkin_ws/src/learn_environment/include/learn_environment/task_ui.hpp
index 120d8d8..4e2d939 100644
--- a/catkin_ws/src/learn_environment/include/learn_environment/task_ui.hpp
+++ b/catkin_ws/src/learn_environment/include/learn_environment/task_ui.hpp
@@ -4,11 +4,14 @@
 #include "sidebar.hpp"
 #include "task.hpp"
 #include "task_manager.hpp"
+#include "execute_frame.hpp"
 
 #include <QObject>
 #include <QVBoxLayout>
 #include <QLabel>
+#include <QToolButton>
 #include <QPushButton>
+#include <QFrame>
 
 /**
  * @class TaskUI
@@ -18,8 +21,7 @@
  * related to tasks and subtasks. It interacts with the TaskManager and Sidebar
  * to provide a cohesive user experience.
  */
-class TaskUI : public QObject
-{
+class TaskUI : public QWidget {
     Q_OBJECT
 
 public:
@@ -31,13 +33,16 @@ public:
      * @param folderLabel Pointer to the QLabel for displaying the folder information.
      * @param nextButton Pointer to the QPushButton for navigating to the next task.
      * @param previousButton Pointer to the QPushButton for navigating to the previous task.
-     * @param sidebar Reference to the Sidebar object.
+     * @param menuButton Pointer to the QToolButton for opening the sidebar.
+     * @param resetRobotStartButton Pointer to the QToolButton for resetting the robot.
+     * @param resetRobotFrame Pointer to the QFrame displaying the reset of the robot.
+     * @param centralWidget Pointer to the central QWidget for the plugin.
      * @param parent Pointer to the parent QObject.
      */
     TaskUI(QVBoxLayout *subtaskListLayout, QLabel *mainTitleLabel,
            QLabel *difficultyLabel, QLabel *folderLabel, QLabel *topicLabel,
-           QPushButton *nextButton, QPushButton *previousButton,
-           Sidebar &sidebar, QObject *parent = nullptr);
+           QPushButton *nextButton, QPushButton *previousButton, QToolButton *menuButton,
+           QToolButton *resetRobotStartButton, QFrame *resetRobotFrame, QWidget *centralwidget, QWidget *parent = nullptr);
 
     /**
      * @brief Initializes the UI with the loaded tasks.
@@ -62,6 +67,23 @@ public:
      */
     void setTaskManager(TaskManager *manager);
 
+    /**
+     * @brief Update the UI to show that the robot reset has been started.
+     * @param noSubtasksLeft indicator, if subtasks are running after the rest or not.
+     */
+    void startedRobotResetUI(bool noSubtasksLeft);
+
+    /**
+     * @brief Update the UI to show that the robot reset has finished.
+     */
+    void finishedRobotResetUI();
+
+    /**
+     * @brief Update the UI to show that the robot reset has failed.
+     * @param error the error that occured while resetting the robot.
+     */
+    void failedRobotResetUI(const QString &error);
+
 Q_SIGNALS:
     /**
      * @brief Signal emitted when a task is selected.
@@ -69,8 +91,14 @@ Q_SIGNALS:
      */
     void taskSelected(int index);
 
+private Q_SLOTS:
+    /**
+     * @brief Toggles the visibility of the sidebar.
+     */
+    void toggleSidebarVisibility();
+
 private:
-    Sidebar &sidebar; ///< Reference to the Sidebar object.
+    Sidebar *sidebar; ///< Pointer to the Sidebar object.
     QVBoxLayout *subtaskListLayout; ///< Pointer to the QVBoxLayout for displaying subtasks.
     QLabel *mainTitleLabel; ///< Pointer to the QLabel for displaying the main title.
     QLabel *difficultyLabel; ///< Pointer to the QLabel for displaying the difficulty level.
@@ -78,6 +106,11 @@ private:
     QLabel *topicLabel; ///< Pointer to the QLabel for displaying the topic of the task.
     QPushButton *nextButton; ///< Pointer to the QPushButton for navigating to the next task.
     QPushButton *previousButton; ///< Pointer to the QPushButton for navigating to the previous task.
+    QToolButton *menuButton; ///< Pointer to the QToolButton for opening the sidebar.
+    QToolButton *resetRobotStartButton; ///< Pointer to the QToolButton for resetting the robot.
+    QFrame *resetRobotFrame; ///< Pointer to the reset robot frame.
+    ExecuteFrame *executeResetRobotFrame; ///< Pointer to the execute reset robot frame.
+    QWidget *centralwidget; ///< Pointer to the central QWidget for the plugin.
     QVector<QSharedPointer<Task>> tasks; ///< Vector of loaded tasks.
     TaskManager *taskManager; ///< Pointer to the TaskManager object.
 
@@ -91,6 +124,11 @@ private:
      * @brief Adds a line between subtask widgets in the QListWidget.
      */
     void addLineBetweenWidgets();
+    
+    /**
+     * @brief Sets up the splitter and layout for the main window.
+     */
+    void setupSplitterAndLayout();
 };
 
 #endif // TASKUI_HPP
\ No newline at end of file
diff --git a/catkin_ws/src/learn_environment/resource/learn_environment.ui b/catkin_ws/src/learn_environment/resource/learn_environment.ui
index fc12258..d89ea16 100644
--- a/catkin_ws/src/learn_environment/resource/learn_environment.ui
+++ b/catkin_ws/src/learn_environment/resource/learn_environment.ui
@@ -139,7 +139,7 @@ QToolButton:hover { background: white; border-radius: 8px; }</string>
               </property>
               <property name="icon">
                <iconset resource="resources.qrc">
-                <normaloff>:/resource/icons/menu.png</normaloff>:/resource/icons/menu.png</iconset>
+                <normaloff>:/icons/menu.png</normaloff>:/icons/menu.png</iconset>
               </property>
               <property name="iconSize">
                <size>
@@ -336,7 +336,7 @@ QToolButton:hover { background: #e6e6e6; border-radius: 8px; }</string>
                  </property>
                  <property name="icon">
                   <iconset resource="resources.qrc">
-                   <normaloff>:/resource/icons/play.png</normaloff>:/resource/icons/play.png</iconset>
+                   <normaloff>:/icons/play.png</normaloff>:/icons/play.png</iconset>
                  </property>
                  <property name="iconSize">
                   <size>
diff --git a/catkin_ws/src/learn_environment/resource/resources.qrc b/catkin_ws/src/learn_environment/resource/resources.qrc
new file mode 100644
index 0000000..ce61f86
--- /dev/null
+++ b/catkin_ws/src/learn_environment/resource/resources.qrc
@@ -0,0 +1,17 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+     <file>icons/menu.png</file>
+     <file>icons/close.png</file>
+     <file>icons/help.png</file>
+     <file>icons/play.png</file>
+     <file>icons/stop.png</file>
+     <file>icons/failed.png</file>
+     <file>icons/succeeded.png</file>
+     <file>icons/loading.gif</file>
+     <file>icons/queued.gif</file>
+     
+     <file>../task_pool/task_definitions.json</file>
+     <file>../task_pool/difficulty_levels.json</file>
+     <file>../task_pool/topic_definitions.json</file>
+ </qresource>
+ </RCC>
diff --git a/catkin_ws/src/learn_environment/resources.qrc b/catkin_ws/src/learn_environment/resources.qrc
deleted file mode 100644
index 6e23edd..0000000
--- a/catkin_ws/src/learn_environment/resources.qrc
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
- <qresource>
-     <file>resource/icons/menu.png</file>
-     <file>resource/icons/close.png</file>
-     <file>resource/icons/help.png</file>
-     <file>resource/icons/play.png</file>
-     <file>resource/icons/stop.png</file>
-     <file>resource/icons/failed.png</file>
-     <file>resource/icons/succeeded.png</file>
-     <file>resource/icons/loading.gif</file>
-     <file>resource/icons/queued.gif</file>
-     
-     <file>task_pool/task_definitions.json</file>
-     <file>task_pool/difficulty_levels.json</file>
-     <file>task_pool/topic_definitions.json</file>
- </qresource>
- </RCC>
diff --git a/catkin_ws/src/learn_environment/src/learn_environment.cpp b/catkin_ws/src/learn_environment/src/learn_environment.cpp
index 97a3133..5df964a 100644
--- a/catkin_ws/src/learn_environment/src/learn_environment.cpp
+++ b/catkin_ws/src/learn_environment/src/learn_environment.cpp
@@ -4,13 +4,6 @@
 #include <pluginlib/class_list_macros.hpp>
 
 #include <QMainWindow>
-#include <QSplitter>
-#include <QHBoxLayout>
-
-namespace {
-    const char* CLOSE_ICON_PATH = ":/resource/icons/close.png";
-    const char* MENU_ICON_PATH = ":/resource/icons/menu.png";
-}
 
 LearnEnvironment::LearnEnvironment(QWidget *parent)
     : rviz::Panel(parent),
@@ -36,7 +29,6 @@ LearnEnvironment::~LearnEnvironment()
 }
 
 void LearnEnvironment::initialize() {
-    sidebar = new Sidebar(this);
     taskUI = new TaskUI(
         ui->subtaskListVLayout,
         ui->mainTitleLabel,
@@ -45,17 +37,18 @@ void LearnEnvironment::initialize() {
         ui->topicLabel,
         ui->nextButton,
         ui->previousButton,
-        *sidebar,
+        ui->menuButton,
+        ui->resetRobotStartButton,
+        ui->resetRobotFrame,
+        ui->centralwidget,
         this
     );
-    taskManager = new TaskManager(taskUI, ui->nextButton, ui->previousButton, ui->resetRobotFrame, this);
-
-    setupSplitterAndLayout();
+    taskManager = new TaskManager(taskUI, this);
 
-    sidebar->setVisible(false);
-
-    connect(ui->menuButton, &QPushButton::clicked, this, &LearnEnvironment::toggleSidebarVisibility);
-    connect(ui->resetRobotStartButton, &QToolButton::clicked, taskManager, &TaskManager::forceResetRobot);
+    QHBoxLayout *mainPanelLayout = new QHBoxLayout(this);
+    mainPanelLayout->addWidget(taskUI);
+    mainPanelLayout->setContentsMargins(0, 0, 0, 0);
+    setLayout(mainPanelLayout);
 
     notebookConverter->moveToThread(notebookThread);
     connect(notebookThread, &QThread::started, notebookConverter, &NotebookConverter::processTaskPool);
@@ -63,33 +56,6 @@ void LearnEnvironment::initialize() {
     notebookThread->start();
 }
 
-void LearnEnvironment::setupSplitterAndLayout() {
-    QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
-
-    splitter->addWidget(sidebar);
-    splitter->addWidget(ui->centralwidget);
-
-    QList<int> sizes;
-    sizes << 200 << 600;
-    splitter->setSizes(sizes);
-
-    // Set the layout to the main widget
-    QHBoxLayout *mainLayout = new QHBoxLayout(this);
-    mainLayout->addWidget(splitter);
-    setLayout(mainLayout);
-}
-
-void LearnEnvironment::toggleSidebarVisibility() {
-    bool isVisible = sidebar->isVisible();
-    sidebar->setVisible(!isVisible);
-
-    if (sidebar->isVisible()) {
-        ui->menuButton->setIcon(QIcon(CLOSE_ICON_PATH));
-    } else {
-        ui->menuButton->setIcon(QIcon(MENU_ICON_PATH));
-    }
-}
-
 void LearnEnvironment::load(const rviz::Config &config) {
     // Implement loading of user-specific settings
 }
diff --git a/catkin_ws/src/learn_environment/src/subtask_item.cpp b/catkin_ws/src/learn_environment/src/subtask_item.cpp
index 830454b..de37eb4 100644
--- a/catkin_ws/src/learn_environment/src/subtask_item.cpp
+++ b/catkin_ws/src/learn_environment/src/subtask_item.cpp
@@ -17,13 +17,13 @@ namespace {
     const char* LINK_STYLE = "font-family:'monospace'; font-size:10pt; color:'#444444'; vertical-align:bottom;";
     const char* BODY_STYLE = "color:#444444;";
 
-    const char* START_ICON_PATH = ":/resource/icons/play.png";
-    const char* STOP_ICON_PATH = ":/resource/icons/stop.png";
-    const char* HELP_ICON_PATH = ":/resource/icons/help.png";
-    const char* LOADING_GIF_PATH = ":/resource/icons/loading.gif";
-    const char* QUEUED_GIF_PATH = ":/resource/icons/queued.gif";
-    const char* FAILED_ICON_PATH = ":/resource/icons/failed.png";
-    const char* SUCCEEDED_ICON_PATH = ":/resource/icons/succeeded.png";
+    const char* START_ICON_PATH = ":/icons/play.png";
+    const char* STOP_ICON_PATH = ":/icons/stop.png";
+    const char* HELP_ICON_PATH = ":/icons/help.png";
+    const char* LOADING_GIF_PATH = ":/icons/loading.gif";
+    const char* QUEUED_GIF_PATH = ":/icons/queued.gif";
+    const char* FAILED_ICON_PATH = ":/icons/failed.png";
+    const char* SUCCEEDED_ICON_PATH = ":/icons/succeeded.png";
 
     const char* ICON_BUTTON_STYLE = 
         "QToolButton { border: 0; padding: 0; }"
diff --git a/catkin_ws/src/learn_environment/src/task_manager.cpp b/catkin_ws/src/learn_environment/src/task_manager.cpp
index a70cf54..8ab2e9d 100644
--- a/catkin_ws/src/learn_environment/src/task_manager.cpp
+++ b/catkin_ws/src/learn_environment/src/task_manager.cpp
@@ -3,40 +3,21 @@
 #include "learn_environment/task_parser.hpp"
 #include "learn_environment/task_executor.hpp"
 #include "learn_environment/notebook_converter.hpp"
+#include "learn_environment/folder_structure_constants.hpp"
 
 #include <QDebug>
 #include <QToolButton>
 
-namespace {
-    const char* TASK_DEFINITIONS_PATH = ":/task_pool/task_definitions.json";
-    const char* TOPIC_DEFINITIONS_PATH = ":/task_pool/topic_definitions.json";
-    const char* DIFFICULTY_LEVELS_DEFINITION_PATH = ":/task_pool/difficulty_levels.json";
-    const char* LOADING_GIF_PATH = ":/resource/icons/loading.gif";
-    const char* START_ICON_PATH = ":/resource/icons/play.png";
-    const char* STOP_ICON_PATH = ":/resource/icons/stop.png";
-    const char* FAILED_ICON_PATH = ":/resource/icons/failed.png";
-    const char* SUCCEEDED_ICON_PATH = ":/resource/icons/succeeded.png";
-    const char* RESET_ROBOT_TEXT = "Resetting the robot to its default state...";
-    const char* RESET_ROBOT_TEXT_SCRIPTS = "Resetting the robot before script execution...";
-    const char* RESET_ROBOT_TEXT_SUCCESS = "Robot successfully reset!";
-    const char* RESET_ROBOT_TEXT_FAILED = "<b>Robot reset failed!</b>";
-    const char* STOP_RESET_ROBOT_TOOLTIP = "Cancel reset process";
-    const char* RESET_ROBOT_TOOLTIP = "Reset robot to default state";
-    const char* RESET_ROBOT_START_BUTTON_NAME = "resetRobotStartButton";
-}
-
-TaskManager::TaskManager(TaskUI *taskUI, QPushButton *nextButton, QPushButton *previousButton, QFrame *resetRobotFrame, QObject *parent)
+TaskManager::TaskManager(TaskUI *taskUI, QObject *parent)
     : QObject(parent),
       taskUI(taskUI),
       taskExecutor(new TaskExecutor(this)),
-      nextButton(nextButton),
-      previousButton(previousButton),
-      resetRobotFrame(resetRobotFrame),
-      executeResetRobotFrame(nullptr),
       currentTaskIndex(0)
 {
     TaskParser parser;
-    tasks = parser.loadTasks(TASK_DEFINITIONS_PATH, DIFFICULTY_LEVELS_DEFINITION_PATH, TOPIC_DEFINITIONS_PATH);
+    tasks = parser.loadTasks(FolderStructureConstants::TASK_DEFINITIONS_PATH, 
+                             FolderStructureConstants::DIFFICULTY_LEVELS_DEFINITION_PATH, 
+                             FolderStructureConstants::TOPIC_DEFINITIONS_PATH);
 
     if (tasks.isEmpty()) {
         qCritical() << "No tasks loaded. Exiting TaskManager initialization.";
@@ -56,12 +37,6 @@ TaskManager::TaskManager(TaskUI *taskUI, QPushButton *nextButton, QPushButton *p
     taskUI->initializeUI(tasks);
 
     selectTask(currentTaskIndex);
-
-    connect(nextButton, &QPushButton::clicked, this, &TaskManager::onNextButtonClicked);
-    connect(previousButton, &QPushButton::clicked, this, &TaskManager::onPreviousButtonClicked);
-
-    // Connect TaskUI's taskSelected signal to the selectTask slot
-    connect(taskUI, &TaskUI::taskSelected, this, &TaskManager::selectTask);
 }
 
 void TaskManager::startStopSubtask(Subtask &subtask, bool startSolution)
@@ -132,14 +107,14 @@ void TaskManager::selectTask(int index)
     }
 }
 
-void TaskManager::onNextButtonClicked()
+void TaskManager::nextTask()
 {
     if (currentTaskIndex < tasks.size() - 1) {
         selectTask(currentTaskIndex + 1);
     }
 }
 
-void TaskManager::onPreviousButtonClicked()
+void TaskManager::previousTask()
 {
     if (currentTaskIndex > 0) {
         selectTask(currentTaskIndex - 1);
@@ -317,58 +292,19 @@ void TaskManager::onResetRobotStarted()
         return;
     }
 
-    QString message = "Robot reset started.";
     resetRobotInProgress = true;
-    
-    QToolButton* resetRobotStartButton = resetRobotFrame->findChild<QToolButton*>(RESET_ROBOT_START_BUTTON_NAME);
-    if (resetRobotStartButton) {
-        resetRobotStartButton->setIcon(QIcon(STOP_ICON_PATH));
-        resetRobotStartButton->setToolTip(STOP_RESET_ROBOT_TOOLTIP);
-    } else {
-        qCritical() << "Reset robot start button not found.";
-    }
 
-    if (!executeResetRobotFrame) {
-        executeResetRobotFrame = new ExecuteFrame(resetRobotFrame);
-        QVBoxLayout *resetLayout = qobject_cast<QVBoxLayout*>(resetRobotFrame->layout());
-        if (!resetLayout) {
-            resetLayout = new QVBoxLayout(resetRobotFrame);
-            resetRobotFrame->setLayout(resetLayout);
-        }
-        if (!resetLayout) {
-            qCritical() << "Reset layout not found.";
-            return;
-        }
-        resetLayout->addWidget(executeResetRobotFrame);
-    }
-    if (!executeResetRobotFrame) {
-        qCritical() << "Execute reset robot frame not found.";
-        return;
-    }
-    executeResetRobotFrame->setImage(LOADING_GIF_PATH);
-    if (queued_and_running_subtasks.isEmpty()) {
-        executeResetRobotFrame->setText(RESET_ROBOT_TEXT);
-    } else {
-        executeResetRobotFrame->setText(RESET_ROBOT_TEXT_SCRIPTS);
-    }
-    logWithHashes(message);
+    bool noSubtasksLeft = queued_and_running_subtasks.isEmpty();
+    taskUI->startedRobotResetUI(noSubtasksLeft);
+
+    logWithHashes("Robot reset started.");
 }
 
 void TaskManager::onResetRobotFinished()
 {
     resetRobotInProgress = false;
-    // update UI
-    QToolButton* resetRobotStartButton = resetRobotFrame->findChild<QToolButton*>(RESET_ROBOT_START_BUTTON_NAME);
-    if (resetRobotStartButton) {
-        resetRobotStartButton->setIcon(QIcon(START_ICON_PATH));
-        resetRobotStartButton->setToolTip(RESET_ROBOT_TOOLTIP);
-    }
-    if (executeResetRobotFrame) {
-        if (!executeResetRobotFrame->getText().contains(RESET_ROBOT_TEXT_FAILED)) {
-            executeResetRobotFrame->setImage(SUCCEEDED_ICON_PATH);
-            executeResetRobotFrame->setText(RESET_ROBOT_TEXT_SUCCESS);
-        }
-    }
+    
+    taskUI->finishedRobotResetUI();
 
     initiateFirstSubtask();
 }
@@ -379,10 +315,7 @@ void TaskManager::onResetRobotFailed(const QString &error)
 
     resetRobotInProgress = false;
 
-    if (executeResetRobotFrame) {
-        executeResetRobotFrame->setImage(FAILED_ICON_PATH);
-        executeResetRobotFrame->setText(QString(RESET_ROBOT_TEXT_FAILED) + "<br>" + error);
-    }
+    taskUI->failedRobotResetUI(error);
 
     onTaskExecutionFailed(error);
 }
diff --git a/catkin_ws/src/learn_environment/src/task_ui.cpp b/catkin_ws/src/learn_environment/src/task_ui.cpp
index fb3d1d7..26375ed 100644
--- a/catkin_ws/src/learn_environment/src/task_ui.cpp
+++ b/catkin_ws/src/learn_environment/src/task_ui.cpp
@@ -2,7 +2,9 @@
 #include "learn_environment/subtask_item.hpp"
 
 #include <QRegExp>
+#include <QSplitter>
 #include <QDebug>
+#include <QHBoxLayout>
 
 namespace {
     const char* FOLDER_HTML_TEMPLATE = R"(
@@ -13,26 +15,48 @@ namespace {
         <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; 
             -qt-block-indent:0; text-indent:0px;"><span style="font-family:'monospace'; 
             color:'#444444';">)";
+    const char* CLOSE_ICON_PATH = ":/icons/close.png";
+    const char* MENU_ICON_PATH = ":/icons/menu.png";
+    const char* LOADING_GIF_PATH = ":/icons/loading.gif";
+    const char* START_ICON_PATH = ":/icons/play.png";
+    const char* STOP_ICON_PATH = ":/icons/stop.png";
+    const char* FAILED_ICON_PATH = ":/icons/failed.png";
+    const char* SUCCEEDED_ICON_PATH = ":/icons/succeeded.png";
+    const char* RESET_ROBOT_TEXT = "Resetting the robot to its default state...";
+    const char* RESET_ROBOT_TEXT_SCRIPTS = "Resetting the robot before script execution...";
+    const char* RESET_ROBOT_TEXT_SUCCESS = "Robot successfully reset!";
+    const char* RESET_ROBOT_TEXT_FAILED = "<b>Robot reset failed!</b>";
+    const char* STOP_RESET_ROBOT_TOOLTIP = "Cancel reset process";
+    const char* RESET_ROBOT_TOOLTIP = "Reset robot to default state";
 }
 
 TaskUI::TaskUI(QVBoxLayout *subtaskListLayout, QLabel *mainTitleLabel,
                QLabel *difficultyLabel, QLabel *folderLabel, QLabel *topicLabel,
-               QPushButton *nextButton, QPushButton *previousButton,
-               Sidebar &sidebar, QObject *parent)
-    : QObject(parent),
-      sidebar(sidebar),
+               QPushButton *nextButton, QPushButton *previousButton, QToolButton *menuButton,
+               QToolButton *resetRobotStartButton, QFrame *resetRobotFrame, QWidget *centralwidget, QWidget *parent)
+    : QWidget(parent),
+      sidebar(new Sidebar(this)),
       subtaskListLayout(subtaskListLayout),
       mainTitleLabel(mainTitleLabel),
       difficultyLabel(difficultyLabel),
       folderLabel(folderLabel),
       topicLabel(topicLabel),
       nextButton(nextButton),
-      previousButton(previousButton)
+      previousButton(previousButton),
+      menuButton(menuButton),
+      resetRobotStartButton(resetRobotStartButton),
+      resetRobotFrame(resetRobotFrame),
+      executeResetRobotFrame(nullptr),
+      centralwidget(centralwidget)
 { }
 
 void TaskUI::setTaskManager(TaskManager *manager)
 {
     taskManager = manager;
+    connect(resetRobotStartButton, &QToolButton::clicked, taskManager, &TaskManager::forceResetRobot);
+    connect(nextButton, &QPushButton::clicked, taskManager, &TaskManager::nextTask);
+    connect(previousButton, &QPushButton::clicked, taskManager, &TaskManager::previousTask);
+    connect(this, &TaskUI::taskSelected, taskManager, &TaskManager::selectTask);
 }
 
 void TaskUI::initializeUI(const QVector<QSharedPointer<Task>> &loadedTasks)
@@ -43,9 +67,13 @@ void TaskUI::initializeUI(const QVector<QSharedPointer<Task>> &loadedTasks)
         return;
     }
 
-    sidebar.fillSidebarWithTasks(tasks);
+    sidebar->fillSidebarWithTasks(tasks);
+    sidebar->setVisible(false);
 
-    connect(&sidebar, &Sidebar::taskSelected, this, &TaskUI::taskSelected);
+    setupSplitterAndLayout();
+
+    connect(menuButton, &QPushButton::clicked, this, &TaskUI::toggleSidebarVisibility);
+    connect(sidebar, &Sidebar::taskSelected, this, &TaskUI::taskSelected);
 }
 
 void TaskUI::setTaskUI(int currentTaskIndex)
@@ -72,7 +100,7 @@ void TaskUI::setTaskUI(int currentTaskIndex)
 
     setSubtaskItems(currentTaskIndex);
 
-    sidebar.selectTask(currentTaskIndex);
+    sidebar->selectTask(currentTaskIndex);
 }
 
 void TaskUI::setSubtaskItems(int currentTaskIndex)
@@ -137,4 +165,84 @@ void TaskUI::addLineBetweenWidgets()
     layout->addWidget(line);
 
     subtaskListLayout->addWidget(container);
+}
+
+void TaskUI::setupSplitterAndLayout() {
+    QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
+
+    centralwidget->setStyleSheet("border: 0; margin: 0;");
+
+    splitter->addWidget(sidebar);
+    splitter->addWidget(centralwidget);
+    splitter->setStyleSheet("border: 0; margin: 0;");
+    splitter->setContentsMargins(0, 0, 0, 0);
+
+    QList<int> sizes;
+    sizes << 200 << 600;
+    splitter->setSizes(sizes);
+
+    // Set the layout to the main widget
+    QHBoxLayout *mainLayout = new QHBoxLayout(this);
+    mainLayout->addWidget(splitter);
+    mainLayout->setContentsMargins(0, 0, 0, 0);
+    setLayout(mainLayout);
+}
+
+void TaskUI::toggleSidebarVisibility() {
+    bool isVisible = sidebar->isVisible();
+    sidebar->setVisible(!isVisible);
+
+    if (sidebar->isVisible()) {
+        menuButton->setIcon(QIcon(CLOSE_ICON_PATH));
+    } else {
+        menuButton->setIcon(QIcon(MENU_ICON_PATH));
+    }
+}
+
+void TaskUI::startedRobotResetUI(bool noSubtasksLeft) {
+    resetRobotStartButton->setIcon(QIcon(STOP_ICON_PATH));
+    resetRobotStartButton->setToolTip(STOP_RESET_ROBOT_TOOLTIP);
+
+
+    if (!executeResetRobotFrame) {
+        executeResetRobotFrame = new ExecuteFrame(resetRobotFrame);
+        QVBoxLayout *resetLayout = qobject_cast<QVBoxLayout*>(resetRobotFrame->layout());
+        if (!resetLayout) {
+            resetLayout = new QVBoxLayout(resetRobotFrame);
+            resetRobotFrame->setLayout(resetLayout);
+        }
+        if (!resetLayout) {
+            qCritical() << "Reset layout not found.";
+            return;
+        }
+        resetLayout->addWidget(executeResetRobotFrame);
+    }
+    if (!executeResetRobotFrame) {
+        qCritical() << "Execute reset robot frame not found.";
+        return;
+    }
+    executeResetRobotFrame->setImage(LOADING_GIF_PATH);
+    if (noSubtasksLeft) {
+        executeResetRobotFrame->setText(RESET_ROBOT_TEXT);
+    } else {
+        executeResetRobotFrame->setText(RESET_ROBOT_TEXT_SCRIPTS);
+    }
+}
+
+void TaskUI::finishedRobotResetUI() {
+    resetRobotStartButton->setIcon(QIcon(START_ICON_PATH));
+    resetRobotStartButton->setToolTip(RESET_ROBOT_TOOLTIP);
+    if (executeResetRobotFrame) {
+        if (!executeResetRobotFrame->getText().contains(RESET_ROBOT_TEXT_FAILED)) {
+            executeResetRobotFrame->setImage(SUCCEEDED_ICON_PATH);
+            executeResetRobotFrame->setText(RESET_ROBOT_TEXT_SUCCESS);
+        }
+    }
+}
+
+void TaskUI::failedRobotResetUI(const QString &error) {
+    if (executeResetRobotFrame) {
+        executeResetRobotFrame->setImage(FAILED_ICON_PATH);
+        executeResetRobotFrame->setText(QString(RESET_ROBOT_TEXT_FAILED) + "<br>" + error);
+    }
 }
\ No newline at end of file
-- 
GitLab