2023-02-09 09:17:37 +01:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
2023-01-04 08:52:22 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2021-05-04 22:35:50 +03:00
|
|
|
|
2022-11-23 11:49:45 +02:00
|
|
|
import QtQuick
|
|
|
|
|
import HelperWidgets as HelperWidgets
|
|
|
|
|
import StudioControls as StudioControls
|
|
|
|
|
import StudioTheme as StudioTheme
|
2023-03-07 16:51:02 +01:00
|
|
|
import AssetsLibraryBackend
|
2021-05-04 22:35:50 +03:00
|
|
|
|
|
|
|
|
Item {
|
2022-03-03 12:40:40 +02:00
|
|
|
id: root
|
2021-11-05 00:45:34 +02:00
|
|
|
|
2023-03-07 16:51:02 +01:00
|
|
|
property var assetsModel: AssetsLibraryBackend.assetsModel
|
|
|
|
|
property var rootView: AssetsLibraryBackend.rootView
|
|
|
|
|
|
2022-03-15 13:02:15 +02:00
|
|
|
// 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: []
|
2021-06-15 17:24:24 +03:00
|
|
|
|
2023-03-09 17:17:03 +02:00
|
|
|
readonly property int qtVersion: rootView.qtVersion()
|
2022-11-23 15:47:34 +02:00
|
|
|
property bool __searchBoxEmpty: true
|
2022-11-23 11:49:45 +02:00
|
|
|
|
2022-10-07 19:49:52 +03:00
|
|
|
AssetsContextMenu {
|
|
|
|
|
id: contextMenu
|
2022-11-23 11:49:45 +02:00
|
|
|
assetsView: assetsView
|
2022-10-07 19:49:52 +03:00
|
|
|
}
|
|
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
function clearSearchFilter() {
|
|
|
|
|
searchBox.clear()
|
2022-02-03 19:49:27 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
function updateDropExtFiles(drag) {
|
2022-03-15 13:02:15 +02:00
|
|
|
root.dropSimpleExtFiles = []
|
|
|
|
|
root.dropComplexExtFiles = []
|
2023-02-09 09:17:37 +01:00
|
|
|
var simpleSuffixes = rootView.supportedAssetSuffixes(false)
|
|
|
|
|
var complexSuffixes = rootView.supportedAssetSuffixes(true)
|
2022-03-03 12:40:40 +02:00
|
|
|
for (const u of drag.urls) {
|
2023-02-09 09:17:37 +01:00
|
|
|
var url = u.toString()
|
2023-02-01 12:10:34 +02:00
|
|
|
if (assetsModel.urlPathExistsInModel(url))
|
|
|
|
|
continue;
|
|
|
|
|
|
2022-03-15 13:02:15 +02:00
|
|
|
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)
|
2022-03-03 12:40:40 +02:00
|
|
|
}
|
2021-05-04 22:35:50 +03:00
|
|
|
|
2022-03-15 13:02:15 +02:00
|
|
|
drag.accepted = root.dropSimpleExtFiles.length > 0 || root.dropComplexExtFiles.length > 0
|
2022-03-03 12:40:40 +02:00
|
|
|
}
|
2021-05-04 22:35:50 +03:00
|
|
|
|
2022-03-03 12:40:40 +02:00
|
|
|
DropArea { // handles external drop on empty area of the view (goes to root folder)
|
|
|
|
|
id: dropArea
|
2023-02-16 14:28:12 +02:00
|
|
|
y: assetsView.y + assetsView.contentHeight - assetsView.rowSpacing
|
2022-03-03 12:40:40 +02:00
|
|
|
width: parent.width
|
|
|
|
|
height: parent.height - y
|
2021-05-04 22:35:50 +03:00
|
|
|
|
2023-02-17 15:22:55 +02:00
|
|
|
onEntered: (drag) => {
|
2022-03-03 12:40:40 +02:00
|
|
|
root.updateDropExtFiles(drag)
|
2021-05-04 22:35:50 +03:00
|
|
|
}
|
|
|
|
|
|
2023-02-17 15:22:55 +02:00
|
|
|
onDropped: (drag) => {
|
|
|
|
|
drag.accept()
|
2023-02-09 09:17:37 +01:00
|
|
|
rootView.handleExtFilesDrop(root.dropSimpleExtFiles,
|
|
|
|
|
root.dropComplexExtFiles,
|
2022-11-23 11:49:45 +02:00
|
|
|
assetsModel.rootPath())
|
2022-03-03 12:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Canvas { // marker for the drop area
|
|
|
|
|
id: dropCanvas
|
2023-02-16 14:28:12 +02:00
|
|
|
y: 5
|
|
|
|
|
width: parent.width
|
|
|
|
|
height: parent.height - y
|
2022-03-15 13:02:15 +02:00
|
|
|
visible: dropArea.containsDrag && root.dropSimpleExtFiles.length > 0
|
2022-03-03 12:40:40 +02:00
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
}
|
2021-05-04 22:35:50 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-28 16:12:23 +02:00
|
|
|
MouseArea { // right clicking the empty area of the view
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
|
|
|
onClicked: {
|
2022-11-23 11:49:45 +02:00
|
|
|
if (assetsModel.haveFiles) {
|
|
|
|
|
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)
|
2022-01-28 16:12:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-08 20:14:14 +03:00
|
|
|
// called from C++ to close context menu on focus out
|
2023-02-09 09:17:37 +01:00
|
|
|
function handleViewFocusOut() {
|
2021-06-08 20:14:14 +03:00
|
|
|
contextMenu.close()
|
2022-11-23 11:49:45 +02:00
|
|
|
assetsView.selectedAssets = {}
|
|
|
|
|
assetsView.selectedAssetsChanged()
|
2022-01-31 19:50:38 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-03 19:49:27 +02:00
|
|
|
Column {
|
2023-02-09 09:17:37 +01:00
|
|
|
id: column
|
2021-05-04 22:35:50 +03:00
|
|
|
anchors.fill: parent
|
2022-02-03 19:49:27 +02:00
|
|
|
spacing: 5
|
2021-07-02 15:10:40 +03:00
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
Rectangle {
|
|
|
|
|
id: toolbar
|
2022-02-03 19:49:27 +02:00
|
|
|
width: parent.width
|
2023-02-09 09:17:37 +01:00
|
|
|
height: StudioTheme.Values.doubleToolbarHeight
|
|
|
|
|
color: StudioTheme.Values.themeToolbarBackground
|
2022-01-28 16:12:23 +02:00
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
Column {
|
|
|
|
|
id: toolbarColumn
|
|
|
|
|
anchors.fill: parent
|
2023-02-13 11:20:27 +01:00
|
|
|
anchors.topMargin: 6
|
|
|
|
|
anchors.bottomMargin: 6
|
|
|
|
|
anchors.leftMargin: 10
|
|
|
|
|
anchors.rightMargin: 10
|
2023-02-09 09:17:37 +01:00
|
|
|
spacing: 12
|
|
|
|
|
|
|
|
|
|
StudioControls.SearchBox {
|
|
|
|
|
id: searchBox
|
2023-02-13 11:20:27 +01:00
|
|
|
width: parent.width
|
2023-02-09 09:17:37 +01:00
|
|
|
style: StudioTheme.Values.searchControlStyle
|
|
|
|
|
onSearchChanged: (searchText) => {
|
|
|
|
|
updateSearchFilterTimer.restart()
|
|
|
|
|
}
|
2022-11-23 11:49:45 +02:00
|
|
|
}
|
2022-01-31 19:50:38 +02:00
|
|
|
|
2023-02-09 09:17:37 +01:00
|
|
|
Row {
|
|
|
|
|
id: buttonRow
|
2023-02-13 11:20:27 +01:00
|
|
|
width: parent.width
|
2023-02-09 09:17:37 +01:00
|
|
|
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()
|
|
|
|
|
}
|
2022-11-23 11:49:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2021-06-08 20:14:14 +03:00
|
|
|
}
|
|
|
|
|
|
2022-02-03 19:49:27 +02:00
|
|
|
Text {
|
|
|
|
|
text: qsTr("No match found.")
|
|
|
|
|
leftPadding: 10
|
|
|
|
|
color: StudioTheme.Values.themeTextColor
|
2023-02-09 09:17:37 +01:00
|
|
|
font.pixelSize: StudioTheme.Values.baseFont
|
2022-11-23 15:47:34 +02:00
|
|
|
visible: !assetsModel.haveFiles && !root.__searchBoxEmpty
|
2022-02-03 19:49:27 +02:00
|
|
|
}
|
2021-05-04 22:35:50 +03:00
|
|
|
|
2022-02-28 15:24:33 +02:00
|
|
|
Item { // placeholder when the assets library is empty
|
|
|
|
|
width: parent.width
|
2023-02-09 09:17:37 +01:00
|
|
|
height: parent.height - toolbar.height - column.spacing
|
2022-11-23 15:47:34 +02:00
|
|
|
visible: !assetsModel.haveFiles && root.__searchBoxEmpty
|
2022-02-28 15:24:33 +02:00
|
|
|
clip: true
|
|
|
|
|
|
2023-01-10 11:51:20 +02:00
|
|
|
MouseArea { // right clicking the empty area of the view
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
|
|
|
onClicked: {
|
|
|
|
|
contextMenu.openContextMenuForEmpty(assetsModel.rootPath())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 15:29:27 +02:00
|
|
|
DropArea { // handles external drop (goes into default folder based on suffix)
|
|
|
|
|
anchors.fill: parent
|
2022-02-28 15:24:33 +02:00
|
|
|
|
2023-02-17 15:22:55 +02:00
|
|
|
onEntered: (drag) => {
|
2022-03-15 15:29:27 +02:00
|
|
|
root.updateDropExtFiles(drag)
|
|
|
|
|
}
|
2022-02-28 15:24:33 +02:00
|
|
|
|
2023-02-17 15:22:55 +02:00
|
|
|
onDropped: (drag) => {
|
|
|
|
|
drag.accept()
|
2022-11-23 11:49:45 +02:00
|
|
|
rootView.emitExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles)
|
2022-02-28 15:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-15 15:29:27 +02:00
|
|
|
Column {
|
2023-02-09 09:17:37 +01:00
|
|
|
id: noAssetsColumn
|
2022-03-15 15:29:27 +02:00
|
|
|
spacing: 20
|
2023-02-09 09:17:37 +01:00
|
|
|
width: root.width - 40
|
|
|
|
|
anchors.centerIn: parent
|
2022-03-15 15:29:27 +02:00
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: qsTr("Looks like you don't have any assets yet.")
|
|
|
|
|
color: StudioTheme.Values.themeTextColor
|
2023-02-09 09:17:37 +01:00
|
|
|
font.pixelSize: StudioTheme.Values.bigFont
|
|
|
|
|
width: noAssetsColumn.width
|
2022-03-15 15:29:27 +02:00
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
|
wrapMode: Text.WordWrap
|
2022-02-28 15:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-15 15:29:27 +02:00
|
|
|
Image {
|
|
|
|
|
source: "image://qmldesigner_assets/browse"
|
|
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
|
scale: maBrowse.containsMouse ? 1.2 : 1
|
2023-02-09 09:17:37 +01:00
|
|
|
|
2022-03-15 15:29:27 +02:00
|
|
|
Behavior on scale {
|
|
|
|
|
NumberAnimation {
|
|
|
|
|
duration: 300
|
|
|
|
|
easing.type: Easing.OutQuad
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MouseArea {
|
|
|
|
|
id: maBrowse
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
hoverEnabled: true
|
|
|
|
|
onClicked: rootView.handleAddAsset();
|
|
|
|
|
}
|
2022-02-28 15:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-15 15:29:27 +02:00
|
|
|
Text {
|
|
|
|
|
text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.")
|
|
|
|
|
color: StudioTheme.Values.themeTextColor
|
2023-02-09 09:17:37 +01:00
|
|
|
font.pixelSize: StudioTheme.Values.bigFont
|
|
|
|
|
width: noAssetsColumn.width
|
2022-03-15 15:29:27 +02:00
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
|
wrapMode: Text.WordWrap
|
|
|
|
|
}
|
2022-02-28 15:24:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-07 19:49:52 +03:00
|
|
|
AssetsView {
|
2022-02-03 19:49:27 +02:00
|
|
|
id: assetsView
|
2022-11-23 11:49:45 +02:00
|
|
|
assetsRoot: root
|
|
|
|
|
contextMenu: contextMenu
|
2022-02-03 19:49:27 +02:00
|
|
|
width: parent.width
|
2023-02-09 09:17:37 +01:00
|
|
|
height: parent.height - assetsView.y
|
2021-05-04 22:35:50 +03:00
|
|
|
}
|
2023-02-09 09:17:37 +01:00
|
|
|
}
|
2021-05-04 22:35:50 +03:00
|
|
|
}
|