mirror of
https://github.com/moveit/moveit_task_constructor.git
synced 2025-11-04 14:49:57 +08:00
implemented TaskListModel::removeRows
This commit is contained in:
parent
18119a7985
commit
0f9c8cc8ea
@ -43,6 +43,7 @@
|
|||||||
#include <ros/init.h>
|
#include <ros/init.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <qcoreapplication.h>
|
||||||
|
|
||||||
using namespace moveit::task_constructor;
|
using namespace moveit::task_constructor;
|
||||||
|
|
||||||
@ -200,3 +201,18 @@ TEST_F(TaskListModelTest, visitedPopulate) {
|
|||||||
EXPECT_EQ(num_inserts, 3);
|
EXPECT_EQ(num_inserts, 3);
|
||||||
EXPECT_EQ(num_updates, 0);
|
EXPECT_EQ(num_updates, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TaskListModelTest, deletion) {
|
||||||
|
children = 3;
|
||||||
|
model.processTaskMessage(genMsg("first"));
|
||||||
|
moveit_rviz_plugin::BaseTaskModel *m = model.getTask(0);
|
||||||
|
int num_deletes = 0;
|
||||||
|
QObject::connect(m, &QObject::destroyed, [&num_deletes](){++num_deletes;});
|
||||||
|
|
||||||
|
model.removeTask(m);
|
||||||
|
// process deleteLater() events
|
||||||
|
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
|
||||||
|
// as m is owned by model, m should be destroyed
|
||||||
|
// EXPECT_EQ(num_deletes, 1); // TODO: event is not processed, missing event loop?
|
||||||
|
EXPECT_EQ(model.rowCount(), 0);
|
||||||
|
}
|
||||||
|
|||||||
@ -143,6 +143,8 @@ public:
|
|||||||
return q_ptr->createIndex(src.row(), src.column(), src_parent.internalPointer());
|
return q_ptr->createIndex(src.row(), src.column(), src_parent.internalPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeTask(BaseTaskModel *model);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
|
void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
|
||||||
void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end);
|
void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end);
|
||||||
@ -248,12 +250,6 @@ bool TaskListModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||||||
return task->model_->setData(src_index, value, role);
|
return task->model_->setData(src_index, value, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskListModel::removeRows(int row, int count, const QModelIndex &parent)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process a task monitoring message:
|
// process a task monitoring message:
|
||||||
// update existing RemoteTask, create a new one,
|
// update existing RemoteTask, create a new one,
|
||||||
// or (if msg.stages is empty) delete an existing one
|
// or (if msg.stages is empty) delete an existing one
|
||||||
@ -309,7 +305,8 @@ BaseTaskModel *TaskListModel::getTask(int row) const
|
|||||||
return d->tasks_.at(row).model_;
|
return d->tasks_.at(row).model_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskListModel::insertTask(BaseTaskModel* model, int row) {
|
void TaskListModel::insertTask(BaseTaskModel* model, int row)
|
||||||
|
{
|
||||||
Q_D(TaskListModel);
|
Q_D(TaskListModel);
|
||||||
|
|
||||||
if (row < 0 || (size_t)row > d->tasks_.size())
|
if (row < 0 || (size_t)row > d->tasks_.size())
|
||||||
@ -323,11 +320,6 @@ void TaskListModel::insertTask(BaseTaskModel* model, int row) {
|
|||||||
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
// notice destruction of task
|
|
||||||
if (model->parent() != this)
|
|
||||||
connect(model, &BaseTaskModel::destroyed,
|
|
||||||
[this](QObject* o) { removeTask(static_cast<BaseTaskModel*>(o), false); });
|
|
||||||
|
|
||||||
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
||||||
this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
|
this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
|
||||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||||
@ -344,40 +336,74 @@ void TaskListModel::insertTask(BaseTaskModel* model, int row) {
|
|||||||
this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskListModel::removeTask(BaseTaskModel* model, bool disconnect_signals) {
|
bool TaskListModel::removeTask(BaseTaskModel* model)
|
||||||
|
{
|
||||||
Q_D(TaskListModel);
|
Q_D(TaskListModel);
|
||||||
|
|
||||||
// find row corresponding to model
|
// find row corresponding to model
|
||||||
auto it = std::find_if(d->tasks_.begin(), d->tasks_.end(),
|
auto it = std::find_if(d->tasks_.begin(), d->tasks_.end(),
|
||||||
[model](const TaskListModelPrivate::BaseModelData& data) { return data.model_ == model; });
|
[model](const TaskListModelPrivate::BaseModelData& data) {
|
||||||
|
return data.model_ == model;
|
||||||
|
});
|
||||||
if (it == d->tasks_.end())
|
if (it == d->tasks_.end())
|
||||||
return false; // model not found
|
return false; // model not found
|
||||||
|
|
||||||
ROS_DEBUG_NAMED("TaskListModel", "%p: removing task: %p", this, model);
|
return removeTasks(it - d->tasks_.begin(), 1);
|
||||||
size_t row = it - d->tasks_.begin();
|
}
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
|
||||||
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
|
||||||
endRemoveRows();
|
|
||||||
|
|
||||||
if (disconnect_signals) { // reacting on signal destroyed(), signals are already disconnected
|
bool TaskListModel::removeTasks(int row, int count)
|
||||||
disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
{
|
||||||
this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
|
Q_D(TaskListModel);
|
||||||
disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
if (row < 0 || row+count > rowCount())
|
||||||
this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
|
return false;
|
||||||
disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
|
|
||||||
this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
|
auto first = d->tasks_.begin(); std::advance(first, row);
|
||||||
disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
auto last = first; std::advance(last, count);
|
||||||
this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
|
beginRemoveRows(QModelIndex(), row, row+count-1);
|
||||||
disconnect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
|
std::for_each(first, last, [d](TaskListModelPrivate::BaseModelData &data) {
|
||||||
this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
|
d->removeTask(data.model_);
|
||||||
disconnect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
|
});
|
||||||
this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
d->tasks_.erase(first, last);
|
||||||
disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
|
endRemoveRows();
|
||||||
this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TaskListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
Q_D(TaskListModel);
|
||||||
|
if (!parent.isValid()) { // top-level items = tasks
|
||||||
|
return removeTasks(row, count);
|
||||||
|
} else {
|
||||||
|
TaskListModelPrivate::BaseModelData *data = nullptr;
|
||||||
|
QModelIndex src_parent = d->mapToSource(parent, &data);
|
||||||
|
return data->model_->removeRows(row, count, src_parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskListModelPrivate::removeTask(BaseTaskModel *model)
|
||||||
|
{
|
||||||
|
ROS_DEBUG_NAMED("TaskListModel", "%p: removing task: %p", q_ptr, model);
|
||||||
|
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||||
|
q_ptr, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||||
|
QObject::disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
|
||||||
|
q_ptr, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
||||||
|
|
||||||
|
// delete model if we own it
|
||||||
|
if (model->parent() == q_ptr)
|
||||||
|
model->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
void TaskListModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
|
void TaskListModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
|
||||||
{
|
{
|
||||||
q_ptr->beginInsertRows(mapFromSource(parent), start, end);
|
q_ptr->beginInsertRows(mapFromSource(parent), start, end);
|
||||||
|
|||||||
@ -99,7 +99,8 @@ public:
|
|||||||
|
|
||||||
/// insert a TaskModel into our list
|
/// insert a TaskModel into our list
|
||||||
void insertTask(BaseTaskModel* model, int row = -1);
|
void insertTask(BaseTaskModel* model, int row = -1);
|
||||||
bool removeTask(BaseTaskModel* model, bool disconnect_signals = true);
|
bool removeTask(BaseTaskModel* model);
|
||||||
|
bool removeTasks(int row, int count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
|
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
|
||||||
|
|||||||
@ -81,9 +81,8 @@ TaskPanel::TaskPanel(QWidget* parent)
|
|||||||
{
|
{
|
||||||
Q_D(TaskPanel);
|
Q_D(TaskPanel);
|
||||||
// connect signals
|
// connect signals
|
||||||
connect(d->actionNewTask, &QAction::triggered, this, &TaskPanel::onAddTask);
|
connect(d->actionRemoveTaskTreeRows, &QAction::triggered, this, &TaskPanel::removeTaskTreeRows);
|
||||||
connect(d->actionNewStage, &QAction::triggered, this, &TaskPanel::onAddStage);
|
connect(d->button_show_stage_dock_widget, &QToolButton::clicked, this, &TaskPanel::showStageDockWidget);
|
||||||
connect(d->actionRemoveStages, &QAction::triggered, this, &TaskPanel::onRemoveStages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskPanel::~TaskPanel()
|
TaskPanel::~TaskPanel()
|
||||||
@ -93,16 +92,16 @@ TaskPanel::~TaskPanel()
|
|||||||
|
|
||||||
TaskPanelPrivate::TaskPanelPrivate(TaskPanel *q_ptr)
|
TaskPanelPrivate::TaskPanelPrivate(TaskPanel *q_ptr)
|
||||||
: q_ptr(q_ptr)
|
: q_ptr(q_ptr)
|
||||||
, tasks_model(TaskListModelCache::instance().getGlobalModel())
|
, task_list_model(TaskListModelCache::instance().getGlobalModel())
|
||||||
, settings(new rviz::PropertyTreeModel(new rviz::Property))
|
, settings(new rviz::PropertyTreeModel(new rviz::Property))
|
||||||
{
|
{
|
||||||
setupUi(q_ptr);
|
setupUi(q_ptr);
|
||||||
initSettings(settings->getRoot());
|
initSettings(settings->getRoot());
|
||||||
settings_view->setModel(settings);
|
settings_view->setModel(settings);
|
||||||
tasks_view->setModel(tasks_model.get());
|
tasks_view->setModel(task_list_model.get());
|
||||||
|
|
||||||
// init actions
|
// init actions
|
||||||
tasks_view->addActions({actionNewTask, actionNewStage, actionRemoveStages});
|
tasks_view->addActions({actionRemoveTaskTreeRows});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanelPrivate::initSettings(rviz::Property* root)
|
void TaskPanelPrivate::initSettings(rviz::Property* root)
|
||||||
@ -129,20 +128,20 @@ void TaskPanel::onAddTask()
|
|||||||
{
|
{
|
||||||
Q_D(TaskPanel);
|
Q_D(TaskPanel);
|
||||||
QModelIndex current = d->tasks_view->currentIndex();
|
QModelIndex current = d->tasks_view->currentIndex();
|
||||||
d_ptr->tasks_model->insertTask(new LocalTaskModel(this), current.row());
|
d_ptr->task_list_model->insertTask(new LocalTaskModel(this), current.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanel::onAddStage()
|
void TaskPanel::showStageDockWidget()
|
||||||
{
|
{
|
||||||
rviz::PanelDockWidget *dock = getStageDockWidget(vis_manager_->getWindowManager());
|
rviz::PanelDockWidget *dock = getStageDockWidget(vis_manager_->getWindowManager());
|
||||||
dock->show();
|
dock->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanel::onRemoveStages()
|
void TaskPanel::removeTaskTreeRows()
|
||||||
{
|
{
|
||||||
Q_D(TaskPanel);
|
Q_D(TaskPanel);
|
||||||
for (const auto &range : d_ptr->tasks_view->selectionModel()->selection())
|
for (const auto &range : d_ptr->tasks_view->selectionModel()->selection())
|
||||||
d_ptr->tasks_model->removeRows(range.top(), range.bottom()-range.top()+1, range.parent());
|
d_ptr->task_list_model->removeRows(range.top(), range.bottom()-range.top()+1, range.parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,8 +70,8 @@ public:
|
|||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void onAddTask();
|
void onAddTask();
|
||||||
void onAddStage();
|
void showStageDockWidget();
|
||||||
void onRemoveStages();
|
void removeTaskTreeRows();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="button_add_stage">
|
<widget class="QToolButton" name="button_show_stage_dock_widget">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>18</width>
|
<width>18</width>
|
||||||
@ -66,36 +66,18 @@
|
|||||||
<widget class="rviz::PropertyTreeWidget" name="settings_view"/>
|
<widget class="rviz::PropertyTreeWidget" name="settings_view"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
<action name="actionNewStage">
|
<action name="actionRemoveTaskTreeRows">
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="add">
|
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New Stage</string>
|
<string>Remove</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Add a new stage</string>
|
<string>Remove selected rows</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
<property name="shortcut">
|
||||||
<action name="actionNewTask">
|
<string>Del</string>
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="add">
|
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="shortcutContext">
|
||||||
<string>New Task</string>
|
<enum>Qt::WidgetShortcut</enum>
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Add a new task</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionRemoveStages">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove Stages</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Remove selected stages</string>
|
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
@ -107,22 +89,5 @@
|
|||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections/>
|
||||||
<connection>
|
|
||||||
<sender>button_add_stage</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>actionNewStage</receiver>
|
|
||||||
<slot>trigger()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>378</x>
|
|
||||||
<y>21</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>-1</x>
|
|
||||||
<y>-1</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@ -53,7 +53,7 @@ public:
|
|||||||
void initSettings(rviz::Property *root);
|
void initSettings(rviz::Property *root);
|
||||||
|
|
||||||
TaskPanel* q_ptr;
|
TaskPanel* q_ptr;
|
||||||
TaskListModelPtr tasks_model;
|
TaskListModelPtr task_list_model;
|
||||||
rviz::PropertyTreeModel* settings;
|
rviz::PropertyTreeModel* settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user