forked from qt-creator/qt-creator
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:
@@ -26,7 +26,8 @@
|
||||
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
|
||||
|
||||
Column {
|
||||
id: colorEditor
|
||||
@@ -45,19 +46,17 @@ Column {
|
||||
|
||||
property alias gradientPropertyName: gradientLine.gradientPropertyName
|
||||
|
||||
property bool shapeGradients: false
|
||||
|
||||
property alias transparent: transparentButton.checked
|
||||
|
||||
function isNotInGradientMode() {
|
||||
return (buttonRow.checkedIndex !== 1)
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
colorEditor.color = colorEditor.value
|
||||
}
|
||||
onValueChanged: colorEditor.color = colorEditor.value
|
||||
|
||||
onBackendValueChanged: {
|
||||
colorEditor.color = colorEditor.value
|
||||
}
|
||||
onBackendValueChanged: colorEditor.color = colorEditor.value
|
||||
|
||||
Timer {
|
||||
id: colorEditorTimer
|
||||
@@ -87,7 +86,13 @@ Column {
|
||||
|
||||
GradientLine {
|
||||
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
|
||||
|
||||
width: parent.width
|
||||
@@ -102,7 +107,22 @@ Column {
|
||||
return
|
||||
|
||||
if (gradientLine.hasGradient) {
|
||||
if (colorEditor.shapeGradients) {
|
||||
switch (gradientLine.gradientTypeName) {
|
||||
case "LinearGradient":
|
||||
buttonRow.initalChecked = 1
|
||||
break;
|
||||
case "RadialGradient":
|
||||
buttonRow.initalChecked = 2
|
||||
break;
|
||||
case "ConicalGradient":
|
||||
buttonRow.initalChecked = 3
|
||||
break;
|
||||
default:
|
||||
buttonRow.initalChecked = 1
|
||||
}
|
||||
}
|
||||
|
||||
colorEditor.color = gradientLine.currentColor
|
||||
} else {
|
||||
buttonRow.initalChecked = 0
|
||||
@@ -155,6 +175,11 @@ Column {
|
||||
|
||||
SecondColumnLayout {
|
||||
|
||||
ColorCheckButton {
|
||||
id: checkButton
|
||||
color: colorEditor.color
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
enabled: !colorEditor.transparent
|
||||
id: textField
|
||||
@@ -181,10 +206,6 @@ Column {
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ColorCheckButton {
|
||||
id: checkButton
|
||||
color: colorEditor.color
|
||||
}
|
||||
|
||||
ButtonRow {
|
||||
|
||||
@@ -193,6 +214,7 @@ Column {
|
||||
|
||||
ButtonRowButton {
|
||||
iconSource: "images/icon_color_solid.png"
|
||||
|
||||
onClicked: {
|
||||
gradientLine.deleteGradient()
|
||||
textField.text = colorEditor.color
|
||||
@@ -205,10 +227,245 @@ Column {
|
||||
iconSource: "images/icon_color_gradient.png"
|
||||
onClicked: {
|
||||
colorEditor.backendValue.resetValue()
|
||||
if (colorEditor.shapeGradients) {
|
||||
gradientLine.deleteGradient()
|
||||
gradientLine.gradientTypeName = "LinearGradient"
|
||||
}
|
||||
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 {
|
||||
id: transparentButton
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -38,6 +38,7 @@ Item {
|
||||
|
||||
|
||||
property alias gradientPropertyName: gradientModel.gradientPropertyName
|
||||
property alias gradientTypeName: gradientModel.gradientTypeName
|
||||
|
||||
onHasGradientChanged: {
|
||||
colorLine.invalidate()
|
||||
|
@@ -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")
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 670 B |
Binary file not shown.
After Width: | Height: | Size: 677 B |
@@ -28,6 +28,7 @@
|
||||
#include "qmlanchorbindingproxy.h"
|
||||
#include "propertyeditorview.h"
|
||||
|
||||
#include <exception.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <variantproperty.h>
|
||||
@@ -35,8 +36,11 @@
|
||||
#include <nodemetainfo.h>
|
||||
#include <rewritertransaction.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
GradientModel::GradientModel(QObject *parent) :
|
||||
QAbstractListModel(parent), m_locked(false)
|
||||
,m_gradientTypeName("Gradient")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -139,38 +143,38 @@ void GradientModel::addGradient()
|
||||
return;
|
||||
|
||||
if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
|
||||
try {
|
||||
|
||||
QColor color = m_itemNode.instanceValue("color").value<QColor>();
|
||||
|
||||
if (!color.isValid())
|
||||
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);
|
||||
|
||||
|
||||
QmlDesigner::ModelNode gradientStopNode =
|
||||
m_itemNode.modelNode().view()->createModelNode("QtQuick.GradientStop",
|
||||
m_itemNode.modelNode().view()->majorQtQuickVersion(), 0);
|
||||
QmlDesigner::ModelNode gradientStopNode = view()->createModelNode("QtQuick.GradientStop", view()->majorQtQuickVersion(), 0);
|
||||
gradientStopNode.variantProperty("position").setValue(0.0);
|
||||
gradientStopNode.variantProperty("color").setValue(color);
|
||||
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
|
||||
|
||||
gradientStopNode = m_itemNode.modelNode().view()->createModelNode(
|
||||
"QtQuick.GradientStop",
|
||||
m_itemNode.modelNode().view()->majorQtQuickVersion(), 0);
|
||||
gradientStopNode = view()->createModelNode("QtQuick.GradientStop", view()->majorQtQuickVersion(), 0);
|
||||
gradientStopNode.variantProperty("position").setValue(1.0);
|
||||
gradientStopNode.variantProperty("color").setValue(QColor(Qt::black));
|
||||
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
|
||||
|
||||
} catch (const QmlDesigner::Exception &e) {
|
||||
e.showException();
|
||||
}
|
||||
|
||||
}
|
||||
setupModel();
|
||||
|
||||
emit hasGradientChanged();
|
||||
emit gradientTypeChanged();
|
||||
}
|
||||
|
||||
void GradientModel::setColor(int index, const QColor &color)
|
||||
@@ -231,7 +235,7 @@ qreal GradientModel::getPosition(int index) const
|
||||
void GradientModel::removeStop(int index)
|
||||
{
|
||||
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::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index);
|
||||
if (stop.isValid()) {
|
||||
@@ -255,7 +259,7 @@ void GradientModel::deleteGradient()
|
||||
|
||||
if (m_itemNode.isInBaseState()) {
|
||||
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();
|
||||
if (QmlDesigner::QmlObjectNode(gradientNode).isValid())
|
||||
QmlDesigner::QmlObjectNode(gradientNode).destroy();
|
||||
@@ -263,6 +267,7 @@ void GradientModel::deleteGradient()
|
||||
}
|
||||
|
||||
emit hasGradientChanged();
|
||||
emit gradientTypeChanged();
|
||||
}
|
||||
|
||||
void GradientModel::lock()
|
||||
@@ -280,6 +285,22 @@ void GradientModel::registerDeclarativeType()
|
||||
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()
|
||||
{
|
||||
m_locked = true;
|
||||
@@ -299,12 +320,17 @@ void GradientModel::setAnchorBackend(const QVariant &anchorBackend)
|
||||
if (backendCasted)
|
||||
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();
|
||||
|
||||
m_locked = true;
|
||||
|
||||
emit anchorBackendChanged();
|
||||
emit hasGradientChanged();
|
||||
emit gradientTypeChanged();
|
||||
|
||||
m_locked = false;
|
||||
}
|
||||
@@ -319,6 +345,16 @@ void GradientModel::setGradientPropertyName(const QString &name)
|
||||
m_gradientPropertyName = name;
|
||||
}
|
||||
|
||||
QString GradientModel::gradientTypeName() const
|
||||
{
|
||||
return m_gradientTypeName;
|
||||
}
|
||||
|
||||
void GradientModel::setGradientTypeName(const QString &name)
|
||||
{
|
||||
m_gradientTypeName = name;
|
||||
}
|
||||
|
||||
bool GradientModel::hasGradient() const
|
||||
{
|
||||
return m_itemNode.isValid()
|
||||
@@ -330,10 +366,114 @@ bool GradientModel::locked() const
|
||||
if (m_locked)
|
||||
return true;
|
||||
|
||||
auto view = qobject_cast<QmlDesigner::PropertyEditorView*>(m_itemNode.view());
|
||||
auto editorView = qobject_cast<QmlDesigner::PropertyEditorView*>(view());
|
||||
|
||||
if (view && view->locked())
|
||||
return true;
|
||||
return editorView && editorView->locked();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ class GradientModel : public QAbstractListModel
|
||||
|
||||
Q_PROPERTY(QVariant anchorBackendProperty READ anchorBackend WRITE setAnchorBackend NOTIFY anchorBackendChanged)
|
||||
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(bool hasGradient READ hasGradient NOTIFY hasGradientChanged)
|
||||
|
||||
@@ -65,9 +66,14 @@ public:
|
||||
|
||||
static void registerDeclarativeType();
|
||||
|
||||
Q_INVOKABLE qreal readGradientProperty(const QString &property) const;
|
||||
|
||||
Q_INVOKABLE void setGradientProperty(const QString &propertyName, qreal value);
|
||||
|
||||
signals:
|
||||
void anchorBackendChanged();
|
||||
void hasGradientChanged();
|
||||
void gradientTypeChanged();
|
||||
|
||||
private:
|
||||
void setupModel();
|
||||
@@ -75,14 +81,22 @@ private:
|
||||
QVariant anchorBackend() const {return QVariant(); }
|
||||
QString gradientPropertyName() const;
|
||||
void setGradientPropertyName(const QString &name);
|
||||
QString gradientTypeName() const;
|
||||
void setGradientTypeName(const QString &name);
|
||||
bool hasGradient() const;
|
||||
bool locked() const;
|
||||
QmlDesigner::ModelNode createGradientNode();
|
||||
|
||||
private:
|
||||
QmlDesigner::QmlItemNode m_itemNode;
|
||||
QString m_gradientPropertyName;
|
||||
QString m_gradientTypeName;
|
||||
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)
|
||||
|
Reference in New Issue
Block a user