forked from qt-creator/qt-creator
Refactor Assets Library
Extracted the dialogs, the context menu, and the assets view into separate qml files. Also, reordered some functions in the assets library model Task-number: QDS-7344 Change-Id: Ida21b60d30f34723c07b2659a138e14b95598421 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -46,6 +46,10 @@ Item {
|
||||
// Array of supported externally dropped files that trigger custom import process
|
||||
property var dropComplexExtFiles: []
|
||||
|
||||
AssetsContextMenu {
|
||||
id: contextMenu
|
||||
}
|
||||
|
||||
function clearSearchFilter()
|
||||
{
|
||||
searchBox.clear();
|
||||
@@ -125,307 +129,11 @@ Item {
|
||||
root.selectedAssetsChanged()
|
||||
}
|
||||
|
||||
StudioControls.Menu {
|
||||
id: contextMenu
|
||||
|
||||
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
|
||||
|
||||
onOpened: {
|
||||
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: root.allExpandedState !== 1
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: assetsModel.toggleExpandAll(true)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Collapse All")
|
||||
enabled: root.allExpandedState !== 2
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: assetsModel.toggleExpandAll(false)
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? StudioTheme.Values.border : 0
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
id: deleteFileItem
|
||||
text: qsTr("Delete File")
|
||||
visible: root.contextFilePath
|
||||
height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0
|
||||
onTriggered: {
|
||||
assetsModel.deleteFiles(Object.keys(root.selectedAssets).filter(p => root.selectedAssets[p]))
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {
|
||||
visible: root.contextFilePath
|
||||
height: visible ? StudioTheme.Values.border : 0
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Rename Folder")
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: renameFolderDialog.open()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("New Folder")
|
||||
onTriggered: newFolderDialog.open()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Delete Folder")
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: {
|
||||
var dirEmpty = !(root.contextDir.dirsModel && root.contextDir.dirsModel.rowCount() > 0)
|
||||
&& !(root.contextDir.filesModel && root.contextDir.filesModel.rowCount() > 0);
|
||||
|
||||
if (dirEmpty)
|
||||
assetsModel.deleteFolder(root.contextDir.dirPath)
|
||||
else
|
||||
confirmDeleteFolderDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegExpValidator {
|
||||
id: folderNameValidator
|
||||
regExp: /^(\w[^*/><?\\|:]*)$/
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: renameFolderDialog
|
||||
|
||||
title: qsTr("Rename Folder")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
implicitWidth: 280
|
||||
modal: true
|
||||
|
||||
property bool renameError: false
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 2
|
||||
|
||||
StudioControls.TextField {
|
||||
id: folderRename
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
width: renameFolderDialog.width - 12
|
||||
validator: folderNameValidator
|
||||
|
||||
onEditChanged: renameFolderDialog.renameError = false
|
||||
Keys.onEnterPressed: btnRename.onClicked()
|
||||
Keys.onReturnPressed: btnRename.onClicked()
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Folder name cannot be empty.")
|
||||
color: "#ff0000"
|
||||
visible: folderRename.text === "" && !renameFolderDialog.renameError
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Could not rename folder. Make sure no folder with the same name exists.")
|
||||
wrapMode: Text.WordWrap
|
||||
width: renameFolderDialog.width - 12
|
||||
color: "#ff0000"
|
||||
visible: renameFolderDialog.renameError
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 10
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("If the folder has assets in use, renaming it might cause the project to not work correctly.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: renameFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 20
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
|
||||
Button {
|
||||
id: btnRename
|
||||
|
||||
text: qsTr("Rename")
|
||||
enabled: folderRename.text !== ""
|
||||
onClicked: {
|
||||
var success = assetsModel.renameFolder(root.contextDir.dirPath, folderRename.text)
|
||||
if (success)
|
||||
renameFolderDialog.accept()
|
||||
|
||||
renameFolderDialog.renameError = !success
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: renameFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
folderRename.text = root.contextDir.dirName
|
||||
folderRename.selectAll()
|
||||
folderRename.forceActiveFocus()
|
||||
renameFolderDialog.renameError = false
|
||||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: newFolderDialog
|
||||
|
||||
title: qsTr("Create New Folder")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
modal: true
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 2
|
||||
|
||||
Row {
|
||||
Text {
|
||||
text: qsTr("Folder name: ")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
StudioControls.TextField {
|
||||
id: folderName
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
validator: folderNameValidator
|
||||
|
||||
Keys.onEnterPressed: btnCreate.onClicked()
|
||||
Keys.onReturnPressed: btnCreate.onClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Folder name cannot be empty.")
|
||||
color: "#ff0000"
|
||||
anchors.right: parent.right
|
||||
visible: folderName.text === ""
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 20
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
|
||||
Button {
|
||||
id: btnCreate
|
||||
|
||||
text: qsTr("Create")
|
||||
enabled: folderName.text !== ""
|
||||
onClicked: {
|
||||
assetsModel.addNewFolder(root.contextDir.dirPath + '/' + folderName.text)
|
||||
newFolderDialog.accept()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: newFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
folderName.text = "New folder"
|
||||
folderName.selectAll()
|
||||
folderName.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: confirmDeleteFolderDialog
|
||||
|
||||
title: qsTr("Folder Not Empty")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
implicitWidth: 300
|
||||
modal: true
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 20
|
||||
width: parent.width
|
||||
|
||||
Text {
|
||||
id: folderNotEmpty
|
||||
|
||||
text: qsTr("Folder \"%1\" is not empty. Delete it anyway?")
|
||||
.arg(root.contextDir ? root.contextDir.dirName : "")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: confirmDeleteFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
|
||||
Keys.onEnterPressed: btnDelete.onClicked()
|
||||
Keys.onReturnPressed: btnDelete.onClicked()
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("If the folder has assets in use, deleting it might cause the project to not work correctly.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: confirmDeleteFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
Button {
|
||||
id: btnDelete
|
||||
|
||||
text: qsTr("Delete")
|
||||
|
||||
onClicked: {
|
||||
assetsModel.deleteFolder(root.contextDir.dirPath)
|
||||
confirmDeleteFolderDialog.accept()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: confirmDeleteFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: folderNotEmpty.forceActiveFocus()
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 5
|
||||
@@ -529,220 +237,10 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
AssetsView {
|
||||
id: assetsView
|
||||
width: parent.width
|
||||
height: parent.height - y
|
||||
clip: true
|
||||
interactive: assetsView.verticalScrollBarVisible && !contextMenu.opened
|
||||
|
||||
Column {
|
||||
Repeater {
|
||||
model: assetsModel // context property
|
||||
delegate: dirSection
|
||||
}
|
||||
|
||||
Component {
|
||||
id: dirSection
|
||||
|
||||
Section {
|
||||
id: section
|
||||
|
||||
width: assetsView.width -
|
||||
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) - 5
|
||||
caption: dirName
|
||||
sectionHeight: 30
|
||||
sectionFontSize: 15
|
||||
leftPadding: 0
|
||||
topPadding: dirDepth > 0 ? 5 : 0
|
||||
bottomPadding: 0
|
||||
hideHeader: dirDepth === 0
|
||||
showLeftBorder: dirDepth > 0
|
||||
expanded: dirExpanded
|
||||
visible: dirVisible
|
||||
expandOnClick: false
|
||||
useDefaulContextMenu: false
|
||||
dropEnabled: true
|
||||
|
||||
onToggleExpand: {
|
||||
dirExpanded = !dirExpanded
|
||||
}
|
||||
|
||||
onDropEnter: (drag)=> {
|
||||
root.updateDropExtFiles(drag)
|
||||
section.highlight = drag.accepted && root.dropSimpleExtFiles.length > 0
|
||||
}
|
||||
|
||||
onDropExit: {
|
||||
section.highlight = false
|
||||
}
|
||||
|
||||
onDrop: {
|
||||
section.highlight = false
|
||||
rootView.handleExtFilesDrop(root.dropSimpleExtFiles,
|
||||
root.dropComplexExtFiles,
|
||||
dirPath)
|
||||
}
|
||||
|
||||
onShowContextMenu: {
|
||||
root.contextFilePath = ""
|
||||
root.contextDir = model
|
||||
root.isDirContextMenu = true
|
||||
root.allExpandedState = assetsModel.getAllExpandedState()
|
||||
contextMenu.popup()
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 5
|
||||
leftPadding: 5
|
||||
|
||||
Repeater {
|
||||
model: dirsModel
|
||||
delegate: dirSection
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: filesModel
|
||||
delegate: fileSection
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Empty folder")
|
||||
color: StudioTheme.Values.themeTextColorDisabled
|
||||
font.pixelSize: 12
|
||||
visible: !(dirsModel && dirsModel.rowCount() > 0)
|
||||
&& !(filesModel && filesModel.rowCount() > 0)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
root.contextFilePath = ""
|
||||
root.contextDir = model
|
||||
root.isDirContextMenu = true
|
||||
contextMenu.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileSection
|
||||
|
||||
Rectangle {
|
||||
width: assetsView.width -
|
||||
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0)
|
||||
height: img.height
|
||||
color: root.selectedAssets[filePath]
|
||||
? StudioTheme.Values.themeInteraction
|
||||
: (mouseArea.containsMouse ? StudioTheme.Values.themeSectionHeadBackground
|
||||
: "transparent")
|
||||
|
||||
Row {
|
||||
spacing: 5
|
||||
|
||||
Image {
|
||||
id: img
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
width: 48
|
||||
height: 48
|
||||
source: "image://qmldesigner_assets/" + filePath
|
||||
}
|
||||
|
||||
Text {
|
||||
text: fileName
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string suffix: fileName.substr(-4)
|
||||
readonly property bool isFont: suffix === ".ttf" || suffix === ".otf"
|
||||
property bool currFileSelected: false
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
property bool allowTooltip: true
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onExited: tooltipBackend.hideTooltip()
|
||||
onEntered: allowTooltip = true
|
||||
onCanceled: {
|
||||
tooltipBackend.hideTooltip()
|
||||
allowTooltip = true
|
||||
}
|
||||
onPositionChanged: tooltipBackend.reposition()
|
||||
onPressed: (mouse)=> {
|
||||
forceActiveFocus()
|
||||
allowTooltip = false
|
||||
tooltipBackend.hideTooltip()
|
||||
var ctrlDown = mouse.modifiers & Qt.ControlModifier
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
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(root.selectedAssets).filter(p => root.selectedAssets[p]),
|
||||
mapToGlobal(mouse.x, mouse.y))
|
||||
}
|
||||
} else {
|
||||
if (!root.selectedAssets[filePath] && !ctrlDown)
|
||||
root.selectedAssets = {}
|
||||
currFileSelected = root.selectedAssets[filePath] || !ctrlDown
|
||||
root.selectedAssets[filePath] = currFileSelected
|
||||
root.selectedAssetsChanged()
|
||||
|
||||
root.contextFilePath = filePath
|
||||
root.contextDir = model.fileDir
|
||||
root.isDirContextMenu = false
|
||||
|
||||
contextMenu.popup()
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: (mouse)=> {
|
||||
allowTooltip = true
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (!(mouse.modifiers & Qt.ControlModifier))
|
||||
root.selectedAssets = {}
|
||||
root.selectedAssets[filePath] = currFileSelected
|
||||
root.selectedAssetsChanged()
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
visible: !isFont && mouseArea.containsMouse && !contextMenu.visible
|
||||
text: filePath
|
||||
delay: 1000
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: mouseArea.containsMouse && mouseArea.allowTooltip
|
||||
onTriggered: {
|
||||
if (suffix === ".ttf" || suffix === ".otf") {
|
||||
tooltipBackend.name = fileName
|
||||
tooltipBackend.path = filePath
|
||||
tooltipBackend.showTooltip()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,120 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuickDesignerTheme
|
||||
import HelperWidgets as HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
StudioControls.Menu {
|
||||
id: contextMenu
|
||||
|
||||
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
|
||||
|
||||
onOpened: {
|
||||
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: root.allExpandedState !== 1
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: assetsModel.toggleExpandAll(true)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Collapse All")
|
||||
enabled: root.allExpandedState !== 2
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: assetsModel.toggleExpandAll(false)
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? StudioTheme.Values.border : 0
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
id: deleteFileItem
|
||||
text: qsTr("Delete File")
|
||||
visible: root.contextFilePath
|
||||
height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0
|
||||
onTriggered: {
|
||||
assetsModel.deleteFiles(Object.keys(root.selectedAssets).filter(p => root.selectedAssets[p]))
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {
|
||||
visible: root.contextFilePath
|
||||
height: visible ? StudioTheme.Values.border : 0
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Rename Folder")
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: renameFolderDialog.open()
|
||||
|
||||
RenameFolderDialog {
|
||||
id: renameFolderDialog
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("New Folder")
|
||||
|
||||
NewFolderDialog {
|
||||
id: newFolderDialog
|
||||
}
|
||||
|
||||
onTriggered: newFolderDialog.open()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Delete Folder")
|
||||
visible: root.isDirContextMenu
|
||||
height: visible ? implicitHeight : 0
|
||||
|
||||
ConfirmDeleteFolderDialog {
|
||||
id: confirmDeleteFolderDialog
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
var dirEmpty = !(root.contextDir.dirsModel && root.contextDir.dirsModel.rowCount() > 0)
|
||||
&& !(root.contextDir.filesModel && root.contextDir.filesModel.rowCount() > 0);
|
||||
|
||||
if (dirEmpty)
|
||||
assetsModel.deleteFolder(root.contextDir.dirPath)
|
||||
else
|
||||
confirmDeleteFolderDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
246
share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml
Normal file
246
share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml
Normal file
@@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuickDesignerTheme
|
||||
import HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
id: assetsView
|
||||
clip: true
|
||||
interactive: assetsView.verticalScrollBarVisible && !contextMenu.opened
|
||||
|
||||
Column {
|
||||
Repeater {
|
||||
model: assetsModel // context property
|
||||
delegate: dirSection
|
||||
}
|
||||
|
||||
Component {
|
||||
id: dirSection
|
||||
|
||||
Section {
|
||||
id: section
|
||||
|
||||
width: assetsView.width -
|
||||
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) - 5
|
||||
caption: dirName
|
||||
sectionHeight: 30
|
||||
sectionFontSize: 15
|
||||
leftPadding: 0
|
||||
topPadding: dirDepth > 0 ? 5 : 0
|
||||
bottomPadding: 0
|
||||
hideHeader: dirDepth === 0
|
||||
showLeftBorder: dirDepth > 0
|
||||
expanded: dirExpanded
|
||||
visible: dirVisible
|
||||
expandOnClick: false
|
||||
useDefaulContextMenu: false
|
||||
dropEnabled: true
|
||||
|
||||
onToggleExpand: {
|
||||
dirExpanded = !dirExpanded
|
||||
}
|
||||
|
||||
onDropEnter: (drag)=> {
|
||||
root.updateDropExtFiles(drag)
|
||||
section.highlight = drag.accepted && root.dropSimpleExtFiles.length > 0
|
||||
}
|
||||
|
||||
onDropExit: {
|
||||
section.highlight = false
|
||||
}
|
||||
|
||||
onDrop: {
|
||||
section.highlight = false
|
||||
rootView.handleExtFilesDrop(root.dropSimpleExtFiles,
|
||||
root.dropComplexExtFiles,
|
||||
dirPath)
|
||||
}
|
||||
|
||||
onShowContextMenu: {
|
||||
root.contextFilePath = ""
|
||||
root.contextDir = model
|
||||
root.isDirContextMenu = true
|
||||
root.allExpandedState = assetsModel.getAllExpandedState()
|
||||
contextMenu.popup()
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 5
|
||||
leftPadding: 5
|
||||
|
||||
Repeater {
|
||||
model: dirsModel
|
||||
delegate: dirSection
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: filesModel
|
||||
delegate: fileSection
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Empty folder")
|
||||
color: StudioTheme.Values.themeTextColorDisabled
|
||||
font.pixelSize: 12
|
||||
visible: !(dirsModel && dirsModel.rowCount() > 0)
|
||||
&& !(filesModel && filesModel.rowCount() > 0)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
root.contextFilePath = ""
|
||||
root.contextDir = model
|
||||
root.isDirContextMenu = true
|
||||
contextMenu.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileSection
|
||||
|
||||
Rectangle {
|
||||
width: assetsView.width -
|
||||
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0)
|
||||
height: img.height
|
||||
color: root.selectedAssets[filePath]
|
||||
? StudioTheme.Values.themeInteraction
|
||||
: (mouseArea.containsMouse ? StudioTheme.Values.themeSectionHeadBackground
|
||||
: "transparent")
|
||||
|
||||
Row {
|
||||
spacing: 5
|
||||
|
||||
Image {
|
||||
id: img
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
width: 48
|
||||
height: 48
|
||||
source: "image://qmldesigner_assets/" + filePath
|
||||
}
|
||||
|
||||
Text {
|
||||
text: fileName
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string suffix: fileName.substr(-4)
|
||||
readonly property bool isFont: suffix === ".ttf" || suffix === ".otf"
|
||||
property bool currFileSelected: false
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
property bool allowTooltip: true
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onExited: tooltipBackend.hideTooltip()
|
||||
onEntered: allowTooltip = true
|
||||
onCanceled: {
|
||||
tooltipBackend.hideTooltip()
|
||||
allowTooltip = true
|
||||
}
|
||||
onPositionChanged: tooltipBackend.reposition()
|
||||
onPressed: (mouse)=> {
|
||||
forceActiveFocus()
|
||||
allowTooltip = false
|
||||
tooltipBackend.hideTooltip()
|
||||
var ctrlDown = mouse.modifiers & Qt.ControlModifier
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
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(root.selectedAssets).filter(p => root.selectedAssets[p]),
|
||||
mapToGlobal(mouse.x, mouse.y))
|
||||
}
|
||||
} else {
|
||||
if (!root.selectedAssets[filePath] && !ctrlDown)
|
||||
root.selectedAssets = {}
|
||||
currFileSelected = root.selectedAssets[filePath] || !ctrlDown
|
||||
root.selectedAssets[filePath] = currFileSelected
|
||||
root.selectedAssetsChanged()
|
||||
|
||||
root.contextFilePath = filePath
|
||||
root.contextDir = model.fileDir
|
||||
root.isDirContextMenu = false
|
||||
|
||||
contextMenu.popup()
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: (mouse)=> {
|
||||
allowTooltip = true
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (!(mouse.modifiers & Qt.ControlModifier))
|
||||
root.selectedAssets = {}
|
||||
root.selectedAssets[filePath] = currFileSelected
|
||||
root.selectedAssetsChanged()
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
visible: !isFont && mouseArea.containsMouse && !contextMenu.visible
|
||||
text: filePath
|
||||
delay: 1000
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: mouseArea.containsMouse && mouseArea.allowTooltip
|
||||
onTriggered: {
|
||||
if (suffix === ".ttf" || suffix === ".otf") {
|
||||
tooltipBackend.name = fileName
|
||||
tooltipBackend.path = filePath
|
||||
tooltipBackend.showTooltip()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuickDesignerTheme
|
||||
import HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
Dialog {
|
||||
id: confirmDeleteFolderDialog
|
||||
|
||||
title: qsTr("Folder Not Empty")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
implicitWidth: 300
|
||||
modal: true
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 20
|
||||
width: parent.width
|
||||
|
||||
Text {
|
||||
id: folderNotEmpty
|
||||
|
||||
text: qsTr("Folder \"%1\" is not empty. Delete it anyway?")
|
||||
.arg(root.contextDir ? root.contextDir.dirName : "")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: confirmDeleteFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
|
||||
Keys.onEnterPressed: btnDelete.onClicked()
|
||||
Keys.onReturnPressed: btnDelete.onClicked()
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("If the folder has assets in use, deleting it might cause the project to not work correctly.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: confirmDeleteFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
Button {
|
||||
id: btnDelete
|
||||
|
||||
text: qsTr("Delete")
|
||||
|
||||
onClicked: {
|
||||
assetsModel.deleteFolder(root.contextDir.dirPath)
|
||||
confirmDeleteFolderDialog.accept()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: confirmDeleteFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: folderNotEmpty.forceActiveFocus()
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuickDesignerTheme
|
||||
import HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
Dialog {
|
||||
id: newFolderDialog
|
||||
|
||||
title: qsTr("Create New Folder")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
modal: true
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 2
|
||||
|
||||
Row {
|
||||
Text {
|
||||
text: qsTr("Folder name: ")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
StudioControls.TextField {
|
||||
id: folderName
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
validator: folderNameValidator
|
||||
|
||||
Keys.onEnterPressed: btnCreate.onClicked()
|
||||
Keys.onReturnPressed: btnCreate.onClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Folder name cannot be empty.")
|
||||
color: "#ff0000"
|
||||
anchors.right: parent.right
|
||||
visible: folderName.text === ""
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 20
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
|
||||
Button {
|
||||
id: btnCreate
|
||||
|
||||
text: qsTr("Create")
|
||||
enabled: folderName.text !== ""
|
||||
onClicked: {
|
||||
assetsModel.addNewFolder(root.contextDir.dirPath + '/' + folderName.text)
|
||||
newFolderDialog.accept()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: newFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
folderName.text = qsTr("New folder")
|
||||
folderName.selectAll()
|
||||
folderName.forceActiveFocus()
|
||||
}
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuickDesignerTheme
|
||||
import HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
Dialog {
|
||||
id: renameFolderDialog
|
||||
|
||||
title: qsTr("Rename Folder")
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
implicitWidth: 280
|
||||
modal: true
|
||||
|
||||
property bool renameError: false
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 2
|
||||
|
||||
StudioControls.TextField {
|
||||
id: folderRename
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
width: renameFolderDialog.width - 12
|
||||
validator: folderNameValidator
|
||||
|
||||
onEditChanged: renameFolderDialog.renameError = false
|
||||
Keys.onEnterPressed: btnRename.onClicked()
|
||||
Keys.onReturnPressed: btnRename.onClicked()
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Folder name cannot be empty.")
|
||||
color: "#ff0000"
|
||||
visible: folderRename.text === "" && !renameFolderDialog.renameError
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Could not rename folder. Make sure no folder with the same name exists.")
|
||||
wrapMode: Text.WordWrap
|
||||
width: renameFolderDialog.width - 12
|
||||
color: "#ff0000"
|
||||
visible: renameFolderDialog.renameError
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 10
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("If the folder has assets in use, renaming it might cause the project to not work correctly.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
width: renameFolderDialog.width
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
width: 1
|
||||
height: 20
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
|
||||
Button {
|
||||
id: btnRename
|
||||
|
||||
text: qsTr("Rename")
|
||||
enabled: folderRename.text !== ""
|
||||
onClicked: {
|
||||
var success = assetsModel.renameFolder(root.contextDir.dirPath, folderRename.text)
|
||||
if (success)
|
||||
renameFolderDialog.accept()
|
||||
|
||||
renameFolderDialog.renameError = !success
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: renameFolderDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
folderRename.text = root.contextDir.dirName
|
||||
folderRename.selectAll()
|
||||
folderRename.forceActiveFocus()
|
||||
renameFolderDialog.renameError = false
|
||||
}
|
||||
}
|
@@ -57,6 +57,25 @@ static Q_LOGGING_CATEGORY(assetsLibraryBenchmark, "qtc.assetsLibrary.setRoot", Q
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
AssetsLibraryModel::AssetsLibraryModel(Utils::FileSystemWatcher *fileSystemWatcher, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_fileSystemWatcher(fileSystemWatcher)
|
||||
{
|
||||
// add role names
|
||||
int role = 0;
|
||||
const QMetaObject meta = AssetsLibraryDir::staticMetaObject;
|
||||
for (int i = meta.propertyOffset(); i < meta.propertyCount(); ++i)
|
||||
m_roleNames.insert(role++, meta.property(i).name());
|
||||
}
|
||||
|
||||
void AssetsLibraryModel::setSearchText(const QString &searchText)
|
||||
{
|
||||
if (m_searchText != searchText) {
|
||||
m_searchText = searchText;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsLibraryModel::saveExpandedState(bool expanded, const QString &assetPath)
|
||||
{
|
||||
m_expandedStateHash.insert(assetPath, expanded);
|
||||
@@ -208,66 +227,18 @@ QObject *AssetsLibraryModel::rootDir() const
|
||||
return m_assetsDir;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedImageSuffixes()
|
||||
bool AssetsLibraryModel::isEmpty() const
|
||||
{
|
||||
static QStringList retList;
|
||||
if (retList.isEmpty()) {
|
||||
const QList<QByteArray> suffixes = QImageReader::supportedImageFormats();
|
||||
for (const QByteArray &suffix : suffixes)
|
||||
retList.append("*." + QString::fromUtf8(suffix));
|
||||
return m_isEmpty;
|
||||
};
|
||||
|
||||
void AssetsLibraryModel::setIsEmpty(bool empty)
|
||||
{
|
||||
if (m_isEmpty != empty) {
|
||||
m_isEmpty = empty;
|
||||
emit isEmptyChanged();
|
||||
}
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedFragmentShaderSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.frag", "*.glsl", "*.glslf", "*.fsh"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedShaderSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.frag", "*.vert",
|
||||
"*.glsl", "*.glslv", "*.glslf",
|
||||
"*.vsh", "*.fsh"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedFontSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.ttf", "*.otf"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedAudioSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.wav", "*.mp3"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedVideoSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.mp4"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedTexture3DSuffixes()
|
||||
{
|
||||
// These are file types only supported by 3D textures
|
||||
static QStringList retList {"*.hdr", "*.ktx"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
AssetsLibraryModel::AssetsLibraryModel(Utils::FileSystemWatcher *fileSystemWatcher, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_fileSystemWatcher(fileSystemWatcher)
|
||||
{
|
||||
// add role names
|
||||
int role = 0;
|
||||
const QMetaObject meta = AssetsLibraryDir::staticMetaObject;
|
||||
for (int i = meta.propertyOffset(); i < meta.propertyCount(); ++i)
|
||||
m_roleNames.insert(role++, meta.property(i).name());
|
||||
}
|
||||
};
|
||||
|
||||
QVariant AssetsLibraryModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
@@ -377,12 +348,54 @@ void AssetsLibraryModel::setRootPath(const QString &path)
|
||||
qCInfo(assetsLibraryBenchmark) << "model reset:" << time.elapsed();
|
||||
}
|
||||
|
||||
void AssetsLibraryModel::setSearchText(const QString &searchText)
|
||||
const QStringList &AssetsLibraryModel::supportedImageSuffixes()
|
||||
{
|
||||
if (m_searchText != searchText) {
|
||||
m_searchText = searchText;
|
||||
refresh();
|
||||
static QStringList retList;
|
||||
if (retList.isEmpty()) {
|
||||
const QList<QByteArray> suffixes = QImageReader::supportedImageFormats();
|
||||
for (const QByteArray &suffix : suffixes)
|
||||
retList.append("*." + QString::fromUtf8(suffix));
|
||||
}
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedFragmentShaderSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.frag", "*.glsl", "*.glslf", "*.fsh"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedShaderSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.frag", "*.vert",
|
||||
"*.glsl", "*.glslv", "*.glslf",
|
||||
"*.vsh", "*.fsh"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedFontSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.ttf", "*.otf"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedAudioSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.wav", "*.mp3"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedVideoSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.mp4"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedTexture3DSuffixes()
|
||||
{
|
||||
// These are file types only supported by 3D textures
|
||||
static QStringList retList {"*.hdr", "*.ktx"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QSet<QString> &AssetsLibraryModel::supportedSuffixes()
|
||||
@@ -403,19 +416,6 @@ const QSet<QString> &AssetsLibraryModel::supportedSuffixes()
|
||||
return allSuffixes;
|
||||
}
|
||||
|
||||
bool AssetsLibraryModel::isEmpty() const
|
||||
{
|
||||
return m_isEmpty;
|
||||
};
|
||||
|
||||
void AssetsLibraryModel::setIsEmpty(bool empty)
|
||||
{
|
||||
if (m_isEmpty != empty) {
|
||||
m_isEmpty = empty;
|
||||
emit isEmptyChanged();
|
||||
}
|
||||
};
|
||||
|
||||
const QSet<QString> &AssetsLibraryModel::previewableSuffixes() const
|
||||
{
|
||||
static QSet<QString> previewableSuffixes;
|
||||
|
Reference in New Issue
Block a user