From ccf6b7032f13317d87790c406f05c2d262c11475 Mon Sep 17 00:00:00 2001 From: Shrief Gabr Date: Thu, 29 Aug 2024 22:27:13 +0300 Subject: [PATCH] QmlDesigner: Allow folders drag & drop in Asset Library Fixes: QDS-13465 Change-Id: Ib9f30f18cf927417037dfa4c79b53534d2ad8e86 Reviewed-by: Mahmoud Badri --- .../assetsLibraryQmlSources/AssetDelegate.qml | 61 ++++++++---------- .../assetsLibraryQmlSources/AssetsView.qml | 4 +- .../assetslibrary/assetslibrary.qrc | 2 + .../assetslibraryiconprovider.cpp | 2 + .../assetslibrary/assetslibrarymodel.cpp | 8 +++ .../assetslibrary/assetslibrarymodel.h | 1 + .../assetslibrary/images/asset_folder.png | Bin 0 -> 180 bytes .../assetslibrary/images/asset_folder@2x.png | Bin 0 -> 232 bytes .../libs/qmldesignerutils/asset.cpp | 10 ++- .../qmldesigner/libs/qmldesignerutils/asset.h | 4 +- 10 files changed, 53 insertions(+), 39 deletions(-) create mode 100644 src/plugins/qmldesigner/components/assetslibrary/images/asset_folder.png create mode 100644 src/plugins/qmldesigner/components/assetslibrary/images/asset_folder@2x.png diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml index 7128e8b09e0..53caf73cbfe 100644 --- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml +++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml @@ -101,20 +101,8 @@ TreeViewDelegate { : "transparent" } border.width: StudioTheme.Values.border - border.color: { - if (root.__isDirectory && (root.isHighlighted || root.hasChildWithDropHover)) - return StudioTheme.Values.themeInteraction - - if (!root.__isDirectory && root.assetsView.selectedAssets[root.__itemPath]) - return StudioTheme.Values.themeInteraction - - if (mouseArea.containsMouse) - return StudioTheme.Values.themeSectionHeadBackground - - return root.__isDirectory - ? StudioTheme.Values.themeSectionHeadBackground - : "transparent" - } + border.color: root.assetsView.selectedAssets[root.__itemPath] ? StudioTheme.Values.themeInteraction + : "transparent" } contentItem: Text { @@ -158,26 +146,31 @@ TreeViewDelegate { mouseArea.allowTooltip = false AssetsLibraryBackend.tooltipBackend.hideTooltip() - if (root.__isDirectory) - return - var ctrlDown = mouse.modifiers & Qt.ControlModifier - if (mouse.button === Qt.LeftButton) { - if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) - root.assetsView.clearSelectedAssets() - root.currFileSelected = ctrlDown ? !root.assetsView.isAssetSelected(root.__itemPath) : true - root.assetsView.setAssetSelected(root.__itemPath, root.currFileSelected) - if (root.currFileSelected) { - let selectedPaths = root.assetsView.selectedPathsAsList() - AssetsLibraryBackend.rootView.startDragAsset(selectedPaths, mapToGlobal(mouse.x, mouse.y)) - } - } else { - if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) - root.assetsView.clearSelectedAssets() - root.currFileSelected = root.assetsView.isAssetSelected(root.__itemPath) || !ctrlDown - root.assetsView.setAssetSelected(root.__itemPath, root.currFileSelected) - } + if (mouse.button === Qt.LeftButton) { + if (root.__isDirectory) { + // ensure only one directory can be selected + root.assetsView.clearSelectedAssets() + root.currFileSelected = true + } else { + if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) + root.assetsView.clearSelectedAssets() + root.currFileSelected = ctrlDown ? !root.assetsView.isAssetSelected(root.__itemPath) : true + } + + root.assetsView.setAssetSelected(root.__itemPath, root.currFileSelected) + + if (root.currFileSelected) { + let selectedPaths = root.assetsView.selectedPathsAsList() + AssetsLibraryBackend.rootView.startDragAsset(selectedPaths, mapToGlobal(mouse.x, mouse.y)) + } + } else { + if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) + root.assetsView.clearSelectedAssets() + root.currFileSelected = root.assetsView.isAssetSelected(root.__itemPath) || !ctrlDown + root.assetsView.setAssetSelected(root.__itemPath, root.currFileSelected) + } } onReleased: (mouse) => { @@ -356,8 +349,8 @@ TreeViewDelegate { onEntered: (drag) => { root.assetsRoot.updateDropExtFiles(drag) - - drag.accepted |= (drag.formats[0] === "application/vnd.qtdesignstudio.assets") + drag.accepted |= drag.formats[0] === "application/vnd.qtdesignstudio.assets" + && !root.assetsModel.isSameOrDescendantPath(drag.urls[0], root.__itemPath) if (root.__isDirectory) root.isHighlighted = drag.accepted diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml index 698011db367..307d3637521 100644 --- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml +++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml @@ -83,9 +83,7 @@ TreeView { interval: 200 repeat: false - onTriggered: { - root.updateRows() - } + onTriggered: root.updateRows() } Connections { diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrary.qrc b/src/plugins/qmldesigner/components/assetslibrary/assetslibrary.qrc index fb4255cdf6f..6f92dd861cf 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrary.qrc +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrary.qrc @@ -22,5 +22,7 @@ images/asset_ktx.png images/asset_ktx@2x.png images/asset_ktx_128.png + images/asset_folder.png + images/asset_folder@2x.png diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp index 6ea038777ae..15e67b74aa1 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp @@ -110,6 +110,8 @@ QPair AssetsLibraryIconProvider::fetchPixmap(const QString &id, type = "video"; else if (asset.isEffect()) type = QmlDesigner::ModelNodeOperations::getEffectIcon(id); + else if (asset.isFolder()) + type = "folder"; QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type); QString path = pathTemplate.arg('_' + QString::number(requestedSize.width())); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index 11eb4b27162..d12d824ddc8 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -197,6 +197,14 @@ bool AssetsLibraryModel::allFilePathsAreComposedEffects(const QStringList &fileP }); } +bool AssetsLibraryModel::isSameOrDescendantPath(const QUrl &source, const QString &target) const +{ + Utils::FilePath srcPath = Utils::FilePath::fromUrl(source); + Utils::FilePath targetPath = Utils::FilePath::fromString(target); + + return targetPath.isChildOf(srcPath); +} + bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QString path = m_sourceFsModel->filePath(sourceParent); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h index d1a78bcaf57..27b5eb77f27 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h @@ -50,6 +50,7 @@ public: Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex); Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const; Q_INVOKABLE bool allFilePathsAreComposedEffects(const QStringList &filePaths) const; + Q_INVOKABLE bool isSameOrDescendantPath(const QUrl &source, const QString &target) const; int columnCount(const QModelIndex &parent = QModelIndex()) const override { diff --git a/src/plugins/qmldesigner/components/assetslibrary/images/asset_folder.png b/src/plugins/qmldesigner/components/assetslibrary/images/asset_folder.png new file mode 100644 index 0000000000000000000000000000000000000000..4258ef5876141084d639b1ed00cbff2b4df7c694 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|7G?$p2BAoW(+ms@iUB?$t_%ze%VA&{7%X4D zeA%*P%a<=-zkdC)Wy@O1{mU5`7`RG;{DK+oE7ZR~zdyi1K)7aY2m=Fyg{O;Sh{WaO z1H4yQSX&>?SrNKAO!9!m>V|}kLJ~dXvJOBUy literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/assetslibrary/images/asset_folder@2x.png b/src/plugins/qmldesigner/components/assetslibrary/images/asset_folder@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bd59f52551f9c93b9ff41ac7319828b6d029f1db GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-7G?$phNU`BwlFX-=mz+NxH2#>EJp&%mMvSp zeEBjkSh{p6mEpI^S?d(sYi*gh-7JR*v|D1UY!PC{xWt~$(695HfS3Lj# literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/libs/qmldesignerutils/asset.cpp b/src/plugins/qmldesigner/libs/qmldesignerutils/asset.cpp index ec1e4312e41..445a0e4fb8b 100644 --- a/src/plugins/qmldesigner/libs/qmldesignerutils/asset.cpp +++ b/src/plugins/qmldesigner/libs/qmldesignerutils/asset.cpp @@ -207,10 +207,18 @@ bool Asset::isValidTextureSource() return isImage() || isTexture3D(); } +bool Asset::isFolder() const +{ + return m_type == Asset::Type::Folder; +} + void Asset::resolveType() { - if (m_suffix.isEmpty()) + if (m_suffix.isEmpty()) { + m_type = Asset::Type::Folder; + return; + } if (supportedImageSuffixes().contains(m_suffix)) m_type = Asset::Type::Image; diff --git a/src/plugins/qmldesigner/libs/qmldesignerutils/asset.h b/src/plugins/qmldesigner/libs/qmldesignerutils/asset.h index 1deafd11b78..e85c1462a40 100644 --- a/src/plugins/qmldesigner/libs/qmldesignerutils/asset.h +++ b/src/plugins/qmldesigner/libs/qmldesignerutils/asset.h @@ -24,7 +24,8 @@ public: Audio, Video, Texture3D, - Effect }; + Effect, + Folder }; Asset(const QString &filePath); @@ -60,6 +61,7 @@ public: bool isEffect() const; bool isSupported() const; bool isValidTextureSource(); + bool isFolder() const; private: void resolveType();