mirror of
https://github.com/moveit/moveit_task_constructor.git
synced 2025-11-04 14:49:57 +08:00
LocalTaskModel: populate via drag-n-drop
This commit is contained in:
parent
1ae3793a9d
commit
953224eba1
@ -36,21 +36,24 @@
|
|||||||
|
|
||||||
#include "factory_model.h"
|
#include "factory_model.h"
|
||||||
#include <rviz/load_resource.h>
|
#include <rviz/load_resource.h>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
namespace moveit_rviz_plugin {
|
namespace moveit_rviz_plugin {
|
||||||
|
|
||||||
FactoryModel::FactoryModel(rviz::Factory *factory, QObject *parent)
|
FactoryModel::FactoryModel(rviz::Factory &factory, const QString& mime_type, QObject *parent)
|
||||||
: QStandardItemModel(parent)
|
: QStandardItemModel(parent)
|
||||||
|
, mime_type_(mime_type)
|
||||||
{
|
{
|
||||||
setHorizontalHeaderLabels({tr("Name")});
|
setHorizontalHeaderLabels({tr("Name")});
|
||||||
fillTree(factory);
|
fillTree(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FactoryModel::fillTree(rviz::Factory *factory)
|
void FactoryModel::fillTree(rviz::Factory &factory)
|
||||||
{
|
{
|
||||||
QIcon default_package_icon = rviz::loadPixmap( "package://rviz/icons/default_package_icon.png" );
|
QIcon default_package_icon = rviz::loadPixmap( "package://rviz/icons/default_package_icon.png" );
|
||||||
|
|
||||||
QStringList classes = factory->getDeclaredClassIds();
|
QStringList classes = factory.getDeclaredClassIds();
|
||||||
classes.sort();
|
classes.sort();
|
||||||
|
|
||||||
// Map from package names to the corresponding top-level tree widget items.
|
// Map from package names to the corresponding top-level tree widget items.
|
||||||
@ -58,7 +61,7 @@ void FactoryModel::fillTree(rviz::Factory *factory)
|
|||||||
|
|
||||||
for(const QString& lookup_name : classes)
|
for(const QString& lookup_name : classes)
|
||||||
{
|
{
|
||||||
QString package = factory->getClassPackage(lookup_name);
|
QString package = factory.getClassPackage(lookup_name);
|
||||||
|
|
||||||
QStandardItem* package_item;
|
QStandardItem* package_item;
|
||||||
auto mi = package_items.find(package);
|
auto mi = package_items.find(package);
|
||||||
@ -72,13 +75,31 @@ void FactoryModel::fillTree(rviz::Factory *factory)
|
|||||||
{
|
{
|
||||||
package_item = mi->second;
|
package_item = mi->second;
|
||||||
}
|
}
|
||||||
QStandardItem* class_item = new QStandardItem(factory->getIcon(lookup_name),
|
QStandardItem* class_item = new QStandardItem(factory.getIcon(lookup_name),
|
||||||
factory->getClassName(lookup_name));
|
factory.getClassName(lookup_name));
|
||||||
class_item->setWhatsThis(factory->getClassDescription(lookup_name));
|
class_item->setWhatsThis(factory.getClassDescription(lookup_name));
|
||||||
class_item->setData(lookup_name);
|
class_item->setData(lookup_name, Qt::UserRole);
|
||||||
class_item->setDragEnabled(true);
|
class_item->setDragEnabled(true);
|
||||||
package_item->appendRow(class_item);
|
package_item->appendRow(class_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList FactoryModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
return { mime_type_ };
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData *FactoryModel::mimeData(const QModelIndexList &indexes) const
|
||||||
|
{
|
||||||
|
QSet<int> rows_considered;
|
||||||
|
QMimeData* mime_data = new QMimeData();
|
||||||
|
for (const auto &index : indexes) {
|
||||||
|
if (rows_considered.contains(index.row()))
|
||||||
|
continue;
|
||||||
|
// mime data is lookup_name
|
||||||
|
mime_data->setData(mime_type_, index.data(Qt::UserRole).toByteArray());
|
||||||
|
}
|
||||||
|
return mime_data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,10 +43,14 @@ namespace moveit_rviz_plugin {
|
|||||||
|
|
||||||
class FactoryModel : public QStandardItemModel
|
class FactoryModel : public QStandardItemModel
|
||||||
{
|
{
|
||||||
void fillTree(rviz::Factory *factory);
|
QString mime_type_;
|
||||||
|
void fillTree(rviz::Factory& factory);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FactoryModel(rviz::Factory *factory, QObject *parent = nullptr);
|
FactoryModel(rviz::Factory& factory, const QString &mime_type, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
|
QMimeData* mimeData(const QModelIndexList &indexes) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,10 +35,13 @@
|
|||||||
/* Author: Robert Haschke */
|
/* Author: Robert Haschke */
|
||||||
|
|
||||||
#include "local_task_model.h"
|
#include "local_task_model.h"
|
||||||
|
#include "factory_model.h"
|
||||||
#include <container_p.h>
|
#include <container_p.h>
|
||||||
|
|
||||||
#include <ros/console.h>
|
#include <ros/console.h>
|
||||||
|
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
using namespace moveit::task_constructor;
|
using namespace moveit::task_constructor;
|
||||||
|
|
||||||
namespace moveit_rviz_plugin {
|
namespace moveit_rviz_plugin {
|
||||||
@ -79,6 +82,13 @@ LocalTaskModel::LocalTaskModel(QObject *parent)
|
|||||||
root_ = pimpl();
|
root_ = pimpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalTaskModel::LocalTaskModel(Stage::pointer &&container, QObject *parent)
|
||||||
|
: BaseTaskModel(parent)
|
||||||
|
, Task(std::move(container))
|
||||||
|
{
|
||||||
|
root_ = pimpl();
|
||||||
|
}
|
||||||
|
|
||||||
int LocalTaskModel::rowCount(const QModelIndex &parent) const
|
int LocalTaskModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.column() > 0)
|
if (parent.column() > 0)
|
||||||
@ -120,7 +130,9 @@ Qt::ItemFlags LocalTaskModel::flags(const QModelIndex &index) const
|
|||||||
{
|
{
|
||||||
Qt::ItemFlags flags = BaseTaskModel::flags(index);
|
Qt::ItemFlags flags = BaseTaskModel::flags(index);
|
||||||
ContainerBasePrivate *c = dynamic_cast<ContainerBasePrivate*>(node(index));
|
ContainerBasePrivate *c = dynamic_cast<ContainerBasePrivate*>(node(index));
|
||||||
if (c) flags |= Qt::ItemIsDropEnabled;
|
// dropping into containers is enabled
|
||||||
|
if (c && stage_factory_)
|
||||||
|
flags |= Qt::ItemIsDropEnabled;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,4 +169,34 @@ bool LocalTaskModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalTaskModel::setStageFactory(const StageFactoryPtr &factory)
|
||||||
|
{
|
||||||
|
stage_factory_ = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalTaskModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(column);
|
||||||
|
|
||||||
|
if (!stage_factory_ || (flags_ & IS_RUNNING))
|
||||||
|
return false;
|
||||||
|
const QString mime_type = stage_factory_->mimeType();
|
||||||
|
if (!mime->hasFormat(mime_type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ContainerBasePrivate *c = dynamic_cast<ContainerBasePrivate*>(node(parent));
|
||||||
|
Q_ASSERT(c);
|
||||||
|
|
||||||
|
QString error;
|
||||||
|
moveit::task_constructor::Stage* stage
|
||||||
|
= stage_factory_->makeRaw(mime->data(mime_type), &error);
|
||||||
|
if (!stage)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
beginInsertRows(parent, row, row);
|
||||||
|
static_cast<ContainerBase*>(c->me())->insert(moveit::task_constructor::Stage::pointer(stage), row);
|
||||||
|
endInsertRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,12 +48,14 @@ class LocalTaskModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
typedef moveit::task_constructor::StagePrivate Node;
|
typedef moveit::task_constructor::StagePrivate Node;
|
||||||
Node *root_;
|
Node *root_;
|
||||||
|
StageFactoryPtr stage_factory_;
|
||||||
|
|
||||||
inline Node* node(const QModelIndex &index) const;
|
inline Node* node(const QModelIndex &index) const;
|
||||||
QModelIndex index(Node *n) const;
|
QModelIndex index(Node *n) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LocalTaskModel(QObject *parent = nullptr);
|
LocalTaskModel(QObject *parent = nullptr);
|
||||||
|
LocalTaskModel(ContainerBase::pointer &&container, QObject *parent = nullptr);
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
@ -62,6 +64,10 @@ public:
|
|||||||
Qt::ItemFlags flags(const QModelIndex & index) const override;
|
Qt::ItemFlags flags(const QModelIndex & index) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
|
||||||
|
/// providing a StageFactory makes the model accepting drops
|
||||||
|
void setStageFactory(const StageFactoryPtr &factory);
|
||||||
|
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,10 +38,11 @@
|
|||||||
|
|
||||||
#ifndef Q_MOC_RUN
|
#ifndef Q_MOC_RUN
|
||||||
#include <pluginlib/class_loader.h>
|
#include <pluginlib/class_loader.h>
|
||||||
|
#include <rviz/load_resource.h>
|
||||||
|
#include <functional>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <rviz/factory.h>
|
#include <rviz/factory.h>
|
||||||
#include <rviz/load_resource.h>
|
|
||||||
|
|
||||||
namespace moveit_rviz_plugin {
|
namespace moveit_rviz_plugin {
|
||||||
|
|
||||||
@ -55,11 +56,12 @@ private:
|
|||||||
QString package_;
|
QString package_;
|
||||||
QString name_;
|
QString name_;
|
||||||
QString description_;
|
QString description_;
|
||||||
Type*(*factory_function_)();
|
std::function<Type*()> factory_function_;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PluginlibFactory( const QString& package, const QString& base_class_type )
|
PluginlibFactory( const QString& package, const QString& base_class_type )
|
||||||
|
: mime_type_(QString("application/%1/%2").arg(package, base_class_type))
|
||||||
{
|
{
|
||||||
class_loader_ = new pluginlib::ClassLoader<Type>( package.toStdString(), base_class_type.toStdString() );
|
class_loader_ = new pluginlib::ClassLoader<Type>( package.toStdString(), base_class_type.toStdString() );
|
||||||
}
|
}
|
||||||
@ -68,56 +70,58 @@ public:
|
|||||||
delete class_loader_;
|
delete class_loader_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// retrieve mime type used for given factory
|
||||||
|
QString mimeType() const {
|
||||||
|
return mime_type_;
|
||||||
|
}
|
||||||
|
|
||||||
virtual QStringList getDeclaredClassIds()
|
virtual QStringList getDeclaredClassIds()
|
||||||
{
|
{
|
||||||
QStringList ids;
|
QStringList ids;
|
||||||
std::vector<std::string> std_ids = class_loader_->getDeclaredClasses();
|
for(const auto& record : built_ins_)
|
||||||
for( size_t i = 0; i < std_ids.size(); i++ )
|
ids.push_back(record.class_id_);
|
||||||
{
|
for (const auto& id : class_loader_->getDeclaredClasses()) {
|
||||||
ids.push_back( QString::fromStdString( std_ids[ i ]));
|
QString sid = QString::fromStdString(id);
|
||||||
}
|
if (ids.contains(sid)) continue; // built_in take precedence
|
||||||
typename QHash<QString, BuiltInClassRecord>::const_iterator iter;
|
ids.push_back(sid);
|
||||||
for( iter = built_ins_.begin(); iter != built_ins_.end(); iter++ )
|
|
||||||
{
|
|
||||||
ids.push_back( iter.key() );
|
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QString getClassDescription( const QString& class_id ) const
|
virtual QString getClassDescription( const QString& class_id ) const
|
||||||
{
|
{
|
||||||
typename QHash<QString, BuiltInClassRecord>::const_iterator iter = built_ins_.find( class_id );
|
auto it = built_ins_.find( class_id );
|
||||||
if( iter != built_ins_.end() )
|
if( it != built_ins_.end() )
|
||||||
{
|
{
|
||||||
return iter->description_;
|
return it->description_;
|
||||||
}
|
}
|
||||||
return QString::fromStdString( class_loader_->getClassDescription( class_id.toStdString() ));
|
return QString::fromStdString( class_loader_->getClassDescription( class_id.toStdString() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QString getClassName( const QString& class_id ) const
|
virtual QString getClassName( const QString& class_id ) const
|
||||||
{
|
{
|
||||||
typename QHash<QString, BuiltInClassRecord>::const_iterator iter = built_ins_.find( class_id );
|
auto it = built_ins_.find( class_id );
|
||||||
if( iter != built_ins_.end() )
|
if( it != built_ins_.end() )
|
||||||
{
|
{
|
||||||
return iter->name_;
|
return it->name_;
|
||||||
}
|
}
|
||||||
return QString::fromStdString( class_loader_->getName( class_id.toStdString() ));
|
return QString::fromStdString( class_loader_->getName( class_id.toStdString() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QString getClassPackage( const QString& class_id ) const
|
virtual QString getClassPackage( const QString& class_id ) const
|
||||||
{
|
{
|
||||||
typename QHash<QString, BuiltInClassRecord>::const_iterator iter = built_ins_.find( class_id );
|
auto it = built_ins_.find( class_id );
|
||||||
if( iter != built_ins_.end() )
|
if( it != built_ins_.end() )
|
||||||
{
|
{
|
||||||
return iter->package_;
|
return it->package_;
|
||||||
}
|
}
|
||||||
return QString::fromStdString( class_loader_->getClassPackage( class_id.toStdString() ));
|
return QString::fromStdString( class_loader_->getClassPackage( class_id.toStdString() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QString getPluginManifestPath( const QString& class_id ) const
|
virtual QString getPluginManifestPath( const QString& class_id ) const
|
||||||
{
|
{
|
||||||
typename QHash<QString, BuiltInClassRecord>::const_iterator iter = built_ins_.find( class_id );
|
auto it = built_ins_.find( class_id );
|
||||||
if( iter != built_ins_.end() )
|
if( it != built_ins_.end() )
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -140,8 +144,8 @@ public:
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void addBuiltInClass( const QString& package, const QString& name, const QString& description,
|
void addBuiltInClass(const QString& package, const QString& name, const QString& description,
|
||||||
Type* (*factory_function)() )
|
const std::function<Type*()>& factory_function)
|
||||||
{
|
{
|
||||||
BuiltInClassRecord record;
|
BuiltInClassRecord record;
|
||||||
record.class_id_ = package + "/" + name;
|
record.class_id_ = package + "/" + name;
|
||||||
@ -151,8 +155,12 @@ public:
|
|||||||
record.factory_function_ = factory_function;
|
record.factory_function_ = factory_function;
|
||||||
built_ins_[ record.class_id_ ] = record;
|
built_ins_[ record.class_id_ ] = record;
|
||||||
}
|
}
|
||||||
|
template <class Derived>
|
||||||
|
void addBuiltInClass(const QString& name, const QString& description)
|
||||||
|
{
|
||||||
|
addBuiltInClass(ROS_PACKAGE_NAME, name, description, [](){return new Derived();});
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
/** @brief Instantiate and return a instance of a subclass of Type using our
|
/** @brief Instantiate and return a instance of a subclass of Type using our
|
||||||
* pluginlib::ClassLoader.
|
* pluginlib::ClassLoader.
|
||||||
* @param class_id A string identifying the class uniquely among
|
* @param class_id A string identifying the class uniquely among
|
||||||
@ -193,6 +201,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const QString mime_type_;
|
||||||
pluginlib::ClassLoader<Type>* class_loader_;
|
pluginlib::ClassLoader<Type>* class_loader_;
|
||||||
QHash<QString, BuiltInClassRecord> built_ins_;
|
QHash<QString, BuiltInClassRecord> built_ins_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,8 +37,10 @@
|
|||||||
#include "task_list_model.h"
|
#include "task_list_model.h"
|
||||||
#include "local_task_model.h"
|
#include "local_task_model.h"
|
||||||
#include "remote_task_model.h"
|
#include "remote_task_model.h"
|
||||||
|
#include "factory_model.h"
|
||||||
|
|
||||||
#include <ros/console.h>
|
#include <ros/console.h>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
namespace moveit_rviz_plugin {
|
namespace moveit_rviz_plugin {
|
||||||
|
|
||||||
@ -70,6 +72,21 @@ Qt::ItemFlags BaseTaskModel::flags(const QModelIndex &index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StageFactoryPtr getStageFactory()
|
||||||
|
{
|
||||||
|
static std::weak_ptr<StageFactory> factory;
|
||||||
|
if (!factory.expired())
|
||||||
|
return factory.lock();
|
||||||
|
|
||||||
|
StageFactoryPtr result(new StageFactory("moveit_task_constructor",
|
||||||
|
"moveit::task_constructor::Stage"));
|
||||||
|
// Hm. pluglinlib / ClassLoader cannot instantiate classes in implicitly loaded libs
|
||||||
|
result->addBuiltInClass<moveit::task_constructor::SerialContainer>("Serial Container", "");
|
||||||
|
factory = result; // remember for future uses
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TaskListModelPrivate {
|
class TaskListModelPrivate {
|
||||||
public:
|
public:
|
||||||
Q_DECLARE_PUBLIC(TaskListModel)
|
Q_DECLARE_PUBLIC(TaskListModel)
|
||||||
@ -91,6 +108,9 @@ public:
|
|||||||
// if task is removed locally from tasks vector, it is marked with a nullptr
|
// if task is removed locally from tasks vector, it is marked with a nullptr
|
||||||
std::map<std::string, RemoteTaskModel*> remote_tasks_;
|
std::map<std::string, RemoteTaskModel*> remote_tasks_;
|
||||||
|
|
||||||
|
// factory used to create stages
|
||||||
|
StageFactoryPtr stage_factory_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TaskListModelPrivate(TaskListModel* q_ptr) : q_ptr(q_ptr) {}
|
TaskListModelPrivate(TaskListModel* q_ptr) : q_ptr(q_ptr) {}
|
||||||
|
|
||||||
@ -217,13 +237,33 @@ Qt::ItemFlags TaskListModel::flags(const QModelIndex &index) const
|
|||||||
{
|
{
|
||||||
Q_D(const TaskListModel);
|
Q_D(const TaskListModel);
|
||||||
|
|
||||||
if (!index.isValid())
|
if (!index.isValid()) {
|
||||||
return QAbstractItemModel::flags(index);
|
Qt::ItemFlags f = QAbstractItemModel::flags(index);
|
||||||
|
// dropping at root will create a new task
|
||||||
|
if (d->stage_factory_)
|
||||||
|
f |= Qt::ItemIsDropEnabled;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
QModelIndex src_index = d->mapToSource(index);
|
QModelIndex src_index = d->mapToSource(index);
|
||||||
return src_index.model()->flags(src_index);
|
return src_index.model()->flags(src_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TaskListModel::setStageFactory(const StageFactoryPtr &factory)
|
||||||
|
{
|
||||||
|
Q_D(TaskListModel);
|
||||||
|
d->stage_factory_ = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList TaskListModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
Q_D(const TaskListModel);
|
||||||
|
QStringList result;
|
||||||
|
if (d->stage_factory_)
|
||||||
|
result << d->stage_factory_->mimeType();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant TaskListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant TaskListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||||
@ -309,6 +349,9 @@ void TaskListModel::insertTask(BaseTaskModel* model, int row)
|
|||||||
auto it = d->tasks_.begin();
|
auto it = d->tasks_.begin();
|
||||||
std::advance(it, row);
|
std::advance(it, row);
|
||||||
|
|
||||||
|
if (LocalTaskModel* lm = dynamic_cast<LocalTaskModel*>(model))
|
||||||
|
lm->setStageFactory(d->stage_factory_);
|
||||||
|
|
||||||
ROS_DEBUG_NAMED(LOGNAME, "%p: inserting task: %p", this, model);
|
ROS_DEBUG_NAMED(LOGNAME, "%p: inserting task: %p", this, model);
|
||||||
beginInsertRows(QModelIndex(), row, row);
|
beginInsertRows(QModelIndex(), row, row);
|
||||||
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
d->tasks_.insert(it, TaskListModelPrivate::BaseModelData(model));
|
||||||
@ -374,6 +417,43 @@ bool TaskListModel::removeRows(int row, int count, const QModelIndex &parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TaskListModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(column);
|
||||||
|
Q_D(TaskListModel);
|
||||||
|
if (!d->stage_factory_)
|
||||||
|
return false;
|
||||||
|
const QString& mime_type = d->stage_factory_->mimeType();
|
||||||
|
if (!mime->hasFormat(mime_type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!parent.isValid() && mime->hasFormat(mime_type)) {
|
||||||
|
QString error;
|
||||||
|
moveit::task_constructor::Stage* stage
|
||||||
|
= d->stage_factory_->makeRaw(mime->data(mime_type), &error);
|
||||||
|
std::unique_ptr<moveit::task_constructor::ContainerBase> container
|
||||||
|
(dynamic_cast<moveit::task_constructor::ContainerBase*>(stage));
|
||||||
|
if (!container) { // only accept container at root level
|
||||||
|
if (stage) delete stage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new local task using the given container as root
|
||||||
|
insertTask(new LocalTaskModel(std::move(container), this), row);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// propagate to corresponding child model
|
||||||
|
TaskListModelPrivate::BaseModelData *data = nullptr;
|
||||||
|
QModelIndex src_parent = d->mapToSource(parent, &data);
|
||||||
|
return data->model_->dropMimeData(mime, action, row, column, src_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions TaskListModel::supportedDragActions() const
|
||||||
|
{
|
||||||
|
return Qt::CopyAction | Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
void TaskListModelPrivate::removeTask(BaseTaskModel *model)
|
void TaskListModelPrivate::removeTask(BaseTaskModel *model)
|
||||||
{
|
{
|
||||||
ROS_DEBUG_NAMED(LOGNAME, "%p: removing task: %p", q_ptr, model);
|
ROS_DEBUG_NAMED(LOGNAME, "%p: removing task: %p", q_ptr, model);
|
||||||
|
|||||||
@ -36,6 +36,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "pluginlib_factory.h"
|
||||||
|
#include <moveit_task_constructor/stage.h>
|
||||||
|
|
||||||
#include <moveit/macros/class_forward.h>
|
#include <moveit/macros/class_forward.h>
|
||||||
#include <moveit_task_constructor/Task.h>
|
#include <moveit_task_constructor/Task.h>
|
||||||
#include <moveit_task_constructor/Solution.h>
|
#include <moveit_task_constructor/Solution.h>
|
||||||
@ -66,6 +69,12 @@ public:
|
|||||||
unsigned int taskFlags() const { return flags_; }
|
unsigned int taskFlags() const { return flags_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef PluginlibFactory<moveit::task_constructor::Stage> StageFactory;
|
||||||
|
typedef std::shared_ptr<StageFactory> StageFactoryPtr;
|
||||||
|
StageFactoryPtr getStageFactory();
|
||||||
|
|
||||||
|
|
||||||
class TaskListModelPrivate;
|
class TaskListModelPrivate;
|
||||||
/** The TaskListModel maintains a list of multiple BaseTaskModels, local and/or remote.
|
/** The TaskListModel maintains a list of multiple BaseTaskModels, local and/or remote.
|
||||||
*
|
*
|
||||||
@ -112,6 +121,12 @@ public:
|
|||||||
bool removeTask(BaseTaskModel* model);
|
bool removeTask(BaseTaskModel* model);
|
||||||
bool removeTasks(int row, int count);
|
bool removeTasks(int row, int count);
|
||||||
|
|
||||||
|
/// providing a StageFactory makes the model accepting drops
|
||||||
|
void setStageFactory(const StageFactoryPtr &factory);
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
|
bool dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
|
Qt::DropActions supportedDragActions() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
|
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int))
|
Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int))
|
||||||
|
|||||||
@ -50,22 +50,16 @@
|
|||||||
#include <rviz/window_manager_interface.h>
|
#include <rviz/window_manager_interface.h>
|
||||||
#include <rviz/panel_dock_widget.h>
|
#include <rviz/panel_dock_widget.h>
|
||||||
#include <ros/console.h>
|
#include <ros/console.h>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
namespace moveit_rviz_plugin {
|
namespace moveit_rviz_plugin {
|
||||||
|
|
||||||
typedef PluginlibFactory<moveit::task_constructor::Stage> StageFactory;
|
|
||||||
StageFactory* getStageFactory() {
|
|
||||||
static std::shared_ptr<StageFactory> factory
|
|
||||||
(new StageFactory("moveit_task_constructor",
|
|
||||||
"moveit::task_constructor::Stage"));
|
|
||||||
return factory.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
rviz::PanelDockWidget* getStageDockWidget(rviz::WindowManagerInterface* mgr) {
|
rviz::PanelDockWidget* getStageDockWidget(rviz::WindowManagerInterface* mgr) {
|
||||||
static rviz::PanelDockWidget *widget = nullptr;
|
static QPointer<rviz::PanelDockWidget> widget = nullptr;
|
||||||
if (!widget && mgr) { // create widget
|
if (!widget && mgr) { // create widget
|
||||||
QTreeView *view = new QTreeView(mgr->getParentWindow());
|
QTreeView *view = new QTreeView();
|
||||||
view->setModel(new FactoryModel(getStageFactory(), view));
|
StageFactoryPtr factory = getStageFactory();
|
||||||
|
view->setModel(new FactoryModel(*factory, factory->mimeType(), view));
|
||||||
view->expandAll();
|
view->expandAll();
|
||||||
view->setHeaderHidden(true);
|
view->setHeaderHidden(true);
|
||||||
view->setDragDropMode(QAbstractItemView::DragOnly);
|
view->setDragDropMode(QAbstractItemView::DragOnly);
|
||||||
@ -82,6 +76,7 @@ TaskPanel::TaskPanel(QWidget* parent)
|
|||||||
Q_D(TaskPanel);
|
Q_D(TaskPanel);
|
||||||
// connect signals
|
// connect signals
|
||||||
connect(d->actionRemoveTaskTreeRows, &QAction::triggered, this, &TaskPanel::removeTaskTreeRows);
|
connect(d->actionRemoveTaskTreeRows, &QAction::triggered, this, &TaskPanel::removeTaskTreeRows);
|
||||||
|
connect(d->actionAddLocalTask, &QAction::triggered, this, &TaskPanel::addTask);
|
||||||
connect(d->button_show_stage_dock_widget, &QToolButton::clicked, this, &TaskPanel::showStageDockWidget);
|
connect(d->button_show_stage_dock_widget, &QToolButton::clicked, this, &TaskPanel::showStageDockWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,12 +91,21 @@ TaskPanelPrivate::TaskPanelPrivate(TaskPanel *q_ptr)
|
|||||||
, settings(new rviz::PropertyTreeModel(new rviz::Property, q_ptr))
|
, settings(new rviz::PropertyTreeModel(new rviz::Property, q_ptr))
|
||||||
{
|
{
|
||||||
setupUi(q_ptr);
|
setupUi(q_ptr);
|
||||||
initSettings(settings->getRoot());
|
// init tasks view
|
||||||
settings_view->setModel(settings);
|
task_list_model->setStageFactory(getStageFactory());
|
||||||
tasks_view->setModel(task_list_model.get());
|
tasks_view->setModel(task_list_model.get());
|
||||||
|
|
||||||
|
tasks_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
tasks_view->setAcceptDrops(true);
|
||||||
|
tasks_view->setDefaultDropAction(Qt::CopyAction);
|
||||||
|
tasks_view->setDropIndicatorShown(true);
|
||||||
|
tasks_view->setDragEnabled(true);
|
||||||
|
|
||||||
// init actions
|
// init actions
|
||||||
tasks_view->addActions({actionRemoveTaskTreeRows});
|
tasks_view->addActions({actionRemoveTaskTreeRows, actionAddLocalTask});
|
||||||
|
|
||||||
|
initSettings(settings->getRoot());
|
||||||
|
settings_view->setModel(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanelPrivate::initSettings(rviz::Property* root)
|
void TaskPanelPrivate::initSettings(rviz::Property* root)
|
||||||
@ -124,11 +128,11 @@ void TaskPanel::load(const rviz::Config& config)
|
|||||||
d_ptr->settings->getRoot()->load(config);
|
d_ptr->settings->getRoot()->load(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanel::onAddTask()
|
void TaskPanel::addTask()
|
||||||
{
|
{
|
||||||
Q_D(TaskPanel);
|
Q_D(TaskPanel);
|
||||||
QModelIndex current = d->tasks_view->currentIndex();
|
QModelIndex current = d->tasks_view->currentIndex();
|
||||||
d_ptr->task_list_model->insertTask(new LocalTaskModel(this), current.row());
|
d_ptr->task_list_model->insertTask(new LocalTaskModel(d_ptr->task_list_model.get()), current.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanel::showStageDockWidget()
|
void TaskPanel::showStageDockWidget()
|
||||||
|
|||||||
@ -69,7 +69,7 @@ public:
|
|||||||
void save(rviz::Config config) const override;
|
void save(rviz::Config config) const override;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void onAddTask();
|
void addTask();
|
||||||
void showStageDockWidget();
|
void showStageDockWidget();
|
||||||
void removeTaskTreeRows();
|
void removeTaskTreeRows();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -80,6 +80,11 @@
|
|||||||
<enum>Qt::WidgetShortcut</enum>
|
<enum>Qt::WidgetShortcut</enum>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionAddLocalTask">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add task</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user