diff --git a/visualization/motion_planning_tasks/src/CMakeLists.txt b/visualization/motion_planning_tasks/src/CMakeLists.txt index c15ed591..5472ad9c 100644 --- a/visualization/motion_planning_tasks/src/CMakeLists.txt +++ b/visualization/motion_planning_tasks/src/CMakeLists.txt @@ -3,7 +3,7 @@ set(MOVEIT_LIB_NAME motion_planning_tasks_rviz_plugin) qt_wrap_ui(UIC_FILES task_panel.ui task_view.ui - task_settings.ui + global_settings.ui ) add_library(${MOVEIT_LIB_NAME} diff --git a/visualization/motion_planning_tasks/src/task_settings.ui b/visualization/motion_planning_tasks/src/global_settings.ui similarity index 80% rename from visualization/motion_planning_tasks/src/task_settings.ui rename to visualization/motion_planning_tasks/src/global_settings.ui index 3a76384c..4efb8c45 100644 --- a/visualization/motion_planning_tasks/src/task_settings.ui +++ b/visualization/motion_planning_tasks/src/global_settings.ui @@ -1,7 +1,7 @@ - moveit_rviz_plugin::TaskSettings - + moveit_rviz_plugin::GlobalSettingsWidget + 0 @@ -27,7 +27,7 @@ 0 - + 0 @@ -44,14 +44,14 @@ 0 - + - Settings + Global Settings - + diff --git a/visualization/motion_planning_tasks/src/task_panel.cpp b/visualization/motion_planning_tasks/src/task_panel.cpp index c9c806dc..d721e481 100644 --- a/visualization/motion_planning_tasks/src/task_panel.cpp +++ b/visualization/motion_planning_tasks/src/task_panel.cpp @@ -87,15 +87,20 @@ TaskPanel::TaskPanel(QWidget* parent) { Q_D(TaskPanel); - d->tasks_widget = new TaskView(this); - d->settings_widget = new TaskSettings(this); - layout()->addWidget(d->tasks_widget); - layout()->addWidget(d->settings_widget); - connect(d->tasks_widget, SIGNAL(configChanged()), this, SIGNAL(configChanged())); + // sync checked tool button with displayed widget + connect(d->tool_buttons_group, static_cast(&QButtonGroup::buttonClicked), + d->stackedWidget, [d](int index) { d->stackedWidget->setCurrentIndex(index); }); + connect(d->stackedWidget, &QStackedWidget::currentChanged, d->tool_buttons_group, + [d](int index) { d->tool_buttons_group->button(index)->setChecked(true); }); + + // create sub widgets with corresponding tool buttons + addSubPanel(new TaskView(this, d->property_root), "Tasks View", QIcon(":/icons/tasks.png")); + d->stackedWidget->setCurrentIndex(0); // Tasks View is show by default + + // settings widget should come last + addSubPanel(new GlobalSettingsWidget(this, d->property_root), "Global Settings", QIcon(":/icons/settings.png")); connect(d->button_show_stage_dock_widget, SIGNAL(clicked()), this, SLOT(showStageDockWidget())); - connect(d->button_show_settings, SIGNAL(toggled(bool)), d->settings_widget, SLOT(setVisible(bool))); - d->settings_widget->setVisible(d->button_show_settings->isChecked()); // if still undefined, this becomes the global instance if (singleton_.isNull()) @@ -107,6 +112,24 @@ TaskPanel::~TaskPanel() delete d_ptr; } +void TaskPanel::addSubPanel(SubPanel *w, const QString& title, const QIcon& icon) +{ + Q_D(TaskPanel); + + auto button = new QToolButton(w); + button->setToolTip(title); + button->setIcon(icon); + button->setCheckable(true); + + int index = d->stackedWidget->count(); + d->tool_buttons_layout->insertWidget(index, button); + d->tool_buttons_group->addButton(button, index); + d->stackedWidget->addWidget(w); + + w->setWindowTitle(title); + connect(w, SIGNAL(configChanged()), this, SIGNAL(configChanged())); +} + void TaskPanel::incDisplayCount(rviz::WindowManagerInterface* window_manager) { ++display_count_; @@ -132,7 +155,11 @@ TaskPanelPrivate::TaskPanelPrivate(TaskPanel *q_ptr) : q_ptr(q_ptr) { setupUi(q_ptr); + tool_buttons_group = new QButtonGroup(q_ptr); + tool_buttons_group->setExclusive(true); button_show_stage_dock_widget->setEnabled(bool(getStageFactory())); + button_show_stage_dock_widget->setToolTip(QStringLiteral("Show available stages")); + property_root = new rviz::Property("Global Settings"); } void TaskPanel::onInitialize() @@ -143,13 +170,19 @@ void TaskPanel::onInitialize() void TaskPanel::save(rviz::Config config) const { rviz::Panel::save(config); - d_ptr->tasks_widget->save(config.mapMakeChild("tasks_view")); + for (int i=0; i < d_ptr->stackedWidget->count(); ++i) { + SubPanel* w = static_cast(d_ptr->stackedWidget->widget(i)); + w->save(config.mapMakeChild(w->windowTitle())); + } } void TaskPanel::load(const rviz::Config& config) { rviz::Panel::load(config); - d_ptr->tasks_widget->load(config.mapGetChild("tasks_view")); + for (int i=0; i < d_ptr->stackedWidget->count(); ++i) { + SubPanel* w = static_cast(d_ptr->stackedWidget->widget(i)); + w->load(config.mapGetChild(w->windowTitle())); + } } void TaskPanel::showStageDockWidget() @@ -235,8 +268,8 @@ void TaskViewPrivate::lock(TaskDisplay* display) locked_display_ = display; } -TaskView::TaskView(QWidget *parent) - : QWidget(parent), d_ptr(new TaskViewPrivate(this)) +TaskView::TaskView(moveit_rviz_plugin::TaskPanel *parent, rviz::Property *root) + : SubPanel(parent), d_ptr(new TaskViewPrivate(this)) { Q_D(TaskView); @@ -426,23 +459,37 @@ void TaskView::onSolutionSelectionChanged(const QItemSelection &selected, const } -TaskSettingsPrivate::TaskSettingsPrivate(TaskSettings *q_ptr) +GlobalSettingsWidgetPrivate::GlobalSettingsWidgetPrivate(GlobalSettingsWidget *q_ptr, rviz::Property *root) : q_ptr(q_ptr) { setupUi(q_ptr); + properties = new rviz::PropertyTreeModel(root, q_ptr); + view->setModel(properties); } -TaskSettings::TaskSettings(QWidget *parent) - : QWidget(parent), d_ptr(new TaskSettingsPrivate(this)) +GlobalSettingsWidget::GlobalSettingsWidget(moveit_rviz_plugin::TaskPanel *parent, rviz::Property *root) + : SubPanel(parent), d_ptr(new GlobalSettingsWidgetPrivate(this, root)) { - Q_D(TaskSettings); + Q_D(GlobalSettingsWidget); + connect(d->properties, &rviz::PropertyTreeModel::configChanged, + this, &GlobalSettingsWidget::configChanged); } -TaskSettings::~TaskSettings() +GlobalSettingsWidget::~GlobalSettingsWidget() { delete d_ptr; } +void GlobalSettingsWidget::save(rviz::Config config) +{ + d_ptr->properties->getRoot()->save(config); +} + +void GlobalSettingsWidget::load(const rviz::Config &config) +{ + d_ptr->properties->getRoot()->load(config); +} + } #include "moc_task_panel.cpp" diff --git a/visualization/motion_planning_tasks/src/task_panel.h b/visualization/motion_planning_tasks/src/task_panel.h index 3b0d44d7..fe5a6321 100644 --- a/visualization/motion_planning_tasks/src/task_panel.h +++ b/visualization/motion_planning_tasks/src/task_panel.h @@ -42,9 +42,11 @@ #include #include class QItemSelection; +class QIcon; namespace rviz { class WindowManagerInterface; +class Property; } namespace moveit_rviz_plugin { @@ -53,12 +55,22 @@ class TaskSolutionVisualization; MOVEIT_CLASS_FORWARD(TaskListModel) MOVEIT_CLASS_FORWARD(TaskPanel) -/** The TaskPanel displays information about manipulation tasks in the system. - * - * Subscribing to task_monitoring and task_solution topics, it collects information - * about running tasks and their solutions and allows to inspect both, - * successful solutions and failed solution attempts. - */ + +/// Base class for all sub panels within the Task Panel +class SubPanel : public QWidget { + Q_OBJECT +public: + SubPanel(QWidget* parent = nullptr) : QWidget(parent) {} + + virtual void save(rviz::Config config) {} + virtual void load(const rviz::Config& config) {} + +Q_SIGNALS: + void configChanged(); +}; + + +/** The TaskPanel is the central panel of this plugin, collecting various sub panels. */ class TaskPanelPrivate; class TaskPanel: public rviz::Panel { @@ -70,6 +82,9 @@ public: TaskPanel(QWidget* parent = 0); ~TaskPanel(); + /// add a new sub panel widget + void addSubPanel(SubPanel* w, const QString &title, const QIcon &icon); + /** Increment/decrement use count of singleton TaskPanel instance. * * If not yet done, an instance is created. If use count drops to zero, @@ -88,21 +103,24 @@ protected Q_SLOTS: class MetaTaskListModel; +/** TaskView displays all known tasks. + * + * Subscribing to task_monitoring and task_solution topics, it collects information + * about running tasks and their solutions and allows to inspect both, + * successful solutions and failed solution attempts. +*/ class TaskViewPrivate; -class TaskView : public QWidget { +class TaskView : public SubPanel { Q_OBJECT Q_DECLARE_PRIVATE(TaskView) TaskViewPrivate *d_ptr; public: - TaskView(QWidget* parent = 0); + TaskView(TaskPanel* parent, rviz::Property* root); ~TaskView(); - void save(rviz::Config config); - void load(const rviz::Config& config); - -Q_SIGNALS: - void configChanged(); + void save(rviz::Config config) override; + void load(const rviz::Config& config) override; public Q_SLOTS: void addTask(); @@ -115,15 +133,18 @@ protected Q_SLOTS: }; -class TaskSettingsPrivate; -class TaskSettings : public QWidget { +class GlobalSettingsWidgetPrivate; +class GlobalSettingsWidget : public SubPanel { Q_OBJECT - Q_DECLARE_PRIVATE(TaskSettings) - TaskSettingsPrivate *d_ptr; + Q_DECLARE_PRIVATE(GlobalSettingsWidget) + GlobalSettingsWidgetPrivate *d_ptr; public: - TaskSettings(QWidget* parent = 0); - ~TaskSettings(); + GlobalSettingsWidget(TaskPanel* parent, rviz::Property* root); + ~GlobalSettingsWidget(); + + void save(rviz::Config config) override; + void load(const rviz::Config &config) override; }; } diff --git a/visualization/motion_planning_tasks/src/task_panel.ui b/visualization/motion_planning_tasks/src/task_panel.ui index 8d178229..c0cf48a5 100644 --- a/visualization/motion_planning_tasks/src/task_panel.ui +++ b/visualization/motion_planning_tasks/src/task_panel.ui @@ -27,23 +27,9 @@ 0 - + - - - ... - - - - :/icons/settings.png:/icons/settings.png - - - true - - - - - + Qt::Horizontal @@ -68,6 +54,9 @@ + + + diff --git a/visualization/motion_planning_tasks/src/task_panel_p.h b/visualization/motion_planning_tasks/src/task_panel_p.h index 37cab821..322150b9 100644 --- a/visualization/motion_planning_tasks/src/task_panel_p.h +++ b/visualization/motion_planning_tasks/src/task_panel_p.h @@ -41,7 +41,7 @@ #include "task_panel.h" #include "ui_task_panel.h" #include "ui_task_view.h" -#include "ui_task_settings.h" +#include "ui_global_settings.h" #include #include @@ -58,8 +58,8 @@ public: TaskPanelPrivate(TaskPanel *q_ptr); TaskPanel* q_ptr; - TaskView* tasks_widget; - TaskSettings* settings_widget; + QButtonGroup* tool_buttons_group; + rviz::Property* property_root; rviz::WindowManagerInterface* window_manager_; }; @@ -85,11 +85,12 @@ public: }; -class TaskSettingsPrivate : public Ui_TaskSettings { +class GlobalSettingsWidgetPrivate : public Ui_GlobalSettingsWidget { public: - TaskSettingsPrivate(TaskSettings *q_ptr); + GlobalSettingsWidgetPrivate(GlobalSettingsWidget *q_ptr, rviz::Property *root); - TaskSettings *q_ptr; + GlobalSettingsWidget *q_ptr; + rviz::PropertyTreeModel *properties; }; }