From 5369aea1ed8828121a4b74ee4959db8a6cdf6287 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 15 Jun 2021 17:24:24 +0300 Subject: [PATCH] QmlDesigner: Implement multi-selection in the asset library Multi-selected assets can be dragged to the form editor and navigator. Also increased font size for newly created text as it was so small and some relvant cleanups. Change-Id: Icf28b627a8392309520b7071209812e1ae051e84 Reviewed-by: Miikka Heikkinen Reviewed-by: Thomas Hartmann Reviewed-by: Qt CI Bot --- .../itemLibraryQmlSources/Assets.qml | 33 +- .../formeditor/abstractformeditortool.cpp | 19 +- .../components/formeditor/dragtool.cpp | 224 +++++----- .../components/formeditor/dragtool.h | 13 +- .../itemlibrary/itemlibrarywidget.cpp | 27 +- .../itemlibrary/itemlibrarywidget.h | 6 +- .../navigator/navigatortreemodel.cpp | 421 ++++++++---------- .../components/navigator/navigatortreemodel.h | 15 +- .../designercore/model/qmlitemnode.cpp | 1 + 9 files changed, 388 insertions(+), 371 deletions(-) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 5a983575e2b..18b3481d7c0 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -32,6 +32,8 @@ import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme Item { + property var selectedAssets: ({}) + DropArea { id: dropArea @@ -142,7 +144,8 @@ Item { width: assetsView.width - (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) height: img.height - color: mouseArea.containsMouse ? "#444444" : "transparent" + color: selectedAssets[filePath] ? StudioTheme.Values.themeInteraction + : (mouseArea.containsMouse ? "#444444" : "transparent") Row { spacing: 5 @@ -178,10 +181,32 @@ Item { onPositionChanged: tooltipBackend.reposition() onPressed: { forceActiveFocus() - if (mouse.button === Qt.LeftButton) - rootView.startDragAsset(filePath, mapToGlobal(mouse.x, mouse.y)) - else + if (mouse.button === Qt.LeftButton) { + var ctrlDown = mouse.modifiers & Qt.ControlModifier + if (!selectedAssets[filePath] && !ctrlDown) + selectedAssets = {} + selectedAssets[filePath] = true + selectedAssetsChanged() + + var selectedAssetsArr = [] + for (var assetPath in selectedAssets) { + if (selectedAssets[assetPath]) + selectedAssetsArr.push(assetPath) + } + + rootView.startDragAsset(selectedAssetsArr, mapToGlobal(mouse.x, mouse.y)) + } else { print("TODO: impl context menu") + } + } + + onReleased: { + if (mouse.button === Qt.LeftButton) { + if (!(mouse.modifiers & Qt.ControlModifier)) + selectedAssets = {} + selectedAssets[filePath] = true + selectedAssetsChanged() + } } ToolTip { diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp index ec856fa5ca8..4d658deb8d5 100644 --- a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp @@ -27,6 +27,7 @@ #include "formeditorview.h" #include "formeditorwidget.h" #include "formeditorscene.h" +#include "itemlibrarywidget.h" #include @@ -234,9 +235,21 @@ void AbstractFormEditorTool::dropEvent(const QList &/*itemList*/ void AbstractFormEditorTool::dragEnterEvent(const QList &itemList, QGraphicsSceneDragDropEvent *event) { - if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) - || event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.image")) - || event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.font"))) { + bool hasValidAssets = false; + if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) { + const QStringList assetPaths = QString::fromUtf8(event->mimeData() + ->data("application/vnd.bauhaus.libraryresource")).split(","); + for (const QString &assetPath : assetPaths) { + QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first; + if (assetType == "application/vnd.bauhaus.libraryresource.image" + || assetType == "application/vnd.bauhaus.libraryresource.font") { + hasValidAssets = true; + break; + } + } + } + + if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) || hasValidAssets) { event->accept(); view()->changeToDragTool(); view()->currentTool()->dragEnterEvent(itemList, event); diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp index 39ef7a37f52..f2eb5844066 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp @@ -27,6 +27,7 @@ #include "formeditorscene.h" #include "formeditorview.h" +#include "itemlibrarywidget.h" #include #include #include @@ -45,9 +46,7 @@ namespace QmlDesigner { DragTool::DragTool(FormEditorView *editorView) : AbstractFormEditorTool(editorView), m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView), - m_selectionIndicator(editorView->scene()->manipulatorLayerItem()), - m_blockMove(false), - m_isAborted(false) + m_selectionIndicator(editorView->scene()->manipulatorLayerItem()) { } @@ -57,7 +56,7 @@ void DragTool::clear() { m_moveManipulator.clear(); m_selectionIndicator.clear(); - m_movingItem = nullptr; + m_movingItems.clear(); } void DragTool::mousePressEvent(const QList &, QGraphicsSceneMouseEvent *) {} @@ -83,9 +82,9 @@ void DragTool::updateMoveManipulator() {} void DragTool::beginWithPoint(const QPointF &beginPoint) { - m_movingItem = scene()->itemForQmlItemNode(m_dragNode); + m_movingItems = scene()->itemsForQmlItemNodes(m_dragNodes); - m_moveManipulator.setItem(m_movingItem); + m_moveManipulator.setItems(m_movingItems); m_moveManipulator.begin(beginPoint); } @@ -108,17 +107,17 @@ void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, adjustedParentNode = view()->rootModelNode(); } - m_dragNode = QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, adjustedParentNode); + m_dragNodes.append(QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, adjustedParentNode)); - if (rootIsFlow) - m_dragNode.setFlowItemPosition(positonInItemSpace); + if (rootIsFlow) { + for (QmlItemNode &dragNode : m_dragNodes) + dragNode.setFlowItemPosition(positonInItemSpace); + } - QList nodeList; - nodeList.append(m_dragNode); - m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList)); + m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(m_dragNodes)); } -void DragTool::createQmlItemNodeFromImage(const QString &imageName, +void DragTool::createQmlItemNodeFromImage(const QString &imagePath, const QmlItemNode &parentNode, const QPointF &scenePosition) { @@ -128,15 +127,11 @@ void DragTool::createQmlItemNodeFromImage(const QString &imageName, FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode); QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform().inverted().map(scenePosition); - m_dragNode = QmlItemNode::createQmlItemNodeFromImage(view(), imageName, positonInItemSpace, parentNode); - - QList nodeList; - nodeList.append(m_dragNode); - m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList)); + m_dragNodes.append(QmlItemNode::createQmlItemNodeFromImage(view(), imagePath, positonInItemSpace, parentNode)); } } -void DragTool::createQmlItemNodeFromFont(const QString &fontFamily, +void DragTool::createQmlItemNodeFromFont(const QString &fontPath, const QmlItemNode &parentNode, const QPointF &scenePos) { @@ -147,18 +142,18 @@ void DragTool::createQmlItemNodeFromFont(const QString &fontFamily, QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform() .inverted().map(scenePos); - m_dragNode = QmlItemNode::createQmlItemNodeFromFont(view(), fontFamily, positonInItemSpace, - parentNode); + const auto typeAndData = ItemLibraryWidget::getAssetTypeAndData(fontPath); + QString fontFamily = QString::fromUtf8(typeAndData.second); - QList nodeList; - nodeList.append(m_dragNode); - m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList)); + m_dragNodes.append(QmlItemNode::createQmlItemNodeFromFont(view(), fontFamily, + positonInItemSpace, parentNode)); } } -FormEditorItem *DragTool::targetContainerOrRootItem(const QList &itemList, FormEditorItem *currentItem) +FormEditorItem *DragTool::targetContainerOrRootItem(const QList &itemList, + const QList ¤tItems) { - FormEditorItem *formEditorItem = containerFormEditorItem(itemList, {currentItem}); + FormEditorItem *formEditorItem = containerFormEditorItem(itemList, currentItems); if (!formEditorItem) formEditorItem = scene()->rootFormEditorItem(); @@ -168,19 +163,27 @@ FormEditorItem *DragTool::targetContainerOrRootItem(const QList void DragTool::formEditorItemsChanged(const QList &itemList) { - if (m_movingItem && itemList.contains(m_movingItem)) { - QList updateItemList; - updateItemList.append(m_movingItem); - m_selectionIndicator.updateItems(updateItemList); + if (!m_movingItems.isEmpty()) { + for (auto item : std::as_const(m_movingItems)) { + if (itemList.contains(item)) { + m_selectionIndicator.updateItems(m_movingItems); + break; + } + } } } void DragTool::instancesCompleted(const QList &itemList) { m_moveManipulator.synchronizeInstanceParent(itemList); - foreach (FormEditorItem* item, itemList) - if (item->qmlItemNode() == m_dragNode) - clearMoveDelay(); + for (FormEditorItem *item : itemList) { + for (const QmlItemNode &dragNode : std::as_const(m_dragNodes)) { + if (item->qmlItemNode() == dragNode) { + clearMoveDelay(); + break; + } + } + } } void DragTool::instancesParentChanged(const QList &itemList) @@ -194,7 +197,7 @@ void DragTool::clearMoveDelay() { if (m_blockMove) { m_blockMove = false; - if (m_dragNode.isValid()) + if (!m_dragNodes.isEmpty()) beginWithPoint(m_startPoint); } } @@ -206,8 +209,11 @@ void DragTool::abort() if (!m_isAborted) { m_isAborted = true; - if (m_dragNode.isValid()) - m_dragNode.destroy(); + for (auto &node : m_dragNodes) { + if (node.isValid()) + node.destroy(); + } + m_dragNodes.clear(); } } @@ -233,48 +239,38 @@ static bool hasItemLibraryInfo(const QMimeData *mimeData) return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo")); } -static bool hasImageResource(const QMimeData *mimeData) -{ - return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.image")); -} - -static bool hasFontResource(const QMimeData *mimeData) -{ - return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.font")); -} - -static bool canHandleMimeData(const QMimeData *mimeData) -{ - return hasItemLibraryInfo(mimeData) || hasImageResource(mimeData) || hasFontResource(mimeData); -} - -static bool dragAndDropPossible(const QMimeData *mimeData) -{ - return canHandleMimeData(mimeData) && canBeDropped(mimeData); -} - void DragTool::dropEvent(const QList &/*itemList*/, QGraphicsSceneDragDropEvent *event) { - if (dragAndDropPossible(event->mimeData())) { + if (canBeDropped(event->mimeData())) { event->accept(); end(generateUseSnapping(event->modifiers())); - if (m_dragNode.isValid()) { - if ((m_dragNode.instanceParentItem().isValid() - && m_dragNode.instanceParent().modelNode().metaInfo().isLayoutable()) - || m_dragNode.isFlowItem()) { - m_dragNode.removeProperty("x"); - m_dragNode.removeProperty("y"); - view()->resetPuppet(); //Otherwise the layout might not reposition the item + bool resetPuppet = false; + for (auto &node : m_dragNodes) { + if (node.isValid()) { + if ((node.instanceParentItem().isValid() + && node.instanceParent().modelNode().metaInfo().isLayoutable()) + || node.isFlowItem()) { + node.removeProperty("x"); + node.removeProperty("y"); + resetPuppet = true; + } } } + if (resetPuppet) + view()->resetPuppet(); // Otherwise the layout might not reposition the items commitTransaction(); - if (m_dragNode.isValid()) - view()->setSelectedModelNode(m_dragNode); - - m_dragNode = QmlItemNode(); + if (!m_dragNodes.isEmpty()) { + QList nodeList; + for (auto &node : std::as_const(m_dragNodes)) { + if (node.isValid()) + nodeList.append(node); + } + view()->setSelectedModelNodes(nodeList); + } + m_dragNodes.clear(); view()->changeToSelectionTool(); } @@ -282,11 +278,10 @@ void DragTool::dropEvent(const QList &/*itemList*/, QGraphicsSc void DragTool::dragEnterEvent(const QList &/*itemList*/, QGraphicsSceneDragDropEvent *event) { - if (dragAndDropPossible(event->mimeData())) { + if (canBeDropped(event->mimeData())) { m_blockMove = false; if (hasItemLibraryInfo(event->mimeData())) { - view()->widgetInfo().widget->setFocus(); m_isAborted = false; } @@ -300,13 +295,17 @@ void DragTool::dragEnterEvent(const QList &/*itemList*/, QGraph void DragTool::dragLeaveEvent(const QList &/*itemList*/, QGraphicsSceneDragDropEvent *event) { - if (dragAndDropPossible(event->mimeData())) { + if (canBeDropped(event->mimeData())) { event->accept(); m_moveManipulator.end(); clear(); - if (m_dragNode.isValid()) - m_dragNode.destroy(); + + for (auto &node : m_dragNodes) { + if (node.isValid()) + node.destroy(); + } + m_dragNodes.clear(); commitTransaction(); } @@ -314,31 +313,31 @@ void DragTool::dragLeaveEvent(const QList &/*itemList*/, QGraph view()->changeToSelectionTool(); } -static QString libraryResourceFile(const QMimeData *mimeData) +void DragTool::createDragNodes(const QMimeData *mimeData, const QPointF &scenePosition, + const QList &itemList) { - return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource")))); -} - -static QString libraryResourceFont(const QMimeData *mimeData) -{ - return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource.font")))); -} - -void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList &itemList) -{ - if (!m_dragNode.hasModelNode()) { + if (m_dragNodes.isEmpty()) { FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList); if (targetContainerFormEditorItem) { - QmlItemNode targetContainerQmlItemNode; - if (targetContainerFormEditorItem) - targetContainerQmlItemNode = targetContainerFormEditorItem->qmlItemNode(); + QmlItemNode targetContainerQmlItemNode = targetContainerFormEditorItem->qmlItemNode(); - if (hasItemLibraryInfo(mimeData)) - createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode, scenePosition); - else if (hasImageResource(mimeData)) - createQmlItemNodeFromImage(libraryResourceFile(mimeData), targetContainerQmlItemNode, scenePosition); - else if (hasFontResource(mimeData)) - createQmlItemNodeFromFont(libraryResourceFont(mimeData), targetContainerQmlItemNode, scenePosition); + if (hasItemLibraryInfo(mimeData)) { + createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode, + scenePosition); + } else { + const QStringList assetPaths = QString::fromUtf8(mimeData + ->data("application/vnd.bauhaus.libraryresource")).split(","); + for (const QString &assetPath : assetPaths) { + QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first; + if (assetType == "application/vnd.bauhaus.libraryresource.image") + createQmlItemNodeFromImage(assetPath, targetContainerQmlItemNode, scenePosition); + else if (assetType == "application/vnd.bauhaus.libraryresource.font") + createQmlItemNodeFromFont(assetPath, targetContainerQmlItemNode, scenePosition); + } + + if (!m_dragNodes.isEmpty()) + m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(m_dragNodes)); + } m_blockMove = true; m_startPoint = scenePosition; @@ -348,18 +347,22 @@ void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePos void DragTool::dragMoveEvent(const QList &itemList, QGraphicsSceneDragDropEvent *event) { - if (!m_blockMove && !m_isAborted && dragAndDropPossible(event->mimeData())) { + if (!m_blockMove && !m_isAborted && canBeDropped(event->mimeData())) { event->accept(); - if (m_dragNode.isValid()) { + if (!m_dragNodes.isEmpty()) { FormEditorItem *targetContainerItem = targetContainerOrRootItem(itemList); if (targetContainerItem) { move(event->scenePos(), itemList); } else { end(); - m_dragNode.destroy(); + for (auto &node : m_dragNodes) { + if (node.isValid()) + node.destroy(); + } + m_dragNodes.clear(); } } else { - createDragNode(event->mimeData(), event->scenePos(), itemList); + createDragNodes(event->mimeData(), event->scenePos(), itemList); } } else { event->ignore(); @@ -378,20 +381,21 @@ void DragTool::end(Snapper::Snapping useSnapping) clear(); } -void DragTool::move(const QPointF &scenePosition, const QList &itemList) +void DragTool::move(const QPointF &scenePosition, const QList &itemList) { - if (m_movingItem) { - FormEditorItem *containerItem = targetContainerOrRootItem(itemList, m_movingItem); - if (containerItem && m_movingItem->parentItem() && - containerItem != m_movingItem->parentItem()) { + if (!m_movingItems.isEmpty()) { + FormEditorItem *containerItem = targetContainerOrRootItem(itemList, m_movingItems); + for (auto &movingItem : std::as_const(m_movingItems)) { + if (containerItem && movingItem->parentItem() && + containerItem != movingItem->parentItem()) { + const QmlItemNode movingNode = movingItem->qmlItemNode(); + const QmlItemNode containerNode = containerItem->qmlItemNode(); - const QmlItemNode movingNode = m_movingItem->qmlItemNode(); - const QmlItemNode containerNode = containerItem->qmlItemNode(); + qCInfo(dragToolInfo()) << Q_FUNC_INFO << movingNode << containerNode << movingNode.canBereparentedTo(containerNode); - qCInfo(dragToolInfo()) << Q_FUNC_INFO << movingNode << containerNode << movingNode.canBereparentedTo(containerNode); - - if (movingNode.canBereparentedTo(containerNode)) - m_moveManipulator.reparentTo(containerItem); + if (movingNode.canBereparentedTo(containerNode)) + m_moveManipulator.reparentTo(containerItem); + } } Snapper::Snapping useSnapping = Snapper::UseSnapping; @@ -409,4 +413,4 @@ void DragTool::commitTransaction() } } -} +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.h b/src/plugins/qmldesigner/components/formeditor/dragtool.h index fee59b1bc95..7e1b4cb4812 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.h +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.h @@ -80,22 +80,23 @@ public: protected: void abort(); void createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QmlItemNode &parentNode, const QPointF &scenePos); - void createQmlItemNodeFromImage(const QString &imageName, const QmlItemNode &parentNode, const QPointF &scenePos); - void createQmlItemNodeFromFont(const QString &fontFamily, const QmlItemNode &parentNode, const QPointF &scenePos); - FormEditorItem *targetContainerOrRootItem(const QList &itemList, FormEditorItem *urrentItem = nullptr); + void createQmlItemNodeFromImage(const QString &imagePath, const QmlItemNode &parentNode, const QPointF &scenePos); + void createQmlItemNodeFromFont(const QString &fontPath, const QmlItemNode &parentNode, const QPointF &scenePos); + FormEditorItem *targetContainerOrRootItem(const QList &itemList, + const QList ¤tItems = {}); void begin(QPointF scenePos); void end(); void end(Snapper::Snapping useSnapping); void move(const QPointF &scenePos, const QList &itemList); - void createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList &itemList); + void createDragNodes(const QMimeData *mimeData, const QPointF &scenePosition, const QList &itemList); void commitTransaction(); private: MoveManipulator m_moveManipulator; SelectionIndicator m_selectionIndicator; - FormEditorItem *m_movingItem = nullptr; + QList m_movingItems; RewriterTransaction m_rewriterTransaction; - QmlItemNode m_dragNode; + QList m_dragNodes; bool m_blockMove; QPointF m_startPoint; bool m_isAborted; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 326e1e39e5f..bf111d6040e 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -117,24 +117,23 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event) m_itemToDrag = {}; } - } else if (!m_assetToDrag.isEmpty()) { + } else if (!m_assetsToDrag.isEmpty()) { QMouseEvent *me = static_cast(event); if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { auto drag = new QDrag(this); - drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetToDrag, nullptr, {128, 128})); + drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetsToDrag[0], nullptr, {128, 128})); QMimeData *mimeData = new QMimeData; - mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetToDrag.toUtf8()); - mimeData->setData(m_assetToDragTypeAndData.first, m_assetToDragTypeAndData.second); + mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetsToDrag.join(',').toUtf8()); drag->setMimeData(mimeData); drag->exec(); drag->deleteLater(); - m_assetToDrag.clear(); + m_assetsToDrag.clear(); } } } else if (event->type() == QMouseEvent::MouseButtonRelease) { m_itemToDrag = {}; - m_assetToDrag.clear(); + m_assetsToDrag.clear(); } return QObject::eventFilter(obj, event); @@ -471,30 +470,24 @@ void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry, const QPo m_dragStartPoint = mousePos.toPoint(); } -void ItemLibraryWidget::startDragAsset(const QString &assetPath, const QPointF &mousePos) +void ItemLibraryWidget::startDragAsset(const QStringList &assetPaths, const QPointF &mousePos) { - QFileInfo fileInfo(assetPath); - m_assetToDragTypeAndData = getAssetTypeAndData(fileInfo); - - if (m_assetToDragTypeAndData.first.isEmpty()) - return; - // Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay // active (and blocks mouse release) if mouse is released at the same spot of the drag start. - m_assetToDrag = fileInfo.absoluteFilePath(); + m_assetsToDrag = assetPaths; m_dragStartPoint = mousePos.toPoint(); } -QPair ItemLibraryWidget::getAssetTypeAndData(const QFileInfo &fi) const +QPair ItemLibraryWidget::getAssetTypeAndData(const QString &assetPath) { - QString suffix = "*." + fi.suffix().toLower(); + QString suffix = "*." + assetPath.split('.').last().toLower(); if (!suffix.isEmpty()) { if (ItemLibraryAssetsModel::supportedImageSuffixes().contains(suffix)) { // Data: Image format (suffix) return {"application/vnd.bauhaus.libraryresource.image", suffix.toUtf8()}; } else if (ItemLibraryAssetsModel::supportedFontSuffixes().contains(suffix)) { // Data: Font family name - QRawFont font(fi.absoluteFilePath(), 10); + QRawFont font(assetPath, 10); QString fontFamily = font.isValid() ? font.familyName() : ""; return {"application/vnd.bauhaus.libraryresource.font", fontFamily.toUtf8()}; } else if (ItemLibraryAssetsModel::supportedShaderSuffixes().contains(suffix)) { diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index a908649d63b..6116b0d9d42 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -90,10 +90,10 @@ public: void setResourcePath(const QString &resourcePath); void setModel(Model *model); void setFlowMode(bool b); - QPair getAssetTypeAndData(const QFileInfo &fi) const; + static QPair getAssetTypeAndData(const QString &assetPath); Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos); - Q_INVOKABLE void startDragAsset(const QString &assetPath, const QPointF &mousePos); + Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos); Q_INVOKABLE void removeImport(const QString &importUrl); Q_INVOKABLE void addImportForItem(const QString &importUrl); Q_INVOKABLE void handleTabChanged(int index); @@ -143,7 +143,7 @@ private: AsynchronousImageCache &m_imageCache; QPointer m_model; QVariant m_itemToDrag; - QString m_assetToDrag; + QStringList m_assetsToDrag; QPair m_assetToDragTypeAndData; bool m_updateRetry = false; QString m_filterText; diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 56de6785cbc..81297a70c62 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -27,6 +27,7 @@ #include "navigatorview.h" #include "choosetexturepropertydialog.h" #include "qmldesignerplugin.h" +#include "itemlibrarywidget.h" #include #include @@ -484,39 +485,6 @@ QModelIndex NavigatorTreeModel::createIndexFromModelNode(int row, int column, co return index; } -bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData, - Qt::DropAction action, - int rowNumber, - int /*columnNumber*/, - const QModelIndex &dropModelIndex) -{ - if (action == Qt::IgnoreAction) - return true; - - if (m_reverseItemOrder) - rowNumber = rowCount(dropModelIndex) - rowNumber; - - if (dropModelIndex.model() == this) { - if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) { - handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.image")) { - handleItemLibraryImageDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.font")) { - handleItemLibraryFontDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.shader")) { - handleItemLibraryShaderDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.sound")) { - handleItemLibrarySoundDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.texture3d")) { - handleItemLibraryTexture3dDrop(mimeData, rowNumber, dropModelIndex); - } else if (mimeData->hasFormat("application/vnd.modelnode.list")) { - handleInternalDrop(mimeData, rowNumber, dropModelIndex); - } - } - - return false; // don't let the view do drag&drop on its own -} - static bool findTargetProperty(const QModelIndex &rowModelIndex, NavigatorTreeModel *navigatorTreeModel, NodeAbstractProperty *targetProperty, @@ -551,6 +519,62 @@ static bool findTargetProperty(const QModelIndex &rowModelIndex, return true; } +bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData, + Qt::DropAction action, + int rowNumber, + int /*columnNumber*/, + const QModelIndex &dropModelIndex) +{ + if (action == Qt::IgnoreAction) + return true; + + if (m_reverseItemOrder) + rowNumber = rowCount(dropModelIndex) - rowNumber; + + if (dropModelIndex.model() == this) { + if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) { + handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); + } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) { + QStringList assetsPaths = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")).split(","); + NodeAbstractProperty targetProperty; + + const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); + int targetRowNumber = rowNumber; + bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); + if (foundTarget) { + QList addedNodes; + ModelNode currNode; + for (const QString &assetPath : std::as_const(assetsPaths)) { + auto assetTypeAndData = ItemLibraryWidget::getAssetTypeAndData(assetPath); + QString assetType = assetTypeAndData.first; + QString assetData = QString::fromUtf8(assetTypeAndData.second); + if (assetType == "application/vnd.bauhaus.libraryresource.image") + currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex); + else if (assetType == "application/vnd.bauhaus.libraryresource.font") + currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily + else if (assetType == "application/vnd.bauhaus.libraryresource.shader") + currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex); + else if (assetType == "application/vnd.bauhaus.libraryresource.sound") + currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex); + else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") + currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty, rowModelIndex); + + if (currNode.isValid()) + addedNodes.append(currNode); + } + if (!addedNodes.isEmpty()) { + moveNodesInteractive(targetProperty, addedNodes, rowNumber); + m_view->setSelectedModelNodes(addedNodes); + } + } + } else if (mimeData->hasFormat("application/vnd.modelnode.list")) { + handleInternalDrop(mimeData, rowNumber, dropModelIndex); + } + } + + return false; // don't let the view do drag&drop on its own +} + void NavigatorTreeModel::handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex) @@ -583,6 +607,7 @@ static ItemLibraryEntry createItemLibraryEntryFromMimeData(const QByteArray &dat void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex) { QTC_ASSERT(m_view, return); + const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); int targetRowNumber = rowNumber; NodeAbstractProperty targetProperty; @@ -714,89 +739,72 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in } } -void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex) +ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath, + NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex) { - QTC_ASSERT(m_view, return); - const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); - int targetRowNumber = rowNumber; - NodeAbstractProperty targetProperty; + QTC_ASSERT(m_view, return {}); - bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - ModelNode targetNode(modelNodeForIndex(rowModelIndex)); + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - const QString imageSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path - const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(imageSource); // relative to .ui.qml file + const QString imagePathRelative = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(imagePath); // relative to .ui.qml file - ModelNode newModelNode; + ModelNode newModelNode; - if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { - if (targetNode.isSubclassOf("QtQuick.Image") - || targetNode.isSubclassOf("QtQuick.BorderImage")) { - // if dropping an image on an existing image, set the source - targetNode.variantProperty("source").setValue(imagePath); - } else { - 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()) { - moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); - m_view->setSelectedModelNode(newModelNode); - } - } -} - -void NavigatorTreeModel::handleItemLibraryFontDrop(const QMimeData *mimeData, int rowNumber, - const QModelIndex &dropModelIndex) -{ - QTC_ASSERT(m_view, return); - const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); - int targetRowNumber = rowNumber; - NodeAbstractProperty targetProperty; - - bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - - const QString fontFamily = QString::fromUtf8( - mimeData->data("application/vnd.bauhaus.libraryresource.font")); - - ModelNode newModelNode; - - m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] { - if (targetNode.isSubclassOf("QtQuick.Text")) { - // if dropping into an existing Text, update font - targetNode.variantProperty("font.family").setValue(fontFamily); - } else { - // create a Text node - QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont( - m_view, fontFamily, QPointF(), targetProperty, false); + if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode)) { + if (targetNode.isSubclassOf("QtQuick.Image") + || targetNode.isSubclassOf("QtQuick.BorderImage")) { + // if dropping an image on an existing image, set the source + targetNode.variantProperty("source").setValue(imagePathRelative); + } else { + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] { + // create an image + QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imagePath, QPointF(), targetProperty, false); if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode())) newModelNode = newItemNode.modelNode(); else newItemNode.destroy(); - } - }); - - if (newModelNode.isValid()) { - moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); - m_view->setSelectedModelNode(newModelNode); + }); } } + + return newModelNode; } -void NavigatorTreeModel::handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber, - const QModelIndex &dropModelIndex) +ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamily, + NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex) { - QTC_ASSERT(m_view, return); + QTC_ASSERT(m_view, return {}); + + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); + + ModelNode newModelNode; + + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] { + if (targetNode.isSubclassOf("QtQuick.Text")) { + // if dropping into an existing Text, update font + targetNode.variantProperty("font.family").setValue(fontFamily); + } else { + // create a Text node + QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont( + m_view, fontFamily, QPointF(), targetProperty, false); + if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode())) + newModelNode = newItemNode.modelNode(); + else + newItemNode.destroy(); + } + }); + + return newModelNode; +} + +ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader, + NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex) +{ + QTC_ASSERT(m_view, return {}); + Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D")); bool addImport = false; if (!m_view->model()->hasImport(import, true, true)) { @@ -811,68 +819,56 @@ void NavigatorTreeModel::handleItemLibraryShaderDrop(const QMimeData *mimeData, } } - const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); - int targetRowNumber = rowNumber; - NodeAbstractProperty targetProperty; + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); + ModelNode newModelNode; - bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - ModelNode newModelNode; + const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderPath); - const QString shaderSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); - const bool fragShader = mimeData->data("application/vnd.bauhaus.libraryresource.shader").startsWith('f'); - const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderSource); + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] { + if (targetNode.isSubclassOf("QtQuick3D.Shader")) { + // if dropping into an existing Shader, update + targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment" + : "Shader.Vertex"); + targetNode.variantProperty("shader").setValue(relPath); + } else { + // create a new Shader + ItemLibraryEntry itemLibraryEntry; + itemLibraryEntry.setName("Shader"); + itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0); - m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] { - if (targetNode.isSubclassOf("QtQuick3D.Shader")) { - // if dropping into an existing Shader, update - if (fragShader) - targetNode.variantProperty("stage").setEnumeration("Shader.Fragment"); - else - targetNode.variantProperty("stage").setEnumeration("Shader.Vertex"); - targetNode.variantProperty("shader").setValue(relPath); - } else { - // create a new Shader - ItemLibraryEntry itemLibraryEntry; - itemLibraryEntry.setName("Shader"); - itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0); + // set shader properties + PropertyName prop = "shader"; + QString type = "QByteArray"; + QVariant val = relPath; + itemLibraryEntry.addProperty(prop, type, val); + prop = "stage"; + type = "enum"; + val = isFragShader ? "Shader.Fragment" : "Shader.Vertex"; + itemLibraryEntry.addProperty(prop, type, val); - // set shader properties - PropertyName prop = "shader"; - QString type = "QByteArray"; - QVariant val = relPath; - itemLibraryEntry.addProperty(prop, type, val); - prop = "stage"; - type = "enum"; - val = fragShader ? "Shader.Fragment" : "Shader.Vertex"; - itemLibraryEntry.addProperty(prop, type, val); + // create a texture + newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, + targetProperty, false); - // create a texture - newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, - targetProperty, false); - - // Rename the node based on shader source - QFileInfo fi(relPath); - newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), - "shader")); - } - }); - - if (newModelNode.isValid()) { - moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); - m_view->setSelectedModelNode(newModelNode); + // Rename the node based on shader source + QFileInfo fi(relPath); + newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), + "shader")); } + }); - if (addImport) - QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); - } + if (addImport) + QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); + + return newModelNode; } -void NavigatorTreeModel::handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber, - const QModelIndex &dropModelIndex) +ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPath, + NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex) { - QTC_ASSERT(m_view, return); + QTC_ASSERT(m_view, return {}); + Import import = Import::createLibraryImport(QStringLiteral("QtMultimedia")); bool addImport = false; if (!m_view->model()->hasImport(import, true, true)) { @@ -887,92 +883,71 @@ void NavigatorTreeModel::handleItemLibrarySoundDrop(const QMimeData *mimeData, i } } - const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); - int targetRowNumber = rowNumber; - NodeAbstractProperty targetProperty; + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); + ModelNode newModelNode; - bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - ModelNode newModelNode; + const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundPath); - const QString soundSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); - const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundSource); + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] { + if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) { + // if dropping into on an existing SoundEffect, update + targetNode.variantProperty("source").setValue(relPath); + } else { + // create a new SoundEffect + ItemLibraryEntry itemLibraryEntry; + itemLibraryEntry.setName("SoundEffect"); + itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0); - m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] { - if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) { - // if dropping into on an existing SoundEffect, update - targetNode.variantProperty("source").setValue(relPath); - } else { - // create a new SoundEffect - ItemLibraryEntry itemLibraryEntry; - itemLibraryEntry.setName("SoundEffect"); - itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0); + // set source property + PropertyName prop = "source"; + QString type = "QUrl"; + QVariant val = relPath; + itemLibraryEntry.addProperty(prop, type, val); - // set shader properties - PropertyName prop = "source"; - QString type = "QUrl"; - QVariant val = relPath; - itemLibraryEntry.addProperty(prop, type, val); + // create a texture + newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, + targetProperty, false); - // create a texture - newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, - targetProperty, false); - - // Rename the node based on source - QFileInfo fi(relPath); - newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), - "soundEffect")); - } - }); - - if (newModelNode.isValid()) { - moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); - m_view->setSelectedModelNode(newModelNode); + // Rename the node based on source + QFileInfo fi(relPath); + newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), + "soundEffect")); } + }); - if (addImport) - QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); - } + if (addImport) + QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); + + return newModelNode; } -void NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QMimeData *mimeData, int rowNumber, - const QModelIndex &dropModelIndex) +ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath, + NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex) { - QTC_ASSERT(m_view, return); + QTC_ASSERT(m_view, return {}); + Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D")); if (!m_view->model()->hasImport(import, true, true)) - return; + return {}; - const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); - int targetRowNumber = rowNumber; - NodeAbstractProperty targetProperty; + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - ModelNode targetNode(modelNodeForIndex(rowModelIndex)); + const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir() + .relativeFilePath(tex3DPath); // relative to qml file - const QString imageSource = QString::fromUtf8( - mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path - const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir() - .relativeFilePath(imageSource); // relative to qml file + ModelNode newModelNode; - ModelNode newModelNode; - - if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { - m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] { - // create a standalone Texture3D at drop location - newModelNode = createTextureNode(targetProperty, imagePath); - if (!NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode)) - newModelNode.destroy(); - }); - } - - if (newModelNode.isValid()) { - moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); - m_view->setSelectedModelNode(newModelNode); - } + if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { + m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] { + // create a standalone Texture3D at drop location + newModelNode = createTextureNode(targetProperty, imagePath); + if (!NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode)) + newModelNode.destroy(); + }); } + + return newModelNode; } bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode, diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h index b97ec042806..3146480506a 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h @@ -114,11 +114,16 @@ private: int targetIndex, bool executeInTransaction = true); void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); - void handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); - void handleItemLibraryFontDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); - void handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); - void handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); - void handleItemLibraryTexture3dDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); + ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex); + ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex); + ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader, + NodeAbstractProperty targetProperty, const QModelIndex &rowModelIndex); + ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex); + ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty, + const QModelIndex &rowModelIndex); bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp, const QString &imagePath, ModelNode &newNode); ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath); diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index 1accbbd54fb..4c329352b92 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -161,6 +161,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view, propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))}); propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))}); propertyPairList.append({PropertyName("font.family"), QVariant(fontFamily)}); + propertyPairList.append({PropertyName("font.pointSize"), 20}); propertyPairList.append({PropertyName("text"), QVariant(fontFamily)}); newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Text", metaInfo.majorVersion(),