diff options
Diffstat (limited to 'share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml')
-rw-r--r-- | share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml new file mode 100644 index 0000000000..7c017476cd --- /dev/null +++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetDelegate.qml @@ -0,0 +1,327 @@ +// 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 QtQuick.Controls +import StudioTheme as StudioTheme +import AssetsLibraryBackend + +TreeViewDelegate { + id: root + + required property Item assetsView + required property Item assetsRoot + + property var assetsModel: AssetsLibraryBackend.assetsModel + property var rootView: AssetsLibraryBackend.rootView + + property bool hasChildWithDropHover: false + property bool isHighlighted: false + readonly property string suffix: model.fileName.substr(-4) + readonly property bool isFont: root.suffix === ".ttf" || root.suffix === ".otf" + readonly property bool isEffect: root.suffix === ".qep" + property bool currFileSelected: false + property int initialDepth: -1 + property bool __isDirectory: assetsModel.isDirectory(model.filePath) + property int __currentRow: model.index + property string __itemPath: model.filePath + + readonly property int __fileItemHeight: thumbnailImage.height + 2 * StudioTheme.Values.border + readonly property int __dirItemHeight: 21 + + implicitHeight: root.__isDirectory ? root.__dirItemHeight : root.__fileItemHeight + implicitWidth: { + if (root.assetsView.verticalScrollBar.scrollBarVisible) + return root.assetsView.width - root.indentation - root.assetsView.verticalScrollBar.width + else + return root.assetsView.width - root.indentation + } + + leftMargin: root.__isDirectory ? 0 : thumbnailImage.width + + Component.onCompleted: { + // the depth of the root path will become available before we get to the actual + // items we display, so it's safe to set assetsView.rootPathDepth here. All other + // tree items (below the root) will have the indentation (basically, depth) adjusted. + if (model.filePath === assetsModel.rootPath()) { + root.assetsView.rootPathDepth = root.depth + root.assetsView.rootPathRow = root.__currentRow + } else if (model.filePath.includes(assetsModel.rootPath())) { + root.depth -= root.assetsView.rootPathDepth + root.initialDepth = root.depth + } + } + + // workaround for a bug -- might be fixed by https://codereview.qt-project.org/c/qt/qtdeclarative/+/442721 + onYChanged: { + if (root.__currentRow === root.assetsView.firstRow) { + if (root.y > root.assetsView.contentY) { + let item = root.assetsView.itemAtCell(0, root.assetsView.rootPathRow) + if (!item) + root.assetsView.contentY = root.y + } + } + } + + onDepthChanged: { + if (root.depth > root.initialDepth && root.initialDepth >= 0) + root.depth = root.initialDepth + } + + background: Rectangle { + id: bg + + x: root.indentation * root.depth + width: root.implicitWidth - bg.x + + color: { + if (root.__isDirectory && (root.isHighlighted || root.hasChildWithDropHover)) + return StudioTheme.Values.themeInteraction + + if (!root.__isDirectory && root.assetsView.selectedAssets[root.__itemPath]) + return StudioTheme.Values.themeSectionHeadBackground + + if (mouseArea.containsMouse) + return StudioTheme.Values.themeSectionHeadBackground + + return root.__isDirectory + ? StudioTheme.Values.themeSectionHeadBackground + : "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" + } + } + + contentItem: Text { + id: assetLabel + text: assetLabel.__computeText() + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.mediumFont + anchors.verticalCenter: parent.verticalCenter + verticalAlignment: Qt.AlignVCenter + + function __computeText() { + return root.__isDirectory + ? (root.hasChildren + ? model.display.toUpperCase() + : model.display.toUpperCase() + qsTr(" (empty)")) + : model.display + } + } + + MouseArea { + id: mouseArea + + property bool allowTooltip: true + + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onExited: AssetsLibraryBackend.tooltipBackend.hideTooltip() + onEntered: mouseArea.allowTooltip = true + + onCanceled: { + AssetsLibraryBackend.tooltipBackend.hideTooltip() + mouseArea.allowTooltip = true + } + + onPositionChanged: tooltipBackend.reposition() + + onPressed: (mouse) => { + mouseArea.forceActiveFocus() + 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) + } + } + + onReleased: (mouse) => { + mouseArea.allowTooltip = true + + if (root.__isDirectory) + return + + if (mouse.button === Qt.LeftButton) { + if (!(mouse.modifiers & Qt.ControlModifier)) + root.assetsView.selectedAssets = {} + root.assetsView.selectedAssets[root.__itemPath] = root.currFileSelected + root.assetsView.selectedAssetsChanged() + + root.assetsView.currentFilePath = root.__itemPath + } + } + + onDoubleClicked: (mouse) => { + mouseArea.forceActiveFocus() + mouseArea.allowTooltip = false + AssetsLibraryBackend.tooltipBackend.hideTooltip() + if (mouse.button === Qt.LeftButton && root.isEffect) + AssetsLibraryBackend.rootView.openEffectMaker(filePath) + } + + ToolTip { + id: assetTooltip + visible: !root.isFont && mouseArea.containsMouse && !root.assetsView.contextMenu.visible + text: assetTooltip.__computeText() + delay: 1000 + + function __computeText() { + let filePath = model.filePath.replace(assetsModel.contentDirPath(), "") + let fileSize = rootView.assetFileSize(model.filePath) + let fileExtMatches = model.filePath.match(/\.(.*)$/) + let fileExt = fileExtMatches ? "(" + fileExtMatches[1] + ")" : "" + + if (root.__isDirectory) + return filePath + + if (rootView.assetIsImageOrTexture(model.filePath)) { + let size = rootView.imageSize(model.filePath) + + return filePath + "\n" + + size.width + " x " + size.height + + "\n" + fileSize + + " " + fileExt + } else { + return filePath + "\n" + + fileSize + + " " + fileExt + } + } + + function refresh() { + assetTooltip.text = assetTooltip.__computeText() + } + } + + Timer { + interval: 1000 + running: mouseArea.containsMouse && mouseArea.allowTooltip + onTriggered: { + if (root.isFont) { + AssetsLibraryBackend.tooltipBackend.name = model.fileName + AssetsLibraryBackend.tooltipBackend.path = model.filePath + AssetsLibraryBackend.tooltipBackend.showTooltip() + } + } + } + + onClicked: (mouse) => { + if (mouse.button === Qt.LeftButton) + root.__toggleExpandCurrentRow() + else + root.__openContextMenuForCurrentRow() + } + } + + function getDirPath() { + if (root.__isDirectory) + return model.filePath + else + return assetsModel.parentDirPath(model.filePath) + } + + function __openContextMenuForCurrentRow() { + let modelIndex = assetsModel.indexForPath(model.filePath) + + function onFolderCreated(path) { + if (path) + root.assetsView.addCreatedFolder(path) + } + + if (root.__isDirectory) { + var allExpandedState = root.assetsView.computeAllExpandedState() + + root.assetsView.contextMenu.openContextMenuForDir(modelIndex, model.filePath, + model.fileName, allExpandedState, onFolderCreated) + } else { + let parentDirIndex = assetsModel.parentDirIndex(model.filePath) + let selectedPaths = root.assetsView.selectedPathsAsList() + root.assetsView.contextMenu.openContextMenuForFile(modelIndex, parentDirIndex, + selectedPaths, onFolderCreated) + } + } + + function __toggleExpandCurrentRow() { + if (!root.__isDirectory) + return + + let index = root.assetsView.__modelIndex(root.__currentRow) + // if the user manually clicked on a directory, then this is definitely not a + // an automatic request to expand all. + root.assetsView.requestedExpandAll = false + + if (root.assetsView.isExpanded(root.__currentRow)) { + root.assetsView.requestedExpandAll = false + root.assetsView.collapse(root.__currentRow) + } else { + root.assetsView.expand(root.__currentRow) + } + } + + function reloadImage() { + if (root.__isDirectory) + return + + thumbnailImage.source = "" + thumbnailImage.source = thumbnailImage.__computeSource() + } + + Image { + id: thumbnailImage + visible: !root.__isDirectory + y: StudioTheme.Values.border + x: root.depth * root.indentation + StudioTheme.Values.border + width: 48 + height: 48 + cache: false + sourceSize.width: 48 + sourceSize.height: 48 + asynchronous: true + fillMode: Image.PreserveAspectFit + source: thumbnailImage.__computeSource() + + function __computeSource() { + return root.__isDirectory + ? "" + : "image://qmldesigner_assets/" + model.filePath + } + + onStatusChanged: { + if (thumbnailImage.status === Image.Ready) + assetTooltip.refresh() + } + } +} |