forked from qt-creator/qt-creator
QmlDesigner: Add button to component specifics
* Add a button to component specifics for simpler access to the component. Currently it is only possible to access a component via the context menu "Go into Component" or shortcut F2. * Add image template * Fix other templates * Cleanup component specifics and introduce nested sections Task-number: QDS-3062 Task-number: QDS-2358 Change-Id: I6b245b013fbf4b960509b0a357ae62d20e0383cc Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
50405d7153
commit
6a1f51b195
@@ -1,8 +1,11 @@
|
|||||||
|
// Dummy comment to consume the first argument and suppress warnings %1
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: "%1"
|
caption: qsTr("Color")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
ColorEditor {
|
ColorEditor {
|
||||||
backendValue: backendValues.%2
|
backendValue: backendValues.%2
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
// Dummy comment to consume the first argument and suppress warnings %1
|
||||||
|
|
||||||
FontSection {
|
FontSection {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: "%1"
|
caption: qsTr("Font")
|
||||||
fontName: "%2"
|
fontName: "%2"
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
// Dummy comment to consume the first argument and suppress warnings %1
|
||||||
|
|
||||||
|
Section {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
caption: qsTr("Image")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
|
SectionLayout {
|
||||||
|
Label {
|
||||||
|
text: qsTr("Source")
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
UrlChooser {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
backendValue: backendValues.%2_source
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Fill mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
ComboBox {
|
||||||
|
scope: "Image"
|
||||||
|
model: ["Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Tile", "TileVertically", "TileHorizontally", "Pad"]
|
||||||
|
backendValue: backendValues.%2_fillMode
|
||||||
|
implicitWidth: 180
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Source size")
|
||||||
|
disabledState: !backendValues.%2_sourceSize.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
Label {
|
||||||
|
text: "W"
|
||||||
|
width: 12
|
||||||
|
disabledStateSoft: !backendValues.%2_sourceSize_width.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinBox {
|
||||||
|
backendValue: backendValues.%2_sourceSize_width
|
||||||
|
minimumValue: 0
|
||||||
|
maximumValue: 8192
|
||||||
|
decimals: 0
|
||||||
|
enabled: backendValue.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: 4
|
||||||
|
height: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "H"
|
||||||
|
width: 12
|
||||||
|
disabledStateSoft: !backendValues.%2_sourceSize_height.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinBox {
|
||||||
|
backendValue: backendValues.%2_sourceSize_height
|
||||||
|
minimumValue: 0
|
||||||
|
maximumValue: 8192
|
||||||
|
decimals: 0
|
||||||
|
enabled: backendValue.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Horizontal alignment")
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
ComboBox {
|
||||||
|
scope: "Image"
|
||||||
|
model: ["AlignLeft", "AlignRight", "AlignHCenter"]
|
||||||
|
backendValue: backendValues.%2_horizontalAlignment
|
||||||
|
implicitWidth: 180
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Vertical alignment")
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
ComboBox {
|
||||||
|
scope: "Image"
|
||||||
|
model: ["AlignTop", "AlignBottom", "AlignVCenter"]
|
||||||
|
backendValue: backendValues.%2_verticalAlignment
|
||||||
|
implicitWidth: 180
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpandingSpacer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Asynchronous")
|
||||||
|
tooltip: qsTr("Loads images on the local filesystem asynchronously in a separate thread.")
|
||||||
|
disabledState: !backendValues.%2_asynchronous.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_asynchronous.isAvailable
|
||||||
|
text: backendValues.%2_asynchronous.valueToString
|
||||||
|
backendValue: backendValues.%2_asynchronous
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Auto transform")
|
||||||
|
tooltip: qsTr("Automatically applies image transformation metadata such as EXIF orientation.")
|
||||||
|
disabledState: !backendValues.%2_autoTransform.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_autoTransform.isAvailable
|
||||||
|
text: backendValues.%2_autoTransform.valueToString
|
||||||
|
backendValue: backendValues.%2_autoTransform
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Cache")
|
||||||
|
tooltip: qsTr("Caches the image.")
|
||||||
|
disabledState: !backendValues.%2_cache.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_cache.isAvailable
|
||||||
|
text: backendValues.%2_cache.valueToString
|
||||||
|
backendValue: backendValues.%2_cache
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Mipmap")
|
||||||
|
tooltip: qsTr("Uses mipmap filtering when the image is scaled or transformed.")
|
||||||
|
disabledState: !backendValues.%2_mipmap.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_mipmap.isAvailable
|
||||||
|
text: backendValues.%2_mipmap.valueToString
|
||||||
|
backendValue: backendValues.%2_mipmap
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Mirror")
|
||||||
|
tooltip: qsTr("Inverts the image horizontally.")
|
||||||
|
disabledState: !backendValues.%2_mirror.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_mirror.isAvailable
|
||||||
|
text: backendValues.%2_mirror.valueToString
|
||||||
|
backendValue: backendValues.%2_mirror
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Smooth")
|
||||||
|
tooltip: qsTr("Smoothly filters the image when it is scaled or transformed.")
|
||||||
|
disabledState: !backendValues.%2_smooth.isAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondColumnLayout {
|
||||||
|
CheckBox {
|
||||||
|
enabled: backendValues.%2_smooth.isAvailable
|
||||||
|
text: backendValues.%2_smooth.valueToString
|
||||||
|
backendValue: backendValues.%2_smooth
|
||||||
|
implicitWidth: 180
|
||||||
|
}
|
||||||
|
ExpandingSpacer {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
|
// Dummy comment to consume the first argument and suppress warnings %1
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: qsTr("%2 Color")
|
caption: qsTr("Color")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
ColorEditor {
|
ColorEditor {
|
||||||
caption: qsTr("Color")
|
caption: qsTr("Color")
|
||||||
backendValue: backendValues.%2_color
|
backendValue: backendValues.%2_color
|
||||||
supportGradient: true
|
supportGradient: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: qsTr("%2 Border Color")
|
caption: qsTr("Border Color")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
ColorEditor {
|
ColorEditor {
|
||||||
caption: qsTr("Border Color")
|
caption: qsTr("Border Color")
|
||||||
@@ -24,11 +28,12 @@ Section {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: "%2 Rectangle"
|
caption: qsTr("Rectangle")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
SectionLayout {
|
SectionLayout {
|
||||||
rows: 2
|
rows: 2
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
AutoTypes {
|
AutoTypes {
|
||||||
imports: [ "import HelperWidgets 2.0", "import QtQuick 2.1", "import QtQuick.Layouts 1.1" ]
|
imports: [ "import HelperWidgets 2.0", "import QtQuick 2.15", "import QtQuick.Layouts 1.15" ]
|
||||||
|
|
||||||
Type {
|
Type {
|
||||||
typeNames: ["int"]
|
typeNames: ["int"]
|
||||||
@@ -71,4 +71,9 @@ AutoTypes {
|
|||||||
separateSection: true
|
separateSection: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type {
|
||||||
|
typeNames: ["Image"]
|
||||||
|
sourceFile: "ImageEditorTemplate.template"
|
||||||
|
separateSection: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
caption: "%1"
|
caption: qsTr("Text")
|
||||||
|
expanded: false
|
||||||
|
level: 2
|
||||||
|
|
||||||
SectionLayout {
|
SectionLayout {
|
||||||
columns: 2
|
columns: 2
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import StudioControls 1.0 as StudioControls
|
||||||
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
width: parent.width
|
||||||
|
spacing: 10
|
||||||
|
padding: 10
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("This item is an instance of a Component")
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 220
|
||||||
|
}
|
||||||
|
|
||||||
|
StudioControls.AbstractButton {
|
||||||
|
id: testtest
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 180
|
||||||
|
|
||||||
|
buttonIcon: qsTr("Edit Master Component")
|
||||||
|
iconFont: StudioTheme.Constants.font
|
||||||
|
|
||||||
|
onClicked: goIntoComponent()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
import QtQuick 2.1
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.12 as Controls
|
import QtQuick.Controls 2.12 as Controls
|
||||||
import QtQuick.Layouts 1.0
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuickDesignerTheme 1.0
|
import QtQuickDesignerTheme 1.0
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
@@ -35,28 +35,22 @@ Item {
|
|||||||
property int leftPadding: 8
|
property int leftPadding: 8
|
||||||
property int topPadding: 4
|
property int topPadding: 4
|
||||||
property int rightPadding: 0
|
property int rightPadding: 0
|
||||||
|
property int bottomPadding: 4
|
||||||
|
|
||||||
property int animationDuration: 0
|
property int animationDuration: 0
|
||||||
|
|
||||||
property bool expanded: true
|
property bool expanded: true
|
||||||
|
property int level: 0
|
||||||
|
property int levelShift: 10
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: header
|
id: header
|
||||||
height: 20
|
height: 20
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
color: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + (0.2 * level))
|
||||||
Controls.Label {
|
|
||||||
id: label
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: StudioTheme.Values.themeTextColor
|
|
||||||
x: 22
|
|
||||||
font.bold: true
|
|
||||||
font.pixelSize: StudioTheme.Values.myFontSize
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: arrow
|
id: arrow
|
||||||
@@ -64,35 +58,27 @@ Item {
|
|||||||
height: 4
|
height: 4
|
||||||
source: "image://icons/down-arrow"
|
source: "image://icons/down-arrow"
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 4
|
anchors.leftMargin: 4 + (level * levelShift)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Behavior on rotation {
|
Behavior on rotation {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
duration: animationDuration
|
duration: section.animationDuration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Controls.Label {
|
||||||
|
id: label
|
||||||
color: StudioTheme.Values.themeSectionHeadBackground
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: StudioTheme.Values.themeTextColor
|
||||||
Rectangle {
|
x: 22 + (level * levelShift)
|
||||||
visible: false
|
font.bold: true
|
||||||
color:"#333"
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
width: parent.width
|
|
||||||
height: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: false
|
|
||||||
color: "#333"
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
width: parent.width
|
|
||||||
height: 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
section.animationDuration = 120
|
section.animationDuration = 120
|
||||||
@@ -105,22 +91,23 @@ Item {
|
|||||||
|
|
||||||
readonly property alias contentItem: row
|
readonly property alias contentItem: row
|
||||||
|
|
||||||
implicitHeight: Math.round(row.height + header.height + 8)
|
implicitHeight: Math.round(row.height + header.height
|
||||||
|
+ section.topPadding + section.bottomPadding)
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: leftPadding
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: rightPadding
|
|
||||||
anchors.top: header.bottom
|
|
||||||
anchors.topMargin: topPadding
|
|
||||||
id: row
|
id: row
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: section.leftPadding
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: section.rightPadding
|
||||||
|
anchors.top: header.bottom
|
||||||
|
anchors.topMargin: section.topPadding
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
Behavior on implicitHeight {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
duration: animationDuration
|
duration: section.animationDuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ ColorEditor 2.0 ColorEditor.qml
|
|||||||
ColorLine 2.0 ColorLine.qml
|
ColorLine 2.0 ColorLine.qml
|
||||||
ColorLogic 2.0 ColorLogic.qml
|
ColorLogic 2.0 ColorLogic.qml
|
||||||
ComboBox 2.0 ComboBox.qml
|
ComboBox 2.0 ComboBox.qml
|
||||||
|
ComponentButton 2.0 ComponentButton.qml
|
||||||
EditableListView 2.0 EditableListView.qml
|
EditableListView 2.0 EditableListView.qml
|
||||||
ExpandingSpacer 2.0 ExpandingSpacer.qml
|
ExpandingSpacer 2.0 ExpandingSpacer.qml
|
||||||
ExtendedFunctionLogic 2.0 ExtendedFunctionLogic.qml
|
ExtendedFunctionLogic 2.0 ExtendedFunctionLogic.qml
|
||||||
|
|||||||
@@ -180,6 +180,21 @@ void PropertyEditorContextObject::toogleExportAlias()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyEditorContextObject::goIntoComponent()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
|
|
||||||
|
/* Ideally we should not missuse the rewriterView
|
||||||
|
* If we add more code here we have to forward the property editor view */
|
||||||
|
RewriterView *rewriterView = m_model->rewriterView();
|
||||||
|
|
||||||
|
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
|
||||||
|
|
||||||
|
const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||||
|
|
||||||
|
DocumentManager::goIntoComponent(selectedNode);
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void toogleExportAlias();
|
Q_INVOKABLE void toogleExportAlias();
|
||||||
|
|
||||||
|
Q_INVOKABLE void goIntoComponent();
|
||||||
|
|
||||||
Q_INVOKABLE void changeTypeName(const QString &typeName);
|
Q_INVOKABLE void changeTypeName(const QString &typeName);
|
||||||
Q_INVOKABLE void insertKeyframe(const QString &propertyName);
|
Q_INVOKABLE void insertKeyframe(const QString &propertyName);
|
||||||
|
|
||||||
|
|||||||
@@ -551,17 +551,13 @@ inline bool dotPropertyHeuristic(const QmlObjectNode &node, const NodeMetaInfo &
|
|||||||
NodeMetaInfo itemInfo = node.view()->model()->metaInfo("QtQuick.Item");
|
NodeMetaInfo itemInfo = node.view()->model()->metaInfo("QtQuick.Item");
|
||||||
NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text");
|
NodeMetaInfo textInfo = node.view()->model()->metaInfo("QtQuick.Text");
|
||||||
NodeMetaInfo rectangleInfo = node.view()->model()->metaInfo("QtQuick.Rectangle");
|
NodeMetaInfo rectangleInfo = node.view()->model()->metaInfo("QtQuick.Rectangle");
|
||||||
|
NodeMetaInfo imageInfo = node.view()->model()->metaInfo("QtQuick.Image");
|
||||||
|
|
||||||
if (itemInfo.hasProperty(itemProperty))
|
if (typeName == "font"
|
||||||
return false;
|
|| itemInfo.hasProperty(itemProperty)
|
||||||
|
|| textInfo.isSubclassOf(typeName)
|
||||||
if (typeName == "font")
|
|| rectangleInfo.isSubclassOf(typeName)
|
||||||
return false;
|
|| imageInfo.isSubclassOf(typeName))
|
||||||
|
|
||||||
if (textInfo.isSubclassOf(typeName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (rectangleInfo.isSubclassOf(typeName))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -576,92 +572,188 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
|
|||||||
|
|
||||||
const auto nodes = templateConfiguration()->children();
|
const auto nodes = templateConfiguration()->children();
|
||||||
|
|
||||||
QStringList sectorTypes;
|
QStringList allTypes; // all template types
|
||||||
|
QStringList separateSectionTypes; // separate section types only
|
||||||
|
|
||||||
for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
|
for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
|
||||||
if (node->propertyNames().contains("separateSection"))
|
if (node->propertyNames().contains("separateSection"))
|
||||||
sectorTypes.append(variantToStringList(node->property("typeNames")));
|
separateSectionTypes.append(variantToStringList(node->property("typeNames")));
|
||||||
|
|
||||||
|
allTypes.append(variantToStringList(node->property("typeNames")));
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports")));
|
const QList<PropertyName> allProperties = type.propertyNames();
|
||||||
|
|
||||||
QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n');
|
QMap<PropertyName, QList<PropertyName>> propertyMap;
|
||||||
|
QList<PropertyName> separateSectionProperties;
|
||||||
|
|
||||||
qmlTemplate += "Column {\n";
|
// Iterate over all properties and isolate the properties which have their own template
|
||||||
qmlTemplate += "anchors.left: parent.left\n";
|
for (const PropertyName &propertyName : allProperties) {
|
||||||
qmlTemplate += "anchors.right: parent.right\n";
|
if (propertyName.startsWith("__"))
|
||||||
|
|
||||||
QList<PropertyName> orderedList = type.propertyNames();
|
|
||||||
Utils::sort(orderedList, [type, §orTypes](const PropertyName &left, const PropertyName &right){
|
|
||||||
const QString typeNameLeft = QString::fromLatin1(type.propertyTypeName(left));
|
|
||||||
const QString typeNameRight = QString::fromLatin1(type.propertyTypeName(right));
|
|
||||||
if (typeNameLeft == typeNameRight)
|
|
||||||
return left > right;
|
|
||||||
|
|
||||||
if (sectorTypes.contains(typeNameLeft)) {
|
|
||||||
if (sectorTypes.contains(typeNameRight))
|
|
||||||
return left > right;
|
|
||||||
return true;
|
|
||||||
} else if (sectorTypes.contains(typeNameRight)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return left > right;
|
|
||||||
});
|
|
||||||
|
|
||||||
bool emptyTemplate = true;
|
|
||||||
|
|
||||||
bool sectionStarted = false;
|
|
||||||
|
|
||||||
foreach (const PropertyName &name, orderedList) {
|
|
||||||
|
|
||||||
if (name.startsWith("__"))
|
|
||||||
continue; // private API
|
continue; // private API
|
||||||
PropertyName properName = name;
|
|
||||||
|
|
||||||
properName.replace('.', '_');
|
if (!superType.hasProperty(propertyName)
|
||||||
|
&& type.propertyIsWritable(propertyName)
|
||||||
|
&& dotPropertyHeuristic(node, type, propertyName)) {
|
||||||
|
const QString typeName = QString::fromLatin1(type.propertyTypeName(propertyName));
|
||||||
|
|
||||||
TypeName typeName = type.propertyTypeName(name);
|
// Check if a template for the type exists
|
||||||
|
if (allTypes.contains(typeName)) {
|
||||||
|
if (separateSectionTypes.contains(typeName)) { // template enforces separate section
|
||||||
|
separateSectionProperties.append(propertyName);
|
||||||
|
} else {
|
||||||
|
if (propertyName.contains('.')) {
|
||||||
|
const PropertyName parentProperty = propertyName.split('.').first();
|
||||||
|
|
||||||
|
if (propertyMap.contains(parentProperty))
|
||||||
|
propertyMap[parentProperty].append(propertyName);
|
||||||
|
else
|
||||||
|
propertyMap[parentProperty] = { propertyName };
|
||||||
|
} else {
|
||||||
|
if (!propertyMap.contains(propertyName))
|
||||||
|
propertyMap[propertyName] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out the properties which have a basic type e.g. int, string, bool
|
||||||
|
QList<PropertyName> basicProperties;
|
||||||
|
for (auto k : propertyMap.keys()) {
|
||||||
|
if (propertyMap.value(k).empty()) {
|
||||||
|
basicProperties.append(k);
|
||||||
|
propertyMap.remove(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::sort(basicProperties);
|
||||||
|
|
||||||
|
auto findAndFillTemplate = [&nodes, &node, &type](const PropertyName &label,
|
||||||
|
const PropertyName &property) {
|
||||||
|
PropertyName underscoreProperty = property;
|
||||||
|
underscoreProperty.replace('.', '_');
|
||||||
|
|
||||||
|
TypeName typeName = type.propertyTypeName(property);
|
||||||
// alias resolution only possible with instance
|
// alias resolution only possible with instance
|
||||||
if (typeName == "alias" && node.isValid())
|
if (typeName == "alias" && node.isValid())
|
||||||
typeName = node.instanceType(name);
|
typeName = node.instanceType(property);
|
||||||
|
|
||||||
auto nodes = templateConfiguration()->children();
|
QString filledTemplate;
|
||||||
|
for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) {
|
||||||
if (!superType.hasProperty(name) && type.propertyIsWritable(name) && dotPropertyHeuristic(node, type, name)) {
|
// Check if we have a template for the type
|
||||||
|
if (variantToStringList(n->property(QStringLiteral("typeNames"))).contains(QString::fromLatin1(typeName))) {
|
||||||
for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
|
const QString fileName = propertyTemplatesPath() + n->property(QStringLiteral("sourceFile")).toString();
|
||||||
if (variantToStringList(node->property(QStringLiteral("typeNames"))).contains(QString::fromLatin1(typeName))) {
|
|
||||||
const QString fileName = propertyTemplatesPath() + node->property(QStringLiteral("sourceFile")).toString();
|
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
QString source = QString::fromUtf8(file.readAll());
|
QString source = QString::fromUtf8(file.readAll());
|
||||||
file.close();
|
file.close();
|
||||||
const bool section = node->propertyNames().contains("separateSection");
|
filledTemplate = source.arg(QString::fromUtf8(label)).arg(QString::fromUtf8(underscoreProperty));
|
||||||
if (section) {
|
|
||||||
} else if (!sectionStarted) {
|
|
||||||
qmlTemplate += QStringLiteral("Section {\n");
|
|
||||||
qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(QString::fromUtf8(type.simplifiedTypeName()));
|
|
||||||
qmlTemplate += "anchors.left: parent.left\n";
|
|
||||||
qmlTemplate += "anchors.right: parent.right\n";
|
|
||||||
qmlTemplate += QStringLiteral("SectionLayout {\n");
|
|
||||||
sectionStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qmlTemplate += source.arg(QString::fromUtf8(name)).arg(QString::fromUtf8(properName));
|
|
||||||
emptyTemplate = false;
|
|
||||||
} else {
|
} else {
|
||||||
qWarning().nospace() << "template definition source file not found:" << fileName;
|
qWarning().nospace() << "template definition source file not found:" << fileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return filledTemplate;
|
||||||
}
|
};
|
||||||
if (sectionStarted) {
|
|
||||||
qmlTemplate += QStringLiteral("}\n"); //Section
|
// QML specfics preparation
|
||||||
qmlTemplate += QStringLiteral("}\n"); //SectionLayout
|
QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports")));
|
||||||
|
QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n');
|
||||||
|
bool emptyTemplate = true;
|
||||||
|
|
||||||
|
const QString anchorLeftRight = "anchors.left: parent.left\nanchors.right: parent.right\n";
|
||||||
|
const QString paddingLeftTopBottom = "leftPadding: 0\ntopPadding: 0\nbottomPadding: 0\n";
|
||||||
|
|
||||||
|
qmlTemplate += "Column {\n";
|
||||||
|
qmlTemplate += anchorLeftRight;
|
||||||
|
|
||||||
|
if (node.modelNode().isComponent())
|
||||||
|
qmlTemplate += "ComponentButton {}\n";
|
||||||
|
|
||||||
|
qmlTemplate += "Section {\n";
|
||||||
|
qmlTemplate += "caption: \"User added properties\"\n";
|
||||||
|
qmlTemplate += anchorLeftRight;
|
||||||
|
qmlTemplate += paddingLeftTopBottom;
|
||||||
|
qmlTemplate += "Column {\n";
|
||||||
|
qmlTemplate += "width: parent.width\n";
|
||||||
|
|
||||||
|
// First the section containing properties of basic type e.g. int, string, bool
|
||||||
|
if (!basicProperties.empty()) {
|
||||||
|
emptyTemplate = false;
|
||||||
|
|
||||||
|
qmlTemplate += "Column {\n";
|
||||||
|
qmlTemplate += "width: parent.width\n";
|
||||||
|
qmlTemplate += "leftPadding: 8\n";
|
||||||
|
qmlTemplate += "rightPadding: 0\n";
|
||||||
|
qmlTemplate += "topPadding: 4\n";
|
||||||
|
qmlTemplate += "bottomPadding: 4\n";
|
||||||
|
qmlTemplate += "SectionLayout {\n";
|
||||||
|
|
||||||
|
for (const auto &p : qAsConst(basicProperties))
|
||||||
|
qmlTemplate += findAndFillTemplate(p, p);
|
||||||
|
|
||||||
|
qmlTemplate += "}\n"; // SectionLayout
|
||||||
|
qmlTemplate += "}\n"; // Column
|
||||||
}
|
}
|
||||||
|
|
||||||
qmlTemplate += "}\n";
|
// Second the section containing properties of complex type for which no specific template exists e.g. Button
|
||||||
|
if (!propertyMap.empty()) {
|
||||||
|
emptyTemplate = false;
|
||||||
|
for (const auto &k : propertyMap.keys()) {
|
||||||
|
TypeName parentTypeName = type.propertyTypeName(k);
|
||||||
|
// alias resolution only possible with instance
|
||||||
|
if (parentTypeName == "alias" && node.isValid())
|
||||||
|
parentTypeName = node.instanceType(k);
|
||||||
|
|
||||||
|
qmlTemplate += "Section {\n";
|
||||||
|
qmlTemplate += QStringLiteral("caption: \"%1 - %2\"\n").arg(QString::fromUtf8(k)).arg(QString::fromUtf8(parentTypeName));
|
||||||
|
qmlTemplate += anchorLeftRight;
|
||||||
|
qmlTemplate += "expanded: false\n";
|
||||||
|
qmlTemplate += "level: 1\n";
|
||||||
|
qmlTemplate += "SectionLayout {\n";
|
||||||
|
|
||||||
|
auto properties = propertyMap.value(k);
|
||||||
|
Utils::sort(properties);
|
||||||
|
|
||||||
|
for (const auto &p : qAsConst(properties)) {
|
||||||
|
const PropertyName shortName = p.contains('.') ? p.split('.').last() : p;
|
||||||
|
qmlTemplate += findAndFillTemplate(shortName, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
qmlTemplate += "}\n"; // SectionLayout
|
||||||
|
qmlTemplate += "}\n"; // Section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third the section containing properties of complex type for which a specific template exists e.g. Rectangle, Image
|
||||||
|
if (!separateSectionProperties.empty()) {
|
||||||
|
emptyTemplate = false;
|
||||||
|
Utils::sort(separateSectionProperties);
|
||||||
|
for (const auto &p : qAsConst(separateSectionProperties)) {
|
||||||
|
TypeName parentTypeName = type.propertyTypeName(p);
|
||||||
|
// alias resolution only possible with instance
|
||||||
|
if (parentTypeName == "alias" && node.isValid())
|
||||||
|
parentTypeName = node.instanceType(p);
|
||||||
|
|
||||||
|
qmlTemplate += "Section {\n";
|
||||||
|
qmlTemplate += QStringLiteral("caption: \"%1 - %2\"\n").arg(QString::fromUtf8(p)).arg(QString::fromUtf8(parentTypeName));
|
||||||
|
qmlTemplate += anchorLeftRight;
|
||||||
|
qmlTemplate += paddingLeftTopBottom;
|
||||||
|
qmlTemplate += "level: 1\n";
|
||||||
|
qmlTemplate += "Column {\n";
|
||||||
|
qmlTemplate += "width: parent.width\n";
|
||||||
|
|
||||||
|
qmlTemplate += findAndFillTemplate(p, p);
|
||||||
|
|
||||||
|
qmlTemplate += "}\n"; // Column
|
||||||
|
qmlTemplate += "}\n"; // Section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qmlTemplate += "}\n"; // Column
|
||||||
|
qmlTemplate += "}\n"; // Section
|
||||||
|
qmlTemplate += "}\n"; // Column
|
||||||
|
|
||||||
if (emptyTemplate)
|
if (emptyTemplate)
|
||||||
return QString();
|
return QString();
|
||||||
|
|||||||
Reference in New Issue
Block a user