Files
qt-creator/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
Shrief Gabr c120ed0ac6 QmlDesigner: Fix missing Assets on folder drag & drop
Fixes: QDS-13784
Change-Id: I86c3f0c9b476a3945219e6be155831c795bdd9da
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
2024-10-10 15:05:44 +00:00

280 lines
9.6 KiB
QML

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import AssetsLibraryBackend
Item {
id: root
property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView
// Array of supported externally dropped files that are imported as-is
property var dropSimpleExtFiles: []
// Array of supported externally dropped files that trigger custom import process
property var dropComplexExtFiles: []
readonly property int qtVersion: rootView.qtVersion()
property bool __searchBoxEmpty: true
property bool highlightCanvas: false
AssetsContextMenu {
id: contextMenu
assetsView: assetsView
}
function clearSearchFilter() {
searchBox.clear()
}
function updateDropExtFiles(drag) {
root.dropSimpleExtFiles = []
root.dropComplexExtFiles = []
var simpleSuffixes = rootView.supportedAssetSuffixes(false)
var complexSuffixes = rootView.supportedAssetSuffixes(true)
for (const u of drag.urls) {
var url = u.toString()
if (assetsModel.urlPathExistsInModel(url))
continue;
var ext = '*.' + url.slice(url.lastIndexOf('.') + 1).toLowerCase()
if (simpleSuffixes.includes(ext))
root.dropSimpleExtFiles.push(url)
else if (complexSuffixes.includes(ext))
root.dropComplexExtFiles.push(url)
}
drag.accepted = root.dropSimpleExtFiles.length > 0 || root.dropComplexExtFiles.length > 0
}
DropArea { // handles external drop on empty area of the view (goes to root folder)
id: dropArea
y: assetsView.y + assetsView.contentHeight - assetsView.rowSpacing
width: parent.width
height: parent.height - y
onEntered: (drag) => {
if (drag.formats[0] === "application/vnd.qtdesignstudio.assets")
drag.accepted = drag.urls.length > 0
else
root.updateDropExtFiles(drag)
}
onDropped: (drag) => {
drag.accept()
if (drag.formats[0] === "application/vnd.qtdesignstudio.assets") {
root.rootView.handleAssetsDrop(drag.urls, assetsModel.rootPath())
} else {
root.rootView.handleExtFilesDrop(root.dropSimpleExtFiles,
root.dropComplexExtFiles,
assetsModel.rootPath())
}
}
Canvas { // marker for the drop area
id: dropCanvas
y: 5
width: parent.width
height: parent.height - y
visible: dropArea.containsDrag || root.highlightCanvas
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()
}
}
}
MouseArea { // right clicking the empty area of the view
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
if (!assetsModel.isEmpty) {
function onFolderCreated(path) {
assetsView.addCreatedFolder(path)
}
var rootIndex = assetsModel.rootIndex()
var dirPath = assetsModel.filePath(rootIndex)
var dirName = assetsModel.fileName(rootIndex)
contextMenu.openContextMenuForRoot(rootIndex, dirPath, dirName, onFolderCreated)
}
}
}
// called from C++ to close context menu on focus out
function handleViewFocusOut() {
contextMenu.close()
assetsView.selectedAssets = {}
assetsView.selectedAssetsChanged()
}
Timer {
id: updateSearchFilterTimer
interval: 200
repeat: false
onTriggered: {
assetsView.resetVerticalScrollPosition()
rootView.handleSearchFilterChanged(searchBox.text)
assetsView.expandAll()
if (root.__searchBoxEmpty && searchBox.text)
root.__searchBoxEmpty = false
else if (!root.__searchBoxEmpty && !searchBox.text)
root.__searchBoxEmpty = true
}
}
Column {
id: column
anchors.fill: parent
spacing: 5
Rectangle {
id: toolbar
width: parent.width
height: StudioTheme.Values.doubleToolbarHeight
color: StudioTheme.Values.themeToolbarBackground
Column {
id: toolbarColumn
anchors.fill: parent
anchors.topMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.bottomMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.leftMargin: StudioTheme.Values.toolbarHorizontalMargin
anchors.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
spacing: StudioTheme.Values.toolbarColumnSpacing
StudioControls.SearchBox {
id: searchBox
width: parent.width
style: StudioTheme.Values.searchControlStyle
onSearchChanged: (searchText) => {
updateSearchFilterTimer.restart()
}
}
Row {
id: buttonRow
width: parent.width
height: StudioTheme.Values.toolbarHeight
spacing: 6
HelperWidgets.AbstractButton {
id: addModuleButton
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.add_medium
tooltip: qsTr("Add a new asset to the project.")
onClicked: rootView.handleAddAsset()
}
}
}
}
Text {
text: qsTr("No match found.")
leftPadding: 10
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFont
visible: assetsModel.isEmpty && !root.__searchBoxEmpty
}
Item { // placeholder when the assets library is empty
width: parent.width
height: parent.height - toolbar.height - column.spacing
visible: assetsModel.isEmpty && root.__searchBoxEmpty
clip: true
MouseArea { // right clicking the empty area of the view
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
contextMenu.openContextMenuForEmpty(assetsModel.rootPath())
}
}
DropArea { // handles external drop (goes into default folder based on suffix)
anchors.fill: parent
onEntered: (drag) => {
root.updateDropExtFiles(drag)
}
onDropped: (drag) => {
drag.accept()
rootView.emitExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles)
}
Column {
id: noAssetsColumn
spacing: 20
width: root.width - 40
anchors.centerIn: parent
Text {
text: qsTr("Looks like you don't have any assets yet.")
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.bigFont
width: noAssetsColumn.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Image {
source: "image://qmldesigner_assets/browse"
anchors.horizontalCenter: parent.horizontalCenter
scale: maBrowse.containsMouse ? 1.2 : 1
Behavior on scale {
NumberAnimation {
duration: 300
easing.type: Easing.OutQuad
}
}
MouseArea {
id: maBrowse
anchors.fill: parent
hoverEnabled: true
onClicked: rootView.handleAddAsset();
}
}
Text {
text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.")
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.bigFont
width: noAssetsColumn.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}
}
}
AssetsView {
id: assetsView
width: parent.width
height: parent.height - assetsView.y
assetsRoot: root
contextMenu: contextMenu
focus: true
}
}
}