extensible TaskPanel

Provide TaskPanel::addSubPanel() to add new sub panels.
Each panel can be activated with an associated QToolButton.
Sub panels, derived from base class SubPanel, automatically load/save their config settings.
All settings are shown in GlobalSettingsWidget (renamed from TaskSettings).
This commit is contained in:
Robert Haschke 2019-02-11 02:07:28 +01:00
parent 6950cf2b8e
commit 1ce66c758b
6 changed files with 122 additions and 64 deletions

View File

@ -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}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>moveit_rviz_plugin::TaskSettings</class>
<widget class="QWidget" name="moveit_rviz_plugin::TaskSettings">
<class>moveit_rviz_plugin::GlobalSettingsWidget</class>
<widget class="QWidget" name="moveit_rviz_plugin::GlobalSettingsWidget">
<property name="geometry">
<rect>
<x>0</x>
@ -27,7 +27,7 @@
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="tab_settings_layout">
<layout class="QVBoxLayout" name="layout">
<property name="spacing">
<number>0</number>
</property>
@ -44,14 +44,14 @@
<number>0</number>
</property>
<item>
<widget class="QLabel" name="settings_view_label">
<widget class="QLabel" name="label">
<property name="text">
<string>Settings</string>
<string>Global Settings</string>
</property>
</widget>
</item>
<item>
<widget class="rviz::PropertyTreeWidget" name="settings_view"/>
<widget class="rviz::PropertyTreeWidget" name="view"/>
</item>
</layout>
</item>

View File

@ -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<void(QButtonGroup::*)(int)>(&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<SubPanel*>(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<SubPanel*>(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"

View File

@ -42,9 +42,11 @@
#include <moveit/macros/class_forward.h>
#include <QModelIndex>
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;
};
}

View File

@ -27,23 +27,9 @@
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="tool_buttons_layout">
<item>
<widget class="QToolButton" name="button_show_settings">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/settings.png</normaloff>:/icons/settings.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -68,6 +54,9 @@
</item>
</layout>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget"/>
</item>
</layout>
</widget>
<resources>

View File

@ -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 <rviz/panel.h>
#include <rviz/properties/property_tree_model.h>
@ -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;
};
}