QmlDesigner: Use StudioQuickWidget in item 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: I03c71dce228a7b8713bd1a5085541ed06c7ee0bd
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Thomas Hartmann
2023-03-02 13:10:47 +01:00
parent c78c4817cd
commit 91e7efa5e0
5 changed files with 60 additions and 52 deletions

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import ItemLibraryBackend
Column { Column {
id: root id: root
@@ -43,7 +44,7 @@ Column {
spacing: 2 spacing: 2
Repeater { Repeater {
model: addModuleModel model: ItemLibraryBackend.addModuleModel
delegate: Rectangle { delegate: Rectangle {
id: itemBackground id: itemBackground
@@ -67,7 +68,7 @@ Column {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: rootView.handleAddImport(index) onClicked: ItemLibraryBackend.rootView.handleAddImport(index)
enabled: !isSeparator enabled: !isSeparator
} }

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls 2.15
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 import HelperWidgets 2.0
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import ItemLibraryBackend
Item { Item {
id: delegateRoot id: delegateRoot
@@ -34,8 +35,8 @@ Item {
anchors.topMargin: styleConstants.cellVerticalMargin anchors.topMargin: styleConstants.cellVerticalMargin
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: itemLibraryIconWidth // to be set in Qml context width: ItemLibraryBackend.itemLibraryIconWidth // to be set in Qml context
height: itemLibraryIconHeight // to be set in Qml context height: ItemLibraryBackend.itemLibraryIconHeight // to be set in Qml context
source: itemLibraryIconPath // to be set by model source: itemLibraryIconPath // to be set by model
// Icons generated for components can change if the component is edited, // Icons generated for components can change if the component is edited,
@@ -75,12 +76,12 @@ Item {
allowTooltip = false allowTooltip = false
hide() hide()
if (mouse.button === Qt.LeftButton) if (mouse.button === Qt.LeftButton)
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y)) ItemLibraryBackend.rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y))
} }
onDoubleClicked: (mouse)=> { onDoubleClicked: (mouse)=> {
if (mouse.button === Qt.LeftButton && itemComponentSource) { if (mouse.button === Qt.LeftButton && itemComponentSource) {
hide() hide()
rootView.goIntoComponent(itemComponentSource) ItemLibraryBackend.rootView.goIntoComponent(itemComponentSource)
} }
} }
} }

View File

@@ -6,6 +6,7 @@ import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import ItemLibraryBackend
/* The view displaying the item grid. /* The view displaying the item grid.
The following Qml context properties have to be set: The following Qml context properties have to be set:
- ItemLibraryModel itemLibraryModel - ItemLibraryModel itemLibraryModel
@@ -52,6 +53,9 @@ Item {
property var currentImport: null property var currentImport: null
property bool isHorizontalView: false property bool isHorizontalView: false
property bool isAddModuleView: false property bool isAddModuleView: false
property var tooltipBackend: ItemLibraryBackend.tooltipBackend
// Called also from C++ to close context menu on focus out // Called also from C++ to close context menu on focus out
function closeContextMenu() function closeContextMenu()
{ {
@@ -66,10 +70,10 @@ Item {
// Called also from C++ // Called also from C++
function switchToComponentsView() function switchToComponentsView()
{ {
isAddModuleView = false ItemLibraryBackend.isAddModuleView = false
} }
onWidthChanged: { onWidthChanged: {
itemsView.isHorizontalView = itemsView.width > widthLimit itemsView.isHorizontalView = itemsView.width > ItemLibraryBackend.widthLimit
} }
onIsHorizontalViewChanged: closeContextMenu() onIsHorizontalViewChanged: closeContextMenu()
Item { Item {
@@ -81,7 +85,7 @@ Item {
property int cellVerticalMargin: 4 property int cellVerticalMargin: 4
// the following depend on the actual shape of the item delegate // the following depend on the actual shape of the item delegate
property int cellWidth: styleConstants.textWidth + 2 * styleConstants.cellHorizontalMargin property int cellWidth: styleConstants.textWidth + 2 * styleConstants.cellHorizontalMargin
property int cellHeight: itemLibraryIconHeight + styleConstants.textHeight + property int cellHeight: ItemLibraryBackend.itemLibraryIconHeight + styleConstants.textHeight +
2 * styleConstants.cellVerticalMargin + styleConstants.cellVerticalSpacing 2 * styleConstants.cellVerticalMargin + styleConstants.cellVerticalSpacing
StudioControls.Menu { StudioControls.Menu {
id: moduleContextMenu id: moduleContextMenu
@@ -89,34 +93,34 @@ Item {
text: qsTr("Remove Module") text: qsTr("Remove Module")
visible: itemsView.currentCategory === null visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
enabled: itemsView.importToRemove && !rootView.subCompEditMode enabled: itemsView.importToRemove && !ItemLibraryBackend.rootView.subCompEditMode
onTriggered: rootView.removeImport(itemsView.importToRemove) onTriggered: ItemLibraryBackend.rootView.removeImport(itemsView.importToRemove)
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
visible: itemsView.currentCategory === null && !rootView.searchActive visible: itemsView.currentCategory === null && !ItemLibraryBackend.rootView.searchActive
height: visible ? StudioTheme.Values.border : 0 height: visible ? StudioTheme.Values.border : 0
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Expand All") text: qsTr("Expand All")
visible: itemsView.currentCategory === null && !rootView.searchActive visible: itemsView.currentCategory === null && !ItemLibraryBackend.rootView.searchActive
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.expandAll() onTriggered: ItemLibraryBackend.itemLibraryModel.expandAll()
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Collapse All") text: qsTr("Collapse All")
visible: itemsView.currentCategory === null && !rootView.searchActive visible: itemsView.currentCategory === null && !ItemLibraryBackend.rootView.searchActive
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.collapseAll() onTriggered: ItemLibraryBackend.itemLibraryModel.collapseAll()
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
visible: itemsView.currentCategory === null && !rootView.searchActive visible: itemsView.currentCategory === null && !ItemLibraryBackend.rootView.searchActive
height: visible ? StudioTheme.Values.border : 0 height: visible ? StudioTheme.Values.border : 0
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Hide Category") text: qsTr("Hide Category")
visible: itemsView.currentCategory visible: itemsView.currentCategory
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.hideCategory(itemsView.currentImport.importUrl, onTriggered: ItemLibraryBackend.itemLibraryModel.hideCategory(itemsView.currentImport.importUrl,
itemsView.currentCategory.categoryName) itemsView.currentCategory.categoryName)
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
@@ -125,17 +129,17 @@ Item {
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Show Module Hidden Categories") text: qsTr("Show Module Hidden Categories")
visible: !rootView.searchActive visible: !ItemLibraryBackend.rootView.searchActive
enabled: itemsView.currentImport && !itemsView.currentImport.allCategoriesVisible enabled: itemsView.currentImport && !itemsView.currentImport.allCategoriesVisible
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.showImportHiddenCategories(itemsView.currentImport.importUrl) onTriggered: ItemLibraryBackend.itemLibraryModel.showImportHiddenCategories(itemsView.currentImport.importUrl)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Show All Hidden Categories") text: qsTr("Show All Hidden Categories")
visible: !rootView.searchActive visible: !ItemLibraryBackend.rootView.searchActive
enabled: itemLibraryModel.isAnyCategoryHidden enabled: ItemLibraryBackend.itemLibraryModel.isAnyCategoryHidden
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.showAllHiddenCategories() onTriggered: ItemLibraryBackend.itemLibraryModel.showAllHiddenCategories()
} }
} }
StudioControls.Menu { StudioControls.Menu {
@@ -147,14 +151,14 @@ Item {
text: qsTr("Add Module: ") + itemsView.importToAdd text: qsTr("Add Module: ") + itemsView.importToAdd
visible: itemsView.importToAdd visible: itemsView.importToAdd
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: rootView.addImportForItem(itemsView.importToAdd) onTriggered: ItemLibraryBackend.rootView.addImportForItem(itemsView.importToAdd)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
id: openSourceItem id: openSourceItem
text: qsTr("Edit Component") text: qsTr("Edit Component")
visible: itemsView.componentSource visible: itemsView.componentSource
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: rootView.goIntoComponent(itemsView.componentSource) onTriggered: ItemLibraryBackend.rootView.goIntoComponent(itemsView.componentSource)
} }
} }
} }
@@ -182,7 +186,7 @@ Item {
width: parent.width width: parent.width
style: StudioTheme.Values.searchControlStyle style: StudioTheme.Values.searchControlStyle
onSearchChanged: (searchText) => rootView.handleSearchFilterChanged(searchText) onSearchChanged: (searchText) => ItemLibraryBackend.rootView.handleSearchFilterChanged(searchText)
} }
Row { Row {
@@ -215,7 +219,7 @@ Item {
id: verticalScrollView id: verticalScrollView
anchors.fill: parent anchors.fill: parent
clip: true clip: true
interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !rootView.isDragging interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !ItemLibraryBackend.rootView.isDragging
onContentHeightChanged: { onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - verticalScrollView.height, 0) var maxPosition = Math.max(contentHeight - verticalScrollView.height, 0)
if (contentY > maxPosition) if (contentY > maxPosition)
@@ -224,7 +228,7 @@ Item {
Column { Column {
spacing: 2 spacing: 2
Repeater { Repeater {
model: itemLibraryModel // to be set in Qml context model: ItemLibraryBackend.itemLibraryModel // to be set in Qml context
delegate: HelperWidgets.Section { delegate: HelperWidgets.Section {
width: itemsView.width - width: itemsView.width -
(verticalScrollView.verticalScrollBarVisible (verticalScrollView.verticalScrollBarVisible
@@ -274,7 +278,7 @@ Item {
onToggleExpand: categoryExpanded = !categoryExpanded onToggleExpand: categoryExpanded = !categoryExpanded
useDefaulContextMenu: false useDefaulContextMenu: false
onShowContextMenu: { onShowContextMenu: {
if (!rootView.searchActive) { if (!ItemLibraryBackend.rootView.searchActive) {
itemsView.currentCategory = model itemsView.currentCategory = model
itemsView.currentImport = parent.currentImportModel itemsView.currentImport = parent.currentImportModel
moduleContextMenu.popup() moduleContextMenu.popup()
@@ -322,7 +326,7 @@ Item {
width: 270 width: 270
height: parent.height height: parent.height
clip: true clip: true
interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !rootView.isDragging interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !ItemLibraryBackend.rootView.isDragging
onContentHeightChanged: { onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - horizontalScrollView.height, 0) var maxPosition = Math.max(contentHeight - horizontalScrollView.height, 0)
@@ -333,7 +337,7 @@ Item {
width: parent.width width: parent.width
spacing: 2 spacing: 2
Repeater { Repeater {
model: itemLibraryModel // to be set in Qml context model: ItemLibraryBackend.itemLibraryModel // to be set in Qml context
delegate: HelperWidgets.Section { delegate: HelperWidgets.Section {
width: 265 - width: 265 -
(horizontalScrollView.verticalScrollBarVisible (horizontalScrollView.verticalScrollBarVisible
@@ -392,10 +396,10 @@ Item {
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => { onClicked: (mouse) => {
itemLibraryModel.selectImportCategory(parent.parent.currentImportModel.importUrl, model.index) ItemLibraryBackend.itemLibraryModel.selectImportCategory(parent.parent.currentImportModel.importUrl, model.index)
if (mouse.button === Qt.RightButton if (mouse.button === Qt.RightButton
&& categoryModel.rowCount() !== 1 && categoryModel.rowCount() !== 1
&& !rootView.searchActive) { && !ItemLibraryBackend.rootView.searchActive) {
itemsView.currentCategory = model itemsView.currentCategory = model
itemsView.currentImport = parent.parent.currentImportModel itemsView.currentImport = parent.parent.currentImportModel
moduleContextMenu.popup() moduleContextMenu.popup()
@@ -419,7 +423,7 @@ Item {
id: itemScrollView id: itemScrollView
width: itemsView.width - 275 width: itemsView.width - 275
height: itemsView.height height: itemsView.height
interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !rootView.isDragging interactive: !itemContextMenu.opened && !moduleContextMenu.opened && !ItemLibraryBackend.rootView.isDragging
onContentHeightChanged: { onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - itemScrollView.height, 0) var maxPosition = Math.max(contentHeight - itemScrollView.height, 0)
@@ -435,10 +439,10 @@ Item {
columns: hItemGrid.actualWidth / styleConstants.cellWidth columns: hItemGrid.actualWidth / styleConstants.cellWidth
rowSpacing: 7 rowSpacing: 7
Repeater { Repeater {
model: itemLibraryModel.itemsModel model: ItemLibraryBackend.itemLibraryModel.itemsModel
delegate: ItemDelegate { delegate: ItemDelegate {
visible: itemVisible visible: itemVisible
textColor: itemLibraryModel.importUnimportedSelected textColor: ItemLibraryBackend.itemLibraryModel.importUnimportedSelected
? StudioTheme.Values.themeUnimportedModuleColor : StudioTheme.Values.themeTextColor ? StudioTheme.Values.themeUnimportedModuleColor : StudioTheme.Values.themeTextColor
width: styleConstants.cellWidth width: styleConstants.cellWidth
height: styleConstants.cellHeight height: styleConstants.cellHeight

View File

@@ -123,7 +123,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
: m_itemIconSize(24, 24) : m_itemIconSize(24, 24)
, m_itemLibraryModel(new ItemLibraryModel(this)) , m_itemLibraryModel(new ItemLibraryModel(this))
, m_addModuleModel(new ItemLibraryAddImportModel(this)) , m_addModuleModel(new ItemLibraryAddImportModel(this))
, m_itemsWidget(new QQuickWidget(this)) , m_itemsWidget(new StudioQuickWidget(this))
, m_imageCache{imageCache} , m_imageCache{imageCache}
{ {
m_compressionTimer.setInterval(1000); m_compressionTimer.setInterval(1000);
@@ -138,24 +138,13 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
m_itemsWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); m_itemsWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_itemsWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_itemsWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_itemsWidget->rootContext()->setContextProperties({
{"itemLibraryModel", QVariant::fromValue(m_itemLibraryModel.data())},
{"addModuleModel", QVariant::fromValue(m_addModuleModel.data())},
{"itemLibraryIconWidth", m_itemIconSize.width()},
{"itemLibraryIconHeight", m_itemIconSize.height()},
{"rootView", QVariant::fromValue(this)},
{"widthLimit", HORIZONTAL_LAYOUT_WIDTH_LIMIT},
{"highlightColor", Utils::StyleHelper::notTooBrightHighlightColor()},
});
m_previewTooltipBackend = std::make_unique<PreviewTooltipBackend>(m_imageCache); m_previewTooltipBackend = std::make_unique<PreviewTooltipBackend>(m_imageCache);
m_itemsWidget->rootContext()->setContextProperty("tooltipBackend", m_previewTooltipBackend.get());
m_itemsWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_itemsWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
m_itemsWidget->engine()->addImageProvider(QStringLiteral("qmldesigner_itemlibrary"), m_itemsWidget->engine()->addImageProvider(QStringLiteral("qmldesigner_itemlibrary"),
new Internal::ItemLibraryImageProvider); new Internal::ItemLibraryImageProvider);
Theme::setupTheme(m_itemsWidget->engine()); Theme::setupTheme(m_itemsWidget->engine());
m_itemsWidget->installEventFilter(this); m_itemsWidget->quickWidget()->installEventFilter(this);
auto layout = new QVBoxLayout(this); auto layout = new QVBoxLayout(this);
layout->setContentsMargins({}); layout->setContentsMargins({});
@@ -178,6 +167,19 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_ITEMLIBRARY_TIME); QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_ITEMLIBRARY_TIME);
// init the first load of the QML UI elements // init the first load of the QML UI elements
auto map = m_itemsWidget->registerPropertyMap("ItemLibraryBackend");
map->setProperties({{"itemLibraryModel", QVariant::fromValue(m_itemLibraryModel.data())},
{"addModuleModel", QVariant::fromValue(m_addModuleModel.data())},
{"itemLibraryIconWidth", m_itemIconSize.width()},
{"itemLibraryIconHeight", m_itemIconSize.height()},
{"rootView", QVariant::fromValue(this)},
{"widthLimit", HORIZONTAL_LAYOUT_WIDTH_LIMIT},
{"highlightColor", Utils::StyleHelper::notTooBrightHighlightColor()},
{"tooltipBackend", QVariant::fromValue(m_previewTooltipBackend.get())}});
reloadQmlSource(); reloadQmlSource();
} }
@@ -321,7 +323,6 @@ void ItemLibraryWidget::reloadQmlSource()
{ {
const QString itemLibraryQmlPath = qmlSourcesPath() + "/ItemsView.qml"; const QString itemLibraryQmlPath = qmlSourcesPath() + "/ItemsView.qml";
QTC_ASSERT(QFileInfo::exists(itemLibraryQmlPath), return); QTC_ASSERT(QFileInfo::exists(itemLibraryQmlPath), return);
m_itemsWidget->engine()->clearComponentCache();
m_itemsWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlPath)); m_itemsWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlPath));
} }

View File

@@ -6,6 +6,8 @@
#include "itemlibraryinfo.h" #include "itemlibraryinfo.h"
#include "import.h" #include "import.h"
#include <studioquickwidget.h>
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/dropsupport.h> #include <utils/dropsupport.h>
#include <previewtooltip/previewtooltipbackend.h> #include <previewtooltip/previewtooltipbackend.h>
@@ -14,7 +16,6 @@
#include <QFrame> #include <QFrame>
#include <QPointF> #include <QPointF>
#include <QQmlPropertyMap> #include <QQmlPropertyMap>
#include <QQuickWidget>
#include <QTimer> #include <QTimer>
#include <QToolButton> #include <QToolButton>
@@ -102,7 +103,7 @@ private:
QPointer<ItemLibraryModel> m_itemLibraryModel; QPointer<ItemLibraryModel> m_itemLibraryModel;
QPointer<ItemLibraryAddImportModel> m_addModuleModel; QPointer<ItemLibraryAddImportModel> m_addModuleModel;
QScopedPointer<QQuickWidget> m_itemsWidget; QScopedPointer<StudioQuickWidget> m_itemsWidget;
std::unique_ptr<PreviewTooltipBackend> m_previewTooltipBackend; std::unique_ptr<PreviewTooltipBackend> m_previewTooltipBackend;
QShortcut *m_qmlSourceUpdateShortcut; QShortcut *m_qmlSourceUpdateShortcut;