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 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
|
||||||
|
@@ -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 gradientPropertyName: gradientModel.gradientPropertyName
|
||||||
|
property alias gradientTypeName: gradientModel.gradientTypeName
|
||||||
|
|
||||||
onHasGradientChanged: {
|
onHasGradientChanged: {
|
||||||
colorLine.invalidate()
|
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 "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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user