aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2024-02-14 12:48:53 +0100
committerEike Ziller <eike.ziller@qt.io>2024-02-14 12:48:53 +0100
commitbcf0d8c319f1356d8c407fe1335ad58a503e1bd5 (patch)
tree08ef3fce62f5e3ef4519306de145174859a8736d
parent1af555ad09be169bebc7525e4bb7e10ad4de271d (diff)
parent0a1783d656964df60f1ec462f81c56ea38100dc5 (diff)
Merge remote-tracking branch 'origin/13.0'
-rw-r--r--dist/changelog/changes-13.0.0.md97
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-built-in-indenter.webpbin0 -> 13192 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-clang-format-global.webpbin15310 -> 15316 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-clang-format-project.webpbin10152 -> 10864 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.pngbin12603 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-new-file-ts.webpbin0 -> 4784 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-options-code-style-qml.pngbin11935 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-preferences-nim-code-style.webpbin8204 -> 8764 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-preferences-qtquick-code-style.webpbin0 -> 10320 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-project-kits.pngbin40239 -> 0 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-projects-kits.webpbin9292 -> 13522 bytes
-rw-r--r--doc/qtcreator/images/qtcreator-projects-vanished-targets.webpbin0 -> 7114 bytes
-rw-r--r--doc/qtcreator/src/editors/creator-code-completion.qdoc3
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-preferences-cpp-code-style.qdoc56
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-preferences-nim.qdoc10
-rw-r--r--doc/qtcreator/src/howto/creator-external-tools.qdoc35
-rw-r--r--doc/qtcreator/src/howto/creator-only/creator-how-to-contact-qt.qdoc49
-rw-r--r--doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc14
-rw-r--r--doc/qtcreator/src/overview/creator-only/creator-issues.qdoc18
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc8
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-how-to-create-ts-files.qdoc30
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc32
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc20
-rw-r--r--doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc44
-rw-r--r--doc/qtcreator/src/qtcreator-toc.qdoc2
-rw-r--r--doc/qtcreator/src/qtcreator.qdoc17
-rw-r--r--doc/qtcreator/src/qtquick/creator-preferences-qtquick-code-style.qdoc22
-rw-r--r--share/qtcreator/debugger/creatortypes.py4
-rw-r--r--share/qtcreator/debugger/dumper.py179
-rw-r--r--share/qtcreator/debugger/qttypes.py169
-rw-r--r--share/qtcreator/debugger/stdtypes.py30
-rw-r--r--src/libs/3rdparty/qtkeychain/qtkeychain.qbs86
-rw-r--r--src/libs/cplusplus/TypePrettyPrinter.cpp6
-rw-r--r--src/libs/libs.qbs1
-rw-r--r--src/libs/nanotrace/CMakeLists.txt7
-rw-r--r--src/libs/nanotrace/nanotracehr.h4
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp10
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h2
-rw-r--r--src/libs/solutions/tasking/networkquery.cpp15
-rw-r--r--src/libs/solutions/tasking/networkquery.h6
-rw-r--r--src/libs/utils/CMakeLists.txt7
-rw-r--r--src/libs/utils/aspects.cpp24
-rw-r--r--src/libs/utils/devicefileaccess.cpp93
-rw-r--r--src/libs/utils/devicefileaccess.h2
-rw-r--r--src/libs/utils/environment.cpp6
-rw-r--r--src/libs/utils/environment.h6
-rw-r--r--src/libs/utils/environmentfwd.h15
-rw-r--r--src/libs/utils/environmentmodel.cpp446
-rw-r--r--src/libs/utils/environmentmodel.h51
-rw-r--r--src/libs/utils/filepath.cpp30
-rw-r--r--src/libs/utils/fileutils.cpp28
-rw-r--r--src/libs/utils/fileutils.h4
-rw-r--r--src/libs/utils/namevaluedictionary.cpp22
-rw-r--r--src/libs/utils/namevaluedictionary.h4
-rw-r--r--src/libs/utils/namevalueitem.cpp60
-rw-r--r--src/libs/utils/namevalueitem.h26
-rw-r--r--src/libs/utils/namevaluemodel.cpp456
-rw-r--r--src/libs/utils/namevaluemodel.h65
-rw-r--r--src/libs/utils/namevaluesdialog.cpp6
-rw-r--r--src/libs/utils/namevaluesdialog.h10
-rw-r--r--src/libs/utils/namevaluevalidator.cpp5
-rw-r--r--src/libs/utils/namevaluevalidator.h6
-rw-r--r--src/libs/utils/projectintropage.cpp1
-rw-r--r--src/libs/utils/terminalinterface.cpp1
-rw-r--r--src/libs/utils/utils.qbs2
-rw-r--r--src/plugins/android/androidconfigurations.cpp9
-rw-r--r--src/plugins/android/androidsdkdownloader.cpp4
-rw-r--r--src/plugins/axivion/axivionoutputpane.cpp10
-rw-r--r--src/plugins/axivion/axivionplugin.cpp148
-rw-r--r--src/plugins/axivion/axivionplugin.h6
-rw-r--r--src/plugins/axivion/axivionprojectsettings.cpp32
-rw-r--r--src/plugins/axivion/axivionsettings.cpp23
-rw-r--r--src/plugins/bazaar/bazaarplugin.cpp56
-rw-r--r--src/plugins/bazaar/constants.h5
-rw-r--r--src/plugins/bineditor/bineditorplugin.cpp8
-rw-r--r--src/plugins/bineditor/bineditorwidget.cpp127
-rw-r--r--src/plugins/bineditor/bineditorwidget.h24
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.cpp2
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.cpp52
-rw-r--r--src/plugins/clangformat/clangformatglobalconfigwidget.cpp9
-rw-r--r--src/plugins/clangformat/clangformatutils.cpp26
-rw-r--r--src/plugins/clangformat/clangformatutils.h6
-rw-r--r--src/plugins/clearcase/clearcaseconstants.h1
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp63
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp25
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp55
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.h3
-rw-r--r--src/plugins/coreplugin/iversioncontrol.cpp150
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h38
-rw-r--r--src/plugins/coreplugin/iwelcomepage.cpp1
-rw-r--r--src/plugins/coreplugin/welcomepagehelper.cpp3
-rw-r--r--src/plugins/cppeditor/baseeditordocumentparser.h8
-rw-r--r--src/plugins/cppeditor/cppeditoroutline.cpp6
-rw-r--r--src/plugins/cppeditor/cppeditoroutline.h2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp4
-rw-r--r--src/plugins/cppeditor/cppmodelmanagersupport.h6
-rw-r--r--src/plugins/cppeditor/cppquickfix_test.cpp39
-rw-r--r--src/plugins/cppeditor/cppquickfix_test.h1
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp33
-rw-r--r--src/plugins/cvs/cvsplugin.cpp79
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp6
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp2
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp15
-rw-r--r--src/plugins/debugger/qml/qmlengine.h1
-rw-r--r--src/plugins/debugger/watchdata.cpp8
-rw-r--r--src/plugins/debugger/watchdata.h2
-rw-r--r--src/plugins/debugger/watchhandler.cpp44
-rw-r--r--src/plugins/diffeditor/diffeditor.h10
-rw-r--r--src/plugins/fossil/constants.h12
-rw-r--r--src/plugins/fossil/fossilclient.cpp12
-rw-r--r--src/plugins/fossil/fossilplugin.cpp90
-rw-r--r--src/plugins/git/branchmodel.cpp13
-rw-r--r--src/plugins/git/changeselectiondialog.cpp9
-rw-r--r--src/plugins/git/gerrit/gerritmodel.cpp2
-rw-r--r--src/plugins/git/gerrit/gerritplugin.cpp4
-rw-r--r--src/plugins/git/gitclient.cpp60
-rw-r--r--src/plugins/git/gitclient.h11
-rw-r--r--src/plugins/git/gitconstants.h15
-rw-r--r--src/plugins/git/gitgrep.cpp4
-rw-r--r--src/plugins/git/gitplugin.cpp176
-rw-r--r--src/plugins/git/gitsettings.cpp15
-rw-r--r--src/plugins/git/gitsettings.h2
-rw-r--r--src/plugins/git/mergetool.cpp2
-rw-r--r--src/plugins/mcusupport/mcukitaspect.cpp12
-rw-r--r--src/plugins/mcusupport/mcukitaspect.h4
-rw-r--r--src/plugins/mcusupport/mcukitmanager.cpp2
-rw-r--r--src/plugins/mercurial/constants.h6
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp5
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp89
-rw-r--r--src/plugins/perforce/perforceplugin.cpp68
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp3
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.h6
-rw-r--r--src/plugins/projectexplorer/environmentwidget.cpp8
-rw-r--r--src/plugins/projectexplorer/environmentwidget.h2
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp53
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.h2
-rw-r--r--src/plugins/projectexplorer/project.cpp4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs10
-rw-r--r--src/plugins/projectexplorer/projectimporter.h1
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.cpp2
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp3
-rw-r--r--src/plugins/qbsprojectmanager/qbseditor.cpp179
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp3
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp2
-rw-r--r--src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp13
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp11
-rw-r--r--src/plugins/remotelinux/linuxdevice.cpp140
-rw-r--r--src/plugins/remotelinux/linuxdevice.h10
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp65
-rw-r--r--src/plugins/squish/squishnavigationwidget.cpp29
-rw-r--r--src/plugins/subversion/subversionclient.cpp6
-rw-r--r--src/plugins/subversion/subversionconstants.h11
-rw-r--r--src/plugins/subversion/subversionplugin.cpp76
-rw-r--r--src/plugins/terminal/terminalpane.cpp12
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.h1
-rw-r--r--src/plugins/texteditor/displaysettingspage.cpp2
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.cpp21
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.h2
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.cpp29
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.h7
-rw-r--r--src/plugins/texteditor/textdocument.cpp8
-rw-r--r--src/plugins/texteditor/texteditor.cpp11
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp63
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.h8
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp33
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.h15
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp8
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.h6
-rw-r--r--src/plugins/vcsbase/vcscommand.h8
-rw-r--r--src/plugins/vcsbase/vcsoutputwindow.cpp2
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp1
-rw-r--r--src/share/3rdparty/package-manager/auto-setup.cmake1
m---------src/shared/qbs0
-rw-r--r--src/src.qbs1
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp27
-rw-r--r--tests/auto/environment/tst_environment.cpp26
-rw-r--r--tests/auto/texteditor/highlighter/tst_highlighter.cpp5
-rw-r--r--tests/auto/utils/filepath/tst_filepath.cpp41
-rw-r--r--tests/system/README5
-rw-r--r--tests/system/shared/build_utils.py6
-rw-r--r--tests/system/shared/debugger.py66
-rw-r--r--tests/system/suite_debugger/tst_simple_debug/test.py5
-rw-r--r--tests/system/suite_tools/tst_git_clone/test.py2
187 files changed, 2875 insertions, 2315 deletions
diff --git a/dist/changelog/changes-13.0.0.md b/dist/changelog/changes-13.0.0.md
index bd3fc5e3d5..793e47e97f 100644
--- a/dist/changelog/changes-13.0.0.md
+++ b/dist/changelog/changes-13.0.0.md
@@ -34,18 +34,18 @@ General
dock area
* Added the option to show file paths relative to the active project to the
search results view
- (QTCREATORBUG-29462)
+ ([QTCREATORBUG-29462](https://bugreports.qt.io/browse/QTCREATORBUG-29462))
* Added a `Current` button for selecting the directory of the current document
for searching in `Files in File System`
* Added `Copy to Clipboard` to the `About Qt Creator` dialog
- (QTCREATORBUG-29886)
+ ([QTCREATORBUG-29886](https://bugreports.qt.io/browse/QTCREATORBUG-29886))
Editing
-------
* Made syntax highlighting asynchronous
* Fixed that `Shift+Tab` did not always unindent
- (QTCREATORBUG-29742)
+ ([QTCREATORBUG-29742](https://bugreports.qt.io/browse/QTCREATORBUG-29742))
* Fixed that `Surround text selection with brackets` did nothing for `<`
* Fixed following links without a file name in documents without a file name
@@ -53,34 +53,39 @@ Editing
* Added the `Move Definition Here` refactoring action that moves an existing
function definition to its declaration
- (QTCREATORBUG-9515)
+ ([QTCREATORBUG-9515](https://bugreports.qt.io/browse/QTCREATORBUG-9515))
+* Added the `Enclose in QByteArrayLiteral` refactoring action
+ ([QTCREATORBUG-12995](https://bugreports.qt.io/browse/QTCREATORBUG-12995))
* Enabled the completion inside comments and strings by falling back to the
built-in code model
- (QTCREATORBUG-20828)
+ ([QTCREATORBUG-20828](https://bugreports.qt.io/browse/QTCREATORBUG-20828))
* Improved the position of headers inserted by refactoring operations
- (QTCREATORBUG-21826)
+ ([QTCREATORBUG-21826](https://bugreports.qt.io/browse/QTCREATORBUG-21826))
* Improved the coding style settings by separating Clang Format and other coding
style settings, and using a plain text editor for custom Clang Format settings
* Fixed that the class wizards used the class name for the include guard
instead of the file name
- (QTCREATORBUG-30140)
+ ([QTCREATORBUG-30140](https://bugreports.qt.io/browse/QTCREATORBUG-30140))
* Fixed that renaming classes did not change the include directive for the
renamed header in the source file
- (QTCREATORBUG-30154)
+ ([QTCREATORBUG-30154](https://bugreports.qt.io/browse/QTCREATORBUG-30154))
* Fixed issues with refactoring template functions
- (QTCREATORBUG-29408)
+ ([QTCREATORBUG-29408](https://bugreports.qt.io/browse/QTCREATORBUG-29408))
+* Fixed the `Add Definition` refactoring action for member functions of a
+ template class in a namespace
+ ([QTCREATORBUG-22076](https://bugreports.qt.io/browse/QTCREATORBUG-22076))
* Clangd
* Fixed that `Follow Symbol Under Cursor` only worked for exact matches
- (QTCREATORBUG-29814)
+ ([QTCREATORBUG-29814](https://bugreports.qt.io/browse/QTCREATORBUG-29814))
### QML
* Added navigation from QML components to the C++ code in the project
- (QTCREATORBUG-28086)
+ ([QTCREATORBUG-28086](https://bugreports.qt.io/browse/QTCREATORBUG-28086))
* Added a button for launching the QML Preview on the current document to
the editor tool bar
* Added color previews when hovering Qt color functions
- (QTCREATORBUG-29966)
+ ([QTCREATORBUG-29966](https://bugreports.qt.io/browse/QTCREATORBUG-29966))
### Python
@@ -95,7 +100,7 @@ Editing
### Widget Designer
* Fixed the indentation of the code that is inserted by `Go to slot`
- (QTCREATORBUG-11730)
+ ([QTCREATORBUG-11730](https://bugreports.qt.io/browse/QTCREATORBUG-11730))
### Compiler Explorer
@@ -108,6 +113,10 @@ Editing
endings) to the tool bar
* Added support for following links to the text editor
+### Binary Files
+
+* Fixed issues with large addresses
+
Projects
--------
@@ -115,41 +124,62 @@ Projects
was configured for kits that have vanished, as a replacement for the automatic
creation of "Replacement" kits
* Added the status of devices to the device lists
- (QTCREATORBUG-20941)
+ ([QTCREATORBUG-20941](https://bugreports.qt.io/browse/QTCREATORBUG-20941))
* Added the `Preferences > Build & Run > General > Application environment`
option for globally modifying the environment for all run configurations
- (QTCREATORBUG-29530)
+ ([QTCREATORBUG-29530](https://bugreports.qt.io/browse/QTCREATORBUG-29530))
* Added a file wizard for Qt translation (`.ts`) files
- (QTCREATORBUG-29775)
+ ([QTCREATORBUG-29775](https://bugreports.qt.io/browse/QTCREATORBUG-29775))
* Increased the maximum width of the target selector
- (QTCREATORBUG-30038)
+ ([QTCREATORBUG-30038](https://bugreports.qt.io/browse/QTCREATORBUG-30038))
* Fixed that the `Left` cursor key did not always collapse the current item
- (QTBUG-118515)
+ ([QTBUG-118515](https://bugreports.qt.io/browse/QTBUG-118515))
* Fixed inconsistent folder hierarchies in the project tree
- (QTCREATORBUG-29923)
+ ([QTCREATORBUG-29923](https://bugreports.qt.io/browse/QTCREATORBUG-29923))
### CMake
* Added support for custom output parsers for the configuration of projects
- (QTCREATORBUG-29992)
+ ([QTCREATORBUG-29992](https://bugreports.qt.io/browse/QTCREATORBUG-29992))
* Made cache variables available even if project configuration failed
+* CMake Presets
+ * Fixed `Reload CMake Presets` if the project was not configured yet
+ ([QTCREATORBUG-30238](https://bugreports.qt.io/browse/QTCREATORBUG-30238))
+ * Fixed that kits were accumulating on the project setup page
+ ([QTCREATORBUG-29535](https://bugreports.qt.io/browse/QTCREATORBUG-29535))
+ * Fixed that `binaryDir` was not handled for all presets
+ ([QTCREATORBUG-30236](https://bugreports.qt.io/browse/QTCREATORBUG-30236))
+ * Fixed a freeze with nested presets
+ ([QTCREATORBUG-30288](https://bugreports.qt.io/browse/QTCREATORBUG-30288))
+* Conan
+ * Fixed that backslashes were wrongly used for paths on Windows
+ ([QTCREATORBUG-30326](https://bugreports.qt.io/browse/QTCREATORBUG-30326))
+
+### Qbs
+
+* Added support for code completion with the Qbs language server
+ (QBS-395)
### Python
* Added `Generate Kit` to the Python interpreter preferences for generating a
Python kit with this interpreter
* Added the target setup page when loading unconfigured Python projects
+* Added a `requirements.txt` file to the application wizard
* Fixed that the same Python interpreter could be auto-detected multiple times
under different names
Debugging
---------
+* Added a `dr` locator filter for debugging a project
+
### C++
+* Added a pretty printer for `std::tuple`
* Fixed that breakpoints were not hit while the message dialog about missing
debug information was shown
- (QTCREATORBUG-30168)
+ ([QTCREATORBUG-30168](https://bugreports.qt.io/browse/QTCREATORBUG-30168))
### Debug Adapter Protocol
@@ -161,7 +191,7 @@ Analyzer
### Clang
* Added `Edit Checks as Strings` for Clazy
- (QTCREATORBUG-24846)
+ ([QTCREATORBUG-24846](https://bugreports.qt.io/browse/QTCREATORBUG-24846))
### Axivion
@@ -171,16 +201,19 @@ Terminal
--------
* Added `Select All` to the context menu
- (QTCREATORBUG-29922)
+ ([QTCREATORBUG-29922](https://bugreports.qt.io/browse/QTCREATORBUG-29922))
* Fixed the startup performance on Windows
- (QTCREATORBUG-29840)
+ ([QTCREATORBUG-29840](https://bugreports.qt.io/browse/QTCREATORBUG-29840))
* Fixed the integration of the `fish` shell
* Fixed that `Ctrl+W` closed the terminal even when shortcuts were blocked
- (QTCREATORBUG-30070)
+ ([QTCREATORBUG-30070](https://bugreports.qt.io/browse/QTCREATORBUG-30070))
+* Fixed issues with Windows Powershell
Version Control Systems
-----------------------
+* Added support for remote version control operations
+
### Git
* Added the upstream status for untracked branches to `Branches` view
@@ -195,22 +228,27 @@ Test Integration
Platforms
---------
+### Windows
+
+* Fixed Clang compiler ABI detection for WOA64
+ ([QTCREATORBUG-30060](https://bugreports.qt.io/browse/QTCREATORBUG-30060))
+
### Android
* Add support for target-based android-build directories (??? is that ready? Qt 6.8+ ???)
- (QTBUG-117443)
+ ([QTBUG-117443](https://bugreports.qt.io/browse/QTBUG-117443))
### iOS
* Fixed the detection of iOS 17 devices
* Fixed deployment and running applications for iOS 17 devices
(application output, debugging, and profiling are not supported)
- (QTCREATORBUG-29682)
+ ([QTCREATORBUG-29682](https://bugreports.qt.io/browse/QTCREATORBUG-29682))
### Remote Linux
* Fixed that debugging unnecessarily downloaded files from the remote system
- (QTCREATORBUG-29614)
+ ([QTCREATORBUG-29614](https://bugreports.qt.io/browse/QTCREATORBUG-29614))
Credits for these changes go to:
--------------------------------
@@ -238,6 +276,7 @@ Esa Törmänen
Fabian Kosmale
Friedemann Kleint
Henning Gruendl
+Ilya Kulakov
Jaroslaw Kobus
Johanna Vanhatapio
Karim Abdelrahman
@@ -249,6 +288,7 @@ Marcus Tillmanns
Mathias Hasselmann
Mats Honkamaa
Mehdi Salem
+Michael Weghorn
Miikka Heikkinen
Mitch Curtis
Olivier De Cannière
@@ -257,6 +297,7 @@ Pranta Dastider
Robert Löhning
Sami Shalayel
Samuel Jose Raposo Vieira Mira
+Samuel Mira
Serg Kryvonos
Shrief Gabr
Sivert Krøvel
diff --git a/doc/qtcreator/images/qtcreator-code-style-built-in-indenter.webp b/doc/qtcreator/images/qtcreator-code-style-built-in-indenter.webp
new file mode 100644
index 0000000000..f8eaa1dac5
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-code-style-built-in-indenter.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-style-clang-format-global.webp b/doc/qtcreator/images/qtcreator-code-style-clang-format-global.webp
index c012f83ce9..ddfc428e8c 100644
--- a/doc/qtcreator/images/qtcreator-code-style-clang-format-global.webp
+++ b/doc/qtcreator/images/qtcreator-code-style-clang-format-global.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-style-clang-format-project.webp b/doc/qtcreator/images/qtcreator-code-style-clang-format-project.webp
index dc4aefecd1..5c210034ec 100644
--- a/doc/qtcreator/images/qtcreator-code-style-clang-format-project.webp
+++ b/doc/qtcreator/images/qtcreator-code-style-clang-format-project.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png b/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png
deleted file mode 100644
index 34473e4bd8..0000000000
--- a/doc/qtcreator/images/qtcreator-code-style-settings-edit-qtquick.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-new-file-ts.webp b/doc/qtcreator/images/qtcreator-new-file-ts.webp
new file mode 100644
index 0000000000..3ad21a25d9
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-new-file-ts.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-options-code-style-qml.png b/doc/qtcreator/images/qtcreator-options-code-style-qml.png
deleted file mode 100644
index 93bf1bdfb8..0000000000
--- a/doc/qtcreator/images/qtcreator-options-code-style-qml.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-preferences-nim-code-style.webp b/doc/qtcreator/images/qtcreator-preferences-nim-code-style.webp
index d6937200c4..8fa9bb0837 100644
--- a/doc/qtcreator/images/qtcreator-preferences-nim-code-style.webp
+++ b/doc/qtcreator/images/qtcreator-preferences-nim-code-style.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-preferences-qtquick-code-style.webp b/doc/qtcreator/images/qtcreator-preferences-qtquick-code-style.webp
new file mode 100644
index 0000000000..574f30dd64
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-preferences-qtquick-code-style.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-project-kits.png b/doc/qtcreator/images/qtcreator-project-kits.png
deleted file mode 100644
index 16bf3a0dad..0000000000
--- a/doc/qtcreator/images/qtcreator-project-kits.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-projects-kits.webp b/doc/qtcreator/images/qtcreator-projects-kits.webp
index 6f863df9a5..827037b022 100644
--- a/doc/qtcreator/images/qtcreator-projects-kits.webp
+++ b/doc/qtcreator/images/qtcreator-projects-kits.webp
Binary files differ
diff --git a/doc/qtcreator/images/qtcreator-projects-vanished-targets.webp b/doc/qtcreator/images/qtcreator-projects-vanished-targets.webp
new file mode 100644
index 0000000000..f4acd354b1
--- /dev/null
+++ b/doc/qtcreator/images/qtcreator-projects-vanished-targets.webp
Binary files differ
diff --git a/doc/qtcreator/src/editors/creator-code-completion.qdoc b/doc/qtcreator/src/editors/creator-code-completion.qdoc
index 522565eecb..4281f77b67 100644
--- a/doc/qtcreator/src/editors/creator-code-completion.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-completion.qdoc
@@ -183,8 +183,7 @@
skipped when you type, and removed when you press \key Backspace.
\if defined(qtcreator)
- \sa {Complete CMake code},
- {Enclose selected code in curly braces, parentheses, or double quotes}, {Nim}
+ \sa {Complete CMake code}, {Enclose code in brackets or quotes}, {Nim}
\endif
\sa {Complete code}, {Snippets}
diff --git a/doc/qtcreator/src/editors/creator-only/creator-preferences-cpp-code-style.qdoc b/doc/qtcreator/src/editors/creator-only/creator-preferences-cpp-code-style.qdoc
index 44622426af..56e413b7e9 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-preferences-cpp-code-style.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-preferences-cpp-code-style.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -18,30 +18,39 @@
To specify global indentation settings for the C++ editor:
\list 1
- \li Select \preferences > \uicontrol {C++}.
+ \li Go to \preferences > \uicontrol {C++}.
\image qtcreator-code-style-clang-format-global.webp {Code Style preferences}
\li In \uicontrol {Formatting mode}, select:
\list
\li \uicontrol {Indenting Only} to only indent code.
\li \uicontrol {Full Formatting} to use the \key {Ctrl+I}
keyboard shortcut to format code instead of indenting.
- \li \uicontrol Disable to turn off ClangFormat.
+ \li \uicontrol {Use Built-In Indenter} to turn off ClangFormat.
\endlist
+ \li Select \uicontrol {Ignore files greater than} to make parsing faster
+ by ignoring big files. Specify the maximum size of files to parse.
\li To apply the formatting while you type, select
\uicontrol {Format while typing}.
\li To apply the formatting to the edited code when you save the file,
select \uicontrol {Format edited code on file save}.
\li To change the ClangFormat style globally for all projects,
- select \uicontrol {Override ClangFormat configuration file}.
- \li In the \uicontrol {Current settings} field, select the settings to
- modify and click \uicontrol Copy.
- \li Give a name to the settings and click \uicontrol OK.
- \li Click \uicontrol Edit to set
+ select \uicontrol {Use custom settings}.
+ \li In \uicontrol {Custom settings}, select the settings to change, and
+ then select \uicontrol Copy.
+ \li Give a name to the settings, and select \uicontrol OK.
+ \li In \uicontrol ClangFormat, edit the
\l{https://clang.llvm.org/docs/ClangFormatStyleOptions.html}
- {ClangFormat Style Options}.
+ {ClangFormat Style Options}. The live preview shows how the
+ preferences change the indentation.
+ If you enter invalid values, you see warning messages.
\endlist
- In the other tabs, you can specify how to:
+ \section1 Using Built-In Indenter
+
+ \image qtcreator-code-style-built-in-indenter.webp {Code Style preferences for built-in indenter}
+
+ If you select \uicontrol {Use Built-In Indenter} in
+ \uicontrol {Formatting mode}, you can specify how to:
\list
\li Interpret the \key Tab and \key Backspace key presses.
@@ -52,12 +61,9 @@
\li Bind pointers (*) and references (&) in types and declarations to
identifiers, type names, or left or right \c const or \c volatile
keywords.
- \li Name getter functions.
\endlist
- Use the live preview to see how the preferences change the indentation.
-
- \section1 Specifying Settings for Content
+ \section2 Specifying Settings for Content
You can indent public, protected, and private statements and declarations
related to them within classes.
@@ -67,24 +73,24 @@
\image qtcreator-code-style-content.png {Content preferences}
- \section1 Specifying Settings for Braces
+ \section2 Specifying Settings for Braces
You can indent class, namespace, enum and function declarations and code
blocks.
\image qtcreator-code-style-braces.png {Braces preferences}
- \section1 Specifying Settings for Switch Statements
+ \section2 Specifying Settings for Switch Statements
You can indent case or default statements, or statements or blocks related
to them within switch statements.
\image qtcreator-code-style-switch.png {Switch preferences}
- \section1 Specifying Alignment
+ \section2 Specifying Alignment
To align continuation lines to tokens after assignments, such as \c = or
- \c +=, select the \uicontrol {Align after assignments} check box. You can
+ \c +=, select \uicontrol {Align after assignments}. You can
specify additional settings for aligning continuation lines in the
\uicontrol General tab.
@@ -94,7 +100,7 @@
\image qtcreator-code-style-alignment.png {Alignment preferences}
- \section1 Binding Pointers and References
+ \section2 Binding Pointers and References
To bind pointers (\c *) and references (\c &) in types and declarations to
identifiers, type names, or left or right \c const or \c volatile keywords,
@@ -105,15 +111,6 @@
\image qtcreator-pointers-references.png {Pointers and References preferences}
- \section1 Creating Project-Specific ClangFormat Files
-
- To override the \c {.clang-format} file for a particular project, create a
- copy of the built-in style and edit its settings by selecting
- \uicontrol Projects > \uicontrol {Project Settings} >
- \uicontrol {Code Style} > \uicontrol Copy > \uicontrol Edit >
- \uicontrol {ClangFormat} >
- \uicontrol {Override ClangFormat configuration file}.
-
\section1 Creating ClangFormat Files from Command Line
You can create \c {.clang-format} files that have the configuration
@@ -124,5 +121,6 @@
clang-format -style=llvm -dump-config > .clang-format
\endcode
- \sa {Indent text or code}, {Behavior}, {Qt Quick Code Style}, {Nim}
+ \sa {Indent text or code}, {Specify code style}, {Behavior},
+ {Qt Quick Code Style}, {Nim}
*/
diff --git a/doc/qtcreator/src/editors/creator-only/creator-preferences-nim.qdoc b/doc/qtcreator/src/editors/creator-only/creator-preferences-nim.qdoc
index fa84ef87ca..b5a62ae20c 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-preferences-nim.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-preferences-nim.qdoc
@@ -16,11 +16,11 @@
To specify preferences for the Nim editor (experimental):
\list 1
- \li Select \preferences > \uicontrol Nim.
- \li In the \uicontrol {Current settings} field, select the settings to
- modify and click \uicontrol Copy.
+ \li Go to \preferences > \uicontrol Nim.
+ \li In \uicontrol {Custom settings}, select the settings to
+ modify, and then select \uicontrol Copy.
\image qtcreator-preferences-nim-code-style.webp {Nim Code Style preferences}
- \li Give a name to the settings and click \uicontrol OK.
+ \li Give a name to the settings, and select \uicontrol OK.
\li Specify how to interpret the \key Tab key presses and how to align
continuation lines.
\li Select \uicontrol OK to save the settings.
@@ -36,7 +36,7 @@
completion.
To use Nimsuggest, you must install it on the development PC and enter the
- path to the tool executable in the \uicontrol Path field.
+ path to the tool executable in \uicontrol Path.
\image qtcreator-preferences-nim-tools.webp
diff --git a/doc/qtcreator/src/howto/creator-external-tools.qdoc b/doc/qtcreator/src/howto/creator-external-tools.qdoc
index 3f29dfc57b..dda7eeb62a 100644
--- a/doc/qtcreator/src/howto/creator-external-tools.qdoc
+++ b/doc/qtcreator/src/howto/creator-external-tools.qdoc
@@ -134,18 +134,30 @@
\title Use Qt Linguist
+ Most of the text to translate in an application consists of either single
+ words or short phrases. These typically appear as window titles, menu items,
+ tooltips, and labels to buttons, checkboxes, and radio buttons.
+
+ You mark the phrases as translatable in the QML and C++ source code. Qt
+ localization tools provide context information for each of the phrases to
+ help the translator understand their meaning. You can add comments to the
+ phrases.
+
+ Translation files contain all the user-visible text and keyboard shortcuts
+ in an application and translations of that text.
+
When you \l{Creating Projects}{create a new project}, you can automatically
- generate a translation source file (TS) for one language. You can add other
- languages later by editing the project file.
+ generate a translation source file (TS) for one language. To add other
+ languages, edit the project file or go to \uicontrol File >
+ \uicontrol {New File}.
To open TS files in Qt Linguist, right-click a TS file in the
- \uicontrol Projects or \uicontrol {File System} view and select
+ \uicontrol Projects or \uicontrol {File System} view and go to
\uicontrol {Open With} > \uicontrol {Qt Linguist} in the context menu.
- For more information about Qt Linguist, see \l{Qt Linguist Manual}.
\section1 Use lupdate and lrelease
- You can use the Qt Linguist release manager tools, lupdate and lrelease,
+ Use the Qt Linguist release manager tools, lupdate and lrelease,
directly from \QC. The lupdate tool synchronizes source
code and translations. The lrelease tool creates run-time
translation files for use by the released application.
@@ -156,22 +168,27 @@
{Qt6::LinguistTools}.
By default, the project .pro file is passed to the tools as an argument. To
- specify other command-line arguments for the tools, select \uicontrol Tools >
+ specify other command-line arguments for the tools, go to \uicontrol Tools >
\uicontrol External > \uicontrol Configure.
\section2 Synchronize TS files
To synchronize TS files from a translator with the
- application code, select \uicontrol Tools > \uicontrol External >
+ application code, go to \uicontrol Tools > \uicontrol External >
\uicontrol Linguist > \uicontrol {Update Translations (lupdate)}.
\section2 Generate QM files
To generate from the TS files Qt message (QM) files that can be used by an
- application, select \uicontrol Tools > \uicontrol External >
+ application, go to \uicontrol Tools > \uicontrol External >
\uicontrol Linguist > \uicontrol {Release Translations (lrelease)}.
- \sa {Use external tools}
+ \if defined(qtcreator)
+ \sa {Add translation files}
+ \endif
+
+ \sa {Use external tools}, {Internationalization with Qt},
+ {Qt Linguist Manual}
*/
/*!
diff --git a/doc/qtcreator/src/howto/creator-only/creator-how-to-contact-qt.qdoc b/doc/qtcreator/src/howto/creator-only/creator-how-to-contact-qt.qdoc
new file mode 100644
index 0000000000..93b8844f24
--- /dev/null
+++ b/doc/qtcreator/src/howto/creator-only/creator-how-to-contact-qt.qdoc
@@ -0,0 +1,49 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page creator-how-to-contact-qt.html
+ \previouspage creator-how-tos.html
+
+ \ingroup creator-how-to-use
+
+ \title Contact Qt
+
+ To report bugs and tell us what you think about \QC and Qt,
+ go to \uicontrol Help.
+
+ \section1 Report bugs and suggest improvements
+
+ To report bugs and add suggestions for improvement to the
+ \l{https://bugreports.qt.io/}{Qt Project Bug Tracker},
+ go to \uicontrol Help > \uicontrol {Report Bug}.
+
+ To copy information about your \QC version that you can paste to the bug
+ report, go to \uicontrol Help > \uicontrol {About \QC} and select
+ \uicontrol {Copy and Close}.
+
+ To copy detailed information about your system that you can paste to the bug
+ report, go to \uicontrol Help > \uicontrol {System Information} and select
+ \uicontrol {Copy to Clipboard}.
+
+ To get commercial Qt support, go to \uicontrol Help >
+ \uicontrol {Commercial Qt Support} and create a service request.
+ To check your licenses and services, go to \uicontrol Help >
+ \uicontrol {Qt Account}.
+
+ \section1 Give feedback
+
+ To rate \QC and send us feedback, go to \uicontrol Help >
+ \uicontrol {Give Feedback}.
+
+ Or, give feedback from your Qt account.
+
+ \section1 Join discussions
+
+ To join the \l{https://lists.qt-project.org/listinfo/qt-creator}
+ {\QC mailing list} or \l{https://web.libera.chat/#qt-creator}
+ {#qt-creator} channel on Libera.Chat IRC, go to \uicontrol Help >
+ \uicontrol Contact.
+
+ \sa {Pasting and Fetching Code Snippets}, {Technical Support}
+*/
diff --git a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
index 8de74cf842..0643c3a152 100644
--- a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
+++ b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc
@@ -77,7 +77,7 @@
\generatelist creator-how-to-projects-create
- \section2 Create Files
+ \section2 Add Files
\generatelist creator-how-to-projects-files
@@ -288,16 +288,18 @@
\ingroup creator-how-to-edit
- \title Enclose selected code in curly braces, parentheses, or double quotes
+ \title Enclose code in brackets or quotes
- When you have selected code and enter one of the following opening
- characters, the matching closing character is added automatically
- at the end of the selection:
+ Select code and enter one of the following opening characters to add
+ the matching closing character at the end of the selection:
\list
- \li {
\li (
+ \li {
+ \li [
+ \li <
\li "
+ \li '
\endlist
To specify whether to automatically insert matching characters,
diff --git a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
index db2af2c5eb..de7c8b45d3 100644
--- a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
+++ b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
// **********************************************************************
@@ -8,20 +8,22 @@
// **********************************************************************
/*!
- \previouspage creator-how-tos.html
\page creator-known-issues.html
- \nextpage creator-glossary.html
+ \previouspage creator-reference.html
+
+ \ingroup creator-reference
\title Known Issues
- This section lists known issues in \QC version \qtcversion. The development
- team is aware of them, and therefore, you do not need to report them as
- bugs.
+ \brief Known issues in \QC version \qtcversion.
- For a list of fixed issues and added features, see the changelog file in
- the \c{qtcreator\dist} folder or the \l{https://bugreports.qt.io}
+ The \QC development team is aware of the issues described here, and
+ therefore, you do not need to report them in the \l{https://bugreports.qt.io}
{Qt Project Bug Tracker}.
+ For a list of fixed issues and added features, go to \uicontrol Help >
+ \uicontrol {Change Log}.
+
\section1 General Issues
\list
diff --git a/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc b/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
index 6b953d4401..d03263d462 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-files-creating.qdoc
@@ -43,8 +43,8 @@
\li \uicontrol {Qt}
\li Source and header files for item, table,
or list models, \QD forms and a matching classes for Qt Widgets
- projects, Qt resource files, as well as QML and JavaScript files
- for Qt Quick projects.
+ projects, Qt resource and translation files, as well as QML and
+ JavaScript files for Qt Quick projects.
\row
\li \uicontrol {Compiler Explorer}
\li Example setup for using Compiler Explorer to compile C++ or Python
@@ -74,9 +74,7 @@
\li Empty Nim source and script files.
\endtable
- \sa {Create compiler explorer sessions}, {Create C++ classes},
- {Create OpenGL fragment and vertex shaders}, {Create resource files},
- {Create UML-style models}, {Create vcpkg manifest files},
+ \sa {Add Files}{How To: Add Files}, {Create UML-style models},
{Use project wizards}
*/
diff --git a/doc/qtcreator/src/projects/creator-only/creator-how-to-create-ts-files.qdoc b/doc/qtcreator/src/projects/creator-only/creator-how-to-create-ts-files.qdoc
new file mode 100644
index 0000000000..cb4471aeb5
--- /dev/null
+++ b/doc/qtcreator/src/projects/creator-only/creator-how-to-create-ts-files.qdoc
@@ -0,0 +1,30 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page creator-how-to-add-ts-files.html
+ \previouspage creator-how-tos.html
+
+ \ingroup creator-how-to-projects-files
+
+ \title Add translation files
+
+ When you \l{Creating Projects}{create a new project}, you can automatically
+ generate a translation source file (TS) for one language. To add other
+ languages later, use a file wizard.
+
+ To create a translation source (TS) file for a language:
+
+ \list 1
+ \li Go to \uicontrol File > \uicontrol {New File}.
+ \li Select \uicontrol Qt > \uicontrol {Qt Translation File} >
+ \uicontrol Choose.
+ \li In \uicontrol Language, select a language and territory (\e locale).
+ \image qtcreator-new-file-ts.webp {Select language for a TS file}
+ \endlist
+
+ You can see the file name in \uicontrol {Translation file}.
+
+ \sa {Create files}, {Use project wizards}, {Use Qt Linguist},
+ {Internationalization with Qt}, {Qt Linguist Manual}
+*/
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
index e60d5c49c5..88e0354aaa 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-code-style.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
// **********************************************************************
@@ -19,16 +19,15 @@
and editor the file opens in. \QC opens C++ files in \uicontrol Edit mode
in the C++ code editor and QML files in the Qt Quick editor.
- You can specify indentation for:
+ Specify indentation for:
\list
\li C++ files
\li QML files
\li Nim files
- \li Other text files
\endlist
- You can specify code style either globally or separately for each project.
+ Specify code style either globally or separately for each project.
You can specify several sets of code style settings and easily switch between
them. In addition, you can import and export code style settings.
@@ -36,31 +35,30 @@
\list 1
- \li Select \uicontrol Projects > \uicontrol {Project Settings} >
+ \li Go to \uicontrol Projects > \uicontrol {Project Settings} >
\uicontrol {Code Style}.
\image qtcreator-code-style-clang-format-project.webp {Code Style settings in Projects mode}
- \li In the \uicontrol Language field, select \uicontrol C++,
+ \li In \uicontrol Language, select \uicontrol C++,
\uicontrol {Qt Quick}, or \uicontrol Nim.
- \li Deselect the \uicontrol {Use global settings} check box.
+ \li For C++, clear \uicontrol {Use global settings} to use the
+ \c {.clang-format} file for the project.
- \li In the \uicontrol {Current settings} field, select the settings to modify
- and click \uicontrol Copy.
-
- \li Give a name to the settings and click \uicontrol OK.
-
- \li Click \uicontrol Edit to specify a code style for the project.
+ \li To override the project's \c {.clang-format} file,
+ select \uicontrol {Use custom settings}.
+ \li In \uicontrol {Custom settings}, select the settings to use for the
+ project.
\endlist
In rare cases, ClangFormat can trip over a code construct and
trigger a \QC crash. If that happens for your project, select
- \uicontrol Disable as the formatting mode to switch
- ClangFormat off for the project. If you can reproduce the crash,
- please select \uicontrol Help > \uicontrol {Report Bug} to report
- the bug and and attach the code that triggers the crash.
+ \uicontrol {Use Built-In Indenter} in \uicontrol {Formatting mode} to
+ turn off ClangFormat for the project. If you can reproduce the crash,
+ go to \uicontrol Help > \uicontrol {Report Bug} to report
+ the bug and attach the code that triggers the crash to the bug report.
\sa {Indent text or code}, {Edit MIME types}, {C++ Code Style},
{Qt Quick Code Style}, {Nim}
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
index 6a883e8666..3f200320fc 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-environment.qdoc
@@ -87,7 +87,25 @@
To run in a clean system environment, select \uicontrol {Clean Environment}.
- \section2 Run on devices
+ \section2 Set the environment for all run configurations
+
+ To set environment variables for running and debugging applications, so
+ that they don't affect \QC itself, set environment variables for run
+ configurations of all projects:
+
+ \list 1
+ \li Go to \preferences > \uicontrol {Build & Run} > \uicontrol General.
+ \li Select \uicontrol Change in \uicontrol {Application environment}.
+ \li Set environment variables in \uicontrol {Edit Environment}.
+ \image qtcreator-edit-environment.webp {Edit Environment dialog}
+ \endlist
+
+ For example, set \c QT_FORCE_STDERR_LOGGING=1 to see application output
+ in \l {Application Output} instead of a journal or system log.
+
+ Or, set \c QT_MESSAGE_PATTERN to add information to debugging messages.
+
+ \section2 Use device environment
When running on a mobile device connected to the development host, \QC
fetches information about the \uicontrol {Device Environment} from the device.
diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
index 458e21c0a0..27ff2fccff 100644
--- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
+++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-overview.qdoc
@@ -112,21 +112,13 @@
lists the kits that are compatible with your project. To activate one or more
kits, click them.
- \image qtcreator-project-kits.png {List of kits in Projects mode sidebar}
+ \image qtcreator-projects-kits.webp {List of kits in Projects mode sidebar}
The list displays kits from \preferences >
\uicontrol Kits. Warning and error icons indicate that the kit configuration
is not suitable for the project type. To view the warning and error messages,
move the mouse pointer over the kit name.
- In the list of kits, you may see entries described as \e {Replacement for
- <kit-name>}. \QC generates them to save your project-specific settings,
- such as custom build flags or run configuration arguments that would
- disappear if the corresponding kits were simply removed when you remove
- Qt versions while updating your Qt installation. You can modify the kit
- configuration to use a currently installed Qt version and save the kit
- under a new name.
-
\section1 Manage kits
To modify kit configuration or to \l{Add kits}{add kits} to the list or to
@@ -134,10 +126,11 @@
Each kit consists of a set of values that define one environment, such as a
\l{glossary-device}{device}, \l{Add compilers}{compiler},
- \l{Add debuggers}{debugger}, and \l{Add Qt versions}{Qt version}.
+ \l{Add debuggers}{debugger}, and \l{Add Qt versions}{Qt version}, as well
+ as steps for building, deploying, and running applications.
- To copy the build and run settings for a kit to another kit, select
- \uicontrol {Copy Steps from Other Kit} in the context menu.
+ To copy the build, deploy, and run steps from another kit, select
+ \uicontrol {Copy Steps from Another Kit} in the context menu.
To deactivate a kit, select \uicontrol {Disable Kit for Project} in the
context menu.
@@ -148,5 +141,32 @@
To import an existing build for the project, select
\uicontrol {Import Existing Build}.
+ \section1 Copy custom settings from vanished targets
+
+ \QC creates a list of \uicontrol {Vanished Targets} to save project-specific
+ settings, such as custom build flags or run configuration arguments, that
+ would disappear if \QOI removes the corresponding kits when you update your
+ Qt installation.
+
+ \image qtcreator-projects-vanished-targets.webp {Vanished Targets in Projects}
+
+ Go to one of the following options in the context menu to restore the
+ project's settings:
+
+ \list
+ \li \uicontrol {Create a New Kit} creates a new kit with the same name
+ for the same device type, with the original build, deploy, and run
+ steps. Other kit settings are not restored.
+ \li \uicontrol {Copy Steps to Another Kit} copies the build, deploy, and
+ run steps to another kit.
+ \endlist
+
+ To remove vanished targets, go to \uicontrol {Remove Vanished Target} or
+ \uicontrol {Remove All Vanished Targets} in the context menu.
+
+ \note Since version 13.0, \QC does not create \e {replacement kits}, but you
+ might still see them listed for existing projects. You can copy the build,
+ deploy, and run steps from them to other kits.
+
\sa {Add kits}, {Configuring Projects}, {kits-tab}{Kits}
*/
diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc
index 5f2daf2737..ec8408795f 100644
--- a/doc/qtcreator/src/qtcreator-toc.qdoc
+++ b/doc/qtcreator/src/qtcreator-toc.qdoc
@@ -157,7 +157,7 @@
\list
\li Create Projects
\generatelist creator-how-to-projects-create
- \li Create Files
+ \li Add Files
\generatelist creator-how-to-projects-files
\li Configure Projects
\generatelist creator-how-to-projects-configure
diff --git a/doc/qtcreator/src/qtcreator.qdoc b/doc/qtcreator/src/qtcreator.qdoc
index 840ef3805b..7c2d8ce775 100644
--- a/doc/qtcreator/src/qtcreator.qdoc
+++ b/doc/qtcreator/src/qtcreator.qdoc
@@ -86,6 +86,7 @@
\endlist
\li \b {\l{Reference}}
\list
+ \li \l {Acknowledgements}
\li \l {Build Systems}
\li \l {Command-Line Options}
\li \l {Custom Wizards}
@@ -94,21 +95,5 @@
\li \l {Supported Platforms}
\li \l {Reference}{See More...}
\endlist
- \row
- \li {4,1} \b {Contact Us}
- \list
- \li To report bugs and suggestions to the
- \l{https://bugreports.qt.io/}{Qt Project Bug Tracker},
- select \uicontrol Help > \uicontrol {Report Bug}.
- \li To copy and paste detailed information about your
- system to the bug report, select \uicontrol Help >
- \uicontrol {System Information}.
- \li To join the \l{https://lists.qt-project.org/listinfo/qt-creator}
- {\QC mailing list} or \l{https://web.libera.chat/#qt-creator}
- {#qt-creator} channel on Libera.Chat IRC, select
- \uicontrol Help > \uicontrol Contact.
- \li For credits and a list of third-party libraries, see
- \l {Acknowledgements}.
- \endlist
\endtable
*/
diff --git a/doc/qtcreator/src/qtquick/creator-preferences-qtquick-code-style.qdoc b/doc/qtcreator/src/qtquick/creator-preferences-qtquick-code-style.qdoc
index 6ea1325162..70655b99ed 100644
--- a/doc/qtcreator/src/qtquick/creator-preferences-qtquick-code-style.qdoc
+++ b/doc/qtcreator/src/qtquick/creator-preferences-qtquick-code-style.qdoc
@@ -19,21 +19,17 @@
To specify QML code style globally:
\list 1
- \li Select \preferences > \uicontrol {Qt Quick}.
- \li In the \uicontrol {Current settings} field, select the settings to
- modify and click \uicontrol Copy.
- \image qtcreator-options-code-style-qml.png {QML Code Style preferences}
- \li Give a name to the settings and click \uicontrol OK.
- \li Click \uicontrol Edit to specify code style settings for the project.
- \image qtcreator-code-style-settings-edit-qtquick.png {Edit Code Style dialog}
+ \li Go to \preferences > \uicontrol {Qt Quick} > \uicontrol {Code Style}.
+ \li In \uicontrol {Custom settings}, select the settings to
+ modify, and then select \uicontrol Copy.
+ \image qtcreator-preferences-qtquick-code-style.webp {Qt Quick Code Style preferences}
+ \li Give a name to the settings, and select \uicontrol OK.
+ \li Specify how to interpret the \key Tab key presses and how to align
+ continuation lines.
+ \li In \uicontrol {Line length}, set the maximum line length for
+ code lines.
\endlist
- You can specify how to interpret the \key Tab key presses and how to align
- continuation lines.
-
- In \uicontrol {Line length}, you can adjust the maximum line length for
- code lines.
-
To override the global preferences for a particular project, select
\uicontrol Projects > \uicontrol {Code Style}.
diff --git a/share/qtcreator/debugger/creatortypes.py b/share/qtcreator/debugger/creatortypes.py
index 24c16ce009..ba5b53450b 100644
--- a/share/qtcreator/debugger/creatortypes.py
+++ b/share/qtcreator/debugger/creatortypes.py
@@ -204,7 +204,7 @@ def qdump__CPlusPlus__Internal__Value(d, value):
def qdump__Utils__FilePath(d, value):
data, path_len, scheme_len, host_len = d.split("{@QString}IHH", value)
- elided, enc = d.encodeStringHelper(data, d.displayStringLimit)
+ length, enc = d.encodeStringHelper(data, d.displayStringLimit)
# enc is concatenated path + scheme + host
if scheme_len:
scheme_pos = path_len * 4
@@ -221,7 +221,7 @@ def qdump__Utils__FilePath(d, value):
val += path_enc
else:
val = enc
- d.putValue(val, "utf16", elided=elided)
+ d.putValue(val, "utf16", length=length)
d.putPlainChildren(value)
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 1fd42848d4..ad25ad2dbe 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -44,15 +44,15 @@ class ReportItem():
subsequent better guesses during a putItem() run.
"""
- def __init__(self, value=None, encoding=None, priority=-100, elided=None):
+ def __init__(self, value=None, encoding=None, priority=-100, length=None):
self.value = value
self.priority = priority
self.encoding = encoding
- self.elided = elided
+ self.length = length
def __str__(self):
- return 'Item(value: %s, encoding: %s, priority: %s, elided: %s)' \
- % (self.value, self.encoding, self.priority, self.elided)
+ return 'Item(value: %s, encoding: %s, priority: %s, length: %s)' \
+ % (self.value, self.encoding, self.priority, self.length)
class Timer():
@@ -349,8 +349,8 @@ class DumperBase():
else:
if self.currentValue.encoding is not None:
self.put('valueencoded="%s",' % self.currentValue.encoding)
- if self.currentValue.elided:
- self.put('valueelided="%s",' % self.currentValue.elided)
+ if self.currentValue.length:
+ self.put('valuelen="%s",' % self.currentValue.length)
self.put('value="%s",' % self.currentValue.value)
except:
pass
@@ -376,7 +376,7 @@ class DumperBase():
b = bytes(bytearray.fromhex(value))
value = codecs.decode(b, 'utf-16')
self.put('"%s"' % value)
- if self.currentValue.elided:
+ if self.currentValue.length:
self.put('...')
if self.currentType.value:
@@ -545,40 +545,40 @@ class DumperBase():
# assume no Qt 3 support by default
return False
- # Clamps size to limit.
- def computeLimit(self, size, limit):
+ # Clamps length to limit.
+ def computeLimit(self, length, limit=0):
if limit == 0:
limit = self.displayStringLimit
- if limit is None or size <= limit:
- return 0, size
- return size, limit
+ if limit is None or length <= limit:
+ return length
+ return limit
def vectorData(self, value):
if self.qtVersion() >= 0x060000:
- data, size, alloc = self.qArrayData(value)
+ data, length, alloc = self.qArrayData(value)
elif self.qtVersion() >= 0x050000:
vector_data_ptr = self.extractPointer(value)
if self.ptrSize() == 4:
- (ref, size, alloc, offset) = self.split('IIIp', vector_data_ptr)
+ (ref, length, alloc, offset) = self.split('IIIp', vector_data_ptr)
else:
- (ref, size, alloc, pad, offset) = self.split('IIIIp', vector_data_ptr)
+ (ref, length, alloc, pad, offset) = self.split('IIIIp', vector_data_ptr)
alloc = alloc & 0x7ffffff
data = vector_data_ptr + offset
else:
vector_data_ptr = self.extractPointer(value)
- (ref, alloc, size) = self.split('III', vector_data_ptr)
+ (ref, alloc, length) = self.split('III', vector_data_ptr)
data = vector_data_ptr + 16
- self.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
- return data, size
+ self.check(0 <= length and length <= alloc and alloc <= 1000 * 1000 * 1000)
+ return data, length
def qArrayData(self, value):
if self.qtVersion() >= 0x60000:
- dd, data, size = self.split('ppp', value)
+ dd, data, length = self.split('ppp', value)
if dd:
_, _, alloc = self.split('iip', dd)
else: # fromRawData
- alloc = size
- return data, size, alloc
+ alloc = length
+ return data, length, alloc
return self.qArrayDataHelper(self.extractPointer(value))
def qArrayDataHelper(self, array_data_ptr):
@@ -586,10 +586,10 @@ class DumperBase():
if self.qtVersion() >= 0x050000:
# QTypedArray:
# - QtPrivate::RefCount ref
- # - int size
+ # - int length
# - uint alloc : 31, capacityReserved : 1
# - qptrdiff offset
- (ref, size, alloc, offset) = self.split('IIpp', array_data_ptr)
+ (ref, length, alloc, offset) = self.split('IIpp', array_data_ptr)
alloc = alloc & 0x7ffffff
data = array_data_ptr + offset
if self.ptrSize() == 4:
@@ -599,43 +599,42 @@ class DumperBase():
elif self.qtVersion() >= 0x040000:
# Data:
# - QBasicAtomicInt ref;
- # - int alloc, size;
+ # - int alloc, length;
# - [padding]
# - char *data;
if self.ptrSize() == 4:
- (ref, alloc, size, data) = self.split('IIIp', array_data_ptr)
+ (ref, alloc, length, data) = self.split('IIIp', array_data_ptr)
else:
- (ref, alloc, size, pad, data) = self.split('IIIIp', array_data_ptr)
+ (ref, alloc, length, pad, data) = self.split('IIIIp', array_data_ptr)
else:
# Data:
# - QShared count;
# - QChar *unicode
# - char *ascii
# - uint len: 30
- (dummy, dummy, dummy, size) = self.split('IIIp', array_data_ptr)
- size = self.extractInt(array_data_ptr + 3 * self.ptrSize()) & 0x3ffffff
- alloc = size # pretend.
+ (dummy, dummy, dummy, length) = self.split('IIIp', array_data_ptr)
+ length = self.extractInt(array_data_ptr + 3 * self.ptrSize()) & 0x3ffffff
+ alloc = length # pretend.
data = self.extractPointer(array_data_ptr + self.ptrSize())
- return data, size, alloc
+ return data, length, alloc
def encodeStringHelper(self, value, limit):
- data, size, alloc = self.qArrayData(value)
+ data, length, alloc = self.qArrayData(value)
if alloc != 0:
- self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000)
- elided, shown = self.computeLimit(2 * size, 2 * limit)
- return elided, self.readMemory(data, shown)
+ self.check(0 <= length and length <= alloc and alloc <= 100 * 1000 * 1000)
+ shown = self.computeLimit(2 * length, 2 * limit)
+ return length, self.readMemory(data, shown)
def encodeByteArrayHelper(self, value, limit):
- data, size, alloc = self.qArrayData(value)
+ data, length, alloc = self.qArrayData(value)
if alloc != 0:
- self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000)
- elided, shown = self.computeLimit(size, limit)
- return elided, self.readMemory(data, shown)
+ self.check(0 <= length and length <= alloc and alloc <= 100 * 1000 * 1000)
+ shown = self.computeLimit(length, limit)
+ return length, self.readMemory(data, shown)
- def putCharArrayValue(self, data, size, charSize,
+ def putCharArrayValue(self, data, length, charSize,
displayFormat=DisplayFormat.Automatic):
- bytelen = size * charSize
- elided, shown = self.computeLimit(bytelen, self.displayStringLimit)
+ shown = self.computeLimit(length, self.displayStringLimit)
mem = self.readMemory(data, shown)
if charSize == 1:
if displayFormat in (DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String):
@@ -650,13 +649,13 @@ class DumperBase():
encodingType = 'ucs4'
#childType = 'int'
- self.putValue(mem, encodingType, elided=elided)
+ self.putValue(mem, encodingType, length=length)
if displayFormat in (
DisplayFormat.SeparateLatin1String,
DisplayFormat.SeparateUtf8String,
DisplayFormat.Separate):
- elided, shown = self.computeLimit(bytelen, 100000)
+ shown = self.computeLimit(length, 100000)
self.putDisplay(encodingType + ':separate', self.readMemory(data, shown))
def putCharArrayHelper(self, data, size, charType,
@@ -676,15 +675,15 @@ class DumperBase():
return self.hexencode(bytes(self.readRawMemory(addr, size)))
def encodeByteArray(self, value, limit=0):
- elided, data = self.encodeByteArrayHelper(value, limit)
+ _, data = self.encodeByteArrayHelper(value, limit)
return data
def putByteArrayValue(self, value):
- elided, data = self.encodeByteArrayHelper(value, self.displayStringLimit)
- self.putValue(data, 'latin1', elided=elided)
+ length, data = self.encodeByteArrayHelper(value, self.displayStringLimit)
+ self.putValue(data, 'latin1', length=length)
def encodeString(self, value, limit=0):
- elided, data = self.encodeStringHelper(value, limit)
+ _, data = self.encodeStringHelper(value, limit)
return data
def encodedUtf16ToUtf8(self, s):
@@ -730,8 +729,8 @@ class DumperBase():
return inner
def putStringValue(self, value):
- elided, data = self.encodeStringHelper(value, self.displayStringLimit)
- self.putValue(data, 'utf16', elided=elided)
+ length, data = self.encodeStringHelper(value, self.displayStringLimit)
+ self.putValue(data, 'utf16', length=length)
def putPtrItem(self, name, value):
with SubItem(self, name):
@@ -900,12 +899,12 @@ class DumperBase():
if not self.isInt(thing):
raise RuntimeError('Expected an integral value, got %s' % type(thing))
- def readToFirstZero(self, base, tsize, maximum):
+ def readToFirstZero(self, base, typesize, maximum):
self.checkIntType(base)
- self.checkIntType(tsize)
+ self.checkIntType(typesize)
self.checkIntType(maximum)
- code = self.packCode + (None, 'b', 'H', None, 'I')[tsize]
+ code = self.packCode + (None, 'b', 'H', None, 'I')[typesize]
#blob = self.readRawMemory(base, 1)
blob = bytes()
while maximum > 1:
@@ -916,8 +915,8 @@ class DumperBase():
maximum = int(maximum / 2)
self.warn('REDUCING READING MAXIMUM TO %s' % maximum)
- #DumperBase.warn('BASE: 0x%x TSIZE: %s MAX: %s' % (base, tsize, maximum))
- for i in range(0, maximum, tsize):
+ #DumperBase.warn('BASE: 0x%x TSIZE: %s MAX: %s' % (base, typesize, maximum))
+ for i in range(0, maximum, typesize):
t = struct.unpack_from(code, blob, i)[0]
if t == 0:
return 0, i, self.hexencode(blob[:i])
@@ -925,9 +924,9 @@ class DumperBase():
# Real end is unknown.
return -1, maximum, self.hexencode(blob[:maximum])
- def encodeCArray(self, p, tsize, limit):
- elided, shown, blob = self.readToFirstZero(p, tsize, limit)
- return elided, blob
+ def encodeCArray(self, p, typesize, limit):
+ length, shown, blob = self.readToFirstZero(p, typesize, limit)
+ return length, blob
def putItemCount(self, count, maximum=1000000000):
# This needs to override the default value, so don't use 'put' directly.
@@ -1043,12 +1042,12 @@ class DumperBase():
self.currentType.value = typish.name
self.currentType.priority = priority
- def putValue(self, value, encoding=None, priority=0, elided=None):
+ def putValue(self, value, encoding=None, priority=0, length=None):
# Higher priority values override lower ones.
- # elided = 0 indicates all data is available in value,
+ # length = None indicates all data is available in value,
# otherwise it's the true length.
if priority >= self.currentValue.priority:
- self.currentValue = ReportItem(value, encoding, priority, elided)
+ self.currentValue = ReportItem(value, encoding, priority, length)
def putSpecialValue(self, encoding, value='', children=None):
self.putValue(value, encoding)
@@ -1226,13 +1225,13 @@ class DumperBase():
return False
- def putSimpleCharArray(self, base, size=None):
- if size is None:
- elided, shown, data = self.readToFirstZero(base, 1, self.displayStringLimit)
+ def putSimpleCharArray(self, base, length=None):
+ if length is None:
+ length, shown, data = self.readToFirstZero(base, 1, self.displayStringLimit)
else:
- elided, shown = self.computeLimit(int(size), self.displayStringLimit)
+ shown = self.computeLimit(length)
data = self.readMemory(base, shown)
- self.putValue(data, 'latin1', elided=elided)
+ self.putValue(data, 'latin1', length=length)
def putDisplay(self, editFormat, value):
self.putField('editformat', editFormat)
@@ -1248,8 +1247,8 @@ class DumperBase():
if targetType.name in ('char', 'signed char', 'unsigned char', 'uint8_t', 'CHAR'):
# Use UTF-8 as default for char *.
self.putType(typeName)
- (elided, shown, data) = self.readToFirstZero(ptr, 1, limit)
- self.putValue(data, 'utf8', elided=elided)
+ (length, shown, data) = self.readToFirstZero(ptr, 1, limit)
+ self.putValue(data, 'utf8', length=length)
if self.isExpanded():
self.putArrayData(ptr, shown, innerType)
return True
@@ -1257,55 +1256,55 @@ class DumperBase():
if targetType.name in ('wchar_t', 'WCHAR'):
self.putType(typeName)
charSize = self.lookupType('wchar_t').size()
- (elided, data) = self.encodeCArray(ptr, charSize, limit)
+ (length, data) = self.encodeCArray(ptr, charSize, limit)
if charSize == 2:
- self.putValue(data, 'utf16', elided=elided)
+ self.putValue(data, 'utf16', length=length)
else:
- self.putValue(data, 'ucs4', elided=elided)
+ self.putValue(data, 'ucs4', length=length)
return True
if displayFormat == DisplayFormat.Latin1String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 1, limit)
- self.putValue(data, 'latin1', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 1, limit)
+ self.putValue(data, 'latin1', length=length)
return True
if displayFormat == DisplayFormat.SeparateLatin1String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 1, limit)
- self.putValue(data, 'latin1', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 1, limit)
+ self.putValue(data, 'latin1', length=length)
self.putDisplay('latin1:separate', data)
return True
if displayFormat == DisplayFormat.Utf8String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 1, limit)
- self.putValue(data, 'utf8', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 1, limit)
+ self.putValue(data, 'utf8', length=length)
return True
if displayFormat == DisplayFormat.SeparateUtf8String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 1, limit)
- self.putValue(data, 'utf8', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 1, limit)
+ self.putValue(data, 'utf8', length=length)
self.putDisplay('utf8:separate', data)
return True
if displayFormat == DisplayFormat.Local8BitString:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 1, limit)
- self.putValue(data, 'local8bit', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 1, limit)
+ self.putValue(data, 'local8bit', length=length)
return True
if displayFormat == DisplayFormat.Utf16String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 2, limit)
- self.putValue(data, 'utf16', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 2, limit)
+ self.putValue(data, 'utf16', length=length)
return True
if displayFormat == DisplayFormat.Ucs4String:
self.putType(typeName)
- (elided, data) = self.encodeCArray(ptr, 4, limit)
- self.putValue(data, 'ucs4', elided=elided)
+ (length, data) = self.encodeCArray(ptr, 4, limit)
+ self.putValue(data, 'ucs4', length=length)
return True
return False
@@ -2577,17 +2576,17 @@ class DumperBase():
def extractQStringFromQDataStream(self, buf, offset):
""" Read a QString from the stream """
- size = struct.unpack_from('!I', buf, offset)[0]
+ length = struct.unpack_from('!I', buf, offset)[0]
offset += 4
- string = buf[offset:offset + size].decode('utf-16be')
- return (string, offset + size)
+ string = buf[offset:offset + length].decode('utf-16be')
+ return (string, offset + length)
def extractQByteArrayFromQDataStream(self, buf, offset):
""" Read a QByteArray from the stream """
- size = struct.unpack_from('!I', buf, offset)[0]
+ length = struct.unpack_from('!I', buf, offset)[0]
offset += 4
- string = buf[offset:offset + size].decode('latin1')
- return (string, offset + size)
+ string = buf[offset:offset + length].decode('latin1')
+ return (string, offset + length)
def extractIntFromQDataStream(self, buf, offset):
""" Read an int from the stream """
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index b08f60a9bb..06e7d47325 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -28,46 +28,46 @@ def qform__QByteArray():
def qedit__QByteArray(d, value, data):
d.call('void', value, 'resize', str(len(data)))
- (base, size, alloc) = d.stringData(value)
+ (base, length, alloc) = d.stringData(value)
d.setValues(base, 'char', [ord(c) for c in data])
def qdump__QByteArray(d, value):
if d.qtVersion() >= 0x60000:
- dd, data, size = value.split('ppi')
+ dd, data, length = value.split('ppi')
if dd:
_, _, alloc = d.split('iii', dd)
else: # fromRawData
- alloc = size
+ alloc = length
else:
- data, size, alloc = d.qArrayData(value)
+ data, length, alloc = d.qArrayData(value)
- d.check(alloc == 0 or (0 <= size and size <= alloc and alloc <= 100000000))
- if size > 0:
+ d.check(alloc == 0 or (0 <= length and length <= alloc and alloc <= 100000000))
+ if length > 0:
d.putExpandable()
- elided, shown = d.computeLimit(size, d.displayStringLimit)
+ shown = d.computeLimit(length, d.displayStringLimit)
p = d.readMemory(data, shown)
displayFormat = d.currentItemFormat()
if displayFormat == DisplayFormat.Automatic or displayFormat == DisplayFormat.Latin1String:
- d.putValue(p, 'latin1', elided=elided)
+ d.putValue(p, 'latin1', length=length)
elif displayFormat == DisplayFormat.SeparateLatin1String:
- d.putValue(p, 'latin1', elided=elided)
+ d.putValue(p, 'latin1', length=length)
d.putDisplay('latin1:separate', d.encodeByteArray(value, limit=100000))
elif displayFormat == DisplayFormat.Utf8String:
- d.putValue(p, 'utf8', elided=elided)
+ d.putValue(p, 'utf8', length=length)
elif displayFormat == DisplayFormat.SeparateUtf8String:
- d.putValue(p, 'utf8', elided=elided)
+ d.putValue(p, 'utf8', length=length)
d.putDisplay('utf8:separate', d.encodeByteArray(value, limit=100000))
if d.isExpanded():
- d.putArrayData(data, size, d.charType())
+ d.putArrayData(data, length, d.charType())
#def qdump__QArrayData(d, value):
-# data, size, alloc = d.qArrayDataHelper(value.address())
-# d.check(alloc == 0 or (0 <= size and size <= alloc and alloc <= 100000000))
-# d.putValue(d.readMemory(data, size), 'latin1')
+# data, length, alloc = d.qArrayDataHelper(value.address())
+# d.check(alloc == 0 or (0 <= length and length <= alloc and alloc <= 100000000))
+# d.putValue(d.readMemory(data, length), 'latin1')
# d.putPlainChildren(value)
@@ -81,10 +81,10 @@ def qdump__QBitArray(d, value):
else:
data, basize, _ = d.qArrayData(value['d'])
unused = d.extractByte(data) if data else 0
- size = basize * 8 - unused
- d.putItemCount(size)
+ length = basize * 8 - unused
+ d.putItemCount(length)
if d.isExpanded():
- with Children(d, size, maxNumChild=10000):
+ with Children(d, length, maxNumChild=10000):
for i in d.childRange():
q = data + 1 + int(i / 8)
with SubItem(d, i):
@@ -1621,17 +1621,17 @@ def qdumpHelper_QSet45(d, value):
ptrSize = d.ptrSize()
dptr = d.extractPointer(value)
- (fakeNext, buckets, ref, size, nodeSize, userNumBits, numBits, numBuckets) = \
+ (fakeNext, buckets, ref, length, nodeSize, userNumBits, numBits, numBuckets) = \
d.split('ppiiihhi', dptr)
- d.check(0 <= size and size <= 100 * 1000 * 1000)
+ d.check(0 <= length and length <= 100 * 1000 * 1000)
d.check(-1 <= ref and ref < 100000)
- d.putItemCount(size)
+ d.putItemCount(length)
if d.isExpanded():
keyType = value.type[0]
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
- with Children(d, size, childType=keyType):
+ with Children(d, length, childType=keyType):
node = hashDataFirstNode()
for i in d.childRange():
if isShort:
@@ -1714,15 +1714,15 @@ def qdump__QStack(d, value):
def qdump__QPolygonF(d, value):
- data, size = d.vectorData(value)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType('@QPointF'))
+ data, length = d.vectorData(value)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType('@QPointF'))
def qdump__QPolygon(d, value):
- data, size = d.vectorData(value)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType('@QPoint'))
+ data, length = d.vectorData(value)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType('@QPoint'))
def qdump__QGraphicsPolygonItem(d, value):
@@ -1741,14 +1741,14 @@ def qdump__QGraphicsPolygonItem(d, value):
offset = 328 if d.isMsvcTarget() else 320
else:
offset = 308
- data, size = d.vectorData(dptr + offset)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType('@QPointF'))
+ data, length = d.vectorData(dptr + offset)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType('@QPointF'))
def qedit__QString(d, value, data):
d.call('void', value, 'resize', str(len(data)))
- (base, size, alloc) = d.stringData(value)
+ (base, length, alloc) = d.stringData(value)
d.setValues(base, 'short', [ord(c) for c in data])
@@ -1758,14 +1758,14 @@ def qform__QString():
def qdump__QString(d, value):
d.putStringValue(value)
- data, size, _ = d.stringData(value)
+ data, length, _ = d.stringData(value)
displayFormat = d.currentItemFormat()
if displayFormat == DisplayFormat.Separate:
d.putDisplay('utf16:separate', d.encodeString(value, limit=100000))
- if (size > 0):
+ if (length > 0):
d.putExpandable()
if d.isExpanded():
- d.putArrayData(data, size, d.createType('@QChar'))
+ d.putArrayData(data, length, d.createType('@QChar'))
def qdump__QSettingsKey(d, value):
@@ -1774,8 +1774,8 @@ def qdump__QSettingsKey(d, value):
def qdump__QStaticStringData(d, value):
- size = value.type[0]
- (ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size))
+ length = value.type[0]
+ (ref, length, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * length))
d.putValue(d.hexencode(data), 'utf16')
d.putPlainChildren(value)
@@ -1788,28 +1788,28 @@ def qdump__QTypedArrayData(d, value):
def qdump__QStringData(d, value):
- (ref, size, alloc, pad, offset) = value.split('III@p')
- elided, shown = d.computeLimit(size, d.displayStringLimit)
+ (ref, length, alloc, pad, offset) = value.split('III@p')
+ shown = d.computeLimit(length, d.displayStringLimit)
data = d.readMemory(value.address() + offset, shown * 2)
- d.putValue(data, 'utf16', elided=elided)
+ d.putValue(data, 'utf16', length=length)
d.putPlainChildren(value)
def qdump__QAnyStringView(d, value):
- data, size = value.split('pp')
+ data, length = value.split('pp')
bits = d.ptrSize() * 8 - 2
- tag = size >> bits
- size = size & (2**bits - 1)
- elided, shown = d.computeLimit(size, d.displayStringLimit)
+ tag = length >> bits
+ length = length & (2**bits - 1)
+ shown = d.computeLimit(length, d.displayStringLimit)
if tag == 0:
mem = d.readMemory(data, shown)
- d.putValue(mem, 'utf8', elided=elided)
+ d.putValue(mem, 'utf8', length=length)
elif tag == 1:
mem = d.readMemory(data, shown)
- d.putValue(mem, 'latin1', elided=elided)
+ d.putValue(mem, 'latin1', length=length)
elif tag == 2:
mem = d.readMemory(data, shown * 2)
- d.putValue(mem, 'utf16', elided=elided)
+ d.putValue(mem, 'utf16', length=length)
else:
d.putSpecialValue('empty')
d.putPlainChildren(value)
@@ -1825,16 +1825,15 @@ def qdump__QStringView(d, value):
if idata == 0:
d.putValue('(null)')
return
- size = value['m_size']
- isize = size.integer()
- elided, shown = d.computeLimit(isize, d.displayStringLimit)
+ length = value['m_size'].integer()
+ shown = d.computeLimit(length, d.displayStringLimit)
mem = d.readMemory(idata, shown * 2)
- d.putValue(mem, 'utf16', elided=elided)
+ d.putValue(mem, 'utf16', length=length)
if d.currentItemFormat() == DisplayFormat.Separate:
d.putDisplay('utf16:separate', mem)
d.putExpandable()
if d.isExpanded():
- d.putArrayData(idata, isize, d.createType('char16_t'))
+ d.putArrayData(idata, length, d.createType('char16_t'))
def qdump__QHashedString(d, value):
@@ -1848,12 +1847,12 @@ def qdump__QQmlRefCount(d, value):
def qdump__QStringRef(d, value):
- (stringptr, pos, size) = value.split('pii')
+ (stringptr, pos, length) = value.split('pii')
if stringptr == 0:
d.putValue('(null)')
return
data, ssize, alloc = d.stringData(d.createValue(stringptr, '@QString'))
- d.putValue(d.readMemory(data + 2 * pos, 2 * size), 'utf16')
+ d.putValue(d.readMemory(data + 2 * pos, 2 * length), 'utf16')
d.putPlainChildren(value)
@@ -1937,7 +1936,7 @@ def qdump__QUrl(d, value):
userNameEnc = d.encodeString(userName)
hostEnc = d.encodeString(host)
- elided, pathEnc = d.encodeStringHelper(path, d.displayStringLimit)
+ length, pathEnc = d.encodeStringHelper(path, d.displayStringLimit)
url = d.encodeString(scheme)
url += '3a002f002f00' # '://'
if len(userNameEnc):
@@ -1946,7 +1945,7 @@ def qdump__QUrl(d, value):
if port >= 0:
url += '3a00' + ''.join(['%02x00' % ord(c) for c in str(port)])
url += pathEnc
- d.putValue(url, 'utf16', elided=elided)
+ d.putValue(url, 'utf16', length=length)
displayFormat = d.currentItemFormat()
if displayFormat == DisplayFormat.Separate:
@@ -2162,7 +2161,7 @@ def qdumpHelper__QVariant6(d, value):
qdumpHelper_QVariant_0(d, value)
return
- revision, alignment, size, flags, variantType, metaObjectPtr, name = \
+ revision, alignment, length, flags, variantType, metaObjectPtr, name = \
d.split('HHIIIpp', metaTypeInterface)
# Well-known simple type.
@@ -2241,7 +2240,7 @@ def qdumpHelper__QVariant45(d, value):
base1 = d.extractPointer(value)
#DumperBase.warn('BASE 1: %s %s' % (base1, innert))
base = d.extractPointer(base1)
- #DumperBase.warn('SIZE 1: %s' % size)
+ #DumperBase.warn('SIZE 1: %s' % length)
val = d.createValue(base, innerType)
else:
#DumperBase.warn('DIRECT ITEM 1: %s' % innerType)
@@ -2268,7 +2267,7 @@ def qdumpHelper__QVariant45(d, value):
d.putSpecialValue('notcallable')
return None
ptr = p.pointer()
- (elided, blob) = d.encodeCArray(ptr, 1, 100)
+ (_, blob) = d.encodeCArray(ptr, 1, 100)
innerType = d.hexdecode(blob)
# Prefer namespaced version.
@@ -2303,34 +2302,34 @@ def qform__QVector():
def qdump__QVector(d, value):
if d.qtVersion() >= 0x060000:
- data, size = d.listData(value)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType(value.type.ltarget[0]))
+ data, length = d.listData(value)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType(value.type.ltarget[0]))
# g++ 9.3 does not add the template parameter list to the debug info.
# Fake it for the common case:
if value.type.name == d.qtNamespace() + "QVector":
d.putBetterType(value.type.name + '<' + value.type.ltarget[0].name + '>')
else:
- data, size = d.vectorData(value)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType(value.type[0]))
+ data, length = d.vectorData(value)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType(value.type[0]))
if False:
def qdump__QObjectConnectionList(d, value):
- data, size = d.vectorData(value)
- d.putItemCount(size)
- d.putPlotData(data, size, d.createType('@QObjectPrivate::ConnectionList'))
+ data, length = d.vectorData(value)
+ d.putItemCount(length)
+ d.putPlotData(data, length, d.createType('@QObjectPrivate::ConnectionList'))
def qdump__QVarLengthArray(d, value):
if d.qtVersion() >= 0x060000:
- cap, size, data = value.split('QQp')
+ cap, length, data = value.split('QQp')
else:
- cap, size, data = value.split('iip')
- d.check(0 <= size)
- d.putItemCount(size)
- d.putPlotData(data, size, value.type[0])
+ cap, length, data = value.split('iip')
+ d.check(0 <= length)
+ d.putItemCount(length)
+ d.putPlotData(data, length, value.type[0])
def qdump__QSharedPointer(d, value):
@@ -2401,20 +2400,20 @@ def qdump__QXmlAttributes(d, value):
def qdump__QXmlStreamStringRef(d, value):
s = value['m_string']
- (data, size, alloc) = d.stringData(s)
+ (data, length, alloc) = d.stringData(s)
data += 2 * int(value['m_position'])
- size = int(value['m_size'])
- s = d.readMemory(data, 2 * size)
+ length = int(value['m_size'])
+ s = d.readMemory(data, 2 * length)
d.putValue(s, 'utf16')
d.putPlainChildren(value)
def qdump__QXmlStreamAttribute(d, value):
s = value['m_name']['m_string']
- (data, size, alloc) = d.stringData(s)
+ (data, length, alloc) = d.stringData(s)
data += 2 * int(value['m_name']['m_position'])
- size = int(value['m_name']['m_size'])
- s = d.readMemory(data, 2 * size)
+ length = int(value['m_name']['m_size'])
+ s = d.readMemory(data, 2 * length)
d.putValue(s, 'utf16')
d.putPlainChildren(value)
@@ -2505,8 +2504,8 @@ def qdump__QV4__ExecutionContext(d, value):
def qdump__QQmlSourceLocation(d, value):
(sourceFile, line, col) = value.split('pHH')
- (data, size, alloc) = d.stringData(value)
- d.putValue(d.readMemory(data, 2 * size), 'utf16')
+ (data, length, alloc) = d.stringData(value)
+ d.putValue(d.readMemory(data, 2 * length), 'utf16')
d.putField('valuesuffix', ':%s:%s' % (line, col))
d.putPlainChildren(value)
@@ -3345,9 +3344,7 @@ def qdump__QJsonValue(d, value):
return
if t == 3:
d.putType('QJsonValue (String)')
- string = value.split('{@QString}')[0]
- elided, base = d.encodeString(string, d.displayStringLimit)
- d.putValue(base, 'utf16', elided=elided)
+ d.putStringValue(value.split('{@QString}')[0])
return
if t == 4:
d.putType('QJsonValue (Array)')
@@ -3472,9 +3469,9 @@ def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes):
bytedata_len = d.extractInt(bytedata)
bytedata_data = bytedata + 4 # sizeof(QtCbor::ByteData) header part
- elided, shown = d.computeLimit(bytedata_len, d.displayStringLimit)
+ shown = d.computeLimit(bytedata_len, d.displayStringLimit)
res = d.readMemory(bytedata_data, shown)
- d.putValue(res, enc, elided=elided)
+ d.putValue(res, enc, length=bytedata_len)
def qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, idx, bytedata, is_cbor):
diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py
index 1c98c76725..bc4bb84dcb 100644
--- a/share/qtcreator/debugger/stdtypes.py
+++ b/share/qtcreator/debugger/stdtypes.py
@@ -697,6 +697,36 @@ def qdump__std__pair(d, value):
d.putValue('(%s, %s)' % (key, value))
+def qdumpHelper_get_tuple_elements(d, tuple, value_typename, value_member):
+ """
+ Helper method that returns the elements of a tuple.
+ """
+ elems = []
+ other_members = []
+ for member in tuple.members(True):
+ if not member.type.templateArguments():
+ continue
+ if member.type.name.startswith(value_typename):
+ elems.append(member[value_member])
+ else:
+ other_members.append(member)
+ for member in other_members:
+ sub_elems = qdumpHelper_get_tuple_elements(d, member, value_typename, value_member)
+ elems = elems + sub_elems
+ return elems
+
+
+def qdump__std__tuple(d, value):
+ if d.isMsvcTarget():
+ elems = qdumpHelper_get_tuple_elements(d, value, "std::_Tuple_val", "_Val")
+ else:
+ elems = qdumpHelper_get_tuple_elements(d, value, "std::_Head_base", "_M_head_impl")
+ d.putItemCount(len(elems))
+ with Children(d):
+ for elem in elems:
+ d.putSubItem(0, elem)
+
+
def qform__std__unordered_map():
return [DisplayFormat.CompactMap]
diff --git a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs
new file mode 100644
index 0000000000..4a532363f0
--- /dev/null
+++ b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs
@@ -0,0 +1,86 @@
+QtcLibrary {
+ name: "qtkeychain"
+
+ property bool useWinCredentialsStore: qbs.targetOS.contains("windows")
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt.core" }
+ Depends { name: "Qt.dbus"; condition: qbs.targetOS.contains("linux") }
+ Depends { name: "libsecret-1"; required: false }
+
+ cpp.defines: base.concat(["QTKEYCHAIN_LIBRARY"])
+
+ Properties {
+ condition: useWinCredentialsStore
+ cpp.defines: outer.concat(["USE_CREDENTIAL_STORE=1"])
+ cpp.dynamicLibraries: ["advapi32"]
+ }
+
+ Properties {
+ condition: qbs.targetOS.contains("windows") && !useWinCredentialsStore
+ cpp.dynamicLibraries: ["crypt32"]
+ }
+
+ Properties {
+ condition: qbs.targetOS.contains("macos")
+ cpp.frameworks: [ "Foundation", "Security" ]
+ }
+
+ files: [
+ "keychain.cpp",
+ "keychain.h",
+ "keychain_p.h",
+ "qkeychain_export.h",
+ ]
+
+ Group {
+ name: "qtkeychain Windows files"
+ condition: qbs.targetOS.contains("windows")
+ files: [
+ "keychain_win.cpp",
+ "plaintextstore_p.h",
+ ]
+
+ Group {
+ name: "qtkeychain Windows no credentials store"
+ condition: !product.useWinCredentialsStore
+ files: [ "plaintextstore.cpp" ]
+ }
+ }
+
+ Group {
+ name: "qtkeychain macOS files"
+ condition: qbs.targetOS.contains("macos")
+ files: [ "keychain_apple.mm" ]
+ }
+
+ Group {
+ name: "qtkeychain Linux files"
+ condition: qbs.targetOS.contains("linux")
+
+ Group {
+ name: "qtkeychain libsecret support"
+ condition: "libsecret-1".present
+ cpp.defines: outer.concat(["HAVE_LIBSECRET=1"])
+ }
+ Group {
+ name: "dbus sources"
+ fileTags: "qt.dbus.interface"
+ files: ["org.kde.KWallet.xml"]
+ }
+
+ Group {
+ name: "qtkeychain dbus support"
+ cpp.defines: outer.concat(["KEYCHAIN_DBUS=1"])
+ files: [
+ "gnomekeyring.cpp",
+ "gnomekeyring_p.h",
+ "keychain_unix.cpp",
+ "libsecret.cpp",
+ "libsecret_p.h",
+ "plaintextstore.cpp",
+ "plaintextstore_p.h",
+ ]
+ }
+ }
+}
diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp
index 7ae1aa3397..0e7ba19342 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.cpp
+++ b/src/libs/cplusplus/TypePrettyPrinter.cpp
@@ -363,12 +363,11 @@ void TypePrettyPrinter::visit(Function *type)
{
bool showTemplateParameters = _overview->showTemplateParameters;
QStringList nameParts = _name.split("::");
- int i = nameParts.length() - 1;
Scope *s = type->enclosingScope();
if (s && s->asTemplate())
s = s->enclosingScope();
- for (; s && i >= 0; s = s->enclosingScope()) {
+ for (int i = nameParts.length() - 1; s && i >= 0; s = s->enclosingScope()) {
if (s->asClass())
showTemplateParameters = true;
@@ -433,7 +432,8 @@ void TypePrettyPrinter::visit(Function *type)
}
if (_overview->showEnclosingTemplate) {
- for (Scope *s = type->enclosingScope(); s && i >= 0; s = s->enclosingScope()) {
+ for (auto [s, i] = std::tuple{type->enclosingScope(), nameParts.length() - 1}; s && i >= 0;
+ s = s->enclosingScope()) {
if (Template *templ = s->asTemplate()) {
QString templateScope = "template<";
const int paramCount = templ->templateParameterCount();
diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs
index ffc3017cba..a6426d4ae4 100644
--- a/src/libs/libs.qbs
+++ b/src/libs/libs.qbs
@@ -26,6 +26,7 @@ Project {
"utils/utils.qbs",
"3rdparty/libptyqt/ptyqt.qbs",
"3rdparty/libvterm/vterm.qbs",
+ "3rdparty/qtkeychain/qtkeychain.qbs",
"3rdparty/syntax-highlighting/syntax-highlighting.qbs",
"3rdparty/winpty/winpty.qbs",
"3rdparty/yaml-cpp/yaml-cpp.qbs",
diff --git a/src/libs/nanotrace/CMakeLists.txt b/src/libs/nanotrace/CMakeLists.txt
index f2fa830e2d..8652a81798 100644
--- a/src/libs/nanotrace/CMakeLists.txt
+++ b/src/libs/nanotrace/CMakeLists.txt
@@ -3,7 +3,6 @@ add_qtc_library(Nanotrace
SOURCES
nanotraceglobals.h
nanotrace.cpp nanotrace.h
- nanotracehr.cpp nanotracehr.h
PUBLIC_DEPENDS Qt::Core Qt::Gui
PROPERTIES
CXX_VISIBILITY_PRESET default
@@ -16,3 +15,9 @@ extend_qtc_library(Nanotrace
CONDITION DESIGN_STUDIO_USE_NANOTRACE
PUBLIC_DEFINES NANOTRACE_DESIGNSTUDIO_ENABLED
)
+
+option(NANOTRACEHR_ENABLED "Enables collecting high resolution performance data" OFF)
+extend_qtc_library(Nanotrace
+ SOURCES
+ nanotracehr.cpp nanotracehr.h
+)
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h
index d49e12a87a..74b1381b06 100644
--- a/src/libs/nanotrace/nanotracehr.h
+++ b/src/libs/nanotrace/nanotracehr.h
@@ -34,7 +34,7 @@ enum class Tracing { IsDisabled, IsEnabled };
constexpr Tracing tracingStatus()
{
-#ifdef NANOTRACE_ENABLED
+#ifdef NANOTRACEHR_ENABLED
return Tracing::IsEnabled;
#else
return Tracing::IsDisabled;
@@ -1569,7 +1569,7 @@ template<typename Category, typename... Arguments>
Tracer(typename Category::ArgumentType name, Category &category, Arguments &&...)
-> Tracer<Category, typename Category::IsActive>;
-#ifdef NANOTRACE_ENABLED
+#ifdef NANOTRACEHR_ENABLED
class GlobalTracer
{
public:
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index aac0de9ab1..a525c6c305 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -317,6 +317,16 @@ void ModelManagerInterface::setDefaultProject(const ModelManagerInterface::Proje
});
}
+void ModelManagerInterface::cancelAllThreads()
+{
+ m_cppQmlTypesUpdater.cancel();
+ // Don't execute the scheduled updates for the old session anymore
+ m_updateCppQmlTypesTimer->stop();
+ m_asyncResetTimer->stop();
+ QMutexLocker locker(&m_futuresMutex);
+ m_futureSynchronizer.cancelAllFutures();
+}
+
Snapshot ModelManagerInterface::snapshot() const
{
return m_syncedData.readLocked()->m_validSnapshot;
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index c57cba7e46..ae3d8e0e6c 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -238,7 +238,7 @@ protected:
void updateImportPaths();
void loadQmlTypeDescriptionsInternal(const QString &path);
void setDefaultProject(const ProjectInfo &pInfo, ProjectExplorer::Project *p);
-
+ void cancelAllThreads();
private:
void joinAllThreads(bool cancelOnWait = false);
void iterateQrcFiles(ProjectExplorer::Project *project,
diff --git a/src/libs/solutions/tasking/networkquery.cpp b/src/libs/solutions/tasking/networkquery.cpp
index b02bb9cea1..335f79afd9 100644
--- a/src/libs/solutions/tasking/networkquery.cpp
+++ b/src/libs/solutions/tasking/networkquery.cpp
@@ -19,7 +19,20 @@ void NetworkQuery::start()
emit done(DoneResult::Error);
return;
}
- m_reply.reset(m_manager->get(m_request));
+ switch (m_operation) {
+ case NetworkOperation::Get:
+ m_reply.reset(m_manager->get(m_request));
+ break;
+ case NetworkOperation::Put:
+ m_reply.reset(m_manager->put(m_request, m_writeData));
+ break;
+ case NetworkOperation::Post:
+ m_reply.reset(m_manager->post(m_request, m_writeData));
+ break;
+ case NetworkOperation::Delete:
+ m_reply.reset(m_manager->deleteResource(m_request));
+ break;
+ }
connect(m_reply.get(), &QNetworkReply::finished, this, [this] {
disconnect(m_reply.get(), &QNetworkReply::finished, this, nullptr);
emit done(toDoneResult(m_reply->error() == QNetworkReply::NoError));
diff --git a/src/libs/solutions/tasking/networkquery.h b/src/libs/solutions/tasking/networkquery.h
index bf08bd1e7b..dd099dc7a8 100644
--- a/src/libs/solutions/tasking/networkquery.h
+++ b/src/libs/solutions/tasking/networkquery.h
@@ -22,6 +22,8 @@ namespace Tasking {
// is independent on Qt::Network.
// Possibly, it could be placed inside Qt::Network library, as a wrapper around QNetworkReply.
+enum class NetworkOperation { Get, Put, Post, Delete };
+
class TASKING_EXPORT NetworkQuery final : public QObject
{
Q_OBJECT
@@ -29,6 +31,8 @@ class TASKING_EXPORT NetworkQuery final : public QObject
public:
~NetworkQuery();
void setRequest(const QNetworkRequest &request) { m_request = request; }
+ void setOperation(NetworkOperation operation) { m_operation = operation; }
+ void setWriteData(const QByteArray &data) { m_writeData = data; }
void setNetworkAccessManager(QNetworkAccessManager *manager) { m_manager = manager; }
QNetworkReply *reply() const { return m_reply.get(); }
void start();
@@ -39,6 +43,8 @@ signals:
private:
QNetworkRequest m_request;
+ NetworkOperation m_operation = NetworkOperation::Get;
+ QByteArray m_writeData; // Used by Put and Post
QNetworkAccessManager *m_manager = nullptr;
std::unique_ptr<QNetworkReply> m_reply;
};
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index 9f11f3fc83..eb2eaed9dd 100644
--- a/src/libs/utils/CMakeLists.txt
+++ b/src/libs/utils/CMakeLists.txt
@@ -43,8 +43,8 @@ add_qtc_library(Utils
elidinglabel.cpp elidinglabel.h
environment.cpp environment.h
environmentdialog.cpp environmentdialog.h
- environmentfwd.h
environmentmodel.cpp environmentmodel.h
+ environmentfwd.h
execmenu.cpp execmenu.h
expected.h
externalterminalprocessimpl.cpp externalterminalprocessimpl.h
@@ -103,12 +103,7 @@ add_qtc_library(Utils
namevaluedictionary.cpp namevaluedictionary.h
namevaluedictionary.cpp namevaluedictionary.h
namevalueitem.cpp namevalueitem.h
- namevalueitem.cpp namevalueitem.h
- namevaluemodel.cpp namevaluemodel.h
- namevaluemodel.cpp namevaluemodel.h
namevaluesdialog.cpp namevaluesdialog.h
- namevaluesdialog.cpp namevaluesdialog.h
- namevaluevalidator.cpp namevaluevalidator.h
namevaluevalidator.cpp namevaluevalidator.h
navigationtreeview.cpp navigationtreeview.h
networkaccessmanager.cpp networkaccessmanager.h
diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp
index 1e8ccbac71..2098c68d1c 100644
--- a/src/libs/utils/aspects.cpp
+++ b/src/libs/utils/aspects.cpp
@@ -7,6 +7,7 @@
#include "checkablemessagebox.h"
#include "environment.h"
#include "fancylineedit.h"
+#include "guard.h"
#include "iconbutton.h"
#include "layoutbuilder.h"
#include "passworddialog.h"
@@ -1181,13 +1182,12 @@ void StringAspect::addToLayout(LayoutItem &parent)
connect(lineEditDisplay, &FancyLineEdit::validChanged, this, &StringAspect::validChanged);
bufferToGui();
if (isAutoApply() && d->m_autoApplyOnEditingFinished) {
- connect(lineEditDisplay,
- &FancyLineEdit::editingFinished,
- this,
- [this, lineEditDisplay] {
- d->undoable.set(undoStack(), lineEditDisplay->text());
- handleGuiChanged();
- });
+ connect(lineEditDisplay, &FancyLineEdit::editingFinished, this, [this, lineEditDisplay] {
+ if (lineEditDisplay->text() != d->undoable.get()) {
+ d->undoable.set(undoStack(), lineEditDisplay->text());
+ handleGuiChanged();
+ }
+ });
} else {
connect(lineEditDisplay, &QLineEdit::textChanged, this, [this, lineEditDisplay] {
d->undoable.set(undoStack(), lineEditDisplay->text());
@@ -1386,6 +1386,8 @@ public:
bool m_autoApplyOnEditingFinished = false;
bool m_allowPathFromDevice = true;
bool m_validatePlaceHolder = false;
+
+ Guard m_editFinishedGuard;
};
FilePathAspect::FilePathAspect(AspectContainer *container)
@@ -1559,8 +1561,12 @@ void FilePathAspect::addToLayout(Layouting::LayoutItem &parent)
connect(d->m_pathChooserDisplay, &PathChooser::validChanged, this, &FilePathAspect::validChanged);
bufferToGui();
if (isAutoApply() && d->m_autoApplyOnEditingFinished) {
- connect(d->m_pathChooserDisplay, &PathChooser::editingFinished,
- this, &FilePathAspect::handleGuiChanged);
+ connect(d->m_pathChooserDisplay, &PathChooser::editingFinished, this, [this] {
+ if (d->m_editFinishedGuard.isLocked())
+ return;
+ GuardLocker lk(d->m_editFinishedGuard);
+ handleGuiChanged();
+ });
connect(d->m_pathChooserDisplay, &PathChooser::browsingFinished,
this, &FilePathAspect::handleGuiChanged);
} else {
diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp
index 0486ece19e..39bdc736e0 100644
--- a/src/libs/utils/devicefileaccess.cpp
+++ b/src/libs/utils/devicefileaccess.cpp
@@ -878,52 +878,73 @@ QByteArray DesktopDeviceFileAccess::fileId(const FilePath &filePath) const
// UnixDeviceAccess
+static Utils::unexpected<QString> make_unexpected_disconnected()
+{
+ return make_unexpected(Tr::tr("Device is not connected"));
+}
+
UnixDeviceFileAccess::~UnixDeviceFileAccess() = default;
bool UnixDeviceFileAccess::runInShellSuccess(const CommandLine &cmdLine,
const QByteArray &stdInData) const
{
+ if (disconnected())
+ return false;
return runInShell(cmdLine, stdInData).exitCode == 0;
}
bool UnixDeviceFileAccess::isExecutableFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-x", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isReadableFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-r", path, "-a", "-f", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isWritableFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-w", path, "-a", "-f", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isReadableDirectory(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-r", path, "-a", "-d", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isWritableDirectory(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-w", path, "-a", "-d", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-f", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::isDirectory(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
if (filePath.isRootPath())
return true;
@@ -933,12 +954,16 @@ bool UnixDeviceFileAccess::isDirectory(const FilePath &filePath) const
bool UnixDeviceFileAccess::isSymLink(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-h", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::hasHardLinks(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QStringList args = statArgs(filePath, "%h", "%l");
const RunResult result = runInShell({"stat", args, OsType::OsTypeLinux});
return result.stdOut.toLongLong() > 1;
@@ -946,29 +971,39 @@ bool UnixDeviceFileAccess::hasHardLinks(const FilePath &filePath) const
bool UnixDeviceFileAccess::ensureExistingFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"touch", {path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::createDirectory(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"mkdir", {"-p", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::exists(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
const QString path = filePath.path();
return runInShellSuccess({"test", {"-e", path}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::removeFile(const FilePath &filePath) const
{
+ if (disconnected())
+ return false;
return runInShellSuccess({"rm", {filePath.path()}, OsType::OsTypeLinux});
}
bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *error) const
{
+ if (disconnected())
+ return false;
QTC_ASSERT(filePath.path().startsWith('/'), return false);
const QString path = filePath.cleanPath().path();
@@ -989,6 +1024,8 @@ bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *
expected_str<void> UnixDeviceFileAccess::copyFile(const FilePath &filePath,
const FilePath &target) const
{
+ if (disconnected())
+ return make_unexpected_disconnected();
const RunResult result = runInShell(
{"cp", {filePath.path(), target.path()}, OsType::OsTypeLinux});
@@ -1003,11 +1040,17 @@ expected_str<void> UnixDeviceFileAccess::copyFile(const FilePath &filePath,
bool UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
{
+ if (disconnected())
+ return false;
+
return runInShellSuccess({"mv", {filePath.path(), target.path()}, OsType::OsTypeLinux});
}
FilePath UnixDeviceFileAccess::symLinkTarget(const FilePath &filePath) const
{
+ if (disconnected())
+ return {};
+
const RunResult result = runInShell(
{"readlink", {"-n", "-e", filePath.path()}, OsType::OsTypeLinux});
const QString out = QString::fromUtf8(result.stdOut);
@@ -1018,6 +1061,9 @@ expected_str<QByteArray> UnixDeviceFileAccess::fileContents(const FilePath &file
qint64 limit,
qint64 offset) const
{
+ if (disconnected())
+ return make_unexpected_disconnected();
+
QStringList args = {"if=" + filePath.path()};
if (limit > 0 || offset > 0) {
const qint64 gcd = std::gcd(limit, offset);
@@ -1045,6 +1091,9 @@ expected_str<qint64> UnixDeviceFileAccess::writeFileContents(const FilePath &fil
const QByteArray &data,
qint64 offset) const
{
+ if (disconnected())
+ return make_unexpected_disconnected();
+
QStringList args = {"of=" + filePath.path()};
if (offset != 0) {
args.append("bs=1");
@@ -1061,6 +1110,9 @@ expected_str<qint64> UnixDeviceFileAccess::writeFileContents(const FilePath &fil
expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &filePath)
{
+ if (disconnected())
+ return make_unexpected_disconnected();
+
if (!m_hasMkTemp.has_value())
m_hasMkTemp = runInShellSuccess({"which", {"mktemp"}, OsType::OsTypeLinux});
@@ -1120,6 +1172,9 @@ expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &file
QDateTime UnixDeviceFileAccess::lastModified(const FilePath &filePath) const
{
+ if (disconnected())
+ return {};
+
const RunResult result = runInShell(
{"stat", {"-L", "-c", "%Y", filePath.path()}, OsType::OsTypeLinux});
qint64 secs = result.stdOut.toLongLong();
@@ -1131,6 +1186,9 @@ QStringList UnixDeviceFileAccess::statArgs(const FilePath &filePath,
const QString &linuxFormat,
const QString &macFormat) const
{
+ if (disconnected())
+ return {};
+
return (filePath.osType() == OsTypeMac ? QStringList{"-f", macFormat}
: QStringList{"-c", linuxFormat})
<< "-L" << filePath.path();
@@ -1138,6 +1196,9 @@ QStringList UnixDeviceFileAccess::statArgs(const FilePath &filePath,
QFile::Permissions UnixDeviceFileAccess::permissions(const FilePath &filePath) const
{
+ if (disconnected())
+ return {};
+
QStringList args = statArgs(filePath, "%a", "%p");
const RunResult result = runInShell({"stat", args, OsType::OsTypeLinux});
@@ -1161,6 +1222,9 @@ QFile::Permissions UnixDeviceFileAccess::permissions(const FilePath &filePath) c
bool UnixDeviceFileAccess::setPermissions(const FilePath &filePath, QFile::Permissions perms) const
{
+ if (disconnected())
+ return false;
+
const int flags = int(perms);
return runInShellSuccess(
{"chmod", {QString::number(flags, 16), filePath.path()}, OsType::OsTypeLinux});
@@ -1168,6 +1232,9 @@ bool UnixDeviceFileAccess::setPermissions(const FilePath &filePath, QFile::Permi
qint64 UnixDeviceFileAccess::fileSize(const FilePath &filePath) const
{
+ if (disconnected())
+ return -1;
+
const QStringList args = statArgs(filePath, "%s", "%z");
const RunResult result = runInShell({"stat", args, OsType::OsTypeLinux});
return result.stdOut.toLongLong();
@@ -1175,12 +1242,18 @@ qint64 UnixDeviceFileAccess::fileSize(const FilePath &filePath) const
qint64 UnixDeviceFileAccess::bytesAvailable(const FilePath &filePath) const
{
+ if (disconnected())
+ return -1;
+
const RunResult result = runInShell({"df", {"-k", filePath.path()}, OsType::OsTypeLinux});
return FileUtils::bytesAvailableFromDFOutput(result.stdOut);
}
QByteArray UnixDeviceFileAccess::fileId(const FilePath &filePath) const
{
+ if (disconnected())
+ return {};
+
const QStringList args = statArgs(filePath, "%D:%i", "%d:%i");
const RunResult result = runInShell({"stat", args, OsType::OsTypeLinux});
@@ -1192,6 +1265,9 @@ QByteArray UnixDeviceFileAccess::fileId(const FilePath &filePath) const
FilePathInfo UnixDeviceFileAccess::filePathInfo(const FilePath &filePath) const
{
+ if (disconnected())
+ return {};
+
if (filePath.path() == "/") // TODO: Add FilePath::isRoot()
{
const FilePathInfo r{4096,
@@ -1218,6 +1294,9 @@ bool UnixDeviceFileAccess::iterateWithFind(const FilePath &filePath,
const FileFilter &filter,
const FilePath::IterateDirCallback &callBack) const
{
+ if (disconnected())
+ return false;
+
QTC_CHECK(filePath.isAbsolutePath());
CommandLine cmdLine{"find", filter.asFindArguments(filePath.path()), OsType::OsTypeLinux};
@@ -1290,6 +1369,9 @@ void UnixDeviceFileAccess::findUsingLs(const QString &current,
QStringList *found,
const QString &start) const
{
+ if (disconnected())
+ return;
+
const RunResult result = runInShell(
{"ls", {"-1", "-a", "-p", "--", current}, OsType::OsTypeLinux});
const QStringList entries = QString::fromUtf8(result.stdOut).split('\n', Qt::SkipEmptyParts);
@@ -1349,6 +1431,9 @@ void UnixDeviceFileAccess::iterateDirectory(const FilePath &filePath,
const FilePath::IterateDirCallback &callBack,
const FileFilter &filter) const
{
+ if (disconnected())
+ return;
+
// We try to use 'find' first, because that can filter better directly.
// Unfortunately, it's not installed on all devices by default.
if (m_tryUseFind) {
@@ -1366,9 +1451,17 @@ void UnixDeviceFileAccess::iterateDirectory(const FilePath &filePath,
Environment UnixDeviceFileAccess::deviceEnvironment() const
{
+ if (disconnected())
+ return {};
+
const RunResult result = runInShell({"env", {}, OsType::OsTypeLinux});
const QString out = QString::fromUtf8(result.stdOut);
return Environment(out.split('\n', Qt::SkipEmptyParts), OsTypeLinux);
}
+bool UnixDeviceFileAccess::disconnected() const
+{
+ return false;
+}
+
} // namespace Utils
diff --git a/src/libs/utils/devicefileaccess.h b/src/libs/utils/devicefileaccess.h
index 5b7c766a8a..ba48454127 100644
--- a/src/libs/utils/devicefileaccess.h
+++ b/src/libs/utils/devicefileaccess.h
@@ -188,6 +188,8 @@ protected:
QStringList *found,
const QString &start) const;
+ virtual bool disconnected() const;
+
private:
bool iterateWithFind(const FilePath &filePath,
const FileFilter &filter,
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index b1143c7fab..be43f2a206 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -50,7 +50,7 @@ Environment::Environment(const NameValueDictionary &dict)
m_changeItems.append(dict);
}
-NameValueItems Environment::diff(const Environment &other, bool checkAppendPrepend) const
+EnvironmentItems Environment::diff(const Environment &other, bool checkAppendPrepend) const
{
const NameValueDictionary &dict = resolved();
const NameValueDictionary &otherDict = other.resolved();
@@ -393,7 +393,7 @@ void Environment::unset(const QString &key)
addItem(Item{std::in_place_index_t<UnsetValue>(), key});
}
-void Environment::modify(const NameValueItems &items)
+void Environment::modify(const EnvironmentItems &items)
{
addItem(Item{std::in_place_index_t<Modify>(), items});
}
@@ -485,7 +485,7 @@ const NameValueDictionary &Environment::resolved() const
break;
}
case Modify: {
- NameValueItems items = std::get<Modify>(item);
+ EnvironmentItems items = std::get<Modify>(item);
m_dict.modify(items);
break;
}
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index 542343aa2a..1b6b7d2c0e 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -37,7 +37,7 @@ public:
void set(const QString &key, const QString &value, bool enabled = true);
void setFallback(const QString &key, const QString &value);
void unset(const QString &key);
- void modify(const NameValueItems &items);
+ void modify(const EnvironmentItems &items);
bool hasChanges() const;
@@ -79,7 +79,7 @@ public:
QStringList expandVariables(const QStringList &input) const;
NameValueDictionary toDictionary() const; // FIXME: avoid
- NameValueItems diff(const Environment &other, bool checkAppendPrepend = false) const; // FIXME: avoid
+ EnvironmentItems diff(const Environment &other, bool checkAppendPrepend = false) const; // FIXME: avoid
struct Entry { QString key; QString value; bool enabled; };
using FindResult = std::optional<Entry>;
@@ -117,7 +117,7 @@ public:
QString, // UnsetValue (key)
std::tuple<QString, QString, PathSeparator>, // PrependOrSet (key, value, separator)
std::tuple<QString, QString, PathSeparator>, // AppendOrSet (key, value, separator)
- NameValueItems, // Modify
+ EnvironmentItems, // Modify
std::monostate, // SetupEnglishOutput
FilePath // SetupSudoAskPass (file path of qtc-askpass or ssh-askpass)
>;
diff --git a/src/libs/utils/environmentfwd.h b/src/libs/utils/environmentfwd.h
index 8a2c444cc4..376d1ea08c 100644
--- a/src/libs/utils/environmentfwd.h
+++ b/src/libs/utils/environmentfwd.h
@@ -7,19 +7,10 @@
namespace Utils {
-class NameValueDictionary;
-class NameValueItem;
-using NameValueItems = QList<NameValueItem>;
-
class Environment;
-using EnvironmentItem = NameValueItem;
-using EnvironmentItems = NameValueItems;
+class EnvironmentItem;
+using EnvironmentItems = QList<EnvironmentItem>;
-class PreprocessorMacroDictionary;
-using PreprocessorMacroItem = NameValueItem;
-using PreprocessorMacroItems = NameValueItems;
-
-class NameValueModel;
-class EnvironmentModel;
+class NameValueDictionary;
} // namespace Utils
diff --git a/src/libs/utils/environmentmodel.cpp b/src/libs/utils/environmentmodel.cpp
index 1332959784..6ac9b35640 100644
--- a/src/libs/utils/environmentmodel.cpp
+++ b/src/libs/utils/environmentmodel.cpp
@@ -1,20 +1,458 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "environmentmodel.h"
+#include "algorithm.h"
#include "environment.h"
+#include "hostosinfo.h"
+#include "namevaluedictionary.h"
+#include "namevalueitem.h"
+#include "qtcassert.h"
+#include "utilstr.h"
+
+#include <QFileInfo>
+#include <QFont>
+#include <QGuiApplication>
+#include <QPalette>
+#include <QString>
namespace Utils {
-Environment EnvironmentModel::baseEnvironment() const
+namespace Internal {
+
+class EnvironmentModelPrivate
+{
+public:
+ void updateResultNameValueDictionary()
+ {
+ m_resultNameValueDictionary = m_baseNameValueDictionary;
+ m_resultNameValueDictionary.modify(m_items);
+ // Add removed variables again and mark them as "<UNSET>" so
+ // that the user can actually see those removals:
+ for (const EnvironmentItem &item : std::as_const(m_items)) {
+ if (item.operation == EnvironmentItem::Unset)
+ m_resultNameValueDictionary.set(item.name, Tr::tr("<UNSET>"));
+ }
+ }
+
+ int findInChanges(const QString &name) const
+ {
+ for (int i = 0; i < m_items.size(); ++i)
+ if (m_items.at(i).name.compare(name,
+ m_baseNameValueDictionary.nameCaseSensitivity()) == 0) {
+ return i;
+ }
+ return -1;
+ }
+
+ int findInResultInsertPosition(const QString &name) const
+ {
+ NameValueDictionary::const_iterator it;
+ int i = 0;
+ for (it = m_resultNameValueDictionary.constBegin();
+ it != m_resultNameValueDictionary.constEnd();
+ ++it, ++i)
+ if (it.key() > DictKey(name, m_resultNameValueDictionary.nameCaseSensitivity()))
+ return i;
+ return m_resultNameValueDictionary.size();
+ }
+
+ int findInResult(const QString &name) const
+ {
+ NameValueDictionary::const_iterator it;
+ int i = 0;
+ for (it = m_resultNameValueDictionary.constBegin();
+ it != m_resultNameValueDictionary.constEnd();
+ ++it, ++i)
+ if (m_resultNameValueDictionary.key(it)
+ .compare(name, m_resultNameValueDictionary.nameCaseSensitivity()) == 0) {
+ return i;
+ }
+ return -1;
+ }
+
+ NameValueDictionary m_baseNameValueDictionary;
+ NameValueDictionary m_resultNameValueDictionary;
+ EnvironmentItems m_items;
+};
+
+} // namespace Internal
+
+EnvironmentModel::EnvironmentModel(QObject *parent)
+ : QAbstractTableModel(parent)
+ , d(std::make_unique<Internal::EnvironmentModelPrivate>())
+{}
+
+EnvironmentModel::~EnvironmentModel() = default;
+
+QString EnvironmentModel::indexToVariable(const QModelIndex &index) const
{
- return Environment(baseNameValueDictionary());
+ const auto it = std::next(d->m_resultNameValueDictionary.constBegin(), index.row());
+ return d->m_resultNameValueDictionary.key(it);
}
void EnvironmentModel::setBaseEnvironment(const Environment &env)
{
- setBaseNameValueDictionary(env.toDictionary());
+ const NameValueDictionary dictionary = env.toDictionary();
+ if (d->m_baseNameValueDictionary == dictionary)
+ return;
+ beginResetModel();
+ d->m_baseNameValueDictionary = dictionary;
+ d->updateResultNameValueDictionary();
+ endResetModel();
+}
+
+int EnvironmentModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return d->m_resultNameValueDictionary.size();
+}
+int EnvironmentModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return 2;
+}
+
+bool EnvironmentModel::changes(const QString &name) const
+{
+ return d->findInChanges(name) >= 0;
+}
+
+Environment EnvironmentModel::baseEnvironment() const
+{
+ return Environment(d->m_baseNameValueDictionary);
+}
+
+QVariant EnvironmentModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ const auto resultIterator = std::next(d->m_resultNameValueDictionary.constBegin(), index.row());
+
+ switch (role) {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ case Qt::ToolTipRole:
+ if (index.column() == 0)
+ return d->m_resultNameValueDictionary.key(resultIterator);
+ if (index.column() == 1) {
+ // Do not return "<UNSET>" when editing a previously unset variable:
+ if (role == Qt::EditRole) {
+ int pos = d->findInChanges(indexToVariable(index));
+ if (pos != -1 && d->m_items.at(pos).operation == EnvironmentItem::Unset)
+ return QString();
+ }
+ QString value = d->m_resultNameValueDictionary.value(resultIterator);
+ if (role == Qt::ToolTipRole && value.length() > 80) {
+ if (currentEntryIsPathList(index)) {
+ // For path lists, display one entry per line without separator
+ const QChar sep = Utils::HostOsInfo::pathListSeparator();
+ value = value.replace(sep, '\n');
+ } else {
+ // Use html to enable text wrapping
+ value = value.toHtmlEscaped();
+ value.prepend(QLatin1String("<html><body>"));
+ value.append(QLatin1String("</body></html>"));
+ }
+ }
+ return value;
+ }
+ break;
+ case Qt::FontRole: {
+ QFont f;
+ f.setStrikeOut(!d->m_resultNameValueDictionary.isEnabled(resultIterator));
+ return f;
+ }
+ case Qt::ForegroundRole: {
+ const QPalette p = QGuiApplication::palette();
+ return p.color(changes(d->m_resultNameValueDictionary.key(resultIterator))
+ ? QPalette::Link : QPalette::Text);
+ }
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags EnvironmentModel::flags(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+QVariant EnvironmentModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Vertical || role != Qt::DisplayRole)
+ return QVariant();
+ return section == 0 ? Tr::tr("Variable") : Tr::tr("Value");
+}
+
+/// *****************
+/// Utility functions
+/// *****************
+QModelIndex EnvironmentModel::variableToIndex(const QString &name) const
+{
+ int row = d->findInResult(name);
+ if (row == -1)
+ return QModelIndex();
+ return index(row, 0);
+}
+
+bool EnvironmentModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid() || role != Qt::EditRole)
+ return false;
+
+ // ignore changes to already set values:
+ if (data(index, role) == value)
+ return true;
+
+ const QString oldName = data(this->index(index.row(), 0, QModelIndex())).toString();
+ const QString oldValue = data(this->index(index.row(), 1, QModelIndex()), Qt::EditRole).toString();
+ int changesPos = d->findInChanges(oldName);
+
+ if (index.column() == 0) {
+ //fail if a variable with the same name already exists
+ const QString &newName = HostOsInfo::isWindowsHost() ? value.toString().toUpper()
+ : value.toString();
+ if (newName.isEmpty() || newName.contains('='))
+ return false;
+ // Does the new name exist already?
+ if (d->m_resultNameValueDictionary.hasKey(newName) || newName.isEmpty())
+ return false;
+
+ EnvironmentItem newVariable(newName, oldValue);
+
+ if (changesPos != -1)
+ resetVariable(oldName); // restore the original base variable again
+
+ QModelIndex newIndex = addVariable(newVariable); // add the new variable
+ emit focusIndex(newIndex.sibling(newIndex.row(), 1)); // hint to focus on the value
+ return true;
+ } else if (index.column() == 1) {
+ // We are changing an existing value:
+ const QString stringValue = value.toString();
+ if (changesPos != -1) {
+ const auto oldIt = d->m_baseNameValueDictionary.constFind(oldName);
+ const auto newIt = d->m_resultNameValueDictionary.constFind(oldName);
+ // We have already changed this value
+ if (oldIt != d->m_baseNameValueDictionary.constEnd()
+ && stringValue == d->m_baseNameValueDictionary.value(oldIt)
+ && d->m_baseNameValueDictionary.isEnabled(oldIt)
+ == d->m_resultNameValueDictionary.isEnabled(newIt)) {
+ // ... and now went back to the base value
+ d->m_items.removeAt(changesPos);
+ } else {
+ // ... and changed it again
+ d->m_items[changesPos].value = stringValue;
+ if (d->m_items[changesPos].operation == EnvironmentItem::Unset)
+ d->m_items[changesPos].operation = EnvironmentItem::SetEnabled;
+ }
+ } else {
+ // Add a new change item:
+ d->m_items.append(EnvironmentItem(oldName, stringValue));
+ }
+ d->updateResultNameValueDictionary();
+ emit dataChanged(index, index);
+ emit userChangesChanged();
+ return true;
+ }
+ return false;
+}
+
+QModelIndex EnvironmentModel::addVariable()
+{
+ return addVariable(EnvironmentItem("NEWVAR", "VALUE"));
+}
+
+QModelIndex EnvironmentModel::addVariable(const EnvironmentItem &item)
+{
+ // Return existing index if the name is already in the result set:
+ int pos = d->findInResult(item.name);
+ if (pos >= 0 && pos < d->m_resultNameValueDictionary.size())
+ return index(pos, 0, QModelIndex());
+
+ int insertPos = d->findInResultInsertPosition(item.name);
+ int changePos = d->findInChanges(item.name);
+ if (d->m_baseNameValueDictionary.hasKey(item.name)) {
+ // We previously unset this!
+ Q_ASSERT(changePos >= 0);
+ // Do not insert a line here as we listed the variable as <UNSET> before!
+ Q_ASSERT(d->m_items.at(changePos).name == item.name);
+ Q_ASSERT(d->m_items.at(changePos).operation == EnvironmentItem::Unset);
+ Q_ASSERT(d->m_items.at(changePos).value.isEmpty());
+ d->m_items[changePos] = item;
+ emit dataChanged(index(insertPos, 0, QModelIndex()), index(insertPos, 1, QModelIndex()));
+ } else {
+ // We add something that is not in the base dictionary
+ // Insert a new line!
+ beginInsertRows(QModelIndex(), insertPos, insertPos);
+ Q_ASSERT(changePos < 0);
+ d->m_items.append(item);
+ d->updateResultNameValueDictionary();
+ endInsertRows();
+ }
+ emit userChangesChanged();
+ return index(insertPos, 0, QModelIndex());
+}
+
+void EnvironmentModel::resetVariable(const QString &name)
+{
+ int rowInChanges = d->findInChanges(name);
+ if (rowInChanges < 0)
+ return;
+
+ int rowInResult = d->findInResult(name);
+ if (rowInResult < 0)
+ return;
+
+ if (d->m_baseNameValueDictionary.hasKey(name)) {
+ d->m_items.removeAt(rowInChanges);
+ d->updateResultNameValueDictionary();
+ emit dataChanged(index(rowInResult, 0, QModelIndex()), index(rowInResult, 1, QModelIndex()));
+ emit userChangesChanged();
+ } else {
+ // Remove the line completely!
+ beginRemoveRows(QModelIndex(), rowInResult, rowInResult);
+ d->m_items.removeAt(rowInChanges);
+ d->updateResultNameValueDictionary();
+ endRemoveRows();
+ emit userChangesChanged();
+ }
+}
+
+void EnvironmentModel::unsetVariable(const QString &name)
+{
+ // This does not change the number of rows as we will display a <UNSET>
+ // in place of the original variable!
+ int row = d->findInResult(name);
+ if (row < 0)
+ return;
+
+ // look in d->m_items for the variable
+ int pos = d->findInChanges(name);
+ if (pos != -1) {
+ d->m_items[pos].operation = EnvironmentItem::Unset;
+ d->m_items[pos].value.clear();
+ d->updateResultNameValueDictionary();
+ emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
+ emit userChangesChanged();
+ return;
+ }
+ d->m_items.append(EnvironmentItem(name, QString(), EnvironmentItem::Unset));
+ d->updateResultNameValueDictionary();
+ emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
+ emit userChangesChanged();
+}
+
+void EnvironmentModel::toggleVariable(const QModelIndex &idx)
+{
+ const QString name = indexToVariable(idx);
+ const auto newIt = d->m_resultNameValueDictionary.constFind(name);
+ QTC_ASSERT(newIt != d->m_resultNameValueDictionary.constEnd(), return);
+ const auto op = d->m_resultNameValueDictionary.isEnabled(newIt)
+ ? EnvironmentItem::SetDisabled : EnvironmentItem::SetEnabled;
+ const int changesPos = d->findInChanges(name);
+ if (changesPos != -1) {
+ const auto oldIt = d->m_baseNameValueDictionary.constFind(name);
+ if (oldIt == d->m_baseNameValueDictionary.constEnd()
+ || oldIt.value().first != newIt.value().first) {
+ d->m_items[changesPos].operation = op;
+ } else {
+ d->m_items.removeAt(changesPos);
+ }
+ } else {
+ d->m_items.append({name, d->m_resultNameValueDictionary.value(newIt), op});
+ }
+ d->updateResultNameValueDictionary();
+ emit dataChanged(index(idx.row(), 0), index(idx.row(), 1));
+ emit userChangesChanged();
+}
+
+bool EnvironmentModel::isUnset(const QString &name)
+{
+ const int pos = d->findInChanges(name);
+ return pos == -1 ? false : d->m_items.at(pos).operation == EnvironmentItem::Unset;
+}
+
+bool EnvironmentModel::isEnabled(const QString &name) const
+{
+ return d->m_resultNameValueDictionary.isEnabled(d->m_resultNameValueDictionary.constFind(name));
+}
+
+bool EnvironmentModel::canReset(const QString &name)
+{
+ return d->m_baseNameValueDictionary.hasKey(name);
+}
+
+EnvironmentItems EnvironmentModel::userChanges() const
+{
+ return d->m_items;
+}
+
+void EnvironmentModel::setUserChanges(const EnvironmentItems &items)
+{
+ EnvironmentItems filtered = Utils::filtered(items, [](const EnvironmentItem &i) {
+ return i.name != "export " && !i.name.contains('=');
+ });
+ // We assume nobody is reordering the items here.
+ if (filtered == d->m_items)
+ return;
+ beginResetModel();
+ d->m_items = filtered;
+ for (EnvironmentItem &item : d->m_items) {
+ QString &name = item.name;
+ name = name.trimmed();
+ if (name.startsWith("export "))
+ name = name.mid(7).trimmed();
+ if (d->m_baseNameValueDictionary.osType() == OsTypeWindows) {
+ // NameValueDictionary variable names are case-insensitive under windows, but we still
+ // want to preserve the case of pre-existing variables.
+ auto it = d->m_baseNameValueDictionary.constFind(name);
+ if (it != d->m_baseNameValueDictionary.constEnd())
+ name = d->m_baseNameValueDictionary.key(it);
+ }
+ }
+
+ d->updateResultNameValueDictionary();
+ endResetModel();
+ emit userChangesChanged();
+}
+
+bool EnvironmentModel::currentEntryIsPathList(const QModelIndex &current) const
+{
+ if (!current.isValid())
+ return false;
+
+ // Look at the name first and check it against some well-known path variables. Extend as needed.
+ const QString varName = indexToVariable(current);
+ if (varName.compare("PATH", Utils::HostOsInfo::fileNameCaseSensitivity()) == 0)
+ return true;
+ if (Utils::HostOsInfo::isMacHost() && varName == "DYLD_LIBRARY_PATH")
+ return true;
+ if (Utils::HostOsInfo::isAnyUnixHost() && varName == "LD_LIBRARY_PATH")
+ return true;
+ if (varName == "PKG_CONFIG_DIR")
+ return true;
+ if (Utils::HostOsInfo::isWindowsHost()
+ && QStringList{"INCLUDE", "LIB", "LIBPATH"}.contains(varName)) {
+ return true;
+ }
+
+ // Now check the value: If it's a list of strings separated by the platform's path separator
+ // and at least one of the strings is an existing directory, then that's enough proof for us.
+ QModelIndex valueIndex = current;
+ if (valueIndex.column() == 0)
+ valueIndex = valueIndex.siblingAtColumn(1);
+ const QStringList entries = data(valueIndex).toString()
+ .split(Utils::HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts);
+ if (entries.length() < 2)
+ return false;
+ return Utils::anyOf(entries, [](const QString &d) { return QFileInfo(d).isDir(); });
}
} // namespace Utils
diff --git a/src/libs/utils/environmentmodel.h b/src/libs/utils/environmentmodel.h
index 82bf98d43f..07670bd13f 100644
--- a/src/libs/utils/environmentmodel.h
+++ b/src/libs/utils/environmentmodel.h
@@ -1,19 +1,64 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "utils_global.h"
-#include "namevaluemodel.h"
+#include "environmentfwd.h"
+
+#include <QAbstractTableModel>
+
+#include <memory>
namespace Utils {
-class QTCREATOR_UTILS_EXPORT EnvironmentModel : public NameValueModel
+namespace Internal { class EnvironmentModelPrivate; }
+
+class QTCREATOR_UTILS_EXPORT EnvironmentModel : public QAbstractTableModel
{
+ Q_OBJECT
+
public:
+ explicit EnvironmentModel(QObject *parent = nullptr);
+ ~EnvironmentModel() override;
+
+ int rowCount(const QModelIndex &parent) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ QVariant headerData(int section,
+ Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const override;
+
Environment baseEnvironment() const;
void setBaseEnvironment(const Environment &env);
+
+ QModelIndex addVariable();
+ QModelIndex addVariable(const EnvironmentItem &item);
+ void resetVariable(const QString &name);
+ void unsetVariable(const QString &name);
+ void toggleVariable(const QModelIndex &index);
+ bool isUnset(const QString &name);
+ bool isEnabled(const QString &name) const;
+ bool canReset(const QString &name);
+ QString indexToVariable(const QModelIndex &index) const;
+ QModelIndex variableToIndex(const QString &name) const;
+ bool changes(const QString &key) const;
+ EnvironmentItems userChanges() const;
+ void setUserChanges(const EnvironmentItems &items);
+ bool currentEntryIsPathList(const QModelIndex &current) const;
+
+signals:
+ void userChangesChanged();
+ /// Hint to the view where it should make sense to focus on next
+ // This is a hack since there is no way for a model to suggest
+ // the next interesting place to focus on to the view.
+ void focusIndex(const QModelIndex &index);
+
+private:
+ std::unique_ptr<Internal::EnvironmentModelPrivate> d;
};
} // namespace Utils
diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp
index 5678be86b2..562f3247bd 100644
--- a/src/libs/utils/filepath.cpp
+++ b/src/libs/utils/filepath.cpp
@@ -2334,12 +2334,30 @@ QTCREATOR_UTILS_EXPORT bool operator!=(const FilePath &first, const FilePath &se
QTCREATOR_UTILS_EXPORT bool operator<(const FilePath &first, const FilePath &second)
{
- const int cmp = first.pathView().compare(second.pathView(), first.caseSensitivity());
- if (cmp != 0)
- return cmp < 0;
- if (first.host() != second.host())
- return first.host() < second.host();
- return first.scheme() < second.scheme();
+ const bool firstNeedsDevice = first.needsDevice();
+ const bool secondNeedsDevice = second.needsDevice();
+
+ // If either needs a device, we have to compare host and scheme first.
+ if (firstNeedsDevice || secondNeedsDevice) {
+ // Paths needing a device are "larger" than those not needing one.
+ if (firstNeedsDevice < secondNeedsDevice)
+ return true;
+ else if (firstNeedsDevice > secondNeedsDevice)
+ return false;
+
+ // First we sort by scheme ...
+ const int s = first.scheme().compare(second.scheme());
+ if (s != 0)
+ return s < 0;
+
+ // than by host ...
+ const int h = first.host().compare(second.host());
+ if (h != 0)
+ return h < 0;
+ }
+
+ const int p = first.pathView().compare(second.pathView(), first.caseSensitivity());
+ return p < 0;
}
QTCREATOR_UTILS_EXPORT bool operator<=(const FilePath &first, const FilePath &second)
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index 4530ea206b..a2998e2f07 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -239,6 +239,11 @@ bool FileSaver::finalize()
TempFileSaver::TempFileSaver(const QString &templ)
{
+ initFromString(templ);
+}
+
+void TempFileSaver::initFromString(const QString &templ)
+{
m_file.reset(new QTemporaryFile{});
auto tempFile = static_cast<QTemporaryFile *>(m_file.get());
if (!templ.isEmpty())
@@ -253,6 +258,29 @@ TempFileSaver::TempFileSaver(const QString &templ)
m_filePath = FilePath::fromString(tempFile->fileName());
}
+TempFileSaver::TempFileSaver(const FilePath &templ)
+{
+ if (templ.isEmpty() || !templ.needsDevice()) {
+ initFromString(templ.path());
+ } else {
+ expected_str<FilePath> result = templ.createTempFile();
+ if (!result) {
+ m_errorString = Tr::tr("Cannot create temporary file %1: %2")
+ .arg(templ.toUserOutput(), result.error());
+ m_hasError = true;
+ return;
+ }
+
+ m_file.reset(new QFile(result->toFSPathString()));
+ if (!m_file->open(QIODevice::WriteOnly)) {
+ m_errorString = Tr::tr("Cannot create temporary file %1: %2")
+ .arg(result->toUserOutput(), m_file->errorString());
+ m_hasError = true;
+ }
+ m_filePath = *result;
+ }
+}
+
TempFileSaver::~TempFileSaver()
{
m_file.reset();
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index 316030b039..b20f7568db 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -222,10 +222,14 @@ class QTCREATOR_UTILS_EXPORT TempFileSaver : public FileSaverBase
{
public:
explicit TempFileSaver(const QString &templ = QString());
+ explicit TempFileSaver(const FilePath &templ);
~TempFileSaver() override;
void setAutoRemove(bool on) { m_autoRemove = on; }
+protected:
+ void initFromString(const QString &templ);
+
private:
bool m_autoRemove = true;
};
diff --git a/src/libs/utils/namevaluedictionary.cpp b/src/libs/utils/namevaluedictionary.cpp
index 05ff4761dd..d93298b3f1 100644
--- a/src/libs/utils/namevaluedictionary.cpp
+++ b/src/libs/utils/namevaluedictionary.cpp
@@ -97,34 +97,34 @@ int NameValueDictionary::size() const
return m_values.size();
}
-void NameValueDictionary::modify(const NameValueItems &items)
+void NameValueDictionary::modify(const EnvironmentItems &items)
{
NameValueDictionary resultKeyValueDictionary = *this;
- for (const NameValueItem &item : items)
+ for (const EnvironmentItem &item : items)
item.apply(&resultKeyValueDictionary);
*this = resultKeyValueDictionary;
}
-NameValueItems NameValueDictionary::diff(const NameValueDictionary &other, bool checkAppendPrepend) const
+EnvironmentItems NameValueDictionary::diff(const NameValueDictionary &other, bool checkAppendPrepend) const
{
NameValueMap::const_iterator thisIt = constBegin();
NameValueMap::const_iterator otherIt = other.constBegin();
- NameValueItems result;
+ EnvironmentItems result;
while (thisIt != constEnd() || otherIt != other.constEnd()) {
if (thisIt == constEnd()) {
result.append({other.key(otherIt), other.value(otherIt),
- otherIt.value().second ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
+ otherIt.value().second ? EnvironmentItem::SetEnabled : EnvironmentItem::SetDisabled});
++otherIt;
} else if (otherIt == other.constEnd()) {
- result.append(NameValueItem(key(thisIt), QString(), NameValueItem::Unset));
+ result.append(EnvironmentItem(key(thisIt), QString(), EnvironmentItem::Unset));
++thisIt;
} else if (thisIt.key() < otherIt.key()) {
- result.append(NameValueItem(key(thisIt), QString(), NameValueItem::Unset));
+ result.append(EnvironmentItem(key(thisIt), QString(), EnvironmentItem::Unset));
++thisIt;
} else if (thisIt.key() > otherIt.key()) {
result.append({other.key(otherIt), otherIt.value().first,
- otherIt.value().second ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
+ otherIt.value().second ? EnvironmentItem::SetEnabled : EnvironmentItem::SetDisabled});
++otherIt;
} else {
const QString &oldValue = thisIt.value().first;
@@ -137,16 +137,16 @@ NameValueItems NameValueDictionary::diff(const NameValueDictionary &other, bool
QString appended = newValue.right(newValue.size() - oldValue.size());
if (appended.startsWith(OsSpecificAspects::pathListSeparator(osType())))
appended.remove(0, 1);
- result.append(NameValueItem(other.key(otherIt), appended, NameValueItem::Append));
+ result.append(EnvironmentItem(other.key(otherIt), appended, EnvironmentItem::Append));
} else if (checkAppendPrepend && newValue.endsWith(oldValue)
&& oldEnabled == newEnabled) {
QString prepended = newValue.left(newValue.size() - oldValue.size());
if (prepended.endsWith(OsSpecificAspects::pathListSeparator(osType())))
prepended.chop(1);
- result.append(NameValueItem(other.key(otherIt), prepended, NameValueItem::Prepend));
+ result.append(EnvironmentItem(other.key(otherIt), prepended, EnvironmentItem::Prepend));
} else {
result.append({other.key(otherIt), newValue, newEnabled
- ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
+ ? EnvironmentItem::SetEnabled : EnvironmentItem::SetDisabled});
}
}
++otherIt;
diff --git a/src/libs/utils/namevaluedictionary.h b/src/libs/utils/namevaluedictionary.h
index 722558f891..87d8124970 100644
--- a/src/libs/utils/namevaluedictionary.h
+++ b/src/libs/utils/namevaluedictionary.h
@@ -48,9 +48,9 @@ public:
QString value(const QString &key) const;
void set(const QString &key, const QString &value, bool enabled = true);
void unset(const QString &key);
- void modify(const NameValueItems &items);
+ void modify(const EnvironmentItems &items);
/// Return the KeyValueDictionary changes necessary to modify this into the other environment.
- NameValueItems diff(const NameValueDictionary &other, bool checkAppendPrepend = false) const;
+ EnvironmentItems diff(const NameValueDictionary &other, bool checkAppendPrepend = false) const;
bool hasKey(const QString &key) const;
OsType osType() const;
Qt::CaseSensitivity nameCaseSensitivity() const;
diff --git a/src/libs/utils/namevalueitem.cpp b/src/libs/utils/namevalueitem.cpp
index adc7ff5afc..3f4cdbd4b2 100644
--- a/src/libs/utils/namevalueitem.cpp
+++ b/src/libs/utils/namevalueitem.cpp
@@ -10,34 +10,34 @@
namespace Utils {
-void NameValueItem::sort(NameValueItems *list)
+void EnvironmentItem::sort(EnvironmentItems *list)
{
- Utils::sort(*list, &NameValueItem::name);
+ Utils::sort(*list, &EnvironmentItem::name);
}
-NameValueItems NameValueItem::fromStringList(const QStringList &list)
+EnvironmentItems EnvironmentItem::fromStringList(const QStringList &list)
{
- NameValueItems result;
+ EnvironmentItems result;
for (const QString &string : list) {
int pos = string.indexOf("+=");
if (pos != -1) {
- result.append({string.left(pos), string.mid(pos + 2), NameValueItem::Append});
+ result.append({string.left(pos), string.mid(pos + 2), EnvironmentItem::Append});
continue;
}
pos = string.indexOf("=+");
if (pos != -1) {
- result.append({string.left(pos), string.mid(pos + 2), NameValueItem::Prepend});
+ result.append({string.left(pos), string.mid(pos + 2), EnvironmentItem::Prepend});
continue;
}
pos = string.indexOf('=', 1);
if (pos == -1) {
- result.append(NameValueItem(string, QString(), NameValueItem::Unset));
+ result.append(EnvironmentItem(string, QString(), EnvironmentItem::Unset));
continue;
}
const int hashPos = string.indexOf('#');
if (hashPos != -1 && hashPos < pos) {
result.append({string.mid(hashPos + 1, pos - hashPos - 1), string.mid(pos + 1),
- NameValueItem::SetDisabled});
+ EnvironmentItem::SetDisabled});
} else {
result.append({string.left(pos), string.mid(pos + 1)});
}
@@ -45,49 +45,49 @@ NameValueItems NameValueItem::fromStringList(const QStringList &list)
return result;
}
-QStringList NameValueItem::toStringList(const NameValueItems &list)
+QStringList EnvironmentItem::toStringList(const EnvironmentItems &list)
{
- return Utils::transform<QStringList>(list, [](const NameValueItem &item) {
+ return Utils::transform<QStringList>(list, [](const EnvironmentItem &item) {
switch (item.operation) {
- case NameValueItem::Unset:
+ case EnvironmentItem::Unset:
return item.name;
- case NameValueItem::Append:
+ case EnvironmentItem::Append:
return QString(item.name + "+=" + item.value);
- case NameValueItem::Prepend:
+ case EnvironmentItem::Prepend:
return QString(item.name + "=+" + item.value);
- case NameValueItem::SetDisabled:
+ case EnvironmentItem::SetDisabled:
return QString('#' + item.name + '=' + item.value);
- case NameValueItem::SetEnabled:
+ case EnvironmentItem::SetEnabled:
return QString(item.name + '=' + item.value);
}
return QString();
});
}
-NameValueItems NameValueItem::itemsFromVariantList(const QVariantList &list)
+EnvironmentItems EnvironmentItem::itemsFromVariantList(const QVariantList &list)
{
- return Utils::transform<NameValueItems>(list, [](const QVariant &item) {
+ return Utils::transform<EnvironmentItems>(list, [](const QVariant &item) {
return itemFromVariantList(item.toList());
});
}
-QVariantList NameValueItem::toVariantList(const NameValueItems &list)
+QVariantList EnvironmentItem::toVariantList(const EnvironmentItems &list)
{
- return Utils::transform<QVariantList>(list, [](const NameValueItem &item) {
+ return Utils::transform<QVariantList>(list, [](const EnvironmentItem &item) {
return QVariant(toVariantList(item));
});
}
-NameValueItem NameValueItem::itemFromVariantList(const QVariantList &list)
+EnvironmentItem EnvironmentItem::itemFromVariantList(const QVariantList &list)
{
- QTC_ASSERT(list.size() == 3, return NameValueItem("", ""));
+ QTC_ASSERT(list.size() == 3, return EnvironmentItem("", ""));
QString key = list.value(0).toString();
Operation operation = Operation(list.value(1).toInt());
QString value = list.value(2).toString();
- return NameValueItem(key, value, operation);
+ return EnvironmentItem(key, value, operation);
}
-QVariantList NameValueItem::toVariantList(const NameValueItem &item)
+QVariantList EnvironmentItem::toVariantList(const EnvironmentItem &item)
{
return QVariantList() << item.name << item.operation << item.value;
}
@@ -118,7 +118,7 @@ static QString expand(const NameValueDictionary *dictionary, QString value)
return value;
}
-void NameValueItem::apply(NameValueDictionary *dictionary, Operation op) const
+void EnvironmentItem::apply(NameValueDictionary *dictionary, Operation op) const
{
switch (op) {
case SetEnabled:
@@ -173,26 +173,26 @@ void NameValueItem::apply(NameValueDictionary *dictionary, Operation op) const
}
}
-QDebug operator<<(QDebug debug, const NameValueItem &i)
+QDebug operator<<(QDebug debug, const EnvironmentItem &i)
{
QDebugStateSaver saver(debug);
debug.noquote();
debug.nospace();
debug << "KeyValueItem(";
switch (i.operation) {
- case NameValueItem::SetEnabled:
+ case EnvironmentItem::SetEnabled:
debug << "set \"" << i.name << "\" to \"" << i.value << '"';
break;
- case NameValueItem::SetDisabled:
+ case EnvironmentItem::SetDisabled:
debug << "set \"" << i.name << "\" to \"" << i.value << '"' << "[disabled]";
break;
- case NameValueItem::Unset:
+ case EnvironmentItem::Unset:
debug << "unset \"" << i.name << '"';
break;
- case NameValueItem::Prepend:
+ case EnvironmentItem::Prepend:
debug << "prepend to \"" << i.name << "\":\"" << i.value << '"';
break;
- case NameValueItem::Append:
+ case EnvironmentItem::Append:
debug << "append to \"" << i.name << "\":\"" << i.value << '"';
break;
}
diff --git a/src/libs/utils/namevalueitem.h b/src/libs/utils/namevalueitem.h
index 62ba9d25ba..6ad5ed0379 100644
--- a/src/libs/utils/namevalueitem.h
+++ b/src/libs/utils/namevalueitem.h
@@ -13,12 +13,12 @@
namespace Utils {
-class QTCREATOR_UTILS_EXPORT NameValueItem
+class QTCREATOR_UTILS_EXPORT EnvironmentItem
{
public:
enum Operation : char { SetEnabled, Unset, Prepend, Append, SetDisabled };
- NameValueItem() = default;
- NameValueItem(const QString &key, const QString &value, Operation operation = SetEnabled)
+ EnvironmentItem() = default;
+ EnvironmentItem(const QString &key, const QString &value, Operation operation = SetEnabled)
: name(key)
, value(value)
, operation(operation)
@@ -26,25 +26,25 @@ public:
void apply(NameValueDictionary *dictionary) const { apply(dictionary, operation); }
- static void sort(NameValueItems *list);
- static NameValueItems fromStringList(const QStringList &list);
- static QStringList toStringList(const NameValueItems &list);
- static NameValueItems itemsFromVariantList(const QVariantList &list);
- static QVariantList toVariantList(const NameValueItems &list);
- static NameValueItem itemFromVariantList(const QVariantList &list);
- static QVariantList toVariantList(const NameValueItem &item);
+ static void sort(EnvironmentItems *list);
+ static EnvironmentItems fromStringList(const QStringList &list);
+ static QStringList toStringList(const EnvironmentItems &list);
+ static EnvironmentItems itemsFromVariantList(const QVariantList &list);
+ static QVariantList toVariantList(const EnvironmentItems &list);
+ static EnvironmentItem itemFromVariantList(const QVariantList &list);
+ static QVariantList toVariantList(const EnvironmentItem &item);
- friend bool operator==(const NameValueItem &first, const NameValueItem &second)
+ friend bool operator==(const EnvironmentItem &first, const EnvironmentItem &second)
{
return first.operation == second.operation && first.name == second.name
&& first.value == second.value;
}
- friend bool operator!=(const NameValueItem &first, const NameValueItem &second)
+ friend bool operator!=(const EnvironmentItem &first, const EnvironmentItem &second)
{
return !(first == second);
}
- friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug debug, const NameValueItem &i);
+ friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug debug, const EnvironmentItem &i);
public:
QString name;
diff --git a/src/libs/utils/namevaluemodel.cpp b/src/libs/utils/namevaluemodel.cpp
deleted file mode 100644
index 57327c4ebe..0000000000
--- a/src/libs/utils/namevaluemodel.cpp
+++ /dev/null
@@ -1,456 +0,0 @@
-// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "namevaluemodel.h"
-
-#include "algorithm.h"
-#include "hostosinfo.h"
-#include "namevaluedictionary.h"
-#include "namevalueitem.h"
-#include "qtcassert.h"
-#include "utilstr.h"
-
-#include <QFileInfo>
-#include <QFont>
-#include <QGuiApplication>
-#include <QPalette>
-#include <QString>
-
-namespace Utils {
-
-namespace Internal {
-
-class NameValueModelPrivate
-{
-public:
- void updateResultNameValueDictionary()
- {
- m_resultNameValueDictionary = m_baseNameValueDictionary;
- m_resultNameValueDictionary.modify(m_items);
- // Add removed variables again and mark them as "<UNSET>" so
- // that the user can actually see those removals:
- for (const NameValueItem &item : std::as_const(m_items)) {
- if (item.operation == NameValueItem::Unset)
- m_resultNameValueDictionary.set(item.name, Tr::tr("<UNSET>"));
- }
- }
-
- int findInChanges(const QString &name) const
- {
- for (int i = 0; i < m_items.size(); ++i)
- if (m_items.at(i).name.compare(name,
- m_baseNameValueDictionary.nameCaseSensitivity()) == 0) {
- return i;
- }
- return -1;
- }
-
- int findInResultInsertPosition(const QString &name) const
- {
- NameValueDictionary::const_iterator it;
- int i = 0;
- for (it = m_resultNameValueDictionary.constBegin();
- it != m_resultNameValueDictionary.constEnd();
- ++it, ++i)
- if (it.key() > DictKey(name, m_resultNameValueDictionary.nameCaseSensitivity()))
- return i;
- return m_resultNameValueDictionary.size();
- }
-
- int findInResult(const QString &name) const
- {
- NameValueDictionary::const_iterator it;
- int i = 0;
- for (it = m_resultNameValueDictionary.constBegin();
- it != m_resultNameValueDictionary.constEnd();
- ++it, ++i)
- if (m_resultNameValueDictionary.key(it)
- .compare(name, m_resultNameValueDictionary.nameCaseSensitivity()) == 0) {
- return i;
- }
- return -1;
- }
-
- NameValueDictionary m_baseNameValueDictionary;
- NameValueDictionary m_resultNameValueDictionary;
- NameValueItems m_items;
-};
-
-} // namespace Internal
-
-NameValueModel::NameValueModel(QObject *parent)
- : QAbstractTableModel(parent)
- , d(std::make_unique<Internal::NameValueModelPrivate>())
-{}
-
-NameValueModel::~NameValueModel() = default;
-
-QString NameValueModel::indexToVariable(const QModelIndex &index) const
-{
- const auto it = std::next(d->m_resultNameValueDictionary.constBegin(), index.row());
- return d->m_resultNameValueDictionary.key(it);
-}
-
-void NameValueModel::setBaseNameValueDictionary(const NameValueDictionary &dictionary)
-{
- if (d->m_baseNameValueDictionary == dictionary)
- return;
- beginResetModel();
- d->m_baseNameValueDictionary = dictionary;
- d->updateResultNameValueDictionary();
- endResetModel();
-}
-
-int NameValueModel::rowCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
-
- return d->m_resultNameValueDictionary.size();
-}
-int NameValueModel::columnCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
-
- return 2;
-}
-
-bool NameValueModel::changes(const QString &name) const
-{
- return d->findInChanges(name) >= 0;
-}
-
-const NameValueDictionary &NameValueModel::baseNameValueDictionary() const
-{
- return d->m_baseNameValueDictionary;
-}
-
-QVariant NameValueModel::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid())
- return QVariant();
-
- const auto resultIterator = std::next(d->m_resultNameValueDictionary.constBegin(), index.row());
-
- switch (role) {
- case Qt::DisplayRole:
- case Qt::EditRole:
- case Qt::ToolTipRole:
- if (index.column() == 0)
- return d->m_resultNameValueDictionary.key(resultIterator);
- if (index.column() == 1) {
- // Do not return "<UNSET>" when editing a previously unset variable:
- if (role == Qt::EditRole) {
- int pos = d->findInChanges(indexToVariable(index));
- if (pos != -1 && d->m_items.at(pos).operation == NameValueItem::Unset)
- return QString();
- }
- QString value = d->m_resultNameValueDictionary.value(resultIterator);
- if (role == Qt::ToolTipRole && value.length() > 80) {
- if (currentEntryIsPathList(index)) {
- // For path lists, display one entry per line without separator
- const QChar sep = Utils::HostOsInfo::pathListSeparator();
- value = value.replace(sep, '\n');
- } else {
- // Use html to enable text wrapping
- value = value.toHtmlEscaped();
- value.prepend(QLatin1String("<html><body>"));
- value.append(QLatin1String("</body></html>"));
- }
- }
- return value;
- }
- break;
- case Qt::FontRole: {
- QFont f;
- f.setStrikeOut(!d->m_resultNameValueDictionary.isEnabled(resultIterator));
- return f;
- }
- case Qt::ForegroundRole: {
- const QPalette p = QGuiApplication::palette();
- return p.color(changes(d->m_resultNameValueDictionary.key(resultIterator))
- ? QPalette::Link : QPalette::Text);
- }
- }
- return QVariant();
-}
-
-Qt::ItemFlags NameValueModel::flags(const QModelIndex &index) const
-{
- Q_UNUSED(index)
- return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
-}
-
-QVariant NameValueModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- if (orientation == Qt::Vertical || role != Qt::DisplayRole)
- return QVariant();
- return section == 0 ? Tr::tr("Variable") : Tr::tr("Value");
-}
-
-/// *****************
-/// Utility functions
-/// *****************
-QModelIndex NameValueModel::variableToIndex(const QString &name) const
-{
- int row = d->findInResult(name);
- if (row == -1)
- return QModelIndex();
- return index(row, 0);
-}
-
-bool NameValueModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- if (!index.isValid() || role != Qt::EditRole)
- return false;
-
- // ignore changes to already set values:
- if (data(index, role) == value)
- return true;
-
- const QString oldName = data(this->index(index.row(), 0, QModelIndex())).toString();
- const QString oldValue = data(this->index(index.row(), 1, QModelIndex()), Qt::EditRole).toString();
- int changesPos = d->findInChanges(oldName);
-
- if (index.column() == 0) {
- //fail if a variable with the same name already exists
- const QString &newName = HostOsInfo::isWindowsHost() ? value.toString().toUpper()
- : value.toString();
- if (newName.isEmpty() || newName.contains('='))
- return false;
- // Does the new name exist already?
- if (d->m_resultNameValueDictionary.hasKey(newName) || newName.isEmpty())
- return false;
-
- NameValueItem newVariable(newName, oldValue);
-
- if (changesPos != -1)
- resetVariable(oldName); // restore the original base variable again
-
- QModelIndex newIndex = addVariable(newVariable); // add the new variable
- emit focusIndex(newIndex.sibling(newIndex.row(), 1)); // hint to focus on the value
- return true;
- } else if (index.column() == 1) {
- // We are changing an existing value:
- const QString stringValue = value.toString();
- if (changesPos != -1) {
- const auto oldIt = d->m_baseNameValueDictionary.constFind(oldName);
- const auto newIt = d->m_resultNameValueDictionary.constFind(oldName);
- // We have already changed this value
- if (oldIt != d->m_baseNameValueDictionary.constEnd()
- && stringValue == d->m_baseNameValueDictionary.value(oldIt)
- && d->m_baseNameValueDictionary.isEnabled(oldIt)
- == d->m_resultNameValueDictionary.isEnabled(newIt)) {
- // ... and now went back to the base value
- d->m_items.removeAt(changesPos);
- } else {
- // ... and changed it again
- d->m_items[changesPos].value = stringValue;
- if (d->m_items[changesPos].operation == NameValueItem::Unset)
- d->m_items[changesPos].operation = NameValueItem::SetEnabled;
- }
- } else {
- // Add a new change item:
- d->m_items.append(NameValueItem(oldName, stringValue));
- }
- d->updateResultNameValueDictionary();
- emit dataChanged(index, index);
- emit userChangesChanged();
- return true;
- }
- return false;
-}
-
-QModelIndex NameValueModel::addVariable()
-{
- return addVariable(NameValueItem("NEWVAR", "VALUE"));
-}
-
-QModelIndex NameValueModel::addVariable(const NameValueItem &item)
-{
- // Return existing index if the name is already in the result set:
- int pos = d->findInResult(item.name);
- if (pos >= 0 && pos < d->m_resultNameValueDictionary.size())
- return index(pos, 0, QModelIndex());
-
- int insertPos = d->findInResultInsertPosition(item.name);
- int changePos = d->findInChanges(item.name);
- if (d->m_baseNameValueDictionary.hasKey(item.name)) {
- // We previously unset this!
- Q_ASSERT(changePos >= 0);
- // Do not insert a line here as we listed the variable as <UNSET> before!
- Q_ASSERT(d->m_items.at(changePos).name == item.name);
- Q_ASSERT(d->m_items.at(changePos).operation == NameValueItem::Unset);
- Q_ASSERT(d->m_items.at(changePos).value.isEmpty());
- d->m_items[changePos] = item;
- emit dataChanged(index(insertPos, 0, QModelIndex()), index(insertPos, 1, QModelIndex()));
- } else {
- // We add something that is not in the base dictionary
- // Insert a new line!
- beginInsertRows(QModelIndex(), insertPos, insertPos);
- Q_ASSERT(changePos < 0);
- d->m_items.append(item);
- d->updateResultNameValueDictionary();
- endInsertRows();
- }
- emit userChangesChanged();
- return index(insertPos, 0, QModelIndex());
-}
-
-void NameValueModel::resetVariable(const QString &name)
-{
- int rowInChanges = d->findInChanges(name);
- if (rowInChanges < 0)
- return;
-
- int rowInResult = d->findInResult(name);
- if (rowInResult < 0)
- return;
-
- if (d->m_baseNameValueDictionary.hasKey(name)) {
- d->m_items.removeAt(rowInChanges);
- d->updateResultNameValueDictionary();
- emit dataChanged(index(rowInResult, 0, QModelIndex()), index(rowInResult, 1, QModelIndex()));
- emit userChangesChanged();
- } else {
- // Remove the line completely!
- beginRemoveRows(QModelIndex(), rowInResult, rowInResult);
- d->m_items.removeAt(rowInChanges);
- d->updateResultNameValueDictionary();
- endRemoveRows();
- emit userChangesChanged();
- }
-}
-
-void NameValueModel::unsetVariable(const QString &name)
-{
- // This does not change the number of rows as we will display a <UNSET>
- // in place of the original variable!
- int row = d->findInResult(name);
- if (row < 0)
- return;
-
- // look in d->m_items for the variable
- int pos = d->findInChanges(name);
- if (pos != -1) {
- d->m_items[pos].operation = NameValueItem::Unset;
- d->m_items[pos].value.clear();
- d->updateResultNameValueDictionary();
- emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
- emit userChangesChanged();
- return;
- }
- d->m_items.append(NameValueItem(name, QString(), NameValueItem::Unset));
- d->updateResultNameValueDictionary();
- emit dataChanged(index(row, 0, QModelIndex()), index(row, 1, QModelIndex()));
- emit userChangesChanged();
-}
-
-void NameValueModel::toggleVariable(const QModelIndex &idx)
-{
- const QString name = indexToVariable(idx);
- const auto newIt = d->m_resultNameValueDictionary.constFind(name);
- QTC_ASSERT(newIt != d->m_resultNameValueDictionary.constEnd(), return);
- const auto op = d->m_resultNameValueDictionary.isEnabled(newIt)
- ? NameValueItem::SetDisabled : NameValueItem::SetEnabled;
- const int changesPos = d->findInChanges(name);
- if (changesPos != -1) {
- const auto oldIt = d->m_baseNameValueDictionary.constFind(name);
- if (oldIt == d->m_baseNameValueDictionary.constEnd()
- || oldIt.value().first != newIt.value().first) {
- d->m_items[changesPos].operation = op;
- } else {
- d->m_items.removeAt(changesPos);
- }
- } else {
- d->m_items.append({name, d->m_resultNameValueDictionary.value(newIt), op});
- }
- d->updateResultNameValueDictionary();
- emit dataChanged(index(idx.row(), 0), index(idx.row(), 1));
- emit userChangesChanged();
-}
-
-bool NameValueModel::isUnset(const QString &name)
-{
- const int pos = d->findInChanges(name);
- return pos == -1 ? false : d->m_items.at(pos).operation == NameValueItem::Unset;
-}
-
-bool NameValueModel::isEnabled(const QString &name) const
-{
- return d->m_resultNameValueDictionary.isEnabled(d->m_resultNameValueDictionary.constFind(name));
-}
-
-bool NameValueModel::canReset(const QString &name)
-{
- return d->m_baseNameValueDictionary.hasKey(name);
-}
-
-NameValueItems NameValueModel::userChanges() const
-{
- return d->m_items;
-}
-
-void NameValueModel::setUserChanges(const NameValueItems &items)
-{
- NameValueItems filtered = Utils::filtered(items, [](const NameValueItem &i) {
- return i.name != "export " && !i.name.contains('=');
- });
- // We assume nobody is reordering the items here.
- if (filtered == d->m_items)
- return;
- beginResetModel();
- d->m_items = filtered;
- for (NameValueItem &item : d->m_items) {
- QString &name = item.name;
- name = name.trimmed();
- if (name.startsWith("export "))
- name = name.mid(7).trimmed();
- if (d->m_baseNameValueDictionary.osType() == OsTypeWindows) {
- // NameValueDictionary variable names are case-insensitive under windows, but we still
- // want to preserve the case of pre-existing variables.
- auto it = d->m_baseNameValueDictionary.constFind(name);
- if (it != d->m_baseNameValueDictionary.constEnd())
- name = d->m_baseNameValueDictionary.key(it);
- }
- }
-
- d->updateResultNameValueDictionary();
- endResetModel();
- emit userChangesChanged();
-}
-
-bool NameValueModel::currentEntryIsPathList(const QModelIndex &current) const
-{
- if (!current.isValid())
- return false;
-
- // Look at the name first and check it against some well-known path variables. Extend as needed.
- const QString varName = indexToVariable(current);
- if (varName.compare("PATH", Utils::HostOsInfo::fileNameCaseSensitivity()) == 0)
- return true;
- if (Utils::HostOsInfo::isMacHost() && varName == "DYLD_LIBRARY_PATH")
- return true;
- if (Utils::HostOsInfo::isAnyUnixHost() && varName == "LD_LIBRARY_PATH")
- return true;
- if (varName == "PKG_CONFIG_DIR")
- return true;
- if (Utils::HostOsInfo::isWindowsHost()
- && QStringList{"INCLUDE", "LIB", "LIBPATH"}.contains(varName)) {
- return true;
- }
-
- // Now check the value: If it's a list of strings separated by the platform's path separator
- // and at least one of the strings is an existing directory, then that's enough proof for us.
- QModelIndex valueIndex = current;
- if (valueIndex.column() == 0)
- valueIndex = valueIndex.siblingAtColumn(1);
- const QStringList entries = data(valueIndex).toString()
- .split(Utils::HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts);
- if (entries.length() < 2)
- return false;
- return Utils::anyOf(entries, [](const QString &d) { return QFileInfo(d).isDir(); });
-}
-
-} // namespace Utils
diff --git a/src/libs/utils/namevaluemodel.h b/src/libs/utils/namevaluemodel.h
deleted file mode 100644
index 84c1f2cece..0000000000
--- a/src/libs/utils/namevaluemodel.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "utils_global.h"
-
-#include "environmentfwd.h"
-
-#include <QAbstractTableModel>
-
-#include <memory>
-
-namespace Utils {
-
-namespace Internal {
-class NameValueModelPrivate;
-}
-
-class QTCREATOR_UTILS_EXPORT NameValueModel : public QAbstractTableModel
-{
- Q_OBJECT
-
-public:
- explicit NameValueModel(QObject *parent = nullptr);
- ~NameValueModel() override;
-
- int rowCount(const QModelIndex &parent) const override;
- int columnCount(const QModelIndex &parent) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- Qt::ItemFlags flags(const QModelIndex &index) const override;
- QVariant headerData(int section,
- Qt::Orientation orientation,
- int role = Qt::DisplayRole) const override;
-
- QModelIndex addVariable();
- QModelIndex addVariable(const NameValueItem &item);
- void resetVariable(const QString &name);
- void unsetVariable(const QString &name);
- void toggleVariable(const QModelIndex &index);
- bool isUnset(const QString &name);
- bool isEnabled(const QString &name) const;
- bool canReset(const QString &name);
- QString indexToVariable(const QModelIndex &index) const;
- QModelIndex variableToIndex(const QString &name) const;
- bool changes(const QString &key) const;
- const NameValueDictionary &baseNameValueDictionary() const;
- void setBaseNameValueDictionary(const NameValueDictionary &dictionary);
- NameValueItems userChanges() const;
- void setUserChanges(const NameValueItems &items);
- bool currentEntryIsPathList(const QModelIndex &current) const;
-
-signals:
- void userChangesChanged();
- /// Hint to the view where it should make sense to focus on next
- // This is a hack since there is no way for a model to suggest
- // the next interesting place to focus on to the view.
- void focusIndex(const QModelIndex &index);
-
-private:
- std::unique_ptr<Internal::NameValueModelPrivate> d;
-};
-
-} // namespace Utils
diff --git a/src/libs/utils/namevaluesdialog.cpp b/src/libs/utils/namevaluesdialog.cpp
index 4f9537655e..43511fe57f 100644
--- a/src/libs/utils/namevaluesdialog.cpp
+++ b/src/libs/utils/namevaluesdialog.cpp
@@ -70,7 +70,7 @@ NameValueItemsWidget::NameValueItemsWidget(QWidget *parent)
layout->addWidget(new QLabel(helpText, this));
const auto checkForItemChange = [this] {
- const NameValueItems newItems = environmentItems();
+ const EnvironmentItems newItems = environmentItems();
if (newItems != m_originalItems) {
m_originalItems = newItems;
emit userChangedItems(newItems);
@@ -190,8 +190,8 @@ void NameValuesDialog::setPlaceholderText(const QString &text)
m_editor->setPlaceholderText(text);
}
-std::optional<NameValueItems> NameValuesDialog::getNameValueItems(QWidget *parent,
- const NameValueItems &initial,
+std::optional<EnvironmentItems> NameValuesDialog::getNameValueItems(QWidget *parent,
+ const EnvironmentItems &initial,
const QString &placeholderText,
Polisher polisher,
const QString &windowTitle)
diff --git a/src/libs/utils/namevaluesdialog.h b/src/libs/utils/namevaluesdialog.h
index af847bb5a1..a1e884fe5b 100644
--- a/src/libs/utils/namevaluesdialog.h
+++ b/src/libs/utils/namevaluesdialog.h
@@ -34,20 +34,20 @@ signals:
private:
Internal::TextEditHelper *m_editor;
- NameValueItems m_originalItems;
+ EnvironmentItems m_originalItems;
};
class QTCREATOR_UTILS_EXPORT NameValuesDialog : public QDialog
{
public:
- void setNameValueItems(const NameValueItems &items);
- NameValueItems nameValueItems() const;
+ void setNameValueItems(const EnvironmentItems &items);
+ EnvironmentItems nameValueItems() const;
void setPlaceholderText(const QString &text);
using Polisher = std::function<void(QWidget *)>;
- static std::optional<NameValueItems> getNameValueItems(QWidget *parent = nullptr,
- const NameValueItems &initial = {},
+ static std::optional<EnvironmentItems> getNameValueItems(QWidget *parent = nullptr,
+ const EnvironmentItems &initial = {},
const QString &placeholderText = {},
Polisher polish = {},
const QString &windowTitle = {});
diff --git a/src/libs/utils/namevaluevalidator.cpp b/src/libs/utils/namevaluevalidator.cpp
index ef2ccbc9a0..620adc137c 100644
--- a/src/libs/utils/namevaluevalidator.cpp
+++ b/src/libs/utils/namevaluevalidator.cpp
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "namevaluevalidator.h"
-#include "namevaluemodel.h"
+
+#include "environmentmodel.h"
#include "tooltip/tooltip.h"
#include <QTreeView>
@@ -10,7 +11,7 @@
namespace Utils {
NameValueValidator::NameValueValidator(QWidget *parent,
- NameValueModel *model,
+ EnvironmentModel *model,
QTreeView *view,
const QModelIndex &index,
const QString &toolTipText)
diff --git a/src/libs/utils/namevaluevalidator.h b/src/libs/utils/namevaluevalidator.h
index bf0f1b27f7..e06560f189 100644
--- a/src/libs/utils/namevaluevalidator.h
+++ b/src/libs/utils/namevaluevalidator.h
@@ -16,13 +16,13 @@ QT_END_NAMESPACE
namespace Utils {
-class NameValueModel;
+class EnvironmentModel;
class QTCREATOR_UTILS_EXPORT NameValueValidator : public QValidator
{
public:
NameValueValidator(QWidget *parent,
- NameValueModel *model,
+ EnvironmentModel *model,
QTreeView *view,
const QModelIndex &index,
const QString &toolTipText);
@@ -33,7 +33,7 @@ public:
private:
const QString m_toolTipText;
- NameValueModel *m_model;
+ EnvironmentModel *m_model;
QTreeView *m_view;
QPersistentModelIndex m_index;
mutable QTimer m_hideTipTimer;
diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index b710e68723..1f32cce6bc 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -82,6 +82,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
d->m_pathChooser->setObjectName("baseFolder"); // used by Squish
d->m_pathChooser->setExpectedKind(PathChooser::Directory);
d->m_pathChooser->setDisabled(d->m_forceSubProject);
+ d->m_pathChooser->setAllowPathFromDevice(true);
d->m_projectsDirectoryCheckBox = new QCheckBox(Tr::tr("Use as default project location"));
d->m_projectsDirectoryCheckBox->setObjectName("projectsDirectoryCheckBox");
diff --git a/src/libs/utils/terminalinterface.cpp b/src/libs/utils/terminalinterface.cpp
index de3f57145c..0d5a3be020 100644
--- a/src/libs/utils/terminalinterface.cpp
+++ b/src/libs/utils/terminalinterface.cpp
@@ -420,6 +420,7 @@ void TerminalInterface::start()
connect(d->stubConnectTimeoutTimer.get(), &QTimer::timeout, this, [this] {
killInferiorProcess();
killStubProcess();
+ emitFinished(-1, QProcess::ExitStatus::CrashExit);
});
d->stubConnectTimeoutTimer->setSingleShot(true);
d->stubConnectTimeoutTimer->start(10000);
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index d7ccd1d676..7bf55d8f24 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -198,8 +198,6 @@ QtcLibrary {
"namevaluedictionary.h",
"namevalueitem.cpp",
"namevalueitem.h",
- "namevaluemodel.cpp",
- "namevaluemodel.h",
"namevaluesdialog.cpp",
"namevaluesdialog.h",
"namevaluevalidator.cpp",
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 2b0bd9492e..21a20ff645 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -1479,9 +1479,12 @@ FilePath AndroidConfig::getJdkPath()
// Look for Android Studio's jdk first
const FilePath androidStudioSdkPath = androidStudioPath();
if (!androidStudioSdkPath.isEmpty()) {
- const FilePath androidStudioSdkJrePath = androidStudioSdkPath / "jre";
- if (androidStudioSdkJrePath.exists())
- jdkHome = androidStudioSdkJrePath;
+ const QStringList allVersions{"jbr", "jre"};
+ for (const QString &version : allVersions) {
+ const FilePath androidStudioSdkJbrPath = androidStudioSdkPath / version;
+ if (androidStudioSdkJbrPath.exists())
+ return androidStudioSdkJbrPath;
+ }
}
if (jdkHome.isEmpty()) {
diff --git a/src/plugins/android/androidsdkdownloader.cpp b/src/plugins/android/androidsdkdownloader.cpp
index 6ff39dc417..7246b5b9a3 100644
--- a/src/plugins/android/androidsdkdownloader.cpp
+++ b/src/plugins/android/androidsdkdownloader.cpp
@@ -100,8 +100,8 @@ void AndroidSdkDownloader::downloadAndExtractSdk()
m_progressDialog->setFixedSize(m_progressDialog->sizeHint());
m_progressDialog->setAutoClose(false);
connect(m_progressDialog.get(), &QProgressDialog::canceled, this, [this] {
- m_progressDialog.release()->deleteLater();
m_taskTreeRunner.reset();
+ m_progressDialog.release()->deleteLater();
});
Storage<std::optional<FilePath>> storage;
@@ -116,6 +116,8 @@ void AndroidSdkDownloader::downloadAndExtractSdk()
return;
connect(reply, &QNetworkReply::downloadProgress,
this, [this](qint64 received, qint64 max) {
+ if (!m_progressDialog)
+ return;
m_progressDialog->setRange(0, max);
m_progressDialog->setValue(received);
});
diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp
index ec5ae04229..a9fb3a4e3f 100644
--- a/src/plugins/axivion/axivionoutputpane.cpp
+++ b/src/plugins/axivion/axivionoutputpane.cpp
@@ -35,6 +35,8 @@
#include <map>
+using namespace Core;
+using namespace ProjectExplorer;
using namespace Tasking;
using namespace Utils;
@@ -199,11 +201,11 @@ public:
if (role == BaseTreeView::ItemActivatedRole && !m_links.isEmpty()) {
// TODO for now only simple - just the first..
Link link = m_links.first();
- ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject();
+ Project *project = ProjectManager::startupProject();
FilePath baseDir = project ? project->projectDirectory() : FilePath{};
link.targetFilePath = baseDir.resolvePath(link.targetFilePath);
if (link.targetFilePath.exists())
- Core::EditorManager::openEditorAt(link);
+ EditorManager::openEditorAt(link);
return true;
}
return StaticTreeItem::setData(column, value, role);
@@ -591,7 +593,7 @@ void IssuesWidget::fetchMoreIssues()
}
AxivionOutputPane::AxivionOutputPane(QObject *parent)
- : Core::IOutputPane(parent)
+ : IOutputPane(parent)
{
setId("Axivion");
setDisplayName(Tr::tr("Axivion"));
@@ -702,7 +704,7 @@ void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml)
browser->setText(ruleHtml);
if (!ruleHtml.isEmpty()) {
m_outputWidget->setCurrentIndex(2);
- popup(Core::IOutputPane::NoModeSwitch);
+ popup(IOutputPane::NoModeSwitch);
}
}
}
diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp
index 26f5196a9a..cd8fca0a0c 100644
--- a/src/plugins/axivion/axivionplugin.cpp
+++ b/src/plugins/axivion/axivionplugin.cpp
@@ -53,21 +53,6 @@ using namespace Utils;
namespace Axivion::Internal {
-class Issue
-{
-public:
- QString id;
- QString state;
- QString errorNumber;
- QString message;
- QString entity;
- QString filePath;
- QString severity;
- int lineNumber = 0;
-};
-
-using Issues = QList<Issue>;
-
QIcon iconForIssue(const QString &prefix)
{
static QHash<QString, QIcon> prefixToIcon;
@@ -154,7 +139,7 @@ public:
void onDocumentOpened(IDocument *doc);
void onDocumentClosed(IDocument * doc);
void clearAllMarks();
- void handleIssuesForFile(const Issues &issues);
+ void handleIssuesForFile(const Dto::FileViewDto &fileView);
void fetchIssueInfo(const QString &id);
NetworkAccessManager m_networkAccessManager;
@@ -173,18 +158,18 @@ static AxivionPluginPrivate *dd = nullptr;
class AxivionTextMark : public TextMark
{
public:
- AxivionTextMark(const FilePath &filePath, const Issue &issue)
- : TextMark(filePath, issue.lineNumber, {Tr::tr("Axivion"), AxivionTextMarkId})
+ AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue)
+ : TextMark(filePath, issue.startLine, {Tr::tr("Axivion"), AxivionTextMarkId})
{
- const QString markText = issue.entity.isEmpty() ? issue.message
- : issue.entity + ": " + issue.message;
- setToolTip(issue.errorNumber + " " + markText);
- setIcon(iconForIssue("SV")); // FIXME adapt to the issue
+ const QString markText = issue.description;
+ const QString id = issue.kind + QString::number(issue.id.value_or(-1));
+ setToolTip(id + markText);
+ setIcon(iconForIssue(issue.kind));
setPriority(TextMark::NormalPriority);
setLineAnnotation(markText);
- setActionsProvider([id = issue.id] {
+ setActionsProvider([id] {
auto action = new QAction;
- action->setIcon(Utils::Icons::INFO.icon());
+ action->setIcon(Icons::INFO.icon());
action->setToolTip(Tr::tr("Show rule details"));
QObject::connect(action, &QAction::triggered, dd, [id] { dd->fetchIssueInfo(id); });
return QList{action};
@@ -281,8 +266,8 @@ static QUrl urlForProject(const QString &projectName)
}
static constexpr int httpStatusCodeOk = 200;
-static const QLatin1String jsonContentType{ "application/json" };
-static const QLatin1String htmlContentType{ "text/html" };
+constexpr char s_htmlContentType[] = "text/html";
+constexpr char s_jsonContentType[] = "application/json";
static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QByteArray &)> &handler)
{
@@ -299,15 +284,11 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QBy
const auto onQuerySetup = [storage, url](NetworkQuery &query) {
QNetworkRequest request(url);
- request.setRawHeader(QByteArrayLiteral("Accept"),
- QByteArray(htmlContentType.data(), htmlContentType.size()));
- request.setRawHeader(QByteArrayLiteral("Authorization"),
- storage->credentials);
- const QByteArray ua = QByteArrayLiteral("Axivion")
- + QCoreApplication::applicationName().toUtf8()
- + QByteArrayLiteral("Plugin/")
- + QCoreApplication::applicationVersion().toUtf8();
- request.setRawHeader(QByteArrayLiteral("X-Axivion-User-Agent"), ua);
+ request.setRawHeader("Accept", s_htmlContentType);
+ request.setRawHeader("Authorization", storage->credentials);
+ const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() +
+ "Plugin/" + QCoreApplication::applicationVersion().toUtf8();
+ request.setRawHeader("X-Axivion-User-Agent", ua);
query.setRequest(request);
query.setNetworkAccessManager(&dd->m_networkAccessManager);
};
@@ -322,11 +303,10 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QBy
.trimmed()
.toLower();
if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk
- && contentType == htmlContentType) {
+ && contentType == s_htmlContentType) {
handler(reply->readAll());
return DoneResult::Success;
}
-
return DoneResult::Error;
};
@@ -355,22 +335,19 @@ static Group fetchDataRecipe(const QUrl &url,
storage->credentials = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8();
};
- const auto onQuerySetup = [storage, url](NetworkQuery &query) {
+ const auto onNetworkQuerySetup = [storage, url](NetworkQuery &query) {
QNetworkRequest request(url);
- request.setRawHeader(QByteArrayLiteral("Accept"),
- QByteArray(jsonContentType.data(), jsonContentType.size()));
- request.setRawHeader(QByteArrayLiteral("Authorization"),
- storage->credentials);
- const QByteArray ua = QByteArrayLiteral("Axivion")
- + QCoreApplication::applicationName().toUtf8()
- + QByteArrayLiteral("Plugin/")
- + QCoreApplication::applicationVersion().toUtf8();
- request.setRawHeader(QByteArrayLiteral("X-Axivion-User-Agent"), ua);
+ request.setRawHeader("Accept", s_jsonContentType);
+ request.setRawHeader("Authorization", storage->credentials);
+ const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() +
+ "Plugin/" + QCoreApplication::applicationVersion().toUtf8();
+ request.setRawHeader("X-Axivion-User-Agent", ua);
query.setRequest(request);
query.setNetworkAccessManager(&dd->m_networkAccessManager);
+ return SetupResult::Continue;
};
- const auto onQueryDone = [storage, url](const NetworkQuery &query, DoneWith doneWith) {
+ const auto onNetworkQueryDone = [storage, url](const NetworkQuery &query, DoneWith doneWith) {
QNetworkReply *reply = query.reply();
const QNetworkReply::NetworkError error = reply->error();
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -381,13 +358,13 @@ static Group fetchDataRecipe(const QUrl &url,
.trimmed()
.toLower();
if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk
- && contentType == jsonContentType) {
+ && contentType == s_jsonContentType) {
storage->serializableData = reply->readAll();
return DoneResult::Success;
}
const auto getError = [&]() -> Error {
- if (contentType == jsonContentType) {
+ if (contentType == s_jsonContentType) {
try {
return DashboardError(reply->url(), statusCode,
reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(),
@@ -404,8 +381,7 @@ static Group fetchDataRecipe(const QUrl &url,
return NetworkError(reply->url(), error, reply->errorString());
};
- MessageManager::writeFlashing(
- QStringLiteral("Axivion: %1").arg(getError().message()));
+ MessageManager::writeFlashing(QStringLiteral("Axivion: %1").arg(getError().message()));
return DoneResult::Error;
};
@@ -426,7 +402,7 @@ static Group fetchDataRecipe(const QUrl &url,
const Group recipe {
storage,
Sync(onCredentialSetup),
- NetworkQueryTask(onQuerySetup, onQueryDone),
+ NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone),
AsyncTask<SerializableType>(onDeserializeSetup, onDeserializeDone)
};
@@ -495,6 +471,17 @@ Group issueTableRecipe(const IssueListSearch &search, const IssueTableHandler &h
return fetchDataRecipe<Dto::IssueTableDto>(url, handler);
}
+Group lineMarkerRecipe(const FilePath &filePath, const LineMarkerHandler &handler)
+{
+ QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected?
+ QTC_ASSERT(!filePath.isEmpty(), return {}); // TODO: Call handler with unexpected?
+
+ const QString fileName = QString::fromUtf8(QUrl::toPercentEncoding(filePath.path()));
+ const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/')
+ .resolved(QString("files?filename=" + fileName));
+ return fetchDataRecipe<Dto::FileViewDto>(url, handler);
+}
+
Group issueHtmlRecipe(const QString &issueId, const HtmlHandler &handler)
{
QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected?
@@ -569,7 +556,7 @@ void AxivionPluginPrivate::fetchIssueInfo(const QString &id)
dd->m_axivionOutputPane.updateAndShowRule(QString::fromUtf8(fixedHtml));
};
- m_issueInfoRunner.start(issueHtmlRecipe(QString("SV") + id, ruleHandler));
+ m_issueInfoRunner.start(issueHtmlRecipe(id, ruleHandler));
}
void AxivionPluginPrivate::handleOpenedDocs()
@@ -591,41 +578,16 @@ void AxivionPluginPrivate::onDocumentOpened(IDocument *doc)
if (!doc || !m_currentProjectInfo || !m_project || !m_project->isKnownFile(doc->filePath()))
return;
- IssueListSearch search;
- search.kind = "SV";
- search.filter_path = doc->filePath().relativeChildPath(m_project->projectDirectory()).path();
- search.limit = 0;
-
- const auto issuesHandler = [this](const Dto::IssueTableDto &dto) {
- Issues issues;
- const std::vector<std::map<QString, Dto::Any>> &rows = dto.rows;
- for (const auto &row : rows) {
- Issue issue;
- for (auto it = row.cbegin(); it != row.cend(); ++it) {
- if (it->first == "id")
- issue.id = anyToSimpleString(it->second);
- else if (it->first == "state")
- issue.state = anyToSimpleString(it->second);
- else if (it->first == "errorNumber")
- issue.errorNumber = anyToSimpleString(it->second);
- else if (it->first == "message")
- issue.message = anyToSimpleString(it->second);
- else if (it->first == "entity")
- issue.entity = anyToSimpleString(it->second);
- else if (it->first == "path")
- issue.filePath = anyToSimpleString(it->second);
- else if (it->first == "severity")
- issue.severity = anyToSimpleString(it->second);
- else if (it->first == "line")
- issue.lineNumber = anyToSimpleString(it->second).toInt();
- }
- issues << issue;
- }
- handleIssuesForFile(issues);
- };
+ const FilePath filePath = doc->filePath().relativeChildPath(m_project->projectDirectory());
+ QTC_ASSERT(!filePath.isEmpty(), return);
+ const auto handler = [this](const Dto::FileViewDto &data) {
+ if (data.lineMarkers.empty())
+ return;
+ handleIssuesForFile(data);
+ };
TaskTree *taskTree = new TaskTree;
- taskTree->setRecipe(issueTableRecipe(search, issuesHandler));
+ taskTree->setRecipe(lineMarkerRecipe(filePath, handler));
m_docMarksTrees.insert_or_assign(doc, std::unique_ptr<TaskTree>(taskTree));
connect(taskTree, &TaskTree::done, this, [this, doc] {
const auto it = m_docMarksTrees.find(doc);
@@ -653,24 +615,22 @@ void AxivionPluginPrivate::onDocumentClosed(IDocument *doc)
}
}
-void AxivionPluginPrivate::handleIssuesForFile(const Issues &issues)
+void AxivionPluginPrivate::handleIssuesForFile(const Dto::FileViewDto &fileView)
{
- if (issues.isEmpty())
+ if (fileView.lineMarkers.empty())
return;
Project *project = ProjectManager::startupProject();
if (!project)
return;
- const FilePath filePath = project->projectDirectory()
- .pathAppended(issues.first().filePath);
+ const FilePath filePath = project->projectDirectory().pathAppended(fileView.fileName);
- const Id axivionId(AxivionTextMarkId);
- for (const Issue &issue : issues) {
+ for (const Dto::LineMarkerDto &marker : std::as_const(fileView.lineMarkers)) {
// FIXME the line location can be wrong (even the whole issue could be wrong)
// depending on whether this line has been changed since the last axivion run and the
// current state of the file - some magic has to happen here
- new AxivionTextMark(filePath, issue);
+ new AxivionTextMark(filePath, marker);
}
}
diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h
index a8090c6b7a..1d5245a503 100644
--- a/src/plugins/axivion/axivionplugin.h
+++ b/src/plugins/axivion/axivionplugin.h
@@ -19,6 +19,8 @@ namespace ProjectExplorer { class Project; }
namespace Tasking { class Group; }
+namespace Utils { class FilePath; }
+
namespace Axivion::Internal {
struct IssueListSearch
@@ -57,6 +59,10 @@ Tasking::Group tableInfoRecipe(const QString &prefix, const TableInfoHandler &ha
using IssueTableHandler = std::function<void(const Dto::IssueTableDto &)>;
Tasking::Group issueTableRecipe(const IssueListSearch &search, const IssueTableHandler &handler);
+// TODO: Wrap into expected_str<>?
+using LineMarkerHandler = std::function<void(const Dto::FileViewDto &)>;
+Tasking::Group lineMarkerRecipe(const Utils::FilePath &filePath, const LineMarkerHandler &handler);
+
using HtmlHandler = std::function<void(const QByteArray &)>;
Tasking::Group issueHtmlRecipe(const QString &issueId, const HtmlHandler &handler);
diff --git a/src/plugins/axivion/axivionprojectsettings.cpp b/src/plugins/axivion/axivionprojectsettings.cpp
index a3e3e3f3bc..14d47eca53 100644
--- a/src/plugins/axivion/axivionprojectsettings.cpp
+++ b/src/plugins/axivion/axivionprojectsettings.cpp
@@ -33,7 +33,7 @@ const char PSK_PROJECTNAME[] = "Axivion.ProjectName";
class AxivionProjectSettingsHandler : public QObject
{
public:
- AxivionProjectSettings *projectSettings(ProjectExplorer::Project *project)
+ AxivionProjectSettings *projectSettings(Project *project)
{
auto &settings = m_axivionProjectSettings[project];
if (!settings)
@@ -47,7 +47,7 @@ public:
m_axivionProjectSettings.clear();
}
- QHash<ProjectExplorer::Project *, AxivionProjectSettings *> m_axivionProjectSettings;
+ QHash<Project *, AxivionProjectSettings *> m_axivionProjectSettings;
};
static AxivionProjectSettingsHandler &projectSettingsHandler()
@@ -58,17 +58,15 @@ static AxivionProjectSettingsHandler &projectSettingsHandler()
// AxivionProjectSettings
-AxivionProjectSettings::AxivionProjectSettings(ProjectExplorer::Project *project)
+AxivionProjectSettings::AxivionProjectSettings(Project *project)
: m_project{project}
{
load();
- connect(project, &ProjectExplorer::Project::settingsLoaded,
- this, &AxivionProjectSettings::load);
- connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
- this, &AxivionProjectSettings::save);
+ connect(project, &Project::settingsLoaded, this, &AxivionProjectSettings::load);
+ connect(project, &Project::aboutToSaveSettings, this, &AxivionProjectSettings::save);
}
-AxivionProjectSettings *AxivionProjectSettings::projectSettings(ProjectExplorer::Project *project)
+AxivionProjectSettings *AxivionProjectSettings::projectSettings(Project *project)
{
return projectSettingsHandler().projectSettings(project);
}
@@ -90,10 +88,10 @@ void AxivionProjectSettings::save()
// AxivionProjectSettingsWidget
-class AxivionProjectSettingsWidget : public ProjectExplorer::ProjectSettingsWidget
+class AxivionProjectSettingsWidget : public ProjectSettingsWidget
{
public:
- explicit AxivionProjectSettingsWidget(ProjectExplorer::Project *project);
+ explicit AxivionProjectSettingsWidget(Project *project);
private:
void fetchProjects();
@@ -109,11 +107,11 @@ private:
QPushButton *m_fetchProjects = nullptr;
QPushButton *m_link = nullptr;
QPushButton *m_unlink = nullptr;
- Utils::InfoLabel *m_infoLabel = nullptr;
+ InfoLabel *m_infoLabel = nullptr;
TaskTreeRunner m_taskTreeRunner;
};
-AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(ProjectExplorer::Project *project)
+AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(Project *project)
: m_projectSettings(projectSettingsHandler().projectSettings(project))
{
setUseGlobalSettingsCheckBoxVisible(false);
@@ -132,7 +130,7 @@ AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(ProjectExplorer::Proj
verticalLayout->addWidget(new QLabel(Tr::tr("Dashboard projects:")));
verticalLayout->addWidget(m_dashboardProjects);
- m_infoLabel = new Utils::InfoLabel(this);
+ m_infoLabel = new InfoLabel(this);
m_infoLabel->setVisible(false);
verticalLayout->addWidget(m_infoLabel);
@@ -171,7 +169,7 @@ void AxivionProjectSettingsWidget::fetchProjects()
const auto onDashboardInfo = [this](const expected_str<DashboardInfo> &info) {
if (!info) {
m_infoLabel->setText(info.error());
- m_infoLabel->setType(Utils::InfoLabel::Error);
+ m_infoLabel->setType(InfoLabel::Error);
m_infoLabel->setVisible(true);
} else {
for (const QString &project : info->projects)
@@ -234,19 +232,19 @@ void AxivionProjectSettingsWidget::updateEnabledStates()
if (!hasDashboardSettings) {
m_infoLabel->setText(Tr::tr("Incomplete or misconfigured settings."));
- m_infoLabel->setType(Utils::InfoLabel::NotOk);
+ m_infoLabel->setType(InfoLabel::NotOk);
m_infoLabel->setVisible(true);
}
}
-class AxivionProjectPanelFactory : public ProjectExplorer::ProjectPanelFactory
+class AxivionProjectPanelFactory : public ProjectPanelFactory
{
public:
AxivionProjectPanelFactory()
{
setPriority(250);
setDisplayName(Tr::tr("Axivion"));
- setCreateWidgetFunction([](ProjectExplorer::Project *project) {
+ setCreateWidgetFunction([](Project *project) {
return new AxivionProjectSettingsWidget(project);
});
}
diff --git a/src/plugins/axivion/axivionsettings.cpp b/src/plugins/axivion/axivionsettings.cpp
index d85178df54..3d95673b9c 100644
--- a/src/plugins/axivion/axivionsettings.cpp
+++ b/src/plugins/axivion/axivionsettings.cpp
@@ -20,11 +20,12 @@
#include <QUuid>
#include <QVBoxLayout>
+using namespace Core;
using namespace Utils;
namespace Axivion::Internal {
-AxivionServer::AxivionServer(const Utils::Id &id, const QString &dashboard,
+AxivionServer::AxivionServer(const Id &id, const QString &dashboard,
const QString &description, const QString &token)
: id(id)
, dashboard(dashboard)
@@ -68,17 +69,17 @@ AxivionServer AxivionServer::fromJson(const QJsonObject &json)
const QJsonValue token = json.value("token");
if (token == QJsonValue::Undefined)
return invalidServer;
- return { Utils::Id::fromString(id.toString()), dashboard.toString(),
+ return { Id::fromString(id.toString()), dashboard.toString(),
description.toString(), token.toString() };
}
-static Utils::FilePath tokensFilePath()
+static FilePath tokensFilePath()
{
- return Utils::FilePath::fromString(Core::ICore::settings()->fileName()).parentDir()
+ return FilePath::fromString(ICore::settings()->fileName()).parentDir()
.pathAppended("qtcreator/axivion.json");
}
-static void writeTokenFile(const Utils::FilePath &filePath, const AxivionServer &server)
+static void writeTokenFile(const FilePath &filePath, const AxivionServer &server)
{
QJsonDocument doc;
doc.setObject(server.toJson());
@@ -87,11 +88,11 @@ static void writeTokenFile(const Utils::FilePath &filePath, const AxivionServer
filePath.setPermissions(QFile::ReadUser | QFile::WriteUser);
}
-static AxivionServer readTokenFile(const Utils::FilePath &filePath)
+static AxivionServer readTokenFile(const FilePath &filePath)
{
if (!filePath.exists())
return {};
- Utils::expected_str<QByteArray> contents = filePath.fileContents();
+ expected_str<QByteArray> contents = filePath.fileContents();
if (!contents)
return {};
const QJsonDocument doc = QJsonDocument::fromJson(*contents);
@@ -120,7 +121,7 @@ AxivionSettings::AxivionSettings()
void AxivionSettings::toSettings() const
{
writeTokenFile(tokensFilePath(), server);
- Utils::AspectContainer::writeSettings();
+ AspectContainer::writeSettings();
}
// AxivionSettingsPage
@@ -214,7 +215,7 @@ AxivionServer DashboardSettingsWidget::dashboardServer() const
if (m_id.isValid())
result.id = m_id;
else
- result.id = m_mode == Edit ? Utils::Id::fromName(QUuid::createUuid().toByteArray()) : m_id;
+ result.id = m_mode == Edit ? Id::fromName(QUuid::createUuid().toByteArray()) : m_id;
result.dashboard = m_dashboardUrl();
result.description = m_description();
result.token = m_token();
@@ -234,7 +235,7 @@ bool DashboardSettingsWidget::isValid() const
return !m_token().isEmpty() && !m_description().isEmpty() && isUrlValid(m_dashboardUrl());
}
-class AxivionSettingsWidget : public Core::IOptionsPageWidget
+class AxivionSettingsWidget : public IOptionsPageWidget
{
public:
AxivionSettingsWidget();
@@ -299,7 +300,7 @@ void AxivionSettingsWidget::showEditServerDialog()
// AxivionSettingsPage
-class AxivionSettingsPage : public Core::IOptionsPage
+class AxivionSettingsPage : public IOptionsPage
{
public:
AxivionSettingsPage()
diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp
index a3b9c22d0c..9a75fbf3b3 100644
--- a/src/plugins/bazaar/bazaarplugin.cpp
+++ b/src/plugins/bazaar/bazaarplugin.cpp
@@ -34,6 +34,7 @@
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcsbasesubmiteditor.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -62,7 +63,6 @@ namespace Bazaar::Internal {
// Submit editor parameters
const char COMMIT_ID[] = "Bazaar Commit Log Editor";
-const char COMMIT_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Bazaar Commit Log Editor");
const char COMMITMIMETYPE[] = "text/vnd.qtcreator.bazaar.commit";
// Menu items
@@ -89,27 +89,6 @@ const char COMMIT[] = "Bazaar.Action.Commit";
const char UNCOMMIT[] = "Bazaar.Action.UnCommit";
const char CREATE_REPOSITORY[] = "Bazaar.Action.CreateRepository";
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput, // type
- Constants::FILELOG_ID, // id
- Constants::FILELOG_DISPLAY_NAME, // display name
- Constants::LOGAPP // mime type
-};
-
-const VcsBaseEditorParameters annotateEditorParameters {
- AnnotateOutput,
- Constants::ANNOTATELOG_ID,
- Constants::ANNOTATELOG_DISPLAY_NAME,
- Constants::ANNOTATEAPP
-};
-
-const VcsBaseEditorParameters diffEditorParameters {
- DiffOutput,
- Constants::DIFFLOG_ID,
- Constants::DIFFLOG_DISPLAY_NAME,
- Constants::DIFFAPP
-};
-
class RevertDialog : public QDialog
{
public:
@@ -220,23 +199,32 @@ public:
FilePath m_submitRepository;
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput, // type
+ Constants::FILELOG_ID, // id
+ VcsBase::Tr::tr("Bazaar File Log Editor"),
+ Constants::LOGAPP,// mime type
[] { return new BazaarEditorWidget; },
std::bind(&BazaarPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory annotateEditorFactory {
- &annotateEditorParameters,
+ VcsEditorFactory annotateEditorFactory {{
+ AnnotateOutput,
+ Constants::ANNOTATELOG_ID,
+ VcsBase::Tr::tr("Bazaar Annotation Editor"),
+ Constants::ANNOTATEAPP,
[] { return new BazaarEditorWidget; },
std::bind(&BazaarPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory diffEditorFactory {
- &diffEditorParameters,
+ VcsEditorFactory diffEditorFactory {{
+ DiffOutput,
+ Constants::DIFFLOG_ID,
+ VcsBase::Tr::tr("Bazaar Diff Editor"),
+ Constants::DIFFAPP,
[] { return new BazaarEditorWidget; },
std::bind(&BazaarPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
class UnCommitDialog : public QDialog
@@ -492,7 +480,7 @@ BazaarPluginPrivate::BazaarPluginPrivate()
setupVcsSubmitEditor(this, {
COMMITMIMETYPE,
COMMIT_ID,
- COMMIT_DISPLAY_NAME,
+ VcsBase::Tr::tr("Bazaar Commit Log Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CommitEditor; }
});
@@ -963,10 +951,10 @@ VcsCommand *BazaarPluginPrivate::createInitialCheckoutCommand(const QString &url
args << m_client.vcsCommandString(BazaarClient::CloneCommand)
<< extraArgs << url << localName;
- Environment env = m_client.processEnvironment();
+ Environment env = m_client.processEnvironment(baseDirectory);
env.set("BZR_PROGRESS_BAR", "text");
auto command = VcsBaseClient::createVcsCommand(baseDirectory, env);
- command->addJob({m_client.vcsBinary(), args}, -1);
+ command->addJob({m_client.vcsBinary(baseDirectory), args}, -1);
return command;
}
diff --git a/src/plugins/bazaar/constants.h b/src/plugins/bazaar/constants.h
index e2cdb549bb..9672d06344 100644
--- a/src/plugins/bazaar/constants.h
+++ b/src/plugins/bazaar/constants.h
@@ -3,8 +3,6 @@
#pragma once
-#include <QtGlobal>
-
namespace Bazaar::Constants {
const char BAZAAR[] = "bazaar";
@@ -23,15 +21,12 @@ const char ANNOTATE_CHANGESET_ID[] = "([.0-9]+)";
// Base editor parameters
const char FILELOG_ID[] = "Bazaar File Log Editor";
-const char FILELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Bazaar File Log Editor");
const char LOGAPP[] = "text/vnd.qtcreator.bazaar.log";
const char ANNOTATELOG_ID[] = "Bazaar Annotation Editor";
-const char ANNOTATELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Bazaar Annotation Editor");
const char ANNOTATEAPP[] = "text/vnd.qtcreator.bazaar.annotation";
const char DIFFLOG_ID[] = "Bazaar Diff Editor";
-const char DIFFLOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Bazaar Diff Editor");
const char DIFFAPP[] = "text/x-patch";
// File status hint
diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp
index 5410385f9d..f3a5ed9879 100644
--- a/src/plugins/bineditor/bineditorplugin.cpp
+++ b/src/plugins/bineditor/bineditorplugin.cpp
@@ -79,7 +79,7 @@ public:
m_widget->highlightSearchResults(QByteArray());
}
- int find(const QByteArray &pattern, int pos, FindFlags findFlags, bool *wrapped)
+ qint64 find(const QByteArray &pattern, qint64 pos, FindFlags findFlags, bool *wrapped)
{
if (wrapped)
*wrapped = false;
@@ -88,7 +88,7 @@ public:
return pos;
}
- int res = m_widget->find(pattern, pos, Utils::textDocumentFlagsForFindFlags(findFlags));
+ qint64 res = m_widget->find(pattern, pos, Utils::textDocumentFlagsForFindFlags(findFlags));
if (res < 0) {
pos = (findFlags & FindBackward) ? -1 : 0;
res = m_widget->find(pattern, pos, Utils::textDocumentFlagsForFindFlags(findFlags));
@@ -111,7 +111,7 @@ public:
if (m_contPos == -1)
m_contPos = m_incrementalStartPos;
bool wrapped;
- int found = find(pattern, m_contPos, findFlags, &wrapped);
+ qint64 found = find(pattern, m_contPos, findFlags, &wrapped);
if (wrapped != m_incrementalWrappedState && (found >= 0)) {
m_incrementalWrappedState = wrapped;
showWrapIndicator(m_widget);
@@ -147,7 +147,7 @@ public:
m_contPos = m_widget->selectionStart()-1;
}
bool wrapped;
- int found = find(pattern, m_contPos, findFlags, &wrapped);
+ qint64 found = find(pattern, m_contPos, findFlags, &wrapped);
if (wrapped)
showWrapIndicator(m_widget);
Result result;
diff --git a/src/plugins/bineditor/bineditorwidget.cpp b/src/plugins/bineditor/bineditorwidget.cpp
index 1d4765b3ca..90e6855ef7 100644
--- a/src/plugins/bineditor/bineditorwidget.cpp
+++ b/src/plugins/bineditor/bineditorwidget.cpp
@@ -238,16 +238,16 @@ bool BinEditorWidget::requestOldDataAt(qint64 pos) const
char BinEditorWidget::dataAt(qint64 pos, bool old) const
{
- qint64 block = pos / m_blockSize;
- int offset = static_cast<int>(pos - block * m_blockSize);
+ const qint64 block = pos / m_blockSize;
+ const qint64 offset = pos - block * m_blockSize;
return blockData(block, old).at(offset);
}
void BinEditorWidget::changeDataAt(qint64 pos, char c)
{
- qint64 block = pos / m_blockSize;
+ const qint64 block = pos / m_blockSize;
BlockMap::iterator it = m_modifiedData.find(block);
- int offset = static_cast<int>(pos - block * m_blockSize);
+ const qint64 offset = pos - block * m_blockSize;
if (it != m_modifiedData.end()) {
it.value()[offset] = c;
} else {
@@ -262,7 +262,7 @@ void BinEditorWidget::changeDataAt(qint64 pos, char c)
d->announceChangedData(m_baseAddr + pos, QByteArray(1, c));
}
-QByteArray BinEditorWidget::dataMid(qint64 from, int length, bool old) const
+QByteArray BinEditorWidget::dataMid(qint64 from, qint64 length, bool old) const
{
qint64 end = from + length;
qint64 block = from / m_blockSize;
@@ -581,20 +581,20 @@ void BinEditorWidget::updateLines()
updateLines(m_cursorPosition, m_cursorPosition);
}
-void BinEditorWidget::updateLines(int fromPosition, int toPosition)
+void BinEditorWidget::updateLines(qint64 fromPosition, qint64 toPosition)
{
- int topLine = verticalScrollBar()->value();
- int firstLine = qMin(fromPosition, toPosition) / m_bytesPerLine;
- int lastLine = qMax(fromPosition, toPosition) / m_bytesPerLine;
- int y = (firstLine - topLine) * m_lineHeight;
- int h = (lastLine - firstLine + 1 ) * m_lineHeight;
+ const qint64 topLine = verticalScrollBar()->value();
+ const qint64 firstLine = qMin(fromPosition, toPosition) / m_bytesPerLine;
+ const qint64 lastLine = qMax(fromPosition, toPosition) / m_bytesPerLine;
+ const int y = (firstLine - topLine) * m_lineHeight;
+ const int h = (lastLine - firstLine + 1 ) * m_lineHeight;
viewport()->update(0, y, viewport()->width(), h);
}
-int BinEditorWidget::dataIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive) const
+qint64 BinEditorWidget::dataIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive) const
{
- int trailing = pattern.size();
+ qint64 trailing = pattern.size();
if (trailing > m_blockSize)
return -1;
@@ -603,7 +603,7 @@ int BinEditorWidget::dataIndexOf(const QByteArray &pattern, qint64 from, bool ca
QByteArrayMatcher matcher(pattern);
qint64 block = from / m_blockSize;
- const int end = qMin<qint64>(from + SearchStride, m_size);
+ const qint64 end = qMin<qint64>(from + SearchStride, m_size);
while (from < end) {
if (!requestDataAt(block * m_blockSize))
return -1;
@@ -615,7 +615,7 @@ int BinEditorWidget::dataIndexOf(const QByteArray &pattern, qint64 from, bool ca
if (!caseSensitive)
buffer = buffer.toLower();
- int pos = matcher.indexIn(buffer, from - (block * m_blockSize) + trailing);
+ qint64 pos = matcher.indexIn(buffer, from - (block * m_blockSize) + trailing);
if (pos >= 0)
return pos + block * m_blockSize - trailing;
++block;
@@ -624,9 +624,9 @@ int BinEditorWidget::dataIndexOf(const QByteArray &pattern, qint64 from, bool ca
return end == m_size ? -1 : -2;
}
-int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive) const
+qint64 BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive) const
{
- int trailing = pattern.size();
+ qint64 trailing = pattern.size();
if (trailing > m_blockSize)
return -1;
@@ -635,10 +635,10 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo
if (from == -1)
from = m_size;
- int block = from / m_blockSize;
- const int lowerBound = qMax(qint64(0), from - SearchStride);
+ qint64 block = from / m_blockSize;
+ const qint64 lowerBound = qMax<qint64>(0, from - SearchStride);
while (from > lowerBound) {
- if (!requestDataAt(qint64(block) * m_blockSize))
+ if (!requestDataAt(block * m_blockSize))
return -1;
QByteArray data = blockData(block);
char *b = buffer.data();
@@ -648,18 +648,19 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo
if (!caseSensitive)
buffer = buffer.toLower();
- int pos = buffer.lastIndexOf(pattern, from - (block * m_blockSize));
+ qint64 pos = buffer.lastIndexOf(pattern, from - (block * m_blockSize));
if (pos >= 0)
return pos + block * m_blockSize;
--block;
- from = qint64(block) * m_blockSize + (m_blockSize-1) + trailing;
+ from = block * m_blockSize + (m_blockSize-1) + trailing;
}
return lowerBound == 0 ? -1 : -2;
}
-int BinEditorWidget::find(const QByteArray &pattern_arg, qint64 from,
- QTextDocument::FindFlags findFlags)
+qint64 BinEditorWidget::find(const QByteArray &pattern_arg,
+ qint64 from,
+ QTextDocument::FindFlags findFlags)
{
if (pattern_arg.isEmpty())
return 0;
@@ -672,14 +673,14 @@ int BinEditorWidget::find(const QByteArray &pattern_arg, qint64 from,
pattern = pattern.toLower();
bool backwards = (findFlags & QTextDocument::FindBackward);
- int found = backwards ? dataLastIndexOf(pattern, from, caseSensitiveSearch)
- : dataIndexOf(pattern, from, caseSensitiveSearch);
+ qint64 found = backwards ? dataLastIndexOf(pattern, from, caseSensitiveSearch)
+ : dataIndexOf(pattern, from, caseSensitiveSearch);
- int foundHex = -1;
+ qint64 foundHex = -1;
QByteArray hexPattern = calculateHexPattern(pattern_arg);
if (!hexPattern.isEmpty()) {
foundHex = backwards ? dataLastIndexOf(hexPattern, from)
- : dataIndexOf(hexPattern, from);
+ : dataIndexOf(hexPattern, from);
}
qint64 pos = foundHex == -1 || (found >= 0 && (foundHex == -2 || found < foundHex))
@@ -695,15 +696,16 @@ int BinEditorWidget::find(const QByteArray &pattern_arg, qint64 from,
return pos;
}
-int BinEditorWidget::findPattern(const QByteArray &data, const QByteArray &dataHex,
- int from, int offset, int *match)
+qint64 BinEditorWidget::findPattern(const QByteArray &data, const QByteArray &dataHex,
+ qint64 from, qint64 offset, qint64 *match)
{
if (m_searchPattern.isEmpty())
return -1;
- int normal = m_searchPattern.isEmpty()
- ? -1 : data.indexOf(m_searchPattern, from - offset);
- int hex = m_searchPatternHex.isEmpty()
- ? -1 : dataHex.indexOf(m_searchPatternHex, from - offset);
+
+ qint64 normal = m_searchPattern.isEmpty()
+ ? -1 : data.indexOf(m_searchPattern, from - offset);
+ qint64 hex = m_searchPatternHex.isEmpty()
+ ? -1 : dataHex.indexOf(m_searchPatternHex, from - offset);
if (normal >= 0 && (hex < 0 || normal < hex)) {
if (match)
@@ -787,10 +789,10 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
painter.fillRect(e->rect() & r, palette().alternateBase());
}
- int matchLength = 0;
+ qint64 matchLength = 0;
QByteArray patternData, patternDataHex;
- int patternOffset = qMax(0, topLine*m_bytesPerLine - m_searchPattern.size());
+ qint64 patternOffset = qMax(0, topLine * m_bytesPerLine - m_searchPattern.size());
if (!m_searchPattern.isEmpty()) {
patternData = dataMid(patternOffset, m_numVisibleLines * m_bytesPerLine + (topLine*m_bytesPerLine - patternOffset));
patternDataHex = patternData;
@@ -798,9 +800,9 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
patternData = patternData.toLower();
}
- int foundPatternAt = findPattern(patternData, patternDataHex, patternOffset, patternOffset, &matchLength);
+ qint64 foundPatternAt = findPattern(patternData, patternDataHex, patternOffset, patternOffset, &matchLength);
- int selStart, selEnd;
+ qint64 selStart, selEnd;
if (m_cursorPosition >= m_anchorPosition) {
selStart = m_anchorPosition;
selEnd = m_cursorPosition;
@@ -817,13 +819,13 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
painter.setPen(palette().text().color());
const QFontMetrics &fm = painter.fontMetrics();
- for (int i = 0; i <= m_numVisibleLines; ++i) {
+ for (qint64 i = 0; i <= m_numVisibleLines; ++i) {
qint64 line = topLine + i;
if (line >= m_numLines)
break;
const quint64 lineAddress = m_baseAddr + line * m_bytesPerLine;
- int y = i * m_lineHeight + m_ascent;
+ qint64 y = i * m_lineHeight + m_ascent;
if (y - m_ascent > e->rect().bottom())
break;
if (y + m_descent < e->rect().top())
@@ -1006,7 +1008,7 @@ qint64 BinEditorWidget::cursorPosition() const
void BinEditorWidget::setCursorPosition(qint64 pos, MoveMode moveMode)
{
pos = qMin(m_size - 1, qMax(qint64(0), pos));
- int oldCursorPosition = m_cursorPosition;
+ qint64 oldCursorPosition = m_cursorPosition;
m_lowNibble = false;
m_cursorPosition = pos;
@@ -1377,33 +1379,34 @@ void BinEditorWidget::keyPressEvent(QKeyEvent *e)
break;
case Qt::Key_PageUp:
case Qt::Key_PageDown: {
- int line = qMax(qint64(0), m_cursorPosition / m_bytesPerLine - verticalScrollBar()->value());
+ qint64 line = qMax(qint64(0), m_cursorPosition / m_bytesPerLine - verticalScrollBar()->value());
verticalScrollBar()->triggerAction(e->key() == Qt::Key_PageUp ?
QScrollBar::SliderPageStepSub : QScrollBar::SliderPageStepAdd);
if (!ctrlPressed)
setCursorPosition((verticalScrollBar()->value() + line) * m_bytesPerLine + m_cursorPosition % m_bytesPerLine, moveMode);
- } break;
-
+ break;
+ }
case Qt::Key_Home: {
- int pos;
+ qint64 pos;
if (ctrlPressed)
pos = 0;
else
- pos = m_cursorPosition/m_bytesPerLine * m_bytesPerLine;
+ pos = m_cursorPosition / m_bytesPerLine * m_bytesPerLine;
setCursorPosition(pos, moveMode);
- } break;
+ break;
+ }
case Qt::Key_End: {
- int pos;
+ qint64 pos;
if (ctrlPressed)
pos = m_size;
else
- pos = m_cursorPosition/m_bytesPerLine * m_bytesPerLine + 15;
+ pos = m_cursorPosition / m_bytesPerLine * m_bytesPerLine + 15;
setCursorPosition(pos, moveMode);
- } break;
- default:
+ break;
+ }
+ default: {
if (m_readOnly)
break;
- {
QString text = e->text();
for (int i = 0; i < text.length(); ++i) {
QChar c = text.at(i);
@@ -1461,9 +1464,9 @@ void BinEditorWidget::zoomF(float delta)
void BinEditorWidget::copy(bool raw)
{
- int selStart = selectionStart();
- int selEnd = selectionEnd();
- const int selectionLength = selEnd - selStart + 1;
+ const qint64 selStart = selectionStart();
+ const qint64 selEnd = selectionEnd();
+ const qint64 selectionLength = selEnd - selStart + 1;
if (selectionLength >> 22) {
QMessageBox::warning(this, Tr::tr("Copying Failed"),
Tr::tr("You cannot copy more than 4 MB of binary data."));
@@ -1479,7 +1482,7 @@ void BinEditorWidget::copy(bool raw)
QString hexString;
const char * const hex = "0123456789abcdef";
hexString.reserve(3 * data.size());
- for (int i = 0; i < data.size(); ++i) {
+ for (qint64 i = 0; i < data.size(); ++i) {
const uchar val = static_cast<uchar>(data[i]);
hexString.append(QLatin1Char(hex[val >> 4])).append(QLatin1Char(hex[val & 0xf])).append(QLatin1Char(' '));
}
@@ -1499,7 +1502,7 @@ void BinEditorWidget::highlightSearchResults(const QByteArray &pattern, QTextDoc
viewport()->update();
}
-void BinEditorWidget::changeData(int position, uchar character, bool highNibble)
+void BinEditorWidget::changeData(qint64 position, uchar character, bool highNibble)
{
if (!requestDataAt(position))
return;
@@ -1572,8 +1575,8 @@ void BinEditorWidget::redo()
void BinEditorWidget::contextMenuEvent(QContextMenuEvent *event)
{
- const int selStart = selectionStart();
- const int byteCount = selectionEnd() - selStart + 1;
+ const qint64 selStart = selectionStart();
+ const qint64 byteCount = selectionEnd() - selStart + 1;
QPointer<QMenu> contextMenu(new QMenu(this));
@@ -1717,12 +1720,12 @@ void BinEditorWidget::asDouble(qint64 offset, double &value, bool old) const
value = *f;
}
-void BinEditorWidget::asIntegers(qint64 offset, int count, quint64 &bigEndianValue,
- quint64 &littleEndianValue, bool old) const
+void BinEditorWidget::asIntegers(qint64 offset, qint64 count, quint64 &bigEndianValue,
+ quint64 &littleEndianValue, bool old) const
{
bigEndianValue = littleEndianValue = 0;
const QByteArray &data = dataMid(offset, count, old);
- for (int pos = 0; pos < data.size(); ++pos) {
+ for (qint64 pos = 0; pos < data.size(); ++pos) {
const quint64 val = static_cast<quint64>(data.at(pos)) & 0xff;
littleEndianValue += val << (pos * 8);
bigEndianValue += val << ((count - pos - 1) * 8);
diff --git a/src/plugins/bineditor/bineditorwidget.h b/src/plugins/bineditor/bineditorwidget.h
index 2ad78e5131..5fb6f2a3fb 100644
--- a/src/plugins/bineditor/bineditorwidget.h
+++ b/src/plugins/bineditor/bineditorwidget.h
@@ -79,7 +79,7 @@ public:
void setReadOnly(bool);
bool isReadOnly() const;
- int find(const QByteArray &pattern, qint64 from = 0, QTextDocument::FindFlags findFlags = {});
+ qint64 find(const QByteArray &pattern, qint64 from = 0, QTextDocument::FindFlags findFlags = {});
void selectAll();
void clear();
@@ -90,8 +90,8 @@ public:
Core::IEditor *editor() const { return m_ieditor; }
void setEditor(Core::IEditor *ieditor) { m_ieditor = ieditor; }
- int selectionStart() const { return qMin(m_anchorPosition, m_cursorPosition); }
- int selectionEnd() const { return qMax(m_anchorPosition, m_cursorPosition); }
+ qint64 selectionStart() const { return qMin(m_anchorPosition, m_cursorPosition); }
+ qint64 selectionEnd() const { return qMax(m_anchorPosition, m_cursorPosition); }
bool event(QEvent*) override;
@@ -146,20 +146,20 @@ private:
QByteArray m_lowerBlock;
qint64 m_size = 0;
- int dataIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive = true) const;
- int dataLastIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive = true) const;
+ qint64 dataIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive = true) const;
+ qint64 dataLastIndexOf(const QByteArray &pattern, qint64 from, bool caseSensitive = true) const;
bool requestDataAt(qint64 pos) const;
bool requestOldDataAt(qint64 pos) const;
char dataAt(qint64 pos, bool old = false) const;
char oldDataAt(qint64 pos) const;
void changeDataAt(qint64 pos, char c);
- QByteArray dataMid(qint64 from, int length, bool old = false) const;
+ QByteArray dataMid(qint64 from, qint64 length, bool old = false) const;
QByteArray blockData(qint64 block, bool old = false) const;
QPoint offsetToPos(qint64 offset) const;
- void asIntegers(qint64 offset, int count, quint64 &bigEndianValue, quint64 &littleEndianValue,
- bool old = false) const;
+ void asIntegers(qint64 offset, qint64 count, quint64 &bigEndianValue, quint64 &littleEndianValue,
+ bool old = false) const;
void asFloat(qint64 offset, float &value, bool old) const;
void asDouble(qint64 offset, double &value, bool old) const;
QString toolTip(const QHelpEvent *helpEvent) const;
@@ -198,14 +198,14 @@ private:
bool inTextArea(const QPoint &pos) const;
QRect cursorRect() const;
void updateLines();
- void updateLines(int fromPosition, int toPosition);
+ void updateLines(qint64 fromPosition, qint64 toPosition);
void ensureCursorVisible();
void setBlinkingCursorEnabled(bool enable);
- void changeData(int position, uchar character, bool highNibble = false);
+ void changeData(qint64 position, uchar character, bool highNibble = false);
- int findPattern(const QByteArray &data, const QByteArray &dataHex,
- int from, int offset, int *match);
+ qint64 findPattern(const QByteArray &data, const QByteArray &dataHex,
+ qint64 from, qint64 offset, qint64 *match);
void drawItems(QPainter *painter, int x, int y, const QString &itemString);
void drawChanges(QPainter *painter, int x, int y, const char *changes);
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index 9f9ea8ac94..2de357b112 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -849,7 +849,7 @@ clang::format::FormatStyle ClangFormatBaseIndenterPrivate::customSettingsStyle(
return currentQtStyle(preferences);
clang::format::FormatStyle currentSettingsStyle;
- bool success = parseConfigurationFile(filePath, currentSettingsStyle);
+ const Utils::expected_str<void> success = parseConfigurationFile(filePath, currentSettingsStyle);
QTC_ASSERT(success, return currentQtStyle(preferences));
return currentSettingsStyle;
diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index c546cc0d21..98de337022 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -37,6 +37,8 @@
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
+#include <utils/infolabel.h>
+#include <utils/expected.h>
#include <QComboBox>
#include <QLabel>
@@ -105,8 +107,7 @@ private:
Guard m_ignoreChanges;
QLabel *m_clangVersion;
- QLabel *m_clangFileIsCorrectText;
- QLabel *m_clangFileIsCorrectIcon;
+ InfoLabel *m_clangFileIsCorrectText;
ClangFormatIndenter *m_indenter;
};
@@ -137,7 +138,7 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferenc
Column {
m_clangVersion,
Row { m_editorScrollArea, m_preview },
- Row {m_clangFileIsCorrectIcon, m_clangFileIsCorrectText, st}
+ Row {m_clangFileIsCorrectText, st}
}.attachTo(this);
connect(codeStyle, &TextEditor::ICodeStylePreferences::currentPreferencesChanged,
@@ -194,46 +195,28 @@ void ClangFormatConfigWidget::initEditor(TextEditor::ICodeStylePreferences *code
m_editorScrollArea->setWidget(m_editor->widget());
m_editorScrollArea->setWidgetResizable(true);
- m_clangFileIsCorrectText = new QLabel(Tr::tr("Clang-Format is configured correctly."));
- QPalette paletteCorrect = m_clangFileIsCorrectText->palette();
- paletteCorrect.setColor(QPalette::WindowText, Qt::darkGreen);
- m_clangFileIsCorrectText->setPalette(paletteCorrect);
-
- m_clangFileIsCorrectIcon = new QLabel(this);
- m_clangFileIsCorrectIcon->setPixmap(Icons::OK.icon().pixmap(16, 16));
+ m_clangFileIsCorrectText = new InfoLabel("", Utils::InfoLabel::Ok);
+ m_clangFileIsCorrectText->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+ m_clangFileIsCorrectText->hide();
m_clangVersion = new QLabel(Tr::tr("Current ClangFormat version: %1.").arg(LLVM_VERSION_STRING),
this);
connect(m_editor->document(), &TextEditor::TextDocument::contentsChanged, this, [this] {
clang::format::FormatStyle currentSettingsStyle;
- const bool success
+ const Utils::expected_str<void> success
= parseConfigurationContent(m_editor->document()->contents().toStdString(),
currentSettingsStyle);
- QString text;
- Qt::GlobalColor currentColor;
- QPixmap pixmap;
if (success) {
- text = Tr::tr("Clang-Format is configured correctly.");
- currentColor = Qt::darkGreen;
- pixmap = Icons::OK.icon().pixmap(16, 16);
- } else {
- text = Tr::tr("Clang-Format is not configured correctly.");
- currentColor = Qt::red;
- pixmap = Icons::WARNING.icon().pixmap(16, 16);
- }
-
- m_clangFileIsCorrectText->setText(text);
- QPalette paletteCorrect = m_clangFileIsCorrectText->palette();
- paletteCorrect.setColor(QPalette::WindowText, currentColor);
- m_clangFileIsCorrectText->setPalette(paletteCorrect);
- m_clangFileIsCorrectIcon->setPixmap(pixmap);
-
- if (!success)
+ m_clangFileIsCorrectText->hide();
+ m_indenter->setOverriddenStyle(currentSettingsStyle);
+ updatePreview();
return;
- m_indenter->setOverriddenStyle(currentSettingsStyle);
- updatePreview();
+ }
+ m_clangFileIsCorrectText->show();
+ m_clangFileIsCorrectText->setText(Tr::tr("Warning: ") + success.error());
+ m_clangFileIsCorrectText->setType(Utils::InfoLabel::Warning);
});
QShortcut *completionSC = new QShortcut(QKeySequence("Ctrl+Space"), this);
@@ -347,8 +330,9 @@ void ClangFormatConfigWidget::apply()
return;
clang::format::FormatStyle currentSettingsStyle;
- const bool success = parseConfigurationContent(m_editor->document()->contents().toStdString(),
- currentSettingsStyle);
+ const Utils::expected_str<void> success
+ = parseConfigurationContent(m_editor->document()->contents().toStdString(),
+ currentSettingsStyle);
auto saveSettings = [this] {
QString errorString;
diff --git a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp
index 973271b8c3..7027511868 100644
--- a/src/plugins/clangformat/clangformatglobalconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatglobalconfigwidget.cpp
@@ -21,6 +21,7 @@
#include <texteditor/texteditorsettings.h>
#include <utils/guard.h>
+#include <utils/infolabel.h>
#include <utils/layoutbuilder.h>
#include <QCheckBox>
@@ -68,7 +69,7 @@ private:
QCheckBox *m_formatOnSave;
QCheckBox *m_useCustomSettingsCheckBox;
QCheckBox *m_useGlobalSettings;
- QLabel *m_currentProjectLabel;
+ InfoLabel *m_currentProjectLabel;
};
ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ICodeStylePreferences *codeStyle,
@@ -95,10 +96,10 @@ ClangFormatGlobalConfigWidget::ClangFormatGlobalConfigWidget(ICodeStylePreferenc
m_useGlobalSettings->hide();
m_useCustomSettings = ClangFormatSettings::instance().useCustomSettings();
- m_currentProjectLabel = new QLabel(
+ m_currentProjectLabel = new Utils::InfoLabel(
Tr::tr("Please note that the current project includes a .clang-format file, which will be "
- "used for code indenting and formatting."));
- m_currentProjectLabel->setStyleSheet("QLabel { color : red; }");
+ "used for code indenting and formatting."),
+ Utils::InfoLabel::Warning);
m_currentProjectLabel->setWordWrap(true);
using namespace Layouting;
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index b1e8090ece..6d16ebe9aa 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -19,6 +19,7 @@
#include <projectexplorer/projectmanager.h>
#include <utils/qtcassert.h>
+#include <utils/expected.h>
#include <QCryptographicHash>
@@ -417,15 +418,30 @@ Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreference
/ QLatin1String(Constants::SETTINGS_FILE_NAME);
}
-bool parseConfigurationContent(const std::string &fileContent, clang::format::FormatStyle &style)
+static QString s_errorMessage;
+Utils::expected_str<void> parseConfigurationContent(const std::string &fileContent,
+ clang::format::FormatStyle &style)
{
- style.Language = clang::format::FormatStyle::LK_Cpp;
- const std::error_code error = parseConfiguration(fileContent, &style);
+ auto diagHandler = [](const llvm::SMDiagnostic &diag, void * /*context*/) {
+ s_errorMessage = QString::fromStdString(diag.getMessage().str()) + " "
+ + QString::number(diag.getLineNo()) + ":"
+ + QString::number(diag.getColumnNo());
+ };
- return error.value() == static_cast<int>(ParseError::Success);
+ style.Language = clang::format::FormatStyle::LK_Cpp;
+ const std::error_code error = parseConfiguration(llvm::MemoryBufferRef(fileContent, "YAML"),
+ &style,
+ false,
+ diagHandler,
+ nullptr);
+
+ if (error)
+ return make_unexpected(s_errorMessage);
+ return {};
}
-bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style)
+Utils::expected_str<void> parseConfigurationFile(const Utils::FilePath &filePath,
+ clang::format::FormatStyle &style)
{
return parseConfigurationContent(filePath.fileContents().value_or(QByteArray()).toStdString(),
style);
diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h
index a4ff429b3e..019414b11f 100644
--- a/src/plugins/clangformat/clangformatutils.h
+++ b/src/plugins/clangformat/clangformatutils.h
@@ -48,7 +48,9 @@ clang::format::FormatStyle currentQtStyle(const TextEditor::ICodeStylePreference
Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreferences *codeStyle);
-bool parseConfigurationContent(const std::string &fileContent, clang::format::FormatStyle &style);
-bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style);
+Utils::expected_str<void> parseConfigurationContent(const std::string &fileContent,
+ clang::format::FormatStyle &style);
+Utils::expected_str<void> parseConfigurationFile(const Utils::FilePath &filePath,
+ clang::format::FormatStyle &style);
} // ClangFormat
diff --git a/src/plugins/clearcase/clearcaseconstants.h b/src/plugins/clearcase/clearcaseconstants.h
index fe42967e55..97d57eb9bd 100644
--- a/src/plugins/clearcase/clearcaseconstants.h
+++ b/src/plugins/clearcase/clearcaseconstants.h
@@ -11,7 +11,6 @@ namespace Constants {
const char VCS_ID_CLEARCASE[] = "E.ClearCase";
const char CLEARCASE_SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.clearcase.submit";
const char CLEARCASECHECKINEDITOR_ID[] = "ClearCase Check In Editor";
-const char CLEARCASECHECKINEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "ClearCase Check In Editor");
const char TASK_INDEX[] = "ClearCase.Task.Index";
const char KEEP_ACTIVITY[] = "__KEEP__";
enum { debug = 0 };
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 56949f6562..f566b8223d 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -43,6 +43,7 @@
#include <vcsbase/vcsoutputwindow.h>
#include <vcsbase/vcsbasesubmiteditor.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <QAbstractButton>
@@ -99,26 +100,9 @@ const char CMD_ID_UPDATE_VIEW[] = "ClearCase.UpdateView";
const char CMD_ID_CHECKIN_ALL[] = "ClearCase.CheckInAll";
const char CMD_ID_STATUS[] = "ClearCase.Status";
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- "ClearCase File Log Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "ClearCase File Log Editor"), // display_name
- "text/vnd.qtcreator.clearcase.log"
-};
-
-const VcsBaseEditorParameters annotateEditorParameters {
- AnnotateOutput,
- "ClearCase Annotation Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "ClearCase Annotation Editor"), // display_name
- "text/vnd.qtcreator.clearcase.annotation"
-};
-
-const VcsBaseEditorParameters diffEditorParameters {
- DiffOutput,
- "ClearCase Diff Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "ClearCase Diff Editor"), // display_name
- "text/x-patch"
-};
+const char LOG_EDITOR_ID[] = "ClearCase File Log Editor";
+const char ANNOTATION_EDITOR_ID[] = "ClearCase Annotation Editor";
+const char DIFF_EDITOR_ID[] = "ClearCase Diff Editor";
static QString debugCodec(const QTextCodec *c)
{
@@ -311,23 +295,32 @@ public:
ClearCaseSettingsPage m_settingsPage;
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ LOG_EDITOR_ID,
+ VcsBase::Tr::tr("ClearCase File Log Editor"), // display_name
+ "text/vnd.qtcreator.clearcase.log",
[] { return new ClearCaseEditorWidget; },
std::bind(&ClearCasePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory annotateEditorFactory {
- &annotateEditorParameters,
+ VcsEditorFactory annotateEditorFactory {{
+ AnnotateOutput,
+ ANNOTATION_EDITOR_ID,
+ VcsBase::Tr::tr("ClearCase Annotation Editor"), // display_name
+ "text/vnd.qtcreator.clearcase.annotation",
[] { return new ClearCaseEditorWidget; },
std::bind(&ClearCasePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory diffEditorFactory {
- &diffEditorParameters,
+ VcsEditorFactory diffEditorFactory {{
+ DiffOutput,
+ DIFF_EDITOR_ID,
+ VcsBase::Tr::tr("ClearCase Diff Editor"), // display_name
+ "text/x-patch",
[] { return new ClearCaseEditorWidget; },
std::bind(&ClearCasePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
#ifdef WITH_TESTS
bool m_fakeClearTool = false;
@@ -740,7 +733,7 @@ ClearCasePluginPrivate::ClearCasePluginPrivate()
setupVcsSubmitEditor(this, {
Constants::CLEARCASE_SUBMIT_MIMETYPE,
Constants::CLEARCASECHECKINEDITOR_ID,
- Constants::CLEARCASECHECKINEDITOR_DISPLAY_NAME,
+ VcsBase::Tr::tr("ClearCase Check In Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new ClearCaseSubmitEditor; }
});
@@ -1218,7 +1211,7 @@ void ClearCasePluginPrivate::ccDiffWithPred(const FilePath &workingDir, const QS
diffname = QDir::toNativeSeparators(files.first());
}
const QString title = QString::fromLatin1("cc diff %1").arg(diffname);
- IEditor *editor = showOutputInEditor(title, result, diffEditorParameters.id, source, codec);
+ IEditor *editor = showOutputInEditor(title, result, DIFF_EDITOR_ID, source, codec);
setWorkingDirectory(editor, workingDir);
VcsBaseEditor::tagEditor(editor, tag);
auto diffEditorWidget = qobject_cast<ClearCaseEditorWidget *>(editor->widget());
@@ -1299,7 +1292,7 @@ void ClearCasePluginPrivate::diffActivity()
}
m_diffPrefix.clear();
const QString title = QString::fromLatin1("%1.patch").arg(activity);
- IEditor *editor = showOutputInEditor(title, result, diffEditorParameters.id,
+ IEditor *editor = showOutputInEditor(title, result, DIFF_EDITOR_ID,
FilePath::fromString(activity), nullptr);
setWorkingDirectory(editor, topLevel);
}
@@ -1461,7 +1454,7 @@ void ClearCasePluginPrivate::history(const FilePath &workingDir,
const QString title = QString::fromLatin1("cc history %1").arg(id);
const FilePath source = VcsBaseEditor::getSource(workingDir, files);
IEditor *newEditor = showOutputInEditor(title, result.cleanedStdOut(),
- logEditorParameters.id, source, codec);
+ LOG_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
if (enableAnnotationContextMenu)
VcsBaseEditor::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
@@ -1564,7 +1557,7 @@ void ClearCasePluginPrivate::vcsAnnotateHelper(const FilePath &workingDir, const
EditorManager::activateEditor(editor);
} else {
const QString title = QString::fromLatin1("cc annotate %1").arg(id);
- IEditor *newEditor = showOutputInEditor(title, res, annotateEditorParameters.id, source, codec);
+ IEditor *newEditor = showOutputInEditor(title, res, ANNOTATION_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
VcsBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
}
@@ -1598,7 +1591,7 @@ void ClearCasePluginPrivate::vcsDescribe(const FilePath &source, const QString &
EditorManager::activateEditor(editor);
} else {
const QString title = QString::fromLatin1("cc describe %1").arg(id);
- IEditor *newEditor = showOutputInEditor(title, description, diffEditorParameters.id, source, codec);
+ IEditor *newEditor = showOutputInEditor(title, description, DIFF_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
}
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 3a79e4a376..7318c7a791 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -89,6 +89,21 @@ PresetsData CMakeProject::presetsData() const
return m_presetsData;
}
+template<typename T>
+static QStringList recursiveInheritsList(const T &presetsHash, const QStringList &inheritsList)
+{
+ QStringList result;
+ for (const QString &inheritFrom : inheritsList) {
+ result << inheritFrom;
+ if (presetsHash.contains(inheritFrom)) {
+ auto item = presetsHash[inheritFrom];
+ if (item.inherits)
+ result << recursiveInheritsList(presetsHash, item.inherits.value());
+ }
+ }
+ return result;
+}
+
Internal::PresetsData CMakeProject::combinePresets(Internal::PresetsData &cmakePresetsData,
Internal::PresetsData &cmakeUserPresetsData)
{
@@ -135,12 +150,14 @@ Internal::PresetsData CMakeProject::combinePresets(Internal::PresetsData &cmakeP
if (!p.inherits)
continue;
- for (const QString &inheritFromName : p.inherits.value()) {
- if (presetsHash.contains(inheritFromName)) {
- p.inheritFrom(presetsHash[inheritFromName]);
+ const QStringList inheritsList = recursiveInheritsList(presetsHash,
+ p.inherits.value());
+ Utils::reverseForeach(inheritsList, [&presetsHash, &p](const QString &inheritFrom) {
+ if (presetsHash.contains(inheritFrom)) {
+ p.inheritFrom(presetsHash[inheritFrom]);
presetsHash[p.name] = p;
}
- }
+ });
}
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
index 2d9631eb40..450d154010 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
@@ -147,19 +147,30 @@ static QString displayPresetName(const QString &presetName)
FilePaths CMakeProjectImporter::importCandidates()
{
- FilePaths candidates;
+ FilePaths candidates = presetCandidates();
+
+ if (candidates.isEmpty()) {
+ candidates << scanDirectory(projectFilePath().absolutePath(), "build");
+
+ const QList<Kit *> kits = KitManager::kits();
+ for (const Kit *k : kits) {
+ FilePath shadowBuildDirectory
+ = CMakeBuildConfiguration::shadowBuildDirectory(projectFilePath(),
+ k,
+ QString(),
+ BuildConfiguration::Unknown);
+ candidates << scanDirectory(shadowBuildDirectory.absolutePath(), QString());
+ }
+ }
- candidates << scanDirectory(projectFilePath().absolutePath(), "build");
+ const FilePaths finalists = Utils::filteredUnique(candidates);
+ qCInfo(cmInputLog) << "import candidates:" << finalists;
+ return finalists;
+}
- const QList<Kit *> kits = KitManager::kits();
- for (const Kit *k : kits) {
- FilePath shadowBuildDirectory
- = CMakeBuildConfiguration::shadowBuildDirectory(projectFilePath(),
- k,
- QString(),
- BuildConfiguration::Unknown);
- candidates << scanDirectory(shadowBuildDirectory.absolutePath(), QString());
- }
+FilePaths CMakeProjectImporter::presetCandidates()
+{
+ FilePaths candidates;
for (const auto &configPreset : m_project->presetsData().configurePresets) {
if (configPreset.hidden.value())
@@ -190,9 +201,9 @@ FilePaths CMakeProjectImporter::importCandidates()
}
}
- const FilePaths finalists = Utils::filteredUnique(candidates);
- qCInfo(cmInputLog) << "import candidates:" << finalists;
- return finalists;
+ m_hasCMakePresets = !candidates.isEmpty();
+
+ return candidates;
}
Target *CMakeProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
@@ -210,6 +221,22 @@ Target *CMakeProjectImporter::preferredTarget(const QList<Target *> &possibleTar
return ProjectImporter::preferredTarget(possibleTargets);
}
+bool CMakeProjectImporter::filter(ProjectExplorer::Kit *k) const
+{
+ if (!m_hasCMakePresets)
+ return true;
+
+ const auto presetConfigItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k);
+ if (presetConfigItem.isNull())
+ return false;
+
+ const QString presetName = presetConfigItem.expandedValue(k);
+ return std::find_if(m_project->presetsData().configurePresets.cbegin(),
+ m_project->presetsData().configurePresets.cend(),
+ [&presetName](const auto &preset) { return presetName == preset.name; })
+ != m_project->presetsData().configurePresets.cend();
+}
+
static CMakeConfig configurationFromPresetProbe(
const FilePath &importPath,
const FilePath &sourceDirectory,
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
index ba8af4d61b..82e1835ba7 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
@@ -24,7 +24,9 @@ public:
Utils::FilePaths importCandidates() final;
ProjectExplorer::Target *preferredTarget(const QList<ProjectExplorer::Target *> &possibleTargets) final;
+ bool filter(ProjectExplorer::Kit *k) const final;
+ Utils::FilePaths presetCandidates();
private:
QList<void *> examineDirectory(const Utils::FilePath &importPath,
QString *warningMessage) const final;
@@ -47,6 +49,7 @@ private:
const CMakeProject *m_project;
Utils::TemporaryDirectory m_presetsTempDir;
+ bool m_hasCMakePresets = false;
};
#ifdef WITH_TESTS
diff --git a/src/plugins/coreplugin/iversioncontrol.cpp b/src/plugins/coreplugin/iversioncontrol.cpp
index 4cbc8050a2..f70e4be492 100644
--- a/src/plugins/coreplugin/iversioncontrol.cpp
+++ b/src/plugins/coreplugin/iversioncontrol.cpp
@@ -14,43 +14,39 @@
#include <QRegularExpression>
#include <QStringList>
-/*!
- \class Core::IVersionControl::TopicCache
- \inheaderfile coreplugin/iversioncontrol.h
- \inmodule QtCreator
-
- \brief The TopicCache class stores a cache which maps a directory to a topic.
-
- A VCS topic is typically the current active branch name, but it can also have other
- values (for example the latest tag) when there is no active branch.
+using namespace Utils;
- It is displayed:
- \list
- \li In the project tree, next to each root project - corresponding to the project.
- \li In the main window title - corresponding to the current active editor.
- \endlist
+namespace Core {
- In order to enable topic display, an IVersionControl subclass needs to create
- an instance of the TopicCache subclass with appropriate overrides for its
- pure virtual functions, and pass this instance to IVersionControl's constructor.
+namespace Internal {
- The cache tracks a file in the repository, which is expected to change when the
- topic changes. When the file is modified, the cache is refreshed.
- For example: for Git this file is typically <repository>/.git/HEAD
- */
+class TopicData
+{
+public:
+ QDateTime timeStamp;
+ QString topic;
+};
-/*!
- \fn Utils::FilePath Core::IVersionControl::TopicCache::trackFile(const Utils::FilePath &repository)
- Returns the path to the file that invalidates the cache for \a repository when
- the file is modified.
+class IVersionControlPrivate
+{
+public:
+ IVersionControl::FileTracker m_fileTracker;
+ IVersionControl::TopicRefresher m_topicRefresher;
+ QHash<FilePath, TopicData> m_topicCache;
+};
- \fn QString Core::IVersionControl::TopicCache::refreshTopic(const Utils::FilePath &repository)
- Returns the current topic for \a repository.
- */
+} // Internal
-using namespace Utils;
+IVersionControl::IVersionControl()
+ : d(new Internal::IVersionControlPrivate)
+{
+ Core::VcsManager::addVersionControl(this);
+}
-namespace Core {
+IVersionControl::~IVersionControl()
+{
+ delete d;
+}
QString IVersionControl::vcsOpenText() const
{
@@ -111,50 +107,49 @@ IVersionControl::RepoUrl IVersionControl::getRepoUrl(const QString &location) co
return RepoUrl(location);
}
-void IVersionControl::setTopicCache(TopicCache *topicCache)
+FilePath IVersionControl::trackFile(const FilePath &repository)
{
- m_topicCache = topicCache;
+ QTC_ASSERT(d->m_fileTracker, return {});
+ return d->m_fileTracker(repository);
}
-QString IVersionControl::vcsTopic(const FilePath &topLevel)
+QString IVersionControl::refreshTopic(const FilePath &repository)
{
- return m_topicCache ? m_topicCache->topic(topLevel) : QString();
+ QTC_ASSERT(d->m_topicRefresher, return {});
+ return d->m_topicRefresher(repository);
}
-IVersionControl::IVersionControl()
-{
- Core::VcsManager::addVersionControl(this);
-}
+/*!
+ Returns the topic for repository under \a topLevel.
-IVersionControl::~IVersionControl()
-{
- delete m_topicCache;
-}
+ A VCS topic is typically the current active branch name, but it can also have other
+ values (for example the latest tag) when there is no active branch.
-FilePaths IVersionControl::unmanagedFiles(const FilePaths &filePaths) const
-{
- return Utils::filtered(filePaths, [this](const FilePath &fp) {
- return !managesFile(fp.parentDir(), fp.fileName());
- });
-}
+ It is displayed:
+ \list
+ \li In the project tree, next to each root project - corresponding to the project.
+ \li In the main window title - corresponding to the current active editor.
+ \endlist
-IVersionControl::OpenSupportMode IVersionControl::openSupportMode(const FilePath &filePath) const
-{
- Q_UNUSED(filePath)
- return NoOpen;
-}
+ In order to enable topic display, an IVersionControl subclass needs to create
+ an instance of the TopicCache subclass with appropriate overrides for its
+ pure virtual functions, and pass this instance to IVersionControl's constructor.
-IVersionControl::TopicCache::~TopicCache() = default;
+ The cache tracks a file in the repository, which is expected to change when the
+ topic changes. When the file is modified, the cache is refreshed.
+ For example: for Git this file is typically <repository>/.git/HEAD
-/*!
- Returns the topic for repository under \a topLevel.
+ The base implementation features a cache. If the cache for \a topLevel is valid,
+ it will be used. Otherwise it will be refreshed using the items provided by
+ \c setTopicFileTracker() and \c setTopicRefresher().
- If the cache for \a topLevel is valid, it will be used. Otherwise it will be refreshed.
+ \sa setTopicFileTracker(), setTopicRefresher().
*/
-QString IVersionControl::TopicCache::topic(const FilePath &topLevel)
+
+QString IVersionControl::vcsTopic(const FilePath &topLevel)
{
QTC_ASSERT(!topLevel.isEmpty(), return QString());
- TopicData &data = m_cache[topLevel];
+ Internal::TopicData &data = d->m_topicCache[topLevel];
const FilePath file = trackFile(topLevel);
if (file.isEmpty())
@@ -166,6 +161,43 @@ QString IVersionControl::TopicCache::topic(const FilePath &topLevel)
return data.topic = refreshTopic(topLevel);
}
+/*!
+ Provides the \a fileTracker function object for use in \c vscTopic() cache handling.
+
+ The parameter object takes a repository as input and returns the file
+ that should trigger topic refresh (e.g. .git/HEAD for Git).
+
+ Modification of this file will invalidate the internal topic cache for the repository.
+*/
+
+void IVersionControl::setTopicFileTracker(const FileTracker &fileTracker)
+{
+ d->m_fileTracker = fileTracker;
+}
+
+/*!
+ Provides the \a topicRefresher function object for use in \c vscTopic() cache handling.
+
+ The parameter object takes a repository as input and returns its current topic.
+ */
+
+void IVersionControl::setTopicRefresher(const TopicRefresher &topicRefresher)
+{
+ d->m_topicRefresher = topicRefresher;
+}
+
+FilePaths IVersionControl::unmanagedFiles(const FilePaths &filePaths) const
+{
+ return Utils::filtered(filePaths, [this](const FilePath &fp) {
+ return !managesFile(fp.parentDir(), fp.fileName());
+ });
+}
+
+IVersionControl::OpenSupportMode IVersionControl::openSupportMode(const FilePath &filePath) const
+{
+ Q_UNUSED(filePath)
+ return NoOpen;
+}
void IVersionControl::fillLinkContextMenu(QMenu *, const FilePath &, const QString &)
{
}
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index e97749ca1b..31e3543777 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -8,16 +8,15 @@
#include <utils/id.h>
#include <utils/filepath.h>
-#include <QDateTime>
#include <QFlags>
-#include <QHash>
#include <QObject>
-#include <QString>
QT_FORWARD_DECLARE_CLASS(QMenu);
namespace Core {
+namespace Internal { class IVersionControlPrivate; }
+
class CORE_EXPORT IVersionControl : public QObject
{
Q_OBJECT
@@ -43,28 +42,6 @@ public:
OpenMandatory /*!< Files must always be opened by the VCS */
};
- class CORE_EXPORT TopicCache
- {
- public:
- virtual ~TopicCache();
- QString topic(const Utils::FilePath &topLevel);
-
- protected:
- virtual Utils::FilePath trackFile(const Utils::FilePath &repository) = 0;
- virtual QString refreshTopic(const Utils::FilePath &repository) = 0;
-
- private:
- class TopicData
- {
- public:
- QDateTime timeStamp;
- QString topic;
- };
-
- QHash<Utils::FilePath, TopicData> m_cache;
-
- };
-
IVersionControl();
~IVersionControl() override;
@@ -218,7 +195,14 @@ public:
};
virtual RepoUrl getRepoUrl(const QString &location) const;
- void setTopicCache(TopicCache *topicCache);
+ // Topic cache
+ using FileTracker = std::function<Utils::FilePath(const Utils::FilePath &)>;
+ Utils::FilePath trackFile(const Utils::FilePath &repository);
+ void setTopicFileTracker(const FileTracker &fileTracker);
+
+ using TopicRefresher = std::function<QString(const Utils::FilePath &)>;
+ QString refreshTopic(const Utils::FilePath &repository);
+ void setTopicRefresher(const TopicRefresher &topicRefresher);
signals:
void repositoryChanged(const Utils::FilePath &repository);
@@ -226,7 +210,7 @@ signals:
void configurationChanged();
private:
- TopicCache *m_topicCache = nullptr;
+ Internal::IVersionControlPrivate *d;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/iwelcomepage.cpp b/src/plugins/coreplugin/iwelcomepage.cpp
index 50f8499708..3eb63d8031 100644
--- a/src/plugins/coreplugin/iwelcomepage.cpp
+++ b/src/plugins/coreplugin/iwelcomepage.cpp
@@ -175,7 +175,6 @@ void WelcomePageButton::setSize(Size size)
const int hMargin = size == SizeSmall ? 12 : 26;
const int vMargin = size == SizeSmall ? 2 : 4;
d->m_layout->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
- d->m_label->setFont(size == SizeSmall ? font() : StyleHelper::uiFont(StyleHelper::UiElementH2));
}
void WelcomePageButton::setWithAccentColor(bool withAccent)
diff --git a/src/plugins/coreplugin/welcomepagehelper.cpp b/src/plugins/coreplugin/welcomepagehelper.cpp
index 37874a9e46..44fc75270d 100644
--- a/src/plugins/coreplugin/welcomepagehelper.cpp
+++ b/src/plugins/coreplugin/welcomepagehelper.cpp
@@ -87,7 +87,6 @@ SearchBox::SearchBox(QWidget *parent)
m_lineEdit = new FancyLineEdit;
m_lineEdit->setFiltering(true);
m_lineEdit->setFrame(false);
- m_lineEdit->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
m_lineEdit->setMinimumHeight(33);
m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
@@ -806,7 +805,6 @@ ListModel *SectionedGridView::addSection(const Section &section, const QList<Lis
}.emerge();
m_sectionLabels.append(sectionLabel);
sectionLabel->setContentsMargins(0, ItemGap, 0, 0);
- sectionLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
auto scrollArea = qobject_cast<QScrollArea *>(widget(0));
auto vbox = qobject_cast<QVBoxLayout *>(scrollArea->widget()->layout());
@@ -877,7 +875,6 @@ void SectionedGridView::zoomInSection(const Section &section)
noMargin
}.emerge();
sectionLabel->setContentsMargins(0, ItemGap, 0, 0);
- sectionLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
auto gridView = new GridView(zoomedInWidget);
gridView->setItemDelegate(m_itemDelegate);
diff --git a/src/plugins/cppeditor/baseeditordocumentparser.h b/src/plugins/cppeditor/baseeditordocumentparser.h
index 45f6b95399..dce8289384 100644
--- a/src/plugins/cppeditor/baseeditordocumentparser.h
+++ b/src/plugins/cppeditor/baseeditordocumentparser.h
@@ -34,11 +34,11 @@ public:
QByteArray editorDefines;
QString preferredProjectPartId;
- bool operator==(const Configuration &other)
+ friend bool operator==(const Configuration &left, const Configuration &right)
{
- return usePrecompiledHeaders == other.usePrecompiledHeaders
- && editorDefines == other.editorDefines
- && preferredProjectPartId == other.preferredProjectPartId;
+ return left.usePrecompiledHeaders == right.usePrecompiledHeaders
+ && left.editorDefines == right.editorDefines
+ && left.preferredProjectPartId == right.preferredProjectPartId;
}
};
diff --git a/src/plugins/cppeditor/cppeditoroutline.cpp b/src/plugins/cppeditor/cppeditoroutline.cpp
index 05c521e0d3..d630a7ad1c 100644
--- a/src/plugins/cppeditor/cppeditoroutline.cpp
+++ b/src/plugins/cppeditor/cppeditoroutline.cpp
@@ -150,12 +150,6 @@ QWidget *CppEditorOutline::widget() const
return m_combo;
}
-QSharedPointer<CPlusPlus::Document> getDocument(const Utils::FilePath &filePath)
-{
- const CPlusPlus::Snapshot snapshot = CppModelManager::snapshot();
- return snapshot.document(filePath);
-}
-
void CppEditorOutline::updateNow()
{
m_combo->view()->expandAll();
diff --git a/src/plugins/cppeditor/cppeditoroutline.h b/src/plugins/cppeditor/cppeditoroutline.h
index d73c0fc363..b7ac18dd0f 100644
--- a/src/plugins/cppeditor/cppeditoroutline.h
+++ b/src/plugins/cppeditor/cppeditoroutline.h
@@ -5,7 +5,6 @@
#include "cppoutlinemodel.h"
-#include <QModelIndex>
#include <QObject>
#include <memory>
@@ -16,7 +15,6 @@ class QSortFilterProxyModel;
class QTimer;
QT_END_NAMESPACE
-namespace TextEditor { class TextEditorWidget; }
namespace Utils { class TreeViewComboBox; }
namespace CppEditor {
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index b68c739f82..c9185e372c 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -323,6 +323,10 @@ void CppEditorPlugin::addPerSymbolActions()
switchDeclDef.setTouchBarText(Tr::tr("Decl/Def", "text on macOS touch bar"));
switchDeclDef.addToContainers(menus, Constants::G_SYMBOL);
switchDeclDef.addToContainer(Core::Constants::TOUCH_BAR, Core::Constants::G_TOUCHBAR_NAVIGATION);
+ switchDeclDef.addOnTriggered(this, [] {
+ if (CppEditorWidget *editorWidget = currentCppEditorWidget())
+ editorWidget->switchDeclarationDefinition(/*inNextSplit*/ false);
+ });
ActionBuilder openDeclDefSplit(this, Constants::OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT);
openDeclDefSplit.setText(Tr::tr("Open Function Declaration/Definition in Next Split"));
diff --git a/src/plugins/cppeditor/cppmodelmanagersupport.h b/src/plugins/cppeditor/cppmodelmanagersupport.h
index a43a1e0b02..c2c463df59 100644
--- a/src/plugins/cppeditor/cppmodelmanagersupport.h
+++ b/src/plugins/cppeditor/cppmodelmanagersupport.h
@@ -9,9 +9,6 @@
#include <utils/link.h>
-#include <QSharedPointer>
-#include <QString>
-
#include <functional>
namespace Core { class SearchResult; }
@@ -30,9 +27,6 @@ class RefactoringEngineInterface;
class CPPEDITOR_EXPORT ModelManagerSupport
{
public:
- using Ptr = QSharedPointer<ModelManagerSupport>;
-
-public:
virtual ~ModelManagerSupport() = 0;
virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp
index 80a4af36db..48c9bbc68a 100644
--- a/src/plugins/cppeditor/cppquickfix_test.cpp
+++ b/src/plugins/cppeditor/cppquickfix_test.cpp
@@ -5008,20 +5008,53 @@ void QuickfixTest::testInsertDefFromDeclTemplateClassAndTemplateFunction()
"class Foo\n"
"{\n"
" template<class U>\n"
- " void fun@c();\n"
+ " T fun@c(U u);\n"
"};\n";
QByteArray expected =
"template<class T>"
"class Foo\n"
"{\n"
" template<class U>\n"
- " void fun@c();\n"
+ " T fun@c(U u);\n"
"};\n"
"\n"
"template<class T>\n"
"template<class U>\n"
- "void Foo<T>::func()\n"
+ "T Foo<T>::func(U u)\n"
+ "{\n"
+ "\n"
+ "}\n";
+
+ InsertDefFromDecl factory;
+ QuickFixOperationTest(singleDocument(original, expected), &factory);
+}
+
+void QuickfixTest::testInsertDefFromDeclTemplateClassAndFunctionInsideNamespace()
+{
+ QByteArray original =
+ "namespace N {\n"
+ "template<class T>"
+ "class Foo\n"
"{\n"
+ " template<class U>\n"
+ " T fun@c(U u);\n"
+ "};\n"
+ "}\n";
+ QByteArray expected =
+ "namespace N {\n"
+ "template<class T>"
+ "class Foo\n"
+ "{\n"
+ " template<class U>\n"
+ " T fun@c(U u);\n"
+ "};\n"
+ "\n"
+ "template<class T>\n"
+ "template<class U>\n"
+ "T Foo<T>::func(U u)\n"
+ "{\n"
+ "\n"
+ "}\n"
"\n"
"}\n";
diff --git a/src/plugins/cppeditor/cppquickfix_test.h b/src/plugins/cppeditor/cppquickfix_test.h
index e677d88af2..4d734c9c09 100644
--- a/src/plugins/cppeditor/cppquickfix_test.h
+++ b/src/plugins/cppeditor/cppquickfix_test.h
@@ -137,6 +137,7 @@ private slots:
void testInsertDefFromDeclTemplateClassWithValueParam();
void testInsertDefFromDeclTemplateFunction();
void testInsertDefFromDeclTemplateClassAndTemplateFunction();
+ void testInsertDefFromDeclTemplateClassAndFunctionInsideNamespace();
void testInsertDefFromDeclFunctionWithSignedUnsignedArgument();
void testInsertDefFromDeclNotTriggeredForFriendFunc();
void testInsertDefFromDeclMinimalFunctionParameterType();
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index b2f01eaad4..90563ccd33 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -141,7 +141,8 @@ enum DefPos {
inline bool isQtStringLiteral(const QByteArray &id)
{
- return id == "QLatin1String" || id == "QLatin1Literal" || id == "QStringLiteral";
+ return id == "QLatin1String" || id == "QLatin1Literal" || id == "QStringLiteral"
+ || id == "QByteArrayLiteral";
}
inline bool isQtStringTranslation(const QByteArray &id)
@@ -1117,21 +1118,20 @@ enum ActionFlags {
EncloseInQLatin1CharAction = 0x1,
EncloseInQLatin1StringAction = 0x2,
EncloseInQStringLiteralAction = 0x4,
- EncloseActionMask = EncloseInQLatin1CharAction
- | EncloseInQLatin1StringAction | EncloseInQStringLiteralAction,
- TranslateTrAction = 0x8,
- TranslateQCoreApplicationAction = 0x10,
- TranslateNoopAction = 0x20,
- TranslationMask = TranslateTrAction
- | TranslateQCoreApplicationAction | TranslateNoopAction,
- RemoveObjectiveCAction = 0x40,
- ConvertEscapeSequencesToCharAction = 0x100,
- ConvertEscapeSequencesToStringAction = 0x200,
- SingleQuoteAction = 0x400,
- DoubleQuoteAction = 0x800
+ EncloseInQByteArrayLiteralAction = 0x8,
+ EncloseActionMask = EncloseInQLatin1CharAction | EncloseInQLatin1StringAction
+ | EncloseInQStringLiteralAction | EncloseInQByteArrayLiteralAction,
+ TranslateTrAction = 0x10,
+ TranslateQCoreApplicationAction = 0x20,
+ TranslateNoopAction = 0x40,
+ TranslationMask = TranslateTrAction | TranslateQCoreApplicationAction | TranslateNoopAction,
+ RemoveObjectiveCAction = 0x100,
+ ConvertEscapeSequencesToCharAction = 0x200,
+ ConvertEscapeSequencesToStringAction = 0x400,
+ SingleQuoteAction = 0x800,
+ DoubleQuoteAction = 0x1000
};
-
/* Convert single-character string literals into character literals with some
* special cases "a" --> 'a', "'" --> '\'', "\n" --> '\n', "\"" --> '"'. */
static QByteArray stringToCharEscapeSequences(const QByteArray &content)
@@ -1167,6 +1167,8 @@ static QString stringLiteralReplacement(unsigned actions)
return QLatin1String("QLatin1String");
if (actions & EncloseInQStringLiteralAction)
return QLatin1String("QStringLiteral");
+ if (actions & EncloseInQByteArrayLiteralAction)
+ return QLatin1String("QByteArrayLiteral");
if (actions & TranslateTrAction)
return QLatin1String("tr");
if (actions & TranslateQCoreApplicationAction)
@@ -1357,6 +1359,9 @@ void WrapStringLiteral::doMatch(const CppQuickFixInterface &interface, QuickFixO
actions = EncloseInQStringLiteralAction | objectiveCActions;
result << new WrapStringLiteralOp(interface, priority, actions,
msgQtStringLiteralDescription(stringLiteralReplacement(actions)), literal);
+ actions = EncloseInQByteArrayLiteralAction | objectiveCActions;
+ result << new WrapStringLiteralOp(interface, priority, actions,
+ msgQtStringLiteralDescription(stringLiteralReplacement(actions)), literal);
}
}
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 61851d9e4e..4ca9dd83b3 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -13,6 +13,7 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -88,35 +89,11 @@ const char CMD_ID_REPOSITORYUPDATE[] = "CVS.RepositoryUpdate";
const char CVS_SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.cvs.submit";
const char CVSCOMMITEDITOR_ID[] = "CVS Commit Editor";
-const char CVSCOMMITEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "CVS Commit Editor");
-const VcsBaseEditorParameters commandLogEditorParameters {
- OtherContent,
- "CVS Command Log Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "CVS Command Log Editor"), // display name
- "text/vnd.qtcreator.cvs.commandlog"
-};
-
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- "CVS File Log Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "CVS File Log Editor"), // display name
- "text/vnd.qtcreator.cvs.log"
-};
-
-const VcsBaseEditorParameters annotateEditorParameters {
- AnnotateOutput,
- "CVS Annotation Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "CVS Annotation Editor"), // display name
- "text/vnd.qtcreator.cvs.annotation"
-};
-
-const VcsBaseEditorParameters diffEditorParameters {
- DiffOutput,
- "CVS Diff Editor", // id
- QT_TRANSLATE_NOOP("QtC::VcsBase", "CVS Diff Editor"), // display name
- "text/x-patch"
-};
+const char CVS_COMMANDLOG_EDITOR_ID[] = "CVS Command Log Editor";
+const char CVS_FILELOG_EDITOR_ID[] = "CVS File Log Editor";
+const char CVS_ANNOTATION_EDITOR_ID[] = "CVS Annotation Editor";
+const char CVS_DIFF_EDITOR_ID[] = "CVS Diff Editor";
static inline bool messageBoxQuestion(const QString &title, const QString &question)
{
@@ -312,29 +289,41 @@ private:
QAction *m_menuAction = nullptr;
public:
- VcsEditorFactory commandLogEditorFactory {
- &commandLogEditorParameters,
+ VcsEditorFactory commandLogEditorFactory {{
+ OtherContent,
+ CVS_COMMANDLOG_EDITOR_ID,
+ VcsBase::Tr::tr("CVS Command Log Editor"), // display name
+ "text/vnd.qtcreator.cvs.commandlog",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ CVS_FILELOG_EDITOR_ID,
+ VcsBase::Tr::tr("CVS File Log Editor"), // display name
+ "text/vnd.qtcreator.cvs.log",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory annotateEditorFactory {
- &annotateEditorParameters,
+ VcsEditorFactory annotateEditorFactory {{
+ AnnotateOutput,
+ CVS_ANNOTATION_EDITOR_ID,
+ VcsBase::Tr::tr("CVS Annotation Editor"), // display name
+ "text/vnd.qtcreator.cvs.annotation",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory diffEditorFactory {
- &diffEditorParameters,
+ VcsEditorFactory diffEditorFactory {{
+ DiffOutput,
+ CVS_DIFF_EDITOR_ID,
+ VcsBase::Tr::tr("CVS Diff Editor"), // display name
+ "text/x-patch",
[] { return new CvsEditorWidget; },
std::bind(&CvsPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
Utils::Id CvsPluginPrivate::id() const
@@ -460,7 +449,7 @@ CvsPluginPrivate::CvsPluginPrivate()
setupVcsSubmitEditor(this, {
CVS_SUBMIT_MIMETYPE,
CVSCOMMITEDITOR_ID,
- CVSCOMMITEDITOR_DISPLAY_NAME,
+ VcsBase::Tr::tr("CVS Commit Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CvsSubmitEditor; },
});
@@ -965,7 +954,7 @@ void CvsPluginPrivate::filelog(const FilePath &workingDir,
} else {
const QString title = QString::fromLatin1("cvs log %1").arg(id);
IEditor *newEditor = showOutputInEditor(title, response.cleanedStdOut(),
- logEditorParameters.id, source, codec);
+ CVS_FILELOG_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
if (enableAnnotationContextMenu)
VcsBaseEditor::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
@@ -1105,7 +1094,7 @@ void CvsPluginPrivate::annotate(const FilePath &workingDir, const QString &file,
} else {
const QString title = QString::fromLatin1("cvs annotate %1").arg(id);
IEditor *newEditor = showOutputInEditor(title, response.cleanedStdOut(),
- annotateEditorParameters.id, source, codec);
+ CVS_ANNOTATION_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
VcsBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
}
@@ -1119,7 +1108,7 @@ bool CvsPluginPrivate::status(const FilePath &topLevel, const QString &file, con
const auto response = runCvs(topLevel, args);
const bool ok = response.result() == ProcessResult::FinishedWithSuccess;
if (ok) {
- showOutputInEditor(title, response.cleanedStdOut(), commandLogEditorParameters.id,
+ showOutputInEditor(title, response.cleanedStdOut(), CVS_COMMANDLOG_EDITOR_ID,
topLevel, nullptr);
}
return ok;
@@ -1284,7 +1273,7 @@ bool CvsPluginPrivate::describe(const FilePath &repositoryPath,
setDiffBaseDirectory(editor, repositoryPath);
} else {
const QString title = QString::fromLatin1("cvs describe %1").arg(commitId);
- IEditor *newEditor = showOutputInEditor(title, output, diffEditorParameters.id,
+ IEditor *newEditor = showOutputInEditor(title, output, CVS_DIFF_EDITOR_ID,
FilePath::fromString(entries.front().file), codec);
VcsBaseEditor::tagEditor(newEditor, commitId);
setDiffBaseDirectory(newEditor, repositoryPath);
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index e49e429f77..d2647f3d7b 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -44,6 +44,7 @@
#include <coreplugin/navigationwidget.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/rightpane.h>
+#include <coreplugin/session.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
@@ -787,9 +788,10 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
ICore::addAdditionalContext(debuggerNotRunning);
m_arguments = arguments;
- if (!m_arguments.isEmpty())
- connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::finishedInitialization,
+ if (!m_arguments.isEmpty()) {
+ connect(SessionManager::instance(), &SessionManager::startupSessionRestored,
this, &DebuggerPluginPrivate::parseCommandLineArguments);
+ }
// Menus
m_menu = ActionManager::createMenu(M_DEBUG_ANALYZER);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 406b552447..9efc98f24c 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -4093,7 +4093,7 @@ void GdbEngine::setEnvironmentVariables()
Environment baseEnv = runParameters().debugger.environment;
Environment runEnv = runParameters().inferior.environment;
- const NameValueItems items = baseEnv.diff(runEnv);
+ const EnvironmentItems items = baseEnv.diff(runEnv);
for (const EnvironmentItem &item : items) {
// imitate the weird windows gdb behavior of setting the case of the path environment
// variable name to an all uppercase PATH
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 7c907678ae..d271d15c5a 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -208,7 +208,6 @@ public:
bool unpausedEvaluate = false;
bool contextEvaluate = false;
bool supportChangeBreakpoint = false;
- bool hasQuit = false;
QTimer connectionTimer;
QmlDebug::QDebugMessageClient *msgClient = nullptr;
@@ -380,7 +379,7 @@ void QmlEngine::beginConnection()
void QmlEngine::connectionStartupFailed()
{
- if (d->hasQuit)
+ if (isDying())
return;
if (d->retryOnConnectFail) {
@@ -502,8 +501,7 @@ void QmlEngine::startProcess()
void QmlEngine::stopProcess()
{
- if (d->process.isRunning())
- d->process.close();
+ d->process.close();
}
void QmlEngine::shutdownInferior()
@@ -937,15 +935,6 @@ bool QmlEngine::hasCapability(unsigned cap) const
| AddWatcherCapability;*/
}
-void QmlEngine::quitDebugger()
-{
- d->automaticConnect = false;
- d->retryOnConnectFail = false;
- d->hasQuit = true;
- stopProcess();
- closeConnection();
-}
-
void QmlEngine::doUpdateLocals(const UpdateParameters &params)
{
d->updateLocals(params.qmlFocusOnFrame);
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 2006ce081f..7c609e1249 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -91,7 +91,6 @@ private:
bool companionPreventsActions() const override;
bool hasCapability(unsigned) const override;
- void quitDebugger() override;
void doUpdateLocals(const UpdateParameters &params) override;
Core::Context languageContext() const override;
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index 8d0af0e4d3..120ce75612 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -151,8 +151,8 @@ QString WatchItem::toString() const
if (!value.isEmpty())
str << "value=\"" << value << doubleQuoteComma;
- if (elided)
- str << "valueelided=\"" << elided << doubleQuoteComma;
+ if (valuelen)
+ str << "valuelen=\"" << valuelen << doubleQuoteComma;
if (!editvalue.isEmpty())
str << "editvalue=\"<...>\",";
@@ -300,9 +300,9 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
if (mi.isValid())
id = mi.toInt();
- mi = input["valueelided"];
+ mi = input["valuelen"];
if (mi.isValid())
- elided = mi.toInt();
+ valuelen = mi.toInt();
mi = input["bitpos"];
if (mi.isValid())
diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h
index bb2e458bcd..672ded5e7c 100644
--- a/src/plugins/debugger/watchdata.h
+++ b/src/plugins/debugger/watchdata.h
@@ -72,7 +72,7 @@ public:
uint bitsize = 0; // Size in case of bit fields
uint autoDerefCount = 0; // number of levels of automatic dereferencing that has taken place (for pointer types)
uint variablesReference = 0;// reference to the variable in the variables request DAP related
- int elided = 0; // Full size if value was cut off, -1 if cut on unknown size, 0 otherwise
+ int valuelen = 0; // -1 if cut on unknown size, full size otherwise
int arrayIndex = -1; // -1 if not an array member
uchar sortGroup = 0; // 0 - ordinary member, 1 - vptr, 2 - base class
bool wantsChildren = false;
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index eef0ba5a3b..841dc4d015 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -818,14 +818,24 @@ static QString formattedValue(const WatchItem *item)
return reformatInteger(integer, format, item->size, false);
}
- if (item->elided) {
- QString v = item->value;
- v.chop(1);
- QString len = item->elided > 0 ? QString::number(item->elided) : "unknown length";
- return quoteUnprintable(v) + "\"... (" + len + ')';
+ const int maxLength = settings().displayStringLimit();
+ QString v = quoteUnprintable(item->value);
+
+ if (v.endsWith('"')) {
+ if (item->valuelen > maxLength) {
+ v.chop(1);
+ v.append("...\"");
+ }
+ if (item->valuelen > 0)
+ v += QString(" (%1)").arg(item->valuelen);
+ return v;
}
- return quoteUnprintable(item->value);
+ if (v.size() > maxLength) {
+ v.truncate(maxLength);
+ v += QLatin1String("...");
+ }
+ return v;
}
// Get a pointer address from pointer values reported by the debugger.
@@ -886,18 +896,6 @@ QVariant WatchItem::editValue() const
return QVariant(quoteUnprintable(stringValue));
}
-// Truncate value for item view, maintaining quotes.
-static QString truncateValue(QString v)
-{
- enum { maxLength = 512 };
- if (v.size() < maxLength)
- return v;
- const bool isQuoted = v.endsWith('"'); // check for 'char* "Hallo"'
- v.truncate(maxLength);
- v += QLatin1String(isQuoted ? "...\"" : "...");
- return v;
-}
-
static QString displayName(const WatchItem *item)
{
QString result;
@@ -939,13 +937,9 @@ static QString displayName(const WatchItem *item)
return result;
}
-
void WatchItem::updateValueCache() const
{
- QString formatted = truncateValue(formattedValue(this));
- if (formatted.endsWith('"'))
- formatted.append(QString(" (%1)").arg(this->value.length() - 2));
- valueCache = formatted;
+ valueCache = formattedValue(this);
valueCache = watchModel(this)->removeNamespaces(valueCache);
if (valueCache.isEmpty() && this->address)
valueCache += QString::fromLatin1("@0x" + QByteArray::number(this->address, 16));
@@ -1303,7 +1297,7 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
// FIXME: Forcing types is not implemented yet.
//if (idx.column() == 2)
// return editable; // Watcher types can be set by force.
- if (column == ValueColumn && item->valueEditable && !item->elided)
+ if (column == ValueColumn && item->valueEditable && item->valuelen >= 0)
return editable; // Watcher values are sometimes editable.
}
} else if (item->isLocal()) {
@@ -1311,7 +1305,7 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
return notEditable;
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
return notEditable;
- if (column == ValueColumn && item->valueEditable && !item->elided)
+ if (column == ValueColumn && item->valueEditable && item->valuelen >= 0)
return editable; // Locals values are sometimes editable.
if (column == ValueColumn && item->arrayIndex >= 0)
return editable;
diff --git a/src/plugins/diffeditor/diffeditor.h b/src/plugins/diffeditor/diffeditor.h
index e00a6e0fe4..60f7a77214 100644
--- a/src/plugins/diffeditor/diffeditor.h
+++ b/src/plugins/diffeditor/diffeditor.h
@@ -79,12 +79,12 @@ private:
QComboBox *m_entriesComboBox = nullptr;
QSpinBox *m_contextSpinBox = nullptr;
QAction *m_contextSpinBoxAction = nullptr;
- QAction *m_toggleSyncAction;
- QAction *m_whitespaceButtonAction;
- QAction *m_toggleDescriptionAction;
- QAction *m_reloadAction;
+ QAction *m_toggleSyncAction = nullptr;
+ QAction *m_whitespaceButtonAction = nullptr;
+ QAction *m_toggleDescriptionAction = nullptr;
+ QAction *m_reloadAction = nullptr;
QAction *m_contextLabelAction = nullptr;
- QAction *m_viewSwitcherAction;
+ QAction *m_viewSwitcherAction = nullptr;
QPair<QString, QString> m_currentFileChunk;
int m_currentViewIndex = -1;
int m_currentDiffFileIndex = -1;
diff --git a/src/plugins/fossil/constants.h b/src/plugins/fossil/constants.h
index 6dd6bd4d04..558c8fc3ed 100644
--- a/src/plugins/fossil/constants.h
+++ b/src/plugins/fossil/constants.h
@@ -3,10 +3,7 @@
#pragma once
-#include <QtGlobal>
-
-namespace Fossil {
-namespace Constants {
+namespace Fossil::Constants {
const char VCS_ID_FOSSIL[] = "I.Fossil";
@@ -31,20 +28,16 @@ const char DIFFFILE_ID_EXACT[] = "[+]{3} (.*)\\s*"; // match and capture
//BaseEditorParameters
const char FILELOG_ID[] = "Fossil File Log Editor";
-const char FILELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Fossil File Log Editor");
const char LOGAPP[] = "text/vnd.qtcreator.fossil.log";
const char ANNOTATELOG_ID[] = "Fossil Annotation Editor";
-const char ANNOTATELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Fossil Annotation Editor");
const char ANNOTATEAPP[] = "text/vnd.qtcreator.fossil.annotation";
const char DIFFLOG_ID[] = "Fossil Diff Editor";
-const char DIFFLOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Fossil Diff Editor");
const char DIFFAPP[] = "text/x-patch";
//SubmitEditorParameters
const char COMMIT_ID[] = "Fossil Commit Log Editor";
-const char COMMIT_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Fossil Commit Log Editor");
const char COMMITMIMETYPE[] = "text/vnd.qtcreator.fossil.commit";
//menu items
@@ -85,5 +78,4 @@ const char FSTATUS_UNKNOWN[] = "Unknown";
// Fossil Json Wizards
const char WIZARD_PATH[] = ":/fossil/wizard";
-} // namespace Constants
-} // namespace Fossil
+} // Fossil::Constants
diff --git a/src/plugins/fossil/fossilclient.cpp b/src/plugins/fossil/fossilclient.cpp
index e892978799..d24935595a 100644
--- a/src/plugins/fossil/fossilclient.cpp
+++ b/src/plugins/fossil/fossilclient.cpp
@@ -736,7 +736,7 @@ void FossilClient::annotate(const FilePath &workingDir, const QString &file, int
lineNumber = -1;
editor->setDefaultLineNumber(lineNumber);
- enqueueJob(createCommand(workingDir, fossilEditor), args);
+ enqueueJob(createCommand(workingDir, fossilEditor), args, workingDir);
}
bool FossilClient::isVcsFileOrDirectory(const FilePath &filePath) const
@@ -833,7 +833,7 @@ void FossilClient::view(const FilePath &source, const QString &id, const QString
VcsBaseEditor::getCodec(source), "view", id);
editor->setWorkingDirectory(workingDirectory);
- enqueueJob(createCommand(workingDirectory, editor), args + extraOptions);
+ enqueueJob(createCommand(workingDirectory, editor), args + extraOptions, source);
}
class FossilLogHighlighter : QSyntaxHighlighter
@@ -935,7 +935,7 @@ void FossilClient::log(const FilePath &workingDir, const QStringList &files,
args << effectiveArgs;
if (!files.isEmpty())
args << "--path" << files;
- enqueueJob(createCommand(workingDir, fossilEditor), args);
+ enqueueJob(createCommand(workingDir, fossilEditor), args, workingDir);
}
void FossilClient::logCurrentFile(const FilePath &workingDir, const QStringList &files,
@@ -989,7 +989,7 @@ void FossilClient::logCurrentFile(const FilePath &workingDir, const QStringList
QStringList args(vcsCmdString);
args << effectiveArgs << files;
- enqueueJob(createCommand(workingDir, fossilEditor), args);
+ enqueueJob(createCommand(workingDir, fossilEditor), args, workingDir);
}
void FossilClient::revertFile(const FilePath &workingDir,
@@ -1009,7 +1009,7 @@ void FossilClient::revertFile(const FilePath &workingDir,
if (cmd->result() == ProcessResult::FinishedWithSuccess)
emit changed(files);
});
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, workingDir);
}
void FossilClient::revertAll(const FilePath &workingDir, const QString &revision, const QStringList &extraOptions)
@@ -1033,7 +1033,7 @@ void FossilClient::revertAll(const FilePath &workingDir, const QString &revision
if (cmd->result() == ProcessResult::FinishedWithSuccess)
emit changed(files);
});
- enqueueJob(createCommand(workingDir), args);
+ enqueueJob(createCommand(workingDir), args, workingDir);
}
QString FossilClient::sanitizeFossilOutput(const QString &output) const
diff --git a/src/plugins/fossil/fossilplugin.cpp b/src/plugins/fossil/fossilplugin.cpp
index 4692446258..c4ea13b446 100644
--- a/src/plugins/fossil/fossilplugin.cpp
+++ b/src/plugins/fossil/fossilplugin.cpp
@@ -37,6 +37,7 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseplugin.h>
#include <vcsbase/vcsbasesubmiteditor.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -60,45 +61,6 @@ using namespace std::placeholders;
namespace Fossil::Internal {
-class FossilTopicCache final : public IVersionControl::TopicCache
-{
-public:
- FossilTopicCache() = default;
-
-protected:
- FilePath trackFile(const FilePath &repository) final
- {
- return repository.pathAppended(Constants::FOSSILREPO);
- }
-
- QString refreshTopic(const FilePath &repository) final
- {
- return fossilClient().synchronousTopic(repository);
- }
-};
-
-const VcsBaseEditorParameters fileLogParameters {
- LogOutput,
- Constants::FILELOG_ID,
- Constants::FILELOG_DISPLAY_NAME,
- Constants::LOGAPP
-};
-
-const VcsBaseEditorParameters annotateLogParameters {
- AnnotateOutput,
- Constants::ANNOTATELOG_ID,
- Constants::ANNOTATELOG_DISPLAY_NAME,
- Constants::ANNOTATEAPP
-};
-
-const VcsBaseEditorParameters diffParameters {
- DiffOutput,
- Constants::DIFFLOG_ID,
- Constants::DIFFLOG_DISPLAY_NAME,
- Constants::DIFFAPP
-};
-
-
class FossilPluginPrivate final : public VersionControlBase
{
public:
@@ -171,23 +133,32 @@ public:
bool pullOrPush(SyncMode mode);
// Variables
- VcsEditorFactory fileLogFactory {
- &fileLogParameters,
+ VcsEditorFactory fileLogFactory {{
+ LogOutput,
+ Constants::FILELOG_ID,
+ VcsBase::Tr::tr("Fossil File Log Editor"),
+ Constants::LOGAPP,
[] { return new FossilEditorWidget; },
std::bind(&FossilPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory annotateLogFactory {
- &annotateLogParameters,
+ VcsEditorFactory annotateLogFactory {{
+ AnnotateOutput,
+ Constants::ANNOTATELOG_ID,
+ VcsBase::Tr::tr("Fossil Annotation Editor"),
+ Constants::ANNOTATEAPP,
[] { return new FossilEditorWidget; },
std::bind(&FossilPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory diffFactory {
- &diffParameters,
+ VcsEditorFactory diffFactory {{
+ DiffOutput,
+ Constants::DIFFLOG_ID,
+ VcsBase::Tr::tr("Fossil Diff Editor"),
+ Constants::DIFFAPP,
[] { return new FossilEditorWidget; },
std::bind(&FossilPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
CommandLocator *m_commandLocator = nullptr;
ActionContainer *m_fossilContainer = nullptr;
@@ -234,7 +205,13 @@ FossilPluginPrivate::FossilPluginPrivate()
{
Context context(Constants::FOSSIL_CONTEXT);
- setTopicCache(new FossilTopicCache);
+ setTopicFileTracker([](const FilePath &repository) {
+ return repository.pathAppended(Constants::FOSSILREPO);
+ });
+ setTopicRefresher([](const FilePath &repository) {
+ return fossilClient().synchronousTopic(repository);
+ });
+
connect(&fossilClient(), &VcsBaseClient::changed, this, &FossilPluginPrivate::changed);
m_commandLocator = new CommandLocator("Fossil", "fossil", "fossil", this);
@@ -251,7 +228,7 @@ FossilPluginPrivate::FossilPluginPrivate()
setupVcsSubmitEditor(this, {
Constants::COMMITMIMETYPE,
Constants::COMMIT_ID,
- Constants::COMMIT_DISPLAY_NAME,
+ VcsBase::Tr::tr("Fossil Commit Log Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CommitEditor; }
});
@@ -831,7 +808,7 @@ bool FossilPluginPrivate::managesFile(const FilePath &workingDirectory, const QS
bool FossilPluginPrivate::isConfigured() const
{
- const FilePath binary = fossilClient().vcsBinary();
+ const FilePath binary = fossilClient().vcsBinary({});
if (binary.isEmpty())
return false;
@@ -950,7 +927,8 @@ VcsCommand *FossilPluginPrivate::createInitialCheckoutCommand(const QString &sou
checkoutPath.createDir();
// Setup the wizard page command job
- auto command = VcsBaseClient::createVcsCommand(checkoutPath, fossilClient().processEnvironment());
+ auto command = VcsBaseClient::createVcsCommand(checkoutPath,
+ fossilClient().processEnvironment(checkoutPath));
if (!isLocalRepository
&& !cloneRepository.exists()) {
@@ -986,7 +964,7 @@ VcsCommand *FossilPluginPrivate::createInitialCheckoutCommand(const QString &sou
<< extraOptions
<< sourceUrl
<< fossilFileNative;
- command->addJob({fossilClient().vcsBinary(), args}, -1);
+ command->addJob({fossilClient().vcsBinary(checkoutPath), args}, -1);
}
// check out the cloned repository file into the working copy directory;
@@ -995,20 +973,20 @@ VcsCommand *FossilPluginPrivate::createInitialCheckoutCommand(const QString &sou
QStringList args({"open", fossilFileNative});
if (!checkoutBranch.isEmpty())
args << checkoutBranch;
- command->addJob({fossilClient().vcsBinary(), args}, -1);
+ command->addJob({fossilClient().vcsBinary(checkoutPath), args}, -1);
// set user default to admin user if specified
if (!isLocalRepository
&& !adminUser.isEmpty()) {
const QStringList args({ "user", "default", adminUser, "--user", adminUser});
- command->addJob({fossilClient().vcsBinary(), args}, -1);
+ command->addJob({fossilClient().vcsBinary(checkoutPath), args}, -1);
}
// turn-off autosync if requested
if (!isLocalRepository
&& disableAutosync) {
const QStringList args({"settings", "autosync", "off"});
- command->addJob({fossilClient().vcsBinary(), args}, -1);
+ command->addJob({fossilClient().vcsBinary(checkoutPath), args}, -1);
}
return command;
diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp
index fa9dee2cb3..99e6e01005 100644
--- a/src/plugins/git/branchmodel.cpp
+++ b/src/plugins/git/branchmodel.cpp
@@ -318,9 +318,12 @@ QVariant BranchModel::data(const QModelIndex &index, int role) const
if (!node->isLocal() || !node->isLeaf())
break;
- res += ' ' + arrowUp + QString::number(node->status.ahead);
+ if (node->status.ahead >= 0)
+ res += ' ' + arrowUp + QString::number(node->status.ahead);
+
if (!node->tracking.isEmpty()) {
- res += ' ' + arrowDown + QString::number(node->status.behind);
+ if (node->status.behind >= 0)
+ res += ' ' + arrowDown + QString::number(node->status.behind);
res += " [" + node->tracking + ']';
}
break;
@@ -911,13 +914,13 @@ void BranchModel::updateUpstreamStatus(BranchNode *node)
return;
Process *process = new Process(node);
- process->setEnvironment(gitClient().processEnvironment());
+ process->setEnvironment(gitClient().processEnvironment(d->workingDirectory));
QStringList parameters = {"rev-list", "--no-color", "--count"};
if (node->tracking.isEmpty())
- parameters += {"HEAD", "--not", "--remotes"};
+ parameters += {node->fullRef(), "--not", "--remotes"};
else
parameters += {"--left-right", node->fullRef() + "..." + node->tracking};
- process->setCommand({gitClient().vcsBinary(), parameters});
+ process->setCommand({gitClient().vcsBinary(d->workingDirectory), parameters});
process->setWorkingDirectory(d->workingDirectory);
connect(process, &Process::done, this, [this, process, node] {
process->deleteLater();
diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp
index cf991e6e93..12cc91eddb 100644
--- a/src/plugins/git/changeselectiondialog.cpp
+++ b/src/plugins/git/changeselectiondialog.cpp
@@ -33,8 +33,8 @@ ChangeSelectionDialog::ChangeSelectionDialog(const FilePath &workingDirectory, I
QWidget *parent) :
QDialog(parent)
{
- m_gitExecutable = gitClient().vcsBinary();
- m_gitEnvironment = gitClient().processEnvironment();
+ m_gitExecutable = gitClient().vcsBinary(workingDirectory);
+ m_gitEnvironment = gitClient().processEnvironment(workingDirectory);
resize(550, 350);
setWindowTitle(Tr::tr("Select a Git Commit"));
@@ -209,8 +209,9 @@ void ChangeSelectionDialog::recalculateCompletion()
return;
Process *process = new Process(this);
- process->setEnvironment(gitClient().processEnvironment());
- process->setCommand({gitClient().vcsBinary(), {"for-each-ref", "--format=%(refname:short)"}});
+ process->setEnvironment(gitClient().processEnvironment(workingDir));
+ process->setCommand(
+ {gitClient().vcsBinary(workingDir), {"for-each-ref", "--format=%(refname:short)"}});
process->setWorkingDirectory(workingDir);
process->setUseCtrlCStub(true);
connect(process, &Process::done, this, [this, process] {
diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp
index b11458393e..8af786ac5e 100644
--- a/src/plugins/git/gerrit/gerritmodel.cpp
+++ b/src/plugins/git/gerrit/gerritmodel.cpp
@@ -266,7 +266,6 @@ QueryContext::QueryContext(const QString &query,
m_output.append(m_process.readAllRawStandardOutput());
});
connect(&m_process, &Process::done, this, &QueryContext::processDone);
- m_process.setEnvironment(Git::Internal::gitClient().processEnvironment());
m_timer.setInterval(timeOutMS);
m_timer.setSingleShot(true);
@@ -286,6 +285,7 @@ void QueryContext::start()
VcsOutputWindow::appendCommand(m_process.workingDirectory(), commandLine);
m_timer.start();
m_process.setCommand(commandLine);
+ m_process.setEnvironment(Git::Internal::gitClient().processEnvironment(m_binary));
auto progress = new Core::ProcessProgress(&m_process);
progress->setDisplayName(Git::Tr::tr("Querying Gerrit"));
m_process.start();
diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp
index 802c921409..3ef90358b9 100644
--- a/src/plugins/git/gerrit/gerritplugin.cpp
+++ b/src/plugins/git/gerrit/gerritplugin.cpp
@@ -101,7 +101,7 @@ FetchContext::FetchContext(const std::shared_ptr<GerritChange> &change,
VcsBase::VcsOutputWindow::append(QString::fromLocal8Bit(m_process.readAllRawStandardOutput()));
});
m_process.setWorkingDirectory(repository);
- m_process.setEnvironment(gitClient().processEnvironment());
+ m_process.setEnvironment(gitClient().processEnvironment(repository));
}
void FetchContext::start()
@@ -279,7 +279,7 @@ QString GerritPlugin::branch(const FilePath &repository)
void GerritPlugin::fetch(const std::shared_ptr<GerritChange> &change, int mode)
{
// Locate git.
- const Utils::FilePath git = gitClient().vcsBinary();
+ const Utils::FilePath git = gitClient().vcsBinary(m_dialog->repositoryPath());
if (git.isEmpty()) {
VcsBase::VcsOutputWindow::appendError(Git::Tr::tr("Git is not available."));
return;
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 6f9224dda0..eb857c4685 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -827,15 +827,12 @@ FilePath GitClient::findRepositoryForDirectory(const FilePath &directory) const
{
if (directory.isEmpty() || directory.endsWith("/.git") || directory.path().contains("/.git/"))
return {};
- // QFileInfo is outside loop, because it is faster this way
- QFileInfo fileInfo;
FilePath parent;
for (FilePath dir = directory; !dir.isEmpty(); dir = dir.parentDir()) {
const FilePath gitName = dir.pathAppended(GIT_DIRECTORY);
if (!gitName.exists())
continue; // parent might exist
- fileInfo.setFile(gitName.toString());
- if (fileInfo.isFile())
+ if (gitName.isFile())
return dir;
if (gitName.pathAppended("config").exists())
return dir;
@@ -929,8 +926,8 @@ void GitClient::requestReload(const QString &documentId, const FilePath &source,
QTC_ASSERT(document, return);
GitBaseDiffEditorController *controller = factory(document);
QTC_ASSERT(controller, return);
- controller->setVcsBinary(settings().gitExecutable());
- controller->setProcessEnvironment(processEnvironment());
+ controller->setVcsBinary(vcsBinary(workingDirectory));
+ controller->setProcessEnvironment(processEnvironment(workingDirectory));
controller->setWorkingDirectory(workingDirectory);
using namespace std::placeholders;
@@ -1047,9 +1044,8 @@ void GitClient::log(const FilePath &workingDirectory, const QString &fileName,
const QString title = Tr::tr("Git Log \"%1\"").arg(msgArg);
const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
const FilePath sourceFile = VcsBaseEditor::getSource(workingDir, fileName);
- GitEditorWidget *editor = static_cast<GitEditorWidget *>(
- createVcsEditor(editorId, title, sourceFile,
- encoding(EncodingLogOutput), "logTitle", msgArg));
+ GitEditorWidget *editor = static_cast<GitEditorWidget *>(createVcsEditor(
+ editorId, title, sourceFile, encoding(EncodingLogOutput, sourceFile), "logTitle", msgArg));
VcsBaseEditorConfig *argWidget = editor->editorConfig();
if (!argWidget) {
argWidget = new GitLogArgumentsWidget(!fileName.isEmpty(), editor);
@@ -2089,9 +2085,9 @@ bool GitClient::synchronousApplyPatch(const FilePath &workingDirectory,
return false;
}
-Environment GitClient::processEnvironment() const
+Environment GitClient::processEnvironment(const FilePath &appliedTo) const
{
- Environment environment = VcsBaseClientImpl::processEnvironment();
+ Environment environment;
environment.prependOrSetPath(settings().path());
if (HostOsInfo::isWindowsHost() && settings().winSetHomeEnvironment()) {
QString homePath;
@@ -2103,7 +2099,7 @@ Environment GitClient::processEnvironment() const
environment.set("HOME", homePath);
}
environment.set("GIT_EDITOR", m_disableEditor ? "true" : m_gitQtcEditor);
- return environment;
+ return environment.appliedToEnvironment(appliedTo.deviceEnvironment());
}
bool GitClient::beginStashScope(const FilePath &workingDirectory, const QString &command,
@@ -2387,7 +2383,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR
void GitClient::launchGitK(const FilePath &workingDirectory, const QString &fileName) const
{
- tryLaunchingGitK(processEnvironment(), workingDirectory, fileName);
+ tryLaunchingGitK(processEnvironment(workingDirectory), workingDirectory, fileName);
}
void GitClient::launchRepositoryBrowser(const FilePath &workingDirectory) const
@@ -2420,7 +2416,7 @@ void GitClient::tryLaunchingGitK(const Environment &env,
const QString &fileName,
GitClient::GitKLaunchTrial trial) const
{
- const FilePath gitBinDirectory = gitBinDir(trial, vcsBinary().parentDir());
+ const FilePath gitBinDirectory = gitBinDir(trial, vcsBinary(workingDirectory).parentDir());
FilePath binary = gitBinDirectory.pathAppended("gitk").withExecutableSuffix();
QStringList arguments;
if (HostOsInfo::isWindowsHost()) {
@@ -2469,7 +2465,7 @@ void GitClient::handleGitKFailedToStart(const Environment &env,
GitKLaunchTrial nextTrial = None;
- if (oldTrial == Bin && vcsBinary().parentDir().fileName() == "bin") {
+ if (oldTrial == Bin && vcsBinary(workingDirectory).parentDir().fileName() == "bin") {
nextTrial = ParentOfBin;
} else if (oldTrial != SystemPath
&& !Environment::systemEnvironment().searchInPath("gitk").isEmpty()) {
@@ -2486,7 +2482,7 @@ void GitClient::handleGitKFailedToStart(const Environment &env,
bool GitClient::launchGitGui(const FilePath &workingDirectory) {
bool success = true;
- FilePath gitBinary = vcsBinary();
+ FilePath gitBinary = vcsBinary(workingDirectory);
if (gitBinary.isEmpty()) {
success = false;
} else {
@@ -2501,7 +2497,7 @@ bool GitClient::launchGitGui(const FilePath &workingDirectory) {
FilePath GitClient::gitBinDirectory() const
{
- const QString git = vcsBinary().toString();
+ const QString git = vcsBinary({}).toString();
if (git.isEmpty())
return {};
@@ -2529,7 +2525,7 @@ FilePath GitClient::gitBinDirectory() const
bool GitClient::launchGitBash(const FilePath &workingDirectory)
{
bool success = true;
- const FilePath git = vcsBinary();
+ const FilePath git = vcsBinary(workingDirectory);
if (git.isEmpty()) {
success = false;
@@ -2544,13 +2540,19 @@ bool GitClient::launchGitBash(const FilePath &workingDirectory)
return success;
}
-FilePath GitClient::vcsBinary() const
+FilePath GitClient::vcsBinary(const FilePath &forDirectory) const
{
- bool ok;
- Utils::FilePath binary = settings().gitExecutable(&ok);
- if (!ok)
- return {};
- return binary;
+ if (forDirectory.needsDevice()) {
+ auto it = m_gitExecutableCache.find(forDirectory.withNewPath({}));
+ if (it == m_gitExecutableCache.end()) {
+ const FilePath gitBin = forDirectory.withNewPath("git").searchInPath();
+ it = m_gitExecutableCache.insert(forDirectory.withNewPath({}),
+ gitBin.isExecutableFile() ? gitBin : FilePath{});
+ }
+
+ return it.value();
+ }
+ return settings().gitExecutable().value_or(FilePath{});
}
// returns first line from log and removes it
@@ -2757,7 +2759,7 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory,
const GitSubmitEditorPanelData &data,
CommitType commitType,
const QString &amendSHA1,
- const QString &messageFile,
+ const FilePath &messageFile,
SubmitFileModel *model)
{
const QString renameSeparator = " -> ";
@@ -2821,7 +2823,7 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory,
if (commitType == FixupCommit) {
arguments << "--fixup" << amendSHA1;
} else {
- arguments << "-F" << QDir::toNativeSeparators(messageFile);
+ arguments << "-F" << messageFile.nativePath();
if (commitType == AmendCommit)
arguments << "--amend";
const QString &authorString = data.authorString();
@@ -3247,7 +3249,7 @@ void GitClient::vcsExecAbortable(const FilePath &workingDirectory, const QString
command->addFlags(RunFlags::ShowStdOut | RunFlags::ShowSuccessMessage);
// For rebase, Git might request an editor (which means the process keeps running until the
// user closes it), so run without timeout.
- command->addJob({vcsBinary(), arguments}, isRebase ? 0 : vcsTimeoutS());
+ command->addJob({vcsBinary(workingDirectory), arguments}, isRebase ? 0 : vcsTimeoutS());
const QObject *actualContext = context ? context : this;
connect(command, &VcsCommand::done, actualContext, [=] {
const CommandResult result = CommandResult(*command);
@@ -3465,7 +3467,7 @@ QFuture<QVersionNumber> GitClient::gitVersion() const
// Do not execute repeatedly if that fails (due to git
// not being installed) until settings are changed.
- const FilePath newGitBinary = vcsBinary();
+ const FilePath newGitBinary = vcsBinary({});
const bool needToRunGit = m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty();
if (needToRunGit) {
auto proc = new Process(const_cast<GitClient *>(this));
@@ -3480,7 +3482,7 @@ QFuture<QVersionNumber> GitClient::gitVersion() const
proc->deleteLater();
});
- proc->setEnvironment(processEnvironment());
+ proc->setEnvironment(processEnvironment(newGitBinary));
proc->setCommand({newGitBinary, {"--version"}});
proc->start();
} else {
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 3f8368c62e..823aae6736 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -73,8 +73,8 @@ public:
UpstreamStatus() = default;
UpstreamStatus(int ahead, int behind) : ahead(ahead), behind(behind) {}
- int ahead = 0;
- int behind = 0;
+ int ahead = -1;
+ int behind = -1;
};
struct Author {
@@ -123,7 +123,7 @@ public:
GitClient();
~GitClient();
- Utils::FilePath vcsBinary() const override;
+ Utils::FilePath vcsBinary(const Utils::FilePath &forDirectory) const override;
QFuture<QVersionNumber> gitVersion() const;
void vcsExecAbortable(const Utils::FilePath &workingDirectory, const QStringList &arguments,
@@ -295,7 +295,7 @@ public:
const GitSubmitEditorPanelData &data,
CommitType commitType,
const QString &amendSHA1,
- const QString &messageFile,
+ const Utils::FilePath &messageFile,
VcsBase::SubmitFileModel *model);
enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed };
@@ -318,7 +318,7 @@ public:
QStringList synchronousRepositoryBranches(const QString &repositoryURL,
const Utils::FilePath &workingDirectory = {}) const;
- Utils::Environment processEnvironment() const override;
+ Utils::Environment processEnvironment(const Utils::FilePath &appliedTo) const override;
bool beginStashScope(const Utils::FilePath &workingDirectory, const QString &command,
StashFlag flag = Default, PushAction pushAction = NoPush);
@@ -395,6 +395,7 @@ private:
mutable Utils::FilePath m_gitVersionForBinary;
mutable QVersionNumber m_cachedGitVersion;
+ mutable QMap<Utils::FilePath, Utils::FilePath> m_gitExecutableCache;
QString m_gitQtcEditor;
QMap<Utils::FilePath, StashInfo> m_stashInfo;
diff --git a/src/plugins/git/gitconstants.h b/src/plugins/git/gitconstants.h
index 32d456ca16..ecd966c77c 100644
--- a/src/plugins/git/gitconstants.h
+++ b/src/plugins/git/gitconstants.h
@@ -3,30 +3,20 @@
#pragma once
-#include <QtGlobal>
-
-namespace Git {
-namespace Constants {
+namespace Git::Constants {
const char GIT_PLUGIN[] = "GitPlugin";
const char GIT_SVN_LOG_EDITOR_ID[] = "Git SVN Log Editor";
-const char GIT_SVN_LOG_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git SVN Log Editor");
const char GIT_LOG_EDITOR_ID[] = "Git Log Editor";
-const char GIT_LOG_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Log Editor");
const char GIT_REFLOG_EDITOR_ID[] = "Git Reflog Editor";
-const char GIT_REFLOG_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Reflog Editor");
const char GIT_BLAME_EDITOR_ID[] = "Git Annotation Editor";
-const char GIT_BLAME_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Annotation Editor");
const char GIT_COMMIT_TEXT_EDITOR_ID[] = "Git Commit Editor";
-const char GIT_COMMIT_TEXT_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Commit Editor");
const char GIT_REBASE_EDITOR_ID[] = "Git Rebase Editor";
-const char GIT_REBASE_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Rebase Editor");
const char GIT_BRANCH_VIEW_ID[] = "Git Branches";
const char GIT_CONTEXT[] = "Git Context";
const char GITSUBMITEDITOR_ID[] = "Git Submit Editor";
-const char GITSUBMITEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Git Submit Editor");
const char SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.git.submit";
const char C_GITEDITORID[] = "Git Editor";
@@ -38,5 +28,4 @@ const char DEFAULT_COMMENT_CHAR = '#';
const char TEXT_MARK_CATEGORY_BLAME[] = "Git.Mark.Blame";
-} // namespace Constants
-} // namespace Git
+} // Git::Constants
diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp
index 2f1f0bda49..5675fe0f48 100644
--- a/src/plugins/git/gitgrep.cpp
+++ b/src/plugins/git/gitgrep.cpp
@@ -134,8 +134,8 @@ static void runGitGrep(QPromise<SearchResultItems> &promise, const FileFindParam
const GitGrepParameters &gitParameters)
{
const auto setupProcess = [&parameters, gitParameters](Process &process) {
- const FilePath vcsBinary = gitClient().vcsBinary();
- const Environment environment = gitClient().processEnvironment();
+ const FilePath vcsBinary = gitClient().vcsBinary(parameters.searchDir);
+ const Environment environment = gitClient().processEnvironment(vcsBinary);
QStringList arguments = {
"-c", "color.grep.match=bold red",
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index d72b397f6e..966abc40b8 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -57,6 +57,7 @@
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -132,48 +133,6 @@ public:
static const QVersionNumber minimumRequiredVersion{1, 9};
-const VcsBaseEditorParameters svnLogEditorParameters {
- OtherContent,
- Git::Constants::GIT_SVN_LOG_EDITOR_ID,
- Git::Constants::GIT_SVN_LOG_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.svnlog"
-};
-
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- Git::Constants::GIT_LOG_EDITOR_ID,
- Git::Constants::GIT_LOG_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.log"
-};
-
-const VcsBaseEditorParameters reflogEditorParameters {
- LogOutput,
- Git::Constants::GIT_REFLOG_EDITOR_ID,
- Git::Constants::GIT_REFLOG_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.reflog"
-};
-
-const VcsBaseEditorParameters blameEditorParameters {
- AnnotateOutput,
- Git::Constants::GIT_BLAME_EDITOR_ID,
- Git::Constants::GIT_BLAME_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.annotation"
-};
-
-const VcsBaseEditorParameters commitTextEditorParameters {
- OtherContent,
- Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID,
- Git::Constants::GIT_COMMIT_TEXT_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.commit"
-};
-
-const VcsBaseEditorParameters rebaseEditorParameters {
- OtherContent,
- Git::Constants::GIT_REBASE_EDITOR_ID,
- Git::Constants::GIT_REBASE_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.git.rebase"
-};
-
// GitPlugin
class GitPluginPrivate final : public VersionControlBase
@@ -322,7 +281,7 @@ public:
const Context &context);
void updateRepositoryBrowserAction();
- IEditor *openSubmitEditor(const QString &fileName, const CommitData &cd);
+ IEditor *openSubmitEditor(const FilePath &fileName, const CommitData &cd);
void cleanCommitMessageFile();
void cleanRepository(const FilePath &directory);
void applyPatch(const FilePath &workingDirectory, QString file = {});
@@ -360,70 +319,69 @@ public:
BranchViewFactory m_branchViewFactory;
QPointer<RemoteDialog> m_remoteDialog;
FilePath m_submitRepository;
- QString m_commitMessageFileName;
+ FilePath m_commitMessageFileName;
InstantBlame m_instantBlame;
GitGrep gitGrep;
- VcsEditorFactory svnLogEditorFactory {
- &svnLogEditorParameters,
+ VcsEditorFactory svnLogEditorFactory {{
+ OtherContent,
+ Git::Constants::GIT_SVN_LOG_EDITOR_ID,
+ VcsBase::Tr::tr("Git SVN Log Editor"),
+ "text/vnd.qtcreator.git.svnlog",
[] { return new GitEditorWidget; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ Git::Constants::GIT_LOG_EDITOR_ID,
+ VcsBase::Tr::tr("Git Log Editor"),
+ "text/vnd.qtcreator.git.log",
[] { return new GitLogEditorWidgetT<GitEditorWidget>; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
-
- VcsEditorFactory reflogEditorFactory {
- &reflogEditorParameters,
- [] { return new GitLogEditorWidgetT<GitReflogEditorWidget>; },
+ }};
+
+ VcsEditorFactory reflogEditorFactory {{
+ LogOutput,
+ Git::Constants::GIT_REFLOG_EDITOR_ID,
+ VcsBase::Tr::tr("Git Reflog Editor"),
+ "text/vnd.qtcreator.git.reflog",
+ [] { return new GitLogEditorWidgetT<GitReflogEditorWidget>; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory blameEditorFactory {
- &blameEditorParameters,
+ VcsEditorFactory blameEditorFactory {{
+ AnnotateOutput,
+ Git::Constants::GIT_BLAME_EDITOR_ID,
+ VcsBase::Tr::tr("Git Annotation Editor"),
+ "text/vnd.qtcreator.git.annotation",
[] { return new GitEditorWidget; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory commitTextEditorFactory {
- &commitTextEditorParameters,
+ VcsEditorFactory commitTextEditorFactory {{
+ OtherContent,
+ Git::Constants::GIT_COMMIT_TEXT_EDITOR_ID,
+ VcsBase::Tr::tr("Git Commit Editor"),
+ "text/vnd.qtcreator.git.commit",
[] { return new GitEditorWidget; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory rebaseEditorFactory {
- &rebaseEditorParameters,
+ VcsEditorFactory rebaseEditorFactory {{
+ OtherContent,
+ Git::Constants::GIT_REBASE_EDITOR_ID,
+ VcsBase::Tr::tr("Git Rebase Editor"),
+ "text/vnd.qtcreator.git.rebase",
[] { return new GitEditorWidget; },
std::bind(&GitPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
static GitPluginPrivate *dd = nullptr;
-class GitTopicCache : public IVersionControl::TopicCache
-{
-public:
- GitTopicCache() {}
-
-protected:
- FilePath trackFile(const FilePath &repository) override
- {
- const FilePath gitDir = gitClient().findGitDirForRepository(repository);
- return gitDir.isEmpty() ? FilePath() : gitDir / "HEAD";
- }
-
- QString refreshTopic(const FilePath &repository) override
- {
- emit dd->repositoryChanged(repository);
- return gitClient().synchronousTopic(repository);
- }
-};
-
GitPluginPrivate::~GitPluginPrivate()
{
cleanCommitMessageFile();
@@ -433,11 +391,9 @@ void GitPluginPrivate::onApplySettings()
{
emit configurationChanged();
updateRepositoryBrowserAction();
- bool gitFoundOk;
- QString errorMessage;
- settings().gitExecutable(&gitFoundOk, &errorMessage);
- if (!gitFoundOk) {
- QTimer::singleShot(0, this, [errorMessage] {
+ const expected_str<FilePath> result = settings().gitExecutable();
+ if (!result) {
+ QTimer::singleShot(0, this, [errorMessage = result.error()] {
AsynchronousMessageBox::warning(Tr::tr("Git Settings"), errorMessage);
});
}
@@ -446,7 +402,7 @@ void GitPluginPrivate::onApplySettings()
void GitPluginPrivate::cleanCommitMessageFile()
{
if (!m_commitMessageFileName.isEmpty()) {
- QFile::remove(m_commitMessageFileName);
+ m_commitMessageFileName.removeFile();
m_commitMessageFileName.clear();
}
}
@@ -585,7 +541,14 @@ GitPluginPrivate::GitPluginPrivate()
{
dd = this;
- setTopicCache(new GitTopicCache);
+ setTopicFileTracker([](const FilePath &repository) {
+ const FilePath gitDir = gitClient().findGitDirForRepository(repository);
+ return gitDir.isEmpty() ? FilePath() : gitDir / "HEAD";
+ });
+ setTopicRefresher([this](const FilePath &repository) {
+ emit repositoryChanged(repository);
+ return gitClient().synchronousTopic(repository);
+ });
m_fileActions.reserve(10);
m_projectActions.reserve(10);
@@ -957,7 +920,7 @@ GitPluginPrivate::GitPluginPrivate()
setupVcsSubmitEditor(this, {
Git::Constants::SUBMIT_MIMETYPE,
Git::Constants::GITSUBMITEDITOR_ID,
- Git::Constants::GITSUBMITEDITOR_DISPLAY_NAME,
+ VcsBase::Tr::tr("Git Submit Editor"),
VcsBaseSubmitEditorParameters::DiffRows,
[] { return new GitSubmitEditor; },
});
@@ -1023,8 +986,12 @@ void GitPluginPrivate::blameFile()
const FilePath fileName = state.currentFile().canonicalPath();
FilePath topLevel;
VcsManager::findVersionControlForDirectory(fileName.parentDir(), &topLevel);
- gitClient().annotate(topLevel, fileName.relativeChildPath(topLevel).toString(),
- lineNumber, {}, extraOptions, firstLine);
+ gitClient().annotate(topLevel,
+ fileName.relativeChildPath(topLevel).path(),
+ lineNumber,
+ {},
+ extraOptions,
+ firstLine);
}
void GitPluginPrivate::logProject()
@@ -1284,7 +1251,9 @@ void GitPluginPrivate::startCommit(CommitType commitType)
m_submitRepository = data.panelInfo.repository;
// Start new temp file with message template
- TempFileSaver saver;
+ TempFileSaver saver(
+ data.panelInfo.repository.tmpDir().value_or(data.panelInfo.repository.withNewPath(""))
+ / "commit-msg.XXXXXX");
// Keep the file alive, else it removes self and forgets its name
saver.setAutoRemove(false);
saver.write(commitTemplate.toLocal8Bit());
@@ -1292,7 +1261,7 @@ void GitPluginPrivate::startCommit(CommitType commitType)
VcsOutputWindow::appendError(saver.errorString());
return;
}
- m_commitMessageFileName = saver.filePath().toString();
+ m_commitMessageFileName = saver.filePath();
openSubmitEditor(m_commitMessageFileName, data);
}
@@ -1321,10 +1290,9 @@ void GitPluginPrivate::instantBlameOnce()
m_instantBlame.once();
}
-IEditor *GitPluginPrivate::openSubmitEditor(const QString &fileName, const CommitData &cd)
+IEditor *GitPluginPrivate::openSubmitEditor(const FilePath &fileName, const CommitData &cd)
{
- IEditor *editor = EditorManager::openEditor(FilePath::fromString(fileName),
- Constants::GITSUBMITEDITOR_ID);
+ IEditor *editor = EditorManager::openEditor(fileName, Constants::GITSUBMITEDITOR_ID);
auto submitEditor = qobject_cast<GitSubmitEditor*>(editor);
QTC_ASSERT(submitEditor, return nullptr);
setSubmitEditor(submitEditor);
@@ -1357,10 +1325,9 @@ bool GitPluginPrivate::activateCommit()
QTC_ASSERT(editorDocument, return true);
// Submit editor closing. Make it write out the commit message
// and retrieve files
- const QFileInfo editorFile = editorDocument->filePath().toFileInfo();
- const QFileInfo changeFile(m_commitMessageFileName);
+
// Paranoia!
- if (editorFile.absoluteFilePath() != changeFile.absoluteFilePath())
+ if (!editorDocument->filePath().isSameFile(m_commitMessageFileName))
return true;
auto model = qobject_cast<SubmitFileModel *>(editor->fileModel());
@@ -1737,7 +1704,7 @@ bool GitPluginPrivate::isVcsFileOrDirectory(const FilePath &filePath) const
bool GitPluginPrivate::isConfigured() const
{
- return !gitClient().vcsBinary().isEmpty();
+ return !gitClient().vcsBinary({}).isEmpty();
}
bool GitPluginPrivate::supportsOperation(Operation operation) const
@@ -1802,9 +1769,10 @@ VcsCommand *GitPluginPrivate::createInitialCheckoutCommand(const QString &url,
QStringList args = {"clone", "--progress"};
args << extraArgs << url << localName;
- auto command = VcsBaseClient::createVcsCommand(baseDirectory, gitClient().processEnvironment());
+ auto command = VcsBaseClient::createVcsCommand(baseDirectory,
+ gitClient().processEnvironment(baseDirectory));
command->addFlags(RunFlags::SuppressStdErr);
- command->addJob({gitClient().vcsBinary(), args}, -1);
+ command->addJob({gitClient().vcsBinary(baseDirectory), args}, -1);
return command;
}
diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp
index 43b0e8ae6c..95938a41d8 100644
--- a/src/plugins/git/gitsettings.cpp
+++ b/src/plugins/git/gitsettings.cpp
@@ -164,14 +164,8 @@ GitSettings::GitSettings()
readSettings();
}
-FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const
+expected_str<FilePath> GitSettings::gitExecutable() const
{
- // Locate binary in path if one is specified, otherwise default to pathless binary.
- if (ok)
- *ok = true;
- if (errorMessage)
- errorMessage->clear();
-
if (tryResolve) {
resolvedBinPath = binaryPath();
if (!resolvedBinPath.isAbsolutePath())
@@ -180,11 +174,8 @@ FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const
}
if (resolvedBinPath.isEmpty()) {
- if (ok)
- *ok = false;
- if (errorMessage)
- *errorMessage = Tr::tr("The binary \"%1\" could not be located in the path \"%2\"")
- .arg(binaryPath().toUserOutput(), path());
+ return make_unexpected(Tr::tr("The binary \"%1\" could not be located in the path \"%2\"")
+ .arg(binaryPath().toUserOutput(), path()));
}
return resolvedBinPath;
}
diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h
index f6ec650c2e..2932cc78c0 100644
--- a/src/plugins/git/gitsettings.h
+++ b/src/plugins/git/gitsettings.h
@@ -44,7 +44,7 @@ public:
mutable Utils::FilePath resolvedBinPath;
mutable bool tryResolve = true;
- Utils::FilePath gitExecutable(bool *ok = nullptr, QString *errorMessage = nullptr) const;
+ Utils::expected_str<Utils::FilePath> gitExecutable() const;
static QString trIgnoreWhitespaceChanges();
static QString trIgnoreLineMoves();
diff --git a/src/plugins/git/mergetool.cpp b/src/plugins/git/mergetool.cpp
index 8829c44518..d0a102c9df 100644
--- a/src/plugins/git/mergetool.cpp
+++ b/src/plugins/git/mergetool.cpp
@@ -37,7 +37,7 @@ void MergeTool::start(const FilePath &workingDirectory, const QStringList &files
{
QStringList arguments;
arguments << "mergetool" << "-y" << files;
- const CommandLine cmd = {gitClient().vcsBinary(), arguments};
+ const CommandLine cmd = {gitClient().vcsBinary(workingDirectory), arguments};
VcsOutputWindow::appendCommand(workingDirectory, cmd);
m_process.setCommand(cmd);
m_process.setWorkingDirectory(workingDirectory);
diff --git a/src/plugins/mcusupport/mcukitaspect.cpp b/src/plugins/mcusupport/mcukitaspect.cpp
index f53dcacfd0..8d497f209d 100644
--- a/src/plugins/mcusupport/mcukitaspect.cpp
+++ b/src/plugins/mcusupport/mcukitaspect.cpp
@@ -32,19 +32,19 @@ Utils::Id McuDependenciesKitAspect::id()
return "PE.Profile.McuCMakeDependencies";
}
-Utils::NameValueItems McuDependenciesKitAspect::dependencies(const Kit *kit)
+Utils::EnvironmentItems McuDependenciesKitAspect::dependencies(const Kit *kit)
{
if (kit)
- return Utils::NameValueItem::fromStringList(
+ return Utils::EnvironmentItem::fromStringList(
kit->value(McuDependenciesKitAspect::id()).toStringList());
- return Utils::NameValueItems();
+ return Utils::EnvironmentItems();
}
-void McuDependenciesKitAspect::setDependencies(Kit *k, const Utils::NameValueItems &dependencies)
+void McuDependenciesKitAspect::setDependencies(Kit *k, const Utils::EnvironmentItems &dependencies)
{
if (k)
k->setValue(McuDependenciesKitAspect::id(),
- Utils::NameValueItem::toStringList(dependencies));
+ Utils::EnvironmentItem::toStringList(dependencies));
}
Utils::NameValuePairs McuDependenciesKitAspect::configuration(const Kit *kit)
@@ -108,7 +108,7 @@ public:
if (!variant.isNull() && !variant.canConvert(QVariant::List)) {
qWarning("Kit \"%s\" has a wrong mcu dependencies value set.",
qPrintable(kit->displayName()));
- McuDependenciesKitAspect::setDependencies(kit, Utils::NameValueItems());
+ McuDependenciesKitAspect::setDependencies(kit, Utils::EnvironmentItems());
}
}
diff --git a/src/plugins/mcusupport/mcukitaspect.h b/src/plugins/mcusupport/mcukitaspect.h
index a86841a72a..4625621348 100644
--- a/src/plugins/mcusupport/mcukitaspect.h
+++ b/src/plugins/mcusupport/mcukitaspect.h
@@ -11,8 +11,8 @@ class McuDependenciesKitAspect final
{
public:
static Utils::Id id();
- static Utils::NameValueItems dependencies(const ProjectExplorer::Kit *kit);
- static void setDependencies(ProjectExplorer::Kit *kit, const Utils::NameValueItems &dependencies);
+ static Utils::EnvironmentItems dependencies(const ProjectExplorer::Kit *kit);
+ static void setDependencies(ProjectExplorer::Kit *kit, const Utils::EnvironmentItems &dependencies);
static Utils::NameValuePairs configuration(const ProjectExplorer::Kit *kit);
};
diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp
index 456bdbdcdf..08c9c8abb0 100644
--- a/src/plugins/mcusupport/mcukitmanager.cpp
+++ b/src/plugins/mcusupport/mcukitmanager.cpp
@@ -180,7 +180,7 @@ public:
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdkPackage)
{
- NameValueItems dependencies;
+ EnvironmentItems dependencies;
auto processPackage = [&dependencies](const McuPackagePtr &package) {
const auto cmakeVariableName = package->cmakeVariableName();
diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h
index e38871e4aa..ee2738dbca 100644
--- a/src/plugins/mercurial/constants.h
+++ b/src/plugins/mercurial/constants.h
@@ -3,8 +3,6 @@
#pragma once
-#include <QtGlobal>
-
namespace Mercurial::Constants {
enum { debug = 0 };
@@ -23,20 +21,16 @@ const char DIFFIDENTIFIER[] = "^(?:diff --git a/|[+-]{3} (?:/dev/null|[ab]/(.+$)
// Base editor parameters
const char FILELOG_ID[] = "Mercurial File Log Editor";
-const char FILELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Mercurial File Log Editor");
const char LOGAPP[] = "text/vnd.qtcreator.mercurial.log";
const char ANNOTATELOG_ID[] = "Mercurial Annotation Editor";
-const char ANNOTATELOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Mercurial Annotation Editor");
const char ANNOTATEAPP[] = "text/vnd.qtcreator.mercurial.annotation";
const char DIFFLOG_ID[] = "Mercurial Diff Editor";
-const char DIFFLOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Mercurial Diff Editor");
const char DIFFAPP[] = "text/x-patch";
// Submit editor parameters
const char COMMIT_ID[] = "Mercurial Commit Log Editor";
-const char COMMIT_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Mercurial Commit Log Editor");
const char COMMITMIMETYPE[] = "text/vnd.qtcreator.mercurial.commit";
// File menu actions
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index 8122896422..fd568c9741 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -273,7 +273,7 @@ void MercurialClient::incoming(const FilePath &repositoryRoot, const QString &re
VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG_ID, title, repositoryRoot,
VcsBaseEditor::getCodec(repositoryRoot),
"incoming", id);
- enqueueJob(createCommand(FilePath::fromString(repository), editor), args);
+ enqueueJob(createCommand(FilePath::fromString(repository), editor), args, repositoryRoot);
}
void MercurialClient::outgoing(const FilePath &repositoryRoot)
@@ -286,7 +286,7 @@ void MercurialClient::outgoing(const FilePath &repositoryRoot)
VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG_ID, title, repositoryRoot,
VcsBaseEditor::getCodec(repositoryRoot),
"outgoing", repositoryRoot.toString());
- enqueueJob(createCommand(repositoryRoot, editor), args);
+ enqueueJob(createCommand(repositoryRoot, editor), args, repositoryRoot);
}
void MercurialClient::annotate(const Utils::FilePath &workingDir, const QString &file,
@@ -424,7 +424,6 @@ void MercurialClient::requestReload(const QString &documentId, const FilePath &s
QTC_ASSERT(document, return);
auto controller = new MercurialDiffEditorController(document, args);
controller->setVcsBinary(settings().binaryPath());
- controller->setProcessEnvironment(processEnvironment());
controller->setWorkingDirectory(workingDirectory);
VcsBase::setSource(document, sourceCopy);
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 081a7a5e41..76c8f2ba8c 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -30,6 +30,7 @@
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbaseeditor.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -50,44 +51,6 @@ using namespace std::placeholders;
namespace Mercurial::Internal {
-class MercurialTopicCache : public Core::IVersionControl::TopicCache
-{
-public:
- MercurialTopicCache() = default;
-
-protected:
- FilePath trackFile(const FilePath &repository) override
- {
- return repository.pathAppended(".hg/branch");
- }
-
- QString refreshTopic(const FilePath &repository) override
- {
- return mercurialClient().branchQuerySync(repository.toString());
- }
-};
-
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- Constants::FILELOG_ID,
- Constants::FILELOG_DISPLAY_NAME,
- Constants::LOGAPP
-};
-
-const VcsBaseEditorParameters annotateEditorParameters {
- AnnotateOutput,
- Constants::ANNOTATELOG_ID,
- Constants::ANNOTATELOG_DISPLAY_NAME,
- Constants::ANNOTATEAPP
-};
-
-const VcsBaseEditorParameters diffEditorParameters {
- DiffOutput,
- Constants::DIFFLOG_ID,
- Constants::DIFFLOG_DISPLAY_NAME,
- Constants::DIFFAPP
-};
-
class MercurialPluginPrivate final : public VcsBase::VersionControlBase
{
public:
@@ -180,23 +143,32 @@ private:
FilePath m_submitRepository;
public:
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
- [this] { return new MercurialEditorWidget; },
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ Constants::FILELOG_ID,
+ VcsBase::Tr::tr("Mercurial File Log Editor"),
+ Constants::LOGAPP,
+ [] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
- };
-
- VcsEditorFactory annotateEditorFactory {
- &annotateEditorParameters,
- [this] { return new MercurialEditorWidget; },
+ }};
+
+ VcsEditorFactory annotateEditorFactory {{
+ AnnotateOutput,
+ Constants::ANNOTATELOG_ID,
+ VcsBase::Tr::tr("Mercurial Annotation Editor"),
+ Constants::ANNOTATEAPP,
+ [] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
- };
-
- VcsEditorFactory diffEditorFactory {
- &diffEditorParameters,
- [this] { return new MercurialEditorWidget; },
+ }};
+
+ VcsEditorFactory diffEditorFactory {{
+ DiffOutput,
+ Constants::DIFFLOG_ID,
+ VcsBase::Tr::tr("Mercurial Diff Editor"),
+ Constants::DIFFAPP,
+ [] { return new MercurialEditorWidget; },
std::bind(&MercurialPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
static MercurialPluginPrivate *dd = nullptr;
@@ -209,12 +181,17 @@ MercurialPluginPrivate::MercurialPluginPrivate()
setupVcsSubmitEditor(this, {
Constants::COMMITMIMETYPE,
Constants::COMMIT_ID,
- Constants::COMMIT_DISPLAY_NAME,
+ VcsBase::Tr::tr("Mercurial Commit Log Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new CommitEditor; }
});
- setTopicCache(new MercurialTopicCache);
+ setTopicFileTracker([](const FilePath &repository) {
+ return repository.pathAppended(".hg/branch");
+ });
+ setTopicRefresher([](const FilePath &repository) {
+ return mercurialClient().branchQuerySync(repository.toString());
+ });
Core::Context context(Constants::MERCURIAL_CONTEXT);
@@ -759,7 +736,9 @@ VcsCommand *MercurialPluginPrivate::createInitialCheckoutCommand(const QString &
{
QStringList args;
args << QLatin1String("clone") << extraArgs << url << localName;
- auto command = VcsBaseClient::createVcsCommand(baseDirectory, mercurialClient().processEnvironment());
+ auto command = VcsBaseClient::createVcsCommand(baseDirectory,
+ mercurialClient().processEnvironment(
+ baseDirectory));
command->addJob({settings().binaryPath(), args}, -1);
return command;
}
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 23d6071d7d..42e2bbfcb1 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -37,6 +37,7 @@
#include <vcsbase/vcsbaseeditorconfig.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcsoutputwindow.h>
#include <QAction>
@@ -62,16 +63,9 @@ const char SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.p4.submit";
const char PERFORCE_CONTEXT[] = "Perforce Context";
const char PERFORCE_SUBMIT_EDITOR_ID[] = "Perforce.SubmitEditor";
-const char PERFORCE_SUBMIT_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Perforce.SubmitEditor");
-
const char PERFORCE_LOG_EDITOR_ID[] = "Perforce.LogEditor";
-const char PERFORCE_LOG_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Perforce Log Editor");
-
const char PERFORCE_DIFF_EDITOR_ID[] = "Perforce.DiffEditor";
-const char PERFORCE_DIFF_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Perforce Diff Editor");
-
const char PERFORCE_ANNOTATION_EDITOR_ID[] = "Perforce.AnnotationEditor";
-const char PERFORCE_ANNOTATION_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Perforce Annotation Editor");
// Ensure adding "..." to relative paths which is p4's convention
// for the current directory
@@ -128,27 +122,6 @@ struct PerforceResponse
QString stdErr;
};
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- PERFORCE_LOG_EDITOR_ID,
- PERFORCE_LOG_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.p4.log"
-};
-
-const VcsBaseEditorParameters annotateEditorParameters {
- AnnotateOutput,
- PERFORCE_ANNOTATION_EDITOR_ID,
- PERFORCE_ANNOTATION_EDITOR_DISPLAY_NAME,
- "text/vnd.qtcreator.p4.annotation"
-};
-
-const VcsBaseEditorParameters diffEditorParameters {
- DiffOutput,
- PERFORCE_DIFF_EDITOR_ID,
- PERFORCE_DIFF_EDITOR_DISPLAY_NAME,
- "text/x-patch"
-};
-
// Flags for runP4Cmd.
enum RunFlags
{
@@ -324,23 +297,32 @@ public:
ManagedDirectoryCache m_managedDirectoryCache;
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ PERFORCE_LOG_EDITOR_ID,
+ VcsBase::Tr::tr("Perforce Log Editor"),
+ "text/vnd.qtcreator.p4.log",
[] { return new PerforceEditorWidget; },
std::bind(&PerforcePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory annotateEditorFactory {
- &annotateEditorParameters,
+ VcsEditorFactory annotateEditorFactory {{
+ AnnotateOutput,
+ PERFORCE_ANNOTATION_EDITOR_ID,
+ VcsBase::Tr::tr("Perforce Annotation Editor"),
+ "text/vnd.qtcreator.p4.annotation",
[] { return new PerforceEditorWidget; },
std::bind(&PerforcePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory diffEditorFactory {
- &diffEditorParameters,
+ VcsEditorFactory diffEditorFactory {{
+ DiffOutput,
+ PERFORCE_DIFF_EDITOR_ID,
+ VcsBase::Tr::tr("Perforce Diff Editor"),
+ "text/x-patch",
[] { return new PerforceEditorWidget; },
std::bind(&PerforcePluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
static PerforcePluginPrivate *dd = nullptr;
@@ -355,7 +337,7 @@ PerforcePluginPrivate::PerforcePluginPrivate()
setupVcsSubmitEditor(this, {
SUBMIT_MIMETYPE,
PERFORCE_SUBMIT_EDITOR_ID,
- PERFORCE_SUBMIT_EDITOR_DISPLAY_NAME,
+ VcsBase::Tr::tr("Perforce.SubmitEditor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new PerforceSubmitEditor; },
});
@@ -827,7 +809,7 @@ void PerforcePluginPrivate::annotate(const FilePath &workingDir,
if (lineNumber < 1)
lineNumber = VcsBaseEditor::lineNumberOfCurrentEditor();
IEditor *ed = showOutputInEditor(Tr::tr("p4 annotate %1").arg(id),
- result.stdOut, annotateEditorParameters.id,
+ result.stdOut, PERFORCE_ANNOTATION_EDITOR_ID,
source, codec);
VcsBaseEditor::gotoLineOfEditor(ed, lineNumber);
}
@@ -878,7 +860,7 @@ void PerforcePluginPrivate::filelog(const FilePath &workingDir, const QString &f
if (!result.error) {
const FilePath source = VcsBaseEditor::getSource(workingDir, fileName);
IEditor *editor = showOutputInEditor(Tr::tr("p4 filelog %1").arg(id), result.stdOut,
- logEditorParameters.id, source, codec);
+ PERFORCE_LOG_EDITOR_ID, source, codec);
if (enableAnnotationContextMenu)
VcsBaseEditor::getVcsBaseEditor(editor)->setFileLogAnnotateEnabled(true);
}
@@ -900,7 +882,7 @@ void PerforcePluginPrivate::changelists(const FilePath &workingDir, const QStrin
if (!result.error) {
const FilePath source = VcsBaseEditor::getSource(workingDir, fileName);
IEditor *editor = showOutputInEditor(Tr::tr("p4 changelists %1").arg(id), result.stdOut,
- logEditorParameters.id, source, codec);
+ PERFORCE_LOG_EDITOR_ID, source, codec);
VcsBaseEditor::gotoLineOfEditor(editor, 1);
}
}
@@ -1376,7 +1358,7 @@ void PerforcePluginPrivate::p4Diff(const PerforceDiffParameters &p)
}
// Create new editor
IEditor *editor = showOutputInEditor(Tr::tr("p4 diff %1").arg(id), result.stdOut,
- diffEditorParameters.id,
+ PERFORCE_DIFF_EDITOR_ID,
VcsBaseEditor::getSource(p.workingDir, p.files),
codec);
VcsBaseEditor::tagEditor(editor, tag);
@@ -1400,7 +1382,7 @@ void PerforcePluginPrivate::vcsDescribe(const FilePath &source, const QString &n
const PerforceResponse result = runP4Cmd(settings().topLevel(), args, CommandToWindow|StdErrToWindow|ErrorToWindow,
{}, {}, codec);
if (!result.error)
- showOutputInEditor(Tr::tr("p4 describe %1").arg(n), result.stdOut, diffEditorParameters.id, source, codec);
+ showOutputInEditor(Tr::tr("p4 describe %1").arg(n), result.stdOut, PERFORCE_DIFF_EDITOR_ID, source, codec);
}
void PerforcePluginPrivate::cleanCommitMessageFile()
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp
index 3d2e86d445..a7405ef46e 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp
@@ -312,6 +312,9 @@ void DeviceSettingsWidget::testDevice()
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setModal(true);
dlg->show();
+ connect(dlg, &QObject::destroyed, this, [this, id = device->id()] {
+ handleDeviceUpdated(id);
+ });
}
void DeviceSettingsWidget::handleDeviceUpdated(Id id)
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 9a79347da1..0fcdae1c91 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -593,7 +593,7 @@ QString IDevice::deviceStateToString() const
QPixmap IDevice::deviceStateIcon() const
{
- switch (d->deviceState) {
+ switch (deviceState()) {
case IDevice::DeviceReadyToUse: return Icons::DEVICE_READY_INDICATOR.pixmap();
case IDevice::DeviceConnected: return Icons::DEVICE_CONNECTED_INDICATOR.pixmap();
case IDevice::DeviceDisconnected: return Icons::DEVICE_DISCONNECTED_INDICATOR.pixmap();
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index c494387de4..6434b5b6dd 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -105,7 +105,7 @@ public:
virtual ~IDevice();
- Ptr clone() const;
+ virtual Ptr clone() const;
DeviceSettings *settings() const;
@@ -154,9 +154,9 @@ public:
virtual DeviceProcessSignalOperation::Ptr signalOperation() const;
enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
- DeviceState deviceState() const;
+ virtual DeviceState deviceState() const;
void setDeviceState(const DeviceState state);
- QString deviceStateToString() const;
+ virtual QString deviceStateToString() const;
QPixmap deviceStateIcon() const;
static Utils::Id typeFromMap(const Utils::Store &map);
diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp
index 9a63d789ec..a34f8bc256 100644
--- a/src/plugins/projectexplorer/environmentwidget.cpp
+++ b/src/plugins/projectexplorer/environmentwidget.cpp
@@ -481,25 +481,25 @@ void EnvironmentWidget::unsetEnvironmentButtonClicked()
d->m_editor.setEnvironmentItems(d->m_model->userChanges());
}
-void EnvironmentWidget::amendPathList(Utils::NameValueItem::Operation op)
+void EnvironmentWidget::amendPathList(Utils::EnvironmentItem::Operation op)
{
const QString varName = d->m_model->indexToVariable(d->m_environmentView->currentIndex());
const FilePath dir = FileUtils::getExistingDirectory(this, Tr::tr("Choose Directory"));
if (dir.isEmpty())
return;
- Utils::NameValueItems changes = d->m_model->userChanges();
+ Utils::EnvironmentItems changes = d->m_model->userChanges();
changes.append({varName, dir.toUserOutput(), op});
setUserChanges(changes);
}
void EnvironmentWidget::appendPathButtonClicked()
{
- amendPathList(Utils::NameValueItem::Append);
+ amendPathList(Utils::EnvironmentItem::Append);
}
void EnvironmentWidget::prependPathButtonClicked()
{
- amendPathList(Utils::NameValueItem::Prepend);
+ amendPathList(Utils::EnvironmentItem::Prepend);
}
void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current)
diff --git a/src/plugins/projectexplorer/environmentwidget.h b/src/plugins/projectexplorer/environmentwidget.h
index a00e45bcda..b1a26b036b 100644
--- a/src/plugins/projectexplorer/environmentwidget.h
+++ b/src/plugins/projectexplorer/environmentwidget.h
@@ -57,7 +57,7 @@ private:
void linkActivated(const QString &link);
using PathListModifier = std::function<QString(const QString &oldList, const QString &newDir)>;
- void amendPathList(Utils::NameValueItem::Operation op);
+ void amendPathList(Utils::EnvironmentItem::Operation op);
class Private;
const std::unique_ptr<Private> d;
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 82e4c5b181..bbf2b8be1d 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -746,14 +746,10 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
bool MiniProjectTargetSelector::event(QEvent *event)
{
- if (event->type() == QEvent::LayoutRequest) {
- doLayout(true);
+ if (event->type() == QEvent::ShortcutOverride
+ && static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
+ event->accept();
return true;
- } else if (event->type() == QEvent::ShortcutOverride) {
- if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
- event->accept();
- return true;
- }
}
return QWidget::event(event);
}
@@ -856,7 +852,7 @@ QVector<int> MiniProjectTargetSelector::listWidgetWidths(int minSize, int maxSiz
}
}
-void MiniProjectTargetSelector::doLayout(bool keepSize)
+void MiniProjectTargetSelector::doLayout()
{
// An unconfigured project shows empty build/deploy/run sections
// if there's a configured project in the seesion
@@ -867,15 +863,12 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
m_kitAreaWidget->move(0, 0);
- int oldSummaryLabelY = m_summaryLabel->y();
-
int kitAreaHeight = m_kitAreaWidget->isVisibleTo(this) ? m_kitAreaWidget->sizeHint().height() : 0;
// 1. Calculate the summary label height
int summaryLabelY = 1 + kitAreaHeight;
int summaryLabelHeight = 0;
- int oldSummaryLabelHeight = m_summaryLabel->height();
bool onlySummary = false;
// Count the number of lines
int visibleLineCount = m_projectListWidget->isVisibleTo(this) ? 0 : 1;
@@ -894,9 +887,6 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
summaryLabelHeight = m_summaryLabel->sizeHint().height();
}
- if (keepSize && oldSummaryLabelHeight > summaryLabelHeight)
- summaryLabelHeight = oldSummaryLabelHeight;
-
m_summaryLabel->move(0, summaryLabelY);
// Height to be aligned with side bar button
@@ -915,16 +905,13 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
maxItemCount = qMax(maxItemCount, m_listWidgets[i]->maxCount());
int titleWidgetsHeight = m_titleWidgets.first()->height();
- if (keepSize) {
- heightWithoutKitArea = height() - oldSummaryLabelY + 1;
- } else {
- // Clamp the size of the listwidgets to be at least as high as the sidebar button
- // and at most half the height of the entire Qt Creator window.
- heightWithoutKitArea = summaryLabelHeight
- + qBound(alignedWithActionHeight,
- maxItemCount * 30 + bottomMargin + titleWidgetsHeight,
- Core::ICore::mainWindow()->height() / 2);
- }
+
+ // Clamp the size of the listwidgets to be at least as high as the sidebar button
+ // and at most half the height of the entire Qt Creator window.
+ heightWithoutKitArea = summaryLabelHeight
+ + qBound(alignedWithActionHeight,
+ maxItemCount * 30 + bottomMargin + titleWidgetsHeight,
+ Core::ICore::mainWindow()->height() / 2);
int titleY = summaryLabelY + summaryLabelHeight;
int listY = titleY + titleWidgetsHeight;
@@ -933,15 +920,6 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
// list widget widths
int minWidth = qMax(m_summaryLabel->sizeHint().width(), 250);
minWidth = qMax(minWidth, m_kitAreaWidget->sizeHint().width());
- if (keepSize) {
- // Do not make the widget smaller then it was before
- int oldTotalListWidgetWidth = m_projectListWidget->isVisibleTo(this) ?
- m_projectListWidget->width() : 0;
- for (int i = TARGET; i < LAST; ++i)
- oldTotalListWidgetWidth += m_listWidgets[i]->width();
- minWidth = qMax(minWidth, oldTotalListWidgetWidth);
- }
-
QVector<int> widths = listWidgetWidths(minWidth, Core::ICore::mainWindow()->width() * 0.9);
const int runColumnWidth = widths[RUN] == -1 ? 0 : RunColumnWidth;
@@ -969,10 +947,7 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
m_kitAreaWidget->resize(x - 1, kitAreaHeight);
newGeometry.setSize({x, heightWithoutKitArea + kitAreaHeight});
} else {
- if (keepSize)
- heightWithoutKitArea = height() - oldSummaryLabelY + 1;
- else
- heightWithoutKitArea = qMax(summaryLabelHeight + bottomMargin, alignedWithActionHeight);
+ heightWithoutKitArea = qMax(summaryLabelHeight + bottomMargin, alignedWithActionHeight);
m_summaryLabel->resize(m_summaryLabel->sizeHint().width(), heightWithoutKitArea - bottomMargin);
m_kitAreaWidget->resize(m_kitAreaWidget->sizeHint());
newGeometry.setSize({m_summaryLabel->width() + 1, heightWithoutKitArea + kitAreaHeight});
@@ -1359,7 +1334,7 @@ void MiniProjectTargetSelector::activeRunConfigurationChanged(RunConfiguration *
void MiniProjectTargetSelector::setVisible(bool visible)
{
- doLayout(false);
+ doLayout();
QWidget::setVisible(visible);
m_projectAction->setChecked(visible);
if (visible) {
@@ -1554,7 +1529,7 @@ void MiniProjectTargetSelector::updateSummary()
}
if (summary != m_summaryLabel->text()) {
m_summaryLabel->setText(summary);
- doLayout(false);
+ doLayout();
}
}
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
index e28828ef4a..81f98c4a45 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.h
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -74,7 +74,7 @@ private:
void paintEvent(QPaintEvent *) override;
void mousePressEvent(QMouseEvent *) override;
- void doLayout(bool keepSize);
+ void doLayout();
QVector<int> listWidgetWidths(int minSize, int maxSize);
QWidget *createTitleLabel(const QString &text);
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index cd46c2a521..7f2eee43db 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -1063,13 +1063,13 @@ void Project::setNamedSettings(const Key &name, const QVariant &value)
void Project::setAdditionalEnvironment(const EnvironmentItems &envItems)
{
- setNamedSettings(PROJECT_ENV_KEY, NameValueItem::toStringList(envItems));
+ setNamedSettings(PROJECT_ENV_KEY, EnvironmentItem::toStringList(envItems));
emit environmentChanged();
}
EnvironmentItems Project::additionalEnvironment() const
{
- return NameValueItem::fromStringList(namedSettings(PROJECT_ENV_KEY).toStringList());
+ return EnvironmentItem::fromStringList(namedSettings(PROJECT_ENV_KEY).toStringList());
}
bool Project::needsConfiguration() const
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index e8aa205abd..4a9d1ef8aa 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -1897,10 +1897,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
&ProjectWelcomePage::requestProject,
m_instance,
&ProjectExplorerPlugin::openProjectWelcomePage);
- connect(SessionManager::instance(),
- &SessionManager::startupSessionRestored,
- m_instance,
- &ProjectExplorerPlugin::finishedInitialization);
dd->updateWelcomePage();
MacroExpander *expander = Utils::globalMacroExpander();
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index eb33841dd9..ffb5d1bcd3 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -24,8 +24,6 @@ namespace Core {
class OutputWindow;
} // Core
-namespace Utils { class CommandLine; }
-
namespace ProjectExplorer {
class CustomParserSettings;
class FolderNode;
@@ -170,8 +168,6 @@ public:
static Core::OutputWindow *buildSystemOutput();
signals:
- void finishedInitialization();
-
// Is emitted when a project has been added/removed,
// or the file list of a specific project has changed.
void fileListChanged();
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 3e5ee74e73..feab87da1b 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -89,6 +89,7 @@ QtcPlugin {
"makestep.cpp", "makestep.h",
"miniprojecttargetselector.cpp", "miniprojecttargetselector.h",
"msvcparser.cpp", "msvcparser.h",
+ "msvctoolchain.cpp", "msvctoolchain.h",
"namedwidget.cpp", "namedwidget.h",
"osparser.cpp", "osparser.h",
"panelswidget.cpp", "panelswidget.h",
@@ -230,15 +231,6 @@ QtcPlugin {
files: ["*.png"]
}
- Group {
- name: "WindowsToolChains"
- condition: qbs.targetOS.contains("windows") || qtc.withPluginTests
- files: [
- "msvctoolchain.cpp",
- "msvctoolchain.h",
- ]
- }
-
QtcTestFiles {
files: ["outputparser_test.h", "outputparser_test.cpp"]
}
diff --git a/src/plugins/projectexplorer/projectimporter.h b/src/plugins/projectexplorer/projectimporter.h
index 3e67f09c06..6946054ca9 100644
--- a/src/plugins/projectexplorer/projectimporter.h
+++ b/src/plugins/projectexplorer/projectimporter.h
@@ -36,6 +36,7 @@ public:
virtual const QList<BuildInfo> import(const Utils::FilePath &importPath, bool silent = false);
virtual Utils::FilePaths importCandidates() = 0;
virtual Target *preferredTarget(const QList<Target *> &possibleTargets);
+ virtual bool filter(Kit *) const { return true; }
bool isUpdating() const { return m_isUpdating; }
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index 11d27bf441..45524bdb16 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -583,11 +583,9 @@ public:
manageSessionsButton->setOnClicked([] { SessionManager::showSessionManager(); });
auto sessionsLabel = new QLabel(this);
- sessionsLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
sessionsLabel->setText(Tr::tr("Sessions"));
auto recentProjectsLabel = new QLabel(this);
- recentProjectsLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
recentProjectsLabel->setText(Tr::tr("Projects"));
auto sessionsList = new TreeView(this, "Sessions");
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index 5e67d29132..72e77fd664 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -304,6 +304,8 @@ void TargetSetupPagePrivate::setupWidgets(const QString &filterText)
for (Kit *k : KitManager::sortedKits()) {
if (!filterText.isEmpty() && !k->displayName().contains(filterText, Qt::CaseInsensitive))
continue;
+ if (m_importer && !m_importer->filter(k))
+ continue;
const auto widget = new TargetSetupWidget(k, m_projectPath);
connect(widget, &TargetSetupWidget::selectedToggled,
this, &TargetSetupPagePrivate::kitSelectionChanged);
@@ -570,7 +572,6 @@ void TargetSetupPagePrivate::doInitializePage()
setupImports();
selectAtLeastOneEnabledKit();
-
updateVisibility();
}
diff --git a/src/plugins/qbsprojectmanager/qbseditor.cpp b/src/plugins/qbsprojectmanager/qbseditor.cpp
index 7eed6977a2..08f6e0a872 100644
--- a/src/plugins/qbsprojectmanager/qbseditor.cpp
+++ b/src/plugins/qbsprojectmanager/qbseditor.cpp
@@ -6,13 +6,23 @@
#include "qbslanguageclient.h"
#include "qbsprojectmanagertr.h"
+#include <languageclient/languageclientcompletionassist.h>
#include <languageclient/languageclientmanager.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectnodes.h>
+#include <qmljseditor/qmljscompletionassist.h>
+#include <texteditor/codeassist/genericproposal.h>
+#include <utils/utilsicons.h>
#include <utils/mimeconstants.h>
#include <QPointer>
+#include <memory>
+#include <optional>
+
using namespace LanguageClient;
using namespace QmlJSEditor;
+using namespace TextEditor;
using namespace Utils;
namespace QbsProjectManager::Internal {
@@ -26,11 +36,79 @@ private:
bool inNextSplit = false) override;
};
+class QbsCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
+{
+public:
+ QbsCompletionAssistProcessor(Client *client);
+
+private:
+ QList<AssistProposalItemInterface *> generateCompletionItems(
+ const QList<LanguageServerProtocol::CompletionItem> &items) const override;
+};
+
+class MergedCompletionAssistProcessor : public IAssistProcessor
+{
+public:
+ MergedCompletionAssistProcessor(const AssistInterface *interface) : m_interface(interface) {}
+ ~MergedCompletionAssistProcessor();
+
+private:
+ IAssistProposal *perform() override;
+ bool running() override { return m_started && (!m_qmlProposal || !m_qbsProposal); }
+ void checkFinished();
+
+ const AssistInterface * const m_interface;
+ std::unique_ptr<IAssistProcessor> m_qmlProcessor;
+ std::unique_ptr<IAssistProcessor> m_qbsProcessor;
+ std::optional<IAssistProposal *> m_qmlProposal;
+ std::optional<IAssistProposal *> m_qbsProposal;
+ bool m_started = false;
+};
+
+class QbsCompletionAssistProvider : public QmlJSCompletionAssistProvider
+{
+private:
+ IAssistProcessor *createProcessor(const AssistInterface *interface) const override
+ {
+ return new MergedCompletionAssistProcessor(interface);
+ }
+};
+
+class QbsCompletionItem : public LanguageClientCompletionItem
+{
+public:
+ using LanguageClientCompletionItem::LanguageClientCompletionItem;
+
+private:
+ QIcon icon() const override;
+};
+
+class MergedProposalModel : public GenericProposalModel
+{
+public:
+ MergedProposalModel(const QList<GenericProposalModelPtr> &sourceModels);
+};
+
+static Client *clientForDocument(const TextDocument *doc)
+{
+ if (!doc)
+ return nullptr;
+ const QList<Client *> &candidates = LanguageClientManager::clientsSupportingDocument(doc);
+ for (Client * const candidate : candidates) {
+ if (const auto qbsClient = qobject_cast<QbsLanguageClient *>(candidate);
+ qbsClient && qbsClient->isActive() && qbsClient->documentOpen(doc)) {
+ return qbsClient;
+ }
+ }
+ return nullptr;
+}
+
QbsEditorFactory::QbsEditorFactory() : QmlJSEditorFactory("QbsEditor.QbsEditor")
{
setDisplayName(Tr::tr("Qbs Editor"));
setMimeTypes({Utils::Constants::QBS_MIMETYPE});
setEditorWidgetCreator([] { return new QbsEditorWidget; });
+ setCompletionAssistProvider(new QbsCompletionAssistProvider);
}
void QbsEditorWidget::findLinkAt(const QTextCursor &cursor, const LinkHandler &processLinkCallback,
@@ -43,18 +121,103 @@ void QbsEditorWidget::findLinkAt(const QTextCursor &cursor, const LinkHandler &p
if (!self)
return;
const auto doc = self->textDocument();
- if (!doc)
- return;
- const QList<Client *> &candidates = LanguageClientManager::clientsSupportingDocument(doc);
- for (Client * const candidate : candidates) {
- const auto qbsClient = qobject_cast<QbsLanguageClient *>(candidate);
- if (!qbsClient || !qbsClient->isActive() || !qbsClient->documentOpen(doc))
- continue;
- qbsClient->findLinkAt(doc, cursor, processLinkCallback, resolveTarget,
+ if (Client * const client = clientForDocument(doc)) {
+ client->findLinkAt(doc, cursor, processLinkCallback, resolveTarget,
LinkTarget::SymbolDef);
}
};
QmlJSEditorWidget::findLinkAt(cursor, extendedCallback, resolveTarget, inNextSplit);
}
+MergedCompletionAssistProcessor::~MergedCompletionAssistProcessor()
+{
+ if (m_qmlProposal)
+ delete *m_qmlProposal;
+ if (m_qbsProposal)
+ delete *m_qbsProposal;
+}
+
+IAssistProposal *MergedCompletionAssistProcessor::perform()
+{
+ m_started = true;
+ if (Client *const qbsClient = clientForDocument(
+ TextDocument::textDocumentForFilePath(m_interface->filePath()))) {
+ m_qbsProcessor.reset(new QbsCompletionAssistProcessor(qbsClient));
+ m_qbsProcessor->setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
+ m_qbsProposal = proposal;
+ checkFinished();
+ });
+ m_qbsProcessor->start(std::make_unique<AssistInterface>(m_interface->cursor(),
+ m_interface->filePath(),
+ ExplicitlyInvoked));
+ } else {
+ m_qbsProposal = nullptr;
+ }
+ m_qmlProcessor.reset(QmlJSCompletionAssistProvider().createProcessor(m_interface));
+ m_qmlProcessor->setAsyncCompletionAvailableHandler([this](IAssistProposal *proposal) {
+ m_qmlProposal = proposal;
+ checkFinished();
+ });
+ const auto qmlJsIface = static_cast<const QmlJSCompletionAssistInterface *>(m_interface);
+ return m_qmlProcessor->start(
+ std::make_unique<QmlJSCompletionAssistInterface>(qmlJsIface->cursor(),
+ qmlJsIface->filePath(),
+ ExplicitlyInvoked,
+ qmlJsIface->semanticInfo()));
+}
+
+void MergedCompletionAssistProcessor::checkFinished()
+{
+ if (running())
+ return;
+
+ QList<GenericProposalModelPtr> sourceModels;
+ int basePosition = -1;
+ for (const IAssistProposal * const proposal : {*m_qmlProposal, *m_qbsProposal}) {
+ if (proposal) {
+ if (const auto model = proposal->model().dynamicCast<GenericProposalModel>())
+ sourceModels << model;
+ if (basePosition == -1)
+ basePosition = proposal->basePosition();
+ else
+ QTC_CHECK(basePosition == proposal->basePosition());
+ }
+ }
+ setAsyncProposalAvailable(
+ new GenericProposal(basePosition >= 0 ? basePosition : m_interface->position(),
+ GenericProposalModelPtr(new MergedProposalModel(sourceModels))));
+}
+
+MergedProposalModel::MergedProposalModel(const QList<GenericProposalModelPtr> &sourceModels)
+{
+ QList<AssistProposalItemInterface *> items;
+ for (const GenericProposalModelPtr &model : sourceModels) {
+ items << model->originalItems();
+ model->loadContent({});
+ }
+ loadContent(items);
+}
+
+QbsCompletionAssistProcessor::QbsCompletionAssistProcessor(Client *client)
+ : LanguageClientCompletionAssistProcessor(client, nullptr, {})
+{}
+
+QList<AssistProposalItemInterface *> QbsCompletionAssistProcessor::generateCompletionItems(
+ const QList<LanguageServerProtocol::CompletionItem> &items) const
+{
+ return Utils::transform<QList<AssistProposalItemInterface *>>(
+ items, [](const LanguageServerProtocol::CompletionItem &item) {
+ return new QbsCompletionItem(item);
+ });
+}
+
+QIcon QbsCompletionItem::icon() const
+{
+ if (!item().detail()) {
+ return ProjectExplorer::DirectoryIcon(
+ ProjectExplorer::Constants::FILEOVERLAY_MODULES).icon();
+ }
+ return CodeModelIcon::iconForType(CodeModelIcon::Property);
+}
+
} // namespace QbsProjectManager::Internal
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index c8265d7354..36d0e657cf 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -10,6 +10,7 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/session.h>
#include <cppeditor/cppmodelmanager.h>
@@ -281,6 +282,8 @@ void ModelManager::delayedInitialization()
this, &ModelManager::removeProjectInfo);
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
this, &ModelManager::updateDefaultProjectInfo);
+ connect(SessionManager::instance(), &SessionManager::aboutToLoadSession,
+ this, &ModelManager::cancelAllThreads);
ViewerContext qbsVContext;
qbsVContext.language = Dialect::QmlQbs;
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
index 524150db41..50d8596ae3 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
+++ b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
@@ -286,7 +286,7 @@ const QString projectEnvironmentVariable(const QString &key)
if (auto buildSystem = getBuildSystem()) {
auto envItems = buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(), envItems.end(), [key](NameValueItem &item) {
+ auto confEnv = std::find_if(envItems.begin(), envItems.end(), [key](EnvironmentItem &item) {
return item.name == key;
});
if (confEnv != envItems.end())
diff --git a/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp b/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
index 2a5e20fa48..77bddffb05 100644
--- a/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
+++ b/src/plugins/qtapplicationmanager/appmanagerrunconfiguration.cpp
@@ -90,9 +90,10 @@ public:
return !tis.isEmpty();
}
- virtual bool filterTarget(const TargetInformation &ti) const
+ virtual bool filterTarget(Target *target, const TargetInformation &ti) const
{
- return !ti.manifest.supportsDebugging();
+ return !ti.manifest.supportsDebugging() ||
+ DeviceKitAspect::device(target->kit())->osType() != OsType::OsTypeLinux;
}
QList<RunConfigurationCreationInfo> availableCreators(Target *target) const
@@ -102,8 +103,8 @@ public:
Qt::UniqueConnection);
const auto buildTargets = TargetInformation::readFromProject(target);
- const auto filteredTargets = Utils::filtered(buildTargets, [this](const TargetInformation &ti){
- return filterTarget(ti);
+ const auto filteredTargets = Utils::filtered(buildTargets, [this, target](const TargetInformation &ti) {
+ return filterTarget(target, ti);
});
auto result = Utils::transform(filteredTargets, [this, target](const TargetInformation &ti) {
@@ -143,9 +144,9 @@ public:
addSupportedTargetDeviceType(Qdb::Constants::QdbLinuxOsType);
}
- virtual bool filterTarget(const TargetInformation &ti) const final
+ virtual bool filterTarget(Target *target, const TargetInformation &ti) const final
{
- return ti.manifest.supportsDebugging();
+ return !AppManagerRunConfigurationFactory::filterTarget(target, ti);
}
};
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index 23a947c45f..399efc3a1c 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -382,9 +382,14 @@ QString QtVersion::defaultUnexpandedDisplayName() const
}
}
- return detectionSource() == "PATH" ?
- Tr::tr("Qt %{Qt:Version} in PATH (%2)").arg(location) :
- Tr::tr("Qt %{Qt:Version} (%2)").arg(location);
+ QString result = detectionSource() == "PATH"
+ ? Tr::tr("Qt %{Qt:Version} in PATH (%2)").arg(location)
+ : Tr::tr("Qt %{Qt:Version} (%2)").arg(location);
+
+ if (qmakeFilePath().needsDevice())
+ result += QString(Tr::tr(" (on %1)")).arg(qmakeFilePath().host().toString());
+
+ return result;
}
QSet<Id> QtVersion::availableFeatures() const
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index a835ef30be..b166b702d3 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -21,12 +21,15 @@
#include <projectexplorer/devicesupport/processlist.h>
#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/devicesupport/sshsettings.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
+#include <utils/async.h>
#include <utils/devicefileaccess.h>
#include <utils/deviceshell.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
+#include <utils/infobar.h>
#include <utils/port.h>
#include <utils/portlist.h>
#include <utils/process.h>
@@ -292,6 +295,8 @@ public:
Environment deviceEnvironment() const override;
+ bool disconnected() const override;
+
LinuxDevicePrivate *m_dev;
};
@@ -307,7 +312,7 @@ public:
explicit LinuxDevicePrivate(LinuxDevice *parent);
~LinuxDevicePrivate();
- bool setupShell();
+ bool setupShell(const SshParameters &sshParameters);
RunResult runInShell(const CommandLine &cmd, const QByteArray &stdInData = {});
void attachToSharedConnection(SshConnectionHandle *connectionHandle,
@@ -319,6 +324,10 @@ public:
void checkOsType();
void queryOsType(std::function<RunResult(const CommandLine &)> run);
+ void setDisconnected(bool disconnected);
+ bool disconnected() const;
+ bool checkDisconnectedWithWarning();
+
LinuxDevice *q = nullptr;
QThread m_shellThread;
ShellThreadHandler *m_handler = nullptr;
@@ -327,6 +336,7 @@ public:
QReadWriteLock m_environmentCacheLock;
std::optional<Environment> m_environmentCache;
+ bool m_disconnected = false;
};
void LinuxDevicePrivate::invalidateEnvironmentCache()
@@ -358,14 +368,24 @@ Environment LinuxDevicePrivate::getEnvironment()
RunResult LinuxDeviceFileAccess::runInShell(const CommandLine &cmdLine,
const QByteArray &stdInData) const
{
+ if (disconnected())
+ return {-1, {}, Tr::tr("Device is disconnected.").toUtf8()};
return m_dev->runInShell(cmdLine, stdInData);
}
Environment LinuxDeviceFileAccess::deviceEnvironment() const
{
+ if (disconnected())
+ return {};
+
return m_dev->getEnvironment();
}
+bool LinuxDeviceFileAccess::disconnected() const
+{
+ return m_dev->checkDisconnectedWithWarning();
+}
+
// SshProcessImpl
class SshProcessInterfacePrivate : public QObject
@@ -987,7 +1007,7 @@ LinuxDevice::LinuxDevice()
setOpenTerminal([this](const Environment &env,
const FilePath &workingDir) -> expected_str<void> {
- Process proc;
+ Process *proc = new Process;
// If we will not set any environment variables, we can leave out the shell executable
// as the "ssh ..." call will automatically launch the default shell if there are
@@ -995,11 +1015,19 @@ LinuxDevice::LinuxDevice()
// specify the shell executable.
const QString shell = env.hasChanges() ? env.value_or("SHELL", "/bin/sh") : QString();
- proc.setCommand({filePath(shell), {}});
- proc.setTerminalMode(TerminalMode::Detached);
- proc.setEnvironment(env);
- proc.setWorkingDirectory(workingDir);
- proc.start();
+ proc->setCommand({filePath(shell), {}});
+ proc->setTerminalMode(TerminalMode::Run);
+ proc->setEnvironment(env);
+ proc->setWorkingDirectory(workingDir);
+ proc->start();
+
+ QObject::connect(proc, &Process::done, proc, [proc](){
+ if (proc->exitCode() != 0){
+ qCWarning(linuxDeviceLog) << proc->exitMessage();
+ Core::MessageManager::writeFlashing(proc->exitMessage());
+ }
+ proc->deleteLater();
+ });
return {};
});
@@ -1023,6 +1051,15 @@ LinuxDevice::~LinuxDevice()
delete d;
}
+IDevice::Ptr LinuxDevice::clone() const
+{
+ IDevice::Ptr clone = IDevice::clone();
+ Ptr linuxClone = std::dynamic_pointer_cast<LinuxDevice>(clone);
+ QTC_ASSERT(linuxClone, return clone);
+ linuxClone->d->setDisconnected(d->disconnected());
+ return clone;
+}
+
IDeviceWidget *LinuxDevice::createWidget()
{
return new Internal::GenericLinuxDeviceConfigurationWidget(shared_from_this());
@@ -1106,15 +1143,31 @@ void LinuxDevicePrivate::queryOsType(std::function<RunResult(const CommandLine &
q->_setOsType(OsTypeLinux);
}
+void LinuxDevicePrivate::setDisconnected(bool disconnected)
+{
+ if (disconnected == m_disconnected)
+ return;
+
+ m_disconnected = disconnected;
+
+ if (m_disconnected)
+ m_handler->closeShell();
+
+}
+
+bool LinuxDevicePrivate::disconnected() const
+{
+ return m_disconnected;
+}
+
void LinuxDevicePrivate::checkOsType()
{
queryOsType([this](const CommandLine &cmd) { return runInShell(cmd); });
}
// Call me with shell mutex locked
-bool LinuxDevicePrivate::setupShell()
+bool LinuxDevicePrivate::setupShell(const SshParameters &sshParameters)
{
- const SshParameters sshParameters = q->sshParameters();
if (m_handler->isRunning(sshParameters))
return true;
@@ -1126,8 +1179,12 @@ bool LinuxDevicePrivate::setupShell()
}, Qt::BlockingQueuedConnection, &ok);
if (ok) {
+ setDisconnected(false);
queryOsType([this](const CommandLine &cmd) { return m_handler->runInShell(cmd); });
+ } else {
+ setDisconnected(true);
}
+
return ok;
}
@@ -1135,11 +1192,43 @@ RunResult LinuxDevicePrivate::runInShell(const CommandLine &cmd, const QByteArra
{
QMutexLocker locker(&m_shellMutex);
DEBUG(cmd.toUserOutput());
- const bool isSetup = setupShell();
+ if (checkDisconnectedWithWarning())
+ return {};
+ const bool isSetup = setupShell(q->sshParameters());
+ if (checkDisconnectedWithWarning())
+ return {};
QTC_ASSERT(isSetup, return {});
return m_handler->runInShell(cmd, data);
}
+bool LinuxDevicePrivate::checkDisconnectedWithWarning()
+{
+ if (!disconnected())
+ return false;
+
+ QMetaObject::invokeMethod(Core::ICore::infoBar(), [id = q->id(), name = q->displayName()] {
+ if (!Core::ICore::infoBar()->canInfoBeAdded(id))
+ return;
+ const QString warnStr
+ = Tr::tr("Device \"%1\" is currently marked as disconnected.").arg(name);
+ InfoBarEntry info(id, warnStr, InfoBarEntry::GlobalSuppression::Enabled);
+ info.setDetailsWidgetCreator([] {
+ const auto label = new QLabel(Tr::tr(
+ "The device was not available when trying to connect previously.<br>"
+ "No further connection attempts will be made until the device is manually reset "
+ "by running a successful connection test via the "
+ "<a href=\"dummy\">settings page</a>."));
+ label->setWordWrap(true);
+ QObject::connect(label, &QLabel::linkActivated, [] {
+ Core::ICore::showOptionsDialog(ProjectExplorer::Constants::DEVICE_SETTINGS_PAGE_ID);
+ });
+ return label;
+ });
+ Core::ICore::infoBar()->addInfo(info);
+ });
+ return true;
+}
+
void LinuxDevicePrivate::attachToSharedConnection(SshConnectionHandle *connectionHandle,
const SshParameters &sshParameters)
{
@@ -1522,6 +1611,37 @@ void LinuxDevice::checkOsType()
d->checkOsType();
}
+IDevice::DeviceState LinuxDevice::deviceState() const
+{
+ if (isDisconnected())
+ return DeviceDisconnected;
+ return IDevice::deviceState();
+}
+
+QString LinuxDevice::deviceStateToString() const
+{
+ if (isDisconnected())
+ return Tr::tr("Device is considered unconnected. Re-run device test to reset state.");
+ return IDevice::deviceStateToString();
+}
+
+bool LinuxDevice::isDisconnected() const
+{
+ return d->disconnected();
+}
+void LinuxDevice::setDisconnected(bool disconnected)
+{
+ d->setDisconnected(disconnected);
+}
+
+QFuture<bool> LinuxDevice::tryToConnect()
+{
+ return Utils::asyncRun([this] {
+ QMutexLocker locker(&d->m_shellMutex);
+ return d->setupShell(sshParameters());
+ });
+}
+
namespace Internal {
class LinuxDeviceFactory final : public IDeviceFactory
diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h
index a6625cdea2..0bb2468eac 100644
--- a/src/plugins/remotelinux/linuxdevice.h
+++ b/src/plugins/remotelinux/linuxdevice.h
@@ -20,6 +20,8 @@ public:
static Ptr create() { return Ptr(new LinuxDevice); }
+ IDevice::Ptr clone() const override;
+
ProjectExplorer::IDeviceWidget *createWidget() override;
bool canCreateProcessModel() const override { return true; }
@@ -42,6 +44,14 @@ public:
class LinuxDevicePrivate *connectionAccess() const;
void checkOsType() override;
+ DeviceState deviceState() const override;
+ QString deviceStateToString() const override;
+
+ bool isDisconnected() const;
+ void setDisconnected(bool disconnected);
+
+ QFuture<bool> tryToConnect();
+
protected:
LinuxDevice();
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 3d6c41cd65..f279bc0c38 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -3,6 +3,7 @@
#include "linuxdevicetester.h"
+#include "linuxdevice.h"
#include "remotelinuxtr.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
@@ -17,6 +18,8 @@
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
+#include <QFutureWatcher>
+
using namespace ProjectExplorer;
using namespace Tasking;
using namespace Utils;
@@ -43,9 +46,13 @@ public:
const Storage<TransferStorage> &storage) const;
GroupItem transferTasks() const;
GroupItem commandTasks() const;
+ void runCommandTests();
+
+ bool isRunning() const { return m_connectionTest || m_taskTreeRunner.isRunning(); }
GenericLinuxDeviceTester *q = nullptr;
- IDevice::Ptr m_device;
+ LinuxDevice::Ptr m_device;
+ QFutureWatcher<bool> *m_connectionTest = nullptr;
TaskTreeRunner m_taskTreeRunner;
QStringList m_extraCommands;
QList<GroupItem> m_extraTests;
@@ -276,6 +283,20 @@ GroupItem GenericLinuxDeviceTesterPrivate::commandTasks() const
return root;
}
+void GenericLinuxDeviceTesterPrivate::runCommandTests()
+{
+ const Group root {
+ echoTask("Hello"), // No quoting necessary
+ echoTask("Hello Remote World!"), // Checks quoting, too.
+ unameTask(),
+ gathererTask(),
+ transferTasks(),
+ m_extraTests,
+ commandTasks()
+ };
+ m_taskTreeRunner.start(root);
+}
+
} // namespace Internal
using namespace Internal;
@@ -302,26 +323,40 @@ void GenericLinuxDeviceTester::setExtraTests(const QList<GroupItem> &extraTests)
void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguration)
{
- QTC_ASSERT(!d->m_taskTreeRunner.isRunning(), return);
+ QTC_ASSERT(!d->isRunning(), return);
- d->m_device = deviceConfiguration;
+ emit progressMessage(Tr::tr("Connecting to device..."));
- const Group root {
- d->echoTask("Hello"), // No quoting necessary
- d->echoTask("Hello Remote World!"), // Checks quoting, too.
- d->unameTask(),
- d->gathererTask(),
- d->transferTasks(),
- d->m_extraTests,
- d->commandTasks()
- };
- d->m_taskTreeRunner.start(root);
+ d->m_device = std::static_pointer_cast<LinuxDevice>(deviceConfiguration);
+
+ d->m_connectionTest = new QFutureWatcher<bool>(this);
+ d->m_connectionTest->setFuture(d->m_device->tryToConnect());
+
+ connect(d->m_connectionTest, &QFutureWatcher<bool>::finished, this, [this] {
+ const bool success = d->m_connectionTest->result();
+ d->m_connectionTest->deleteLater();
+ d->m_connectionTest = nullptr;
+ if (success) {
+ emit progressMessage(Tr::tr("Connected. Now doing extended checks.\n"));
+ d->runCommandTests();
+ } else {
+ emit errorMessage(
+ Tr::tr("Basic connectivity test failed, device is considered unusable."));
+ emit finished(TestFailure);
+ }
+ });
}
void GenericLinuxDeviceTester::stopTest()
{
- QTC_ASSERT(d->m_taskTreeRunner.isRunning(), return);
- d->m_taskTreeRunner.reset();
+ QTC_ASSERT(d->isRunning(), return);
+ if (d->m_connectionTest) {
+ d->m_connectionTest->disconnect();
+ d->m_connectionTest->cancel();
+ d->m_connectionTest = nullptr;
+ } else {
+ d->m_taskTreeRunner.reset();
+ }
emit finished(TestFailure);
}
diff --git a/src/plugins/squish/squishnavigationwidget.cpp b/src/plugins/squish/squishnavigationwidget.cpp
index 95f37c67ea..7921938c37 100644
--- a/src/plugins/squish/squishnavigationwidget.cpp
+++ b/src/plugins/squish/squishnavigationwidget.cpp
@@ -47,6 +47,7 @@ private:
void onRowsInserted(const QModelIndex &parent, int, int);
void onRowsRemoved(const QModelIndex &parent, int, int);
void onAddSharedFileTriggered(const QModelIndex &idx);
+ void onRemoveSharedFileTriggered(const QModelIndex &idx);
void onRemoveSharedFolderTriggered(int row, const QModelIndex &parent);
void onRemoveAllSharedFolderTriggered();
void onRecordTestCase(const QString &suiteName, const QString &testCase);
@@ -161,6 +162,9 @@ void SquishNavigationWidget::contextMenuEvent(QContextMenuEvent *event)
case SquishTestTreeItem::SquishSharedFile: {
QAction *deleteSharedFile = new QAction(Tr::tr("Delete Shared File"), &menu);
menu.addAction(deleteSharedFile);
+ connect(deleteSharedFile, &QAction::triggered, this, [this, idx] {
+ onRemoveSharedFileTriggered(idx);
+ });
break;
}
case SquishTestTreeItem::SquishSharedFolder: {
@@ -325,6 +329,31 @@ void SquishNavigationWidget::onAddSharedFileTriggered(const QModelIndex &idx)
m_view->edit(m_sortModel->mapFromSource(added));
}
+void SquishNavigationWidget::onRemoveSharedFileTriggered(const QModelIndex &idx)
+{
+ const auto scriptFile = FilePath::fromVariant(idx.data(LinkRole));
+ QTC_ASSERT(!scriptFile.isEmpty(), return);
+
+ const QString detail = Tr::tr("Do you really want to delete \"%1\" permanently?")
+ .arg(scriptFile.toUserOutput());
+ const QMessageBox::StandardButton pressed
+ = CheckableMessageBox::question(Core::ICore::dialogParent(),
+ Tr::tr("Remove Shared File"),
+ detail,
+ Key("RemoveSharedSquishScript"));
+ if (pressed != QMessageBox::Yes)
+ return;
+
+ const QModelIndex &realIdx = m_sortModel->mapToSource(idx);
+ // close document silently if open
+ if (Core::IDocument *doc = Core::DocumentModel::documentForFilePath(scriptFile))
+ Core::EditorManager::closeDocuments({doc}, false);
+ if (scriptFile.removeFile())
+ m_model->removeTreeItem(realIdx.row(), realIdx.parent());
+ else
+ SquishMessages::criticalMessage(Tr::tr("Failed to remove \"%1\"."));
+}
+
void SquishNavigationWidget::onRemoveSharedFolderTriggered(int row, const QModelIndex &parent)
{
const auto folder = Utils::FilePath::fromVariant(m_sortModel->index(row, 0, parent).data(LinkRole));
diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp
index 4f378731d4..e30abd5bc8 100644
--- a/src/plugins/subversion/subversionclient.cpp
+++ b/src/plugins/subversion/subversionclient.cpp
@@ -57,7 +57,7 @@ bool SubversionClient::doCommit(const FilePath &repositoryRoot,
const QString &commitMessageFile,
const QStringList &extraOptions) const
{
- CommandLine args{vcsBinary()};
+ CommandLine args{vcsBinary(repositoryRoot)};
args << vcsCommandString(CommitCommand)
<< extraOptions
<< AddAuthOptions()
@@ -117,7 +117,7 @@ QString SubversionClient::synchronousTopic(const FilePath &repository) const
{
QStringList args;
- QString svnVersionBinary = vcsBinary().toString();
+ QString svnVersionBinary = vcsBinary(repository).toString();
int pos = svnVersionBinary.lastIndexOf('/');
if (pos < 0)
svnVersionBinary.clear();
@@ -237,7 +237,7 @@ SubversionDiffEditorController *SubversionClient::findOrCreateDiffEditor(const Q
if (!controller) {
controller = new SubversionDiffEditorController(document);
controller->setVcsBinary(settings().binaryPath());
- controller->setProcessEnvironment(processEnvironment());
+ controller->setProcessEnvironment(processEnvironment(workingDirectory));
controller->setWorkingDirectory(workingDirectory);
}
VcsBase::setSource(document, source);
diff --git a/src/plugins/subversion/subversionconstants.h b/src/plugins/subversion/subversionconstants.h
index b0d6ce8f45..2b834ed64a 100644
--- a/src/plugins/subversion/subversionconstants.h
+++ b/src/plugins/subversion/subversionconstants.h
@@ -3,10 +3,7 @@
#pragma once
-#include <QtGlobal>
-
-namespace Subversion {
-namespace Constants {
+namespace Subversion::Constants {
const char SUBVERSION_PLUGIN[] = "SubversionPlugin";
@@ -16,16 +13,12 @@ enum { debug = 0 };
const char SUBVERSION_CONTEXT[] = "Subversion Context";
const char SUBVERSION_COMMIT_EDITOR_ID[] = "Subversion Commit Editor";
-const char SUBVERSION_COMMIT_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Subversion Commit Editor");
const char SUBVERSION_SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.svn.submit";
const char SUBVERSION_LOG_EDITOR_ID[] = "Subversion File Log Editor";
-const char SUBVERSION_LOG_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Subversion File Log Editor");
const char SUBVERSION_LOG_MIMETYPE[] = "text/vnd.qtcreator.svn.log";
const char SUBVERSION_BLAME_EDITOR_ID[] = "Subversion Annotation Editor";
-const char SUBVERSION_BLAME_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::VcsBase", "Subversion Annotation Editor");
const char SUBVERSION_BLAME_MIMETYPE[] = "text/vnd.qtcreator.svn.annotation";
-} // namespace Constants
-} // namespace Subversion
+} // Subversion::Constants
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index c70df10640..fc9d5ed122 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -36,6 +36,7 @@
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbaseplugin.h>
+#include <vcsbase/vcsbasetr.h>
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
@@ -85,20 +86,6 @@ const char CMD_ID_UPDATE[] = "Subversion.Update";
const char CMD_ID_COMMIT_PROJECT[] = "Subversion.CommitProject";
const char CMD_ID_DESCRIBE[] = "Subversion.Describe";
-const VcsBaseEditorParameters logEditorParameters {
- LogOutput,
- Constants::SUBVERSION_LOG_EDITOR_ID,
- Constants::SUBVERSION_LOG_EDITOR_DISPLAY_NAME,
- Constants::SUBVERSION_LOG_MIMETYPE
-};
-
-const VcsBaseEditorParameters blameEditorParameters {
- AnnotateOutput,
- Constants::SUBVERSION_BLAME_EDITOR_ID,
- Constants::SUBVERSION_BLAME_EDITOR_DISPLAY_NAME,
- Constants::SUBVERSION_BLAME_MIMETYPE
-};
-
static inline QString debugCodec(const QTextCodec *c)
{
return c ? QString::fromLatin1(c->name()) : QString::fromLatin1("Null codec");
@@ -139,24 +126,6 @@ static inline QStringList svnDirectories()
return rc;
}
-class SubversionPluginPrivate;
-
-class SubversionTopicCache : public Core::IVersionControl::TopicCache
-{
-public:
- SubversionTopicCache(SubversionPluginPrivate *plugin) :
- m_plugin(plugin)
- { }
-
-protected:
- FilePath trackFile(const FilePath &repository) override;
-
- QString refreshTopic(const FilePath &repository) override;
-
-private:
- SubversionPluginPrivate *m_plugin;
-};
-
class SubversionPluginPrivate final : public VcsBase::VersionControlBase
{
public:
@@ -276,17 +245,23 @@ private:
QAction *m_menuAction = nullptr;
public:
- VcsEditorFactory logEditorFactory {
- &logEditorParameters,
+ VcsEditorFactory logEditorFactory {{
+ LogOutput,
+ Constants::SUBVERSION_LOG_EDITOR_ID,
+ VcsBase::Tr::tr("Subversion File Log Editor"),
+ Constants::SUBVERSION_LOG_MIMETYPE,
[] { return new SubversionEditorWidget; },
std::bind(&SubversionPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
- VcsEditorFactory blameEditorFactory {
- &blameEditorParameters,
+ VcsEditorFactory blameEditorFactory {{
+ AnnotateOutput,
+ Constants::SUBVERSION_BLAME_EDITOR_ID,
+ VcsBase::Tr::tr("Subversion Annotation Editor"),
+ Constants::SUBVERSION_BLAME_MIMETYPE,
[] { return new SubversionEditorWidget; },
std::bind(&SubversionPluginPrivate::vcsDescribe, this, _1, _2)
- };
+ }};
};
@@ -319,7 +294,12 @@ SubversionPluginPrivate::SubversionPluginPrivate()
{
dd = this;
- setTopicCache(new SubversionTopicCache(this));
+ setTopicFileTracker([this](const FilePath &repository) {
+ return FilePath::fromString(monitorFile(repository));
+ });
+ setTopicRefresher([this](const FilePath &repository) {
+ return synchronousTopic(repository);
+ });
using namespace Constants;
using namespace Core::Constants;
@@ -488,7 +468,7 @@ SubversionPluginPrivate::SubversionPluginPrivate()
setupVcsSubmitEditor(this, {
Constants::SUBVERSION_SUBMIT_MIMETYPE,
Constants::SUBVERSION_COMMIT_EDITOR_ID,
- Constants::SUBVERSION_COMMIT_EDITOR_DISPLAY_NAME,
+ VcsBase::Tr::tr("Subversion Commit Editor"),
VcsBaseSubmitEditorParameters::DiffFiles,
[] { return new SubversionSubmitEditor; },
});
@@ -853,7 +833,7 @@ void SubversionPluginPrivate::vcsAnnotateHelper(const FilePath &workingDir, cons
} else {
const QString title = QString::fromLatin1("svn annotate %1").arg(id);
IEditor *newEditor = showOutputInEditor(title, response.cleanedStdOut(),
- blameEditorParameters.id, source, codec);
+ Constants::SUBVERSION_BLAME_EDITOR_ID, source, codec);
VcsBaseEditor::tagEditor(newEditor, tag);
VcsBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
}
@@ -1155,21 +1135,13 @@ VcsCommand *SubversionPluginPrivate::createInitialCheckoutCommand(const QString
args << SubversionClient::AddAuthOptions();
args << Subversion::Constants::NON_INTERACTIVE_OPTION << extraArgs << url << localName;
- auto command = VcsBaseClient::createVcsCommand(baseDirectory, subversionClient().processEnvironment());
+ auto command = VcsBaseClient::createVcsCommand(baseDirectory,
+ subversionClient().processEnvironment(
+ baseDirectory));
command->addJob(args, -1);
return command;
}
-FilePath SubversionTopicCache::trackFile(const FilePath &repository)
-{
- return FilePath::fromString(m_plugin->monitorFile(repository));
-}
-
-QString SubversionTopicCache::refreshTopic(const FilePath &repository)
-{
- return m_plugin->synchronousTopic(repository);
-}
-
#ifdef WITH_TESTS
diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp
index 111e6d2d99..1648638713 100644
--- a/src/plugins/terminal/terminalpane.cpp
+++ b/src/plugins/terminal/terminalpane.cpp
@@ -106,6 +106,18 @@ void TerminalPane::openTerminal(const OpenTerminalParameters &parameters)
}
}
+ if (parametersCopy.workingDirectory && parametersCopy.workingDirectory->needsDevice()
+ && !parametersCopy.shellCommand) {
+ const FilePath shell = parametersCopy.workingDirectory->withNewPath(
+ parametersCopy.environment
+ .value_or(parametersCopy.workingDirectory->deviceEnvironment())
+ .value_or("SHELL", "/bin/sh"));
+ if (!shell.isExecutableFile())
+ parametersCopy.workingDirectory.reset();
+ else
+ parametersCopy.shellCommand = CommandLine{shell, {}};
+ }
+
const auto terminalWidget = new TerminalWidget(&m_tabWidget, parametersCopy);
using namespace Constants;
diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.h b/src/plugins/texteditor/codeassist/genericproposalmodel.h
index 610fab1a1f..3107fae0d3 100644
--- a/src/plugins/texteditor/codeassist/genericproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/genericproposalmodel.h
@@ -45,6 +45,7 @@ public:
virtual int indexOf(const std::function<bool (AssistProposalItemInterface *)> &predicate) const;
void loadContent(const QList<AssistProposalItemInterface *> &items);
+ const QList<AssistProposalItemInterface *> &originalItems() const { return m_originalItems; }
bool isPerfectMatch(const QString &prefix) const;
bool hasItemsToPropose(const QString &prefix, AssistReason reason) const;
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index e46c5b7c5b..b5435ed5e9 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -98,7 +98,7 @@ public:
visualizeWhitespace = new QCheckBox(Tr::tr("&Visualize whitespace"));
visualizeWhitespace->setToolTip(Tr::tr("Shows tabs and spaces."));
- highlightSelection = new QCheckBox(Tr::tr("&Highlight Selection"));
+ highlightSelection = new QCheckBox(Tr::tr("&Highlight selection"));
highlightSelection->setToolTip(Tr::tr("Adds a colored background and a marker to the "
"scrollbar to occurrences of the selected text."));
diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp
index 8c9cc19437..0ed00af389 100644
--- a/src/plugins/texteditor/syntaxhighlighter.cpp
+++ b/src/plugins/texteditor/syntaxhighlighter.cpp
@@ -60,7 +60,6 @@ public:
QList<QTextCharFormat> formats;
QList<std::pair<int,TextStyle>> formatCategories;
QTextCharFormat whitespaceFormat;
- bool noAutomaticHighlighting = false;
QString mimeType;
};
@@ -345,12 +344,11 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
d->doc = doc;
documentChanged(oldDoc, d->doc);
if (d->doc) {
- if (!d->noAutomaticHighlighting) {
- connect(d->doc, &QTextDocument::contentsChange, this, &SyntaxHighlighter::reformatBlocks);
- d->rehighlightPending = true;
- QMetaObject::invokeMethod(this, &SyntaxHighlighter::delayedRehighlight,
- Qt::QueuedConnection);
- }
+ connect(d->doc, &QTextDocument::contentsChange, this, &SyntaxHighlighter::reformatBlocks);
+ d->rehighlightPending = true;
+ QMetaObject::invokeMethod(this,
+ &SyntaxHighlighter::delayedRehighlight,
+ Qt::QueuedConnection);
d->foldValidator.setup(qobject_cast<TextDocumentLayout *>(doc->documentLayout()));
}
}
@@ -846,15 +844,6 @@ FontSettings SyntaxHighlighter::fontSettings() const
Q_D(const SyntaxHighlighter);
return d->fontSettings;
}
-/*!
- The syntax highlighter is not anymore reacting to the text document if \a noAutomatic is
- \c true.
-*/
-void SyntaxHighlighter::setNoAutomaticHighlighting(bool noAutomatic)
-{
- Q_D(SyntaxHighlighter);
- d->noAutomaticHighlighting = noAutomatic;
-}
/*!
Creates text format categories for the text styles themselves, so the highlighter can
diff --git a/src/plugins/texteditor/syntaxhighlighter.h b/src/plugins/texteditor/syntaxhighlighter.h
index dbd57a4588..94cee8a65e 100644
--- a/src/plugins/texteditor/syntaxhighlighter.h
+++ b/src/plugins/texteditor/syntaxhighlighter.h
@@ -53,8 +53,6 @@ public:
virtual void setFontSettings(const TextEditor::FontSettings &fontSettings);
TextEditor::FontSettings fontSettings() const;
- void setNoAutomaticHighlighting(bool noAutomatic);
-
enum State {
InProgress,
Done
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.cpp b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
index 0d5e32893e..bf53d90561 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.cpp
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
@@ -27,26 +27,22 @@ class SyntaxHighlighterRunnerPrivate : public QObject
{
Q_OBJECT
public:
- SyntaxHighlighterRunnerPrivate(SyntaxHighlighterRunner::SyntaxHighlighterCreator creator,
+ SyntaxHighlighterRunnerPrivate(SyntaxHighlighter *highlighter,
QTextDocument *document,
- bool async,
- const QString &mimeType,
- FontSettings fontSettings)
+ bool async)
+ : m_highlighter(highlighter)
{
if (async) {
m_document = new QTextDocument(this);
m_document->setDocumentLayout(new TextDocumentLayout(m_document));
+ m_highlighter->setParent(m_document);
} else {
m_document = document;
}
- m_highlighter.reset(creator());
- m_highlighter->setFontSettings(fontSettings);
m_highlighter->setDocument(m_document);
- m_highlighter->setMimeType(mimeType);
- m_highlighter->setParent(m_document);
- connect(m_highlighter.get(),
+ connect(m_highlighter,
&SyntaxHighlighter::resultsReady,
this,
&SyntaxHighlighterRunnerPrivate::resultsReady);
@@ -102,7 +98,7 @@ public:
void rehighlight() { m_highlighter->rehighlight(); }
- std::unique_ptr<SyntaxHighlighter> m_highlighter;
+ SyntaxHighlighter *m_highlighter = nullptr;
QTextDocument *m_document = nullptr;
signals:
@@ -110,15 +106,13 @@ signals:
};
-SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighterCreator creator,
+SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
QTextDocument *document,
- bool async,
- const QString &mimeType,
- const TextEditor::FontSettings &fontSettings)
- : d(new SyntaxHighlighterRunnerPrivate(creator, document, async, mimeType, fontSettings))
+ bool async)
+ : d(new SyntaxHighlighterRunnerPrivate(highlighter, document, async))
, m_document(document)
{
- m_useGenericHighlighter = qobject_cast<Highlighter *>(d->m_highlighter.get());
+ m_useGenericHighlighter = qobject_cast<Highlighter *>(d->m_highlighter);
if (async) {
m_thread.emplace();
@@ -163,6 +157,7 @@ SyntaxHighlighterRunner::~SyntaxHighlighterRunner()
m_thread->quit();
m_thread->wait();
} else {
+ delete d->m_highlighter;
delete d;
}
}
@@ -185,7 +180,7 @@ void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::R
result.copyToBlock(docBlock);
- if (!result.m_formatRanges.empty()) {
+ if (result.m_formatRanges != docBlock.layout()->formats()) {
TextDocumentLayout::FoldValidator foldValidator;
foldValidator.setup(qobject_cast<TextDocumentLayout *>(m_document->documentLayout()));
docBlock.layout()->setFormats(result.m_formatRanges);
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.h b/src/plugins/texteditor/syntaxhighlighterrunner.h
index 7202ebf401..ccb292ea08 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.h
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.h
@@ -24,12 +24,7 @@ class TEXTEDITOR_EXPORT SyntaxHighlighterRunner : public QObject
public:
using SyntaxHighlighterCreator = std::function<SyntaxHighlighter *()>;
- SyntaxHighlighterRunner(
- SyntaxHighlighterCreator creator,
- QTextDocument *document,
- bool async,
- const QString &mimeType,
- const TextEditor::FontSettings &fontSettings = TextEditorSettings::fontSettings());
+ SyntaxHighlighterRunner(SyntaxHighlighter *highlighter, QTextDocument *document, bool async);
virtual ~SyntaxHighlighterRunner();
void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formats);
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index a60c729ed4..cb421f2bf7 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -921,10 +921,12 @@ void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter
= qtcEnvironmentVariable("QTC_USE_THREADED_HIGHLIGHTER", "TRUE").toUpper()
== QLatin1String("TRUE");
- d->m_highlighterRunner = new SyntaxHighlighterRunner(creator,
+ SyntaxHighlighter *highlighter = creator();
+ highlighter->setFontSettings(TextEditorSettings::fontSettings());
+ highlighter->setMimeType(mimeType());
+ d->m_highlighterRunner = new SyntaxHighlighterRunner(highlighter,
document(),
- threaded && envValue,
- mimeType());
+ threaded && envValue);
}
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 1184749e86..c8ef69c63e 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -25,7 +25,6 @@
#include "refactoroverlay.h"
#include "snippets/snippetoverlay.h"
#include "storagesettings.h"
-#include "syntaxhighlighter.h"
#include "tabsettings.h"
#include "textdocument.h"
#include "textdocumentlayout.h"
@@ -9425,7 +9424,7 @@ public:
TextEditorFactory::SyntaxHighLighterCreator m_syntaxHighlighterCreator;
CommentDefinition m_commentDefinition;
QList<BaseHoverHandler *> m_hoverHandlers; // owned
- CompletionAssistProvider * m_completionAssistProvider = nullptr; // owned
+ std::unique_ptr<CompletionAssistProvider> m_completionAssistProvider; // owned
std::unique_ptr<TextEditorActionHandler> m_textEditorActionHandler;
bool m_useGenericHighlighter = false;
bool m_duplicatedSupported = true;
@@ -9445,7 +9444,6 @@ TextEditorFactory::TextEditorFactory()
TextEditorFactory::~TextEditorFactory()
{
qDeleteAll(d->m_hoverHandlers);
- delete d->m_completionAssistProvider;
delete d;
}
@@ -9472,8 +9470,9 @@ void TextEditorFactory::setEditorCreator(const EditorCreator &creator)
if (d->m_syntaxHighlighterCreator)
doc->resetSyntaxHighlighter(d->m_syntaxHighlighterCreator);
- doc->setCompletionAssistProvider(d->m_completionAssistProvider ? d->m_completionAssistProvider
- : &basicSnippetProvider);
+ doc->setCompletionAssistProvider(d->m_completionAssistProvider
+ ? d->m_completionAssistProvider.get()
+ : &basicSnippetProvider);
return d->createEditorHelper(doc);
});
@@ -9511,7 +9510,7 @@ void TextEditorFactory::addHoverHandler(BaseHoverHandler *handler)
void TextEditorFactory::setCompletionAssistProvider(CompletionAssistProvider *provider)
{
- d->m_completionAssistProvider = provider;
+ d->m_completionAssistProvider.reset(provider);
}
void TextEditorFactory::setCommentDefinition(CommentDefinition definition)
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index ea2ddcadc5..81a816c009 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -61,15 +61,18 @@ VcsBaseClientImpl::VcsBaseClientImpl(VcsBaseSettings *baseSettings)
this, &VcsBaseClientImpl::saveSettings);
}
-FilePath VcsBaseClientImpl::vcsBinary() const
+FilePath VcsBaseClientImpl::vcsBinary(const Utils::FilePath &forDirectory) const
{
+ if (forDirectory.needsDevice())
+ return {};
+
return m_baseSettings->binaryPath();
}
VcsCommand *VcsBaseClientImpl::createCommand(const FilePath &workingDirectory,
VcsBaseEditorWidget *editor) const
{
- auto cmd = createVcsCommand(workingDirectory, processEnvironment());
+ auto cmd = createVcsCommand(workingDirectory, processEnvironment(workingDirectory));
if (editor) {
editor->setCommand(cmd);
connect(cmd, &VcsCommand::done, editor, [editor, cmd] {
@@ -88,24 +91,24 @@ void VcsBaseClientImpl::setupCommand(Utils::Process &process,
const FilePath &workingDirectory,
const QStringList &args) const
{
- process.setEnvironment(processEnvironment());
+ process.setEnvironment(workingDirectory.deviceEnvironment());
process.setWorkingDirectory(workingDirectory);
- process.setCommand({vcsBinary(), args});
+ process.setCommand({vcsBinary(workingDirectory), args});
process.setUseCtrlCStub(true);
}
-void VcsBaseClientImpl::enqueueJob(VcsCommand *cmd, const QStringList &args,
+void VcsBaseClientImpl::enqueueJob(VcsCommand *cmd,
+ const QStringList &args,
+ const Utils::FilePath &forDirectory,
const ExitCodeInterpreter &interpreter) const
{
- cmd->addJob({vcsBinary(), args}, vcsTimeoutS(), {}, interpreter);
+ cmd->addJob({vcsBinary(forDirectory), args}, vcsTimeoutS(), {}, interpreter);
cmd->start();
}
-Environment VcsBaseClientImpl::processEnvironment() const
+Environment VcsBaseClientImpl::processEnvironment(const FilePath &appliedTo) const
{
- Environment environment = Environment::systemEnvironment();
- VcsBase::setProcessEnvironment(&environment);
- return environment;
+ return appliedTo.deviceEnvironment();
}
QStringList VcsBaseClientImpl::splitLines(const QString &s)
@@ -129,14 +132,18 @@ QString VcsBaseClientImpl::stripLastNewline(const QString &in)
CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir,
const QStringList &args, RunFlags flags, int timeoutS, QTextCodec *codec) const
{
- return vcsSynchronousExec(workingDir, {vcsBinary(), args}, flags, timeoutS, codec);
+ return vcsSynchronousExec(workingDir, {vcsBinary(workingDir), args}, flags, timeoutS, codec);
}
CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir,
const CommandLine &cmdLine, RunFlags flags, int timeoutS, QTextCodec *codec) const
{
- return VcsCommand::runBlocking(workingDir, processEnvironment(), cmdLine, flags,
- timeoutS > 0 ? timeoutS : vcsTimeoutS(), codec);
+ return VcsCommand::runBlocking(workingDir,
+ processEnvironment(workingDir),
+ cmdLine,
+ flags,
+ timeoutS > 0 ? timeoutS : vcsTimeoutS(),
+ codec);
}
void VcsBaseClientImpl::resetCachedVcsInfo(const FilePath &workingDir)
@@ -166,7 +173,7 @@ void VcsBaseClientImpl::vcsExecWithHandler(const FilePath &workingDirectory,
VcsCommand *command = createCommand(workingDirectory);
command->addFlags(additionalFlags);
command->setCodec(codec);
- command->addJob({vcsBinary(), arguments}, vcsTimeoutS());
+ command->addJob({vcsBinary(workingDirectory), arguments}, vcsTimeoutS());
if (handler) {
const QObject *actualContext = context ? context : this;
connect(command, &VcsCommand::done, actualContext, [command, handler] {
@@ -182,7 +189,7 @@ void VcsBaseClientImpl::vcsExec(const FilePath &workingDirectory,
{
VcsCommand *command = createCommand(workingDirectory);
command->addFlags(additionalFlags);
- command->addJob({vcsBinary(), arguments}, vcsTimeoutS());
+ command->addJob({vcsBinary(workingDirectory), arguments}, vcsTimeoutS());
command->start();
}
@@ -192,7 +199,7 @@ void VcsBaseClientImpl::vcsExecWithEditor(const Utils::FilePath &workingDirector
{
VcsCommand *command = createCommand(workingDirectory, editor);
command->setCodec(editor->codec());
- command->addJob({vcsBinary(), arguments}, vcsTimeoutS());
+ command->addJob({vcsBinary(workingDirectory), arguments}, vcsTimeoutS());
command->start();
}
@@ -350,7 +357,7 @@ void VcsBaseClient::annotate(const Utils::FilePath &workingDir, const QString &f
VcsCommand *cmd = createCommand(workingDir, editor);
editor->setDefaultLineNumber(lineNumber);
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, workingDir);
}
void VcsBaseClient::diff(const FilePath &workingDir, const QStringList &files)
@@ -387,7 +394,7 @@ void VcsBaseClient::diff(const FilePath &workingDir, const QStringList &files)
: VcsBaseEditor::getCodec(source);
VcsCommand *command = createCommand(workingDir, editor);
command->setCodec(codec);
- enqueueJob(command, args, exitCodeInterpreter(DiffCommand));
+ enqueueJob(command, args, workingDir, exitCodeInterpreter(DiffCommand));
}
void VcsBaseClient::log(const FilePath &workingDir,
@@ -421,7 +428,7 @@ void VcsBaseClient::log(const FilePath &workingDir,
}
}
- CommandLine args{vcsBinary(), {vcsCmdString}};
+ CommandLine args{vcsBinary(workingDir), {vcsCmdString}};
if (addAuthOptions)
addAuthOptions(args);
if (editorConfig)
@@ -448,7 +455,7 @@ void VcsBaseClient::revertFile(const FilePath &workingDir,
if (cmd->result() == ProcessResult::FinishedWithSuccess)
emit changed(files);
});
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, workingDir);
}
void VcsBaseClient::revertAll(const FilePath &workingDir,
@@ -464,7 +471,7 @@ void VcsBaseClient::revertAll(const FilePath &workingDir,
if (cmd->result() == ProcessResult::FinishedWithSuccess)
emit changed(files);
});
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, workingDir);
}
void VcsBaseClient::status(const FilePath &workingDir,
@@ -475,7 +482,7 @@ void VcsBaseClient::status(const FilePath &workingDir,
args << extraOptions << file;
VcsCommand *cmd = createCommand(workingDir);
cmd->addFlags(RunFlags::ShowStdOut);
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, workingDir);
}
void VcsBaseClient::emitParsedStatus(const FilePath &repository, const QStringList &extraOptions)
@@ -484,7 +491,7 @@ void VcsBaseClient::emitParsedStatus(const FilePath &repository, const QStringLi
args << extraOptions;
VcsCommand *cmd = createCommand(repository);
connect(cmd, &VcsCommand::done, this, [this, cmd] { statusParser(cmd->cleanedStdOut()); });
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, repository);
}
QString VcsBaseClient::vcsCommandString(VcsCommandTag cmd) const
@@ -525,7 +532,7 @@ void VcsBaseClient::import(const FilePath &repositoryRoot,
{
QStringList args(vcsCommandString(ImportCommand));
args << extraOptions << files;
- enqueueJob(createCommand(repositoryRoot), args);
+ enqueueJob(createCommand(repositoryRoot), args, repositoryRoot);
}
void VcsBaseClient::view(const FilePath &source,
@@ -541,7 +548,7 @@ void VcsBaseClient::view(const FilePath &source,
VcsBaseEditor::getCodec(source), "view", id);
const FilePath workingDirPath = source.isFile() ? source.absolutePath() : source;
- enqueueJob(createCommand(workingDirPath, editor), args);
+ enqueueJob(createCommand(workingDirPath, editor), args, source);
}
void VcsBaseClient::update(const FilePath &repositoryRoot, const QString &revision,
@@ -554,7 +561,7 @@ void VcsBaseClient::update(const FilePath &repositoryRoot, const QString &revisi
if (cmd->result() == ProcessResult::FinishedWithSuccess)
emit changed(repositoryRoot.toString());
});
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, repositoryRoot);
}
void VcsBaseClient::commit(const FilePath &repositoryRoot,
@@ -576,12 +583,12 @@ void VcsBaseClient::commit(const FilePath &repositoryRoot,
cmd->addFlags(RunFlags::ShowStdOut);
if (!commitMessageFile.isEmpty())
connect(cmd, &VcsCommand::done, [commitMessageFile] { QFile(commitMessageFile).remove(); });
- enqueueJob(cmd, args);
+ enqueueJob(cmd, args, repositoryRoot);
}
QString VcsBaseClient::vcsEditorTitle(const QString &vcsCmd, const QString &sourceId) const
{
- return vcsBinary().baseName() + QLatin1Char(' ') + vcsCmd + QLatin1Char(' ')
+ return vcsBinary({}).baseName() + QLatin1Char(' ') + vcsCmd + QLatin1Char(' ')
+ FilePath::fromString(sourceId).fileName();
}
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index f1db56ebeb..99b818b59b 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -41,7 +41,7 @@ public:
explicit VcsBaseClientImpl(VcsBaseSettings *baseSettings);
~VcsBaseClientImpl() override = default;
- virtual Utils::FilePath vcsBinary() const;
+ virtual Utils::FilePath vcsBinary(const Utils::FilePath &forDirectory) const;
int vcsTimeoutS() const;
static VcsCommand *createVcsCommand(const Utils::FilePath &defaultWorkingDir,
@@ -59,10 +59,12 @@ public:
const Utils::FilePath &workingDirectory,
const QStringList &args) const;
- void enqueueJob(VcsCommand *cmd, const QStringList &args,
+ void enqueueJob(VcsCommand *cmd,
+ const QStringList &args,
+ const Utils::FilePath &forDirectory,
const ExitCodeInterpreter &interpreter = {}) const;
- virtual Utils::Environment processEnvironment() const;
+ virtual Utils::Environment processEnvironment(const Utils::FilePath &appliedTo) const;
// VCS functionality:
virtual void annotate(const Utils::FilePath &workingDir, const QString &file,
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 729ee682c4..b10758233a 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -563,7 +563,6 @@ public:
VcsBaseEditorConfig *m_config = nullptr;
QList<AbstractTextCursorHandler *> m_textCursorHandlers;
QPointer<VcsCommand> m_command;
- VcsBaseEditorWidget::DescribeFunc m_describeFunc = nullptr;
ProgressIndicator *m_progressIndicator = nullptr;
bool m_fileLogAnnotateEnabled = false;
bool m_mouseDragging = false;
@@ -723,14 +722,10 @@ int VcsBaseEditorWidget::lineNumberDigits() const
return digits;
}
-void VcsBaseEditorWidget::setDescribeFunc(DescribeFunc describeFunc)
-{
- d->m_describeFunc = describeFunc;
-}
-
void VcsBaseEditorWidget::finalizeInitialization()
{
- connect(this, &VcsBaseEditorWidget::describeRequested, this, d->m_describeFunc);
+ QTC_CHECK(d->m_parameters.describeFunc);
+ connect(this, &VcsBaseEditorWidget::describeRequested, this, d->m_parameters.describeFunc);
init();
}
@@ -1332,7 +1327,7 @@ bool VcsBaseEditor::gotoLineOfEditor(IEditor *e, int lineNumber)
// ('git diff XX' -> 'XX' , 'git diff XX file' -> 'XX/file').
FilePath VcsBaseEditor::getSource(const FilePath &workingDirectory, const QString &fileName)
{
- return workingDirectory.pathAppended(fileName);
+ return workingDirectory.resolvePath(fileName);
}
FilePath VcsBaseEditor::getSource(const FilePath &workingDirectory, const QStringList &fileNames)
@@ -1653,30 +1648,26 @@ IEditor *VcsBaseEditor::locateEditorByTag(const QString &tag)
\sa VcsBase::VcsBaseEditorWidget
*/
-VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters *parameters,
- // Force copy, see QTCREATORBUG-13218
- const EditorWidgetCreator editorWidgetCreator,
- std::function<void (const Utils::FilePath &, const QString &)> describeFunc)
+VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters &parameters)
{
- setId(parameters->id);
- setDisplayName(Tr::tr(parameters->displayName));
- if (QLatin1String(parameters->mimeType) != QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE))
- addMimeType(QLatin1String(parameters->mimeType));
+ setId(parameters.id);
+ setDisplayName(parameters.displayName);
+ if (parameters.mimeType != DiffEditor::Constants::DIFF_EDITOR_MIMETYPE)
+ addMimeType(parameters.mimeType);
setEditorActionHandlers(TextEditorActionHandler::None);
setDuplicatedSupported(false);
setDocumentCreator([parameters] {
- auto document = new TextDocument(parameters->id);
- document->setMimeType(QLatin1String(parameters->mimeType));
+ auto document = new TextDocument(parameters.id);
+ document->setMimeType(parameters.mimeType);
document->setSuspendAllowed(false);
return document;
});
- setEditorWidgetCreator([parameters=*parameters, editorWidgetCreator, describeFunc] {
- auto widget = editorWidgetCreator();
+ setEditorWidgetCreator([parameters] {
+ auto widget = parameters.editorWidgetCreator();
auto editorWidget = Aggregation::query<VcsBaseEditorWidget>(widget);
- editorWidget->setDescribeFunc(describeFunc);
editorWidget->setParameters(parameters);
return widget;
});
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index b2a9a80cb3..04e698f4ea 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -42,9 +42,11 @@ class VCSBASE_EXPORT VcsBaseEditorParameters
{
public:
EditorContentType type;
- const char *id;
- const char *displayName;
- const char *mimeType;
+ Utils::Id id;
+ QString displayName;
+ QString mimeType;
+ std::function<QWidget *()> editorWidgetCreator;
+ std::function<void (const Utils::FilePath &, const QString &)> describeFunc;
};
class VCSBASE_EXPORT DiffChunk
@@ -145,8 +147,6 @@ public:
void finalizeInitialization() override;
// FIXME: Consolidate these into finalizeInitialization
- void setDescribeFunc(DescribeFunc describeFunc);
- // void
virtual void init();
//
void setParameters(const VcsBaseEditorParameters &parameters);
@@ -289,10 +289,7 @@ public:
class VCSBASE_EXPORT VcsEditorFactory : public TextEditor::TextEditorFactory
{
public:
- VcsEditorFactory(const VcsBaseEditorParameters *parameters,
- const EditorWidgetCreator editorWidgetCreator,
- std::function<void(const Utils::FilePath &, const QString &)> describeFunc);
-
+ explicit VcsEditorFactory(const VcsBaseEditorParameters &parameters);
~VcsEditorFactory();
};
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index ee2ea42813..b506f0ed38 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -374,7 +374,7 @@ FilePath VcsBasePluginState::currentFileDirectory() const
QString VcsBasePluginState::relativeCurrentFile() const
{
QTC_ASSERT(hasFile(), return {});
- return data->m_state.currentFile.relativeChildPath(data->m_state.currentFileTopLevel).toString();
+ return data->m_state.currentFile.relativeChildPath(data->m_state.currentFileTopLevel).path();
}
QString VcsBasePluginState::currentPatchFile() const
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index 79dcddc3f9..4c29da91f2 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -147,10 +147,10 @@ void VcsBaseSubmitEditor::setParameters(const VcsBaseSubmitEditorParameters &par
{
d->m_parameters = parameters;
d->m_file.setId(parameters.id);
- d->m_file.setMimeType(QLatin1String(parameters.mimeType));
+ d->m_file.setMimeType(parameters.mimeType);
setWidget(d->m_widget);
- document()->setPreferredDisplayName(Tr::tr(d->m_parameters.displayName));
+ document()->setPreferredDisplayName(d->m_parameters.displayName);
// Message font according to settings
CompletingTextEdit *descriptionEdit = d->m_widget->descriptionEdit();
@@ -643,8 +643,8 @@ public:
.bindContextAction(&diffAction);
setId(parameters.id);
- setDisplayName(QLatin1String(parameters.displayName));
- addMimeType(QLatin1String(parameters.mimeType));
+ setDisplayName(parameters.displayName);
+ addMimeType(parameters.mimeType);
setEditorCreator([parameters, submitAction, diffAction, undoAction, redoAction] {
VcsBaseSubmitEditor *editor = parameters.editorCreator();
editor->setParameters(parameters);
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.h b/src/plugins/vcsbase/vcsbasesubmiteditor.h
index 204ab9b6af..b2eb958a79 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.h
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.h
@@ -28,9 +28,9 @@ class VcsBaseSubmitEditorPrivate;
class VCSBASE_EXPORT VcsBaseSubmitEditorParameters
{
public:
- const char *mimeType;
- const char *id;
- const char *displayName;
+ QString mimeType;
+ Utils::Id id;
+ QString displayName;
enum DiffType { DiffRows, DiffFiles } diffType;
std::function<VcsBaseSubmitEditor *()> editorCreator;
};
diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h
index e9975dcb14..6271139544 100644
--- a/src/plugins/vcsbase/vcscommand.h
+++ b/src/plugins/vcsbase/vcscommand.h
@@ -82,9 +82,11 @@ public:
void setProgressParser(const Core::ProgressParser &parser);
static CommandResult runBlocking(const Utils::FilePath &workingDirectory,
- const Utils::Environment &environmentconst,
- const Utils::CommandLine &command, RunFlags flags,
- int timeoutS, QTextCodec *codec);
+ const Utils::Environment &environment,
+ const Utils::CommandLine &command,
+ RunFlags flags,
+ int timeoutS,
+ QTextCodec *codec);
void cancel();
QString cleanedStdOut() const;
diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp
index fdd91a5ed0..3ad77c9eb0 100644
--- a/src/plugins/vcsbase/vcsoutputwindow.cpp
+++ b/src/plugins/vcsbase/vcsoutputwindow.cpp
@@ -393,7 +393,7 @@ QString VcsOutputWindow::msgExecutionLogEntry(const FilePath &workingDir, const
+ ' ' + formatArguments(command.splitArguments());
if (workingDir.isEmpty())
return Tr::tr("Running: %1").arg(maskedCmdline) + '\n';
- return Tr::tr("Running in \"%1\": %2.").arg(workingDir.toUserOutput(), maskedCmdline) + '\n';
+ return Tr::tr("Running in \"%1\": %2").arg(workingDir.toUserOutput(), maskedCmdline) + '\n';
}
void VcsOutputWindow::appendShellCommandLine(const QString &text)
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index b7161fcb0d..0590823ea6 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -245,7 +245,6 @@ public:
vbox->addItem(newVBox);
auto newLabel = new QLabel(Tr::tr("New to Qt?"), mainWidget);
- newLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH2));
newLabel->setAlignment(Qt::AlignHCenter);
newVBox->addWidget(newLabel);
diff --git a/src/share/3rdparty/package-manager/auto-setup.cmake b/src/share/3rdparty/package-manager/auto-setup.cmake
index a2e30686f9..628b69cc76 100644
--- a/src/share/3rdparty/package-manager/auto-setup.cmake
+++ b/src/share/3rdparty/package-manager/auto-setup.cmake
@@ -137,6 +137,7 @@ macro(qtc_auto_setup_conan)
get_property(CONAN_INSTALL_SUCCESS GLOBAL PROPERTY CONAN_INSTALL_SUCCESS)
if (CONAN_INSTALL_SUCCESS)
get_property(CONAN_GENERATORS_FOLDER GLOBAL PROPERTY CONAN_GENERATORS_FOLDER)
+ file(TO_CMAKE_PATH \"\${CONAN_GENERATORS_FOLDER}\" CONAN_GENERATORS_FOLDER)
file(WRITE \"${CMAKE_BINARY_DIR}/conan-dependencies/conan_paths.cmake\" \"
list(PREPEND CMAKE_PREFIX_PATH \\\"\${CONAN_GENERATORS_FOLDER}\\\")
list(PREPEND CMAKE_MODULE_PATH \\\"\${CONAN_GENERATORS_FOLDER}\\\")
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 0d589c18b570ce895cf3d6e69545439c2f68eba
+Subproject a30e54c2e7fb7d9735a364497914a5df452dd1a
diff --git a/src/src.qbs b/src/src.qbs
index fb7532b03c..95f2e96dcc 100644
--- a/src/src.qbs
+++ b/src/src.qbs
@@ -34,6 +34,7 @@ Project {
qbsBaseDir + "/share/share.qbs",
qbsBaseDir + "/src/app/apps.qbs",
qbsBaseDir + "/src/shared/bundledqt/bundledqt.qbs",
+ qbsBaseDir + "/src/shared/lsp/lsp.qbs",
qbsBaseDir + "/src/shared/json/json.qbs",
qbsBaseDir + "/src/shared/variant/variant.qbs",
]
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index 698147c419..1cf8f1bbf2 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -5264,7 +5264,12 @@ void tst_Dumpers::dumper_data()
<< Data("#include <string>\n"
"template<class T>\n"
- "class myallocator : public std::allocator<T> {};\n",
+ "class myallocator : public std::allocator<T> {\n"
+ "template<typename _Tp1>\n"
+ "struct rebind {\n"
+ "typedef myallocator<_Tp1> other;\n"
+ "};\n"
+ "};\n",
"std::basic_string<char, std::char_traits<char>, myallocator<char>> str(\"hello\");",
@@ -5313,8 +5318,8 @@ void tst_Dumpers::dumper_data()
"&view, &u16view, basicview, u16basicview")
- + Check("view", "\"test\"", "std::string_view")
- + Check("u16view", "\"test\"", "std::u16string_view")
+ + Check("view", "\"test\"", TypeDef("std::basic_string_view<char, std::char_traits<char> >", "std::string_view"))
+ + Check("u16view", "\"test\"", TypeDef("std::basic_string_view<char16_t, std::char_traits<char16_t> >", "std::u16string_view"))
+ Check("basicview", "\"test\"", "std::basic_string_view<char, std::char_traits<char> >")
+ Check("u16basicview", "\"test\"", "std::basic_string_view<char16_t, std::char_traits<char16_t> >");
@@ -5343,6 +5348,18 @@ void tst_Dumpers::dumper_data()
+ Check("v.0", "[0]", "\"foo\"", "std::string");
+ QTest::newRow("StdTuple")
+ << Data("#include <string>\n",
+
+ "std::tuple<int, std::string, int> tuple = std::make_tuple(123, std::string(\"hello\"), 456);\n",
+
+ "&tuple")
+
+ + Check("tuple.0", "[0]", "123", "int")
+ + Check("tuple.1", "[1]", "\"hello\"", "std::string")
+ + Check("tuple.2", "[2]", "456", "int");
+
+
QTest::newRow("StdValArray")
<< Data("#include <valarray>\n"
"#include <list>\n",
@@ -5418,6 +5435,10 @@ void tst_Dumpers::dumper_data()
"template<class T>\n"
"class myallocator : public std::allocator<T> {\n"
"using std::allocator<T>::allocator;\n"
+ "template<typename _Tp1>\n"
+ "struct rebind {\n"
+ "typedef myallocator<_Tp1> other;\n"
+ "};\n"
"};\n",
"std::vector<double> v0, v1;\n"
diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp
index 64dfe42648..3cf9c127a2 100644
--- a/tests/auto/environment/tst_environment.cpp
+++ b/tests/auto/environment/tst_environment.cpp
@@ -262,11 +262,11 @@ void tst_Environment::expansion()
void tst_Environment::incrementalChanges()
{
const Environment origEnv({{"VAR1", "VALUE1"}, {"VAR2", "VALUE2"}, {"PATH", "/usr/bin"}});
- const NameValueItems changes({
- {"VAR1", QString(), NameValueItem::Unset},
- {"VAR2", "VALUE2", NameValueItem::SetDisabled},
- {"PATH", "/usr/local/bin", NameValueItem::Append},
- {"PATH", "/tmp", NameValueItem::Prepend}});
+ const EnvironmentItems changes({
+ {"VAR1", QString(), EnvironmentItem::Unset},
+ {"VAR2", "VALUE2", EnvironmentItem::SetDisabled},
+ {"PATH", "/usr/local/bin", EnvironmentItem::Append},
+ {"PATH", "/tmp", EnvironmentItem::Prepend}});
// Check values after change application.
Environment newEnv = origEnv;
@@ -281,8 +281,8 @@ void tst_Environment::incrementalChanges()
QString("/tmp").append(sep).append("/usr/bin").append(sep).append("/usr/local/bin"));
// Check apply/diff round-trips.
- const NameValueItems diff = origEnv.diff(newEnv);
- const NameValueItems reverseDiff = newEnv.diff(origEnv);
+ const EnvironmentItems diff = origEnv.diff(newEnv);
+ const EnvironmentItems reverseDiff = newEnv.diff(origEnv);
Environment newEnv2 = origEnv;
newEnv2.modify(diff);
QCOMPARE(newEnv, newEnv2);
@@ -290,12 +290,12 @@ void tst_Environment::incrementalChanges()
QCOMPARE(newEnv2, origEnv);
// Check conversion round-trips.
- QCOMPARE(NameValueItem::fromStringList(NameValueItem::toStringList(changes)), changes);
- QCOMPARE(NameValueItem::fromStringList(NameValueItem::toStringList(diff)), diff);
- QCOMPARE(NameValueItem::fromStringList(NameValueItem::toStringList(reverseDiff)), reverseDiff);
- QCOMPARE(NameValueItem::itemsFromVariantList(NameValueItem::toVariantList(changes)), changes);
- QCOMPARE(NameValueItem::itemsFromVariantList(NameValueItem::toVariantList(diff)), diff);
- QCOMPARE(NameValueItem::itemsFromVariantList(NameValueItem::toVariantList(reverseDiff)),
+ QCOMPARE(EnvironmentItem::fromStringList(EnvironmentItem::toStringList(changes)), changes);
+ QCOMPARE(EnvironmentItem::fromStringList(EnvironmentItem::toStringList(diff)), diff);
+ QCOMPARE(EnvironmentItem::fromStringList(EnvironmentItem::toStringList(reverseDiff)), reverseDiff);
+ QCOMPARE(EnvironmentItem::itemsFromVariantList(EnvironmentItem::toVariantList(changes)), changes);
+ QCOMPARE(EnvironmentItem::itemsFromVariantList(EnvironmentItem::toVariantList(diff)), diff);
+ QCOMPARE(EnvironmentItem::itemsFromVariantList(EnvironmentItem::toVariantList(reverseDiff)),
reverseDiff);
}
diff --git a/tests/auto/texteditor/highlighter/tst_highlighter.cpp b/tests/auto/texteditor/highlighter/tst_highlighter.cpp
index aaba61161b..9044065a01 100644
--- a/tests/auto/texteditor/highlighter/tst_highlighter.cpp
+++ b/tests/auto/texteditor/highlighter/tst_highlighter.cpp
@@ -58,9 +58,8 @@ Last)";
doc = new QTextDocument();
doc->setPlainText(text);
-
- highlighterRunner = new SyntaxHighlighterRunner(
- [this] { return new SyntaxHighlighter(doc, fontsettings); }, doc, false, {}, fontsettings);
+ auto highlighter = new SyntaxHighlighter(doc, fontsettings);
+ highlighterRunner = new SyntaxHighlighterRunner(highlighter, doc, false);
}
static const HighlightingResults &highlightingResults()
diff --git a/tests/auto/utils/filepath/tst_filepath.cpp b/tests/auto/utils/filepath/tst_filepath.cpp
index 0cd0629609..369fb6a258 100644
--- a/tests/auto/utils/filepath/tst_filepath.cpp
+++ b/tests/auto/utils/filepath/tst_filepath.cpp
@@ -117,6 +117,11 @@ private slots:
void isRootPath();
+ void lessThan();
+ void lessThan_data();
+
+ void asQMapKey();
+
private:
QTemporaryDir tempDir;
QString rootPath;
@@ -1666,6 +1671,42 @@ void tst_filepath::sort()
QCOMPARE(sortedPaths, sorted);
}
+void tst_filepath::lessThan_data()
+{
+ QTest::addColumn<FilePath>("left");
+ QTest::addColumn<FilePath>("right");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("empty") << FilePath() << FilePath() << false;
+ QTest::newRow("simple") << FilePath("/a") << FilePath("/b") << true;
+ QTest::newRow("simple-2") << FilePath("/a") << FilePath("/a") << false;
+ QTest::newRow("simple-3") << FilePath("/b") << FilePath("/a") << false;
+
+ QTest::newRow("remote-vs-local") << FilePath("docker://1234/a") << FilePath("/a") << false;
+ QTest::newRow("local-vs-remote") << FilePath("/a") << FilePath("docker://1234/a") << true;
+
+ QTest::newRow("remote-vs-local-2") << FilePath("docker://1234/a") << FilePath("/b") << false;
+ QTest::newRow("local-vs-remote-2") << FilePath("/a") << FilePath("docker://1234/b") << true;
+}
+
+void tst_filepath::lessThan()
+{
+ QFETCH(FilePath, left);
+ QFETCH(FilePath, right);
+ QFETCH(bool, expected);
+
+ QCOMPARE(left < right, expected);
+}
+
+void tst_filepath::asQMapKey()
+{
+ QMap<FilePath, int> map;
+ map.insert(FilePath::fromString("/Users/mtillmanns/projects/qt/qtc-work/fsengine"), 1);
+
+ QCOMPARE(map.contains(FilePath::fromString("ssh://marcus@mad-ubuntu-23.local/tmp/untitled")),
+ false);
+}
+
void tst_filepath::isRootPath()
{
FilePath localRoot = FilePath::fromString(QDir::rootPath());
diff --git a/tests/system/README b/tests/system/README
index 1174b18187..7dff67a84d 100644
--- a/tests/system/README
+++ b/tests/system/README
@@ -63,10 +63,7 @@ started. On Windows, this has the following prerequisites:
Either:
* have no firewall at all enabled (sure that's a bad idea)
Or:
- * run Windows with English UI
- * have the Windows Firewall enabled (no other firewalls are handled by the scripts)
- * run the Squish tests with administrator privileges
- * additionally the UAC should be disabled, too
+ * have notifications disabled for the firewall when an application tries to access network
Otherwise you'll have some trouble with popping up dialogs from the firewall.
If you're using a different firewall - try to figure out and add a rule for this.
diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py
index 6a2904286a..c26634f61d 100644
--- a/tests/system/shared/build_utils.py
+++ b/tests/system/shared/build_utils.py
@@ -40,12 +40,6 @@ def getBuildIssues(ignoreCodeModel=True):
# lines within the Issues output
# param expectedToFail can be used to tell this function if the build was expected to fail or not
def checkLastBuild(expectedToFail=False):
- try:
- # can't use waitForObject() 'cause visible is always 0
- findObject("{type='ProjectExplorer::Internal::BuildProgress' unnamed='1' }")
- except LookupError:
- test.log("checkLastBuild called without a build")
- return
buildIssues = getBuildIssues()
types = [i[1] for i in buildIssues]
errors = types.count("1")
diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py
index bb6b4082b6..5ee31dec20 100644
--- a/tests/system/shared/debugger.py
+++ b/tests/system/shared/debugger.py
@@ -266,69 +266,3 @@ def verifyBreakPoint(bpToVerify):
test.fatal("Expected a dict for bpToVerify - got '%s'" % className(bpToVerify))
return False
-# helper to check whether win firewall is running or not
-# this doesn't check for other firewalls!
-def __isWinFirewallRunning__():
- if hasattr(__isWinFirewallRunning__, "fireWallState"):
- return __isWinFirewallRunning__.fireWallState
- if platform.system() not in ('Microsoft' 'Windows'):
- __isWinFirewallRunning__.fireWallState = False
- return False
- result = getOutputFromCmdline(["netsh", "firewall", "show", "state"])
- for line in result.splitlines():
- if "Operational mode" in line:
- __isWinFirewallRunning__.fireWallState = not "Disable" in line
- return __isWinFirewallRunning__.fireWallState
- return None
-
-# helper that can modify the win firewall to allow a program to communicate through it or delete it
-# param addToFW defines whether to add (True) or delete (False) this program to/from the firewall
-def __configureFW__(workingDir, projectName, isReleaseBuild, addToFW=True):
- if isReleaseBuild == None:
- if projectName[-4:] == ".exe":
- projectName = projectName[:-4]
- path = "%s%s%s" % (workingDir, os.sep, projectName)
- elif isReleaseBuild:
- path = "%s%s%s%srelease%s%s" % (workingDir, os.sep, projectName, os.sep, os.sep, projectName)
- else:
- path = "%s%s%s%sdebug%s%s" % (workingDir, os.sep, projectName, os.sep, os.sep, projectName)
- if addToFW:
- mode = "add"
- enable = "ENABLE"
- else:
- mode = "delete"
- enable = ""
- projectName = ""
- # Needs admin privileges on Windows 7
- # Using the deprecated "netsh firewall" because the newer
- # "netsh advfirewall" would need admin privileges on Windows Vista, too.
- return subprocess.call(["netsh", "firewall", mode, "allowedprogram",
- "%s.exe" % path, projectName, enable])
-
-# function to add a program to allow communication through the win firewall
-# param workingDir this directory is the parent of the project folder
-# param projectName this is the name of the project (the folder inside workingDir as well as the name for the executable)
-# param isReleaseBuild should currently always be set to True (will later add debug build testing)
-def allowAppThroughWinFW(workingDir, projectName, isReleaseBuild=True):
- if not __isWinFirewallRunning__():
- return
- # WinFirewall seems to run - hopefully no other
- result = __configureFW__(workingDir, projectName, isReleaseBuild)
- if result == 0:
- test.log("Added %s to firewall" % projectName)
- else:
- test.fatal("Could not add %s as allowed program to win firewall" % projectName)
-
-# function to delete a (former added) program from the win firewall
-# param workingDir this directory is the parent of the project folder
-# param projectName this is the name of the project (the folder inside workingDir as well as the name for the executable)
-# param isReleaseBuild should currently always be set to True (will later add debug build testing)
-def deleteAppFromWinFW(workingDir, projectName, isReleaseBuild=True):
- if not __isWinFirewallRunning__():
- return
- # WinFirewall seems to run - hopefully no other
- result = __configureFW__(workingDir, projectName, isReleaseBuild, False)
- if result == 0:
- test.log("Deleted %s from firewall" % projectName)
- else:
- test.warning("Could not delete %s as allowed program from win firewall" % (projectName))
diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py
index e6301f941c..518ac1b23b 100644
--- a/tests/system/suite_debugger/tst_simple_debug/test.py
+++ b/tests/system/suite_debugger/tst_simple_debug/test.py
@@ -36,7 +36,7 @@ def main():
for kit, config in availableConfigs:
test.log("Selecting '%s' as build config" % config)
verifyBuildConfig(kit, config, True, True, True)
- # explicitly build before start debugging for adding the executable as allowed program to WinFW
+ # explicitly build before start debugging
selectFromLocator("t rebuild", "Rebuild All Projects")
waitForCompile(300000)
if not checkCompile():
@@ -52,7 +52,6 @@ def main():
buildDir = os.path.join(str(waitForObject(":Qt Creator_Utils::BuildDirectoryLineEdit").text),
"debug")
switchViewTo(ViewConstants.EDIT)
- allowAppThroughWinFW(buildDir, projectName, None)
if not doSimpleDebugging(kit, config, expectedBreakpointsOrder):
try:
stopB = findObject(':Qt Creator.Stop_QToolButton')
@@ -60,8 +59,6 @@ def main():
clickButton(stopB)
except:
pass
- if platform.system() in ('Microsoft' 'Windows'):
- deleteAppFromWinFW(buildDir, projectName, None)
# close application output window of current run to avoid mixing older output on the next run
ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")
clickButton(waitForObject("{type='CloseButton' unnamed='1' visible='1' "
diff --git a/tests/system/suite_tools/tst_git_clone/test.py b/tests/system/suite_tools/tst_git_clone/test.py
index 42473264f7..17ce84d752 100644
--- a/tests/system/suite_tools/tst_git_clone/test.py
+++ b/tests/system/suite_tools/tst_git_clone/test.py
@@ -47,7 +47,7 @@ def verifyVersionControlView(targetDir, canceled):
"Searching for target directory in clone log")
test.verify(" ".join(["clone", "--progress", cloneUrl, cloneDir]) in vcsLog,
"Searching for git parameters in clone log")
- test.compare(canceled, " terminated abnormally" in vcsLog,
+ test.compare(canceled, " was canceled after " in vcsLog,
"Searching for result in clone log")
clickButton(waitForObject(":*Qt Creator.Clear_QToolButton"))