From 818f2d0c5cf19e2a036e858ea1d9339750ef0296 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 21 Nov 2019 15:09:08 +0100 Subject: [PATCH 01/37] CppTools: Fix race condition when opening projects for tests The ClangTools plugin tests open a project and immediately trigger a build afterwards. We checked whether CppModelManager got already data from the project manager, but this alone was racy for the mentioned use case as e.g. the QbsProjectManager might still be in parsing mode and thus the build was not triggerable. Check for the parsing state, too. While at it, simplify the code by using QTest::qWaitFor(), which also takes care of posted events. Change-Id: Id298695b2e67578def42275bac4ea31f4a39edf2 Reviewed-by: Christian Kandeler --- .../test/clangbatchfileprocessor.cpp | 2 +- src/plugins/cpptools/cpptoolstestcase.cpp | 21 +++++++------------ src/plugins/cpptools/cpptoolstestcase.h | 5 ++--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp b/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp index 25d22bb1c1b..8556c84b4b0 100644 --- a/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp +++ b/src/plugins/clangcodemodel/test/clangbatchfileprocessor.cpp @@ -237,7 +237,7 @@ bool OpenProjectCommand::run() Project *project = openProjectSucceeded.project(); project->configureAsExampleProject(); - return CppTools::Tests::TestCase::waitUntilCppModelManagerIsAwareOf(project, timeOutInMs()); + return CppTools::Tests::TestCase::waitUntilProjectIsFullyOpened(project, timeOutInMs()); } Command::Ptr OpenProjectCommand::parse(BatchFileLineTokenizer &arguments, diff --git a/src/plugins/cpptools/cpptoolstestcase.cpp b/src/plugins/cpptools/cpptoolstestcase.cpp index b9ba701aebb..8040e3f811f 100644 --- a/src/plugins/cpptools/cpptoolstestcase.cpp +++ b/src/plugins/cpptools/cpptoolstestcase.cpp @@ -226,22 +226,17 @@ QList TestCase::waitForFilesInGlobalSnapshot(const QSt return result; } -bool TestCase::waitUntilCppModelManagerIsAwareOf(Project *project, int timeOutInMs) +bool TestCase::waitUntilProjectIsFullyOpened(Project *project, int timeOutInMs) { if (!project) return false; - QElapsedTimer t; - t.start(); - - CppModelManager *modelManager = CppModelManager::instance(); - forever { - if (modelManager->projectInfo(project).isValid()) - return true; - if (t.elapsed() > timeOutInMs) - return false; - QCoreApplication::processEvents(); - } + return QTest::qWaitFor( + [project]() { + return !project->isParsing() + && CppModelManager::instance()->projectInfo(project).isValid(); + }, + timeOutInMs); } bool TestCase::writeFile(const QString &filePath, const QByteArray &contents) @@ -293,7 +288,7 @@ ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile, bool config if (configureAsExampleProject) project->configureAsExampleProject(); - if (TestCase::waitUntilCppModelManagerIsAwareOf(project)) { + if (TestCase::waitUntilProjectIsFullyOpened(project)) { m_openProjects.append(project); return CppModelManager::instance()->projectInfo(project); } diff --git a/src/plugins/cpptools/cpptoolstestcase.h b/src/plugins/cpptools/cpptoolstestcase.h index 009a5a9c3ed..d6e306d255f 100644 --- a/src/plugins/cpptools/cpptoolstestcase.h +++ b/src/plugins/cpptools/cpptoolstestcase.h @@ -92,9 +92,8 @@ public: static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000); enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ }; - static bool waitUntilCppModelManagerIsAwareOf( - ProjectExplorer::Project *project, - int timeOutInMs = defaultTimeOutInMs); + static bool waitUntilProjectIsFullyOpened(ProjectExplorer::Project *project, + int timeOutInMs = defaultTimeOutInMs); static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot( const QString &filePath, int timeOutInMs = defaultTimeOutInMs); From 668cd2091adf616448e424f60a463236014dc339 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 22 Nov 2019 09:29:39 +0100 Subject: [PATCH 02/37] ClangTools: Fix clazy plugin invocation with recent clazy As the no-autowrite-fixits option was removed with https://github.com/KDE/clazy/commit/c5d0a2d0169c6faa981328ea3ad0e285d048b102 our clazy invocation is incorrect and results in the usage being printed. Change-Id: I104273da8722f00c3df0d69d2b57c68fc9d3c1e6 Reviewed-by: Cristian Adam Reviewed-by: Nikolai Kosjar --- src/plugins/clangtools/clangtidyclazyrunner.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp index bd909384d00..09ac2aa2f8d 100644 --- a/src/plugins/clangtools/clangtidyclazyrunner.cpp +++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp @@ -68,8 +68,6 @@ static QStringList clazyPluginArguments(const ClangDiagnosticConfig diagnosticCo "-plugin-arg-clazy", "enable-all-fixits", "-plugin-arg-clazy", - "no-autowrite-fixits", - "-plugin-arg-clazy", diagnosticConfig.clazyChecks()}); } From 77cb514a797ffa4ec0eb66fd6f397b0b053bde26 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 15 Nov 2019 15:20:31 +0200 Subject: [PATCH 03/37] QmlDesigner: Implement better camera navigation in 3D edit view Edit camera is now controlled as in Qt 3D Studio: ALT + left button orbits camera. ALT + middle button pans camera. ALT + right button zooms camera. Wheel zooms camera. Task-number: QDS-1206 Change-Id: Ia72644073d172b00483ceed8bcc5ffb8dce68741 Reviewed-by: Thomas Hartmann --- .../qmlpuppet/mockfiles/AutoScaleHelper.qml | 2 +- .../mockfiles/EditCameraController.qml | 118 ++++++++++++++++ .../qml/qmlpuppet/mockfiles/EditView3D.qml | 54 +++---- .../qml/qmlpuppet/mockfiles/Overlay2D.qml | 2 +- .../editor3d/cameracontrolhelper.cpp | 78 ----------- .../qml2puppet/editor3d/editor3d.pri | 4 +- .../qml2puppet/editor3d/generalhelper.cpp | 132 ++++++++++++++++++ ...{cameracontrolhelper.h => generalhelper.h} | 33 +++-- .../qml2puppet/editor3d/mousearea3d.cpp | 5 +- .../qml2puppet/editor3d/mousearea3d.h | 6 +- .../qt5informationnodeinstanceserver.cpp | 7 +- share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 1 + src/tools/qml2puppet/CMakeLists.txt | 2 +- src/tools/qml2puppet/qml2puppet.qbs | 4 +- 14 files changed, 303 insertions(+), 145 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml delete mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp create mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp rename share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/{cameracontrolhelper.h => generalhelper.h} (59%) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml index 9ffd3aa85bd..cec64b32b57 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml @@ -46,7 +46,7 @@ Node { } Connections { - target: designStudioNativeCameraControlHelper + target: _generalHelper onOverlayUpdateNeeded: updateScale() } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml new file mode 100644 index 00000000000..90f82bd341e --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick3D 1.0 + +Item { + id: cameraCtrl + + property Camera camera: null + + property vector3d _lookAtPoint + property vector3d _pressPoint + property vector3d _prevPoint + property vector3d _startRotation + property vector3d _startPosition + property vector3d _startLookAtPoint + property matrix4x4 _startTransform + property bool _dragging + property int _button + property real _zoomFactor: 1 + property real _defaultCameraLookAtDistance: 0 + property Camera _prevCamera: null + + function zoomRelative(distance) + { + _zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance, + _lookAtPoint, _zoomFactor, true); + } + + Component.onCompleted: { + cameraCtrl._defaultCameraLookAtDistance = cameraCtrl.camera.position.length(); + } + + onCameraChanged: { + if (_prevCamera) { + // Reset zoom on previous camera to ensure it's properties are good to copy to new cam + _generalHelper.zoomCamera(_prevCamera, 0, _defaultCameraLookAtDistance, _lookAtPoint, + 1, false); + + camera.position = _prevCamera.position; + camera.rotation = _prevCamera.rotation; + + // Apply correct zoom to new camera + _generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint, + _zoomFactor, false); + } + _prevCamera = camera; + } + + MouseArea { + id: mouseHandler + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + hoverEnabled: false + anchors.fill: parent + onPositionChanged: { + if (mouse.modifiers === Qt.AltModifier && cameraCtrl._dragging) { + var currentPoint = Qt.vector3d(mouse.x, mouse.y, 0); + if (cameraCtrl._button == Qt.LeftButton) { + _generalHelper.orbitCamera(cameraCtrl.camera, cameraCtrl._startRotation, + cameraCtrl._lookAtPoint, cameraCtrl._pressPoint, + currentPoint); + } else if (cameraCtrl._button == Qt.MiddleButton) { + cameraCtrl._lookAtPoint = _generalHelper.panCamera( + cameraCtrl.camera, cameraCtrl._startTransform, + cameraCtrl._startPosition, cameraCtrl._startLookAtPoint, + cameraCtrl._pressPoint, currentPoint, _zoomFactor); + } else if (cameraCtrl._button == Qt.RightButton) { + cameraCtrl.zoomRelative(currentPoint.y - cameraCtrl._prevPoint.y) + cameraCtrl._prevPoint = currentPoint; + } + } + } + onPressed: { + if (mouse.modifiers === Qt.AltModifier) { + cameraCtrl._dragging = true; + cameraCtrl._startRotation = cameraCtrl.camera.rotation; + cameraCtrl._startPosition = cameraCtrl.camera.position; + cameraCtrl._startLookAtPoint = _lookAtPoint; + cameraCtrl._pressPoint = Qt.vector3d(mouse.x, mouse.y, 0); + cameraCtrl._prevPoint = cameraCtrl._pressPoint; + cameraCtrl._button = mouse.button; + cameraCtrl._startTransform = cameraCtrl.camera.sceneTransform; + } else { + mouse.accepted = false; + } + } + + onReleased: cameraCtrl._dragging = false; + onCanceled: cameraCtrl._dragging = false; + onWheel: { + // Emprically determined divisor for nice zoom + cameraCtrl.zoomRelative(wheel.angleDelta.y / -40); + } + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 9db9d0c8a83..a4d63962d8b 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -26,7 +26,6 @@ import QtQuick 2.12 import QtQuick.Window 2.0 import QtQuick3D 1.0 -import QtQuick3D.Helpers 1.0 import QtQuick.Controls 2.0 import QtGraphicalEffects 1.0 @@ -78,7 +77,7 @@ Window { { var component = Qt.createComponent("CameraGizmo.qml"); if (component.status === Component.Ready) { - var geometryName = designStudioNativeCameraControlHelper.generateUniqueName("CameraGeometry"); + var geometryName = _generalHelper.generateUniqueName("CameraGeometry"); var gizmo = component.createObject( overlayScene, {"view3D": overlayView, "targetNode": obj, "geometryName": geometryName, @@ -92,10 +91,10 @@ Window { // Work-around the fact that the projection matrix for the camera is not calculated until // the first frame is rendered, so any initial calls to mapFrom3DScene() will fail. - Component.onCompleted: designStudioNativeCameraControlHelper.requestOverlayUpdate(); + Component.onCompleted: _generalHelper.requestOverlayUpdate(); - onWidthChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); - onHeightChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); + onWidthChanged: _generalHelper.requestOverlayUpdate(); + onHeightChanged: _generalHelper.requestOverlayUpdate(); Node { id: overlayScene @@ -114,6 +113,7 @@ Window { clipNear: editOrthoCamera.clipNear position: editOrthoCamera.position rotation: editOrthoCamera.rotation + scale: editOrthoCamera.scale } MoveGizmo { @@ -209,11 +209,14 @@ Window { linearFade: 0 } + // Initial camera position and rotation should be such that they look at origin. + // Otherwise EditCameraController._lookAtPoint needs to be initialized to correct + // point. PerspectiveCamera { id: editPerspectiveCamera z: -600 - y: 200 - rotation.x: 30 + y: 600 + rotation.x: 45 clipFar: 100000 clipNear: 1 } @@ -221,8 +224,8 @@ Window { OrthographicCamera { id: editOrthoCamera z: -600 - y: 200 - rotation.x: 30 + y: 600 + rotation.x: 45 clipFar: 100000 clipNear: 1 } @@ -273,19 +276,10 @@ Window { } } - WasdController { + EditCameraController { id: cameraControl - controlledObject: editView.camera - acceptedButtons: Qt.RightButton - - onInputsNeedProcessingChanged: designStudioNativeCameraControlHelper.enabled - = cameraControl.inputsNeedProcessing - - // Use separate native timer as QML timers don't work inside Qt Design Studio - Connections { - target: designStudioNativeCameraControlHelper - onUpdateInputs: cameraControl.processInputs() - } + camera: editView.camera + anchors.fill: parent } } @@ -365,39 +359,25 @@ Window { id: editLightCheckbox checked: false text: qsTr("Use Edit View Light") - onCheckedChanged: cameraControl.forceActiveFocus() } CheckBox { id: usePerspectiveCheckbox checked: true text: qsTr("Use Perspective Projection") - onCheckedChanged: { - // Since WasdController always acts on active camera, we need to update pos/rot - // to the other camera when we change - if (checked) { - editPerspectiveCamera.position = editOrthoCamera.position; - editPerspectiveCamera.rotation = editOrthoCamera.rotation; - } else { - editOrthoCamera.position = editPerspectiveCamera.position; - editOrthoCamera.rotation = editPerspectiveCamera.rotation; - } - designStudioNativeCameraControlHelper.requestOverlayUpdate(); - cameraControl.forceActiveFocus(); - } + onCheckedChanged: _generalHelper.requestOverlayUpdate() } CheckBox { id: globalControl checked: true text: qsTr("Use Global Orientation") - onCheckedChanged: cameraControl.forceActiveFocus() } } Text { id: helpText - text: qsTr("Camera: W,A,S,D,R,F,right mouse drag") + text: qsTr("Camera controls: ALT + mouse press and drag. Left: Rotate, Middle: Pan, Right/Wheel: Zoom.") anchors.bottom: parent.bottom } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml index 1392c60cb24..ce8c85bffb4 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml @@ -49,7 +49,7 @@ Item { } Connections { - target: designStudioNativeCameraControlHelper + target: _generalHelper onOverlayUpdateNeeded: updateOverlay() } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp deleted file mode 100644 index 1091e45911b..00000000000 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ -#include "cameracontrolhelper.h" - -#include - -namespace QmlDesigner { -namespace Internal { - -CameraControlHelper::CameraControlHelper() - : QObject() -{ - m_inputUpdateTimer.setInterval(16); - QObject::connect(&m_inputUpdateTimer, &QTimer::timeout, - this, &CameraControlHelper::handleUpdateTimer); - - m_overlayUpdateTimer.setInterval(16); - m_overlayUpdateTimer.setSingleShot(true); - QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout, - this, &CameraControlHelper::overlayUpdateNeeded); -} - -bool CameraControlHelper::enabled() -{ - return m_enabled; -} - -void CameraControlHelper::handleUpdateTimer() -{ - emit updateInputs(); -} - -void CameraControlHelper::setEnabled(bool enabled) -{ - if (enabled) - m_inputUpdateTimer.start(); - else - m_inputUpdateTimer.stop(); - m_enabled = enabled; -} - -void CameraControlHelper::requestOverlayUpdate() -{ - if (!m_overlayUpdateTimer.isActive()) - m_overlayUpdateTimer.start(); -} - -QString CameraControlHelper::generateUniqueName(const QString &nameRoot) -{ - static QHash counters; - int count = counters[nameRoot]++; - return QStringLiteral("%1_%2").arg(nameRoot).arg(count); -} - -} -} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri index e8f546e8187..60046015986 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri @@ -1,9 +1,9 @@ -HEADERS += $$PWD/cameracontrolhelper.h \ +HEADERS += $$PWD/generalhelper.h \ $$PWD/mousearea3d.h \ $$PWD/camerageometry.h \ $$PWD/gridgeometry.h -SOURCES += $$PWD/cameracontrolhelper.cpp \ +SOURCES += $$PWD/generalhelper.cpp \ $$PWD/mousearea3d.cpp \ $$PWD/camerageometry.cpp \ $$PWD/gridgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp new file mode 100644 index 00000000000..b4872ed48fb --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "generalhelper.h" + +#ifdef QUICK3D_MODULE + +#include +#include +#include +#include + +namespace QmlDesigner { +namespace Internal { + +GeneralHelper::GeneralHelper() + : QObject() +{ + m_overlayUpdateTimer.setInterval(16); + m_overlayUpdateTimer.setSingleShot(true); + QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout, + this, &GeneralHelper::overlayUpdateNeeded); +} + +void GeneralHelper::requestOverlayUpdate() +{ + if (!m_overlayUpdateTimer.isActive()) + m_overlayUpdateTimer.start(); +} + +QString GeneralHelper::generateUniqueName(const QString &nameRoot) +{ + static QHash counters; + int count = counters[nameRoot]++; + return QStringLiteral("%1_%2").arg(nameRoot).arg(count); +} + +void GeneralHelper::orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, + const QVector3D &lookAtPoint, const QVector3D &pressPos, + const QVector3D ¤tPos) +{ + QVector3D dragVector = currentPos - pressPos; + + if (dragVector.length() < 0.001f) + return; + + camera->setRotation(startRotation); + QVector3D newRotation(dragVector.y(), dragVector.x(), 0.f); + newRotation *= 0.5f; // Emprically determined multiplier for nice drag + newRotation += startRotation; + + camera->setRotation(newRotation); + + const QVector3D oldLookVector = camera->position() - lookAtPoint; + QMatrix4x4 m = camera->sceneTransform(); + const float *dataPtr(m.data()); + QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]); + newLookVector.normalize(); + newLookVector *= oldLookVector.length(); + + camera->setPosition(lookAtPoint + newLookVector); +} + +// Pans camera and returns the new look-at point +QVector3D GeneralHelper::panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform, + const QVector3D &startPosition, const QVector3D &startLookAt, + const QVector3D &pressPos, const QVector3D ¤tPos, + float zoomFactor) +{ + QVector3D dragVector = currentPos - pressPos; + + if (dragVector.length() < 0.001f) + return startLookAt; + + const float *dataPtr(startTransform.data()); + const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized(); + const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized(); + const QVector3D xDelta = -1.f * xAxis * dragVector.x(); + const QVector3D yDelta = yAxis * dragVector.y(); + const QVector3D delta = (xDelta + yDelta) * zoomFactor; + + camera->setPosition(startPosition + delta); + return startLookAt + delta; +} + +float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float defaultLookAtDistance, + const QVector3D &lookAt, float zoomFactor, bool relative) +{ + // Emprically determined divisor for nice zoom + float multiplier = 1.f + (distance / 40.f); + float newZoomFactor = relative ? qBound(.0001f, zoomFactor * multiplier, 10000.f) + : zoomFactor; + + if (qobject_cast(camera)) { + // Ortho camera we can simply scale + camera->setScale(QVector3D(newZoomFactor, newZoomFactor, newZoomFactor)); + } else if (qobject_cast(camera)) { + // Perspective camera is zoomed by moving camera forward or backward while keeping the + // look-at point the same + const QVector3D lookAtVec = (camera->position() - lookAt).normalized(); + const float newDistance = defaultLookAtDistance * newZoomFactor; + camera->setPosition(lookAt + (lookAtVec * newDistance)); + } + + return newZoomFactor; +} + +} +} + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h similarity index 59% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.h rename to share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index ae171960441..fbf1658924a 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/cameracontrolhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -25,38 +25,43 @@ #pragma once -#include -#include +#ifdef QUICK3D_MODULE + +#include +#include +#include namespace QmlDesigner { namespace Internal { -class CameraControlHelper : public QObject +class GeneralHelper : public QObject { Q_OBJECT - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) public: - CameraControlHelper(); - - bool enabled(); - void setEnabled(bool enabled); + GeneralHelper(); Q_INVOKABLE void requestOverlayUpdate(); Q_INVOKABLE QString generateUniqueName(const QString &nameRoot); -public slots: - void handleUpdateTimer(); + Q_INVOKABLE void orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation, + const QVector3D &lookAtPoint, const QVector3D &pressPos, + const QVector3D ¤tPos); + Q_INVOKABLE QVector3D panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform, + const QVector3D &startPosition, const QVector3D &startLookAt, + const QVector3D &pressPos, const QVector3D ¤tPos, + float zoomFactor); + Q_INVOKABLE float zoomCamera(QQuick3DCamera *camera, float distance, + float defaultLookAtDistance, const QVector3D &lookAt, + float zoomFactor, bool relative); signals: - void updateInputs(); - void enabledChanged(bool enabled); void overlayUpdateNeeded(); private: - bool m_enabled = false; - QTimer m_inputUpdateTimer; QTimer m_overlayUpdateTimer; }; } } + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index 31ed6611250..a1e25dea3a8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -37,7 +37,6 @@ namespace QmlDesigner { namespace Internal { MouseArea3D *MouseArea3D::s_mouseGrab = nullptr; -static const qreal s_mouseDragMultiplier = .02; MouseArea3D::MouseArea3D(QQuick3DNode *parent) : QQuick3DNode(parent) @@ -340,7 +339,7 @@ qreal QmlDesigner::Internal::MouseArea3D::getNewRotationAngle( dragDir = (screenDragDir - nodePos).normalized(); const QVector3D pressToCurrent = (currentPos - pressPos); float magnitude = QVector3D::dotProduct(pressToCurrent, dragDir); - qreal angle = -s_mouseDragMultiplier * qreal(magnitude); + qreal angle = -mouseDragMultiplier() * qreal(magnitude); return angle; } else { const QVector3D nodeToPress = (pressPos - nodePos).normalized(); @@ -397,7 +396,7 @@ void MouseArea3D::applyFreeRotation(QQuick3DNode *node, const QVector3D &startRo QVector3D finalAxis = (dragVector.x() * yAxis + dragVector.y() * xAxis); - qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * s_mouseDragMultiplier); + qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * mouseDragMultiplier()); finalAxis.normalize(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h index e227b3f9dde..c824b92969d 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h @@ -51,7 +51,7 @@ class MouseArea3D : public QQuick3DNode Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged) Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) - Q_PROPERTY(int active READ active WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(QPointF circlePickArea READ circlePickArea WRITE setCirclePickArea NOTIFY circlePickAreaChanged) Q_PROPERTY(qreal minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged) Q_PROPERTY(QQuick3DNode *pickNode READ pickNode WRITE setPickNode NOTIFY pickNodeChanged) @@ -77,6 +77,8 @@ public: qreal minAngle() const; QQuick3DNode *pickNode() const; + static qreal mouseDragMultiplier() { return .02; } + public slots: void setView3D(QQuick3DViewport *view3D); void setGrabsMouse(bool grabsMouse); @@ -157,7 +159,7 @@ private: QVector3D getMousePosInPlane(const QPointF &mousePosInView) const; static MouseArea3D *s_mouseGrab; - bool m_grabsMouse; + bool m_grabsMouse = false; QVector3D m_mousePosInPlane; QPointF m_circlePickArea; qreal m_minAngle = 0.; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 2cd59af4607..9aa90bfad0f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -62,7 +62,7 @@ #include #include "dummycontextobject.h" -#include "../editor3d/cameracontrolhelper.h" +#include "../editor3d/generalhelper.h" #include "../editor3d/mousearea3d.h" #include "../editor3d/camerageometry.h" #include "../editor3d/gridgeometry.h" @@ -104,10 +104,9 @@ bool Qt5InformationNodeInstanceServer::eventFilter(QObject *, QEvent *event) QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) { - auto helper = new QmlDesigner::Internal::CameraControlHelper(); - engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper); - #ifdef QUICK3D_MODULE + auto helper = new QmlDesigner::Internal::GeneralHelper(); + engine->rootContext()->setContextProperty("_generalHelper", helper); qmlRegisterType("MouseArea3D", 1, 0, "MouseArea3D"); qmlRegisterType("CameraGeometry", 1, 0, "CameraGeometry"); qmlRegisterType("GridGeometry", 1, 0, "GridGeometry"); diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index f818f23fd52..a91590b59e7 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -8,6 +8,7 @@ mockfiles/GenericBackend.qml mockfiles/Dialog.qml mockfiles/EditView3D.qml + mockfiles/EditCameraController.qml mockfiles/Arrow.qml mockfiles/AutoScaleHelper.qml mockfiles/MoveGizmo.qml diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 3f8987ee60f..2954059971c 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -108,7 +108,7 @@ extend_qtc_executable(qml2puppet extend_qtc_executable(qml2puppet SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d" SOURCES - cameracontrolhelper.cpp cameracontrolhelper.h + generalhelper.cpp generalhelper.h mousearea3d.cpp mousearea3d.h camerageometry.cpp camerageometry.h gridgeometry.cpp gridgeometry.h diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index ca1c3654fbe..8e7ac853317 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -197,8 +197,8 @@ QtcTool { "instances/qt5testnodeinstanceserver.h", "instances/servernodeinstance.cpp", "instances/servernodeinstance.h", - "editor3d/cameracontrolhelper.cpp", - "editor3d/cameracontrolhelper.h", + "editor3d/generalhelper.cpp", + "editor3d/generalhelper.h", "editor3d/mousearea3d.cpp", "editor3d/mousearea3d.h", "editor3d/camerageometry.cpp", From 4c73b4629c5797a1c8eaf1ac54f10cc00ebcc11d Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 18 Nov 2019 13:10:54 +0200 Subject: [PATCH 04/37] QmlDesigner: Some fixes to edit 3D after UX review - Slightly larger cam plane rotate ring to avoid overlap - Scale tool is always local - Little more transparent and borderless light/cam icons when selected - Center light/cam icon on the object Change-Id: Icb24d89fb3ea852b139677aebe797881a12e474a Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml | 2 +- share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml | 8 ++++---- share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index a4d63962d8b..da5a5a4950d 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -138,7 +138,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: false visible: selectedNode && btnScale.selected view3D: overlayView diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml index 8623b87a840..f41fbad0be2 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml @@ -61,13 +61,13 @@ Node { width: iconImage.width height: iconImage.height x: -width / 2 - y: -height + y: -height / 2 color: "transparent" border.color: "#7777ff" - border.width: iconGizmo.selectedNode === iconGizmo.targetNode - || (iconGizmo.highlightOnHover && iconMouseArea.containsMouse) ? 2 : 0 + border.width: iconGizmo.selectedNode !== iconGizmo.targetNode + && iconGizmo.highlightOnHover && iconMouseArea.containsMouse ? 2 : 0 radius: 5 - opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.3 : 1 + opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.2 : 1 Image { id: iconImage fillMode: Image.Pad diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml index b2f42b39e2f..b730e869103 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml @@ -134,8 +134,7 @@ Node { targetNode: rotateGizmo.targetNode color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) : Qt.rgba(0.5, 0.5, 0.5, 1) - // Just a smidge smaller than higher priority rings so that it doesn't obscure them - scale: Qt.vector3d(0.994, 0.994, 0.994) + scale: Qt.vector3d(1.1, 1.1, 1.1) priority: 10 view3D: rotateGizmo.view3D active: rotateGizmo.visible From 3dd5e089b10c89446f34b01a0f535aa936719cb7 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 18 Nov 2019 15:02:07 +0200 Subject: [PATCH 05/37] QmlDesigner: Add UX approved light icons for 3D editview Light icons have a color overlay that indicates light color. Change-Id: I5f6d80f63d0916dd7cb7b2d5345d586aacd550ef Fixes: QDS-1209 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/CameraGizmo.qml | 25 +++++++++++------- .../qml/qmlpuppet/mockfiles/IconGizmo.qml | 21 ++++++++++----- .../qml/qmlpuppet/mockfiles/LightGizmo.qml | 17 +++++------- .../mockfiles/images/area_light_gradient.png | Bin 0 -> 1054 bytes .../images/area_light_gradient@2x.png | Bin 0 -> 1268 bytes .../images/directional_light_gradient.png | Bin 0 -> 1420 bytes .../images/directional_light_gradient@2x.png | Bin 0 -> 3367 bytes .../mockfiles/images/point_light_gradient.png | Bin 0 -> 1177 bytes .../images/point_light_gradient@2x.png | Bin 0 -> 2634 bytes share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 6 +++++ 10 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml index e158128a5fd..3b6badbb281 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml @@ -31,21 +31,26 @@ IconGizmo { id: cameraGizmo iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png" - gizmoModel.geometry: cameraGeometry property alias geometryName: cameraGeometry.name // Name must be unique for each geometry property alias viewPortRect: cameraGeometry.viewPortRect + Model { + id: gizmoModel + geometry: cameraGeometry + visible: cameraGizmo.visible + materials: [ + DefaultMaterial { + id: defaultMaterial + emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" + : "#555555" + lighting: DefaultMaterial.NoLighting + cullingMode: Material.DisableCulling + } + ] + } + CameraGeometry { id: cameraGeometry camera: cameraGizmo.targetNode } - - gizmoModel.materials: [ - DefaultMaterial { - id: defaultMaterial - emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" : "#555555" - lighting: DefaultMaterial.NoLighting - cullingMode: Material.DisableCulling - } - ] } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml index f41fbad0be2..ea6c17a1c3e 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml @@ -25,6 +25,7 @@ import QtQuick 2.0 import QtQuick3D 1.0 +import QtGraphicalEffects 1.12 Node { id: iconGizmo @@ -34,8 +35,8 @@ Node { property Node targetNode: null property Node selectedNode: null - property alias gizmoModel: gizmoModel property alias iconSource: iconImage.source + property alias overlayColor: colorOverlay.color signal positionCommit() signal clicked(Node node) @@ -44,13 +45,9 @@ Node { rotation: targetNode ? targetNode.sceneRotation : Qt.vector3d(0, 0, 0) visible: targetNode ? targetNode.visible : false - Model { - id: gizmoModel - visible: iconGizmo.visible - } Overlay2D { - id: gizmoLabel - targetNode: gizmoModel + id: iconOverlay + targetNode: iconGizmo targetView: view3D offsetX: 0 offsetY: 0 @@ -58,6 +55,7 @@ Node { parent: view3D Rectangle { + id: iconRect width: iconImage.width height: iconImage.height x: -width / 2 @@ -81,6 +79,15 @@ Node { ? Qt.LeftButton : Qt.NoButton } } + ColorOverlay { + id: colorOverlay + anchors.fill: parent + cached: true + source: iconImage + color: transparent + opacity: 0.6 + } + } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml index 888b2fce5cd..de6deefb943 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml @@ -29,14 +29,11 @@ import QtQuick3D 1.0 IconGizmo { id: lightGizmo - iconSource: "qrc:///qtquickplugin/mockfiles/images/light-pick-icon.png" - gizmoModel.source: "#Sphere" - gizmoModel.scale: Qt.vector3d(0.10, 0.10, 0.10) - gizmoModel.materials: [ - DefaultMaterial { - id: defaultMaterial - emissiveColor: "yellow" - lighting: DefaultMaterial.NoLighting - } - ] + iconSource: targetNode instanceof DirectionalLight + ? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png" + : targetNode instanceof AreaLight + ? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png" + : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" + + overlayColor: targetNode.color } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6404a36c9dda12ce6e212617a6d08e2930a281 GIT binary patch literal 1054 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F9ehxU}5hx&Z^?`~=bL5p?xh3rr=ACJuP!wdcX_v9(V_hA?w`vlS9h}=wOc2?V zqF~Wuz?b}>Ss}$ZIg-P&`OMsv+Rq=R{JuT!Mj_AT;xB({uIH^?{(1BMt=FyY+f~>9 zmZ^CY@yYPz`Sa)RD=fX^?ZT)utIKV1`*hVtz33@ZrmRt1RO_ySlnUUA9DX2pY`)qBeWk)r%Ql4DGfw7Fg_=)3NES;=*~K%-9eA(r4IuS-m@J z!OE4IQ#~+q_wL=Zv#gyIz?_?#tLgHkS2K*ab1sA3cgM=jTeog4 zf7aR}`QpWk9Ud-A8N!SL|M4qW{C*Uq_UZeDn>Tk#I#@2QXf@W=)%|~V-wXj}hAf69 z2A}?NJ(zZtw~RS9Hufe1pFz;RF#S9gA;UF!o1|X6dlwd*Fk`atfu+x$Jxkm@`;O!Z z)(y=Q-**}r#50>Q+uGWm7JGGuxl2k~TKzfq<1-G54ZS@z+oh$Xs>HI6BrVv!y_~h7 zSSCg-j=|#X62)+~ko46vcZf87{rc5Vowru{#p~D6xm%rn9mr=;@;hv4B*3&`j^~~L z{k+)NxliZhv&OUi`u+Q=_wTv#eUUq2f`dP|&t}*!xgt%6V?NW0BIzeL4;(nqu<9v) zW$*R_A6Knf6`t4pC#7L?%8ua3$e-QQ9sJqY*x5rjZaeM0hBc1K;;HG4t&Iy8E?kADxAh<3hs1mK6(F8W~twt=i`~ zt)PVCL0)F&%kw@leZ~u>{RnCMr^YZR=1P;K4zf=P{0 zZT~synJgkAB5u5xoX+>m)WFVeAOC?m`9Jl{7OVC>6&De?^I83>)V8GsI%3gEOV`9I z+~X5YTUo2Cuiu}#tuU9tL9QWJ?`MeRodrjpKYOQ7mv zox1w-pGh3^+hWzopr02%Dy>;M1& literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/area_light_gradient@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..463f3ac481ef022c6b806f9cf6d7e12924524fd0 GIT binary patch literal 1268 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0D>?DlkV45_&F_U3=@yQLz> zKW>jNx~rDD>6GdAj0;JZ6OMKyNVBb#*qG|)Vlr{h?v5EVGN$pK?VLH&%5c9z^7YP{ z!p5=Xi*C3c`I45l?8IHYduQ_A`T5*^`)vE|ulHWBj{lXo@$8o>i}~kSlg;gNQc?QHXaB(P;VOqz7pK%ey%tB5*e-TB zsVLcfYWOf^?n(8@UBdN2Yc(e}RNP@SaCtMKu%a!#D&p49EB~fkO;J%4)VjmUF*&tj z+xeZ!k&!d+r>$9{%)8R#U@gP+RIz#Qr;5*-J*(LCb`@Xb2^Y3&tY_TcPV%j~_|GZy z;M6}eZJsEx-@GC4AXl%|TPm+Zj=4I$}9?oW3eLf^KOyX2vTaZZd zWrpfAnmE3G;ihCzoo0U20T{E+MwECIPLw{ z{JR$?U0stKmFdF#Dv(|1fOgOJ{IeO3#1(MsfF+xJu7e7+ALAfWVrwG z>c{R$4$QBgUzWVe7}TKpvhdiSb?jF4ifk&I?(Kg)*KYz-$;mnE_g~xpnm?#PS+(Ws zzgv6sCNSA0o_)`ENpB)kop0y|rd3-NSoa*8b-#GQZBMR@q<=4Od@eQTV7&H4;o6^j z)2ke~Jd*a+zb{|X@ZNY&HpdB! zb9T1R{Ma0u6*-d-dmnkGGWDqcFTBq12ccN0gsDBN}OO2zww#3`iq&- zfwM{Vbq!JcMh9lU`T1CpOu|xFefK^7;86jQ%;WN$7ol z$nGNL$Wjn0lX!mqm$?R$811G%IA3m5$>hRNeD&~~pKAY4N*W!I}H_SN-UR|j@=#;m)F7aR+!+jnZp-;CDCBDAJ#;|MQVyAi0FE%}@XE1j= z)EcwBB8l-e)0yOS_uACi``>J}*u!@qt0I2AK+(NV(cL@v52WeH)rXv@HrxO7WHnRF zBf>VpcEikZz}DllqNG`X95w85fT8Gaq~YJ|)`_UA!tX z{-I}a%%;cj4OeHS26CLA^?JeK%y!<>+m23Zb$D1=oGG(m{Y^dn_rmimWQq?Ko|V(G lDb*;H6~BFZUi5GF3DR-1-kHcqF)%PNc)I$ztaD0e0suf8T8jVx literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional_light_gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..f3c013e157d2b87df24b6356c3160b52728f58ab GIT binary patch literal 1420 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 PFfe$!`njxgN@xNAF`{Ws literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..5136b39fc2f37b80177f3d2b6d5d99b374298af8 GIT binary patch literal 1177 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZsh37#&FArXhy&dAP?2^Bg1 z-}v{bH2J%36MkhZ_2_t8ep%m6OG1l7jAi1fB(JmVoldvvZuUPC&#YM*m6a2?#%W*1 zCXxB8ul|bY4sy-i+Ld`JEJtVUi?s4G_1U#m?~=>Z4zuN#J(trf{(ffX^YU{$&5g?! zIWPU1D6;;c_L)ceF~{;PIz4TcnF#;-9~IN@Y|(xA$p^nLkJ;|D+%DjkQ-8oJbD;Dt z)3=B0HlBW!mmfS{)H#3l#6#v4ONt$u7S%LbUKem;DGXZkc+!HxmJ*g%#|>rP@Ju)m zsMWnp*+=iO%CzD_(OCvx7><2NQ*RLeC~)Dh?9F#`lkUD`l#8|PzRK`>WAtJp7s1Du zUqxa zA=|27&WE!aaush$@(8xYt|()Ol*v1p*0N2L(TSPq!I?vQCqG*IS9$Ssp*xFMIPOTe z2>5kGa9Xnq?iby=f&1c|2WqAcN(XwP1;Q9s`&?7%ei6NN;^(L-8%{8?v3J;5Jjwd{(sbWsZT3^4 z59>PJ&)>N%X~1$i$y4c+`##(4ZU_2jeyUdb6~sLuzmrv?Q>QN8?#98LD{79c>AJPP z=l;y*i0-A^{hnJf{Q1-Qv$E4Y)1zUt3+uY4-}PrsmX(t|`*@MXyB}|5Di)@ldt$|M z##c;#Cu4VBLuA$B?!)E&fsVJ>KH|gN(WVX7F5Bl3udaLJ&J;5<8IqgG4 zQB8@BW!?23y6v8u56@ojb9`YnbFIZ4?^@>G(AiQ6eD9TFz4e#(ev!X2J=15F<$H$D z6=FB%Z&Kf6eDnIs`3np)pY7GT_;yBzZ_eBu$&cz@MQ8d*RqSCCwEB^EMBpn+@7`GE z2hJ*IQ}ikgf7*SO>Ggc9nIIP28hqI~`S$l5dFfepp)-_vud6Ql@5}RErm`~Sxk0au rzF>Cuj!pk=t-bzh-35=Gf7#znmtqs1mDj|;z`)??>gTe~DWM4f9}_6A literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/point_light_gradient@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ccbfb1c8466ae4c95ee4f551786c5bfdf9d6eb1d GIT binary patch literal 2634 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 b|M*Q0i|su+`_yIz1_lOCS3j3^P6mockfiles/images/scale_active@2x.png mockfiles/images/scale_selected.png mockfiles/images/scale_selected@2x.png + mockfiles/images/directional_light_gradient.png + mockfiles/images/directional_light_gradient@2x.png + mockfiles/images/point_light_gradient.png + mockfiles/images/point_light_gradient@2x.png + mockfiles/images/area_light_gradient.png + mockfiles/images/area_light_gradient@2x.png From dbfdacecf4fe60ee85200510e325930272e0850e Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 18 Nov 2019 15:44:33 +0200 Subject: [PATCH 06/37] QmlDesigner: Fix issues with MouseArea3D deactivation detection Existing mouse grab is now released when MouseArea3D is deactivated or set to no longer grab the mouse. Various gizmos were also set to follow MouseArea3D's dragging property instead of keeping track of drag themselves. Change-Id: I49f968f20b26eb222fc8635b943e9144073fb164 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qmlpuppet/mockfiles/DirectionalDraggable.qml | 4 +--- .../qml/qmlpuppet/mockfiles/PlanarDraggable.qml | 4 +--- .../qml/qmlpuppet/mockfiles/RotateRing.qml | 4 +--- .../qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp | 14 ++++++++++++++ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml index 243744210ee..7ccfaa9816c 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml @@ -34,7 +34,7 @@ Model { property View3D view3D property alias color: material.emissiveColor property Node targetNode: null - property bool dragging: false + property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging property bool active: false readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering @@ -61,7 +61,6 @@ Model { _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition); var sp = targetNode.scenePosition; _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - dragging = true; pressed(mouseArea); } @@ -88,7 +87,6 @@ Model { return; released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); - dragging = false; } MouseArea3D { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml index 7bb1085e65c..bd4fcd388bf 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml @@ -34,7 +34,7 @@ Model { property alias color: gizmoMaterial.emissiveColor property alias priority: mouseArea.priority property Node targetNode: null - property bool dragging: false + property bool dragging: mouseArea.dragging property bool active: false readonly property bool hovering: mouseArea.hovering @@ -65,7 +65,6 @@ Model { _pointerPosPressed = mouseArea.mapPositionToScene(scenePos); var sp = targetNode.scenePosition; _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); - dragging = true; pressed(mouseArea); } @@ -91,7 +90,6 @@ Model { return; released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); - dragging = false; } MouseArea3D { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml index 634eb017c9b..3d21f8fd6a3 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml @@ -33,7 +33,7 @@ Model { property View3D view3D property alias color: material.emissiveColor property Node targetNode: null - property bool dragging: false + property bool dragging: mouseAreaMain.dragging property bool active: false property alias hovering: mouseAreaMain.hovering property alias priority: mouseAreaMain.priority @@ -80,7 +80,6 @@ Model { _targetPosOnScreen = view3D.mapFrom3DScene(targetNode.scenePosition); _targetPosOnScreen.z = 0; _pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0); - dragging = true; _trackBall = angle < 0.1; // Recreate vector so we don't follow the changes in targetNode.rotation @@ -108,7 +107,6 @@ Model { applyLocalRotation(screenPos); rotateCommit(); - dragging = false; currentAngle = 0; currentMousePos = screenPos; } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index a1e25dea3a8..d571b24dcbe 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -123,6 +123,13 @@ void MouseArea3D::setGrabsMouse(bool grabsMouse) return; m_grabsMouse = grabsMouse; + + if (!m_grabsMouse && s_mouseGrab == this) { + setDragging(false); + setHovering(false); + s_mouseGrab = nullptr; + } + emit grabsMouseChanged(); } @@ -132,6 +139,13 @@ void MouseArea3D::setActive(bool active) return; m_active = active; + + if (!m_active && s_mouseGrab == this) { + setDragging(false); + setHovering(false); + s_mouseGrab = nullptr; + } + emit activeChanged(); } From 0b510f173eccc5ca07b2c9fbb587107cc6aacb3f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 19 Nov 2019 17:43:03 +0200 Subject: [PATCH 07/37] QmlDesigner: Implement selection box to 3D edit view Change-Id: Ib0b13ecd7946e3b7da8ed06d4f5965e06e51a152 Fixes: QDS-1210 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 5 + .../qml/qmlpuppet/mockfiles/IconGizmo.qml | 2 +- .../qml/qmlpuppet/mockfiles/LightGizmo.qml | 14 +- .../qml/qmlpuppet/mockfiles/SelectionBox.qml | 65 ++++++ .../qml2puppet/editor3d/editor3d.pri | 6 +- .../editor3d/selectionboxgeometry.cpp | 216 ++++++++++++++++++ .../editor3d/selectionboxgeometry.h | 79 +++++++ .../qt5informationnodeinstanceserver.cpp | 2 + share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 1 + src/tools/qml2puppet/CMakeLists.txt | 1 + src/tools/qml2puppet/qml2puppet.qbs | 2 + 11 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml create mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp create mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index da5a5a4950d..3ce3c5deabe 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -200,6 +200,11 @@ Window { step: 50 } + SelectionBox { + view3D: editView + targetNode: viewWindow.selectedNode + } + PointLight { id: editLight visible: showEditLight diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml index ea6c17a1c3e..ebc52a126aa 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml @@ -84,7 +84,7 @@ Node { anchors.fill: parent cached: true source: iconImage - color: transparent + color: "transparent" opacity: 0.6 } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml index de6deefb943..6e321f8398a 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml @@ -29,11 +29,13 @@ import QtQuick3D 1.0 IconGizmo { id: lightGizmo - iconSource: targetNode instanceof DirectionalLight - ? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png" - : targetNode instanceof AreaLight - ? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png" - : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" + iconSource: targetNode + ? targetNode instanceof DirectionalLight + ? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png" + : targetNode instanceof AreaLight + ? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png" + : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" + : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png" - overlayColor: targetNode.color + overlayColor: targetNode ? targetNode.color : "transparent" } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml new file mode 100644 index 00000000000..6465cab2b78 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 +import SelectionBoxGeometry 1.0 + +Node { + id: selectionBox + + property View3D view3D + property Node targetNode: null + + SelectionBoxGeometry { + id: selectionBoxGeometry + name: "Selection Box of 3D Edit View" + view3D: selectionBox.view3D + targetNode: selectionBox.targetNode + rootNode: selectionBox + } + + Model { + id: selectionBoxModel + geometry: selectionBoxGeometry + + scale: selectionBox.targetNode ? selectionBox.targetNode.scale : Qt.vector3d(1, 1, 1) + rotation: selectionBox.targetNode ? selectionBox.targetNode.rotation : Qt.vector3d(0, 0, 0) + position: selectionBox.targetNode ? selectionBox.targetNode.position : Qt.vector3d(0, 0, 0) + pivot: selectionBox.targetNode ? selectionBox.targetNode.pivot : Qt.vector3d(0, 0, 0) + orientation: selectionBox.targetNode ? selectionBox.targetNode.orientation : Node.LeftHanded + rotationOrder: selectionBox.targetNode ? selectionBox.targetNode.rotationOrder : Node.YXZ + + visible: selectionBox.targetNode && selectionBox.targetNode instanceof Model + + materials: [ + DefaultMaterial { + emissiveColor: "#e5009e" + lighting: DefaultMaterial.NoLighting + cullingMode: Material.DisableCulling + } + ] + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri index 60046015986..7b515e7a60c 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri @@ -1,9 +1,11 @@ HEADERS += $$PWD/generalhelper.h \ $$PWD/mousearea3d.h \ $$PWD/camerageometry.h \ - $$PWD/gridgeometry.h + $$PWD/gridgeometry.h \ + $$PWD/selectionboxgeometry.h SOURCES += $$PWD/generalhelper.cpp \ $$PWD/mousearea3d.cpp \ $$PWD/camerageometry.cpp \ - $$PWD/gridgeometry.cpp + $$PWD/gridgeometry.cpp \ + $$PWD/selectionboxgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp new file mode 100644 index 00000000000..452d924427e --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#ifdef QUICK3D_MODULE + +#include "selectionboxgeometry.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace QmlDesigner { +namespace Internal { + +SelectionBoxGeometry::SelectionBoxGeometry() + : QQuick3DGeometry() +{ +} + +SelectionBoxGeometry::~SelectionBoxGeometry() +{ +} + +QQuick3DNode *SelectionBoxGeometry::targetNode() const +{ + return m_targetNode; +} + +QQuick3DNode *SelectionBoxGeometry::rootNode() const +{ + return m_rootNode; +} + +QQuick3DViewport *SelectionBoxGeometry::view3D() const +{ + return m_view3D; +} + +void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode) +{ + if (m_targetNode == targetNode) + return; + + if (m_targetNode) + m_targetNode->disconnect(this); + m_targetNode = targetNode; + + if (auto model = qobject_cast(m_targetNode)) { + QObject::connect(model, &QQuick3DModel::sourceChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + QObject::connect(model, &QQuick3DModel::geometryChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + } + + emit targetNodeChanged(); + update(); +} + +void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode) +{ + if (m_rootNode == rootNode) + return; + + m_rootNode = rootNode; + + emit rootNodeChanged(); + update(); +} + +void SelectionBoxGeometry::setView3D(QQuick3DViewport *view) +{ + if (m_view3D == view) + return; + + m_view3D = view; + + emit view3DChanged(); + update(); +} + +QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node) +{ + node = QQuick3DGeometry::updateSpatialNode(node); + QSSGRenderGeometry *geometry = static_cast(node); + + geometry->clear(); + + QByteArray vertexData; + QByteArray indexData; + + QVector3D minBounds(-100.f, -100.f, -100.f); + QVector3D maxBounds(100.f, 100.f, 100.f); + QVector3D extents; + + if (m_targetNode) { + auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode); + auto targetPriv = QQuick3DObjectPrivate::get(m_targetNode); + auto rootRN = static_cast(rootPriv->spatialNode); + auto targetRN = static_cast(targetPriv->spatialNode); + if (rootRN && targetRN) { + // Explicitly set local transform of root node to target node parent's global transform + // to avoid having to reparent the selection box. This has to be done directly on render + // nodes. + targetRN->parent->calculateGlobalVariables(); + QMatrix4x4 m = targetRN->parent->globalTransform; + rootRN->localTransform = m; + rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty); + rootRN->calculateGlobalVariables(); + } + if (auto modelNode = qobject_cast(m_targetNode)) { + auto nodePriv = QQuick3DObjectPrivate::get(m_targetNode); + if (auto renderModel = static_cast(nodePriv->spatialNode)) { + QWindow *window = static_cast(m_view3D->window()); + if (window) { + auto context = QSSGRenderContextInterface::getRenderContextInterface( + quintptr(window)); + if (!context.isNull()) { + auto bufferManager = context->bufferManager(); + QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); + QVector3D center = bounds.center(); + extents = bounds.extents(); + minBounds = center - extents; + maxBounds = center + extents; + } + } + } + } + } + + // Adjust bounds to reduce targetNode pixels obscuring the selection box + extents /= 1000.f; + minBounds -= extents; + maxBounds += extents; + + fillVertexData(vertexData, indexData, minBounds, maxBounds); + + geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0, + QSSGRenderGeometry::Attribute::ComponentType::F32Type); + geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0, + QSSGRenderGeometry::Attribute::ComponentType::U16Type); + geometry->setStride(12); + geometry->setVertexData(vertexData); + geometry->setIndexData(indexData); + geometry->setPrimitiveType(QSSGRenderGeometry::Lines); + geometry->setBounds(minBounds, maxBounds); + + return node; +} + +void SelectionBoxGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds) +{ + const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert + vertexData.resize(vertexSize); + const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line + indexData.resize(indexSize); + + auto dataPtr = reinterpret_cast(vertexData.data()); + auto indexPtr = reinterpret_cast(indexData.data()); + + *dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); + *dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); + + *indexPtr++ = 0; *indexPtr++ = 1; + *indexPtr++ = 1; *indexPtr++ = 2; + *indexPtr++ = 2; *indexPtr++ = 3; + *indexPtr++ = 3; *indexPtr++ = 0; + + *indexPtr++ = 0; *indexPtr++ = 4; + *indexPtr++ = 1; *indexPtr++ = 5; + *indexPtr++ = 2; *indexPtr++ = 6; + *indexPtr++ = 3; *indexPtr++ = 7; + + *indexPtr++ = 4; *indexPtr++ = 5; + *indexPtr++ = 5; *indexPtr++ = 6; + *indexPtr++ = 6; *indexPtr++ = 7; + *indexPtr++ = 7; *indexPtr++ = 4; +} + +} +} + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h new file mode 100644 index 00000000000..afe5efd8cf0 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#ifdef QUICK3D_MODULE + +#include +#include +#include + +namespace QmlDesigner { +namespace Internal { + +class SelectionBoxGeometry : public QQuick3DGeometry +{ + Q_OBJECT + Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged) + Q_PROPERTY(QQuick3DNode *rootNode READ rootNode WRITE setRootNode NOTIFY rootNodeChanged) + Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged) + +public: + SelectionBoxGeometry(); + ~SelectionBoxGeometry() override; + + QQuick3DNode *targetNode() const; + QQuick3DNode *rootNode() const; + QQuick3DViewport *view3D() const; + +public Q_SLOTS: + void setTargetNode(QQuick3DNode *targetNode); + void setRootNode(QQuick3DNode *rootNode); + void setView3D(QQuick3DViewport *view); + +Q_SIGNALS: + void targetNodeChanged(); + void rootNodeChanged(); + void view3DChanged(); + +protected: + QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override; + +private: + void fillVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds); + + QQuick3DNode *m_targetNode = nullptr; + QQuick3DViewport *m_view3D = nullptr; + QQuick3DNode *m_rootNode = nullptr; +}; + +} +} + +QML_DECLARE_TYPE(QmlDesigner::Internal::SelectionBoxGeometry) + +#endif // QUICK3D_MODULE diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 9aa90bfad0f..fabb2a67cc8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -66,6 +66,7 @@ #include "../editor3d/mousearea3d.h" #include "../editor3d/camerageometry.h" #include "../editor3d/gridgeometry.h" +#include "../editor3d/selectionboxgeometry.h" #include @@ -110,6 +111,7 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) qmlRegisterType("MouseArea3D", 1, 0, "MouseArea3D"); qmlRegisterType("CameraGeometry", 1, 0, "CameraGeometry"); qmlRegisterType("GridGeometry", 1, 0, "GridGeometry"); + qmlRegisterType("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry"); #endif QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml")); diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index fa07a2ff117..f27f93e0d45 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -26,6 +26,7 @@ mockfiles/ToolBarButton.qml mockfiles/RotateGizmo.qml mockfiles/RotateRing.qml + mockfiles/SelectionBox.qml mockfiles/meshes/arrow.mesh mockfiles/meshes/scalerod.mesh mockfiles/meshes/ring.mesh diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 2954059971c..1859bebe98f 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -112,6 +112,7 @@ extend_qtc_executable(qml2puppet mousearea3d.cpp mousearea3d.h camerageometry.cpp camerageometry.h gridgeometry.cpp gridgeometry.h + selectionboxgeometry.cpp selectionboxgeometry.h ) extend_qtc_executable(qml2puppet diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index 8e7ac853317..fe42083d6e2 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -205,6 +205,8 @@ QtcTool { "editor3d/camerageometry.h", "editor3d/gridgeometry.cpp", "editor3d/gridgeometry.h", + "editor3d/selectionboxgeometry.cpp", + "editor3d/selectionboxgeometry.h", "qml2puppetmain.cpp", ] } From 2a7a90823362602ad0badc261773ff08c237ab2d Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 19 Nov 2019 17:27:32 +0100 Subject: [PATCH 08/37] McuSupport: Only (re-)generate kits when on Mcu options page ... less surprises, like for example user is on the Kits page, edits an existing kit, and that gets overwritten when pressing "Apply" Change-Id: I2d936b757cb5c891a087854805fa2f056834185f Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcusupportoptionspage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 06bb9a86e63..c0d1c42afc7 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -168,6 +168,9 @@ void McuSupportOptionsPage::apply() QTC_ASSERT(m_options->armGccPackage, return); QTC_ASSERT(m_options->qtForMCUsSdkPackage, return); + if (!widget()->isVisible()) + return; // Only create/overwrite kits when this option page is shown + const McuTarget *mcuTarget = m_widget->currentMcuTarget(); if (!mcuTarget) return; From 1b89d4ba533650ce479b760a0c207d8f2e9c0bad Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 21 Nov 2019 11:29:53 +0100 Subject: [PATCH 09/37] McuSupport: Rename package key QtMCUSdk -> Package_QtForMCUsSdk ...final name. Forever. Task-number: QTBUG-80242 Change-Id: Id9fe7001738e2fd5f4f08c3cd02a78dbf9c45e7d Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcusupportoptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 10147d2ac3f..431b91f1e2a 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -267,7 +267,7 @@ static McuPackage *createQtForMCUsPackage() McuPackage::tr("Qt for MCUs SDK"), QDir::homePath(), Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"), - "QtMCUSdk"); + "QtForMCUsSdk"); result->setEnvironmentVariableName("Qul_DIR"); return result; } From 7a46dc620ebe715b95077a04098bec8c039ed978 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 22 Nov 2019 13:00:29 +0200 Subject: [PATCH 10/37] QmlDesigner: Fix build error Change-Id: I53d425d0b6f4e66c09bd988bd188218cbf51a99c Reviewed-by: Nikolai Kosjar --- .../qml2puppet/instances/qt5informationnodeinstanceserver.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index fabb2a67cc8..d3747ab3b33 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -137,7 +137,10 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) surfaceFormat.setVersion(4, 1); surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); window->setFormat(surfaceFormat); + +#ifdef QUICK3D_MODULE helper->setParent(window); +#endif return window; } From b619c60ff715c99a3bee64e14ae41600028df48e Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 21 Nov 2019 22:06:38 +0100 Subject: [PATCH 11/37] CMakeprojectManager: Use Utils::ElidingLabel in GeneratorKitAspect Don't stretch the kit options page horizontally more than required. Change-Id: I8eb3855ae48a8a172741b1c42f79b9e05cc7eb42 Reviewed-by: Eike Ziller --- src/plugins/cmakeprojectmanager/cmakekitinformation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 63dfdac4c6c..26e4bffdebb 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -318,7 +318,7 @@ class CMakeGeneratorKitAspectWidget : public KitAspectWidget public: CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki) : KitAspectWidget(kit, ki), - m_label(new QLabel), + m_label(new Utils::ElidingLabel), m_changeButton(new QPushButton) { m_label->setToolTip(ki->description()); @@ -459,7 +459,7 @@ private: } bool m_ignoreChange = false; - QLabel *m_label; + Utils::ElidingLabel *m_label; QPushButton *m_changeButton; CMakeTool *m_currentTool = nullptr; }; From c7120bde92d1ad3402fb8a093187e6b752da244f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 20 Nov 2019 18:01:34 +0200 Subject: [PATCH 12/37] QmlDesigner: Implement axis helper on 3D edit view Axis helper shows up on top right corner of 3D edit view. Clicking on axis helper arms zooms camera on that side of the selected object. Change-Id: Ibd81a933036f7965f825e3dc97ad7156da62e14c Fixes: QDS-1205 Reviewed-by: Thomas Hartmann --- .../qmlpuppet/mockfiles/AutoScaleHelper.qml | 1 + .../qml/qmlpuppet/mockfiles/AxisHelper.qml | 133 ++++++++++++++++++ .../qml/qmlpuppet/mockfiles/AxisHelperArm.qml | 70 +++++++++ .../mockfiles/EditCameraController.qml | 10 ++ .../qml/qmlpuppet/mockfiles/EditView3D.qml | 17 ++- .../qml/qmlpuppet/mockfiles/IconGizmo.qml | 2 - .../qml/qmlpuppet/mockfiles/Overlay2D.qml | 7 +- .../mockfiles/meshes/axishelper.mesh | Bin 0 -> 158516 bytes .../qml2puppet/editor3d/generalhelper.cpp | 59 ++++++++ .../qml2puppet/editor3d/generalhelper.h | 4 + share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 3 + 11 files changed, 297 insertions(+), 9 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml index cec64b32b57..dc4c38d1009 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml @@ -81,6 +81,7 @@ Node { MouseArea3D { id: helper + active: false view3D: overlayNode.view3D } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml new file mode 100644 index 00000000000..86c60db7213 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 + +View3D { + id: axisHelperView + + property var editCameraCtrl + property Node selectedNode + + camera: axisHelperCamera + + Node { + OrthographicCamera { + id: axisHelperCamera + rotation: editCameraCtrl.camera.rotation + position: editCameraCtrl.camera.position.minus(editCameraCtrl._lookAtPoint) + .normalized().times(600) + } + + AutoScaleHelper { + id: autoScale + view3D: axisHelperView + position: axisHelperGizmo.scenePosition + } + + Node { + id: axisHelperGizmo + scale: autoScale.getScale(Qt.vector3d(4, 4, 4)) + + AxisHelperArm { + id: armX + rotation: Qt.vector3d(0, 0, -90) + color: Qt.rgba(1, 0, 0, 1) + hoverColor: Qt.lighter(Qt.rgba(1, 0, 0, 1)) + view3D: axisHelperView + camRotPos: Qt.vector3d(0, 90, 0) + camRotNeg: Qt.vector3d(0, -90, 0) + } + + AxisHelperArm { + id: armY + rotation: Qt.vector3d(0, 0, 0) + color: Qt.rgba(0, 0.6, 0, 1) + hoverColor: Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) + view3D: axisHelperView + camRotPos: Qt.vector3d(-90, 0, 0) + camRotNeg: Qt.vector3d(90, 0, 0) + } + + AxisHelperArm { + id: armZ + rotation: Qt.vector3d(90, 0, 0) + color: Qt.rgba(0, 0, 1, 1) + hoverColor: Qt.lighter(Qt.rgba(0, 0, 1, 1)) + view3D: axisHelperView + camRotPos: Qt.vector3d(0, 0, 0) + camRotNeg: Qt.vector3d(0, 180, 0) + } + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton + + property var pickObj: null + + function cancelHover() + { + if (pickObj) { + pickObj.hovering = false; + pickObj = null; + } + } + + function pick(mouse) + { + var result = axisHelperView.pick(mouse.x, mouse.y); + if (result.objectHit) { + if (result.objectHit !== pickObj) { + cancelHover(); + pickObj = result.objectHit; + pickObj.hovering = true; + } + } else { + cancelHover(); + } + } + + onPositionChanged: { + pick(mouse); + } + + onPressed: { + pick(mouse); + if (pickObj) { + axisHelperView.editCameraCtrl.fitObject(axisHelperView.selectedNode, + pickObj.cameraRotation); + } else { + mouse.accepted = false; + } + } + + onExited: cancelHover() + onCanceled: cancelHover() + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml new file mode 100644 index 00000000000..23d2f9bbaf3 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick3D 1.0 + +Node { + id: armRoot + property alias posModel: posModel + property alias negModel: negModel + property View3D view3D + property color hoverColor + property color color + property vector3d camRotPos + property vector3d camRotNeg + + Model { + id: posModel + + property bool hovering: false + property vector3d cameraRotation: armRoot.camRotPos + + source: "meshes/axishelper.mesh" + materials: DefaultMaterial { + id: posMat + emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color + lighting: DefaultMaterial.NoLighting + } + pickable: true + } + + Model { + id: negModel + + property bool hovering: false + property vector3d cameraRotation: armRoot.camRotNeg + + source: "#Sphere" + y: -6 + scale: Qt.vector3d(0.025, 0.025, 0.025) + materials: DefaultMaterial { + id: negMat + emissiveColor: negModel.hovering ? armRoot.hoverColor : armRoot.color + lighting: DefaultMaterial.NoLighting + } + pickable: true + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml index 90f82bd341e..dba7e30f96c 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml @@ -30,6 +30,7 @@ Item { id: cameraCtrl property Camera camera: null + property View3D view3d: null property vector3d _lookAtPoint property vector3d _pressPoint @@ -44,6 +45,15 @@ Item { property real _defaultCameraLookAtDistance: 0 property Camera _prevCamera: null + function fitObject(targetObject, rotation) + { + camera.rotation = rotation; + var newLookAtAndZoom = _generalHelper.fitObjectToCamera( + camera, _defaultCameraLookAtDistance, targetObject, view3d); + _lookAtPoint = newLookAtAndZoom.toVector3d(); + _zoomFactor = newLookAtAndZoom.w; + } + function zoomRelative(distance) { _zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance, diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 3ce3c5deabe..19443113ee3 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -248,8 +248,7 @@ Window { id: gizmoLabel targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo targetView: overlayView - offsetX: 0 - offsetY: 45 + offset: Qt.vector3d(0, 45, 0) visible: targetNode.dragging Rectangle { @@ -285,6 +284,7 @@ Window { id: cameraControl camera: editView.camera anchors.fill: parent + view3d: editView } } @@ -357,9 +357,18 @@ Window { } } - Column { - y: 8 + AxisHelper { anchors.right: parent.right + anchors.top: parent.top + width: 100 + height: width + editCameraCtrl: cameraControl + selectedNode : viewWindow.selectedNode + } + + Column { + anchors.left: parent.left + anchors.bottom: parent.bottom CheckBox { id: editLightCheckbox checked: false diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml index ebc52a126aa..3d4183a9dc5 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml @@ -49,8 +49,6 @@ Node { id: iconOverlay targetNode: iconGizmo targetView: view3D - offsetX: 0 - offsetY: 0 visible: iconGizmo.visible && !isBehindCamera parent: view3D diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml index ce8c85bffb4..f4a85226b78 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml @@ -31,8 +31,7 @@ Item { property Node targetNode property View3D targetView - property real offsetX: 0 - property real offsetY: 0 + property vector3d offset: Qt.vector3d(0, 0, 0) property bool isBehindCamera @@ -56,7 +55,9 @@ Item { function updateOverlay() { var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0); - var scenePosWithOffset = Qt.vector3d(scenePos.x + offsetX, scenePos.y + offsetY, scenePos.z); + var scenePosWithOffset = Qt.vector3d(scenePos.x + offset.x, + scenePos.y + offset.y, + scenePos.z + offset.z); var viewPos = targetView ? targetView.mapFrom3DScene(scenePosWithOffset) : Qt.vector3d(0, 0, 0); root.x = viewPos.x; diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh new file mode 100644 index 0000000000000000000000000000000000000000..3e9e4958e4b694eb6bbd34185ff7a5e703866572 GIT binary patch literal 158516 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

Q&Ic9{)-CAfm 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 #include +#include +#include +#include +#include +#include +#include +#include #include +#include #include namespace QmlDesigner { @@ -126,6 +134,57 @@ float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float de return newZoomFactor; } +// Return value contains new lookAt point (xyz) and zoom factor (w) +QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance, + QQuick3DNode *targetObject, QQuick3DViewport *viewPort) +{ + if (!camera) + return QVector4D(0.f, 0.f, 0.f, 1.f); + + QVector3D lookAt = targetObject ? targetObject->scenePosition() : QVector3D(); + + // Get object bounds + qreal maxExtent = 200.; + if (auto modelNode = qobject_cast(targetObject)) { + auto targetPriv = QQuick3DObjectPrivate::get(targetObject); + if (auto renderModel = static_cast(targetPriv->spatialNode)) { + QWindow *window = static_cast(viewPort->window()); + if (window) { + auto context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window)); + if (!context.isNull()) { + auto bufferManager = context->bufferManager(); + QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); + QVector3D center = bounds.center(); + const QVector3D e = bounds.extents(); + const QVector3D s = targetObject->sceneScale(); + qreal maxScale = qSqrt(qreal(s.x() * s.x() + s.y() * s.y() + s.z() * s.z())); + maxExtent = qSqrt(qreal(e.x() * e.x() + e.y() * e.y() + e.z() * e.z())); + maxExtent *= maxScale; + + // Adjust lookAt to look directly at the center of the object bounds + QMatrix4x4 m = targetObject->sceneTransform(); + lookAt = m.map(center); + } + } + } + } + + // Reset camera position to default zoom + QMatrix4x4 m = camera->sceneTransform(); + const float *dataPtr(m.data()); + QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]); + newLookVector.normalize(); + newLookVector *= defaultLookAtDistance; + + camera->setPosition(lookAt + newLookVector); + + // Emprically determined algorithm for nice zoom + float newZoomFactor = qBound(.0001f, float(maxExtent / 700.), 10000.f); + + return QVector4D(lookAt, + zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false)); +} + } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index fbf1658924a..f667a974423 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -28,6 +28,8 @@ #ifdef QUICK3D_MODULE #include +#include +#include #include #include @@ -53,6 +55,8 @@ public: Q_INVOKABLE float zoomCamera(QQuick3DCamera *camera, float distance, float defaultLookAtDistance, const QVector3D &lookAt, float zoomFactor, bool relative); + Q_INVOKABLE QVector4D fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance, + QQuick3DNode *targetObject, QQuick3DViewport *viewPort); signals: void overlayUpdateNeeded(); diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index f27f93e0d45..c82164c1ff9 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -27,10 +27,13 @@ mockfiles/RotateGizmo.qml mockfiles/RotateRing.qml mockfiles/SelectionBox.qml + mockfiles/AxisHelper.qml + mockfiles/AxisHelperArm.qml mockfiles/meshes/arrow.mesh mockfiles/meshes/scalerod.mesh mockfiles/meshes/ring.mesh mockfiles/meshes/ringselect.mesh + mockfiles/meshes/axishelper.mesh mockfiles/images/editor_camera.png mockfiles/images/editor_camera@2x.png mockfiles/images/light-pick-icon.png From 9dac42f153b42c057713aadfa48aa2873643b2f3 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 21 Nov 2019 11:13:19 +0200 Subject: [PATCH 13/37] QmlDesigner: Implement fit selection button in 3D edit view Shortcuts for scale and move were also updated to correct ones. Change-Id: Iffcad0c81475553003962e65dc059879a237546e Fixes: QDS-1235 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 39 ++++++++++++++---- .../qml/qmlpuppet/mockfiles/ToolBarButton.qml | 6 +++ .../qmlpuppet/mockfiles/images/fit_active.png | Bin 0 -> 266 bytes .../mockfiles/images/fit_active@2x.png | Bin 0 -> 386 bytes .../mockfiles/images/fit_selected.png | Bin 0 -> 266 bytes .../mockfiles/images/fit_selected@2x.png | Bin 0 -> 386 bytes .../qml2puppet/editor3d/generalhelper.cpp | 8 ++++ .../qml2puppet/editor3d/generalhelper.h | 2 + share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 4 ++ 9 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 19443113ee3..56faf67ec41 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -300,7 +300,8 @@ Window { spacing: 5 padding: 5 - property var group: [btnSelectItem, btnSelectGroup, btnMove, btnRotate, btnScale] + property var groupSelect: [btnSelectGroup, btnSelectItem] + property var groupTransform: [btnMove, btnRotate, btnScale] ToolBarButton { id: btnSelectItem @@ -309,7 +310,7 @@ Window { shortcut: "Q" currentShortcut: selected ? "" : shortcut tool: "item_selection" - buttonsGroup: col.group + buttonsGroup: col.groupSelect } ToolBarButton { @@ -318,7 +319,7 @@ Window { shortcut: "Q" currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut tool: "group_selection" - buttonsGroup: col.group + buttonsGroup: col.groupSelect } Rectangle { // separator @@ -330,11 +331,12 @@ Window { ToolBarButton { id: btnMove + selected: true tooltip: qsTr("Move current selection") - shortcut: "M" + shortcut: "W" currentShortcut: shortcut tool: "move" - buttonsGroup: col.group + buttonsGroup: col.groupTransform } ToolBarButton { @@ -343,16 +345,37 @@ Window { shortcut: "E" currentShortcut: shortcut tool: "rotate" - buttonsGroup: col.group + buttonsGroup: col.groupTransform } ToolBarButton { id: btnScale tooltip: qsTr("Scale current selection") - shortcut: "T" + shortcut: "R" currentShortcut: shortcut tool: "scale" - buttonsGroup: col.group + buttonsGroup: col.groupTransform + } + + Rectangle { // separator + width: 25 + height: 1 + color: "#f1f1f1" + anchors.horizontalCenter: parent.horizontalCenter + } + + ToolBarButton { + id: btnFit + tooltip: qsTr("Fit camera to current selection") + shortcut: "F" + currentShortcut: shortcut + tool: "fit" + togglable: false + + onSelectedChanged: { + if (selected) + cameraControl.fitObject(viewWindow.selectedNode, editView.camera.rotation); + } } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml index cbc450ed2bc..38a8608e475 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml @@ -34,6 +34,7 @@ Rectangle { property string currentShortcut property string tool property variant buttonsGroup: [] + property bool togglable: true id: root width: img.width + 5 @@ -71,6 +72,11 @@ Rectangle { root.buttonsGroup[i].selected = false; root.selected = true; + + if (!root.togglable) { + // Deselect button after a short while (selection acts as simple click indicator) + _generalHelper.delayedPropertySet(root, 200, "selected", false); + } } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png new file mode 100644 index 0000000000000000000000000000000000000000..056e9ec3c8b690fa708232ff38f26bd477ca91ae GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|7G?$p2BAoW(+ms@iUB?$t_%ze|M7zJim!h% zFfeeH1o;IsFmegVD|Aes_kFM4?BUDd zmXO#X6v5&Uq!g)e&d7a()wWQDbE{Yk)VU8uvQ2C#I1qH^*fF=c##4HGc@>rwuZgMG6~mKvvKSfy(?M7(iWEXms7Cf;x-jCEtW<&E4&0)C1Sve}{?n{61*6pFAH q3b`JbC!C{3i~y?LMUs zGOi@ZFPMRmTR>hxrLtrC<(t3GybI`HU|{&=>Eak-(R+6CM&3gP0t~sD3#RB@N@3#i z67w)iU`boxeu_!Y$ib|kZ651{6&o4fH`&+yek&ke^7GNxQ!oF_pMLg6(Bj6BUAvk? z6jmsBhHHE1GUZLZwBuI9Qh^?kmyJq{Q!Z5`SP89B;?xjYz|45r)!~@KQl>_aiJAeO z0*wn!Xnr`A$Ft4ye*eC{FwA>M43f1K z-U%|UB*-tAfstE4UO}a@WBTQrzs|f1=wM)A_~q&17-G?TcJfBvLk0p2xta^6=v_)- z;_?#nFiT)bTi||*Nzcf^tf6fl>x2~>8Q(YA*ZqDgAYStG(brQi|ID9$_D0a+#*kgR znnM&;D0qfzd+0LdO}(_^R>V?)9+8)gN{mx3RU}vmtx@9C5L&>@c-htAn8Q-0MvsY_ z0i6Pk3r=W$IF-k<&GLT#zP{vI<7c%A`!}{auQPtY^1zZ=k0H+Z0po+u{3qn5=FXEf z|J|IY>dCXiMX#V!%F*_2UVj6>=7pxCT#Wh)gcvyeI2%}wg)uYk?RSV4exdyiRl4_pV(!I{W5r-BIn6JUJN@n4YeFF6*2UngG~R Bl@I^` literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index e7b091504ff..30be47d2dca 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -185,6 +185,14 @@ QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float default zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false)); } +void GeneralHelper::delayedPropertySet(QObject *obj, int delay, const QString &property, + const QVariant &value) +{ + QTimer::singleShot(delay, [obj, property, value]() { + obj->setProperty(property.toLatin1().constData(), value); + }); +} + } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index f667a974423..8a1cbe7001d 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -57,6 +57,8 @@ public: float zoomFactor, bool relative); Q_INVOKABLE QVector4D fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance, QQuick3DNode *targetObject, QQuick3DViewport *viewPort); + Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property, + const QVariant& value); signals: void overlayUpdateNeeded(); diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index c82164c1ff9..fcb510ccf08 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -64,5 +64,9 @@ mockfiles/images/point_light_gradient@2x.png mockfiles/images/area_light_gradient.png mockfiles/images/area_light_gradient@2x.png + mockfiles/images/fit_active.png + mockfiles/images/fit_active@2x.png + mockfiles/images/fit_selected.png + mockfiles/images/fit_selected@2x.png From 389f96b0ee8b2485290aee5c3c1eac05403f04ac Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 21 Nov 2019 17:37:09 +0200 Subject: [PATCH 14/37] QmlDesigner: Implement group selection boxes in 3D edit view Object's selection box now includes the bounds of all of its descendants. Selection boxes of immediate children of a selected object are also drawn. Individual/group selection buttons also now work as expected. Change-Id: Ice7ef9a536e32c6bb6da70fe23bf0a38e72c14f8 Fixes: QDS-1210 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 17 +- .../qml/qmlpuppet/mockfiles/SelectionBox.qml | 2 +- .../qml2puppet/editor3d/generalhelper.cpp | 6 +- .../qml2puppet/editor3d/generalhelper.h | 13 +- .../editor3d/selectionboxgeometry.cpp | 210 ++++++++++++++---- .../editor3d/selectionboxgeometry.h | 11 +- .../qt5informationnodeinstanceserver.cpp | 20 +- 7 files changed, 212 insertions(+), 67 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 56faf67ec41..7af8cf0cbad 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -55,9 +55,14 @@ Window { selectedNode = object; } - function emitObjectClicked(object) { - selectObject(object); - objectClicked(object); + function handleObjectClicked(object) { + var theObject = object; + if (btnSelectGroup.selected) { + while (theObject && theObject.parent !== scene) + theObject = theObject.parent; + } + selectObject(theObject); + objectClicked(theObject); } function addLightGizmo(obj) @@ -68,7 +73,7 @@ Window { {"view3D": overlayView, "targetNode": obj, "selectedNode": selectedNode}); lightGizmos[lightGizmos.length] = gizmo; - gizmo.clicked.connect(emitObjectClicked); + gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); } } @@ -83,7 +88,7 @@ Window { {"view3D": overlayView, "targetNode": obj, "geometryName": geometryName, "viewPortRect": viewPortRect, "selectedNode": selectedNode}); cameraGizmos[cameraGizmos.length] = gizmo; - gizmo.clicked.connect(emitObjectClicked); + gizmo.clicked.connect(handleObjectClicked); gizmo.viewPortRect = Qt.binding(function() {return viewPortRect;}); gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); } @@ -178,7 +183,7 @@ Window { onTapped: { var pickResult = editView.pick(eventPoint.scenePosition.x, eventPoint.scenePosition.y); - emitObjectClicked(pickResult.objectHit); + handleObjectClicked(pickResult.objectHit); } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml index 6465cab2b78..08de0a7ae12 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml @@ -52,7 +52,7 @@ Node { orientation: selectionBox.targetNode ? selectionBox.targetNode.orientation : Node.LeftHanded rotationOrder: selectionBox.targetNode ? selectionBox.targetNode.rotationOrder : Node.YXZ - visible: selectionBox.targetNode && selectionBox.targetNode instanceof Model + visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty materials: [ DefaultMaterial { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index 30be47d2dca..f5c7c6e6566 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -29,15 +29,17 @@ #include #include #include +#include +#include #include +#include +#include #include #include #include #include #include -#include #include -#include namespace QmlDesigner { namespace Internal { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index 8a1cbe7001d..16007e6798f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -27,14 +27,21 @@ #ifdef QUICK3D_MODULE -#include -#include -#include #include #include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QQuick3DCamera; +class QQuick3DNode; +class QQuick3DViewport; +QT_END_NAMESPACE namespace QmlDesigner { namespace Internal { + class GeneralHelper : public QObject { Q_OBJECT diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp index 452d924427e..db6218c3319 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp @@ -35,6 +35,9 @@ #include #include #include +#include + +#include namespace QmlDesigner { namespace Internal { @@ -46,6 +49,9 @@ SelectionBoxGeometry::SelectionBoxGeometry() SelectionBoxGeometry::~SelectionBoxGeometry() { + for (auto &connection : qAsConst(m_connections)) + QObject::disconnect(connection); + m_connections.clear(); } QQuick3DNode *SelectionBoxGeometry::targetNode() const @@ -63,6 +69,11 @@ QQuick3DViewport *SelectionBoxGeometry::view3D() const return m_view3D; } +bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const +{ + return m_isEmpty; +} + void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode) { if (m_targetNode == targetNode) @@ -111,13 +122,18 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb QSSGRenderGeometry *geometry = static_cast(node); geometry->clear(); + for (auto &connection : qAsConst(m_connections)) + QObject::disconnect(connection); + m_connections.clear(); QByteArray vertexData; QByteArray indexData; - QVector3D minBounds(-100.f, -100.f, -100.f); - QVector3D maxBounds(100.f, 100.f, 100.f); - QVector3D extents; + static const float floatMin = std::numeric_limits::lowest(); + static const float floatMax = std::numeric_limits::max(); + + QVector3D minBounds = QVector3D(floatMax, floatMax, floatMax); + QVector3D maxBounds = QVector3D(floatMin, floatMin, floatMin); if (m_targetNode) { auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode); @@ -134,33 +150,12 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty); rootRN->calculateGlobalVariables(); } - if (auto modelNode = qobject_cast(m_targetNode)) { - auto nodePriv = QQuick3DObjectPrivate::get(m_targetNode); - if (auto renderModel = static_cast(nodePriv->spatialNode)) { - QWindow *window = static_cast(m_view3D->window()); - if (window) { - auto context = QSSGRenderContextInterface::getRenderContextInterface( - quintptr(window)); - if (!context.isNull()) { - auto bufferManager = context->bufferManager(); - QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); - QVector3D center = bounds.center(); - extents = bounds.extents(); - minBounds = center - extents; - maxBounds = center + extents; - } - } - } - } + getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds, QMatrix4x4()); + } else { + // Fill some dummy data so geometry won't get rejected + appendVertexData(vertexData, indexData, minBounds, maxBounds); } - // Adjust bounds to reduce targetNode pixels obscuring the selection box - extents /= 1000.f; - minBounds -= extents; - maxBounds += extents; - - fillVertexData(vertexData, indexData, minBounds, maxBounds); - geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0, QSSGRenderGeometry::Attribute::ComponentType::F32Type); geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0, @@ -171,19 +166,138 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb geometry->setPrimitiveType(QSSGRenderGeometry::Lines); geometry->setBounds(minBounds, maxBounds); + bool empty = minBounds.isNull() && maxBounds.isNull(); + if (m_isEmpty != empty) { + m_isEmpty = empty; + // Delay notification until we're done with spatial node updates + QTimer::singleShot(0, this, &SelectionBoxGeometry::isEmptyChanged); + } + return node; } -void SelectionBoxGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData, - const QVector3D &minBounds, const QVector3D &maxBounds) +void SelectionBoxGeometry::getBounds(QQuick3DNode *node, QByteArray &vertexData, + QByteArray &indexData, QVector3D &minBounds, + QVector3D &maxBounds, const QMatrix4x4 &transform) { - const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert - vertexData.resize(vertexSize); - const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line - indexData.resize(indexSize); + QMatrix4x4 fullTransform; + auto nodePriv = QQuick3DObjectPrivate::get(node); + auto renderNode = static_cast(nodePriv->spatialNode); - auto dataPtr = reinterpret_cast(vertexData.data()); - auto indexPtr = reinterpret_cast(indexData.data()); + // All transforms are relative to targetNode transform, so its local transform is ignored + if (node != m_targetNode) { + if (renderNode) { + if (renderNode->flags.testFlag(QSSGRenderNode::Flag::TransformDirty)) + renderNode->calculateLocalTransform(); + fullTransform = transform * renderNode->localTransform; + } + + m_connections << QObject::connect(node, &QQuick3DNode::scaleChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::rotationChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::positionChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::pivotChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::orientationChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + m_connections << QObject::connect(node, &QQuick3DNode::rotationOrderChanged, + this, &SelectionBoxGeometry::update, Qt::QueuedConnection); + } + + QVector minBoundsVec; + QVector maxBoundsVec; + + // Check for children + const auto children = node->childItems(); + for (const auto child : children) { + if (auto childNode = qobject_cast(child)) { + QVector3D newMinBounds = minBounds; + QVector3D newMaxBounds = maxBounds; + getBounds(childNode, vertexData, indexData, newMinBounds, newMaxBounds, fullTransform); + minBoundsVec << newMinBounds; + maxBoundsVec << newMaxBounds; + } + } + + // Combine all child bounds + for (const auto &newBounds : qAsConst(minBoundsVec)) { + minBounds.setX(qMin(newBounds.x(), minBounds.x())); + minBounds.setY(qMin(newBounds.y(), minBounds.y())); + minBounds.setZ(qMin(newBounds.z(), minBounds.z())); + } + for (const auto &newBounds : qAsConst(maxBoundsVec)) { + maxBounds.setX(qMax(newBounds.x(), maxBounds.x())); + maxBounds.setY(qMax(newBounds.y(), maxBounds.y())); + maxBounds.setZ(qMax(newBounds.z(), maxBounds.z())); + } + + if (auto modelNode = qobject_cast(node)) { + if (auto renderModel = static_cast(renderNode)) { + QWindow *window = static_cast(m_view3D->window()); + if (window) { + auto context = QSSGRenderContextInterface::getRenderContextInterface( + quintptr(window)); + if (!context.isNull()) { + auto bufferManager = context->bufferManager(); + QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); + QVector3D center = bounds.center(); + QVector3D extents = bounds.extents(); + QVector3D localMin = center - extents; + QVector3D localMax = center + extents; + + // Transform all corners of the local bounding box to find final extent in + // in parent space + + auto checkCorner = [&minBounds, &maxBounds, &fullTransform] + (const QVector3D &corner) { + QVector3D mappedCorner = fullTransform.map(corner); + minBounds.setX(qMin(mappedCorner.x(), minBounds.x())); + minBounds.setY(qMin(mappedCorner.y(), minBounds.y())); + minBounds.setZ(qMin(mappedCorner.z(), minBounds.z())); + maxBounds.setX(qMax(mappedCorner.x(), maxBounds.x())); + maxBounds.setY(qMax(mappedCorner.y(), maxBounds.y())); + maxBounds.setZ(qMax(mappedCorner.z(), maxBounds.z())); + }; + + checkCorner(localMin); + checkCorner(localMax); + checkCorner(QVector3D(localMin.x(), localMin.y(), localMax.z())); + checkCorner(QVector3D(localMin.x(), localMax.y(), localMin.z())); + checkCorner(QVector3D(localMax.x(), localMin.y(), localMin.z())); + checkCorner(QVector3D(localMin.x(), localMax.y(), localMax.z())); + checkCorner(QVector3D(localMax.x(), localMax.y(), localMin.z())); + checkCorner(QVector3D(localMax.x(), localMin.y(), localMax.z())); + } + } + } + } + + // Target node and immediate children get selection boxes + if (transform.isIdentity()) { + // Adjust bounds to reduce targetNode pixels obscuring the selection box + QVector3D extents = (maxBounds - minBounds) / 1000.f; + QVector3D minAdjBounds = minBounds - extents; + QVector3D maxAdjBounds = maxBounds + extents; + + appendVertexData(vertexData, indexData, minAdjBounds, maxAdjBounds); + } +} + +void SelectionBoxGeometry::appendVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds) +{ + int initialVertexSize = vertexData.size(); + int initialIndexSize = indexData.size(); + const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert + quint16 indexAdd = quint16(initialVertexSize / 12); + vertexData.resize(initialVertexSize + vertexSize); + const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line + indexData.resize(initialIndexSize + indexSize); + + auto dataPtr = reinterpret_cast(vertexData.data() + initialVertexSize); + auto indexPtr = reinterpret_cast(indexData.data() + initialIndexSize); *dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); *dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z(); @@ -194,20 +308,20 @@ void SelectionBoxGeometry::fillVertexData(QByteArray &vertexData, QByteArray &in *dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); *dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z(); - *indexPtr++ = 0; *indexPtr++ = 1; - *indexPtr++ = 1; *indexPtr++ = 2; - *indexPtr++ = 2; *indexPtr++ = 3; - *indexPtr++ = 3; *indexPtr++ = 0; + *indexPtr++ = 0 + indexAdd; *indexPtr++ = 1 + indexAdd; + *indexPtr++ = 1 + indexAdd; *indexPtr++ = 2 + indexAdd; + *indexPtr++ = 2 + indexAdd; *indexPtr++ = 3 + indexAdd; + *indexPtr++ = 3 + indexAdd; *indexPtr++ = 0 + indexAdd; - *indexPtr++ = 0; *indexPtr++ = 4; - *indexPtr++ = 1; *indexPtr++ = 5; - *indexPtr++ = 2; *indexPtr++ = 6; - *indexPtr++ = 3; *indexPtr++ = 7; + *indexPtr++ = 0 + indexAdd; *indexPtr++ = 4 + indexAdd; + *indexPtr++ = 1 + indexAdd; *indexPtr++ = 5 + indexAdd; + *indexPtr++ = 2 + indexAdd; *indexPtr++ = 6 + indexAdd; + *indexPtr++ = 3 + indexAdd; *indexPtr++ = 7 + indexAdd; - *indexPtr++ = 4; *indexPtr++ = 5; - *indexPtr++ = 5; *indexPtr++ = 6; - *indexPtr++ = 6; *indexPtr++ = 7; - *indexPtr++ = 7; *indexPtr++ = 4; + *indexPtr++ = 4 + indexAdd; *indexPtr++ = 5 + indexAdd; + *indexPtr++ = 5 + indexAdd; *indexPtr++ = 6 + indexAdd; + *indexPtr++ = 6 + indexAdd; *indexPtr++ = 7 + indexAdd; + *indexPtr++ = 7 + indexAdd; *indexPtr++ = 4 + indexAdd; } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h index afe5efd8cf0..ef472a51130 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h @@ -40,6 +40,7 @@ class SelectionBoxGeometry : public QQuick3DGeometry Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged) Q_PROPERTY(QQuick3DNode *rootNode READ rootNode WRITE setRootNode NOTIFY rootNodeChanged) Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged) + Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged) public: SelectionBoxGeometry(); @@ -48,6 +49,7 @@ public: QQuick3DNode *targetNode() const; QQuick3DNode *rootNode() const; QQuick3DViewport *view3D() const; + bool isEmpty() const; public Q_SLOTS: void setTargetNode(QQuick3DNode *targetNode); @@ -58,17 +60,22 @@ Q_SIGNALS: void targetNodeChanged(); void rootNodeChanged(); void view3DChanged(); + void isEmptyChanged(); protected: QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override; private: - void fillVertexData(QByteArray &vertexData, QByteArray &indexData, - const QVector3D &minBounds, const QVector3D &maxBounds); + void getBounds(QQuick3DNode *node, QByteArray &vertexData, QByteArray &indexData, + QVector3D &minBounds, QVector3D &maxBounds, const QMatrix4x4 &transform); + void appendVertexData(QByteArray &vertexData, QByteArray &indexData, + const QVector3D &minBounds, const QVector3D &maxBounds); QQuick3DNode *m_targetNode = nullptr; QQuick3DViewport *m_view3D = nullptr; QQuick3DNode *m_rootNode = nullptr; + bool m_isEmpty = true; + QVector m_connections; }; } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index d3747ab3b33..95360eaa4fc 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -340,12 +340,24 @@ QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport( { for (const ServerNodeInstance &instance : instanceList) { if (instance.isSubclassOf("QQuick3DViewport")) { + QObject *rootObj = nullptr; + int viewChildCount = 0; for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */ /* The QQuick3DViewport always creates a root node. * This root node contains the complete scene. */ - if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) - return child.internalObject()->property("parent").value(); + if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) { + // Implicit root node is not visible in editor, so there is often another node + // added below it that serves as the actual scene root node. + // If the found root is the only node child of the view, assume that is the case. + ++viewChildCount; + if (!rootObj) + rootObj = child.internalObject(); + } } + if (viewChildCount == 1) + return rootObj; + else if (rootObj) + return rootObj->property("parent").value(); } } return nullptr; @@ -603,10 +615,8 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm if (hasInstanceForId(id)) { ServerNodeInstance instance = instanceForId(id); QObject *object = nullptr; - if (instance.isSubclassOf("QQuick3DModel") || instance.isSubclassOf("QQuick3DCamera") - || instance.isSubclassOf("QQuick3DAbstractLight")) { + if (instance.isSubclassOf("QQuick3DNode")) object = instance.internalObject(); - } QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant, objectToVariant(object))); return; // TODO: support multi-selection From d65c61ffcba0026c8787717dd19699599da3f78a Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 22 Nov 2019 16:48:46 +0100 Subject: [PATCH 15/37] McuSupport: Fix name of McuSupportRunConfigurationFactory Was a remainder of initial clone&rename action. Change-Id: Ifd06626cf2c895a1e20289ebd7ce711432f0a23a Reviewed-by: hjk --- src/plugins/mcusupport/mcusupportplugin.cpp | 4 ++-- src/plugins/mcusupport/mcusupportrunconfiguration.cpp | 2 +- src/plugins/mcusupport/mcusupportrunconfiguration.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 68ec688c5f2..d6b2dd427a6 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -45,8 +45,8 @@ class McuSupportPluginPrivate { public: McuSupportDeviceFactory deviceFactory; - EmrunRunConfigurationFactory emrunRunConfigurationFactory; - RunWorkerFactory emrunRunWorkerFactory{ + McuSupportRunConfigurationFactory runConfigurationFactory; + RunWorkerFactory runWorkerFactory{ makeFlashAndRunWorker(), {ProjectExplorer::Constants::NORMAL_RUN_MODE}, {Constants::RUNCONFIGURATION} diff --git a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp index 47e2d6af4fb..e4a21ae19bc 100644 --- a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp +++ b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp @@ -107,7 +107,7 @@ RunWorkerFactory::WorkerCreator makeFlashAndRunWorker() return RunWorkerFactory::make(); } -EmrunRunConfigurationFactory::EmrunRunConfigurationFactory() +McuSupportRunConfigurationFactory::McuSupportRunConfigurationFactory() : FixedRunConfigurationFactory(FlashAndRunConfiguration::tr("Flash and run")) { registerRunConfiguration(Constants::RUNCONFIGURATION); diff --git a/src/plugins/mcusupport/mcusupportrunconfiguration.h b/src/plugins/mcusupport/mcusupportrunconfiguration.h index b53eea03a4a..704c8c9c904 100644 --- a/src/plugins/mcusupport/mcusupportrunconfiguration.h +++ b/src/plugins/mcusupport/mcusupportrunconfiguration.h @@ -31,10 +31,10 @@ namespace McuSupport { namespace Internal { -class EmrunRunConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory +class McuSupportRunConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory { public: - EmrunRunConfigurationFactory(); + McuSupportRunConfigurationFactory(); }; class FlashAndRunConfiguration : public ProjectExplorer::RunConfiguration From e0af519d1a662731a838dc2eb4264f87d4ea0f1f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 22 Nov 2019 11:41:50 +0100 Subject: [PATCH 16/37] ClangTools: Fix clazy plugin invocation with recent clazy II The enable-all-fixits option was also removed: https://github.com/KDE/clazy/commit/05c9ccade074fb7468f7983990b9697accd07fe1 Change-Id: Ide64e80a7ed8ee828fe4973fbf74bbaa8d3a09b8 Reviewed-by: Cristian Adam Reviewed-by: Nikolai Kosjar --- src/plugins/clangtools/clangtidyclazyrunner.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp index 09ac2aa2f8d..34a149c8236 100644 --- a/src/plugins/clangtools/clangtidyclazyrunner.cpp +++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp @@ -66,8 +66,6 @@ static QStringList clazyPluginArguments(const ClangDiagnosticConfig diagnosticCo arguments << XclangArgs({"-add-plugin", "clazy", "-plugin-arg-clazy", - "enable-all-fixits", - "-plugin-arg-clazy", diagnosticConfig.clazyChecks()}); } From 6ee83b4c19eceba502079ae20a906e9201a9b403 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 22 Nov 2019 16:53:36 +0200 Subject: [PATCH 17/37] QmlDesigner: Center on selection box when fit tool is used in 3D Edit Instead of centering edit camera on selected object, center it on the selection box, which includes child objects. Change-Id: I7315a4bcfffc74e72a2b21d0a04fc99ee9f4f3c3 Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 9 ++++++--- .../qml/qmlpuppet/mockfiles/SelectionBox.qml | 1 + .../qml2puppet/editor3d/generalhelper.cpp | 17 +++++++++++++---- .../editor3d/selectionboxgeometry.cpp | 8 +++++++- .../qml2puppet/editor3d/selectionboxgeometry.h | 4 ++++ 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 7af8cf0cbad..bf1bfebf861 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -206,6 +206,7 @@ Window { } SelectionBox { + id: selectionBox view3D: editView targetNode: viewWindow.selectedNode } @@ -378,8 +379,10 @@ Window { togglable: false onSelectedChanged: { - if (selected) - cameraControl.fitObject(viewWindow.selectedNode, editView.camera.rotation); + if (selected) { + var targetNode = viewWindow.selectedNode ? selectionBox.model : null; + cameraControl.fitObject(targetNode, editView.camera.rotation); + } } } } @@ -391,7 +394,7 @@ Window { width: 100 height: width editCameraCtrl: cameraControl - selectedNode : viewWindow.selectedNode + selectedNode : viewWindow.selectedNode ? selectionBox.model : null } Column { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml index 08de0a7ae12..524f5688899 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml @@ -32,6 +32,7 @@ Node { property View3D view3D property Node targetNode: null + property alias model: selectionBoxModel SelectionBoxGeometry { id: selectionBoxGeometry diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index f5c7c6e6566..850a440a129 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -26,6 +26,8 @@ #ifdef QUICK3D_MODULE +#include "selectionboxgeometry.h" + #include #include #include @@ -154,8 +156,15 @@ QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float default if (window) { auto context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window)); if (!context.isNull()) { - auto bufferManager = context->bufferManager(); - QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager); + QSSGBounds3 bounds; + auto geometry = qobject_cast(modelNode->geometry()); + if (geometry) { + bounds = geometry->bounds(); + } else { + auto bufferManager = context->bufferManager(); + bounds = renderModel->getModelBounds(bufferManager); + } + QVector3D center = bounds.center(); const QVector3D e = bounds.extents(); const QVector3D s = targetObject->sceneScale(); @@ -164,8 +173,8 @@ QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float default maxExtent *= maxScale; // Adjust lookAt to look directly at the center of the object bounds - QMatrix4x4 m = targetObject->sceneTransform(); - lookAt = m.map(center); + lookAt = renderModel->globalTransform.map(center); + lookAt.setZ(-lookAt.z()); // Render node transforms have inverted z } } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp index db6218c3319..77700619237 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -74,6 +73,11 @@ bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const return m_isEmpty; } +QSSGBounds3 SelectionBoxGeometry::bounds() const +{ + return m_bounds; +} + void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode) { if (m_targetNode == targetNode) @@ -166,6 +170,8 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb geometry->setPrimitiveType(QSSGRenderGeometry::Lines); geometry->setBounds(minBounds, maxBounds); + m_bounds = QSSGBounds3(minBounds, maxBounds); + bool empty = minBounds.isNull() && maxBounds.isNull(); if (m_isEmpty != empty) { m_isEmpty = empty; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h index ef472a51130..08a28cec06c 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace QmlDesigner { namespace Internal { @@ -51,6 +52,8 @@ public: QQuick3DViewport *view3D() const; bool isEmpty() const; + QSSGBounds3 bounds() const; + public Q_SLOTS: void setTargetNode(QQuick3DNode *targetNode); void setRootNode(QQuick3DNode *rootNode); @@ -76,6 +79,7 @@ private: QQuick3DNode *m_rootNode = nullptr; bool m_isEmpty = true; QVector m_connections; + QSSGBounds3 m_bounds; }; } From f80b676e4aef3a8ae23281594615bbc26db6f367 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Mon, 18 Nov 2019 14:33:06 +0100 Subject: [PATCH 18/37] QmlDesigner: Fix sticky popups Task-number: QTCREATORBUG-23102 Change-Id: I53a2abc67221b714e2b4ff7d09045f0b817b59d2 Reviewed-by: Thomas Hartmann --- .../imports/StudioControls/ComboBox.qml | 4 +++- .../imports/StudioControls/Menu.qml | 10 ++++++---- .../imports/StudioControls/RealSliderPopup.qml | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml index f8865e62cf9..747a0d45109 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -185,7 +185,9 @@ T.ComboBox { StudioTheme.Values.maxComboBoxPopupHeight) padding: StudioTheme.Values.border margins: 0 // If not defined margin will be -1 - closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent + | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside + | T.Popup.CloseOnReleaseOutsideParent contentItem: ListView { clip: true diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml index 01a86847fc3..773282958f5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml @@ -1,3 +1,5 @@ + + /**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. @@ -22,7 +24,6 @@ ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ - import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Templates 2.12 as T @@ -43,10 +44,11 @@ T.Menu { overlap: 1 padding: 0 - closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape + closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent + | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside + | T.Popup.CloseOnReleaseOutsideParent - delegate: MenuItem { - } + delegate: MenuItem {} contentItem: ListView { model: control.contentModel diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml index fe83e82ee60..dd6be8cbc13 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSliderPopup.qml @@ -33,7 +33,9 @@ T.Popup { property T.Control myControl dim: false - closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent + | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside + | T.Popup.CloseOnReleaseOutsideParent background: Rectangle { color: StudioTheme.Values.themeControlBackground From 3228d2626f8be736f992a4712e503368c245faa0 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 4 Nov 2019 17:18:56 +0100 Subject: [PATCH 19/37] Doc: Update info about Clang tools Change-Id: I86fecea5e5bc6d1b514cca4b8ad7a865cbf87c7e Reviewed-by: Nikolai Kosjar --- doc/config/qtcreator-project.qdocconf | 3 +- doc/images/qtcreator-clang-tools-options.png | Bin 5355 -> 8210 bytes doc/images/qtcreator-clang-tools.png | Bin 16541 -> 9933 bytes doc/images/qtcreator-files-to-analyze.png | Bin 9716 -> 5402 bytes .../creator-clang-static-analyzer.qdoc | 37 ++++++------------ 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/doc/config/qtcreator-project.qdocconf b/doc/config/qtcreator-project.qdocconf index 82daf9faad7..b6710edb436 100644 --- a/doc/config/qtcreator-project.qdocconf +++ b/doc/config/qtcreator-project.qdocconf @@ -23,7 +23,8 @@ imagedirs = ../images \ ../../src/plugins/qmldesigner/qmlpreviewplugin/images \ ../../src/plugins/scxmleditor/common/images \ ../../src/plugins/texteditor/images \ - ../../src/plugins/valgrind/images + ../../src/plugins/valgrind/images \ + ../../src/plugins/welcome/images exampledirs = ../examples examples.fileextensions += *.qml *.svg diff --git a/doc/images/qtcreator-clang-tools-options.png b/doc/images/qtcreator-clang-tools-options.png index 6cf866f13fa317324d14b15129d221786c56ebc7..3fce1e2dffd5bbf3d118b139161883ba4badc5fe 100644 GIT binary patch literal 8210 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 V`oz~0{R|8Y44$rjF6*2UngB=reHZ`$ diff --git a/doc/images/qtcreator-clang-tools.png b/doc/images/qtcreator-clang-tools.png index 0ae985591cf9c16ac6cdcea24fab539f47fe8b97..cd80438a8ae845429187864ea6a0ddf3331927ab 100644 GIT binary patch literal 9933 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 XPHNNSW#=bZfC9_Y)z4*}Q$iB}f-Zca5 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 T(Y8tMJ;-yOu6{1-oD!M<)c^H% diff --git a/doc/images/qtcreator-files-to-analyze.png b/doc/images/qtcreator-files-to-analyze.png index fcdf05c0dbe7dd1c90559109926d8979cf0e3c6b..add972f337c10efa8080d25fce63511be5181abe 100644 GIT binary patch literal 5402 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 Hr-UW|$iD^4 literal 9716 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 UYm#8ez`(%Z>FVdQ&MBb@00#Fy*Z=?k diff --git a/doc/src/analyze/creator-clang-static-analyzer.qdoc b/doc/src/analyze/creator-clang-static-analyzer.qdoc index c4468ef0389..b3785534954 100644 --- a/doc/src/analyze/creator-clang-static-analyzer.qdoc +++ b/doc/src/analyze/creator-clang-static-analyzer.qdoc @@ -60,6 +60,11 @@ Clang tools are delivered and installed with \QC, and therefore you do not need to set them up separately. + In addition to running the tools to collect diagnostics, you can select + \inlineimage open.png + to load diagnostics from \l{https://yaml.org/}{YAML} files that you exported + using the \c {-export fixes} option. + \section1 Running Clang Tools To run the Clang tools to analyze an open project: @@ -68,41 +73,25 @@ \li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}. - \image qtcreator-files-to-analyze.png "Analyzer Configuration dialog" + \image qtcreator-files-to-analyze.png "Files to Analyze dialog" - \li In the \uicontrol General group, select \uicontrol {Custom Settings} - to modify the analyzer configuration. - - \li To build the project before running the Clang tools, select the - \uicontrol {Build the project before analysis} check box. The Clang - tools do not require the project to be built before analysis, but - they might display misleading warnings about files missing that are - generated during the build. For big projects, not building the - project might save some time. - - \li In the \uicontrol {Diagnostic configuration} field, select a Clang - configuration in the list of pre-defined configurations (1). For - more information about creating a custom configuration, see - \l {Configuring Clang Tools}. - - \li In the \uicontrol {Files to Analyze} group, select the files to - apply the checks to. + \li Select the files to apply the checks to. \li Select \uicontrol Analyze to start the checks. \endlist - If you select \uicontrol Debug in the mode selector to open the - \uicontrol Debug mode and then select \uicontrol {Clang-Tidy and Clazy}, - you must select the \inlineimage qtcreator-analyze-start-button.png - (\uicontrol Start) button to open the \uicontrol {Analyzer Configuration} - dialog. - The found issues are displayed in the \uicontrol {Clang-Tidy and Clazy} view: \image qtcreator-clang-tools.png "Clang-Tidy and Clazy view" + \note If you select \uicontrol Debug in the mode selector to open the + \uicontrol Debug mode and then select \uicontrol {Clang-Tidy and Clazy}, + you must select the \inlineimage qtcreator-analyze-start-button.png + (\uicontrol Start) button to open the \uicontrol {Files to Analyze} + dialog. + Double-click an issue to move to the location where the issue appears in the code editor. From d48fa5b8d6c797fb2637ada5fbb0009fd9847355 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 26 Sep 2019 15:47:54 +0200 Subject: [PATCH 20/37] Doc: Update info about building with CMake Change-Id: I30813c51deec50043c0015aef5a672babe6b5608 Reviewed-by: Cristian Adam Reviewed-by: Eike Ziller --- doc/images/qtcreator-cmake-build-settings.png | Bin 41710 -> 11650 bytes doc/images/qtcreator-cmake-build-steps.png | Bin 7998 -> 5838 bytes doc/images/qtcreator-cmake-clean-steps.png | Bin 8315 -> 6320 bytes doc/images/qtcreator-cmakeexecutable.png | Bin 11541 -> 13050 bytes doc/images/qtcreator-kits.png | Bin 28799 -> 27172 bytes .../creator-projects-cmake-building.qdocinc | 6 +++- doc/src/cmake/creator-projects-cmake.qdoc | 11 ++++++- doc/src/editors/creator-locator.qdoc | 5 +++ .../creator-projects-building.qdoc | 31 +++++++++++++----- 9 files changed, 42 insertions(+), 11 deletions(-) diff --git a/doc/images/qtcreator-cmake-build-settings.png b/doc/images/qtcreator-cmake-build-settings.png index 35b4401820d90adb3314e0d07c4f1b0c085e5678..534ddf6be11c2567ce2d17d6f2208291239e037a 100644 GIT binary patch literal 11650 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 literal 41710 zcmeAS@N?(olHy`uVBq!ia0y~yVDe;OU|ht(#K6E%(|L411H+=No-U3d6}R5ZWseDU z|Fyw$TS|HGnY7#W<@?X3ndh3%&g;5(<0zX(S44nAmxunP?uG@IL>yT%FD+?iy0qKm zrN{fdcbUEyRqNlcejl2wvr*;Rp7Z(#i~Z*s7oW39e|BbO;HouyV!9PLniS4+tE#Gc zoz-0%#NsHxQW=+#l@*kgm3OeiL4d_^p0t#-^u=6`CIyaNyp94aju*h}raWf>7Ds^+ z=_Un^rUkbVY#Zi3NA7RuWMN`zG*C@XOk{j44l?wQ!*vz=-rEkDfq{YU{c^sZo-0?Z zSh0F_vz~ufSJ#S=SN%8FMjTkGACTX4Z2F%MVnTN9jIRwXYF18(toe1}*4FIaX0IRj zquayluE{)`-8%JS-hIaTb&nI)$lJ{5IN!EF*WiZI$*miVQWKXJvnKuYSM=VtoONA5 z({;%vg%gjL?A-ZtdExB&^Y5q6ul;tf`hD)rO;3M(e7thy%B4$}8X6it6ckiZ+Nf*2 z?N`l&9|w(p-YnXmf3NCsuj~3fD_HjY`1HCy*jmE&sKA|CZofrmr*C*AZkG9A!wu&6 z17CLUx;W?kdg1g>_A~w;JScJP`!nw2w@&4R{QoxTPlA`%{y*za9Xw_D>aLURguL(9 z&F@tNUtJd+=rDI}K>VNO=Kp@|%>TJ2C;stM>wC>}_mr)f0(0`-y?>V%&UR6H`S$JC zuU})g<=mW|zi;KTWzU{IWlh}??0E3qxxRGM`@Xk6E??Dhc@q1T+aU)Z);DI>eGm6F zW@n#0H-A6Fwu-AJ>mqBe>$1omy?F25y^X20L7LhJYgBVS>?~yZ{#!fMs)qUV{!M-< z_f00>D9igPU$=6}ms3K%#p&+u-L={ZxU zPW5f_cAS3s>GIGiQ@7ukt5~%3acW{zR8*BCtB|Jc#iFT)a*cj}cqU|fC0sXtSJKgK zxu@jsJTnX2xSVaq+pFKpMb5Wy{^}Bk0-PS16r$zoz4J)TjD=WD>XUfHg8|oKt z>Z(hrS@ZQ?>FR51H``6zu5f+Ngn)97{L`mWH@sgzeSO^OHG95BI2oUL-hZX?#k!bJ zTi;CZ4n5P|{-R=|5=WDb;dV`nLZc7;|G$4fZx^4FkRTu;QgcTC!etj_uh;uapEob% z4=Q8czW00fQt^MkZg#FYbt>e%f86i8*6}Z%e0Ov^-*+iqXLbIS&bGT>kH0vnCAi-} zCeiD)|B8c8xL5rX($v10we?J{nr0BE_MIQI;}7=V|MPY8`F;N$%wK=_$#paH-M*KK z?{Pib_hI$){~w;8U*o?#JoI|+#MIK6PEqZTul3jc{B(am+t)R}KlSVH`|y71HOZaN z%W6NV2i)vl|L5ahe)0VK%c=wNZ))ow?1}$>f4}{Yl$&iwn!GOOADHU(Tlm=0&#B)3 z)VLp5$FKYKZFT)AuK8a1^4fESJ}$S}zE_|7t@QhvPbdH1o1hUtDSuzzr!CM zzd!Ak%-4^Wc|VWJJ38*)eqJ@8TXvzy&s$li8C{n?j(Pg)d)>k>kF1YtJ=MSQVs4st zJoD9=OZ>bvr(fU8-2Lxu?M$}kDcgUD-nc*S^7M8+_dVa0X8gY0qIZMUxPW=jg5O8u z?q@x^D!jkJ^xysK+wLtdt`a}td$qLpvC^I>K^Dh(3vSQgzTy;rIjCJU?$+slpW5%& zf4Z3z8+-S{g$qljT-mavq=K{j*OyF-4NvU23a+2doiF39r>Cc9mAWzP+L9-0n`?8j zR-Kia5tlQIV>Pep?Eek7_Z4cqTK}Pr-K?fQS(iENx!TRT+S#{{Fhv&J;0;}>s`@i; zR{Xwi(UFGl=kBdLd2f^Kz8|lr*J+C1^Ios>>vR0SZ0VbqViWlFpTtF{UR#;rZ4|sG zOl`yVev#8(G?$j$d1rRs$Y_rs&%N($Yi!DwtDK=VD4m^JCeEoJ#^N|Z{h66qt>W?92FD-0-j}g>pRm?D>3?62hu3}m zs6Jm(*1)RxnNLYcNkG7al`CI%iE3wMWxYF|+x0zn?x*=*q~`BG{pojp@$%)9);xKC ziDz=^>ZMY9OUk#`=EhsZl|R}WueJBX_otO9H|z9v>g_(8duGpt;KqfP*Y}Ghw7)!c z@8sY4n`#er{!Q3=U-xRhs@ANj9BtLox78*7o>Wt~a=$j)Y>7sY@6+`^zH@u&|2e(e z>77;B@|RuV`K8gC8eO$X&)=u!Sw~+iJNTRbg3M><#c@CLoXwp6KH;7<&vi=c$$6Zg zoZQ=b&uu&U|A*)*$NWUg_SXV3Cl6nJv)cafdi&^QrDyzOuKh62 zS-r*UxMWm9m3(1P-0n+DCmhi$oHq4MTy1*)OmByjhcYj_j@3Jq?f+9Ud7rdNf6hAd zc*WJ#HWO?VmxiqQqwe$Xae<-WooCx)w{4%Rxb@0IuBr77Zy(E>OYhvVD`I^e_nhyu z_a4`JwQ24D%~j_wE$(`>(OM<<=z-1b#& z^=aS#Q&)Yg>N;AbR;cu^=8<&$kHeExy{GBL{<;>Of6&F>|NP%K#oNw&e_gK=_2t$3 zb$c0qAI+ckwrJg~341R*nk4;p-`@{Y@BjVul;1p3@@>o3dm+U$61=08zbu^kYtRepGC=h^yt=A19Pw})k|sNwp2-D3IOFL!6B)GfIhT>NqU`u#c8 zZ}%?!CvGkF#C7Y-Ml18P=ks-bU3RZN{k$dUS;zKw)4St-_MT~+FJ0cf<1c4f{r}6^ z``IM_Kl|^uBz$M~p3NB-=kvwRm==`1z3$twMfd9;MROi?^E>gc{?Nrz|LaWw)t6%S z*Sz=NU;njSJ~t%p^S}L$Q`wc)Z+iCG?Ek;;uH?NtUer4OcVY_e5C@f?kIST|+%Ssy zo*J!}&2PM-FgCF0!`dfryM=ti&hwp=2@4BT%f9^M-R|}K|NW}}|NH*6YuA3?SsQU6 zZo!%RJinLu#GOeyFo%`z3TKyCLf5gT^M_kwZu)RBN2PmI=_ZycB85Q zcZB)*|9p&}k2S6+`F2ZNGEeP6v;nV4y zx#o|z?U7r&KWEkc$KR&@tg$<0(WJofDP(tUU6#&8x5rISUs=_^jhTF2@6B)bo>z;C ze^2-OUYc-53Dn}Acl*R+XU?!!GoP)_s`;KKT{~&t^Z%}^b-FG^8r{6ycCia&XLa7} z*)o>-OXub7+x6+jJfFY+Rp0-qezNTPq3?Bu_b&Dn{;F6Ipm9O>tI4M+hQ`LqB3$$D zera;JS9r!%qD;b%ck%;HHO5aT?z%}ycNm9zZ;yyBO9@}~t^Qp0AKjYAi#A7fAKx8i z;3Usq@YVUYjK?0nCz(ubJxwl+ew;IWo*B=I6F9ML+qTZm&e@00KP`H=#DH^Nf{;T0 zo!pj(_acn1nrtprm7C=m_5Nu7@9Y_$7HzmYzkjQFLXO=wA?Z6yZx}pZ$-1v-r)6^0 zvrFA>i$lZ1@7pY2y_)+@gXag9$qbcS@|ZUsosr|WH9)WA?z|1J-_BTDZ@c;3R^wUo zd$wFn46!p)Q&)fZkWbC!JA2PA1t&T233>q;J8rV@&x-RGdvQ?4%Z8Wtes##+qNiME zT3lza_-k=aaDQQTDB%0fX6fKFQ$EXVKbBLk?e$iF`Sm?zQI8j2Tpey8C$Ao$%rC0n z6|TUv@Wrv^_k=cj6mUCTj1`Y{UlgIo$jHTdqTfwR{>;B;JzuL|eqC_l^7rbK%RPcm zZaosD^1**b$%O5fUVi!Y>(^|3%M7Q}h_~e+WW=+^62aR19|Mx#Rd5^2y zhv`Y+&fK&G#+M3WyMDIiRBv6e_CL@4Khqb4u4l{reZS!IVtote_Rx?^UzYGFO)Xvf zea**L7dES}JLk|Jqtobd;NhpdJANBvTCJMD4D*CPC={t3cXM}Bf4aBM z@!jG5b(@_Ud+$zov~1Zr(O5&3J+X0{Y&>G7KavY8n0ox#h8r;^moGmvTi9?uV#e}~ zKNn?tY6)IU4>}~HzfIra)gk7SE}=W>bAHJ@SFbh+Oj)yCL`v>VE)!#Rqm8MZm66?9 z5f7C^>B^ixVy@kJbLGW}6K`aKuX*2_TqZs3w%p{~%c|BNi_TP$sFB|I^z4S-dd`@i zuU4-8FPpRHk3`dnSHAcEy_|Gbs$p63k*C>rANoI=Is5&&U3cclm8Y&!FWv9Y^ZFRu z8$M&(#S7S;&0XTOV@BD+4QAJ4)16;!eRp8V+=;iAxu3f%r{Qy_PCUAM!KHK84y}38 zbB%r7(fRoszkXV?)RUE2bmd0TE9~XcDzo3XwMI|4m$N7VvDj zUuu7HezwJ;t+wkXx;(#^VWuW_!n-Qz;nslkikuDo{@!I@I<+S5oiFgAqUH&E;FEdV z3zA>T8i%=7*}iC0Sg64Ib$WfWU=&}w$VbuRb3bp7coyvx@}}n7rG>HI;wJl4#0mXT zNoUvPaZKJm{q}>I0%CWoiw#3o2>Q*g*_Cp4+S*gvK1`=xIK4cps`OD-&f=%dzppoi z9&T+9mwO-88S?4w)av=ypEav9-jSVjaMES1|Iv$f<-V>eojfPe>W-qhnK)N|-9M2} zKkn-aalF59Tbm{BL+pmuJ?wjyznj5wLV3;PIkK<#uKl@_|MI=xnhMi`)Aem~-8UG5 z?pn%TZI~UG63nIaC+F*Sz3WEna^zQ?U44ez{O9lG_oHO`Wdb<5F26215pw&`wU;ke z-qPHcvPpC4mS~No=5ZQQQqt>p#*{AI`eeq%ZEp%Cc(*)UG5fLI)BZ1iKkvByU2oC1 zpZrp9>S+=foDT^AmcNyzj@K&3DVvKXq$sXCF^k zeeKNRzCOJ;^&$_SpwP@n?TMb!nR@5#X=3a_UC^7f*P5pQCfbuza|EoTqmL@qRM#VfmQ>(jepFVmtE8^Pynv=OF?e|@297U=>xL-1vU)7adt+ZF}L%^n09S>JMh<){&uky#X zQ^#1IY z^Kj~&j>CO3Q>CUyhj*yJyj937@3YOuvr(yAMxn z_>|Z-!+x^tqjx-wyKWqrJ6}t~pU3KrT!GrQRXW#CA2i&PCBbxFau$fb780i? z_Q^-Duim)e#<@GcJiLB!uHO4oxJ4&hnR~xS{^6^~{@uL(>yP-wOa0O-UhSIe@AF#n z&9{yB(qC3yigZ7(xX$qPkzK0RZ;}e%NvLnvM6?+^rHb ze17M8O+v}i|6RQkKdziM^PzX0T9o2f*T(nt`z#eU=cLSwsQ&k*@U`sxb=$Nxd;>zrA&@6)ql^VYGOe6vamw6Hb1J&pbPh5T~q zkeCCyno6Nj8qskw6G9K1yE^yw-q$6mUp2jJZOyZr*OyDMyUO0(Suxo==YNo|T{DNckzwzEip@y+Gjh zv0iEO{Cj&653?mFC%a19th0Hf5UWs{cRnKVU$ZQyiQ=Lql@{sOLw@YCbTTM>zPx$E27$Du zJ&wuSQ`USCc3aX=yubX<0qLfl3zO5d_in0EU$^A;i(OkcWE?%-%e%%#cU$f1QXP}m zOO9^$HtGK%6SJpcae2g^yL?X49Kyf&BBY4?G#p_cdLclFTL*_cmDgdCl6`q^Oo9YW$|M-tysB zMNdC2=E^mhVm@n^<*VGgnNv;lpPHq&{6@`aH_YsVUG1s7 z_F3utwOSWX964~(H@xyA<9{6qb?*b!8?xVgQ*n@6d%NM_uda2U-W-=a^7Gh^y{Gt6 zoe!Ll$$r$c%`-sL_0+1;LdyvgCnl|}UborU@385U-Lq`-`u9%s%vkPVHRVA<+VshS zyYFgF)t}3IGjn2m*u!@(9?hRwdC1RxzeWD`dlMZsjF-;1`FpwM8%2fq!pmW2XHC1_ z_hs1&*()!bijoQyBwplf=!-4tpAxk&uVByC&zo9TCtsaY@!(FO^z=JlUfeZ1xna3t z`q#r>ZNu-pkx|-xA~-eioZG~3ufw4_$qzP8@PB3ba>2^|^{vEAZLgy-ZS zFTdN;uFK|@-+UF%=3A<`trDYKnG1Hlo9o-|eOhP@zoePJ!RKb#FV0z? zoxfMAEpwAA;W{(v>ZPKaIU+as52S4ty_%Z9R9adpEiEna*eOt<;zrL`y+?vh3-{LC zf7F}z{M?MZh;-p8(K3&6UrkV+R&;pI_IW2y72V2-^O-#9^qsGFYK~>{KQ?PUdF=S{ zwQJY%%iHnvK0A1!{7i)WiQGf2Cm;X5_pjvXuY9{ZHT$NkKQ)#6@k{&Z-CehKU)lP1 zk^YYzGpy1k&b&HJn>TC5rCY|vl0SR*&z5#s(iZ*eSozi1 zOF?zjm-TAj%0{pGyZNNk#0kGU?x?*vXSwgyTL191f81^cnWcQpnRk8vz4&Fd3IF?Y ztrr{XSxL=q-6EjY)zq_H>+W* zLuHPm%GIN9?hASB_|`4AcK>P9U6T!qE}rnPS604Rl65=ZQq{TO>5+HM>oU(| zAKj+M-m71GDs`1W|Ff6xZpYf3erff5RqmV#0?Sh8U(%d==6=zE^-I?txo}J=zvZ6b zyVRF6X3MVMug}1>>8@Y&9jRaIEHb27ul8qOFu8I z4xb@@?dePTO*#r*ove*!Y!6#sx=%eTTp6_K|Gl+^H(UL#m8IY2Om20YW|gkSI;CsP zl4&cWU#l!!z+mbjv(Lpt!#FZ^9`E5^@3h5hO}?BHOR0LXa<==SmjTZ_n!_LIUYivf zykutHY18vD4^7(F-^~mU5LuqOVfCJVnNkne=Ov}@X4>jKf7HB1w_kPp;nmE1+zHC| z3@!pG4iAharV7~oX_5&x4BjYmi8bi?w4Tt3ar{L*Cm2=tuKXr_eZ74~a`yV&mAyOt z*UVpg@85;YZ!O3FeO=DYeaAfGNco1{lh2sw)E;}eY0^RGIUEd(!6i2sg}Z{8d+%P% zeek~e-Q?5apE_#e(z5-p`)yafebaKOu*6%l`>TG4I$gERFDrU7seSUsyRC&@8^2~< zmg+LOpWf}9drkhZ|5SG+y3`{npv#QOk5LE{rJ}jF)^Mg7M4~n z&pumzFD$gH5Gqg&iVJR<-udliExzsjDk6XFovcYjqxiNS-$^0H;i&mFp8vZ8K_ z`R)5b<~wxmexDti{><`h+Ns@#&#AxNZnpo5*}UpQRrg;?Nh#iUy18waY5w(PYd7i^ zh@bQA@sByVOJM$e$A#soZF65MaO^sjd`@(`)6f6w3Qs(}H;?6na`9}IV?R@Z)Yv19 zYh|45OBc=et@qh`$Y6KywwfPPyVN$Ew%nGv&bIEk+g0D!*H+ECE&e>dz{JMfZ?$=F z?7F-Mm(12{)bz^PuGmzvchx7guMe6cpVc(qoTa*o{rie_COYfa+rKMRu~1jP5xBpi z>83=^o}|ggp5@zZvx+{l_n+2o-QPQIZC`Ct{_5G+i?4-kx39UoC9^y9o59nfCEL8+ zwwLTmnO|B^{X8|>eEFn8xAK^V#o>mHL4^ftSIz5tRsU~o^x*}ue4FBy?x}13WtQFk zMWb}b^W`quiIUFn7?jY+F7DpU&1$WY>ptr8jy+=~$I61!J~NnaYAm_<_T^WG-ED!zt(Px~ z9ou)ZE3l^ePAUJ=XG?Zxh|5WO`4|ntWeJGrpVXH zU707MPo{i&o7X&Z!;5*lnRXU-{QXy!mA>j>-jXGjuV%^h>Ur5M{B_pq>|E*IKSG=T z*1oyB`S>%hx!Z1BJLlcy|E|PipVK=ZPxMj(YXz4kP*Dg<4y|Q}yOqKAEqdVUHNo#)g z?X6a!_~|>jvWKPItBRZ7^d8=QOnS|>wfFKi6o2OWyJZdcGQV#>bCX#W{oEdI4RP9d zSnRiz(At-4UWRL5Da(s}Dp#s`>r}<&++$yAuKhcjZS-qtWL$RmZWV{c*LUB|fb{Zt zwQOD-@svxQWo~{>wZFhadCN>ez3zV&hcup@6;^9!Z(QiPX-$p4svlp!&$-PJ7Y=lJ zPTzVjee!bmV``Dt7($cuYAt?eysES(o`S}=3Vo0B4|!e*50d$U{d z+K~?@j_^$U`FC3Wm6aC{9!y-dX0K>|T1iEdiuM)Gnr`KV>^IYcS6s=Yh=LJSHWW;i}EMHunkkaI^aC3yoqY(e} z<0n))Ew(!-o)^$GImWbb|L)ECb2!}773`Tjrdy}2`SfL1y@KS57R^U8Q}xcjmG~TN z93o{BB>y(&z0|xpv!W9|-xTrK^lsn6%uhCRKTcjMbw{DRM7q*iSjVBl9t=`Lg`9q*kYTY!C1v&?W9_h?HwIG$|R>9HF#-MdT*!sVirs73a@+_IK{nX7xs!uEZ#pZQT_9S1r+g*z)fJyin(m(BQ}FgSd(H00diUFo``b_M zV_6os^NZyMnfZQ?^aU!eM2e+OJD-|tW9Rq4)v37H_)dh$lb6h|zAH%YwM?$vc8U8_ zn9{@w?_*rGd5yOd1l0~s_F{T+ahqymoxqNO*~gb~S(-3TK9qjuqhtzSF5kYF$5+(k z91xJ}?d{#v9`ocSvy_g58CUHKo5e3#nP$wMy?XWP-AnJ7SzA}z=Xx4&$^{B3^k2*U zWTu)_A*_;cxiv;@Pg7G?Dr5JlWIc!V91^qp*>`+d=xA)?<$Tne`_mN0&Yd!x- z&xchxDjZC?@bB|8?>+|whwWcxu=pErPH=x`w)5VC_hE{E^#Aj#EqL1e#=ht5aW2a0U zZ5Qubzy4tEd!fS*n!M|xybi1n7oV8WD>*&2zBRr+yjV(C*AveY_Jpj&EOQv|;PkJKv73|F`8y z&fO&mT0fJQ#%tYn7jd)tg&N^kw!~6gJRku}zG>J2T*1Nnd zyd=0Y+B0)vV#epQ#`^O^f`h8UEB_WfbzXj%xp!M$#K&v;Q~oWkteB!4Ib+6C57(Y~ zH~6PanI@?&xU6{J&$sXI|N3xv|GrO$_Fw4}{&8vDgHo^kKR#bf63W;6oUFR^yNQ4B zM<)jX7RT+jer`rS@gcvaww2%fDj8$d9rt2?sOL-N?++gDI(_fgcXumy=DqvsB46&6 zl~Xwuv+DZ2|F!$PVuOF`E)~BXF>k)q+1P)l^2PSUv$f z{ZH6S0@3 zkISF$IZONgm*3O>-A_N(8|-W-_xs=XgP-p1F3*qsdX=wxv&$X<@De5e1z(QMla_q* z`sGVmwG&>EN@i0X6bvgLNq3*z%<`#e&CbpVZW7Y(-b>F^5aI}73s-q`PLShs37<~V z1j|K884_pagshdqvTo|noI7p{1C}jc zo-V-RI3ZpB#Cc8@rs=2uM(*Z4VrFiB9JIu0p7;!(XK&u<%s>DC=Pq6zeG#sW9lZ)1 zpKKhJCcY^7b^cZ^QzOHAX0Y=hrNH)u(B)XzxOdyY3%4%hLR^cTi`N9l?Y8Ulgu9O} zUc7ki+O=Q5e&yw8QuxmPL}EgIPj9cIT#@%WCl#UDvt~)nuX>=PFvsA?78fPQ?Y8-O z&EA{$@0UL|bFP~JOQnFq{f0ZtpC-)SEW*@y;o?QdYPSUe8VZ>l#=G8D7Dq=%OHV(2 zG>U`8QI6?^tpfkfO1>%Wa&sl*Sl_;VJ9+Zt7u%kn&HZrZP}0T^Vy*&D6caYzoX~z} z($WTr1&e}y=qxC>edUVCuD8c``g+Jp%uVAGDc!Bal~^?8#GX`9wak*5wqG~SF=fpG zEo`&da$A9ar>b}3F1v{yDnA@s?pGf!?Vl(nC6XLF|q{nCEDn=NIz&Wyb^A3tgQU6-!E zkZ0QcE%PsK`*UpD>d>=inLi);&B3}@?b{0XfKw-$ew;g<>1=s4JZ*!SxZ`%)9k&xS zCtsLb^J>NJ*{gTIzd5V0%|%D>v|!UWm!yn4ib7nhP79Ol4cs;M{Ob>3@mAer`qSK( z`$tX5ZRO(IHO@zV@o$^&=WAP>(LT#v&RfTu?L_jzC)x>T%|fU3Y)#32vHSYj!@}JY z%(wsUXb#0W;94RlJ-C|sG zEi7AnL29(cnLr)cGj^|2M2(7l&o?jp#-6aVHUH2Yk5kf`UH#rqJyc&V*LiECUUzEu z(!YDw{rfg)_nS!}6*o>imytZz99f#s8F=r_+&hP*&vBg1)#x`fxD{AcYwyaq$}e%E z``x}HG4rNcZqhv(RLwr8Z`sk0Z6~8yJ#&2nE??+Bvr6UDJE2nxr(E65Z_ZcZs(N(m zxkRz{1-JK|4q6eS^`v*tZl&FKkDdOreQm_k`IBCyZ##eBlZ~U+!;Kj!N}UIVJ9ltz zHfCXqS9ww#p<~vs{-AKC%)W->iN+Q+hVyORXUtVSTl_;waK7V=d5S@jH47)4ua-E_ zqaa;!+xCuIX4n0_w;lyKAFj+#UOYuFsC9qthf2=kS1sQ+Zf-rw*(i5abY~QM|2E?r zrYGfYPc^Um{P8;b;#ql98jk6+(k}!J?CRqd3)Q4M%@moE}Fb+*TTw#+b1e| z`WqMi^Q--?qgJhW`Fz6BU2Db4;?}jB?f*Hyzf?B)cbnFo@|8Iei{H(@dr(5l@ZOHv z^%FO~y*Jk}T;YD|yzd)MWxnk&y`L{0rM~NIZjM<@)|cY2-DNx69GI7{y7FMcC&y1W zKB#o6&RhA}>Q$tf=0vXL{?YHZ+RS6sK4ST1o8`>t`R}$RuJwwk^#9vhu>Npo$j+o2 z#?DKRw({N${%q`=tE@6pdz~hITFI>1>KZC*B+7YmvFK7)QD5hnsMCqF8`LI6 zoXXyGw?ISZc~Yh?e=tw=jJY!wbuO86^P`|t^PQ-=(glh)4@IpPb2>O{t)8Au(uPA1 zlcL?{)H^t7x*W=ATe@nWYiYH+>!Rm|`Yb$9YJcKotKA#!OsxEKNzie7?CGEd9~I}He|}F? z&SqhMILph-tfkk@Tr8t^{R;Elay&QW=Bm_JK~eX`UM^a@X45Sjh4o8q4jw+cxOP^- zr8M^|sb1mJR-e4N=2Axg+u0!@TYOKsN6KdY+x7eV%C}Zit~-f%wcKH6_v(7Ft$KIw zy?Gm6+IxSOl$L&X@vCpvD*y5u^(rA=^2OV%N^Eq`UibPPl(=u++0L$0D#6;b+dQKZ zH{30Mx~;XU`|UH<$#0&mXnwcQbGqN$4Ta})&u@s`s9zDM^Uf;&*Zi-$-udn7zJJ|9 zRCLMe+%Q|^h7ieJ3ES^0w&IpA-A|rqVjY+9 zR>H_@`4!dUDIt8_`Nh)i8lpZ=-rP%wbKDom>SwWXW88iIL&thczxb_ED0T}Dy?V9# ziFm^j>%!GD(@#vSonQB5<+j5=&#e~kmo3j}(oRe?__*UDqw#Lp-@g6szq4|$Ywr$v zm%Tzb*wEz4gv9jx<=cvumR~J!pY!rp@9eS_nK?n1ON&hIt=gr#rZGf#(Wa2l(^>D` zzA9TD4lm}vDZfHe@!8H>vKuzv+IDxtik%nlyE)hPPh7e-f3ri>la;mWG99&EY>3*M z_}uaCTj?uGr=nJ$`!(x!{337by75I1r#M7U`uVd` zL#Xf_mw3^_leaeC-uI{CIpgEMyLR`_(a!Vy^vCJ!!gl3%ejEOm)k{pgTAgyeZ*t

G8P++&w*4Zh!dst)Yqa*Oh|WZ|knU=Cg{<{rSVb`mX-L)9f1? zxUHvWPCeXsNpb%1r+2tld~PY5_hMW1j@}6I^ex&!Vf8x#mh3;Jr*!J#4SP2&g&ntV z{78?pNL)TYeoB5uxsvJ4+ovv7I%?_KC$BF4wd*!p(A4j;l2g2XKk~iPEd1H2N#@R{ zQ`~nzP09md=F)=1>Rx{_C&9Jf8@75T z+=$%0H$5e^aL&aUhsBOP<8wT@^vv!(W=*e!x_r;vdXRcM=hnXJqpGvsWWASOeo||( zax7DjcH8U4rsc29wQlY35zUDD5qpBKsQk->t#d?q=6$iLTG{TE%XRb1$>mmV&$9Q$ zJu6u`J?7QdgSX>v9lPo*GqKvcZ`O>Jy4B@}S3X+(oG+_7enJ1#H&;W}t9xZHjx9NF zBGUfu0{2d(sox^9s?weux7s-~-lIF_-~9Zqx;^H#n{Q|u+zR-s{QHNPT<$cT34Bj> z$aG{){uHHi?d?8~2|-@5IHf9>E|6K(y|Rnv`+ zxMd$X=gfIFC~yAidF95wRx_Wkd0yD1<9}e&gV=W)J=MRhULSV#;^nB#S^ddAM=t&q zG~J}}MtjRflhEIfd~5fgS!8_BOz)GkMD|m$XPMFS-n>}1tz@hIj3YXHj@xU`=LV=G z-52ExnZqOcGb&16?J!&N$y>Xxo^N5vvN-0<7b01faCoEBiKZmosm+(V{bWBEZ?G1b zKT%#TacAz^hp+ZsoY(efGov5dw|AKn-KVe4`N-*e=8VV6Hxi2tBYD^+pG~`zX>!!Q zgsr<)|3RzZuDAE{X0PwR@nvI}Ph#S%>8;CL-C|1*+>+gOQt){A`dcq%PkflWXlCil zM`g_GyQbMB%Zl#*AadJQx{NI@-}}&xSG!^l8>+p1@oqhzobR5JOUKVVOA5TEn0mf@ z!v^iE&Y^crwr||1^Y7BrV>4uDhuEBZI?enG|C7oUS&~n#l|7wrVr=t5xcpY=?Ngg| z)Wg#MPOSSG_uEMK-^cxHU4;eC{p3*Ay=`2+YO;ujO7PO?>8sjHwYlWCcpCNkshz!? zs;jD^ta{%PeS$V!sN zymN2~uDlX=o~dH}^}J<|rc7hcGxp~C9=j|t*xtt2T~1z3$DHj85R>3{ zOJvQCW|rN0!xw*Tg8og(${)*qRz&Zb+PQS@xu{u{Yjxvx?>R8BFK?OTOwP91dmVpY zWqdX5xx@TRMe=JWususzcbf6ON2Ft@!K2g-nj05f@$|p@BuBN;!rIVV%dR@(_R1p7 z^=IoQ=T-QI-+H*#%yH$;Mmw=}pPb*^o*O=8d2;2VrAtp7xVEc6YO@8)-EVVmFIdj6 zA++%wSF}d)?DOADPo)=iFY13GF>8*7&HMd#9+<4i+w|azTj=K*XD08OU26RM*(_z> ze_x+1^SV^h^YoJWwB5bmO5=Qbdb&C9Y{?6Caa;ED+*`hlslDRD+)`4H=bSZ-*_5tP zsiwU>jXzL0=i2PHIJVM_k@hT49$whZwd<{1p0L1d|67qWB&26Y{4@_v37qoi^^=U` zVw+VPw(VZ5WW96wdTYhCGZaMmrysc~EiG>)H0k1pyT<=xyt|feT)K8{@VBe){=GVF z`O~)9_NQU$-LBg3d7Dkm%*?i1n(K-7PdPeMTKe|<9S-y4Z6D{QKAmf&KI8nSR?$0M z?KgvxqJvUq?x}5FvfkjvF~b%O?Jb6S$6c39 zn6_+!trpup(M?l-G9TCNGdZJYvdl8~cG82|KRX`A^?o=d_$pxC!)NRHb}jAuv~1OX)haI>o zkGykIo@~3;xakf<@!Jc}R-KStT|R5~%lzBVX5G0yDKTqd?5&9Ukm|#6?DqSU!xm0l zntrEO_HOUCcNRC8zIMJ@xH+${^=_$|_w{$h8?WEl^D-o@x<2#BwW-p+e6kU{Yn=14 zH+Qe{E(+T*b8B8|{CP>)RNvLfw_e{f?Z}#PDqrjNigy!jmOs@Fx2&v+l6-G!H_bx- znVH+{^|!NLJb(U7cAAjzgB7o)>x=gMet$3T#mmGEADIs~c*nLH-VQs-w=wVPvpt8r zrP$(fm2>mhuU_Hb71~>5Fx&Y;F4y)(X$R?^-AugB6;BSn5;k*dV`KZZE$*svj+gtt zl}k=p>cyW}cwMdX^=s)lC*LM?yKK4l=)jU1C3k~>Dm|06bM`vy5O|f8ky4{#FkMH; zKlJ$QQ)P)W+USyN_q=pdV%Ec=rt>=&`Dxf0N!qhqncH+*!PtHK-wC(p zS?yTzVlmrtZx8zor+n`-cvN)>D=R6TQ@v`q^v}j^ZQmAJ{`_t389Sr3xJut=i@5sj zoXEXt`5$;@YYT0@bt-uA;;!WnC4DYD-EjRg*UaN`nSMQ89X==Z^t3ZyOw6p_^z_u# zI-%4}s%Bbx`xouX%xW~dcFol1k)em|+_fg_W?0<0YUZc^C3bt!`Gp-XuEb?DomAak zzQsT_=w3*%Pl$_4&aDGHJJ;%{YJG|+v<{S0@=NU5{`}^qb*tvgIB{ae9=D&V9{DHw zyZz2(XJjf}&aCaNz1;G#Z=G42$EkT)9i3gLPn>=|W8&HqGgo~!vJWyg3YalXKvGa} zYU$HoyN%pJ<&HR{l$Acea>U{Cf;G}|w>%HVxesJ~y+NGM=AJ zx?uSsazn&{giY(}CDfak3)axh1`u*qQIn{AMy|G7ekEuLp}amsJ!?Y8ZC!rUu9 z8|z%;Ut47VchVVNF_z_K@xL823h!@^jJ>@7arOQAp0kpjz1mLj%U+sQaobolnP1>1 z@AS))w2tzx{Im0P=5j5L8TyJR{2y$){adwh-=vv7Gndb+Taa-5(xs-n>T7q(ntLav7e8))R9*Lv zf6eCy2jb*2KFgQyke7^Laa?!TV?s3#FYnzsOAn}TFtA`SnW|#Xt)rvkFjs5WTgwvZ zIfouRP_Wr~;BuI4lfsF=jFxOqq$gD0nZ(=ld0ouTpy=r6?>Yg&!OTW%o{MkKGv6M& zKG{Wpr7~e&^P2bHX1>_={5W`9-Y#D7=x&}fc!>CgSqXT59#-yx+ZT|vVCUjBK>;cY zwRFMldFtCck3QPCapSga+uGXN+*lkZJQqLlRAIfeynK5N|J`qMcJof!xqf|qT3T9B zQ4yD;z>}Y>MV2RCD;#fzO3zEOkl~y50u<5*o)#(IciwLMJa6^-_30ZUDt0P!d@^o4 zo94W)J+J!QT{h7Rph2vG7^5n~R@ABp~pLhK9`SZh|8FS~_mc9}>!_Ui`o1fqA8qjulHe{&p z?aNZ>E1t)WA3q$wa*ycArQXv;@}y;DS?3>ou3#W2DQRhMzkkDq11UxecL}}H{ixPw2eAvL& z$f(Jj6B3faugp9$UDr?Q68mq!dsca2Am@}b3;wEHant(4{%rN?)!CVui3SoI%`NJedZPx9pLD-UubG?bM(OOEmh!jJ{f)_^SwN zFEr2lw=h|^V+!jN$A-G-1;Hr) z0}pPnMG}p5${%;1V|UUJITWz&Lj;4cgfz#eH4K%qUplJ0Z!eHwxv5Yir|?HJpe98j z=#Rk3dQX=_^Z8nDKe#D%x6FV0#dWIfE*$gUYClUhSN;Cj>_u0wQor89HOHCvIjHOu z>;98HSE0keNbt$Za_N$}Jo@5t?*!u~GJCY#f6BAw=gEyPBl+U>l;o<*iY9nG{@22P z@Wr;@rP94@{5o&uy*f2dGV)5v6qWh<@0(JdDc9Kf_dTli?+~65cBVa}WumY}joixZ zn-;F_SDj!xy-;$=wyv(gT>&cLvS((>=bp`%Y~<|mWT}*Dm@O#t;qngNd1*(3lF~Ds zqBJKmM>p?HXDCptHLf2OPWmoJ6!tG6!KI=R5U0m8YcZv7@J9ar_*raDH zDPLFQp|o=wlgP4#CQ4$T7J8>P)^vS0W>#WsTf@!G9o&<@d{&M^<}IqP@hGt^QhjtUXML%=p4Ov@$De+373z#IQ{1tyPbaRDqsc~1ftjWE z?mM#`yAv-mzvC`C`Ln|R?f3tC^{QvE>ECnAw-MWGc+BOrWrEnQ1>)Q*lGnEPUO#bH zt?C8CeU9ZyEg!B4q%`O4-hNw5OhV{n%%;hAcTQ0Wwq89YY?F*=^mxwP3yC-?&xPPJ0nxm*2ZW>KF9omtp}MErev)?|0-G~b}E+} z^BLK$sNJ6**W{kze{*H4-`nUJdVCjbg0IicdtGBCX6NzJb7Kjot-YOP)yp%9ubtbs ze3$JwCzImMB4gI1(9gW1_@Kb{?W&Be2bi^=Gd}QK@@Mr)MLG8%HulXWB}~U>CaZtT zvktbtKRK`d!H<=bS{#gx=g+&DS--lpQS?Gw{DI1X1#F_XoTDNmb8l@qdHc3>&9aKr z8`rM2f#Uetvz1PQmgk&O-_F`v_D^+FKGX8mrQ2(F=1pI@^xif9kgv(cliv88KWlK? zhJTmH_el?!68_mVST9_@TwPs#`GN%t0{qg_)b^w`KiAA~WjdVVV9WL+f0O0Y2M1>~ zZnH4HzCm$W!Xmq)cW*dU{`8uBV%f)44`LO!#;!D5r?@d-(`(PIc0$u5iWPGnvwMG8 zqg%c{dYi9)Ns!Ld%`-TfY}g*0YkhzCLG9JIdCk9nG0L12_GrB#^4mB6e|hh-d%XXD zug@y-UHCTYw9%}RT^G)NSrNWw_wJRo`yzG;WNdwxBI&60(0)$O!ITR*x;8d4aZLxd zEXp+lbo;Gy`EvF}6B8Q?1HUDLzb-rX&9$jC zGEmEIQhc;Q!d^a4euwBf-5qTY_!=h~Jz$)0_UY!d-;4ONvm}3~hHd+H-R+j#ment0 zx(duT@veI@dG}iVtJnU7Fx7BfFTZz3S7+asniv1p_NCf7J2(G*YAK|D`>=mkwoBYOmTW5`kZ@v);_X12Am$Ik`)u8}-@ToyVkB~G`JtYY#Znz} z9@g~s&h9_@{7B`E9Q%Y~C5sPtj-KYO`F8b`!_}v^EPIt@1p6J`Ulbg4{AzCV+Hgj| zau0pJtA8#puhLaHmy>#A-qoyj=9-f76*JkwzD@g`YY}xq=FF{y+peCweLUsx@!$Q+ zdwH)}yv{K%x0Nh0TC<>X%GuQ9DM}|EGk#h2qVgt#>(` zq5Il*p8NFV#;JwpY%c$0@9p(v+O(>&Bq^<9ao;z`-O2Zs+KMpt|Gkjvd-LIw#NZv0 zueuK8PMEp)_Pd8>N}Wei&Xr${c_*X%v1QJ>O!u9Q1yh+SxaiSf2)pM1*PJT>y+zq-0Y@zb}g)H#xK zUC%nl9CXSKo3sD^%N<9i+-hW;7GQEQL`3Mp^Vj8S>kDTbO}uF6B=}_Gf)~ZF%eFU4 zFYqY&-)gVdK6}or!cQR%4eR^+``3Rjy#MQ0)X833uAe+=-W7k%=O3OD{dGCxJ?=%f z-<{6AFkfYf#g<3SKb8k&#xzFgBwUt!^V<2x$K}ynd(Zg1Oqz0}mnYZVn{g#bSHb-s{>sH@$ZN>D% zEoTK;DsyZPI`x(BzU@$vu!eo@&c?t!x1X47-=bkvT*2e&zhX|yW3W>MG|RQ;Z?Jr_ zM?w7eVa~-ia?#iH4eWl#YH$Dg?OW6BcXFj1O*Ya`x9!?xRlt1b3jY@Eqt+Xw8*a#* z*IaP>UAas{S6A1qTeoKI4vf8hh>OHhE>5P)${7b7}^iASH9TxTWfow@6p4d-bpG7CybB3Eu9n~v}$VbcO8Z{wwoHe ze4Mubz3@G^t1$}Hvf*>+D?h#cc31hsN9pai{kiUzv2Q;ZE(>WcKm7Lb_B>|DbT5bm zcL;Xz-u+fwI6Gyb$*Jh*=-UVWMTq;F1PeZXIN7p1S##sf^U8}RD%IcCjPS6mwpiJ@ zWXHN$lQwBdr6sKTx##`KAE$-)KF#}`V18?w+{R?4J?{lrDw*<_4G#o_U10q6;c~B1 z%ZF0gU2hNGVY~c+Rq2b3tuA|8VdFaUcMnW2)+{>8sC@p$ueP>RhdxcaxA0rU-2SjP zr{09WiMb^4e)}`#uS{Ihbstug{<^=;@LS)UX?q!$E}yZ>HC{p@mt&)0`5GzZ(&h8b z!t8_YUAS<~_L$J)+IEE#kISTMOxS7{*lWioIb|#~j{eb|SIw~9k;ReSXx6M*0TXU* z&7R)ZcTQKnNkgH0nfw+0`G3!qKKhq)dusHzN_MeRw_+~cVrusJrY)bXa{5u#76l6x z%ag}XTd!yDD!k);PQCVS?V0}DQ~6J`Pw?&ID$qavo7ZuI`cpFvo`dZ-&R@_xFoR+H z6srrl-`7oU+4r`#w)X1PtByI_Ygmh#&y|QDKJtEU=5JPi@%s+jl^IJ@rSrC-Dnl})J1do*Dq$Vx4T14f2#ApDX=|1xvTq* z?V2m!-)`X8b!tNHjj5H_qE0Vgv~c0#a<=`OoduqJ+|9e{$AaTJ7up^iSNL zmJ5IFOZ(0|I9cT@*8Q};{*EKV4-x*XfQz~OkGEAHlF_=mKQG*C|C`!nGc3)mEH2M^ z_hN#jj^z1UdqZ7M+hjUgl}0`GxO*oia>e0kz1F-uJUsj_*4$eWZ0>%hnA2m|g|I0P zc3l0)vi5*ZEaoc=6gSGx!9xVi z`h+Pq{xWiMOE$SC3GRBESvosJ>y?hp(%tU0_xIKAQgdJ3&JimfD>Hc^(`3Qag)gU> zvn+nZlKnH>T>SShne{VvZ1c_SXpD@iTerHt;Kuw*`=PB)&BhR$yE0-zbsN_#`{xx~`(1*)jZKhCjN@+P^T*Nc zoy^U`!GFJg{Al<#SZ3n~cbU%P&AWm#p0?*zyW~waG%pf8*0$r8HK*tSCbr5xJ?TYJ zhZ0Y;=Qp}6-8AD%eWe zy1kCfz7F%7BC{h5j!u0acqrqPuirX3VQ%%$lO{*qjtVyJvfeFaY;>tjL#T7Y>3@O_ zcQqk{3Pt(b4?f6UznJ5m3%0|70O#l;eAWbj=TzTM2d|7x-F_KI9Zv(-Ti!x@6h% zsV7s;^IP+n|>HS2cAhKt~3 zGZU(J_$IDwXW&Yluyxv$sfTYY3xAT_er_U%On^WVuzWzvgNxCt{a7Q?z`qt(fL5_gY%1z~aijX>G4o zt!mrm`0VW5?VXX2V|BNNhW7sbq&MTJj8ft}?bn~&w1hUC2o_;{)8(?@vnmrC=QoXC z|H4AAmO69WKYQ|Hb94B5hYhQ;syOdh>n``7xUxp@nHI+3N%Wp4z=_Mv(00huUj%c3wEL zM=^V9{+h+BpK?pi+!l9Hyxrx@L*r#q?&rcw#ambZ&;M#?yVp66^Rf9{_URF251Lc0 zzkUfRf06e6toO~{Z({0EPiHOcom!Q_((idwl27a<^P!J1>fb*+X?-0nS-T;Joy9xc z`|Odeo8Bw_Ra;cLb7jrKMZDIxw%7K@`W?QqHk&6kYlnN!CBtyX3Cl0$Zfei!bm5sR zY0vFok#DbAa$C4SI(^;Q+RcGE+=1^HAIeO;F+1_sRkpJW)&&0i^z(@EyWP`g$1Xfs z6}Rkb`VGn3*0Pq@d|KnzaDS^SJbCq`U{&15(hF0=%e`D0s*k>HkC4#(c&nJN#N))K zyMiIgspdCl&(GNTY@5*cw?*4;&OUvo?BvG}rQ3CTrd4FMX|*xucWgDYEh=jIZJ>Ta zbqib6P7OC^sk2-cwtjv;>AKj52p+ZW;Hqw_ z-@Ed3EQL+J=YA{wHpjNOtnA#oGc(PibyvDC-@WwJq>!MUU)pA-SXI5>`&}i&@%`TK zp6~anJ90BAywK%vW}alg!r1iTz%f=2war?qLv>batq%JCeS#;$b(a{1kBX1n{_OuU zVbY^l)`b^eTc0@A8ZPv0=j>X+zG-4=YD=BfPc`3r?kBfTkFEdx9nN*}Q$LDr`g|!p zAk9(FP+5KQq2P_4OVi5Vzpyvm{)yX5@?P^bc7_AF54O$Ub$gmrQ?B;?T{=^4ZP;=B zE2m=N+0AEm-uv@r)-f6HKMLL}Enj^;I#t2FVAthjFSZHis+`}}e~zzv8MJfFZ9!F| z+ArPbdv$f19$EjqUhQ||#iRH0q9bPfd=RbSbM@wye)m^@1efg(K9KtGe@^D!zR(fSA0A&TwbAo+^{W3n61w#7sqfh7!rQmSceVV>=+pGn79AEa`)Igjf%8sl@&h&)&@+< z{?oiWEK+ypzJot*On5R=IO^c)6NdA;Zc6<*nQv#hX@kM_-%qBq1-eUR`e$Sn7A@S| zoLgh>)x9`!jiwJ*{qq@59Hs;sUh}=3X;L-oVA#6HyoZn9jBsM&T&?e+|F!q_E#^gD zvrB)nwe&FF`K%MG-|4T(&CxaEcbsS0k{qv9)dG>#u~XN?{qLBt?xWoL`w|a6adUNh zOaFdWv3hM=py)2154??bQ+cQE*fB%%i>1xnuCD$ZNqPTm2QF_A57ku_jC)|l@Z;j$ zwrdO%JeKU-X?e+CdWz93AGP}2Nh&+u{@vlLnxuBqcALM3`{}RNQn!z#nRRTH(|dYa z>S)u~=l@?D^6l)BEVnPIX`a&gx&QQgNABP1>6{nCz6&2qpKYV`Njme;+_Ku{3yW{oKFB_vO^= zbEoI7T^%mk6Q=Loe?afcp+9Wdi%#(x^;#-pU;}xW?!2( z=c1d!mbBSbX=^U7sE}vhzv$k@RROlbzb~HMyJzcJ%6+-q{};-N!_n8QznthiD9we&L2moHWI zcfb6T-1XjM!u`#=+_GNh-QPFk@A{i_*PWG|yUeVt|J)+!e5tJ1P4Q9Exs?L#YSB>< z7A!~Ccdmb(YJ2@CpKbo*89SHkHC=8Of39SUZgT2R)I|PHS<#=(znglcYOZeUF`jU3LqWy2cehURWi6K7`gBug z-om&)JTb4iOb+wOM*3dsxVA~#_|QeRXa8iiZ}97hEj)De&Y`0>?U(MW=I<2w6wH<{k|(hPUW9*bz%E5-7KudZRroaYRz@ue#yP~mHS{D|F-+z6cHy*v((Y;u+gn!GaV2zFYFTNJK^@Sy~ z(0|>(JS~>(jkg&X81}W_4#*3-V&;|4a&3x{@R$7PV_z1pyuN4Qj{aPy>wQzDrt-LY ziFKxWwFa#W>R_qa=b$lBbHe?WntPoBZ_9$xexFiZ@-w3A>4Ay&1VlbCo@BejmdDJ% z@WVLIdGo8l5YLmn6BY(~r0tryulSRIRMErUW%e8%^JLa_Z>p>L{;}Ko{GH_%OkwVi z4!8d*f4{qA?c0l;u72y+%#+?Vo%hR+`~T$sf9SryJC&Cs)NALLwB@d`_65>Aco`TT zoZrEFR@Jfib>Q?Df80DmrA%#){#Y6ONgyibw6u4(0E{0AkDyV zV1BvuE1}N(BbKv-iXu{yUrcRbonkTDWB2391~+EBc`Uc%(OD` zx6Z4rKlRpsZLLnq^9-!C&)jzCw5HPBhHum7cIR`=(&Efx-pEGB7aIAIsG+;d~|3nb#Dc zVPo%pR&%|!<&|^i&Y9`te-1eu|58V9)e`ycU9Uf9rCnF+cJ@7cMmE_yb2*pU)|LHId{7|0u?daoMGn7C5y&kx0f=bvz*TuIcO#1Zldf=_} zoX6Ffvo?Qq$vq>aUZeW@4fA@1X>N`??%le$sVda#W}fOfziOL17N0*UD=wM(Xzqo{ zjD>S+rZ!y(us!RfulcKcv5<9`>7lJH4kCY!s;%x^6%eoe>SkVO6L(qE@eO@jzka-P z$uM`%%+GH(Hl0yyEYLNTuwK^c{YQkmdY<<>{td^o!YmI?>E3>8)9;dt?v>e>_iETg z`HS7UC3N~<`_aXbf>~E~FMj!>OZVp0oiP`^zcCheN9=fYdF8%U2hVmdFg??$rJwt^ zxj4$=deLFIK8=Lr73(%HUdtP@ug!K=L$~_tMarEso0Avc zUOp>1Xm0m62eEexolPQse4Jb$UBvuKh%=vQm;LsA`^2QB=g*uS9uP2L`sAszryhLD zeeu<83hSKr$gcj(KyiEHcXPFZ!wh^4-0 zm3QcGw_@6(8&q8;lJ5Obe@mb|XKh7v@bxWmD}!PL|J_mCJKJGK%q`)p4Bq&ts_jB< zo9^l)a~)qQU&8uW%cJY?$_9b?al5{;TsquTP^@1w^IL`Gy=QrMO=dppd6k(j6xH%5 zLFm?RwrSVCXYG-B9qu>XDk-P=@w3S2)P;$PH*CZJ4#C)ITUpysi1& z(KVU;hhOOPef6GqKYFf`iN!vXZ@z2X3tjw0X5GEMZvXylv5Turt+H=iK5DXha)9u= zm-2U2gS$^9uN89F+vFk;WIMNJGFxEKlG0^QX4PJIn{5Br|No2V-7U5jl7;=N9(1Ly zmhEIamzSH7eaIndLu|^s52tJvu2p!jZl1l-n`?Hft?vE}%n)rfaJ*|ZO^)xO&YF*@ zwh>dV%#q;Uenxg?+QK_GSEhtjw@v=UW4~RkEp7X!?f;*Kzx!A_!_B{gbEafV?aP?b zmW|GAw>EAU`hVrd*80ahHJ|U@Evu;L*yXa^oH6%&+UAQg-ixN)ycxMfX3I2&m(Rbn zv)mPTah!ZG_x=6cIZNHxyXTm{Z}!@H@73Sq?rIlT)tqe9;E;wtJH& z#)V2sOJ3dDRyS?_cGhJo4}|U{+5R>+xE`=ym7gKms zi;cNg-`y$j=WCsGv4)aionzV6X*sFwmPgx;SuGEhTYNUdSN~C#zTWzlNP%|&F8fx^ zoaJ9VxuU}~NK|&(!o3^rG|gz)+-Y_2$YBGmlA`dng6CP5ZlC-1OzW?zXXoQIqRvQg z)V8|co1Sk{$!eOlT4|ML510JD47;|EevO{8)5Uv&=RBBZa4vlt+s{QG7D_bTVv2FF zj`e;2t?<+L@89!O=4FX!N4BzFW*16wt_s+1o$4SJYw@>?~E33cHl8)y$SHWozH(C7U=W zd&-xd4^w=XrYPBKZs%l`4g215<8S@{pYLnh^pxW2qyKH2sFPfy|MqNp`MLv2J3qZJ z>fAQ#p7>mWCM)Zoc6H&A*FG&4eqHrUTA1hG-+dEXr#c_i@h`qm{{LXEax$~+>ki9p zPY$nBn7R6jOn<9;{Epmp2lRJtdcW%2mwmHZCiHBPm|peiYsBM8*ZKDUuebYUk^F7Z z{Ehb4AAWu_Z)v#1*X)hv{T+5{`}cpAk&aT$Xb-F8p2}~x|LQvK-zVSfDgW=yJmr+e zo`h*OQ&J{wD9jDdo%iL+TJyZqSH7OxbZD{mmei*{sgF*%oBa8DQd>f-P^Zq^YinouxFnT5ST7_=i9%#+pbDx%lr?EZwZo>xa|9)!~4uy zxh##Y_4Aac&vNIJ%~F}7!|c7kZ{^H=ChgM~h6eSn($_ijbmGP0?`vG&>i>Rvto-?1 zwP_aBq5AtO_XMZEn0NOcI`U7f}7)1cHG`qc|y00E=z6OzPmtfeQBq{5#Og5@0~Synznd#{@ftt zT+fZCbyu8Qy>iCA`qR087K+5gSF{pCi~NCZ*AtB);N^yyrTKx$HFV# z{|i^T>hW35j&>=RUtd@_6|UenLodQ3IU zZAZ)0Z1vq6jGUFVIcm<{Oxp2QoWED+?8P3wz5eo#qjp+PHaz)Jdxq*R+q-wuB@Ru~ z>34c{l;fpKRYjil*C2&8OD7~A2lnULcAi}-cRKC$;HP`#;0qO-C^Aw`*Yhb|1HNafA`J4<1R0J)zN)XzhIe=@$(s<&N9apFQ`5{ zDMI<)hnkNE%y+MQUfQ#AV(Zd{6LXVzKUZb$EVes#OF5eTnwe?4rNz^rjcZCj-z@ue z@9pw-=Khl8Nn!_WS1(te{rF;7+xiV%k*ZtH$#zc>F8x>a{h~g@WA^@-+1E>dwg&Fk zT~_z5Ab*XL){+OGLRQRP=8vjv_lN^jY=?SlD6Ug^6>+yeMD!~br( ze5wXdQ@TgE!DIq%;7+jZ|6Zr{88Yunn3lH zf3n=&o$1XIt&c0WnH2rAd+(!R@vKl~x^na;W4-3n;V6I-@%`Lb>LX*?_Z z`L{jW;vbk9(;IatX0cCFF;`@S=8`{$4<~oV97}!Q^(5=!$A>FjJ{}ASxE(k_Hb?(V zLi?PhvWck{aq3z9+v{>SIBzp;FPk56?U{_dt(8c^MhTOoZ`ZV%wFTb0Dg*Rj$*z=}UOJ#Yx`>vI8 zT5tU}WxwB9GPfhv?$NK=yC-Q~)GKT86pH?}^{%PcNzUwQ|5evCTHdr;=B&QCG*@&5 zXt3jV1@R&&D z{(jD&rM@elCl4|j;GXB)ee6Zaub1apwuB`X7Yk37gpQ$vZC`jaSL4C8^DDTlt*te7 z81LY{!^XhyVQpS?e7yVWU!|8{*Z+EPr)|AaJdHPfZ?;u3S0R@czn(pRby>f?d(H2uvQ`eXn zcf~nR)ZNd-{@c24PfGrG4~^?~3&RR``kZs^3{m3qFX+;3npzk++uB{IGaAcH|1eMdbN;QS?PGb_`zG^eJc>E-c%H_BlPq=T@|=?{uzuPvs9}9u zZ{yl!@~2;IxEUUI)3$!yly&F7gosZIH~*Sjxbw-pwn=-wta^7cdEy+qyRlKBfp={- z>@tcJkZnD$CmC()B)eUDe#kc#a}ogL&mD(3B6J#qTY`k(C8GSbzau99oco}W39YsS)heEw(8>YQo*C1#d2IhL0< z@Bgp;|DUa#8R>Gi$4z$?|K;8JvFo_Qx|wu#{)~0;__a^;i?jXlb#InU+jv^|aPhBQ zhv(Z@q@<+%Iis_u((MnkJHL&T*Po;B^A;YmcohA@ddaS~Po=-|T)%u?T@ZL*O|!^7 z&%ufLd)sp7i@%Z&m0tX{zw(6esY^n^ALK)S{OQ=YX9J@%`+?u3(zAm4w-nYnU*P{_ zTa+H>nE3vHM|k#qq1P?PXRJMOG9%;dsgq}_V#B9To@u+M#inG>Zo}|dv+m!xKX1Cs zeM_%5YgWHryeT06-Ld5^>Qhf&)G{x){kwd2i?w{+{bdDi(mjEC)@hr=rRLOCKd-Ek zj{R-5UQPSYQ+XM6|BaSAntI*xqu(>c@NgRUtT?H@?#)-1+=Zg+Qedhx*A zf1z*Bq+=IOSnu(b+keGB?|7e$eL(OO>%((SSH6f?Tm4J_2RH%aU-qu*<;wSSs=@b>(}m*?)e zpw273Yv0SQmsd`Gu_9<^PH+Vb_Q?hKo2qS0;hro~=yh?ZXycl&N-o!rK3BUYDC zmV1kDUsz=LWzUbc1^u7pR&HLPv47c`C5sAKc0Ns5sI9(nMS4EwP-8 zw}N7!JKB#e+x}ZvSXV}VneV$r=5B^FB=7EY((343DdqN3|7q;Oh3EIX++C$Nahs=$ zW`a#m68rMyE48aPZNFpIP(97@ddKa;gRJYjYwq0fY~S>?^Vp#~k%ILXezs;7{nYsU z=IpWQH}$7Zx%a7QlBQR*i-YR4vez$s6YlI^()9eS;6dN+jIW)uVuU7{l`XQI|Ml~! zdyc)^bMD+$E-qSSZ+`2-8Lb5=Q#M|ioYC}YolTA4r>b8u3-8U<-Mpv%{DA|P%rs2W zCoPW1H7F}9E9ZYbZ~m$B;tiXOiu_+pTRBxYGBPkuu3ujA*YW97(|6q8U(6qFsl0m% zbGE|IY3^2Dsy5qeRU%&N>Uc%p7Y}i<%}&&CS@Tk)I$PVjyJsHn#gln~Eo=W3*UrBq zSW@agv-ZaYEfKemJ@?*y{?IsY-pSV&pH5sSRGsh7ewn?@bL!SkyZ(1|azT4r*8Pbn zoH2Fk)#7#yrRYO5YvxMCZ!NYE&q$qVyW!w{NzU!tHyM?!o_RCwWzVnQ{dT|3+Ug(L zmoY!$S#o-6+T+VxTOKK2-@Ugc?Zc79rG0bW|2pda|HpZM;V2gY9{Gy;Jm;UACYqhg z>j+u6(BE|0w!TggC9izv+X|J%xvNz6C#ALS^Sr&JulMZwHRrxuStfopKz!NiuG5^_ z>}zyCJv)|`UK)9qq4TWxy!!shUQ06^<#xRNyE}KI;)!itHGd_&Vk2UFV{1HOxF@>4 z(mt_n-T7@t_!r$fSGZq(9m~qr%X0;zts1I$_bx2^|EvDrp{1{s0>!-U{tU2IlWchZ zVDIVN-hXkr);UFj=Ztq}cU=ga(wchGYI$!< zIOwt?p6}Ou`~S6fzV&j=^ADLOQ05}VX?o1E^+aH1ib}uuvAT~d73V#h`1P^6w(PU> zc~{qT`H5N2nKQSotmTk%&;oY{-{&b!-!Hc$F8fe&^75aB`PSY>P5;H4C$QeLymakb zL1fC3({JOW_~sW_{ndScOHBTq@Z0%!IJ0gi`97_72AYgNR?n;HL~l&_mOu`Z22-a<{}_-u(^ zqMHpRS8uQGc4D3sc0Tn&KJ&fBw*$`kFX6rD>u}ls!UFd4b|c3)H^VJgAN}q8muK`i zW46twT`P9%*f-f{8Bh5&vFTU(Cv87cWcX{@lxb7LuU(lq^SJesiLWlL+W55giP=S7 z$K>TFa#tJx&petb{-0U-Ep$oA)*#n)ANgO#C7M0`(R%E$^W^0}Z?~>jI$og_7JWi} z|KG)(Q>Q+i>|gg)=U0UCTTWkHuT$llw)@H)iMn!h)}bRG7MAyV#_c@2RqCl<*qdXm zGk?0IPk*-1I!iqFSxDE})geBm%cHixU9kU!?D_hy+P2==+QNVP?e|?jbiw0#)?H@l z)cQ*)R1nSOV^^sd$;Dq&wfUy-`$6{};%aP@h?3RV5Zq1R(y@^$p~ zdL6QS8C19`%1ep)R$0qs%k!JvE0UYZfO+NaMXM|>`+b`8{vUFK>pT|I@1`98%)sJF z&y0=_Z|+F6>)UWuzxd32tp5N0zxT^pZyfKq`>*w%cT7-TTwP%5@jE|HHs#0IST!W= zJN4(?Rj0-WF{|c^XdXWHRyFADACFFn+j4hp9Q;qGX!I}mA@e(0Y2QuB z(glZ`Zr2Ir1#`XRH0zg{wCci{z3-;=ZJf!Qw061o(M@iSTYvqjx8-ubsW7wfyYq2# z&q#~^H|F>qx^d&jm5i37e^r<^o-|&xU}D*>yT7hH@cd|!yw>ovBfq(Ut*v*g<<4aa zCDEtf`!V?zhds`UHR`_WWv!TA`{(t2*0gh7k$YKrGenBFXS!Txy>!)*zF=gGcZ zcXB>l4St-Q-14!>!TtGxWpB^AO@8iJn-Qd1*%>gs^YhAEj|7r?l%A_ri+<}|%yV%5 z+5~^^>o<5dTB_!C7==%ne$mtB*tQ4#R=3sjW77HrC!B6>lDQZnb@W?9^V!d5rmbAr z=oS6`L)oF4!U=^TM}M42nSAtgyW?CRMa8FOIpVicExw*q{(tK1*}(qW=d&}Sb?5E) zl67TzY%wR-rGNjeG)^>@{5-g<^!Tf9hg|&h_&JN!4O@>Y^3UEjW9d4#jjEG1B<}M4 z_fZvnn-?rSi8&{BvUQyJvg_XyrKYV@zaho4w8Y2v?AxMmTAP^XyecY2@^ZNcx$?^~{{tlVOF$JWBi_K4!Hg5+AA8`o6V_V)N~tS?$8xSpM5 zhwIeouQuiyE%Y`FCgC)U7+Go!j>Ibff9Dl+tS-uGG|CKf&`%%geXPKTA6|Q{fEH zVLOF)RdS+NPi7Un*}E$%UkmlSSjr}Jb?Hy>K7%V-Wv)A9Zyi$ro6{D zuRk?r7jK(#fo=7v*V`n!E8MxaY@F+U<#pSySBDnb9;^y2IXbQ9^86TgTbti}qB=`Y z2O6%LCDnDwc=Zgc`JLwR;omN>iigJ?nw6Qm_Ts)J_vCa7OP$~D!SsCU>A1Y5P-K%kaZXkHKKjr$iZCU^4@3v83 zOWzs3efqnYT-mQa^HMhHHaG3#ezVaa`wi1BF+SOg&nL~%&3SW2+Kv6xB_p=y`iCxS zMl4-nddJ2+ka<{<%!_=Uyl5anz5VZ2fK-$&inP}zL)rR z1x`Az@%_v+QN_L2FAA*|GUE+h9GT@+ZooZ9Y(?Z`(LA*q(cu@iZZw&em!Fs`J#YJ= z;8m&BsuQoJdA?0A*w0(xpBEh+?fg)3qBM&+%iE&AeiE;Ka@JK`=)92cUU1w0aIQT= z_S;IoX;w~E*IDhiKAJ0YA#D2o^h>5!IXUy6UOPA8zenoSH|y8ve^&HX`>_3$*_HdZ z?%s6`R{d$uKH+cxgHOTj_E%=6^EaAVE^FRWt@Kl2U&*G6N%xQU%iC8}=&#N6X6qGT z_@j~MY|I}X9v&VR7FN%vqp!bM@xuD8Pac?c?EE@eY+FoGTkqrUBL%t)58R8TzugU9 z9jK#y^*m$9x%@CLNDuqYwhxV=Fg6>cKMv|jKQLopU;uTMLEUZ8!YJ@k3D6?1?{Cd6 zMpW8#$-EbsvOy_i(;4L%R`QSoqAU5W7NLg%vJZ!siuoYi*E~;ecYYfKCN_p;==y$ zTih`lj)$GxYV2gW`3Cdt8^`=kHHV01@6CIChR+^4 z&E*cuT7Bo<)zg{#U-iz*@h(|(BI{eKUBJI%KGmNO#0yLc^i>b3T6DR>&DUV#q0iT= znRM6c%-tNe^(?dGoQ)B05z9o{oOlwN&0vZW|oTl;#)>2mkdD>LRr z``a~q69El=*qLl!8TuzGpMCa(KNBZTe0MGH(J8U5N4`v-zc1(Bu8i59Q$NnHU2^^C za1 zZU3B~v)bJ)YI5`0#kC-(Z@b%s?SGx0 zd+H+dA)9a?Z%&TY60Vng42nCKbzXfubKbL)XVovgk3G1K^V2Em&4uD0<~9EHDf3)% zlzY9(7RPw+rp*hZ<(-#K)SLRtH0fjS&eNUS#6&N5e}3{*Irm=BRms%`C)V_7%{puP zMf*k69QB0{dUj=WHyw35y}ZnoS$Sro{^3`iS#PhsZEds@eezzuFR<3Y`p&gm=9lKZ ze=R(3&yhvx)l%tZJyYDQB9``QnW&dmd_Qkj_u%QZj=j#mA1^$(j`eT%=kC*Qwg>gB zei1C1xNwKvrAL>foWFM^Y<_b8-(`Civ-Qr^T%e>YKkK%|X6u=mf8%lu6Y+?(eOxHAk$_ z^f}a9^I1gQnpsf4c;h~~et}O0xxaJF&TJR(7S)n2EAda%VtxCMv-EGy-D6E}_h~GC zbb8(8ytIgrqY_-D^&uh;AI%qdD>z|e-9PcL4>j#BcOE9W-&B9*cJ)%r<(F-ao@-7! zD7Q?SvEat9#_Jd3|2=MgF|E)n+3d$QN0-Et501H(%?*yS=DXi&md{(0B{(VIn(IEU z-J7lm)Yx;L7A@Zwlbk=fziL*N;#v;z{S|ttzH4>-wl7IF%lZ7HcE&lmSDSDRKguaURdXQ|s&*+)OFru(m1Gl$#i`gxbhefxhLHrCdz z-tKhF($-#UThfF^+19}HzsK1VAJ5spqp2xKeYKF1)@RSP;R(;z6)n7Dr?UE`)-{ge z1tQPIL!%n@|6bj`u=Mbo%ZC>}dUM3${q%m{=#w7#uO@Ce@a3az&X2-1hNgxGul?|J zsQW)Ns+?75UUZtQhf22T!t#Aw%av>Uma(QTT5)9e#QI;aCVE@kyXtoTf|{E0y`L}V zu5kPG&+6d$BM0m)_trK{kbcyc?^b*2amD`&O@2t&QiN{yL=b-tElPMSu6L+OkCB|8Y09^;;M35I@oP>FvM2 z`!X%;^sd~vRW@hoqVGqaUFS7%Umk9<)(M^`wpk_j3g3H`6S%55Y1i@FA37^d5BDDB z40S15S$XBcLN}xNf6rJgs4mMhIDFDzP1LHuudS_CwiRFR7^g>Ow>@1Zb6s5U?&8HR zTAzQdSokI5!Y}!MPsL8f=L*^#o0y?e9Cz(sX{qbAY2TiPq;Q9>u5XCX5R__-Nu9@W zQ@JjFS6FXPkM9~T(KB;8W^^fDIX>C{`qEi8mx?uI!~Y)@oic~(NKtRi)_eBLzIiNO zbai)i%C-2fdv8qMYIyOeb<1(i`&Tc|fB87!^+k=)`BPY3%Pw8Kpr-71erb~HO2IF8HuK(gihKK+TQ}q0{TW{> zzv-;5{ur^ua{jrGe)&h;C*RuBnM`X(XjyWvnS3R#ql{u(D z{8G+ewJrCjx87oUV)k(BB|fp%swF-9D|OP`ZvQoGY`D5&dJvQc9CDtL3V5Ju0=;al=paYz4&{u zKly~l{T8$C-e)O?j@#CHuM?bb$)@&GrBvkV{FvPPM`tXVa83H3PVxJs@G!TGE3YHh zwOGD-Bw@F0$E5eqBXtH#a)raDwQ7H#r@hsVl0BUn*_iiouJxqH3k_;@ZhjYKHuT%ryyfVx8&^&>zJ4}M z(3rQ-HG9im)mOJtpZnjCe*ZXZyK3~RV!yREhqm4GGwqOYZBO1R=_0lT7A;lJLV{*ZZZnRcE~1%I0)#eSdLpuAAzFYfG$N+-}`DGa@2N;_u7F z_5Yq|fA6&I_`?IP8>Zb3*ld2i%iOdot+}96Huipe4%dg3%al}8Z@>PzHD^KKt}D|E zlb6`l_3W~oy6^;XJZ zV>PMCJ`492-fh|Lt@M(EckA4gTYI?VWZw0c{C~B1`HMe07M*+h_T`H7lhV`kP9HiN z`n6A_<;K#Gyu{eU&opdrYy2|Z-t(Y#t?jJxYuP;edzN=Dw_Uq9{rma-Yn!&|eO&zd zb?862t8aN{w*K5)ZN=^NOgd;S&zFmAYW)Ac&d;yT>A14$a_Gqz=YtWUb{Gn~j3oY%V| z;?mujD(2GC#?FTw{&0O?ySl(f_Jf(3$=1qOVu1w(ng8D%__0ZBhBwonD|eUuD+5(0 z|2vwuzI^!bVWt-E+_64pY)=-oCGtoPJbr-Y0&`_VDEJpofNUXK1I$f8O#l z`^j;hQ%12WkJg;=>*3+=KO0b%aXV#E-%?w??-Nc|K2}~jWAAy(@Py++pEIS|WenRL z=g2s-Dy+M7en}AD>#StU_cIPZE_`|Wb;lqCm1N4O7 z8168-`cttiEK5j#;ciA)B?D~)K_cY;@3Z-kb3U?g4ku(HdubiGW`EzhJG+tIOmIp$*SklaJ_Rj_ubKls_w>%4wX_P;FKNTwMP2KfpHx(p%-FEwf7+DL1J+g+p~>zRNBAs^_8kk%y0ZMWw|G8N zrS$6uvhM@j+Kxx&7wuT(chlXbk>ytKgXM3`tmgWuO@4l#wMuR;7id33#hNWCw`aZJ zcoFyXe`vq%yS~rYWp7=wD}Gzew|r&j{jz>fRY4AyP322xhG|ZD^}a6MYiYpB`>$(t z{wdx2|Hya4`8PrbZA~9Me`)qbV5j2`y}thb{f8NrHEs2pdC%gXwrIc>D>LWEcixCA z?%;hiiGhJ3ui87@+uK{i_NBG?w38_>uCBLr*XZrjliqtRPfPmo9A2U0|GijK9_H^o zBc0j|nOCfzczfSk$tfNx@x`)FulZT(5Y-V>; zdlJ{kMOT)vxM$mnteWXxh(6#KDX`vzJ7lvlGXoDIQ`Jh z4VTX|PQQ3PR4V07`0}?0WYwi?|9G80b?r&Fy-o3I4L_5Q*^Zz06wkXk#ZRUQ61MhT zx6eI)yZ_JA&RqeT2=p!3A`ZMVy2)x6)OmQ&2KTq$kW%hfkFapm7`&#Mbm`{o$Q`%}n#!%}3-QOWq%BdvEDqH2;?U<`Y-e=G#WR zo0}+GxZ?25k3Y_QGCRa3b~<6Y$sLGSdzS_mH z_v$2Pu1=50n5dW;>XXF3v&2V>EKAUxd|}(?*Jrw?9&6n1_y19;;ckjokEf!y~`p)NKz1IQD ztY<_WODj_OWc=(GQ&`i|x4|!6cg--(x%u(YK8L<*uEjgVS8q;P6m0kXP4${9lZwhV zsGiZDou04%My&fMyL!Y={}wT>ROfm9V@l6cRRjN$5<~uaDLIwn2VtoLz2!tH0-a}vf4k*wDEYtJC6IY zRjSWh%9XeMu`}>rUU3>Cw`TxJn>vyE4yuQDsV6StnS;ULqAGXaayM6rSSCKEDTkK?hF0bD@ z>&D&%5Z&Q<+^hnHf=l1Il-^&H24Ww z%dZ)^>n7@lJe+gZH?Z@}=a>X+^Q$j|(!Bn2S3r%#VJ0ynFo_-JC-4 zLUGYU=W6EnlpQPDdssgI_3YWRQ_FN;uWOsLJ@i3Z$?*$M_U&^$KJA^7w#MAbMo!-Q z_U0>JrL59B_h;(K&(qHbOPx>``smX6{It5-_x&d4=D3@0Il6gnYM=kS+icsC_vf@~ zTO4QK&U@zUox{gp@OAI$~1!P^@Pstr`smfBdF z{r>u5>gkl~BVDVSwwCMen{LGE`0(Q2Gw%hjxqP^Fe{tKHwlbL?dU?s4Z@y@|{%W_w z`NiP}bL+M9tQYt1y1!X(mgNOgzmsvxB5flSPP86+apu>`_0a_;pXY7;-?NQh;r8o~ zMxSNVK1CXD?f-Xs{o<;$(xTg1Wpx>;(@lH7^1RsGESb07$Jsk$c|`TS`TtgxGz85T zdJ*}LYKD*w>blfuti*Ipu;lB3Dd*{`Yb*iVu=W5N=lbaE=uHy3Ypwp>FtX&nK zd{=6w810N%`rxg+T=MMo;q1S6@tyN!vuItg#@;DwuZ`xgbWi@6Y!CW%}FyD$P^bsiRYu)jUOha+GO}+Vs8JMKfPT z?G!DxW&L=QdD3aE75le6baj0?J=SHaQ(xBN-wvFs_RLwmMYCcG*VCg@C!P#_zhZyh z@6`($#T(p!5LS#PjTJP;uR{3_MKYtsB^8@obszS z*UWm;?P^w~Ka;$>Sh{}M)*m}tkM&IOIKAcX>$P`p79~%Z?s-G#Wk()jyRVtL&~md-Soe1Cthb^5shhR+4+zf}%=&(@{_oN{mzUS{Oh4UQ``iD0 zWJ|bQ=J8K6m|rdo)p$O0m-ewotAF$FH~J(M@$mI4uXW#QCAy!gO+6R7r%I$-@3m#N zg58?1B@fMh9dU8l@$&BGQ|oelKG)ZMpXdAeQfJ7XXqn9P4}T(4sw$(hUS%uoT5_px z%Av4BYPs7kyjeHzp7;HUr|*6Ci`V0uZ*LltH*3x5LTBHtA7@{Q<92hmJjL7)yLs=* zgvtKz?P?OF;*L#=k^VBdI6C;uMd{QJUnYj8u)YeMpI^Sb^|)JwTG-XVt*fHE`Ohu! zd^+WlhCYA#?&($A<97PL@d`OJ@zJC&Piym(?^zq1_3ZuU<<}GF|(`=lAg=t~+e^rHh8#j(Gb2&p+GQE0zY&EXo(k&(F)u5(=wPX7n@kd#ysbbNldwp|1`mVAM zpKq#KX*Q|iP%q;f(ctHoKKjm-ieUh?O3&`-4U+z0QT*a;daB-S!+lf!=WU;Ro$cO9 znJVGZay@IC#VgBqZM9R~u}nvMK}qZO>yzfr`)*}!yP-iN>~q@Vzn25TpH7+ZYJR)# zWLe)okM`Gp3Cu7I-EO_u_{qKW`ijJ)NAqu%tl49yb~E??gT?InzBzxAN|+b5bN{UW z^LTCEsg>JWTKV(-o;z^ih~~ng%2cI`I*E^?1o=;f>M?FzK0SF-V4V5u?Yh_4Z-z}? zZ>uP$tt+vV)AZ8Oh~*-yB0P0B^PbJx#iejYZvDZ>LCdcnJ2dae1lQ*pO-ug#@i}n+ z#HPxQ>?MnT&)BK>aPMoT+~qD>LLASu_RRm4ws~uw$eQofcBcI&&UEo_F*ERRzTBc& zsn}VYp&#}lz5ESV=bo8O_IInUZaO;i)HWWS7mEa~*XG$~-g0vfp8ToV>D2KhdwgqZ zO5O(K&skl3-fDim(iPWjOMLh7^>nOIEwo6^ta^E4cK1`YuOF^FRolC)X6u_jZ@y$0 zANyUIaCYmxWhwSS|L5lfaoX4^TOP65IQ2%fpygRh$^LUIF7O+h3pFy>)tY&!_S3+VIBcIdgNozdv!iVj3cF`_ti?H*&Tc=82uO zYO<{l@%bHf@8Z5i-=}WW{mBALPHz)z{iv6 z#~SU|HHWSyBihcSp6v5@n^e3kIqu1ucITVQMZSK^$UMJz!<>igbI&jGn(+BXEaQ$v z$AmwAJn(vr!TAX-mo$F{<}2uJ-nU3&_m=eJb!RjlolRXLe9QRJV-B7-ZMP1l?2F70 zE{p9`Q{pKMdAWP{=FMAIGM-#~y=C9@ZsT){6Y9U2JhK0J`R)0-^5f@D{yX>o*LHh5 zo~UJ)i-jj;b>1+YcZTPD&Wwv*`yOYeh^9U%Eeg8uMNRv@`GlTdA@Ri|e;-I=v*gWThrQIp*ZZcFZc99lAS+oFGgsu>GcFVhx?4>UJ7|98ujW&TXb z)K8Bbzc=o>{g?m$&-e9`rhQZQnO^-Se0f1n&zU)MxDL%KyLsVf*Yd-~$@72o^sKq_ z$ZX1sZ#8y*|Np)Je`N{#?t;Gab{F?e3ch4^uvLcbfmy-r`+c{kEVnM4#y|IRK(~>3 zlyL3ym2a19J1XJ*sax~S-&+s;%5Uk&@AFta+eP}i%WS)?XPw?3NQ+JD$X*AR~_7Us>jxbAMhDf4-X+3gd$JJN;r z?mB2a*-ymU)|~T|6YH#uT&YRc{x3{Ni>)zY8w0gzkR5^E> z8*5IU$(wcKw_bSig2m-EZ8v7kvv5)seZI8(%&VwNTRBdr#}$6fXx?~>WAE{8lWlYw zSN#v~JNw#aV#j_%|5>wNcNl%oh+SMRy6oDQb=mn}Pu!F~oiY7Z#qI}_=6zkc@6DA> zu}^;ToFjTytxUH-#b*5L;y@zklAG^K( z)a#kqXTEInd~vxpMniO_W1p$h+bzd>f9|w&@?Wt&((qx_gW|0vt4t1F-JVjjPV>&` zZ5!%q>zWKqZixMOFts}6^|xCUSzf<(g-vb=d7Zv3v1RAZHkaE69!;$E5|;9s8} zH9cKyJ2&`7ij7nGSBBP0AvgEd-&}a>UB1RTrHP!Dw%rlSGq%~7Xl%@`-D-Q`7Kin; z`e(+bMlua=ZM=5^?p7F&v0G~w3@k+-}l|^+p~}Cl*o+lo$0dwlIg0Q zuT-?ZT)4G*T1iVS#?iv3Rgy?;Nm1^hhv+Bwru_V}i?K`}SE+HXeRH}J9jR~&v= zO7xWFjtqCTnJYE3*XVnlUXv0Nd&@W~a6#+0BFPtfH+kx3+_ZSI?U-cb@hSOv0w4L( zGT2g!Uay*9Hha=6|9uvs`<1WpzfEe@z7d|`lAX+3x;KZ@_B!L)_gl2&mSmqR^PV*6 zxBj-Y@}*`vpF*VcG`A)O{I2&s&GK@FXYXe7t(yw9s8M?%NHXUt*OO}+0*y+5UO!7uvguFcA8BPYf$C~{QaWG@@KYf zxtgUd-6Xa29H953yjPr9tH6>-tg*B8BzFz#%6(b$R$IF zv#L)ncdLqAl(a)7gnxVZ(doRaO_#6zF`>`ZvVP;u(?YjxmgV@cXfbSWy!|ijdfw$@ zuRa+53^{jo;?c?LC+C({sGNNhH+$Q{i9J`B9(nTpU+AZ`xnEVSU!8mO;@)1x-=48q z_wHT$bZGbDXB*VCk{+L)#&>^X*q14e(UEt4t~3@O`c2Q4y>t496a&Z^bt2nqnU5Z1OARGJEif`LG~7Or`vBK!2Jk5dph+4w(8wb*1D&lLa- z5$)i`zAyq|6tWf~Z3k%qEy&nT0|zrO;Pwb8^q66mGB7Z}JcuHWJ@mFi$La`c0qvgv zc@QHQF>E0m@+ew}b}$V>l|V889TLIR$N=$nZ9v}anKKz7;cTa|{p`7OO`wxU@Ozi~ z@pkaIERECdpZ{;~{tTB2muLG>|L5;o+uHM)m%sT6Pt{o6wcw5QB885oCLOKa3JVso zOe}3ktlw{}k~?Xcr_XFP!}HIds2sX8vwH5GneEjx8B?S;@!n)(XvlHirg)oyVM6W+ zvlM9thE2RT+j5v0FlD!$pPhR#W6Sl|3wJXgFmF0nQF70Do9%}jYfDQ@D=RBDh972U z&Q+Y)#y&51@x>MF3?FnCewN$xwlQ6rfkEN+gj@!&Rg4S_o8HEs+vc}CSVQE~&l*Ms zhJ6W}g}=_vzvHxR@66n{WxxOY*~7)a5Z~;zw5Y7?TGrMHx$jSH%Q5?X%#MknK|fM& z`tH4ZUAOJkz8$nuz^{R)9RW(rq~=?$TVME zmchi>li4EW_U=u(bN!5YoPTFCd?;*N9C>HY<}(Ec%5M8C|1W+zed5=7Zv*!5u&=%K z`BU!XRWkQ?pXWP1`R2EsZ1oRb9S)B=RyNb@vh0I|#`9T5GeJK3aI!h~$hP%GGf!vD z_MW%DYu(E&rQ6i6TISzA{PFeCUw;qI(976$*1eC9pV|HA^R)+GP>!q$U9wHxb5GblG599UuKKn^m!Wlwsvi*VOHb=jndM&A8&2_=Fwgx z`2T%F&hJl~d++7H{{CC%z}~OzlR1OEPSpSDPq4lx>7(Iz?D5B(PZJI`&OY{d*@qn) z{f(art+}mrCc{YXTV&qF3GYiyQnK%-lw4xnc`YHNd+D=;#pcT{Ud@r7qOV*hH6hJp z`Q&q*&WrDOZJNBh;=z(LJn6zMA)McD^~hfh^p`6N{hWPP?mSz~gxFV;nUUw$r zjz?R+-m5F$F0PrSD1T{l)sLv3_j~hi&hyinknO8>_SLM5sn>EM4o%4o-ghSFvVL}b zZt1(1H{&EO<)1Wvd(=+y!}*Kz8T%}MSX^m+@z*Tn_V3NT-#Fgt*YNP)k-jb8Z}oD) z?G<+eq+-N-1HZp=Ne^1-;vF=1cSx>kbK1_NT3?l$U7^vD>r-Oi-zxht`Rd6PqMvSj z3li;O<~qJ1v-GII1O2SD(^I2HeYGfQ61bl5drXP&(Lj&H$d-+le}EbZ5;tos=;lTVi`t^6_3d#{#Q z_O>5a>;Ju5zWkT$|9gGU_n76ReM^1By75?L=RjK+kZvXXF{0^{J&Un-u&ix^IC>UMtv#cyUtB(@9+8; zb@gD7?V9-Fbg8vp&gJ(nz37zXz3`4z$IcL@iJBAqcZN@!`*KP7(FFdtc`tdYuW#KG zxvnpKw@K5?ZC!1y3qStIvXK3D<6y~=mNP}2KMm%8JF(=KkCjTzt{t;|a@KkFSSQZ+ z-I~LH|Bj5Nn8`;cC+*<&^+oSWXP&IBd1H3^tNYe-JL8lry_Sa-_kU&InYR7D#?tTG zON;yK%qkYw&CWV1SNG3m;ZmcOTO75Dm!IR;J-zB|!j+{}T1H1VHBPlmTwx-?|Lbw4 zc0xpqsoeJV;Hr=2bHAN0yDq-uTI9?RXG=n?zgO!X`u{h4V`a^&u=8ib=1+I=F1Ooy zL~ftgE^`&P>o-6CJGICo-N?4`)0JJB!ZvlAL_J0HyPp19(0`ckUH`dvC9#ro4dA=%U z{>?8@vt8Gh&MRa4o0o6!GA7D}Y3lzuzf{f3Pu#IG5h~td^;W!h^(F_6Ez35D+Q=!X&7c@iijbmc7WDCRm)SWNH|>)0THc!!`ed7N?$kNb zMXjOgwN~jL=dsLXyINOwLd+-oQ-Fp-w5iC=%&$kZ%p>__!?yOu*G85^q#S21GkNKv zqcri<{UryMc3)PT+j4oszeQY`8u6CfG*hiE-+H9~`dmOsdT{Ps-6+nblWr~TwJ=^g zFE1}b_F(Sc{C-uj=gW@1v_74-xNiE*oT49n^UbSty5m?*Z1bO%yEUpek2!(iU8mn! z&HkdgqeU{kKfdb(Ewqy<>Ymzm=jKXBrLA(u?waj9C9E$eB|d%b$r;&>dHddeGm5*r z`2GAJ>#|I;5_f2;-&}KEBO=JAB&}ZKj)* zUu<3-KDX0NcacCw(#Z)v3ZKP|cFzhuou{)eU1)8Df6}{jf3fD1OWYLr?-(o&N=S?= zESh;YCN98IxiPo*NJYS|&PC@ zvm)oaY}g`tcKYeo4aXl}Sby@X<&w?X&X8bxm9uYm+NtMm} z1)fJe>tdI2TBsMiGWPx)bv~t&pFh9&_RIhCB$t`88!X;EQ0}vy_U^9Rw!QYZ-@SX6 zQNNY(UHi+DcZdA`)_t0$Cn{OCs{P$r+wI98PcGj1vvTRx@O4{jcI}j}n>pEY`rest ziv`T`erwGQR810Jn;&PM@xWa=bL;K7dDA6va+*^@4=h)nuy)$oYU8AkKzwZCyThrHue+p}L*s*D$`OTo# zrt5Efro7gP=C(FT`nf5|SGwb=ezAL3dbd{l?bPkdPwlPB^4E%*kg=_M`&y?PyWjfW z*{Zj<>~rQyXLFr^(-~%qWxji;CN1<>QOuUi9(VoUnjY1_cd4~(CqH#LZG6V59_+Zk zxIaE+v1^Xyvzrm&dVhcY6~0=xIhH#&d)hPBL#4qcG8;2fm=3;LrXQ9ZDO37EFk@El zrrvY6Pi*_1E?wToxWj(gVONp=$-B+xgeCV`?%Wyjy6`%q*{QOv5!C@pqEG&iczr>- z#QE8+m0>rUBir8oz4-h`&Ff2V7{80(bw0Ld&exQv5@*SH#?T|adI5s}0=Ii#uH3%- zx3${UO%aRuo~?@gw~Oaptb-KaIi|_06Sk$ki>&LovT&*Fx{G&${>Ag{-ST+*nKP%1 z*Kg^myt&CQ{n|eJQwI9m@6=x0Am07r=A)PU&Mpz^R6Uol?(Ei_Z?6N+#vHuKEK~HM zaK(3p+jbhaGjhCtujc$<`0s_K2+P+~S0n!|x|UI>KTYcE>7;cP#qOS;7cs;?vYEYm z*V^Dl^KHhTUoAG*u2^f)nrd1u_3`c7`DyyIeYXESW)_uy|I_NJe||oU)~?x`x_(;a zZJ~Xs*LPlS$bbLAr26`jJ2iWs++M}h%J{+j>T8iKlXqD~ z_LrL3daGuHP5%G!yO3`l)1R&C_S-g9O_t}{WWthV_V3-Ze;4ltEWdl0 znPeSj`mo*nHZN!K>s+s;LVG8;^fNO2(Av~{Ol8NkC$=};g0~mOF)=XgtJoOPb1e6d z?er7d_Mh9PSspA{t0Ta`P$T;ydHX$!Ugg{OCgn0Pd*?#K$LF#$Fz~xA z4O)2GXW!i%?dhlI>)mE#cyQlcdD`pO*}LAqy?xf~7OP0UN!4y9hKBX`-_-aui~Txx zDc}4yM{TLfz8zu=4-Wpg^4_FY_9h#s!N|0RyU^L=jVqjok_RRXlz#ul&)5S5Q;?~={xBFwh zCLZ|sM_1R3?_hTIbu%Fq2StfJr~h8MmA8=p;EdQL=T)YS3%nY%w%y1G4~P+be9EmX zrvFMrk<`v73!~QG_xR1w`|Coj=9c$cSFH+M?X_aR@pGg7#WQct-233}-18UR&)qam zKNoW&W8bg2_vih*Hn+T1oT1@g?dfO+h6VE(7`_NIG}JLMT<~XL_{GV<@RtQy^xD+- zcWcjcyT{oSetI&~xL&kn>S28u&S-Y46T$xWn|o$|34T(MZK$*M@yBB?b8f$~ecW8k z&0Wl%_ip#K|HUib@06SO-ze@)TlFo5FJBJqV^2?ier}%a_h+;7ef{=|v`qc*__utG zK;Em*3jX$=&)h72-X~`pwqG-c$GlaxZO!~k5?a&V&7aHuY~A*J`z7;#o$3>{`+v3e zr*@?xL(Y?l%LV-9=UII{vAF-}?fO5rvK6cD)&Fn)=f3cgU)59h`k?ziK55(U+NuA! ze_rjoPft&Ozx)4h{+{`_46o!fzg(W5@W<1haYK^6jHOW9EUk}I+|IwY|LM8o<HVS|?%Y75UQ!Og$^Zu#O| zUYX7(qQBwe&o9Qdt3Ph|#hG9{cfa+_x%;zi?tZ%#ov;7?PppOCvw+2`+z249>kd3!1Ury8}2&n_>Q3D->R$yo2FpIlUa`QO~lIUhgkoGt6mi!HN% zn(tBZ@b3MYx9ShRE56aaIJEEn*H(rNA6rigx4gD#JyrR3>-EQP`|ZB{SQ%Vj`DyQW zw!L+Zs)xcR1r*vZy(sK=QdE1Y?PcNOkFkd?M5X@G{PX+T?fmxHhxi^IH`%Q9&Gtt? z#ktbN-wl6{ESu=Z{N0X0fK&V=&-F^K#X1jN;%0mhX}MhX@VJ2g{rZIX`RtM1uhWmE zKe}}C!PmD(O+FZ0)tqZTZ(YmN{JMXiPyGn4`nPUI=DuU~^~c%7W1W&34(c+rWr=9T zJb!uqey#Z#G5$kd7P-%VN28XM4)%=5B_*`{#4d_bsz%-a_U7*H>htpgyN@PqjL>o3 z*}}tNxL`h8_wtDoW%pN~7Gp@r=Jq)JedAoS#OZ_+?FTxB6!ocTmNkLv>;yX}L-nMzZ*y+=U?kw!R?ti-0?iVLR#JeAt7yMl~pMl|T z$gBPj$!1blXXV`qdOel7`1)tYHLo|bZw50|a3e&&AqTj#v`qU>$|OICZB|7BrVlW8A%&AIQ(y&%~IuZ#|r zTo3viqQ7v@v_(t5rD%Q6+8&jDn}-~l2Q3Lgnw(?-z$ALxx z3@?`7TNZthrQo_eJHwaB@ADZMzFgjLV{dx@eF+8ymBzYP*XQl6c6TfLv6QhP(agwb zQ~7(@UzrRK|8kwQ%-R^CBi5a&F?|A~?ITZnMg|@qdq##A>ZtXrlwY;37&sB!>aLSo zFnhz>1n=sHl2sz%jCLKzgEuw9&XRrP@|h5FwRqmSqQJbKi+($C?{`8WUFCO=iPz4qfw z&EKhJc`OWnm&{+K>_4|6D*1lOT%Dg052s#_uXyanaKZoAN*fR3|K}=-!{^Rlvu=C% zq1Z`Jx~|_oesWsL`M;ifeNvXQUhaE2M|q7+($jr&my7US+L!{G~RC#`dS zZs+ayaLyH}R4BL4%^Om{^DLq$L&-xiE{W@z$ zzTLNA*{!F_SFrg$4(^rHzPEpKT&3<)ft~t@GbHr~D${T;tBU##I-&br$7bjDN^zpz}9GGO;Uv?fT=^`fkY~H}gF6 zb;TODu3Z0r$`hyUoVQNed|YEGl|ChZ?^YY@-DY){Zx-9s&Nw9y@^jzY{cLk|dPPI| z<#IKjX@$#NI$Z%gmC(O}3qRo8XAy~{}}kJmEf{qkQoLQ5Z8t|T6T-Wr4F8ATNHIu{!6Q8;Ln^@rIr8kO4jUu&oB4+??HwI z^Ro`SUS9j>PVDNd28T-aY`szX??;lM)l|8Z#JpvpJBZ@>OK^ZONb+t~lV|NnmF@2$;n;Mb!0Vf*Lv z$=FnUeRcKm`hB-7{+XEl^wh8ac69%r-{S3$L>UtHUi4pm$$xv^?=qVoB~MRH-MI1Y z*E%WNTT-A;o9uQzcN$*iden8TkgN-$D@?T4}zD@FO$uETk|pI z-6{Y7Z(slab^prr_1n$=9n{bN^Xl;>E`|;F-dyt6ezW}c_Wqb%B`-fcJ-s-2_v>c= zuXVQypTyjr+Q0ADulfJKc~#dwyu9A-|KFU)z5Vz4!WkM$-R;*N`nfxOeyv`Q<=&6S zq`w|q?q&bh=9ZLYkzV1i)Bpdpx8C}7=>FgH)9v-vGBCV8=l6HZr#i05^Xsa9eYyHA zNU~RAz5V$)Lj$jF&4Smq)@%`7Ye-Ac97fyexAA9Rt^JazvZDvMKf4`r0+y8XI z>&?rz@4q7TQ;}gqVD9`~Tb}m&zg~Xu*GdaRb1SQB*MD4o5n;dlCqo0Ti@omV`A*Vz zH>JLw^lOe9E5nQB3tud^d*1(Bl^IlSURyLDT+V)x=4ANgY5(=M|6}9NpN)V2bz=gR z$bY|Ge$slBJGf4k(ZT-Za=G2D!euXw{-67??XU6Y=jz(G#Xsu`zd!SQ_NU^S-;*D% z>J*55%Pg^jiQ(^-pT9Lbm)P`Qa`MtzWx}l`J<;ot=8~YY^)^!v^?v@GS=73F$#+(U zFPGKcEq`@$m(A==j7v+FWUktko^Jbc?dQqDYV(*I>ZGRCd7a-kRjq&f;T5~~?opL2 z_PYM~ck)6=-Mn=+8lj$g3=a0Wr+)e$o${efXsiG2 zt;QO&wC0Hh+0FfP$j8oom6e9**~Lr@UnalqXJ+`7`MIY4Lqz?3d7Edyn?e2r<=L0Z zpZ3`Iel!1PlJ$oZTv4f;fkW|3JrgM4&d9Tas5~$GUiIr$QG4IVYOZs7SM-Eo!TcWk zufeWILr=u^$$&K8y5%n_8m_XwZnGT2g863N_M+DX{KGft^PN-H{CR8Iw@ES4dp<8c z^z!Gv7gA4uE(p0{zn80WBNM}mm>*!XXseZ`sY?98Ba!~h~rOV&%h&Hs~m<%ck+PM_kRvn%!VHPxB_SwKl| zrad2sdI<{r+?G127rVo147ouHLw-+s5XW{)lHr2??61Ebzg6AaR#6xF@z1Qsztf*t z+lQ62F?_ik&}ZN3bZXx`RXg+Pb+U1}TQtEMoNxIHPt9L{dfJ=aEt4Ovc#-{P(OgD` zzb0$`UXd*B+V5mBEhSWaIXI9^p8OS=yU=@?mFaoj^P5jTDFn42G(8u6d%5f6n=dgn z|JHp@HhaEui!sB3`7!pw3>W+lfBJhc`EPCghZ*nr*+8j*0Ysp*V;3MbYcKeNg8?V; zixXrc7UBgcOuzwyo%qWF3MQPy5>PW48_`k+$^*EGOSm13)2$E*Pz&)F9s;{R7#!@u zO?qr@g^J+}+%J>wOE5Ut<20C4Z2&^4E)(n|oHn0@`U;$Gun{=DOMF@~Up!w2(kA~R z%y3}UMaZxis9T5BdIxp(wBMGcbI)?f?C5`Tc#hzrXRk7K*E` zU_YcWC7zXG!Tq|b9}nBV^L!V&*I1x*emxU|frI^9xp%JijG)}l$dG;0UszZ;`LB-u z-txD%s{Oy-yYzfhS9?^i>K`@GKebu^cF4~3U3ZGl+iu>xIsKM*1gHHgb%unQf49{C{}+36QrX#c zv6&94(TAc=O#E@|*R&V+x(j)ymaq68-0!@Ue^11nn48OE!>1m8cHY7+D|P4Zce~SX zdq;F`Z!ZT0{pnZBgBE<@Sr8lhEA!-BX{}W|=X*&`eHO6MU-QZ>^Xc#It=xaCWz~_% zbxaJ??)y*G@svur`F9GR;MzU&A6;CwW4@O4_q+bR-E~Y1Y_FHM%T;BhZ?Y+TbnDU4 zWb4gOBRVDs`#zb8ntoTKB4M#ifl_=1X>~ z+lS}nS7m^@prQ7*KOQt&oBjG!A(Yau|NY)WSy=KtFzf5(eYL;c+Nz<(zgWKe-LBX7 zs^81rs^D60yNCJV`VW7!7#RM33!dRn`+RP>-G>9rzuRERE$9BeyX%=4F67(i-nSEC rN-BvE|H#6?bI1Q46GKDeAA2Kf)6jJiTXr!pFfe$!`njxgN@xNAMjW|y literal 7998 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 g1FVdQ&MBb@03V7T^8f$< diff --git a/doc/images/qtcreator-cmake-clean-steps.png b/doc/images/qtcreator-cmake-clean-steps.png index 9ecfbc74f1196946ace91b87f57528cdee746755..88be99d715a813ed2c9413a27379a0de30fb78b0 100644 GIT binary patch literal 6320 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 literal 8315 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 Str!>>7(8A5T-G@yGywn+9J8+g diff --git a/doc/images/qtcreator-cmakeexecutable.png b/doc/images/qtcreator-cmakeexecutable.png index a0475e0c042463e7c286ad071e9624ba68d8c83b..b98085b4e0d701ff2cfc623d020b223e6c66187d 100644 GIT binary patch literal 13050 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 Rrva3gJYD@<);T3K0RVItM_K>? literal 11541 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

4CR{slhgbLh0aR-HAW{yw$kg6(1Z| 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%0A}V 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 + \uicontrol {Clear CMake Configuration}, and then + select \uicontrol Build > \uicontrol {Rescan Project}. + //! [cmake build configuration] @@ -65,7 +69,7 @@ \section2 CMake Build Steps \QC builds CMake projects by running \c {cmake . --build}, which then runs - run whatever is needed based on how the project was configured: \c make, + whatever is needed based on how the project was configured: \c make, \c mingw32-make, \c nmake, or \c ninja, for example. You can add arguments and targets for the build command in diff --git a/doc/src/cmake/creator-projects-cmake.qdoc b/doc/src/cmake/creator-projects-cmake.qdoc index 585031ded78..a6d0ad66710 100644 --- a/doc/src/cmake/creator-projects-cmake.qdoc +++ b/doc/src/cmake/creator-projects-cmake.qdoc @@ -61,6 +61,10 @@ provide less information to the code model, which will then fail to resolve includes and defines. + For CMake version 3.14, or later, \QC supports the + \l {https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html} + {file-based API}. + To specify paths to CMake executables: \list 1 @@ -99,9 +103,14 @@ \section1 Editing CMake Configuration Files To open a CMakeLists.txt file for editing, right-click it in the - \uicontrol Projects view and select \uicontrol {Open with} > + \uicontrol Projects view and select \uicontrol {Open With} > \uicontrol {CMake Editor}. + You can also use the \c cmo filter in the \l {Searching with the Locator} + {locator} to open the CMakeLists.txt file for the current run configuration + in the editor. This is the same build target as when you select + \uicontrol Build > \uicontrol {Build for Run Configuration}. + The following features are supported: \list diff --git a/doc/src/editors/creator-locator.qdoc b/doc/src/editors/creator-locator.qdoc index e7c048f6d2f..cd99ab139b2 100644 --- a/doc/src/editors/creator-locator.qdoc +++ b/doc/src/editors/creator-locator.qdoc @@ -150,6 +150,11 @@ \if defined(qtcreator) \li Running external tools (\c x) + \li Using CMake to build the project for the current run configuration + (\c {cm}). For more information, see \l {Setting up CMake}. + \li Opening the CMakeLists.txt file for the current run configuration in + the editor (\c {cmo}). This is the same build target as when you + select \uicontrol Build > \uicontrol {Build for Run Configuration}. \endif \endlist diff --git a/doc/src/projects/creator-only/creator-projects-building.qdoc b/doc/src/projects/creator-only/creator-projects-building.qdoc index c87557dc699..86b8b617489 100644 --- a/doc/src/projects/creator-only/creator-projects-building.qdoc +++ b/doc/src/projects/creator-only/creator-projects-building.qdoc @@ -84,16 +84,18 @@ To quickly check the compile output for changes that you made in one file or subproject, you can use the \uicontrol Build menu commands to build a file or - subproject. + subproject. The available build menu commands depend on the build system + you selected for the project: CMake, qmake, or Qbs. - To build the executable that corresponds to the selected run configuration, - select \uicontrol Build > \uicontrol {Build for Run Configuration}. + Select \uicontrol Build > \uicontrol {Build for Run Configuration} to + build the executable that corresponds to the selected run configuration. + You can also use the \c cm filter in the \l {Searching with the Locator} + {locator}. To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or \uicontrol {Clean Project}. To clean the build directory and then build the project, select \uicontrol Build > \uicontrol {Rebuild All} or - \uicontrol {Rebuild Project}. If you use qmake, rebuilding also runs qmake - to generate new Makefiles between cleaning and building. + \uicontrol {Rebuild Project}. To build and clean projects without dependencies, select the \uicontrol {Build Without Dependencies}, @@ -101,11 +103,22 @@ \uicontrol {Clean Without Dependencies} options in the context menu in the \uicontrol Projects view. - \section1 Additional qmake Commands + To run qmake or CMake to regenerate build system files, select + \uicontrol Build > \uicontrol {Run qmake} or \uicontrol {Run CMake}. - To run qmake to generate new Makefiles, select \uicontrol Build > - \uicontrol qmake. To prevent failures on incremental builds, it might make - sense to always run qmake before building, even though it means that + \section2 Building with CMake + + \QC automatically runs CMake when you make changes to \c {CMakeLists.txt} + files. To disable this feature, select \uicontrol Tools > + \uicontrol Options > \uicontrol Kits > \uicontrol CMake > + \uicontrol {Autorun CMake}. + + For more information, see \l {Setting Up CMake}. + + \section2 Building with qmake + + To prevent failures on incremental builds, it might make sense + to always run qmake before building, even though it means that building will take more time. To enable this option, select \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake > \uicontrol {Run qmake on every build}. From 4bf0105bacb5e948e1539809507e252d564d7e8f Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Wed, 13 Nov 2019 12:09:01 +0100 Subject: [PATCH 21/37] QmlDesigner Binding Editor structure rework Separated Binding Editor into 3 files. Cleaned up includes. Change-Id: I84d06148b09cfc0df7db0f5a3a99e0f92997b586 Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/CMakeLists.txt | 2 + .../bindingeditor/bindingeditor.cpp | 377 +----------------- .../components/bindingeditor/bindingeditor.h | 111 +----- .../bindingeditor/bindingeditor.pri | 4 + .../bindingeditor/bindingeditordialog.cpp | 258 ++++++++++++ .../bindingeditor/bindingeditordialog.h | 99 +++++ .../bindingeditor/bindingeditorwidget.cpp | 160 ++++++++ .../bindingeditor/bindingeditorwidget.h | 104 +++++ src/plugins/qmldesigner/qmldesignerplugin.qbs | 4 + 9 files changed, 637 insertions(+), 482 deletions(-) create mode 100644 src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp create mode 100644 src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h create mode 100644 src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp create mode 100644 src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 9d291c7bad2..5689455b63b 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -524,6 +524,8 @@ extend_qtc_plugin(QmlDesigner extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/bindingeditor SOURCES bindingeditor.cpp bindingeditor.h + bindingeditordialog.cpp bindingeditordialog.h + bindingeditorwidget.cpp bindingeditorwidget.h ) extend_qtc_plugin(QmlDesigner diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp index e56822b2a3b..a6fcffa3fbf 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp @@ -26,393 +26,19 @@ #include "bindingeditor.h" #include - -#include "texteditorview.h" -#include "texteditorwidget.h" -#include - #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include - namespace QmlDesigner { static BindingEditor *s_lastBindingEditor = nullptr; -const char BINDINGEDITOR_CONTEXT_ID[] = "BindingEditor.BindingEditorContext"; - -BindingEditorWidget::BindingEditorWidget() - : m_context(new BindingEditorContext(this)) -{ - Core::ICore::addContextObject(m_context); - - const Core::Context context(BINDINGEDITOR_CONTEXT_ID); - - /* - * We have to register our own active auto completion shortcut, because the original short cut will - * use the cursor position of the original editor in the editor manager. - */ - - m_completionAction = new QAction(tr("Trigger Completion"), this); - Core::Command *command = Core::ActionManager::registerAction( - m_completionAction, TextEditor::Constants::COMPLETE_THIS, context); - command->setDefaultKeySequence(QKeySequence( - Core::useMacShortcuts - ? tr("Meta+Space") - : tr("Ctrl+Space"))); - - connect(m_completionAction, &QAction::triggered, [this]() { - invokeAssist(TextEditor::Completion); - }); -} - -BindingEditorWidget::~BindingEditorWidget() -{ - unregisterAutoCompletion(); - - Core::ICore::removeContextObject(m_context); - delete m_context; -} - -void BindingEditorWidget::unregisterAutoCompletion() -{ - if (m_completionAction) { - Core::ActionManager::unregisterAction(m_completionAction, TextEditor::Constants::COMPLETE_THIS); - delete m_completionAction; - m_completionAction = nullptr; - } -} - -bool BindingEditorWidget::event(QEvent *event) -{ - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { - emit returnKeyClicked(); - return true; - } else { - return QmlJSEditor::QmlJSEditorWidget::event(event); - } - } - return QmlJSEditor::QmlJSEditorWidget::event(event); -} - -TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface( - TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const -{ - Q_UNUSED(assistKind) - return new QmlJSEditor::QmlJSCompletionAssistInterface( - document(), position(), QString(), - assistReason, qmljsdocument->semanticInfo()); -} - -class BindingDocument : public QmlJSEditor::QmlJSEditorDocument -{ -public: - BindingDocument() - : QmlJSEditor::QmlJSEditorDocument(BINDINGEDITOR_CONTEXT_ID) - , m_semanticHighlighter(new QmlJSEditor::SemanticHighlighter(this)) {} - ~BindingDocument() { delete m_semanticHighlighter; } - -protected: - void applyFontSettings() - { - TextDocument::applyFontSettings(); - m_semanticHighlighter->updateFontSettings(fontSettings()); - if (!isSemanticInfoOutdated()) - m_semanticHighlighter->rerun(semanticInfo()); - } - - void triggerPendingUpdates() - { - TextDocument::triggerPendingUpdates(); // calls applyFontSettings if necessary - if (!isSemanticInfoOutdated()) - m_semanticHighlighter->rerun(semanticInfo()); - } - -private: - QmlJSEditor::SemanticHighlighter *m_semanticHighlighter = nullptr; -}; - -class BindingEditorFactory : public TextEditor::TextEditorFactory -{ -public: - BindingEditorFactory() - { - setId(BINDINGEDITOR_CONTEXT_ID); - setDisplayName(QCoreApplication::translate("OpenWith::Editors", BINDINGEDITOR_CONTEXT_ID)); - - - setDocumentCreator([]() { return new BindingDocument; }); - setEditorWidgetCreator([]() { return new BindingEditorWidget; }); - setEditorCreator([]() { return new QmlJSEditor::QmlJSEditor; }); - setAutoCompleterCreator([]() { return new QmlJSEditor::AutoCompleter; }); - setCommentDefinition(Utils::CommentDefinition::CppStyle); - setParenthesesMatchingEnabled(true); - setCodeFoldingSupported(true); - - addHoverHandler(new QmlJSEditor::QmlJSHoverHandler); - setCompletionAssistProvider(new QmlJSEditor::QmlJSCompletionAssistProvider); - } - - static void decorateEditor(TextEditor::TextEditorWidget *editor) - { - editor->textDocument()->setSyntaxHighlighter(new QmlJSEditor::QmlJSHighlighter); - editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter( - editor->textDocument()->document())); - editor->setAutoCompleter(new QmlJSEditor::AutoCompleter); - } -}; - -BindingEditorDialog::BindingEditorDialog(QWidget *parent) - : QDialog(parent) -{ - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setWindowTitle(tr("Binding Editor")); - setModal(false); - - setupJSEditor(); - setupUIComponents(); - - QObject::connect(m_buttonBox, &QDialogButtonBox::accepted, - this, &BindingEditorDialog::accepted); - QObject::connect(m_buttonBox, &QDialogButtonBox::rejected, - this, &BindingEditorDialog::rejected); - QObject::connect(m_editorWidget, &BindingEditorWidget::returnKeyClicked, - this, &BindingEditorDialog::accepted); - - QObject::connect(m_comboBoxItem, QOverload::of(&QComboBox::currentIndexChanged), - this, &BindingEditorDialog::itemIDChanged); - QObject::connect(m_comboBoxProperty, QOverload::of(&QComboBox::currentIndexChanged), - this, &BindingEditorDialog::propertyIDChanged); - QObject::connect(m_editorWidget, &QPlainTextEdit::textChanged, - this, &BindingEditorDialog::textChanged); -} - -BindingEditorDialog::~BindingEditorDialog() -{ - delete m_editor; //m_editorWidget is handled by basetexteditor destructor - delete m_buttonBox; - delete m_comboBoxItem; - delete m_comboBoxProperty; - delete m_comboBoxLayout; - delete m_verticalLayout; -} - -void BindingEditorDialog::showWidget(int x, int y) -{ - this->show(); - this->raise(); - move(QPoint(x, y)); - m_editorWidget->setFocus(); -} - -QString BindingEditorDialog::editorValue() const -{ - if (!m_editorWidget) - return {}; - - return m_editorWidget->document()->toPlainText(); -} - -void BindingEditorDialog::setEditorValue(const QString &text) -{ - if (m_editorWidget) - m_editorWidget->document()->setPlainText(text); -} - -void BindingEditorDialog::setAllBindings(QList bindings) -{ - m_lock = true; - - m_bindings = bindings; - setupComboBoxes(); - adjustProperties(); - - m_lock = false; -} - -void BindingEditorDialog::adjustProperties() -{ - const QString expression = editorValue(); - QString item; - QString property; - QStringList expressionElements = expression.split("."); - - if (!expressionElements.isEmpty()) { - const int itemIndex = m_bindings.indexOf(expressionElements.at(0)); - - if (itemIndex != -1) { - item = expressionElements.at(0); - expressionElements.removeFirst(); - - if (!expressionElements.isEmpty()) { - const QString sum = expressionElements.join("."); - - if (m_bindings.at(itemIndex).properties.contains(sum)) - property = sum; - } - } - } - - if (item.isEmpty()) { - item = undefinedString; - if (m_comboBoxItem->findText(item) == -1) - m_comboBoxItem->addItem(item); - } - m_comboBoxItem->setCurrentText(item); - - if (property.isEmpty()) { - property = undefinedString; - if (m_comboBoxProperty->findText(property) == -1) - m_comboBoxProperty->addItem(property); - } - m_comboBoxProperty->setCurrentText(property); -} - -void BindingEditorDialog::unregisterAutoCompletion() -{ - if (m_editorWidget) - m_editorWidget->unregisterAutoCompletion(); -} - -void BindingEditorDialog::setupJSEditor() -{ - static BindingEditorFactory f; - m_editor = qobject_cast(f.createEditor()); - m_editorWidget = qobject_cast(m_editor->editorWidget()); - - Core::Context context = m_editor->context(); - context.prepend(BINDINGEDITOR_CONTEXT_ID); - m_editorWidget->m_context->setContext(context); - - auto qmlDesignerEditor = QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor(); - - m_editorWidget->qmljsdocument = qobject_cast( - qmlDesignerEditor->widget())->qmlJsEditorDocument(); - - - m_editorWidget->setLineNumbersVisible(false); - m_editorWidget->setMarksVisible(false); - m_editorWidget->setCodeFoldingSupported(false); - m_editorWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_editorWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_editorWidget->setTabChangesFocus(true); -} - -void BindingEditorDialog::setupUIComponents() -{ - m_verticalLayout = new QVBoxLayout(this); - m_comboBoxLayout = new QHBoxLayout; - - m_comboBoxItem = new QComboBox(this); - m_comboBoxProperty = new QComboBox(this); - - m_editorWidget->setParent(this); - m_editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); - m_editorWidget->show(); - - m_buttonBox = new QDialogButtonBox(this); - m_buttonBox->setOrientation(Qt::Horizontal); - m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - - - m_comboBoxLayout->addWidget(m_comboBoxItem); - m_comboBoxLayout->addWidget(m_comboBoxProperty); - - m_verticalLayout->addLayout(m_comboBoxLayout); - m_verticalLayout->addWidget(m_editorWidget); - m_verticalLayout->addWidget(m_buttonBox); - - this->resize(660, 240); -} - -void BindingEditorDialog::setupComboBoxes() -{ - m_comboBoxItem->clear(); - m_comboBoxProperty->clear(); - - for (auto bind : m_bindings) - m_comboBoxItem->addItem(bind.item); -} - -void BindingEditorDialog::itemIDChanged(int itemID) -{ - const QString previousProperty = m_comboBoxProperty->currentText(); - m_comboBoxProperty->clear(); - - if (m_bindings.size() > itemID && itemID != -1) { - m_comboBoxProperty->addItems(m_bindings.at(itemID).properties); - - if (!m_lock) - if (m_comboBoxProperty->findText(previousProperty) != -1) - m_comboBoxProperty->setCurrentText(previousProperty); - - const int undefinedItem = m_comboBoxItem->findText(undefinedString); - if ((undefinedItem != -1) && (m_comboBoxItem->itemText(itemID) != undefinedString)) - m_comboBoxItem->removeItem(undefinedItem); - } -} - -void BindingEditorDialog::propertyIDChanged(int propertyID) -{ - const int itemID = m_comboBoxItem->currentIndex(); - - if (!m_lock) - if (!m_comboBoxProperty->currentText().isEmpty() && (m_comboBoxProperty->currentText() != undefinedString)) - setEditorValue(m_comboBoxItem->itemText(itemID) + "." + m_comboBoxProperty->itemText(propertyID)); - - const int undefinedProperty = m_comboBoxProperty->findText(undefinedString); - if ((undefinedProperty != -1) && (m_comboBoxProperty->itemText(propertyID) != undefinedString)) - m_comboBoxProperty->removeItem(undefinedProperty); -} - -void BindingEditorDialog::textChanged() -{ - if (m_lock) - return; - - m_lock = true; - adjustProperties(); - m_lock = false; -} - - BindingEditor::BindingEditor(QObject *) { } @@ -556,5 +182,4 @@ QVariant BindingEditor::stateModelNode() const return m_stateModelNode; } - -} +} // QmlDesigner namespace diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h index a1deb741080..5da06d2ecf0 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h @@ -26,117 +26,16 @@ #ifndef BINDINGEDITOR_H #define BINDINGEDITOR_H -#include "texteditorview.h" -#include -#include +#include +#include +#include -#include -#include +#include +#include #include -#include - -#include - -QT_BEGIN_NAMESPACE -class QTextEdit; -class QDialogButtonBox; -class QVBoxLayout; -class QHBoxLayout; -class QComboBox; -QT_END_NAMESPACE - namespace QmlDesigner { -class BindingEditorContext : public Core::IContext -{ - Q_OBJECT - -public: - BindingEditorContext(QWidget *parent) : Core::IContext(parent) - { - setWidget(parent); - } -}; - -class BindingEditorWidget : public QmlJSEditor::QmlJSEditorWidget -{ - Q_OBJECT - -public: - BindingEditorWidget(); - ~BindingEditorWidget() override; - - void unregisterAutoCompletion(); - - bool event(QEvent *event) override; - - TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind, - TextEditor::AssistReason assistReason) const override; - -signals: - void returnKeyClicked(); - -public: - QmlJSEditor::QmlJSEditorDocument *qmljsdocument = nullptr; - BindingEditorContext *m_context = nullptr; - QAction *m_completionAction = nullptr; -}; - -class BindingEditorDialog : public QDialog -{ - Q_OBJECT - -public: - struct BindingOption - { - BindingOption() {} - BindingOption(const QString &value) { item = value; } - - bool operator==(const QString &value) const { return value == item; } - bool operator==(const BindingOption &value) const { return value.item == item; } - - QString item; - QStringList properties; - }; - -public: - BindingEditorDialog(QWidget *parent = nullptr); - ~BindingEditorDialog() override; - - void showWidget(int x, int y); - - QString editorValue() const; - void setEditorValue(const QString &text); - - void setAllBindings(QList bindings); - void adjustProperties(); - - void unregisterAutoCompletion(); - -private: - void setupJSEditor(); - void setupUIComponents(); - void setupComboBoxes(); - -public slots: - void itemIDChanged(int); - void propertyIDChanged(int); - void textChanged(); - -private: - TextEditor::BaseTextEditor *m_editor = nullptr; - BindingEditorWidget *m_editorWidget = nullptr; - QVBoxLayout *m_verticalLayout = nullptr; - QDialogButtonBox *m_buttonBox = nullptr; - QHBoxLayout *m_comboBoxLayout = nullptr; - QComboBox *m_comboBoxItem = nullptr; - QComboBox *m_comboBoxProperty = nullptr; - QList m_bindings; - bool m_lock = false; - const QString undefinedString = {"[Undefined]"}; -}; - class BindingEditor : public QObject { Q_OBJECT diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.pri b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.pri index 518905eb2a0..88b2897c7bd 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.pri +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.pri @@ -1,3 +1,7 @@ HEADERS += $$PWD/bindingeditor.h +HEADERS += $$PWD/bindingeditordialog.h +HEADERS += $$PWD/bindingeditorwidget.h SOURCES += $$PWD/bindingeditor.cpp +SOURCES += $$PWD/bindingeditordialog.cpp +SOURCES += $$PWD/bindingeditorwidget.cpp diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp new file mode 100644 index 00000000000..08cb5d8bd36 --- /dev/null +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "bindingeditordialog.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +BindingEditorDialog::BindingEditorDialog(QWidget *parent) + : QDialog(parent) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setWindowTitle(tr("Binding Editor")); + setModal(false); + + setupJSEditor(); + setupUIComponents(); + + QObject::connect(m_buttonBox, &QDialogButtonBox::accepted, + this, &BindingEditorDialog::accepted); + QObject::connect(m_buttonBox, &QDialogButtonBox::rejected, + this, &BindingEditorDialog::rejected); + QObject::connect(m_editorWidget, &BindingEditorWidget::returnKeyClicked, + this, &BindingEditorDialog::accepted); + + QObject::connect(m_comboBoxItem, QOverload::of(&QComboBox::currentIndexChanged), + this, &BindingEditorDialog::itemIDChanged); + QObject::connect(m_comboBoxProperty, QOverload::of(&QComboBox::currentIndexChanged), + this, &BindingEditorDialog::propertyIDChanged); + QObject::connect(m_editorWidget, &QPlainTextEdit::textChanged, + this, &BindingEditorDialog::textChanged); +} + +BindingEditorDialog::~BindingEditorDialog() +{ + delete m_editor; //m_editorWidget is handled by basetexteditor destructor + delete m_buttonBox; + delete m_comboBoxItem; + delete m_comboBoxProperty; + delete m_comboBoxLayout; + delete m_verticalLayout; +} + +void BindingEditorDialog::showWidget(int x, int y) +{ + this->show(); + this->raise(); + move(QPoint(x, y)); + m_editorWidget->setFocus(); +} + +QString BindingEditorDialog::editorValue() const +{ + if (!m_editorWidget) + return {}; + + return m_editorWidget->document()->toPlainText(); +} + +void BindingEditorDialog::setEditorValue(const QString &text) +{ + if (m_editorWidget) + m_editorWidget->document()->setPlainText(text); +} + +void BindingEditorDialog::setAllBindings(QList bindings) +{ + m_lock = true; + + m_bindings = bindings; + setupComboBoxes(); + adjustProperties(); + + m_lock = false; +} + +void BindingEditorDialog::adjustProperties() +{ + const QString expression = editorValue(); + QString item; + QString property; + QStringList expressionElements = expression.split("."); + + if (!expressionElements.isEmpty()) { + const int itemIndex = m_bindings.indexOf(expressionElements.at(0)); + + if (itemIndex != -1) { + item = expressionElements.at(0); + expressionElements.removeFirst(); + + if (!expressionElements.isEmpty()) { + const QString sum = expressionElements.join("."); + + if (m_bindings.at(itemIndex).properties.contains(sum)) + property = sum; + } + } + } + + if (item.isEmpty()) { + item = undefinedString; + if (m_comboBoxItem->findText(item) == -1) + m_comboBoxItem->addItem(item); + } + m_comboBoxItem->setCurrentText(item); + + if (property.isEmpty()) { + property = undefinedString; + if (m_comboBoxProperty->findText(property) == -1) + m_comboBoxProperty->addItem(property); + } + m_comboBoxProperty->setCurrentText(property); +} + +void BindingEditorDialog::unregisterAutoCompletion() +{ + if (m_editorWidget) + m_editorWidget->unregisterAutoCompletion(); +} + +void BindingEditorDialog::setupJSEditor() +{ + static BindingEditorFactory f; + m_editor = qobject_cast(f.createEditor()); + m_editorWidget = qobject_cast(m_editor->editorWidget()); + + Core::Context context = m_editor->context(); + context.prepend(BINDINGEDITOR_CONTEXT_ID); + m_editorWidget->m_context->setContext(context); + + auto qmlDesignerEditor = QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor(); + + m_editorWidget->qmljsdocument = qobject_cast( + qmlDesignerEditor->widget())->qmlJsEditorDocument(); + + + m_editorWidget->setLineNumbersVisible(false); + m_editorWidget->setMarksVisible(false); + m_editorWidget->setCodeFoldingSupported(false); + m_editorWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_editorWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_editorWidget->setTabChangesFocus(true); +} + +void BindingEditorDialog::setupUIComponents() +{ + m_verticalLayout = new QVBoxLayout(this); + m_comboBoxLayout = new QHBoxLayout; + + m_comboBoxItem = new QComboBox(this); + m_comboBoxProperty = new QComboBox(this); + + m_editorWidget->setParent(this); + m_editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); + m_editorWidget->show(); + + m_buttonBox = new QDialogButtonBox(this); + m_buttonBox->setOrientation(Qt::Horizontal); + m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + + m_comboBoxLayout->addWidget(m_comboBoxItem); + m_comboBoxLayout->addWidget(m_comboBoxProperty); + + m_verticalLayout->addLayout(m_comboBoxLayout); + m_verticalLayout->addWidget(m_editorWidget); + m_verticalLayout->addWidget(m_buttonBox); + + this->resize(660, 240); +} + +void BindingEditorDialog::setupComboBoxes() +{ + m_comboBoxItem->clear(); + m_comboBoxProperty->clear(); + + for (auto bind : m_bindings) + m_comboBoxItem->addItem(bind.item); +} + +void BindingEditorDialog::itemIDChanged(int itemID) +{ + const QString previousProperty = m_comboBoxProperty->currentText(); + m_comboBoxProperty->clear(); + + if (m_bindings.size() > itemID && itemID != -1) { + m_comboBoxProperty->addItems(m_bindings.at(itemID).properties); + + if (!m_lock) + if (m_comboBoxProperty->findText(previousProperty) != -1) + m_comboBoxProperty->setCurrentText(previousProperty); + + const int undefinedItem = m_comboBoxItem->findText(undefinedString); + if ((undefinedItem != -1) && (m_comboBoxItem->itemText(itemID) != undefinedString)) + m_comboBoxItem->removeItem(undefinedItem); + } +} + +void BindingEditorDialog::propertyIDChanged(int propertyID) +{ + const int itemID = m_comboBoxItem->currentIndex(); + + if (!m_lock) + if (!m_comboBoxProperty->currentText().isEmpty() && (m_comboBoxProperty->currentText() != undefinedString)) + setEditorValue(m_comboBoxItem->itemText(itemID) + "." + m_comboBoxProperty->itemText(propertyID)); + + const int undefinedProperty = m_comboBoxProperty->findText(undefinedString); + if ((undefinedProperty != -1) && (m_comboBoxProperty->itemText(propertyID) != undefinedString)) + m_comboBoxProperty->removeItem(undefinedProperty); +} + +void BindingEditorDialog::textChanged() +{ + if (m_lock) + return; + + m_lock = true; + adjustProperties(); + m_lock = false; +} + +} // QmlDesigner namespace diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h new file mode 100644 index 00000000000..f1b224a716f --- /dev/null +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#ifndef BINDINGEDITORDIALOG_H +#define BINDINGEDITORDIALOG_H + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QDialogButtonBox; +class QVBoxLayout; +class QHBoxLayout; +class QComboBox; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class BindingEditorDialog : public QDialog +{ + Q_OBJECT + +public: + struct BindingOption + { + BindingOption() {} + BindingOption(const QString &value) { item = value; } + + bool operator==(const QString &value) const { return value == item; } + bool operator==(const BindingOption &value) const { return value.item == item; } + + QString item; + QStringList properties; + }; + +public: + BindingEditorDialog(QWidget *parent = nullptr); + ~BindingEditorDialog() override; + + void showWidget(int x, int y); + + QString editorValue() const; + void setEditorValue(const QString &text); + + void setAllBindings(QList bindings); + void adjustProperties(); + + void unregisterAutoCompletion(); + +private: + void setupJSEditor(); + void setupUIComponents(); + void setupComboBoxes(); + +public slots: + void itemIDChanged(int); + void propertyIDChanged(int); + void textChanged(); + +private: + TextEditor::BaseTextEditor *m_editor = nullptr; + BindingEditorWidget *m_editorWidget = nullptr; + QVBoxLayout *m_verticalLayout = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; + QHBoxLayout *m_comboBoxLayout = nullptr; + QComboBox *m_comboBoxItem = nullptr; + QComboBox *m_comboBoxProperty = nullptr; + QList m_bindings; + bool m_lock = false; + const QString undefinedString = {"[Undefined]"}; +}; + +} + +#endif //BINDINGEDITORDIALOG_H diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp new file mode 100644 index 00000000000..6a058cb49a4 --- /dev/null +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "bindingeditorwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlDesigner { + +BindingEditorWidget::BindingEditorWidget() + : m_context(new BindingEditorContext(this)) +{ + Core::ICore::addContextObject(m_context); + + const Core::Context context(BINDINGEDITOR_CONTEXT_ID); + + /* + * We have to register our own active auto completion shortcut, because the original short cut will + * use the cursor position of the original editor in the editor manager. + */ + + m_completionAction = new QAction(tr("Trigger Completion"), this); + Core::Command *command = Core::ActionManager::registerAction( + m_completionAction, TextEditor::Constants::COMPLETE_THIS, context); + command->setDefaultKeySequence(QKeySequence( + Core::useMacShortcuts + ? tr("Meta+Space") + : tr("Ctrl+Space"))); + + connect(m_completionAction, &QAction::triggered, [this]() { + invokeAssist(TextEditor::Completion); + }); +} + +BindingEditorWidget::~BindingEditorWidget() +{ + unregisterAutoCompletion(); + + Core::ICore::removeContextObject(m_context); + delete m_context; +} + +void BindingEditorWidget::unregisterAutoCompletion() +{ + if (m_completionAction) { + Core::ActionManager::unregisterAction(m_completionAction, TextEditor::Constants::COMPLETE_THIS); + delete m_completionAction; + m_completionAction = nullptr; + } +} + +bool BindingEditorWidget::event(QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { + emit returnKeyClicked(); + return true; + } else { + return QmlJSEditor::QmlJSEditorWidget::event(event); + } + } + return QmlJSEditor::QmlJSEditorWidget::event(event); +} + +TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface( + TextEditor::AssistKind assistKind, TextEditor::AssistReason assistReason) const +{ + Q_UNUSED(assistKind) + return new QmlJSEditor::QmlJSCompletionAssistInterface( + document(), position(), QString(), + assistReason, qmljsdocument->semanticInfo()); +} + +BindingDocument::BindingDocument() + : QmlJSEditor::QmlJSEditorDocument(BINDINGEDITOR_CONTEXT_ID) + , m_semanticHighlighter(new QmlJSEditor::SemanticHighlighter(this)) +{ + +} + +BindingDocument::~BindingDocument() +{ + delete m_semanticHighlighter; +} + +void BindingDocument::applyFontSettings() +{ + TextDocument::applyFontSettings(); + m_semanticHighlighter->updateFontSettings(fontSettings()); + if (!isSemanticInfoOutdated()) + m_semanticHighlighter->rerun(semanticInfo()); +} + +void BindingDocument::triggerPendingUpdates() +{ + TextDocument::triggerPendingUpdates(); // calls applyFontSettings if necessary + if (!isSemanticInfoOutdated()) + m_semanticHighlighter->rerun(semanticInfo()); +} + +BindingEditorFactory::BindingEditorFactory() +{ + setId(BINDINGEDITOR_CONTEXT_ID); + setDisplayName(QCoreApplication::translate("OpenWith::Editors", QmlDesigner::BINDINGEDITOR_CONTEXT_ID)); + + setDocumentCreator([]() { return new BindingDocument; }); + setEditorWidgetCreator([]() { return new BindingEditorWidget; }); + setEditorCreator([]() { return new QmlJSEditor::QmlJSEditor; }); + setAutoCompleterCreator([]() { return new QmlJSEditor::AutoCompleter; }); + setCommentDefinition(Utils::CommentDefinition::CppStyle); + setParenthesesMatchingEnabled(true); + setCodeFoldingSupported(true); + + addHoverHandler(new QmlJSEditor::QmlJSHoverHandler); + setCompletionAssistProvider(new QmlJSEditor::QmlJSCompletionAssistProvider); +} + +void BindingEditorFactory::decorateEditor(TextEditor::TextEditorWidget *editor) +{ + editor->textDocument()->setSyntaxHighlighter(new QmlJSEditor::QmlJSHighlighter); + editor->textDocument()->setIndenter(new QmlJSEditor::Internal::Indenter( + editor->textDocument()->document())); + editor->setAutoCompleter(new QmlJSEditor::AutoCompleter); +} + +} // QmlDesigner namespace diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.h new file mode 100644 index 00000000000..597051d89f0 --- /dev/null +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#ifndef BINDINGEDITORWIDGET_H +#define BINDINGEDITORWIDGET_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace QmlDesigner { + +const char BINDINGEDITOR_CONTEXT_ID[] = "BindingEditor.BindingEditorContext"; + + +class BindingEditorContext : public Core::IContext +{ + Q_OBJECT + +public: + BindingEditorContext(QWidget *parent) : Core::IContext(parent) + { + setWidget(parent); + } +}; + +class BindingEditorWidget : public QmlJSEditor::QmlJSEditorWidget +{ + Q_OBJECT + +public: + BindingEditorWidget(); + ~BindingEditorWidget() override; + + void unregisterAutoCompletion(); + + bool event(QEvent *event) override; + + TextEditor::AssistInterface *createAssistInterface(TextEditor::AssistKind assistKind, + TextEditor::AssistReason assistReason) const override; + +signals: + void returnKeyClicked(); + +public: + QmlJSEditor::QmlJSEditorDocument *qmljsdocument = nullptr; + BindingEditorContext *m_context = nullptr; + QAction *m_completionAction = nullptr; +}; + +class BindingDocument : public QmlJSEditor::QmlJSEditorDocument +{ +public: + BindingDocument(); + ~BindingDocument(); + +protected: + void applyFontSettings(); + + void triggerPendingUpdates(); + +private: + QmlJSEditor::SemanticHighlighter *m_semanticHighlighter = nullptr; +}; + + +class BindingEditorFactory : public TextEditor::TextEditorFactory +{ +public: + BindingEditorFactory(); + + static void decorateEditor(TextEditor::TextEditorWidget *editor); +}; + +} + +#endif //BINDINGEDITORWIDGET_H diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 4ebac8ce310..736d4ed52c2 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -630,6 +630,10 @@ Project { files: [ "bindingeditor/bindingeditor.cpp", "bindingeditor/bindingeditor.h", + "bindingeditor/bindingeditordialog.cpp", + "bindingeditor/bindingeditordialog.h", + "bindingeditor/bindingeditorwidget.cpp", + "bindingeditor/bindingeditorwidget.h", "colortool/colortool.cpp", "colortool/colortool.h", "connectioneditor/addnewbackenddialog.h", From 6160abb4f8c72c5f7227d2527b69d992bc1afb50 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Fri, 22 Nov 2019 16:31:04 +0100 Subject: [PATCH 22/37] Documentation: Fix Ninja reference Change-Id: I95967b62b46ebe08ac837c490c54f5f3fc24d443 Reviewed-by: Nikolai Kosjar --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c96302bf474..d2a347e5eee 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ Prerequisites: * ActiveState Active Perl * MinGW with g++ 5.3 or Visual Studio 2017 or later * jom - * Ninja (optional, needed for CMake) * Python 3.5 or later (optional, needed for the python enabled debug helper) * On Mac OS X: latest Xcode * On Linux: g++ 5.3 or later @@ -40,6 +39,7 @@ Prerequisites: "Get LLVM/Clang for the Clang Code Model". The LLVM C++ API provides no compatibility garantee, so if later versions don't compile we don't support that version.) * CMake (for manual builds of LLVM/Clang, and Qt Creator itself) +* Ninja (optional, recommended for building with CMake) * Qbs 1.7.x (optional, sources also contain Qbs itself) The installed toolchains have to match the one Qt was compiled with. From 901b6b023784bb76484f79be3f441f4df1afb172 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 20 Nov 2019 16:15:06 +0100 Subject: [PATCH 23/37] Change log for 4.11 RC Change-Id: I564242e9205bd107e1e213b814141caf97395464 Reviewed-by: Leena Miettinen --- dist/changes-4.11.0.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dist/changes-4.11.0.md b/dist/changes-4.11.0.md index a85f8e5c3d2..3b24537c3e0 100644 --- a/dist/changes-4.11.0.md +++ b/dist/changes-4.11.0.md @@ -112,6 +112,10 @@ you can check out from the public Git repository. For example: * Added option to remove directories directly from project tree (QTCREATORBUG-16575) * Added support for Framework paths (QTCREATORBUG-20099) +### Compilation Database + +* Fixed issue with `/imsvc` compiler option (QTCREATORBUG-23146) + ## Debugging ### CDB @@ -131,6 +135,7 @@ you can check out from the public Git repository. For example: * Changed to use separate `clang-tidy` executable * Separated diagnostic configuration settings for code model (`C++` > `Code Model`) and analyzer (`Analyzer` > `Clang Tools`) +* Fixed invocation of `clazy` with latest `clazy` versions ## Qt Widget Designer @@ -174,6 +179,8 @@ you can check out from the public Git repository. For example: * Removed auto-detection of GCC toolchains * Fixed closing of terminal window after application finishes (QTCREATORBUG-15138) +* Fixed execution of `qtc-askpass` (QTCREATORBUG-23120) +* Fixed environment when opening terminal with `zsh` (QTCREATORBUG-21712) ### Android From f9c1795d3b14d32d750661dd4dfb55520742fe63 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 25 Nov 2019 15:11:34 +0200 Subject: [PATCH 24/37] QmlDesigner: Add UX approved gradient background to 3D edit view Change-Id: I18b976324f57cf559a43d9ff239796cf25b3cb2f Fixes: QDS-1202 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index bf1bfebf861..1e17ccd7f99 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -174,11 +174,14 @@ Window { } Rectangle { - id: sceneBg - color: "#FFFFFF" anchors.fill: parent focus: true + gradient: Gradient { + GradientStop { position: 1.0; color: "#222222" } + GradientStop { position: 0.0; color: "#999999" } + } + TapHandler { // check tapping/clicking an object in the scene onTapped: { var pickResult = editView.pick(eventPoint.scenePosition.x, @@ -397,31 +400,45 @@ Window { selectedNode : viewWindow.selectedNode ? selectionBox.model : null } - Column { + Item { anchors.left: parent.left anchors.bottom: parent.bottom - CheckBox { - id: editLightCheckbox - checked: false - text: qsTr("Use Edit View Light") + width: 200 + height: 120 + + Rectangle { + anchors.fill: parent + color: "white" + opacity: 0.3 } - CheckBox { - id: usePerspectiveCheckbox - checked: true - text: qsTr("Use Perspective Projection") - onCheckedChanged: _generalHelper.requestOverlayUpdate() - } + Column { + anchors.left: parent.left + anchors.bottom: parent.bottom + CheckBox { + id: editLightCheckbox + checked: false + text: qsTr("Use Edit View Light") + } - CheckBox { - id: globalControl - checked: true - text: qsTr("Use Global Orientation") + CheckBox { + id: usePerspectiveCheckbox + checked: true + text: qsTr("Use Perspective Projection") + onCheckedChanged: _generalHelper.requestOverlayUpdate() + } + + CheckBox { + id: globalControl + checked: true + text: qsTr("Use Global Orientation") + } } } Text { id: helpText + color: "white" text: qsTr("Camera controls: ALT + mouse press and drag. Left: Rotate, Middle: Pan, Right/Wheel: Zoom.") anchors.bottom: parent.bottom } From b96bf86f180ea3a90bf396b8a45b587a9fb0539d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 25 Nov 2019 14:23:33 +0100 Subject: [PATCH 25/37] Qt Designer: Fix some clang warnings - Use using instead of typedef - User member initialization - Use nullptr - Do not use else after return - Delete pointers unconditionally - Fix some integer conversion warnings - Use auto for new/casts to avoid type name repetition - Use = default for trivial destructors Task-number: QTCREATORBUG-23248 Change-Id: I0a7465d3aa200b5c862bec82636d2d22ddf8297b Reviewed-by: Jarek Kobus --- src/plugins/designer/codemodelhelpers.cpp | 8 +++---- src/plugins/designer/cpp/formclasswizard.cpp | 7 ++++--- src/plugins/designer/formeditorplugin.cpp | 2 +- src/plugins/designer/formeditorstack.cpp | 6 +++--- src/plugins/designer/formeditorw.cpp | 21 ++++++++----------- .../designer/formtemplatewizardpage.cpp | 3 +-- src/plugins/designer/formwindoweditor.cpp | 4 +--- src/plugins/designer/formwindowfile.cpp | 2 +- src/plugins/designer/qtcreatorintegration.cpp | 16 +++++++------- src/plugins/designer/resourcehandler.cpp | 5 +---- .../designerintegrationv2/formresizer.cpp | 7 +++---- .../designerintegrationv2/formresizer.h | 4 ++-- .../designerintegrationv2/widgethost.cpp | 6 ++---- src/shared/designerintegrationv2/widgethost.h | 2 +- 14 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/plugins/designer/codemodelhelpers.cpp b/src/plugins/designer/codemodelhelpers.cpp index 5f3422e4121..94e861ae0e6 100644 --- a/src/plugins/designer/codemodelhelpers.cpp +++ b/src/plugins/designer/codemodelhelpers.cpp @@ -36,10 +36,10 @@ // Debug helpers for code model. @todo: Move to some CppTools library? -typedef QMap DependencyMap; -typedef CPlusPlus::Document::Ptr DocumentPtr; -typedef QList SymbolList; -typedef QList DocumentPtrList; +using DependencyMap = QMap; +using DocumentPtr = CPlusPlus::Document::Ptr; +using SymbolList = QList; +using DocumentPtrList = QList; static const char setupUiC[] = "setupUi"; diff --git a/src/plugins/designer/cpp/formclasswizard.cpp b/src/plugins/designer/cpp/formclasswizard.cpp index 88c1b5da4c5..9b878cf32cc 100644 --- a/src/plugins/designer/cpp/formclasswizard.cpp +++ b/src/plugins/designer/cpp/formclasswizard.cpp @@ -58,14 +58,14 @@ QString FormClassWizard::formSuffix() const Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const { - FormClassWizardDialog *wizardDialog = new FormClassWizardDialog(this, parent); + auto wizardDialog = new FormClassWizardDialog(this, parent); wizardDialog->setPath(parameters.defaultPath()); return wizardDialog; } Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *errorMessage) const { - const FormClassWizardDialog *wizardDialog = qobject_cast(w); + auto wizardDialog = qobject_cast(w); const Designer::FormClassWizardParameters params = wizardDialog->parameters(); if (params.uiTemplate.isEmpty()) { @@ -90,7 +90,8 @@ Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *e uiFile.setContents(params.uiTemplate); uiFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute); - QString source, header; + QString source; + QString header; QtDesignerFormClassCodeGenerator::generateCpp(params, &header, &source); sourceFile.setContents(source); diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index 06be5637024..9a912ac68ee 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -105,7 +105,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error) // Ensure that loading designer translations is done before FormEditorW is instantiated const QString locale = ICore::userInterfaceLanguage(); if (!locale.isEmpty()) { - QTranslator *qtr = new QTranslator(this); + auto qtr = new QTranslator(this); const QString &creatorTrPath = ICore::resourcePath() + "/translations"; const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); const QString &trFile = "designer_" + locale; diff --git a/src/plugins/designer/formeditorstack.cpp b/src/plugins/designer/formeditorstack.cpp index f109138cb3a..65c89fc359f 100644 --- a/src/plugins/designer/formeditorstack.cpp +++ b/src/plugins/designer/formeditorstack.cpp @@ -92,7 +92,7 @@ void FormEditorStack::add(const EditorData &data) // Since we have 1 pixel splitters we enforce no frame // on the content widget - if (QFrame *frame = qobject_cast(data.widgetHost)) + if (auto frame = qobject_cast(data.widgetHost)) frame->setFrameStyle(QFrame::NoFrame); } @@ -122,7 +122,7 @@ EditorData FormEditorStack::activeEditor() const if (index >= 0) return m_formEditors.at(index); } - return EditorData(); + return {}; } SharedTools::WidgetHost *FormEditorStack::formWindowEditorForFormWindow(const QDesignerFormWindowInterface *fw) const @@ -173,7 +173,7 @@ void FormEditorStack::formSizeChanged(int w, int h) // Handle main container resize. if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO << w << h; - if (const SharedTools::WidgetHost *wh = qobject_cast(sender())) { + if (auto wh = qobject_cast(sender())) { wh->formWindow()->setDirty(true); static const QString geometry = "geometry"; m_designerCore->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) ); diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index 36db2e05ba8..d7df1c8e859 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -115,7 +115,7 @@ namespace Internal { class DesignerXmlEditorWidget : public TextEditor::TextEditorWidget { public: - DesignerXmlEditorWidget() {} + using TextEditorWidget::TextEditorWidget; void finalizeInitialization() override { @@ -196,7 +196,7 @@ public: QDesignerFormEditorInterface *m_formeditor = nullptr; QtCreatorIntegration *m_integration = nullptr; QDesignerFormWindowManagerInterface *m_fwm = nullptr; - FormEditorW::InitializationStage m_initStage; + FormEditorW::InitializationStage m_initStage = FormEditorW::RegisterPlugins; QWidget *m_designerSubWindows[DesignerSubWindowCount]; @@ -229,8 +229,7 @@ static FormEditorData *d = nullptr; static FormEditorW *m_instance = nullptr; FormEditorData::FormEditorData() : - m_formeditor(QDesignerComponents::createFormEditor(nullptr)), - m_initStage(FormEditorW::RegisterPlugins) + m_formeditor(QDesignerComponents::createFormEditor(nullptr)) { if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO; @@ -409,19 +408,18 @@ void FormEditorData::fullInit() m_modeWidget = new QWidget; m_modeWidget->setObjectName("DesignerModeWidget"); - QVBoxLayout *layout = new QVBoxLayout; + auto layout = new QVBoxLayout(m_modeWidget); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(m_toolBar); // Avoid mode switch to 'Edit' mode when the application started by // 'Run' in 'Design' mode emits output. - MiniSplitter *splitter = new MiniSplitter(Qt::Vertical); + auto splitter = new MiniSplitter(Qt::Vertical); splitter->addWidget(m_editorWidget); QWidget *outputPane = new OutputPanePlaceHolder(Core::Constants::MODE_DESIGN, splitter); outputPane->setObjectName("DesignerOutputPanePlaceHolder"); splitter->addWidget(outputPane); layout->addWidget(splitter); - m_modeWidget->setLayout(layout); Context designerContexts = m_contexts; designerContexts.add(Core::Constants::C_EDITORMANAGER); @@ -648,9 +646,8 @@ void FormEditorData::setupActions() QToolBar *FormEditorData::createEditorToolBar() const { QToolBar *editorToolBar = new QToolBar; - const QList::const_iterator cend = m_toolActionIds.constEnd(); - for (QList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) { - Command *cmd = ActionManager::command(*it); + for (const auto &id : m_toolActionIds) { + Command *cmd = ActionManager::command(id); QTC_ASSERT(cmd, continue); QAction *action = cmd->action(); if (!action->icon().isNull()) // Simplify grid has no action yet @@ -735,7 +732,7 @@ QAction *FormEditorData::createEditModeAction(QActionGroup *ag, const QString &iconName, const QString &keySequence) { - QAction *rc = new QAction(actionName, ag); + auto rc = new QAction(actionName, ag); rc->setCheckable(true); if (!iconName.isEmpty()) rc->setIcon(designerIcon(iconName)); @@ -774,7 +771,7 @@ IEditor *FormEditorData::createEditor() QTC_ASSERT(form, return nullptr); QObject::connect(form, &QDesignerFormWindowInterface::toolChanged, [this] (int i) { toolChanged(i); }); - SharedTools::WidgetHost *widgetHost = new SharedTools::WidgetHost( /* parent */ nullptr, form); + auto widgetHost = new SharedTools::WidgetHost( /* parent */ nullptr, form); FormWindowEditor *formWindowEditor = m_xmlEditorFactory->create(form); m_editorWidget->add(widgetHost, formWindowEditor); diff --git a/src/plugins/designer/formtemplatewizardpage.cpp b/src/plugins/designer/formtemplatewizardpage.cpp index 3387ec63950..738a70285d9 100644 --- a/src/plugins/designer/formtemplatewizardpage.cpp +++ b/src/plugins/designer/formtemplatewizardpage.cpp @@ -60,8 +60,7 @@ Utils::WizardPage *FormPageFactory::create(ProjectExplorer::JsonWizard *wizard, QTC_ASSERT(canCreate(typeId), return nullptr); - FormTemplateWizardPage *page = new FormTemplateWizardPage; - return page; + return new FormTemplateWizardPage; } bool FormPageFactory::validateData(Core::Id typeId, const QVariant &data, QString *errorMessage) diff --git a/src/plugins/designer/formwindoweditor.cpp b/src/plugins/designer/formwindoweditor.cpp index b75bad127fd..27dfb068899 100644 --- a/src/plugins/designer/formwindoweditor.cpp +++ b/src/plugins/designer/formwindoweditor.cpp @@ -44,9 +44,7 @@ FormWindowEditor::FormWindowEditor() addContext(Designer::Constants::C_DESIGNER_XML_EDITOR); } -FormWindowEditor::~FormWindowEditor() -{ -} +FormWindowEditor::~FormWindowEditor() = default; QWidget *FormWindowEditor::toolBar() { diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index 2a3b77df5dc..176cf417419 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -84,7 +84,7 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, const QSt Utils::TextFileFormat::ReadResult readResult = read(absfileName, &contents, errorString); if (readResult == Utils::TextFileFormat::ReadEncodingError) return OpenResult::CannotHandle; - else if (readResult != Utils::TextFileFormat::ReadSuccess) + if (readResult != Utils::TextFileFormat::ReadSuccess) return OpenResult::ReadError; form->setFileName(absfileName); diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index 4a760ff65e0..37756425297 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -218,18 +218,18 @@ static const Class *findClass(const Namespace *parentNameSpace, const LookupCont static Function *findDeclaration(const Class *cl, const QString &functionName) { const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8())); - const unsigned mCount = cl->memberCount(); + const int mCount = cl->memberCount(); // we are interested only in declarations (can be decl of function or of a field) // we are only interested in declarations of functions const Overview overview; - for (unsigned j = 0; j < mCount; ++j) { // go through all members + for (int j = 0; j < mCount; ++j) { // go through all members if (Declaration *decl = cl->memberAt(j)->asDeclaration()) if (Function *fun = decl->type()->asFunctionType()) { // Format signature QString memberFunction = overview.prettyName(fun->name()); memberFunction += '('; - const uint aCount = fun->argumentCount(); - for (uint i = 0; i < aCount; i++) { // we build argument types string + const int aCount = fun->argumentCount(); + for (int i = 0; i < aCount; i++) { // we build argument types string const Argument *arg = fun->argumentAt(i)->asArgument(); if (i > 0) memberFunction += ','; @@ -350,7 +350,7 @@ static QString addConstRefIfNeeded(const QString &argument) "unsigned", "qint64", "quint64"}); for (int i = 0; i < nonConstRefs.count(); i++) { - const QString nonConstRef = nonConstRefs.at(i); + const QString &nonConstRef = nonConstRefs.at(i); if (argument == nonConstRef || argument.startsWith(nonConstRef + ' ')) return argument; } @@ -411,7 +411,7 @@ static QString addParameterNames(const QString &functionSignature, const QString // included files (going down [maxIncludeDepth] includes) and return a pair // of . -typedef QPair ClassDocumentPtrPair; +using ClassDocumentPtrPair = QPair; static ClassDocumentPtrPair findClassRecursively(const LookupContext &context, const QString &className, @@ -431,7 +431,7 @@ static ClassDocumentPtrPair for (const QString &include : includedFiles) { const Snapshot::const_iterator it = docTable.find(include); if (it != docTable.end()) { - const Document::Ptr includeDoc = it.value(); + const Document::Ptr &includeDoc = it.value(); LookupContext context(includeDoc, docTable); const ClassDocumentPtrPair irc = findClassRecursively(context, className, recursionMaxIncludeDepth, namespaceName); @@ -489,7 +489,7 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName, const QStringList ¶meterNames, QString *errorMessage) { - typedef QMap DocumentMap; + using DocumentMap = QMap; const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath(); #if 0 diff --git a/src/plugins/designer/resourcehandler.cpp b/src/plugins/designer/resourcehandler.cpp index 392b632a8f8..f111e8dbf8c 100644 --- a/src/plugins/designer/resourcehandler.cpp +++ b/src/plugins/designer/resourcehandler.cpp @@ -73,10 +73,7 @@ void ResourceHandler::ensureInitialized() qDebug() << "ResourceHandler::ensureInitialized() origPaths=" << m_originalUiQrcPaths; } -ResourceHandler::~ResourceHandler() -{ - -} +ResourceHandler::~ResourceHandler() = default; void ResourceHandler::updateResourcesHelper(bool updateProjectResources) { diff --git a/src/shared/designerintegrationv2/formresizer.cpp b/src/shared/designerintegrationv2/formresizer.cpp index 34de90a477c..354c7b4f467 100644 --- a/src/shared/designerintegrationv2/formresizer.cpp +++ b/src/shared/designerintegrationv2/formresizer.cpp @@ -42,14 +42,13 @@ using namespace SharedTools::Internal; FormResizer::FormResizer(QWidget *parent) : QWidget(parent), - m_frame(new QFrame), - m_formWindow(0) + m_frame(new QFrame) { // Make the resize grip of a mainwindow form find us as resizable window. setWindowFlags(windowFlags() | Qt::SubWindow); setBackgroundRole(QPalette::Base); - QVBoxLayout *handleLayout = new QVBoxLayout(this); + auto handleLayout = new QVBoxLayout(this); handleLayout->setContentsMargins(SELECTION_MARGIN, SELECTION_MARGIN, SELECTION_MARGIN, SELECTION_MARGIN); handleLayout->addWidget(m_frame); @@ -166,7 +165,7 @@ QWidget *FormResizer::mainContainer() { if (m_formWindow) return m_formWindow->mainContainer(); - return 0; + return nullptr; } void FormResizer::mainContainerChanged() diff --git a/src/shared/designerintegrationv2/formresizer.h b/src/shared/designerintegrationv2/formresizer.h index aad1a57b0fc..a1bdf021616 100644 --- a/src/shared/designerintegrationv2/formresizer.h +++ b/src/shared/designerintegrationv2/formresizer.h @@ -60,7 +60,7 @@ class FormResizer : public QWidget Q_OBJECT public: - FormResizer(QWidget *parent = 0); + FormResizer(QWidget *parent = nullptr); void updateGeometry(); void setState(SelectionHandleState st); @@ -84,7 +84,7 @@ private: QFrame *m_frame; typedef QVector Handles; Handles m_handles; - QDesignerFormWindowInterface * m_formWindow; + QDesignerFormWindowInterface *m_formWindow = nullptr; }; } diff --git a/src/shared/designerintegrationv2/widgethost.cpp b/src/shared/designerintegrationv2/widgethost.cpp index ed7f2fb91da..3ce7975c03f 100644 --- a/src/shared/designerintegrationv2/widgethost.cpp +++ b/src/shared/designerintegrationv2/widgethost.cpp @@ -41,7 +41,6 @@ using namespace SharedTools; // ---------- WidgetHost WidgetHost::WidgetHost(QWidget *parent, QDesignerFormWindowInterface *formWindow) : QScrollArea(parent), - m_formWindow(0), m_formResizer(new Internal::FormResizer) { setWidget(m_formResizer); @@ -52,8 +51,7 @@ WidgetHost::WidgetHost(QWidget *parent, QDesignerFormWindowInterface *formWindow WidgetHost::~WidgetHost() { - if (m_formWindow) - delete m_formWindow; + delete m_formWindow; } void WidgetHost::setFormWindow(QDesignerFormWindowInterface *fw) @@ -75,7 +73,7 @@ void WidgetHost::setFormWindow(QDesignerFormWindowInterface *fw) QSize WidgetHost::formWindowSize() const { if (!m_formWindow || !m_formWindow->mainContainer()) - return QSize(); + return {}; return m_formWindow->mainContainer()->size(); } diff --git a/src/shared/designerintegrationv2/widgethost.h b/src/shared/designerintegrationv2/widgethost.h index ccf8590e91f..1545509493c 100644 --- a/src/shared/designerintegrationv2/widgethost.h +++ b/src/shared/designerintegrationv2/widgethost.h @@ -60,7 +60,7 @@ private slots: private: QSize formWindowSize() const; - QDesignerFormWindowInterface *m_formWindow; + QDesignerFormWindowInterface *m_formWindow = nullptr; Internal::FormResizer *m_formResizer; QSize m_oldFakeWidgetSize; }; From d076c59429e2898f7d88699ed733ec0c3b2d66b6 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 25 Nov 2019 17:10:59 +0200 Subject: [PATCH 26/37] QmlDesigner: Block selection of hidden objects If eyeball is turned off for object, it shouldn't be pickable in 3D edit view. Change-Id: Ib9308aaaecc822f448591f249bd96ffb5d0c9c48 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../instances/quick3dnodeinstance.cpp | 60 +++++++++++++++---- .../instances/quick3dnodeinstance.h | 1 + .../qml2puppet/instances/servernodeinstance.h | 2 + 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp index ff555f6514a..f35d1659311 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp @@ -56,17 +56,7 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo InstanceContainer::NodeFlags flags) { ObjectNodeInstance::initialize(objectNodeInstance, flags); - -#ifdef QUICK3D_MODULE - if (quick3DNode()) { - QQuick3DObject::Type nodeType = quick3DNode()->type(); - if (nodeType == QQuick3DObject::Camera || nodeType == QQuick3DObject::Light - || nodeType == QQuick3DObject::Model || nodeType == QQuick3DObject::Image - || nodeType == QQuick3DObject::Text) { - setPropertyVariant("pickable", true); // allow 3D objects to receive mouse clicks - } - } -#endif + setPickable(true, true, false); } Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const @@ -83,6 +73,48 @@ QQuick3DNode *Quick3DNodeInstance::quick3DNode() const #endif } +void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyToChildren) +{ +#ifdef QUICK3D_MODULE + auto node = quick3DNode(); + if (node) { + QQuick3DObject::Type nodeType = node->type(); + bool parentHidden = false; + if (checkParent) { + // First check if any parent node is already hidden. Never set pickable on that case. + auto parentNode = node->parentNode(); + while (parentNode && !parentHidden) { + parentHidden = QQuick3DNodePrivate::get(parentNode)->m_isHiddenInEditor; + parentNode = parentNode->parentNode(); + } + + } + if (!parentHidden) { + if (applyToChildren) { + auto getQuick3DInstance = [this](QQuick3DObject *obj) -> Quick3DNodeInstance * { + if (nodeInstanceServer()->hasInstanceForObject(obj)) { + ServerNodeInstance instance = nodeInstanceServer()->instanceForObject(obj); + if (instance.isValid() && qobject_cast(instance.internalObject())) + return static_cast(instance.internalInstance().data()); + } + return nullptr; + }; + const auto childItems = node->childItems(); + for (auto childItem : childItems) { + if (auto quick3dInstance = getQuick3DInstance(childItem)) { + // Don't override explicit block in children + if (!QQuick3DNodePrivate::get(quick3dInstance->quick3DNode())->m_isHiddenInEditor) + quick3dInstance->setPickable(enable, false, true); + } + } + } + if (nodeType == QQuick3DObject::Model) + setPropertyVariant("pickable", enable); // allow 3D objects to receive mouse clicks + } + } +#endif +} + Quick3DNodeInstance::Pointer Quick3DNodeInstance::create(QObject *object) { Pointer instance(new Quick3DNodeInstance(object)); @@ -94,8 +126,12 @@ void Quick3DNodeInstance::setHideInEditor(bool b) { #ifdef QUICK3D_MODULE QQuick3DNodePrivate *privateNode = QQuick3DNodePrivate::get(quick3DNode()); - if (privateNode) + if (privateNode) { privateNode->setIsHiddenInEditor(b); + + // Hidden objects should not be pickable + setPickable(!b, true, true); + } #else Q_UNUSED(b); #endif diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h index 96c44c4d525..27e2488eb3f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h @@ -53,6 +53,7 @@ protected: private: Qt5NodeInstanceServer *qt5NodeInstanceServer() const; QQuick3DNode *quick3DNode() const; + void setPickable(bool enable, bool checkParent, bool applyToChildren); }; } // namespace Internal diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h index 86003b51b65..c85ba9a2b85 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h @@ -60,6 +60,7 @@ namespace Internal { class GraphicsObjectNodeInstance; class QmlStateNodeInstance; class QuickItemNodeInstance; + class Quick3DNodeInstance; } class ServerNodeInstance @@ -82,6 +83,7 @@ class ServerNodeInstance friend class QmlDesigner::Internal::ObjectNodeInstance; friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance; friend class QmlDesigner::Internal::QmlStateNodeInstance; + friend class QmlDesigner::Internal::Quick3DNodeInstance; public: enum ComponentWrap { From 05bb285b0d528c7dd57bd7405e3010d7bdbd625c Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 25 Nov 2019 17:24:59 +0200 Subject: [PATCH 27/37] QmlDesigner: Offset move/scale gizmo label in screen space Offsetting in scene space resulted in label being inconsistent distance away from the object, depending on zoom and angle. Change-Id: Ief555de664c042bb1a5c93af0ee7e5a1c3e7ce0a Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri --- share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 1e17ccd7f99..837a01f4148 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -257,13 +257,12 @@ Window { id: gizmoLabel targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo targetView: overlayView - offset: Qt.vector3d(0, 45, 0) visible: targetNode.dragging Rectangle { color: "white" x: -width / 2 - y: -height + y: -height - 8 width: gizmoLabelText.width + 4 height: gizmoLabelText.height + 4 border.width: 1 From bec91cbad8c12e2c2dffc16611522bf463f2591a Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 26 Nov 2019 11:28:11 +0100 Subject: [PATCH 28/37] QmlDesigner: Fix editable ComboBox popup selection This patch introduces a new state called 'popup' to disable text editing while the popup is opened and enables text editing whenever the popup is closed. Task-number: QDS-1262 Change-Id: I74ad4723d2cfe81447e94c37e9ba1f0913790d97 Reviewed-by: Thomas Hartmann --- .../imports/StudioControls/ComboBox.qml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml index 747a0d45109..1c3dc46c15f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -244,7 +244,7 @@ T.ComboBox { }, State { name: "edit" - when: myComboBox.edit && myComboBox.editable + when: myComboBox.edit && myComboBox.editable && !comboBoxPopup.opened PropertyChanges { target: myComboBox wheelEnabled: true @@ -252,12 +252,29 @@ T.ComboBox { PropertyChanges { target: comboBoxInput selectByMouse: true + readOnly: false } PropertyChanges { target: comboBoxBackground color: StudioTheme.Values.themeInteraction border.color: StudioTheme.Values.themeInteraction } + StateChangeScript { + script: comboBoxPopup.close() + } + }, + State { + name: "popup" + when: myComboBox.edit && comboBoxPopup.opened + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + selectByMouse: false + readOnly: true + } } ] From 8e2ef36e6054bd2b2c6dc247fef85f627b887893 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 26 Nov 2019 11:25:12 +0200 Subject: [PATCH 29/37] Implement 3D edit view top controls UI Implement global/local, projection type, and default light controls UI. Also small tweaks: - Fixed ortho. camera near clipping - Grid color darkened a bit - Selection rect color changed to yellow Task-number: QDS-1250 Change-Id: I03cf2023ee1b8a6a0768e4dbf7d6fee621a25ce2 Reviewed-by: Miikka Heikkinen Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 70 +++++++++--------- .../qml/qmlpuppet/mockfiles/HelperGrid.qml | 2 +- .../qml/qmlpuppet/mockfiles/SelectionBox.qml | 2 +- .../qml/qmlpuppet/mockfiles/ToggleButton.qml | 70 ++++++++++++++++++ .../mockfiles/images/edit_light_off.png | Bin 0 -> 1189 bytes .../mockfiles/images/edit_light_off@2x.png | Bin 0 -> 1430 bytes .../mockfiles/images/edit_light_on.png | Bin 0 -> 1355 bytes .../mockfiles/images/edit_light_on@2x.png | Bin 0 -> 1766 bytes .../qml/qmlpuppet/mockfiles/images/global.png | Bin 0 -> 433 bytes .../qmlpuppet/mockfiles/images/global@2x.png | Bin 0 -> 561 bytes .../qml/qmlpuppet/mockfiles/images/local.png | Bin 0 -> 1309 bytes .../qmlpuppet/mockfiles/images/local@2x.png | Bin 0 -> 1960 bytes .../qml/qmlpuppet/mockfiles/images/ortho.png | Bin 0 -> 1310 bytes .../qmlpuppet/mockfiles/images/ortho@2x.png | Bin 0 -> 1727 bytes .../qml/qmlpuppet/mockfiles/images/persp.png | Bin 0 -> 1391 bytes .../qmlpuppet/mockfiles/images/persp@2x.png | Bin 0 -> 1971 bytes share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc | 13 ++++ 17 files changed, 122 insertions(+), 35 deletions(-) create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/persp.png create mode 100644 share/qtcreator/qml/qmlpuppet/mockfiles/images/persp@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 837a01f4148..2200048fa5f 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -38,8 +38,8 @@ Window { flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint property alias scene: editView.importScene - property alias showEditLight: editLightCheckbox.checked - property alias usePerspective: usePerspectiveCheckbox.checked + property alias showEditLight: btnEditViewLight.toggled + property alias usePerspective: btnPerspective.toggled property Node selectedNode: null @@ -128,7 +128,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: btnLocalGlobal.toggled visible: selectedNode && btnMove.selected view3D: overlayView @@ -158,7 +158,7 @@ Window { targetNode: viewWindow.selectedNode position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition : Qt.vector3d(0, 0, 0) - globalOrientation: globalControl.checked + globalOrientation: btnLocalGlobal.toggled visible: selectedNode && btnRotate.selected view3D: overlayView @@ -241,7 +241,7 @@ Window { y: 600 rotation.x: 45 clipFar: 100000 - clipNear: 1 + clipNear: -10000 } } } @@ -399,39 +399,43 @@ Window { selectedNode : viewWindow.selectedNode ? selectionBox.model : null } - Item { - anchors.left: parent.left - anchors.bottom: parent.bottom - width: 200 - height: 120 + Rectangle { // top controls bar + color: "#aa000000" + width: 265 + height: btnPerspective.height + 10 + anchors.top: parent.top + anchors.right: parent.right + anchors.rightMargin: 100 - Rectangle { - anchors.fill: parent - color: "white" - opacity: 0.3 + ToggleButton { + id: btnPerspective + anchors.top: parent.top + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 5 + tooltip: qsTr("Toggle Perspective / Orthographic Projection") + states: [{iconId: "ortho", text: qsTr("Orthographic")}, {iconId: "persp", text: qsTr("Perspective")}] } - Column { + ToggleButton { + id: btnLocalGlobal + anchors.top: parent.top + anchors.topMargin: 5 anchors.left: parent.left - anchors.bottom: parent.bottom - CheckBox { - id: editLightCheckbox - checked: false - text: qsTr("Use Edit View Light") - } + anchors.leftMargin: 100 + tooltip: qsTr("Toggle Global / Local Orientation") + states: [{iconId: "local", text: qsTr("Local")}, {iconId: "global", text: qsTr("Global")}] + } - CheckBox { - id: usePerspectiveCheckbox - checked: true - text: qsTr("Use Perspective Projection") - onCheckedChanged: _generalHelper.requestOverlayUpdate() - } - - CheckBox { - id: globalControl - checked: true - text: qsTr("Use Global Orientation") - } + ToggleButton { + id: btnEditViewLight + anchors.top: parent.top + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 165 + toggleBackground: true + tooltip: qsTr("Toggle Edit Light") + states: [{iconId: "edit_light_off", text: qsTr("Edit Light Off")}, {iconId: "edit_light_on", text: qsTr("Edit Light On")}] } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml index 54af572a7ba..2d70c0b95ce 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml @@ -45,7 +45,7 @@ Node { materials: [ DefaultMaterial { id: mainGridMaterial - emissiveColor: "#e6e6e6" + emissiveColor: "#cccccc" lighting: DefaultMaterial.NoLighting cullingMode: Material.DisableCulling } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml index 524f5688899..995b4badd80 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml @@ -57,7 +57,7 @@ Node { materials: [ DefaultMaterial { - emissiveColor: "#e5009e" + emissiveColor: "#fff600" lighting: DefaultMaterial.NoLighting cullingMode: Material.DisableCulling } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml new file mode 100644 index 00000000000..a0ebeabbd47 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick 2.0 +import QtQuick.Controls 2.0 + +Rectangle { + property bool toggled: false + property string tooltip + property bool toggleBackground: false // show a black background for the toggled state + property var states: [] // array of 2 state-objects, idx 0: untoggled, idx 1: toggled + + id: root + color: toggleBackground && toggled ? "#aa000000" : mouseArea.containsMouse ? "#44000000" : "#00000000" + width: img.width + txt.width + 5 + height: img.height + + Image { + id: img + anchors.verticalCenter: parent.verticalCenter + source: "qrc:///qtquickplugin/mockfiles/images/" + root.states[toggled ? 1 : 0].iconId + ".png" + } + + Text { + id: txt + color: "#b5b5b5" + anchors.verticalCenter: parent.verticalCenter + anchors.left: img.right + text: root.states[toggled ? 1 : 0].text + } + + ToolTip { + text: tooltip + visible: mouseArea.containsMouse + delay: 1000 + } + + MouseArea { + id: mouseArea + cursorShape: "PointingHandCursor" + hoverEnabled: true + anchors.fill: parent + onClicked: root.toggled = !root.toggled + } +} + + diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_off.png new file mode 100644 index 0000000000000000000000000000000000000000..73e6e92374b15f4b693ef5804309327c65a06253 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztF!N`IM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyje1YYl>zP+vl9-pA3e%g3(Cds>ua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zE!ZY(y^2>`s;R+5kE0@%w%(B!Jx1#)91#rMv zWg=N_>0)GIZt7xcWM*k@Xlia@VPxoLY-wR`W?|s$Y+!7t1l5y*zXjWXkDm^&28sGc4pMq_I}YbleZpRcAi@Q*y#B{v+%Q1nW68zBR5&6%HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCUB zH#c=La5XhFFt#)_bak{eG_-WIa58kXG_y1{G&X_h^~@_SNz6-5h3U;i=rzHs*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_7;hA|U`Q^o+a0LgNl}l<-W?5>ATTyF?VaXfv- zhRq)|`dd}rPq69MbnUpH^CU1V$jnU4OsplyEGOs94FO*@Gdb?0!x~~|E-bj>(~*+; zN#=j>{8`JaC(pcn#&Y|){dKjM=M+Di_y11u`JekF_a1+IF*7pIs@Gd;0^1VCOa~~{ z%9CY(AjeF5Z!Fs_2fiOnX4gb-)LPH-QQOB>GletEai!C3l^d*gA4DEey~3ZD@riqZ z%#x;(0PpezayE@(iPHo!17rhrc&Yv^Bob=~sETQK~Cju_ty} z#*>{bTpCtR64joDvzIsKcU{z4_xJGS1CmGo2pkg&-15<+z+t0#%f{L%X>SUR8}2sC z26!(Je!^g!QW=-4N@0JEmh0o{z6+UQI(99{wx2gI9%cVW@IP1GuuYcKfC|mf! zyfe9tdI3Don7(Wd_!Yo<&h@lg_yINvCQYulR~HESG%E*cZ`yBq_p$ojv{|A%muv|N zIrTldQP`#{PWXOM*W1-81q)jj{o_6IGqadG{EBwRQnuEFDcd~DZm9*_o+`$}(`?o1 z+?6{!Im+O{66apgFKePM1s{7EG`rI66vJip9hY4lJ}p1W5XHj(pw;jGh7$sA%sJMz stcDM4W5h3>w%@fB5=B>Dgf}oUJf4u1AFtuD6jV}ry85}Sb4q9e06~TX5dZ)H literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png new file mode 100644 index 0000000000000000000000000000000000000000..7660c285460512ed0025dd1d64014fb5b661adaf GIT binary patch literal 1355 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztF!N`IM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjezP+vl9-pA3e%g3&})EKua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zE!ZY(y^2>`s;R+5kE0@%w%(B!Jx1#)91#rMv zWg=N_>0)GIZt7xcWM*k@Xlia@VPxoLY-wR`W?|s$Y+!7t1l5y*2l`<&6)ovDqo6U@tD!eqQcsZl(7} zQ);%Kdy&7(`2U~a%|)+Y->H6Q`FvjW`=9Ug`;R7V%Q0)$J$?2P)5C%r+{R%wMY?Js zxuxtoXX#8`C#ZKP@4Neq#g>j)+RdarXleunL_JyfB9e3YYD_l@o z#GZBHQ*4Q9hjfJN_DO{^g;q#EWDK|2ap$t~B4M_TAD4u>N>~Z{MSgK*+IE2RueGn? zoX5r9+nKi=-5>Gph3UKrh3tn5c)~BJ?^ov5@{c*>#O&Y|eq!@d@?^H@)Ml`7DRF6-PIr7h{d$P1 zXky+WgYuRg&gN6z71y#=bM6XUSv>XP=4XOACtj@dxN&n$)w+{crk|BRw_KF{_y1on e(=XMrN-#uRHRzxA|JX-R@#g93=d#Wzp$P!*$nT2) literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..836bd2a0d594e7a283a3f755ce6bb6817cad5562 GIT binary patch literal 1766 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCUB zHZ*s1b96K`Ft#)_baiwzH8pf`HE?pYbTv0Ma5aJH^~@_SNz6-5h3U;i=(WVF*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_7;hA|U`Q^o+a0LgNl}l<-W?5>ATTyS zSEjm5xai^9z3Ju6@)zQK(?7qtTYbOwyGoe`-$>3Y9-mbC8;K`HfJhh6WNT})1T*J>eUTD0u&tcCLv?QXCA z{lR|GWt%;FHsrpuxp^^X?b#-)XX|>e^?qyB`Mb`eFe(0p@1z&Rk^K*mC`dd4j4>!{NO)*EL=qHmQ)=vM4Sz zJ3LXC$8gJPqe8hi?bVKdwJsJf3zxp-LQ$%>Yt ze|QoOonDdtBF6bMx97&UMiE^#moL6bSo3O!!~vJDK|NP)-d}cNyGLMf%yP{IE5(D3 z-3Z+mmf};uww3LhV1rhUYO04fZ%E5s&AcGdugpu{u2ht$3-vm-&SCk-+uLSbXXdG4 z*eaSeGogE-+PjGhKLng|kDYRR4o|EZ^Beczx9_Uz>;+#dmx!0W=YZo7ja|%z;`Y1&@|pJ!sdw(%=dr7wO{4sm>X-NREcSn9 s9r60R*gDnWRKpZTP3Ao(;u+Z(QtxvvdltR#G^pnBboFyt=akR{0OLWj0{{R3 literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd09c680acf7f5310f22d04ef374ffef54345a4 GIT binary patch literal 433 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoD?D8sLp(a)PTsH2;wW<5 z-o<6nf(aKiT@+P>IISkl%>2Vq{&s3tca-z;PwW~VB8!|?PMhiZ#ATggiItV0iwT!t z%6XY;>)pjoP7f#N82#RtfA9A9r7 zNT%AW=>pHXhCSB(yY4+tuIes-ygMVg_|}bCZ!aGEw(BidP(GXDuSVtEobm(D-8q$h zHEc2~I}u!`>F6RJaO&2YS-M4j?Ot8&Gjh-UJsRlEm-J5dT-Z}q4J}PGXHg#J-?wg< ziPtbhu;(>iK2kh!NA=?`QkSlk98sOgxUEsxK~r;{@YQDxncu7Ud^9xm_D@j_T= zE8FCQ!c!U|RgdmnzGRDrpLzlBoyt?{yVvcy^5CnG%ak7$GWf@PVN@2h%!85kHCJYD@<);T3K0RZmQyXgP` literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a857fb10cb935e127fe65d0263ed0fcb7ef423 GIT binary patch literal 561 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4rT@hhJ-tuTNxM_<_GwMxH2#>?Ag0-&>~aQ zg-00}7)(ln{DK)6nV31b1Vlt7l~r|g^$kretZW^eeEkE1^9o9;8~P?pn?7^R+TBNw zoj8B(`mNiqzy19C@8g?KS_}+~yq+$OAs)xyPVo#r6qbfg%qJToP9PQ`M&n)esHw+6ZM9gTf4y}z{R)#Uvr9Be+N-)GQ2_cMXj;oqAX z?{zgUY|lH?BYShHcikEJmkX@zPkm>(HurUhsj1an|9nwa=bsAX{lh% ztxqbw$25D*XMESbcY2S>`DuqLTGns4W;fxs9g~CD-1MCMDT*1d?KRpqHiai2*v1*k zw86%(Wy@3XDL?14C%3MRUN_G>M0nCQ>qA*QxA!xYIa_k{xz+bO$Xc50&${huDF4)- Rmw|zS!PC{xWt~$(69AmUAF==d literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png new file mode 100644 index 0000000000000000000000000000000000000000..0a608f6816e62e1942a668cbe66f2745db13e623 GIT binary patch literal 1309 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_$;M3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjezP+vl9-pA3e%g3(Cds>ua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zEG{Q6UQu51-H9;W@4mK;7)S}F?)D*X({9FZa z&{$<+vEJ0k*wNI`%)-FU!W`suM{`FQL22%>BK2jvr}%8i$qcrm;Yg&!g^C9Xi<#UNvBh7lVXI#PAt`lxUn)aqDM_< z=@joG$@{_kS6*(pC;47y&M%Ynb927iyx(ctt1iKF?C7Q=$B*tfV&jlharoiI!WFZ6 zm|`9(PjZxgwYM)Vf$jd0hNhkSTuL>LZb-Y>>|@TnCGu;H&tpdC`diFXl`7W0f2MPP zrtTrhppT2btzeq5-T&b3Uq1p{mtU|;l3D$zzoc{4gUbuvYB+BE`kQl-L7R8&d$*-= zZ>}@EeBs>MwC1r?aM*nFFRSM@M4d@E;@RNNo3nm>E{JUY_+MAC`Q*DR?21d|eX?#G zu*tf^@gR8Bw%=11hE_lEGK<~zihG5d-nP3ZmMwd;n0xoGlt9t*`~Qc3R6W43TsinZ Tf0y}6P=V#?>gTe~DWM4fMkwDG literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c931e750fa19f3baaae1fd47679c4683d1ddd6 GIT binary patch literal 1960 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCVx zFn2aIH*zvGFg7(bbaiwzHg$0_H8wYJHgIw=uyBIu^~@_SNz6-5h3U;i=yk-a*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_78sV9FDf#8anxK#c2b+~kYEfocYKmJ?ey##I zXsj}^S#MhftcVV2}+)J3W#){nwMg$RHS5YSEA}C&cMJT>*?YcQgQ3etef5;g(An( z?{pnG<#pJr>7v*Q9qn5Sx7c40oRcUl+TohZ`<8^pbPVxFH z8+0z1ZN5|_o4)LQm&24>lfPK!+({qZ?fBOATZzK7D|osNYJa$V!tSFggXYYadVR~ALpCtl zur6I7wWZyO(=&4o%g4NP(uWm39W2~%dWG9}Gv*+rZd;r0+7-N6j>a2Utr<>UtJ&c2 ze8-DVaUXb18rXFfZqKQC%2@N@ep;OH28LrR)q2XbTrWzl{CasoUt>h*bJymW35{Y4599^dGj?*VkDZ8}Mu4}if-n*-()ZUdpzMh|U zP@j9IwdRNEpB8rBJXKh%pZP$}oZsivR+S0Tv(oG~G8**H^4J)Wwc_am0crD#NB5?v z%zyCW>u#}2#)W(4EDn>})F7O06u}g>vGVx`Yhh{IW1R+j4k{*cr!c7f%Mks}z4J_0 zYv1{xx#5T1&a*_$aZw8mxRh_-6STN0?OFfnQ&t>m4azYLN3A68lzwR86Em>(T=m;S z@}6ms-|I-FZ0qo+B}~i1BzGKR*cEy`q*zOn@lWF8Z*0m8+~sMRfBx{quuhMe;%qH` zbm^4{-8=Kx{%q}{!@MaF*%P9w| z52k&X$bBhf)d|K|RoNQ*W(uqBnrf}}^lyOB{5qNHrE@3y+VQvFn!PjaR6@G&i8ZfS zZ_brvogLz=U?yUeko@+0fSQG|=K8mHBA*t%)?BrzcW)AZ8ru}z#7_3-M}seP2JAl3 zu(&za>C_(k)t|39THo%T(VEg1mc7B-Lw9EC^Q}&wYwe9gPR0e^Z&A4f5R&!!DVYzo)sFBg$8V?9{I`#{#>SlkPfq+Jy{&C36^1vwws^FNr+z|3Iw Wi<>>uV)AcL-RbG-=d#Wzp$Py!UjHrt literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png new file mode 100644 index 0000000000000000000000000000000000000000..35b36203fa20ad34b5b48264723aa966b33786e9 GIT binary patch literal 1310 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_$;M3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjegWv9>zP+vl9-pA3e%g3&})oWua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zEG{Q6UQu51-H9;W@4mK;7)S}F?)D*X({9FZa z&{$<+vEJFp$jH&i$;80T(iG%$CqpAwH#ZXt0~a?Vb5~1OC8*vMEZ&CdHN~k{-%i0s z9~7@h@eC6Ra&ZGO!ATO7Jna+^={_|t#a5|E$=)t9*6J4n1LI^*7srr_TW_v~%`l6+{QK3Ic**cs1JZtJgoe4`@Rl+9aJTdf`#mjv@>9OF` ztut674X*#cW?m}({oEYMw1qWaqwf@_pZh-d{k-aRv6oGvRg_POJ^b;TbJ1D0?c46A z9sXRfP@X+ZI4m@*WlvLu%pw;5h=UVVivDeJt*khzUUadkMrQ%%^Baz(7M!OF+FYkd z9h-01m~_Q+_p}F&bF!M`R<03@W$gNJA}eVr$MUQu$C`zVhds9bxGUkew1Zb=wb~AM zTfK{I+-pwHus6Hd&XhS(drJBO{hz##KP{O3@aPnuJ#8jS9v=zVx$KLafSroOy7Jb2 zsp=PbcR$>BH|LWB=bA^dmo-c@PkfJdZ@nkg{-HfQ>`j2LK=W;d&K_MUCpNhdVU@&l zOGN*5e!W(A;;WHcK%ezhmbDd)(Pf_N6PMeZa`CIY{8h;)RanEmx%SE;j@2)Y7^Xet zIC*HQ%Bf?eJKFE^vOP(C<)Gv?Q8{-d=j-YO!Rke_nll1_PX7CUvAoVcRtbjJt|6yA SzI_%2l~|sxelF{r5}E)fYu0}N literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..443c73e444b195ca8aaf90f77707a87405bd379a GIT binary patch literal 1727 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 F1OV(@6C(fs literal 0 HcmV?d00001 diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index fcb510ccf08..c4a49064b60 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -24,6 +24,7 @@ mockfiles/ScaleRod.qml mockfiles/ScaleGizmo.qml mockfiles/ToolBarButton.qml + mockfiles/ToggleButton.qml mockfiles/RotateGizmo.qml mockfiles/RotateRing.qml mockfiles/SelectionBox.qml @@ -68,5 +69,17 @@ mockfiles/images/fit_active@2x.png mockfiles/images/fit_selected.png mockfiles/images/fit_selected@2x.png + mockfiles/images/local.png + mockfiles/images/local@2x.png + mockfiles/images/global.png + mockfiles/images/global@2x.png + mockfiles/images/ortho.png + mockfiles/images/ortho@2x.png + mockfiles/images/persp.png + mockfiles/images/persp@2x.png + mockfiles/images/edit_light_off.png + mockfiles/images/edit_light_off@2x.png + mockfiles/images/edit_light_on.png + mockfiles/images/edit_light_on@2x.png From 21865fed296d5a605c8ae8d88768e87360049d3c Mon Sep 17 00:00:00 2001 From: Knud Dollereder Date: Tue, 26 Nov 2019 14:55:34 +0100 Subject: [PATCH 30/37] Enable Antialiasing for the curve-editor Add missing include Task-number: QDS-1227 Change-Id: I8a7160b1a85152a721fd1b24b6dcbb541dc192c2 Reviewed-by: Thomas Hartmann --- .../qmldesigner/components/curveeditor/detail/graphicsview.cpp | 1 + .../components/itemlibrary/itemlibraryassetimporter.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp index f225128a01b..b0f0c7637fa 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp @@ -54,6 +54,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent) setScene(&m_scene); setAlignment(Qt::AlignLeft | Qt::AlignVCenter); setResizeAnchor(QGraphicsView::NoAnchor); + setRenderHint(QPainter::Antialiasing, true); setTransformationAnchor(QGraphicsView::NoAnchor); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h index 76af5b80139..67b36c6e72b 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h @@ -24,6 +24,7 @@ ****************************************************************************/ #pragma once +#include #include #include #include From 60e4c629126e29b0c12cbd993dce861e3629b428 Mon Sep 17 00:00:00 2001 From: Richard Weickelt Date: Tue, 26 Nov 2019 13:08:54 +0100 Subject: [PATCH 31/37] Update Qbs submodule Change-Id: Ia0e9effcb6332db340c724a2f849156a4d6d6118 Reviewed-by: Christian Kandeler --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index de04ecbbf59..491b293b07e 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit de04ecbbf59b361320a174ee0117c2cfa8c10012 +Subproject commit 491b293b07e59f69f2c8d9721ac6a098844d590d From 3e72fd9f4535f68815ef53a92cf97091302b6048 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 27 Nov 2019 11:02:48 +0100 Subject: [PATCH 32/37] ClangTools: Fix converting old settings on Windows As the settings keys are case-insensitive on Windows, the condition s->value(oldDiagnosticConfigIdKey).isNull() in ClangToolsSettings::readSettings always evaluated to true, leaving inconsistent settings around (new and old). As a result, the QTC_ASSERT parallelRuns >= 1 was triggered in ClangToolRunWorker::start() and nothing was analyzed. Fix by using a truly different settings key after conversion. Change-Id: I467f7d71298f240812a56dfcf7d6ca81728dee32 Reviewed-by: Cristian Adam Reviewed-by: David Schulz --- src/plugins/clangtools/clangtoolssettings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/clangtools/clangtoolssettings.h b/src/plugins/clangtools/clangtoolssettings.h index 36da00d2932..aaa52011b10 100644 --- a/src/plugins/clangtools/clangtoolssettings.h +++ b/src/plugins/clangtools/clangtoolssettings.h @@ -34,7 +34,7 @@ namespace ClangTools { namespace Internal { -const char diagnosticConfigIdKey[] = "DiagnosticConfigId"; +const char diagnosticConfigIdKey[] = "DiagnosticConfig"; class RunSettings { From 2ca150c097eac0aa224d8f0f1a73124a2403d12f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 27 Nov 2019 11:38:01 +0100 Subject: [PATCH 33/37] ClangTools: Fix showing diagnostics from clang-tidy on Windows When reading file paths from clang-tidy's YAML files, ensure to clean/normalize the file paths. Otherwise, no diagnostics will be shown as they are not accepted by the is-file-part-of-project filter. Change-Id: Iacff9ab5611072ca0b19788f6861f73c244258cc Reviewed-by: Cristian Adam Reviewed-by: David Schulz --- src/plugins/clangtools/clangtoolslogfilereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/clangtools/clangtoolslogfilereader.cpp b/src/plugins/clangtools/clangtoolslogfilereader.cpp index 1fe490a6bf3..8c4211544b2 100644 --- a/src/plugins/clangtools/clangtoolslogfilereader.cpp +++ b/src/plugins/clangtools/clangtoolslogfilereader.cpp @@ -347,7 +347,7 @@ public: int extraOffset = 0) : m_node(node) , m_fileCache(fileCache) - , m_filePath(asString(node["FilePath"])) + , m_filePath(QDir::cleanPath(asString(node["FilePath"]))) , m_fileOffsetKey(fileOffsetKey) , m_extraOffset(extraOffset) {} From b2f5ed78e187fe57308549dde306563c7a9520e3 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 25 Nov 2019 10:09:21 +0100 Subject: [PATCH 34/37] ClangTools: Add "go to project settings" toolbar button With the introduction of the "Analyze Current File" action the widget to configure the diagnostic config was moved to the project panel (Project mode > Project Settings > Clang Tools). As not too many users are aware of the project settings there and navigating there involves more user interation now (mode switch, looking for the "Clang Tools" item), add a toolbar button as a shortcut. Change-Id: I4c864045ef41ff501d925d3175ce604def213f29 Reviewed-by: hjk Reviewed-by: Leena Miettinen Reviewed-by: Christian Kandeler --- src/plugins/clangtools/clangtool.cpp | 11 ++++++++++ src/plugins/clangtools/clangtool.h | 1 + src/plugins/clangtools/clangtoolsconstants.h | 2 ++ src/plugins/clangtools/clangtoolsplugin.cpp | 10 ++++++++- src/plugins/clangtools/clangtoolsplugin.h | 4 ++++ .../projectexplorer/projectexplorer.cpp | 6 +++++ src/plugins/projectexplorer/projectexplorer.h | 2 ++ .../projectexplorer/projectpanelfactory.cpp | 10 +++++++++ .../projectexplorer/projectpanelfactory.h | 6 +++++ src/plugins/projectexplorer/projectwindow.cpp | 22 +++++++++++++++++++ src/plugins/projectexplorer/projectwindow.h | 4 ++++ 11 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp index 607b78680cd..780a38c4ffa 100644 --- a/src/plugins/clangtools/clangtool.cpp +++ b/src/plugins/clangtools/clangtool.cpp @@ -33,6 +33,7 @@ #include "clangtoolsdiagnosticmodel.h" #include "clangtoolsdiagnosticview.h" #include "clangtoolslogfilereader.h" +#include "clangtoolsplugin.h" #include "clangtoolsprojectsettings.h" #include "clangtoolssettings.h" #include "clangtoolsutils.h" @@ -399,6 +400,15 @@ ClangTool::ClangTool() ApplyFixIts(diagnosticItems).apply(m_diagnosticModel); }); + // Open Project Settings + action = new QAction(this); + action->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon()); + //action->setToolTip(tr("Open Project Settings")); // TODO: Uncomment in master. + connect(action, &QAction::triggered, []() { + ProjectExplorerPlugin::activateProjectPanel(Constants::PROJECT_PANEL_ID); + }); + m_openProjectSettings = action; + ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER); const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the " "Clang project to search for diagnostics."); @@ -424,6 +434,7 @@ ClangTool::ClangTool() m_perspective.addToolBarAction(m_startAction); m_perspective.addToolBarAction(m_startOnCurrentFileAction); m_perspective.addToolBarAction(m_stopAction); + m_perspective.addToolBarAction(m_openProjectSettings); m_perspective.addToolBarAction(m_loadExported); m_perspective.addToolBarAction(m_clear); m_perspective.addToolBarAction(m_goBack); diff --git a/src/plugins/clangtools/clangtool.h b/src/plugins/clangtools/clangtool.h index bde31d355dc..d994a6b2f9c 100644 --- a/src/plugins/clangtools/clangtool.h +++ b/src/plugins/clangtools/clangtool.h @@ -129,6 +129,7 @@ private: Utils::FancyLineEdit *m_filterLineEdit = nullptr; QToolButton *m_applyFixitsButton = nullptr; + QAction *m_openProjectSettings = nullptr; QAction *m_goBack = nullptr; QAction *m_goNext = nullptr; QAction *m_loadExported = nullptr; diff --git a/src/plugins/clangtools/clangtoolsconstants.h b/src/plugins/clangtools/clangtoolsconstants.h index a3da1d78f54..8f09865b1c1 100644 --- a/src/plugins/clangtools/clangtoolsconstants.h +++ b/src/plugins/clangtools/clangtoolsconstants.h @@ -28,6 +28,8 @@ namespace ClangTools { namespace Constants { +const char PROJECT_PANEL_ID[] = "ClangTools"; + const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject"; const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile"; diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp index cdcda4d3c6e..b53901e95ac 100644 --- a/src/plugins/clangtools/clangtoolsplugin.cpp +++ b/src/plugins/clangtools/clangtoolsplugin.cpp @@ -67,6 +67,13 @@ using namespace ProjectExplorer; namespace ClangTools { namespace Internal { +static ProjectPanelFactory *m_projectPanelFactoryInstance = nullptr; + +ProjectPanelFactory *projectPanelFactory() +{ + return m_projectPanelFactoryInstance; +} + class ClangToolsOptionsPage : public IOptionsPage { public: @@ -123,8 +130,9 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(), Constants::RUN_ON_CURRENT_FILE); - auto panelFactory = new ProjectPanelFactory(); + auto panelFactory = m_projectPanelFactoryInstance = new ProjectPanelFactory; panelFactory->setPriority(100); + panelFactory->setId(Constants::PROJECT_PANEL_ID); panelFactory->setDisplayName(tr("Clang Tools")); panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); }); ProjectPanelFactory::registerFactory(panelFactory); diff --git a/src/plugins/clangtools/clangtoolsplugin.h b/src/plugins/clangtools/clangtoolsplugin.h index 7f24d79f4bc..30c28b276b9 100644 --- a/src/plugins/clangtools/clangtoolsplugin.h +++ b/src/plugins/clangtools/clangtoolsplugin.h @@ -27,9 +27,13 @@ #include +namespace ProjectExplorer { class ProjectPanelFactory; } + namespace ClangTools { namespace Internal { +ProjectExplorer::ProjectPanelFactory *projectPanelFactory(); + class ClangToolsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 30fdbcc58a0..96f46a11c9e 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3903,6 +3903,12 @@ void ProjectExplorerPlugin::updateActions() dd->updateActions(); } +void ProjectExplorerPlugin::activateProjectPanel(Core::Id panelId) +{ + Core::ModeManager::activateMode(Constants::MODE_SESSION); + dd->m_proWindow->activateProjectPanel(panelId); +} + QList > ProjectExplorerPlugin::recentProjects() { return dd->recentProjects(); diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index feb53ccdef2..5b1617e1828 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -172,6 +172,8 @@ public: static void updateActions(); + static void activateProjectPanel(Core::Id panelId); + signals: void finishedInitialization(); diff --git a/src/plugins/projectexplorer/projectpanelfactory.cpp b/src/plugins/projectexplorer/projectpanelfactory.cpp index d734b8d336d..c4eaef05b4c 100644 --- a/src/plugins/projectexplorer/projectpanelfactory.cpp +++ b/src/plugins/projectexplorer/projectpanelfactory.cpp @@ -80,6 +80,16 @@ void ProjectPanelFactory::destroyFactories() s_factories.clear(); } +Core::Id ProjectPanelFactory::id() const +{ + return m_id; +} + +void ProjectPanelFactory::setId(Core::Id id) +{ + m_id = id; +} + QString ProjectPanelFactory::icon() const { return m_icon; diff --git a/src/plugins/projectexplorer/projectpanelfactory.h b/src/plugins/projectexplorer/projectpanelfactory.h index 27e643b0ed2..6d031253982 100644 --- a/src/plugins/projectexplorer/projectpanelfactory.h +++ b/src/plugins/projectexplorer/projectpanelfactory.h @@ -30,6 +30,8 @@ #include "panelswidget.h" #include "projectwindow.h" +#include + #include #include @@ -44,6 +46,9 @@ class PROJECTEXPLORER_EXPORT ProjectPanelFactory public: ProjectPanelFactory(); + Core::Id id() const; + void setId(Core::Id id); + // simple properties QString displayName() const; void setDisplayName(const QString &name); @@ -78,6 +83,7 @@ private: friend class ProjectExplorerPlugin; static void destroyFactories(); + Core::Id m_id; int m_priority = 0; QString m_displayName; SupportsFunction m_supportsFunction; diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index dfa20793e31..d72f7812ffe 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -84,6 +84,8 @@ public: Qt::ItemFlags flags(int column) const override; bool setData(int column, const QVariant &, int role) override; + ProjectPanelFactory *factory() const { return m_factory; } + protected: ProjectPanelFactory *m_factory = nullptr; QPointer m_project; @@ -281,6 +283,13 @@ public: return activeItem ? activeItem->index() : QModelIndex(); } + TreeItem *itemForProjectPanel(Core::Id panelId) + { + return m_miscItem->findChildAtLevel(1, [panelId](const TreeItem *item){ + return static_cast(item)->factory()->id() == panelId; + }); + } + private: int m_currentChildIndex = 0; // Start with Build & Run. Project *m_project = nullptr; @@ -497,6 +506,14 @@ public: item->setData(0, QVariant(), ItemActivatedDirectlyRole); } + void activateProjectPanel(Core::Id panelId) + { + if (ProjectItem *projectItem = m_projectsModel.rootItem()->childAt(0)) { + if (TreeItem *item = projectItem->itemForProjectPanel(panelId)) + itemActivated(item->index()); + } + } + void openContextMenu(const QPoint &pos) { QMenu menu; @@ -606,6 +623,11 @@ ProjectWindow::ProjectWindow() setContextMenuPolicy(Qt::CustomContextMenu); } +void ProjectWindow::activateProjectPanel(Core::Id panelId) +{ + d->activateProjectPanel(panelId); +} + ProjectWindow::~ProjectWindow() = default; QSize SelectorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h index 1aeeb882f92..01840951ab1 100644 --- a/src/plugins/projectexplorer/projectwindow.h +++ b/src/plugins/projectexplorer/projectwindow.h @@ -31,6 +31,8 @@ #include +namespace Core { class Id; } + namespace ProjectExplorer { namespace Internal { @@ -60,6 +62,8 @@ public: ProjectWindow(); ~ProjectWindow() override; + void activateProjectPanel(Core::Id panelId); + private: const std::unique_ptr d; }; From 2ebffd3eaf4e2660dfe6c6fc5c8328c682fae351 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 27 Nov 2019 15:21:48 +0100 Subject: [PATCH 35/37] QmlDesigner: Fix RealSpinBoxInput Fixes RealSpinBoxInput scroll behavior. Without this change the RealSpinBox would block the ScrollView from getting mouse wheel events, which means whenever the mouse is hovering over a RealSpinBox the ScrollView can't be scrolled via the mouse wheel. Change-Id: I4533e36700fc2652a9c246a0e30613c71258edaf Reviewed-by: Thomas Hartmann --- .../imports/StudioControls/RealSpinBoxInput.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml index 72a713c2820..98c592f1126 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml @@ -193,6 +193,7 @@ TextInput { PropertyChanges { target: mouseArea cursorShape: Qt.PointingHandCursor + enabled: false } }, State { From 7cf6632d7d0b23fa78bc770fee8b4ce76e052383 Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Wed, 27 Nov 2019 16:05:34 +0100 Subject: [PATCH 36/37] QmlDesigner Binding Editor UX improvement Binding Editor now shows which property type it expects. Binding Editor now works with alias and unknown types. Change-Id: I23d0bed3db5126de5107cf2f1f6b46485b89e1ea Reviewed-by: Thomas Hartmann --- .../bindingeditor/bindingeditor.cpp | 31 +++++++++++++++++-- .../components/bindingeditor/bindingeditor.h | 1 + .../bindingeditor/bindingeditordialog.cpp | 7 ++++- .../bindingeditor/bindingeditordialog.h | 3 ++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp index a6fcffa3fbf..fe3871c6c16 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp @@ -102,9 +102,16 @@ void BindingEditor::setBackendValue(const QVariant &backendValue) m_backendValue = backendValue; const QObject *backendValueObj = backendValue.value(); const PropertyEditorValue *propertyEditorValue = qobject_cast(backendValueObj); + const ModelNode node = propertyEditorValue->modelNode(); - m_backendValueTypeName = propertyEditorValue->modelNode().metaInfo().propertyTypeName( - propertyEditorValue->name()); + if (node.isValid()) + { + m_backendValueTypeName = node.metaInfo().propertyTypeName(propertyEditorValue->name()); + + if (m_backendValueTypeName == "alias" || m_backendValueTypeName == "unknown") + if (QmlObjectNode::isValidQmlObjectNode(node)) + m_backendValueTypeName = QmlObjectNode(node).instanceType(propertyEditorValue->name()); + } emit backendValueChanged(); } @@ -154,8 +161,16 @@ void BindingEditor::prepareBindings() for (auto objnode : allNodes) { BindingEditorDialog::BindingOption binding; for (auto propertyName : objnode.metaInfo().propertyNames()) - if (m_backendValueTypeName == objnode.metaInfo().propertyTypeName(propertyName)) + { + TypeName propertyTypeName = objnode.metaInfo().propertyTypeName(propertyName); + + if ((propertyTypeName == "alias" || propertyTypeName == "unknown")) + if (QmlObjectNode::isValidQmlObjectNode(objnode)) + propertyTypeName = QmlObjectNode(objnode).instanceType(propertyName); + + if (m_backendValueTypeName == propertyTypeName) binding.properties.append(QString::fromUtf8(propertyName)); + } if (!binding.properties.isEmpty() && objnode.hasId()) { binding.item = objnode.displayName(); @@ -165,6 +180,16 @@ void BindingEditor::prepareBindings() if (!bindings.isEmpty() && !m_dialog.isNull()) m_dialog->setAllBindings(bindings); + + updateWindowName(); +} + +void BindingEditor::updateWindowName() +{ + if (!m_dialog.isNull() && !m_backendValueTypeName.isEmpty()) + { + m_dialog->setWindowTitle(m_dialog->defaultTitle() + " [" + m_backendValueTypeName + "]"); + } } QVariant BindingEditor::backendValue() const diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h index 5da06d2ecf0..8f9a77baec1 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h @@ -62,6 +62,7 @@ public: void setStateModelNode(const QVariant &stateModelNode); Q_INVOKABLE void prepareBindings(); + Q_INVOKABLE void updateWindowName(); signals: void accepted(); diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp index 08cb5d8bd36..51bd771843a 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp @@ -45,7 +45,7 @@ BindingEditorDialog::BindingEditorDialog(QWidget *parent) : QDialog(parent) { setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setWindowTitle(tr("Binding Editor")); + setWindowTitle(defaultTitle()); setModal(false); setupJSEditor(); @@ -153,6 +153,11 @@ void BindingEditorDialog::unregisterAutoCompletion() m_editorWidget->unregisterAutoCompletion(); } +QString BindingEditorDialog::defaultTitle() const +{ + return titleString; +} + void BindingEditorDialog::setupJSEditor() { static BindingEditorFactory f; diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h index f1b224a716f..6cb0c003610 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h @@ -71,6 +71,8 @@ public: void unregisterAutoCompletion(); + QString defaultTitle() const; + private: void setupJSEditor(); void setupUIComponents(); @@ -92,6 +94,7 @@ private: QList m_bindings; bool m_lock = false; const QString undefinedString = {"[Undefined]"}; + const QString titleString = {tr("Binding Editor")}; }; } From 6b1d54421e3831576c8d169bf38caf1ab503c84a Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Wed, 27 Nov 2019 17:10:21 +0100 Subject: [PATCH 37/37] QmlDesigner Removed some debug output Change-Id: Iaa03c5783cc76b94364eda184d439024c35c4102 Reviewed-by: Thomas Hartmann --- .../imports/HelperWidgets/FontSection.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml index 6cbc8a77c00..a97923a032c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml @@ -41,7 +41,6 @@ Section { function getBackendValue(name) { - print(fontSection.fontName + "_" + name) return backendValues[fontSection.fontName + "_" + name] }