diff options
author | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-03-03 12:40:40 +0200 |
---|---|---|
committer | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-03-04 10:14:00 +0000 |
commit | c250d31ca0befccf08cf74bbe9349ad4f481cfc3 (patch) | |
tree | 75e24497d33cb1ba27406549a88a33dff82dab90 /share | |
parent | 8da5a772fed3f85ba41ee0f91efbed592137458c (diff) |
QmlDesigner: Enable dropping external assets to a specific folder
Fixes: QDS-6311
Change-Id: I25bccfa6788e3b5d47fc598decbf7e03a00399b4
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'share')
-rw-r--r-- | share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml | 186 | ||||
-rw-r--r-- | share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml | 19 |
2 files changed, 131 insertions, 74 deletions
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index cf125d72d8..5ac4d0fc6e 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -32,45 +32,67 @@ import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme Item { - id: rootItem + id: root property var selectedAssets: ({}) property int allExpandedState: 0 property string contextFilePath: "" property var contextDir: undefined property bool isDirContextMenu: false + property var dropExtFiles: [] // array of supported externally dropped files function clearSearchFilter() { searchBox.text = ""; } - DropArea { - id: dropArea + function updateDropExtFiles(drag) + { + root.dropExtFiles = [] + for (const u of drag.urls) { + var url = u.toString(); + if (url.startsWith("file:///")) // remove file scheme (happens on Windows) + url = url.substr(8) + + var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase() + if (rootView.supportedDropSuffixes().includes('*.' + ext)) + root.dropExtFiles.push(url) + } - property var files // list of supported dropped files + drag.accepted = root.dropExtFiles.length > 0 + } - enabled: true - anchors.fill: parent + DropArea { // handles external drop on empty area of the view (goes to root folder) + id: dropArea + y: assetsView.y + assetsView.contentHeight + 5 + width: parent.width + height: parent.height - y onEntered: (drag)=> { - files = [] - for (var i = 0; i < drag.urls.length; ++i) { - var url = drag.urls[i].toString(); - if (url.startsWith("file:///")) // remove file scheme (happens on Windows) - url = url.substr(8) - var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase() - if (rootView.supportedDropSuffixes().includes('*.' + ext)) - files.push(url) - } - - if (files.length === 0) - drag.accepted = false; + root.updateDropExtFiles(drag) } onDropped: { - if (files.length > 0) - rootView.handleFilesDrop(files) + rootView.handleExtFilesDrop(root.dropExtFiles, assetsModel.rootDir().dirPath) + } + + Canvas { // marker for the drop area + id: dropCanvas + anchors.fill: parent + visible: dropArea.containsDrag + + onWidthChanged: dropCanvas.requestPaint() + onHeightChanged: dropCanvas.requestPaint() + + onPaint: { + var ctx = getContext("2d") + ctx.reset() + ctx.strokeStyle = StudioTheme.Values.themeInteraction + ctx.lineWidth = 2 + ctx.setLineDash([4, 4]) + ctx.rect(5, 5, dropCanvas.width - 10, dropCanvas.height - 10) + ctx.stroke() + } } } @@ -79,9 +101,9 @@ Item { acceptedButtons: Qt.RightButton onClicked: { if (!assetsModel.isEmpty) { - contextFilePath = "" - contextDir = assetsModel.rootDir() - isDirContextMenu = false + root.contextFilePath = "" + root.contextDir = assetsModel.rootDir() + root.isDirContextMenu = false contextMenu.popup() } } @@ -91,8 +113,8 @@ Item { function handleViewFocusOut() { contextMenu.close() - selectedAssets = {} - selectedAssetsChanged() + root.selectedAssets = {} + root.selectedAssetsChanged() } StudioControls.Menu { @@ -101,49 +123,49 @@ Item { closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape onOpened: { - var numSelected = Object.values(selectedAssets).filter(p => p).length + var numSelected = Object.values(root.selectedAssets).filter(p => p).length deleteFileItem.text = numSelected > 1 ? qsTr("Delete Files") : qsTr("Delete File") } StudioControls.MenuItem { text: qsTr("Expand All") - enabled: allExpandedState !== 1 - visible: isDirContextMenu + enabled: root.allExpandedState !== 1 + visible: root.isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: assetsModel.toggleExpandAll(true) } StudioControls.MenuItem { text: qsTr("Collapse All") - enabled: allExpandedState !== 2 - visible: isDirContextMenu + enabled: root.allExpandedState !== 2 + visible: root.isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: assetsModel.toggleExpandAll(false) } StudioControls.MenuSeparator { - visible: isDirContextMenu + visible: root.isDirContextMenu height: visible ? StudioTheme.Values.border : 0 } StudioControls.MenuItem { id: deleteFileItem text: qsTr("Delete File") - visible: contextFilePath - height: visible ? implicitHeight : 0 + visible: root.contextFilePath + height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0 onTriggered: { - assetsModel.deleteFiles(Object.keys(selectedAssets).filter(p => selectedAssets[p])) + assetsModel.deleteFiles(Object.keys(root.selectedAssets).filter(p => root.selectedAssets[p])) } } StudioControls.MenuSeparator { - visible: contextFilePath + visible: root.contextFilePath height: visible ? StudioTheme.Values.border : 0 } StudioControls.MenuItem { text: qsTr("Rename Folder") - visible: isDirContextMenu + visible: root.isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: renameFolderDialog.open() } @@ -155,14 +177,14 @@ Item { StudioControls.MenuItem { text: qsTr("Delete Folder") - visible: isDirContextMenu + visible: root.isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: { - var dirEmpty = !(contextDir.dirsModel && contextDir.dirsModel.rowCount() > 0) - && !(contextDir.filesModel && contextDir.filesModel.rowCount() > 0); + var dirEmpty = !(root.contextDir.dirsModel && root.contextDir.dirsModel.rowCount() > 0) + && !(root.contextDir.filesModel && root.contextDir.filesModel.rowCount() > 0); if (dirEmpty) - assetsModel.deleteFolder(contextDir.dirPath) + assetsModel.deleteFolder(root.contextDir.dirPath) else confirmDeleteFolderDialog.open() } @@ -243,7 +265,7 @@ Item { text: qsTr("Rename") enabled: folderRename.text !== "" onClicked: { - var success = assetsModel.renameFolder(contextDir.dirPath, folderRename.text) + var success = assetsModel.renameFolder(root.contextDir.dirPath, folderRename.text) if (success) renameFolderDialog.accept() @@ -259,7 +281,7 @@ Item { } onOpened: { - folderRename.text = contextDir.dirName + folderRename.text = root.contextDir.dirName folderRename.selectAll() folderRename.forceActiveFocus() renameFolderDialog.renameError = false @@ -317,7 +339,7 @@ Item { text: qsTr("Create") enabled: folderName.text !== "" onClicked: { - assetsModel.addNewFolder(contextDir.dirPath + '/' + folderName.text) + assetsModel.addNewFolder(root.contextDir.dirPath + '/' + folderName.text) newFolderDialog.accept() } } @@ -353,7 +375,7 @@ Item { id: folderNotEmpty text: qsTr("Folder \"%1\" is not empty. Delete it anyway?") - .arg(contextDir ? contextDir.dirName : "") + .arg(root.contextDir ? root.contextDir.dirName : "") color: StudioTheme.Values.themeTextColor wrapMode: Text.WordWrap width: confirmDeleteFolderDialog.width @@ -381,7 +403,7 @@ Item { text: qsTr("Delete") onClicked: { - assetsModel.deleteFolder(contextDir.dirPath) + assetsModel.deleteFolder(root.contextDir.dirPath) confirmDeleteFolderDialog.accept() } } @@ -441,7 +463,7 @@ Item { spacing: 20 x: 20 - width: rootItem.width - 2 * x + width: root.width - 2 * x anchors.verticalCenter: parent.verticalCenter Text { @@ -500,6 +522,8 @@ Item { id: dirSection Section { + id: section + width: assetsView.width - (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) - 5 caption: dirName @@ -514,16 +538,31 @@ Item { visible: dirVisible expandOnClick: false useDefaulContextMenu: false + dropEnabled: true onToggleExpand: { dirExpanded = !dirExpanded } + onDropEnter: (drag)=> { + root.updateDropExtFiles(drag) + section.highlight = drag.accepted + } + + onDropExit: { + section.highlight = false + } + + onDrop: { + section.highlight = false + rootView.handleExtFilesDrop(root.dropExtFiles, dirPath) + } + onShowContextMenu: { - contextFilePath = "" - contextDir = model - isDirContextMenu = true - allExpandedState = assetsModel.getAllExpandedState() + root.contextFilePath = "" + root.contextDir = model + root.isDirContextMenu = true + root.allExpandedState = assetsModel.getAllExpandedState() contextMenu.popup() } @@ -552,9 +591,9 @@ Item { anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { - contextFilePath = "" - contextDir = model - isDirContextMenu = true + root.contextFilePath = "" + root.contextDir = model + root.isDirContextMenu = true contextMenu.popup() } } @@ -570,9 +609,10 @@ Item { width: assetsView.width - (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) height: img.height - color: selectedAssets[filePath] ? StudioTheme.Values.themeInteraction - : (mouseArea.containsMouse ? StudioTheme.Values.themeSectionHeadBackground - : "transparent") + color: root.selectedAssets[filePath] + ? StudioTheme.Values.themeInteraction + : (mouseArea.containsMouse ? StudioTheme.Values.themeSectionHeadBackground + : "transparent") Row { spacing: 5 @@ -611,29 +651,29 @@ Item { forceActiveFocus() var ctrlDown = mouse.modifiers & Qt.ControlModifier if (mouse.button === Qt.LeftButton) { - if (!selectedAssets[filePath] && !ctrlDown) - selectedAssets = {} - currFileSelected = ctrlDown ? !selectedAssets[filePath] : true - selectedAssets[filePath] = currFileSelected - selectedAssetsChanged() + if (!root.selectedAssets[filePath] && !ctrlDown) + root.selectedAssets = {} + currFileSelected = ctrlDown ? !root.selectedAssets[filePath] : true + root.selectedAssets[filePath] = currFileSelected + root.selectedAssetsChanged() if (currFileSelected) { rootView.startDragAsset( - Object.keys(selectedAssets).filter(p => selectedAssets[p]), + Object.keys(root.selectedAssets).filter(p => root.selectedAssets[p]), mapToGlobal(mouse.x, mouse.y)) } } else { - if (!selectedAssets[filePath] && !ctrlDown) - selectedAssets = {} - currFileSelected = selectedAssets[filePath] || !ctrlDown - selectedAssets[filePath] = currFileSelected - selectedAssetsChanged() + if (!root.selectedAssets[filePath] && !ctrlDown) + root.selectedAssets = {} + currFileSelected = root.selectedAssets[filePath] || !ctrlDown + root.selectedAssets[filePath] = currFileSelected + root.selectedAssetsChanged() - contextFilePath = filePath - contextDir = model.fileDir + root.contextFilePath = filePath + root.contextDir = model.fileDir + root.isDirContextMenu = false tooltipBackend.hideTooltip() - isDirContextMenu = false contextMenu.popup() } } @@ -641,9 +681,9 @@ Item { onReleased: (mouse)=> { if (mouse.button === Qt.LeftButton) { if (!(mouse.modifiers & Qt.ControlModifier)) - selectedAssets = {} - selectedAssets[filePath] = currFileSelected - selectedAssetsChanged() + root.selectedAssets = {} + root.selectedAssets[filePath] = currFileSelected + root.selectedAssetsChanged() } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index 3f8a331189..143ec349d0 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -54,6 +54,8 @@ Item { property bool expandOnClick: true // if false, toggleExpand signal will be emitted instead property bool addTopPadding: true property bool addBottomPadding: true + property bool dropEnabled: false + property bool highlight: false property bool useDefaulContextMenu: true @@ -72,9 +74,22 @@ Item { function onExpandAll() { section.expanded = true } } + signal drop(var drag) + signal dropEnter(var drag) + signal dropExit() signal showContextMenu() signal toggleExpand() + DropArea { + id: dropArea + + enabled: section.dropEnabled + anchors.fill: parent + + onEntered: (drag)=> section.dropEnter(drag) + onDropped: (drag)=> section.drop(drag) + onExited: section.dropExit() + } Rectangle { id: header @@ -82,7 +97,9 @@ Item { visible: !section.hideHeader anchors.left: parent.left anchors.right: parent.right - color: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + (0.2 * section.level)) + color: section.highlight ? StudioTheme.Values.themeInteraction + : Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + + (0.2 * section.level)) Item { StudioControls.Menu { |