QmlDesigner: Add support for ShapeGradient

This adds support for ShapeGradient in the property editor.

* LinearGradient
* RadialGradient
* ConicalGradient

The custom properties can be edited using a small popup.

Task-number: QDS-359
Change-Id: I6232a4685f2d919dcab3efbb14a70c3617aea36c
Reviewed-by: Brook Cronin <brook.cronin@qt.io>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Thomas Hartmann
2019-02-04 17:32:23 +01:00
parent 67b3d25624
commit 46ddfb9bad
9 changed files with 683 additions and 43 deletions

View File

@@ -26,7 +26,8 @@
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
import QtQuick.Controls.Styles 1.1
Column { Column {
id: colorEditor id: colorEditor
@@ -45,19 +46,17 @@ Column {
property alias gradientPropertyName: gradientLine.gradientPropertyName property alias gradientPropertyName: gradientLine.gradientPropertyName
property bool shapeGradients: false
property alias transparent: transparentButton.checked property alias transparent: transparentButton.checked
function isNotInGradientMode() { function isNotInGradientMode() {
return (buttonRow.checkedIndex !== 1) return (buttonRow.checkedIndex !== 1)
} }
onValueChanged: { onValueChanged: colorEditor.color = colorEditor.value
colorEditor.color = colorEditor.value
}
onBackendValueChanged: { onBackendValueChanged: colorEditor.color = colorEditor.value
colorEditor.color = colorEditor.value
}
Timer { Timer {
id: colorEditorTimer id: colorEditorTimer
@@ -87,7 +86,13 @@ Column {
GradientLine { GradientLine {
property bool isInValidState: false property bool isInValidState: false
visible: buttonRow.checkedIndex === 1 visible: {
if (colorEditor.shapeGradients) {
return buttonRow.checkedIndex > 0 && buttonRow.checkedIndex < 4
} else {
return buttonRow.checkedIndex === 1
}
}
id: gradientLine id: gradientLine
width: parent.width width: parent.width
@@ -102,7 +107,22 @@ Column {
return return
if (gradientLine.hasGradient) { if (gradientLine.hasGradient) {
if (colorEditor.shapeGradients) {
switch (gradientLine.gradientTypeName) {
case "LinearGradient":
buttonRow.initalChecked = 1 buttonRow.initalChecked = 1
break;
case "RadialGradient":
buttonRow.initalChecked = 2
break;
case "ConicalGradient":
buttonRow.initalChecked = 3
break;
default:
buttonRow.initalChecked = 1
}
}
colorEditor.color = gradientLine.currentColor colorEditor.color = gradientLine.currentColor
} else { } else {
buttonRow.initalChecked = 0 buttonRow.initalChecked = 0
@@ -155,6 +175,11 @@ Column {
SecondColumnLayout { SecondColumnLayout {
ColorCheckButton {
id: checkButton
color: colorEditor.color
}
LineEdit { LineEdit {
enabled: !colorEditor.transparent enabled: !colorEditor.transparent
id: textField id: textField
@@ -181,10 +206,6 @@ Column {
Layout.fillWidth: true Layout.fillWidth: true
} }
ColorCheckButton {
id: checkButton
color: colorEditor.color
}
ButtonRow { ButtonRow {
@@ -193,6 +214,7 @@ Column {
ButtonRowButton { ButtonRowButton {
iconSource: "images/icon_color_solid.png" iconSource: "images/icon_color_solid.png"
onClicked: { onClicked: {
gradientLine.deleteGradient() gradientLine.deleteGradient()
textField.text = colorEditor.color textField.text = colorEditor.color
@@ -205,10 +227,245 @@ Column {
iconSource: "images/icon_color_gradient.png" iconSource: "images/icon_color_gradient.png"
onClicked: { onClicked: {
colorEditor.backendValue.resetValue() colorEditor.backendValue.resetValue()
if (colorEditor.shapeGradients) {
gradientLine.deleteGradient()
gradientLine.gradientTypeName = "LinearGradient"
}
gradientLine.addGradient() gradientLine.addGradient()
} }
tooltip: qsTr("Gradient") tooltip: qsTr("Linear Gradient")
GradientPopupIndicator {
onClicked: gradientDialogPopupLinear.toggle()
GradientDialogPopup {
id: gradientDialogPopupLinear
dialogHeight: 80
content: GridLayout {
rowSpacing: 4
anchors.fill: parent
height: 40
columns: 4
rows: 2
anchors.leftMargin: 12
anchors.rightMargin: 6
anchors.topMargin: 24
anchors.bottomMargin: 6
Label {
text: "X1"
width: 16
tooltip: qsTr("Defines the start point for color interpolation.")
}
GradientPropertySpinBox {
propertyName: "x1"
}
Label {
text: "X2"
width: 16
tooltip: qsTr("Defines the end point for color interpolation.")
}
GradientPropertySpinBox {
propertyName: "x2"
}
Label {
text: "y1"
width: 16
tooltip: qsTr("Defines the start point for color interpolation.")
}
GradientPropertySpinBox {
propertyName: "y1"
}
Label {
text: "Y2"
width: 16
tooltip: qsTr("Defines the end point for color interpolation.")
}
GradientPropertySpinBox {
propertyName: "y2"
}
}
}
}
}
ButtonRowButton {
visible: supportGradient && colorEditor.shapeGradients
iconSource: "images/icon_color_radial_gradient.png"
onClicked: {
colorEditor.backendValue.resetValue()
if (colorEditor.shapeGradients) {
gradientLine.deleteGradient()
gradientLine.gradientTypeName = "RadialGradient"
}
gradientLine.addGradient()
}
tooltip: qsTr("Radial Gradient")
GradientPopupIndicator {
onClicked: gradientDialogPopupRadial.toggle()
GradientDialogPopup {
id: gradientDialogPopupRadial
dialogHeight: 140
dialogWidth: 340
content: GridLayout {
rowSpacing: 4
anchors.fill: parent
height: 40
columns: 4
rows: 3
anchors.leftMargin: 12
anchors.rightMargin: 6
anchors.topMargin: 24
anchors.bottomMargin: 6
Label {
text: "CenterX"
width: 54
tooltip: qsTr("Defines the center point.")
}
GradientPropertySpinBox {
propertyName: "centerX"
}
Label {
text: "CenterY"
width: 54
tooltip: qsTr("Defines the center point.")
}
GradientPropertySpinBox {
propertyName: "centerY"
}
Label {
text: "FocalX"
width: 54
tooltip: qsTr("Defines the focal point.")
}
GradientPropertySpinBox {
propertyName: "focalX"
}
Label {
text: "FocalY"
width: 54
tooltip: qsTr("Defines the focal point.")
}
GradientPropertySpinBox {
propertyName: "focalY"
}
Label {
text: "Center Radius"
width: 54
tooltip: qsTr("Defines the center point.")
}
GradientPropertySpinBox {
propertyName: "centerRadius"
}
Label {
text: "Focal Radius"
width: 54
tooltip: qsTr("Defines the focal radius. Set to 0 for simple radial gradients.")
}
GradientPropertySpinBox {
propertyName: "focalRadius"
}
}
}
}
}
ButtonRowButton {
visible: supportGradient && colorEditor.shapeGradients
iconSource: "images/icon_color_conical_gradient.png"
onClicked: {
colorEditor.backendValue.resetValue()
if (colorEditor.shapeGradients) {
gradientLine.deleteGradient()
gradientLine.gradientTypeName = "ConicalGradient"
}
gradientLine.addGradient()
}
tooltip: qsTr("Concial Gradient")
GradientPopupIndicator {
onClicked: gradientDialogPopupConical.toggle()
GradientDialogPopup {
id: gradientDialogPopupConical
dialogHeight: 80
content: GridLayout {
rowSpacing: 4
anchors.fill: parent
height: 40
columns: 4
rows: 2
anchors.leftMargin: 12
anchors.rightMargin: 6
anchors.topMargin: 24
anchors.bottomMargin: 6
Label {
text: "CenterX"
width: 32
tooltip: qsTr("Defines the center point.")
}
GradientPropertySpinBox {
propertyName: "centerX"
}
Label {
text: "CenterY"
width: 32
tooltip: qsTr("Defines the center point.")
}
GradientPropertySpinBox {
propertyName: "centerY"
}
Label {
text: "Angle"
width: 32
tooltip: qsTr("Defines the start angle for the conical gradient. The value is in degrees (0-360).")
}
GradientPropertySpinBox {
propertyName: "angle"
}
}
}
}
} }
ButtonRowButton { ButtonRowButton {
id: transparentButton id: transparentButton

View File

@@ -0,0 +1,135 @@
/****************************************************************************
**
** Copyright (C) 2019 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.1
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
import QtQuick.Controls.Styles 1.1
Loader {
id: gradientDialogLoader
parent: itemPane
anchors.fill: parent
visible: false
active: visible
function toggle() {
gradientDialogLoader.visible = !gradientDialogLoader.visible
}
property Component content
property int dialogHeight: 240
property int dialogWidth: 280
sourceComponent: Component {
FocusScope {
id: popup
Keys.onEscapePressed: {
event.accepted = true
gradientDialogLoader.visible = false
}
Component.onCompleted: {
popup.forceActiveFocus()
}
Rectangle {
anchors.fill: parent
color: Theme.qmlDesignerBackgroundColorDarker()
opacity: 0.6
}
MouseArea {
anchors.fill: parent
onClicked: gradientDialogLoader.visible = false
}
Rectangle {
id: background
property int xOffset: itemPane.width - gradientDialogLoader.dialogWidth
x: 4 + xOffset
Component.onCompleted: {
var pos = itemPane.mapFromItem(buttonRow.parent, 0, 0)
y = pos.y + 32
}
width: parent.width - 8 - xOffset
height: gradientDialogLoader.dialogHeight
radius: 2
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
border.color: Theme.qmlDesignerBorderColor()
Label {
x: 8
y: 6
font.bold: true
text: qsTr("Gradient Properties")
}
Button {
width: 16
height: 16
style: ButtonStyle {
background: Item {
Image {
width: 16
height: 16
source: "image://icons/error"
opacity: {
if (control.pressed)
return 0.8
return 1.0
}
Rectangle {
z: -1
anchors.fill: parent
color: control.pressed
|| control.hovered ? Theme.qmlDesignerBackgroundColorDarker() : Theme.qmlDesignerButtonColor()
border.color: Theme.qmlDesignerBorderColor()
radius: 2
}
}
}
}
onClicked: gradientDialogLoader.visible = false
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 4
}
Loader {
anchors.fill: parent
sourceComponent: gradientDialogLoader.content
}
}
}
}
}

View File

@@ -38,6 +38,7 @@ Item {
property alias gradientPropertyName: gradientModel.gradientPropertyName property alias gradientPropertyName: gradientModel.gradientPropertyName
property alias gradientTypeName: gradientModel.gradientTypeName
onHasGradientChanged: { onHasGradientChanged: {
colorLine.invalidate() colorLine.invalidate()

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2019 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.1
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
Image {
id: root
signal clicked
visible: colorEditor.shapeGradients && parent.checked
width: 8
height: 4
source: "image://icons/down-arrow"
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.bottom
anchors.topMargin: 2
opacity: popupRegion.containsMouse ? 1 : 0.8
ToolTipArea {
id: popupRegion
onClicked: root.clicked()
hoverEnabled: true
anchors.fill: parent
anchors.margins: -2
tooltip: qsTr("Edit Gradient Properties")
}
}

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2019 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.1
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
import QtQuick.Controls.Styles 1.1
DoubleSpinBox {
id: spinBox
property string propertyName
minimumValue: -9999
maximumValue: 9999
Component.onCompleted: spinBox.value = gradientLine.model.readGradientProperty(propertyName)
onValueChanged: gradientLine.model.setGradientProperty(propertyName, spinBox.value)
stepSize: 1
}

View File

@@ -28,6 +28,7 @@
#include "qmlanchorbindingproxy.h" #include "qmlanchorbindingproxy.h"
#include "propertyeditorview.h" #include "propertyeditorview.h"
#include <exception.h>
#include <nodeproperty.h> #include <nodeproperty.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
#include <variantproperty.h> #include <variantproperty.h>
@@ -35,8 +36,11 @@
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <rewritertransaction.h> #include <rewritertransaction.h>
#include <utils/qtcassert.h>
GradientModel::GradientModel(QObject *parent) : GradientModel::GradientModel(QObject *parent) :
QAbstractListModel(parent), m_locked(false) QAbstractListModel(parent), m_locked(false)
,m_gradientTypeName("Gradient")
{ {
} }
@@ -139,38 +143,38 @@ void GradientModel::addGradient()
return; return;
if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) { if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
try {
QColor color = m_itemNode.instanceValue("color").value<QColor>(); QColor color = m_itemNode.instanceValue("color").value<QColor>();
if (!color.isValid()) if (!color.isValid())
color = QColor(Qt::white); color = QColor(Qt::white);
QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::addGradient")); QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::addGradient"));
QmlDesigner::ModelNode gradientNode = createGradientNode();
QmlDesigner::ModelNode gradientNode =
m_itemNode.modelNode().view()->createModelNode("QtQuick.Gradient",
m_itemNode.modelNode().view()->majorQtQuickVersion(), 0);
m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).reparentHere(gradientNode); m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).reparentHere(gradientNode);
QmlDesigner::ModelNode gradientStopNode = view()->createModelNode("QtQuick.GradientStop", view()->majorQtQuickVersion(), 0);
QmlDesigner::ModelNode gradientStopNode =
m_itemNode.modelNode().view()->createModelNode("QtQuick.GradientStop",
m_itemNode.modelNode().view()->majorQtQuickVersion(), 0);
gradientStopNode.variantProperty("position").setValue(0.0); gradientStopNode.variantProperty("position").setValue(0.0);
gradientStopNode.variantProperty("color").setValue(color); gradientStopNode.variantProperty("color").setValue(color);
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
gradientStopNode = m_itemNode.modelNode().view()->createModelNode( gradientStopNode = view()->createModelNode("QtQuick.GradientStop", view()->majorQtQuickVersion(), 0);
"QtQuick.GradientStop",
m_itemNode.modelNode().view()->majorQtQuickVersion(), 0);
gradientStopNode.variantProperty("position").setValue(1.0); gradientStopNode.variantProperty("position").setValue(1.0);
gradientStopNode.variantProperty("color").setValue(QColor(Qt::black)); gradientStopNode.variantProperty("color").setValue(QColor(Qt::black));
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
} catch (const QmlDesigner::Exception &e) {
e.showException();
}
} }
setupModel(); setupModel();
emit hasGradientChanged(); emit hasGradientChanged();
emit gradientTypeChanged();
} }
void GradientModel::setColor(int index, const QColor &color) void GradientModel::setColor(int index, const QColor &color)
@@ -231,7 +235,7 @@ qreal GradientModel::getPosition(int index) const
void GradientModel::removeStop(int index) void GradientModel::removeStop(int index)
{ {
if (index < rowCount() - 1 && index != 0) { if (index < rowCount() - 1 && index != 0) {
QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::removeStop")); QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::removeStop"));
QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
QmlDesigner::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index); QmlDesigner::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index);
if (stop.isValid()) { if (stop.isValid()) {
@@ -255,7 +259,7 @@ void GradientModel::deleteGradient()
if (m_itemNode.isInBaseState()) { if (m_itemNode.isInBaseState()) {
if (modelNode.hasProperty(gradientPropertyName().toUtf8())) { if (modelNode.hasProperty(gradientPropertyName().toUtf8())) {
QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::deleteGradient")); QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::deleteGradient"));
QmlDesigner::ModelNode gradientNode = modelNode.nodeProperty(gradientPropertyName().toUtf8()).modelNode(); QmlDesigner::ModelNode gradientNode = modelNode.nodeProperty(gradientPropertyName().toUtf8()).modelNode();
if (QmlDesigner::QmlObjectNode(gradientNode).isValid()) if (QmlDesigner::QmlObjectNode(gradientNode).isValid())
QmlDesigner::QmlObjectNode(gradientNode).destroy(); QmlDesigner::QmlObjectNode(gradientNode).destroy();
@@ -263,6 +267,7 @@ void GradientModel::deleteGradient()
} }
emit hasGradientChanged(); emit hasGradientChanged();
emit gradientTypeChanged();
} }
void GradientModel::lock() void GradientModel::lock()
@@ -280,6 +285,22 @@ void GradientModel::registerDeclarativeType()
qmlRegisterType<GradientModel>("HelperWidgets",2,0,"GradientModel"); qmlRegisterType<GradientModel>("HelperWidgets",2,0,"GradientModel");
} }
qreal GradientModel::readGradientProperty(const QString &propertyName) const
{
if (!m_itemNode.isValid())
return 0;
QmlDesigner::QmlObjectNode gradient;
if (m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8()))
gradient = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
if (!gradient.isValid())
return 0;
return gradient.modelValue(propertyName.toUtf8()).toReal();
}
void GradientModel::setupModel() void GradientModel::setupModel()
{ {
m_locked = true; m_locked = true;
@@ -299,12 +320,17 @@ void GradientModel::setAnchorBackend(const QVariant &anchorBackend)
if (backendCasted) if (backendCasted)
m_itemNode = backendCasted->getItemNode(); m_itemNode = backendCasted->getItemNode();
if (m_itemNode.isValid()
&& m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8()))
m_gradientTypeName = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode().simplifiedTypeName();
setupModel(); setupModel();
m_locked = true; m_locked = true;
emit anchorBackendChanged(); emit anchorBackendChanged();
emit hasGradientChanged(); emit hasGradientChanged();
emit gradientTypeChanged();
m_locked = false; m_locked = false;
} }
@@ -319,6 +345,16 @@ void GradientModel::setGradientPropertyName(const QString &name)
m_gradientPropertyName = name; m_gradientPropertyName = name;
} }
QString GradientModel::gradientTypeName() const
{
return m_gradientTypeName;
}
void GradientModel::setGradientTypeName(const QString &name)
{
m_gradientTypeName = name;
}
bool GradientModel::hasGradient() const bool GradientModel::hasGradient() const
{ {
return m_itemNode.isValid() return m_itemNode.isValid()
@@ -330,10 +366,114 @@ bool GradientModel::locked() const
if (m_locked) if (m_locked)
return true; return true;
auto view = qobject_cast<QmlDesigner::PropertyEditorView*>(m_itemNode.view()); auto editorView = qobject_cast<QmlDesigner::PropertyEditorView*>(view());
if (view && view->locked()) return editorView && editorView->locked();
return true; }
bool GradientModel::hasShapesImport() const
{
if (m_itemNode.isValid()) {
QmlDesigner::Import import = QmlDesigner::Import::createLibraryImport("QtQuick.Shapes", "1.0");
return model()->hasImport(import, true, true);
}
return false; return false;
} }
void GradientModel::ensureShapesImport()
{
if (!hasShapesImport()) {
QmlDesigner::Import timelineImport = QmlDesigner::Import::createLibraryImport("QtQuick.Shapes", "1.0");
model()->changeImports({timelineImport}, {});
}
}
void GradientModel::setupGradientProperties(const QmlDesigner::ModelNode &gradient)
{
QTC_ASSERT(m_itemNode.isValid(), return);
QTC_ASSERT(gradient.isValid(), return);
if (m_gradientTypeName == "Gradient") {
} else if (m_gradientTypeName == "LinearGradient") {
gradient.variantProperty("x1").setValue(0);
gradient.variantProperty("x2").setValue(m_itemNode.instanceValue("width"));
gradient.variantProperty("y1").setValue(0);
gradient.variantProperty("y2").setValue(m_itemNode.instanceValue("height"));
} else if (m_gradientTypeName == "RadialGradient") {
qreal width = m_itemNode.instanceValue("width").toReal();
qreal height = m_itemNode.instanceValue("height").toReal();
gradient.variantProperty("centerX").setValue(width / 2.0);
gradient.variantProperty("centerY").setValue(height / 2.0);
gradient.variantProperty("focalX").setValue(width / 2.0);
gradient.variantProperty("focalY").setValue(height / 2.0);
qreal radius = qMin(width, height) / 2;
gradient.variantProperty("centerRadius").setValue(radius);
gradient.variantProperty("focalRadius").setValue(0);
} else if (m_gradientTypeName == "ConicalGradient") {
qreal width = m_itemNode.instanceValue("width").toReal();
qreal height = m_itemNode.instanceValue("height").toReal();
gradient.variantProperty("centerX").setValue(width / 2.0);
gradient.variantProperty("centerY").setValue(height / 2.0);
gradient.variantProperty("angle").setValue(0);
}
}
QmlDesigner::Model *GradientModel::model() const
{
QTC_ASSERT(m_itemNode.isValid(), return nullptr);
return m_itemNode.view()->model();
}
QmlDesigner::AbstractView *GradientModel::view() const
{
QTC_ASSERT(m_itemNode.isValid(), return nullptr);
return m_itemNode.view();
}
QmlDesigner::ModelNode GradientModel::createGradientNode()
{
QByteArray fullTypeName = m_gradientTypeName.toUtf8();
if (m_gradientTypeName == "Gradient") {
fullTypeName.prepend("QtQuick.");
} else {
fullTypeName.prepend("QtQuick.Shapes.");
ensureShapesImport();
}
auto metaInfo = model()->metaInfo(fullTypeName);
int minorVersion = metaInfo.minorVersion();
int majorVersion = metaInfo.majorVersion();
auto gradientNode = view()->createModelNode(fullTypeName, majorVersion, minorVersion);
setupGradientProperties(gradientNode);
return gradientNode;
}
void GradientModel::setGradientProperty(const QString &propertyName, qreal value)
{
QTC_ASSERT(m_itemNode.isValid(), return);
QmlDesigner::QmlObjectNode gradient;
if (m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8()))
gradient = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
QTC_ASSERT(gradient.isValid(), return);
try {
gradient.setVariantProperty(propertyName.toUtf8(), value);
} catch (const QmlDesigner::Exception &e) {
e.showException();
}
}

View File

@@ -37,6 +37,7 @@ class GradientModel : public QAbstractListModel
Q_PROPERTY(QVariant anchorBackendProperty READ anchorBackend WRITE setAnchorBackend NOTIFY anchorBackendChanged) Q_PROPERTY(QVariant anchorBackendProperty READ anchorBackend WRITE setAnchorBackend NOTIFY anchorBackendChanged)
Q_PROPERTY(QString gradientPropertyName READ gradientPropertyName WRITE setGradientPropertyName) Q_PROPERTY(QString gradientPropertyName READ gradientPropertyName WRITE setGradientPropertyName)
Q_PROPERTY(QString gradientTypeName READ gradientTypeName WRITE setGradientTypeName NOTIFY gradientTypeChanged)
Q_PROPERTY(int count READ rowCount) Q_PROPERTY(int count READ rowCount)
Q_PROPERTY(bool hasGradient READ hasGradient NOTIFY hasGradientChanged) Q_PROPERTY(bool hasGradient READ hasGradient NOTIFY hasGradientChanged)
@@ -65,9 +66,14 @@ public:
static void registerDeclarativeType(); static void registerDeclarativeType();
Q_INVOKABLE qreal readGradientProperty(const QString &property) const;
Q_INVOKABLE void setGradientProperty(const QString &propertyName, qreal value);
signals: signals:
void anchorBackendChanged(); void anchorBackendChanged();
void hasGradientChanged(); void hasGradientChanged();
void gradientTypeChanged();
private: private:
void setupModel(); void setupModel();
@@ -75,14 +81,22 @@ private:
QVariant anchorBackend() const {return QVariant(); } QVariant anchorBackend() const {return QVariant(); }
QString gradientPropertyName() const; QString gradientPropertyName() const;
void setGradientPropertyName(const QString &name); void setGradientPropertyName(const QString &name);
QString gradientTypeName() const;
void setGradientTypeName(const QString &name);
bool hasGradient() const; bool hasGradient() const;
bool locked() const; bool locked() const;
QmlDesigner::ModelNode createGradientNode();
private: private:
QmlDesigner::QmlItemNode m_itemNode; QmlDesigner::QmlItemNode m_itemNode;
QString m_gradientPropertyName; QString m_gradientPropertyName;
QString m_gradientTypeName;
bool m_locked; bool m_locked;
bool hasShapesImport() const;
void ensureShapesImport();
void setupGradientProperties(const QmlDesigner::ModelNode &gradient);
QmlDesigner::Model *model() const;
QmlDesigner::AbstractView *view() const;
}; };
QML_DECLARE_TYPE(GradientModel) QML_DECLARE_TYPE(GradientModel)