Merge remote-tracking branch 'origin/4.11'

Conflicts:
	src/plugins/designer/codemodelhelpers.cpp

Change-Id: I78906f2fbbfd27d254589a272ebca423b0b80699
This commit is contained in:
Eike Ziller
2019-11-28 08:24:10 +01:00
125 changed files with 2380 additions and 881 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -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.

View File

@@ -57,6 +57,10 @@
To reset the changes that you made, select \uicontrol Reset.
To reconfigure CMake, select \uicontrol Build >
\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

View File

@@ -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

View File

@@ -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

View File

@@ -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}.

View File

@@ -46,7 +46,7 @@ Node {
}
Connections {
target: designStudioNativeCameraControlHelper
target: _generalHelper
onOverlayUpdateNeeded: updateScale()
}
@@ -81,6 +81,7 @@ Node {
MouseArea3D {
id: helper
active: false
view3D: overlayNode.view3D
}
}

View File

@@ -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()
}
}

View File

@@ -23,40 +23,48 @@
**
****************************************************************************/
#pragma once
import QtQuick 2.0
import QtQuick3D 1.0
#include <QtCore/QObject>
#include <QtCore/QTimer>
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
namespace QmlDesigner {
namespace Internal {
class CameraControlHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Model {
id: posModel
public:
CameraControlHelper();
property bool hovering: false
property vector3d cameraRotation: armRoot.camRotPos
bool enabled();
void setEnabled(bool enabled);
source: "meshes/axishelper.mesh"
materials: DefaultMaterial {
id: posMat
emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
}
Q_INVOKABLE void requestOverlayUpdate();
Q_INVOKABLE QString generateUniqueName(const QString &nameRoot);
Model {
id: negModel
public slots:
void handleUpdateTimer();
signals:
void updateInputs();
void enabledChanged(bool enabled);
void overlayUpdateNeeded();
private:
bool m_enabled = false;
QTimer m_inputUpdateTimer;
QTimer m_overlayUpdateTimer;
};
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
}
}

View File

@@ -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
}
]
}

View File

@@ -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 {

View File

@@ -0,0 +1,128 @@
/****************************************************************************
**
** 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 View3D view3d: 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 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,
_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);
}
}
}

View File

@@ -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
@@ -39,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
@@ -56,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)
@@ -69,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;});
}
}
@@ -78,13 +82,13 @@ 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,
"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;});
}
@@ -92,10 +96,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 +118,7 @@ Window {
clipNear: editOrthoCamera.clipNear
position: editOrthoCamera.position
rotation: editOrthoCamera.rotation
scale: editOrthoCamera.scale
}
MoveGizmo {
@@ -123,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
@@ -138,7 +143,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
@@ -153,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
@@ -169,16 +174,19 @@ 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,
eventPoint.scenePosition.y);
emitObjectClicked(pickResult.objectHit);
handleObjectClicked(pickResult.objectHit);
}
}
@@ -200,6 +208,12 @@ Window {
step: 50
}
SelectionBox {
id: selectionBox
view3D: editView
targetNode: viewWindow.selectedNode
}
PointLight {
id: editLight
visible: showEditLight
@@ -209,11 +223,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,10 +238,10 @@ Window {
OrthographicCamera {
id: editOrthoCamera
z: -600
y: 200
rotation.x: 30
y: 600
rotation.x: 45
clipFar: 100000
clipNear: 1
clipNear: -10000
}
}
}
@@ -240,14 +257,12 @@ Window {
id: gizmoLabel
targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
targetView: overlayView
offsetX: 0
offsetY: 45
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
@@ -273,19 +288,11 @@ 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
view3d: editView
}
}
@@ -301,7 +308,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
@@ -310,7 +318,7 @@ Window {
shortcut: "Q"
currentShortcut: selected ? "" : shortcut
tool: "item_selection"
buttonsGroup: col.group
buttonsGroup: col.groupSelect
}
ToolBarButton {
@@ -319,7 +327,7 @@ Window {
shortcut: "Q"
currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut
tool: "group_selection"
buttonsGroup: col.group
buttonsGroup: col.groupSelect
}
Rectangle { // separator
@@ -331,11 +339,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 {
@@ -344,60 +353,96 @@ 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) {
var targetNode = viewWindow.selectedNode ? selectionBox.model : null;
cameraControl.fitObject(targetNode, editView.camera.rotation);
}
}
}
}
}
Column {
y: 8
AxisHelper {
anchors.right: parent.right
CheckBox {
id: editLightCheckbox
checked: false
text: qsTr("Use Edit View Light")
onCheckedChanged: cameraControl.forceActiveFocus()
anchors.top: parent.top
width: 100
height: width
editCameraCtrl: cameraControl
selectedNode : viewWindow.selectedNode ? selectionBox.model : null
}
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();
}
Rectangle { // top controls bar
color: "#aa000000"
width: 265
height: btnPerspective.height + 10
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 100
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")}]
}
CheckBox {
id: globalControl
checked: true
text: qsTr("Use Global Orientation")
onCheckedChanged: cameraControl.forceActiveFocus()
ToggleButton {
id: btnLocalGlobal
anchors.top: parent.top
anchors.topMargin: 5
anchors.left: parent.left
anchors.leftMargin: 100
tooltip: qsTr("Toggle Global / Local Orientation")
states: [{iconId: "local", text: qsTr("Local")}, {iconId: "global", text: qsTr("Global")}]
}
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")}]
}
}
Text {
id: helpText
text: qsTr("Camera: W,A,S,D,R,F,right mouse drag")
color: "white"
text: qsTr("Camera controls: ALT + mouse press and drag. Left: Rotate, Middle: Pan, Right/Wheel: Zoom.")
anchors.bottom: parent.bottom
}
}

View File

@@ -45,7 +45,7 @@ Node {
materials: [
DefaultMaterial {
id: mainGridMaterial
emissiveColor: "#e6e6e6"
emissiveColor: "#cccccc"
lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling
}

View File

@@ -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,30 +45,25 @@ 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
visible: iconGizmo.visible && !isBehindCamera
parent: view3D
Rectangle {
id: iconRect
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
@@ -81,6 +77,15 @@ Node {
? Qt.LeftButton : Qt.NoButton
}
}
ColorOverlay {
id: colorOverlay
anchors.fill: parent
cached: true
source: iconImage
color: "transparent"
opacity: 0.6
}
}
}
}

View File

@@ -29,14 +29,13 @@ 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
? 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 ? targetNode.color : "transparent"
}

View File

@@ -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
@@ -49,14 +48,16 @@ Item {
}
Connections {
target: designStudioNativeCameraControlHelper
target: _generalHelper
onOverlayUpdateNeeded: updateOverlay()
}
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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;
}

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** 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
property alias model: selectionBoxModel
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 && !selectionBoxGeometry.isEmpty
materials: [
DefaultMaterial {
emissiveColor: "#fff600"
lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling
}
]
}
}

View File

@@ -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
}
}

View File

@@ -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);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -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 <QHash>
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<QString, int> counters;
int count = counters[nameRoot]++;
return QStringLiteral("%1_%2").arg(nameRoot).arg(count);
}
}
}

View File

@@ -1,9 +1,11 @@
HEADERS += $$PWD/cameracontrolhelper.h \
HEADERS += $$PWD/generalhelper.h \
$$PWD/mousearea3d.h \
$$PWD/camerageometry.h \
$$PWD/gridgeometry.h
$$PWD/gridgeometry.h \
$$PWD/selectionboxgeometry.h
SOURCES += $$PWD/cameracontrolhelper.cpp \
SOURCES += $$PWD/generalhelper.cpp \
$$PWD/mousearea3d.cpp \
$$PWD/camerageometry.cpp \
$$PWD/gridgeometry.cpp
$$PWD/gridgeometry.cpp \
$$PWD/selectionboxgeometry.cpp

View File

@@ -0,0 +1,210 @@
/****************************************************************************
**
** 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 "selectionboxgeometry.h"
#include <QtQuick3D/private/qquick3dorthographiccamera_p.h>
#include <QtQuick3D/private/qquick3dperspectivecamera_p.h>
#include <QtQuick3D/private/qquick3dobject_p_p.h>
#include <QtQuick3D/private/qquick3dcamera_p.h>
#include <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
#include <QtQuick/qquickwindow.h>
#include <QtCore/qmath.h>
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<QString, int> 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 &currentPos)
{
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 &currentPos,
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<QQuick3DOrthographicCamera *>(camera)) {
// Ortho camera we can simply scale
camera->setScale(QVector3D(newZoomFactor, newZoomFactor, newZoomFactor));
} else if (qobject_cast<QQuick3DPerspectiveCamera *>(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;
}
// 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<QQuick3DModel *>(targetObject)) {
auto targetPriv = QQuick3DObjectPrivate::get(targetObject);
if (auto renderModel = static_cast<QSSGRenderModel *>(targetPriv->spatialNode)) {
QWindow *window = static_cast<QWindow *>(viewPort->window());
if (window) {
auto context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window));
if (!context.isNull()) {
QSSGBounds3 bounds;
auto geometry = qobject_cast<SelectionBoxGeometry *>(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();
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
lookAt = renderModel->globalTransform.map(center);
lookAt.setZ(-lookAt.z()); // Render node transforms have inverted z
}
}
}
}
// 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));
}
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);
});
}
}
}
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** 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 <QtCore/qobject.h>
#include <QtCore/qtimer.h>
#include <QtCore/qhash.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qmatrix4x4.h>
QT_BEGIN_NAMESPACE
class QQuick3DCamera;
class QQuick3DNode;
class QQuick3DViewport;
QT_END_NAMESPACE
namespace QmlDesigner {
namespace Internal {
class GeneralHelper : public QObject
{
Q_OBJECT
public:
GeneralHelper();
Q_INVOKABLE void requestOverlayUpdate();
Q_INVOKABLE QString generateUniqueName(const QString &nameRoot);
Q_INVOKABLE void orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation,
const QVector3D &lookAtPoint, const QVector3D &pressPos,
const QVector3D &currentPos);
Q_INVOKABLE QVector3D panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform,
const QVector3D &startPosition, const QVector3D &startLookAt,
const QVector3D &pressPos, const QVector3D &currentPos,
float zoomFactor);
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);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
signals:
void overlayUpdateNeeded();
private:
QTimer m_overlayUpdateTimer;
};
}
}
#endif // QUICK3D_MODULE

View File

@@ -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)
@@ -124,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();
}
@@ -133,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();
}
@@ -340,7 +353,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 +410,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();

View File

@@ -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.;

View File

@@ -0,0 +1,336 @@
/****************************************************************************
**
** 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 <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
#include <QtQuick3D/private/qquick3dobject_p_p.h>
#include <QtQuick/qquickwindow.h>
#include <QtCore/qvector.h>
#include <limits>
namespace QmlDesigner {
namespace Internal {
SelectionBoxGeometry::SelectionBoxGeometry()
: QQuick3DGeometry()
{
}
SelectionBoxGeometry::~SelectionBoxGeometry()
{
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
}
QQuick3DNode *SelectionBoxGeometry::targetNode() const
{
return m_targetNode;
}
QQuick3DNode *SelectionBoxGeometry::rootNode() const
{
return m_rootNode;
}
QQuick3DViewport *SelectionBoxGeometry::view3D() const
{
return m_view3D;
}
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)
return;
if (m_targetNode)
m_targetNode->disconnect(this);
m_targetNode = targetNode;
if (auto model = qobject_cast<QQuick3DModel *>(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<QSSGRenderGeometry *>(node);
geometry->clear();
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
QByteArray vertexData;
QByteArray indexData;
static const float floatMin = std::numeric_limits<float>::lowest();
static const float floatMax = std::numeric_limits<float>::max();
QVector3D minBounds = QVector3D(floatMax, floatMax, floatMax);
QVector3D maxBounds = QVector3D(floatMin, floatMin, floatMin);
if (m_targetNode) {
auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode);
auto targetPriv = QQuick3DObjectPrivate::get(m_targetNode);
auto rootRN = static_cast<QSSGRenderNode *>(rootPriv->spatialNode);
auto targetRN = static_cast<QSSGRenderNode *>(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();
}
getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds, QMatrix4x4());
} else {
// Fill some dummy data so geometry won't get rejected
appendVertexData(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);
m_bounds = QSSGBounds3(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::getBounds(QQuick3DNode *node, QByteArray &vertexData,
QByteArray &indexData, QVector3D &minBounds,
QVector3D &maxBounds, const QMatrix4x4 &transform)
{
QMatrix4x4 fullTransform;
auto nodePriv = QQuick3DObjectPrivate::get(node);
auto renderNode = static_cast<QSSGRenderNode *>(nodePriv->spatialNode);
// 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<QVector3D> minBoundsVec;
QVector<QVector3D> maxBoundsVec;
// Check for children
const auto children = node->childItems();
for (const auto child : children) {
if (auto childNode = qobject_cast<QQuick3DNode *>(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<QQuick3DModel *>(node)) {
if (auto renderModel = static_cast<QSSGRenderModel *>(renderNode)) {
QWindow *window = static_cast<QWindow *>(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<float *>(vertexData.data() + initialVertexSize);
auto indexPtr = reinterpret_cast<quint16 *>(indexData.data() + initialIndexSize);
*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 + indexAdd; *indexPtr++ = 1 + indexAdd;
*indexPtr++ = 1 + indexAdd; *indexPtr++ = 2 + indexAdd;
*indexPtr++ = 2 + indexAdd; *indexPtr++ = 3 + indexAdd;
*indexPtr++ = 3 + indexAdd; *indexPtr++ = 0 + indexAdd;
*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 + indexAdd; *indexPtr++ = 5 + indexAdd;
*indexPtr++ = 5 + indexAdd; *indexPtr++ = 6 + indexAdd;
*indexPtr++ = 6 + indexAdd; *indexPtr++ = 7 + indexAdd;
*indexPtr++ = 7 + indexAdd; *indexPtr++ = 4 + indexAdd;
}
}
}
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** 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 <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
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)
Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
public:
SelectionBoxGeometry();
~SelectionBoxGeometry() override;
QQuick3DNode *targetNode() const;
QQuick3DNode *rootNode() const;
QQuick3DViewport *view3D() const;
bool isEmpty() const;
QSSGBounds3 bounds() const;
public Q_SLOTS:
void setTargetNode(QQuick3DNode *targetNode);
void setRootNode(QQuick3DNode *rootNode);
void setView3D(QQuick3DViewport *view);
Q_SIGNALS:
void targetNodeChanged();
void rootNodeChanged();
void view3DChanged();
void isEmptyChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
private:
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<QMetaObject::Connection> m_connections;
QSSGBounds3 m_bounds;
};
}
}
QML_DECLARE_TYPE(QmlDesigner::Internal::SelectionBoxGeometry)
#endif // QUICK3D_MODULE

View File

@@ -62,10 +62,11 @@
#include <drop3dlibraryitemcommand.h>
#include "dummycontextobject.h"
#include "../editor3d/cameracontrolhelper.h"
#include "../editor3d/generalhelper.h"
#include "../editor3d/mousearea3d.h"
#include "../editor3d/camerageometry.h"
#include "../editor3d/gridgeometry.h"
#include "../editor3d/selectionboxgeometry.h"
#include <designersupportdelegate.h>
@@ -104,13 +105,13 @@ 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<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
#endif
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
@@ -136,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;
}
@@ -336,13 +340,25 @@ 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<QObject *>();
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<QObject *>();
}
}
return nullptr;
}
@@ -599,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

View File

@@ -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<QQuick3DNode *>(instance.internalObject()))
return static_cast<Quick3DNodeInstance *>(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

View File

@@ -53,6 +53,7 @@ protected:
private:
Qt5NodeInstanceServer *qt5NodeInstanceServer() const;
QQuick3DNode *quick3DNode() const;
void setPickable(bool enable, bool checkParent, bool applyToChildren);
};
} // namespace Internal

View File

@@ -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 {

View File

@@ -8,6 +8,7 @@
<file>mockfiles/GenericBackend.qml</file>
<file>mockfiles/Dialog.qml</file>
<file>mockfiles/EditView3D.qml</file>
<file>mockfiles/EditCameraController.qml</file>
<file>mockfiles/Arrow.qml</file>
<file>mockfiles/AutoScaleHelper.qml</file>
<file>mockfiles/MoveGizmo.qml</file>
@@ -23,12 +24,17 @@
<file>mockfiles/ScaleRod.qml</file>
<file>mockfiles/ScaleGizmo.qml</file>
<file>mockfiles/ToolBarButton.qml</file>
<file>mockfiles/ToggleButton.qml</file>
<file>mockfiles/RotateGizmo.qml</file>
<file>mockfiles/RotateRing.qml</file>
<file>mockfiles/SelectionBox.qml</file>
<file>mockfiles/AxisHelper.qml</file>
<file>mockfiles/AxisHelperArm.qml</file>
<file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file>
<file>mockfiles/meshes/ringselect.mesh</file>
<file>mockfiles/meshes/axishelper.mesh</file>
<file>mockfiles/images/editor_camera.png</file>
<file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/light-pick-icon.png</file>
@@ -53,5 +59,27 @@
<file>mockfiles/images/scale_active@2x.png</file>
<file>mockfiles/images/scale_selected.png</file>
<file>mockfiles/images/scale_selected@2x.png</file>
<file>mockfiles/images/directional_light_gradient.png</file>
<file>mockfiles/images/directional_light_gradient@2x.png</file>
<file>mockfiles/images/point_light_gradient.png</file>
<file>mockfiles/images/point_light_gradient@2x.png</file>
<file>mockfiles/images/area_light_gradient.png</file>
<file>mockfiles/images/area_light_gradient@2x.png</file>
<file>mockfiles/images/fit_active.png</file>
<file>mockfiles/images/fit_active@2x.png</file>
<file>mockfiles/images/fit_selected.png</file>
<file>mockfiles/images/fit_selected@2x.png</file>
<file>mockfiles/images/local.png</file>
<file>mockfiles/images/local@2x.png</file>
<file>mockfiles/images/global.png</file>
<file>mockfiles/images/global@2x.png</file>
<file>mockfiles/images/ortho.png</file>
<file>mockfiles/images/ortho@2x.png</file>
<file>mockfiles/images/persp.png</file>
<file>mockfiles/images/persp@2x.png</file>
<file>mockfiles/images/edit_light_off.png</file>
<file>mockfiles/images/edit_light_off@2x.png</file>
<file>mockfiles/images/edit_light_on.png</file>
<file>mockfiles/images/edit_light_on@2x.png</file>
</qresource>
</RCC>

View File

@@ -41,7 +41,6 @@ Section {
function getBackendValue(name)
{
print(fontSection.fontName + "_" + name)
return backendValues[fontSection.fontName + "_" + name]
}

View File

@@ -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
@@ -242,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
@@ -250,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
}
}
]

View File

@@ -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

View File

@@ -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

View File

@@ -193,6 +193,7 @@ TextInput {
PropertyChanges {
target: mouseArea
cursorShape: Qt.PointingHandCursor
enabled: false
}
},
State {

View File

@@ -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,

View File

@@ -66,10 +66,6 @@ static QStringList clazyPluginArguments(const ClangDiagnosticConfig diagnosticCo
arguments << XclangArgs({"-add-plugin",
"clazy",
"-plugin-arg-clazy",
"enable-all-fixits",
"-plugin-arg-clazy",
"no-autowrite-fixits",
"-plugin-arg-clazy",
diagnosticConfig.clazyChecks()});
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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";

View File

@@ -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)
{}

View File

@@ -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);

View File

@@ -27,9 +27,13 @@
#include <extensionsystem/iplugin.h>
namespace ProjectExplorer { class ProjectPanelFactory; }
namespace ClangTools {
namespace Internal {
ProjectExplorer::ProjectPanelFactory *projectPanelFactory();
class ClangToolsPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT

View File

@@ -34,7 +34,7 @@
namespace ClangTools {
namespace Internal {
const char diagnosticConfigIdKey[] = "DiagnosticConfigId";
const char diagnosticConfigIdKey[] = "DiagnosticConfig";
class RunSettings
{

View File

@@ -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;
};

View File

@@ -226,22 +226,17 @@ QList<CPlusPlus::Document::Ptr> 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);
}

View File

@@ -92,8 +92,7 @@ public:
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
static bool waitUntilCppModelManagerIsAwareOf(
ProjectExplorer::Project *project,
static bool waitUntilProjectIsFullyOpened(ProjectExplorer::Project *project,
int timeOutInMs = defaultTimeOutInMs);
static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot(
const QString &filePath,

View File

@@ -40,10 +40,10 @@
using namespace ProjectExplorer;
typedef QMap<QString, QStringList> DependencyMap;
typedef CPlusPlus::Document::Ptr DocumentPtr;
typedef QList<CPlusPlus::Symbol *> SymbolList;
typedef QList<DocumentPtr> DocumentPtrList;
using DependencyMap = QMap<QString, QStringList>;
using DocumentPtr = CPlusPlus::Document::Ptr;
using SymbolList = QList<CPlusPlus::Symbol *>;
using DocumentPtrList = QList<DocumentPtr>;
static const char setupUiC[] = "setupUi";

View File

@@ -58,14 +58,14 @@ QString FormClassWizard::formSuffix() const
Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) 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<const FormClassWizardDialog *>(w);
auto wizardDialog = qobject_cast<const FormClassWizardDialog *>(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);

View File

@@ -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;

View File

@@ -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<QFrame*>(data.widgetHost))
if (auto frame = qobject_cast<QFrame*>(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<const SharedTools::WidgetHost *>(sender())) {
if (auto wh = qobject_cast<const SharedTools::WidgetHost *>(sender())) {
wh->formWindow()->setDirty(true);
static const QString geometry = "geometry";
m_designerCore->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) );

View File

@@ -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<Id>::const_iterator cend = m_toolActionIds.constEnd();
for (QList<Id>::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);

View File

@@ -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)

View File

@@ -44,9 +44,7 @@ FormWindowEditor::FormWindowEditor()
addContext(Designer::Constants::C_DESIGNER_XML_EDITOR);
}
FormWindowEditor::~FormWindowEditor()
{
}
FormWindowEditor::~FormWindowEditor() = default;
QWidget *FormWindowEditor::toolBar()
{

View File

@@ -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);

View File

@@ -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 <Class*, Document>.
typedef QPair<const Class *, Document::Ptr> ClassDocumentPtrPair;
using ClassDocumentPtrPair = QPair<const Class *, Document::Ptr>;
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 &parameterNames,
QString *errorMessage)
{
typedef QMap<int, Document::Ptr> DocumentMap;
using DocumentMap = QMap<int, Document::Ptr>;
const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath();
#if 0

View File

@@ -73,10 +73,7 @@ void ResourceHandler::ensureInitialized()
qDebug() << "ResourceHandler::ensureInitialized() origPaths=" << m_originalUiQrcPaths;
}
ResourceHandler::~ResourceHandler()
{
}
ResourceHandler::~ResourceHandler() = default;
void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
{

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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}

View File

@@ -103,7 +103,7 @@ RunWorkerFactory::WorkerCreator makeFlashAndRunWorker()
return RunWorkerFactory::make<FlashAndRunWorker>();
}
EmrunRunConfigurationFactory::EmrunRunConfigurationFactory()
McuSupportRunConfigurationFactory::McuSupportRunConfigurationFactory()
: FixedRunConfigurationFactory(FlashAndRunConfiguration::tr("Flash and run"))
{
registerRunConfiguration<FlashAndRunConfiguration>(Constants::RUNCONFIGURATION);

Some files were not shown because too many files have changed in this diff Show More