QmlDesigner: Allow folders drag & drop in Asset Library

Fixes: QDS-13465
Change-Id: Ib9f30f18cf927417037dfa4c79b53534d2ad8e86
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Shrief Gabr
2024-08-29 22:27:13 +03:00
parent 3b06797374
commit ccf6b7032f
10 changed files with 53 additions and 39 deletions

View File

@@ -101,20 +101,8 @@ TreeViewDelegate {
: "transparent" : "transparent"
} }
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
border.color: { border.color: root.assetsView.selectedAssets[root.__itemPath] ? StudioTheme.Values.themeInteraction
if (root.__isDirectory && (root.isHighlighted || root.hasChildWithDropHover)) : "transparent"
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"
}
} }
contentItem: Text { contentItem: Text {
@@ -158,26 +146,31 @@ TreeViewDelegate {
mouseArea.allowTooltip = false mouseArea.allowTooltip = false
AssetsLibraryBackend.tooltipBackend.hideTooltip() AssetsLibraryBackend.tooltipBackend.hideTooltip()
if (root.__isDirectory)
return
var ctrlDown = mouse.modifiers & Qt.ControlModifier 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) { if (mouse.button === Qt.LeftButton) {
let selectedPaths = root.assetsView.selectedPathsAsList() if (root.__isDirectory) {
AssetsLibraryBackend.rootView.startDragAsset(selectedPaths, mapToGlobal(mouse.x, mouse.y)) // ensure only one directory can be selected
} root.assetsView.clearSelectedAssets()
} else { root.currFileSelected = true
if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) } else {
root.assetsView.clearSelectedAssets() if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown)
root.currFileSelected = root.assetsView.isAssetSelected(root.__itemPath) || !ctrlDown root.assetsView.clearSelectedAssets()
root.assetsView.setAssetSelected(root.__itemPath, root.currFileSelected) 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) => { onReleased: (mouse) => {
@@ -356,8 +349,8 @@ TreeViewDelegate {
onEntered: (drag) => { onEntered: (drag) => {
root.assetsRoot.updateDropExtFiles(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) if (root.__isDirectory)
root.isHighlighted = drag.accepted root.isHighlighted = drag.accepted

View File

@@ -83,9 +83,7 @@ TreeView {
interval: 200 interval: 200
repeat: false repeat: false
onTriggered: { onTriggered: root.updateRows()
root.updateRows()
}
} }
Connections { Connections {

View File

@@ -22,5 +22,7 @@
<file>images/asset_ktx.png</file> <file>images/asset_ktx.png</file>
<file>images/asset_ktx@2x.png</file> <file>images/asset_ktx@2x.png</file>
<file>images/asset_ktx_128.png</file> <file>images/asset_ktx_128.png</file>
<file>images/asset_folder.png</file>
<file>images/asset_folder@2x.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -110,6 +110,8 @@ QPair<QPixmap, qint64> AssetsLibraryIconProvider::fetchPixmap(const QString &id,
type = "video"; type = "video";
else if (asset.isEffect()) else if (asset.isEffect())
type = QmlDesigner::ModelNodeOperations::getEffectIcon(id); type = QmlDesigner::ModelNodeOperations::getEffectIcon(id);
else if (asset.isFolder())
type = "folder";
QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type); QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type);
QString path = pathTemplate.arg('_' + QString::number(requestedSize.width())); QString path = pathTemplate.arg('_' + QString::number(requestedSize.width()));

View File

@@ -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 bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{ {
QString path = m_sourceFsModel->filePath(sourceParent); QString path = m_sourceFsModel->filePath(sourceParent);

View File

@@ -50,6 +50,7 @@ public:
Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex); Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex);
Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const; Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const;
Q_INVOKABLE bool allFilePathsAreComposedEffects(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 int columnCount(const QModelIndex &parent = QModelIndex()) const override
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

View File

@@ -207,10 +207,18 @@ bool Asset::isValidTextureSource()
return isImage() || isTexture3D(); return isImage() || isTexture3D();
} }
bool Asset::isFolder() const
{
return m_type == Asset::Type::Folder;
}
void Asset::resolveType() void Asset::resolveType()
{ {
if (m_suffix.isEmpty()) if (m_suffix.isEmpty()) {
m_type = Asset::Type::Folder;
return; return;
}
if (supportedImageSuffixes().contains(m_suffix)) if (supportedImageSuffixes().contains(m_suffix))
m_type = Asset::Type::Image; m_type = Asset::Type::Image;

View File

@@ -24,7 +24,8 @@ public:
Audio, Audio,
Video, Video,
Texture3D, Texture3D,
Effect }; Effect,
Folder };
Asset(const QString &filePath); Asset(const QString &filePath);
@@ -60,6 +61,7 @@ public:
bool isEffect() const; bool isEffect() const;
bool isSupported() const; bool isSupported() const;
bool isValidTextureSource(); bool isValidTextureSource();
bool isFolder() const;
private: private:
void resolveType(); void resolveType();