forked from qt-creator/qt-creator
QmlDesigner: Add Loader and Repeater to component library
Also fixes some issues with Repeater usage. Fixes: QDS-5149 Change-Id: I259dcb73be634150dd0c5e602165b63112ec958c Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -1287,8 +1287,15 @@ PixmapChangedCommand NodeInstanceServer::createPixmapChangedCommand(const QList<
|
||||
QVector<ImageContainer> imageVector;
|
||||
|
||||
for (const ServerNodeInstance &instance : instanceList) {
|
||||
if (instance.isValid() && instance.hasContent())
|
||||
imageVector.append(ImageContainer(instance.instanceId(), instance.renderImage(), instance.instanceId()));
|
||||
if (!instance.isValid())
|
||||
continue;
|
||||
|
||||
QImage renderImage;
|
||||
// We need to return empty image if instance has no content to correctly update the
|
||||
// item image in case the instance changed from having content to not having content.
|
||||
if (instance.hasContent())
|
||||
renderImage = instance.renderImage();
|
||||
imageVector.append(ImageContainer(instance.instanceId(), renderImage, instance.instanceId()));
|
||||
}
|
||||
|
||||
return PixmapChangedCommand(imageVector);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <addimportcontainer.h>
|
||||
#include <createscenecommand.h>
|
||||
#include <reparentinstancescommand.h>
|
||||
#include <removeinstancescommand.h>
|
||||
#include <clearscenecommand.h>
|
||||
|
||||
#include <QDebug>
|
||||
@@ -193,6 +194,19 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
|
||||
return QList<QQuickItem*>();
|
||||
}
|
||||
|
||||
void Qt5NodeInstanceServer::markRepeaterParentDirty(qint32 id) const
|
||||
{
|
||||
if (!hasInstanceForId(id))
|
||||
return;
|
||||
|
||||
// If a Repeater instance was moved/removed, the old parent must be marked dirty to rerender it
|
||||
ServerNodeInstance instance = instanceForId(id);
|
||||
if (instance.isValid() && instance.isSubclassOf("QQuickRepeater") && instance.hasParent()) {
|
||||
ServerNodeInstance parentInstance = instance.parent();
|
||||
DesignerSupport::addDirty(parentInstance.rootQuickItem(), QQuickDesignerSupport::Content);
|
||||
}
|
||||
}
|
||||
|
||||
bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
@@ -523,9 +537,23 @@ void Qt5NodeInstanceServer::clearScene(const ClearSceneCommand &command)
|
||||
|
||||
void Qt5NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
|
||||
{
|
||||
const QVector<ReparentContainer> &containerVector = command.reparentInstances();
|
||||
for (const ReparentContainer &container : containerVector)
|
||||
markRepeaterParentDirty(container.instanceId());
|
||||
|
||||
NodeInstanceServer::reparentInstances(command.reparentInstances());
|
||||
startRenderTimer();
|
||||
}
|
||||
|
||||
void Qt5NodeInstanceServer::removeInstances(const RemoveInstancesCommand &command)
|
||||
{
|
||||
const QVector<qint32> &idVector = command.instanceIds();
|
||||
for (const qint32 id : idVector)
|
||||
markRepeaterParentDirty(id);
|
||||
|
||||
NodeInstanceServer::removeInstances(command);
|
||||
startRenderTimer();
|
||||
}
|
||||
|
||||
|
||||
} // QmlDesigner
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
void createScene(const CreateSceneCommand &command) override;
|
||||
void clearScene(const ClearSceneCommand &command) override;
|
||||
void reparentInstances(const ReparentInstancesCommand &command) override;
|
||||
void removeInstances(const RemoveInstancesCommand &command) override;
|
||||
|
||||
QImage grabWindow() override;
|
||||
QImage grabItem(QQuickItem *item) override;
|
||||
@@ -79,6 +80,7 @@ protected:
|
||||
void resetAllItems();
|
||||
void setupScene(const CreateSceneCommand &command) override;
|
||||
QList<QQuickItem*> allItems() const;
|
||||
void markRepeaterParentDirty(qint32 id) const;
|
||||
|
||||
struct RenderViewData {
|
||||
QPointer<QQuickWindow> window = nullptr;
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 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 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import HelperWidgets 2.0
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Column {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Section {
|
||||
caption: qsTr("Loader")
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
SectionLayout {
|
||||
PropertyLabel {
|
||||
text: qsTr("Active")
|
||||
tooltip: qsTr("This property is true if the Loader is currently active.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
CheckBox {
|
||||
text: backendValues.active.valueToString
|
||||
backendValue: backendValues.active
|
||||
implicitWidth: StudioTheme.Values.twoControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Source")
|
||||
tooltip: qsTr("This property holds the URL of the QML component to instantiate.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
UrlChooser {
|
||||
filter: "*.qml"
|
||||
backendValue: backendValues.source
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Source Component")
|
||||
tooltip: qsTr("This property holds the component to instantiate.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
ItemFilterComboBox {
|
||||
typeFilter: "Component"
|
||||
validator: RegExpValidator { regExp: /(^$|^[a-z_]\w*)/ }
|
||||
backendValue: backendValues.sourceComponent
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Asynchronous")
|
||||
tooltip: qsTr("This property holds whether the component will be instantiated asynchronously.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
CheckBox {
|
||||
text: backendValues.asynchronous.valueToString
|
||||
backendValue: backendValues.asynchronous
|
||||
implicitWidth: StudioTheme.Values.twoControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 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 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import HelperWidgets 2.0
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Column {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Section {
|
||||
caption: qsTr("Repeater")
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
SectionLayout {
|
||||
PropertyLabel {
|
||||
text: qsTr("Model")
|
||||
tooltip: qsTr("The model providing data for the repeater. This can simply specify the number of delegate instances to create or it can be bound to an actual model.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
LineEdit {
|
||||
backendValue: backendValues.model
|
||||
showTranslateCheckBox: false
|
||||
writeAsExpression: true
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
width: implicitWidth
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Delegate")
|
||||
tooltip: qsTr("The delegate provides a template defining each object instantiated by the repeater.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
ItemFilterComboBox {
|
||||
typeFilter: "Component"
|
||||
validator: RegExpValidator { regExp: /(^$|^[a-z_]\w*)/ }
|
||||
backendValue: backendValues.delegate
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +91,9 @@ void FormEditorView::modelAttached(Model *model)
|
||||
//This function does the setup of the initial FormEditorItem tree in the scene
|
||||
void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
|
||||
{
|
||||
if (!qmlItemNode.hasFormEditorItem())
|
||||
return;
|
||||
|
||||
if (qmlItemNode.isFlowTransition()) {
|
||||
m_scene->addFormEditorItem(qmlItemNode, FormEditorScene::FlowTransition);
|
||||
if (qmlItemNode.hasNodeParent())
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
bool canBeDroppedInView3D() const;
|
||||
bool isMovable() const;
|
||||
bool isResizable() const;
|
||||
bool hasFormEditorItem() const;
|
||||
bool isStackedContainer() const;
|
||||
bool canBeReparentedTo(const ModelNode &potenialParent);
|
||||
QString indexPropertyForStackedContainer() const;
|
||||
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
bool modelIsResizable() const;
|
||||
bool modelIsRotatable() const;
|
||||
bool modelIsInLayout() const;
|
||||
bool hasFormEditorItem() const;
|
||||
|
||||
QRectF instanceBoundingRect() const;
|
||||
QRectF instanceSceneBoundingRect() const;
|
||||
|
||||
@@ -183,6 +183,11 @@ bool NodeHints::isResizable() const
|
||||
return evaluateBooleanExpression("isResizable", true);
|
||||
}
|
||||
|
||||
bool NodeHints::hasFormEditorItem() const
|
||||
{
|
||||
return evaluateBooleanExpression("hasFormEditorItem", true);
|
||||
}
|
||||
|
||||
bool NodeHints::isStackedContainer() const
|
||||
{
|
||||
if (!isValid())
|
||||
|
||||
@@ -395,6 +395,11 @@ bool QmlItemNode::modelIsInLayout() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QmlItemNode::hasFormEditorItem() const
|
||||
{
|
||||
return NodeHints::fromModelNode(modelNode()).hasFormEditorItem();
|
||||
}
|
||||
|
||||
QRectF QmlItemNode::instanceBoundingRect() const
|
||||
{
|
||||
return QRectF(QPointF(0, 0), nodeInstance().size());
|
||||
|
||||
@@ -448,4 +448,35 @@ MetaInfo {
|
||||
version: "2.0"
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtQuick.Loader"
|
||||
icon: ":/qtquickplugin/images/item-icon16.png"
|
||||
|
||||
ItemLibraryEntry {
|
||||
name: "Loader"
|
||||
category: "e.Qt Quick - Component"
|
||||
libraryIcon: ":/qtquickplugin/images/item-icon.png"
|
||||
version: "2.0"
|
||||
Property { name: "width"; type: "int"; value: 200; }
|
||||
Property { name: "height"; type: "int"; value: 200; }
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtQuick.Repeater"
|
||||
icon: ":/qtquickplugin/images/item-icon16.png"
|
||||
|
||||
Hints {
|
||||
canBeDroppedInFormEditor: false
|
||||
hasFormEditorItem: false
|
||||
}
|
||||
|
||||
ItemLibraryEntry {
|
||||
name: "Repeater"
|
||||
category: "e.Qt Quick - Component"
|
||||
libraryIcon: ":/qtquickplugin/images/item-icon.png"
|
||||
version: "2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user