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 <gtest/gtest.h>
|
||||
#include <initializer_list>
|
||||
#include <qcoreapplication.h>
|
||||
|
||||
using namespace moveit::task_constructor;
|
||||
|
||||
@ -200,3 +201,18 @@ TEST_F(TaskListModelTest, visitedPopulate) {
|
||||
EXPECT_EQ(num_inserts, 3);
|
||||
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());
|
||||
}
|
||||
|
||||
void removeTask(BaseTaskModel *model);
|
||||
|
||||
private:
|
||||
void _q_sourceRowsAboutToBeInserted(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);
|
||||
}
|
||||
|
||||
bool TaskListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
// process a task monitoring message:
|
||||
// update existing RemoteTask, create a new 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_;
|
||||
}
|
||||
|
||||
void TaskListModel::insertTask(BaseTaskModel* model, int row) {
|
||||
void TaskListModel::insertTask(BaseTaskModel* model, int row)
|
||||
{
|
||||
Q_D(TaskListModel);
|
||||
|
||||
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));
|
||||
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)),
|
||||
this, SLOT(_q_sourceRowsAboutToBeInserted(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>)));
|
||||
}
|
||||
|
||||
bool TaskListModel::removeTask(BaseTaskModel* model, bool disconnect_signals) {
|
||||
bool TaskListModel::removeTask(BaseTaskModel* model)
|
||||
{
|
||||
Q_D(TaskListModel);
|
||||
|
||||
// find row corresponding to model
|
||||
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())
|
||||
return false; // model not found
|
||||
|
||||
ROS_DEBUG_NAMED("TaskListModel", "%p: removing task: %p", this, model);
|
||||
size_t row = it - d->tasks_.begin();
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
||||
endRemoveRows();
|
||||
return removeTasks(it - d->tasks_.begin(), 1);
|
||||
}
|
||||
|
||||
if (disconnect_signals) { // reacting on signal destroyed(), signals are already disconnected
|
||||
disconnect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
||||
this, SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex,int,int)));
|
||||
disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(_q_sourceRowsInserted(QModelIndex,int,int)));
|
||||
disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(_q_sourceRowsRemoved(QModelIndex,int,int)));
|
||||
disconnect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||
this, SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||
disconnect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||
this, SLOT(_q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)));
|
||||
disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
|
||||
this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
|
||||
}
|
||||
bool TaskListModel::removeTasks(int row, int count)
|
||||
{
|
||||
Q_D(TaskListModel);
|
||||
if (row < 0 || row+count > rowCount())
|
||||
return false;
|
||||
|
||||
auto first = d->tasks_.begin(); std::advance(first, row);
|
||||
auto last = first; std::advance(last, count);
|
||||
beginRemoveRows(QModelIndex(), row, row+count-1);
|
||||
std::for_each(first, last, [d](TaskListModelPrivate::BaseModelData &data) {
|
||||
d->removeTask(data.model_);
|
||||
});
|
||||
d->tasks_.erase(first, last);
|
||||
endRemoveRows();
|
||||
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)
|
||||
{
|
||||
q_ptr->beginInsertRows(mapFromSource(parent), start, end);
|
||||
|
||||
@ -99,7 +99,8 @@ public:
|
||||
|
||||
/// insert a TaskModel into our list
|
||||
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:
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
|
||||
|
||||
@ -81,9 +81,8 @@ TaskPanel::TaskPanel(QWidget* parent)
|
||||
{
|
||||
Q_D(TaskPanel);
|
||||
// connect signals
|
||||
connect(d->actionNewTask, &QAction::triggered, this, &TaskPanel::onAddTask);
|
||||
connect(d->actionNewStage, &QAction::triggered, this, &TaskPanel::onAddStage);
|
||||
connect(d->actionRemoveStages, &QAction::triggered, this, &TaskPanel::onRemoveStages);
|
||||
connect(d->actionRemoveTaskTreeRows, &QAction::triggered, this, &TaskPanel::removeTaskTreeRows);
|
||||
connect(d->button_show_stage_dock_widget, &QToolButton::clicked, this, &TaskPanel::showStageDockWidget);
|
||||
}
|
||||
|
||||
TaskPanel::~TaskPanel()
|
||||
@ -93,16 +92,16 @@ TaskPanel::~TaskPanel()
|
||||
|
||||
TaskPanelPrivate::TaskPanelPrivate(TaskPanel *q_ptr)
|
||||
: q_ptr(q_ptr)
|
||||
, tasks_model(TaskListModelCache::instance().getGlobalModel())
|
||||
, task_list_model(TaskListModelCache::instance().getGlobalModel())
|
||||
, settings(new rviz::PropertyTreeModel(new rviz::Property))
|
||||
{
|
||||
setupUi(q_ptr);
|
||||
initSettings(settings->getRoot());
|
||||
settings_view->setModel(settings);
|
||||
tasks_view->setModel(tasks_model.get());
|
||||
tasks_view->setModel(task_list_model.get());
|
||||
|
||||
// init actions
|
||||
tasks_view->addActions({actionNewTask, actionNewStage, actionRemoveStages});
|
||||
tasks_view->addActions({actionRemoveTaskTreeRows});
|
||||
}
|
||||
|
||||
void TaskPanelPrivate::initSettings(rviz::Property* root)
|
||||
@ -129,20 +128,20 @@ void TaskPanel::onAddTask()
|
||||
{
|
||||
Q_D(TaskPanel);
|
||||
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());
|
||||
dock->show();
|
||||
}
|
||||
|
||||
void TaskPanel::onRemoveStages()
|
||||
void TaskPanel::removeTaskTreeRows()
|
||||
{
|
||||
Q_D(TaskPanel);
|
||||
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:
|
||||
void onAddTask();
|
||||
void onAddStage();
|
||||
void onRemoveStages();
|
||||
void showStageDockWidget();
|
||||
void removeTaskTreeRows();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_add_stage">
|
||||
<widget class="QToolButton" name="button_show_stage_dock_widget">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
@ -66,36 +66,18 @@
|
||||
<widget class="rviz::PropertyTreeWidget" name="settings_view"/>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionNewStage">
|
||||
<property name="icon">
|
||||
<iconset theme="add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<action name="actionRemoveTaskTreeRows">
|
||||
<property name="text">
|
||||
<string>New Stage</string>
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add a new stage</string>
|
||||
<string>Remove selected rows</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNewTask">
|
||||
<property name="icon">
|
||||
<iconset theme="add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New Task</string>
|
||||
</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 name="shortcutContext">
|
||||
<enum>Qt::WidgetShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
@ -107,22 +89,5 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<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>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@ -53,7 +53,7 @@ public:
|
||||
void initSettings(rviz::Property *root);
|
||||
|
||||
TaskPanel* q_ptr;
|
||||
TaskListModelPtr tasks_model;
|
||||
TaskListModelPtr task_list_model;
|
||||
rviz::PropertyTreeModel* settings;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user