diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 7e7c0df87b..e71993d647 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -389,7 +389,42 @@ void TreeWidget::onActivateDocument(QAction* active) Qt::DropActions TreeWidget::supportedDropActions () const { - return QTreeWidget::supportedDropActions(); + Qt::DropActions da = QTreeWidget::supportedDropActions(); + QList idxs = selectedIndexes(); + + if (idxs.size() == 1) { + // as we can't know here where the drop action will occur that is the best we can do + da |= Qt::LinkAction; + } + + for (QList::Iterator it = idxs.begin(); it != idxs.end(); ++it) { + QTreeWidgetItem* item = itemFromIndex(*it); + if (item->type() != TreeWidget::ObjectType) { + return Qt::IgnoreAction; + } + QTreeWidgetItem* parent = item->parent(); + if (parent) { + if (parent->type() != TreeWidget::ObjectType) { + da &= ~Qt::MoveAction; + } + else { + // Now check for object with a parent that is an ObjectType, too. + // If this object is *not* selected and *not* a group we are not allowed to remove + // its child (e.g. the sketch of a pad). + Gui::ViewProvider* vp = static_cast(parent)->object(); + App::DocumentObject* obj = static_cast(item)-> + object()->getObject(); + if (!vp->canDragObjects() || !vp->canDragObject(obj)) { + da &= ~Qt::MoveAction; + } + } + } + else { + da &= ~Qt::MoveAction; + } + } + + return da; } bool TreeWidget::event(QEvent *e) @@ -456,22 +491,6 @@ QMimeData * TreeWidget::mimeData (const QList items) const doc = obj->getDocument(); else if (doc != obj->getDocument()) return 0; - // Now check for object with a parent that is an ObjectType, too. - // If this object is *not* selected and *not* a group we are not allowed to remove - // its child (e.g. the sketch of a pad). - QTreeWidgetItem* parent = (*it)->parent(); - if (parent && parent->type() == TreeWidget::ObjectType) { - // fix issue #0001456 - if (!items.contains(parent)) { - Gui::ViewProvider* vp = static_cast(parent)->object(); - if (!vp->canDragObjects()) { - return 0; - } - else if (!vp->canDragObject(obj)) { - return 0; - } - } - } } return QTreeWidget::mimeData(items); } @@ -492,6 +511,18 @@ void TreeWidget::dragLeaveEvent(QDragLeaveEvent * event) QTreeWidget::dragLeaveEvent(event); } +QList TreeWidget::buildListChildren(QTreeWidgetItem* targetitem, Gui::ViewProviderDocumentObject* vp) +{ + // to check we do not drop the part on itself + QList children; + children << vp->getObject(); + for (int i=0; ichildCount(); i++) { + Gui::ViewProviderDocumentObject* vpc = static_cast(targetitem->child(i))->object(); + children << vpc->getObject(); + } + return children; +} + void TreeWidget::dragMoveEvent(QDragMoveEvent *event) { QTreeWidget::dragMoveEvent(event); @@ -503,6 +534,9 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) event->ignore(); } else { + QTreeWidgetItem* parentTarget = targetItem->parent(); + Qt::DropAction da = event->proposedAction(); + if (targetItem->type() == TreeWidget::DocumentType) { QList idxs = selectedIndexes(); App::Document* doc = static_cast(targetItem)-> @@ -519,20 +553,31 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) event->ignore(); return; } + + // Dropping an object on the document that is not part of a composed object is non-sense + // Dropping an object on document means to remove the object of a composed object + QTreeWidgetItem* parent = item->parent(); + if (!parent || parent->type() != TreeWidget::ObjectType) { + event->ignore(); + return; + } + } + + // Link is non-sense on a document. + if (da == Qt::LinkAction) { + if (event->possibleActions() & Qt::MoveAction) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else { + event->ignore(); + } } } else if (targetItem->type() == TreeWidget::ObjectType) { DocumentObjectItem* targetItemObj = static_cast(targetItem); Gui::ViewProviderDocumentObject* vpTarget = targetItemObj->object(); - - if (!vpTarget->canDropObjects()) { - event->ignore(); - } - - QList children; - for (int i=0; ichildCount(); i++) - children << targetItem->child(i); - + QList children = buildListChildren(targetItem, vpTarget); App::DocumentObject* targetObj = vpTarget->getObject(); App::Document* docTarget = targetObj->getDocument(); @@ -559,24 +604,60 @@ void TreeWidget::dragMoveEvent(QDragMoveEvent *event) // 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( - static_cast(item))) { - event->ignore(); - return; - } + bool canDrop = !targetObj->isInInListRecursive(objDropped) && ( + !objDropped->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()) || + targetObj->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()) + ); // if the item is already a child of the target item there is nothing to do - if (children.contains(item)) { + canDrop = canDrop && vpTarget->canDropObjects() && !children.contains(objDropped); + + if (!canDrop) { + if (idxsSelected.size() == 1) { + if (parentTarget) { + if (parentTarget->type() == TreeWidget::ObjectType) { + DocumentObjectItem* parentTargetItemObj = + static_cast(parentTarget); + Gui::ViewProviderDocumentObject* vpParent = parentTargetItemObj->object(); + App::DocumentObject* objParentTarget = vpParent->getObject(); + + if (!buildListChildren(parentTarget, vpParent).contains(objDropped) && + !objParentTarget->isInInListRecursive(objDropped) && ( + !objDropped->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()) || + objParentTarget->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()))) { + if (da == Qt::CopyAction || da == Qt::MoveAction) { + event->setDropAction(Qt::LinkAction); + event->accept(); + return; + } + else if (da == Qt::LinkAction) { + event->acceptProposedAction(); + return; + } + } + } + } + } event->ignore(); return; } - - // let the view provider decide to accept the object or ignore it - if (!vpTarget->canDropObject(objDropped)) { - event->ignore(); - return; + else { + // let the view provider decide to accept the object or ignore it + if (!vpTarget->canDropObject(objDropped)) { + event->ignore(); + return; + } + else if (da == Qt::LinkAction) { + if (!parentTarget || parentTarget->type() != TreeWidget::ObjectType) { + // no need to test compatibility between parent and objDropped and objParentTarget + // as test between objDropped and targetObj has been tested before + event->ignore(); + return; + } + } } } + event->acceptProposedAction(); } else { event->ignore(); @@ -600,7 +681,7 @@ void TreeWidget::dropEvent(QDropEvent *event) QList items; QList idxs = selectedIndexes(); for (QList::Iterator it = idxs.begin(); it != idxs.end(); ++it) { - // ignore child elements if the parent is selected + // ignore child elements if the parent is selected (issue #0001456) QModelIndex parent = (*it).parent(); if (idxs.contains(parent)) continue; @@ -618,17 +699,39 @@ void TreeWidget::dropEvent(QDropEvent *event) if (targetItem->type() == TreeWidget::ObjectType) { // add object to group DocumentObjectItem* targetItemObj = static_cast(targetItem); + + Qt::DropAction da = event->dropAction(); + Gui::ViewProviderDocumentObject* vpTarget = targetItemObj->object(); Gui::Document* gui = vpTarget->getDocument(); - if (false) { + if (da == Qt::LinkAction) { +#if 0 + // Open command + gui->openCommand("Drop object"); + for (QList::Iterator it = items.begin(); it != items.end(); ++it) { + Gui::ViewProviderDocumentObject* vpDropped = static_cast(*it)->object(); + App::DocumentObject* objDropped = vpDropped->getObject(); + + // does this have a parent object + QTreeWidgetItem* parent = targetItemObj->parent(); + + if (parent && parent->type() == TreeWidget::ObjectType) { + Gui::ViewProvider* vpParent = static_cast(parent)->object(); + // now add the object to the target object + vpParent->replaceObject(vpTarget->getObject(), objDropped); + } + + } + gui->commitCommand(); +#endif } else { if (!vpTarget->canDropObjects()) { return; // no group like object } - bool dropOnly = QApplication::keyboardModifiers()== Qt::ControlModifier; + bool dropOnly = da == Qt::CopyAction; // Open command gui->openCommand("Drag object"); diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index e3c20c8a9b..d39df0d75c 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -98,6 +98,8 @@ protected: bool event(QEvent *e); void keyPressEvent(QKeyEvent *event); void mouseDoubleClickEvent(QMouseEvent * event); + QList buildListChildren(QTreeWidgetItem* targetitem, + Gui::ViewProviderDocumentObject* vp); protected Q_SLOTS: void onCreateGroup();