aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2019-10-28 11:48:31 +0100
committerEike Ziller <eike.ziller@qt.io>2019-10-28 11:48:31 +0100
commitbea3a8fa6fd53cf1e85aa30cc45d1e62464c985d (patch)
treec9755caff5786475c51c65cfec939ec90ab6ccd2
parent3c556096caf17cf6b09a91ebf0d262d0be3f65a1 (diff)
parent3f74b04c3072b2beb23ecdd108894da4057830fc (diff)
Merge remote-tracking branch 'origin/4.11'
-rw-r--r--doc/config/macros.qdocconf1
-rw-r--r--doc/config/qtcreator-project.qdocconf1
-rw-r--r--doc/images/icons/action-icon-binding.pngbin0 -> 417 bytes
-rw-r--r--doc/images/icons/action-icon.pngbin0 -> 273 bytes
-rw-r--r--doc/images/qmldesigner-binding-editor.pngbin4189 -> 5228 bytes
-rw-r--r--doc/images/qmldesigner-set-expression.pngbin4213 -> 10970 bytes
-rw-r--r--doc/images/qt-design-viewer.pngbin0 -> 46254 bytes
-rw-r--r--doc/images/qtcreator-mcu-options.pngbin19827 -> 18542 bytes
-rw-r--r--doc/src/mcu/creator-mcu-dev.qdoc16
-rw-r--r--doc/src/projects/creator-only/creator-projects-building.qdoc2
-rw-r--r--doc/src/qtcreator-toc.qdoc1
-rw-r--r--doc/src/qtquick/qt-design-viewer.qdoc72
-rw-r--r--doc/src/qtquick/qtquick-components.qdoc19
-rw-r--r--doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc12
-rw-r--r--doc/src/qtquick/qtquick-live-preview-devices.qdoc6
-rw-r--r--doc/src/qtquick/qtquick-live-preview.qdoc13
-rw-r--r--doc/src/qtquick/qtquick-properties.qdoc6
-rw-r--r--doc/src/qtquick/qtquick-timeline.qdoc12
-rwxr-xr-xscripts/deployqt.py2
-rw-r--r--share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp35
-rw-r--r--share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h7
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp7
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h1
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml129
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml80
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml137
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml80
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml58
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.meshbin0 -> 6356 bytes
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri7
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp251
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h125
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp25
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h7
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp112
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h10
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp1
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp17
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc5
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt34
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt49
-rw-r--r--src/libs/utils/fancymainwindow.cpp1
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp8
-rw-r--r--src/plugins/android/androidconstants.h1
-rw-r--r--src/plugins/autotest/boost/boostcodeparser.cpp3
-rw-r--r--src/plugins/autotest/boost/boosttesttreeitem.cpp6
-rw-r--r--src/plugins/baremetal/gdbserverprovidermanager.cpp1
-rw-r--r--src/plugins/baremetal/iarewparser.cpp176
-rw-r--r--src/plugins/baremetal/iarewparser.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp37
-rw-r--r--src/plugins/coreplugin/locator/filesystemfilter.cpp55
-rw-r--r--src/plugins/coreplugin/outputpanemanager.cpp3
-rw-r--r--src/plugins/debugger/breakhandler.cpp43
-rw-r--r--src/plugins/debugger/breakhandler.h1
-rw-r--r--src/plugins/debugger/debuggermainwindow.cpp6
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.cpp8
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.h1
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.h1
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.cpp17
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.h1
-rw-r--r--src/plugins/languageclient/languageclientsettings.cpp1
-rw-r--r--src/plugins/modeleditor/actionhandler.h1
-rw-r--r--src/plugins/modeleditor/diagramsviewmanager.h2
-rw-r--r--src/plugins/modeleditor/modeleditor.h2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizard_test.cpp18
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp72
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h1
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp22
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.h2
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.cpp7
-rw-r--r--src/plugins/python/pythoneditor.cpp15
-rw-r--r--src/plugins/python/pythonplugin.cpp13
-rw-r--r--src/plugins/python/pythonplugin.h4
-rw-r--r--src/plugins/python/pythonrunconfiguration.cpp15
-rw-r--r--src/plugins/python/pythonsettings.cpp24
-rw-r--r--src/plugins/python/pythonsettings.h10
-rw-r--r--src/plugins/python/pythonutils.cpp131
-rw-r--r--src/plugins/python/pythonutils.h38
-rw-r--r--src/plugins/qmakeprojectmanager/addlibrarywizard.cpp14
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp12
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp40
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp5
-rw-r--r--src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp11
-rw-r--r--src/plugins/remotelinux/remotelinuxdebugsupport.cpp1
-rw-r--r--src/plugins/texteditor/basehoverhandler.cpp13
-rw-r--r--src/plugins/webassembly/webassemblyqtversion.cpp3
-rw-r--r--src/plugins/webassembly/webassemblyrunconfiguration.cpp24
-rw-r--r--src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp40
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp7
m---------src/shared/qbs0
-rw-r--r--src/shared/qtcreator_gui_pch.h13
-rw-r--r--src/shared/qtcreator_pch.h50
-rw-r--r--src/tools/qml2puppet/CMakeLists.txt1
-rw-r--r--src/tools/qml2puppet/qml2puppet.qbs2
-rw-r--r--tests/system/shared/utils.py4
-rw-r--r--tests/system/suite_general/tst_create_proj_wizard/test.py2
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h2
103 files changed, 1886 insertions, 466 deletions
diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf
index a6817d36426..c71ddf7fa2a 100644
--- a/doc/config/macros.qdocconf
+++ b/doc/config/macros.qdocconf
@@ -21,6 +21,7 @@ macro.QC = "$IDE_DISPLAY_NAME"
macro.QCE = "$IDE_DISPLAY_NAME Enterprise"
macro.QD = "Qt Designer"
macro.QDS = "Qt Design Studio"
+macro.QDV = "Qt Design Viewer"
macro.QL = "Qt Linguist"
macro.QMLD = "Qt Quick Designer"
macro.QQV = "Qt QML Viewer"
diff --git a/doc/config/qtcreator-project.qdocconf b/doc/config/qtcreator-project.qdocconf
index ba394e3b275..82daf9faad7 100644
--- a/doc/config/qtcreator-project.qdocconf
+++ b/doc/config/qtcreator-project.qdocconf
@@ -42,6 +42,7 @@ depends += qtwidgets \
qthelp \
qtquickcontrols \
qtquickextras \
+ qtquicktimeline \
qtlinguist \
qtscxml \
qtsensors \
diff --git a/doc/images/icons/action-icon-binding.png b/doc/images/icons/action-icon-binding.png
new file mode 100644
index 00000000000..34b2c6adda2
--- /dev/null
+++ b/doc/images/icons/action-icon-binding.png
Binary files differ
diff --git a/doc/images/icons/action-icon.png b/doc/images/icons/action-icon.png
new file mode 100644
index 00000000000..94e95ce8efc
--- /dev/null
+++ b/doc/images/icons/action-icon.png
Binary files differ
diff --git a/doc/images/qmldesigner-binding-editor.png b/doc/images/qmldesigner-binding-editor.png
index 0fd07427b63..fc6650bc5bc 100644
--- a/doc/images/qmldesigner-binding-editor.png
+++ b/doc/images/qmldesigner-binding-editor.png
Binary files differ
diff --git a/doc/images/qmldesigner-set-expression.png b/doc/images/qmldesigner-set-expression.png
index da93bd2cc63..a5386d6937d 100644
--- a/doc/images/qmldesigner-set-expression.png
+++ b/doc/images/qmldesigner-set-expression.png
Binary files differ
diff --git a/doc/images/qt-design-viewer.png b/doc/images/qt-design-viewer.png
new file mode 100644
index 00000000000..1c4916036be
--- /dev/null
+++ b/doc/images/qt-design-viewer.png
Binary files differ
diff --git a/doc/images/qtcreator-mcu-options.png b/doc/images/qtcreator-mcu-options.png
index e5bcf1f4e68..f01f1894379 100644
--- a/doc/images/qtcreator-mcu-options.png
+++ b/doc/images/qtcreator-mcu-options.png
Binary files differ
diff --git a/doc/src/mcu/creator-mcu-dev.qdoc b/doc/src/mcu/creator-mcu-dev.qdoc
index c4da995de38..90d5df54865 100644
--- a/doc/src/mcu/creator-mcu-dev.qdoc
+++ b/doc/src/mcu/creator-mcu-dev.qdoc
@@ -31,7 +31,7 @@
\title Connecting MCUs
- \l{Qt for MCUs} enables you to use subsets of QML and Qt Quick Controls
+ \l{Qt for MCU} enables you to use subsets of QML and Qt Quick Controls
to create user interfaces for devices that are powered by microcontroller
units (MCU). It includes a new graphics rendering engine that has a low
memory footprint and is optimized for MCUs and other resource-constrained
@@ -44,7 +44,8 @@
debug them using \QC.
The toolchains are available for cross-compilation on Microsoft Windows,
- Linux, and macOS.
+ Linux, and macOS. However, the Qt for MCU SDK is currently only available
+ for Windows.
The following MCU boards are currently supported:
@@ -52,7 +53,7 @@
\li \l{https://www.st.com/en/evaluation-tools/stm32f7508-dk.html}
{STM32F7508-DK}
\li \l{https://www.st.com/en/evaluation-tools/32f769idiscovery.html}
- {32F769IDISCOVERY}
+ {STM32F769I-DISCO}
\li \l{https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1050-evaluation-kit:MIMXRT1050-EVK}
{NXP i.MX RT1050 EVK}
\endlist
@@ -68,9 +69,10 @@
To use \QC to develop QML applications for MCUs, you need the following:
\list
- \li Qt for MCU SDK
+ \li Qt for MCU SDK (only available for Windows)
\li The Bare Metal plugin
- \li GNU ARM Embedded Toolchain
+ \li \l{https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm}
+ {GNU ARM Embedded Toolchain}
\li For STM32 boards:
\list
\li \l{https://www.st.com/en/embedded-software/stm32cubef7.html}
@@ -81,7 +83,7 @@
\li For NXP boards:
\list
\li \l{https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1050-evaluation-kit:MIMXRT1050-EVK}
- NXP EVKB-IMXRT 1050 SDK
+ {NXP EVKB-IMXRT 1050 SDK}
\li \l{https://www.segger.com/downloads/jlink}{SEGGER JLink}
\endlist
\endlist
@@ -184,7 +186,7 @@
You can use a wizard to set up a project for developing an application that
you can run on MCUs. The project uses a subset of QML and Qt Quick Controls
- that are supported by Qt for MCUs. For more information about developing
+ that are supported by Qt for MCU. For more information about developing
applications for MCUs, see the Qt for MCU documentation.
To create an application and run it on a MCU board:
diff --git a/doc/src/projects/creator-only/creator-projects-building.qdoc b/doc/src/projects/creator-only/creator-projects-building.qdoc
index 14f97704563..c87557dc699 100644
--- a/doc/src/projects/creator-only/creator-projects-building.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-building.qdoc
@@ -31,7 +31,7 @@
/*!
\contentspage index.html
- \previouspage creator-live-preview-devices.html
+ \previouspage qt-design-viewer.html
\page creator-building-targets.html
\nextpage creator-running-targets.html
diff --git a/doc/src/qtcreator-toc.qdoc b/doc/src/qtcreator-toc.qdoc
index 7774af49512..f0bd3f9e02a 100644
--- a/doc/src/qtcreator-toc.qdoc
+++ b/doc/src/qtcreator-toc.qdoc
@@ -160,6 +160,7 @@
\list
\li \l{Previewing on Desktop}
\li \l{Previewing on Devices}
+ \li \l{Previewing in Browsers}
\endlist
\li \l{Building for Multiple Platforms}
\li \l{Running on Multiple Platforms}
diff --git a/doc/src/qtquick/qt-design-viewer.qdoc b/doc/src/qtquick/qt-design-viewer.qdoc
new file mode 100644
index 00000000000..2c63c05baf4
--- /dev/null
+++ b/doc/src/qtquick/qt-design-viewer.qdoc
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Design Studio documentation.
+**
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \contentspage {Qt Creator}
+ \previouspage creator-live-preview-devices.html
+ \page qt-design-viewer.html
+ \if defined(qtdesignstudio)
+ \nextpage studio-advanced.html
+ \else
+ \nextpage creator-building-targets.html
+ \endif
+
+ \title Previewing in Browsers
+
+ \image qt-design-viewer.png
+
+ \QDV is a QML viewer that runs in your web browser. This means that you can
+ run applications in most widely-used web browsers, such as Apple Safari,
+ Google Chrome, Microsoft Edge, and Mozilla Firefox, on the desktop and on
+ mobile devices.
+
+ The startup and compilation time depend on your browser and configuration.
+ However, the actual performance of the application once started is
+ indistinguishable from the same application running on the desktop.
+
+ \if defined(qtdesignstudio)
+ To create a resource file out of your project, select \uicontrol Tools >
+ \uicontrol {Generate Resource File} in \QC. Then upload the package into
+ \QDV.
+ \else
+ You can run \l{Creating Qt Quick UI Projects}{Qt Quick UI projects}, which
+ have a .qmlproject file that define the main QML file and the import paths.
+ Compress the project folder into a ZIP file that you upload to \QDV.
+ \endif
+
+ The loaded applications remain locally in your browser. No data is uploaded
+ into the cloud.
+
+ To preview an application in a web browser:
+
+ \list
+ \li In the browser, open \l{http://qt-webassembly.io/designviewer/}
+ {\QDV}.
+ \li Drag and drop your application package to \QDV, or click the load
+ icon to browse for your file.
+ \endlist
+
+ Your application is compiled and run on \QDV.
+*/
diff --git a/doc/src/qtquick/qtquick-components.qdoc b/doc/src/qtquick/qtquick-components.qdoc
index 9a82fbd44d7..d8327fd2f85 100644
--- a/doc/src/qtquick/qtquick-components.qdoc
+++ b/doc/src/qtquick/qtquick-components.qdoc
@@ -170,20 +170,27 @@
Property bindings are created implicitly in QML whenever a property is
assigned a JavaScript expression. To set JavaScript expressions as values
- of properties in the Design mode, select the \uicontrol Settings menu next to
- a property, and then select \uicontrol {Set Binding}.
+ of properties in the Design mode, select the
+ \inlineimage icons/action-icon.png
+ (\uicontrol Actions) menu next to a property, and then select
+ \uicontrol {Set Binding}.
\image qmldesigner-set-expression.png "Type properties context menu"
- The \uicontrol {Binding Editor} supports code completion. Start typing a
+ In the \uicontrol {Binding Editor}, select an item and a property from
+ lists of available items and their properties.
+
+ \image qmldesigner-binding-editor.png "Binding Editor"
+
+ Alternatively, start typing a
string and press \key Ctrl+Space to display a list of properties, IDs, and
code snippets. When you enter a period (.) after a property name, a list of
available values is displayed. Press \key Enter to accept the first
suggestion in the list and to complete the code.
- \image qmldesigner-binding-editor.png "Binding Editor"
-
- To remove bindings, select \uicontrol Reset in the context menu.
+ When a binding is set, the \uicontrol Actions menu icon changes to
+ \inlineimage icons/action-icon-binding
+ . To remove bindings, select \uicontrol Reset in the \uicontrol Actions menu.
You can set bindings also in the \uicontrol Connections view. For more
information, see \l {Adding Bindings Between Properties}.
diff --git a/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc b/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
index 9e1fe9919ed..ff8d929f9eb 100644
--- a/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
+++ b/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
@@ -64,10 +64,10 @@
Then you can use the \l QQuickView class in the main C++ source file to
show the main QML file when the application starts.
- At the time of this writing, the Qt Quick Timeline module is delivered with
- \QDS, but not with Qt. If you use a timeline in a \QDS project that you
- import to \QC, you must build the Qt Quick Timeline module and install it to
- your Qt to be able to build your project.
+ The \l{Qt Quick Timeline} module is delivered with \QDS and with Qt 5.14,
+ and later. If you use a timeline in a \QDS project that you import to \QC,
+ and your Qt is older than 5.14, you must build the Qt Quick Timeline module
+ and install it to your Qt to be able to build your project.
\section1 Converting Projects
@@ -116,7 +116,9 @@
\section1 Adding Qt Quick Timeline Module to Qt Installations
- Check out the Qt Quick Timeline module from
+ \note You only need to do this if your Qt version is older than 5.14.
+
+ Check out the \l{Qt Quick Timeline} module from
\l{https://codereview.qt-project.org/#/admin/projects/qt/qtquicktimeline}
{Qt Code Review}.
diff --git a/doc/src/qtquick/qtquick-live-preview-devices.qdoc b/doc/src/qtquick/qtquick-live-preview-devices.qdoc
index d37b84075a1..4686ef485b0 100644
--- a/doc/src/qtquick/qtquick-live-preview-devices.qdoc
+++ b/doc/src/qtquick/qtquick-live-preview-devices.qdoc
@@ -27,11 +27,7 @@
\contentspage {Qt Creator}
\previouspage creator-live-preview-desktop.html
\page creator-live-preview-devices.html
- \if defined(qtdesignstudio)
- \nextpage studio-advanced.html
- \else
- \nextpage creator-building-targets.html
- \endif
+ \nextpage qt-design-viewer.html
\title Previewing on Devices
diff --git a/doc/src/qtquick/qtquick-live-preview.qdoc b/doc/src/qtquick/qtquick-live-preview.qdoc
index 95b01b9fe2a..9145c2826a0 100644
--- a/doc/src/qtquick/qtquick-live-preview.qdoc
+++ b/doc/src/qtquick/qtquick-live-preview.qdoc
@@ -40,6 +40,15 @@
devices. The changes you make to the UI are instantly visible
to you in the preview.
+ In addition, you can use \QDV to run
+ \if defined(qtcreator)
+ \l{Creating Qt Quick UI Projects}{Qt Quick UI projects}
+ \else
+ applications
+ \endif
+ in most widely-used web browsers on the desktop and in mobile devices This
+ enables you to easily share your designs with reviewers who don't have \QC.
+
\if defined(qtcreator)
\image qtcreator-live-preview.png
\else
@@ -62,5 +71,9 @@
devices is set up automatically. You only need to connect your
devices to your system.
\endif
+ \li \l{Previewing in Browsers}
+
+ You can open \l{http://qt-webassembly.io/designviewer/}{\QDV}
+ in a browser and load applications to it.
\endlist
*/
diff --git a/doc/src/qtquick/qtquick-properties.qdoc b/doc/src/qtquick/qtquick-properties.qdoc
index add17138c4f..e7ce811e491 100644
--- a/doc/src/qtquick/qtquick-properties.qdoc
+++ b/doc/src/qtquick/qtquick-properties.qdoc
@@ -46,9 +46,9 @@
\uicontrol Properties pane, and enter the name of another QML type in the
field. If you have specified properties for the item that are not supported
for the new type, the type cannot be changed and an error message is
- displayed. Select the \uicontrol Settings menu next to the property name, and
- then select \uicontrol Reset to remove the property values before trying
- again.
+ displayed. Select the \inlineimage icons/action-icon.png
+ (\uicontrol Actions) menu next to the property name, and then select
+ \uicontrol Reset to remove the property values before trying again.
To modify the common properties of multiple items simultaneously, select
them in the \uicontrol Navigator or on the canvas:
diff --git a/doc/src/qtquick/qtquick-timeline.qdoc b/doc/src/qtquick/qtquick-timeline.qdoc
index de012b94e56..b3b40a81675 100644
--- a/doc/src/qtquick/qtquick-timeline.qdoc
+++ b/doc/src/qtquick/qtquick-timeline.qdoc
@@ -59,14 +59,10 @@
\uicontrol {Qt Quick Designer} > \uicontrol {Enable Timeline editor}. You
need to restart \QC for the \uicontrol Timeline view to appear.
- To be able to create timelines, you also need the Qt Quick Timeline module.
- At the time of this writing, the module is not available as a library in
- the Qt installer, and therefore you must check out the repository and build
- the module yourself using the same Qt version that you used to build \QC.
-
- You can check out the module from
- \l{https://codereview.qt-project.org/#/admin/projects/qt/qtquicktimeline}
- {Qt Code Review Tool}.
+ To be able to create timelines, you also need the \l {Qt Quick Timeline}
+ module, which is delivered with Qt 5.14, and later. For more
+ information about adding the module to an older Qt version, see
+ \l{Adding Qt Quick Timeline Module to Qt Installations}.
\endif
\section1 Creating Timelines
diff --git a/scripts/deployqt.py b/scripts/deployqt.py
index 2b98e3ca421..5e4808a211a 100755
--- a/scripts/deployqt.py
+++ b/scripts/deployqt.py
@@ -323,7 +323,7 @@ def main():
QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML']
QT_INSTALL_TRANSLATIONS = qt_install_info['QT_INSTALL_TRANSLATIONS']
- plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes',
+ plugins = ['assetimporters', 'accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes',
'platforminputcontexts', 'platforms', 'printsupport', 'qmltooling', 'sqldrivers', 'styles',
'xcbglintegrations',
'wayland-decoration-client',
diff --git a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp b/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp
index c5468bc999b..1ff3bf3320b 100644
--- a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp
+++ b/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp
@@ -95,7 +95,14 @@ QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command)
{
static const bool dontUseSharedMemory = qEnvironmentVariableIsSet("DESIGNER_DONT_USE_SHARED_MEMORY");
- if (!dontUseSharedMemory && command.valueChanges().count() > 5) {
+ QVector<PropertyValueContainer> propertyValueContainer = command.valueChanges();
+
+ if (command.transactionOption != ValuesChangedCommand::TransactionOption::None) {
+ PropertyValueContainer optionContainer(command.transactionOption);
+ propertyValueContainer.append(optionContainer);
+ }
+
+ if (!dontUseSharedMemory && propertyValueContainer.count() > 5) {
static quint32 keyCounter = 0;
++keyCounter;
command.m_keyNumber = keyCounter;
@@ -103,7 +110,7 @@ QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command)
QDataStream temporaryOutDataStream(&outDataStreamByteArray, QIODevice::WriteOnly);
temporaryOutDataStream.setVersion(QDataStream::Qt_4_8);
- temporaryOutDataStream << command.valueChanges();
+ temporaryOutDataStream << propertyValueContainer;
SharedMemory *sharedMemory = createSharedMemory(keyCounter, outDataStreamByteArray.size());
@@ -118,7 +125,7 @@ QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command)
}
out << qint32(0);
- out << command.valueChanges();
+ out << propertyValueContainer;
return out;
}
@@ -144,17 +151,29 @@ QDataStream &operator>>(QDataStream &in, ValuesChangedCommand &command)
{
in >> command.m_keyNumber;
- if (command.keyNumber() > 0) {
- readSharedMemory(command.keyNumber(), &command.m_valueChangeVector);
- } else {
- in >> command.m_valueChangeVector;
+ QVector<PropertyValueContainer> valueChangeVector;
+
+ if (command.keyNumber() > 0)
+ readSharedMemory(command.keyNumber(), &valueChangeVector);
+ else
+ in >> valueChangeVector;
+
+ // '-option-' is not a valid property name and indicates that we store the transaction option.
+ if (!valueChangeVector.isEmpty() && valueChangeVector.last().name() == "-option-") {
+ command.transactionOption =
+ static_cast<ValuesChangedCommand::TransactionOption>(valueChangeVector.last().instanceId());
+ valueChangeVector.removeLast();
}
+
+ command.m_valueChangeVector = valueChangeVector;
+
return in;
}
bool operator ==(const ValuesChangedCommand &first, const ValuesChangedCommand &second)
{
- return first.m_valueChangeVector == second.m_valueChangeVector;
+ return first.m_valueChangeVector == second.m_valueChangeVector
+ && first.transactionOption == second.transactionOption;
}
QDebug operator <<(QDebug debug, const ValuesChangedCommand &command)
diff --git a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h b/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h
index bf7fe1e43d4..5be50903df2 100644
--- a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h
+++ b/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h
@@ -39,6 +39,7 @@ class ValuesChangedCommand
friend bool operator ==(const ValuesChangedCommand &first, const ValuesChangedCommand &second);
public:
+ enum TransactionOption { Start, End, None };
ValuesChangedCommand();
explicit ValuesChangedCommand(const QVector<PropertyValueContainer> &valueChangeVector);
@@ -48,6 +49,7 @@ public:
static void removeSharedMemorys(const QVector<qint32> &keyNumberVector);
void sort();
+ TransactionOption transactionOption = TransactionOption::None;
private:
QVector<PropertyValueContainer> m_valueChangeVector;
@@ -69,12 +71,11 @@ QDebug operator <<(QDebug debug, const ValuesChangedCommand &instance);
class ValuesModifiedCommand : public ValuesChangedCommand
{
public:
- ValuesModifiedCommand()
- {}
+ ValuesModifiedCommand() = default;
+
explicit ValuesModifiedCommand(const QVector<PropertyValueContainer> &valueChangeVector)
: ValuesChangedCommand(valueChangeVector)
{}
-
};
} // namespace QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp
index cde5957bf5d..19265df0359 100644
--- a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp
@@ -42,6 +42,13 @@ PropertyValueContainer::PropertyValueContainer(qint32 instanceId, const Property
{
}
+PropertyValueContainer::PropertyValueContainer(qint32 option)
+ : m_instanceId(option),
+ m_name("-option-")
+{
+// '-option-' is not a valid property name and indicates that we store the transaction option.
+}
+
qint32 PropertyValueContainer::instanceId() const
{
return m_instanceId;
diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h b/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h
index 3423066bc14..4d30f3fb7e4 100644
--- a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h
+++ b/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h
@@ -43,6 +43,7 @@ class PropertyValueContainer
public:
PropertyValueContainer();
PropertyValueContainer(qint32 instanceId, const PropertyName &name, const QVariant &value, const TypeName &dynamicTypeName);
+ PropertyValueContainer(qint32 option);
qint32 instanceId() const;
PropertyName name() const;
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
new file mode 100644
index 00000000000..dc2fee64543
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** 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 MouseArea3D 1.0
+
+Model {
+ id: arrow
+ rotationOrder: Node.XYZr
+ source: "meshes/Arrow.mesh"
+
+ property View3D view3D
+ property alias color: material.emissiveColor
+ property Node targetNode: null
+ property bool isDragging: false
+
+ readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
+
+ property var _pointerPosPressed
+ property var _targetStartPos
+
+ signal positionCommit()
+
+ materials: DefaultMaterial {
+ id: material
+ emissiveColor: mouseAreaFront.hovering ? "white" : Qt.rgba(1.0, 0.0, 0.0, 1.0)
+ lighting: DefaultMaterial.NoLighting
+ }
+
+ function handlePressed(mouseArea, pointerPosition)
+ {
+ if (!targetNode)
+ return;
+
+ var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
+ _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
+ var sp = targetNode.scenePosition;
+ _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
+ isDragging = true;
+ }
+
+ function posInParent(mouseArea, pointerPosition)
+ {
+ var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
+ var scenePointerPos = mouseArea.mapPositionToScene(maskedPosition);
+ var sceneRelativeDistance = Qt.vector3d(
+ scenePointerPos.x - _pointerPosPressed.x,
+ scenePointerPos.y - _pointerPosPressed.y,
+ scenePointerPos.z - _pointerPosPressed.z);
+
+ var newScenePos = Qt.vector3d(
+ _targetStartPos.x + sceneRelativeDistance.x,
+ _targetStartPos.y + sceneRelativeDistance.y,
+ _targetStartPos.z + sceneRelativeDistance.z);
+
+ return targetNode.parent.mapPositionFromScene(newScenePos);
+ }
+
+ function handleDragged(mouseArea, pointerPosition)
+ {
+ if (!targetNode)
+ return;
+
+ targetNode.position = posInParent(mouseArea, pointerPosition);
+ }
+
+ function handleReleased(mouseArea, pointerPosition)
+ {
+ if (!targetNode)
+ return;
+
+ targetNode.position = posInParent(mouseArea, pointerPosition);
+ isDragging = false;
+ arrow.positionCommit();
+ }
+
+ MouseArea3D {
+ id: mouseAreaYZ
+ view3D: arrow.view3D
+ x: 0
+ y: -1.5
+ width: 12
+ height: 3
+ rotation: Qt.vector3d(0, 90, 0)
+ grabsMouse: targetNode
+ onPressed: arrow.handlePressed(mouseAreaYZ, pointerPosition)
+ onDragged: arrow.handleDragged(mouseAreaYZ, pointerPosition)
+ onReleased: arrow.handleReleased(mouseAreaYZ, pointerPosition)
+ }
+
+ MouseArea3D {
+ id: mouseAreaXZ
+ view3D: arrow.view3D
+ x: 0
+ y: -1.5
+ width: 12
+ height: 3
+ rotation: Qt.vector3d(90, 90, 0)
+ grabsMouse: targetNode
+ onPressed: arrow.handlePressed(mouseAreaXZ, pointerPosition)
+ onDragged: arrow.handleDragged(mouseAreaXZ, pointerPosition)
+ onReleased: arrow.handleReleased(mouseAreaXZ, pointerPosition)
+ }
+
+}
+
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml
new file mode 100644
index 00000000000..2e8425016df
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml
@@ -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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick3D 1.0
+import MouseArea3D 1.0
+
+Node {
+ id: overlayNode
+
+ property View3D view3D
+ property Node target: parent
+ property bool autoScale: true
+
+ // Read-only
+ property real relativeScale: 1
+
+ onSceneTransformChanged: updateScale()
+ onAutoScaleChanged: updateScale()
+ Connections {
+ target: view3D.camera
+ onSceneTransformChanged: updateScale()
+ }
+
+ function getScale(baseScale)
+ {
+ return Qt.vector3d(baseScale.x * relativeScale, baseScale.y * relativeScale,
+ baseScale.z * relativeScale);
+ }
+
+ function updateScale()
+ {
+ if (!autoScale) {
+ target.scale = Qt.vector3d(1, 1, 1);
+ } else {
+ // Calculate the distance independent scale by first mapping the targets position to
+ // the view. We then measure up a distance on the view (100px) that we use as an
+ // "anchor" distance. Map the two positions back to the target node, and measure the
+ // distance between them now, in the 3D scene. The difference of the two distances,
+ // view and scene, will tell us what the distance independent scale should be.
+ var posInView1 = view3D.mapFrom3DScene(scenePosition);
+ var posInView2 = Qt.vector3d(posInView1.x + 100, posInView1.y, posInView1.z);
+
+ var rayPos1 = view3D.mapTo3DScene(Qt.vector3d(posInView2.x, posInView2.y, 0));
+ var rayPos2 = view3D.mapTo3DScene(Qt.vector3d(posInView2.x, posInView2.y, 10));
+
+ var planeNormal = view3D.camera.forward;
+ var rayHitPos = helper.rayIntersectsPlane(rayPos1, rayPos2, scenePosition,
+ planeNormal);
+ relativeScale = scenePosition.minus(rayHitPos).length() / 100;
+ }
+ }
+
+ MouseArea3D {
+ id: helper
+ view3D: overlayNode.view3D
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
index d3b693788a3..a0a9c0e5998 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
@@ -42,42 +42,130 @@ Window {
property alias showEditLight: editLightCheckbox.checked
property alias usePerspective: usePerspectiveCheckbox.checked
+ property Node selectedNode: null
+
+ signal objectClicked(var object)
+ signal commitObjectPosition(var object)
+
+ function selectObject(object) {
+ selectedNode = object;
+ }
+
+ Node {
+ id: overlayScene
+
+ Camera {
+ id: overlayCamera
+ projectionMode: usePerspectiveCheckbox.checked ? Camera.Perspective
+ : Camera.Orthographic
+ clipFar: editCamera.clipFar
+ position: editCamera.position
+ rotation: editCamera.rotation
+ }
+
+ MoveGizmo {
+ id: moveGizmo
+ scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
+ highlightOnHover: true
+ targetNode: viewWindow.selectedNode
+ position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
+ : Qt.vector3d(0, 0, 0)
+ rotation: globalControl.checked || !viewWindow.selectedNode
+ ? Qt.vector3d(0, 0, 0)
+ : viewWindow.selectedNode.sceneRotation
+
+ visible: selectedNode
+ view3D: overlayView
+
+ onPositionCommit: viewWindow.commitObjectPosition(selectedNode)
+ }
+
+ AutoScaleHelper {
+ id: autoScale
+ view3D: overlayView
+ position: moveGizmo.scenePosition
+ }
+ }
+
Rectangle {
id: sceneBg
color: "#FFFFFF"
anchors.fill: parent
focus: true
+ TapHandler { // check tapping/clicking an object in the scene
+ onTapped: {
+ var pickResult = editView.pick(eventPoint.scenePosition.x,
+ eventPoint.scenePosition.y);
+ viewWindow.objectClicked(pickResult.objectHit);
+ selectObject(pickResult.objectHit);
+ }
+ }
+
View3D {
id: editView
anchors.fill: parent
- enableWireframeMode: true
camera: editCamera
- AxisHelper {
- id: axisGrid
- enableXZGrid: true
- enableAxisLines: false
- }
+ Node {
+ id: mainSceneHelpers
- Light {
- id: pointLight
- visible: showEditLight
- position: editCamera.position
- lightType: Light.Point
- }
+ AxisHelper {
+ id: axisGrid
+ enableXZGrid: true
+ enableAxisLines: false
+ }
+
+ PointLight {
+ id: pointLight
+ visible: showEditLight
+ position: editCamera.position
+ }
- Camera {
- id: editCamera
- y: 200
- z: -300
- clipFar: 100000
- projectionMode: usePerspective ? Camera.Perspective : Camera.Orthographic
+ Camera {
+ id: editCamera
+ y: 200
+ z: -300
+ clipFar: 100000
+ projectionMode: usePerspective ? Camera.Perspective : Camera.Orthographic
+ }
}
+ }
- Component.onCompleted: {
- pointLight.setParentItem(editView.scene);
- editCamera.setParentItem(editView.scene);
+ View3D {
+ id: overlayView
+ anchors.fill: parent
+ camera: overlayCamera
+ scene: overlayScene
+ }
+
+ Overlay2D {
+ id: gizmoLabel
+ targetNode: moveGizmo
+ targetView: overlayView
+ offsetX: 0
+ offsetY: 45
+ visible: moveGizmo.isDragging
+
+ Rectangle {
+ color: "white"
+ x: -width / 2
+ y: -height
+ width: gizmoLabelText.width + 4
+ height: gizmoLabelText.height + 4
+ border.width: 1
+ Text {
+ id: gizmoLabelText
+ text: {
+ var l = Qt.locale();
+ selectedNode
+ ? qsTr("x:") + Number(selectedNode.position.x).toLocaleString(l, 'f', 1)
+ + qsTr(" y:") + Number(selectedNode.position.y).toLocaleString(l, 'f', 1)
+ + qsTr(" z:") + Number(selectedNode.position.z).toLocaleString(l, 'f', 1)
+ : "";
+ }
+ anchors.centerIn: parent
+ }
}
}
@@ -112,6 +200,13 @@ Window {
text: qsTr("Use Perspective Projection")
onCheckedChanged: cameraControl.forceActiveFocus()
}
+
+ CheckBox {
+ id: globalControl
+ checked: true
+ text: qsTr("Use global orientation")
+ onCheckedChanged: cameraControl.forceActiveFocus()
+ }
}
Text {
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
new file mode 100644
index 00000000000..73b80018a92
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
@@ -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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick3D 1.0
+
+Node {
+ id: arrows
+
+ property View3D view3D
+ property bool highlightOnHover: false
+ property Node targetNode: null
+ readonly property bool isDragging: arrowX.isDragging || arrowY.isDragging || arrowZ.isDragging
+
+ scale: Qt.vector3d(5, 5, 5)
+
+ property alias arrowX: arrowX
+ property alias arrowY: arrowY
+ property alias arrowZ: arrowZ
+
+ signal positionCommit()
+
+ Arrow {
+ id: arrowX
+ objectName: "Arrow X"
+ rotation: Qt.vector3d(0, -90, 0)
+ targetNode: arrows.targetNode
+ color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ : Qt.rgba(1, 0, 0, 1)
+ view3D: arrows.view3D
+
+ onPositionCommit: arrows.positionCommit()
+ }
+
+ Arrow {
+ id: arrowY
+ objectName: "Arrow Y"
+ rotation: Qt.vector3d(90, 0, 0)
+ targetNode: arrows.targetNode
+ color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ : Qt.rgba(0, 0, 1, 1)
+ view3D: arrows.view3D
+
+ onPositionCommit: arrows.positionCommit()
+ }
+
+ Arrow {
+ id: arrowZ
+ objectName: "Arrow Z"
+ rotation: Qt.vector3d(0, 180, 0)
+ targetNode: arrows.targetNode
+ color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ : Qt.rgba(0, 0.6, 0, 1)
+ view3D: arrows.view3D
+
+ onPositionCommit: arrows.positionCommit()
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml
new file mode 100644
index 00000000000..7e1e231133a
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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
+
+Item {
+ id: root
+ property Node targetNode
+ property View3D targetView
+
+ property real offsetX: 0
+ property real offsetY: 0
+
+ onTargetNodeChanged: updateOverlay()
+
+ Connections {
+ target: targetNode
+ onSceneTransformChanged: updateOverlay()
+ }
+
+ Connections {
+ target: targetView.camera
+ onSceneTransformChanged: updateOverlay()
+ }
+
+ function updateOverlay()
+ {
+ var scenePos = targetNode.scenePosition;
+ var scenePosWithOffset = Qt.vector3d(scenePos.x + offsetX, scenePos.y + offsetY, scenePos.z);
+ var viewPos = targetView.mapFrom3DScene(scenePosWithOffset);
+ root.x = viewPos.x;
+ root.y = viewPos.y;
+ root.z = 100000 - viewPos.z; // flip left-handed to right-handed
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.mesh b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.mesh
new file mode 100644
index 00000000000..f872b5e008e
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.mesh
Binary files differ
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
index 7b86f8bc820..a052b7285c9 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
@@ -1,2 +1,5 @@
-HEADERS += $$PWD/cameracontrolhelper.h
-SOURCES += $$PWD/cameracontrolhelper.cpp
+HEADERS += $$PWD/cameracontrolhelper.h \
+ $$PWD/mousearea3d.h
+
+SOURCES += $$PWD/cameracontrolhelper.cpp \
+ $$PWD/mousearea3d.cpp
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp
new file mode 100644
index 00000000000..e3ec5c704bb
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** 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 "mousearea3d.h"
+
+#include <QtGui/qguiapplication.h>
+#include <QtQml/qqmlinfo.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+MouseArea3D *MouseArea3D::s_mouseGrab = nullptr;
+
+MouseArea3D::MouseArea3D(QQuick3DNode *parent)
+ : QQuick3DNode(parent)
+{
+}
+
+QQuick3DViewport *MouseArea3D::view3D() const
+{
+ return m_view3D;
+}
+
+bool MouseArea3D::hovering() const
+{
+ return m_hovering;
+}
+
+bool MouseArea3D::dragging() const
+{
+ return m_dragging;
+}
+
+bool MouseArea3D::grabsMouse() const
+{
+ return m_grabsMouse;
+}
+
+qreal MouseArea3D::x() const
+{
+ return m_x;
+}
+
+qreal MouseArea3D::y() const
+{
+ return m_y;
+}
+
+qreal MouseArea3D::width() const
+{
+ return m_width;
+}
+
+qreal MouseArea3D::height() const
+{
+ return m_height;
+}
+
+void MouseArea3D::setView3D(QQuick3DViewport *view3D)
+{
+ if (m_view3D == view3D)
+ return;
+
+ m_view3D = view3D;
+ emit view3DChanged();
+}
+
+void MouseArea3D::setGrabsMouse(bool grabsMouse)
+{
+ if (m_grabsMouse == grabsMouse)
+ return;
+
+ m_grabsMouse = grabsMouse;
+ emit grabsMouseChanged(grabsMouse);
+}
+
+void MouseArea3D::setX(qreal x)
+{
+ if (qFuzzyCompare(m_x, x))
+ return;
+
+ m_x = x;
+ emit xChanged(x);
+}
+
+void MouseArea3D::setY(qreal y)
+{
+ if (qFuzzyCompare(m_y, y))
+ return;
+
+ m_y = y;
+ emit yChanged(y);
+}
+
+void MouseArea3D::setWidth(qreal width)
+{
+ if (qFuzzyCompare(m_width, width))
+ return;
+
+ m_width = width;
+ emit widthChanged(width);
+}
+
+void MouseArea3D::setHeight(qreal height)
+{
+ if (qFuzzyCompare(m_height, height))
+ return;
+
+ m_height = height;
+ emit heightChanged(height);
+}
+
+void MouseArea3D::componentComplete()
+{
+ if (!m_view3D) {
+ qmlDebug(this) << "property 'view3D' is not set!";
+ return;
+ }
+ m_view3D->setAcceptedMouseButtons(Qt::LeftButton);
+ m_view3D->setAcceptHoverEvents(true);
+ m_view3D->setAcceptTouchEvents(false);
+ m_view3D->installEventFilter(this);
+}
+
+QVector3D MouseArea3D::rayIntersectsPlane(const QVector3D &rayPos0,
+ const QVector3D &rayPos1,
+ const QVector3D &planePos,
+ const QVector3D &planeNormal) const
+{
+ QVector3D rayDirection = rayPos1 - rayPos0;
+ QVector3D rayPos0RelativeToPlane = rayPos0 - planePos;
+
+ float dotPlaneRayDirection = QVector3D::dotProduct(planeNormal, rayDirection);
+ float dotPlaneRayPos0 = -QVector3D::dotProduct(planeNormal, rayPos0RelativeToPlane);
+
+ if (qFuzzyIsNull(dotPlaneRayDirection)) {
+ // The ray is is parallel to the plane. Note that if dotLinePos0 == 0, it
+ // additionally means that the line lies in plane as well. In any case, we
+ // signal that we cannot find a single intersection point.
+ return QVector3D(0, 0, -1);
+ }
+
+ // Since we work with a ray (that has a start), distanceFromLinePos0ToPlane
+ // must be above 0. If it was a line segment (with an end), it also need to be less than 1.
+ // (Note: a third option would be a "line", which is different from a ray or segment in that
+ // it has neither a start, nor an end). Then we wouldn't need to check the distance at all.
+ // But that would also mean that the line could intersect the plane behind the camera, if
+ // the line were directed away from the plane when looking forward.
+ float distanceFromRayPos0ToPlane = dotPlaneRayPos0 / dotPlaneRayDirection;
+ if (distanceFromRayPos0ToPlane <= 0)
+ return QVector3D(0, 0, -1);
+ return rayPos0 + distanceFromRayPos0ToPlane * rayDirection;
+}
+
+QVector3D MouseArea3D::getMousePosInPlane(const QPointF &mousePosInView) const
+{
+ const QVector3D mousePos1(float(mousePosInView.x()), float(mousePosInView.y()), 0);
+ const QVector3D mousePos2(float(mousePosInView.x()), float(mousePosInView.y()), 1);
+ const QVector3D rayPos0 = m_view3D->mapTo3DScene(mousePos1);
+ const QVector3D rayPos1 = m_view3D->mapTo3DScene(mousePos2);
+ const QVector3D globalPlanePosition = mapPositionToScene(QVector3D(0, 0, 0));
+ const QVector3D intersectGlobalPos = rayIntersectsPlane(rayPos0, rayPos1,
+ globalPlanePosition, forward());
+ if (qFuzzyCompare(intersectGlobalPos.z(), -1))
+ return intersectGlobalPos;
+
+ return mapPositionFromScene(intersectGlobalPos);
+}
+
+bool MouseArea3D::eventFilter(QObject *, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::HoverMove: {
+ if (m_grabsMouse && s_mouseGrab && s_mouseGrab != this)
+ break;
+
+ auto const mouseEvent = static_cast<QMouseEvent *>(event);
+ const QVector3D mousePosInPlane = getMousePosInPlane(mouseEvent->pos());
+ if (qFuzzyCompare(mousePosInPlane.z(), -1))
+ break;
+
+ const bool mouseOnTopOfMouseArea =
+ mousePosInPlane.x() >= float(m_x) &&
+ mousePosInPlane.x() <= float(m_x + m_width) &&
+ mousePosInPlane.y() >= float(m_y) &&
+ mousePosInPlane.y() <= float(m_y + m_height);
+
+ const bool buttonPressed = QGuiApplication::mouseButtons().testFlag(Qt::LeftButton);
+
+ // The filter will detect a mouse press on the view, but not a mouse release, since the
+ // former is not accepted by the view, which means that the release will end up being
+ // sent elsewhere. So we need this extra logic inside HoverMove, rather than in
+ // MouseButtonRelease, which would otherwise be more elegant.
+
+ if (m_hovering != mouseOnTopOfMouseArea) {
+ m_hovering = mouseOnTopOfMouseArea;
+ emit hoveringChanged();
+ }
+
+ if (!m_dragging && m_hovering && buttonPressed) {
+ m_dragging = true;
+ emit pressed(mousePosInPlane);
+ emit draggingChanged();
+ } else if (m_dragging && !buttonPressed) {
+ m_dragging = false;
+ emit released(mousePosInPlane);
+ emit draggingChanged();
+ }
+
+ if (m_grabsMouse)
+ s_mouseGrab = m_hovering || m_dragging ? this : nullptr;
+
+ if (m_dragging)
+ emit dragged(mousePosInPlane);
+
+ break; }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+}
+}
+
+#endif // QUICK3D_MODULE
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
new file mode 100644
index 00000000000..b42b438b473
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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 <QtGui/qvector3d.h>
+#include <QtCore/qpointer.h>
+
+#include <QtQuick3D/private/qquick3dnode_p.h>
+#include <QtQuick3D/private/qquick3dviewport_p.h>
+#include <QtQuick3D/private/qtquick3dglobal_p.h>
+
+namespace QmlDesigner {
+namespace Internal {
+
+class MouseArea3D : public QQuick3DNode
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
+ Q_PROPERTY(bool grabsMouse READ grabsMouse WRITE setGrabsMouse NOTIFY grabsMouseChanged)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged)
+ Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged)
+ Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ MouseArea3D(QQuick3DNode *parent = nullptr);
+
+ QQuick3DViewport *view3D() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal width() const;
+ qreal height() const;
+
+ bool hovering() const;
+ bool dragging() const;
+ bool grabsMouse() const;
+
+public slots:
+ void setView3D(QQuick3DViewport *view3D);
+ void setGrabsMouse(bool grabsMouse);
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setWidth(qreal width);
+ void setHeight(qreal height);
+
+ Q_INVOKABLE QVector3D rayIntersectsPlane(const QVector3D &rayPos0,
+ const QVector3D &rayPos1,
+ const QVector3D &planePos,
+ const QVector3D &planeNormal) const;
+
+signals:
+ void view3DChanged();
+
+ void xChanged(qreal x);
+ void yChanged(qreal y);
+ void widthChanged(qreal width);
+ void heightChanged(qreal height);
+
+ void hoveringChanged();
+ void draggingChanged();
+ void pressed(const QVector3D &pointerPosition);
+ void released(const QVector3D &pointerPosition);
+ void dragged(const QVector3D &pointerPosition);
+ void grabsMouseChanged(bool grabsMouse);
+
+protected:
+ void classBegin() override {}
+ void componentComplete() override;
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+private:
+ Q_DISABLE_COPY(MouseArea3D)
+ QQuick3DViewport *m_view3D = nullptr;
+
+ qreal m_x;
+ qreal m_y;
+ qreal m_width;
+ qreal m_height;
+
+ bool m_hovering = false;
+ bool m_dragging = false;
+
+ QVector3D getMousePosInPlane(const QPointF &mousePosInView) const;
+
+ static MouseArea3D *s_mouseGrab;
+ bool m_grabsMouse;
+};
+
+}
+}
+
+QML_DECLARE_TYPE(QmlDesigner::Internal::MouseArea3D)
+
+#endif // QUICK3D_MODULE
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
index bd293488f19..9103ef5de01 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -1190,6 +1190,31 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVecto
return ValuesChangedCommand(valueVector);
}
+ValuesModifiedCommand NodeInstanceServer::createValuesModifiedCommand(
+ const QVector<InstancePropertyValueTriple> &propertyList) const
+{
+ QVector<PropertyValueContainer> valueVector;
+
+ for (const InstancePropertyValueTriple &property : propertyList) {
+ const PropertyName propertyName = property.propertyName;
+ const ServerNodeInstance instance = property.instance;
+ const QVariant propertyValue = property.propertyValue;
+
+ if (instance.isValid()) {
+ if (QMetaType::isRegistered(propertyValue.userType())
+ && supportedVariantType(propertyValue.type())) {
+ valueVector.append(PropertyValueContainer(instance.instanceId(),
+ propertyName,
+ propertyValue,
+ PropertyName()));
+ }
+ }
+ }
+
+ return ValuesModifiedCommand(valueVector);
+}
+
+
QByteArray NodeInstanceServer::importCode() const
{
return m_importCode;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
index 65c2bdfac14..7af63c0b5be 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
@@ -60,6 +60,7 @@ namespace QmlDesigner {
class NodeInstanceClientInterface;
class ValuesChangedCommand;
+class ValuesModifiedCommand;
class PixmapChangedCommand;
class InformationChangedCommand;
class ChildrenChangedCommand;
@@ -82,6 +83,11 @@ public:
using IdPropertyPair = QPair<qint32, QString>;
using InstancePropertyPair= QPair<ServerNodeInstance, PropertyName>;
using DummyPair = QPair<QString, QPointer<QObject> >;
+ using InstancePropertyValueTriple = struct {
+ ServerNodeInstance instance;
+ PropertyName propertyName;
+ QVariant propertyValue;
+ };
explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
@@ -168,6 +174,7 @@ protected:
ValuesChangedCommand createValuesChangedCommand(const QList<ServerNodeInstance> &instanceList) const;
ValuesChangedCommand createValuesChangedCommand(const QVector<InstancePropertyPair> &propertyList) const;
+ ValuesModifiedCommand createValuesModifiedCommand(const QVector<InstancePropertyValueTriple> &propertyList) const;
PixmapChangedCommand createPixmapChangedCommand(const QList<ServerNodeInstance> &instanceList) const;
InformationChangedCommand createAllInformationChangedCommand(const QList<ServerNodeInstance> &instanceList, bool initial = false) const;
ChildrenChangedCommand createChildrenChangedCommand(const ServerNodeInstance &parentInstance, const QList<ServerNodeInstance> &instanceList) const;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index d0931da3e04..b1fa8be60d5 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -59,9 +59,11 @@
#include "dummycontextobject.h"
#include "../editor3d/cameracontrolhelper.h"
+#include "../editor3d/mousearea3d.h"
#include <designersupportdelegate.h>
+#include <QVector3D>
#include <QQmlProperty>
#include <QOpenGLContext>
#include <QQuickView>
@@ -75,15 +77,28 @@ static QVariant objectToVariant(QObject *object)
return QVariant::fromValue(object);
}
-static QObject *createEditView3D(QQmlEngine *engine)
+QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
{
- QmlDesigner::Internal::CameraControlHelper *helper = new QmlDesigner::Internal::CameraControlHelper();
+ auto helper = new QmlDesigner::Internal::CameraControlHelper();
engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper);
+#ifdef QUICK3D_MODULE
+ qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
+#endif
+
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
QWindow *window = qobject_cast<QWindow *>(component.create());
+ if (!window) {
+ qWarning() << "Could not create edit view" << component.errors();
+ return nullptr;
+ }
+
+ QObject::connect(window, SIGNAL(objectClicked(QVariant)), this, SLOT(objectClicked(QVariant)));
+ QObject::connect(window, SIGNAL(commitObjectPosition(QVariant)),
+ this, SLOT(handleObjectPositionCommit(QVariant)));
+
//For macOS we have to use the 4.1 core profile
QSurfaceFormat surfaceFormat = window->requestedFormat();
surfaceFormat.setVersion(4, 1);
@@ -94,6 +109,58 @@ static QObject *createEditView3D(QQmlEngine *engine)
return window;
}
+// an object is clicked in the 3D edit view. Null object indicates selection clearing.
+void Qt5InformationNodeInstanceServer::objectClicked(const QVariant &object)
+{
+ auto obj = object.value<QObject *>();
+ ServerNodeInstance instance;
+ if (obj)
+ instance = instanceForObject(obj);
+ selectInstance(instance);
+}
+
+QVector<Qt5InformationNodeInstanceServer::InstancePropertyValueTriple>
+Qt5InformationNodeInstanceServer::vectorToPropertyValue(
+ const ServerNodeInstance &instance,
+ const PropertyName &propertyName,
+ const QVariant &variant)
+{
+ QVector<InstancePropertyValueTriple> result;
+
+ auto vector3d = variant.value<QVector3D>();
+
+ if (vector3d.isNull())
+ return result;
+
+ const PropertyName dot = propertyName.isEmpty() ? "" : ".";
+
+ InstancePropertyValueTriple propTriple;
+ propTriple.instance = instance;
+ propTriple.propertyName = propertyName + dot + PropertyName("x");
+ propTriple.propertyValue = vector3d.x();
+ result.append(propTriple);
+ propTriple.propertyName = propertyName + dot + PropertyName("y");
+ propTriple.propertyValue = vector3d.y();
+ result.append(propTriple);
+ propTriple.propertyName = propertyName + dot + PropertyName("z");
+ propTriple.propertyValue = vector3d.z();
+ result.append(propTriple);
+
+ return result;
+}
+
+void Qt5InformationNodeInstanceServer::handleObjectPositionCommit(const QVariant &object)
+{
+ auto *obj = object.value<QObject *>();
+ if (obj) {
+ /* We do have to split position into position.x, position.y, position.z */
+ nodeInstanceClient()->valuesModified(createValuesModifiedCommand(vectorToPropertyValue(
+ instanceForObject(obj),
+ "position",
+ obj->property("position"))));
+ }
+}
+
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient)
{
@@ -160,6 +227,15 @@ void Qt5InformationNodeInstanceServer::selectInstance(const ServerNodeInstance &
nodeInstanceClient()->selectionChanged(createChangeSelectionCommand({instance}));
}
+/* This method allows changing property values from the puppet
+ * For performance reasons (and the undo stack) properties should always be modifed in 'bulks'.
+ */
+void Qt5InformationNodeInstanceServer::modifyProperties(
+ const QVector<NodeInstanceServer::InstancePropertyValueTriple> &properties)
+{
+ nodeInstanceClient()->valuesModified(createValuesModifiedCommand(properties));
+}
+
QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
const QList<ServerNodeInstance> &instanceList) const
{
@@ -191,14 +267,17 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
}
if (node) { // If we found a scene we create the edit view
- QObject *view = createEditView3D(engine());
+ m_editView3D = createEditView3D(engine());
+
+ if (!m_editView3D)
+ return;
- QQmlProperty sceneProperty(view, "scene", context());
- node->setParent(view);
+ QQmlProperty sceneProperty(m_editView3D, "scene", context());
+ node->setParent(m_editView3D);
sceneProperty.write(objectToVariant(node));
QQmlProperty parentProperty(node, "parent", context());
- parentProperty.write(objectToVariant(view));
- QQmlProperty completeSceneProperty(view, "showLight", context());
+ parentProperty.write(objectToVariant(m_editView3D));
+ QQmlProperty completeSceneProperty(m_editView3D, "showLight", context());
completeSceneProperty.write(showCustomLight);
}
}
@@ -373,8 +452,23 @@ void QmlDesigner::Qt5InformationNodeInstanceServer::removeSharedMemory(const Qml
void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionCommand &command)
{
- // keep track of selection.
- qDebug() << Q_FUNC_INFO << command;
+ if (!m_editView3D)
+ return;
+
+ const QVector<qint32> instanceIds = command.instanceIds();
+ for (qint32 id : instanceIds) {
+ if (hasInstanceForId(id)) {
+ ServerNodeInstance instance = instanceForId(id);
+ QObject *object = nullptr;
+ if (instance.isSubclassOf("QQuick3DModel") || instance.isSubclassOf("QQuick3DCamera")
+ || instance.isSubclassOf("QQuick3DAbstractLight")) {
+ object = instance.internalObject();
+ }
+ QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant,
+ objectToVariant(object)));
+ return; // TODO: support multi-selection
+ }
+ }
}
} // namespace QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index 962336ccdc4..c574a6ed11d 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -44,6 +44,10 @@ public:
void removeSharedMemory(const RemoveSharedMemoryCommand &command) override;
void changeSelection(const ChangeSelectionCommand &command) override;
+private slots:
+ void objectClicked(const QVariant &object);
+ void handleObjectPositionCommit(const QVariant &object);
+
protected:
void collectItemChangesAndSendChangeCommands() override;
void sendChildrenChangedCommand(const QList<ServerNodeInstance> &childList);
@@ -51,11 +55,17 @@ protected:
bool isDirtyRecursiveForNonInstanceItems(QQuickItem *item) const;
bool isDirtyRecursiveForParentInstances(QQuickItem *item) const;
void selectInstance(const ServerNodeInstance &instance);
+ void modifyProperties(const QVector<InstancePropertyValueTriple> &properties);
private:
+ QObject *createEditView3D(QQmlEngine *engine);
void setup3DEditView(const QList<ServerNodeInstance> &instanceList);
QObject *findRootNodeOf3DViewport(const QList<ServerNodeInstance> &instanceList) const;
+ QVector<InstancePropertyValueTriple> vectorToPropertyValue(const ServerNodeInstance &instance,
+ const PropertyName &propertyName,
+ const QVariant &variant);
+ QObject *m_editView3D = nullptr;
QSet<ServerNodeInstance> m_parentChangedSet;
QList<ServerNodeInstance> m_completedComponentList;
QList<TokenCommand> m_tokenList;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp
index 2ec58bbfbe3..dbee5969be4 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp
@@ -55,6 +55,7 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
{
prioritizeDown();
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {
+ DesignerSupport::activateDesignerWindowManager();
qputenv("DESIGNER_DONT_USE_SHARED_MEMORY", "1");
setNodeInstanceServer(new Qt5TestNodeInstanceServer(this));
initializeCapturedStream(QCoreApplication::arguments().at(2));
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
index 29c3ab3f299..27a52e48a40 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
@@ -52,6 +52,23 @@ Quick3DNodeInstance::~Quick3DNodeInstance()
{
}
+void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
+ 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
+}
+
Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const
{
return qobject_cast<Qt5NodeInstanceServer *>(nodeInstanceServer());
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h
index 6bfc2a02a19..96c44c4d525 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h
@@ -44,6 +44,8 @@ public:
~Quick3DNodeInstance() override;
static Pointer create(QObject *objectToBeWrapped);
void setHideInEditor(bool b) override;
+ void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
+ InstanceContainer::NodeFlags flags) override;
protected:
explicit Quick3DNodeInstance(QObject *node);
diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
index 8354e475f17..03931c280e6 100644
--- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
+++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
@@ -8,5 +8,10 @@
<file>mockfiles/GenericBackend.qml</file>
<file>mockfiles/Dialog.qml</file>
<file>mockfiles/EditView3D.qml</file>
+ <file>mockfiles/Arrow.qml</file>
+ <file>mockfiles/AutoScaleHelper.qml</file>
+ <file>mockfiles/MoveGizmo.qml</file>
+ <file>mockfiles/Overlay2D.qml</file>
+ <file>mockfiles/meshes/Arrow.mesh</file>
</qresource>
</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
index 3678b3dcdb8..beeae355834 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
@@ -11,6 +11,19 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
+# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
+# They need to be set before the find_package(Qt5 ...) call.
+
+#if(ANDROID)
+# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
+# if (ANDROID_ABI STREQUAL "armeabi-v7a")
+# set(ANDROID_EXTRA_LIBS
+# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
+# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
+# endif()
+#endif()
+
@if %{HasTranslation}
find_package(Qt5 COMPONENTS Core Quick LinguistTools REQUIRED)
@@ -20,8 +33,7 @@ find_package(Qt5 COMPONENTS Core Quick REQUIRED)
@endif
if(ANDROID)
- set(TARGET %{ProjectName}_${ANDROID_ABI})
- add_library(${TARGET} SHARED
+ add_library(%{ProjectName} SHARED
%{MainCppFileName}
qml.qrc
@if %{HasTranslation}
@@ -29,8 +41,7 @@ if(ANDROID)
@endif
)
else()
- set(TARGET %{ProjectName})
- add_executable(${TARGET}
+ add_executable(%{ProjectName}
%{MainCppFileName}
qml.qrc
@if %{HasTranslation}
@@ -39,22 +50,11 @@ else()
)
endif()
-target_compile_definitions(${TARGET}
+target_compile_definitions(%{ProjectName}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
-target_link_libraries(${TARGET}
+target_link_libraries(%{ProjectName}
PRIVATE Qt5::Core Qt5::Quick)
@if %{HasTranslation}
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
@endif
-
-# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
-# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
-# These variables must use CACHE, otherwise QtCreator won't see them.
-
-#if(ANDROID)
-# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" CACHE INTERNAL "")
-# if (ANDROID_ABI STREQUAL "armeabi-v7a")
-# set(ANDROID_EXTRA_LIBS ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so CACHE INTERNAL "")
-# endif()
-#endif()
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
index ea825062f41..59f7cf0d65f 100644
--- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
@@ -11,6 +11,19 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
+# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
+# They need to be set before the find_package(Qt5 ...) call.
+
+#if(ANDROID)
+# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
+# if (ANDROID_ABI STREQUAL "armeabi-v7a")
+# set(ANDROID_EXTRA_LIBS
+# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
+# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
+# endif()
+#endif()
+
@if %{HasTranslation}
find_package(Qt5 COMPONENTS Widgets LinguistTools REQUIRED)
@@ -19,17 +32,31 @@ set(TS_FILES %{TsFileName})
find_package(Qt5 COMPONENTS Widgets REQUIRED)
@endif
-add_executable(%{ProjectName}
- %{MainFileName}
- %{SrcFileName}
- %{HdrFileName}
-@if %{GenerateForm}
- %{FormFileName}
-@endif
-@if %{HasTranslation}
- ${TS_FILES}
-@endif
-)
+if(ANDROID)
+ add_library(%{ProjectName} SHARED
+ %{MainFileName}
+ %{SrcFileName}
+ %{HdrFileName}
+ @if %{GenerateForm}
+ %{FormFileName}
+ @endif
+ @if %{HasTranslation}
+ ${TS_FILES}
+ @endif
+ )
+else()
+ add_executable(%{ProjectName}
+ %{MainFileName}
+ %{SrcFileName}
+ %{HdrFileName}
+ @if %{GenerateForm}
+ %{FormFileName}
+ @endif
+ @if %{HasTranslation}
+ ${TS_FILES}
+ @endif
+ )
+endif()
target_link_libraries(%{ProjectName} PRIVATE Qt5::Widgets)
@if %{HasTranslation}
diff --git a/src/libs/utils/fancymainwindow.cpp b/src/libs/utils/fancymainwindow.cpp
index d49473beb75..dfee5df1cfd 100644
--- a/src/libs/utils/fancymainwindow.cpp
+++ b/src/libs/utils/fancymainwindow.cpp
@@ -182,7 +182,6 @@ public:
m_maximumActiveSize = QSize(maxWidth, activeHeight);
auto layout = new QHBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->setContentsMargins(4, 0, 0, 0);
layout->addWidget(m_titleLabel);
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index bf89bd4a934..ccd9bec14d7 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -393,6 +393,10 @@ void AndroidBuildApkStep::doRun()
if (!node)
return false;
+ FilePath deploymentSettingsFile = FilePath::fromString(node->data(Android::Constants::AndroidDeploySettingsFile).toString());
+ if (deploymentSettingsFile.exists())
+ return true; // cmake creates this file for us
+
auto targets = node->data(Android::Constants::AndroidTargets).toStringList();
if (targets.isEmpty())
return true; // qmake does this job for us
@@ -449,7 +453,7 @@ void AndroidBuildApkStep::doRun()
qmlRootPath = target()->project()->rootProjectDirectory().toString();
deploySettings["qml-root-path"] = qmlRootPath;
- QFile f{bc->buildDirectory().pathAppended("android_deployment_settings.json").toString()};
+ QFile f{deploymentSettingsFile.toString()};
if (!f.open(QIODevice::WriteOnly))
return false;
f.write(QJsonDocument{deploySettings}.toJson());
@@ -518,6 +522,8 @@ QVariant AndroidBuildApkStep::data(Core::Id id) const
return AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::minimumSDK(target())).mid(8);
if (id == Constants::NdkLocation)
return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation());
+ if (id == Constants::SdkLocation)
+ return QVariant::fromValue(AndroidConfigurations::currentConfig().sdkLocation());
if (id == Constants::AndroidABIs)
return AndroidManager::applicationAbis(target());
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index b6170877873..8c8f6385556 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -82,6 +82,7 @@ const char AndroidManifest[] = "Android.Manifest"; // QStringList
const char AndroidNdkPlatform[] = "AndroidNdkPlatform"; //QString
const char NdkLocation[] = "NdkLocation"; // FileName
+const char SdkLocation[] = "SdkLocation"; // FileName
const char AndroidABIs[] = "AndroidABIs"; // QString
} // namespace Constants;
diff --git a/src/plugins/autotest/boost/boostcodeparser.cpp b/src/plugins/autotest/boost/boostcodeparser.cpp
index 42504a05624..c626285c22c 100644
--- a/src/plugins/autotest/boost/boostcodeparser.cpp
+++ b/src/plugins/autotest/boost/boostcodeparser.cpp
@@ -105,6 +105,7 @@ void BoostCodeParser::handleIdentifier()
} else if (identifier == "BOOST_TEST_CASE") {
handleTestCase(TestCaseType::Functions);
} else if (identifier == "BOOST_PARAM_TEST_CASE") {
+ m_currentState.setFlag(BoostTestTreeItem::Parameterized);
handleTestCase(TestCaseType::Parameter);
} else if (identifier == "BOOST_AUTO_TEST_CASE") {
handleTestCase(TestCaseType::Auto);
@@ -203,8 +204,6 @@ void BoostCodeParser::handleTestCase(TestCaseType testCaseType)
m_currentState = BoostTestTreeItem::Enabled;
return;
}
- if (testCaseType == TestCaseType::Parameter)
- m_currentState |= BoostTestTreeItem::Parameterized;
} else if (m_currentState.testFlag(BoostTestTreeItem::Fixture)) {
// ignore first parameter (fixture) and first comma
if (!skipCommentsUntil(T_IDENTIFIER))
diff --git a/src/plugins/autotest/boost/boosttesttreeitem.cpp b/src/plugins/autotest/boost/boosttesttreeitem.cpp
index 98a27c04977..f82ff942bba 100644
--- a/src/plugins/autotest/boost/boosttesttreeitem.cpp
+++ b/src/plugins/autotest/boost/boosttesttreeitem.cpp
@@ -238,6 +238,8 @@ QList<TestConfiguration *> BoostTestTreeItem::getSelectedTestConfigurations() co
QString tcName = item->name();
if (item->state().testFlag(BoostTestTreeItem::Templated))
tcName.append("<*");
+ else if (item->state().testFlag(BoostTestTreeItem::Parameterized))
+ tcName.append('*');
tcName = handleSpecialFunctionNames(tcName);
testCasesForProjectFile[item->proFile()].testCases.append(
item->prependWithParentsSuitePaths(tcName));
@@ -275,6 +277,8 @@ TestConfiguration *BoostTestTreeItem::testConfiguration() const
QString tcName = handleSpecialFunctionNames(boostItem->name());
if (boostItem->type() == TestSuite) // execute everything below a suite
tcName.append("/*");
+ else if (boostItem->state().testFlag(BoostTestTreeItem::Parameterized))
+ tcName.append('*');
else if (boostItem->state().testFlag(BoostTestTreeItem::Templated))
tcName.append("<*");
testCases.append(boostItem->prependWithParentsSuitePaths(tcName));
@@ -285,6 +289,8 @@ TestConfiguration *BoostTestTreeItem::testConfiguration() const
QString tcName = name();
if (state().testFlag(BoostTestTreeItem::Templated))
tcName.append("<*");
+ else if (state().testFlag(BoostTestTreeItem::Parameterized))
+ tcName.append('*');
testCases.append(prependWithParentsSuitePaths(handleSpecialFunctionNames(tcName)));
}
diff --git a/src/plugins/baremetal/gdbserverprovidermanager.cpp b/src/plugins/baremetal/gdbserverprovidermanager.cpp
index 16758ee30ce..cd4f199508f 100644
--- a/src/plugins/baremetal/gdbserverprovidermanager.cpp
+++ b/src/plugins/baremetal/gdbserverprovidermanager.cpp
@@ -77,6 +77,7 @@ GdbServerProviderManager::~GdbServerProviderManager()
{
qDeleteAll(m_providers);
m_providers.clear();
+ qDeleteAll(m_factories);
delete m_writer;
m_instance = nullptr;
}
diff --git a/src/plugins/baremetal/iarewparser.cpp b/src/plugins/baremetal/iarewparser.cpp
index 50e25706ca6..039e32aa8d8 100644
--- a/src/plugins/baremetal/iarewparser.cpp
+++ b/src/plugins/baremetal/iarewparser.cpp
@@ -101,73 +101,112 @@ void IarParser::amendFilePath()
m_expectFilePath = false;
}
+bool IarParser::parseErrorOrFatalErrorDetailsMessage1(const QString &lne)
+{
+ const QRegularExpression re("^(Error|Fatal error)\\[(.+)\\]:\\s(.+)\\s\\[(.+)$");
+ const QRegularExpressionMatch match = re.match(lne);
+ if (!match.hasMatch())
+ return false;
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
+ DescriptionIndex, FilepathBeginIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(DescriptionIndex));
+ // This task has a file path, but this patch are split on
+ // some lines, which will be received later.
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ // Prepare first part of a file path.
+ QString firstPart = match.captured(FilepathBeginIndex);
+ firstPart.remove("referenced from ");
+ m_filePathParts.push_back(firstPart);
+ m_expectFilePath = true;
+ m_expectSnippet = false;
+ return true;
+}
+
+bool IarParser::parseErrorOrFatalErrorDetailsMessage2(const QString &lne)
+{
+ const QRegularExpression re("^.*(Error|Fatal error)\\[(.+)\\]:\\s(.+)$");
+ const QRegularExpressionMatch match = re.match(lne);
+ if (!match.hasMatch())
+ return false;
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
+ DescriptionIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(DescriptionIndex));
+ // This task has not a file path. The description details
+ // will be received later on the next lines.
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ m_expectSnippet = true;
+ m_expectFilePath = false;
+ m_expectDescription = false;
+ return true;
+}
+
+bool IarParser::parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne)
+{
+ const QRegularExpression re("^\"(.+)\",(\\d+)?\\s+(Warning|Error|Fatal error)\\[(.+)\\].+$");
+ const QRegularExpressionMatch match = re.match(lne);
+ if (!match.hasMatch())
+ return false;
+ enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
+ MessageTypeIndex, MessageCodeIndex };
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ // A full description will be received later on next lines.
+ const Task task(type, {}, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ const QString firstPart = QString("[%1]: ").arg(match.captured(MessageCodeIndex));
+ m_descriptionParts.append(firstPart);
+ m_expectDescription = true;
+ m_expectSnippet = false;
+ m_expectFilePath = false;
+ return true;
+}
+
+bool IarParser::parseErrorInCommandLineMessage(const QString &lne)
+{
+ if (!lne.startsWith("Error in command line"))
+ return false;
+ const Task task(Task::TaskType::Error, lne.trimmed(), {},
+ -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return true;
+}
+
+bool IarParser::parseErrorMessage1(const QString &lne)
+{
+ const QRegularExpression re("^(Error)\\[(.+)\\]:\\s(.+)$");
+ const QRegularExpressionMatch match = re.match(lne);
+ if (!match.hasMatch())
+ return false;
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, DescriptionIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(DescriptionIndex));
+ // This task has not a file path and line number (as it is a linker message)
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return true;
+}
+
void IarParser::stdError(const QString &line)
{
IOutputParser::stdError(line);
const QString lne = rightTrimmed(line);
- QRegularExpression re;
- QRegularExpressionMatch match;
-
- re.setPattern("^(Error|Fatal error)\\[(.+)\\]:\\s(.+)\\s\\[(.+)$");
- match = re.match(lne);
- if (match.hasMatch()) {
- enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
- DescriptionIndex, FilepathBeginIndex };
- const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
- const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
- match.captured(DescriptionIndex));
- // This task has a file path, but this patch are split on
- // some lines, which will be received later.
- const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
- newTask(task);
- // Prepare first part of a file path.
- QString firstPart = match.captured(FilepathBeginIndex);
- firstPart.remove("referenced from ");
- m_filePathParts.push_back(firstPart);
- m_expectFilePath = true;
- m_expectSnippet = false;
+ if (parseErrorOrFatalErrorDetailsMessage1(lne))
return;
- }
-
- re.setPattern("^.*(Error|Fatal error)\\[(.+)\\]:\\s(.+)$");
- match = re.match(lne);
- if (match.hasMatch()) {
- enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
- DescriptionIndex };
- const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
- const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
- match.captured(DescriptionIndex));
- // This task has not a file path. The description details
- // will be received later on the next lines.
- const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
- newTask(task);
- m_expectSnippet = true;
- m_expectFilePath = false;
- m_expectDescription = false;
+ if (parseErrorOrFatalErrorDetailsMessage2(lne))
return;
- }
-
- re.setPattern("^\"(.+)\",(\\d+)?\\s+(Warning|Error|Fatal error)\\[(.+)\\].+$");
- match = re.match(lne);
- if (match.hasMatch()) {
- enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
- MessageTypeIndex, MessageCodeIndex };
- const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
- match.captured(FilePathIndex));
- const int lineno = match.captured(LineNumberIndex).toInt();
- const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
- // A full description will be received later on next lines.
- const Task task(type, {}, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
- newTask(task);
- const QString firstPart = QString("[%1]: ").arg(match.captured(MessageCodeIndex));
- m_descriptionParts.append(firstPart);
- m_expectDescription = true;
- m_expectSnippet = false;
- m_expectFilePath = false;
+ if (parseWarningOrErrorOrFatalErrorDetailsMessage1(lne))
return;
- }
if (lne.isEmpty()) {
//
@@ -201,12 +240,13 @@ void IarParser::stdOutput(const QString &line)
IOutputParser::stdOutput(line);
const QString lne = rightTrimmed(line);
- if (!lne.startsWith("Error in command line"))
+
+ // The call sequence has the meaning!
+ const bool leastOneParsed = parseErrorInCommandLineMessage(lne)
+ || parseErrorMessage1(lne);
+ if (!leastOneParsed)
return;
- const Task task(Task::TaskType::Error, line.trimmed(), {},
- -1, Constants::TASK_CATEGORY_COMPILE);
- newTask(task);
doFlush();
}
@@ -276,6 +316,18 @@ void BareMetalPlugin::testIarOutputParsers_data()
categoryCompile))
<< QString();
+ QTest::newRow("Linker error")
+ << QString::fromLatin1("Error[e46]: Some error")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("Error[e46]: Some error\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[e46]: Some error"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
// For std error.
QTest::newRow("No details warning")
<< QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
diff --git a/src/plugins/baremetal/iarewparser.h b/src/plugins/baremetal/iarewparser.h
index 48348d4f6fa..28cd89960ff 100644
--- a/src/plugins/baremetal/iarewparser.h
+++ b/src/plugins/baremetal/iarewparser.h
@@ -46,6 +46,12 @@ private:
void amendDescription();
void amendFilePath();
+ bool parseErrorOrFatalErrorDetailsMessage1(const QString &lne);
+ bool parseErrorOrFatalErrorDetailsMessage2(const QString &lne);
+ bool parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne);
+ bool parseErrorInCommandLineMessage(const QString &lne);
+ bool parseErrorMessage1(const QString &lne);
+
void stdError(const QString &line) final;
void stdOutput(const QString &line) final;
void doFlush() final;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index fcbebaebc6f..a638ec439a1 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -48,6 +48,7 @@
#include <projectexplorer/projectmacroexpander.h>
#include <projectexplorer/target.h>
+#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/algorithm.h>
@@ -199,11 +200,13 @@ void CMakeBuildConfiguration::initialize()
m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_NDK",
CMakeProjectManager::CMakeConfigItem::Type::PATH,
"Android NDK PATH",
- ndkLocation.toUserOutput().toUtf8()});
+ ndkLocation.toString().toUtf8()});
+
m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_TOOLCHAIN_FILE",
CMakeProjectManager::CMakeConfigItem::Type::PATH,
"Android CMake toolchain file",
- ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").toUserOutput().toUtf8()});
+ ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").toString().toUtf8()});
+
auto androidAbis = bs->data(Android::Constants::AndroidABIs).toStringList();
QString preferredAbi;
if (androidAbis.contains("arm64-v8a")) {
@@ -219,14 +222,23 @@ void CMakeBuildConfiguration::initialize()
"Android ABI",
preferredAbi.toLatin1(),
androidAbis});
+
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target()->kit());
+ if (qt->qtVersion() >= QtSupport::QtVersionNumber{5, 14, 0}) {
+ auto sdkLocation = bs->data(Android::Constants::SdkLocation).value<FilePath>();
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_SDK",
+ CMakeProjectManager::CMakeConfigItem::Type::PATH,
+ "Android SDK PATH",
+ sdkLocation.toString().toUtf8()});
+
+ }
+
m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_STL",
CMakeProjectManager::CMakeConfigItem::Type::STRING,
"Android STL",
"c++_shared"});
- m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM", "BOTH"});
- m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY", "BOTH"});
- m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE", "BOTH"});
- m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PACKAGE", "BOTH"});
+
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH", "%{Qt:QT_INSTALL_PREFIX}"});
}
BuildStepList *cleanSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN);
@@ -435,6 +447,16 @@ void CMakeBuildConfiguration::setConfigurationForCMake(const QList<ConfigModel::
const CMakeConfig config = configurationForCMake() + newConfig;
setConfigurationForCMake(config);
+
+ if (Utils::indexOf(newConfig, [](const CMakeConfigItem &item){
+ return item.key.startsWith("ANDROID_BUILD_ABI_");
+ }) != -1) {
+ // We always need to clean when we change the ANDROID_BUILD_ABI_ variables
+ QList<ProjectExplorer::BuildStepList *> stepLists;
+ const Core::Id clean = ProjectExplorer::Constants::BUILDSTEPS_CLEAN;
+ stepLists << stepList(clean);
+ BuildManager::buildLists(stepLists, QStringList() << ProjectExplorerPlugin::displayNameForStepId(clean));
+ }
}
void CMakeBuildConfiguration::clearError(ForceEnabledChanged fec)
@@ -474,7 +496,8 @@ void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config
{
auto configs = removeDuplicates(config);
if (m_configurationForCMake.isEmpty())
- m_configurationForCMake = removeDuplicates(configs + m_initialConfiguration);
+ m_configurationForCMake = removeDuplicates(m_initialConfiguration +
+ CMakeConfigurationKitAspect::configuration(target()->kit()) + configs);
else
m_configurationForCMake = configs;
diff --git a/src/plugins/coreplugin/locator/filesystemfilter.cpp b/src/plugins/coreplugin/locator/filesystemfilter.cpp
index 5e04215539d..41ad77e5c1e 100644
--- a/src/plugins/coreplugin/locator/filesystemfilter.cpp
+++ b/src/plugins/coreplugin/locator/filesystemfilter.cpp
@@ -29,13 +29,17 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
-#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
+#include <utils/checkablemessagebox.h>
#include <utils/fileutils.h>
#include <QDir>
+#include <QPushButton>
#include <QRegularExpression>
+#include <QTimer>
using namespace Core;
using namespace Core::Internal;
@@ -148,8 +152,12 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
return std::accumulate(std::begin(entries), std::end(entries), QList<LocatorFilterEntry>());
}
+const char kAlwaysCreate[] = "Locator/FileSystemFilter/AlwaysCreate";
+
void FileSystemFilter::accept(LocatorFilterEntry selection,
- QString *newText, int *selectionStart, int *selectionLength) const
+ QString *newText,
+ int *selectionStart,
+ int *selectionLength) const
{
Q_UNUSED(selectionLength)
QString fileName = selection.fileName;
@@ -159,15 +167,42 @@ void FileSystemFilter::accept(LocatorFilterEntry selection,
+ QDir::toNativeSeparators(info.absoluteFilePath() + '/');
*newText = value;
*selectionStart = value.length();
- return;
- } else if (!info.exists()) {
- QFile file(selection.internalData.toString());
- file.open(QFile::WriteOnly);
- file.close();
+ } else {
+ // Don't block locator filter execution with dialog
+ QTimer::singleShot(0, EditorManager::instance(), [info, selection] {
+ const QString targetFile = selection.internalData.toString();
+ if (!info.exists()) {
+ if (Utils::CheckableMessageBox::shouldAskAgain(ICore::settings(), kAlwaysCreate)) {
+ Utils::CheckableMessageBox messageBox(ICore::dialogParent());
+ messageBox.setWindowTitle(tr("Create File"));
+ messageBox.setIcon(QMessageBox::Question);
+ messageBox.setText(
+ tr("Create \"%1\"?")
+ .arg(Utils::FilePath::fromString(targetFile).shortNativePath()));
+ messageBox.setCheckBoxVisible(true);
+ messageBox.setCheckBoxText(tr("Always create"));
+ messageBox.setChecked(false);
+ messageBox.setStandardButtons(QDialogButtonBox::Cancel);
+ QPushButton *createButton = messageBox.addButton(tr("Create"),
+ QDialogButtonBox::AcceptRole);
+ messageBox.setDefaultButton(QDialogButtonBox::Cancel);
+ messageBox.exec();
+ if (messageBox.clickedButton() != createButton)
+ return;
+ if (messageBox.isChecked())
+ Utils::CheckableMessageBox::doNotAskAgain(ICore::settings(), kAlwaysCreate);
+ }
+ QFile file(targetFile);
+ file.open(QFile::WriteOnly);
+ file.close();
+ }
+ const QFileInfo fileInfo(targetFile);
+ const QString cleanedFilePath = QDir::cleanPath(fileInfo.absoluteFilePath());
+ EditorManager::openEditor(cleanedFilePath,
+ Id(),
+ EditorManager::CanContainLineAndColumnNumber);
+ });
}
- const QFileInfo fileInfo(selection.internalData.toString());
- const QString cleanedFilePath = QDir::cleanPath(fileInfo.absoluteFilePath());
- EditorManager::openEditor(cleanedFilePath, Id(), EditorManager::CanContainLineAndColumnNumber);
}
bool FileSystemFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp
index 31af49521fa..00201293827 100644
--- a/src/plugins/coreplugin/outputpanemanager.cpp
+++ b/src/plugins/coreplugin/outputpanemanager.cpp
@@ -513,7 +513,8 @@ void OutputPaneManager::shortcutTriggered(int idx)
// then just give it focus.
int current = currentIndex();
if (OutputPanePlaceHolder::isCurrentVisible() && current == idx) {
- if (!outputPane->hasFocus() && outputPane->canFocus()) {
+ if ((!m_outputWidgetPane->isActiveWindow() || !outputPane->hasFocus())
+ && outputPane->canFocus()) {
outputPane->setFocus();
ICore::raiseWindow(m_outputWidgetPane);
} else {
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 0958c233067..90dd8f3c86e 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -169,31 +169,24 @@ public:
// running, as this can be triggered by moving the breakpoint to
// the next line that generated code.
- m_gbp->m_params.lineNumber = lineNumber;
- m_gbp->updateMarker();
- m_gbp->update();
+ m_gbp->updateLineNumber(lineNumber);
}
void updateFileName(const FilePath &fileName) final
{
TextMark::updateFileName(fileName);
QTC_ASSERT(m_gbp, return);
- m_gbp->m_params.fileName = fileName.toString();
- m_gbp->update();
+ m_gbp->updateFileName(fileName);
}
bool isDraggable() const final { return true; }
void dragToLine(int line) final
{
+ TextMark::move(line);
QTC_ASSERT(m_gbp, return);
QTC_ASSERT(BreakpointManager::globalBreakpoints().contains(m_gbp), return);
- BreakpointParameters params = m_gbp->m_params;
- params.lineNumber = line;
- GlobalBreakpoint gbp = m_gbp;
- m_gbp = GlobalBreakpoint();
- gbp->deleteBreakpoint();
- m_gbp = BreakpointManager::createBreakpoint(params);
+ m_gbp->updateLineNumber(line);
}
bool isClickable() const final { return true; }
@@ -2273,6 +2266,23 @@ void GlobalBreakpointItem::removeBreakpointFromModel()
theBreakpointManager->destroyItem(this);
}
+void GlobalBreakpointItem::updateLineNumber(int lineNumber)
+{
+ if (m_params.lineNumber == lineNumber)
+ return;
+ m_params.lineNumber = lineNumber;
+ update();
+}
+
+void GlobalBreakpointItem::updateFileName(const FilePath &fileName)
+{
+ const QString &file = fileName.toString();
+ if (m_params.fileName == file)
+ return;
+ m_params.fileName = file;
+ update();
+}
+
QString GlobalBreakpointItem::markerFileName() const
{
// Some heuristics to find a "good" file name.
@@ -2308,11 +2318,14 @@ void GlobalBreakpointItem::updateMarker()
const FilePath file = FilePath::fromString(m_params.fileName);
const int line = m_params.lineNumber;
- if (m_marker && (file != m_marker->fileName() || line != m_marker->lineNumber()))
- destroyMarker();
-
- if (!m_marker && !file.isEmpty() && line > 0)
+ if (m_marker) {
+ if (file != m_marker->fileName())
+ m_marker->updateFileName(file);
+ if (line != m_marker->lineNumber())
+ m_marker->move(line);
+ } else if (!file.isEmpty() && line > 0) {
m_marker = new GlobalBreakpointMarker(this, file, line);
+ }
if (m_marker)
m_marker->setToolTip(toolTip());
diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h
index 83d934034b6..fa7434657f3 100644
--- a/src/plugins/debugger/breakhandler.h
+++ b/src/plugins/debugger/breakhandler.h
@@ -93,7 +93,6 @@ private:
friend class BreakHandler;
friend class BreakpointManager;
friend class BreakpointMarker;
- friend class GlobalBreakpointMarker;
void updateMarker();
void updateMarkerIcon();
diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp
index b77a2536a6b..ce01d5a5a9e 100644
--- a/src/plugins/debugger/debuggermainwindow.cpp
+++ b/src/plugins/debugger/debuggermainwindow.cpp
@@ -131,6 +131,7 @@ class DebuggerMainWindowPrivate : public QObject
{
public:
DebuggerMainWindowPrivate(DebuggerMainWindow *parent);
+ ~DebuggerMainWindowPrivate();
void selectPerspective(Perspective *perspective);
void depopulateCurrentPerspective();
@@ -256,6 +257,11 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
});
}
+DebuggerMainWindowPrivate::~DebuggerMainWindowPrivate()
+{
+ delete m_editorPlaceHolder;
+}
+
DebuggerMainWindow::DebuggerMainWindow()
: d(new DebuggerMainWindowPrivate(this))
{
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
index a8deb293471..bf9d4d9a20b 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
@@ -215,6 +215,14 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
m_overrideStartupAspect->setLabelText(tr("Additional startup commands:"));
}
+DebuggerRunConfigurationAspect::~DebuggerRunConfigurationAspect()
+{
+ delete m_cppAspect;
+ delete m_qmlAspect;
+ delete m_multiProcessAspect;
+ delete m_overrideStartupAspect;
+}
+
void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value)
{
m_qmlAspect->setValue(value);
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.h b/src/plugins/debugger/debuggerrunconfigurationaspect.h
index e34185d39e4..58619ee3ef1 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.h
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.h
@@ -42,6 +42,7 @@ class DEBUGGER_EXPORT DebuggerRunConfigurationAspect
public:
DebuggerRunConfigurationAspect(ProjectExplorer::Target *target);
+ ~DebuggerRunConfigurationAspect();
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
index 1750a13ba8e..5fbd253e7c3 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
@@ -40,7 +40,6 @@ class TextEditorWidget;
QT_BEGIN_NAMESPACE
class QMenu;
class QSplitter;
-class QTextBlock;
QT_END_NAMESPACE
namespace DiffEditor {
diff --git a/src/plugins/languageclient/languageclienthoverhandler.cpp b/src/plugins/languageclient/languageclienthoverhandler.cpp
index 9f4fc3ad370..9b53e0f9eca 100644
--- a/src/plugins/languageclient/languageclienthoverhandler.cpp
+++ b/src/plugins/languageclient/languageclienthoverhandler.cpp
@@ -96,14 +96,6 @@ void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
m_client->sendContent(request);
}
-void HoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point)
-{
- if (toolTip().isEmpty())
- Utils::ToolTip::hide();
- else
- Utils::ToolTip::show(point, toolTip(), editorWidget);
-}
-
void HoverHandler::handleResponse(const HoverRequest::Response &response)
{
m_currentRequest.reset();
@@ -134,10 +126,13 @@ void HoverHandler::setContent(const HoverContent &hoverContent)
{
if (auto markupContent = Utils::get_if<MarkupContent>(&hoverContent)) {
const QString &content = markupContent->content();
- if (markupContent->kind() == MarkupKind::plaintext)
+ if (markupContent->kind() == MarkupKind::plaintext) {
setToolTip(content);
- else if (m_client)
- m_client->log(tr("Got unsupported markup hover content: ") + content);
+ } else if (m_client) {
+ m_client->log(tr("Got unsupported markup hover content: ") + content,
+ Core::MessageManager::Silent);
+ setToolTip(content);
+ }
} else if (auto markedString = Utils::get_if<MarkedString>(&hoverContent)) {
setToolTip(toolTipForMarkedStrings({*markedString}));
} else if (auto markedStrings = Utils::get_if<QList<MarkedString>>(&hoverContent)) {
diff --git a/src/plugins/languageclient/languageclienthoverhandler.h b/src/plugins/languageclient/languageclienthoverhandler.h
index 88a439e2117..c702cd3c585 100644
--- a/src/plugins/languageclient/languageclienthoverhandler.h
+++ b/src/plugins/languageclient/languageclienthoverhandler.h
@@ -45,7 +45,6 @@ protected:
void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
int pos,
ReportPriority report) override;
- void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
private:
void handleResponse(const LanguageServerProtocol::HoverRequest::Response &response);
diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp
index a08e52208fc..fcd3a07b4ac 100644
--- a/src/plugins/languageclient/languageclientsettings.cpp
+++ b/src/plugins/languageclient/languageclientsettings.cpp
@@ -530,6 +530,7 @@ void BaseSettings::fromMap(const QVariantMap &map)
map.value(startupBehaviorKey, BaseSettings::RequiresFile).toInt());
m_languageFilter.mimeTypes = map[mimeTypeKey].toStringList();
m_languageFilter.filePattern = map[filePatternKey].toStringList();
+ m_languageFilter.filePattern.removeAll({}); // remove empty entries
}
static LanguageClientSettingsPage &settingsPage()
diff --git a/src/plugins/modeleditor/actionhandler.h b/src/plugins/modeleditor/actionhandler.h
index 192a665839c..5ec858e5356 100644
--- a/src/plugins/modeleditor/actionhandler.h
+++ b/src/plugins/modeleditor/actionhandler.h
@@ -37,7 +37,6 @@ class QAction;
QT_END_NAMESPACE
namespace Core {
-class ActionContainer;
class Command;
}
diff --git a/src/plugins/modeleditor/diagramsviewmanager.h b/src/plugins/modeleditor/diagramsviewmanager.h
index 62ecff23cc2..06a261a08bc 100644
--- a/src/plugins/modeleditor/diagramsviewmanager.h
+++ b/src/plugins/modeleditor/diagramsviewmanager.h
@@ -31,8 +31,6 @@
#include <QHash>
namespace qmt {
-class Uid;
-class DiagramView;
class MDiagram;
}
diff --git a/src/plugins/modeleditor/modeleditor.h b/src/plugins/modeleditor/modeleditor.h
index a05ab654280..7e91b38daed 100644
--- a/src/plugins/modeleditor/modeleditor.h
+++ b/src/plugins/modeleditor/modeleditor.h
@@ -42,7 +42,6 @@ class MPackage;
class MDiagram;
class DElement;
class DContainer;
-class DocumentController;
}
namespace ModelEditor {
@@ -50,7 +49,6 @@ namespace Internal {
class UiController;
class ActionHandler;
-class DiagramsViewManager;
enum class SelectedArea {
Nothing,
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizard_test.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizard_test.cpp
index 9a5947cdd1b..073432ab26c 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizard_test.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizard_test.cpp
@@ -94,12 +94,16 @@ auto findComboBox(Utils::Wizard *wizard, const QString &objectName) {
};
} // namespace
+
+struct FactoryDeleter { void operator()(ProjectExplorer::JsonWizardFactory *f) { f->deleteLater(); } };
+using FactoryPtr = std::unique_ptr<ProjectExplorer::JsonWizardFactory, FactoryDeleter>;
+
void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsEmptyWizard()
{
QString errorMessage;
const QJsonObject wizard = createGeneralWizard(QJsonObject());
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(ProjectExplorer::JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage));
QVERIFY(factory == nullptr);
QCOMPARE(qPrintable(errorMessage), "Page has no typeId set.");
}
@@ -110,7 +114,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsEmptyPage()
const QJsonObject pages = createFieldPageJsonObject(QJsonArray());
const QJsonObject wizard = createGeneralWizard(pages);
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage));
QVERIFY(factory == nullptr);
QCOMPARE(qPrintable(errorMessage), "When parsing fields of page \"PE.Wizard.Page.Fields\": ");
}
@@ -143,7 +147,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsUnusedKeyAtFields()
const QJsonObject wizard = createGeneralWizard(pages);
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("has unsupported keys: wrong"));
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizard.toVariantMap(), QDir(), &errorMessage));
QVERIFY(factory);
QVERIFY(errorMessage.isEmpty());
}
@@ -166,7 +170,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsCheckBox()
});
const QJsonObject pages = createFieldPageJsonObject(widgets);
const QJsonObject wizardObject = createGeneralWizard(pages);
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage));
QVERIFY2(factory, qPrintable(errorMessage));
Utils::Wizard *wizard = factory->runWizard(QString(), &parent, Core::Id(), QVariantMap());
@@ -198,7 +202,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsLineEdit()
});
const QJsonObject pages = createFieldPageJsonObject(widgets);
const QJsonObject wizardObject = createGeneralWizard(pages);
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage));
QVERIFY2(factory, qPrintable(errorMessage));
Utils::Wizard *wizard = factory->runWizard(QString(), &parent, Core::Id(), QVariantMap());
@@ -227,7 +231,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsComboBox()
const QJsonObject pages = createFieldPageJsonObject(widgets);
const QJsonObject wizardObject = createGeneralWizard(pages);
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage));
QVERIFY2(factory, qPrintable(errorMessage));
Utils::Wizard *wizard = factory->runWizard(QString(), &parent, Core::Id(), QVariantMap());
@@ -285,7 +289,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsIconList()
const QJsonObject pages = createFieldPageJsonObject(widgets);
const QJsonObject wizardObject = createGeneralWizard(pages);
- JsonWizardFactory *factory = ProjectExplorer::JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage);
+ const FactoryPtr factory(JsonWizardFactory::createWizardFactory(wizardObject.toVariantMap(), QDir(), &errorMessage));
QVERIFY2(factory, qPrintable(errorMessage));
Utils::Wizard *wizard = factory->runWizard(QString(), &parent, Core::Id(), QVariantMap());
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 48c5b22871f..fbdefa79962 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -776,39 +776,51 @@ void MsvcToolChain::updateEnvironmentModifications(Utils::EnvironmentItems modif
void MsvcToolChain::detectInstalledAbis()
{
- if (!m_supportedAbis.isEmpty()) // Build Tools 2015
- return;
static QMap<QString, Abis> abiCache;
const QString vcVarsBase
= QDir::fromNativeSeparators(m_vcvarsBat).left(m_vcvarsBat.lastIndexOf('/'));
if (abiCache.contains(vcVarsBase)) {
m_supportedAbis = abiCache.value(vcVarsBase);
- return;
- }
-
- QTC_ASSERT(m_supportedAbis.isEmpty(), return);
- const Abi baseAbi = targetAbi();
- for (MsvcPlatform platform : platforms) {
- bool toolchainInstalled = false;
- QString perhapsVcVarsPath = vcVarsBase + QLatin1Char('/') + QLatin1String(platform.bat);
- const Platform p = platform.platform;
- if (QFileInfo(perhapsVcVarsPath).isFile()) {
- toolchainInstalled = true;
- } else {
- // MSVC 2015 and below had various versions of vcvars scripts in subfolders. Try these
- // as fallbacks.
- perhapsVcVarsPath = vcVarsBase + platform.prefix + QLatin1Char('/')
- + QLatin1String(platform.bat);
- toolchainInstalled = QFileInfo(perhapsVcVarsPath).isFile();
- }
- if (hostSupportsPlatform(platform.platform) && toolchainInstalled) {
- Abi newAbi(archForPlatform(p), baseAbi.os(), baseAbi.osFlavor(), baseAbi.binaryFormat(),
- wordWidthForPlatform(p));
- if (!m_supportedAbis.contains(newAbi))
- m_supportedAbis.append(newAbi);
+ } else {
+ // Clear previously detected m_supportedAbis to repopulate it.
+ m_supportedAbis.clear();
+ const Abi baseAbi = targetAbi();
+ for (MsvcPlatform platform : platforms) {
+ bool toolchainInstalled = false;
+ QString perhapsVcVarsPath = vcVarsBase + QLatin1Char('/') + QLatin1String(platform.bat);
+ const Platform p = platform.platform;
+ if (QFileInfo(perhapsVcVarsPath).isFile()) {
+ toolchainInstalled = true;
+ } else {
+ // MSVC 2015 and below had various versions of vcvars scripts in subfolders. Try these
+ // as fallbacks.
+ perhapsVcVarsPath = vcVarsBase + platform.prefix + QLatin1Char('/')
+ + QLatin1String(platform.bat);
+ toolchainInstalled = QFileInfo(perhapsVcVarsPath).isFile();
+ }
+ if (hostSupportsPlatform(platform.platform) && toolchainInstalled) {
+ Abi newAbi(archForPlatform(p),
+ baseAbi.os(),
+ baseAbi.osFlavor(),
+ baseAbi.binaryFormat(),
+ wordWidthForPlatform(p));
+ if (!m_supportedAbis.contains(newAbi))
+ m_supportedAbis.append(newAbi);
+ }
}
+
+ abiCache.insert(vcVarsBase, m_supportedAbis);
}
- abiCache.insert(vcVarsBase, m_supportedAbis);
+
+ // Always add targetAbi in supportedAbis if it is empty.
+ // targetAbi is the abi with which the toolchain was detected.
+ // This is necessary for toolchains that don't have vcvars32.bat and the like in their
+ // vcVarsBase path, like msvc2010.
+ // Also, don't include that one in abiCache to avoid polluting it with values specific
+ // to one toolchain as the cache is global for a vcVarsBase path. For this reason, the
+ // targetAbi needs to be added manually.
+ if (m_supportedAbis.empty())
+ m_supportedAbis.append(targetAbi());
}
Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment &env) const
@@ -1253,13 +1265,6 @@ void MsvcToolChain::resetVarsBat()
m_varsBatArg.clear();
}
-void MsvcToolChain::setSupportedAbi(const Abi &abi)
-{
- // Hack for Build Tools 2015 only.
- QTC_CHECK(m_supportedAbis.isEmpty());
- m_supportedAbis = { abi };
-}
-
// --------------------------------------------------------------------------
// MsvcBasedToolChainConfigWidget: Creates a simple GUI without error label
// to display name and varsBat. Derived classes should add the error label and
@@ -1864,7 +1869,6 @@ static void detectCppBuildTools2015(QList<ToolChain *> *list)
tc->setDisplayName(name + QLatin1String(e.postFix));
tc->setDetection(ToolChain::AutoDetection);
tc->setLanguage(language);
- tc->setSupportedAbi(abi);
list->append(tc);
}
}
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index 79a3db4884f..80d8db723c4 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -95,8 +95,6 @@ public:
void setupVarsBat(const Abi &abi, const QString &varsBat, const QString &varsBatArg);
void resetVarsBat();
- void setSupportedAbi(const Abi &abi);
-
bool operator==(const ToolChain &) const override;
bool isJobCountSupported() const override { return false; }
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 0a69b05d028..fb3e912a651 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -639,6 +639,10 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin()
delete dd;
dd = nullptr;
m_instance = nullptr;
+
+#ifdef WITH_TESTS
+ deleteTestToolchains();
+#endif
}
ProjectExplorerPlugin *ProjectExplorerPlugin::instance()
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index 9b839e13f06..c2dffd4f6fa 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -244,6 +244,7 @@ private slots:
void testToolChainMerging_data();
void testToolChainMerging();
+ void deleteTestToolchains();
void testUserFileAccessor_prepareToReadSettings();
void testUserFileAccessor_prepareToReadSettingsObsoleteVersion();
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index 2895a2983e5..d80b2689c16 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -209,12 +209,12 @@ TargetSetupPage::TargetSetupPage(QWidget *parent) :
void TargetSetupPage::initializePage()
{
- reset();
-
- setupWidgets();
- setupImports();
- selectAtLeastOneKit();
- updateVisibility();
+ if (KitManager::isLoaded()) {
+ doInitializePage();
+ } else {
+ connect(KitManager::instance(), &KitManager::kitsLoaded,
+ this, &TargetSetupPage::doInitializePage);
+ }
}
void TargetSetupPage::setRequiredKitPredicate(const Kit::Predicate &predicate)
@@ -241,6 +241,7 @@ TargetSetupPage::~TargetSetupPage()
{
disconnect();
reset();
+ delete m_spacer;
delete m_ui;
}
@@ -493,6 +494,15 @@ void TargetSetupPage::kitFilterChanged(const QString &filterText)
selectAtLeastOneKit();
}
+void TargetSetupPage::doInitializePage()
+{
+ reset();
+ setupWidgets();
+ setupImports();
+ selectAtLeastOneKit();
+ updateVisibility();
+}
+
void TargetSetupPage::changeAllKitsSelections()
{
if (m_ui->allKitsCheckBox->checkState() == Qt::PartiallyChecked)
diff --git a/src/plugins/projectexplorer/targetsetuppage.h b/src/plugins/projectexplorer/targetsetuppage.h
index c0814a1ce48..e8cc7aef9e6 100644
--- a/src/plugins/projectexplorer/targetsetuppage.h
+++ b/src/plugins/projectexplorer/targetsetuppage.h
@@ -87,6 +87,8 @@ public:
void kitFilterChanged(const QString &filterText);
private:
+ void doInitializePage();
+
void handleKitAddition(Kit *k);
void handleKitRemoval(Kit *k);
void handleKitUpdate(Kit *k);
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
index ea5a07f0fe1..78fafb5ea75 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
@@ -309,7 +309,7 @@ public:
setTypeDisplayName("Test Tool Chain");
}
- static QList<TTC *> toolChains();
+ static QList<TTC *> toolChains() { return m_toolChains; }
static bool hasToolChains() { return !m_toolChains.isEmpty(); }
Abi targetAbi() const override { return Abi::hostAbi(); }
@@ -507,6 +507,11 @@ void ProjectExplorerPlugin::testToolChainMerging()
Utils::toSet(ops.toRegister + ops.toDemote + ops.toDelete));
}
+void ProjectExplorerPlugin::deleteTestToolchains()
+{
+ qDeleteAll(TTC::toolChains());
+}
+
} // namespace ProjectExplorer
#endif // WITH_TESTS
diff --git a/src/plugins/python/pythoneditor.cpp b/src/plugins/python/pythoneditor.cpp
index 6481897e699..eea74c17868 100644
--- a/src/plugins/python/pythoneditor.cpp
+++ b/src/plugins/python/pythoneditor.cpp
@@ -35,19 +35,6 @@
namespace Python {
namespace Internal {
-static void documentOpened(Core::IDocument *document)
-{
- auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
- if (!textDocument || textDocument->mimeType() != Constants::C_PY_MIMETYPE)
- return;
-
- const Utils::FilePath &python = detectPython(textDocument->filePath());
- if (!python.exists())
- return;
-
- updateEditorInfoBar(python, textDocument);
-}
-
PythonEditorFactory::PythonEditorFactory()
{
setId(Constants::C_PYTHONEDITOR_ID);
@@ -68,7 +55,7 @@ PythonEditorFactory::PythonEditorFactory()
setCodeFoldingSupported(true);
connect(Core::EditorManager::instance(), &Core::EditorManager::documentOpened,
- this, documentOpened);
+ this, &PyLSConfigureAssistant::documentOpened);
}
} // namespace Internal
diff --git a/src/plugins/python/pythonplugin.cpp b/src/plugins/python/pythonplugin.cpp
index bdb0d6a32e6..63d7c663c2e 100644
--- a/src/plugins/python/pythonplugin.cpp
+++ b/src/plugins/python/pythonplugin.cpp
@@ -51,6 +51,8 @@ namespace Internal {
//
////////////////////////////////////////////////////////////////////////////////////
+static PythonPlugin *m_instance = nullptr;
+
class PythonPluginPrivate
{
public:
@@ -65,11 +67,22 @@ public:
};
};
+PythonPlugin::PythonPlugin()
+{
+ m_instance = this;
+}
+
PythonPlugin::~PythonPlugin()
{
+ m_instance = nullptr;
delete d;
}
+PythonPlugin *PythonPlugin::instance()
+{
+ return m_instance;
+}
+
bool PythonPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(arguments)
diff --git a/src/plugins/python/pythonplugin.h b/src/plugins/python/pythonplugin.h
index 5b2e395d917..c0d79d7a874 100644
--- a/src/plugins/python/pythonplugin.h
+++ b/src/plugins/python/pythonplugin.h
@@ -36,9 +36,11 @@ class PythonPlugin : public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Python.json")
public:
- PythonPlugin() = default;
+ PythonPlugin();
~PythonPlugin() final;
+ static PythonPlugin *instance();
+
private:
bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final;
diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp
index 37cbc53a9af..4477f11cb14 100644
--- a/src/plugins/python/pythonrunconfiguration.cpp
+++ b/src/plugins/python/pythonrunconfiguration.cpp
@@ -294,23 +294,10 @@ void PythonRunConfiguration::updateLanguageServer()
const FilePath python(FilePath::fromUserInput(interpreter()));
- if (const StdIOSettings *lsSetting = languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientForSetting(lsSetting).value(0)) {
- for (FilePath &file : project()->files(Project::AllFiles)) {
- if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
- if (document->mimeType() == Constants::C_PY_MIMETYPE) {
- resetEditorInfoBar(document);
- LanguageClientManager::reOpenDocumentWithClient(document, client);
- }
- }
- }
- }
- }
-
for (FilePath &file : project()->files(Project::AllFiles)) {
if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
if (document->mimeType() == Constants::C_PY_MIMETYPE)
- updateEditorInfoBar(python, document);
+ PyLSConfigureAssistant::instance()->openDocumentWithPython(python, document);
}
}
}
diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp
index be1ad7b4ee9..d9ab47093c9 100644
--- a/src/plugins/python/pythonsettings.cpp
+++ b/src/plugins/python/pythonsettings.cpp
@@ -272,15 +272,14 @@ static bool alreadyRegistered(const QList<Interpreter> &pythons, const FilePath
});
}
-Interpreter interpreterForPythonExecutable(const FilePath &python,
- const QString &defaultName,
- bool windowedSuffix = false)
+Interpreter::Interpreter(const FilePath &python, const QString &defaultName, bool windowedSuffix)
+ : id(QUuid::createUuid().toString())
+ , command(python)
{
SynchronousProcess pythonProcess;
pythonProcess.setProcessChannelMode(QProcess::MergedChannels);
SynchronousProcessResponse response = pythonProcess.runBlocking(
CommandLine(python, {"--version"}));
- QString name;
if (response.result == SynchronousProcessResponse::Finished)
name = response.stdOut().trimmed();
if (name.isEmpty())
@@ -290,9 +289,14 @@ Interpreter interpreterForPythonExecutable(const FilePath &python,
QDir pythonDir(python.parentDir().toString());
if (pythonDir.exists() && pythonDir.exists("activate") && pythonDir.cdUp())
name += QString(" (%1 Virtual Environment)").arg(pythonDir.dirName());
- return Interpreter{QUuid::createUuid().toString(), name, python};
}
+Interpreter::Interpreter(const QString &_id, const QString &_name, const FilePath &_command)
+ : id(_id)
+ , name(_name)
+ , command(_command)
+{}
+
static InterpreterOptionsPage &interpreterOptionsPage()
{
static InterpreterOptionsPage page;
@@ -388,11 +392,11 @@ static void addPythonsFromRegistry(QList<Interpreter> &pythons)
const FilePath &path = FilePath::fromUserInput(regVal.toString());
const FilePath &python = path.pathAppended(HostOsInfo::withExecutableSuffix("python"));
if (python.exists() && !alreadyRegistered(pythons, python))
- pythons << interpreterForPythonExecutable(python, "Python " + versionGroup);
+ pythons << Interpreter(python, "Python " + versionGroup);
const FilePath &pythonw = path.pathAppended(
HostOsInfo::withExecutableSuffix("pythonw"));
if (pythonw.exists() && !alreadyRegistered(pythons, pythonw))
- pythons << interpreterForPythonExecutable(pythonw, "Python " + versionGroup, true);
+ pythons << Interpreter(pythonw, "Python " + versionGroup, true);
}
pythonRegistry.endGroup();
}
@@ -405,11 +409,11 @@ static void addPythonsFromPath(QList<Interpreter> &pythons)
if (HostOsInfo::isWindowsHost()) {
for (const FilePath &executable : env.findAllInPath("python")) {
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << interpreterForPythonExecutable(executable, "Python from Path");
+ pythons << Interpreter(executable, "Python from Path");
}
for (const FilePath &executable : env.findAllInPath("pythonw")) {
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << interpreterForPythonExecutable(executable, "Python from Path", true);
+ pythons << Interpreter(executable, "Python from Path", true);
}
} else {
const QStringList filters = {"python",
@@ -421,7 +425,7 @@ static void addPythonsFromPath(QList<Interpreter> &pythons)
for (const QFileInfo &fi : dir.entryInfoList(filters)) {
const FilePath executable = Utils::FilePath::fromFileInfo(fi);
if (executable.exists() && !alreadyRegistered(pythons, executable))
- pythons << interpreterForPythonExecutable(executable, "Python from Path");
+ pythons << Interpreter(executable, "Python from Path");
}
}
}
diff --git a/src/plugins/python/pythonsettings.h b/src/plugins/python/pythonsettings.h
index 583d4fb212f..7ca5218ae39 100644
--- a/src/plugins/python/pythonsettings.h
+++ b/src/plugins/python/pythonsettings.h
@@ -35,7 +35,15 @@ namespace Internal {
class Interpreter
{
public:
- QString id;
+ Interpreter() = default;
+ Interpreter(const Utils::FilePath &python,
+ const QString &defaultName,
+ bool windowedSuffix = false);
+ Interpreter(const QString &id,
+ const QString &name,
+ const Utils::FilePath &command);
+
+ QString id = QUuid::createUuid().toString();
QString name;
Utils::FilePath command;
};
diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp
index 0af6d5fd5a9..03096ee96e9 100644
--- a/src/plugins/python/pythonutils.cpp
+++ b/src/plugins/python/pythonutils.cpp
@@ -26,6 +26,7 @@
#include "pythonutils.h"
#include "pythonconstants.h"
+#include "pythonplugin.h"
#include "pythonproject.h"
#include "pythonrunconfiguration.h"
#include "pythonsettings.h"
@@ -33,8 +34,8 @@
#include <coreplugin/infobar.h>
#include <coreplugin/progressmanager/progressmanager.h>
-#include <languageclient/languageclientsettings.h>
#include <languageclient/languageclientmanager.h>
+#include <languageclient/languageclientsettings.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -49,6 +50,7 @@
#include <QRegularExpression>
#include <QTimer>
+using namespace LanguageClient;
using namespace Utils;
namespace Python {
@@ -58,7 +60,6 @@ static constexpr char startPylsInfoBarId[] = "Python::StartPyls";
static constexpr char installPylsInfoBarId[] = "Python::InstallPyls";
static constexpr char enablePylsInfoBarId[] = "Python::EnablePyls";
static constexpr char installPylsTaskId[] = "Python::InstallPylsTask";
-static constexpr char pythonUtilsTrContext[] = "Python::Utils";
struct PythonLanguageServerState
{
@@ -116,7 +117,7 @@ FilePath getPylsModulePath(CommandLine pylsCommand)
return {};
}
-QList<const LanguageClient::StdIOSettings *> configuredPythonLanguageServer()
+QList<const StdIOSettings *> configuredPythonLanguageServer()
{
using namespace LanguageClient;
QList<const StdIOSettings *> result;
@@ -156,7 +157,7 @@ static PythonLanguageServerState checkPythonLanguageServer(const FilePath &pytho
return {PythonLanguageServerState::CanNotBeInstalled, FilePath()};
}
-FilePath detectPython(const FilePath &documentPath)
+static FilePath detectPython(const FilePath &documentPath)
{
FilePath python;
@@ -183,26 +184,33 @@ FilePath detectPython(const FilePath &documentPath)
return python;
}
-const LanguageClient::StdIOSettings *languageServerForPython(const FilePath &python)
+PyLSConfigureAssistant *PyLSConfigureAssistant::instance()
+{
+ static auto *instance = new PyLSConfigureAssistant(PythonPlugin::instance());
+ return instance;
+}
+
+const StdIOSettings *PyLSConfigureAssistant::languageServerForPython(const FilePath &python)
{
return findOrDefault(configuredPythonLanguageServer(),
- [pythonModulePath = getPylsModulePath(CommandLine(python, {"-m", "pyls"}))](
- const LanguageClient::StdIOSettings *setting) {
+ [pythonModulePath = getPylsModulePath(
+ CommandLine(python, {"-m", "pyls"}))](const StdIOSettings *setting) {
return getPylsModulePath(setting->command()) == pythonModulePath;
});
}
-static LanguageClient::Client *registerLanguageServer(const FilePath &python)
+static Client *registerLanguageServer(const FilePath &python)
{
- auto *settings = new LanguageClient::StdIOSettings();
+ auto *settings = new StdIOSettings();
settings->m_executable = python.toString();
settings->m_arguments = "-m pyls";
- settings->m_name = QCoreApplication::translate(pythonUtilsTrContext,
- "Python Language Server (%1)")
+ settings->m_name = PyLSConfigureAssistant::tr("Python Language Server (%1)")
.arg(pythonName(python));
settings->m_languageFilter.mimeTypes = QStringList(Constants::C_PY_MIMETYPE);
- LanguageClient::LanguageClientManager::registerClientSettings(settings);
- return LanguageClient::LanguageClientManager::clientForSetting(settings).value(0);
+ LanguageClientManager::registerClientSettings(settings);
+ Client *client = LanguageClientManager::clientForSetting(settings).value(0);
+ PyLSConfigureAssistant::updateEditorInfoBars(python, client);
+ return client;
}
class PythonLSInstallHelper : public QObject
@@ -240,7 +248,7 @@ public:
? QString{"python-language-server[pyflakes]"}
: QString{"python-language-server[all]"};
- m_process.start(m_python.toString(), {"-m", "pip", "install", pylsVersion});
+ m_process.start(m_python.toString(), {"-m", "pip", "install", "--user", pylsVersion});
Core::MessageManager::write(tr("Running '%1 %2' to install python language server")
.arg(m_process.program(), m_process.arguments().join(' ')));
@@ -253,17 +261,16 @@ private:
void cancel()
{
SynchronousProcess::stopProcess(m_process);
- Core::MessageManager::write(
- tr("The Python language server installation canceled by %1.")
- .arg(m_killTimer.isActive() ? tr("user") : tr("time out")));
+ Core::MessageManager::write(tr("The Python language server installation canceled by %1.")
+ .arg(m_killTimer.isActive() ? tr("user") : tr("time out")));
}
void installFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
m_future.reportFinished();
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
- if (LanguageClient::Client *client = registerLanguageServer(m_python))
- LanguageClient::LanguageClientManager::reOpenDocumentWithClient(m_document, client);
+ if (Client *client = registerLanguageServer(m_python))
+ LanguageClientManager::reOpenDocumentWithClient(m_document, client);
} else {
Core::MessageManager::write(
tr("Installing the Python language server failed with exit code %1").arg(exitCode));
@@ -293,11 +300,16 @@ private:
QPointer<TextEditor::TextDocument> m_document;
};
-static void installPythonLanguageServer(const FilePath &python,
- QPointer<TextEditor::TextDocument> document)
+void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
+ QPointer<TextEditor::TextDocument> document)
{
document->infoBar()->removeInfo(installPylsInfoBarId);
+ // Hide all install info bar entries for this python, but keep them in the list
+ // so the language server will be setup properly after the installation is done.
+ for (TextEditor::TextDocument *additionalDocument : m_infoBarEntries[python])
+ additionalDocument->infoBar()->removeInfo(installPylsInfoBarId);
+
auto install = new PythonLSInstallHelper(python, document);
install->run();
}
@@ -306,36 +318,49 @@ static void setupPythonLanguageServer(const FilePath &python,
QPointer<TextEditor::TextDocument> document)
{
document->infoBar()->removeInfo(startPylsInfoBarId);
- if (LanguageClient::Client *client = registerLanguageServer(python))
- LanguageClient::LanguageClientManager::reOpenDocumentWithClient(document, client);
+ if (Client *client = registerLanguageServer(python))
+ LanguageClientManager::reOpenDocumentWithClient(document, client);
}
static void enablePythonLanguageServer(const FilePath &python,
QPointer<TextEditor::TextDocument> document)
{
- using namespace LanguageClient;
document->infoBar()->removeInfo(enablePylsInfoBarId);
- if (const StdIOSettings *setting = languageServerForPython(python)) {
+ if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
LanguageClientManager::enableClientSettings(setting->m_id);
- if (const StdIOSettings *setting = languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientForSetting(setting).value(0))
+ if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
+ if (Client *client = LanguageClientManager::clientForSetting(setting).value(0)) {
LanguageClientManager::reOpenDocumentWithClient(document, client);
+ PyLSConfigureAssistant::updateEditorInfoBars(python, client);
+ }
}
}
}
-void updateEditorInfoBar(const FilePath &python, TextEditor::TextDocument *document)
+void PyLSConfigureAssistant::documentOpened(Core::IDocument *document)
+{
+ auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
+ if (!textDocument || textDocument->mimeType() != Constants::C_PY_MIMETYPE)
+ return;
+
+ const FilePath &python = detectPython(textDocument->filePath());
+ if (!python.exists())
+ return;
+
+ instance()->openDocumentWithPython(python, textDocument);
+}
+
+void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
+ TextEditor::TextDocument *document)
{
const PythonLanguageServerState &lsState = checkPythonLanguageServer(python);
if (lsState.state == PythonLanguageServerState::CanNotBeInstalled)
return;
if (lsState.state == PythonLanguageServerState::AlreadyConfigured) {
- if (const LanguageClient::StdIOSettings *setting = languageServerForPython(python)) {
- if (LanguageClient::Client *client
- = LanguageClient::LanguageClientManager::clientForSetting(setting).value(0)) {
- LanguageClient::LanguageClientManager::reOpenDocumentWithClient(document, client);
- }
+ if (const StdIOSettings *setting = languageServerForPython(python)) {
+ if (Client *client = LanguageClientManager::clientForSetting(setting).value(0))
+ LanguageClientManager::reOpenDocumentWithClient(document, client);
}
return;
}
@@ -345,52 +370,66 @@ void updateEditorInfoBar(const FilePath &python, TextEditor::TextDocument *docum
if (lsState.state == PythonLanguageServerState::CanBeInstalled
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
auto message
- = QCoreApplication::translate(pythonUtilsTrContext,
- "Install and set up Python language server (PyLS) for %1 (%2). "
- "The language server provides Python specific completions and annotations.")
+ = tr("Install and set up Python language server (PyLS) for %1 (%2). "
+ "The language server provides Python specific completions and annotations.")
.arg(pythonName(python), python.toUserOutput());
Core::InfoBarEntry info(installPylsInfoBarId,
message,
Core::InfoBarEntry::GlobalSuppression::Enabled);
- info.setCustomButtonInfo(QCoreApplication::translate(pythonUtilsTrContext, "Install"),
+ info.setCustomButtonInfo(tr("Install"),
[=]() { installPythonLanguageServer(python, document); });
infoBar->addInfo(info);
+ m_infoBarEntries[python] << document;
} else if (lsState.state == PythonLanguageServerState::AlreadyInstalled
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
- auto message = QCoreApplication::translate(pythonUtilsTrContext,
- "Found a Python language server for %1 (%2). "
- "Should this one be set up for this document?")
+ auto message = tr("Found a Python language server for %1 (%2). "
+ "Should this one be set up for this document?")
.arg(pythonName(python), python.toUserOutput());
Core::InfoBarEntry info(startPylsInfoBarId,
message,
Core::InfoBarEntry::GlobalSuppression::Enabled);
- info.setCustomButtonInfo(QCoreApplication::translate(pythonUtilsTrContext, "Setup"),
+ info.setCustomButtonInfo(tr("Setup"),
[=]() { setupPythonLanguageServer(python, document); });
infoBar->addInfo(info);
+ m_infoBarEntries[python] << document;
} else if (lsState.state == PythonLanguageServerState::ConfiguredButDisabled
&& infoBar->canInfoBeAdded(enablePylsInfoBarId)) {
- auto message = QCoreApplication::translate(pythonUtilsTrContext,
- "Enable Python language server for %1 (%2)?")
+ auto message = tr("Enable Python language server for %1 (%2)?")
.arg(pythonName(python), python.toUserOutput());
Core::InfoBarEntry info(enablePylsInfoBarId,
message,
Core::InfoBarEntry::GlobalSuppression::Enabled);
- info.setCustomButtonInfo(QCoreApplication::translate(pythonUtilsTrContext, "Enable"),
+ info.setCustomButtonInfo(tr("Enable"),
[=]() { enablePythonLanguageServer(python, document); });
infoBar->addInfo(info);
+ m_infoBarEntries[python] << document;
}
}
-void resetEditorInfoBar(TextEditor::TextDocument *document)
+void PyLSConfigureAssistant::updateEditorInfoBars(const FilePath &python, Client *client)
{
+ for (TextEditor::TextDocument *document : instance()->m_infoBarEntries.take(python)) {
+ instance()->resetEditorInfoBar(document);
+ if (client)
+ LanguageClientManager::reOpenDocumentWithClient(document, client);
+ }
+}
+
+void PyLSConfigureAssistant::resetEditorInfoBar(TextEditor::TextDocument *document)
+{
+ for (QList<TextEditor::TextDocument *> &documents : m_infoBarEntries)
+ documents.removeAll(document);
Core::InfoBar *infoBar = document->infoBar();
infoBar->removeInfo(installPylsInfoBarId);
infoBar->removeInfo(startPylsInfoBarId);
infoBar->removeInfo(enablePylsInfoBarId);
}
+PyLSConfigureAssistant::PyLSConfigureAssistant(QObject *parent)
+ : QObject(parent)
+{}
+
} // namespace Internal
} // namespace Python
#include "pythonutils.moc"
-
diff --git a/src/plugins/python/pythonutils.h b/src/plugins/python/pythonutils.h
index f376a4d7492..20cb674ddb9 100644
--- a/src/plugins/python/pythonutils.h
+++ b/src/plugins/python/pythonutils.h
@@ -23,21 +23,45 @@
**
****************************************************************************/
+#pragma once
+
#include <utils/fileutils.h>
-#pragma once
+#include <QHash>
+#include <QObject>
+namespace Core { class IDocument; }
+namespace LanguageClient {
+class Client;
+class StdIOSettings;
+}
namespace TextEditor { class TextDocument; }
-namespace LanguageClient { class StdIOSettings; }
namespace Python {
namespace Internal {
-QList<const LanguageClient::StdIOSettings *> configuredPythonLanguageServers();
-const LanguageClient::StdIOSettings *languageServerForPython(const Utils::FilePath &python);
-Utils::FilePath detectPython(const Utils::FilePath &NdocumentPath);
-void updateEditorInfoBar(const Utils::FilePath &python, TextEditor::TextDocument *document);
-void resetEditorInfoBar(TextEditor::TextDocument *document);
+class PyLSConfigureAssistant : public QObject
+{
+ Q_OBJECT
+public:
+ static PyLSConfigureAssistant *instance();
+
+ static const LanguageClient::StdIOSettings *languageServerForPython(
+ const Utils::FilePath &python);
+ static void documentOpened(Core::IDocument *document);
+ static void updateEditorInfoBars(const Utils::FilePath &python, LanguageClient::Client *client);
+
+ void openDocumentWithPython(const Utils::FilePath &python, TextEditor::TextDocument *document);
+
+private:
+ explicit PyLSConfigureAssistant(QObject *parent);
+
+ void resetEditorInfoBar(TextEditor::TextDocument *document);
+ void installPythonLanguageServer(const Utils::FilePath &python,
+ QPointer<TextEditor::TextDocument> document);
+
+ QHash<Utils::FilePath, QList<TextEditor::TextDocument *>> m_infoBarEntries;
+};
} // namespace Internal
} // namespace Python
diff --git a/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp b/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
index 998a33fdddc..34553567b94 100644
--- a/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
+++ b/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
@@ -30,9 +30,10 @@
#include <utils/hostosinfo.h>
#include <utils/fileutils.h>
-#include <QVBoxLayout>
-#include <QRadioButton>
#include <QLabel>
+#include <QRadioButton>
+#include <QScrollArea>
+#include <QVBoxLayout>
#include <QFileInfo>
#include <QTextStream>
@@ -268,11 +269,18 @@ SummaryPage::SummaryPage(AddLibraryWizard *parent)
setFinalPage(true);
auto *layout = new QVBoxLayout(this);
+ const auto scrollArea = new QScrollArea;
+ const auto snippetWidget = new QWidget;
+ const auto snippetLayout = new QVBoxLayout(snippetWidget);
m_summaryLabel = new QLabel(this);
m_snippetLabel = new QLabel(this);
m_snippetLabel->setWordWrap(true);
layout->addWidget(m_summaryLabel);
- layout->addWidget(m_snippetLabel);
+ snippetLayout->addWidget(m_snippetLabel);
+ snippetLayout->addStretch(1);
+ scrollArea->setWidget(snippetWidget);
+ scrollArea->setWidgetResizable(true);
+ layout->addWidget(scrollArea);
m_summaryLabel->setTextFormat(Qt::RichText);
m_snippetLabel->setTextFormat(Qt::RichText);
m_snippetLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
index bfdbfe5c224..3f403d03133 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
@@ -165,7 +165,7 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
QMap<QString, int> tabMap; // QMap used for alphabetical order
for (const auto &file : qAsConst(m_quick3DFiles)) {
auto extIt = supportedExtensions.constBegin();
- QString ext = QFileInfo(file).suffix();
+ QString ext = QFileInfo(file).suffix().toLower();
while (extIt != supportedExtensions.constEnd()) {
if (!tabMap.contains(extIt.key()) && extIt.value().contains(ext)) {
tabMap.insert(extIt.key(), m_extToImportOptionsMap.value(ext));
@@ -298,6 +298,10 @@ void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int option
QJsonValue optValue = optObj.value("value");
QJsonArray conditions = optObj.value("conditions").toArray();
+ auto *optLabel = new QLabel(optionsAreaContents);
+ optLabel->setText(optName);
+ optLabel->setToolTip(optDesc);
+
QWidget *optControl = nullptr;
if (optType == "Boolean") {
auto *optCheck = new QCheckBox(optionsAreaContents);
@@ -346,15 +350,11 @@ void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int option
qWarning() << __FUNCTION__ << "Unsupported option type:" << optType;
continue;
}
+ optControl->setToolTip(optDesc);
if (!conditions.isEmpty())
conditionMap.insert(optKey, conditions);
- auto *optLabel = new QLabel(optionsAreaContents);
- optLabel->setText(optName);
- optLabel->setToolTip(optDesc);
- optControl->setToolTip(optDesc);
-
const QString &groupName = optionToGroupMap.value(optKey);
if (!groupName.isEmpty() && groupIndexMap.contains(groupName))
widgets[groupIndexMap[groupName]].append({optLabel, optControl});
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index ac40e87c791..d4f1d090baf 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -173,7 +173,7 @@ bool ItemLibraryAssetImporter::isQuick3DAsset(const QString &fileName) const
for (const auto &ext : exts)
quick3DExt << ext;
}
- return quick3DExt.contains(QFileInfo(fileName).suffix());
+ return quick3DExt.contains(QFileInfo(fileName).suffix().toLower());
#else
Q_UNUSED(fileName)
return false;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 8010ed61075..a24cfc731e2 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -517,7 +517,7 @@ void ItemLibraryWidget::addResources()
QMultiMap<QString, QString> partitionedFileNames;
for (const QString &fileName : fileNames) {
- const QString suffix = "*." + QFileInfo(fileName).suffix();
+ const QString suffix = "*." + QFileInfo(fileName).suffix().toLower();
const QString category = reverseMap.value(suffix);
partitionedFileNames.insert(category, fileName);
}
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 1e1032900bf..5c9356f556e 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -194,6 +194,8 @@ private: // functions
private:
void handleCrash();
+ void startPuppetTransaction();
+ void endPuppetTransaction();
private: //variables
NodeInstance m_rootNodeInstance;
@@ -209,6 +211,7 @@ private: //variables
ProjectExplorer::Kit *m_currentKit = nullptr;
ProjectExplorer::Project *m_currentProject = nullptr;
int m_restartProcessTimerId;
+ RewriterTransaction m_puppetTransaction;
};
} // namespace ProxyNodeInstanceView
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 7200231267a..92b0880c808 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -70,6 +70,7 @@
#include "nodeinstanceserverproxy.h"
#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
#include <QUrl>
#include <QMultiHash>
@@ -218,6 +219,30 @@ void NodeInstanceView::handleCrash()
emitCustomNotification(QStringLiteral("puppet crashed"));
}
+void NodeInstanceView::startPuppetTransaction()
+{
+ /* We assume no transaction is active. */
+ QTC_ASSERT(!m_puppetTransaction.isValid(), return);
+ m_puppetTransaction = beginRewriterTransaction("NodeInstanceView::PuppetTransaction");
+}
+
+void NodeInstanceView::endPuppetTransaction()
+{
+ /* We assume a transaction is active. */
+ QTC_ASSERT(m_puppetTransaction.isValid(), return);
+
+ /* Committing a transaction should not throw, but if there is
+ * an issue with rewriting we should show an error message, instead
+ * of simply crashing.
+ */
+
+ try {
+ m_puppetTransaction.commit();
+ } catch (Exception &e) {
+ e.showException();
+ }
+}
+
void NodeInstanceView::restartProcess()
{
if (rootNodeInstance().isValid())
@@ -1195,11 +1220,20 @@ void NodeInstanceView::valuesModified(const ValuesModifiedCommand &command)
if (!model())
return;
+ if (command.transactionOption == ValuesModifiedCommand::TransactionOption::Start)
+ startPuppetTransaction();
+ else if (command.transactionOption == ValuesModifiedCommand::TransactionOption::End)
+ endPuppetTransaction();
+
for (const PropertyValueContainer &container : command.valueChanges()) {
if (hasInstanceForId(container.instanceId())) {
NodeInstance instance = instanceForId(container.instanceId());
- if (instance.isValid())
- instance.modelNode().variantProperty(container.name()).setValue(container.value());
+ if (instance.isValid()) {
+ ModelNode node = instance.modelNode();
+ VariantProperty property = instance.modelNode().variantProperty(container.name());
+ if (property.value() != container.value())
+ property.setValue(container.value());
+ }
}
}
}
@@ -1329,7 +1363,6 @@ void NodeInstanceView::childrenChanged(const ChildrenChangedCommand &command)
if (!model())
return;
-
QVector<ModelNode> childNodeVector;
foreach (qint32 instanceId, command.childrenInstances()) {
@@ -1396,6 +1429,7 @@ void NodeInstanceView::sendToken(const QString &token, int number, const QVector
void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
{
+ clearSelectedModelNodes();
foreach (const qint32 &instanceId, command.instanceIds()) {
if (hasModelNodeForInternalId(instanceId))
selectModelNode(modelNodeForInternalId(instanceId));
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index b2e5e3a8b84..69bc9ff0f92 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -356,7 +356,10 @@ bool compareJavaScriptExpression(const QString &expression1, const QString &expr
bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2)
{ //we ignore slight changes on doubles and only check three digits
- if ((value1.type() == QVariant::Double) || (value2.type() == QVariant::Double)) {
+ if ((value1.type() == QMetaType::Double)
+ || (value2.type() == QMetaType::Double)
+ || (value1.type() == QMetaType::Float)
+ || (value2.type() == QMetaType::Float)) {
bool ok1, ok2;
qreal a = value1.toDouble(&ok1);
qreal b = value2.toDouble(&ok2);
diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
index 4182ca28264..2e3f9c2d4d9 100644
--- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
+++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
@@ -169,12 +169,11 @@ void QnxDeployQtLibrariesDialog::updateProgress(const QString &progressMessage)
{
QTC_CHECK(m_state == Uploading);
- if (!progressMessage.startsWith(QLatin1String("Uploading file")))
- return;
-
- ++m_progressCount;
-
- m_ui->deployProgress->setValue(m_progressCount);
+ const int progress = progressMessage.count("sftp> put");
+ if (progress != 0) {
+ m_progressCount += progress;
+ m_ui->deployProgress->setValue(m_progressCount);
+ }
}
void QnxDeployQtLibrariesDialog::handleUploadFinished()
diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
index 5143efe7d95..a9a3eca3a1e 100644
--- a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
+++ b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
@@ -42,6 +42,7 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
addQmlServerInferiorCommandLineArgumentIfNeeded();
auto gdbServer = new GdbServerRunner(runControl, portsGatherer());
+ gdbServer->setEssential(true);
addStartDependency(gdbServer);
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index 136fa30e769..d7d53ca5f0c 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -142,12 +142,15 @@ void BaseHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, Re
void BaseHoverHandler::decorateToolTip()
{
- m_toolTip = m_toolTip.toHtmlEscaped();
+ if (!m_toolTip.isEmpty())
+ m_toolTip = "<p>" + m_toolTip.toHtmlEscaped().replace('\n', "<br/>") + "</p>";
if (lastHelpItemIdentified().isValid() && !lastHelpItemIdentified().isFuzzyMatch()) {
const QString &helpContents = lastHelpItemIdentified().extractContent(false);
- if (!helpContents.isEmpty())
- m_toolTip = m_toolTip.isEmpty() ? helpContents : ("<p>" + m_toolTip + "</p><hr/><p>" + helpContents + "</p>");
+ if (!helpContents.isEmpty()) {
+ m_toolTip = m_toolTip.isEmpty() ? helpContents
+ : (m_toolTip + "<hr/><p>" + helpContents + "</p>");
+ }
}
}
@@ -159,7 +162,9 @@ void BaseHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoi
Utils::ToolTip::show(point,
m_toolTip,
editorWidget,
- QVariant::fromValue(m_lastHelpItemIdentified));
+ m_lastHelpItemIdentified.isEmpty()
+ ? QVariant()
+ : QVariant::fromValue(m_lastHelpItemIdentified));
}
} // namespace TextEditor
diff --git a/src/plugins/webassembly/webassemblyqtversion.cpp b/src/plugins/webassembly/webassemblyqtversion.cpp
index 54f51be4bb4..ba1b0a76999 100644
--- a/src/plugins/webassembly/webassemblyqtversion.cpp
+++ b/src/plugins/webassembly/webassemblyqtversion.cpp
@@ -59,6 +59,9 @@ WebAssemblyQtVersionFactory::WebAssemblyQtVersionFactory()
setQtVersionCreator([] { return new WebAssemblyQtVersion; });
setSupportedType(Constants::WEBASSEMBLY_QT_VERSION);
setPriority(1);
+ setRestrictionChecker([](const SetupData &setup) {
+ return setup.platforms.contains("wasm");
+ });
}
} // namespace Internal
diff --git a/src/plugins/webassembly/webassemblyrunconfiguration.cpp b/src/plugins/webassembly/webassemblyrunconfiguration.cpp
index 6bed76d2dd0..f4c56630fde 100644
--- a/src/plugins/webassembly/webassemblyrunconfiguration.cpp
+++ b/src/plugins/webassembly/webassemblyrunconfiguration.cpp
@@ -42,17 +42,19 @@ namespace Internal {
static CommandLine emrunCommand(Target *target, const QString &browser, const QString &port)
{
- BuildConfiguration *bc = target->activeBuildConfiguration();
- const QFileInfo emrunScript = bc->environment().searchInPath("emrun").toFileInfo();
- auto html = bc->buildDirectory().pathAppended(target->project()->displayName() + ".html");
-
- return CommandLine(bc->environment().searchInPath("python"), {
- emrunScript.absolutePath() + "/" + emrunScript.baseName() + ".py",
- "--browser", browser,
- "--port", port,
- "--no_emrun_detect",
- html.toString()
- });
+ if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
+ const QFileInfo emrunScript = bc->environment().searchInPath("emrun").toFileInfo();
+ auto html = bc->buildDirectory().pathAppended(target->project()->displayName() + ".html");
+
+ return CommandLine(bc->environment().searchInPath("python"), {
+ emrunScript.absolutePath() + "/" + emrunScript.baseName() + ".py",
+ "--browser", browser,
+ "--port", port,
+ "--no_emrun_detect",
+ html.toString()
+ });
+ }
+ return {};
}
// Runs a webassembly application via emscripten's "emrun" tool
diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
index 49f896ce09f..c4c9f8f376d 100644
--- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
+++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp
@@ -41,24 +41,26 @@ static QStringList detectedBrowsers(ProjectExplorer::Target *target)
{
static QStringList result;
if (result.isEmpty()) {
- const Utils::Environment environment = target->activeBuildConfiguration()->environment();
- const Utils::FilePath emrunPath = environment.searchInPath("emrun");
+ if (auto bc = target->activeBuildConfiguration()) {
+ const Utils::Environment environment = bc->environment();
+ const Utils::FilePath emrunPath = environment.searchInPath("emrun");
- QProcess browserLister;
- browserLister.setProcessEnvironment(environment.toProcessEnvironment());
- browserLister.setProgram(emrunPath.toString());
- browserLister.setArguments({"--list_browsers"});
- browserLister.start(QIODevice::ReadOnly);
+ QProcess browserLister;
+ browserLister.setProcessEnvironment(environment.toProcessEnvironment());
+ browserLister.setProgram(emrunPath.toString());
+ browserLister.setArguments({"--list_browsers"});
+ browserLister.start(QIODevice::ReadOnly);
- if (browserLister.waitForFinished()) {
- const QByteArray output = browserLister.readAllStandardOutput();
- QTextStream ts(output);
- QString line;
- const QRegularExpression regExp(" - (.*):.*");
- while (ts.readLineInto(&line)) {
- const QRegularExpressionMatch match = regExp.match(line);
- if (match.hasMatch())
- result << match.captured(1);
+ if (browserLister.waitForFinished()) {
+ const QByteArray output = browserLister.readAllStandardOutput();
+ QTextStream ts(output);
+ QString line;
+ const QRegularExpression regExp(" - (.*):.*");
+ while (ts.readLineInto(&line)) {
+ const QRegularExpressionMatch match = regExp.match(line);
+ if (match.hasMatch())
+ result << match.captured(1);
+ }
}
}
}
@@ -68,7 +70,8 @@ static QStringList detectedBrowsers(ProjectExplorer::Target *target)
WebBrowserSelectionAspect::WebBrowserSelectionAspect(ProjectExplorer::Target *target)
: m_availableBrowsers(detectedBrowsers(target))
{
- m_currentBrowser = m_availableBrowsers.first();
+ if (!m_availableBrowsers.isEmpty())
+ m_currentBrowser = m_availableBrowsers.first();
setDisplayName(tr("Web browser"));
setId("WebBrowserAspect");
setSettingsKey("RunConfiguration.WebBrowser");
@@ -91,7 +94,8 @@ void WebBrowserSelectionAspect::addToLayout(ProjectExplorer::LayoutBuilder &buil
void WebBrowserSelectionAspect::fromMap(const QVariantMap &map)
{
- m_currentBrowser = map.value(BROWSER_KEY, m_availableBrowsers.first()).toString();
+ if (!m_availableBrowsers.isEmpty())
+ m_currentBrowser = map.value(BROWSER_KEY, m_availableBrowsers.first()).toString();
}
void WebBrowserSelectionAspect::toMap(QVariantMap &map) const
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index d60e7adf9c8..93dcec3d0e6 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -53,7 +53,6 @@
#include <QHeaderView>
#include <QLabel>
#include <QMouseEvent>
-#include <QOpenGLWidget>
#include <QPainter>
#include <QScrollArea>
#include <QStackedWidget>
@@ -352,12 +351,6 @@ WelcomeMode::WelcomeMode()
layout->addWidget(new StyledBar(m_modeWidget));
layout->addItem(hbox);
- if (Utils::HostOsInfo::isMacHost()) { // workaround QTBUG-61384
- auto openglWidget = new QOpenGLWidget;
- openglWidget->hide();
- layout->addWidget(openglWidget);
- }
-
setWidget(m_modeWidget);
}
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject aec975a3f95f905b2d63ea1500ace28eddea7b9
+Subproject a703c788abc0035bafe53a05370900db0a3ac43
diff --git a/src/shared/qtcreator_gui_pch.h b/src/shared/qtcreator_gui_pch.h
index 9ac491898b9..b25dbf67b70 100644
--- a/src/shared/qtcreator_gui_pch.h
+++ b/src/shared/qtcreator_gui_pch.h
@@ -32,7 +32,16 @@
#if defined __cplusplus
-#include <QtGui>
-#include <QtWidgets>
+#include <QEvent>
+#include <QTimer>
+#include <QApplication>
+#include <QBitmap>
+#include <QCursor>
+#include <QImage>
+#include <QLayout>
+#include <QPainter>
+#include <QPixmap>
+#include <QStyle>
+#include <QWidget>
#endif
diff --git a/src/shared/qtcreator_pch.h b/src/shared/qtcreator_pch.h
index a80eb42e7a6..4988f3d9392 100644
--- a/src/shared/qtcreator_pch.h
+++ b/src/shared/qtcreator_pch.h
@@ -29,38 +29,26 @@
*/
#if defined __cplusplus
-#include <QtCore/qsystemdetection.h>
+#include <QtGlobal>
-#ifdef Q_OS_WIN
-#define WIN32_LEAN_AND_MEAN
-
-// lib/Utils needs defines for Windows 8
-#ifdef Q_CC_MINGW
-#define WINVER _WIN32_WINNT_WIN8
-#define _WIN32_WINNT _WIN32_WINNT_WIN8
-#endif // Q_CC_MINGW
-#define NOHELP
-#include <qt_windows.h>
-
-#undef DELETE
-#undef IN
-#undef OUT
-#undef ERROR
-#undef ABSOLUTE
-
-//QT_NO_FLOAT16_OPERATORS is used on Visual Studio 2017 (and earlier):
-//when including <QFloat16> and <bitset> in the same translation unit,
-//it would cause a compilation error due to a toolchain bug (see [QTBUG-72073])
-#if _MSC_VER <= 1920
-#define QT_NO_FLOAT16_OPERATORS
+#ifdef Q_WS_WIN
+# define _POSIX_
+# include <limits.h>
+# undef _POSIX_
#endif
-#define _POSIX_
-#include <limits.h>
-#undef _POSIX_
-#endif // Q_OS_WIN
-
-#include <QtCore>
+#include <QCoreApplication>
+#include <QList>
+#include <QVariant>
+#include <QObject>
+#include <QRegExp>
+#include <QString>
+#include <QStringList>
+#include <QTextCodec>
+#include <QPointer>
+#include <QScopedPointer>
+#include <QSharedPointer>
+#include <QDebug>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QTextStream>
@@ -71,7 +59,7 @@ using Qt::dec;
using Qt::showbase;
using Qt::hex;
using Qt::noforcesign;
-#endif //QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#endif
#include <stdlib.h>
-#endif //defined __cplusplus
+#endif
diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt
index 105b0a63f0b..d2f43adc1b3 100644
--- a/src/tools/qml2puppet/CMakeLists.txt
+++ b/src/tools/qml2puppet/CMakeLists.txt
@@ -108,6 +108,7 @@ extend_qtc_executable(qml2puppet
SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d"
SOURCES
cameracontrolhelper.cpp cameracontrolhelper.h
+ mousearea3d.cpp mousearea3d.h
)
extend_qtc_executable(qml2puppet
diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs
index 995c29eac04..5bf57a534c7 100644
--- a/src/tools/qml2puppet/qml2puppet.qbs
+++ b/src/tools/qml2puppet/qml2puppet.qbs
@@ -197,6 +197,8 @@ QtcTool {
"instances/servernodeinstance.h",
"editor3d/cameracontrolhelper.cpp",
"editor3d/cameracontrolhelper.h",
+ "editor3d/mousearea3d.cpp",
+ "editor3d/mousearea3d.h",
"qml2puppetmain.cpp",
]
}
diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py
index ef46aca7b26..6501f738a2c 100644
--- a/tests/system/shared/utils.py
+++ b/tests/system/shared/utils.py
@@ -391,9 +391,9 @@ def getConfiguredKits():
test.log("Configured kits: %s" % str(result))
return result
-def visibleCheckBoxExists(text):
+def enabledCheckBoxExists(text):
try:
- findObject("{type='QCheckBox' text='%s' visible='1'}" % text)
+ waitForObject("{type='QCheckBox' text='%s'}" % text, 100)
return True
except:
return False
diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py
index 69a69ace30a..1d822c7ca59 100644
--- a/tests/system/suite_general/tst_create_proj_wizard/test.py
+++ b/tests/system/suite_general/tst_create_proj_wizard/test.py
@@ -93,7 +93,7 @@ def main():
def verifyKitCheckboxes(kits, displayedPlatforms):
waitForObject("{type='QLabel' unnamed='1' visible='1' text='Kit Selection'}")
- availableCheckboxes = frozenset(filter(visibleCheckBoxExists, kits.keys()))
+ availableCheckboxes = frozenset(filter(enabledCheckBoxExists, kits.keys()))
# verification whether expected, found and configured match
expectedShownKits = availableCheckboxes.intersection(displayedPlatforms)
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 2a43f7d1a13..e26809ca519 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -81,7 +81,7 @@ std::ostream &operator<<(std::ostream &out, const HeaderPath &headerPath);
namespace Utils {
class LineColumn;
class SmallStringView;
-class Link;
+struct Link;
std::ostream &operator<<(std::ostream &out, const LineColumn &lineColumn);
std::ostream &operator<<(std::ostream &out, const Utils::Language &language);