summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2021-11-04 13:52:30 +0100
committerEike Ziller <eike.ziller@qt.io>2021-11-04 13:52:30 +0100
commite6d31c2b3775bcc8609ca084d86eeb5d3e9c48f2 (patch)
treeaee8c7aa60996c891444eb2bcddd144fee8bfd93
parent8e8e8ddead1272ace0706da0a4c3c7c810102b39 (diff)
parentacfe22428199afea13554e7c1293e56ac76e325a (diff)
downloadqt-creator-e6d31c2b3775bcc8609ca084d86eeb5d3e9c48f2.tar.gz
Merge remote-tracking branch 'origin/6.0'
Change-Id: I560583b200db8f180574256d6d851a867be11c37
-rw-r--r--README.md22
-rw-r--r--dist/changes-5.0.3.md56
-rw-r--r--doc/qtcreator/images/qtcreator-add-resource-wizard.pngbin16369 -> 18218 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-avd-arguments.pngbin0 -> 4442 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-avd-manager.pngbin10873 -> 14237 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-build-apk-step.pngbin0 -> 13157 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-create-avd.pngbin25294 -> 7950 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-deploy-configurations.pngbin15752 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-deployment-settings.pngbin0 -> 6339 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-manifest-editor-package.pngbin12238 -> 11248 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-manifest-editor-splash-screen.pngbin8124 -> 10588 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-run-settings.pngbin43749 -> 48325 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-android-sdk-manager.pngbin8841 -> 8740 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-font-colors.pngbin16917 -> 16366 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-import-color-scheme.pngbin0 -> 3151 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-qt-gui-application-translationfile.pngbin0 -> 12059 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-qt-gui-application.pngbin17577 -> 18659 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-android-main.pngbin28682 -> 15736 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-settings-run.pngbin31475 -> 24017 bytes
-rw-r--r--doc/qtcreator/src/android/androiddev.qdoc130
-rw-r--r--doc/qtcreator/src/android/creator-projects-settings-run-android.qdocinc22
-rw-r--r--doc/qtcreator/src/android/deploying-android.qdoc129
-rw-r--r--doc/qtcreator/src/editors/creator-code-refactoring.qdoc4
-rw-r--r--doc/qtcreator/src/editors/creator-editors-options-text.qdoc23
-rw-r--r--doc/qtcreator/src/overview/creator-acknowledgements.qdoc35
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc10
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc3
-rw-r--r--doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc44
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml2
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml4
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioOutputSpecifics.qml37
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioSection.qml67
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml56
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSpecifics.qml37
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSection.qml105
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSpecifics.qml41
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml39
-rw-r--r--src/libs/languageserverprotocol/clientcapabilities.h24
-rw-r--r--src/libs/languageserverprotocol/jsonkeys.h1
-rw-r--r--src/libs/languageserverprotocol/semantictokens.cpp4
-rw-r--r--src/libs/languageserverprotocol/semantictokens.h9
-rw-r--r--src/libs/utils/aspects.cpp5
-rw-r--r--src/libs/utils/filesearch.cpp9
-rw-r--r--src/libs/utils/launchersocket.cpp7
-rw-r--r--src/libs/utils/multitextcursor.cpp8
-rw-r--r--src/plugins/android/androidconfigurations.cpp18
-rw-r--r--src/plugins/android/androidrunner.h3
-rw-r--r--src/plugins/android/androidsdkdownloader.cpp3
-rw-r--r--src/plugins/android/androidsdkmanagerwidget.cpp1
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp1
-rw-r--r--src/plugins/clangcodemodel/clangdclient.cpp132
-rw-r--r--src/plugins/clangcodemodel/clangdclient.h4
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp14
-rw-r--r--src/plugins/clangcodemodel/test/clangdtests.cpp7
-rw-r--r--src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp5
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp1
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.cpp2
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp1
-rw-r--r--src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp1
-rw-r--r--src/plugins/cppeditor/compileroptionsbuilder.cpp11
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettings.cpp37
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettings.h9
-rw-r--r--src/plugins/cppeditor/cppcodemodelsettingspage.cpp21
-rw-r--r--src/plugins/cppeditor/cppprojectupdater.cpp7
-rw-r--r--src/plugins/cppeditor/generatedcodemodelsupport.h1
-rw-r--r--src/plugins/debugger/debuggeritem.cpp1
-rw-r--r--src/plugins/debugger/watchhandler.cpp5
-rw-r--r--src/plugins/git/gitclient.cpp2
-rw-r--r--src/plugins/ios/iosconfigurations.cpp3
-rw-r--r--src/plugins/ios/iosprobe.cpp1
-rw-r--r--src/plugins/ios/iostoolhandler.h1
-rw-r--r--src/plugins/ios/simulatorcontrol.cpp1
-rw-r--r--src/plugins/languageclient/client.cpp21
-rw-r--r--src/plugins/languageclient/client.h2
-rw-r--r--src/plugins/languageclient/languageclientmanager.cpp1
-rw-r--r--src/plugins/languageclient/semantichighlightsupport.cpp22
-rw-r--r--src/plugins/languageclient/semantichighlightsupport.h11
-rw-r--r--src/plugins/mcusupport/mcusupportoptions.cpp1
-rw-r--r--src/plugins/nim/project/nimtoolchainfactory.cpp1
-rw-r--r--src/plugins/perforce/perforceeditor.cpp1
-rw-r--r--src/plugins/projectexplorer/abi.cpp16
-rw-r--r--src/plugins/projectexplorer/abi.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.cpp1
-rw-r--r--src/plugins/projectexplorer/extracompiler.cpp3
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp17
-rw-r--r--src/plugins/qbsprojectmanager/qbssession.h2
-rw-r--r--src/plugins/qmakeprojectmanager/externaleditors.cpp4
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt3
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore.pri2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp1235
-rw-r--r--src/plugins/qmldesigner/components/componentcore/svgpasteaction.h56
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp47
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.h2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h3
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp12
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetbuildprogressdialog.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp10
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp11
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.pro2
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs4
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-16px.pngbin0 -> 267 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-24px.pngbin0 -> 521 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-24px@2x.pngbin0 -> 1026 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-output-16px.pngbin0 -> 359 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px.pngbin0 -> 595 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px@2x.pngbin0 -> 1129 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/media-player-16px.pngbin0 -> 148 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/media-player-24px.pngbin0 -> 179 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/media-player-24px@2x.pngbin0 -> 260 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-16px.pngbin0 -> 216 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-24px.pngbin0 -> 286 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-24px@2x.pngbin0 -> 399 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-output-16px.pngbin0 -> 289 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-output-24px.pngbin0 -> 387 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/video-output-24px@2x.pngbin0 -> 610 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc18
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/quick.metainfo107
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/source/audio.qml35
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/source/component.qml34
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/source/component3d.qml33
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp2
-rw-r--r--src/plugins/qtsupport/qscxmlcgenerator.h2
-rw-r--r--src/plugins/qtsupport/uicgenerator.h2
-rw-r--r--src/plugins/texteditor/texteditor.cpp8
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp8
m---------src/shared/qbs0
-rw-r--r--src/src.qbs1
-rw-r--r--tests/auto/utils/qtcprocess/tst_qtcprocess.cpp34
-rw-r--r--tests/system/suite_debugger/tst_simple_debug/test.py5
-rw-r--r--tests/unit/unittest/clientserveroutsideprocess-test.cpp1
141 files changed, 2739 insertions, 295 deletions
diff --git a/README.md b/README.md
index 02f5e6c7f4..83c18a47da 100644
--- a/README.md
+++ b/README.md
@@ -312,7 +312,10 @@ we thank the authors who made this possible:
With backported/additional patches from https://code.qt.io/clang/llvm-project.git
-### Reference implementation for std::experimental::optional
+### Optional
+
+ A single-header header-only library for representing optional (nullable)
+ objects for C++14 (and C++11 to some extent) and passing them by value.
https://github.com/akrzemi1/Optional
@@ -327,7 +330,9 @@ we thank the authors who made this possible:
The idea and interface is based on Boost.Optional library
authored by Fernando Luis Cacciola Carballal
-### Implementation for std::variant
+### MPark.Variant
+
+ MPark.Variant is an implementation of C++17 std::variant for C++11/14/17.
https://github.com/mpark/variant
@@ -338,7 +343,11 @@ we thank the authors who made this possible:
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-### Implementation for std::span
+### std::span implementation for C++11 and later
+
+ A single-header implementation of C++20's std::span, conforming to the C++20
+ committee draft. It is compatible with C++11, but will use newer language
+ features if they are available.
https://github.com/tcbrindle/span
@@ -398,7 +407,10 @@ we thank the authors who made this possible:
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-### SQLite, in-process library that implements a SQL database engine
+### SQLite (version 3.8.10.2)
+
+SQLite is a C-language library that implements a small, fast, self-contained,
+high-reliability, full-featured, SQL database engine.
SQLite (https://www.sqlite.org) is in the Public Domain.
@@ -490,7 +502,7 @@ SQLite (https://www.sqlite.org) is in the Public Domain.
from Florian Loitsch which is licensed under the MIT License (see above).
Copyright © 2009 Florian Loitsch
-### Minitrace
+### minitrace
Simple C/C++ library for producing JSON traces.
diff --git a/dist/changes-5.0.3.md b/dist/changes-5.0.3.md
new file mode 100644
index 0000000000..2c8f9d5bd1
--- /dev/null
+++ b/dist/changes-5.0.3.md
@@ -0,0 +1,56 @@
+Qt Creator 5.0.3
+================
+
+Qt Creator version 5.0.3 contains bug fixes.
+
+The most important changes are listed in this document. For a complete list of
+changes, see the Git log for the Qt Creator sources that you can check out from
+the public Git repository. For example:
+
+ git clone git://code.qt.io/qt-creator/qt-creator.git
+ git log --cherry-pick --pretty=oneline origin/v5.0.2..v5.0.3
+
+Editing
+-------
+
+### QML
+
+* Fixed possible crash on shutdown
+
+### Image Viewer
+
+* Fixed crash when opening invalid movie (QTCREATORBUG-26377)
+
+Projects
+--------
+
+### qmake
+
+* Fixed handling of `QMAKE_EXTRA_COMPILERS` (QTCREATORBUG-26323)
+
+Platforms
+---------
+
+### macOS
+
+* Fixed crash when opening qmake projects on ARM Macs (QTBUG-97085)
+
+### Android
+
+* Fixed issue in installation step with qmake projects (QTCREATORBUG-26357)
+
+Credits for these changes go to:
+--------------------------------
+Assam Boudjelthia
+Christian Kandeler
+Eike Ziller
+Henning Gruendl
+Jaroslaw Kobus
+Johanna Vanhatapio
+Jörg Bornemann
+Kai Köhne
+Kaj Grönholm
+Leena Miettinen
+Robert Löhning
+Thomas Hartmann
+Tim Jenssen
diff --git a/doc/qtcreator/images/qtcreator-add-resource-wizard.png b/doc/qtcreator/images/qtcreator-add-resource-wizard.png
index 7f35d735c1..3b1b8b045e 100644
--- a/doc/qtcreator/images/qtcreator-add-resource-wizard.png
+++ b/doc/qtcreator/images/qtcreator-add-resource-wizard.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-avd-arguments.png b/doc/qtcreator/images/qtcreator-android-avd-arguments.png
new file mode 100644
index 0000000000..03a4298888
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-android-avd-arguments.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-avd-manager.png b/doc/qtcreator/images/qtcreator-android-avd-manager.png
index 7db5c73bbc..022395a800 100644
--- a/doc/qtcreator/images/qtcreator-android-avd-manager.png
+++ b/doc/qtcreator/images/qtcreator-android-avd-manager.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-build-apk-step.png b/doc/qtcreator/images/qtcreator-android-build-apk-step.png
new file mode 100644
index 0000000000..8e3b7c43e0
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-android-build-apk-step.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-create-avd.png b/doc/qtcreator/images/qtcreator-android-create-avd.png
index 3fc6627cb8..50121765e5 100644
--- a/doc/qtcreator/images/qtcreator-android-create-avd.png
+++ b/doc/qtcreator/images/qtcreator-android-create-avd.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-deploy-configurations.png b/doc/qtcreator/images/qtcreator-android-deploy-configurations.png
deleted file mode 100644
index a2b8faaf34..0000000000
--- a/doc/qtcreator/images/qtcreator-android-deploy-configurations.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-deployment-settings.png b/doc/qtcreator/images/qtcreator-android-deployment-settings.png
new file mode 100644
index 0000000000..b301a6c946
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-android-deployment-settings.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-manifest-editor-package.png b/doc/qtcreator/images/qtcreator-android-manifest-editor-package.png
index f3c07868f0..843ca804bf 100644
--- a/doc/qtcreator/images/qtcreator-android-manifest-editor-package.png
+++ b/doc/qtcreator/images/qtcreator-android-manifest-editor-package.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-manifest-editor-splash-screen.png b/doc/qtcreator/images/qtcreator-android-manifest-editor-splash-screen.png
index c1e99cd24e..d90e58b33f 100644
--- a/doc/qtcreator/images/qtcreator-android-manifest-editor-splash-screen.png
+++ b/doc/qtcreator/images/qtcreator-android-manifest-editor-splash-screen.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-run-settings.png b/doc/qtcreator/images/qtcreator-android-run-settings.png
index 5638b0ad7c..0b9143eb9f 100644
--- a/doc/qtcreator/images/qtcreator-android-run-settings.png
+++ b/doc/qtcreator/images/qtcreator-android-run-settings.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-android-sdk-manager.png b/doc/qtcreator/images/qtcreator-android-sdk-manager.png
index 4894e9bd99..8ff625d223 100644
--- a/doc/qtcreator/images/qtcreator-android-sdk-manager.png
+++ b/doc/qtcreator/images/qtcreator-android-sdk-manager.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-font-colors.png b/doc/qtcreator/images/qtcreator-font-colors.png
index 8dfb7451e5..1cfe802c33 100644
--- a/doc/qtcreator/images/qtcreator-font-colors.png
+++ b/doc/qtcreator/images/qtcreator-font-colors.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-import-color-scheme.png b/doc/qtcreator/images/qtcreator-import-color-scheme.png
new file mode 100644
index 0000000000..4c46359260
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-import-color-scheme.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-qt-gui-application-translationfile.png b/doc/qtcreator/images/qtcreator-new-qt-gui-application-translationfile.png
new file mode 100644
index 0000000000..27282a68e8
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-new-qt-gui-application-translationfile.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-qt-gui-application.png b/doc/qtcreator/images/qtcreator-new-qt-gui-application.png
index 6ee1705462..19d8e0c1eb 100644
--- a/doc/qtcreator/images/qtcreator-new-qt-gui-application.png
+++ b/doc/qtcreator/images/qtcreator-new-qt-gui-application.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-android-main.png b/doc/qtcreator/images/qtcreator-options-android-main.png
index 4a2c09dd8b..15afbe73b6 100644
--- a/doc/qtcreator/images/qtcreator-options-android-main.png
+++ b/doc/qtcreator/images/qtcreator-options-android-main.png
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-settings-run.png b/doc/qtcreator/images/qtcreator-settings-run.png
index 5d0680fbdf..3df81e9daf 100644
--- a/doc/qtcreator/images/qtcreator-settings-run.png
+++ b/doc/qtcreator/images/qtcreator-settings-run.png
Binary files differ
diff --git a/doc/qtcreator/src/android/androiddev.qdoc b/doc/qtcreator/src/android/androiddev.qdoc
index ed53310649..d66a1468b5 100644
--- a/doc/qtcreator/src/android/androiddev.qdoc
+++ b/doc/qtcreator/src/android/androiddev.qdoc
@@ -36,7 +36,9 @@
You can connect Android devices to the development PC using USB cables
to build, run, debug, and analyze applications from \QC. Devices with
- Android version 4.1 (API level 16) or later are supported.
+ Android version 4.1 (API level 16) or later are supported when developing
+ with Qt 5 and devices with Android version 6.0 (API level 23) when
+ developing with Qt 6.
To develop for Android, you must have a tool chain for building applications
for Android devices installed on the development PC. \QC can automatically
@@ -47,10 +49,6 @@
Starting from Qt 5.14.0, the Qt for Android package contains all the
architectures (ABIs) installed as one.
- \note You can build a 64-bit version of Qt for Android yourself. However,
- for such a Qt version, the minimum required Android version on devices
- is 5.0 (API level 21). For more information, see \l{Qt for Android}.
-
To enable helpful code editing features for Java, such as code completion,
highlighting, function tooltips, and navigating in code, specify settings
for a \l{Specifying Java Language Server Settings}{Java language server}.
@@ -83,7 +81,9 @@
\list 1
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
- \uicontrol Android.
+ \uicontrol Android on Windows and Linux or \uicontrol {\QC} >
+ \uicontrol Preferences > \uicontrol Devices > \uicontrol Android on
+ \macos.
\image qtcreator-options-android-main.png "Android options"
\li In the \uicontrol {JDK location} field, set the path to the JDK.
\QC checks the JDK installation and reports errors.
@@ -108,7 +108,8 @@
offers to add or remove those packages. Before taking action, it
prompts you to accept the changes it is about to make. In addition,
it prompts you to accept Google licenses, as necessary.
- \li The installed NDK versions are listed below the SDK path.
+ \li The installed NDK versions are listed in
+ \uicontrol {Android NDK list}.
The locked items were installed by the SDK Manager,
and can only be modified from the \uicontrol {SDK Manager} tab.
For more information, see \l{Managing Android NDK Packages}.
@@ -118,10 +119,9 @@
For Qt applications that require OpenSSL support, \QC allows to
quickly add the \l {Android OpenSSL support} to your project.
For more information, see \l{Adding External Libraries}.
- \li Select \inlineimage online.png
- to download the OpenSSL repository to the selected path. If the
- automatic download fails, the download web page opens for manual
- download.
+ \li Select \uicontrol {Download OpenSSL} to download the OpenSSL
+ repository to the selected path. If the automatic download fails,
+ the download web page opens for manual download.
\li Select the \uicontrol {Automatically create kits for Android tool chains}
check box to allow \QC to create the kits for you. \QC displays a
warning if it cannot find a suitable Qt version.
@@ -172,7 +172,9 @@
\section2 Managing Android NDK Packages
To view the installed \l{Android NDK} versions, select \uicontrol Tools >
- \uicontrol Options > \uicontrol Devices > \uicontrol Android.
+ \uicontrol Options > \uicontrol Devices > \uicontrol Android on Windows and
+ Linux or \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Devices >
+ \uicontrol Android on \macos.
\image qtcreator-options-android-sdk-tools.png "Android NDK and SDK checks"
@@ -198,7 +200,9 @@
To view the installed Android SDK packages, select \uicontrol Tools >
\uicontrol Options > \uicontrol Devices > \uicontrol Android >
- \uicontrol {SDK Manager}.
+ \uicontrol {SDK Manager} on Windows and Linux or \uicontrol {\QC} >
+ \uicontrol Preferences > \uicontrol Devices > \uicontrol Android >
+ \uicontrol {SDK Manager} on \macos.
\image qtcreator-android-sdk-manager.png "Android SDK Manager"
@@ -216,84 +220,58 @@
\section1 Managing Android Virtual Devices (AVD)
- A list of AVDs is shown under \uicontrol Tools > \uicontrol Options >
- \uicontrol Devices > \uicontrol Android > \uicontrol {AVD Manager}. This
- works only if the \uicontrol {Android SDK location} is set correctly in
- \uicontrol {Android Settings}.
-
- The value in \uicontrol {System/data partition size} is used to set the
- emulator's system partition size upon execution with \uicontrol {Start}.
-
- \image qtcreator-android-avd-manager.png "Android NDK and SDK checks"
-
- \section2 Creating a New AVD
-
- To create new virtual devices:
-
- \list 1
- \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
- \uicontrol Android.
- \li In the \uicontrol {SDK Manager} tab, select \uicontrol Install for
- an Android version, and then select \uicontrol Apply to install a
- system image. Alternatively, you can install the system image from
- Android Studio.
- \li In the \uicontrol {AVD Manager} tab, select \uicontrol {Add} to
- open the \uicontrol {Create New AVD} dialog.
- \image qtcreator-android-create-avd.png "Android NDK and SDK checks"
- \li Set the name, type, skin, architecture, API level, and SD card size
- of the device.
- \li Select \uicontrol OK to create the AVD.
- \endlist
-
- For more advanced options for creating a new AVD, use the command-line tool
- \l{avdmanager}, or use Android Studio's native AVD Manager's UI.
-
- \section1 Selecting Android Devices
+ The available AVDs are listed in \uicontrol Tools > \uicontrol Options
+ > \uicontrol Devices on Windows and Linux or \uicontrol {\QC} >
+ \uicontrol Preferences > \uicontrol Devices > on \macos. You can add more
+ AVDs.
- When you deploy an application to an Android device with Android
- version 4.2 (API 16) or later, the \uicontrol {Select Android Device} dialog
- opens. It lists the devices that are connected to the development PC, as
- well as AVDs, and their status. You can select devices or AVDs from the
- \uicontrol {Compatible Devices} list for deployment.
+ \image qtcreator-android-avd-manager.png "Android device in Devices"
- If \QC determines that a device is not ready for deployment, it places the
- device in the \uicontrol {Incompatible Devices} list, with information about the
- issue. For example, you might need to authorize the connection on the
- device. After you authorize the connection on the device, select
- \uicontrol {Refresh Device List}. The device is moved to the
- \uicontrol {Compatible Devices} list and you can select it for deployment.
+ You can see the status of the selected device in \uicontrol {Current state}.
+ To update the status information, select \uicontrol Refresh.
- Other reasons for showing a device in \uicontrol {Incompatible Devices} are
- that the Android version on the device is too old or that the tool chain
- used for building does not match the Android architecture on the device
- (for example, you cannot deploy an ARM build on an x86 device).
+ To start an AVD, select \uicontrol {Start AVD}. Usually, you don't need to
+ start AVDs separately because they are automatically started when you
+ select them in the \l{Building for Multiple Platforms}{kit selector} to
+ \l{Deploying Applications to Android Devices}{deploy applications} to them.
- \image qtcreator-android-select-devices.png "Select Android Devices dialog"
+ To remove an AVD from the list and the kit selector, select
+ \uicontrol {Erase AVD}.
- To \l{Creating a New AVD}{create a new AVD}, select \uicontrol {Create Android Virtual Device}.
+ To specify options for starting an AVD, select \uicontrol {AVD Arguments}.
- To set a device as the default device for a particular Android architecture
- for the current project, select the \uicontrol {Always use this device for architecture}
- check box. The \uicontrol {Select Android Devices} dialog will not appear
- until you switch to another project or restart \QC.
+ \image qtcreator-android-avd-arguments.png "Startup options for AVDs"
- \section1 Using the Android Emulator
-
- To run your application on the Android Emulator, you must have an Android
- virtual device (AVD). For more information about creating a new one, see
- \l{Creating a New AVD}. If you run an application without a device connected to the
- development PC and without an AVD specified, \QC asks you to add an AVD.
+ Specify the options in \uicontrol {Emulator command-line startup options}.
+ For available options, see \l{Start the emulator from the command line}.
\note The Android Emulator has a bug that prevents it from starting on some
- systems. If the Android Emulator does not start, you can try starting it
- manually by running the following commands:
+ systems. If an AVD does not start, you can try starting it manually by
+ running the following commands:
\badcode
cd <ANDROID_SDK>/emulator
./emulator -avd <AVD_NAME>
\endcode
- For more information, see \l{Start the emulator from the command line}.
+ \section2 Creating a New AVD
+
+ To create new virtual devices:
+
+ \list 1
+ \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
+ \uicontrol Add > \uicontrol {Android Device} on Windows and Linux
+ or \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Devices >
+ \uicontrol Add > \uicontrol {Android Device} on \macos to open the
+ \uicontrol {Create New AVD} dialog.
+ \image qtcreator-android-create-avd.png "Create New AVD dialog"
+ \li Set the name, definition, architecture, target API level, and
+ SD card size of the device.
+ \li Select \uicontrol OK to create the AVD.
+ \endlist
+
+ For more advanced options for creating a new AVD, use the command-line tool
+ \l{avdmanager} or the Android Studio's native AVD Manager UI.
\section1 Debugging on Android Devices
diff --git a/doc/qtcreator/src/android/creator-projects-settings-run-android.qdocinc b/doc/qtcreator/src/android/creator-projects-settings-run-android.qdocinc
index b5f781c87e..3c37010390 100644
--- a/doc/qtcreator/src/android/creator-projects-settings-run-android.qdocinc
+++ b/doc/qtcreator/src/android/creator-projects-settings-run-android.qdocinc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -34,19 +34,19 @@
A default set of Android Activity manager (am) start options is applied when
starting applications. You can specify additional start options in the
- \uicontrol {Activity manager start options} field. However, if the default
+ \uicontrol {Activity manager start arguments} field. However, if the default
options conflict with the added options, the application might not start.
The default arguments for the Activity manager for a normal run:
\badcode
- am start -n org.qtproject.example.notification/org.qtproject.qt5.android.bindings.QtActivity
+ am start -n <package_name>/<QtActivity_name>
\endcode
The default arguments for the Activity manager for the debugger mode:
\badcode
- am start -n org.qtproject.example.notification/org.qtproject.qt5.android.bindings.QtActivity -D
+ am start -n <package_name>/<QtActivity_name> -D
\endcode
For example, to run the application as a particular user, enter the start
@@ -54,18 +54,20 @@
\image qtcreator-android-run-settings.png
- You can specify shell commands to run before the application is started and
- after it is quit. For example, enter the following commands to unlock the
- screen and to switch to the user account \c 10 on the device before running
- the application:
+ You can specify shell commands to run before the application is started
+ and after it is quit. For example, enter the following commands into
+ \uicontrol{Pre-launch on-device shell commands} to unlock the screen and
+ to switch to the user account \c 10 on the device before running the
+ application:
\code
input keyevent 82
am switch-user 10
\endcode
- Enter the following commands to switch back to the default user, \c 0, and
- to unlock the screen after the application is quit:
+ Enter the following commands into
+ \uicontrol{Post-quit on-device shell commands} to switch back to the
+ default user, \c 0, and to unlock the screen after the application is quit:
\code
am switch-user 0
diff --git a/doc/qtcreator/src/android/deploying-android.qdoc b/doc/qtcreator/src/android/deploying-android.qdoc
index 734d868193..7a97cf2b39 100644
--- a/doc/qtcreator/src/android/deploying-android.qdoc
+++ b/doc/qtcreator/src/android/deploying-android.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -52,7 +52,8 @@
\note Since \QC 4.12, Ministro is not supported.
- To specify settings for application packages, select \uicontrol Projects >
+ To \l{Specifying Settings for Packages}{specify settings} for application
+ packages, select \uicontrol Projects > \uicontrol Build >
\uicontrol {Build Android APK} > \uicontrol Details.
\if defined(qtcreator)
@@ -64,7 +65,7 @@
Because bundling applications as APK packages is not
trivial, Qt 5 provides a deployment tool called \c androiddeployqt.
- When you deploy an application using a \uicontrol {Qt for Android Kit}, \QC uses
+ When you deploy an application using a \e {Qt for Android kit}, \QC uses
the \c androiddeployqt tool to create the necessary files and to bundle them
into an APK:
@@ -100,41 +101,58 @@
To view the packages that the \c androiddeployqt tool created, select the
\uicontrol {Open package location after build} check box.
- The packages are deployed on the connected Android devices. To switch the
- device used as a default device for the selected kit, select
- \uicontrol Projects > \uicontrol Run > \uicontrol {Deploy to Android Device}
- > \uicontrol {Reset Default Devices}. The setting applies until you restart \QC.
- For more information, see \l{Selecting Android Devices}.
+ \section2 Specifying Deployment Settings
- For more information about the \c androiddeployqt tool, see
- \l{Deploying an Application on Android}.
+ The available deployment settings are listed in the \uicontrol Method field.
+ To add deployment methods for a project, select \uicontrol Add.
+
+ \image qtcreator-android-deployment-settings.png "Deployment settings"
+
+ To rename the current deployment method, select \uicontrol Rename.
+
+ To remove the current deployment method, select \uicontrol Remove.
+
+ The packages are deployed on the Android device that you select in the
+ \l{Building for Multiple Platforms}{kit selector}. To add devices, select
+ \uicontrol Manage.
+
+ For more information about specifying additional start options for
+ applications, see \l{Specifying Run Settings for Android Devices}.
+
+ To remove previously installed files from the device, select
+ \uicontrol {Uninstall the existing app before deployment}.
+
+ To install a pre-built APK, such as a 3rd-party application to a device,
+ select \uicontrol {Install an APK File}.
\section2 Specifying Settings for Packages
- You can specify settings for the \c androiddeployqt tool in \QC and in the
- project .pro file. To specify settings in \QC, select \uicontrol Projects >
- \uicontrol Build > \uicontrol {Build Android APK} > \uicontrol Details.
+ To specify settings for the \c androiddeployqt tool, select
+ \uicontrol Projects > \uicontrol Build > \uicontrol {Build Android APK} >
+ \uicontrol Details.
- \image qtcreator-android-deploy-configurations.png "Deploy configurations"
+ \image qtcreator-android-build-apk-step.png "Build Android APK step"
- The anddroiddeployqt tool uses the information in the project .pro file to
- create APKs. For more information about the qmake variables
- that you can set in the .pro file to tailor the APK, see
- \l{Deploying an Application on Android}.
+ The \c androiddeployqt tool uses the configuration information to
+ create APKs. For more information about the available options, see
+ \l{androiddeployqt}.
- You can view information about what the anddroiddeployqt tool is doing in
+ You can view information about what the \c androiddeployqt tool is doing in
the \uicontrol {Compile Output} pane. To view additional information, select the
\uicontrol {Verbose output} check box.
+ Select \uicontrol {Add debug server} to include the debug server binary
+ into a package.
+
\section3 Selecting API Level
- In the \uicontrol {Android build SDK} field, you can select the API level to use
- for building the application. Usually, you should select the newest API
- level available.
+ In the \uicontrol {Android build platform SDK} field, you can select the
+ API level to use for building the application. Usually, you should select
+ the highest API level available.
- \note For Qt 5.12.0 to 5.12.5 and Qt 5.13.0 to 5.13.1, Android build SDK 28 should
- be used. For recent versions than the latter, build SDK 29, or the most recent
- should be used.
+ \note For Qt 5.12.0 to 5.12.5 and Qt 5.13.0 to 5.13.1, Android build
+ platform SDK 28 should be used. For more recent versions than Qt 5.13.1,
+ build platform SDK 29 or the most recent one should be used.
This field does not specify the minimum supported API level nor the target
API level, which you can specify in the Android manifest. See
@@ -146,7 +164,7 @@
For testing the application locally, use the APK format, because
the package can be uploaded directly to the device and run. For
distribution to the Google Play store, create an AAB by selecting
- the \uicontrol {Build .aab (Android App Bundle)} check box.
+ the \uicontrol {Build Android App Bundle (*.aab)} check box.
When building with CMake, you can view the selected ABIs in the
\uicontrol {Initial CMake parameters} field in the \uicontrol CMake section.
@@ -253,11 +271,11 @@
\section1 Editing Manifest Files
- You can use the qmake variables to specify all
- the settings you need for the \c androiddeployqt tool and you do not need an
- Android manifest file unless you need to specify Android specific settings
- like the application's icon. Also, the manifest file is needed if you want
- to publish the package in the Play Store.
+ You can use the configuration options to specify all the settings you need
+ for the \c androiddeployqt tool. You only need an Adroid manifest file
+ to specify Android-specific settings, such as the application icon.
+ However, the manifest file is needed when you want to publish the package
+ in the Play Store.
\section2 Package Names
@@ -384,7 +402,7 @@
\li Locks the orientation to its current rotation, whatever that is.
\endtable
- \section2 Supported Resolutions
+ \section2 Icons and Splash Screens
You can set different images to be shown as application icons and splash
screens on low, medium, high, and extra high DPI displays. The following
@@ -399,6 +417,36 @@
\li Extra-extra-extra-high-density (XXXHDPI): ~640dpi
\endlist
+ Specify settings for icons in the \uicontrol {Application icon} tab. Select
+ the image with the highest resolution as the \uicontrol {Master icon}.
+ \QC resizes the icon and sets versions of it to be shown on low, medium,
+ high, and extra high DPI displays, as needed. Alternatively, set the icons
+ for each resolution separately.
+
+ \image qtcreator-android-manifest-editor-app-icon.png "Application icons in Android Manifest Editor"
+
+ Specify settings for splash screens in the \uicontrol {Splash screen} tab.
+ Select images to display as splash screens depending on the device
+ orientation and screen resolution.
+
+ \image qtcreator-android-manifest-editor-splash-screen.png "Splash screens in Android Manifest Editor"
+
+ By default, the splash screen is hidden automatically
+ when an activity is drawn. To keep it visible until
+ \l{QNativeInterface::QAndroidApplication::hideSplashScreen()} is
+ called, select the \uicontrol {Sticky splash screen} check box.
+
+ In \uicontrol {Image show mode}, select whether to center the splash screen
+ on the device display or scale it to fill the display.
+
+ Set a background color in \uicontrol {Background color}.
+
+ Select the images with the highest resolution as the
+ \uicontrol {Master image}, \uicontrol {Portrait master image},
+ and \uicontrol {Landscape master image}.
+
+ Select \uicontrol {Clear All} to reset all settings or remove all images.
+
\section2 Android Manifest Editor
If you use qmake as the build system, you can create an Android manifest
@@ -447,22 +495,11 @@
\li In the \uicontrol {Screen orientation} field, select the option for
determining \l{Screen Orientation}{screen orientation}.
- \li In \uicontrol {Application icon}, select an image with the highest
- \l{Supported Resolutions}{resolution} as the \uicontrol {Master icon}.
- \QC resizes the icon and sets versions of it to be shown on low,
- medium, high, and extra high DPI displays, as needed. Alternatively,
- set the icons for each resolution separately.
-
- \image qtcreator-android-manifest-editor-app-icon.png "Application icons in Android Manifest Editor"
+ \li In \uicontrol {Application icon}, specify images to use as application
+ icons depending on screen resolution.
\li In \uicontrol {Splash screen}, select images to display as splash
- screens depending on the device orientation. You can set different images
- to be shown on low, medium, high, and extra high DPI displays. By default,
- the splash screen is hidden automatically when an activity is drawn. To keep
- it visible until \l{QtAndroid::hideSplashScreen()} is called, select the
- \uicontrol {Sticky splash screen} check box.
-
- \image qtcreator-android-manifest-editor-splash-screen.png "Splash screens in Android Manifest Editor"
+ screens depending on the screen orientation and resolution.
\li In \uicontrol {Android services}, select \uicontrol Add to add a service.
You must enter at least a service class name for a new service. If you select
diff --git a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
index ab57bb4d8f..d0e569543e 100644
--- a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc
@@ -43,6 +43,10 @@
code by selecting them in a context menu. For more information, see
\l{Applying Refactoring Actions}.
+ By default, the refactored files are saved automatically. To disable
+ this feature, deselect \uicontrol Tools > \uicontrol Options >
+ \uicontrol System > \uicontrol {Auto-save files after refactoring}.
+
\if defined(qtcreator)
\section1 Finding Symbols
diff --git a/doc/qtcreator/src/editors/creator-editors-options-text.qdoc b/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
index 307728cfc3..d644875448 100644
--- a/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
+++ b/doc/qtcreator/src/editors/creator-editors-options-text.qdoc
@@ -85,12 +85,35 @@
The backgound of the \uicontrol Text element determines the background of the
code editor.
+ \li In \uicontrol Font, select \uicontrol Bold or \uicontrol Italic to
+ format the text of the selected code element by making it bold or
+ italic.
+
+ \li In \uicontrol Underline, select the color and style to use for
+ underlining code elements.
+
\endlist
When you copy code from \QC, it is copied in both plain text and HTML
format. The latter makes sure that syntax highlighting is preserved when
pasting to a rich-text editor.
+ \section2 Exporting and Importing Color Schemes
+
+ To share color schemes with others, export and import them as XML files.
+ To export a color scheme, select \uicontrol Tools > \uicontrol Options >
+ \uicontrol {Text Editor} > \uicontrol {Fonts & Color} > \uicontrol Export,
+ and then select the filename and location for the XML file.
+
+ To import a color scheme, select \uicontrol Import, and then select the XML
+ file to import. In the \uicontrol {Import Color Scheme} dialog, enter a name
+ for the color scheme in \uicontrol {Color scheme name}:
+
+ \image qtcreator-import-color-scheme.png "Import Color Scheme dialog"
+
+ When you select \uicontrol OK, the color scheme is added to the list of
+ color schemes in the \uicontrol {Fonts & Color} tab.
+
\section2 File Encoding
To define the default file encoding, select \uicontrol Tools >
diff --git a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
index 4ec9eb9ea2..2e6b71d0f7 100644
--- a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
+++ b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
@@ -385,7 +385,11 @@
\li \l{http://code.qt.io/cgit/clang/clang.git}
\endlist
- \li \b{Reference implementation for std::experimental::optional}
+ \li \b{Optional}
+
+ A single-header header-only library for representing optional
+ (nullable) objects for C++14 (and C++11 to some extent) and passing
+ them by value.
Copyright (C) 2011-2012 Andrzej Krzemienski
@@ -404,7 +408,9 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/optional}
\endlist
- \li \b{Implementation for std::variant}
+ \li \b{MPark.Variant}
+
+ MPark.Variant is an implementation of C++17 std::variant for C++11/14/17.
Copyright Michael Park, 2015-2017
@@ -419,7 +425,11 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/variant}
\endlist
- \li \b{Implementation for std::span}
+ \li \b{std::span implementation for C++11 and later}
+
+ A single-header implementation of C++20's std::span, conforming to
+ the C++20 committee draft. It is compatible with C++11, but will use
+ newer language features if they are available.
Copyright Tristan Brindle, 2018
@@ -613,7 +623,10 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endcode
- \li \b{SQLite, an embedded database. Version 3.8.10.2}\br\br
+ \li \b{SQLite (version 3.8.10.2)}
+
+ SQLite is a C-language library that implements a small, fast,
+ self-contained, high-reliability, full-featured, SQL database engine.
The author or authors of this code dedicate any and all copyright
interest in this code to the public domain. We make this dedication
@@ -628,11 +641,15 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/sqlite}
\endlist
- \li \b{three.js (license MIT)}\br
- Copyright (C) 2010-2015 three.js authors\br
+ \li \b{three.js}
+
+ Copyright (C) 2010-2015 three.js authors
+
+ MIT License.
+
share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication
- \li \b{OpenSSL toolkit}
+ \li \b{OpenSSL}
The OpenSSL toolkit stays under a double license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
@@ -753,7 +770,7 @@
[including the GNU Public Licence.]
\endcode
- \li \b{Mesa LLVMPipe, 3D graphics library}
+ \li \b{LLVMPipe - The Mesa 3D Graphics Library}
Mesa is a 3D graphics library with an API which is very similar to that
of OpenGL. The llvmpipe software renderer enables the running of OpenGL
@@ -826,7 +843,7 @@
from Florian Loitsch which is licensed under the MIT License (see above).
Copyright (C) 2009 Florian Loitsch
- \li \b Minitrace
+ \li \b minitrace
Simple C/C++ library for producing JSON traces.
diff --git a/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc b/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
index bf08dceaff..70ff6464d6 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-mobile-targets.qdoc
@@ -56,11 +56,11 @@
Qt applications for Android are compiled as \c {shared objects} that
are loaded by a Java launcher that is part of Qt.
This is totally transparent to users. As Qt is composed of libraries
- referencing each other, Qt 4 applications are only supported on
- Android version 1.6, or later, and Qt 5 applications on version
- 4.1 (API level 16), or later. You must install a Qt version
- targeting Android and the Android SDK and NDK to develop for
- Android devices.
+ referencing each other, Qt 5 applications are only supported on
+ Android version 4.1 (API level 16), or later, and Qt 6 applications
+ on Android version 6.0 (API level 23), or later. You must install a
+ Qt version targeting Android and the Android SDK and NDK to develop
+ for Android devices.
\if defined(qtcreator)
\li \l{Connecting Bare Metal Devices}
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
index b5a3b750e4..a16d5bc93d 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc
@@ -55,7 +55,8 @@
\li Click the \uicontrol {Build and Run Kit Selector} icon (1) or select
\uicontrol Build > \uicontrol {Open Build and Run Kit Selector} to select the
- build and run \l{glossary-buildandrun-kit}{kit}.
+ build and run \l{glossary-buildandrun-kit}{kit} or an
+ \l{Managing Android Virtual Devices (AVD)}{Android device}.
\image qtcreator-kit-selector.png "Kit selector"
diff --git a/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc b/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
index a28111f574..2dab21729e 100644
--- a/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
+++ b/doc/qtcreator/src/widgets/qtdesigner-app-tutorial.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -48,8 +48,8 @@
\list 1
\li Select \uicontrol File > \uicontrol {New File or Project} >
- \uicontrol Application (Qt) > \uicontrol {Qt Widgets Application} >
- \uicontrol Choose.
+ \uicontrol {Application (Qt)} > \uicontrol {Qt Widgets Application}
+ > \uicontrol Choose.
\image qtcreator-new-qt-gui-application.png "New File or Project dialog"
@@ -60,10 +60,11 @@
\li In the \uicontrol{Name} field, type \b {TextFinder}.
\li In the \uicontrol {Create in} field, enter the path for the project files.
- For example, \c {C:\Qt\examples}, and then select \uicontrol{Next} (on
- Windows and Linux) or \uicontrol Continue (on \macos).
+ For example, \c {C:\Qt\examples}.
- The \uicontrol {Define Build System} dialog opens.
+ \li Select \uicontrol{Next} (on Windows and Linux) or
+ \uicontrol Continue (on \macos) to open the
+ \uicontrol {Define Build System} dialog.
\image qtcreator-new-project-build-system-qt-gui.png "Define Build System dialog"
@@ -71,7 +72,8 @@
use for building and running the project: \l qmake,
\l {Setting Up CMake}{CMake}, or \l {Setting Up Qbs}{Qbs}.
- The \uicontrol{Class Information} dialog opens.
+ \li Select \uicontrol Next or \uicontrol Continue to open the
+ \uicontrol{Class Information} dialog.
\image qtcreator-class-info-qt-gui.png "Class Information dialog"
@@ -84,16 +86,26 @@
\note The \uicontrol{Header file}, \uicontrol{Source file} and \uicontrol{Form file}
fields are automatically updated to match the name of the class.
- The \uicontrol {Kit Selection} dialog opens.
+ \li Select \uicontrol Next or \uicontrol Continue to open the
+ \uicontrol {Translation File} dialog.
- \image qtcreator-new-project-qt-versions-qt-gui.png "Kit Selection dialog"
+ \image qtcreator-new-qt-gui-application-translationfile.png "Translation File dialog"
- \li Select build and run \l{glossary-buildandrun-kit}{kits} for your project,
- and select \uicontrol Next or \uicontrol Continue.
+ \li In the \uicontrol Language field, you can select a language that you
+ plan to \l {Using Qt Linguist}{translate} the application to. This
+ sets up localization support for the application. You can add other
+ languages later by editing the project file.
- \li Select \uicontrol Next or \uicontrol Continue.
+ \li Select \uicontrol Next or \uicontrol Continue to open the
+ \uicontrol {Kit Selection} dialog.
- The \uicontrol{Project Management} dialog opens.
+ \image qtcreator-new-project-qt-versions-qt-gui.png "Kit Selection dialog"
+
+ \li Select build and run \l{glossary-buildandrun-kit}{kits} for your
+ project.
+
+ \li Select \uicontrol Next or \uicontrol Continue to open the
+ \uicontrol {Project Management} dialog.
\image qtcreator-new-project-summary-qt-gui.png "Project Management dialog"
@@ -105,7 +117,8 @@
\note The project opens in the \uicontrol Edit mode, and these instructions are
hidden. To return to these instructions, open the \uicontrol Help mode.
- The TextFinder project now contains the following files:
+ If you selected qmake as the build system, the TextFinder project now
+ contains the following files:
\list
@@ -122,6 +135,9 @@
The .h and .cpp files come with the necessary boiler plate code.
The .pro file is complete.
+ If you selected CMake as the build system, \QC created a CMakeLists.txt
+ project file for you.
+
\section1 Filling in the Missing Pieces
Begin by designing the user interface and then move on to filling
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml
index 498c474411..5ca714051b 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml
@@ -51,7 +51,7 @@ Item {
if (url.startsWith("file:///")) // remove file scheme (happens on Windows)
url = url.substr(8)
var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase()
- if (rootView.supportedSuffixes().includes('*.' + ext))
+ if (rootView.supportedDropSuffixes().includes('*.' + ext))
files.push(url)
}
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
index 815d4427ad..cbd9e5ed50 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
@@ -82,7 +82,7 @@ Item {
property var currentImport: null
property bool isHorizontalView: false
- // called from C++ to close context menu on focus out
+ // Called also from C++ to close context menu on focus out
function closeContextMenu()
{
moduleContextMenu.close()
@@ -93,6 +93,8 @@ Item {
itemsView.isHorizontalView = itemsView.width > widthLimit
}
+ onIsHorizontalViewChanged: closeContextMenu()
+
Item {
id: styleConstants
property int textWidth: 58
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioOutputSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioOutputSpecifics.qml
new file mode 100644
index 0000000000..ab5860ec02
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioOutputSpecifics.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ AudioSection {}
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioSection.qml
new file mode 100644
index 0000000000..db226e755a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/AudioSection.qml
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ caption: qsTr("Audio")
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Volume") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.volume
+ decimals: 1
+ minimumValue: 0.0
+ maximumValue: 1.0
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Muted") }
+
+ SecondColumnLayout {
+ CheckBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.muted
+ text: backendValues.muted.valueToString
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml
new file mode 100644
index 0000000000..b76a1bd0fb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ caption: qsTr("Media Player")
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ // TODO position property, what should be the range?!
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Playback rate") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.playbackRate
+ decimals: 1
+ minimumValue: -1000 // TODO correct range
+ maximumValue: 1000
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSpecifics.qml
new file mode 100644
index 0000000000..1a6c41ecf8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSpecifics.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ MediaPlayerSection {}
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSection.qml
new file mode 100644
index 0000000000..d5a87af559
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSection.qml
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ caption: qsTr("Video")
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Source") }
+
+ SecondColumnLayout {
+ UrlChooser {
+ backendValue: backendValues.source
+ filter: "*.mp4"
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Fill mode") }
+
+ SecondColumnLayout {
+ ComboBox {
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: implicitWidth
+ scope: "VideoOutput"
+ model: ["Stretch", "PreserveAspectFit", "PreserveAspectCrop"]
+ backendValue: backendValues.fillMode
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Orientation") }
+
+ SecondColumnLayout {
+ ComboBox {
+ id: orientationComboBox
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: implicitWidth
+ model: [0, 90, 180, 270, 360]
+ backendValue: backendValues.orientation
+ manualMapping: true
+
+ onValueFromBackendChanged: {
+ if (!orientationComboBox.__isCompleted)
+ return
+
+ orientationComboBox.syncIndexToBackendValue()
+ }
+ onCompressedActivated: {
+ if (!orientationComboBox.__isCompleted)
+ return
+
+ if (orientationComboBox.block)
+ return
+
+ backendValues.orientation.value = orientationComboBox.model[orientationComboBox.currentIndex]
+ }
+ Component.onCompleted: orientationComboBox.syncIndexToBackendValue()
+
+ function syncIndexToBackendValue() {
+ orientationComboBox.block = true
+ orientationComboBox.currentIndex = orientationComboBox.model.indexOf(backendValues.orientation.value)
+ orientationComboBox.block = false
+ }
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
+
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSpecifics.qml
new file mode 100644
index 0000000000..45c8cce629
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/VideoSpecifics.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ MediaPlayerSection {}
+
+ VideoSection {}
+
+ AudioSection {}
+}
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml
index 18ba641639..b50b67e925 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml
@@ -102,6 +102,7 @@ jobs:
run: |
set(qt_version "$ENV{QT_VERSION}")
+ string(REGEX MATCH "^[0-9]+" qt_version_major "${qt_version}")
string(REPLACE "." "" qt_version_dotless "${qt_version}")
if ("${{ runner.os }}" STREQUAL "Windows")
set(url_os "windows_x86")
@@ -112,45 +113,63 @@ jobs:
set(url_os "linux_x64")
set(qt_package_arch_suffix "gcc_64")
set(qt_dir_prefix "${qt_version}/gcc_64")
- set(qt_package_suffix "-Linux-RHEL_7_6-GCC-Linux-RHEL_7_6-X86_64")
+ if("${qt_version_major}" STREQUAL "5")
+ set(qt_package_suffix "-Linux-RHEL_7_6-GCC-Linux-RHEL_7_6-X86_64")
+ else()
+ set(qt_package_suffix "-Linux-RHEL_8_2-GCC-Linux-RHEL_8_2-X86_64")
+ endif()
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(url_os "mac_x64")
set(qt_package_arch_suffix "clang_64")
- set(qt_dir_prefix "${qt_version}/clang_64")
- set(qt_package_suffix "-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64")
+ if("${qt_version_major}" STREQUAL "5")
+ set(qt_dir_prefix "${qt_version}/clang_64")
+ set(qt_package_suffix "-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64")
+ else()
+ set(qt_dir_prefix "${qt_version}/macos")
+ set(qt_package_suffix "-MacOS-MacOS_11_00-Clang-MacOS-MacOS_11_00-X86_64-ARM64")
+ endif()
endif()
- set(qt_base_url "https://download.qt.io/online/qtsdkrepository/${url_os}/desktop/qt5_${qt_version_dotless}")
+ set(qt_base_url "https://download.qt.io/online/qtsdkrepository/${url_os}/desktop/qt${qt_version_major}_${qt_version_dotless}")
file(DOWNLOAD "${qt_base_url}/Updates.xml" ./Updates.xml SHOW_PROGRESS)
file(READ ./Updates.xml updates_xml)
- string(REGEX MATCH "<Name>qt.qt5.*<Version>([0-9+-.]+)</Version>" updates_xml_output "${updates_xml}")
+ string(REGEX MATCH "<Name>qt.qt${qt_version_major}.*<Version>([0-9+-.]+)</Version>" updates_xml_output "${updates_xml}")
set(qt_package_version ${CMAKE_MATCH_1})
- file(MAKE_DIRECTORY qt5)
+ file(MAKE_DIRECTORY qt)
# Save the path for other steps
- file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt5/${qt_dir_prefix}" qt_dir)
+ file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt/${qt_dir_prefix}" qt_dir)
message("::set-output name=qt_dir::${qt_dir}")
message("Downloading Qt to ${qt_dir}")
function(downloadAndExtract url archive)
message("Downloading ${url}")
file(DOWNLOAD "${url}" ./${archive} SHOW_PROGRESS)
- execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../${archive} WORKING_DIRECTORY qt5)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../${archive} WORKING_DIRECTORY qt)
endfunction()
foreach(package qtbase qtdeclarative)
downloadAndExtract(
- "${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}${package}${qt_package_suffix}.7z"
+ "${qt_base_url}/qt.qt${qt_version_major}.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}${package}${qt_package_suffix}.7z"
${package}.7z
)
endforeach()
+ if("${qt_version_major}" STREQUAL "6")
+ foreach(package qt5compat qtshadertools)
+ downloadAndExtract(
+ "${qt_base_url}/qt.qt6.${qt_version_dotless}.${package}.${qt_package_arch_suffix}/${qt_package_version}${package}${qt_package_suffix}.7z"
+ ${package}.7z
+ )
+ endforeach()
+ endif()
+
# uic depends on libicu56.so
if ("${{ runner.os }}" STREQUAL "Linux")
downloadAndExtract(
- "${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}icu-linux-Rhel7.2-x64.7z"
+ "${qt_base_url}/qt.qt${qt_version_major}.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}icu-linux-Rhel7.2-x64.7z"
icu.7z
)
endif()
diff --git a/src/libs/languageserverprotocol/clientcapabilities.h b/src/libs/languageserverprotocol/clientcapabilities.h
index c0bdae4031..693fc231f2 100644
--- a/src/libs/languageserverprotocol/clientcapabilities.h
+++ b/src/libs/languageserverprotocol/clientcapabilities.h
@@ -529,6 +529,24 @@ public:
void clearSemanticTokens() { remove(semanticTokensKey); }
};
+class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensWorkspaceClientCapabilities : public JsonObject
+{
+public:
+ using JsonObject::JsonObject;
+ /**
+ * Whether the client implementation supports a refresh request sent from
+ * the server to the client.
+ *
+ * Note that this event is global and will force the client to refresh all
+ * semantic tokens currently shown. It should be used with absolute care
+ * and is useful for situation where a server for example detect a project
+ * wide change that requires such a calculation.
+ */
+ Utils::optional<bool> refreshSupport() const { return optionalValue<bool>(refreshSupportKey); }
+ void setRefreshSupport(bool refreshSupport) { insert(refreshSupportKey, refreshSupport); }
+ void clearRefreshSupport() { remove(refreshSupportKey); }
+};
+
class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceClientCapabilities : public JsonObject
{
public:
@@ -601,6 +619,12 @@ public:
Utils::optional<bool> configuration() const { return optionalValue<bool>(configurationKey); }
void setConfiguration(bool configuration) { insert(configurationKey, configuration); }
void clearConfiguration() { remove(configurationKey); }
+
+ Utils::optional<SemanticTokensWorkspaceClientCapabilities> semanticTokens() const
+ { return optionalValue<SemanticTokensWorkspaceClientCapabilities>(semanticTokensKey); }
+ void setSemanticTokens(const SemanticTokensWorkspaceClientCapabilities &semanticTokens)
+ { insert(semanticTokensKey, semanticTokens); }
+ void clearSemanticTokens() { remove(semanticTokensKey); }
};
class WindowClientClientCapabilities : public JsonObject
diff --git a/src/libs/languageserverprotocol/jsonkeys.h b/src/libs/languageserverprotocol/jsonkeys.h
index fa0e5d63e0..332571fb2c 100644
--- a/src/libs/languageserverprotocol/jsonkeys.h
+++ b/src/libs/languageserverprotocol/jsonkeys.h
@@ -171,6 +171,7 @@ constexpr char reasonKey[] = "reason";
constexpr char redKey[] = "red";
constexpr char referencesKey[] = "references";
constexpr char referencesProviderKey[] = "referencesProvider";
+constexpr char refreshSupportKey[] = "refreshSupport";
constexpr char registerOptionsKey[] = "registerOptions";
constexpr char registrationsKey[] = "registrations";
constexpr char removedKey[] = "removed";
diff --git a/src/libs/languageserverprotocol/semantictokens.cpp b/src/libs/languageserverprotocol/semantictokens.cpp
index d827136a41..fb8cc4247b 100644
--- a/src/libs/languageserverprotocol/semantictokens.cpp
+++ b/src/libs/languageserverprotocol/semantictokens.cpp
@@ -156,4 +156,8 @@ SemanticTokensDeltaResult::SemanticTokensDeltaResult(const QJsonValue &value)
}
}
+SemanticTokensRefreshRequest::SemanticTokensRefreshRequest()
+ : Request(methodName, nullptr)
+{}
+
} // namespace LanguageServerProtocol
diff --git a/src/libs/languageserverprotocol/semantictokens.h b/src/libs/languageserverprotocol/semantictokens.h
index fccfd29dcb..cc561ec670 100644
--- a/src/libs/languageserverprotocol/semantictokens.h
+++ b/src/libs/languageserverprotocol/semantictokens.h
@@ -240,4 +240,13 @@ public:
constexpr static const char methodName[] = "textDocument/semanticTokens/range";
};
+class LANGUAGESERVERPROTOCOL_EXPORT SemanticTokensRefreshRequest
+ : public Request<std::nullptr_t, std::nullptr_t, std::nullptr_t>
+{
+public:
+ explicit SemanticTokensRefreshRequest();
+ using Request::Request;
+ constexpr static const char methodName[] = "workspace/semanticTokens/refresh";
+};
+
} // namespace LanguageServerProtocol
diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp
index 6a6c9d8e91..f22c10ac46 100644
--- a/src/libs/utils/aspects.cpp
+++ b/src/libs/utils/aspects.cpp
@@ -1081,8 +1081,9 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
d->m_blockAutoApply = false;
});
} else {
- connect(d->m_pathChooserDisplay, &PathChooser::pathChanged, this, [this] {
- setValue(d->m_pathChooserDisplay->filePath().toString());
+ connect(d->m_pathChooserDisplay, &PathChooser::pathChanged,
+ this, [this](const QString &path) {
+ setValue(path);
});
}
}
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index bb096e59bf..4be8ef209f 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -32,12 +32,15 @@
#include "stringutils.h"
#include <QCoreApplication>
+#include <QLoggingCategory>
#include <QMutex>
#include <QRegularExpression>
#include <QTextCodec>
#include <cctype>
+Q_LOGGING_CATEGORY(log, "qtc.utils.filesearch", QtWarningMsg)
+
using namespace Utils;
static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
@@ -140,11 +143,13 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
{
if (futureInterface.isCanceled())
return;
+ qCDebug(log) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0);
FileSearchResultList results;
QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
+ qCDebug(log) << "- failed to get content for" << item.filePath;
futureInterface.cancel(); // failure
return;
}
@@ -222,6 +227,7 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
futureInterface.reportResult(results);
futureInterface.setProgressValue(1);
}
+ qCDebug(log) << "- finished searching in" << item.filePath;
}
FileSearchRegExp::FileSearchRegExp(const QString &searchTerm, QTextDocument::FindFlags flags,
@@ -257,11 +263,13 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
}
if (futureInterface.isCanceled())
return;
+ qCDebug(log) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0);
FileSearchResultList results;
QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
+ qCDebug(log) << "- failed to get content for" << item.filePath;
futureInterface.cancel(); // failure
return;
}
@@ -296,6 +304,7 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
futureInterface.reportResult(results);
futureInterface.setProgressValue(1);
}
+ qCDebug(log) << "- finished searching in" << item.filePath;
}
struct SearchState
diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp
index 28dfee2346..fc7b865e67 100644
--- a/src/libs/utils/launchersocket.cpp
+++ b/src/libs/utils/launchersocket.cpp
@@ -141,10 +141,8 @@ QList<CallerHandle::SignalType> CallerHandle::flushFor(CallerHandle::SignalType
{
// 1. If signalType is no signal - flush all
// 2. Flush all if we have any error
- // 3. If we are flushing for Finished, flush Started / ReadyRead, too
- // 4. If we are flushing for ReadyRead, flush Started, too
- // 5. (?) If we have collected Finished, flush it only when flushing
- // for ReadyRead / Finished (not for Started)
+ // 3. If we are flushing for Finished or ReadyRead, flush all, too
+ // 4. If we are flushing for Started, flush Started only
QMutexLocker locker(&m_mutex);
@@ -154,6 +152,7 @@ QList<CallerHandle::SignalType> CallerHandle::flushFor(CallerHandle::SignalType
});
const bool flushAll = (signalType == CallerHandle::SignalType::NoSignal)
+ || (signalType == CallerHandle::SignalType::ReadyRead)
|| (signalType == CallerHandle::SignalType::Finished)
|| storedSignals.contains(CallerHandle::SignalType::Error);
if (flushAll) {
diff --git a/src/libs/utils/multitextcursor.cpp b/src/libs/utils/multitextcursor.cpp
index c06eb95f18..7225de9344 100644
--- a/src/libs/utils/multitextcursor.cpp
+++ b/src/libs/utils/multitextcursor.cpp
@@ -27,6 +27,7 @@
#include "algorithm.h"
#include "camelcasecursor.h"
+#include "hostosinfo.h"
#include "qtcassert.h"
#include <QKeyEvent>
@@ -296,7 +297,10 @@ static QTextLine currentTextLine(const QTextCursor &cursor)
bool multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey)
{
uint searchkey = (e->modifiers() | e->key())
- & ~(Qt::KeypadModifier | Qt::GroupSwitchModifier | Qt::AltModifier);
+ & ~(Qt::KeypadModifier
+ | Qt::GroupSwitchModifier
+ | Qt::AltModifier
+ | Qt::ShiftModifier);
const QList<QKeySequence> bindings = QKeySequence::keyBindings(matchKey);
return bindings.contains(QKeySequence(searchkey));
@@ -306,7 +310,7 @@ bool MultiTextCursor::handleMoveKeyEvent(QKeyEvent *e,
QPlainTextEdit *edit,
bool camelCaseNavigationEnabled)
{
- if (e->modifiers() & Qt::AltModifier) {
+ if (e->modifiers() & Qt::AltModifier && !Utils::HostOsInfo::isMacHost()) {
QTextCursor::MoveOperation op = QTextCursor::NoMove;
if (multiCursorAddEvent(e, QKeySequence::MoveToNextWord)) {
op = QTextCursor::WordRight;
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 6377ee73ee..25862d4fc1 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -840,11 +840,23 @@ QStringList AndroidConfig::getAbis(const QString &device)
bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
{
auto ndkPath = Utils::FilePath::fromUserInput(ndkLocation);
+
+ if (!ndkPath.exists())
+ return false;
+
+ if (!ndkPath.pathAppended("toolchains").exists())
+ return false;
+
+ const QVersionNumber version = ndkVersion(ndkPath);
+ if (ndkVersion(ndkPath).isNull())
+ return false;
+
const FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms");
+ if (version.majorVersion() <= 22
+ && (!ndkPlatformsDir.exists() || ndkPlatformsDir.toString().contains(' ')))
+ return false; // TODO: Adapt code that assumes the presence of a "platforms" folder
- return ndkPath.exists() && ndkPath.pathAppended("toolchains").exists()
- && ndkPlatformsDir.exists() && !ndkPlatformsDir.toString().contains(' ')
- && !ndkVersion(ndkPath).isNull();
+ return true;
}
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
index 2dd8e9e455..f2ae4c5ca0 100644
--- a/src/plugins/android/androidrunner.h
+++ b/src/plugins/android/androidrunner.h
@@ -32,10 +32,9 @@
#include <qmldebug/qmloutputparser.h>
#include <QObject>
-#include <QTimer>
#include <QTcpSocket>
#include <QThread>
-#include <QProcess>
+#include <QTimer>
namespace Android {
namespace Internal {
diff --git a/src/plugins/android/androidsdkdownloader.cpp b/src/plugins/android/androidsdkdownloader.cpp
index 1ed8e04581..59adbe50bd 100644
--- a/src/plugins/android/androidsdkdownloader.cpp
+++ b/src/plugins/android/androidsdkdownloader.cpp
@@ -28,11 +28,10 @@
#include "utils/qtcprocess.h"
#include <coreplugin/icore.h>
+#include <QCryptographicHash>
#include <QDir>
#include <QDirIterator>
#include <QLoggingCategory>
-#include <QProcess>
-#include <QCryptographicHash>
#include <QStandardPaths>
using namespace Utils;
diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp
index 96824298ee..9edb0fdf4e 100644
--- a/src/plugins/android/androidsdkmanagerwidget.cpp
+++ b/src/plugins/android/androidsdkmanagerwidget.cpp
@@ -41,7 +41,6 @@
#include <QLineEdit>
#include <QLoggingCategory>
#include <QMessageBox>
-#include <QProcess>
#include <QSortFilterProxyModel>
namespace {
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index bc5dde7ac5..aa2f8e4532 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -62,7 +62,6 @@
#include <QFileInfo>
#include <QMenu>
#include <QPlainTextEdit>
-#include <QProcess>
#include <QScrollBar>
#include <QTextBlock>
diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp
index 7c81168155..7efc37a572 100644
--- a/src/plugins/clangcodemodel/clangdclient.cpp
+++ b/src/plugins/clangcodemodel/clangdclient.cpp
@@ -27,6 +27,7 @@
#include "clangcompletioncontextanalyzer.h"
#include "clangdiagnosticmanager.h"
+#include "clangmodelmanagersupport.h"
#include "clangpreprocessorassistproposalitem.h"
#include "clangtextmark.h"
#include "clangutils.h"
@@ -51,6 +52,7 @@
#include <cppeditor/cppvirtualfunctionproposalitem.h>
#include <cppeditor/semantichighlighter.h>
#include <languageclient/languageclientinterface.h>
+#include <languageclient/languageclientmanager.h>
#include <languageclient/languageclientutils.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
@@ -559,12 +561,12 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
{
QString indexingOption = "--background-index";
const CppEditor::ClangdSettings settings(CppEditor::ClangdProjectSettings(project).settings());
- if (!settings.indexingEnabled())
+ if (!settings.indexingEnabled() || jsonDbDir.isEmpty())
indexingOption += "=0";
const QString headerInsertionOption = QString("--header-insertion=")
+ (settings.autoIncludeHeaders() ? "iwyu" : "never");
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, headerInsertionOption,
- "--limit-results=0", "--clang-tidy=0"}};
+ "--limit-results=0", "--limit-references=0", "--clang-tidy=0"}};
if (settings.workerThreadLimit() != 0)
cmd.addArg("-j=" + QString::number(settings.workerThreadLimit()));
if (!jsonDbDir.isEmpty())
@@ -654,6 +656,7 @@ public:
bool openInSplit)
: q(q), id(id), cursor(cursor), editorWidget(editorWidget), uri(uri),
callback(std::move(callback)), virtualFuncAssistProvider(q->d),
+ docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1),
openInSplit(openInSplit) {}
~FollowSymbolData()
@@ -678,6 +681,8 @@ public:
openedFiles.clear();
}
+ bool defLinkIsAmbiguous() const;
+
ClangdClient * const q;
const quint64 id;
const QTextCursor cursor;
@@ -688,6 +693,7 @@ public:
QList<MessageId> pendingSymbolInfoRequests;
QList<MessageId> pendingGotoImplRequests;
QList<MessageId> pendingGotoDefRequests;
+ const int docRevision;
const bool openInSplit;
Utils::Link defLink;
@@ -1059,6 +1065,12 @@ public:
// The highlighters are owned by their respective documents.
std::unordered_map<TextDocument *, CppEditor::SemanticHighlighter *> highlighters;
+ QHash<TextDocument *, QPair<QList<ExpandedSemanticToken>, int>> previousTokens;
+
+ // The ranges of symbols referring to virtual functions, with document version,
+ // as extracted by the highlighting procedure.
+ QHash<TextDocument *, QPair<QList<Range>, int>> virtualRanges;
+
VersionedDataCache<const TextDocument *, AstNode> astCache;
VersionedDataCache<Utils::FilePath, AstNode> externalAstCache;
TaskTimer highlightingTimer{"highlighting"};
@@ -1074,6 +1086,10 @@ public:
: TextDocumentClientCapabilities::CompletionCapabilities(object)
{
insert("editsNearCursor", true); // For dot-to-arrow correction.
+ if (Utils::optional<CompletionItemCapbilities> completionItemCaps = completionItem()) {
+ completionItemCaps->setSnippetSupport(false);
+ setCompletionItem(*completionItemCaps);
+ }
}
};
@@ -1188,6 +1204,15 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
initOptions.insert("fallbackFlags", QJsonArray::fromStringList(clangOptions));
setInitializationOptions(initOptions);
}
+ auto isRunningClangdClient = [](const LanguageClient::Client *c) {
+ return qobject_cast<const ClangdClient *>(c) && c->state() != Client::ShutdownRequested
+ && c->state() != Client::Shutdown;
+ };
+ const QList<Client *> clients =
+ Utils::filtered(LanguageClientManager::clientsForProject(project), isRunningClangdClient);
+ QTC_CHECK(clients.isEmpty());
+ for (const Client *client : clients)
+ qCWarning(clangdLog) << client->name() << client->stateString();
ClientCapabilities caps = Client::defaultClientCapabilities();
Utils::optional<TextDocumentClientCapabilities> textCaps = caps.textDocument();
if (textCaps) {
@@ -1366,6 +1391,8 @@ void ClangdClient::handleDocumentClosed(TextDocument *doc)
{
d->highlighters.erase(doc);
d->astCache.remove(doc);
+ d->previousTokens.remove(doc);
+ d->virtualRanges.remove(doc);
}
QVersionNumber ClangdClient::versionNumber() const
@@ -1996,6 +2023,14 @@ void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverR
d->getAndHandleAst(doc, astHandler, Private::AstCallbackMode::SyncIfPossible);
}
+void ClangdClient::setVirtualRanges(const Utils::FilePath &filePath, const QList<Range> &ranges,
+ int revision)
+{
+ TextDocument * const doc = documentForFilePath(filePath);
+ if (doc && doc->document()->revision() == revision)
+ d->virtualRanges.insert(doc, {ranges, revision});
+}
+
void ClangdClient::Private::handleGotoDefinitionResult()
{
QTC_ASSERT(followSymbolData->defLink.hasValidTarget(), return);
@@ -2003,8 +2038,7 @@ void ClangdClient::Private::handleGotoDefinitionResult()
qCDebug(clangdLog) << "handling go to definition result";
// No dis-ambiguation necessary. Call back with the link and finish.
- if (!followSymbolData->cursorNode->mightBeAmbiguousVirtualCall()
- && !followSymbolData->cursorNode->isPureVirtualDeclaration()) {
+ if (!followSymbolData->defLinkIsAmbiguous()) {
followSymbolData->callback(followSymbolData->defLink);
followSymbolData.reset();
return;
@@ -2377,16 +2411,37 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
return true;
if (token.type != "variable" && token.type != "property" && token.type != "parameter")
return false;
- const QList<AstNode> path = getAstPath(ast, tokenRange(token));
+ const Range range = tokenRange(token);
+ const QList<AstNode> path = getAstPath(ast, range);
if (path.size() < 2)
return false;
if (path.last().hasConstType())
return false;
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
if (it->kind() == "Call" || it->kind() == "CXXConstruct"
- || it->kind() == "MemberInitializer" || it->kind() == "CXXOperatorCall") {
+ || it->kind() == "MemberInitializer") {
return true;
}
+
+ // The token should get marked for e.g. lambdas, but not for assignment operators,
+ // where the user sees that it's being written.
+ if (it->kind() == "CXXOperatorCall") {
+ const QList<AstNode> children = it->children().value_or(QList<AstNode>());
+ if (children.size() < 2)
+ return false;
+ if (!children.last().range().contains(range))
+ return false;
+ QList<AstNode> firstChildTree{children.first()};
+ while (!firstChildTree.isEmpty()) {
+ const AstNode n = firstChildTree.takeFirst();
+ const QString detail = n.detail().value_or(QString());
+ if (detail.startsWith("operator"))
+ return !detail.contains('=');
+ firstChildTree << n.children().value_or(QList<AstNode>());
+ }
+ return true;
+ }
+
if (it->kind().endsWith("Cast") && it->hasConstType())
return false;
if (it->kind() == "Member" && it->arcanaContains("(")
@@ -2491,6 +2546,20 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
ExtraHighlightingResultsCollector(future, results, filePath, ast, &doc, docContents).collect();
if (!future.isCanceled()) {
qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
+ QList<Range> virtualRanges;
+ for (const HighlightingResult &r : results) {
+ if (r.textStyles.mainStyle != C_VIRTUAL_METHOD)
+ continue;
+ const Position startPos(r.line - 1, r.column - 1);
+ virtualRanges << Range(startPos, startPos.withOffset(r.length, &doc));
+ }
+ QMetaObject::invokeMethod(ClangModelManagerSupport::instance(),
+ [filePath, virtualRanges, docRevision] {
+ if (ClangdClient * const client
+ = ClangModelManagerSupport::instance()->clientForFile(filePath)) {
+ client->setVirtualRanges(filePath, virtualRanges, docRevision);
+ }
+ }, Qt::QueuedConnection);
future.reportResults(QVector<HighlightingResult>(results.cbegin(),
results.cend()));
}
@@ -2520,6 +2589,17 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc,
<< version << q->documentVersion(doc->filePath());
return;
}
+ const auto previous = previousTokens.find(doc);
+ if (previous != previousTokens.end()) {
+ if (previous->first == tokens && previous->second == version) {
+ qCDebug(clangdLogHighlight) << "tokens and version same as last time; nothing to do";
+ return;
+ }
+ previous->first = tokens;
+ previous->second = version;
+ } else {
+ previousTokens.insert(doc, qMakePair(tokens, version));
+ }
for (const ExpandedSemanticToken &t : tokens)
qCDebug(clangdLogHighlight()) << '\t' << t.line << t.column << t.length << t.type
<< t.modifiers;
@@ -2788,7 +2868,21 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
if (!edit)
return;
- const QString rawInsertText = edit->newText();
+ const auto kind = static_cast<CompletionItemKind::Kind>(
+ item.kind().value_or(CompletionItemKind::Text));
+ const bool isFunctionLike = kind == CompletionItemKind::Function
+ || kind == CompletionItemKind::Method || kind == CompletionItemKind::Constructor;
+ QString rawInsertText = edit->newText();
+
+ // Some preparation for our magic involving (non-)insertion of parentheses and
+ // cursor placement.
+ if (isFunctionLike && !rawInsertText.contains('(')) {
+ if (item.label().contains("()")) // function takes no arguments
+ rawInsertText += "()";
+ else if (item.label().contains('(')) // function takes arguments
+ rawInsertText += "( )";
+ }
+
const int firstParenOffset = rawInsertText.indexOf('(');
const int lastParenOffset = rawInsertText.lastIndexOf(')');
const QString detail = item.detail().value_or(QString());
@@ -2802,12 +2896,6 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
const QTextDocument * const doc = manipulator.textCursorAt(currentPos).document();
const Range range = edit->range();
const int rangeStart = range.start().toPositionInDocument(doc);
-
- const auto kind = static_cast<CompletionItemKind::Kind>(
- item.kind().value_or(CompletionItemKind::Text));
- const bool isFunctionLike = kind == CompletionItemKind::Function
- || kind == CompletionItemKind::Method || kind == CompletionItemKind::Constructor
- || (firstParenOffset != -1 && lastParenOffset != -1);
if (isFunctionLike && completionSettings.m_autoInsertBrackets) {
// If the user typed the opening parenthesis, they'll likely also type the closing one,
// in which case it would be annoying if we put the cursor after the already automatically
@@ -3463,6 +3551,24 @@ void ExtraHighlightingResultsCollector::visitNode(const AstNode &node)
}
}
+bool ClangdClient::FollowSymbolData::defLinkIsAmbiguous() const
+{
+ // If we have up-to-date highlighting info, we can give a definite answer.
+ if (editorWidget) {
+ const auto virtualRanges = q->d->virtualRanges.constFind(editorWidget->textDocument());
+ if (virtualRanges != q->d->virtualRanges.constEnd()
+ && virtualRanges->second == docRevision) {
+ const auto matcher = [cursorRange = cursorNode->range()](const Range &r) {
+ return cursorRange.overlaps(r);
+ };
+ return Utils::contains(virtualRanges->first, matcher);
+ }
+ }
+
+ // Otherwise, we have to rely on AST-based heuristics.
+ return cursorNode->mightBeAmbiguousVirtualCall() || cursorNode->isPureVirtualDeclaration();
+}
+
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h
index 0367551661..580168c3e3 100644
--- a/src/plugins/clangcodemodel/clangdclient.h
+++ b/src/plugins/clangcodemodel/clangdclient.h
@@ -35,6 +35,7 @@
namespace Core { class SearchResultItem; }
namespace CppEditor { class CppEditorWidget; }
+namespace LanguageServerProtocol { class Range; }
namespace ProjectExplorer { class Project; }
namespace TextEditor { class BaseTextEditor; }
@@ -76,6 +77,9 @@ public:
const LanguageServerProtocol::HoverRequest::Response &hoverResponse,
const LanguageServerProtocol::DocumentUri &uri);
+ void setVirtualRanges(const Utils::FilePath &filePath,
+ const QList<LanguageServerProtocol::Range> &ranges, int revision);
+
void enableTesting();
bool testingEnabled() const;
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index c06d8a8fff..090a4549c3 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -388,6 +388,18 @@ ClangdClient *ClangModelManagerSupport::clientForProject(
&& c->state() != Client::Shutdown;
});
QTC_ASSERT(clients.size() <= 1, qDebug() << project << clients.size());
+ if (clients.size() > 1) {
+ Client *activeClient = nullptr;
+ for (Client * const c : clients) {
+ if (!activeClient && (c->state() == Client::Initialized
+ || c->state() == Client::InitializeRequested)) {
+ activeClient = c;
+ } else {
+ LanguageClientManager::shutdownClient(c);
+ }
+ }
+ return qobject_cast<ClangdClient *>(activeClient);
+ }
return clients.empty() ? nullptr : qobject_cast<ClangdClient *>(clients.first());
}
@@ -463,7 +475,7 @@ void ClangModelManagerSupport::watchForExternalChanges()
return;
ClangdClient * const client = clientForProject(project);
- if (client) {
+ if (client && !m_clientsToRestart.contains(client)) {
m_clientsToRestart.append(client);
timer->start();
}
diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp
index 6a31aafd09..49dac93f49 100644
--- a/src/plugins/clangcodemodel/test/clangdtests.cpp
+++ b/src/plugins/clangcodemodel/test/clangdtests.cpp
@@ -674,7 +674,7 @@ void ClangdTestHighlighting::initTestCase()
m_results = results;
loop.quit();
};
- connect(client(), &ClangdClient::highlightingResultsReady, handler);
+ connect(client(), &ClangdClient::highlightingResultsReady, &loop, handler);
timer.start(10000);
loop.exec();
QVERIFY(timer.isActive());
@@ -1040,7 +1040,9 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_PARAMETER, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("typedef as underlying type in enum declaration") << 424 << 21 << 424 << 39
<< QList<int>{C_TYPE} << 0;
- QTest::newRow("argument to user-defined subscript operator") << 434 << 12 << 434 << 17
+ QTest::newRow("argument 1 to user-defined subscript operator") << 434 << 5 << 434 << 11
+ << QList<int>{C_PARAMETER} << 0;
+ QTest::newRow("argument 2 to user-defined subscript operator") << 434 << 12 << 434 << 17
<< QList<int>{C_PARAMETER, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("partial class template specialization") << 553 << 25 << 553 << 28
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
@@ -1246,6 +1248,7 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("const argument to unnamed lambda") << 830 << 16 << 830 << 19
<< QList<int>{C_LOCAL} << 0;
+ QTest::newRow("simple assignment") << 835 << 5 << 835 << 6 << QList<int>{C_LOCAL} << 0;
}
void ClangdTestHighlighting::test()
diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp
index 6e0ed1c8ec..652d9540c8 100644
--- a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp
+++ b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp
@@ -829,3 +829,8 @@ void lambdaArgTest()
[](int &) {}(val);
[](int) {}(val);
}
+
+void assignmentTest() {
+ struct S {} s;
+ s = {};
+}
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index deea46530e..8a058e9e71 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -88,7 +88,6 @@
#include <QMessageBox>
#include <QMetaObject>
#include <QMutex>
-#include <QProcess>
#include <QRegularExpression>
#include <QSharedPointer>
#include <QTextCodec>
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
index a27d65b7b5..6d6ab01060 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
@@ -483,6 +483,8 @@ void ShortcutSettingsWidget::resetToDefault()
ShortcutItem *scitem = shortcutItem(current);
if (scitem) {
scitem->m_keys = scitem->m_cmd->defaultKeySequences();
+ current->setText(2, keySequencesToNativeString(scitem->m_keys));
+ CommandMappings::setModified(current, false);
setupShortcutBox(scitem);
markAllCollisions();
}
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 920b612aae..9c4293d2b5 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -2288,7 +2288,6 @@ void EditorManagerPrivate::vcsOpenCurrentEditor()
return;
if (!versionControl->vcsOpen(document->filePath())) {
- // TODO: wrong dialog parent
QMessageBox::warning(ICore::dialogParent(), tr("Cannot Open File"),
tr("Cannot open the file for editing with VCS."));
}
diff --git a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
index 90dab9a8ec..4f7e49d2f2 100644
--- a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
+++ b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp
@@ -45,7 +45,6 @@
#include <QJsonObject>
#include <QMutex>
#include <QMutexLocker>
-#include <QProcess>
#include <QRegularExpression>
#include <QWaitCondition>
diff --git a/src/plugins/cppeditor/compileroptionsbuilder.cpp b/src/plugins/cppeditor/compileroptionsbuilder.cpp
index 09f71fa93f..e80de33f2b 100644
--- a/src/plugins/cppeditor/compileroptionsbuilder.cpp
+++ b/src/plugins/cppeditor/compileroptionsbuilder.cpp
@@ -791,6 +791,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
bool containsDriverMode = false;
bool skipNext = false;
bool nextIsTarget = false;
+ bool nextIsGccToolchain = false;
const QStringList allFlags = m_projectPart.extraCodeModelFlags + m_projectPart.compilerFlags;
for (const QString &option : allFlags) {
if (skipNext) {
@@ -802,6 +803,11 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
m_explicitTarget = option;
continue;
}
+ if (nextIsGccToolchain) {
+ nextIsGccToolchain = false;
+ m_compilerFlags.flags.append("--gcc-toolchain=" + option);
+ continue;
+ }
if (userBlackList.contains(option))
continue;
@@ -833,6 +839,11 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
continue;
}
+ if (option == "-gcc-toolchain") {
+ nextIsGccToolchain = true;
+ continue;
+ }
+
if (option == includeUserPathOption || option == includeSystemPathOption
|| option == includeUserPathOptionWindows) {
skipNext = true;
diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp
index f6c4629d0c..cf57ee3973 100644
--- a/src/plugins/cppeditor/cppcodemodelsettings.cpp
+++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp
@@ -34,6 +34,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <QSettings>
@@ -312,6 +313,11 @@ ClangdSettings &ClangdSettings::instance()
return settings;
}
+bool ClangdSettings::useClangd() const
+{
+ return m_data.useClangd && clangdVersion(clangdFilePath()) >= QVersionNumber(13);
+}
+
void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
{
g_defaultClangdFilePath = filePath;
@@ -333,6 +339,37 @@ void ClangdSettings::setData(const Data &data)
}
}
+static QVersionNumber getClangdVersion(const FilePath &clangdFilePath)
+{
+ Utils::QtcProcess clangdProc;
+ clangdProc.setCommand({clangdFilePath, {"--version"}});
+ clangdProc.start();
+ if (!clangdProc.waitForStarted() || !clangdProc.waitForFinished())
+ return{};
+ const QString output = clangdProc.allOutput();
+ static const QString versionPrefix = "clangd version ";
+ const int prefixOffset = output.indexOf(versionPrefix);
+ if (prefixOffset == -1)
+ return {};
+ return QVersionNumber::fromString(output.mid(prefixOffset + versionPrefix.length()));
+}
+
+QVersionNumber ClangdSettings::clangdVersion(const FilePath &clangdFilePath)
+{
+ const QDateTime timeStamp = clangdFilePath.lastModified();
+ const auto it = m_versionCache.find(clangdFilePath);
+ if (it == m_versionCache.end()) {
+ const QVersionNumber version = getClangdVersion(clangdFilePath);
+ m_versionCache.insert(clangdFilePath, qMakePair(timeStamp, version));
+ return version;
+ }
+ if (it->first != timeStamp) {
+ it->first = timeStamp;
+ it->second = getClangdVersion(clangdFilePath);
+ }
+ return it->second;
+}
+
void ClangdSettings::loadSettings()
{
m_data.fromMap(Core::ICore::settings()->value(clangdSettingsKey()).toMap());
diff --git a/src/plugins/cppeditor/cppcodemodelsettings.h b/src/plugins/cppeditor/cppcodemodelsettings.h
index 5f4f4622c7..2f3de7dd6b 100644
--- a/src/plugins/cppeditor/cppcodemodelsettings.h
+++ b/src/plugins/cppeditor/cppcodemodelsettings.h
@@ -29,8 +29,12 @@
#include <utils/fileutils.h>
+#include <QDateTime>
+#include <QHash>
#include <QObject>
+#include <QPair>
#include <QStringList>
+#include <QVersionNumber>
QT_BEGIN_NAMESPACE
class QSettings;
@@ -117,7 +121,7 @@ public:
ClangdSettings(const Data &data) : m_data(data) {}
static ClangdSettings &instance();
- bool useClangd() const { return m_data.useClangd; }
+ bool useClangd() const;
static void setDefaultClangdPath(const Utils::FilePath &filePath);
Utils::FilePath clangdFilePath() const;
@@ -129,6 +133,8 @@ public:
void setData(const Data &data);
Data data() const { return m_data; }
+ static QVersionNumber clangdVersion(const Utils::FilePath &clangdFilePath);
+
#ifdef WITH_TESTS
static void setUseClangd(bool use);
static void setClangdFilePath(const Utils::FilePath &filePath);
@@ -144,6 +150,7 @@ private:
void saveSettings();
Data m_data;
+ static inline QHash<Utils::FilePath, QPair<QDateTime, QVersionNumber>> m_versionCache;
};
inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
index 7a850df329..3e899ae01f 100644
--- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
+++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp
@@ -35,7 +35,6 @@
#include <utils/algorithm.h>
#include <utils/infolabel.h>
#include <utils/pathchooser.h>
-#include <utils/qtcprocess.h>
#include <QFormLayout>
#include <QSpinBox>
@@ -285,30 +284,14 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
if (!d->clangdChooser.isValid())
return;
const Utils::FilePath clangdPath = d->clangdChooser.filePath();
- Utils::QtcProcess clangdProc;
- clangdProc.setCommand({clangdPath, {"--version"}});
- clangdProc.start();
- if (!clangdProc.waitForStarted() || !clangdProc.waitForFinished()) {
- labelSetter.setWarning(tr("Failed to retrieve clangd version: %1")
- .arg(clangdProc.exitMessage()));
- return;
- }
- const QString output = clangdProc.allOutput();
- static const QString versionPrefix = "clangd version ";
- const int prefixOffset = output.indexOf(versionPrefix);
- QVersionNumber clangdVersion;
- if (prefixOffset != -1) {
- clangdVersion = QVersionNumber::fromString(output.mid(prefixOffset
- + versionPrefix.length()));
- }
+ const QVersionNumber clangdVersion = ClangdSettings::clangdVersion(clangdPath);
if (clangdVersion.isNull()) {
labelSetter.setWarning(tr("Failed to retrieve clangd version: "
"Unexpected clangd output."));
return;
}
if (clangdVersion < QVersionNumber(13)) {
- labelSetter.setWarning(tr("The clangd version is %1, but %2 or greater is "
- "recommended for full functionality.")
+ labelSetter.setWarning(tr("The clangd version is %1, but %2 or greater is required.")
.arg(clangdVersion.toString()).arg(13));
return;
}
diff --git a/src/plugins/cppeditor/cppprojectupdater.cpp b/src/plugins/cppeditor/cppprojectupdater.cpp
index 4e97779a3e..96e7f3b66c 100644
--- a/src/plugins/cppeditor/cppprojectupdater.cpp
+++ b/src/plugins/cppeditor/cppprojectupdater.cpp
@@ -90,11 +90,16 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo,
// extra compilers
for (QPointer<ExtraCompiler> compiler : qAsConst(m_extraCompilers)) {
if (compiler->isDirty()) {
- auto watcher = new QFutureWatcher<void>;
+ QPointer<QFutureWatcher<void>> watcher = new QFutureWatcher<void>;
// queued connection to delay after the extra compiler updated its result contents,
// which is also done in the main thread when compiler->run() finished
connect(watcher, &QFutureWatcherBase::finished,
this, [this, watcher] {
+ // In very unlikely case the CppProjectUpdater::cancel() could have been
+ // invoked after posting the finished() signal and before this handler
+ // gets called. In this case the watcher is already deleted.
+ if (!watcher)
+ return;
m_projectUpdateFutureInterface->setProgressValue(
m_projectUpdateFutureInterface->progressValue() + 1);
m_extraCompilersFutureWatchers.remove(watcher);
diff --git a/src/plugins/cppeditor/generatedcodemodelsupport.h b/src/plugins/cppeditor/generatedcodemodelsupport.h
index f4e94acbf2..918b017a34 100644
--- a/src/plugins/cppeditor/generatedcodemodelsupport.h
+++ b/src/plugins/cppeditor/generatedcodemodelsupport.h
@@ -33,7 +33,6 @@
#include <QDateTime>
#include <QHash>
-#include <QProcess>
#include <QSet>
namespace Core { class IEditor; }
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
index e759d1889e..2f71c8606b 100644
--- a/src/plugins/debugger/debuggeritem.cpp
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -41,7 +41,6 @@
#include <utils/winutils.h>
#include <QFileInfo>
-#include <QProcess>
#include <QUuid>
#ifdef WITH_TESTS
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index ed3fb5de9d..2b5373a042 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -71,14 +71,13 @@
#include <QMenu>
#include <QMimeData>
#include <QPainter>
-#include <QProcess>
#include <QSet>
+#include <QTableWidget>
#include <QTabWidget>
#include <QTextEdit>
-#include <QTableWidget>
#include <QTimer>
-#include <QVBoxLayout>
#include <QToolTip>
+#include <QVBoxLayout>
#include <algorithm>
#include <cstring>
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index f12eb5915b..1e4ed5346e 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -2598,7 +2598,7 @@ bool GitClient::tryLauchingGitK(const Environment &env,
process->start();
success = process->waitForStarted();
if (success)
- connect(process, &QtcProcess::finished, process, &QProcess::deleteLater);
+ connect(process, &QtcProcess::finished, process, &QObject::deleteLater);
else
delete process;
} else {
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index cf137c68bc..6c244cfd4e 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -60,10 +60,9 @@
#include <QHash>
#include <QList>
#include <QLoggingCategory>
-#include <QProcess>
#include <QSettings>
-#include <QStringList>
#include <QStandardPaths>
+#include <QStringList>
#include <QTimer>
#include <memory>
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
index 7fafba0ef4..84bfa56102 100644
--- a/src/plugins/ios/iosprobe.cpp
+++ b/src/plugins/ios/iosprobe.cpp
@@ -32,7 +32,6 @@
#include <QFileInfo>
#include <QFileInfoList>
#include <QLoggingCategory>
-#include <QProcess>
static Q_LOGGING_CATEGORY(probeLog, "qtc.ios.probe", QtWarningMsg)
diff --git a/src/plugins/ios/iostoolhandler.h b/src/plugins/ios/iostoolhandler.h
index cc17b526a2..5860f5333e 100644
--- a/src/plugins/ios/iostoolhandler.h
+++ b/src/plugins/ios/iostoolhandler.h
@@ -31,7 +31,6 @@
#include <QMap>
#include <QString>
#include <QStringList>
-#include <QProcess>
namespace Ios {
namespace Internal {
diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp
index 993a245716..0bf72b8a2f 100644
--- a/src/plugins/ios/simulatorcontrol.cpp
+++ b/src/plugins/ios/simulatorcontrol.cpp
@@ -42,7 +42,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QLoggingCategory>
-#include <QProcess>
using namespace Utils;
using namespace std;
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index b177f82c52..03b75680ab 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -170,6 +170,9 @@ static ClientCapabilities generateClientCapabilities()
workspaceCapabilities.setDidChangeConfiguration(allowDynamicRegistration);
workspaceCapabilities.setExecuteCommand(allowDynamicRegistration);
workspaceCapabilities.setConfiguration(true);
+ SemanticTokensWorkspaceClientCapabilities semanticTokensWorkspaceClientCapabilities;
+ semanticTokensWorkspaceClientCapabilities.setRefreshSupport(true);
+ workspaceCapabilities.setSemanticTokens(semanticTokensWorkspaceClientCapabilities);
capabilities.setWorkspace(workspaceCapabilities);
TextDocumentClientCapabilities documentCapabilities;
@@ -340,6 +343,19 @@ Client::State Client::state() const
return m_state;
}
+QString Client::stateString() const
+{
+ switch (m_state){
+ case Uninitialized: return tr("uninitialized");
+ case InitializeRequested: return tr("initialize requested");
+ case Initialized: return tr("initialized");
+ case ShutdownRequested: return tr("shutdown requested");
+ case Shutdown: return tr("shutdown");
+ case Error: return tr("error");
+ }
+ return {};
+}
+
ClientCapabilities Client::defaultClientCapabilities()
{
return generateClientCapabilities();
@@ -1350,6 +1366,11 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon
dynamic_cast<const WorkDoneProgressCreateRequest *>(content)->id());
response.setResult(nullptr);
sendContent(response);
+ } else if (method == SemanticTokensRefreshRequest::methodName) {
+ m_tokenSupport.refresh();
+ Response<std::nullptr_t, JsonObject> response(id);
+ response.setResult(nullptr);
+ sendContent(response);
} else if (method == ProgressNotification::methodName) {
if (Utils::optional<ProgressParams> params
= dynamic_cast<const ProgressNotification *>(content)->params()) {
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index 59f23599a4..1465dabad8 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -58,7 +58,6 @@
#include <QBuffer>
#include <QHash>
-#include <QProcess>
#include <QJsonDocument>
#include <QTextCursor>
@@ -116,6 +115,7 @@ public:
Error
};
State state() const;
+ QString stateString() const;
bool reachable() const { return m_state == Initialized; }
// capabilities
diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp
index c05f8df459..63a4f1c9da 100644
--- a/src/plugins/languageclient/languageclientmanager.cpp
+++ b/src/plugins/languageclient/languageclientmanager.cpp
@@ -71,6 +71,7 @@ LanguageClientManager::LanguageClientManager(QObject *parent)
JsonRpcMessageHandler::registerMessageProvider<UnregisterCapabilityRequest>();
JsonRpcMessageHandler::registerMessageProvider<WorkDoneProgressCreateRequest>();
JsonRpcMessageHandler::registerMessageProvider<ProgressNotification>();
+ JsonRpcMessageHandler::registerMessageProvider<SemanticTokensRefreshRequest>();
connect(EditorManager::instance(), &EditorManager::editorOpened,
this, &LanguageClientManager::editorOpened);
connect(EditorManager::instance(), &EditorManager::documentOpened,
diff --git a/src/plugins/languageclient/semantichighlightsupport.cpp b/src/plugins/languageclient/semantichighlightsupport.cpp
index 11365566ba..5132cd9326 100644
--- a/src/plugins/languageclient/semantichighlightsupport.cpp
+++ b/src/plugins/languageclient/semantichighlightsupport.cpp
@@ -183,6 +183,17 @@ SemanticTokenSupport::SemanticTokenSupport(Client *client)
&TextEditorSettings::fontSettingsChanged,
client,
[this]() { updateFormatHash(); });
+ QObject::connect(Core::EditorManager::instance(),
+ &Core::EditorManager::currentEditorChanged,
+ this,
+ &SemanticTokenSupport::onCurrentEditorChanged);
+}
+
+void SemanticTokenSupport::refresh()
+{
+ m_tokens.clear();
+ for (Core::IEditor *editor : Core::EditorManager::visibleEditors())
+ onCurrentEditorChanged(editor);
}
void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
@@ -224,8 +235,11 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
if (supportedRequests.testFlag(SemanticRequestType::FullDelta)) {
const Utils::FilePath filePath = textDocument->filePath();
- const QString &previousResultId = m_tokens.value(filePath).tokens.resultId().value_or(QString());
+ const VersionedTokens versionedToken = m_tokens.value(filePath);
+ const QString &previousResultId = versionedToken.tokens.resultId().value_or(QString());
if (!previousResultId.isEmpty()) {
+ if (m_client->documentVersion(filePath) == versionedToken.version)
+ return;
SemanticTokensDeltaParams params;
params.setTextDocument(TextDocumentIdentifier(DocumentUri::fromFilePath(filePath)));
params.setPreviousResultId(previousResultId);
@@ -325,6 +339,12 @@ void SemanticTokenSupport::updateFormatHash()
rehighlight();
}
+void SemanticTokenSupport::onCurrentEditorChanged(Core::IEditor *editor)
+{
+ if (auto textEditor = qobject_cast<BaseTextEditor *>(editor))
+ updateSemanticTokens(textEditor->textDocument());
+}
+
void SemanticTokenSupport::setTokenTypesMap(const QMap<QString, int> &tokenTypesMap)
{
m_tokenTypesMap = tokenTypesMap;
diff --git a/src/plugins/languageclient/semantichighlightsupport.h b/src/plugins/languageclient/semantichighlightsupport.h
index 1a90101b3e..110b14f23b 100644
--- a/src/plugins/languageclient/semantichighlightsupport.h
+++ b/src/plugins/languageclient/semantichighlightsupport.h
@@ -36,6 +36,8 @@
#include <functional>
+namespace Core { class IEditor; }
+
namespace LanguageClient {
class Client;
@@ -48,6 +50,11 @@ public:
QString type;
QStringList modifiers;
};
+inline bool operator==(const ExpandedSemanticToken &t1, const ExpandedSemanticToken &t2)
+{
+ return t1.line == t2.line && t1.column == t2.column && t1.length == t2.length
+ && t1.type == t2.type && t1.modifiers == t2.modifiers;
+}
using SemanticTokensHandler = std::function<void(TextEditor::TextDocument *,
const QList<ExpandedSemanticToken> &, int)>;
@@ -62,11 +69,12 @@ void applyHighlight(TextEditor::TextDocument *doc,
} // namespace SemanticHighligtingSupport
-class SemanticTokenSupport
+class SemanticTokenSupport : public QObject
{
public:
explicit SemanticTokenSupport(Client *client);
+ void refresh();
void reloadSemanticTokens(TextEditor::TextDocument *doc);
void updateSemanticTokens(TextEditor::TextDocument *doc);
void rehighlight();
@@ -94,6 +102,7 @@ private:
void highlight(const Utils::FilePath &filePath);
void updateFormatHash();
void currentEditorChanged();
+ void onCurrentEditorChanged(Core::IEditor *editor);
Client *m_client = nullptr;
diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp
index 6ac2e30fd1..75f829b530 100644
--- a/src/plugins/mcusupport/mcusupportoptions.cpp
+++ b/src/plugins/mcusupport/mcusupportoptions.cpp
@@ -381,6 +381,7 @@ static ToolChain *msvcToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
const Abi abi = t->targetAbi();
+ // TODO: Should Abi::WindowsMsvc2022Flavor be added too?
return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor || abi.osFlavor() == Abi::WindowsMsvc2019Flavor)
&& abi.architecture() == Abi::X86Architecture
&& abi.wordWidth() == 64
diff --git a/src/plugins/nim/project/nimtoolchainfactory.cpp b/src/plugins/nim/project/nimtoolchainfactory.cpp
index 91e74e3e3a..289a29e693 100644
--- a/src/plugins/nim/project/nimtoolchainfactory.cpp
+++ b/src/plugins/nim/project/nimtoolchainfactory.cpp
@@ -36,7 +36,6 @@
#include <utils/fileutils.h>
#include <QFormLayout>
-#include <QProcess>
using namespace ProjectExplorer;
using namespace Utils;
diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp
index 4566efc357..3a642db9bb 100644
--- a/src/plugins/perforce/perforceeditor.cpp
+++ b/src/plugins/perforce/perforceeditor.cpp
@@ -34,7 +34,6 @@
#include <QDebug>
#include <QFileInfo>
-#include <QProcess>
#include <QSet>
#include <QTextStream>
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 7c61260b54..fb9df9ef78 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -111,6 +111,7 @@ static void setupPreregisteredOsFlavors() {
registerOsFlavor(Abi::WindowsMsvc2015Flavor, "msvc2015", {Abi::OS::WindowsOS});
registerOsFlavor(Abi::WindowsMsvc2017Flavor, "msvc2017", {Abi::OS::WindowsOS});
registerOsFlavor(Abi::WindowsMsvc2019Flavor, "msvc2019", {Abi::OS::WindowsOS});
+ registerOsFlavor(Abi::WindowsMsvc2022Flavor, "msvc2022", {Abi::OS::WindowsOS});
registerOsFlavor(Abi::WindowsMSysFlavor, "msys", {Abi::OS::WindowsOS});
registerOsFlavor(Abi::WindowsCEFlavor, "ce", {Abi::OS::WindowsOS});
registerOsFlavor(Abi::VxWorksFlavor, "vxworks", {Abi::OS::VxWorks});
@@ -285,7 +286,9 @@ static Abis parseCoffHeader(const QByteArray &data)
flavor = Abi::WindowsMsvc2013Flavor;
break;
case 14:
- if (minorLinker >= quint8(20))
+ if (minorLinker >= quint8(30))
+ flavor = Abi::WindowsMsvc2022Flavor;
+ else if (minorLinker >= quint8(20))
flavor = Abi::WindowsMsvc2019Flavor;
else if (minorLinker >= quint8(10))
flavor = Abi::WindowsMsvc2017Flavor;
@@ -295,6 +298,9 @@ static Abis parseCoffHeader(const QByteArray &data)
case 15:
flavor = Abi::WindowsMsvc2019Flavor;
break;
+ case 16:
+ flavor = Abi::WindowsMsvc2022Flavor;
+ break;
default: // Keep unknown flavor
if (minorLinker != 0)
flavor = Abi::WindowsMSysFlavor; // MSVC seems to avoid using minor numbers
@@ -692,9 +698,9 @@ bool Abi::operator == (const Abi &other) const
static bool compatibleMSVCFlavors(const Abi::OSFlavor &left, const Abi ::OSFlavor &right)
{
- // MSVC 2019, 2017 and 2015 are compatible
- return left >= Abi::WindowsMsvc2015Flavor && left <= Abi::WindowsMsvc2019Flavor
- && right >= Abi::WindowsMsvc2015Flavor && right <= Abi::WindowsMsvc2019Flavor;
+ // MSVC 2022, 2019, 2017 and 2015 are compatible
+ return left >= Abi::WindowsMsvc2015Flavor && left <= Abi::WindowsMsvc2022Flavor
+ && right >= Abi::WindowsMsvc2015Flavor && right <= Abi::WindowsMsvc2022Flavor;
}
bool Abi::isCompatibleWith(const Abi &other) const
@@ -1091,6 +1097,8 @@ bool Abi::osSupportsFlavor(const Abi::OS &os, const Abi::OSFlavor &flavor)
Abi::OSFlavor Abi::flavorForMsvcVersion(int version)
{
+ if (version >= 1930)
+ return WindowsMsvc2022Flavor;
if (version >= 1920)
return WindowsMsvc2019Flavor;
if (version >= 1910)
diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h
index 2ddfdfa881..56272baced 100644
--- a/src/plugins/projectexplorer/abi.h
+++ b/src/plugins/projectexplorer/abi.h
@@ -112,7 +112,8 @@ public:
WindowsMsvc2015Flavor,
WindowsMsvc2017Flavor,
WindowsMsvc2019Flavor,
- WindowsLastMsvcFlavor = WindowsMsvc2019Flavor,
+ WindowsMsvc2022Flavor,
+ WindowsLastMsvcFlavor = WindowsMsvc2022Flavor,
WindowsMSysFlavor,
WindowsCEFlavor,
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
index 33796e3b12..1579b2cc9f 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
@@ -31,7 +31,6 @@
#include <QTimer>
#ifdef Q_OS_UNIX
-#include <QProcess>
#include <QDir>
#include <signal.h>
#include <errno.h>
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index 8e842b0226..e18df2b0f3 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -45,10 +45,9 @@
#include <QDateTime>
#include <QFutureInterface>
#include <QFutureWatcher>
-#include <QProcess>
+#include <QTextBlock>
#include <QThreadPool>
#include <QTimer>
-#include <QTextBlock>
using namespace Utils;
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index ca93d5582b..56b7431073 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -51,7 +51,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QLoggingCategory>
-#include <QProcess>
#include <QRegularExpression>
#include <QSettings>
#include <QVector>
@@ -430,7 +429,9 @@ static Abi findAbiOfMsvc(MsvcToolChain::Type type,
else if (version == QLatin1String("v7.0A") || version == QLatin1String("v7.1"))
msvcVersionString = QLatin1String("10.0");
}
- if (msvcVersionString.startsWith(QLatin1String("16.")))
+ if (msvcVersionString.startsWith(QLatin1String("17.")))
+ flavor = Abi::WindowsMsvc2022Flavor;
+ else if (msvcVersionString.startsWith(QLatin1String("16.")))
flavor = Abi::WindowsMsvc2019Flavor;
else if (msvcVersionString.startsWith(QLatin1String("15.")))
flavor = Abi::WindowsMsvc2017Flavor;
@@ -927,6 +928,10 @@ QStringList MsvcToolChain::suggestedMkspecList() const
"winrt-arm-msvc2019",
"winrt-x86-msvc2019",
"winrt-x64-msvc2019"};
+ case Abi::WindowsMsvc2022Flavor:
+ return {"win32-msvc",
+ "win32-msvc2022",
+ "win32-arm64-msvc"};
default:
break;
}
@@ -938,6 +943,14 @@ Abis MsvcToolChain::supportedAbis() const
Abi abi = targetAbi();
Abis abis = {abi};
switch (abi.osFlavor()) {
+ case Abi::WindowsMsvc2022Flavor:
+ abis << Abi(abi.architecture(),
+ abi.os(),
+ Abi::WindowsMsvc2019Flavor,
+ abi.binaryFormat(),
+ abi.wordWidth(),
+ abi.param());
+ Q_FALLTHROUGH();
case Abi::WindowsMsvc2019Flavor:
abis << Abi(abi.architecture(),
abi.os(),
diff --git a/src/plugins/qbsprojectmanager/qbssession.h b/src/plugins/qbsprojectmanager/qbssession.h
index d9775b6f0b..8829085f9d 100644
--- a/src/plugins/qbsprojectmanager/qbssession.h
+++ b/src/plugins/qbsprojectmanager/qbssession.h
@@ -31,7 +31,7 @@
#include <QHash>
#include <QJsonObject>
#include <QObject>
-#include <QProcess>
+#include <QProcessEnvironment>
#include <QString>
#include <QVariant>
diff --git a/src/plugins/qmakeprojectmanager/externaleditors.cpp b/src/plugins/qmakeprojectmanager/externaleditors.cpp
index fe953a0049..ad6192844d 100644
--- a/src/plugins/qmakeprojectmanager/externaleditors.cpp
+++ b/src/plugins/qmakeprojectmanager/externaleditors.cpp
@@ -36,11 +36,9 @@
#include <qtsupport/qtkitinformation.h>
#include <designer/designerconstants.h>
-#include <QProcess>
#include <QDebug>
-
-#include <QTcpSocket>
#include <QTcpServer>
+#include <QTcpSocket>
using namespace ProjectExplorer;
using namespace Utils;
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 1aac7a17cd..48cdb6f123 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -7,7 +7,7 @@ add_qtc_plugin(QmlDesigner
CONDITION TARGET Qt5::QuickWidgets
DEPENDS
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
- Qt5::QuickWidgets Qt5::CorePrivate Sqlite
+ Qt5::QuickWidgets Qt5::CorePrivate Sqlite Qt5::Xml Qt5::Svg
DEFINES
DESIGNER_CORE_LIBRARY
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
@@ -139,6 +139,7 @@ extend_qtc_plugin(QmlDesigner
theme.cpp theme.h
zoomaction.cpp zoomaction.h
hdrimage.cpp hdrimage.h
+ svgpasteaction.cpp svgpasteaction.h
)
extend_qtc_plugin(QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore.pri b/src/plugins/qmldesigner/components/componentcore/componentcore.pri
index 49d646d462..d47c4cf8a4 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore.pri
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore.pri
@@ -20,6 +20,7 @@ SOURCES += crumblebar.cpp
SOURCES += qmldesignericonprovider.cpp
SOURCES += zoomaction.cpp
SOURCES += hdrimage.cpp
+SOURCES += svgpasteaction.cpp
HEADERS += modelnodecontextmenu.h
HEADERS += addimagesdialog.h
@@ -43,6 +44,7 @@ HEADERS += crumblebar.h
HEADERS += qmldesignericonprovider.h
HEADERS += zoomaction.h
HEADERS += hdrimage.h
+HEADERS += svgpasteaction.h
FORMS += \
$$PWD/addsignalhandlerdialog.ui
diff --git a/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
new file mode 100644
index 0000000000..dac06f73e6
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
@@ -0,0 +1,1235 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "svgpasteaction.h"
+
+#include <itemlibraryinfo.h>
+#include <variantproperty.h>
+#include <nodeabstractproperty.h>
+
+#include <private/qlocale_tools_p.h>
+
+#include <QSvgGenerator>
+#include <QBuffer>
+#include <QColor>
+#include <QPainter>
+#include <QPainterPath>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
+#include <QtMath>
+
+#include <array>
+
+namespace QmlDesigner {
+
+namespace {
+
+/* Copied from qquicksvgparser.cpp 3e783b26a8fb41e3f5a53b883735f5d10fbbd98a */
+
+// '0' is 0x30 and '9' is 0x39
+static inline bool isDigit(ushort ch)
+{
+ static quint16 magic = 0x3ff;
+ return ((ch >> 4) == 3) && (magic >> (ch & 15));
+}
+
+static qreal toDouble(const QChar *&str)
+{
+ const int maxLen = 255;//technically doubles can go til 308+ but whatever
+ char temp[maxLen+1];
+ int pos = 0;
+
+ if (*str == QLatin1Char('-')) {
+ temp[pos++] = '-';
+ ++str;
+ } else if (*str == QLatin1Char('+')) {
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ if (*str == QLatin1Char('.') && pos < maxLen) {
+ temp[pos++] = '.';
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ bool exponent = false;
+ if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
+ exponent = true;
+ temp[pos++] = 'e';
+ ++str;
+ if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ }
+
+ temp[pos] = '\0';
+
+ qreal val;
+ if (!exponent && pos < 10) {
+ int ival = 0;
+ const char *t = temp;
+ bool neg = false;
+ if (*t == '-') {
+ neg = true;
+ ++t;
+ }
+ while (*t && *t != '.') {
+ ival *= 10;
+ ival += (*t) - '0';
+ ++t;
+ }
+ if (*t == '.') {
+ ++t;
+ int div = 1;
+ while (*t) {
+ ival *= 10;
+ ival += (*t) - '0';
+ div *= 10;
+ ++t;
+ }
+ val = ((qreal)ival)/((qreal)div);
+ } else {
+ val = ival;
+ }
+ if (neg)
+ val = -val;
+ } else {
+ bool ok = false;
+ val = qstrtod(temp, nullptr, &ok);
+ }
+ return val;
+}
+
+static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
+{
+ while (str->isSpace())
+ ++str;
+ while (isDigit(str->unicode()) ||
+ *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
+ *str == QLatin1Char('.')) {
+
+ points.append(toDouble(str));
+
+ while (str->isSpace())
+ ++str;
+ if (*str == QLatin1Char(','))
+ ++str;
+
+ //eat the rest of space
+ while (str->isSpace())
+ ++str;
+ }
+}
+
+static void pathArcSegment(QPainterPath &path,
+ qreal xc, qreal yc,
+ qreal th0, qreal th1,
+ qreal rx, qreal ry, qreal xAxisRotation)
+{
+ qreal sinTh, cosTh;
+ qreal a00, a01, a10, a11;
+ qreal x1, y1, x2, y2, x3, y3;
+ qreal t;
+ qreal thHalf;
+
+ sinTh = qSin(qDegreesToRadians(xAxisRotation));
+ cosTh = qCos(qDegreesToRadians(xAxisRotation));
+
+ a00 = cosTh * rx;
+ a01 = -sinTh * ry;
+ a10 = sinTh * rx;
+ a11 = cosTh * ry;
+
+ thHalf = 0.5 * (th1 - th0);
+ t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
+ x1 = xc + qCos(th0) - t * qSin(th0);
+ y1 = yc + qSin(th0) + t * qCos(th0);
+ x3 = xc + qCos(th1);
+ y3 = yc + qSin(th1);
+ x2 = x3 + t * qSin(th1);
+ y2 = y3 - t * qCos(th1);
+
+ path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
+ a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
+ a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
+}
+
+void pathArc(QPainterPath &path,
+ qreal rx, qreal ry,
+ qreal x_axis_rotation,
+ int large_arc_flag,
+ int sweep_flag,
+ qreal x, qreal y,
+ qreal curx, qreal cury)
+{
+ qreal sin_th, cos_th;
+ qreal a00, a01, a10, a11;
+ qreal x0, y0, x1, y1, xc, yc;
+ qreal d, sfactor, sfactor_sq;
+ qreal th0, th1, th_arc;
+ int i, n_segs;
+ qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
+
+ rx = qAbs(rx);
+ ry = qAbs(ry);
+
+ sin_th = qSin(qDegreesToRadians(x_axis_rotation));
+ cos_th = qCos(qDegreesToRadians(x_axis_rotation));
+
+ dx = (curx - x) / 2.0;
+ dy = (cury - y) / 2.0;
+ dx1 = cos_th * dx + sin_th * dy;
+ dy1 = -sin_th * dx + cos_th * dy;
+ Pr1 = rx * rx;
+ Pr2 = ry * ry;
+ Px = dx1 * dx1;
+ Py = dy1 * dy1;
+ /* Spec : check if radii are large enough */
+ check = Px / Pr1 + Py / Pr2;
+ if (check > 1) {
+ rx = rx * qSqrt(check);
+ ry = ry * qSqrt(check);
+ }
+
+ a00 = cos_th / rx;
+ a01 = sin_th / rx;
+ a10 = -sin_th / ry;
+ a11 = cos_th / ry;
+ x0 = a00 * curx + a01 * cury;
+ y0 = a10 * curx + a11 * cury;
+ x1 = a00 * x + a01 * y;
+ y1 = a10 * x + a11 * y;
+ /* (x0, y0) is current point in transformed coordinate space.
+ (x1, y1) is new point in transformed coordinate space.
+ The arc fits a unit-radius circle in this space.
+ */
+ d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
+ sfactor_sq = 1.0 / d - 0.25;
+ if (sfactor_sq < 0) sfactor_sq = 0;
+ sfactor = qSqrt(sfactor_sq);
+ if (sweep_flag == large_arc_flag) sfactor = -sfactor;
+ xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
+ yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
+ /* (xc, yc) is center of the circle. */
+
+ th0 = qAtan2(y0 - yc, x0 - xc);
+ th1 = qAtan2(y1 - yc, x1 - xc);
+
+ th_arc = th1 - th0;
+ if (th_arc < 0 && sweep_flag)
+ th_arc += 2 * M_PI;
+ else if (th_arc > 0 && !sweep_flag)
+ th_arc -= 2 * M_PI;
+
+ n_segs = qCeil(qAbs(th_arc / (M_PI * 0.5 + 0.001)));
+
+ for (i = 0; i < n_segs; i++) {
+ pathArcSegment(path, xc, yc,
+ th0 + i * th_arc / n_segs,
+ th0 + (i + 1) * th_arc / n_segs,
+ rx, ry, x_axis_rotation);
+ }
+}
+
+
+bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
+{
+ qreal x0 = 0, y0 = 0; // starting point
+ qreal x = 0, y = 0; // current point
+ char lastMode = 0;
+ QPointF ctrlPt;
+ const QChar *str = dataStr.constData();
+ const QChar *end = str + dataStr.size();
+
+ while (str != end) {
+ while (str->isSpace())
+ ++str;
+ QChar pathElem = *str;
+ ++str;
+ QVarLengthArray<qreal, 8> arg;
+ parseNumbersArray(str, arg);
+ if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
+ arg.append(0);//dummy
+ const qreal *num = arg.constData();
+ int count = arg.count();
+ while (count > 0) {
+ qreal offsetX = x; // correction offsets
+ qreal offsetY = y; // for relative commands
+ switch (pathElem.unicode()) {
+ case 'm': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
+ path.moveTo(x0, y0);
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('l');
+ }
+ break;
+ case 'M': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
+ path.moveTo(x0, y0);
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('L');
+ }
+ break;
+ case 'z':
+ case 'Z': {
+ x = x0;
+ y = y0;
+ count--; // skip dummy
+ num++;
+ path.closeSubpath();
+ }
+ break;
+ case 'l': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = num[0] + offsetX;
+ y = num[1] + offsetY;
+ num += 2;
+ count -= 2;
+ path.lineTo(x, y);
+
+ }
+ break;
+ case 'L': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = num[0];
+ y = num[1];
+ num += 2;
+ count -= 2;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'h': {
+ x = num[0] + offsetX;
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'H': {
+ x = num[0];
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'v': {
+ y = num[0] + offsetY;
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'V': {
+ y = num[0];
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'c': {
+ if (count < 6) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1(num[0] + offsetX, num[1] + offsetY);
+ QPointF c2(num[2] + offsetX, num[3] + offsetY);
+ QPointF e(num[4] + offsetX, num[5] + offsetY);
+ num += 6;
+ count -= 6;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'C': {
+ if (count < 6) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1(num[0], num[1]);
+ QPointF c2(num[2], num[3]);
+ QPointF e(num[4], num[5]);
+ num += 6;
+ count -= 6;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 's': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1;
+ if (lastMode == 'c' || lastMode == 'C' ||
+ lastMode == 's' || lastMode == 'S')
+ c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c1 = QPointF(x, y);
+ QPointF c2(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'S': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1;
+ if (lastMode == 'c' || lastMode == 'C' ||
+ lastMode == 's' || lastMode == 'S')
+ c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c1 = QPointF(x, y);
+ QPointF c2(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'q': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'Q': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 't': {
+ if (count < 2) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF e(num[0] + offsetX, num[1] + offsetY);
+ num += 2;
+ count -= 2;
+ QPointF c;
+ if (lastMode == 'q' || lastMode == 'Q' ||
+ lastMode == 't' || lastMode == 'T')
+ c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c = QPointF(x, y);
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'T': {
+ if (count < 2) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF e(num[0], num[1]);
+ num += 2;
+ count -= 2;
+ QPointF c;
+ if (lastMode == 'q' || lastMode == 'Q' ||
+ lastMode == 't' || lastMode == 'T')
+ c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c = QPointF(x, y);
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'a': {
+ if (count < 7) {
+ num += count;
+ count = 0;
+ break;
+ }
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++) + offsetX;
+ qreal ey = (*num++) + offsetY;
+ count -= 7;
+ qreal curx = x;
+ qreal cury = y;
+ pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
+ int(sweepFlag), ex, ey, curx, cury);
+
+ x = ex;
+ y = ey;
+ }
+ break;
+ case 'A': {
+ if (count < 7) {
+ num += count;
+ count = 0;
+ break;
+ }
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++);
+ qreal ey = (*num++);
+ count -= 7;
+ qreal curx = x;
+ qreal cury = y;
+ pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
+ int(sweepFlag), ex, ey, curx, cury);
+
+ x = ex;
+ y = ey;
+ }
+ break;
+ default:
+ return false;
+ }
+ lastMode = pathElem.toLatin1();
+ }
+ }
+ return true;
+}
+
+/* Copied from qquicksvgparser.cpp 3e783b26a8fb41e3f5a53b883735f5d10fbbd98a */
+
+double round(double value, int decimal_places) {
+ const double multiplier = std::pow(10.0, decimal_places);
+ return std::round(value * multiplier) / multiplier;
+}
+
+static const std::initializer_list<QStringView> tagAllowList{
+ u"path", u"rect", u"polygon", u"circle", u"ellipse"
+};
+
+// fillOpacity and strokeOpacity aren't actual QML properties, but get mapped anyways
+// for completeness.
+static const std::initializer_list<std::pair<QStringView, QString>> mapping{
+ {u"fill", "fillColor"},
+ {u"stroke", "strokeColor"},
+ {u"stroke-width", "strokeWidth"},
+ {u"opacity", "opacity"},
+ {u"fill-opacity", "fillOpacity"},
+ {u"stroke-opacity", "strokeOpacity"}
+};
+
+template <typename Container>
+bool contains(const Container &c, const QStringView &stringView) {
+ return std::find(std::begin(c), std::end(c), stringView) != std::end(c);
+}
+
+template <typename Container>
+auto findKey(const Container &c, const QStringView &key) {
+ return std::find_if(std::begin(c), std::end(c), [&](const auto &pair){
+ return pair.first == key;
+ });
+}
+
+template<typename Callable>
+void depthFirstTraversal(const QDomNode &node,
+ const Callable &action)
+{
+ QDomNode currentNode = node;
+
+ while (!currentNode.isNull()) {
+ action(currentNode);
+ depthFirstTraversal(currentNode.firstChild(), action);
+ currentNode = currentNode.nextSibling();
+ }
+}
+
+template<typename Callable>
+void topToBottomTraversal(const QDomNode &node,
+ const Callable &action)
+{
+ if (node.isNull())
+ return;
+
+ topToBottomTraversal(node.parentNode(), action);
+ action(node);
+}
+
+QTransform parseMatrix(const QString &values)
+{
+ // matrix(<a> <b> <c> <d> <e> <f>)
+ // [a c e] [m11 m21 m31]
+ // SVG [b d f] Qt [m12 m22 m32]
+ // [0 0 1] [m13 m23 m33]
+ static const QRegularExpression re("([0-9-.]+)");
+ QRegularExpressionMatchIterator iter = re.globalMatch(values.simplified());
+
+ std::array<float, 6> arr = {1, 0, 0, 1, 0, 0};
+ int i = 0;
+ while (iter.hasNext()) {
+ QRegularExpressionMatch match = iter.next();
+ arr[i] = match.captured(1).toFloat();
+ ++i;
+ }
+
+ if (i != 6)
+ return QTransform();
+
+ return QTransform(arr[0], arr[1], 0, arr[2], arr[3], 0, arr[4], arr[5], 1);
+}
+
+QTransform parseTranslate(const QString &values)
+{
+ // translate(<x> [<y>]) translate(<x>[,<y>])
+ static const QRegularExpression re(R"(^([\d.-]+)(?:(?:\s*,\s*|\s+)([\d.-]+))?$)");
+ QRegularExpressionMatch m = re.match(values.simplified());
+
+ if (!m.hasMatch())
+ return QTransform();
+
+ return QTransform().translate(m.captured(1).toFloat(), m.captured(2).toFloat());
+}
+
+QTransform parseScale(const QString &values)
+{
+ // scale(<x> [<y>]) scale(<x>[,<y>])
+ static const QRegularExpression re(R"(^([\d.-]+)(?:(?:\s*,\s*|\s+)([\d.-]+))?$)");
+ QRegularExpressionMatch m = re.match(values.simplified());
+
+ if (!m.hasMatch())
+ return QTransform();
+
+ float x = m.captured(1).toFloat();
+ // If y is not provided, it is assumed to be equal to x.
+ float y = (m.captured(2).isEmpty()) ? x : m.captured(2).toFloat();
+
+ return QTransform().scale(x, y);
+}
+
+QTransform parseRotate(const QString &values)
+{
+ // rotate(<a> [<x> <y>]) rotate(<a>[,<x>,<y>])
+ static const QRegularExpression re(R"(^([\d.-]+)(?:(?:\s*,\s*|\s+)([\d.-]+)(?:\s*,\s*|\s+)([\d.-]+))?$)");
+ QRegularExpressionMatch m = re.match(values.simplified());
+
+ if (!m.hasMatch())
+ return QTransform();
+
+ float a = m.captured(1).toFloat();
+
+ QTransform transform;
+
+ if (m.captured(2).isEmpty() || m.captured(3).isEmpty()) {
+ transform.rotate(a);
+ } else {
+ float x = m.captured(2).toFloat();
+ float y = m.captured(3).toFloat();
+ transform.translate(x, y);
+ transform.rotate(a);
+ transform.translate(-x, -y);
+ }
+
+ return transform;
+}
+
+QTransform parseSkewX(const QString &values)
+{
+ // skewX(<a>)
+ static const QRegularExpression re(R"(^([\d.-]+)$)");
+ QRegularExpressionMatch m = re.match(values.simplified());
+
+ if (!m.hasMatch())
+ return QTransform();
+
+ float a = m.captured(1).toFloat();
+
+ return QTransform(1, 0, 0, std::tan(a * M_PI / 180.0), 1, 0, 0, 0, 1);
+}
+
+QTransform parseSkewY(const QString &values)
+{
+ // skewY(<a>)
+ static const QRegularExpression re(R"(^([\d.-]+)$)");
+ QRegularExpressionMatch m = re.match(values.simplified());
+
+ if (!m.hasMatch())
+ return QTransform();
+
+ float a = m.captured(1).toFloat();
+
+ return QTransform(1, std::tan(a * M_PI / 180.0), 0, 0, 1, 0, 0, 0, 1);
+}
+
+QTransform parseTransform(const QString &transformStr)
+{
+ if (transformStr.isEmpty())
+ return QTransform();
+
+ std::vector<QTransform> transforms;
+
+ static const QRegularExpression reTransform(R"(([\w]+)\(([\s\S]*?)\))");
+ QRegularExpressionMatchIterator i = reTransform.globalMatch(transformStr.simplified());
+
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+
+ const QString function = match.captured(1).simplified();
+ const QString values = match.captured(2).simplified();
+
+ if (function == "matrix")
+ transforms.push_back(parseMatrix(values));
+ else if (function == "translate")
+ transforms.push_back(parseTranslate(values));
+ else if (function == "scale")
+ transforms.push_back(parseScale(values));
+ else if (function == "rotate")
+ transforms.push_back(parseRotate(values));
+ else if (function == "skewX")
+ transforms.push_back(parseSkewX(values));
+ else if (function == "skewY")
+ transforms.push_back(parseSkewY(values));
+ }
+
+ QTransform transform;
+ std::for_each(transforms.rbegin(), transforms.rend(), [&](const QTransform &t)
+ {
+ transform *= t;
+ });
+
+ return transform;
+}
+
+QString convertQPainterPathtoSVGPath(const QPainterPath &path)
+{
+ QByteArray byteArray;
+ QBuffer buffer(&byteArray);
+
+ QSvgGenerator generator;
+ generator.setOutputDevice(&buffer);
+
+ QPainter p;
+ p.begin(&generator);
+ p.drawPath(path);
+ p.end();
+
+ QDomDocument tmpDomDocument;
+ if (!tmpDomDocument.setContent(byteArray))
+ return QString();
+
+ QDomElement pathElement;
+
+ auto extractPathElement = [&pathElement](const QDomNode &node) {
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ if (element.tagName() == "path")
+ pathElement = element;
+ }
+ };
+
+ depthFirstTraversal(tmpDomDocument.firstChild(), extractPathElement);
+
+ return pathElement.attribute("d");
+}
+
+QVariant convertValue(const QByteArray &key, const QString &value)
+{
+ if (key == "fillOpacity" || key == "strokeOpacity") {
+ if (value.contains("%"))
+ return QString(value).replace("%", "").toFloat() / 100.0f;
+
+ return value.toFloat();
+ } else if (key == "strokeWidth") {
+ return value.toInt();
+ } else if (key == "opacity") {
+ return value.toFloat();
+ }
+
+ return value;
+}
+
+CSSRule parseCSSRule(const QString &ruleStr)
+{
+ static const QRegularExpression reRules(R"(([\s\S]*?):([\s\S]*?)(?:;|;?$))");
+
+ CSSRule rule;
+ QRegularExpressionMatchIterator i = reRules.globalMatch(ruleStr);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+
+ if (match.lastCapturedIndex() != 2)
+ continue;
+
+ CSSProperty property;
+ property.directive = match.captured(1).trimmed();
+ property.value = match.captured(2).trimmed();
+
+ rule.push_back(property);
+ }
+
+ return rule;
+}
+
+CSSRules parseCSS(const QDomElement &styleElement)
+{
+ static const QRegularExpression reCSS(R"(([\s\S]*?){([\s\S]*?)})");
+
+ CSSRules cssRules;
+ QRegularExpressionMatchIterator i = reCSS.globalMatch(styleElement.text().simplified());
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+
+ if (match.lastCapturedIndex() != 2)
+ continue;
+
+ cssRules.insert(match.captured(1).trimmed(),
+ parseCSSRule(match.captured(2).trimmed()));
+ }
+
+ return cssRules;
+}
+
+void applyCSSRules(const CSSRule &cssRule, PropertyMap &properties)
+{
+ for (const CSSProperty &property : cssRule) {
+ const QString directive = property.directive;
+ if (auto iter = findKey(mapping, directive); iter != mapping.end()) {
+ const QByteArray directive = iter->second.toUtf8();
+ properties.insert(directive, convertValue(directive, property.value));
+ }
+ }
+}
+
+// This merges potential fill and/or stroke opacity with fill and/or stroke color
+void mergeOpacity(PropertyMap &properties)
+{
+ auto merge = [&](const QByteArray &opacityKey, const QByteArray &colorKey) {
+
+ if (!properties.contains(opacityKey))
+ return;
+
+ QColor color; // By default black same as SVG
+
+ if (properties.contains(colorKey))
+ color = QColor(properties[colorKey].toString());
+
+ color.setAlphaF(properties[opacityKey].toFloat());
+ // Insert/replace merged color and remove opacity
+ properties.insert(colorKey, color.name(QColor::HexArgb));
+ properties.remove(opacityKey);
+ };
+
+ merge("fillOpacity", "fillColor");
+ merge("strokeOpacity", "strokeColor");
+}
+
+void flattenTransformsAndStyles(const QDomElement &element,
+ const CSSRules &cssRules,
+ QTransform &transform,
+ PropertyMap &properties)
+{
+ properties.insert("fillColor", "black"); // overwrite default fillColor
+ properties.insert("strokeWidth", -1); // overwrite default strokeWidth of 4
+
+ auto collectTransformAndStyle = [&](const QDomNode &node) {
+ QDomElement e = node.toElement();
+ transform *= parseTransform(e.attribute("transform"));
+
+ // Parse and assign presentation attributes contained in mapping
+ for (const auto &p : mapping) {
+ const QString attributeValue = e.attribute(p.first.toString()).trimmed();
+ if (attributeValue.isEmpty())
+ continue;
+
+ const QByteArray directive = p.second.toUtf8();
+ properties.insert(directive, convertValue(directive, attributeValue));
+ }
+
+ // Parse and assign css styles
+ if (e.hasAttribute("class")) {
+ // Replace all commas with whitespaces, if there are commas contained
+ const QString classStr = e.attribute("class").replace(",", " ").simplified();
+ const QStringList classes = classStr.split(" ", Qt::SkipEmptyParts);
+
+ for (const auto &c : classes)
+ applyCSSRules(cssRules["." + e.attribute("class")], properties);
+ }
+
+ if (e.hasAttribute("id")) {
+ const QString id = e.attribute("id").simplified();
+ applyCSSRules(cssRules["#" + id], properties);
+ }
+
+ // Parse and assign inline style
+ if (e.hasAttribute("style")) {
+ const QString rule = e.attribute("style").simplified();
+ applyCSSRules(parseCSSRule(rule), properties);
+ }
+ };
+
+ topToBottomTraversal(element, collectTransformAndStyle);
+
+ mergeOpacity(properties);
+}
+
+bool applyMinimumBoundingBox(QPainterPath &path, PropertyMap &properties)
+{
+ const QRectF boundingRect = path.boundingRect();
+
+ path.translate(-boundingRect.topLeft());
+
+ properties.insert("x", round(boundingRect.x(), 2));
+ properties.insert("y", round(boundingRect.y(), 2));
+ properties.insert("width", round(boundingRect.width(), 2));
+ properties.insert("height", round(boundingRect.height(), 2));
+
+ const QString svgPath = convertQPainterPathtoSVGPath(path);
+
+ if (svgPath.isEmpty())
+ return false;
+
+ properties.insert("path", svgPath);
+
+ return true;
+}
+
+PropertyMap generateRectProperties(const QDomElement &e, const CSSRules &cssRules)
+{
+ QRectF rect(e.attribute("x").toFloat(),
+ e.attribute("y").toFloat(),
+ e.attribute("width").toFloat(),
+ e.attribute("height").toFloat());
+
+ if (!rect.isValid())
+ return {};
+
+ QPainterPath path;
+ path.addRect(rect);
+
+ PropertyMap properties;
+ QTransform transform;
+ flattenTransformsAndStyles(e, cssRules, transform, properties);
+
+ path = transform.map(path);
+
+ if (!applyMinimumBoundingBox(path, properties))
+ return {};
+
+ return properties;
+}
+
+PropertyMap generateEllipseProperties(const QDomElement &e, const CSSRules &cssRules)
+{
+ const QPointF center(e.attribute("cx").toFloat(), e.attribute("cy").toFloat());
+ qreal radiusX = 0;
+ qreal radiusY = 0;
+
+ if (e.tagName() == "circle")
+ radiusX = radiusY = e.attribute("r").toFloat();
+ else if (e.tagName() == "ellipse") {
+ radiusX = e.attribute("rx").toFloat();
+ radiusY = e.attribute("ry").toFloat();
+ }
+
+ if (radiusX <= 0 || radiusY <= 0)
+ return {};
+
+ QPainterPath path;
+ path.addEllipse(center, radiusX, radiusY);
+
+ PropertyMap properties;
+ QTransform transform;
+ flattenTransformsAndStyles(e, cssRules, transform, properties);
+
+ path = transform.map(path);
+
+ if (!applyMinimumBoundingBox(path, properties))
+ return {};
+
+ return properties;
+}
+
+PropertyMap generatePathProperties(const QDomElement &e, const CSSRules &cssRules)
+{
+ if (!e.hasAttribute("d"))
+ return {};
+
+ QPainterPath path;
+
+ if (!parsePathDataFast(e.attribute("d"), path))
+ return {};
+
+ PropertyMap properties;
+ QTransform transform;
+ flattenTransformsAndStyles(e, cssRules, transform, properties);
+
+ path = transform.map(path);
+
+ if (!applyMinimumBoundingBox(path, properties))
+ return {};
+
+ return properties;
+}
+
+PropertyMap generatePolygonProperties(const QDomElement &e, const CSSRules &cssRules)
+{
+ if (!e.hasAttribute("points"))
+ return {};
+
+ // Replace all commas with whitespaces, if there are commas contained
+ const QString pointsStr = e.attribute("points").replace(",", " ").simplified();
+ const QStringList pointList = pointsStr.split(" ", Qt::SkipEmptyParts);
+
+ if (pointList.isEmpty() || pointList.length() < 4)
+ return {};
+
+ QPolygonF polygon;
+
+ for (int i = 0; i < pointList.length(); i += 2)
+ polygon.push_back({pointList[i].toFloat(), pointList[i + 1].toFloat()});
+
+ if (!polygon.isClosed() && polygon.size())
+ polygon.push_back(polygon.front());
+
+ QPainterPath path;
+ path.addPolygon(polygon);
+
+ PropertyMap properties;
+ QTransform transform;
+ flattenTransformsAndStyles(e, cssRules, transform, properties);
+
+ path = transform.map(path);
+
+ if (!applyMinimumBoundingBox(path, properties))
+ return {};
+
+ return properties;
+}
+
+ModelNode createPathNode(ModelNode parent, const PropertyMap &properties)
+{
+ ItemLibraryEntry itemLibraryEntry;
+ itemLibraryEntry.setName("SVG Path Item");
+ itemLibraryEntry.setType("QtQuick.Studio.Components.SvgPathItem", 1, 0);
+
+ ModelNode node = QmlItemNode::createQmlObjectNode(
+ parent.view(), itemLibraryEntry, {}, parent.defaultNodeAbstractProperty(), false);
+
+ PropertyMap::const_iterator i = properties.constBegin();
+ while (i != properties.constEnd()) {
+ node.variantProperty(i.key()).setValue(i.value());
+ ++i;
+ }
+
+ return node;
+}
+
+ModelNode createGroupNode(ModelNode parent, const PropertyMap &properties)
+{
+ ItemLibraryEntry itemLibraryEntry;
+ itemLibraryEntry.setName("Group");
+ itemLibraryEntry.setType("QtQuick.Studio.Components.GroupItem", 1, 0);
+
+ ModelNode node = QmlItemNode::createQmlObjectNode(
+ parent.view(), itemLibraryEntry, {}, parent.defaultNodeAbstractProperty(), false);
+
+ PropertyMap::const_iterator i = properties.constBegin();
+ while (i != properties.constEnd()) {
+ node.variantProperty(i.key()).setValue(i.value());
+ ++i;
+ }
+
+ return node;
+}
+
+} // namespace
+
+SVGPasteAction::SVGPasteAction()
+ : m_domDocument()
+{}
+
+bool SVGPasteAction::containsSVG(const QString &str)
+{
+ if (!m_domDocument.setContent(str, true))
+ return false; // TODO error reporting
+
+ if (m_domDocument.documentElement().namespaceURI() == "http://www.w3.org/2000/svg")
+ return true;
+
+ return false;
+}
+
+QmlObjectNode SVGPasteAction::createQmlObjectNode(QmlDesigner::ModelNode &targetNode)
+{
+ const QDomElement rootElement = m_domDocument.documentElement();
+ if (rootElement.isNull()) {
+ qWarning() << Q_FUNC_INFO << "Couldn't create a root element.";
+ return {};
+ }
+
+ PropertyMap viewBoxProperties;
+ QRectF viewBox(0, 0, 100, 100);
+
+ if (rootElement.hasAttribute("viewBox")) {
+ // Replace all commas with whitespaces, if there are commas contained
+ const QString viewBoxStr = rootElement.attribute("viewBox").replace(",", " ").simplified();
+ const QStringList tmp = viewBoxStr.split(" ", Qt::SkipEmptyParts);
+
+ if (tmp.size() == 4) {
+ viewBox = QRectF(round(tmp[0].toFloat(), 2),
+ round(tmp[1].toFloat(), 2),
+ round(tmp[2].toFloat(), 2),
+ round(tmp[3].toFloat(), 2));
+ }
+ }
+
+ viewBoxProperties.insert("x", viewBox.x());
+ viewBoxProperties.insert("y", viewBox.y());
+ viewBoxProperties.insert("width", viewBox.width());
+ viewBoxProperties.insert("height", viewBox.height());
+
+ const QDomNode node = rootElement.firstChild();
+ std::vector<QDomElement> shapeElements;
+ CSSRules cssRules;
+
+ auto processStyleAndCollectShapes = [&](const QDomNode &node) {
+ QDomElement element = node.toElement();
+ if (!element.isNull()) {
+ if (element.tagName() == "style"/* && element.attribute("type") == "text/css"*/)
+ cssRules = parseCSS(element);
+
+ if (contains(tagAllowList, element.tagName()))
+ shapeElements.push_back(element);
+ }
+ };
+
+ depthFirstTraversal(node, processStyleAndCollectShapes);
+
+ viewBoxProperties.insert("clip", true);
+
+ ModelNode groupNode = createGroupNode(targetNode, viewBoxProperties);
+
+ for (const QDomElement &e : shapeElements) {
+ PropertyMap pathProperties;
+
+ if (e.tagName() == "path")
+ pathProperties = generatePathProperties(e, cssRules);
+ else if (e.tagName() == "rect")
+ pathProperties = generateRectProperties(e, cssRules);
+ else if (e.tagName() == "polygon")
+ pathProperties = generatePolygonProperties(e, cssRules);
+ else if (e.tagName() == "circle" || e.tagName() == "ellipse")
+ pathProperties = generateEllipseProperties(e, cssRules);
+
+ if (pathProperties.empty())
+ continue;
+
+ const QPointF topLeft = -viewBox.topLeft();
+
+ pathProperties["x"] = pathProperties["x"].toDouble() + topLeft.x();
+ pathProperties["y"] = pathProperties["y"].toDouble() + topLeft.y();
+
+ createPathNode(groupNode, pathProperties);
+ }
+
+ return groupNode;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/svgpasteaction.h b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.h
new file mode 100644
index 0000000000..0fc144369d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+#pragma once
+
+#include <qmlitemnode.h>
+
+#include <QDomDocument>
+
+namespace QmlDesigner {
+
+struct CSSProperty
+{
+ QString directive;
+ QString value;
+};
+
+using CSSRule = std::vector<CSSProperty>;
+using CSSRules = QHash<QString, CSSRule>;
+using PropertyMap = QHash<QByteArray, QVariant>;
+
+class SVGPasteAction
+{
+public:
+ SVGPasteAction();
+
+ bool containsSVG(const QString &str);
+
+ QmlObjectNode createQmlObjectNode(QmlDesigner::ModelNode &targetNode);
+
+private:
+ QDomDocument m_domDocument;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp
index 2659ffbbd7..4b5e217097 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp
@@ -51,9 +51,12 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <timelineactions.h>
+#include <svgpasteaction.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <utils/qtcassert.h>
+
#include <QFileInfo>
#include <QUrl>
#include <QDebug>
@@ -62,6 +65,7 @@
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QRandomGenerator>
+#include <QClipboard>
using namespace ProjectExplorer;
@@ -166,10 +170,46 @@ Model* DesignDocument::createInFileComponentModel()
{
Model *model = Model::create("QtQuick.Item", 1, 0);
model->setFileUrl(m_documentModel->fileUrl());
+ model->setMetaInfo(m_documentModel->metaInfo());
return model;
}
+bool DesignDocument::pasteSVG()
+{
+ SVGPasteAction svgPasteAction;
+
+ if (!svgPasteAction.containsSVG(QApplication::clipboard()->text()))
+ return false;
+
+ rewriterView()->executeInTransaction("DesignDocument::paste1", [&]() {
+ ModelNode targetNode;
+
+ // If nodes are currently selected make the first node in selection the target
+ if (!view()->selectedModelNodes().isEmpty())
+ targetNode = view()->firstSelectedModelNode();
+
+ // If target is still invalid make the root node the target
+ if (!targetNode.isValid())
+ targetNode = view()->rootModelNode();
+
+ // Check if document has studio components import, if not create it
+ QmlDesigner::Import import = QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
+ if (!currentModel()->hasImport(import, true, true)) {
+ QmlDesigner::Import studioComponentsImport = QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
+ try {
+ currentModel()->changeImports({studioComponentsImport}, {});
+ } catch (const QmlDesigner::Exception &) {
+ QTC_ASSERT(false, return);
+ }
+ }
+
+ svgPasteAction.createQmlObjectNode(targetNode);
+ });
+
+ return true;
+}
+
QList<DocumentMessage> DesignDocument::qmlParseWarnings() const
{
return m_rewriterView->warnings();
@@ -494,6 +534,9 @@ static void scatterItem(const ModelNode &pastedNode, const ModelNode &targetNode
void DesignDocument::paste()
{
+ if (pasteSVG())
+ return;
+
if (TimelineActions::clipboardContainsKeyframes()) // pasting keyframes is handled in TimelineView
return;
@@ -517,7 +560,7 @@ void DesignDocument::paste()
ModelNode targetNode;
if (!view.selectedModelNodes().isEmpty())
- targetNode = view.selectedModelNodes().constFirst();
+ targetNode = view.firstSelectedModelNode();
// in case we copy and paste a selection we paste in the parent item
if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.hasParentProperty()) {
@@ -571,7 +614,7 @@ void DesignDocument::paste()
ModelNode targetNode;
if (!view.selectedModelNodes().isEmpty()) {
- targetNode = view.selectedModelNodes().constFirst();
+ targetNode = view.firstSelectedModelNode();
} else {
// if selection is empty and this is a 3D Node, paste it under the active scene
if (pastedNode.isSubclassOf("QtQuick3D.Node")) {
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h
index 0d80f344de..ed2ef9ed11 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.h
+++ b/src/plugins/qmldesigner/components/integration/designdocument.h
@@ -145,6 +145,8 @@ private: // functions
Model *createInFileComponentModel();
+ bool pasteSVG();
+
private: // variables
QScopedPointer<Model> m_documentModel;
QScopedPointer<Model> m_inFileComponentModel;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h
index 641f987fc0..294a760a6b 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h
@@ -66,7 +66,6 @@ public:
static const QStringList &supportedAudioSuffixes();
static const QStringList &supportedTexture3DSuffixes();
- const QSet<QString> &supportedSuffixes() const;
const QSet<QString> &previewableSuffixes() const;
static void saveExpandedState(bool expanded, const QString &assetPath);
@@ -84,6 +83,8 @@ public:
Q_INVOKABLE void removeFile(const QString &filePath);
private:
+ const QSet<QString> &supportedSuffixes() const;
+
SynchronousImageCache &m_fontImageCache;
QHash<QString, QPair<QDateTime, QIcon>> m_iconCache;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 28b5d9fb94..fb4de1d84b 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -372,6 +372,18 @@ void ItemLibraryWidget::handleFilesDrop(const QStringList &filesPaths)
addResources(filesPaths);
}
+QSet<QString> ItemLibraryWidget::supportedDropSuffixes()
+{
+ const QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager()
+ .designerActionManager().addResourceHandler();
+
+ QSet<QString> suffixes;
+ for (const AddResourceHandler &handler : handlers)
+ suffixes.insert(handler.filter);
+
+ return suffixes;
+}
+
void ItemLibraryWidget::delayedUpdateModel()
{
static bool disableTimer = DesignerSettings::getValue(DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER).toBool();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
index 6695c01da5..5f631ae243 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -105,7 +105,7 @@ public:
Q_INVOKABLE void handleAddImport(int index);
Q_INVOKABLE bool isSearchActive() const;
Q_INVOKABLE void handleFilesDrop(const QStringList &filesPaths);
- Q_INVOKABLE QSet<QString> supportedSuffixes() const { return m_assetsModel->supportedSuffixes(); };
+ Q_INVOKABLE QSet<QString> supportedDropSuffixes();
signals:
void itemActivated(const QString& itemName);
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index 8a1e0b7abb..cb453a5756 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -88,6 +88,7 @@ public:
MetaInfo metaInfo();
NodeMetaInfo metaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1);
bool hasNodeMetaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1);
+ void setMetaInfo(const MetaInfo &metaInfo);
void attachView(AbstractView *view);
void detachView(AbstractView *view, ViewNotification emitDetachNotify = NotifyView);
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 44e804f25d..e3a4af0b75 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -179,6 +179,8 @@ public:
void sanitizeModel();
+ void setAllowComponentRoot(bool allow);
+ bool allowComponentRoot() const;
signals:
void modelInterfaceProjectUpdated();
@@ -221,6 +223,7 @@ private: //variables
bool m_hasIncompleteTypeInformation = false;
bool m_restoringAuxData = false;
bool m_modelAttachPending = false;
+ bool m_allowComponentRoot = false;
mutable QHash<int, ModelNode> m_canonicalIntModelNode;
mutable QHash<ModelNode, int> m_canonicalModelNodeInt;
diff --git a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h
index 58588542f7..2d144777a5 100644
--- a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h
+++ b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h
@@ -27,8 +27,6 @@
#include "connectionmanagerinterface.h"
-#include <QProcess>
-
#include <mutex>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp
index 7e0114bd8e..43ff7f48a2 100644
--- a/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp
@@ -26,7 +26,6 @@
#include "connectionmanagerinterface.h"
#include <QLocalSocket>
-#include <QProcess>
#include <QTimer>
namespace QmlDesigner {
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index e04d725b38..663af8f0f4 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -81,7 +81,6 @@
#include <QLocalSocket>
#include <QLoggingCategory>
#include <QMessageBox>
-#include <QProcess>
#include <QTextStream>
#include <QTimer>
#include <QUuid>
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
index 7233038b8e..566c201c9b 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
@@ -27,10 +27,9 @@
#include "nodeinstanceserverinterface.h"
-#include <QPointer>
-#include <QProcess>
#include <QElapsedTimer>
#include <QFile>
+#include <QPointer>
#include <QTimer>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetbuildprogressdialog.cpp b/src/plugins/qmldesigner/designercore/instances/puppetbuildprogressdialog.cpp
index 51d0242a1f..b2e455a44f 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetbuildprogressdialog.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetbuildprogressdialog.cpp
@@ -26,7 +26,6 @@
#include "puppetbuildprogressdialog.h"
#include "ui_puppetbuildprogressdialog.h"
-#include <QProcess>
#include <QtDebug>
#include <QApplication>
#include <coreplugin/icore.h>
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index 63185d8dfb..bc45647b60 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -494,7 +494,7 @@ void SubComponentManager::update(const QUrl &filePath, const QList<Import> &impo
if (!filePath.isEmpty()) {
const QString file = filePath.toLocalFile();
newDir = QFileInfo(QFileInfo(file).path());
- m_filePathDir = {newDir.absoluteFilePath()};
+ m_filePathDir.setPath(newDir.absoluteFilePath());
}
m_filePath = filePath;
diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp
index 42dbbdd2a0..f925522505 100644
--- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp
@@ -123,6 +123,9 @@ QTextDocument *ComponentTextModifier::textDocument() const
QString ComponentTextModifier::text() const
{
+ if (m_componentStartOffset == -1)
+ return {};
+
QString txt(m_originalModifier->text());
const int leader = m_componentStartOffset - m_rootStartOffset;
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index eda7b13c5c..5f211b8605 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -1606,6 +1606,11 @@ bool Model::hasNodeMetaInfo(const TypeName &typeName, int majorVersion, int mino
return metaInfo(typeName, majorVersion, minorVersion).isValid();
}
+void Model::setMetaInfo(const MetaInfo &metaInfo)
+{
+ d->setMetaInfo(metaInfo);
+}
+
NodeMetaInfo Model::metaInfo(const TypeName &typeName, int majorVersion, int minorVersion)
{
return NodeMetaInfo(metaInfoProxyModel(), typeName, majorVersion, minorVersion);
diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
index f26c32ad78..a580ee5549 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
@@ -249,6 +249,7 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view,
QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, nullptr));
rewriterView->setCheckSemanticErrors(false);
rewriterView->setTextModifier(&modifier);
+ rewriterView->setAllowComponentRoot(true);
inputModel->setRewriterView(rewriterView.data());
if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index 84b3678f5d..051c449e21 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -704,6 +704,16 @@ void RewriterView::sanitizeModel()
});
}
+void RewriterView::setAllowComponentRoot(bool allow)
+{
+ m_allowComponentRoot = allow;
+}
+
+bool RewriterView::allowComponentRoot() const
+{
+ return m_allowComponentRoot;
+}
+
Internal::ModelNodePositionStorage *RewriterView::positionStorage() const
{
return m_positionStorage.data();
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 3f6a04fde4..49845ab13f 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -1044,6 +1044,15 @@ void TextToModelMerger::setupUsedImports()
Document::MutablePtr TextToModelMerger::createParsedDocument(const QUrl &url, const QString &data, QList<DocumentMessage> *errors)
{
+ if (data.isEmpty()) {
+ if (errors) {
+ QmlJS::DiagnosticMessage msg;
+ msg.message = QObject::tr("Empty document");
+ errors->append(DocumentMessage(msg, url));
+ }
+ return {};
+ }
+
const QString fileName = url.toLocalFile();
Dialect dialect = ModelManagerInterface::guessLanguageOfFile(fileName);
@@ -1200,7 +1209,7 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
return;
}
- if (modelNode.isRootNode() && isComponentType(typeName)) {
+ if (modelNode.isRootNode() && !m_rewriterView->allowComponentRoot() && isComponentType(typeName)) {
for (AST::UiObjectMemberList *iter = astInitializer->members; iter; iter = iter->next) {
if (auto def = AST::cast<AST::UiObjectDefinition *>(iter->member)) {
syncNode(modelNode, def, context, differenceHandler);
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pro b/src/plugins/qmldesigner/qmldesignerplugin.pro
index 41e7568ff7..78fe856fb0 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.pro
+++ b/src/plugins/qmldesigner/qmldesignerplugin.pro
@@ -1,4 +1,4 @@
-QT += quickwidgets core-private
+QT += quickwidgets core-private xml svg
CONFIG += exceptions
INCLUDEPATH += $$PWD
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index 2ff2d3cb2b..80b54747a6 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -10,7 +10,7 @@ Project {
Depends {
name: "Qt";
submodules: [
- "core-private", "quickwidgets"
+ "core-private", "quickwidgets", "xml", "svg"
]
}
Depends { name: "AdvancedDockingSystem" }
@@ -482,6 +482,8 @@ Project {
"componentcore/zoomaction.h",
"componentcore/hdrimage.cpp",
"componentcore/hdrimage.h",
+ "componentcore/svgpasteaction.cpp",
+ "componentcore/svgpasteaction.h",
"texteditor/texteditorstatusbar.cpp",
"texteditor/texteditorstatusbar.h",
"componentcore/changestyleaction.cpp",
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-16px.png
new file mode 100644
index 0000000000..d9fd2f57bf
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-24px.png
new file mode 100644
index 0000000000..9e477c806d
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-24px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-24px@2x.png
new file mode 100644
index 0000000000..41948718fd
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-24px@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-output-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-16px.png
new file mode 100644
index 0000000000..6ae703de64
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px.png
new file mode 100644
index 0000000000..f2133ca716
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px@2x.png
new file mode 100644
index 0000000000..9336b81b6e
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/audio-output-24px@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/media-player-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/media-player-16px.png
new file mode 100644
index 0000000000..515287a846
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/media-player-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px.png
new file mode 100644
index 0000000000..1b31ddc826
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px@2x.png
new file mode 100644
index 0000000000..86ae5914ac
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/media-player-24px@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/video-16px.png
new file mode 100644
index 0000000000..caf9c16a61
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/video-24px.png
new file mode 100644
index 0000000000..df1b84e5c9
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-24px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/video-24px@2x.png
new file mode 100644
index 0000000000..4b9f31faf3
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-24px@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-output-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/video-output-16px.png
new file mode 100644
index 0000000000..f00afc52e9
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-output-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px.png
new file mode 100644
index 0000000000..fd3c89c081
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px@2x.png
new file mode 100644
index 0000000000..0f651a1013
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/images/video-output-24px@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc
index 8adfb84baf..af2ff0ff41 100644
--- a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc
+++ b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc
@@ -31,6 +31,7 @@
<file>images/text-edit-icon16.png</file>
<file>images/text-input-icon16.png</file>
<file>images/webview-icon16.png</file>
+ <file>source/audio.qml</file>
<file>source/listview.qml</file>
<file>source/listviewv2.qml</file>
<file>source/gridview.qml</file>
@@ -43,6 +44,8 @@
<file>source/texteditv2.qml</file>
<file>source/textinput.qml</file>
<file>source/textinputv2.qml</file>
+ <file>source/component.qml</file>
+ <file>source/component3d.qml</file>
<file>images/column-positioner-icon.png</file>
<file>images/column-positioner-icon-16px.png</file>
<file>images/default-icon.png</file>
@@ -81,5 +84,20 @@
<file>images/loader-icon.png</file>
<file>images/loader-icon@2x.png</file>
<file>images/loader-icon16.png</file>
+ <file>images/audio-16px.png</file>
+ <file>images/audio-24px.png</file>
+ <file>images/audio-24px@2x.png</file>
+ <file>images/audio-output-16px.png</file>
+ <file>images/audio-output-24px.png</file>
+ <file>images/audio-output-24px@2x.png</file>
+ <file>images/media-player-16px.png</file>
+ <file>images/media-player-24px.png</file>
+ <file>images/media-player-24px@2x.png</file>
+ <file>images/video-16px.png</file>
+ <file>images/video-24px.png</file>
+ <file>images/video-24px@2x.png</file>
+ <file>images/video-output-16px.png</file>
+ <file>images/video-output-24px.png</file>
+ <file>images/video-output-24px@2x.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
index 851d457cdc..7858ca08ea 100644
--- a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
+++ b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
@@ -446,6 +446,28 @@ MetaInfo {
category: "e.Qt Quick - Component"
libraryIcon: ":/qtquickplugin/images/component-icon.png"
version: "2.0"
+
+ QmlSource { source: ":/qtquickplugin/source/component.qml" }
+ }
+ }
+
+ Type {
+ name: "QtQml.Component"
+ icon: ":/qtquickplugin/images/component-icon16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Component 3D"
+ category: "Qt Quick 3D Component"
+ libraryIcon: ":/qtquickplugin/images/component-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick3D"
+
+ QmlSource { source: ":/qtquickplugin/source/component3d.qml" }
}
}
@@ -479,4 +501,89 @@ MetaInfo {
version: "2.0"
}
}
+
+ Type {
+ name: "QtMultimedia.MediaPlayer"
+ icon: ":/qtquickplugin/images/media-player-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Media Player"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: ":/qtquickplugin/images/media-player-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.MediaPlayer"
+ icon: ":/qtquickplugin/images/audio-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Audio"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: ":/qtquickplugin/images/audio-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+
+ QmlSource { source: ":/qtquickplugin/source/audio.qml" }
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.AudioOutput"
+ icon: ":/qtquickplugin/images/audio-output-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Audio Output"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: ":/qtquickplugin/images/audio-output-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.Video"
+ icon: ":/qtquickplugin/images/video-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: true
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Video"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: ":/qtquickplugin/images/video-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+
+ Property { name: "width"; type: "int"; value: 200; }
+ Property { name: "height"; type: "int"; value: 200; }
+ }
+ }
}
diff --git a/src/plugins/qmldesigner/qtquickplugin/source/audio.qml b/src/plugins/qmldesigner/qtquickplugin/source/audio.qml
new file mode 100644
index 0000000000..b3d1347e85
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/source/audio.qml
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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 QtMultimedia 6.0
+
+MediaPlayer {
+ audioOutput: output
+
+ AudioOutput {
+ id: output
+ }
+}
diff --git a/src/plugins/qmldesigner/qtquickplugin/source/component.qml b/src/plugins/qmldesigner/qtquickplugin/source/component.qml
new file mode 100644
index 0000000000..1a3b2770bb
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/source/component.qml
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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
+
+Component {
+ Item {
+ id: componentRoot
+ width: 100
+ height: 100
+ }
+}
diff --git a/src/plugins/qmldesigner/qtquickplugin/source/component3d.qml b/src/plugins/qmldesigner/qtquickplugin/source/component3d.qml
new file mode 100644
index 0000000000..474497e54b
--- /dev/null
+++ b/src/plugins/qmldesigner/qtquickplugin/source/component3d.qml
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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 6.0
+
+Component {
+ Node {
+ id: componentRoot
+ }
+}
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index 4275f4e341..61e943824a 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -2274,6 +2274,8 @@ static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &pr
flavor = Abi::WindowsMsvc2017Flavor;
} else if (compiler.startsWith("MSVC 2019") && os == Abi::WindowsOS) {
flavor = Abi::WindowsMsvc2019Flavor;
+ } else if (compiler.startsWith("MSVC 2022") && os == Abi::WindowsOS) {
+ flavor = Abi::WindowsMsvc2022Flavor;
}
return Abi(arch, os, flavor, format, wordWidth);
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.h b/src/plugins/qtsupport/qscxmlcgenerator.h
index 99f7234af3..7ab98b3ad7 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.h
+++ b/src/plugins/qtsupport/qscxmlcgenerator.h
@@ -29,8 +29,6 @@
#include <utils/fileutils.h>
#include <utils/temporarydirectory.h>
-#include <QProcess>
-
namespace QtSupport {
class QScxmlcGenerator : public ProjectExplorer::ProcessExtraCompiler
diff --git a/src/plugins/qtsupport/uicgenerator.h b/src/plugins/qtsupport/uicgenerator.h
index 37c3a273b0..b879e3d326 100644
--- a/src/plugins/qtsupport/uicgenerator.h
+++ b/src/plugins/qtsupport/uicgenerator.h
@@ -28,8 +28,6 @@
#include <projectexplorer/extracompiler.h>
#include <utils/fileutils.h>
-#include <QProcess>
-
namespace QtSupport {
class UicGenerator : public ProjectExplorer::ProcessExtraCompiler
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index a54732ec39..59ac0bba32 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -5245,6 +5245,14 @@ void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
return;
QPlainTextEdit::mouseReleaseEvent(e);
+
+ d->setClipboardSelection();
+ const QTextCursor plainTextEditCursor = textCursor();
+ const QTextCursor multiMainCursor = multiTextCursor().mainCursor();
+ if (multiMainCursor.position() != plainTextEditCursor.position()
+ || multiMainCursor.anchor() != plainTextEditCursor.anchor()) {
+ doSetTextCursor(plainTextEditCursor, true);
+ }
}
void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index ecbb5ea37c..9339d2ffd6 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -41,15 +41,11 @@
#include <vcsbase/vcsoutputwindow.h>
#include <vcsbase/vcsbaseplugin.h>
-#include <QStringList>
-#include <QDir>
-#include <QProcess>
-#include <QTextCodec>
#include <QDebug>
#include <QFileInfo>
-#include <QByteArray>
+#include <QStringList>
+#include <QTextCodec>
#include <QVariant>
-#include <QProcessEnvironment>
using namespace Utils;
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 38f233502e32112e15179420da86d6e6afb79b2
+Subproject ae937f07673aa95b67218e4be36a38e4438c017
diff --git a/src/src.qbs b/src/src.qbs
index 4f8db24ca9..8d50dafdc1 100644
--- a/src/src.qbs
+++ b/src/src.qbs
@@ -34,6 +34,7 @@ Project {
qbsBaseDir + "/src/app/apps.qbs",
qbsBaseDir + "/src/shared/bundledqt/bundledqt.qbs",
qbsBaseDir + "/src/shared/json/json.qbs",
+ qbsBaseDir + "/src/shared/variant/variant.qbs",
]
}
}
diff --git a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
index 2ad9eba89d..ac0bf2f862 100644
--- a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
+++ b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp
@@ -65,6 +65,7 @@ const char kBlockingProcess[] = "QTC_TST_BLOCKING_PROCESS";
// the recursion, as from the test point of view we meant to execute only our custom code
// without further execution of the test itself.
+const char testProcessData[] = "Test process successfully executed.";
const char forwardedOutputData[] = "This is the output message.";
const char forwardedErrorData[] = "This is the error message.";
const char runBlockingStdOutSubProcessMagicWord[] = "42";
@@ -108,7 +109,7 @@ static void lineCallbackMain()
static void testProcessSubProcessMain()
{
- std::cout << "Test process successfully executed." << std::endl;
+ std::cout << testProcessData << std::endl;
exit(0);
}
@@ -207,6 +208,7 @@ private slots:
void processChannelForwarding_data();
void processChannelForwarding();
void killBlockingProcess();
+ void flushFinishedWhileWaitingForReadyRead();
void cleanupTestCase();
@@ -1175,6 +1177,36 @@ void tst_QtcProcess::killBlockingProcess()
QVERIFY(msgHandler.testPassed());
}
+void tst_QtcProcess::flushFinishedWhileWaitingForReadyRead()
+{
+ Environment env = Environment::systemEnvironment();
+ env.set(kTestProcess, {});
+ QStringList args = QCoreApplication::arguments();
+ const QString binary = args.takeFirst();
+ const CommandLine command(FilePath::fromString(binary), args);
+
+ QtcProcess process;
+ process.setCommand(command);
+ process.setEnvironment(env);
+ process.start();
+
+ QVERIFY(process.waitForStarted());
+ QCOMPARE(process.state(), QProcess::Running);
+
+ QDeadlineTimer timer(1000);
+ QByteArray reply;
+ while (process.state() == QProcess::Running) {
+ process.waitForReadyRead(500);
+ reply += process.readAllStandardOutput();
+ if (timer.hasExpired())
+ break;
+ }
+
+ QCOMPARE(process.state(), QProcess::NotRunning);
+ QVERIFY(!timer.hasExpired());
+ QVERIFY(reply.contains(testProcessData));
+}
+
QTEST_MAIN(tst_QtcProcess)
#include "tst_qtcprocess.moc"
diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py
index 9468ac4f8a..7237e00aae 100644
--- a/tests/system/suite_debugger/tst_simple_debug/test.py
+++ b/tests/system/suite_debugger/tst_simple_debug/test.py
@@ -51,8 +51,9 @@ def main():
expectedBreakpointsOrder = setBreakpointsForCurrentProject(filesAndLines)
if expectedBreakpointsOrder:
availableConfigs = iterateBuildConfigs("Debug")
- progressBarWait()
- if not availableConfigs:
+ if len(availableConfigs) > 1: # having just one config means no change, no progress bar
+ progressBarWait()
+ elif len(availableConfigs) == 0:
test.fatal("Haven't found a suitable Qt version - leaving without debugging.")
for kit, config in availableConfigs:
test.log("Selecting '%s' as build config" % config)
diff --git a/tests/unit/unittest/clientserveroutsideprocess-test.cpp b/tests/unit/unittest/clientserveroutsideprocess-test.cpp
index c2231614e7..75e838c8a6 100644
--- a/tests/unit/unittest/clientserveroutsideprocess-test.cpp
+++ b/tests/unit/unittest/clientserveroutsideprocess-test.cpp
@@ -35,7 +35,6 @@
#include <utils/hostosinfo.h>
#include <QBuffer>
-#include <QProcess>
#include <QSignalSpy>
#include <QString>
#include <QVariant>