aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml2
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml5
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml2
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp6
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h5
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp2
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml62
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml95
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimationSection.qml20
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/BorderImageSpecifics.qml68
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ColorAnimationSpecifics.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GridSpecifics.qml25
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ImageSpecifics.qml132
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml29
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml193
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/NumberAnimationSpecifics.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/PropertyAnimationSpecifics.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TextInputSection.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml60
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml72
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml96
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml137
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttfbin10568 -> 12576 bytes
-rwxr-xr-xshare/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir2
-rw-r--r--src/libs/advanceddockingsystem/ads_globals.h9
-rw-r--r--src/libs/advanceddockingsystem/dockareatitlebar.cpp5
-rw-r--r--src/libs/advanceddockingsystem/dockwidgettab.cpp16
-rw-r--r--src/libs/advanceddockingsystem/iconprovider.cpp2
-rw-r--r--src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp24
-rw-r--r--src/libs/utils/stylehelper.cpp45
-rw-r--r--src/libs/utils/stylehelper.h3
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h12
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp99
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp33
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h8
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp133
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h3
-rw-r--r--src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp9
-rw-r--r--src/plugins/qmldesigner/components/componentcore/selectioncontext.h13
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.cpp46
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.h86
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp29
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h1
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp11
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditor.pri6
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp561
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.h38
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp170
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizemanipulator.h3
-rw-r--r--src/plugins/qmldesigner/components/formeditor/resizetool.cpp3
-rw-r--r--src/plugins/qmldesigner/components/formeditor/transitiontool.cpp438
-rw-r--r--src/plugins/qmldesigner/components/formeditor/transitiontool.h98
-rw-r--r--src/plugins/qmldesigner/components/importmanager/importmanagerview.cpp8
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp29
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp37
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp12
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp5
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp33
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.h4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp11
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp41
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp23
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h5
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp59
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp56
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltimeline.cpp9
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp9
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp32
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp7
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs2
84 files changed, 2922 insertions, 451 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml
index 7481d24225..7ae7bd44d9 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml
@@ -121,7 +121,7 @@ View3D {
pick(mouse);
if (pickObj) {
axisHelperView.editCameraCtrl.focusObject(axisHelperView.selectedNode,
- pickObj.cameraRotation, false);
+ pickObj.cameraRotation, false, false);
} else {
mouse.accepted = false;
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
index 207dc94199..20dd112d61 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
@@ -87,14 +87,15 @@ Item {
}
- function focusObject(targetObject, rotation, updateZoom)
+ function focusObject(targetObject, rotation, updateZoom, closeUp)
{
if (!camera)
return;
camera.eulerRotation = rotation;
var newLookAtAndZoom = _generalHelper.focusObjectToCamera(
- camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor, updateZoom);
+ camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor,
+ updateZoom, closeUp);
_lookAtPoint = newLookAtAndZoom.toVector3d();
_zoomFactor = newLookAtAndZoom.w;
storeCameraState(0);
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
index db8d4fb4ea..6527d06e6e 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
@@ -146,7 +146,7 @@ Item {
if (editView) {
var targetNode = selectionBoxes.length > 0
? selectionBoxes[0].model : null;
- cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true);
+ cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true, false);
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml
index b16b27406d..afaf8481ca 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml
@@ -42,7 +42,7 @@ Item {
function fitAndHideBox() : bool
{
- cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true);
+ cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true, true);
if (cameraControl._zoomFactor < 0.1) {
view3D.importScene.scale = view3D.importScene.scale.times(10);
return false;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
index f99d219c5c..f62a7e5173 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
@@ -148,7 +148,7 @@ float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float de
// Return value contains new lookAt point (xyz) and zoom factor (w)
QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
- float oldZoom, bool updateZoom)
+ float oldZoom, bool updateZoom, bool closeUp)
{
if (!camera)
return QVector4D(0.f, 0.f, 0.f, 1.f);
@@ -200,7 +200,9 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau
camera->setPosition(lookAt + newLookVector);
- float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 900.), 100.f) : oldZoom;
+ qreal divisor = closeUp ? 900. : 725.;
+
+ float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / divisor), 100.f) : oldZoom;
float cameraZoomFactor = zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false);
return QVector4D(lookAt, cameraZoomFactor);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
index e9d8e52545..15795ac28b 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
@@ -66,8 +66,9 @@ public:
float defaultLookAtDistance, const QVector3D &lookAt,
float zoomFactor, bool relative);
Q_INVOKABLE QVector4D focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
- QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
- float oldZoom, bool updateZoom = true);
+ QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
+ float oldZoom, bool updateZoom = true,
+ bool closeUp = false);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
index 87e0cc4d71..e018e7bf31 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
@@ -768,6 +768,8 @@ QObject *ObjectNodeInstance::createComponent(const QString &componentPath, QQmlC
qWarning() << error;
}
+ object->setProperty("__designer_url__", QUrl::fromLocalFile(componentPath));
+
return object;
}
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
index 37f9712678..cd3ddef34d 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
@@ -47,6 +47,8 @@ Item {
width: itemLibraryIconWidth // to be set in Qml context
height: itemLibraryIconHeight // to be set in Qml context
source: itemLibraryIconPath // to be set by model
+
+ cache: false // Allow thumbnail to be dynamically updated
}
Text {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
index 4eb7420d74..5434e4705b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
@@ -100,14 +100,17 @@ Section {
}
Label {
- text: "State"
+ text: qsTr("State")
}
SecondColumnLayout {
- LineEdit {
+
+ ComboBox {
+ Layout.fillWidth: true
backendValue: backendValues.state
- showTranslateCheckBox: false
- enabled: anchorBackend.hasParent || isBaseState
+ model: allStateNames
+ valueType: ComboBox.String
}
+
ExpandingSpacer {
}
}
@@ -158,5 +161,56 @@ Section {
}
}
+ Label {
+ text: qsTr("Focus")
+ tooltip: qsTr("Holds whether the item has focus within the enclosing FocusScope.")
+ disabledState: !backendValues.focus.isAvailable
+ }
+ SecondColumnLayout {
+ CheckBox {
+ backendValue: backendValues.focus
+ text: backendValues.focus.valueToString
+ enabled: backendValues.focus.isAvailable
+ implicitWidth: 180
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Active focus on tab")
+ tooltip: qsTr("Holds whether the item wants to be in the tab focus chain.")
+ disabledState: !backendValues.activeFocusOnTab.isAvailable
+ }
+ SecondColumnLayout {
+ CheckBox {
+ backendValue: backendValues.activeFocusOnTab
+ text: backendValues.activeFocusOnTab.valueToString
+ enabled: backendValues.activeFocusOnTab.isAvailable
+ implicitWidth: 180
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Baseline offset")
+ tooltip: qsTr("Specifies the position of the item's baseline in local coordinates.")
+ disabledState: !backendValues.baselineOffset.isAvailable
+ }
+ SecondColumnLayout {
+ SpinBox {
+ sliderIndicatorVisible: true
+ backendValue: backendValues.baselineOffset
+ hasSlider: true
+ decimals: 0
+ minimumValue: -1000
+ maximumValue: 1000
+ Layout.preferredWidth: 140
+ enabled: backendValues.baselineOffset.isAvailable
+ }
+ ExpandingSpacer {
+ }
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml
new file mode 100644
index 0000000000..787e390cbd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 HelperWidgets 2.0
+import QtQuick.Layouts 1.0
+
+Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ ImageSpecifics {
+ }
+
+ Section {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Animated Image")
+
+ SectionLayout {
+ Label {
+ text: qsTr("Speed")
+ disabledState: !backendValues.speed.isAvailable
+ }
+ SecondColumnLayout {
+ SpinBox {
+ sliderIndicatorVisible: true
+ backendValue: backendValues.speed
+ hasSlider: true
+ decimals: 2
+ minimumValue: 0
+ maximumValue: 100
+ Layout.preferredWidth: 140
+ enabled: backendValues.speed.isAvailable
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Paused")
+ tooltip: qsTr("Holds whether the animated image is paused.")
+ disabledState: !backendValues.paused.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.paused.isAvailable
+ text: backendValues.paused.valueToString
+ backendValue: backendValues.paused
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Playing")
+ tooltip: qsTr("Holds whether the animated image is playing.")
+ disabledState: !backendValues.playing.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.playing.isAvailable
+ text: backendValues.playing.valueToString
+ backendValue: backendValues.playing
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimationSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimationSection.qml
index 9641d74b1b..abf69756fa 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimationSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimationSection.qml
@@ -26,6 +26,8 @@
import HelperWidgets 2.0
import QtQuick 2.1
import QtQuick.Layouts 1.1
+import StudioTheme 1.0 as StudioTheme
+
Section {
id: section
caption: qsTr("Animation")
@@ -33,6 +35,7 @@ Section {
anchors.right: parent.right
property bool showDuration: true
+ property bool showEasingCurve: false
SectionLayout {
Label {
@@ -100,5 +103,22 @@ Section {
text: backendValues.alwaysRunToEnd.valueToString
backendValue: backendValues.alwaysRunToEnd
}
+
+ Label {
+ visible: section.showEasingCurve
+ text: qsTr("Easing Curve")
+ tooltip: qsTr("Define custom easing curve")
+ }
+
+ BoolButtonRowButton {
+ visible: section.showEasingCurve
+ buttonIcon: StudioTheme.Constants.curveDesigner
+ EasingCurveEditor {
+ id: easingCurveEditor
+ modelNodeBackendProperty: modelNodeBackend
+ }
+ onClicked: easingCurveEditor.runDialog()
+
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/BorderImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/BorderImageSpecifics.qml
index 3d39d44e8f..362ba144c5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/BorderImageSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/BorderImageSpecifics.qml
@@ -124,7 +124,7 @@ Column {
}
Label {
- text: qsTr("Horizontal Fill mode")
+ text: qsTr("Horizontal Tile mode")
}
SecondColumnLayout {
@@ -138,7 +138,7 @@ Column {
}
Label {
- text: qsTr("Vertical Fill mode")
+ text: qsTr("Vertical Tile mode")
}
SecondColumnLayout {
@@ -186,6 +186,70 @@ Column {
}
}
+
+ Label {
+ text: qsTr("Mirror")
+ tooltip: qsTr("Specifies whether the image should be horizontally inverted.")
+ disabledState: !backendValues.mirror.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.mirror.isAvailable
+ text: backendValues.mirror.valueToString
+ backendValue: backendValues.mirror
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Smooth")
+ tooltip: qsTr("Specifies whether the image is smoothly filtered when scaled or transformed.")
+ disabledState: !backendValues.smooth.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.smooth.isAvailable
+ text: backendValues.smooth.valueToString
+ backendValue: backendValues.smooth
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Cache")
+ tooltip: qsTr("Specifies whether the image should be cached.")
+ disabledState: !backendValues.cache.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.cache.isAvailable
+ text: backendValues.cache.valueToString
+ backendValue: backendValues.cache
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Asynchronous")
+ tooltip: qsTr("Specifies that images on the local filesystem should be loaded asynchronously in a separate thread.")
+ disabledState: !backendValues.asynchronous.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.asynchronous.isAvailable
+ text: backendValues.asynchronous.valueToString
+ backendValue: backendValues.asynchronous
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ColorAnimationSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ColorAnimationSpecifics.qml
index 26a38d4211..398515b7e0 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ColorAnimationSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ColorAnimationSpecifics.qml
@@ -57,6 +57,7 @@ Column {
}
AnimationSection {
+ showEasingCurve: true
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GridSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GridSpecifics.qml
index 37be5e5770..284849a415 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GridSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GridSpecifics.qml
@@ -95,7 +95,32 @@ Column {
Layout.fillWidth: true
scope: "Qt"
}
+ }
+ Label {
+ text: qsTr("Horizontal item alignment")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ model: ["AlignLeft", "AlignRight" ,"AlignHCenter"]
+ backendValue: backendValues.horizontalItemAlignment
+ Layout.fillWidth: true
+ scope: "Grid"
+ }
+ }
+
+ Label {
+ text: qsTr("Vertical item alignment")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ model: ["AlignTop", "AlignBottom" ,"AlignVCenter"]
+ backendValue: backendValues.verticalItemAlignment
+ Layout.fillWidth: true
+ scope: "Grid"
+ }
}
Label {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ImageSpecifics.qml
index 8f742f06e2..60b97a1179 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ImageSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ImageSpecifics.qml
@@ -58,7 +58,7 @@ Column {
SecondColumnLayout {
ComboBox {
scope: "Image"
- model: ["Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Tile", "TileVertically", "TileHorizontally"]
+ model: ["Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Tile", "TileVertically", "TileHorizontally", "Pad"]
backendValue: backendValues.fillMode
implicitWidth: 180
Layout.fillWidth: true
@@ -105,6 +105,136 @@ Column {
ExpandingSpacer {
}
}
+
+ Label {
+ text: qsTr("Horizontal alignment")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ scope: "Image"
+ model: ["AlignLeft", "AlignRight", "AlignHCenter"]
+ backendValue: backendValues.horizontalAlignment
+ implicitWidth: 180
+ Layout.fillWidth: true
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Vertical alignment")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ scope: "Image"
+ model: ["AlignTop", "AlignBottom", "AlignVCenter"]
+ backendValue: backendValues.verticalAlignment
+ implicitWidth: 180
+ Layout.fillWidth: true
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Asynchronous")
+ tooltip: qsTr("Specifies that images on the local filesystem should be loaded asynchronously in a separate thread.")
+ disabledState: !backendValues.asynchronous.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.asynchronous.isAvailable
+ text: backendValues.asynchronous.valueToString
+ backendValue: backendValues.asynchronous
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Auto transform")
+ tooltip: qsTr("Specifies whether the image should automatically apply image transformation metadata such as EXIF orientation.")
+ disabledState: !backendValues.autoTransform.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.autoTransform.isAvailable
+ text: backendValues.autoTransform.valueToString
+ backendValue: backendValues.autoTransform
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Cache")
+ tooltip: qsTr("Specifies whether the image should be cached.")
+ disabledState: !backendValues.cache.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.cache.isAvailable
+ text: backendValues.cache.valueToString
+ backendValue: backendValues.cache
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Mipmap")
+ tooltip: qsTr("Specifies whether the image uses mipmap filtering when scaled or transformed.")
+ disabledState: !backendValues.mipmap.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.mipmap.isAvailable
+ text: backendValues.mipmap.valueToString
+ backendValue: backendValues.mipmap
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Mirror")
+ tooltip: qsTr("Specifies whether the image should be horizontally inverted.")
+ disabledState: !backendValues.mirror.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.mirror.isAvailable
+ text: backendValues.mirror.valueToString
+ backendValue: backendValues.mirror
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
+
+ Label {
+ text: qsTr("Smooth")
+ tooltip: qsTr("Specifies whether the image is smoothly filtered when scaled or transformed.")
+ disabledState: !backendValues.smooth.isAvailable
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ enabled: backendValues.smooth.isAvailable
+ text: backendValues.smooth.valueToString
+ backendValue: backendValues.smooth
+ implicitWidth: 180
+ }
+ ExpandingSpacer {}
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
index 2a05bb6622..41abe776ce 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
@@ -325,13 +325,11 @@ Rectangle {
frameVisible: false
id: tabView
- height: Math.max(layoutSectionHeight, specficsHeight)
+ height: Math.max(layoutSectionHeight, specficsHeight, advancedHeight) + extraHeight
- property int layoutSectionHeight: 400
- property int specficsOneHeight: 0
- property int specficsTwoHeight: 0
-
- property int specficsHeight: Math.max(specficsOneHeight, specficsTwoHeight)
+ property int advancedHeight: 0
+ property int layoutSectionHeight: 0
+ property int specficsHeight: 0
property int extraHeight: 40
@@ -341,6 +339,9 @@ Rectangle {
component: Column {
anchors.left: parent.left
anchors.right: parent.right
+
+ onImplicitHeightChanged: tabView.specficsHeight = implicitHeight
+
Loader {
anchors.left: parent.left
anchors.right: parent.right
@@ -355,13 +356,6 @@ Rectangle {
active = false
active = true
}
-
- property int loaderHeight: specificsTwo.item.height + tabView.extraHeight
- onLoaderHeightChanged: tabView.specficsTwoHeight = loaderHeight
-
- onLoaded: {
- tabView.specficsTwoHeight = loaderHeight
- }
}
Loader {
@@ -387,11 +381,9 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
+ onImplicitHeightChanged: tabView.layoutSectionHeight = implicitHeight
+
LayoutSection {
- property int childRectHeight: childrenRect.height
- onChildRectHeightChanged: {
- tabView.layoutSectionHeight = childRectHeight + tabView.extraHeight
- }
}
MarginSection {
@@ -720,6 +712,9 @@ Rectangle {
component: Column {
anchors.left: parent.left
anchors.right: parent.right
+
+ onImplicitHeightChanged: tabView.advancedHeight = implicitHeight
+
AdvancedSection {
}
LayerSection {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
index 71ff0260ba..0ca7f3d888 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
@@ -54,7 +54,7 @@ Column {
}
Label {
- text: qsTr("Hover Enabled")
+ text: qsTr("Hover enabled")
tooltip: qsTr("This property holds whether hover events are handled.")
}
@@ -68,6 +68,197 @@ Column {
ExpandingSpacer {
}
}
+
+ Label {
+ text: qsTr("Accepted buttons")
+ tooltip: qsTr("This property holds the mouse buttons that the mouse area reacts to.")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ backendValue: backendValues.acceptedButtons
+ model: ["LeftButton", "RightButton", "MiddleButton", "BackButton", "ForwardButton", "AllButtons"]
+ Layout.fillWidth: true
+ scope: "Qt"
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Press and hold interval")
+ tooltip: qsTr("This property overrides the elapsed time in milliseconds before pressAndHold is emitted.")
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ backendValue: backendValues.pressAndHoldInterval
+ minimumValue: 0
+ maximumValue: 2000
+ decimals: 0
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Scroll gesture enabled")
+ tooltip: qsTr("This property controls whether this MouseArea responds to scroll gestures from non-mouse devices.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.scrollGestureEnabled
+ text: backendValues.scrollGestureEnabled.valueToString
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Cursor shape")
+ tooltip: qsTr("This property holds the cursor shape for this mouse area.")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ backendValue: backendValues.cursorShape
+ model: ["ArrowCursor", "UpArrowCursor", "CrossCursor", "WaitCursor",
+ "IBeamCursor", "SizeVerCursor", "SizeHorCursor", "SizeBDiagCursor",
+ "SizeFDiagCursor", "SizeAllCursor", "BlankCursor", "SplitVCursor",
+ "SplitHCursor", "PointingHandCursor", "ForbiddenCursor", "WhatsThisCursor",
+ "BusyCursor", "OpenHandCursor", "ClosedHandCursor", "DragCopyCursor",
+ "DragMoveCursor", "DragLinkCursor"]
+ Layout.fillWidth: true
+ scope: "Qt"
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Prevent stealing")
+ tooltip: qsTr("This property controls whether the mouse events may be stolen from this MouseArea.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.preventStealing
+ text: backendValues.preventStealing.valueToString
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Propagate composed events")
+ tooltip: qsTr("This property controls whether composed mouse events will automatically propagate to other MouseAreas.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.propagateComposedEvents
+ text: backendValues.propagateComposedEvents.valueToString
+ }
+
+ ExpandingSpacer {
+ }
+ }
+ }
+ }
+
+ Section {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Drag")
+
+ SectionLayout {
+ Label {
+ text: qsTr("Target")
+ tooltip: qsTr("Sets the id of the item to drag.")
+ }
+ SecondColumnLayout {
+ ItemFilterComboBox {
+ typeFilter: "QtQuick.QtObject"
+ validator: RegExpValidator { regExp: /(^$|^[a-z_]\w*)/ }
+ backendValue: backendValues.drag_target
+ Layout.fillWidth: true
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Axis")
+ tooltip: qsTr("Specifies whether dragging can be done horizontally, vertically, or both.")
+ }
+ SecondColumnLayout {
+ ComboBox {
+ scope: "Drag"
+ model: ["XAxis", "YAxis", "XAndYAxis"]
+ backendValue: backendValues.drag_axis
+ Layout.fillWidth: true
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Filter children")
+ tooltip: qsTr("Specifies whether a drag overrides descendant MouseAreas.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.drag_filterChildren
+ text: backendValues.drag_filterChildren.valueToString
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Threshold")
+ tooltip: qsTr("Determines the threshold in pixels of when the drag operation should start.")
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ backendValue: backendValues.drag_threshold
+ minimumValue: 0
+ maximumValue: 5000
+ decimals: 0
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Smoothed")
+ tooltip: qsTr("If set to true, the target will be moved only after the drag operation has started.\n"
+ + "If set to false, the target will be moved straight to the current mouse position.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.drag_smoothed
+ text: backendValues.drag_smoothed.valueToString
+ }
+
+ ExpandingSpacer {
+ }
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/NumberAnimationSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/NumberAnimationSpecifics.qml
index 19f159526b..f6cbab67db 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/NumberAnimationSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/NumberAnimationSpecifics.qml
@@ -79,6 +79,7 @@ Column {
}
AnimationSection {
+ showEasingCurve: true
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/PropertyAnimationSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/PropertyAnimationSpecifics.qml
index 271f6bae67..ccb48c084f 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/PropertyAnimationSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/PropertyAnimationSpecifics.qml
@@ -35,6 +35,7 @@ Column {
}
AnimationSection {
+ showEasingCurve: true
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TextInputSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TextInputSection.qml
index cfd972b085..5c0e84d039 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TextInputSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TextInputSection.qml
@@ -114,6 +114,19 @@ Section {
}
Label {
+ visible: textInputSection.isTextInput
+ text: qsTr("Maximum length")
+ tooltip: qsTr("Sets the maximum permitted length of the text in the TextInput.")
+ }
+ SpinBox {
+ visible: textInputSection.isTextInput
+ Layout.fillWidth: true
+ backendValue: backendValues.maximumLength
+ minimumValue: 0
+ maximumValue: 32767
+ }
+
+ Label {
text: qsTr("Flags")
Layout.alignment: Qt.AlignTop
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
index 2d70e40b1d..bb44927318 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
@@ -163,4 +163,9 @@ StudioControls.ComboBox {
colorLogic.invalidate()
comboBox.__isCompleted = true
}
+
+ Connections {
+ target: modelNodeBackend
+ onSelectionToBeChanged: comboBox.popup.close()
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
index 2b97df0646..11f46d29c5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
@@ -47,7 +47,7 @@ Section {
SecondColumnLayout {
ComboBox {
backendValue: backendValues.flickableDirection
- model: ["AutoFlickDirection", "HorizontalFlick", "VerticalFlick", "HorizontalAndVerticalFlick"]
+ model: ["AutoFlickDirection", "AutoFlickIfNeeded", "HorizontalFlick", "VerticalFlick", "HorizontalAndVerticalFlick"]
Layout.fillWidth: true
scope: "Flickable"
}
@@ -63,7 +63,7 @@ Section {
SecondColumnLayout {
ComboBox {
backendValue: backendValues.boundsBehavior
- model: ["StopAtBounds", "DragOverBounds", "DragAndOvershootBounds"]
+ model: ["StopAtBounds", "DragOverBounds", "OvershootBounds", "DragAndOvershootBounds"]
Layout.fillWidth: true
scope: "Flickable"
}
@@ -167,6 +167,23 @@ Section {
}
Label {
+ text: qsTr("Synchronous drag")
+ tooltip: qsTr("If set to true, then when the mouse or touchpoint moves far enough to begin dragging\n"
+ + "the content, the content will jump, such that the content pixel which was under the\n"
+ + "cursor or touchpoint when pressed remains under that point.")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ Layout.fillWidth: true
+ backendValue: backendValues.synchronousDrag
+ text: backendValues.synchronousDrag.valueToString
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
text: qsTr("Content size")
}
@@ -247,6 +264,45 @@ Section {
}
Label {
+ text: qsTr("Origin")
+ }
+
+ SecondColumnLayout {
+ Label {
+ text: "X"
+ width: root.labelWidth
+ }
+
+ SpinBox {
+ backendValue: backendValues.originX
+ minimumValue: -8000
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+ Layout.fillWidth: true
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ Label {
+ text: "Y"
+ width: root.labelWidth
+ }
+
+ SpinBox {
+ backendValue: backendValues.originY
+ minimumValue: -8000
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+ Layout.fillWidth: true
+ }
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
text: qsTr("Margins")
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
index a97923a032..8f1c130089 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
@@ -68,9 +68,12 @@ Section {
text: qsTr("Font")
}
FontComboBox {
+ id: fontComboBox
backendValue: fontSection.fontFamily
Layout.fillWidth: true
width: 160
+ property string familyName: backendValue.value
+ onFamilyNameChanged: print(styleNamesForFamily(familyName))
}
Label {
@@ -151,6 +154,7 @@ Section {
italic: fontSection.italicStyle
underline: fontSection.underlineStyle
strikeout: fontSection.strikeoutStyle
+ enabled: !styleComboBox.styleSet
}
Label {
@@ -175,6 +179,21 @@ Section {
backendValue: getBackendValue("weight")
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
scope: "Font"
+ enabled: !styleComboBox.styleSet
+ }
+
+ Label {
+ text: qsTr("Style name")
+ toolTip: qsTr("Sets the font's style.")
+ }
+
+ ComboBox {
+ id: styleComboBox
+ property bool styleSet: backendValue.isInModel
+ Layout.fillWidth: true
+ backendValue: getBackendValue("styleName")
+ model: styleNamesForFamily(fontComboBox.familyName)
+ valueType: ComboBox.String
}
Label {
@@ -257,5 +276,17 @@ Section {
"Latin script,\n it is merely a cosmetic feature. Setting the preferShaping property to false will disable all such features\nwhen they are not required, which will improve performance in most cases.")
}
}
+
+ Label {
+ text: qsTr("Hinting preference")
+ toolTip: qsTr("Sets the preferred hinting on the text.")
+ }
+
+ ComboBox {
+ Layout.fillWidth: true
+ backendValue: getBackendValue("hintingPreference")
+ model: ["PreferDefaultHinting", "PreferNoHinting", "PreferVerticalHinting", "PreferFullHinting"]
+ scope: "Font"
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml
index 6ecc8d525c..6c5e6fde86 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml
@@ -61,7 +61,7 @@ Section {
Layout.fillWidth: true
backendValue: backendValues.wrapMode
scope: "Text"
- model: ["NoWrap", "WordWrap", "WrapAnywhere", "WrapAtWordBoundaryOrAnywhere"]
+ model: ["NoWrap", "WordWrap", "WrapAnywhere", "Wrap"]
}
Label {
@@ -78,6 +78,21 @@ Section {
}
Label {
+ visible: showElide
+ text: qsTr("Maximum line count")
+ tooltip: qsTr("Limits the number of lines that the text item will show.")
+ }
+
+ SpinBox {
+ visible: showElide
+ Layout.fillWidth: true
+ backendValue: backendValues.maximumLineCount
+ minimumValue: 0
+ maximumValue: 10000
+ decimals: 0
+ }
+
+ Label {
text: qsTr("Alignment")
}
@@ -124,6 +139,7 @@ Section {
toolTip: qsTr("Specifies how the font size of the displayed text is determined.")
}
ComboBox {
+ id: fontSizeMode
visible: showFontSizeMode
scope: "Text"
model: ["FixedSize", "HorizontalFit", "VerticalFit", "Fit"]
@@ -131,6 +147,48 @@ Section {
Layout.fillWidth: true
}
+ Label {
+ visible: showFontSizeMode
+ text: qsTr("Minimum size")
+ }
+ SecondColumnLayout {
+ visible: showFontSizeMode
+
+ SpinBox {
+ enabled: fontSizeMode.currentIndex !== 0
+ minimumValue: 0
+ maximumValue: 500
+ decimals: 0
+ backendValue: backendValues.minimumPixelSize
+ Layout.fillWidth: true
+ Layout.minimumWidth: 60
+ }
+ Label {
+ text: qsTr("Pixel")
+ tooltip: qsTr("Specifies the minimum font pixel size of scaled text.")
+ width: 42
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ SpinBox {
+ enabled: fontSizeMode.currentIndex !== 0
+ minimumValue: 0
+ maximumValue: 500
+ decimals: 0
+ backendValue: backendValues.minimumPointSize
+ Layout.fillWidth: true
+ Layout.minimumWidth: 60
+ }
+ Label {
+ text: qsTr("Point")
+ tooltip: qsTr("Specifies the minimum font point size of scaled text.")
+ width: 42
+ }
+ }
Label {
visible: showLineHeight
@@ -148,5 +206,17 @@ Section {
stepSize: 0.1
}
+ Label {
+ visible: showLineHeight
+ text: qsTr("Line height mode")
+ toolTip: qsTr("Determines how the line height is specified.")
+ }
+ ComboBox {
+ visible: showLineHeight
+ scope: "Text"
+ model: ["ProportionalHeight", "FixedHeight"]
+ backendValue: backendValues.lineHeightMode
+ Layout.fillWidth: true
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml
index 42d7b3eda8..a9b0a2b81c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml
@@ -36,9 +36,11 @@ ButtonRow {
property alias checked: myAbstractButton.checked
signal onCheckedChanged()
+ signal clicked
AbstractButton {
id: myAbstractButton
onCheckedChanged: myButtonRow.onCheckedChanged()
+ onClicked: myButtonRow.clicked()
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml
index 3d692af671..74edf9ccee 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml
@@ -26,98 +26,4 @@
pragma Singleton
import QtQuick 2.10
-QtObject {
- readonly property int width: 1920
- readonly property int height: 1080
- readonly property FontLoader mySystemFont: FontLoader {
- name: "Arial"
- }
- readonly property FontLoader controlIcons: FontLoader {
- source: "icons.ttf"
- }
-
- readonly property string actionIcon: "\u0021"
- readonly property string actionIconBinding: "\u0022"
- readonly property string addColumnAfter: "\u0023"
- readonly property string addColumnBefore: "\u0024"
- readonly property string addFile: "\u0025"
- readonly property string addRowAfter: "\u0026"
- readonly property string addRowBefore: "\u0027"
- readonly property string addTable: "\u0028"
- readonly property string alignBottom: "\u0029"
- readonly property string alignCenterHorizontal: "\u002A"
- readonly property string alignCenterVertical: "\u002B"
- readonly property string alignLeft: "\u002C"
- readonly property string alignRight: "\u002D"
- readonly property string alignTo: "\u002E"
- readonly property string alignTop: "\u002F"
- readonly property string anchorBaseline: "\u0030"
- readonly property string anchorBottom: "\u0031"
- readonly property string anchorFill: "\u0032"
- readonly property string anchorLeft: "\u0033"
- readonly property string anchorRight: "\u0034"
- readonly property string anchorTop: "\u0035"
- readonly property string annotationBubble: "\u0036"
- readonly property string annotationDecal: "\u0037"
- readonly property string centerHorizontal: "\u0038"
- readonly property string centerVertical: "\u0039"
- readonly property string closeCross: "\u003A"
- readonly property string deleteColumn: "\u003B"
- readonly property string deleteRow: "\u003C"
- readonly property string deleteTable: "\u003D"
- readonly property string distributeBottom: "\u003E"
- readonly property string distributeCenterHorizontal: "\u003F"
- readonly property string distributeCenterVertical: "\u0040"
- readonly property string distributeLeft: "\u0041"
- readonly property string distributeOriginBottomRight: "\u0042"
- readonly property string distributeOriginCenter: "\u0043"
- readonly property string distributeOriginNone: "\u0044"
- readonly property string distributeOriginTopLeft: "\u0045"
- readonly property string distributeRight: "\u0046"
- readonly property string distributeSpacingHorizontal: "\u0047"
- readonly property string distributeSpacingVertical: "\u0048"
- readonly property string distributeTop: "\u0049"
- readonly property string edit: "\u004A"
- readonly property string fontStyleBold: "\u004B"
- readonly property string fontStyleItalic: "\u004C"
- readonly property string fontStyleStrikethrough: "\u004D"
- readonly property string fontStyleUnderline: "\u004E"
- readonly property string mergeCells: "\u004F"
- readonly property string redo: "\u0050"
- readonly property string splitColumns: "\u0051"
- readonly property string splitRows: "\u0052"
- readonly property string testIcon: "\u0053"
- readonly property string textAlignBottom: "\u0054"
- readonly property string textAlignCenter: "\u0055"
- readonly property string textAlignLeft: "\u0056"
- readonly property string textAlignMiddle: "\u0057"
- readonly property string textAlignRight: "\u0058"
- readonly property string textAlignTop: "\u0059"
- readonly property string textBulletList: "\u005A"
- readonly property string textFullJustification: "\u005B"
- readonly property string textNumberedList: "\u005C"
- readonly property string tickIcon: "\u005D"
- readonly property string triState: "\u005E"
- readonly property string undo: "\u005F"
- readonly property string upDownIcon: "\u0060"
- readonly property string upDownSquare2: "\u0061"
-
- readonly property font iconFont: Qt.font({
- "family": controlIcons.name,
- "pixelSize": 12
- })
-
- readonly property font font: Qt.font({
- "family": mySystemFont.name,
- "pointSize": Qt.application.font.pixelSize
- })
-
- readonly property font largeFont: Qt.font({
- "family": mySystemFont.name,
- "pointSize": Qt.application.font.pixelSize * 1.6
- })
-
- readonly property color backgroundColor: "#c2c2c2"
-
- readonly property bool showActionIndicatorBackground: false
-}
+InternalConstants {}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
new file mode 100644
index 0000000000..c326cc08f1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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.10
+
+QtObject {
+ readonly property int width: 1920
+ readonly property int height: 1080
+ readonly property FontLoader mySystemFont: FontLoader {
+ name: "Arial"
+ }
+ readonly property FontLoader controlIcons: FontLoader {
+ source: "icons.ttf"
+ }
+
+ objectName: "internalConstantsObject"
+
+ readonly property string actionIcon: "\u0021"
+ readonly property string actionIconBinding: "\u0022"
+ readonly property string addColumnAfter: "\u0023"
+ readonly property string addColumnBefore: "\u0024"
+ readonly property string addFile: "\u0025"
+ readonly property string addRowAfter: "\u0026"
+ readonly property string addRowBefore: "\u0027"
+ readonly property string addTable: "\u0028"
+ readonly property string adsClose: "\u0029"
+ readonly property string adsDetach: "\u002A"
+ readonly property string adsDropDown: "\u002B"
+ readonly property string aliasAnimated: "\u002C"
+ readonly property string aliasProperty: "\u002D"
+ readonly property string alignBottom: "\u002E"
+ readonly property string alignCenterHorizontal: "\u002F"
+ readonly property string alignCenterVertical: "\u0030"
+ readonly property string alignLeft: "\u0031"
+ readonly property string alignRight: "\u0032"
+ readonly property string alignTo: "\u0033"
+ readonly property string alignTop: "\u0034"
+ readonly property string anchorBaseline: "\u0035"
+ readonly property string anchorBottom: "\u0036"
+ readonly property string anchorFill: "\u0037"
+ readonly property string anchorLeft: "\u0038"
+ readonly property string anchorRight: "\u0039"
+ readonly property string anchorTop: "\u003A"
+ readonly property string animatedProperty: "\u003B"
+ readonly property string annotationBubble: "\u003C"
+ readonly property string annotationDecal: "\u003D"
+ readonly property string assign: "\u003E"
+ readonly property string centerHorizontal: "\u003F"
+ readonly property string centerVertical: "\u0040"
+ readonly property string closeCross: "\u0041"
+ readonly property string curveDesigner: "\u0042"
+ readonly property string curveEditor: "\u0043"
+ readonly property string decisionNode: "\u0044"
+ readonly property string deleteColumn: "\u0045"
+ readonly property string deleteRow: "\u0046"
+ readonly property string deleteTable: "\u0047"
+ readonly property string detach: "\u0048"
+ readonly property string distributeBottom: "\u0049"
+ readonly property string distributeCenterHorizontal: "\u004A"
+ readonly property string distributeCenterVertical: "\u004B"
+ readonly property string distributeLeft: "\u004C"
+ readonly property string distributeOriginBottomRight: "\u004D"
+ readonly property string distributeOriginCenter: "\u004E"
+ readonly property string distributeOriginNone: "\u004F"
+ readonly property string distributeOriginTopLeft: "\u0050"
+ readonly property string distributeRight: "\u0051"
+ readonly property string distributeSpacingHorizontal: "\u0052"
+ readonly property string distributeSpacingVertical: "\u0053"
+ readonly property string distributeTop: "\u0054"
+ readonly property string edit: "\u0055"
+ readonly property string fontStyleBold: "\u0056"
+ readonly property string fontStyleItalic: "\u0057"
+ readonly property string fontStyleStrikethrough: "\u0058"
+ readonly property string fontStyleUnderline: "\u0059"
+ readonly property string mergeCells: "\u005A"
+ readonly property string redo: "\u005B"
+ readonly property string splitColumns: "\u005C"
+ readonly property string splitRows: "\u005D"
+ readonly property string startNode: "\u005E"
+ readonly property string testIcon: "\u005F"
+ readonly property string textAlignBottom: "\u0060"
+ readonly property string textAlignCenter: "\u0061"
+ readonly property string textAlignLeft: "\u0062"
+ readonly property string textAlignMiddle: "\u0063"
+ readonly property string textAlignRight: "\u0064"
+ readonly property string textAlignTop: "\u0065"
+ readonly property string textBulletList: "\u0066"
+ readonly property string textFullJustification: "\u0067"
+ readonly property string textNumberedList: "\u0068"
+ readonly property string tickIcon: "\u0069"
+ readonly property string triState: "\u006A"
+ readonly property string undo: "\u006B"
+ readonly property string upDownIcon: "\u006C"
+ readonly property string upDownSquare2: "\u006D"
+ readonly property string wildcard: "\u006E"
+
+ readonly property font iconFont: Qt.font({
+ "family": controlIcons.name,
+ "pixelSize": 12
+ })
+
+ readonly property font font: Qt.font({
+ "family": mySystemFont.name,
+ "pointSize": Qt.application.font.pixelSize
+ })
+
+ readonly property font largeFont: Qt.font({
+ "family": mySystemFont.name,
+ "pointSize": Qt.application.font.pixelSize * 1.6
+ })
+
+ readonly property color backgroundColor: "#c2c2c2"
+
+ readonly property bool showActionIndicatorBackground: false
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
index d65b065195..47becb6873 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir
index b768fe63a2..4f689f9f63 100755
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir
@@ -1,2 +1,4 @@
singleton Values 1.0 Values.qml
singleton Constants 1.0 Constants.qml
+InternalConstants 1.0 InternalConstants.qml
+
diff --git a/src/libs/advanceddockingsystem/ads_globals.h b/src/libs/advanceddockingsystem/ads_globals.h
index 4c0b8d6896..e61bfa7ceb 100644
--- a/src/libs/advanceddockingsystem/ads_globals.h
+++ b/src/libs/advanceddockingsystem/ads_globals.h
@@ -107,10 +107,11 @@ enum eDragState {
* The different icons used in the UI
*/
enum eIcon {
- TabCloseIcon, //!< TabCloseIcon
- DockAreaMenuIcon, //!< DockAreaMenuIcon
- DockAreaUndockIcon, //!< DockAreaUndockIcon
- DockAreaCloseIcon, //!< DockAreaCloseIcon
+ TabCloseIcon, //!< TabCloseIcon
+ DockAreaMenuIcon, //!< DockAreaMenuIcon
+ DockAreaUndockIcon, //!< DockAreaUndockIcon
+ DockAreaCloseIcon, //!< DockAreaCloseIcon
+ FloatingWidgetCloseIcon, //!< FloatingWidgetCloseIcon
IconCount, //!< just a delimiter for range checks
};
diff --git a/src/libs/advanceddockingsystem/dockareatitlebar.cpp b/src/libs/advanceddockingsystem/dockareatitlebar.cpp
index 9ee647265d..79ba7ae70d 100644
--- a/src/libs/advanceddockingsystem/dockareatitlebar.cpp
+++ b/src/libs/advanceddockingsystem/dockareatitlebar.cpp
@@ -132,6 +132,7 @@ namespace ADS
void DockAreaTitleBarPrivate::createButtons()
{
+ const QSize iconSize(14, 14);
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
// Tabs menu button
m_tabsMenuButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasTabsMenuButton));
@@ -149,6 +150,7 @@ namespace ADS
m_tabsMenuButton->setMenu(tabsMenu);
internal::setToolTip(m_tabsMenuButton, QObject::tr("List All Tabs"));
m_tabsMenuButton->setSizePolicy(sizePolicy);
+ m_tabsMenuButton->setIconSize(iconSize);
m_layout->addWidget(m_tabsMenuButton, 0);
QObject::connect(m_tabsMenuButton->menu(),
&QMenu::triggered,
@@ -164,6 +166,7 @@ namespace ADS
QStyle::SP_TitleBarNormalButton,
ADS::DockAreaUndockIcon);
m_undockButton->setSizePolicy(sizePolicy);
+ m_undockButton->setIconSize(iconSize);
m_layout->addWidget(m_undockButton, 0);
QObject::connect(m_undockButton,
&QToolButton::clicked,
@@ -183,7 +186,7 @@ namespace ADS
internal::setToolTip(m_closeButton, QObject::tr("Close Group"));
}
m_closeButton->setSizePolicy(sizePolicy);
- m_closeButton->setIconSize(QSize(16, 16));
+ m_closeButton->setIconSize(iconSize);
m_layout->addWidget(m_closeButton, 0);
QObject::connect(m_closeButton,
&QToolButton::clicked,
diff --git a/src/libs/advanceddockingsystem/dockwidgettab.cpp b/src/libs/advanceddockingsystem/dockwidgettab.cpp
index 611580d368..b46d172050 100644
--- a/src/libs/advanceddockingsystem/dockwidgettab.cpp
+++ b/src/libs/advanceddockingsystem/dockwidgettab.cpp
@@ -168,12 +168,18 @@ namespace ADS
m_titleLabel->setText(m_dockWidget->windowTitle());
m_titleLabel->setObjectName("dockWidgetTabLabel");
m_titleLabel->setAlignment(Qt::AlignCenter);
- QObject::connect(m_titleLabel, &ElidingLabel::elidedChanged, q, &DockWidgetTab::elidedChanged);
+ QObject::connect(m_titleLabel,
+ &ElidingLabel::elidedChanged,
+ q,
+ &DockWidgetTab::elidedChanged);
m_closeButton = createCloseButton();
m_closeButton->setObjectName("tabCloseButton");
- internal::setButtonIcon(m_closeButton, QStyle::SP_TitleBarCloseButton, TabCloseIcon);
+ internal::setButtonIcon(m_closeButton,
+ QStyle::SP_TitleBarCloseButton,
+ TabCloseIcon);
m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_closeButton->setIconSize(QSize(14, 14));
q->onDockWidgetFeaturesChanged();
internal::setToolTip(m_closeButton, QObject::tr("Close Tab"));
QObject::connect(m_closeButton,
@@ -189,11 +195,11 @@ namespace ADS
boxLayout->setContentsMargins(2 * spacing, 0, 0, 0);
boxLayout->setSpacing(0);
q->setLayout(boxLayout);
- boxLayout->addWidget(m_titleLabel, 1);
+ boxLayout->addWidget(m_titleLabel, 1, Qt::AlignVCenter);
boxLayout->addSpacing(spacing);
- boxLayout->addWidget(m_closeButton);
+ boxLayout->addWidget(m_closeButton, 0, Qt::AlignVCenter);
boxLayout->addSpacing(qRound(spacing * 4.0 / 3.0));
- boxLayout->setAlignment(Qt::AlignCenter);
+ boxLayout->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
m_titleLabel->setVisible(true);
}
diff --git a/src/libs/advanceddockingsystem/iconprovider.cpp b/src/libs/advanceddockingsystem/iconprovider.cpp
index 6a6f46752b..f220418220 100644
--- a/src/libs/advanceddockingsystem/iconprovider.cpp
+++ b/src/libs/advanceddockingsystem/iconprovider.cpp
@@ -51,7 +51,7 @@ namespace ADS {
*/
IconProviderPrivate(IconProvider *parent);
};
- // struct LedArrayPanelPrivate
+ // struct IconProviderPrivate
IconProviderPrivate::IconProviderPrivate(IconProvider *parent)
: q(parent)
diff --git a/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp b/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp
index 64e71a3b1c..7d92952d70 100644
--- a/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp
+++ b/src/libs/advanceddockingsystem/linux/floatingwidgettitlebar.cpp
@@ -41,7 +41,7 @@
namespace ADS {
using TabLabelType = ElidingLabel;
-using tCloseButton = QPushButton;
+using CloseButtonType = QPushButton;
/**
* @brief Private data class of public interface CFloatingWidgetTitleBar
@@ -52,7 +52,7 @@ public:
FloatingWidgetTitleBar *q; ///< public interface class
QLabel *m_iconLabel = nullptr;
TabLabelType *m_titleLabel = nullptr;
- tCloseButton *m_closeButton = nullptr;
+ CloseButtonType *m_closeButton = nullptr;
FloatingDockContainer *m_floatingWidget = nullptr;
eDragState m_dragState = DraggingInactive;
@@ -74,22 +74,20 @@ void FloatingWidgetTitleBarPrivate::createLayout()
m_titleLabel->setObjectName("floatingTitleLabel");
m_titleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
- m_closeButton = new tCloseButton();
+ m_closeButton = new CloseButtonType();
m_closeButton->setObjectName("floatingTitleCloseButton");
m_closeButton->setFlat(true);
-
- // The standard icons do does not look good on high DPI screens
- QIcon closeIcon;
- QPixmap normalPixmap = q->style()->standardPixmap(QStyle::SP_TitleBarCloseButton,
- nullptr,
- m_closeButton);
- closeIcon.addPixmap(normalPixmap, QIcon::Normal);
- closeIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
- m_closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
+ internal::setButtonIcon(m_closeButton,
+ QStyle::SP_TitleBarCloseButton,
+ ADS::FloatingWidgetCloseIcon);
m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_closeButton->setIconSize(QSize(14, 14));
m_closeButton->setVisible(true);
m_closeButton->setFocusPolicy(Qt::NoFocus);
- q->connect(m_closeButton, &QPushButton::clicked, q, &FloatingWidgetTitleBar::closeRequested);
+ QObject::connect(m_closeButton,
+ &QPushButton::clicked,
+ q,
+ &FloatingWidgetTitleBar::closeRequested);
QFontMetrics fontMetrics(m_titleLabel->font());
int spacing = qRound(fontMetrics.height() / 4.0);
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index f91c24b52a..68d40accbc 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -28,6 +28,8 @@
#include "theme/theme.h"
#include "hostosinfo.h"
+#include <utils/qtcassert.h>
+
#include <QPixmapCache>
#include <QPainter>
#include <QApplication>
@@ -35,6 +37,7 @@
#include <QCommonStyle>
#include <QStyleOption>
#include <QWindow>
+#include <QFontDatabase>
#include <qmath.h>
// Clamps float color values within (0, 255)
@@ -542,6 +545,48 @@ QLinearGradient StyleHelper::statusBarGradient(const QRect &statusBarRect)
return grad;
}
+QIcon StyleHelper::getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize, QColor color)
+{
+ QFontDatabase a;
+
+ QTC_ASSERT(a.hasFamily(fontName), {});
+
+ if (a.hasFamily(fontName)) {
+
+ QIcon icon;
+ QSize size(iconSize, iconSize);
+
+ const int maxDpr = qRound(qApp->devicePixelRatio());
+ for (int dpr = 1; dpr <= maxDpr; dpr++) {
+ QPixmap pixmap(size * dpr);
+ pixmap.setDevicePixelRatio(dpr);
+ pixmap.fill(Qt::transparent);
+
+ QFont font(fontName);
+ font.setPixelSize(fontSize * dpr);
+
+ QPainter painter(&pixmap);
+ painter.save();
+ painter.setPen(color);
+ painter.setFont(font);
+ painter.drawText(QRectF(QPoint(0, 0), size), iconSymbol);
+ painter.restore();
+
+ icon.addPixmap(pixmap);
+ }
+
+ return icon;
+ }
+
+ return {};
+}
+
+QIcon StyleHelper::getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize)
+{
+ QColor penColor = QApplication::palette("QWidget").color(QPalette::Normal, QPalette::ButtonText);
+ return getIconFromIconFont(fontName, iconSymbol, fontSize, iconSize, penColor);
+}
+
QString StyleHelper::dpiSpecificImageFile(const QString &fileName)
{
// See QIcon::addFile()
diff --git a/src/libs/utils/stylehelper.h b/src/libs/utils/stylehelper.h
index 4bcec960ad..09f3253435 100644
--- a/src/libs/utils/stylehelper.h
+++ b/src/libs/utils/stylehelper.h
@@ -93,6 +93,9 @@ public:
static void tintImage(QImage &img, const QColor &tintColor);
static QLinearGradient statusBarGradient(const QRect &statusBarRect);
+ static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize, QColor color);
+ static QIcon getIconFromIconFont(const QString &fontName, const QString &iconSymbol, int fontSize, int iconSize);
+
static QString dpiSpecificImageFile(const QString &fileName);
static QString imageFileWithResolution(const QString &fileName, int dpr);
static QList<int> availableImageResolutions(const QString &fileName);
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 9c32da72c4..ad7ad2831f 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -247,6 +247,7 @@ extend_qtc_plugin(QmlDesigner
snapper.cpp snapper.h
snappinglinecreator.cpp snappinglinecreator.h
toolbox.cpp toolbox.h
+ transitiontool.cpp transitiontool.h
)
extend_qtc_plugin(QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 2965bcd90b..e76b5c1ff7 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -39,8 +39,10 @@ const char qmlPreviewCategory[] = "QmlPreview";
const char editCategory[] = "Edit";
const char anchorsCategory[] = "Anchors";
const char positionCategory[] = "Position";
+const char groupCategory[] = "Group";
const char layoutCategory[] = "Layout";
const char flowCategory[] = "Flow";
+const char flowEffectCategory[] = "FlowEffect";
const char flowConnectionCategory[] = "FlowConnection";
const char stackedContainerCategory[] = "StackedContainer";
const char genericToolBarCategory[] = "GenericToolBar";
@@ -57,6 +59,8 @@ const char anchorsFillCommandId[] = "AnchorsFill";
const char anchorsResetCommandId[] = "AnchorsReset";
const char removePositionerCommandId[] = "RemovePositioner";
const char createFlowActionAreaCommandId[] = "CreateFlowActionArea";
+const char setFlowStartCommandId[] = "SetFlowStart";
+const char selectFlowEffectCommandId[] = "SelectFlowEffect";
const char layoutRowPositionerCommandId[] = "LayoutRowPositioner";
const char layoutColumnPositionerCommandId[] = "LayoutColumnPositioner";
const char layoutGridPositionerCommandId[] = "LayoutGridPositioner";
@@ -76,15 +80,19 @@ const char addTabBarToStackedContainerCommandId[] = "AddTabBarToStackedContainer
const char increaseIndexOfStackedContainerCommandId[] = "IncreaseIndexOfStackedContainer";
const char decreaseIndexOfStackedContainerCommandId[] = "DecreaseIndexOfStackedContainer";
const char flowAssignEffectCommandId[] = "AssignFlowEffect";
+const char addToGroupItemCommandId[] = "AddToGroupItem";
const char selectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Selection");
const char flowConnectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect");
+const char selectEffectDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select Effect");
const char stackCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Stack (z)");
const char editCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Edit");
const char anchorsCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Anchors");
const char positionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Position");
+const char groupCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Group");
const char layoutCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout");
const char flowCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Flow");
+const char flowEffectCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Flow Effects");
const char stackedContainerCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Stacked Container");
const char cutSelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Cut");
@@ -124,8 +132,11 @@ const char layoutGridPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerCon
const char layoutFlowPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Position in Flow");
const char removePositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Remove Positioner");
const char createFlowActionAreaDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Create Flow Action");
+const char setFlowStartDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Set Flow Start");
const char removeLayoutDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Remove Layout");
+const char addToGroupItemDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Group in GroupItem");
+
const char addItemToStackedContainerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Add Item");
const char addTabBarToStackedContainerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Add Tab Bar");
const char increaseIndexToStackedContainerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Increase Index");
@@ -165,6 +176,7 @@ const int priorityStackCategory = 180;
const int priorityEditCategory = 160;
const int priorityAnchorsCategory = 140;
const int priorityFlowCategory = 240;
+const int priorityGroupCategory = 140;
const int priorityPositionCategory = 130;
const int priorityLayoutCategory = 120;
const int priorityStackedContainerCategory = priorityLayoutCategory;
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 42f95952db..07246f175c 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -346,12 +346,28 @@ bool isFlowItem(const SelectionContext &context)
&& QmlFlowItemNode::isValidQmlFlowItemNode(context.currentSingleSelectedNode());
}
+bool isFlowTarget(const SelectionContext &context)
+{
+ return context.singleNodeIsSelected()
+ && QmlFlowTargetNode::isFlowEditorTarget(context.currentSingleSelectedNode());
+}
+
bool isFlowTransitionItem(const SelectionContext &context)
{
return context.singleNodeIsSelected()
&& QmlFlowItemNode::isFlowTransition(context.currentSingleSelectedNode());
}
+bool isFlowTransitionItemWithEffect(const SelectionContext &context)
+{
+ if (!isFlowTransitionItem(context))
+ return false;
+
+ ModelNode node = context.currentSingleSelectedNode();
+
+ return node.hasNodeProperty("effect");
+}
+
bool isFlowActionItemItem(const SelectionContext &context)
{
const ModelNode selectedNode = context.currentSingleSelectedNode();
@@ -362,9 +378,9 @@ bool isFlowActionItemItem(const SelectionContext &context)
|| QmlVisualNode::isFlowWildcard(selectedNode));
}
-bool isFlowItemOrTransition(const SelectionContext &context)
+bool isFlowTargetOrTransition(const SelectionContext &context)
{
- return isFlowItem(context) || isFlowTransitionItem(context);
+ return isFlowTarget(context) || isFlowTransitionItem(context);
}
class FlowActionConnectAction : public ActionGroup
@@ -642,6 +658,12 @@ bool positionOptionVisible(const SelectionContext &context)
|| isPositioner(context);
}
+bool studioComponentsAvailable(const SelectionContext &context)
+{
+ const Import import = Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
+ return context.view()->model()->isImportPossible(import, true, true);
+}
+
bool singleSelectedAndUiFile(const SelectionContext &context)
{
if (!singleSelection(context))
@@ -853,15 +875,31 @@ void DesignerActionManager::createDefaultDesignerActions()
priorityLayoutCategory,
&layoutOptionVisible));
- //isFlowTransitionItem
+ addDesignerAction(new ActionGroup(
+ groupCategoryDisplayName,
+ groupCategory,
+ priorityGroupCategory,
+ &positionOptionVisible,
+ &studioComponentsAvailable));
addDesignerAction(new ActionGroup(
flowCategoryDisplayName,
flowCategory,
priorityFlowCategory,
- &isFlowItemOrTransition,
+ &isFlowTargetOrTransition,
&flowOptionVisible));
+
+ auto effectMenu = new ActionGroup(
+ flowEffectCategoryDisplayName,
+ flowEffectCategory,
+ priorityFlowCategory,
+ &isFlowTransitionItem,
+ &flowOptionVisible);
+
+ effectMenu->setCategory(flowCategory);
+ addDesignerAction(effectMenu);
+
addDesignerAction(new ModelNodeFormEditorAction(
createFlowActionAreaCommandId,
createFlowActionAreaDisplayName,
@@ -874,26 +912,41 @@ void DesignerActionManager::createDefaultDesignerActions()
&isFlowItem,
&flowOptionVisible));
+ addDesignerAction(new ModelNodeContextMenuAction(
+ setFlowStartCommandId,
+ setFlowStartDisplayName,
+ {},
+ flowCategory,
+ priorityFirst,
+ {},
+ &setFlowStartItem,
+ &isFlowItem,
+ &flowOptionVisible));
+
addDesignerAction(new FlowActionConnectAction(
flowConnectionCategoryDisplayName,
flowConnectionCategory,
priorityFlowCategory));
- const QList<TypeName> types = {"FlowActionArea",
- "FlowFadeEffect",
- "FlowPushRightEffect",
- "FlowPushLeftEffect",
- "FlowPushUpEffect",
- "FlowSlideDownEffect",
- "FlowSlideLeftEffect",
- "FlowSlideRightEffect",
- "FlowSlideUpEffect",
+ const QList<TypeName> transitionTypes = {"FlowFadeEffect",
+ "FlowPushEffect",
+ "FlowMoveEffect",
"None"};
- for (const TypeName &typeName : types)
+ for (const TypeName &typeName : transitionTypes)
addTransitionEffectAction(typeName);
+ addDesignerAction(new ModelNodeContextMenuAction(
+ selectFlowEffectCommandId,
+ selectEffectDisplayName,
+ {},
+ flowCategory,
+ {},
+ priorityFlowCategory,
+ &selectFlowEffect,
+ &isFlowTransitionItemWithEffect));
+
addDesignerAction(new ActionGroup(
stackedContainerCategoryDisplayName,
stackedContainerCategory,
@@ -968,6 +1021,18 @@ void DesignerActionManager::createDefaultDesignerActions()
&isLayout,
&isLayout));
+ addDesignerAction(new ModelNodeContextMenuAction(
+ addToGroupItemCommandId,
+ addToGroupItemDisplayName,
+ {},
+ groupCategory,
+ QKeySequence(),
+ 110,
+ &addToGroupItem,
+ &selectionCanBeLayouted,
+ &selectionCanBeLayouted));
+
+
addDesignerAction(new ModelNodeFormEditorAction(
addItemToStackedContainerCommandId,
addItemToStackedContainerDisplayName,
@@ -1175,7 +1240,7 @@ void DesignerActionManager::addTransitionEffectAction(const TypeName &typeName)
QByteArray(ComponentCoreConstants::flowAssignEffectCommandId) + typeName,
QLatin1String(ComponentCoreConstants::flowAssignEffectDisplayName) + typeName,
{},
- ComponentCoreConstants::flowCategory,
+ ComponentCoreConstants::flowEffectCategory,
{},
typeName == "None" ? 100 : 140,
[typeName](const SelectionContext &context)
@@ -1186,6 +1251,10 @@ void DesignerActionManager::addTransitionEffectAction(const TypeName &typeName)
DesignerActionToolBar::DesignerActionToolBar(QWidget *parentWidget) : Utils::StyledBar(parentWidget),
m_toolBar(new QToolBar("ActionToolBar", this))
{
+ QWidget* empty = new QWidget();
+ empty->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
+ m_toolBar->addWidget(empty);
+
m_toolBar->setContentsMargins(0, 0, 0, 0);
m_toolBar->setFloatable(true);
m_toolBar->setMovable(true);
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
index 6876684504..8a6c06fcdc 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
@@ -25,6 +25,8 @@
#include "designeractionmanagerview.h"
+#include <customnotifications.h>
+
#include <selectioncontext.h>
#include <actioninterface.h>
#include <variantproperty.h>
@@ -53,7 +55,7 @@ void DesignerActionManagerView::modelAboutToBeDetached(Model *model)
void DesignerActionManagerView::nodeCreated(const ModelNode &)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::NodeCreated);
}
void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
@@ -63,17 +65,17 @@ void DesignerActionManagerView::nodeRemoved(const ModelNode &, const NodeAbstrac
void DesignerActionManagerView::nodeAboutToBeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::NodeHierachy);
}
void DesignerActionManagerView::nodeReparented(const ModelNode &, const NodeAbstractProperty &, const NodeAbstractProperty &, AbstractView::PropertyChangeFlags)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::NodeHierachy);
}
void DesignerActionManagerView::propertiesRemoved(const QList<AbstractProperty> &)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
}
void DesignerActionManagerView::rootNodeTypeChanged(const QString &, int, int)
@@ -112,7 +114,7 @@ void DesignerActionManagerView::selectedNodesChanged(const QList<ModelNode> &sel
void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &, const ModelNode &, int)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::NodeHierachy);
}
void DesignerActionManagerView::importsChanged(const QList<Import> &, const QList<Import> &)
@@ -122,27 +124,38 @@ void DesignerActionManagerView::importsChanged(const QList<Import> &, const QLis
void DesignerActionManagerView::signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &, AbstractView::PropertyChangeFlags)
{
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
}
void DesignerActionManagerView::variantPropertiesChanged(const QList<VariantProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
{
if (propertyChangeFlag == AbstractView::PropertiesAdded)
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
else if (hasSingleSelectedModelNode())
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
}
void DesignerActionManagerView::bindingPropertiesChanged(const QList<BindingProperty> &, AbstractView::PropertyChangeFlags propertyChangeFlag)
{
if (propertyChangeFlag == AbstractView::PropertiesAdded)
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
}
void DesignerActionManagerView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &)
{
if (hasSingleSelectedModelNode())
- setupContext(SelectionContext::UpdateMode::Fast);
+ setupContext(SelectionContext::UpdateMode::Properties);
+}
+
+void DesignerActionManagerView::customNotification(const AbstractView * /*view*/,
+ const QString &identifier,
+ const QList<ModelNode> & /* nodeList */,
+ const QList<QVariant> & /*data */)
+{
+ if (identifier == StartRewriterAmend)
+ m_isInRewriterTransaction = true;
+ else if (identifier == EndRewriterAmend)
+ m_isInRewriterTransaction = false;
}
DesignerActionManager &DesignerActionManagerView::designerActionManager()
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
index 5eb0efe542..a7a34271ea 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
@@ -71,6 +71,10 @@ public:
void emitSelectionChanged();
void setupContext(SelectionContext::UpdateMode updateMode = SelectionContext::UpdateMode::Normal);
+ void customNotification(const AbstractView *,
+ const QString &identifier,
+ const QList<ModelNode> &,
+ const QList<QVariant> &) override;
signals:
void selectionChanged(bool itemsSelected, bool rootItemIsSelected);
diff --git a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
index a1629c0b5b..e106fc9357 100644
--- a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
@@ -167,7 +167,6 @@ void LayoutInGridLayout::doIt()
const TypeName layoutType = "QtQuick.Layouts.GridLayout";
if (!m_selectionContext.view()
- || !m_selectionContext.hasSingleSelectedModelNode()
|| !m_selectionContext.view()->model()->hasNodeMetaInfo(layoutType))
return;
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
index 67a53ef997..59029400e5 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
@@ -132,16 +132,22 @@ public:
bool isVisible(const SelectionContext &m_selectionState) const override { return m_visibility(m_selectionState); }
bool isEnabled(const SelectionContext &m_selectionState) const override { return m_enabled(m_selectionState); }
- QByteArray category() const override { return QByteArray(); }
+ QByteArray category() const override { return m_category; }
QByteArray menuId() const override { return m_menuId; }
int priority() const override { return m_priority; }
Type type() const override { return ContextMenu; }
+ void setCategory(const QByteArray &catageoryId)
+ {
+ m_category = catageoryId;
+ }
+
private:
const QByteArray m_menuId;
const int m_priority;
SelectionContextPredicate m_enabled;
SelectionContextPredicate m_visibility;
+ QByteArray m_category;
};
class SeperatorDesignerAction : public AbstractAction
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 2c239a8aa9..00e2ac028a 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -311,8 +311,10 @@ void resetSize(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetSize",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
- itemNode.removeProperty("width");
- itemNode.removeProperty("height");
+ if (itemNode.isValid()) {
+ itemNode.removeProperty("width");
+ itemNode.removeProperty("height");
+ }
}
});
}
@@ -325,8 +327,10 @@ void resetPosition(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetPosition",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
- itemNode.removeProperty("x");
- itemNode.removeProperty("y");
+ if (itemNode.isValid()) {
+ itemNode.removeProperty("x");
+ itemNode.removeProperty("y");
+ }
}
});
}
@@ -348,7 +352,8 @@ void resetZ(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetZ",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
- itemNode.removeProperty("z");
+ if (itemNode.isValid())
+ itemNode.removeProperty("z");
}
});
}
@@ -452,7 +457,6 @@ static void layoutHelperFunction(const SelectionContext &selectionContext,
const LessThan &lessThan)
{
if (!selectionContext.view()
- || !selectionContext.hasSingleSelectedModelNode()
|| !selectionContext.view()->model()->hasNodeMetaInfo(layoutType))
return;
@@ -1095,7 +1099,122 @@ void addFlowEffect(const SelectionContext &selectionContext, const TypeName &typ
container.nodeProperty("effect").reparentHere(effectNode);
view->setSelectedModelNode(effectNode);
}
- });
+ });
+}
+
+void setFlowStartItem(const SelectionContext &selectionContext)
+{
+ AbstractView *view = selectionContext.view();
+
+ QTC_ASSERT(view && selectionContext.hasSingleSelectedModelNode(), return);
+ ModelNode node = selectionContext.currentSingleSelectedNode();
+ QTC_ASSERT(node.isValid(), return);
+ QTC_ASSERT(node.metaInfo().isValid(), return);
+ QmlFlowItemNode flowItem(node);
+ QTC_ASSERT(flowItem.isValid(), return);
+ QTC_ASSERT(flowItem.flowView().isValid(), return);
+ view->executeInTransaction("DesignerActionManager:setFlowStartItem",
+ [&flowItem](){
+ flowItem.flowView().setStartFlowItem(flowItem);
+ });
+}
+
+
+bool static hasStudioComponentsImport(const SelectionContext &context)
+{
+ if (context.view() && context.view()->model()) {
+ Import import = Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
+ return context.view()->model()->hasImport(import, true, true);
+ }
+
+ return false;
+}
+
+static inline void setAdjustedPos(const QmlDesigner::ModelNode &modelNode)
+{
+ if (modelNode.hasParentProperty()) {
+ ModelNode parentNode = modelNode.parentProperty().parentModelNode();
+
+ const QPointF instancePos = QmlItemNode(modelNode).instancePosition();
+ const int x = instancePos.x() - parentNode.variantProperty("x").value().toInt();
+ const int y = instancePos.y() - parentNode.variantProperty("y").value().toInt();
+
+ modelNode.variantProperty("x").setValue(x);
+ modelNode.variantProperty("y").setValue(y);
+ }
+}
+
+void reparentToNodeAndAdjustPosition(const ModelNode &parentModelNode,
+ const QList<ModelNode> &modelNodeList)
+{
+ for (ModelNode modelNode : modelNodeList) {
+ reparentTo(modelNode, parentModelNode);
+ setAdjustedPos(modelNode);
+
+ for (const VariantProperty &variantProperty : modelNode.variantProperties()) {
+ if (variantProperty.name().contains("anchors."))
+ modelNode.removeProperty(variantProperty.name());
+ }
+ for (const BindingProperty &bindingProperty : modelNode.bindingProperties()) {
+ if (bindingProperty.name().contains("anchors."))
+ modelNode.removeProperty(bindingProperty.name());
+ }
+ }
+}
+
+void addToGroupItem(const SelectionContext &selectionContext)
+{
+ const TypeName typeName = "QtQuick.Studio.Components.GroupItem";
+
+ try {
+ if (!hasStudioComponentsImport(selectionContext)) {
+ Import studioImport = Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
+ selectionContext.view()-> model()->changeImports({studioImport}, {});
+ }
+
+ if (!selectionContext.view())
+ return;
+
+ if (QmlItemNode::isValidQmlItemNode(selectionContext.firstSelectedModelNode())) {
+ const QmlItemNode qmlItemNode = QmlItemNode(selectionContext.firstSelectedModelNode());
+
+ if (qmlItemNode.hasInstanceParentItem()) {
+ ModelNode groupNode;
+ selectionContext.view()->executeInTransaction("DesignerActionManager|addToGroupItem1",[=, &groupNode](){
+
+ QmlItemNode parentNode = qmlItemNode.instanceParentItem();
+ NodeMetaInfo metaInfo = selectionContext.view()->model()->metaInfo(typeName);
+ groupNode = selectionContext.view()->createModelNode(typeName, metaInfo.majorVersion(), metaInfo.minorVersion());
+ reparentTo(groupNode, parentNode);
+ });
+ selectionContext.view()->executeInTransaction("DesignerActionManager|addToGroupItem2",[=](){
+
+ QList<ModelNode> selectedNodes = selectionContext.selectedModelNodes();
+ setUpperLeftPostionToNode(groupNode, selectedNodes);
+
+ reparentToNodeAndAdjustPosition(groupNode, selectedNodes);
+ });
+ }
+ }
+ } catch (RewritingException &e) {
+ e.showException();
+ }
+}
+
+void selectFlowEffect(const SelectionContext &selectionContext)
+{
+ if (!selectionContext.singleNodeIsSelected())
+ return;
+
+ ModelNode node = selectionContext.currentSingleSelectedNode();
+ QmlVisualNode transition(node);
+
+ QTC_ASSERT(transition.isValid(), return);
+ QTC_ASSERT(transition.isFlowTransition(), return);
+
+ if (node.hasNodeProperty("effect")) {
+ selectionContext.view()->setSelectedModelNode(node.nodeProperty("effect").modelNode());
+ }
}
} // namespace Mode
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index 994110297e..220afe9d4e 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -77,6 +77,9 @@ bool addFontToProject(const QStringList &fileNames, const QString &directory);
void createFlowActionArea(const SelectionContext &selectionContext);
void addTransition(const SelectionContext &selectionState);
void addFlowEffect(const SelectionContext &selectionState, const TypeName &typeName);
+void setFlowStartItem(const SelectionContext &selectionContext);
+void addToGroupItem(const SelectionContext &selectionContext);
+void selectFlowEffect(const SelectionContext &selectionContext);
} // namespace ModelNodeOperationso
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
index 59a9454b09..80201b315b 100644
--- a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
@@ -124,12 +124,17 @@ bool SelectionContext::isValid() const
bool SelectionContext::fastUpdate() const
{
- return m_updateMode == UpdateMode::Fast;
+ return m_updateReason != UpdateMode::Normal;
}
void SelectionContext::setUpdateMode(UpdateMode mode)
{
- m_updateMode = mode;
+ m_updateReason = mode;
+}
+
+SelectionContext::UpdateMode SelectionContext::updateReason() const
+{
+ return m_updateReason;
}
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/selectioncontext.h b/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
index 929bf4eebb..3fe2157788 100644
--- a/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
+++ b/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
@@ -35,7 +35,14 @@ namespace QmlDesigner {
class QMLDESIGNERCORE_EXPORT SelectionContext {
public:
- enum class UpdateMode {Normal, Fast};
+ enum class UpdateMode {
+ Normal,
+ Fast,
+ Properties,
+ NodeCreated,
+ NodeHierachy,
+ Selection
+ };
SelectionContext();
SelectionContext(AbstractView *view);
@@ -68,13 +75,15 @@ public:
bool fastUpdate() const;
void setUpdateMode(UpdateMode mode);
+ UpdateMode updateReason() const;
+
private:
QPointer<AbstractView> m_view;
ModelNode m_targetNode;
QPointF m_scenePosition;
bool m_showSelectionTools = false;
bool m_toggled = false;
- UpdateMode m_updateMode = UpdateMode::Normal;
+ UpdateMode m_updateReason = UpdateMode::Normal;
};
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.cpp b/src/plugins/qmldesigner/components/componentcore/theme.cpp
index ec4128479f..29b937a502 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/theme.cpp
@@ -28,19 +28,46 @@
#include <qmldesignerplugin.h>
+#include <coreplugin/icore.h>
+
#include <utils/stylehelper.h>
#include <QApplication>
#include <QRegExp>
#include <QScreen>
#include <QPointer>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QQmlProperty>
#include <qqml.h>
+static Q_LOGGING_CATEGORY(themeLog, "qtc.qmldesigner.theme", QtWarningMsg)
+
namespace QmlDesigner {
Theme::Theme(Utils::Theme *originTheme, QObject *parent)
: Utils::Theme(originTheme, parent)
+ , m_constants(nullptr)
{
+ QString constantsPath = Core::ICore::resourcePath() +
+ QStringLiteral("/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml");
+
+ QQmlEngine* engine = new QQmlEngine(this);
+ QQmlComponent component(engine, QUrl::fromLocalFile(constantsPath));
+
+ if (component.status() == QQmlComponent::Ready) {
+ m_constants = component.create();
+ }
+ else if (component.status() == QQmlComponent::Error ) {
+ qCWarning(themeLog) << "Couldn't load" << constantsPath
+ << "due to the following error(s):";
+ for (QQmlError error : component.errors())
+ qCWarning(themeLog) << error.toString();
+ }
+ else {
+ qCWarning(themeLog) << "Couldn't load" << constantsPath
+ << "the status of the QQmlComponent is" << component.status();
+ }
}
QColor Theme::evaluateColorAtThemeInstance(const QString &themeColorName)
@@ -129,6 +156,25 @@ QPixmap Theme::getPixmap(const QString &id)
return QmlDesignerIconProvider::getPixmap(id);
}
+QString Theme::getIconUnicode(Theme::Icon i)
+{
+ if (!instance()->m_constants)
+ return QString();
+
+ const QMetaObject *m = instance()->metaObject();
+ const char *enumName = "Icon";
+ int enumIndex = m->indexOfEnumerator(enumName);
+
+ if (enumIndex == -1) {
+ qCWarning(themeLog) << "Couldn't find enum" << enumName;
+ return QString();
+ }
+
+ QMetaEnum e = m->enumerator(enumIndex);
+
+ return instance()->m_constants->property(e.valueToKey(i)).toString();
+}
+
QColor Theme::qmlDesignerBackgroundColorDarker() const
{
return getColor(QmlDesigner_BackgroundColorDarker);
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h
index 6940c0c1cf..4cc4deb298 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.h
+++ b/src/plugins/qmldesigner/components/componentcore/theme.h
@@ -41,12 +41,95 @@ namespace QmlDesigner {
class QMLDESIGNERCORE_EXPORT Theme : public Utils::Theme
{
Q_OBJECT
+
+ Q_ENUMS(Icon)
+
public:
+ enum Icon {
+ actionIcon,
+ actionIconBinding,
+ addColumnAfter,
+ addColumnBefore,
+ addFile,
+ addRowAfter,
+ addRowBefore,
+ addTable,
+ adsClose,
+ adsDetach,
+ adsDropDown,
+ aliasAnimated,
+ aliasProperty,
+ alignBottom,
+ alignCenterHorizontal,
+ alignCenterVertical,
+ alignLeft,
+ alignRight,
+ alignTo,
+ alignTop,
+ assign,
+ anchorBaseline,
+ anchorBottom,
+ anchorFill,
+ anchorLeft,
+ anchorRight,
+ anchorTop,
+ annotationBubble,
+ annotationDecal,
+ centerHorizontal,
+ centerVertical,
+ curveEditor,
+ closeCross,
+ decisionNode,
+ deleteColumn,
+ deleteRow,
+ deleteTable,
+ detach,
+ distributeBottom,
+ distributeCenterHorizontal,
+ distributeCenterVertical,
+ distributeLeft,
+ distributeOriginBottomRight,
+ distributeOriginCenter,
+ distributeOriginNone,
+ distributeOriginTopLeft,
+ distributeRight,
+ distributeSpacingHorizontal,
+ distributeSpacingVertical,
+ distributeTop,
+ edit,
+ fontStyleBold,
+ fontStyleItalic,
+ fontStyleStrikethrough,
+ fontStyleUnderline,
+ mergeCells,
+ redo,
+ splitColumns,
+ splitRows,
+ startNode,
+ testIcon,
+ textAlignBottom,
+ textAlignCenter,
+ textAlignLeft,
+ textAlignMiddle,
+ textAlignRight,
+ textAlignTop,
+ textBulletList,
+ textFullJustification,
+ textNumberedList,
+ tickIcon,
+ triState,
+ undo,
+ upDownIcon,
+ upDownSquare2,
+ wildcard
+ };
+
static Theme *instance();
static QString replaceCssColors(const QString &input);
static void setupTheme(QQmlEngine *engine);
static QColor getColor(Color role);
static QPixmap getPixmap(const QString &id);
+ static QString getIconUnicode(Theme::Icon i);
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarker() const;
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarkAlternate() const;
@@ -58,9 +141,12 @@ public:
Q_INVOKABLE int smallFontPixelSize() const;
Q_INVOKABLE int captionFontPixelSize() const;
Q_INVOKABLE bool highPixelDensity() const;
+
private:
Theme(Utils::Theme *originTheme, QObject *parent);
QColor evaluateColorAtThemeInstance(const QString &themeColorName);
+
+ QObject *m_constants;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index c8e1e222e5..9e882be2fd 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -179,6 +179,17 @@ void Edit3DView::importsChanged(const QList<Import> &addedImports,
checkImports();
}
+void Edit3DView::customNotification(const AbstractView *view, const QString &identifier,
+ const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ Q_UNUSED(view)
+ Q_UNUSED(nodeList)
+ Q_UNUSED(data)
+
+ if (identifier == "asset_import_update")
+ resetPuppet();
+}
+
void Edit3DView::sendInputEvent(QInputEvent *e) const
{
if (nodeInstanceView())
@@ -301,14 +312,16 @@ QVector<Edit3DAction *> Edit3DView::rightActions() const
void Edit3DView::addQuick3DImport()
{
- const QList<Import> imports = model()->possibleImports();
- for (const auto &import : imports) {
- if (import.url() == "QtQuick3D") {
- model()->changeImports({import}, {});
-
- // Subcomponent manager update needed to make item library entries appear
- QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
- return;
+ if (model()) {
+ const QList<Import> imports = model()->possibleImports();
+ for (const auto &import : imports) {
+ if (import.url() == "QtQuick3D") {
+ model()->changeImports({import}, {});
+
+ // Subcomponent manager update needed to make item library entries appear
+ QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
+ return;
+ }
}
}
Core::AsynchronousMessageBox::warning(tr("Failed to Add Import"),
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index d1646470b7..6c3ae892a9 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -58,6 +58,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void sendInputEvent(QInputEvent *e) const;
void edit3DViewResized(const QSize &size) const;
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index c948227233..3d0d3f2f64 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -106,12 +106,11 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
// Onboarding label contains instructions for new users how to get 3D content into the project
m_onboardingLabel = new QLabel(this);
QString labelText =
- "No 3D import here yet!<br><br>"
- "To create a 3D View you need to add the QtQuick3D import to your file.<br>"
- "You can add the import via the QML Imports tab of the Library view, or alternatively click"
- " <a href=\"#add_import\"><span style=\"text-decoration:none;color:%1\">here</span></a> "
- "to add it straight away.<br><br>"
- "If you want to import 3D assets from another tool, click on the \"Add New Assets...\" button in the Assets tab of the Library view.";
+ tr("Your file does not import Qt Quick 3D.<br><br>"
+ "To create a 3D view, add the QtQuick3D import to your file in the QML Imports tab of the Library view. Or click"
+ " <a href=\"#add_import\"><span style=\"text-decoration:none;color:%1\">here</span></a> "
+ "here to add it immediately.<br><br>"
+ "To import 3D assets from another tool, click on the \"Add New Assets...\" button in the Assets tab of the Library view.");
m_onboardingLabel->setText(labelText.arg(Utils::creatorTheme()->color(Utils::Theme::TextColorLink).name()));
m_onboardingLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
connect(m_onboardingLabel, &QLabel::linkActivated, this, &Edit3DWidget::linkActivated);
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditor.pri b/src/plugins/qmldesigner/components/formeditor/formeditor.pri
index 3464ba3afe..4609b277f9 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditor.pri
+++ b/src/plugins/qmldesigner/components/formeditor/formeditor.pri
@@ -36,7 +36,8 @@ SOURCES += formeditoritem.cpp \
contentnoteditableindicator.cpp \
backgroundaction.cpp \
formeditortoolbutton.cpp \
- formeditorannotationicon.cpp
+ formeditorannotationicon.cpp \
+ transitiontool.cpp
HEADERS += formeditorscene.h \
formeditorwidget.h \
@@ -75,6 +76,7 @@ HEADERS += formeditorscene.h \
contentnoteditableindicator.h \
backgroundaction.h \
formeditortoolbutton.h \
- formeditorannotationicon.h
+ formeditorannotationicon.h \
+ transitiontool.h
RESOURCES += formeditor.qrc
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index 96a4cc5adf..0c022431c9 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -32,10 +32,13 @@
#include <nodehints.h>
#include <nodemetainfo.h>
+#include <theme.h>
+
#include <utils/theme/theme.h>
#include <utils/qtcassert.h>
#include <QDebug>
+#include <QFontDatabase>
#include <QPainter>
#include <QPainterPath>
#include <QStyleOptionGraphicsItem>
@@ -47,6 +50,36 @@
namespace QmlDesigner {
const int flowBlockSize = 200;
+const int blockRadius = 18;
+const int blockAdjust = 40;
+
+const char startNodeIcon[] = "\u0055";
+
+void drawIcon(QPainter *painter,
+ int x,
+ int y,
+ const QString &iconSymbol,
+ int fontSize, int iconSize,
+ const QColor &penColor)
+{
+ static QFontDatabase a;
+
+ const QString fontName = "qtds_propertyIconFont.ttf";
+
+ Q_ASSERT(a.hasFamily(fontName));
+
+ if (a.hasFamily(fontName)) {
+ QFont font(fontName);
+ font.setPixelSize(fontSize);
+
+ painter->save();
+ painter->setPen(penColor);
+ painter->setFont(font);
+ painter->drawText(QRectF(x, y, iconSize, iconSize), iconSymbol);
+
+ painter->restore();
+ }
+}
FormEditorScene *FormEditorItem::scene() const {
return qobject_cast<FormEditorScene*>(QGraphicsItem::scene());
@@ -410,6 +443,8 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
|| painterTransform.isRotating())
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
+ painter->setClipRegion(boundingRect().toRect());
+
if (m_blurContent)
painter->drawPixmap(m_paintedBoundingRect.topLeft(), qmlItemNode().instanceBlurredRenderPixmap());
else
@@ -419,6 +454,7 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
}
}
+ painter->setClipping(false);
if (!qmlItemNode().isRootModelNode())
paintBoundingRect(painter);
@@ -578,6 +614,7 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi
return;
painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
QPen pen;
pen.setJoinStyle(Qt::MiterJoin);
@@ -622,10 +659,9 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi
fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value<QColor>();
if (fillColor.alpha() > 0)
- painter->fillRect(boundingRect(), fillColor);
-
- painter->drawRect(boundingRect());
+ painter->setBrush(fillColor);
+ painter->drawRoundedRect(boundingRect(), blockRadius, blockRadius);
painter->restore();
}
@@ -719,7 +755,7 @@ void FormEditorTransitionItem::updateGeometry()
QPointF toP = QmlItemNode(resolved.to).flowPosition();
if (QmlItemNode(resolved.to).isFlowDecision())
- sizeTo = QRectF(0, 0, flowBlockSize, flowBlockSize);
+ sizeTo = QRectF(0, 0, flowBlockSize * 2, flowBlockSize * 2);
qreal x1 = fromP.x();
qreal x2 = toP.x();
@@ -757,10 +793,10 @@ QPointF FormEditorTransitionItem::instancePosition() const
static bool verticalOverlap(const QRectF &from, const QRectF &to)
{
- if (from.top() < to.bottom() && (from.top() + from.height()) > to.top())
+ if (from.top() < to.bottom() && from.bottom() > to.top())
return true;
- if (to.top() < from.bottom() && (to.top() + to.height()) > from.top())
+ if (to.top() < from.bottom() && to.bottom() > from.top())
return true;
return false;
@@ -769,25 +805,231 @@ static bool verticalOverlap(const QRectF &from, const QRectF &to)
static bool horizontalOverlap(const QRectF &from, const QRectF &to)
{
- if (from.left() < to.right() && (from.left() + from.width()) > to.left())
+ if (from.left() < to.right() && from.right() > to.left())
return true;
- if (to.left() < from.right() && (to.left() + to.width()) > from.left())
+ if (to.left() < from.right() && to.right() > from.left())
return true;
return false;
}
+static void drawArrow(QPainter *painter,
+ const QLineF &line,
+ int arrowLength,
+ int arrowWidth)
+{
+ const QPointF peakP(0, 0);
+ const QPointF leftP(-arrowLength, -arrowWidth * 0.5);
+ const QPointF rightP(-arrowLength, arrowWidth * 0.5);
+
+ painter->save();
+
+ painter->translate(line.p2());
+ painter->rotate(-line.angle());
+ painter->drawLine(leftP, peakP);
+ painter->drawLine(rightP, peakP);
+
+ painter->restore();
+}
+
+static QPainterPath roundedCorner(const QPointF &s,
+ const QPointF &m,
+ const QPointF &e,
+ int radius)
+{
+ const QVector2D sm(m - s);
+ const QVector2D me(e - m);
+ const float smLength = sm.length();
+ const float meLength = me.length();
+ const int actualRadius = qMin(radius, static_cast<int>(qMin(smLength, meLength)));
+ const QVector2D smNorm = sm.normalized();
+ const QVector2D meNorm = me.normalized();
+ QRectF rect(m, QSizeF(actualRadius * 2, actualRadius * 2));
+
+ QPainterPath path(s);
+
+ if (smNorm.y() < 0 && meNorm.x() > 0) {
+ rect.moveTopLeft(m);
+ path.arcTo(rect, 180, -90);
+ } else if (smNorm.x() < 0 && meNorm.y() > 0) {
+ rect.moveTopLeft(m);
+ path.arcTo(rect, 90, 90);
+ } else if (smNorm.y() > 0 && meNorm.x() > 0) {
+ rect.moveBottomLeft(m);
+ path.arcTo(rect, 180, 90);
+ } else if (smNorm.x() < 0 && meNorm.y() < 0) {
+ rect.moveBottomLeft(m);
+ path.arcTo(rect, 270, -90);
+ } else if (smNorm.x() > 0 && meNorm.y() > 0) {
+ rect.moveTopRight(m);
+ path.arcTo(rect, 90, -90);
+ } else if (smNorm.y() < 0 && meNorm.x() < 0) {
+ rect.moveTopRight(m);
+ path.arcTo(rect, 0, 90);
+ } else if (smNorm.y() > 0 && meNorm.x() < 0) {
+ rect.moveBottomRight(m);
+ path.arcTo(rect, 0, -90);
+ } else if (smNorm.x() > 0 && meNorm.y() < 0) {
+ rect.moveBottomRight(m);
+ path.arcTo(rect, 270, 90);
+ }
+
+ path.lineTo(e);
+ return path;
+}
+
+// This function determines whether the vertices are in cw or ccw order.
+// It finds the lowest and rightmost vertex, and computes the cross-product
+// of the vectors along its incident edges.
+// Written by Joseph O'Rourke, 25 August 1995. orourke@cs.smith.edu
+// 1: ccw
+// 0: default
+// -1: cw
+
+static int counterClockWise(const std::vector<QPointF> &points)
+{
+ if (points.empty())
+ return 0;
+
+ // FindLR finds the lowest, rightmost point.
+ auto findLR = [](const std::vector<QPointF> &points) {
+ int i = 0;
+ int m = 0;
+ QPointF min = points.front();
+
+ for (const auto p : points) {
+ if ((p.y() < min.y()) || ((p.y() == min.y()) && (p.x() > min.x()))) {
+ m = i;
+ min = p;
+ }
+ ++i;
+ }
+ return m;
+ };
+
+ const int m = findLR(points);
+ const int n = points.size();
+
+ // Determine previous and next point to m (the lowest, rightmost point).
+ const QPointF a = points[(m + (n - 1)) % n];
+ const QPointF b = points[m];
+ const QPointF c = points[(m + 1) % n];
+
+ const int area = a.x() * b.y() - a.y() * b.x() +
+ a.y() * c.x() - a.x() * c.y() +
+ b.x() * c.y() - c.x() * b.y();
+
+ if (area > 0)
+ return 1;
+ else if (area < 0)
+ return -1;
+ else
+ return 0;
+}
+
+static QPainterPath quadBezier(const QPointF &s,
+ const QPointF &c,
+ const QPointF &e,
+ int bezier,
+ int breakOffset)
+{
+ QLineF se(s, e);
+ QPointF breakPoint = se.pointAt(breakOffset / 100.0);
+ QLineF breakLine;
+
+ if (counterClockWise({s, c, e}) == 1)
+ breakLine = QLineF(breakPoint, breakPoint + QPointF(se.dy(), -se.dx()));
+ else
+ breakLine = QLineF(breakPoint, breakPoint + QPointF(-se.dy(), se.dx()));
+
+ breakLine.setLength(se.length());
+
+ const QPointF controlPoint = breakLine.pointAt(bezier / 100.0);
+
+ QPainterPath path(s);
+ path.quadTo(controlPoint, e);
+
+ return path;
+}
+
+static QPainterPath cubicBezier(const QPointF &s,
+ const QPointF &c1,
+ const QPointF &c2,
+ const QPointF &e,
+ int bezier)
+{
+ QPainterPath path(s);
+ const QPointF adjustedC1 = QLineF(s, c1).pointAt(bezier / 100.0);
+ const QPointF adjustedC2 = QLineF(e, c2).pointAt(bezier / 100.0);
+
+ path.cubicTo(adjustedC1, adjustedC2, e);
+
+ return path;
+}
+
+
+static QPainterPath lShapedConnection(const QPointF &start,
+ const QPointF &end,
+ Qt::Orientation orientation,
+ const ConnectionStyle &style)
+{
+ const QPointF mid = (orientation == Qt::Horizontal) ? QPointF(end.x(), start.y())
+ : QPointF(start.x(), end.y());
+
+ if (style.type == ConnectionType::Default) {
+ if (style.radius == 0) {
+ QPainterPath path(start);
+ path.lineTo(mid);
+ path.lineTo(end);
+ return path;
+ } else {
+ return roundedCorner(start, mid, end, style.radius);
+ }
+ } else {
+ return quadBezier(start, mid, end, style.bezier, style.breakOffset);
+ }
+}
+
+static QPainterPath sShapedConnection(const QPointF &start,
+ const QPointF &end,
+ Qt::Orientation orientation,
+ const ConnectionStyle &style)
+{
+ const qreal middleFactor = style.breakOffset / 100.0;
+ QPointF mid1;
+ QPointF mid2;
+
+ if (orientation == Qt::Horizontal) {
+ mid1 = QPointF(start.x() * middleFactor + end.x() * (1 - middleFactor), start.y());
+ mid2 = QPointF(mid1.x(), end.y());
+ } else {
+ mid1 = QPointF(start.x(), start.y() * middleFactor + end.y() * (1 - middleFactor));
+ mid2 = QPointF(end.x(), mid1.y());
+ }
+
+ if (style.type == ConnectionType::Default) {
+ if (style.radius == 0) {
+ QPainterPath path(start);
+ path.lineTo(mid1);
+ path.lineTo(mid2);
+ path.lineTo(end);
+ return path;
+ } else {
+ const QLineF breakLine(mid1, mid2);
+ QPainterPath path1 = roundedCorner(start, mid1, breakLine.center(), style.radius);
+ QPainterPath path2 = roundedCorner(breakLine.center(), mid2, end, style.radius);
+ return path1 + path2;
+ }
+ } else {
+ return cubicBezier(start, mid1, mid2, end, style.bezier);
+ }
+}
+
static void paintConnection(QPainter *painter,
const QRectF &from,
const QRectF &to,
- qreal width,
- qreal adjustedWidth,
- const QColor &color,
- bool dash,
- int startOffset,
- int endOffset,
- int breakOffset)
+ const ConnectionStyle &style)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
@@ -796,23 +1038,22 @@ static void paintConnection(QPainter *painter,
pen.setCosmetic(true);
pen.setJoinStyle(Qt::MiterJoin);
pen.setCapStyle(Qt::RoundCap);
+ pen.setColor(style.color);
- pen.setColor(color);
-
- if (dash)
+ if (style.dash)
pen.setStyle(Qt::DashLine);
else
pen.setStyle(Qt::SolidLine);
- pen.setWidthF(width);
+ pen.setWidthF(style.width);
painter->setPen(pen);
//const bool forceVertical = false;
//const bool forceHorizontal = false;
- const int padding = 2 * width + 2 * adjustedWidth;
+ const int padding = 2 * style.width + 2 * style.adjustedWidth;
- const int arrowLength = 4 * adjustedWidth;
- const int arrowWidth = 8 * adjustedWidth;
+ const int arrowLength = 4 * style.adjustedWidth;
+ const int arrowWidth = 8 * style.adjustedWidth;
const bool boolExitRight = from.right() < to.center().x();
const bool boolExitBottom = from.bottom() < to.center().y();
@@ -824,10 +1065,6 @@ static void paintConnection(QPainter *painter,
horizontalFirst = false;
*/
- const qreal middleFactor = breakOffset / 100.0;
-
- QPointF startP;
-
bool extraLine = false;
if (horizontalFirst) {
@@ -849,131 +1086,50 @@ static void paintConnection(QPainter *painter,
}
}
- if (horizontalFirst) {
- const qreal startY = from.center().y() + startOffset;
- qreal startX = from.x() - padding;
- if (boolExitRight)
- startX = from.right() + padding;
+ QPointF startP;
+ QPointF endP;
+ QPainterPath path;
+ if (horizontalFirst) {
+ const qreal startX = boolExitRight ? from.right() + padding : from.x() - padding;
+ const qreal startY = from.center().y() + style.outOffset;
startP = QPointF(startX, startY);
- qreal endY = to.top() - padding;
-
- if (from.bottom() > to.y())
- endY = to.bottom() + padding;
-
if (!extraLine) {
-
-
- const qreal endX = to.center().x() + endOffset;
-
- const QPointF midP(endX, startY);
-
- const QPointF endP(endX, endY);
-
- painter->drawLine(startP, midP);
- painter->drawLine(midP, endP);
-
- int flip = 1;
-
- if (midP.y() < endP.y())
- flip = -1;
-
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- painter->drawLine(endP + flip * QPoint(arrowWidth / 2, arrowLength), endP);
- painter->drawLine(endP + flip * QPoint(-arrowWidth / 2, arrowLength), endP);
+ const qreal endY = (from.bottom() > to.y()) ? to.bottom() + padding : to.top() - padding;
+ endP = QPointF(to.center().x() + style.inOffset, endY);
+ path = lShapedConnection(startP, endP, Qt::Horizontal, style);
} else {
-
- qreal endX = to.left() - padding;
-
- if (from.right() > to.x())
- endX = to.right() + padding;
-
- const qreal midX = startX * middleFactor + endX * (1-middleFactor);
- const QPointF midP(midX, startY);
- const QPointF midP2(midX, to.center().y() + endOffset);
- const QPointF endP(endX, to.center().y() + endOffset);
- painter->drawLine(startP, midP);
- painter->drawLine(midP, midP2);
- painter->drawLine(midP2, endP);
-
- int flip = 1;
-
- if (midP2.x() < endP.x())
- flip = -1;
-
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- painter->drawLine(endP + flip * QPoint(arrowWidth / 2, arrowWidth / 2), endP);
- painter->drawLine(endP + flip * QPoint(arrowLength, -arrowWidth / 2), endP);
+ const qreal endX = (from.right() > to.x()) ? to.right() + padding : to.left() - padding;
+ endP = QPointF(endX, to.center().y() + style.inOffset);
+ path = sShapedConnection(startP, endP, Qt::Horizontal, style);
}
-
} else {
- const qreal startX = from.center().x() + startOffset;
-
- qreal startY = from.top() - padding;
- if (boolExitBottom)
- startY = from.bottom() + padding;
-
+ const qreal startX = from.center().x() + style.outOffset;
+ const qreal startY = boolExitBottom ? from.bottom() + padding : from.top() - padding;
startP = QPointF(startX, startY);
- qreal endX = to.left() - padding;
-
- if (from.right() > to.x())
- endX = to.right() + padding;
if (!extraLine) {
- const qreal endY = to.center().y() + endOffset;
-
- const QPointF midP(startX, endY);
-
- const QPointF endP(endX, endY);
-
- painter->drawLine(startP, midP);
- painter->drawLine(midP, endP);
-
- int flip = 1;
-
- if (midP.x() < endP.x())
- flip = -1;
-
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- painter->drawLine(endP + flip * QPoint(arrowWidth / 2, arrowWidth / 2), endP);
- painter->drawLine(endP + flip * QPoint(arrowLength, -arrowWidth / 2), endP);
+ const qreal endX = (from.right() > to.x()) ? to.right() + padding : to.left() - padding;
+ endP = QPointF(endX, to.center().y() + style.inOffset);
+ path = lShapedConnection(startP, endP, Qt::Vertical, style);
} else {
-
- qreal endY = to.top() - padding;
-
- if (from.bottom() > to.y())
- endY = to.bottom() + padding;
-
- const qreal midY = startY * middleFactor + endY * (1-middleFactor);
- const QPointF midP(startX, midY);
- const QPointF midP2(to.center().x() + endOffset, midY);
- const QPointF endP(to.center().x() + endOffset, endY);
-
- painter->drawLine(startP, midP);
- painter->drawLine(midP, midP2);
- painter->drawLine(midP2, endP);
-
- int flip = 1;
-
- if (midP2.y() < endP.y())
- flip = -1;
-
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- painter->drawLine(endP + flip * QPoint(arrowWidth / 2, arrowLength), endP);
- painter->drawLine(endP + flip * QPoint(-arrowWidth / 2, arrowLength), endP);
+ const qreal endY = (from.bottom() > to.y()) ? to.bottom() + padding : to.top() - padding;
+ endP = QPointF(to.center().x() + style.inOffset, endY);
+ path = sShapedConnection(startP, endP, Qt::Vertical, style);
}
}
- pen.setWidthF(width);
+ painter->drawPath(path);
+
+ pen.setWidthF(style.width);
pen.setStyle(Qt::SolidLine);
painter->setPen(pen);
+
+ drawArrow(painter, QLineF(path.pointAtPercent(0.9), endP), arrowLength, arrowWidth);
+
painter->setBrush(Qt::white);
- painter->drawEllipse(startP, arrowLength / 3, arrowLength / 3);
+ painter->drawEllipse(startP, arrowLength / 3, arrowLength / 3);
painter->restore();
}
@@ -991,6 +1147,8 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+
ResolveConnection resolved(qmlItemNode());
if (!resolved.from.modelNode().isValid())
@@ -1022,77 +1180,108 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
toRect.translate(QmlItemNode(resolved.to).flowPosition());
if (resolved.isStartLine) {
- fromRect = QRectF(0,0,50,50);
- fromRect.translate(QmlItemNode(resolved.to).flowPosition() + QPoint(-120, toRect.height() / 2 - 25));
+ fromRect = QRectF(0, 0, 96, 96);
+ fromRect.translate(QmlItemNode(resolved.to).flowPosition() + QPoint(-180, toRect.height() / 2 - 96 / 2));
}
toRect.translate(-pos());
fromRect.translate(-pos());
- qreal width = 2;
+ ConnectionStyle style;
+
+ style.width = 2;
const qreal scaleFactor = viewportTransform().m11();
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
- width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
+ style.width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
- qreal adjustedWidth = width / scaleFactor;
+ style.adjustedWidth = style.width / scaleFactor;
if (qmlItemNode().modelNode().isSelected())
- width += 2;
+ style.width += 2;
if (m_hitTest)
- width *= 8;
+ style.width *= 8;
- QColor color = "#e71919";
+ style.color = "#e71919";
if (resolved.isStartLine)
- color = "blue";
+ style.color = "blue";
if (resolved.isWildcardLine)
- color = "green";
-
- bool dash = false;
+ style.color = "green";
if (qmlItemNode().rootModelNode().hasAuxiliaryData("transitionColor"))
- color = qmlItemNode().rootModelNode().auxiliaryData("transitionColor").value<QColor>();
+ style.color = qmlItemNode().rootModelNode().auxiliaryData("transitionColor").value<QColor>();
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
- color = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
+ style.color = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
+
+ style.dash = false;
if (qmlItemNode().modelNode().hasAuxiliaryData("dash"))
- dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
+ style.dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
- int outOffset = 0;
- int inOffset = 0;
+ style.outOffset = 0;
+ style.inOffset = 0;
if (qmlItemNode().modelNode().hasAuxiliaryData("outOffset"))
- outOffset = qmlItemNode().modelNode().auxiliaryData("outOffset").toInt();
+ style.outOffset = qmlItemNode().modelNode().auxiliaryData("outOffset").toInt();
if (qmlItemNode().modelNode().hasAuxiliaryData("inOffset"))
- inOffset = qmlItemNode().modelNode().auxiliaryData("inOffset").toInt();
+ style.inOffset = qmlItemNode().modelNode().auxiliaryData("inOffset").toInt();
- int breakOffset = 50;
+ style.breakOffset = 50;
if (qmlItemNode().modelNode().hasAuxiliaryData("breakPoint"))
- breakOffset = qmlItemNode().modelNode().auxiliaryData("breakPoint").toInt();
+ style.breakOffset = qmlItemNode().modelNode().auxiliaryData("breakPoint").toInt();
+
+ style.radius = 8;
+
+ if (qmlItemNode().rootModelNode().hasAuxiliaryData("transitionRadius"))
+ style.radius = qmlItemNode().rootModelNode().auxiliaryData("transitionRadius").toInt();
+
+ if (qmlItemNode().modelNode().hasAuxiliaryData("radius"))
+ style.radius = qmlItemNode().modelNode().auxiliaryData("radius").toInt();
+
+ style.bezier = 50;
+
+ if (qmlItemNode().rootModelNode().hasAuxiliaryData("transitionBezier"))
+ style.bezier = qmlItemNode().rootModelNode().auxiliaryData("transitionBezier").toInt();
+
+ if (qmlItemNode().modelNode().hasAuxiliaryData("bezier"))
+ style.bezier = qmlItemNode().modelNode().auxiliaryData("bezier").toInt();
+
+ style.type = ConnectionType::Default;
- paintConnection(painter, fromRect, toRect, width, adjustedWidth ,color, dash, outOffset, inOffset, breakOffset);
+ if (qmlItemNode().rootModelNode().hasAuxiliaryData("transitionType"))
+ style.type = static_cast<ConnectionType>(qmlItemNode().rootModelNode().auxiliaryData("transitionType").toInt());
+
+ if (qmlItemNode().modelNode().hasAuxiliaryData("type"))
+ style.type = static_cast<ConnectionType>(qmlItemNode().modelNode().auxiliaryData("type").toInt());
+
+ if (resolved.isStartLine)
+ fromRect.translate(0, style.outOffset);
+
+ paintConnection(painter, fromRect, toRect, style);
if (resolved.isStartLine) {
+
+ const QString icon = Theme::getIconUnicode(Theme::startNode);
+
QPen pen;
pen.setCosmetic(true);
-
- pen.setColor(color);
+ pen.setColor(style.color);
painter->setPen(pen);
- painter->drawRect(fromRect);
-
- if (scaleFactor > 0.4) {
- painter->drawLine(fromRect.topRight() + QPoint(20,10), fromRect.bottomRight() + QPoint(20,-10));
- painter->drawLine(fromRect.topRight() + QPoint(25,12), fromRect.bottomRight() + QPoint(25,-12));
- painter->drawLine(fromRect.topRight() + QPoint(30,15), fromRect.bottomRight() + QPoint(30,-15));
- painter->drawLine(fromRect.topRight() + QPoint(35,17), fromRect.bottomRight() + QPoint(35,-17));
- painter->drawLine(fromRect.topRight() + QPoint(40,20), fromRect.bottomRight() + QPoint(40,-20));
- }
+
+ const int iconAdjust = 48;
+ const int offset = 96;
+ const int size = fromRect.width();
+ const int iconSize = size - iconAdjust;
+ const int x = fromRect.topRight().x() - offset;
+ const int y = fromRect.topRight().y();
+ painter->drawRoundedRect(x, y , size - 10, size, size / 2, iconSize / 2);
+ drawIcon(painter, x + iconAdjust / 2, y + iconAdjust / 2, icon, iconSize, iconSize, style.color);
}
painter->restore();
@@ -1141,6 +1330,9 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform);
+
QPen pen;
pen.setJoinStyle(Qt::MiterJoin);
pen.setCosmetic(true);
@@ -1179,20 +1371,37 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor"))
fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value<QColor>();
+ painter->save();
+
+ if (m_iconType == DecisionIcon) {
+ painter->translate(boundingRect().center());
+ painter->rotate(45);
+ painter->translate(-boundingRect().center());
+ }
+
if (fillColor.alpha() > 0)
- painter->fillRect(boundingRect(), fillColor);
+ painter->setBrush(fillColor);
- painter->drawLine(boundingRect().left(), boundingRect().center().y(),
- boundingRect().center().x(), boundingRect().top());
+ int radius = blockRadius;
- painter->drawLine(boundingRect().center().x(), boundingRect().top(),
- boundingRect().right(), boundingRect().center().y());
+ const QRectF adjustedRect = boundingRect().adjusted(blockAdjust,
+ blockAdjust,
+ -blockAdjust,
+ -blockAdjust);
+
+ painter->drawRoundedRect(adjustedRect, radius, radius);
+
+ const int iconDecrement = 32;
+ const int iconSize = adjustedRect.width() - iconDecrement;
+ const int offset = iconDecrement / 2 + blockAdjust;
+
+ painter->restore();
- painter->drawLine(boundingRect().right(), boundingRect().center().y(),
- boundingRect().center().x(), boundingRect().bottom());
+ const QString icon = (m_iconType ==
+ WildcardIcon) ? Theme::getIconUnicode(Theme::wildcard)
+ : Theme::getIconUnicode(Theme::decisionNode);
- painter->drawLine(boundingRect().center().x(), boundingRect().bottom(),
- boundingRect().left(), boundingRect().center().y());
+ drawIcon(painter, offset, offset, icon, iconSize, iconSize, flowColor);
painter->restore();
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
index d725afd0b0..8569059b7a 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
@@ -47,6 +47,27 @@ namespace Internal {
class MoveController;
}
+enum ConnectionType
+{
+ Default = 0,
+ Bezier
+};
+
+class ConnectionStyle
+{
+public:
+ qreal width;
+ qreal adjustedWidth;
+ QColor color;
+ bool dash;
+ int outOffset;
+ int inOffset;
+ int breakOffset;
+ int radius;
+ int bezier;
+ ConnectionType type;
+};
+
class QMLDESIGNERCORE_EXPORT FormEditorItem : public QGraphicsItem
{
friend class QmlDesigner::FormEditorScene;
@@ -207,9 +228,17 @@ public:
bool flowHitTest(const QPointF &point) const override;
protected:
- FormEditorFlowDecisionItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
- : FormEditorFlowItem(qmlItemNode, scene)
+ enum IconType {
+ DecisionIcon,
+ WildcardIcon
+ };
+
+ FormEditorFlowDecisionItem(const QmlItemNode &qmlItemNode,
+ FormEditorScene* scene,
+ IconType iconType = DecisionIcon)
+ : FormEditorFlowItem(qmlItemNode, scene), m_iconType(iconType)
{}
+ IconType m_iconType;
};
class FormEditorFlowWildcardItem : FormEditorFlowDecisionItem
@@ -221,8 +250,9 @@ public:
protected:
FormEditorFlowWildcardItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
- : FormEditorFlowDecisionItem(qmlItemNode, scene)
- {}
+ : FormEditorFlowDecisionItem(qmlItemNode, scene, WildcardIcon)
+ {
+ }
};
inline int FormEditorItem::type() const
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
index 49bb98db4a..8907aab2bc 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp
@@ -97,8 +97,11 @@ void ResizeManipulator::begin(const QPointF &/*beginPoint*/)
// return QSizeF(sizeAsPoint.x(), sizeAsPoint.y());
//}
-void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping useSnapping)
+void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping useSnapping, Qt::KeyboardModifiers keyMods)
{
+ const bool preserveAspectRatio = keyMods.testFlag(Qt::ShiftModifier);
+ const bool resizeFromCenter = keyMods.testFlag(Qt::AltModifier);
+
const double minimumWidth = 0.0;
const double minimumHeight = 0.0;
@@ -118,6 +121,16 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
QmlAnchors anchors(formEditorItem->qmlItemNode().anchors());
QRectF boundingRect(m_beginBoundingRect);
+
+ auto getRatioSizes = [&](){
+ double ratio = std::min(boundingRect.width() / m_beginBoundingRect.width(),
+ boundingRect.height() / m_beginBoundingRect.height());
+ double newW = m_beginBoundingRect.width() * ratio;
+ double newH = m_beginBoundingRect.height() * ratio;
+
+ return QSizeF(newW, newH);
+ };
+
if (m_resizeHandle->isBottomRightHandle()) {
boundingRect.setBottomRight(updatePointInLocalSpace);
@@ -132,6 +145,28 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
}
boundingRect.setBottomRight(updatePointInLocalSpace);
+ if (preserveAspectRatio) {
+ QSizeF newSize = getRatioSizes();
+
+ updatePointInLocalSpace.rx() = (boundingRect.topLeft().x() + newSize.width());
+ updatePointInLocalSpace.ry() = (boundingRect.topLeft().y() + newSize.height());
+
+ boundingRect.setBottomRight(updatePointInLocalSpace);
+ }
+
+ if (resizeFromCenter) {
+ QPointF grow = { boundingRect.width() - m_beginBoundingRect.width(),
+ boundingRect.height() - m_beginBoundingRect.height() };
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineTop))
+ boundingRect.setTop(boundingRect.top() - grow.y());
+ if (!anchors.instanceHasAnchor(AnchorLineLeft))
+ boundingRect.setLeft(boundingRect.left() - grow.x());
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
@@ -144,6 +179,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setHeight(minimumHeight);
formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
if (anchors.instanceHasAnchor(AnchorLineBottom)) {
anchors.setMargin(AnchorLineBottom,
@@ -168,6 +204,28 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
}
boundingRect.setTopLeft(updatePointInLocalSpace);
+ if (preserveAspectRatio) {
+ QSizeF newSize = getRatioSizes();
+
+ updatePointInLocalSpace.rx() = (boundingRect.bottomRight().x() - newSize.width());
+ updatePointInLocalSpace.ry() = (boundingRect.bottomRight().y() - newSize.height());
+
+ boundingRect.setTopLeft(updatePointInLocalSpace);
+ }
+
+ if (resizeFromCenter) {
+ QPointF grow = { boundingRect.width() - m_beginBoundingRect.width(),
+ boundingRect.height() - m_beginBoundingRect.height() };
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineBottom))
+ boundingRect.setBottom(boundingRect.bottom() + grow.y());
+ if (!anchors.instanceHasAnchor(AnchorLineRight))
+ boundingRect.setRight(boundingRect.right() + grow.x());
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
@@ -208,6 +266,28 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
}
boundingRect.setTopRight(updatePointInLocalSpace);
+ if (preserveAspectRatio) {
+ QSizeF newSize = getRatioSizes();
+
+ updatePointInLocalSpace.rx() = (boundingRect.bottomLeft().x() + newSize.width());
+ updatePointInLocalSpace.ry() = (boundingRect.bottomLeft().y() - newSize.height());
+
+ boundingRect.setTopRight(updatePointInLocalSpace);
+ }
+
+ if (resizeFromCenter) {
+ QPointF grow = { boundingRect.width() - m_beginBoundingRect.width(),
+ boundingRect.height() - m_beginBoundingRect.height() };
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineBottom))
+ boundingRect.setBottom(boundingRect.bottom() + grow.y());
+ if (!anchors.instanceHasAnchor(AnchorLineLeft))
+ boundingRect.setLeft(boundingRect.left() - grow.x());
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
@@ -246,6 +326,28 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setBottomLeft(updatePointInLocalSpace);
+ if (preserveAspectRatio) {
+ QSizeF newSize = getRatioSizes();
+
+ updatePointInLocalSpace.rx() = (boundingRect.topRight().x() - newSize.width());
+ updatePointInLocalSpace.ry() = (boundingRect.topRight().y() + newSize.height());
+
+ boundingRect.setBottomLeft(updatePointInLocalSpace);
+ }
+
+ if (resizeFromCenter) {
+ QPointF grow = { boundingRect.width() - m_beginBoundingRect.width(),
+ boundingRect.height() - m_beginBoundingRect.height() };
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineTop))
+ boundingRect.setTop(boundingRect.top() - grow.y());
+ if (!anchors.instanceHasAnchor(AnchorLineRight))
+ boundingRect.setRight(boundingRect.right() + grow.x());
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
@@ -280,13 +382,30 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setBottom(updatePointInLocalSpace.y());
+ if (resizeFromCenter) {
+ double grow = boundingRect.height() - m_beginBoundingRect.height();
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineTop))
+ boundingRect.setTop(boundingRect.top() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineLeft))
+ boundingRect.setLeft(boundingRect.left() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineRight))
+ boundingRect.setRight(boundingRect.right() + grow);
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineVerticalCenter))
boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom()));
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setWidth(minimumWidth);
if (boundingRect.height() < minimumHeight)
boundingRect.setHeight(minimumHeight);
formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
if (anchors.instanceHasAnchor(AnchorLineBottom)) {
anchors.setMargin(AnchorLineBottom,
@@ -303,9 +422,25 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setTop(updatePointInLocalSpace.y());
+ if (resizeFromCenter) {
+ double grow = boundingRect.height() - m_beginBoundingRect.height();
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineBottom))
+ boundingRect.setBottom(boundingRect.bottom() + grow);
+ if (!anchors.instanceHasAnchor(AnchorLineLeft))
+ boundingRect.setLeft(boundingRect.left() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineRight))
+ boundingRect.setRight(boundingRect.right() + grow);
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineVerticalCenter))
boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top()));
+ if (boundingRect.width() < minimumWidth)
+ boundingRect.setWidth(minimumWidth);
if (boundingRect.height() < minimumHeight)
boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height());
@@ -327,13 +462,30 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setRight(updatePointInLocalSpace.x());
+ if (resizeFromCenter) {
+ double grow = boundingRect.width() - m_beginBoundingRect.width();
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineTop))
+ boundingRect.setTop(boundingRect.top() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineLeft))
+ boundingRect.setLeft(boundingRect.left() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineBottom))
+ boundingRect.setBottom(boundingRect.bottom() + grow);
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right()));
if (boundingRect.width() < minimumWidth)
boundingRect.setWidth(minimumWidth);
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setHeight(minimumHeight);
formEditorItem->qmlItemNode().setSize(boundingRect.size());
+ formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
if (anchors.instanceHasAnchor(AnchorLineRight)) {
@@ -351,11 +503,27 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapper::Snapping use
boundingRect.setLeft(updatePointInLocalSpace.x());
+ if (resizeFromCenter) {
+ double grow = boundingRect.width() - m_beginBoundingRect.width();
+
+ if (!anchors.instanceHasAnchor(AnchorLineHorizontalCenter)
+ && !anchors.instanceHasAnchor(AnchorLineVerticalCenter)) {
+ if (!anchors.instanceHasAnchor(AnchorLineTop))
+ boundingRect.setTop(boundingRect.top() - grow);
+ if (!anchors.instanceHasAnchor(AnchorLineBottom))
+ boundingRect.setBottom(boundingRect.bottom() + grow);
+ if (!anchors.instanceHasAnchor(AnchorLineRight))
+ boundingRect.setRight(boundingRect.right() + grow);
+ }
+ }
+
if (anchors.instanceHasAnchor(AnchorLineHorizontalCenter))
boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left()));
if (boundingRect.width() < minimumWidth)
boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width());
+ if (boundingRect.height() < minimumHeight)
+ boundingRect.setHeight(minimumHeight);
formEditorItem->qmlItemNode().setSize(boundingRect.size());
formEditorItem->qmlItemNode().setPosition(m_beginToParentTransform.map(boundingRect.topLeft()));
diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h
index ab4f97f9cb..551006d161 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h
+++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h
@@ -46,7 +46,8 @@ public:
void removeHandle();
void begin(const QPointF& beginPoint);
- void update(const QPointF& updatePoint, Snapper::Snapping useSnapping);
+ void update(const QPointF& updatePoint, Snapper::Snapping useSnapping,
+ Qt::KeyboardModifiers keyMods = Qt::NoModifier);
void end(Snapper::Snapping useSnapping);
void moveBy(double deltaX, double deltaY);
diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
index 8b4e5c552a..e959a4b6b1 100644
--- a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp
@@ -71,7 +71,8 @@ void ResizeTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
QGraphicsSceneMouseEvent *event)
{
if (m_resizeManipulator.isActive())
- m_resizeManipulator.update(event->scenePos(), generateUseSnapping(event->modifiers()));
+ m_resizeManipulator.update(event->scenePos(), generateUseSnapping(event->modifiers()),
+ event->modifiers());
}
void ResizeTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
diff --git a/src/plugins/qmldesigner/components/formeditor/transitiontool.cpp b/src/plugins/qmldesigner/components/formeditor/transitiontool.cpp
new file mode 100644
index 0000000000..e8222e8ac8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/transitiontool.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#include "transitiontool.h"
+
+#include <formeditorscene.h>
+#include <formeditorview.h>
+#include <formeditorwidget.h>
+#include <itemutilfunctions.h>
+#include <formeditoritem.h>
+#include <layeritem.h>
+
+#include <resizehandleitem.h>
+
+#include <bindingproperty.h>
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <qmlitemnode.h>
+#include <qmldesignerplugin.h>
+#include <abstractaction.h>
+#include <designeractionmanager.h>
+#include <variantproperty.h>
+#include <rewritingexception.h>
+#include <rewritertransaction.h>
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QAction>
+#include <QMessageBox>
+#include <QPair>
+#include <QGraphicsSceneMouseEvent>
+
+namespace QmlDesigner {
+
+static bool isTransitionSource(const ModelNode &node)
+{
+ return QmlFlowTargetNode::isFlowEditorTarget(node);
+}
+
+static bool isTransitionTarget(const QmlItemNode &node)
+{
+ return QmlFlowTargetNode::isFlowEditorTarget(node)
+ && !node.isFlowActionArea()
+ && !node.isFlowWildcard();
+}
+
+class TransitionToolAction : public AbstractAction
+{
+public:
+ TransitionToolAction(const QString &name) : AbstractAction(name) {}
+
+ QByteArray category() const override
+ {
+ return QByteArray();
+ }
+
+ QByteArray menuId() const override
+ {
+ return "TransitionTool";
+ }
+
+ int priority() const override
+ {
+ return CustomActionsPriority;
+ }
+
+ Type type() const override
+ {
+ return ContextMenuAction;
+ }
+
+protected:
+ bool isVisible(const SelectionContext &selectionContext) const override
+ {
+ if (selectionContext.scenePosition().isNull())
+ return false;
+
+ if (selectionContext.singleNodeIsSelected())
+ return isTransitionSource(selectionContext.currentSingleSelectedNode());
+
+ return false;
+ }
+
+ bool isEnabled(const SelectionContext &selectionContext) const override
+ {
+ return isVisible(selectionContext);
+ }
+};
+
+class TransitionCustomAction : public TransitionToolAction
+{
+public:
+ TransitionCustomAction(const QString &name) : TransitionToolAction(name) {}
+
+ QByteArray category() const override
+ {
+ return ComponentCoreConstants::flowCategory;
+ }
+
+ SelectionContext selectionContext() const
+ {
+ return AbstractAction::selectionContext();
+ }
+
+};
+
+static QRectF paintedBoundingRect(FormEditorItem *item)
+{
+ QRectF boundingRect = item->qmlItemNode().instanceBoundingRect();
+ if (boundingRect.width() < 4)
+ boundingRect = item->boundingRect();
+ return boundingRect;
+}
+
+static QPointF centerPoint(FormEditorItem *item)
+{
+ QRectF boundingRect = paintedBoundingRect(item);
+ return QPointF(item->scenePos().x() + boundingRect.width() / 2,
+ item->scenePos().y() + boundingRect.height() / 2);
+}
+
+void static setToBoundingRect(QGraphicsRectItem *rect, FormEditorItem *item)
+{
+ QPolygonF boundingRectInSceneSpace(item->mapToScene(paintedBoundingRect(item)));
+ rect->setRect(boundingRectInSceneSpace.boundingRect());
+}
+
+TransitionTool::TransitionTool()
+ : QObject(), AbstractCustomTool()
+{
+
+ TransitionToolAction *transitionToolAction = new TransitionToolAction(tr("Add Transition"));
+ QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(transitionToolAction);
+
+ connect(transitionToolAction->action(), &QAction::triggered,
+ this, &TransitionTool::activateTool);
+
+ TransitionCustomAction *removeAction = new TransitionCustomAction(tr("Remove Transitions"));
+ QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeAction);
+
+ connect(removeAction->action(), &QAction::triggered,
+ this, [removeAction](){
+
+ SelectionContext context = removeAction->selectionContext();
+ QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
+
+ context.view()->executeInTransaction("Remove Transitions", [&node](){
+ if (node.isValid())
+ node.removeTransitions();
+ });
+ });
+
+ TransitionCustomAction *removeAllTransitionsAction = new TransitionCustomAction(tr("Remove All Transitions"));
+ QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeAllTransitionsAction);
+
+ connect(removeAllTransitionsAction->action(), &QAction::triggered,
+ this, [removeAllTransitionsAction](){
+
+ if (QMessageBox::question(Core::ICore::dialogParent(),
+ tr("Remove All Transitions"),
+ tr("Do you really want to remove all transitions?"),
+ QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
+ return;
+
+ SelectionContext context = removeAllTransitionsAction->selectionContext();
+ QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
+
+ context.view()->executeInTransaction("Remove All Transitions", [&node](){
+ if (node.isValid() && node.flowView().isValid())
+ node.flowView().removeAllTransitions();
+ });
+ });
+
+ TransitionCustomAction *removeDanglingTransitionAction = new TransitionCustomAction(tr("Remove Dangling Transitions"));
+ QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeDanglingTransitionAction);
+
+ connect(removeDanglingTransitionAction->action(), &QAction::triggered,
+ this, [removeDanglingTransitionAction](){
+
+ SelectionContext context = removeDanglingTransitionAction->selectionContext();
+ QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
+
+ context.view()->executeInTransaction("Remove Dangling Transitions", [&node](){
+ if (node.isValid() && node.flowView().isValid())
+ node.flowView().removeDanglingTransitions();
+ });
+ });
+}
+
+TransitionTool::~TransitionTool()
+{
+}
+
+void TransitionTool::clear()
+{
+ m_lineItem.reset(nullptr);
+ m_rectangleItem1.reset(nullptr);
+ m_rectangleItem2.reset(nullptr);
+
+ AbstractFormEditorTool::clear();
+}
+
+void TransitionTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_blockEvents)
+ return;
+
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ AbstractFormEditorTool::mousePressEvent(itemList, event);
+ TransitionTool::mouseMoveEvent(itemList, event);
+}
+
+void TransitionTool::mouseMoveEvent(const QList<QGraphicsItem*> & itemList,
+ QGraphicsSceneMouseEvent * event)
+{
+ if (!m_lineItem)
+ return;
+
+ QTC_ASSERT(currentFormEditorItem(), return);
+
+ const QPointF pos = centerPoint(m_formEditorItem);
+ lineItem()->setLine(pos.x(),
+ pos.y(),
+ event->scenePos().x(),
+ event->scenePos().y());
+
+ FormEditorItem *formEditorItem = nearestFormEditorItem(event->scenePos(), itemList);
+
+ if (formEditorItem
+ && formEditorItem->qmlItemNode().isValid()
+ && isTransitionTarget(formEditorItem->qmlItemNode().modelNode())) {
+ rectangleItem2()->setVisible(true);
+ setToBoundingRect(rectangleItem2(), formEditorItem);
+ } else {
+ rectangleItem2()->setVisible(false);
+ }
+}
+
+void TransitionTool::hoverMoveEvent(const QList<QGraphicsItem*> & itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ mouseMoveEvent(itemList, event);
+}
+
+void TransitionTool::keyPressEvent(QKeyEvent * /*keyEvent*/)
+{
+}
+
+void TransitionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
+{
+ view()->changeToSelectionTool();
+}
+
+void TransitionTool::dragLeaveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
+{
+}
+
+void TransitionTool::dragMoveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
+{
+}
+
+void TransitionTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event)
+{
+ if (m_blockEvents)
+ return;
+
+ if (event->button() == Qt::LeftButton) {
+ FormEditorItem *formEditorItem = nearestFormEditorItem(event->scenePos(), itemList);
+
+ if (formEditorItem
+ && QmlFlowTargetNode(formEditorItem->qmlItemNode().modelNode()).isValid())
+ createTransition(m_formEditorItem, formEditorItem);
+ }
+
+ view()->changeToSelectionTool();
+}
+
+
+void TransitionTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent *event)
+{
+ AbstractFormEditorTool::mouseDoubleClickEvent(itemList, event);
+}
+
+void TransitionTool::itemsAboutToRemoved(const QList<FormEditorItem*> &)
+{
+ view()->changeCurrentToolTo(this);
+}
+
+void TransitionTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
+{
+ if (!itemList.isEmpty()) {
+ createItems();
+
+ m_formEditorItem = itemList.first();
+ setToBoundingRect(rectangleItem1(), m_formEditorItem);
+ }
+}
+
+void TransitionTool::instancesCompleted(const QList<FormEditorItem*> & /*itemList*/)
+{
+}
+
+void TransitionTool::instancesParentChanged(const QList<FormEditorItem *> & /*itemList*/)
+{
+}
+
+void TransitionTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > & /*propertyList*/)
+{
+}
+
+void TransitionTool::formEditorItemsChanged(const QList<FormEditorItem*> & /*itemList*/)
+{
+}
+
+int TransitionTool::wantHandleItem(const ModelNode &modelNode) const
+{
+ if (isTransitionSource(modelNode))
+ return 10;
+
+ return 0;
+}
+
+QString TransitionTool::name() const
+{
+ return tr("Transition Tool");
+}
+
+void TransitionTool::activateTool()
+{
+ view()->changeToCustomTool();
+}
+
+void TransitionTool::unblock()
+{
+ m_blockEvents = false;
+}
+
+QGraphicsLineItem *TransitionTool::lineItem()
+{
+ return m_lineItem.get();
+}
+
+QGraphicsRectItem *TransitionTool::rectangleItem1()
+{
+ return m_rectangleItem1.get();
+}
+
+QGraphicsRectItem *TransitionTool::rectangleItem2()
+{
+ return m_rectangleItem2.get();
+}
+
+FormEditorItem *TransitionTool::currentFormEditorItem() const
+{
+ if (scene()->items().contains(m_formEditorItem))
+ return m_formEditorItem;
+
+ return nullptr;
+}
+
+void TransitionTool::createItems() {
+ m_blockEvents = true;
+ QTimer::singleShot(200, this, [this](){ unblock(); });
+
+ if (!lineItem())
+ m_lineItem.reset(new QGraphicsLineItem(scene()->manipulatorLayerItem()));
+
+ if (!rectangleItem1())
+ m_rectangleItem1.reset(new QGraphicsRectItem(scene()->manipulatorLayerItem()));
+
+ if (!rectangleItem2())
+ m_rectangleItem2.reset(new QGraphicsRectItem(scene()->manipulatorLayerItem()));
+
+ m_rectangleItem2->setVisible(false);
+
+ QPen pen;
+ pen.setColor(QColor(Qt::lightGray));
+ pen.setStyle(Qt::DashLine);
+ pen.setWidth(0);
+ m_lineItem->setPen(pen);
+
+ pen.setColor(QColor(108, 141, 221));
+ pen.setStyle(Qt::SolidLine);
+ pen.setWidth(4);
+ pen.setCosmetic(true);
+ m_rectangleItem1->setPen(pen);
+
+ m_rectangleItem2->setPen(pen);
+}
+
+void TransitionTool::createTransition(FormEditorItem *source, FormEditorItem *target)
+{
+ QmlFlowTargetNode sourceNode(source->qmlItemNode().modelNode());
+ QmlFlowTargetNode targetNode(target->qmlItemNode().modelNode());
+
+ if (sourceNode.isValid() && targetNode.isValid()
+ && sourceNode != targetNode
+ && !targetNode.isFlowActionArea()
+ && !targetNode.isFlowWildcard()) {
+ view()->executeInTransaction("create transition", [&sourceNode, targetNode](){
+ sourceNode.assignTargetItem(targetNode);
+ });
+ } else {
+ qWarning() << Q_FUNC_INFO << "nodes invalid";
+ }
+}
+
+}
diff --git a/src/plugins/qmldesigner/components/formeditor/transitiontool.h b/src/plugins/qmldesigner/components/formeditor/transitiontool.h
new file mode 100644
index 0000000000..43c3894933
--- /dev/null
+++ b/src/plugins/qmldesigner/components/formeditor/transitiontool.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+#pragma once
+
+#include "abstractcustomtool.h"
+#include "selectionindicator.h"
+
+#include <QGraphicsLineItem>
+#include <QHash>
+#include <QPointer>
+
+#include <memory>
+
+namespace QmlDesigner {
+
+class TransitionTool : public QObject, public AbstractCustomTool
+{
+ Q_OBJECT
+public:
+ TransitionTool();
+ ~TransitionTool();
+
+ void mousePressEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) override;
+ void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) override;
+ void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) override;
+ void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) override;
+ void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneMouseEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *keyEvent) override;
+
+ void dragLeaveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneDragDropEvent * event) override;
+ void dragMoveEvent(const QList<QGraphicsItem*> &itemList,
+ QGraphicsSceneDragDropEvent * event) override;
+
+ void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList) override;
+
+ void selectedItemsChanged(const QList<FormEditorItem*> &itemList) override;
+
+ void instancesCompleted(const QList<FormEditorItem*> &itemList) override;
+ void instancesParentChanged(const QList<FormEditorItem *> &itemList) override;
+ void instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
+
+ void clear() override;
+
+ void formEditorItemsChanged(const QList<FormEditorItem*> &itemList) override;
+
+ int wantHandleItem(const ModelNode &modelNode) const override;
+
+ QString name() const override;
+
+ void activateTool();
+ void unblock();
+
+ QGraphicsLineItem *lineItem();
+ QGraphicsRectItem *rectangleItem1();
+ QGraphicsRectItem *rectangleItem2();
+
+private:
+ FormEditorItem *currentFormEditorItem() const;
+ void createItems();
+ void createTransition(FormEditorItem *item1, FormEditorItem *item2);
+
+ FormEditorItem* m_formEditorItem;
+ std::unique_ptr<QGraphicsLineItem> m_lineItem;
+ std::unique_ptr<QGraphicsRectItem> m_rectangleItem1;
+ std::unique_ptr<QGraphicsRectItem> m_rectangleItem2;
+ bool m_blockEvents = true;
+};
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/importmanager/importmanagerview.cpp b/src/plugins/qmldesigner/components/importmanager/importmanagerview.cpp
index df9590af64..c2bce0b0ce 100644
--- a/src/plugins/qmldesigner/components/importmanager/importmanagerview.cpp
+++ b/src/plugins/qmldesigner/components/importmanager/importmanagerview.cpp
@@ -81,14 +81,16 @@ void ImportManagerView::modelAboutToBeDetached(Model *model)
void ImportManagerView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
{
- if (m_importsWidget)
+ if (m_importsWidget) {
m_importsWidget->setImports(model()->imports());
+ // setImports recreates labels, so we need to update used imports, as it is not guaranteed
+ // usedImportsChanged notification will come after this.
+ m_importsWidget->setUsedImports(model()->usedImports());
+ }
}
void ImportManagerView::possibleImportsChanged(const QList<Import> &/*possibleImports*/)
{
- QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
-
if (m_importsWidget)
m_importsWidget->setPossibleImports(model()->possibleImports());
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
index 3f403d0313..0beb5bce72 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
@@ -32,6 +32,9 @@
#include "utils/outputformatter.h"
#include "theme.h"
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/qloggingcategory.h>
@@ -97,6 +100,20 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
+ QStringList importPaths;
+ auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
+ if (doc) {
+ Model *model = doc->currentModel();
+ if (model)
+ importPaths = model->importPaths();
+ }
+
+ QString targetDir = defaulTargetDirectory;
+
+ ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(doc->fileName());
+ if (currentProject)
+ targetDir = currentProject->projectDirectory().toString();
+
// Import is always done under known folder. The order of preference for folder is:
// 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
// 2) An existing QUICK_3D_ASSETS_FOLDER under any project import path
@@ -105,19 +122,11 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
// 5) New QUICK_3D_ASSETS_FOLDER under new DEFAULT_ASSET_IMPORT_FOLDER under project
const QString defaultAssetFolder = QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER);
const QString quick3DFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
- QString candidatePath = defaulTargetDirectory + defaultAssetFolder + quick3DFolder;
+ QString candidatePath = targetDir + defaultAssetFolder + quick3DFolder;
int candidatePriority = 5;
- QStringList importPaths;
-
- auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
- if (doc) {
- Model *model = doc->currentModel();
- if (model)
- importPaths = model->importPaths();
- }
for (auto importPath : qAsConst(importPaths)) {
- if (importPath.startsWith(defaulTargetDirectory)) {
+ if (importPath.startsWith(targetDir)) {
const bool isDefaultFolder = importPath.endsWith(defaultAssetFolder);
const QString assetFolder = importPath + quick3DFolder;
const bool exists = QFileInfo(assetFolder).exists();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index 34fa71222d..6a5edb18a3 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -280,7 +280,16 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
return;
}
+ QString originalAssetName = assetName;
if (targetDir.exists(assetName)) {
+ // If we have a file system with case insensitive filenames, assetName may be
+ // different from the existing name. Modify assetName to ensure exact match to
+ // the overwritten old asset capitalization
+ const QStringList assetDirs = targetDir.entryList({assetName}, QDir::Dirs);
+ if (assetDirs.size() == 1) {
+ assetName = assetDirs[0];
+ targetDirPath = targetDir.filePath(assetName);
+ }
if (!confirmAssetOverwrite(assetName)) {
addWarning(tr("Skipped import of existing asset: \"%1\"").arg(assetName));
return;
@@ -306,6 +315,16 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
return;
}
+ // The importer is reset after every import to avoid issues with it caching various things
+ m_quick3DAssetImporter.reset(new QSSGAssetImportManager);
+
+ if (originalAssetName != assetName) {
+ // Fix the generated qml file name
+ const QString assetQml = originalAssetName + ".qml";
+ if (outDir.exists(assetQml))
+ outDir.rename(assetQml, assetName + ".qml");
+ }
+
QHash<QString, QString> assetFiles;
const int outDirPathSize = outDir.path().size();
auto insertAsset = [&](const QString &filePath) {
@@ -512,18 +531,24 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
addInfo(progressTitle);
notifyProgress(0, progressTitle);
- // There is an inbuilt delay before rewriter change actually updates the data model,
- // so we need to wait for a moment to allow the change to take effect.
+ // First we have to wait a while to ensure qmljs detects new files and updates its
+ // internal model. Then we make a non-change to the document to trigger qmljs snapshot
+ // update. There is an inbuilt delay before rewriter change actually updates the data
+ // model, so we need to wait for another moment to allow the change to take effect.
// Otherwise subsequent subcomponent manager update won't detect new imports properly.
QTimer *timer = new QTimer(parent());
static int counter;
counter = 0;
- timer->callOnTimeout([this, timer, progressTitle, model]() {
+ timer->callOnTimeout([this, timer, progressTitle, model, doc]() {
if (!isCancelled()) {
- notifyProgress(++counter * 10, progressTitle);
- if (counter >= 10) {
- // Trigger underlying qmljs snapshot update by making a non-change to the doc
+ notifyProgress(++counter * 5, progressTitle);
+ if (counter == 10) {
model->rewriterView()->textModifier()->replace(0, 0, {});
+ } else if (counter == 19) {
+ doc->updateSubcomponentManager();
+ } else if (counter >= 20) {
+ if (!m_overwrittenImports.isEmpty())
+ model->rewriterView()->emitCustomNotification("asset_import_update");
timer->stop();
notifyFinished();
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index caf0663dce..3f7ca2c366 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -384,7 +384,19 @@ void ItemLibraryWidget::updateModel()
{
QTC_ASSERT(m_itemLibraryModel, return);
+ if (m_compressionTimer.isActive()) {
+ m_updateRetry = false;
+ m_compressionTimer.stop();
+ }
+
m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data());
+
+ if (m_itemLibraryModel->rowCount() == 0 && !m_updateRetry) {
+ m_updateRetry = true; // Only retry once to avoid endless loops
+ m_compressionTimer.start();
+ } else {
+ m_updateRetry = false;
+ }
updateImports();
updateSearch();
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
index 6e8fc0340a..11dea7d0c1 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -121,6 +121,7 @@ private:
QPointer<Model> m_model;
FilterChangeFlag m_filterFlag;
ItemLibraryEntry m_currentitemLibraryEntry;
+ bool m_updateRetry = false;
};
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
index bedcc2f561..d560eb2824 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
@@ -43,6 +43,7 @@ public:
virtual void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
+ virtual void notifyIconsChanged() = 0;
virtual void setFilter(bool showObjects) = 0;
virtual void resetModel() = 0;
};
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index c91ff78626..70d2e405f9 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -695,6 +695,11 @@ void NavigatorTreeModel::notifyModelNodesMoved(const QList<ModelNode> &modelNode
emit layoutChanged(indexes);
}
+void NavigatorTreeModel::notifyIconsChanged()
+{
+ emit dataChanged(index(0, 0), index(rowCount(), 0), {Qt::DecorationRole});
+}
+
void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
{
m_showOnlyVisibleItems = showOnlyVisibleItems;
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
index f10198adcc..15e89d3636 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
@@ -87,6 +87,7 @@ public:
void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
+ void notifyIconsChanged() override;
void setFilter(bool showOnlyVisibleItems) override;
void resetModel() override;
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index ea64f0715a..cd6857d789 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -147,6 +147,17 @@ void NavigatorView::bindingPropertiesChanged(const QList<BindingProperty> & prop
}
}
+void NavigatorView::customNotification(const AbstractView *view, const QString &identifier,
+ const QList<ModelNode> &nodeList, const QList<QVariant> &data)
+{
+ Q_UNUSED(view)
+ Q_UNUSED(nodeList)
+ Q_UNUSED(data)
+
+ if (identifier == "asset_import_update")
+ m_currentModelInterface->notifyIconsChanged();
+}
+
void NavigatorView::handleChangedExport(const ModelNode &modelNode, bool exported)
{
const ModelNode rootNode = rootModelNode();
@@ -416,12 +427,24 @@ void NavigatorView::updateItemSelection()
QItemSelection itemSelection;
foreach (const ModelNode &node, selectedModelNodes()) {
const QModelIndex index = indexForModelNode(node);
+
if (index.isValid()) {
const QModelIndex beginIndex(currentModel()->index(index.row(), 0, index.parent()));
const QModelIndex endIndex(currentModel()->index(index.row(), currentModel()->columnCount(index.parent()) - 1, index.parent()));
if (beginIndex.isValid() && endIndex.isValid())
itemSelection.select(beginIndex, endIndex);
- }
+ } else {
+ // if the node index is invalid expand ancestors manually if they are valid.
+ ModelNode parentNode = node;
+ while (parentNode.hasParentProperty()) {
+ parentNode = parentNode.parentProperty().parentQmlObjectNode();
+ QModelIndex parentIndex = indexForModelNode(parentNode);
+ if (parentIndex.isValid())
+ treeWidget()->expand(parentIndex);
+ else
+ break;
+ }
+ }
}
bool blocked = blockSelectionChangedSignal(true);
@@ -431,10 +454,10 @@ void NavigatorView::updateItemSelection()
if (!selectedModelNodes().isEmpty())
treeWidget()->scrollTo(indexForModelNode(selectedModelNodes().constFirst()));
- // make sure selected nodes a visible
+ // make sure selected nodes are visible
foreach (const QModelIndex &selectedIndex, itemSelection.indexes()) {
if (selectedIndex.column() == 0)
- expandRecursively(selectedIndex);
+ expandAncestors(selectedIndex);
}
}
@@ -458,9 +481,9 @@ bool NavigatorView::blockSelectionChangedSignal(bool block)
return oldValue;
}
-void NavigatorView::expandRecursively(const QModelIndex &index)
+void NavigatorView::expandAncestors(const QModelIndex &index)
{
- QModelIndex currentIndex = index;
+ QModelIndex currentIndex = index.parent();
while (currentIndex.isValid()) {
if (!treeWidget()->isExpanded(currentIndex))
treeWidget()->expand(currentIndex);
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
index 852dddc70f..3bafe0fa80 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -84,6 +84,8 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags) override;
+ void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
+
void handleChangedExport(const ModelNode &modelNode, bool exported);
bool isNodeInvisible(const ModelNode &modelNode) const;
@@ -108,7 +110,7 @@ protected: //functions
QTreeView *treeWidget() const;
NavigatorTreeModel *treeModel();
bool blockSelectionChangedSignal(bool block);
- void expandRecursively(const QModelIndex &index);
+ void expandAncestors(const QModelIndex &index);
void reparentAndCatch(NodeAbstractProperty property, const ModelNode &modelNode);
void setupWidget();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
index 8be49060e6..1a52a639a7 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
@@ -426,6 +426,17 @@ QStringList PropertyEditorContextObject::styleNamesForFamily(const QString &fami
return dataBase.styles(family);
}
+QStringList PropertyEditorContextObject::allStatesForId(const QString &id)
+{
+ if (m_model && m_model->rewriterView()) {
+ const QmlObjectNode node = m_model->rewriterView()->modelNodeForId(id);
+ if (node.isValid())
+ return node.allStateNames();
+ }
+
+ return {};
+}
+
void EasingCurveEditor::registerDeclarativeType()
{
qmlRegisterType<EasingCurveEditor>("HelperWidgets", 2, 0, "EasingCurveEditor");
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h
index 9e3309ee35..03d82dbc34 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h
@@ -94,6 +94,8 @@ public:
Q_INVOKABLE QStringList styleNamesForFamily(const QString &family);
+ Q_INVOKABLE QStringList allStatesForId(const QString &id);
+
int majorVersion() const;
int majorQtQuickVersion() const;
int minorQtQuickVersion() const;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index ddded6400b..171046b4ae 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -47,6 +47,7 @@
#include <QApplication>
#include <QDir>
#include <QFileInfo>
+#include <QVector3D>
#include <QLoggingCategory>
@@ -166,6 +167,18 @@ QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
return 0;
else if (propertyName == "breakPoint")
return 50;
+ else if (propertyName == "transitionType")
+ return 0;
+ else if (propertyName == "type")
+ return 0;
+ else if (propertyName == "transitionRadius")
+ return 8;
+ else if (propertyName == "radius")
+ return 8;
+ else if (propertyName == "transitionBezier")
+ return 50;
+ else if (propertyName == "bezier")
+ return 50;
else if (propertyName == "customId")
return QString();
else if (propertyName == "joinConnection")
@@ -235,7 +248,7 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
propertyNames.append("customId");
if (itemNode.isFlowTransition()) {
- propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "breakPoint"});
+ propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "breakPoint", "type", "radius", "bezier"});
} else if (itemNode.isFlowItem()) {
propertyNames.append({"color", "width", "inOffset", "outOffset", "joinConnection"});
} else if (itemNode.isFlowActionArea()) {
@@ -245,7 +258,7 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
} else if (itemNode.isFlowWildcard()) {
propertyNames.append({"color", "width", "fillColor", "dash"});
} else if (itemNode.isFlowView()) {
- propertyNames.append({"transitionColor", "areaColor", "areaFillColor", "blockColor" });
+ propertyNames.append({"transitionColor", "areaColor", "areaFillColor", "blockColor", "transitionType", "transitionRadius", "transitionBezier"});
}
for (const PropertyName &propertyName : propertyNames) {
@@ -294,11 +307,25 @@ void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qm
void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyName &name, const QVariant &value)
{
- PropertyName propertyName = name;
- propertyName.replace('.', '_');
- auto propertyValue = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(propertyName))));
- if (propertyValue)
- propertyValue->setValue(value);
+ if (value.type() == QVariant::Vector3D) {
+ // Vector3D values need to be split into their subcomponents
+ const char *suffix[3] = {"_x", "_y", "_z"};
+ auto vecValue = value.value<QVector3D>();
+ for (int i = 0; i < 3; ++i) {
+ PropertyName subPropName(name.size() + 2, '\0');
+ subPropName.replace(0, name.size(), name);
+ subPropName.replace(name.size(), 2, suffix[i]);
+ auto propertyValue = qobject_cast<PropertyEditorValue *>(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName))));
+ if (propertyValue)
+ propertyValue->setValue(QVariant(vecValue[i]));
+ }
+ } else {
+ PropertyName propertyName = name;
+ propertyName.replace('.', '_');
+ auto propertyValue = qobject_cast<PropertyEditorValue *>(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(propertyName))));
+ if (propertyValue)
+ propertyValue->setValue(value);
+ }
}
QQmlContext *PropertyEditorQmlBackend::context() {
diff --git a/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp b/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp
index a35ff98ef4..cc82a5607e 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp
+++ b/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp
@@ -85,10 +85,25 @@ bool ChangeImportsVisitor::remove(QmlJS::AST::UiProgram *ast, const Import &impo
bool ChangeImportsVisitor::equals(QmlJS::AST::UiImport *ast, const Import &import)
{
+ bool equal = false;
if (import.isLibraryImport())
- return toString(ast->importUri) == import.url();
+ equal = toString(ast->importUri) == import.url();
else if (import.isFileImport())
- return ast->fileName == import.file();
- else
- return false;
+ equal = ast->fileName == import.file();
+
+ if (equal) {
+ equal = (!ast->version || (ast->version->minorVersion == 0 && ast->version->majorVersion == 0))
+ && import.version().isEmpty();
+ if (!equal && ast->version) {
+ const QStringList versions = import.version().split('.');
+ if (versions.size() >= 1 && versions[0].toInt() == ast->version->majorVersion) {
+ if (versions.size() >= 2)
+ equal = versions[1].toInt() == ast->version->minorVersion;
+ else
+ equal = ast->version->minorVersion == 0;
+ }
+ }
+ }
+
+ return equal;
}
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index ef8f1b28ba..d779cc15bf 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -182,8 +182,13 @@ public:
const QList<ModelNode> wildcards() const;
const QList<ModelNode> decicions() const;
QList<ModelNode> transitionsForTarget(const ModelNode &modelNode);
+ QList<ModelNode> transitionsForSource(const ModelNode &modelNode);
void removeDanglingTransitions();
void removeAllTransitions();
+ void setStartFlowItem(const QmlFlowItemNode &flowItem);
+ ModelNode createTransition();
+protected:
+ QList<ModelNode> transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode);
};
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
index 453c1b31a4..535350055d 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
@@ -32,6 +32,7 @@
#include <QDebug>
#include <QPainter>
+#include <QVector3D>
QT_BEGIN_NAMESPACE
void qt_blurImage(QPainter *painter, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
@@ -306,8 +307,38 @@ int NodeInstance::penWidth() const
QVariant NodeInstance::property(const PropertyName &name) const
{
- if (isValid())
- return d->propertyValues.value(name);
+ if (isValid()) {
+ if (d->propertyValues.contains(name)) {
+ return d->propertyValues.value(name);
+ } else {
+ // Query may be for a subproperty, e.g. scale.x
+ const int index = name.indexOf('.');
+ if (index != -1) {
+ PropertyName parentPropName = name.left(index);
+ QVariant varValue = d->propertyValues.value(parentPropName);
+ if (varValue.type() == QVariant::Vector3D) {
+ auto value = varValue.value<QVector3D>();
+ char subProp = name.right(1)[0];
+ float subValue = 0.f;
+ switch (subProp) {
+ case 'x':
+ subValue = value.x();
+ break;
+ case 'y':
+ subValue = value.y();
+ break;
+ case 'z':
+ subValue = value.z();
+ break;
+ default:
+ subValue = 0.f;
+ break;
+ }
+ return QVariant(subValue);
+ }
+ }
+ }
+ }
return QVariant();
}
@@ -362,6 +393,30 @@ QPair<PropertyName, qint32> NodeInstance::anchor(const PropertyName &name) const
void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
{
+ const int index = name.indexOf('.');
+ if (index != -1) {
+ PropertyName parentPropName = name.left(index);
+ QVariant oldValue = d->propertyValues.value(parentPropName);
+ QVector3D newValue;
+ if (oldValue.type() == QVariant::Vector3D)
+ newValue = oldValue.value<QVector3D>();
+ bool update = false;
+ if (name.endsWith(".x")) {
+ newValue.setX(value.toFloat());
+ update = true;
+ } else if (name.endsWith(".y")) {
+ newValue.setY(value.toFloat());
+ update = true;
+ } else if (name.endsWith(".z")) {
+ newValue.setZ(value.toFloat());
+ update = true;
+ }
+ if (update) {
+ d->propertyValues.insert(parentPropName, newValue);
+ return;
+ }
+ }
+
d->propertyValues.insert(name, value);
}
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
index f480e9bb97..6e6660a5cb 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
@@ -510,6 +510,8 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
customFileSelectors = m_target->additionalData("CustomFileSelectorsData").toStringList();
}
+ customFileSelectors.append("DesignMode");
+
if (m_availablePuppetType == FallbackPuppet)
importPaths.prepend(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index ff65187f46..b4b043847e 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -420,8 +420,7 @@ void SubComponentManager::parseQuick3DAssetDir(const QString &assetPath)
itemLibraryEntry.addHints(hints);
}
- if (!model()->metaInfo().itemLibraryInfo()->containsEntry(itemLibraryEntry))
- model()->metaInfo().itemLibraryInfo()->addEntries({itemLibraryEntry});
+ model()->metaInfo().itemLibraryInfo()->addEntries({itemLibraryEntry}, true);
}
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 098f8317a5..e2f0602cc2 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -664,9 +664,7 @@ QList<QmlFlowItemNode> QmlFlowViewNode::flowItems() const
ModelNode QmlFlowViewNode::addTransition(const QmlFlowTargetNode &from, const QmlFlowTargetNode &to)
{
- ModelNode transition = view()->createModelNode("FlowView.FlowTransition", 1, 0);
-
- nodeListProperty("flowTransitions").reparentHere(transition);
+ ModelNode transition = createTransition();
QmlFlowTargetNode f = from;
QmlFlowTargetNode t = to;
@@ -684,8 +682,6 @@ const QList<ModelNode> QmlFlowViewNode::transitions() const
return modelNode().nodeListProperty("flowTransitions").toModelNodeList();
return {};
-
-
}
const QList<ModelNode> QmlFlowViewNode::wildcards() const
@@ -706,13 +702,12 @@ const QList<ModelNode> QmlFlowViewNode::decicions() const
QList<ModelNode> QmlFlowViewNode::transitionsForTarget(const ModelNode &modelNode)
{
- QList<ModelNode> list;
- for (const ModelNode &transition : transitions()) {
- if (transition.hasBindingProperty("to")
- && transition.bindingProperty("to").resolveToModelNode() == modelNode)
- list.append(transition);
- }
- return list;
+ return transitionsForProperty("to", modelNode);
+}
+
+QList<ModelNode> QmlFlowViewNode::transitionsForSource(const ModelNode &modelNode)
+{
+ return transitionsForProperty("from", modelNode);
}
void QmlFlowViewNode::removeDanglingTransitions()
@@ -830,4 +825,41 @@ void QmlFlowViewNode::removeAllTransitions()
removeProperty("flowTransitions");
}
+void QmlFlowViewNode::setStartFlowItem(const QmlFlowItemNode &flowItem)
+{
+ QTC_ASSERT(flowItem.isValid(), return);
+ QmlFlowItemNode item = flowItem;
+
+ ModelNode transition;
+
+ for (const ModelNode &node : transitionsForSource(modelNode()))
+ transition = node;
+ if (!transition.isValid())
+ transition = createTransition();
+
+ transition.bindingProperty("from").setExpression(modelNode().validId());
+ transition.bindingProperty("to").setExpression(item.validId());
+}
+
+ModelNode QmlFlowViewNode::createTransition()
+{
+ ModelNode transition = view()->createModelNode("FlowView.FlowTransition", 1, 0);
+ nodeListProperty("flowTransitions").reparentHere(transition);
+
+ return transition;
+}
+
+QList<ModelNode> QmlFlowViewNode::transitionsForProperty(const PropertyName &propertyName,
+ const ModelNode &modelNode)
+{
+ QList<ModelNode> list;
+ for (const ModelNode &transition : transitions()) {
+ if (transition.hasBindingProperty(propertyName)
+ && transition.bindingProperty(propertyName).resolveToModelNode() == modelNode)
+ list.append(transition);
+ }
+ return list;
+
+}
+
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp b/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp
index a687853604..68738b06de 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp
@@ -90,11 +90,12 @@ bool QmlTimeline::hasTimeline(const ModelNode &node, const PropertyName &propert
for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(childNode)) {
const QmlTimelineKeyframeGroup frames(childNode);
-
- if (frames.target().isValid()
- && frames.target() == node
- && frames.propertyName() == propertyName)
+ if (frames.target().isValid() && frames.target() == node
+ && (frames.propertyName() == propertyName
+ || (frames.propertyName().contains('.')
+ && frames.propertyName().startsWith(propertyName)))) {
return true;
+ }
}
}
}
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 41bc1944ca..fd0d9a51ff 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -91,7 +91,12 @@ QStringList globalQtEnums()
"Horizontal", "Vertical", "AlignVCenter", "AlignLeft", "LeftToRight", "RightToLeft",
"AlignHCenter", "AlignRight", "AlignBottom", "AlignBaseline", "AlignTop", "BottomLeft",
"LeftEdge", "RightEdge", "BottomEdge", "TopEdge", "TabFocus", "ClickFocus", "StrongFocus",
- "WheelFocus", "NoFocus"
+ "WheelFocus", "NoFocus", "ArrowCursor", "UpArrowCursor", "CrossCursor", "WaitCursor",
+ "IBeamCursor", "SizeVerCursor", "SizeHorCursor", "SizeBDiagCursor", "SizeFDiagCursor",
+ "SizeAllCursor", "BlankCursor", "SplitVCursor", "SplitHCursor", "PointingHandCursor",
+ "ForbiddenCursor", "WhatsThisCursor", "BusyCursor", "OpenHandCursor", "ClosedHandCursor",
+ "DragCopyCursor", "DragMoveCursor", "DragLinkCursor", "TopToBottom",
+ "LeftButton", "RightButton", "MiddleButton", "BackButton", "ForwardButton", "AllButtons"
};
return list;
@@ -101,7 +106,7 @@ QStringList knownEnumScopes()
{
static const QStringList list = {
"TextInput", "TextEdit", "Material", "Universal", "Font", "Shape", "ShapePath",
- "AbstractButton", "Text", "ShaderEffectSource"
+ "AbstractButton", "Text", "ShaderEffectSource", "Grid"
};
return list;
}
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index d9db2ea006..e52eabc7bf 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -60,6 +60,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <utils/stylehelper.h>
#include <QSettings>
#include <QToolBar>
@@ -70,6 +71,7 @@
#include <advanceddockingsystem/dockareawidget.h>
#include <advanceddockingsystem/docksplitter.h>
+#include <advanceddockingsystem/iconprovider.h>
using Core::MiniSplitter;
using Core::IEditor;
@@ -210,6 +212,13 @@ void DesignModeWidget::disableWidgets()
m_isDisabled = true;
}
+static void addSpacerToToolBar(QToolBar *toolBar)
+{
+ QWidget* empty = new QWidget();
+ empty->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
+ toolBar->addWidget(empty);
+}
+
void DesignModeWidget::setup()
{
auto &actionManager = viewManager().designerActionManager();
@@ -227,6 +236,26 @@ void DesignModeWidget::setup()
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/dockwidgets.css"));
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
+ // Setup icons
+ QColor buttonColor(Theme::getColor(Theme::QmlDesigner_TabLight)); // TODO Use correct color roles
+ QColor tabColor(Theme::getColor(Theme::QmlDesigner_TabDark));
+
+ const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::adsClose);
+ const QString menuUnicode = Theme::getIconUnicode(Theme::Icon::adsDropDown);
+ const QString undockUnicode = Theme::getIconUnicode(Theme::Icon::adsDetach);
+
+ const QString fontName = "qtds_propertyIconFont.ttf";
+ const QIcon tabsCloseIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, tabColor);
+ const QIcon menuIcon = Utils::StyleHelper::getIconFromIconFont(fontName, menuUnicode, 28, 28, buttonColor);
+ const QIcon undockIcon = Utils::StyleHelper::getIconFromIconFont(fontName, undockUnicode, 28, 28, buttonColor);
+ const QIcon closeIcon = Utils::StyleHelper::getIconFromIconFont(fontName, closeUnicode, 28, 28, buttonColor);
+
+ m_dockManager->iconProvider().registerCustomIcon(ADS::TabCloseIcon, tabsCloseIcon);
+ m_dockManager->iconProvider().registerCustomIcon(ADS::DockAreaMenuIcon, menuIcon);
+ m_dockManager->iconProvider().registerCustomIcon(ADS::DockAreaUndockIcon, undockIcon);
+ m_dockManager->iconProvider().registerCustomIcon(ADS::DockAreaCloseIcon, closeIcon);
+ m_dockManager->iconProvider().registerCustomIcon(ADS::FloatingWidgetCloseIcon, closeIcon);
+
// Setup Actions and Menus
Core::ActionContainer *mwindow = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW);
// Window > Views
@@ -344,6 +373,7 @@ void DesignModeWidget::setup()
// Create toolbars
auto toolBar = new QToolBar();
+
toolBar->addAction(viewManager().componentViewAction());
toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
DesignerActionToolBar *designerToolBar = QmlDesignerPlugin::instance()->viewManager().designerActionManager().createToolBar(m_toolBar);
@@ -385,6 +415,8 @@ void DesignModeWidget::setup()
}
});
+ addSpacerToToolBar(toolBar);
+
auto workspaceComboBox = new QComboBox();
workspaceComboBox->setMinimumWidth(120);
workspaceComboBox->setToolTip(tr("Switch the active workspace."));
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index a65ff3600b..21d1ffadf2 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -38,6 +38,7 @@
#include <sourcetool/sourcetool.h>
#include <colortool/colortool.h>
#include <annotationeditor/annotationtool.h>
+#include <formeditor/transitiontool.h>
#include <texttool/texttool.h>
#include <timelineeditor/timelineview.h>
#include <pathtool/pathtool.h>
@@ -216,6 +217,11 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool())
GenerateResource::generateMenuEntry();
+ QString fontPath = Core::ICore::resourcePath() +
+ QStringLiteral("/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf");
+ if (QFontDatabase::addApplicationFont(fontPath) < 0)
+ qCWarning(qmldesignerLog) << "Could not add font " << fontPath << "to font database";
+
return true;
}
@@ -242,6 +248,7 @@ bool QmlDesignerPlugin::delayedInitialize()
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::AnnotationTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::TextTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::PathTool);
+ d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::TransitionTool);
return true;
}
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index 3c434788cd..c69f5e5c22 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -530,6 +530,8 @@ Project {
"formeditor/toolbox.h",
"formeditor/formeditortoolbutton.cpp",
"formeditor/formeditortoolbutton.h",
+ "formeditor/transitiontool.cpp",
+ "formeditor/transitiontool.h",
"importmanager/importlabel.cpp",
"importmanager/importlabel.h",
"importmanager/importmanagercombobox.cpp",