Merge remote-tracking branch 'origin/6.0'
Change-Id: If773f217a9708ce0ad0b8adeefe3266ba0371a32
70
dist/changes-5.0.2.md
vendored
Normal 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
|
Before Width: | Height: | Size: 604 B After Width: | Height: | Size: 358 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 677 B |
@@ -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}",
|
||||||
|
|
||||||
|
@@ -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":
|
||||||
|
@@ -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" },
|
||||||
|
@@ -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" },
|
||||||
|
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 342 B |
Before Width: | Height: | Size: 989 B After Width: | Height: | Size: 592 B |
@@ -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')}" },
|
||||||
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 450 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 983 B After Width: | Height: | Size: 543 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 685 B |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -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}",
|
||||||
|
|
||||||
|
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 609 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -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":
|
||||||
|
@@ -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":[
|
||||||
{
|
{
|
||||||
|
@@ -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":
|
||||||
|
@@ -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":
|
||||||
|
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 728 B After Width: | Height: | Size: 682 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 855 B After Width: | Height: | Size: 466 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 849 B |
@@ -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":
|
||||||
|
@@ -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":
|
||||||
|
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -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}",
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 231 B |
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 413 B |
@@ -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}",
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 560 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -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" ],
|
||||||
|
|
||||||
|
@@ -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}",
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 551 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -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":
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 868 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -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}",
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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: [
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 196 B |
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 241 B |
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
82
src/libs/utils/singleton.cpp
Normal 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
@@ -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
|
@@ -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 \
|
||||||
|
@@ -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",
|
||||||
|
@@ -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",
|
||||||
|
@@ -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();
|
||||||
|
const AndroidDevice *androidDev = static_cast<AndroidDevice*>(dev.data());
|
||||||
|
if (androidDev) {
|
||||||
|
qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".",
|
||||||
|
qPrintable(androidDev->avdName()));
|
||||||
|
} else {
|
||||||
AndroidDeviceWidget::criticalDialog(
|
AndroidDeviceWidget::criticalDialog(
|
||||||
QObject::tr("The returned device info is invalid."));
|
QObject::tr("The device info returned from AvdDialog is invalid."));
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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();
|
||||||
|
@@ -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_minApiLevel(minApiLevel),
|
|
||||||
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
|
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
|
||||||
m_androidConfig(config)
|
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);
|
||||||
|
connect(m_avdDialog.deviceDefinitionTypeComboBox,
|
||||||
|
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
this, &AvdDialog::updateDeviceDefinitionComboBox);
|
||||||
|
connect(m_avdDialog.abiComboBox,
|
||||||
|
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
this, &AvdDialog::updateApiLevelComboBox);
|
||||||
|
|
||||||
|
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({
|
m_avdDialog.abiComboBox->addItems(QStringList({
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_X86,
|
ProjectExplorer::Constants::ANDROID_ABI_X86,
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
|
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
|
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI,
|
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
|
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
|
||||||
} else {
|
|
||||||
m_avdDialog.abiComboBox->addItems(abis);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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));
|
||||||
|
|
||||||
|
@@ -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 ¶ms) override;
|
void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams ¶ms) 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;
|
||||||
};
|
};
|
||||||
|
@@ -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();
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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())
|
||||||
|
@@ -41,18 +41,22 @@ 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",
|
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
|
||||||
|
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 atomic", "pragma omp parallel", "pragma omp for",
|
||||||
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
|
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
|
||||||
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
|
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
|
||||||
"pragma omp master", "pragma omp critical", "pragma omp barrier",
|
"pragma omp master", "pragma omp critical", "pragma omp barrier",
|
||||||
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
|
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
|
||||||
"ifndef", "elif", "else", "endif"}))
|
"ifndef", "elif", "else", "endif"};
|
||||||
, m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
|
return list;
|
||||||
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
|
|
||||||
snippetItemOrder)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCompletionAssistProcessor::addSnippets()
|
void CppCompletionAssistProcessor::addSnippets()
|
||||||
|
@@ -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:
|
||||||
|
@@ -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 ¤t, const QModelIndex &)
|
(const QModelIndex ¤t, const QModelIndex &)
|
||||||
{
|
{
|
||||||
setEditFieldMapping(current.isValid()
|
setEditFieldMapping(current.isValid() ? m_model->mappingAt(current.row()) : Mapping());
|
||||||
? m_model->mappingAt(current.row()) : Mapping());
|
|
||||||
updateEnabled();
|
updateEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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:
|
||||||
|
@@ -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 *>(
|
||||||
|
@@ -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,
|
||||||
|