diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 6b80f63b18..f71de515f1 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -444,7 +444,10 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) } } else if (targetitem->type() == TreeWidget::ObjectType) { - Gui::ViewProviderDocumentObject* vp = static_cast(targetitem)->object(); + + DocumentObjectItem* targetItemObj = static_cast(targetitem); + Gui::ViewProviderDocumentObject* vp = targetItemObj->object(); + if (!vp->canDropObjects()) { event->ignore(); } @@ -456,6 +459,10 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) App::DocumentObject* grp = vp->getObject(); App::Document* doc = grp->getDocument(); QList idxs = selectedIndexes(); + + std::vector dropObjects; + dropObjects.reserve(idxs.size()); + for (QList::Iterator it = idxs.begin(); it != idxs.end(); ++it) { QTreeWidgetItem* item = itemFromIndex(*it); if (item->type() != TreeWidget::ObjectType) { @@ -469,6 +476,8 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) return; } + dropObjects.push_back(obj); + // To avoid a cylic dependency it must be made sure to not allow to // drag'n'drop a tree item onto a child or grandchild item of it. if (static_cast(targetitem)->isChildOfItem( @@ -528,20 +537,26 @@ void TreeWidget::dropEvent(QDropEvent *event) if (targetitem->type() == TreeWidget::ObjectType) { // add object to group - Gui::ViewProviderDocumentObject* vp = static_cast(targetitem)->object(); + DocumentObjectItem* targetItemObj = static_cast(targetitem); + Gui::ViewProviderDocumentObject* vp = targetItemObj->object(); App::DocumentObject* grp = vp->getObject(); if (!vp->canDropObjects()) { return; // no group like object } + std::vector dropObjects; + dropObjects.reserve(idxs.size()); + // Open command App::Document* doc = grp->getDocument(); Gui::Document* gui = Gui::Application::Instance->getDocument(doc); - gui->openCommand("Move object"); + for (QList::Iterator it = items.begin(); it != items.end(); ++it) { Gui::ViewProviderDocumentObject* vpc = static_cast(*it)->object(); App::DocumentObject* obj = vpc->getObject(); + dropObjects.push_back(obj); + // does this have a parent object QTreeWidgetItem* parent = (*it)->parent(); if (parent && parent->type() == TreeWidget::ObjectType) { @@ -552,7 +567,7 @@ void TreeWidget::dropEvent(QDropEvent *event) // now add the object to the target object vp->dropObject(obj); } - gui->commitCommand(); + targetItemObj->drop(dropObjects,event->keyboardModifiers(),event->mouseButtons(),event->pos()); } else if (targetitem->type() == TreeWidget::DocumentType) { // Open command @@ -861,6 +876,8 @@ DocumentItem::~DocumentItem() connectExpObject.disconnect(); } + + void DocumentItem::slotInEdit(const Gui::ViewProviderDocumentObject& v) { std::string name (v.getObject()->getNameInDocument()); @@ -1398,6 +1415,15 @@ void DocumentObjectItem::testStatus() this->setIcon(0, icon_mod); } +bool DocumentObjectItem::allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ + return viewObject->allowDrop(objList,keys,mouseBts,pos); +} +void DocumentObjectItem::drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ + viewObject->drop(objList,keys,mouseBts,pos); +} + void DocumentObjectItem::displayStatusInfo() { App::DocumentObject* Obj = viewObject->getObject(); diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index fb3e3f3dbb..f4ce69a0fe 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -203,6 +203,9 @@ public: void setData(int column, int role, const QVariant & value); bool isChildOfItem(DocumentObjectItem*); + bool allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + void drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + protected: void slotChangeIcon(); void slotChangeToolTip(const QString&); diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index a3a650e02b..62c33bb630 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -247,3 +247,11 @@ PyObject* ViewProviderDocumentObject::getPyObject() pyViewObject->IncRef(); return pyViewObject; } + +bool ViewProviderDocumentObject::allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ + return false; +} +void ViewProviderDocumentObject::drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ +} diff --git a/src/Gui/ViewProviderDocumentObject.h b/src/Gui/ViewProviderDocumentObject.h index 924dff83c0..3b567a540c 100644 --- a/src/Gui/ViewProviderDocumentObject.h +++ b/src/Gui/ViewProviderDocumentObject.h @@ -89,6 +89,15 @@ public: virtual void finishRestoring(); //@} + /** @name drag & drop handling */ + //@{ + /// get called if the user hover over a object in the tree + virtual bool allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + /// get called if the user drops some objects + virtual void drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + //@} + + protected: /*! Get the active mdi view of the document this view provider is part of. @note The returned mdi view doesn't need to be a 3d view but can be e.g. diff --git a/src/Gui/ViewProviderDocumentObjectGroup.cpp b/src/Gui/ViewProviderDocumentObjectGroup.cpp index bec1cb7e6e..4217419593 100644 --- a/src/Gui/ViewProviderDocumentObjectGroup.cpp +++ b/src/Gui/ViewProviderDocumentObjectGroup.cpp @@ -157,6 +157,53 @@ bool ViewProviderDocumentObjectGroup::onDelete(const std::vector &) return true; } +bool ViewProviderDocumentObjectGroup::allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ + for( std::vector::const_iterator it = objList.begin();it!=objList.end();++it) + if ((*it)->getTypeId().isDerivedFrom(App::DocumentObjectGroup::getClassTypeId())) { + if (static_cast(getObject())->isChildOf( + static_cast(*it))) { + return false; + } + } + + return true; +} +void ViewProviderDocumentObjectGroup::drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos) +{ + // Open command + App::DocumentObjectGroup* grp = static_cast(getObject()); + App::Document* doc = grp->getDocument(); + Gui::Document* gui = Gui::Application::Instance->getDocument(doc); + gui->openCommand("Move object"); + for( std::vector::const_iterator it = objList.begin();it!=objList.end();++it) { + // get document object + const App::DocumentObject* obj = *it; + const App::DocumentObjectGroup* par = App::DocumentObjectGroup::getGroupOfObject(obj); + if (par) { + // allow an object to be in one group only + QString cmd; + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(par->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + Gui::Application::Instance->runPythonCode(cmd.toUtf8()); + } + + // build Python command for execution + QString cmd; + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(grp->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + + Gui::Application::Instance->runPythonCode(cmd.toUtf8()); + } + gui->commitCommand(); + +} void ViewProviderDocumentObjectGroup::hide(void) { diff --git a/src/Gui/ViewProviderDocumentObjectGroup.h b/src/Gui/ViewProviderDocumentObjectGroup.h index 5ba06eae98..31126501d1 100644 --- a/src/Gui/ViewProviderDocumentObjectGroup.h +++ b/src/Gui/ViewProviderDocumentObjectGroup.h @@ -58,6 +58,11 @@ public: virtual bool onDelete(const std::vector &); + /// get called if the user hover over a object in the tree + virtual bool allowDrop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + /// get called if the user drops some objects + virtual void drop(const std::vector &objList,Qt::KeyboardModifiers keys,Qt::MouseButtons mouseBts,const QPoint &pos); + protected: /// get called by the container whenever a property has been changed void onChanged(const App::Property* prop);