QmlDesigner: Use StudioQuickWidget in assets library

The event filter has to be installed on the actual QQuickWidget.
Using registerPropertyMap instead of global context properties.

Task-number: QDS-9124
Change-Id: I9e0e59d4bdf312d98177b8da51761bca8073c9e5
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Thomas Hartmann
2023-03-07 16:51:02 +01:00
parent fb685307f9
commit c3e5f3e83c
12 changed files with 70 additions and 38 deletions

View File

@@ -4,6 +4,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
TreeViewDelegate { TreeViewDelegate {
id: root id: root
@@ -11,6 +12,9 @@ TreeViewDelegate {
required property Item assetsView required property Item assetsView
required property Item assetsRoot required property Item assetsRoot
property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView
property bool hasChildWithDropHover: false property bool hasChildWithDropHover: false
property bool isHighlighted: false property bool isHighlighted: false
readonly property string suffix: model.fileName.substr(-4) readonly property string suffix: model.fileName.substr(-4)
@@ -127,11 +131,11 @@ TreeViewDelegate {
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onExited: tooltipBackend.hideTooltip() onExited: AssetsLibraryBackend.tooltipBackend.hideTooltip()
onEntered: mouseArea.allowTooltip = true onEntered: mouseArea.allowTooltip = true
onCanceled: { onCanceled: {
tooltipBackend.hideTooltip() AssetsLibraryBackend.tooltipBackend.hideTooltip()
mouseArea.allowTooltip = true mouseArea.allowTooltip = true
} }
@@ -140,7 +144,7 @@ TreeViewDelegate {
onPressed: (mouse) => { onPressed: (mouse) => {
mouseArea.forceActiveFocus() mouseArea.forceActiveFocus()
mouseArea.allowTooltip = false mouseArea.allowTooltip = false
tooltipBackend.hideTooltip() AssetsLibraryBackend.tooltipBackend.hideTooltip()
if (root.__isDirectory) if (root.__isDirectory)
return return
@@ -154,7 +158,7 @@ TreeViewDelegate {
if (root.currFileSelected) { if (root.currFileSelected) {
let selectedPaths = root.assetsView.selectedPathsAsList() let selectedPaths = root.assetsView.selectedPathsAsList()
rootView.startDragAsset(selectedPaths, mapToGlobal(mouse.x, mouse.y)) AssetsLibraryBackend.rootView.startDragAsset(selectedPaths, mapToGlobal(mouse.x, mouse.y))
} }
} else { } else {
if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown) if (!root.assetsView.isAssetSelected(root.__itemPath) && !ctrlDown)
@@ -178,9 +182,9 @@ TreeViewDelegate {
onDoubleClicked: (mouse) => { onDoubleClicked: (mouse) => {
mouseArea.forceActiveFocus() mouseArea.forceActiveFocus()
mouseArea.allowTooltip = false mouseArea.allowTooltip = false
tooltipBackend.hideTooltip() AssetsLibraryBackend.tooltipBackend.hideTooltip()
if (mouse.button === Qt.LeftButton && root.isEffect) if (mouse.button === Qt.LeftButton && root.isEffect)
rootView.openEffectMaker(filePath) AssetsLibraryBackend.rootView.openEffectMaker(filePath)
} }
ToolTip { ToolTip {
@@ -222,9 +226,9 @@ TreeViewDelegate {
running: mouseArea.containsMouse && mouseArea.allowTooltip running: mouseArea.containsMouse && mouseArea.allowTooltip
onTriggered: { onTriggered: {
if (root.isFont) { if (root.isFont) {
tooltipBackend.name = model.fileName AssetsLibraryBackend.tooltipBackend.name = model.fileName
tooltipBackend.path = model.filePath AssetsLibraryBackend.tooltipBackend.path = model.filePath
tooltipBackend.showTooltip() AssetsLibraryBackend.tooltipBackend.showTooltip()
} }
} }
} }

View File

@@ -5,10 +5,14 @@ import QtQuick
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
Item { Item {
id: root id: root
property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView
// Array of supported externally dropped files that are imported as-is // Array of supported externally dropped files that are imported as-is
property var dropSimpleExtFiles: [] property var dropSimpleExtFiles: []

View File

@@ -5,12 +5,16 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
StudioControls.Menu { StudioControls.Menu {
id: root id: root
required property Item assetsView required property Item assetsView
property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView
property bool __isDirectory: false property bool __isDirectory: false
property var __fileIndex: null property var __fileIndex: null
property string __dirPath: "" property string __dirPath: ""
@@ -79,7 +83,7 @@ StudioControls.Menu {
root.__selectedAssetPathsList = selectedAssetPathsList root.__selectedAssetPathsList = selectedAssetPathsList
root.__fileIndex = fileIndex root.__fileIndex = fileIndex
root.__dirIndex = dirModelIndex root.__dirIndex = dirModelIndex
root.__dirPath = assetsModel.filePath(dirModelIndex) root.__dirPath = AssetsLibraryBackend.assetsModel.filePath(dirModelIndex)
root.__isDirectory = false root.__isDirectory = false
root.popup() root.popup()
} }
@@ -120,9 +124,9 @@ StudioControls.Menu {
id: addTexturesItem id: addTexturesItem
text: qsTr("Add Texture") text: qsTr("Add Texture")
enabled: rootView.hasMaterialLibrary enabled: rootView.hasMaterialLibrary
visible: root.__fileIndex && assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList) visible: root.__fileIndex && AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0 height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0
onTriggered: rootView.addTextures(root.__selectedAssetPathsList) onTriggered: AssetsLibraryBackend.rootView.addTextures(root.__selectedAssetPathsList)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
@@ -130,7 +134,7 @@ StudioControls.Menu {
text: qsTr("Add Light Probe") text: qsTr("Add Light Probe")
enabled: rootView.hasMaterialLibrary enabled: rootView.hasMaterialLibrary
visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1 visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1
&& assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList) && AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addLightProbes.visible ? addLightProbes.implicitHeight : 0 height: addLightProbes.visible ? addLightProbes.implicitHeight : 0
onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0]) onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0])
} }
@@ -141,7 +145,7 @@ StudioControls.Menu {
visible: root.__fileIndex visible: root.__fileIndex
height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0 height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0
onTriggered: { onTriggered: {
let deleted = assetsModel.requestDeleteFiles(root.__selectedAssetPathsList) let deleted = AssetsLibraryBackend.assetsModel.requestDeleteFiles(root.__selectedAssetPathsList)
if (!deleted) if (!deleted)
confirmDeleteFiles.open() confirmDeleteFiles.open()
} }
@@ -178,7 +182,7 @@ StudioControls.Menu {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("New Folder") text: qsTr("New Folder")
visible: assetsModel.haveFiles visible: AssetsLibraryBackend.assetsModel.haveFiles
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
NewFolderDialog { NewFolderDialog {
@@ -205,11 +209,11 @@ StudioControls.Menu {
} }
onTriggered: { onTriggered: {
if (!assetsModel.hasChildren(root.__dirIndex)) { if (!AssetsLibraryBackend.assetsModel.hasChildren(root.__dirIndex)) {
// NOTE: the folder may still not be empty -- it doesn't have files visible to the // NOTE: the folder may still not be empty -- it doesn't have files visible to the
// user, but that doesn't mean that there are no other files (e.g. files of unknown // user, but that doesn't mean that there are no other files (e.g. files of unknown
// types) on disk in this directory. // types) on disk in this directory.
assetsModel.deleteFolderRecursively(root.__dirIndex) AssetsLibraryBackend.assetsModel.deleteFolderRecursively(root.__dirIndex)
} else { } else {
confirmDeleteFolderDialog.open() confirmDeleteFolderDialog.open()
} }

View File

@@ -5,6 +5,7 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import AssetsLibraryBackend
TreeView { TreeView {
id: root id: root
@@ -14,6 +15,10 @@ TreeView {
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
rowSpacing: 5 rowSpacing: 5
property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView
property var tooltipBackend: AssetsLibraryBackend.tooltipBackend
required property Item assetsRoot required property Item assetsRoot
required property StudioControls.Menu contextMenu required property StudioControls.Menu contextMenu
property alias verticalScrollBar: verticalScrollBar property alias verticalScrollBar: verticalScrollBar

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import StudioControls as StudioControls import StudioControls as StudioControls
import AssetsLibraryBackend
Dialog { Dialog {
id: root id: root
@@ -61,7 +62,7 @@ Dialog {
text: qsTr("Delete") text: qsTr("Delete")
onClicked: { onClicked: {
assetsModel.deleteFiles(root.files, dontAskAgain.checked) AssetsLibraryBackend.assetsModel.deleteFiles(root.files, dontAskAgain.checked)
root.accept() root.accept()
} }
} }
@@ -98,7 +99,7 @@ Dialog {
delegate: Text { delegate: Text {
elide: Text.ElideLeft elide: Text.ElideLeft
text: model.modelData.replace(assetsModel.currentProjectDirPath(), "") text: model.modelData.replace(AssetsLibraryBackend.assetsModel.currentProjectDirPath(), "")
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
width: parent.width - (verticalScrollBar.scrollBarVisible ? verticalScrollBar.width : 0) width: parent.width - (verticalScrollBar.scrollBarVisible ? verticalScrollBar.width : 0)
} }

View File

@@ -5,6 +5,7 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
Dialog { Dialog {
id: root id: root
@@ -53,7 +54,7 @@ Dialog {
text: qsTr("Delete") text: qsTr("Delete")
onClicked: { onClicked: {
assetsModel.deleteFolderRecursively(root.dirIndex) AssetsLibraryBackend.assetsModel.deleteFolderRecursively(root.dirIndex)
root.accept() root.accept()
} }
} }

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
Dialog { Dialog {
id: root id: root
@@ -18,6 +19,8 @@ Dialog {
required property string dirPath required property string dirPath
readonly property int __maxPath: 32 readonly property int __maxPath: 32
property var rootView: AssetsLibraryBackend.rootView
ErrorDialog { ErrorDialog {
id: creationFailedDialog id: creationFailedDialog
title: qsTr("Could not create effect") title: qsTr("Could not create effect")
@@ -93,8 +96,8 @@ Dialog {
&& effectName.length >=3 && effectName.length >=3
&& effectName.text.length <= root.__maxPath && effectName.text.length <= root.__maxPath
onClicked: { onClicked: {
const path = rootView.getUniqueEffectPath(root.dirPath, effectName.text) const path = AssetsLibraryBackend.rootView.getUniqueEffectPath(root.dirPath, effectName.text)
if (rootView.createNewEffect(path)) if (AssetsLibraryBackend.rootView.createNewEffect(path))
root.accept() root.accept()
else else
creationFailedDialog.open() creationFailedDialog.open()
@@ -109,7 +112,7 @@ Dialog {
} }
onOpened: { onOpened: {
const path = rootView.getUniqueEffectPath(root.dirPath, "Effect01") const path = AssetsLibraryBackend.rootView.getUniqueEffectPath(root.dirPath, "Effect01")
effectName.text = path.split('/').pop().replace(".qep", '') effectName.text = path.split('/').pop().replace(".qep", '')
effectName.selectAll() effectName.selectAll()
effectName.forceActiveFocus() effectName.forceActiveFocus()

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
Dialog { Dialog {
id: root id: root
@@ -86,7 +87,7 @@ Dialog {
enabled: folderName.text !== "" && root.createdDirPath.length <= root.__maxPath enabled: folderName.text !== "" && root.createdDirPath.length <= root.__maxPath
onClicked: { onClicked: {
root.createdDirPath = root.dirPath + '/' + folderName.text root.createdDirPath = root.dirPath + '/' + folderName.text
if (assetsModel.addNewFolder(root.createdDirPath)) if (AssetsLibraryBackend.assetsModel.addNewFolder(root.createdDirPath))
root.accept() root.accept()
else else
creationFailedDialog.open() creationFailedDialog.open()

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import AssetsLibraryBackend
Dialog { Dialog {
id: root id: root
@@ -84,7 +85,7 @@ Dialog {
text: qsTr("Rename") text: qsTr("Rename")
enabled: folderRename.text !== "" enabled: folderRename.text !== ""
onClicked: { onClicked: {
var success = assetsModel.renameFolder(root.dirPath, folderRename.text) var success = AssetsLibraryBackend.assetsModel.renameFolder(root.dirPath, folderRename.text)
if (success) { if (success) {
root.renamedDirPath = root.dirPath.replace(/(.*\/)[^/]+$/, "$1" + folderRename.text) root.renamedDirPath = root.dirPath.replace(/(.*\/)[^/]+$/, "$1" + folderRename.text)
root.accept() root.accept()

View File

@@ -13,6 +13,8 @@
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "theme.h" #include "theme.h"
#include <studioquickwidget.h>
#include <coreplugin/fileutils.h> #include <coreplugin/fileutils.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
@@ -87,12 +89,12 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
, m_fontImageCache{synchronousFontImageCache} , m_fontImageCache{synchronousFontImageCache}
, m_assetsIconProvider{new AssetsLibraryIconProvider(synchronousFontImageCache)} , m_assetsIconProvider{new AssetsLibraryIconProvider(synchronousFontImageCache)}
, m_assetsModel{new AssetsLibraryModel(this)} , m_assetsModel{new AssetsLibraryModel(this)}
, m_assetsWidget{new QQuickWidget(this)} , m_assetsWidget{new StudioQuickWidget(this)}
{ {
setWindowTitle(tr("Assets Library", "Title of assets library widget")); setWindowTitle(tr("Assets Library", "Title of assets library widget"));
setMinimumWidth(250); setMinimumWidth(250);
m_assetsWidget->installEventFilter(this); m_assetsWidget->quickWidget()->installEventFilter(this);
m_fontPreviewTooltipBackend = std::make_unique<PreviewTooltipBackend>(asynchronousFontImageCache); m_fontPreviewTooltipBackend = std::make_unique<PreviewTooltipBackend>(asynchronousFontImageCache);
// We want font images to have custom size, so don't scale them in the tooltip // We want font images to have custom size, so don't scale them in the tooltip
@@ -113,11 +115,6 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
m_assetsWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_assetsWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_assetsWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate)); m_assetsWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
m_assetsWidget->engine()->addImageProvider("qmldesigner_assets", m_assetsIconProvider); m_assetsWidget->engine()->addImageProvider("qmldesigner_assets", m_assetsIconProvider);
m_assetsWidget->rootContext()->setContextProperties(QVector<QQmlContext::PropertyPair>{
{{"assetsModel"}, QVariant::fromValue(m_assetsModel)},
{{"rootView"}, QVariant::fromValue(this)},
{{"tooltipBackend"}, QVariant::fromValue(m_fontPreviewTooltipBackend.get())}
});
connect(m_assetsModel, &AssetsLibraryModel::fileChanged, [](const QString &changeFilePath) { connect(m_assetsModel, &AssetsLibraryModel::fileChanged, [](const QString &changeFilePath) {
QmlDesignerPlugin::instance()->emitAssetChanged(changeFilePath); QmlDesignerPlugin::instance()->emitAssetChanged(changeFilePath);
@@ -135,9 +132,19 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6), this); m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6), this);
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &AssetsLibraryWidget::reloadQmlSource); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &AssetsLibraryWidget::reloadQmlSource);
connect(this, &AssetsLibraryWidget::extFilesDrop, this, &AssetsLibraryWidget::handleExtFilesDrop, Qt::QueuedConnection); connect(this,
&AssetsLibraryWidget::extFilesDrop,
this,
&AssetsLibraryWidget::handleExtFilesDrop,
Qt::QueuedConnection);
QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_ASSETSLIBRARY_TIME); QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_ASSETSLIBRARY_TIME);
auto map = m_assetsWidget->registerPropertyMap("AssetsLibraryBackend");
map->setProperties({{"assetsModel", QVariant::fromValue(m_assetsModel)},
{"rootView", QVariant::fromValue(this)},
{"tooltipBackend", QVariant::fromValue(m_fontPreviewTooltipBackend.get())}});
// init the first load of the QML UI elements // init the first load of the QML UI elements
reloadQmlSource(); reloadQmlSource();
@@ -339,9 +346,9 @@ QString AssetsLibraryWidget::qmlSourcesPath()
{ {
#ifdef SHARE_QML_PATH #ifdef SHARE_QML_PATH
if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/itemLibraryQmlSources"; return QLatin1String(SHARE_QML_PATH) + "/assetsLibraryQmlSources";
#endif #endif
return Core::ICore::resourcePath("qmldesigner/itemLibraryQmlSources").toString(); return Core::ICore::resourcePath("qmldesigner/assetsLibraryQmlSources").toString();
} }
void AssetsLibraryWidget::clearSearchFilter() void AssetsLibraryWidget::clearSearchFilter()
@@ -353,7 +360,6 @@ void AssetsLibraryWidget::reloadQmlSource()
{ {
const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml"; const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml";
QTC_ASSERT(QFileInfo::exists(assetsQmlPath), return); QTC_ASSERT(QFileInfo::exists(assetsQmlPath), return);
m_assetsWidget->engine()->clearComponentCache();
m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath)); m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath));
} }

View File

@@ -18,6 +18,8 @@ class QShortcut;
class QToolButton; class QToolButton;
QT_END_NAMESPACE QT_END_NAMESPACE
class StudioQuickWidget;
namespace Utils { namespace Utils {
class QtcProcess; class QtcProcess;
} }
@@ -123,7 +125,7 @@ private:
AssetsLibraryIconProvider *m_assetsIconProvider = nullptr; AssetsLibraryIconProvider *m_assetsIconProvider = nullptr;
AssetsLibraryModel *m_assetsModel = nullptr; AssetsLibraryModel *m_assetsModel = nullptr;
QScopedPointer<QQuickWidget> m_assetsWidget; QScopedPointer<StudioQuickWidget> m_assetsWidget;
std::unique_ptr<PreviewTooltipBackend> m_fontPreviewTooltipBackend; std::unique_ptr<PreviewTooltipBackend> m_fontPreviewTooltipBackend;
QShortcut *m_qmlSourceUpdateShortcut = nullptr; QShortcut *m_qmlSourceUpdateShortcut = nullptr;