From cc0ca7e1ab83bdf950a81923249916ea3551d9fd Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 1 Oct 2020 15:59:57 +0300 Subject: [PATCH] QmlDesigner: Respect canBeContainer on drag from library to navigator If the parent node can't be a container for the newly created node, the newly created node is deleted within the same transaction. Change-Id: I4f4771add3aae5b4509b3bb0a8fbabfed2e7c99e Fixes: QDS-2660 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../navigator/navigatortreemodel.cpp | 39 ++++++++++---- .../designercore/include/qmlitemnode.h | 6 ++- .../designercore/model/qmlitemnode.cpp | 51 ++++++++++--------- 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 804d8c2d4be..5538a9cb8d2 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -557,9 +557,10 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in bool moveNodesAfter = true; if (foundTarget) { - if (!NodeHints::fromItemLibraryEntry(itemLibraryEntry).canBeDroppedInNavigator()) + if (!hints.canBeDroppedInNavigator()) return; + bool validContainer = false; QmlObjectNode newQmlObjectNode; m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryItemDrop", [&] { newQmlObjectNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, QPointF(), targetProperty, false); @@ -587,6 +588,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in ModelNode targetEnv; if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.SceneEnvironment")) { targetEnv = targetProperty.parentModelNode(); + validContainer = true; } else if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.View3D")) { // see if View3D has environment set to it BindingProperty envNodeProp = targetProperty.parentModelNode().bindingProperty("environment"); @@ -595,6 +597,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in if (envNode.isValid()) targetEnv = envNode; } + validContainer = true; } insertIntoList("effects", targetEnv); } else if (newModelNode.isSubclassOf("QtQuick3D.Material")) { @@ -603,6 +606,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in ModelNode targetModel; targetModel = targetProperty.parentModelNode(); insertIntoList("materials", targetModel); + validContainer = true; } } else { const bool isShader = newModelNode.isSubclassOf("QtQuick3D.Shader"); @@ -627,22 +631,30 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in // want undo to place the node under invalid parent moveNodesAfter = false; moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false); + validContainer = true; } } } } + if (!validContainer) { + validContainer = NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode); + if (!validContainer) + newQmlObjectNode.destroy(); + } } }); - if (moveNodesAfter && newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) { - QList newModelNodeList; - newModelNodeList.append(newQmlObjectNode); + if (validContainer) { + if (moveNodesAfter && newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) { + QList newModelNodeList; + newModelNodeList.append(newQmlObjectNode); - moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber); + moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber); + } + + if (newQmlObjectNode.isValid()) + m_view->setSelectedModelNode(newQmlObjectNode.modelNode()); } - - if (newQmlObjectNode.isValid()) - m_view->setSelectedModelNode(newQmlObjectNode.modelNode()); } } @@ -717,9 +729,14 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i // if dropping an image on a texture, set the texture source targetNode.variantProperty("source").setValue(imagePath); } else { - - // create an image - newModelNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageSource , QPointF(), targetProperty); + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] { + // create an image + QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageSource, QPointF(), targetProperty, false); + if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode())) + newModelNode = newItemNode.modelNode(); + else + newItemNode.destroy(); + }); } if (newModelNode.isValid()) { diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h index f37bae869e6..62c5303a31d 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h @@ -61,11 +61,13 @@ public: static QmlItemNode createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, - QmlItemNode parentQmlItemNode); + QmlItemNode parentQmlItemNode, + bool executeInTransaction = true); static QmlItemNode createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, - NodeAbstractProperty parentproperty); + NodeAbstractProperty parentproperty, + bool executeInTransaction = true); QList children() const; QList resources() const; diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index 886e524b291..12a6092f931 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -73,47 +73,50 @@ QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view, return QmlItemNode(createQmlObjectNode(view, itemLibraryEntry, position, parentQmlItemNode)); } -QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, QmlItemNode parentQmlItemNode) +QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, QmlItemNode parentQmlItemNode, bool executeInTransaction) { if (!parentQmlItemNode.isValid()) parentQmlItemNode = QmlItemNode(view->rootModelNode()); NodeAbstractProperty parentProperty = parentQmlItemNode.defaultNodeAbstractProperty(); - return QmlItemNode::createQmlItemNodeFromImage(view, imageName, position, parentProperty); + return QmlItemNode::createQmlItemNodeFromImage(view, imageName, position, parentProperty, executeInTransaction); } -QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, NodeAbstractProperty parentproperty) +QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, NodeAbstractProperty parentproperty, bool executeInTransaction) { QmlItemNode newQmlItemNode; - if (parentproperty.isValid() && view->model()->hasNodeMetaInfo("QtQuick.Image")) { - view->executeInTransaction("QmlItemNode::createQmlItemNodeFromImage", [=, &newQmlItemNode, &parentproperty](){ - NodeMetaInfo metaInfo = view->model()->metaInfo("QtQuick.Image"); - QList > propertyPairList; - propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))}); - propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))}); + auto doCreateQmlItemNodeFromImage = [=, &newQmlItemNode, &parentproperty]() { + NodeMetaInfo metaInfo = view->model()->metaInfo("QtQuick.Image"); + QList > propertyPairList; + propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))}); + propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))}); - QString relativeImageName = imageName; + QString relativeImageName = imageName; - //use relative path - if (QFileInfo::exists(view->model()->fileUrl().toLocalFile())) { - QDir fileDir(QFileInfo(view->model()->fileUrl().toLocalFile()).absolutePath()); - relativeImageName = fileDir.relativeFilePath(imageName); - propertyPairList.append({PropertyName("source"), QVariant(relativeImageName)}); - } + //use relative path + if (QFileInfo::exists(view->model()->fileUrl().toLocalFile())) { + QDir fileDir(QFileInfo(view->model()->fileUrl().toLocalFile()).absolutePath()); + relativeImageName = fileDir.relativeFilePath(imageName); + propertyPairList.append({PropertyName("source"), QVariant(relativeImageName)}); + } - newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Image", metaInfo.majorVersion(), metaInfo.minorVersion(), propertyPairList)); - parentproperty.reparentHere(newQmlItemNode); + newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Image", metaInfo.majorVersion(), metaInfo.minorVersion(), propertyPairList)); + parentproperty.reparentHere(newQmlItemNode); - QFileInfo fi(relativeImageName); - newQmlItemNode.setId(view->generateNewId(fi.baseName(), "image")); + QFileInfo fi(relativeImageName); + newQmlItemNode.setId(view->generateNewId(fi.baseName(), "image")); - newQmlItemNode.modelNode().variantProperty("fillMode").setEnumeration("Image.PreserveAspectFit"); + newQmlItemNode.modelNode().variantProperty("fillMode").setEnumeration("Image.PreserveAspectFit"); - Q_ASSERT(newQmlItemNode.isValid()); - }); - } + Q_ASSERT(newQmlItemNode.isValid()); + }; + + if (executeInTransaction) + view->executeInTransaction("QmlItemNode::createQmlItemNodeFromImage", doCreateQmlItemNodeFromImage); + else + doCreateQmlItemNodeFromImage(); return newQmlItemNode; }