Merge remote-tracking branch 'origin/6.0'

Change-Id: If773f217a9708ce0ad0b8adeefe3266ba0371a32
This commit is contained in:
Eike Ziller
2021-09-29 12:54:38 +02:00
134 changed files with 1422 additions and 1037 deletions

70
dist/changes-5.0.2.md vendored Normal file
View File

@@ -0,0 +1,70 @@
Qt Creator 5.0.2
================
Qt Creator version 5.0.2 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.1..v5.0.2
Help
----
* Fixed that Qt 5 context help was shown even if Qt 6 documentation is available
(QTCREATORBUG-26292)
Projects
--------
* Fixed canceling of builds (QTCREATORBUG-26271)
### CMake
* Changed the `File System` special node to be shown only on parsing failure
(QTCREATORBUG-25994, QTCREATORBUG-25974)
* Fixed loading of projects without targets (QTCREATORBUG-25509)
* Fixed that no targets where shown in added build step (QTCREATORBUG-25759)
* Fixed that `ninja` could not be found after changing Qt installation location
(QTCREATORBUG-26289)
Debugging
---------
### GDB
* Fixed debugging of terminal applications with GDB < 10 (QTCREATORBUG-26299)
Platforms
---------
### macOS
* Fixed issue with absolute RPATH in `clazy-standalone` (QTCREATORBUG-26196)
### Android
* Fixed that wrong deployment file could be used (QTCREATORBUG-25793)
Credits for these changes go to:
--------------------------------
Alessandro Portale
Assam Boudjelthia
Christian Kandeler
Christian Stenger
Cristian Adam
Eike Ziller
Henning Gruendl
Ivan Komissarov
Jaroslaw Kobus
Johanna Vanhatapio
Kai Köhne
Knud Dollereder
Leena Miettinen
Mahmoud Badri
Marco Bubke
Orgad Shaneh
Robert Löhning
Thomas Hartmann

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 677 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Auto Test Project", "trDisplayName": "Auto Test Project",
"trDisplayCategory": "Other Project", "trDisplayCategory": "Other Project",
"icon": "autotest.png", "icon": "autotest.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureDesktop" ], "featuresRequired": [ "QtSupport.Wizards.FeatureDesktop" ],
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Python Class", "trDisplayName": "Python Class",
"trDisplayCategory": "Python", "trDisplayCategory": "Python",
"icon": "../../files/python/icon.png", "icon": "../../files/python/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": "options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Nim File", "trDisplayName": "Nim File",
"trDisplayCategory": "Nim", "trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png", "icon": "../../projects/nim/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"options": { "key": "DefaultSuffix", "value": "nim" }, "options": { "key": "DefaultSuffix", "value": "nim" },

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Nim Script File", "trDisplayName": "Nim Script File",
"trDisplayCategory": "Nim", "trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png", "icon": "../../projects/nim/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"options": { "key": "DefaultSuffix", "value": "nims" }, "options": { "key": "DefaultSuffix", "value": "nims" },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 592 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Python File", "trDisplayName": "Python File",
"trDisplayCategory": "Python", "trDisplayCategory": "Python",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-python')}" }, "options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-python')}" },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 B

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Console Application", "trDisplayName": "Qt Console Application",
"trDisplayCategory": "Application (Qt)", "trDisplayCategory": "Application (Qt)",
"icon": "../../global/consoleapplication.png", "icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}",

View File

@@ -7,6 +7,7 @@
"trDisplayName": "C++ Library", "trDisplayName": "C++ Library",
"trDisplayCategory": "Library", "trDisplayCategory": "Library",
"icon": "../../global/lib.png", "icon": "../../global/lib.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}", "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -8,6 +8,7 @@
"trDisplayCategory": "Non-Qt Project", "trDisplayCategory": "Non-Qt Project",
"featuresRequired": [ "ToolChain.Nim.NimToolChain" ], "featuresRequired": [ "ToolChain.Nim.NimToolChain" ],
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0 }", "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options": "options":

View File

@@ -10,6 +10,7 @@
"ToolChain.Nim.NimToolChain" "ToolChain.Nim.NimToolChain"
], ],
"icon":"../nim/icon.png", "icon":"../nim/icon.png",
"iconKind": "Themed",
"enabled":"%{JS: value('Plugins').indexOf('Nim') >= 0 }", "enabled":"%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options":[ "options":[
{ {

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Plain C Application", "trDisplayName": "Plain C Application",
"trDisplayCategory": "Non-Qt Project", "trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png", "icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}", "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options": "options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Plain C++ Application", "trDisplayName": "Plain C++ Application",
"trDisplayCategory": "Non-Qt Project", "trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png", "icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}", "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options": "options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Empty qmake Project", "trDisplayName": "Empty qmake Project",
"trDisplayCategory": "Other Project", "trDisplayCategory": "Other Project",
"icon": "../../../global/guiapplication.png", "icon": "../../../global/guiapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Empty", "trDisplayName": "Qt for Python - Empty",
"trDisplayCategory": "Application (Qt for Python)", "trDisplayCategory": "Application (Qt for Python)",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 B

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 849 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Window", "trDisplayName": "Qt for Python - Window",
"trDisplayCategory": "Application (Qt for Python)", "trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png", "icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": "options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Qt Quick Application - Empty", "trDisplayName": "Qt for Python - Qt Quick Application - Empty",
"trDisplayCategory": "Application (Qt for Python)", "trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png", "icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": "options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Window (UI file)", "trDisplayName": "Qt for Python - Window (UI file)",
"trDisplayCategory": "Application (Qt for Python)", "trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png", "icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick 2 Extension Plugin", "trDisplayName": "Qt Quick 2 Extension Plugin",
"trDisplayCategory": "Library", "trDisplayCategory": "Library",
"icon": "lib.png", "icon": "lib.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick", "QtSupport.Wizards.FeatureQtQuick.2" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick", "QtSupport.Wizards.FeatureQtQuick.2" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick Application", "trDisplayName": "Qt Quick Application",
"trDisplayCategory": "Application (Qt)", "trDisplayCategory": "Application (Qt)",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick UI Prototype", "trDisplayName": "Qt Quick UI Prototype",
"trDisplayCategory": "Other Project", "trDisplayCategory": "Other Project",
"icon": "qtquickuiprototype.png", "icon": "qtquickuiprototype.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Widgets Application", "trDisplayName": "Qt Widgets Application",
"trDisplayCategory": "Application (Qt)", "trDisplayCategory": "Application (Qt)",
"icon": "../../global/guiapplication.png", "icon": "../../global/guiapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Bazaar Clone (Or Branch)", "trDisplayName": "Bazaar Clone (Or Branch)",
"trDisplayCategory": "Import Project", "trDisplayCategory": "Import Project",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Bazaar') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Bazaar') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "CVS Checkout", "trDisplayName": "CVS Checkout",
"trDisplayCategory": "Import Project", "trDisplayCategory": "Import Project",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CVS') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('CVS') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Git Clone", "trDisplayName": "Git Clone",
"trDisplayCategory": "Import Project", "trDisplayCategory": "Import Project",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Git') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Git') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Mercurial Clone", "trDisplayName": "Mercurial Clone",
"trDisplayCategory": "Import Project", "trDisplayCategory": "Import Project",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Mercurial') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Mercurial') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Subversion Checkout", "trDisplayName": "Subversion Checkout",
"trDisplayCategory": "Import Project", "trDisplayCategory": "Import Project",
"icon": "icon.png", "icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Subversion') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('Subversion') >= 0}",
"options": "options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Creator Plugin", "trDisplayName": "Qt Creator Plugin",
"trDisplayCategory": "Library", "trDisplayCategory": "Library",
"icon": "qtcreatorplugin.png", "icon": "qtcreatorplugin.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt", "QtSupport.Wizards.FeatureDesktop" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt", "QtSupport.Wizards.FeatureDesktop" ],
"enabled": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}", "enabled": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}",

View File

@@ -12,7 +12,7 @@ install(
add_qtc_executable(qtcreator add_qtc_executable(qtcreator
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\" DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils QtcSsh shared_qtsingleapplication app_version DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils shared_qtsingleapplication app_version
SOURCES SOURCES
main.cpp main.cpp
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h

View File

@@ -17,7 +17,7 @@ include(../rpath.pri)
include(../libs/qt-breakpad/qtbreakpad.pri) include(../libs/qt-breakpad/qtbreakpad.pri)
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils) -l$$qtLibraryName(QtcSsh) LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
win32 { win32 {
# We need the version in two separate formats for the .rc file # We need the version in two separate formats for the .rc file

View File

@@ -46,7 +46,6 @@ QtcProduct {
Depends { name: "app_version_header" } Depends { name: "app_version_header" }
Depends { name: "Qt"; submodules: ["widgets", "network"] } Depends { name: "Qt"; submodules: ["widgets", "network"] }
Depends { name: "Utils" } Depends { name: "Utils" }
Depends { name: "QtcSsh" }
Depends { name: "ExtensionSystem" } Depends { name: "ExtensionSystem" }
files: [ files: [

View File

@@ -32,16 +32,13 @@
#include <extensionsystem/pluginspec.h> #include <extensionsystem/pluginspec.h>
#include <qtsingleapplication.h> #include <qtsingleapplication.h>
#include <ssh/sshconnectionmanager.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/launcherinterface.h>
#include <utils/optional.h> #include <utils/optional.h>
#include <utils/processreaper.h>
#include <utils/qtcsettings.h> #include <utils/qtcsettings.h>
#include <utils/singleton.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <QDebug> #include <QDebug>
@@ -537,10 +534,7 @@ int main(int argc, char **argv)
QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)); QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR));
QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME); QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
Utils::ProcessReaper processReaper; auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); });
Utils::LauncherInterface::startLauncher();
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
QSsh::SshConnectionManager sshConnectionManager;
const QStringList pluginArguments = app.arguments(); const QStringList pluginArguments = app.arguments();

View File

@@ -53,16 +53,11 @@ bool operator!=(const UnacquiredConnection &c1, const UnacquiredConnection &c2)
return !(c1 == c2); return !(c1 == c2);
} }
static class SshConnectionManagerPrivate *s_instance = nullptr;
class SshConnectionManagerPrivate : public QObject class SshConnectionManagerPrivate : public QObject
{ {
public: public:
SshConnectionManagerPrivate() SshConnectionManagerPrivate()
{ {
QTC_ASSERT(s_instance == nullptr, return);
s_instance = this;
connect(&m_removalTimer, &QTimer::timeout, connect(&m_removalTimer, &QTimer::timeout,
this, &SshConnectionManagerPrivate::removeInactiveConnections); this, &SshConnectionManagerPrivate::removeInactiveConnections);
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2); m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
@@ -70,8 +65,6 @@ public:
~SshConnectionManagerPrivate() override ~SshConnectionManagerPrivate() override
{ {
QTC_ASSERT(s_instance == this, return);
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) { for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
disconnect(connection.connection, nullptr, this, nullptr); disconnect(connection.connection, nullptr, this, nullptr);
delete connection.connection; delete connection.connection;
@@ -79,8 +72,6 @@ public:
QTC_CHECK(m_acquiredConnections.isEmpty()); QTC_CHECK(m_acquiredConnections.isEmpty());
QTC_CHECK(m_deprecatedConnections.isEmpty()); QTC_CHECK(m_deprecatedConnections.isEmpty());
s_instance = nullptr;
} }
SshConnection *acquireConnection(const SshConnectionParameters &sshParams) SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
@@ -213,6 +204,7 @@ private:
SshConnectionManager::SshConnectionManager() SshConnectionManager::SshConnectionManager()
: d(new Internal::SshConnectionManagerPrivate()) : d(new Internal::SshConnectionManagerPrivate())
{ {
QTC_CHECK(QThread::currentThread() == qApp->thread());
} }
SshConnectionManager::~SshConnectionManager() SshConnectionManager::~SshConnectionManager()
@@ -222,20 +214,17 @@ SshConnectionManager::~SshConnectionManager()
SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams) SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
{ {
QTC_ASSERT(Internal::s_instance, return nullptr); return instance()->d->acquireConnection(sshParams);
return Internal::s_instance->acquireConnection(sshParams);
} }
void SshConnectionManager::releaseConnection(SshConnection *connection) void SshConnectionManager::releaseConnection(SshConnection *connection)
{ {
QTC_ASSERT(Internal::s_instance, return); instance()->d->releaseConnection(connection);
Internal::s_instance->releaseConnection(connection);
} }
void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams) void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
{ {
QTC_ASSERT(Internal::s_instance, return); instance()->d->forceNewConnection(sshParams);
Internal::s_instance->forceNewConnection(sshParams);
} }
} // namespace QSsh } // namespace QSsh

View File

@@ -27,6 +27,9 @@
#include "ssh_global.h" #include "ssh_global.h"
#include <utils/launcherinterface.h>
#include <utils/singleton.h>
namespace QSsh { namespace QSsh {
class SshConnection; class SshConnection;
@@ -35,18 +38,21 @@ class SshConnectionParameters;
namespace Internal { class SshConnectionManagerPrivate; } namespace Internal { class SshConnectionManagerPrivate; }
class QSSH_EXPORT SshConnectionManager final class QSSH_EXPORT SshConnectionManager final
: public Utils::SingletonWithOptionalDependencies<SshConnectionManager,
Utils::LauncherInterface>
{ {
public: public:
SshConnectionManager();
~SshConnectionManager();
static SshConnection *acquireConnection(const SshConnectionParameters &sshParams); static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
static void releaseConnection(SshConnection *connection); static void releaseConnection(SshConnection *connection);
// Make sure the next acquireConnection with the given parameters will return a new connection. // Make sure the next acquireConnection with the given parameters will return a new connection.
static void forceNewConnection(const SshConnectionParameters &sshParams); static void forceNewConnection(const SshConnectionParameters &sshParams);
private: private:
SshConnectionManager();
~SshConnectionManager();
Internal::SshConnectionManagerPrivate *d; Internal::SshConnectionManagerPrivate *d;
friend class Utils::SingletonWithOptionalDependencies<SshConnectionManager, Utils::LauncherInterface>;
}; };
} // namespace QSsh } // namespace QSsh

View File

@@ -144,6 +144,7 @@ add_qtc_library(Utils
settingsutils.h settingsutils.h
shellcommand.cpp shellcommand.h shellcommand.cpp shellcommand.h
shellcommandpage.cpp shellcommandpage.h shellcommandpage.cpp shellcommandpage.h
singleton.cpp singleton.h
sizedarray.h sizedarray.h
smallstring.h smallstring.h
smallstringfwd.h smallstringfwd.h

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 241 B

View File

@@ -28,7 +28,6 @@
#include "filepath.h" #include "filepath.h"
#include "launcherpackets.h" #include "launcherpackets.h"
#include "launchersocket.h" #include "launchersocket.h"
#include "processreaper.h"
#include "qtcassert.h" #include "qtcassert.h"
#include <QCoreApplication> #include <QCoreApplication>
@@ -42,7 +41,6 @@
#endif #endif
namespace Utils { namespace Utils {
namespace Internal { namespace Internal {
class LauncherProcess : public QProcess class LauncherProcess : public QProcess
@@ -185,92 +183,73 @@ void LauncherInterfacePrivate::handleProcessStderr()
using namespace Utils::Internal; using namespace Utils::Internal;
static QMutex s_instanceMutex; static QMutex s_instanceMutex;
static LauncherInterface *s_instance = nullptr; static QString s_pathToLauncher;
static std::atomic_bool s_started = false;
LauncherInterface::LauncherInterface() LauncherInterface::LauncherInterface()
: m_private(new LauncherInterfacePrivate()) : m_private(new LauncherInterfacePrivate())
{ {
m_private->moveToThread(&m_thread); m_private->moveToThread(&m_thread);
connect(m_private, &LauncherInterfacePrivate::errorOccurred, QObject::connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
this, &LauncherInterface::errorOccurred);
connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
m_thread.start(); m_thread.start();
} m_thread.moveToThread(qApp->thread());
LauncherInterface::~LauncherInterface() m_private->setPathToLauncher(s_pathToLauncher);
{ const FilePath launcherFilePath = FilePath::fromString(m_private->launcherFilePath())
m_thread.quit();
m_thread.wait();
}
// Called from main thread
void LauncherInterface::startLauncher(const QString &pathToLauncher)
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance == nullptr, return);
s_instance = new LauncherInterface();
LauncherInterfacePrivate *p = s_instance->m_private;
p->setPathToLauncher(pathToLauncher);
const FilePath launcherFilePath = FilePath::fromString(p->launcherFilePath())
.cleanPath().withExecutableSuffix(); .cleanPath().withExecutableSuffix();
auto launcherIsNotExecutable = [&launcherFilePath]() { auto launcherIsNotExecutable = [&launcherFilePath]() {
qWarning() << "The Creator's process launcher" qWarning() << "The Creator's process launcher"
<< launcherFilePath << "is not executable."; << launcherFilePath << "is not executable.";
}; };
QTC_ASSERT(launcherFilePath.isExecutableFile(), launcherIsNotExecutable(); return); QTC_ASSERT(launcherFilePath.isExecutableFile(), launcherIsNotExecutable(); return);
s_started = true;
// Call in launcher's thread. // Call in launcher's thread.
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStart); QMetaObject::invokeMethod(m_private, &LauncherInterfacePrivate::doStart);
} }
// Called from main thread LauncherInterface::~LauncherInterface()
void LauncherInterface::stopLauncher()
{ {
QMutexLocker locker(&s_instanceMutex); QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return); LauncherInterfacePrivate *p = instance()->m_private;
LauncherInterfacePrivate *p = s_instance->m_private;
// Call in launcher's thread. // Call in launcher's thread.
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStop, Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStop, Qt::BlockingQueuedConnection);
delete s_instance; m_thread.quit();
s_instance = nullptr; m_thread.wait();
}
void LauncherInterface::setPathToLauncher(const QString &pathToLauncher)
{
s_pathToLauncher = pathToLauncher;
} }
bool LauncherInterface::isStarted() bool LauncherInterface::isStarted()
{ {
QMutexLocker locker(&s_instanceMutex); return s_started;
return s_instance != nullptr;
} }
bool LauncherInterface::isReady() bool LauncherInterface::isReady()
{ {
QMutexLocker locker(&s_instanceMutex); QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return false); return instance()->m_private->socket()->isReady();
return s_instance->m_private->socket()->isReady();
} }
void LauncherInterface::sendData(const QByteArray &data) void LauncherInterface::sendData(const QByteArray &data)
{ {
QMutexLocker locker(&s_instanceMutex); QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return); instance()->m_private->socket()->sendData(data);
s_instance->m_private->socket()->sendData(data);
} }
Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token, Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token,
ProcessMode mode) ProcessMode mode)
{ {
QMutexLocker locker(&s_instanceMutex); QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return nullptr); return instance()->m_private->socket()->registerHandle(parent, token, mode);
return s_instance->m_private->socket()->registerHandle(parent, token, mode);
} }
void LauncherInterface::unregisterHandle(quintptr token) void LauncherInterface::unregisterHandle(quintptr token)
{ {
QMutexLocker locker(&s_instanceMutex); QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return); instance()->m_private->socket()->unregisterHandle(token);
s_instance->m_private->socket()->unregisterHandle(token);
} }
} // namespace Utils } // namespace Utils

View File

@@ -27,9 +27,10 @@
#include "utils_global.h" #include "utils_global.h"
#include "processreaper.h"
#include "processutils.h" #include "processutils.h"
#include "singleton.h"
#include <QObject>
#include <QThread> #include <QThread>
namespace Utils { namespace Utils {
@@ -40,15 +41,11 @@ class LauncherInterfacePrivate;
class ProcessLauncherImpl; class ProcessLauncherImpl;
} }
class QTCREATOR_UTILS_EXPORT LauncherInterface : public QObject class QTCREATOR_UTILS_EXPORT LauncherInterface final
: public SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>
{ {
Q_OBJECT
public: public:
static void startLauncher(const QString &pathToLauncher = {}); static void setPathToLauncher(const QString &pathToLauncher);
static void stopLauncher();
signals:
void errorOccurred(const QString &error);
private: private:
friend class Utils::Internal::CallerHandle; friend class Utils::Internal::CallerHandle;
@@ -63,10 +60,11 @@ private:
static void unregisterHandle(quintptr token); static void unregisterHandle(quintptr token);
LauncherInterface(); LauncherInterface();
~LauncherInterface() override; ~LauncherInterface();
QThread m_thread; QThread m_thread;
Internal::LauncherInterfacePrivate *m_private; Internal::LauncherInterfacePrivate *m_private;
friend class SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -36,8 +36,6 @@ using namespace Utils;
namespace Utils { namespace Utils {
namespace Internal { namespace Internal {
static ProcessReaper *d = nullptr;
class Reaper final : public QObject class Reaper final : public QObject
{ {
public: public:
@@ -57,7 +55,7 @@ private:
Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p) Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
{ {
d->m_reapers.append(this); ProcessReaper::instance()->m_reapers.append(this);
m_iterationTimer.setInterval(timeoutMs); m_iterationTimer.setInterval(timeoutMs);
m_iterationTimer.setSingleShot(true); m_iterationTimer.setSingleShot(true);
@@ -68,7 +66,7 @@ Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
Reaper::~Reaper() Reaper::~Reaper()
{ {
d->m_reapers.removeOne(this); ProcessReaper::instance()->m_reapers.removeOne(this);
} }
int Reaper::timeoutMs() const int Reaper::timeoutMs() const
@@ -112,15 +110,8 @@ void Reaper::nextIteration()
} // namespace Internal } // namespace Internal
ProcessReaper::ProcessReaper()
{
QTC_ASSERT(Internal::d == nullptr, return);
Internal::d = this;
}
ProcessReaper::~ProcessReaper() ProcessReaper::~ProcessReaper()
{ {
QTC_ASSERT(Internal::d == this, return);
while (!m_reapers.isEmpty()) { while (!m_reapers.isEmpty()) {
int alreadyWaited = 0; int alreadyWaited = 0;
QList<Internal::Reaper *> toDelete; QList<Internal::Reaper *> toDelete;
@@ -145,8 +136,6 @@ ProcessReaper::~ProcessReaper()
qDeleteAll(toDelete); qDeleteAll(toDelete);
toDelete.clear(); toDelete.clear();
} }
Internal::d = nullptr;
} }
void ProcessReaper::reap(QProcess *process, int timeoutMs) void ProcessReaper::reap(QProcess *process, int timeoutMs)
@@ -175,8 +164,6 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
return; return;
} }
QTC_ASSERT(Internal::d, return);
new Internal::Reaper(process, timeoutMs); new Internal::Reaper(process, timeoutMs);
} }

View File

@@ -27,6 +27,8 @@
#include "utils_global.h" #include "utils_global.h"
#include "singleton.h"
#include <QList> #include <QList>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -38,15 +40,16 @@ namespace Utils {
namespace Internal { class Reaper; } namespace Internal { class Reaper; }
class QTCREATOR_UTILS_EXPORT ProcessReaper final class QTCREATOR_UTILS_EXPORT ProcessReaper final
: public SingletonWithOptionalDependencies<ProcessReaper>
{ {
public: public:
ProcessReaper();
~ProcessReaper();
static void reap(QProcess *process, int timeoutMs = 500); static void reap(QProcess *process, int timeoutMs = 500);
private: private:
ProcessReaper() = default;
~ProcessReaper();
QList<Internal::Reaper *> m_reapers; QList<Internal::Reaper *> m_reapers;
friend class Internal::Reaper; friend class Internal::Reaper;
friend class SingletonWithOptionalDependencies<ProcessReaper>;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 "qtcassert.h"
#include "singleton.h"
#include <QCoreApplication>
#include <QList>
#include <QThread>
#include <unordered_map>
using namespace Utils;
namespace Utils {
// The order of elements reflects dependencies, i.e.
// if B requires A then B will follow A on this list
static QList<Singleton *> s_singletonList;
static QMutex s_mutex;
static std::unordered_map<std::type_index, SingletonStaticData> s_staticDataList;
Singleton::~Singleton()
{
QMutexLocker locker(&s_mutex);
s_singletonList.removeAll(this);
}
void Singleton::addSingleton(Singleton *singleton)
{
QMutexLocker locker(&s_mutex);
s_singletonList.append(singleton);
}
SingletonStaticData &Singleton::staticData(std::type_index index)
{
QMutexLocker locker(&s_mutex);
return s_staticDataList[index];
}
// Note: it's caller responsibility to ensure that this function is being called when all other
// threads don't use any singleton. As a good practice: finish all other threads that were using
// singletons before this function is called.
// Some singletons (currently e.g. SshConnectionManager) can work only in main thread,
// so this method should be called from main thread only.
void Singleton::deleteAll()
{
QTC_ASSERT(QThread::currentThread() == qApp->thread(), return);
QList<Singleton *> oldList;
{
QMutexLocker locker(&s_mutex);
oldList = s_singletonList;
s_singletonList = {};
}
// Keep the reverse order when deleting
while (!oldList.isEmpty())
delete oldList.takeLast();
}
} // namespace Utils

106
src/libs/utils/singleton.h Normal file
View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** 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 "utils_global.h"
#include <QMutex>
#include <QMutexLocker>
#include <type_traits>
#include <typeindex>
namespace Utils {
class Singleton;
struct SingletonStaticData
{
Singleton *m_instance = nullptr;
QMutex m_mutex;
};
class QTCREATOR_UTILS_EXPORT Singleton
{
Q_DISABLE_COPY_MOVE(Singleton)
public:
static void deleteAll();
private:
template <typename SingletonSubClass, typename ...Dependencies>
friend class SingletonWithOptionalDependencies;
Singleton() = default;
virtual ~Singleton();
static void addSingleton(Singleton *singleton);
static SingletonStaticData &staticData(std::type_index index);
};
template <typename SingletonSubClass, typename ...Dependencies>
class SingletonWithOptionalDependencies : public Singleton
{
public:
Q_DISABLE_COPY_MOVE(SingletonWithOptionalDependencies)
static SingletonSubClass *instance()
{
SingletonStaticData &data = staticData();
QMutexLocker locker(&data.m_mutex);
if (data.m_instance == nullptr) {
// instantiate all dependencies first
if constexpr (sizeof...(Dependencies))
instantiateDependencies<Dependencies...>();
data.m_instance = new SingletonSubClass;
// put instance into static list of registered instances
addSingleton(data.m_instance);
}
return static_cast<SingletonSubClass *>(data.m_instance);
}
protected:
SingletonWithOptionalDependencies() = default;
~SingletonWithOptionalDependencies() override
{
SingletonStaticData &data = staticData();
QMutexLocker locker(&data.m_mutex);
if (data.m_instance == this)
data.m_instance = nullptr;
}
private:
template <typename ...Dependency> static void instantiateDependencies()
{
static_assert ((... && std::is_base_of_v<Singleton, Dependency>),
"All Dependencies must derive from SingletonWithOptionalDependencies class.");
(..., Dependency::instance());
}
static SingletonStaticData &staticData()
{
static SingletonStaticData &data = Singleton::staticData(std::type_index(typeid(SingletonSubClass)));
return data;
}
};
} // namespace Utils

View File

@@ -143,6 +143,7 @@ SOURCES += \
$$PWD/link.cpp \ $$PWD/link.cpp \
$$PWD/linecolumn.cpp \ $$PWD/linecolumn.cpp \
$$PWD/multitextcursor.cpp \ $$PWD/multitextcursor.cpp \
$$PWD/singleton.cpp
HEADERS += \ HEADERS += \
$$PWD/environmentfwd.h \ $$PWD/environmentfwd.h \
@@ -307,8 +308,9 @@ HEADERS += \
$$PWD/launcherinterface.h \ $$PWD/launcherinterface.h \
$$PWD/launcherpackets.h \ $$PWD/launcherpackets.h \
$$PWD/launchersocket.h \ $$PWD/launchersocket.h \
$$PWD/qtcsettings.h $$PWD/qtcsettings.h \
$$PWD/multitextcursor.h \ $$PWD/multitextcursor.h \
$$PWD/singleton.h
FORMS += $$PWD/filewizardpage.ui \ FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \ $$PWD/projectintropage.ui \

View File

@@ -264,6 +264,8 @@ Project {
"shellcommand.h", "shellcommand.h",
"shellcommandpage.cpp", "shellcommandpage.cpp",
"shellcommandpage.h", "shellcommandpage.h",
"singleton.cpp",
"singleton.h",
"sizedarray.h", "sizedarray.h",
"smallstring.h", "smallstring.h",
"smallstringiterator.h", "smallstringiterator.h",

View File

@@ -119,6 +119,7 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
qCDebug(avdManagerLog) qCDebug(avdManagerLog)
<< "Running AVD Manager command:" << CommandLine(avdManagerTool, arguments).toUserOutput(); << "Running AVD Manager command:" << CommandLine(avdManagerTool, arguments).toUserOutput();
QProcess proc; QProcess proc;
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config).toStringList());
proc.start(avdManagerTool.toString(), arguments); proc.start(avdManagerTool.toString(), arguments);
if (!proc.waitForStarted()) { if (!proc.waitForStarted()) {
result.error = QApplication::translate("AndroidAvdManager", result.error = QApplication::translate("AndroidAvdManager",

View File

@@ -604,50 +604,20 @@ AndroidDeviceFactory::AndroidDeviceFactory()
IDevice::Ptr AndroidDeviceFactory::create() const IDevice::Ptr AndroidDeviceFactory::create() const
{ {
AndroidSdkManager sdkManager = AndroidSdkManager(m_androidConfig); AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent());
const CreateAvdInfo info = AvdDialog::gatherCreateAVDInfo(Core::ICore::dialogParent(), if (dialog.exec() != QDialog::Accepted)
&sdkManager, m_androidConfig); return ProjectExplorer::IDevice::Ptr();
if (!info.isValid()) {
if (!info.cancelled) { const ProjectExplorer::IDevice::Ptr dev = dialog.device();
AndroidDeviceWidget::criticalDialog( const AndroidDevice *androidDev = static_cast<AndroidDevice*>(dev.data());
QObject::tr("The returned device info is invalid.")); if (androidDev) {
} qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".",
return nullptr; qPrintable(androidDev->avdName()));
} else {
AndroidDeviceWidget::criticalDialog(
QObject::tr("The device info returned from AvdDialog is invalid."));
} }
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
createAvdFutureWatcher.setFuture(avdManager.createAvd(info));
QEventLoop loop;
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
&loop, &QEventLoop::quit);
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
&loop, &QEventLoop::quit);
loop.exec(QEventLoop::ExcludeUserInputEvents);
QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
if (!(future.isResultReadyAt(0) && future.result().isValid())) {
AndroidDeviceWidget::criticalDialog(QObject::tr("The device info returned by "
"avdmanager tool is invalid for the device name \"%1\".").arg(info.name));
return nullptr;
}
const CreateAvdInfo newAvdInfo = createAvdFutureWatcher.result();
AndroidDevice *dev = new AndroidDevice();
const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(newAvdInfo);
dev->setupId(IDevice::AutoDetected, deviceId);
dev->setMachineType(IDevice::Emulator);
dev->setDisplayName(newAvdInfo.name);
dev->setDeviceState(IDevice::DeviceConnected);
dev->setExtraData(Constants::AndroidAvdName, newAvdInfo.name);
dev->setExtraData(Constants::AndroidCpuAbi, {newAvdInfo.abi});
dev->setExtraData(Constants::AndroidSdk, newAvdInfo.systemImage->apiLevel());
dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB").arg(newAvdInfo.sdcardSize));
dev->setExtraData(Constants::AndroidAvdDevice, newAvdInfo.deviceDefinition);
qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", qPrintable(newAvdInfo.name));
return IDevice::Ptr(dev); return IDevice::Ptr(dev);
} }

View File

@@ -694,7 +694,7 @@ bool SdkManagerOutputParser::parseAbstractData(SdkManagerOutputParser::GenericPa
for (const auto &key: qAsConst(keys)) { for (const auto &key: qAsConst(keys)) {
if (valueForKey(key, line, &value)) { if (valueForKey(key, line, &value)) {
if (key == installLocationKey) if (key == installLocationKey)
output.installedLocation = Utils::FilePath::fromString(value); output.installedLocation = Utils::FilePath::fromUserInput(value);
else if (key == revisionKey) else if (key == revisionKey)
output.revision = QVersionNumber::fromString(value); output.revision = QVersionNumber::fromString(value);
else if (key == descriptionKey) else if (key == descriptionKey)

View File

@@ -241,7 +241,7 @@ void AndroidSettingsWidget::updateNdkList()
const auto installedPkgs = m_sdkManager.installedNdkPackages(); const auto installedPkgs = m_sdkManager.installedNdkPackages();
for (const Ndk *ndk : installedPkgs) { for (const Ndk *ndk : installedPkgs) {
m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::LOCKED.icon(), m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::LOCKED.icon(),
ndk->installedLocation().toString())); ndk->installedLocation().toUserOutput()));
} }
const auto customNdks = m_androidConfig.getCustomNdkList(); const auto customNdks = m_androidConfig.getCustomNdkList();

View File

@@ -26,6 +26,8 @@
#include "avddialog.h" #include "avddialog.h"
#include "androidsdkmanager.h" #include "androidsdkmanager.h"
#include "androidavdmanager.h" #include "androidavdmanager.h"
#include "androiddevice.h"
#include "androidconstants.h"
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -33,6 +35,7 @@
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QFutureWatcher>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QMessageBox>
#include <QToolTip> #include <QToolTip>
@@ -46,29 +49,35 @@ namespace {
static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg) static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg)
} }
AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStringList &abis, AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
const AndroidConfig &config, QWidget *parent) : : QDialog(parent),
QDialog(parent), m_sdkManager(m_androidConfig),
m_sdkManager(sdkManager), m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
m_minApiLevel(minApiLevel), m_androidConfig(config)
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
m_androidConfig(config)
{ {
QTC_CHECK(m_sdkManager);
m_avdDialog.setupUi(this); m_avdDialog.setupUi(this);
m_hideTipTimer.setInterval(2000); m_hideTipTimer.setInterval(2000);
m_hideTipTimer.setSingleShot(true); m_hideTipTimer.setSingleShot(true);
if (abis.isEmpty()) { connect(&m_hideTipTimer, &QTimer::timeout, this, &Utils::ToolTip::hide);
m_avdDialog.abiComboBox->addItems(QStringList({ connect(m_avdDialog.deviceDefinitionTypeComboBox,
ProjectExplorer::Constants::ANDROID_ABI_X86, QOverload<int>::of(&QComboBox::currentIndexChanged),
ProjectExplorer::Constants::ANDROID_ABI_X86_64, this, &AvdDialog::updateDeviceDefinitionComboBox);
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A, connect(m_avdDialog.abiComboBox,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI, QOverload<int>::of(&QComboBox::currentIndexChanged),
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A})); this, &AvdDialog::updateApiLevelComboBox);
} else {
m_avdDialog.abiComboBox->addItems(abis); deviceTypeToStringMap.insert(AvdDialog::Phone, "Phone");
} deviceTypeToStringMap.insert(AvdDialog::Tablet, "Tablet");
deviceTypeToStringMap.insert(AvdDialog::Automotive, "Automotive");
deviceTypeToStringMap.insert(AvdDialog::TV, "TV");
deviceTypeToStringMap.insert(AvdDialog::Wear, "Wear");
m_avdDialog.abiComboBox->addItems(QStringList({
ProjectExplorer::Constants::ANDROID_ABI_X86,
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
auto v = new QRegularExpressionValidator(m_allowedNameChars, this); auto v = new QRegularExpressionValidator(m_allowedNameChars, this);
m_avdDialog.nameLineEdit->setValidator(v); m_avdDialog.nameLineEdit->setValidator(v);
@@ -77,46 +86,70 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
m_avdDialog.warningText->setType(Utils::InfoLabel::Warning); m_avdDialog.warningText->setType(Utils::InfoLabel::Warning);
m_avdDialog.warningText->setElideMode(Qt::ElideNone); m_avdDialog.warningText->setElideMode(Qt::ElideNone);
connect(&m_hideTipTimer, &QTimer::timeout, this, []() { Utils::ToolTip::hide(); });
parseDeviceDefinitionsList(); parseDeviceDefinitionsList();
for (const QString &type : DeviceTypeToStringMap) for (const QString &type : deviceTypeToStringMap)
m_avdDialog.deviceDefinitionTypeComboBox->addItem(type); m_avdDialog.deviceDefinitionTypeComboBox->addItem(type);
connect(m_avdDialog.deviceDefinitionTypeComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&AvdDialog::updateDeviceDefinitionComboBox);
connect(m_avdDialog.abiComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AvdDialog::updateApiLevelComboBox);
m_avdDialog.deviceDefinitionTypeComboBox->setCurrentIndex(1); // Set Phone type as default index
updateApiLevelComboBox(); updateApiLevelComboBox();
} }
int AvdDialog::exec()
{
const int execResult = QDialog::exec();
if (execResult == QDialog::Accepted) {
CreateAvdInfo result;
result.systemImage = systemImage();
result.name = name();
result.abi = abi();
result.deviceDefinition = deviceDefinition();
result.sdcardSize = sdcardSize();
result.overwrite = m_avdDialog.overwriteCheckBox->isChecked();
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
createAvdFutureWatcher.setFuture(avdManager.createAvd(result));
QEventLoop loop;
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
&loop, &QEventLoop::quit);
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
&loop, &QEventLoop::quit);
loop.exec(QEventLoop::ExcludeUserInputEvents);
const QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
if (future.isResultReadyAt(0))
m_createdAvdInfo = future.result();
}
return execResult;
}
bool AvdDialog::isValid() const bool AvdDialog::isValid() const
{ {
return !name().isEmpty() && systemImage() && systemImage()->isValid() && !abi().isEmpty(); return !name().isEmpty() && systemImage() && systemImage()->isValid() && !abi().isEmpty();
} }
CreateAvdInfo AvdDialog::gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager, ProjectExplorer::IDevice::Ptr AvdDialog::device() const
const AndroidConfig &config, int minApiLevel, const QStringList &abis)
{ {
CreateAvdInfo result; AndroidDevice *dev = new AndroidDevice();
AvdDialog d(minApiLevel, sdkManager, abis, config, parent); const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(m_createdAvdInfo);
result.cancelled = (d.exec() != QDialog::Accepted); using namespace ProjectExplorer;
if (result.cancelled || !d.isValid()) dev->setupId(IDevice::AutoDetected, deviceId);
return result; dev->setMachineType(IDevice::Emulator);
dev->setDisplayName(m_createdAvdInfo.name);
dev->setDeviceState(IDevice::DeviceConnected);
dev->setExtraData(Constants::AndroidAvdName, m_createdAvdInfo.name);
dev->setExtraData(Constants::AndroidCpuAbi, {m_createdAvdInfo.abi});
if (!m_createdAvdInfo.systemImage) {
qCWarning(avdDialogLog) << "System image of the created AVD is nullptr";
return IDevice::Ptr();
}
dev->setExtraData(Constants::AndroidSdk, m_createdAvdInfo.systemImage->apiLevel());
dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB")
.arg(m_createdAvdInfo.sdcardSize));
dev->setExtraData(Constants::AndroidAvdDevice, m_createdAvdInfo.deviceDefinition);
result.systemImage = d.systemImage(); return IDevice::Ptr(dev);
result.name = d.name();
result.abi = d.abi();
result.deviceDefinition = d.deviceDefinition();
result.sdcardSize = d.sdcardSize();
result.overwrite = d.m_avdDialog.overwriteCheckBox->isChecked();
return result;
} }
AvdDialog::DeviceType AvdDialog::tagToDeviceType(const QString &type_tag) AvdDialog::DeviceType AvdDialog::tagToDeviceType(const QString &type_tag)
@@ -175,7 +208,7 @@ void AvdDialog::parseDeviceDefinitionsList()
void AvdDialog::updateDeviceDefinitionComboBox() void AvdDialog::updateDeviceDefinitionComboBox()
{ {
DeviceType curDeviceType = DeviceTypeToStringMap.key( DeviceType curDeviceType = deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_avdDialog.deviceDefinitionTypeComboBox->currentText());
m_avdDialog.deviceDefinitionComboBox->clear(); m_avdDialog.deviceDefinitionComboBox->clear();
@@ -215,8 +248,8 @@ int AvdDialog::sdcardSize() const
void AvdDialog::updateApiLevelComboBox() void AvdDialog::updateApiLevelComboBox()
{ {
SystemImageList installedSystemImages = m_sdkManager->installedSystemImages(); SystemImageList installedSystemImages = m_sdkManager.installedSystemImages();
DeviceType curDeviceType = DeviceTypeToStringMap.key( DeviceType curDeviceType = deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_avdDialog.deviceDefinitionTypeComboBox->currentText());
QString selectedAbi = abi(); QString selectedAbi = abi();
@@ -250,8 +283,7 @@ void AvdDialog::updateApiLevelComboBox()
m_avdDialog.warningText->setVisible(true); m_avdDialog.warningText->setVisible(true);
m_avdDialog.warningText->setText( m_avdDialog.warningText->setText(
tr("Cannot create a new AVD. No suitable Android system image is installed.<br/>" tr("Cannot create a new AVD. No suitable Android system image is installed.<br/>"
"Install a system image of at least API version %1 from the SDK Manager tab.") "Install a system image for the intended Android version from the SDK Manager."));
.arg(m_minApiLevel));
m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else if (filteredList.isEmpty()) { } else if (filteredList.isEmpty()) {
m_avdDialog.targetApiComboBox->setEnabled(false); m_avdDialog.targetApiComboBox->setEnabled(false);

View File

@@ -41,21 +41,27 @@ class AvdDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AvdDialog(int minApiLevel, explicit AvdDialog(const AndroidConfig &config, QWidget *parent = nullptr);
AndroidSdkManager *sdkManager, int exec() override;
const QStringList &abis,
const AndroidConfig &config,
QWidget *parent = nullptr);
enum DeviceType { TV, Phone, Wear, Tablet, Automotive, PhoneOrTablet }; enum DeviceType { Phone, Tablet, Automotive, TV, Wear, PhoneOrTablet };
const QMap<DeviceType, QString> DeviceTypeToStringMap{ ProjectExplorer::IDevice::Ptr device() const;
{TV, "TV"},
{Phone, "Phone"}, const SystemImage *systemImage() const;
{Wear, "Wear"}, QString name() const;
{Tablet, "Tablet"}, QString abi() const;
{Automotive, "Automotive"} QString deviceDefinition() const;
}; int sdcardSize() const;
bool isValid() const;
private:
void parseDeviceDefinitionsList();
void updateDeviceDefinitionComboBox();
void updateApiLevelComboBox();
bool eventFilter(QObject *obj, QEvent *event) override;
static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag);
struct DeviceDefinitionStruct struct DeviceDefinitionStruct
{ {
@@ -64,30 +70,14 @@ public:
DeviceType deviceType; DeviceType deviceType;
}; };
const SystemImage *systemImage() const;
QString name() const;
QString abi() const;
QString deviceDefinition() const;
int sdcardSize() const;
bool isValid() const;
static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag);
static CreateAvdInfo gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager,
const AndroidConfig &config,
int minApiLevel = 0, const QStringList &abis = {});
private:
void parseDeviceDefinitionsList();
void updateDeviceDefinitionComboBox();
void updateApiLevelComboBox();
bool eventFilter(QObject *obj, QEvent *event) override;
Ui::AddNewAVDDialog m_avdDialog; Ui::AddNewAVDDialog m_avdDialog;
AndroidSdkManager *m_sdkManager; AndroidSdkManager m_sdkManager;
int m_minApiLevel; CreateAvdInfo m_createdAvdInfo;
QTimer m_hideTipTimer; QTimer m_hideTipTimer;
QRegularExpression m_allowedNameChars; QRegularExpression m_allowedNameChars;
QList<DeviceDefinitionStruct> m_deviceDefinitionsList; QList<DeviceDefinitionStruct> m_deviceDefinitionsList;
AndroidConfig m_androidConfig; AndroidConfig m_androidConfig;
QMap<AvdDialog::DeviceType, QString> deviceTypeToStringMap;
}; };
} }
} }

View File

@@ -568,7 +568,7 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
bool ClangCompletionAssistProcessor::completePreprocessorDirectives() bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
{ {
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions) foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion, addCompletionItem(preprocessorCompletion,
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro)); Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));

File diff suppressed because it is too large Load Diff

View File

@@ -77,6 +77,7 @@ public:
const LanguageServerProtocol::DocumentUri &uri); const LanguageServerProtocol::DocumentUri &uri);
void enableTesting(); void enableTesting();
bool testingEnabled() const;
signals: signals:
void indexingFinished(); void indexingFinished();
@@ -90,12 +91,15 @@ signals:
private: private:
void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override; void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override;
void handleDocumentOpened(TextEditor::TextDocument *doc) override;
void handleDocumentClosed(TextEditor::TextDocument *doc) override; void handleDocumentClosed(TextEditor::TextDocument *doc) override;
class Private; class Private;
class FollowSymbolData; class FollowSymbolData;
class VirtualFunctionAssistProcessor; class VirtualFunctionAssistProcessor;
class VirtualFunctionAssistProvider; class VirtualFunctionAssistProvider;
class ClangdFunctionHintProcessor;
class ClangdCompletionAssistProcessor;
class ClangdCompletionAssistProvider; class ClangdCompletionAssistProvider;
Private * const d; Private * const d;
}; };

View File

@@ -77,6 +77,7 @@ using Range = std::tuple<int, int, int>;
} // namespace ClangCodeModel } // namespace ClangCodeModel
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Tests::Range) Q_DECLARE_METATYPE(ClangCodeModel::Internal::Tests::Range)
Q_DECLARE_METATYPE(IAssistProposal *)
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
@@ -392,7 +393,7 @@ void ClangdTestFollowSymbol::test()
timer.stop(); timer.stop();
QCOMPARE(actualLink.targetFilePath, filePath(targetFile)); QCOMPARE(actualLink.targetFilePath, filePath(targetFile));
QEXPECT_FAIL("union member ref", "FIXME: clangd points to union", Abort); QEXPECT_FAIL("union member ref", "https://github.com/clangd/clangd/issues/877", Abort);
QCOMPARE(actualLink.targetLine, targetLine); QCOMPARE(actualLink.targetLine, targetLine);
QCOMPARE(actualLink.targetColumn + 1, targetColumn); QCOMPARE(actualLink.targetColumn + 1, targetColumn);
} }
@@ -1274,7 +1275,7 @@ void ClangdTestHighlighting::test()
const TextEditor::HighlightingResults results = findResults(); const TextEditor::HighlightingResults results = findResults();
QEXPECT_FAIL("typedef as underlying type in enum declaration", QEXPECT_FAIL("typedef as underlying type in enum declaration",
"FIXME: clangd does not report this symbol", "https://github.com/clangd/clangd/issues/878",
Abort); Abort);
QEXPECT_FAIL("Q_PROPERTY (property name)", "FIXME: How to do this?", Abort); QEXPECT_FAIL("Q_PROPERTY (property name)", "FIXME: How to do this?", Abort);
QEXPECT_FAIL("Q_PROPERTY (getter)", "FIXME: How to do this?", Abort); QEXPECT_FAIL("Q_PROPERTY (getter)", "FIXME: How to do this?", Abort);
@@ -1461,20 +1462,19 @@ void ClangdTestCompletion::testCompletePreprocessorKeywords()
ProposalModelPtr proposal; ProposalModelPtr proposal;
getProposal("preprocessorKeywordsCompletion.cpp", proposal); getProposal("preprocessorKeywordsCompletion.cpp", proposal);
QVERIFY(proposal); QVERIFY(proposal);
QVERIFY(hasItem(proposal, " ifdef macro")); QVERIFY(hasItem(proposal, "ifdef"));
QVERIFY(!hasSnippet(proposal, "class ")); QVERIFY(!hasSnippet(proposal, "class "));
proposal.clear(); proposal.clear();
getProposal("preprocessorKeywordsCompletion2.cpp", proposal); getProposal("preprocessorKeywordsCompletion2.cpp", proposal);
QVERIFY(proposal); QVERIFY(proposal);
QVERIFY(hasItem(proposal, " endif")); QVERIFY(hasItem(proposal, "endif"));
QVERIFY(!hasSnippet(proposal, "class ")); QVERIFY(!hasSnippet(proposal, "class "));
proposal.clear(); proposal.clear();
getProposal("preprocessorKeywordsCompletion3.cpp", proposal); getProposal("preprocessorKeywordsCompletion3.cpp", proposal);
QVERIFY(proposal); QVERIFY(proposal);
QEXPECT_FAIL("", "TODO: Fix in clangd", Continue); QVERIFY(hasItem(proposal, "endif"));
QVERIFY(hasItem(proposal, " endif"));
QVERIFY(!hasSnippet(proposal, "class ")); QVERIFY(!hasSnippet(proposal, "class "));
} }
@@ -1885,7 +1885,7 @@ void ClangdTestCompletion::getProposal(const QString &fileName,
connect(client(), &ClangdClient::proposalReady, &loop, [&proposal, &loop](IAssistProposal *p) { connect(client(), &ClangdClient::proposalReady, &loop, [&proposal, &loop](IAssistProposal *p) {
proposal = p; proposal = p;
loop.quit(); loop.quit();
}); }, Qt::QueuedConnection);
editor->editorWidget()->invokeAssist(Completion, nullptr); editor->editorWidget()->invokeAssist(Completion, nullptr);
timer.start(5000); timer.start(5000);
loop.exec(); loop.exec();

View File

@@ -34,6 +34,7 @@
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/icon.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/wizard.h> #include <utils/wizard.h>
@@ -369,6 +370,11 @@ void IWizardFactory::requestNewItemDialog(const QString &title,
s_reopenData.setData(title, factories, defaultLocation, extraVariables); s_reopenData.setData(title, factories, defaultLocation, extraVariables);
} }
QIcon IWizardFactory::themedIcon(const Utils::FilePath &iconMaskPath)
{
return Utils::Icon({{iconMaskPath, Theme::PanelTextColorDark}}, Icon::Tint).icon();
}
void IWizardFactory::destroyFeatureProvider() void IWizardFactory::destroyFeatureProvider()
{ {
qDeleteAll(s_providerList); qDeleteAll(s_providerList);
@@ -427,7 +433,8 @@ void IWizardFactory::initialize()
static QIcon iconWithText(const QIcon &icon, const QString &text) static QIcon iconWithText(const QIcon &icon, const QString &text)
{ {
if (icon.isNull()) { if (icon.isNull()) {
static const QIcon fallBack(":/utils/images/wizardicon-file.png"); static const QIcon fallBack =
IWizardFactory::themedIcon(":/utils/images/wizardicon-file.png");
return iconWithText(fallBack, text); return iconWithText(fallBack, text);
} }
@@ -445,6 +452,7 @@ static QIcon iconWithText(const QIcon &icon, const QString &text)
font.setPixelSize(fontSize); font.setPixelSize(fontSize);
font.setStretch(85); font.setStretch(85);
QPainter p(&pixmap); QPainter p(&pixmap);
p.setPen(Utils::creatorTheme()->color(Theme::PanelTextColorDark));
p.setFont(font); p.setFont(font);
QTextOption textOption(Qt::AlignHCenter | Qt::AlignBottom); QTextOption textOption(Qt::AlignHCenter | Qt::AlignBottom);
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

View File

@@ -115,6 +115,8 @@ public:
const Utils::FilePath &defaultLocation, const Utils::FilePath &defaultLocation,
const QVariantMap &extraVariables); const QVariantMap &extraVariables);
static QIcon themedIcon(const Utils::FilePath &iconMaskPath);
protected: protected:
static QSet<Utils::Id> pluginFeatures(); static QSet<Utils::Id> pluginFeatures();
static QSet<Utils::Id> availableFeatures(Utils::Id platformId); static QSet<Utils::Id> availableFeatures(Utils::Id platformId);

View File

@@ -37,6 +37,7 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QApplication> #include <QApplication>
#include <QCheckBox>
#include <QComboBox> #include <QComboBox>
#include <QDockWidget> #include <QDockWidget>
#include <QFormLayout> #include <QFormLayout>
@@ -288,7 +289,8 @@ void ManhattanStyle::polish(QWidget *widget)
if (qobject_cast<QToolButton*>(widget) || qobject_cast<QLineEdit*>(widget)) { if (qobject_cast<QToolButton*>(widget) || qobject_cast<QLineEdit*>(widget)) {
widget->setAttribute(Qt::WA_Hover); widget->setAttribute(Qt::WA_Hover);
widget->setMaximumHeight(height - 2); widget->setMaximumHeight(height - 2);
} else if (qobject_cast<QLabel*>(widget)) { } else if (qobject_cast<QLabel*>(widget) || qobject_cast<QSpinBox*>(widget)
|| qobject_cast<QCheckBox*>(widget)) {
widget->setPalette(panelPalette(widget->palette(), lightColored(widget))); widget->setPalette(panelPalette(widget->palette(), lightColored(widget)));
} else if (widget->property("panelwidget_singlerow").toBool()) { } else if (widget->property("panelwidget_singlerow").toBool()) {
widget->setFixedHeight(height); widget->setFixedHeight(height);
@@ -303,10 +305,6 @@ void ManhattanStyle::polish(QWidget *widget)
widget->setPalette(palette); widget->setPalette(palette);
widget->setMaximumHeight(height - 2); widget->setMaximumHeight(height - 2);
widget->setAttribute(Qt::WA_Hover); widget->setAttribute(Qt::WA_Hover);
} else if (qobject_cast<QSpinBox*>(widget)) {
const bool isLightColored = lightColored(widget);
QPalette palette = panelPalette(widget->palette(), isLightColored);
widget->setPalette(palette);
} }
} }
} }

View File

@@ -1302,7 +1302,7 @@ void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPa
void InternalCppCompletionAssistProcessor::completePreprocessor() void InternalCppCompletionAssistProcessor::completePreprocessor()
{ {
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions) foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion); addCompletionItem(preprocessorCompletion);
if (objcKeywordsWanted()) if (objcKeywordsWanted())

View File

@@ -41,20 +41,24 @@ using namespace CPlusPlus;
namespace CppEditor { namespace CppEditor {
CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder) CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder)
: m_preprocessorCompletions( : m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
QStringList({"define", "error", "include", "line", "pragma", "pragma once",
"pragma omp atomic", "pragma omp parallel", "pragma omp for",
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
"pragma omp master", "pragma omp critical", "pragma omp barrier",
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
"ifndef", "elif", "else", "endif"}))
, m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
QIcon(QLatin1String(":/texteditor/images/snippet.png")), QIcon(QLatin1String(":/texteditor/images/snippet.png")),
snippetItemOrder) snippetItemOrder)
{ {
} }
const QStringList CppCompletionAssistProcessor::preprocessorCompletions()
{
static QStringList list{"define", "error", "include", "line", "pragma", "pragma once",
"pragma omp atomic", "pragma omp parallel", "pragma omp for",
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
"pragma omp master", "pragma omp critical", "pragma omp barrier",
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
"ifndef", "elif", "else", "endif"};
return list;
}
void CppCompletionAssistProcessor::addSnippets() void CppCompletionAssistProcessor::addSnippets()
{ {
m_completions.append(m_snippetCollector.collect()); m_completions.append(m_snippetCollector.collect());

View File

@@ -45,6 +45,8 @@ class CPPEDITOR_EXPORT CppCompletionAssistProcessor : public TextEditor::IAssist
public: public:
explicit CppCompletionAssistProcessor(int snippetItemOrder = 0); explicit CppCompletionAssistProcessor(int snippetItemOrder = 0);
static const QStringList preprocessorCompletions();
protected: protected:
void addSnippets(); void addSnippets();
@@ -60,7 +62,6 @@ protected:
int m_positionForProposal = -1; int m_positionForProposal = -1;
QList<TextEditor::AssistProposalItemInterface *> m_completions; QList<TextEditor::AssistProposalItemInterface *> m_completions;
QStringList m_preprocessorCompletions;
TextEditor::IAssistProposal *m_hintProposal = nullptr; TextEditor::IAssistProposal *m_hintProposal = nullptr;
private: private:

View File

@@ -55,7 +55,7 @@ class SourcePathMappingModel;
enum { SourceColumn, TargetColumn, ColumnCount }; enum { SourceColumn, TargetColumn, ColumnCount };
using Mapping = QPair<QString, QString>; using Mapping = QPair<FilePath, FilePath>;
class DebuggerSourcePathMappingWidget : public QGroupBox class DebuggerSourcePathMappingWidget : public QGroupBox
{ {
@@ -79,7 +79,7 @@ private:
void updateEnabled(); void updateEnabled();
QString editSourceField() const; QString editSourceField() const;
QString editTargetField() const; QString editTargetField() const;
void setEditFieldMapping(const QPair<QString, QString> &m); void setEditFieldMapping(const Mapping &m);
int currentRow() const; int currentRow() const;
void setCurrentRow(int r); void setCurrentRow(int r);
@@ -162,9 +162,9 @@ SourcePathMap SourcePathMappingModel::sourcePathMap() const
SourcePathMap rc; SourcePathMap rc;
const int rows = rowCount(); const int rows = rowCount();
for (int r = 0; r < rows; ++r) { for (int r = 0; r < rows; ++r) {
const QPair<QString, QString> m = mappingAt(r); // Skip placeholders. const Mapping m = mappingAt(r); // Skip placeholders.
if (!m.first.isEmpty() && !m.second.isEmpty()) if (!m.first.isEmpty() && !m.second.isEmpty())
rc.insert(m.first, m.second); rc.insert(m.first.toString(), m.second.toString());
} }
return rc; return rc;
} }
@@ -176,17 +176,17 @@ bool SourcePathMappingModel::isNewPlaceHolder(const Mapping &m) const
const QChar greaterThan('>'); const QChar greaterThan('>');
return m.first.isEmpty() || m.first.startsWith(lessThan) return m.first.isEmpty() || m.first.startsWith(lessThan)
|| m.first.endsWith(greaterThan) || m.first.endsWith(greaterThan)
|| m.first == m_newSourcePlaceHolder || m.first.toString() == m_newSourcePlaceHolder
|| m.second.isEmpty() || m.second.startsWith(lessThan) || m.second.isEmpty() || m.second.startsWith(lessThan)
|| m.second.endsWith(greaterThan) || m.second.endsWith(greaterThan)
|| m.second == m_newTargetPlaceHolder; || m.second.toString() == m_newTargetPlaceHolder;
} }
// Return raw, unfixed mapping // Return raw, unfixed mapping
Mapping SourcePathMappingModel::rawMappingAt(int row) const Mapping SourcePathMappingModel::rawMappingAt(int row) const
{ {
return Mapping(QDir::fromNativeSeparators(item(row, SourceColumn)->text()), return Mapping(FilePath::fromUserInput(item(row, SourceColumn)->text()),
QDir::fromNativeSeparators(item(row, TargetColumn)->text())); FilePath::fromUserInput(item(row, TargetColumn)->text()));
} }
// Return mapping, empty if it is the place holder. // Return mapping, empty if it is the place holder.
@@ -337,15 +337,14 @@ QString DebuggerSourcePathMappingWidget::editTargetField() const
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m) void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
{ {
m_sourceLineEdit->setText(m.first); m_sourceLineEdit->setText(m.first.toUserOutput());
m_targetChooser->setPath(m.second); m_targetChooser->setFilePath(m.second);
} }
void DebuggerSourcePathMappingWidget::slotCurrentRowChanged void DebuggerSourcePathMappingWidget::slotCurrentRowChanged
(const QModelIndex &current, const QModelIndex &) (const QModelIndex &current, const QModelIndex &)
{ {
setEditFieldMapping(current.isValid() setEditFieldMapping(current.isValid() ? m_model->mappingAt(current.row()) : Mapping());
? m_model->mappingAt(current.row()) : Mapping());
updateEnabled(); updateEnabled();
} }

View File

@@ -145,6 +145,8 @@ RemoteDialog::RemoteDialog(QWidget *parent) :
connect(m_ui->remoteView->selectionModel(), &QItemSelectionModel::selectionChanged, connect(m_ui->remoteView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &RemoteDialog::updateButtonState); this, &RemoteDialog::updateButtonState);
connect(m_remoteModel, &RemoteModel::refreshed,
this, &RemoteDialog::updateButtonState);
updateButtonState(); updateButtonState();
} }

View File

@@ -199,6 +199,7 @@ bool RemoteModel::refresh(const FilePath &workingDirectory, QString *errorMessag
m_remotes.push_back(newRemote); m_remotes.push_back(newRemote);
} }
endResetModel(); endResetModel();
emit refreshed();
return true; return true;
} }

View File

@@ -65,6 +65,9 @@ public:
Utils::FilePath workingDirectory() const; Utils::FilePath workingDirectory() const;
int findRemoteByName(const QString &name) const; int findRemoteByName(const QString &name) const;
signals:
void refreshed();
protected: protected:
class Remote { class Remote {
public: public:

View File

@@ -394,6 +394,7 @@ void Client::openDocument(TextEditor::TextDocument *document)
m_documentVersions[filePath] = 0; m_documentVersions[filePath] = 0;
item.setVersion(m_documentVersions[filePath]); item.setVersion(m_documentVersions[filePath]);
sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item))); sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)));
handleDocumentOpened(document);
const Client *currentClient = LanguageClientManager::clientForDocument(document); const Client *currentClient = LanguageClientManager::clientForDocument(document);
if (currentClient == this) { if (currentClient == this) {
@@ -1047,22 +1048,6 @@ SymbolStringifier Client::symbolStringifier() const
return m_symbolStringifier; return m_symbolStringifier;
} }
void Client::setCompletionProposalHandler(const ProposalHandler &handler)
{
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
m_clientProviders.completionAssistProvider)) {
provider->setProposalHandler(handler);
}
}
void Client::setFunctionHintProposalHandler(const ProposalHandler &handler)
{
if (const auto provider = qobject_cast<FunctionHintAssistProvider *>(
m_clientProviders.functionHintProvider)) {
provider->setProposalHandler(handler);
}
}
void Client::setSnippetsGroup(const QString &group) void Client::setSnippetsGroup(const QString &group)
{ {
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>( if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(

View File

@@ -185,8 +185,6 @@ public:
void setSemanticTokensHandler(const SemanticTokensHandler &handler); void setSemanticTokensHandler(const SemanticTokensHandler &handler);
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier); void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
LanguageServerProtocol::SymbolStringifier symbolStringifier() const; LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
void setCompletionProposalHandler(const ProposalHandler &handler);
void setFunctionHintProposalHandler(const ProposalHandler &handler);
void setSnippetsGroup(const QString &group); void setSnippetsGroup(const QString &group);
void setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider); void setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider);
@@ -240,6 +238,7 @@ private:
void rehighlight(); void rehighlight();
virtual void handleDocumentClosed(TextEditor::TextDocument *) {} virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
using ContentHandler = std::function<void(const QByteArray &, QTextCodec *, QString &, using ContentHandler = std::function<void(const QByteArray &, QTextCodec *, QString &,
LanguageServerProtocol::ResponseHandlers, LanguageServerProtocol::ResponseHandlers,

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