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