mirror of
https://github.com/moveit/moveit_task_constructor.git
synced 2025-11-04 14:49:57 +08:00
rework RViz panel
There's no need for individually resizable columns, but all numeric content should autoresize and be visible all the time. We will add an option to hide the time column in the future. Remove intermediate AutoAdjustingTreeView layer to simplify code. Resizing the columns did not work perfectly well before and the auto_hide_cols_ feature was not really used.
This commit is contained in:
parent
25fea7198a
commit
75bc6566f6
@ -2,6 +2,7 @@
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2017, Bielefeld University
|
||||
* Copyright (c) 2020, Hamburg University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -359,99 +360,7 @@ Qt::DropActions TaskListModel::supportedDropActions() const {
|
||||
return Qt::CopyAction | Qt::MoveAction;
|
||||
}
|
||||
|
||||
AutoAdjustingTreeView::AutoAdjustingTreeView(QWidget* parent) : QTreeView(parent) {
|
||||
// consider viewportSizeHint()
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AutoAdjustingTreeView::setStretchSection(int section) {
|
||||
stretch_section_ = section;
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void AutoAdjustingTreeView::setAutoHideSections(const QList<int>& sections) {
|
||||
auto_hide_cols_ = sections;
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void AutoAdjustingTreeView::setModel(QAbstractItemModel* model) {
|
||||
size_hints_.clear();
|
||||
QTreeView::setModel(model);
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
QSize AutoAdjustingTreeView::viewportSizeHint() const {
|
||||
bool preferred = sizePolicy().horizontalPolicy() & QSizePolicy::ShrinkFlag;
|
||||
auto m = model();
|
||||
auto* h = header();
|
||||
size_hints_.clear();
|
||||
|
||||
int width = 0;
|
||||
for (int i = 0, end = m ? m->columnCount() : 0; i < end; ++i) {
|
||||
size_hints_.push_back(h->sectionSizeHint(i));
|
||||
if (preferred || !auto_hide_cols_.contains(i))
|
||||
width += size_hints_.back();
|
||||
}
|
||||
|
||||
QSize main_size(width, sizeHintForRow(0) * ((!preferred || !m) ? 2 : m->rowCount()));
|
||||
|
||||
// add size for header
|
||||
QSize header_size(0, header()->isVisible() ? header()->height() : 0);
|
||||
|
||||
// add size for scrollbars
|
||||
QSize scrollbars(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
|
||||
horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
|
||||
|
||||
return main_size + header_size + scrollbars;
|
||||
}
|
||||
|
||||
void AutoAdjustingTreeView::resizeEvent(QResizeEvent* event) {
|
||||
auto* m = model();
|
||||
int columns = m ? m->columnCount() : 0;
|
||||
if ((int)size_hints_.size() != columns)
|
||||
viewportSizeHint();
|
||||
|
||||
// auto hide/show columns > 0, stretch last column to width
|
||||
int available_width = event->size().width();
|
||||
|
||||
int required_width = std::accumulate(size_hints_.begin(), size_hints_.end(), 0);
|
||||
std::vector<int> width = size_hints_;
|
||||
|
||||
// if required is larger than available width, try to hide some columns
|
||||
QListIterator<int> it(auto_hide_cols_);
|
||||
for (it.toBack(); it.hasPrevious() && required_width > available_width;) {
|
||||
int section = it.previous();
|
||||
required_width -= size_hints_[section];
|
||||
width[section] = 0;
|
||||
}
|
||||
|
||||
// extend width to current column width if possible
|
||||
for (int i = 0; i < columns; ++i) {
|
||||
if (i == stretch_section_)
|
||||
continue; // ignore auto-stretch section for now
|
||||
int delta = columnWidth(i) > 0 ? columnWidth(i) - width[i] : 0;
|
||||
if (delta < 0 || required_width + delta <= available_width) {
|
||||
width[i] += delta;
|
||||
required_width += delta;
|
||||
}
|
||||
}
|
||||
|
||||
// stretch section if there is still space available
|
||||
if (stretch_section_ >= 0 && stretch_section_ < (int)width.size() && width[stretch_section_] > 0 &&
|
||||
available_width > required_width)
|
||||
width[stretch_section_] += available_width - required_width;
|
||||
|
||||
// apply stuff
|
||||
for (int i = 0; i < columns; ++i)
|
||||
setColumnWidth(i, width[i]);
|
||||
}
|
||||
|
||||
TaskListView::TaskListView(QWidget* parent) : AutoAdjustingTreeView(parent) {
|
||||
setStretchSection(0);
|
||||
}
|
||||
TaskListView::TaskListView(QWidget* parent) : QTreeView(parent) {}
|
||||
|
||||
// dropping onto an item, should expand this item
|
||||
void TaskListView::dropEvent(QDropEvent* event) {
|
||||
@ -460,6 +369,64 @@ void TaskListView::dropEvent(QDropEvent* event) {
|
||||
if (event->isAccepted())
|
||||
expand(index);
|
||||
}
|
||||
|
||||
void TaskListView::setModel(QAbstractItemModel* model) {
|
||||
QTreeView::setModel(model);
|
||||
if (header()->count() >= 4) {
|
||||
header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
updateColumnWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskListView::dataChanged(const QModelIndex& /*topLeft*/, const QModelIndex& bottomRight,
|
||||
const QVector<int>& /*roles*/) {
|
||||
if (bottomRight.column() > 0) {
|
||||
updateColumnWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskListView::updateColumnWidth() {
|
||||
for (int i = 3; i > 0; --i) {
|
||||
header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
}
|
||||
|
||||
SolutionListView::SolutionListView(QWidget* parent) : QTreeView(parent) {}
|
||||
|
||||
void SolutionListView::setModel(QAbstractItemModel* model) {
|
||||
QTreeView::setModel(model);
|
||||
updateColumnWidth();
|
||||
}
|
||||
|
||||
void SolutionListView::dataChanged(const QModelIndex& /*topLeft*/, const QModelIndex& bottomRight,
|
||||
const QVector<int>& /*roles*/) {
|
||||
if (bottomRight.column() > 0) {
|
||||
updateColumnWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void SolutionListView::resizeEvent(QResizeEvent* e) {
|
||||
QTreeView::resizeEvent(e);
|
||||
updateColumnWidth();
|
||||
}
|
||||
|
||||
void SolutionListView::updateColumnWidth() {
|
||||
// do nothing if current model is not what we expect
|
||||
if (header()->count() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
|
||||
const int stretch_size = viewport()->size().width() - header()->sectionPosition(2);
|
||||
|
||||
const int content_size = sizeHintForColumn(2);
|
||||
|
||||
header()->resizeSection(2, std::max(stretch_size, content_size));
|
||||
}
|
||||
|
||||
} // namespace moveit_rviz_plugin
|
||||
|
||||
#include "moc_task_list_model.cpp"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2017, Bielefeld University
|
||||
* Copyright (c) 2020, Hamburg University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -47,6 +48,7 @@
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QTreeView>
|
||||
#include <QTableView>
|
||||
#include <memory>
|
||||
#include <QPointer>
|
||||
|
||||
@ -178,34 +180,34 @@ protected Q_SLOTS:
|
||||
void highlightStage(size_t id);
|
||||
};
|
||||
|
||||
class AutoAdjustingTreeView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int stretchSection READ stretchSection WRITE setStretchSection)
|
||||
|
||||
mutable std::vector<int> size_hints_; // size hints for sections
|
||||
QList<int> auto_hide_cols_; // auto-hiding sections
|
||||
int stretch_section_ = -1;
|
||||
|
||||
public:
|
||||
AutoAdjustingTreeView(QWidget* parent = nullptr);
|
||||
|
||||
int stretchSection() const { return stretch_section_; }
|
||||
void setStretchSection(int section);
|
||||
|
||||
void setAutoHideSections(const QList<int>& sections);
|
||||
|
||||
void setModel(QAbstractItemModel* model) override;
|
||||
QSize viewportSizeHint() const override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
};
|
||||
|
||||
class TaskListView : public AutoAdjustingTreeView
|
||||
class TaskListView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TaskListView(QWidget* parent = nullptr);
|
||||
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
|
||||
void setModel(QAbstractItemModel* model) override;
|
||||
void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles = QVector<int>()) override;
|
||||
|
||||
protected:
|
||||
void updateColumnWidth();
|
||||
};
|
||||
|
||||
class SolutionListView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SolutionListView(QWidget* parent = nullptr);
|
||||
|
||||
void setModel(QAbstractItemModel* model) override;
|
||||
void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
|
||||
const QVector<int>& roles = QVector<int>()) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
protected:
|
||||
void updateColumnWidth();
|
||||
};
|
||||
} // namespace moveit_rviz_plugin
|
||||
|
||||
@ -234,9 +234,6 @@ TaskViewPrivate::TaskViewPrivate(TaskView* q_ptr) : q_ptr(q_ptr), exec_action_cl
|
||||
tasks_view->setDropIndicatorShown(true);
|
||||
tasks_view->setDragEnabled(true);
|
||||
|
||||
solutions_view->setAutoHideSections({ 1, 2 });
|
||||
solutions_view->setStretchSection(2);
|
||||
|
||||
// init actions
|
||||
tasks_view->addActions({ actionAddLocalTask, actionRemoveTaskTreeRows });
|
||||
}
|
||||
@ -304,15 +301,15 @@ void TaskView::save(rviz::Config config) {
|
||||
write_splitter_sizes(d_ptr->tasks_property_splitter, "property_splitter");
|
||||
write_splitter_sizes(d_ptr->tasks_solutions_splitter, "solutions_splitter");
|
||||
|
||||
auto write_column_sizes = [&config](QTreeView* view, const QString& key) {
|
||||
auto write_column_sizes = [&config](QHeaderView* view, const QString& key) {
|
||||
rviz::Config group = config.mapMakeChild(key);
|
||||
for (int c = 0, end = view->header()->count(); c != end; ++c) {
|
||||
for (int c = 0, end = view->count(); c != end; ++c) {
|
||||
rviz::Config item = group.listAppendNew();
|
||||
item.setValue(view->columnWidth(c));
|
||||
item.setValue(view->sectionSize(c));
|
||||
}
|
||||
};
|
||||
write_column_sizes(d_ptr->tasks_view, "tasks_view_columns");
|
||||
write_column_sizes(d_ptr->solutions_view, "solutions_view_columns");
|
||||
write_column_sizes(d_ptr->tasks_view->header(), "tasks_view_columns");
|
||||
write_column_sizes(d_ptr->solutions_view->header(), "solutions_view_columns");
|
||||
|
||||
const QHeaderView* view = d_ptr->solutions_view->header();
|
||||
rviz::Config group = config.mapMakeChild("solution_sorting");
|
||||
@ -413,10 +410,10 @@ void TaskView::onCurrentStageChanged(const QModelIndex& current, const QModelInd
|
||||
}
|
||||
|
||||
// update the PropertyModel
|
||||
view = d_ptr->property_view;
|
||||
sm = view->selectionModel();
|
||||
QTreeView* pview = d_ptr->property_view;
|
||||
sm = pview->selectionModel();
|
||||
m = task ? task->getPropertyModel(task_index) : nullptr;
|
||||
view->setModel(m);
|
||||
pview->setModel(m);
|
||||
delete sm; // we don't store the selection model
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="">
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout1">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
@ -64,11 +64,23 @@
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="moveit_rviz_plugin::AutoAdjustingTreeView" name="solutions_view">
|
||||
<widget class="moveit_rviz_plugin::SolutionListView" name="solutions_view">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
@ -78,6 +90,15 @@
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideNone</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -87,15 +108,15 @@
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="">
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
@ -141,16 +162,16 @@
|
||||
<extends>QTreeView</extends>
|
||||
<header>task_list_model.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>moveit_rviz_plugin::AutoAdjustingTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>task_list_model.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>rviz::PropertyTreeWidget</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header location="global">rviz/properties/property_tree_widget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>moveit_rviz_plugin::SolutionListView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>task_list_model.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user