diff --git a/README.md b/README.md index 32b53aacb53..9f4b6f1457d 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,11 @@ Prerequisites: * Qt WebEngine module for QtWebEngine based help viewer * On Windows: * MinGW with GCC 9 or Visual Studio 2019 or later - * Python 3.5 or later (optional, needed for the python enabled debug helper) + * Python 3.8 or later (optional, needed for the python enabled debug helper) * Debugging Tools for Windows (optional, for MSVC debugging support with CDB) * On Mac OS X: latest Xcode * On Linux: GCC 9 or later -* LLVM/Clang 10 or later (optional, LLVM/Clang 14 is recommended. +* LLVM/Clang 14 or later (optional, LLVM/Clang 17 is recommended. See [instructions](#getting-llvmclang-for-the-clang-code-model) on how to get LLVM. The ClangFormat plugin uses the LLVM C++ API. diff --git a/cmake/CreatePythonXY.cmake b/cmake/CreatePythonXY.cmake index 637c4940c83..4e234703cb8 100644 --- a/cmake/CreatePythonXY.cmake +++ b/cmake/CreatePythonXY.cmake @@ -24,34 +24,34 @@ function(create_python_xy PythonExe PythonZipFilePath) cgi.py nntplib.py tarfile.py cgitb.py nturl2path.py telnetlib.py chunk.py numbers.py tempfile.py - cmd.py optparse.py textwrap.py - code.py pathlib.py this.py - codeop.py pdb.py timeit.py - colorsys.py pickle.py trace.py - compileall.py pickletools.py tracemalloc.py - configparser.py pipes.py tty.py - contextvars.py plistlib.py turtle.py - cProfile.py poplib.py typing.py - crypt.py pprint.py uu.py - csv.py profile.py uuid.py - dataclasses.py pstats.py wave.py - datetime.py pty.py webbrowser.py - decimal.py pyclbr.py xdrlib.py - difflib.py py_compile.py zipapp.py - doctest.py queue.py zipfile.py - dummy_threading.py quopri.py zipimport.py - filecmp.py random.py _compat_pickle.py - fileinput.py rlcompleter.py _compression.py - formatter.py runpy.py _dummy_thread.py - fractions.py sched.py _markupbase.py - ftplib.py secrets.py _osx_support.py - getopt.py selectors.py _pydecimal.py - getpass.py shelve.py _pyio.py - gettext.py shlex.py _py_abc.py - gzip.py shutil.py _strptime.py - hashlib.py smtpd.py _threading_local.py - hmac.py smtplib.py __future__.py - imaplib.py sndhdr.py __phello__.foo.py + cmd.py optparse.py this.py + code.py pathlib.py timeit.py + codeop.py pdb.py trace.py + colorsys.py pickle.py tracemalloc.py + compileall.py pickletools.py tty.py + configparser.py pipes.py turtle.py + contextvars.py plistlib.py typing.py + cProfile.py poplib.py uu.py + crypt.py pprint.py uuid.py + csv.py profile.py wave.py + dataclasses.py pstats.py webbrowser.py + datetime.py pty.py xdrlib.py + decimal.py pyclbr.py zipapp.py + difflib.py py_compile.py zipfile.py + doctest.py queue.py zipimport.py + dummy_threading.py quopri.py _compat_pickle.py + filecmp.py random.py _compression.py + fileinput.py rlcompleter.py _dummy_thread.py + formatter.py runpy.py _markupbase.py + fractions.py sched.py _osx_support.py + ftplib.py secrets.py _pydecimal.py + getopt.py selectors.py _pyio.py + getpass.py shelve.py _py_abc.py + gettext.py shlex.py _strptime.py + gzip.py shutil.py _threading_local.py + hashlib.py smtpd.py __future__.py + hmac.py smtplib.py __phello__.foo.py + imaplib.py sndhdr.py ) list(FIND python_lib_files "${python_lib_dir}/${not_needed}" found_not_needed) if (NOT found_not_needed STREQUAL "-1") diff --git a/cmake/QtCreatorDocumentation.cmake b/cmake/QtCreatorDocumentation.cmake index 1ef9030a43a..9587a77e0b1 100644 --- a/cmake/QtCreatorDocumentation.cmake +++ b/cmake/QtCreatorDocumentation.cmake @@ -283,7 +283,7 @@ function(add_qtc_doc_attribution target attribution_file output_file qdocconf_fi file(MAKE_DIRECTORY ${output_dir}) # add target add_custom_target(${target} - Qt6::qtattributionsscanner -o "${output_file}" ${attribution_file} + Qt6::qtattributionsscanner -o "${output_file}" --basedir "${PROJECT_SOURCE_DIR}" ${attribution_file} COMMENT "Create attributions ${output_file} from ${attribution_file}" DEPENDS "${attribution_file}" SOURCES "${attribution_file}" diff --git a/cmake/QtCreatorIDEBranding.cmake b/cmake/QtCreatorIDEBranding.cmake index 275454a6684..6890a1ef957 100644 --- a/cmake/QtCreatorIDEBranding.cmake +++ b/cmake/QtCreatorIDEBranding.cmake @@ -1,6 +1,6 @@ -set(IDE_VERSION "12.0.82") # The IDE version. -set(IDE_VERSION_COMPAT "12.0.82") # The IDE Compatibility version. -set(IDE_VERSION_DISPLAY "13.0.0-beta1") # The IDE display version. +set(IDE_VERSION "12.0.83") # The IDE version. +set(IDE_VERSION_COMPAT "12.0.83") # The IDE Compatibility version. +set(IDE_VERSION_DISPLAY "13.0.0-beta2") # The IDE display version. set(IDE_COPYRIGHT_YEAR "2024") # The IDE current copyright year. set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation. diff --git a/dist/changelog/changes-13.0.0.md b/dist/changelog/changes-13.0.0.md index 793e47e97f2..82530d29768 100644 --- a/dist/changelog/changes-13.0.0.md +++ b/dist/changelog/changes-13.0.0.md @@ -18,7 +18,7 @@ What's new? ### Qt Application Manager Adds support for Qt 6 based applications with CMake for creating, building, -deploying, running, and debugging on devices that use the +deploying, running, and debugging for devices that use the [Qt Application Manager](https://doc.qt.io/QtApplicationManager/). ([Documentation](https://doc.qt.io/qtcreator/creator-overview-qtasam.html)) @@ -39,6 +39,12 @@ General for searching in `Files in File System` * Added `Copy to Clipboard` to the `About Qt Creator` dialog ([QTCREATORBUG-29886](https://bugreports.qt.io/browse/QTCREATORBUG-29886)) +* Fixed issues with the window actions + ([QTCREATORBUG-30381](https://bugreports.qt.io/browse/QTCREATORBUG-30381)) +* Known Issues + * Installers provided by The Qt Company mostly display English text, not + the system's language + ([QTIFW-3310](https://bugreports.qt.io/browse/QTIFW-3310)) Editing ------- @@ -63,6 +69,7 @@ Editing ([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 + ([Documentation](https://doc-snapshots.qt.io/qtcreator-13.0/creator-preferences-cpp-code-style.html)) * Fixed that the class wizards used the class name for the include guard instead of the file name ([QTCREATORBUG-30140](https://bugreports.qt.io/browse/QTCREATORBUG-30140)) @@ -77,6 +84,8 @@ Editing * Clangd * Fixed that `Follow Symbol Under Cursor` only worked for exact matches ([QTCREATORBUG-29814](https://bugreports.qt.io/browse/QTCREATORBUG-29814)) + * Fixed the version check for remote `clangd` executables + ([QTCREATORBUG-30374](https://bugreports.qt.io/browse/QTCREATORBUG-30374)) ### QML @@ -96,6 +105,7 @@ Editing * Added automatic setup up of language servers for `YAML`, `JSON`, and `Bash` (requires `npm`) + ([Documentation](https://doc-snapshots.qt.io/qtcreator-13.0/creator-language-servers.html#adding-language-servers)) ### Widget Designer @@ -123,6 +133,7 @@ Projects * Added a section `Vanished Targets` to `Projects` mode in case the project was configured for kits that have vanished, as a replacement for the automatic creation of "Replacement" kits + ([Documentation](https://doc-snapshots.qt.io/qtcreator-13.0/creator-how-to-activate-kits.html#copy-custom-settings-from-vanished-targets)) * Added the status of devices to the device lists ([QTCREATORBUG-20941](https://bugreports.qt.io/browse/QTCREATORBUG-20941)) * Added the `Preferences > Build & Run > General > Application environment` @@ -130,6 +141,10 @@ Projects ([QTCREATORBUG-29530](https://bugreports.qt.io/browse/QTCREATORBUG-29530)) * Added a file wizard for Qt translation (`.ts`) files ([QTCREATORBUG-29775](https://bugreports.qt.io/browse/QTCREATORBUG-29775)) +* Added an optional warning for special characters in build directories + ([QTCREATORBUG-20834](https://bugreports.qt.io/browse/QTCREATORBUG-20834)) +* Improved the environment settings by making the changes explicit in a + separate, text-based editor * Increased the maximum width of the target selector ([QTCREATORBUG-30038](https://bugreports.qt.io/browse/QTCREATORBUG-30038)) * Fixed that the `Left` cursor key did not always collapse the current item @@ -164,11 +179,13 @@ Projects * 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 the `Kit Selection` page for creating and opening 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 + ([Documentation](https://doc-snapshots.qt.io/qtcreator-13.0/creator-python-development.html)) + Debugging --------- @@ -177,6 +194,9 @@ Debugging ### C++ * Added a pretty printer for `std::tuple` +* Improved the display of size information for the pretty printer of + `QByteArray` + ([QTCREATORBUG-30065](https://bugreports.qt.io/browse/QTCREATORBUG-30065)) * Fixed that breakpoints were not hit while the message dialog about missing debug information was shown ([QTCREATORBUG-30168](https://bugreports.qt.io/browse/QTCREATORBUG-30168)) @@ -244,6 +264,7 @@ Platforms * Fixed deployment and running applications for iOS 17 devices (application output, debugging, and profiling are not supported) ([QTCREATORBUG-29682](https://bugreports.qt.io/browse/QTCREATORBUG-29682)) + ([Documentation](https://doc-snapshots.qt.io/qtcreator-13.0/creator-developing-ios.html)) ### Remote Linux @@ -262,6 +283,7 @@ Andre Hartmann André Pönitz Andreas Loth Artem Sokolovskii +Assam Boudjelthia Brook Cronin Burak Hancerli Christian Kandeler @@ -298,6 +320,7 @@ Robert Löhning Sami Shalayel Samuel Jose Raposo Vieira Mira Samuel Mira +Semih Yavuz Serg Kryvonos Shrief Gabr Sivert Krøvel diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 00786024dfd..f78240e4fb0 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -43,6 +43,14 @@ function(_add_doc _doc_file _dev_doc_file) "${GENERATED_ATTRIBUTIONS_DIR}/creator-attributions.qdoc" ${_doc_file} ) + set(litehtml_attributions "${CMAKE_CURRENT_SOURCE_DIR}/../src/libs/qlitehtml/src/3rdparty/qt_attribution.json") + if(EXISTS "${litehtml_attributions}") + add_qtc_doc_attribution(doc_attributions_litehtml + "${litehtml_attributions}" + "${GENERATED_ATTRIBUTIONS_DIR}/creator-attributions-litehtml.qdoc" + ${_doc_file} + ) + endif() if (BUILD_DEVELOPER_DOCS) _find_all_includes(_all_includes _framework_paths) add_qtc_documentation(${_dev_doc_file} diff --git a/doc/qtcreator/images/heartgame-start.webp b/doc/qtcreator/images/heartgame-start.webp new file mode 100644 index 00000000000..9fef6fe0057 Binary files /dev/null and b/doc/qtcreator/images/heartgame-start.webp differ diff --git a/doc/qtcreator/images/icons/build.png b/doc/qtcreator/images/icons/build.png new file mode 100644 index 00000000000..590e9b052c3 Binary files /dev/null and b/doc/qtcreator/images/icons/build.png differ diff --git a/doc/qtcreator/images/icons/cancel-build.png b/doc/qtcreator/images/icons/cancel-build.png new file mode 100644 index 00000000000..a3773413a88 Binary files /dev/null and b/doc/qtcreator/images/icons/cancel-build.png differ diff --git a/doc/qtcreator/images/icons/live-preview.png b/doc/qtcreator/images/icons/live-preview.png new file mode 100644 index 00000000000..62feef8122c Binary files /dev/null and b/doc/qtcreator/images/icons/live-preview.png differ diff --git a/doc/qtcreator/images/qt-app-dev-flow.webp b/doc/qtcreator/images/qt-app-dev-flow.webp new file mode 100644 index 00000000000..14be8fb3d70 Binary files /dev/null and b/doc/qtcreator/images/qt-app-dev-flow.webp differ diff --git a/doc/qtcreator/images/qt-tools.webp b/doc/qtcreator/images/qt-tools.webp new file mode 100644 index 00000000000..986846140fa Binary files /dev/null and b/doc/qtcreator/images/qt-tools.webp differ diff --git a/doc/qtcreator/images/qtcreator-android-avd-manager.png b/doc/qtcreator/images/qtcreator-android-avd-manager.png deleted file mode 100644 index 022395a800f..00000000000 Binary files a/doc/qtcreator/images/qtcreator-android-avd-manager.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-android-avd-manager.webp b/doc/qtcreator/images/qtcreator-android-avd-manager.webp new file mode 100644 index 00000000000..88c4f1bd0b3 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-android-avd-manager.webp differ diff --git a/doc/qtcreator/images/qtcreator-editor-toolbar-qml.webp b/doc/qtcreator/images/qtcreator-editor-toolbar-qml.webp new file mode 100644 index 00000000000..22e7b298f42 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-editor-toolbar-qml.webp differ diff --git a/doc/qtcreator/images/qtcreator-find-from-current-file.webp b/doc/qtcreator/images/qtcreator-find-from-current-file.webp new file mode 100644 index 00000000000..d9296f04ac0 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-find-from-current-file.webp differ diff --git a/doc/qtcreator/images/qtcreator-find-incremental.png b/doc/qtcreator/images/qtcreator-find-incremental.png deleted file mode 100644 index 3bb17a1a41f..00000000000 Binary files a/doc/qtcreator/images/qtcreator-find-incremental.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-git-add-branch.webp b/doc/qtcreator/images/qtcreator-git-add-branch.webp new file mode 100644 index 00000000000..19782ad4fe9 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-git-add-branch.webp differ diff --git a/doc/qtcreator/images/qtcreator-git-branches.webp b/doc/qtcreator/images/qtcreator-git-branches.webp new file mode 100644 index 00000000000..a2b343461d1 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-git-branches.webp differ diff --git a/doc/qtcreator/images/qtcreator-kit-selector.png b/doc/qtcreator/images/qtcreator-kit-selector.png deleted file mode 100644 index e2635364c1c..00000000000 Binary files a/doc/qtcreator/images/qtcreator-kit-selector.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-kit-selector.webp b/doc/qtcreator/images/qtcreator-kit-selector.webp new file mode 100644 index 00000000000..a9b44fd822c Binary files /dev/null and b/doc/qtcreator/images/qtcreator-kit-selector.webp differ diff --git a/doc/qtcreator/images/qtcreator-live-preview.png b/doc/qtcreator/images/qtcreator-live-preview.png deleted file mode 100644 index 4fd62939ab8..00000000000 Binary files a/doc/qtcreator/images/qtcreator-live-preview.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-live-preview.webp b/doc/qtcreator/images/qtcreator-live-preview.webp new file mode 100644 index 00000000000..8d7442d4702 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-live-preview.webp differ diff --git a/doc/qtcreator/images/qtcreator-locator-m-filter.webp b/doc/qtcreator/images/qtcreator-locator-m-filter.webp new file mode 100644 index 00000000000..9b681b38c00 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-locator-m-filter.webp 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 00000000000..3ad21a25d91 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-new-file-ts.webp differ diff --git a/doc/qtcreator/images/qtcreator-new-project-qt-for-python-kit-selection.webp b/doc/qtcreator/images/qtcreator-new-project-qt-for-python-kit-selection.webp new file mode 100644 index 00000000000..f7c3be17d5b Binary files /dev/null and b/doc/qtcreator/images/qtcreator-new-project-qt-for-python-kit-selection.webp differ diff --git a/doc/qtcreator/images/qtcreator-new-qt-for-python-app-project-details.webp b/doc/qtcreator/images/qtcreator-new-qt-for-python-app-project-details.webp new file mode 100644 index 00000000000..14494a04d37 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-new-qt-for-python-app-project-details.webp differ diff --git a/doc/qtcreator/images/qtcreator-new-qt-for-python-app-qt-quick-empty-project-details.webp b/doc/qtcreator/images/qtcreator-new-qt-for-python-app-qt-quick-empty-project-details.webp deleted file mode 100644 index 1dd0962f4f3..00000000000 Binary files a/doc/qtcreator/images/qtcreator-new-qt-for-python-app-qt-quick-empty-project-details.webp and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-new-qt-for-python-app-widgets-project-details.webp b/doc/qtcreator/images/qtcreator-new-qt-for-python-app-widgets-project-details.webp deleted file mode 100644 index 3890e8e75ba..00000000000 Binary files a/doc/qtcreator/images/qtcreator-new-qt-for-python-app-widgets-project-details.webp and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp b/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp new file mode 100644 index 00000000000..c7636894960 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-preferences-build-run-general.webp differ diff --git a/doc/qtcreator/images/qtcreator-project-options-deploy.png b/doc/qtcreator/images/qtcreator-project-options-deploy.png deleted file mode 100644 index 2461d6a7e7e..00000000000 Binary files a/doc/qtcreator/images/qtcreator-project-options-deploy.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-python-interpreters.webp b/doc/qtcreator/images/qtcreator-python-interpreters.webp index 597b99e720d..b5027b0a0d4 100644 Binary files a/doc/qtcreator/images/qtcreator-python-interpreters.webp and b/doc/qtcreator/images/qtcreator-python-interpreters.webp differ diff --git a/doc/qtcreator/images/qtcreator-python-run-settings.png b/doc/qtcreator/images/qtcreator-python-run-settings.png deleted file mode 100644 index 5d3875f4e35..00000000000 Binary files a/doc/qtcreator/images/qtcreator-python-run-settings.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-python-run-settings.webp b/doc/qtcreator/images/qtcreator-python-run-settings.webp new file mode 100644 index 00000000000..69f2d7676d6 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-python-run-settings.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-all-projects.webp b/doc/qtcreator/images/qtcreator-search-all-projects.webp new file mode 100644 index 00000000000..7cabff26631 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-search-all-projects.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-allprojects.png b/doc/qtcreator/images/qtcreator-search-allprojects.png deleted file mode 100644 index c442572f996..00000000000 Binary files a/doc/qtcreator/images/qtcreator-search-allprojects.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-search-file-system.webp b/doc/qtcreator/images/qtcreator-search-file-system.webp new file mode 100644 index 00000000000..31494d1a17f Binary files /dev/null and b/doc/qtcreator/images/qtcreator-search-file-system.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-filesystem.png b/doc/qtcreator/images/qtcreator-search-filesystem.png deleted file mode 100644 index df344a79e33..00000000000 Binary files a/doc/qtcreator/images/qtcreator-search-filesystem.png and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-search-reg-exp.webp b/doc/qtcreator/images/qtcreator-search-reg-exp.webp new file mode 100644 index 00000000000..a56f9b18d42 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-search-reg-exp.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-results-matches.webp b/doc/qtcreator/images/qtcreator-search-results-matches.webp index 8b49a72fbf2..6a3939e9074 100644 Binary files a/doc/qtcreator/images/qtcreator-search-results-matches.webp and b/doc/qtcreator/images/qtcreator-search-results-matches.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-results-reg-exp.webp b/doc/qtcreator/images/qtcreator-search-results-reg-exp.webp new file mode 100644 index 00000000000..7b2c9aab7a4 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-search-results-reg-exp.webp differ diff --git a/doc/qtcreator/images/qtcreator-search-results.webp b/doc/qtcreator/images/qtcreator-search-results.webp deleted file mode 100644 index d36ec5e2851..00000000000 Binary files a/doc/qtcreator/images/qtcreator-search-results.webp and /dev/null differ diff --git a/doc/qtcreator/images/qtcreator-vcs-gitbranch.png b/doc/qtcreator/images/qtcreator-vcs-gitbranch.png deleted file mode 100644 index f6a5586eac2..00000000000 Binary files a/doc/qtcreator/images/qtcreator-vcs-gitbranch.png and /dev/null differ diff --git a/doc/qtcreator/src/android/androiddev.qdoc b/doc/qtcreator/src/android/androiddev.qdoc index 69947c4fc03..7e172f0650a 100644 --- a/doc/qtcreator/src/android/androiddev.qdoc +++ b/doc/qtcreator/src/android/androiddev.qdoc @@ -195,7 +195,7 @@ To view the available AVDs, select \preferences > \uicontrol Devices. You can add more AVDs. - \image qtcreator-android-avd-manager.png {Android device in Devices} + \image qtcreator-android-avd-manager.webp {Android device in Devices} You can see the status of the selected device in \uicontrol {Current state}. To update the status information, select \uicontrol Refresh. diff --git a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc index 368e313851a..dfde42b473e 100644 --- a/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc +++ b/doc/qtcreator/src/baremetal/creator-baremetal-dev.qdoc @@ -262,7 +262,7 @@ You can build applications for and run them on bare metal devices in the same way as for and on the desktop. For more information, see - \l{Building for Multiple Platforms} and \l{Running on Multiple Platforms}. + \l{Building for Multiple Platforms} and \l{Run on many platforms}. \sa {Enable and disable plugins} */ diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc index 90ffd7cd809..c8da5117fb6 100644 --- a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc +++ b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc @@ -180,7 +180,7 @@ case-sensitivity. Select \uicontrol {Show Non-matching Lines} to hide the lines that match the filter. - Press \key {Ctrl+F} to \l{Finding and Replacing}{search} for a string from + Press \key {Ctrl+F} to \l{Search in current file}{search} for a string in the output. To increase or decrease the output text size, select \inlineimage icons/plus.png @@ -188,7 +188,7 @@ (\uicontrol {Zoom Out}), or press \key Ctrl++ or \key Ctrl+-. To hide the output, select the \inlineimage icons/rightsidebaricon.png - (\uicontrol {Hide/Show Right Sidebar}) button or press \key {Alt+Shift+0}. + (\uicontrol {Hide Right Sidebar}) button or press \key {Alt+Shift+0}. \section1 CLICOLOR_FORCE Environment Variable @@ -275,6 +275,7 @@ The build errors and warnings are parsed and displayed in \l Issues. - \sa {Activate kits for a project}, {Configure projects for building}, - {Configure projects for running}, {Open projects}, {CMake} + \sa {Activate kits for a project}, {Add custom output parsers}, + {Configure projects for building}, {Configure projects for running}, + {Open projects}, {CMake} */ diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc index 53780c96a5d..66386d72c0a 100644 --- a/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc +++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger-setup.qdoc @@ -99,7 +99,7 @@ \section2 Supported GDB Versions Use GDB 7.5, or later, with the Python scripting extension and Python version - 3.3, or later. + 3.5, or later. For remote debugging using GDB and GDB server, the minimum supported version of GDB server on the target \l{glossary-device}{device} is 7.0. @@ -121,35 +121,26 @@ On Linux, the minimum supported version is LLDB 3.8. - \omit - - \section2 GDB Adapter Modes - - [Advanced Topic] + \section2 GDB Run Modes The GDB native debugger used internally by the debugger plugin runs in - different adapter modes to cope with the variety of supported platforms and - environments. All GDB adapters inherit from AbstractGdbAdapter: + different modes to cope with the variety of supported platforms and + environments: \list - \li PlainGdbAdapter debugs locally started GUI processes. It is - physically split into parts that are relevant only when Python is - available, parts relevant only when Python is not available, and - mixed code. + \li Plain mode debugs locally started processes that do not need console input. - \li TermGdbAdapter debugs locally started processes that need a console. + \li Terminal mode debugs locally started processes that need a console. - \li AttachGdbAdapter debugs local processes started outside \QC. + \li Attach mode debugs local processes started outside \QC. - \li CoreGdbAdapter debugs core files generated from crashes. + \li Core mode debugs core files generated from crashes. - \li RemoteGdbAdapter interacts with the GDB server running on Linux. + \li Remote mode interacts with the GDB server running on Linux. \endlist - \endomit - \section1 Installing Native Debuggers The following sections describe installing native debuggers. diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc index 101bd3a1889..34ea75fc528 100644 --- a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc +++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc @@ -14,18 +14,6 @@ \title Debugging - A debugger lets you see what happens \e inside an application while it runs - or when it crashes. A debugger can do the following to help you find errors - in the application: - - \list - \li Start the application with parameters that specify its behavior. - \li Stop the application when conditions are met. - \li Examine what happens when the application stops. - \li Make changes in the application when you fix an error and continue - to find the next one. - \endlist - The \QC debugger plugin acts as an interface between the \QC core and external native debuggers that you can use to: @@ -127,9 +115,17 @@ \title Launching the Debugger - To start an application from an open project under the control of a - debugger, select the \inlineimage icons/qtcreator-debug-button.png - (\uicontrol {Start Debugging of Startup Project}) button or press \key F5. + You can start an application from an open project under the control of a + debugger in the following ways: + + \list + \li Select \inlineimage icons/qtcreator-debug-button.png + (\uicontrol {Start Debugging of Startup Project}). + \li Press \key F5. + \li Enter \c {dr} in the locator, and select the project to debug. + \li Go to \uicontrol Debug > \uicontrol {Start Debugging} > + \uicontrol {Start Debugging of Startup Project}. + \endlist \QC checks whether the compiled application is up-to-date, and rebuilds and deploys it if you set the \uicontrol {Build before deploying} field to @@ -1985,7 +1981,7 @@ \li Select the \inlineimage icons/run_small.png (\uicontrol Run) button to verify that the - \l {Running on Multiple Platforms}{build and run kit selector} + \l {Run on many platforms}{build and run kit selector} picked a runnable target and you can run the application. \li Make sure the debugger is \l{Setting Up Debugger}{set up properly}. diff --git a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc index a9d297419cd..c888927e022 100644 --- a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc +++ b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc @@ -80,7 +80,7 @@ \li To debug applications on \l{glossary-device}{devices}, check that Qt 5.0, or later, libraries are installed on the device and - \l{Running on Multiple Platforms}{select the corresponding kit for the device} + \l{Run on many platforms}{select the corresponding kit for the device} before you start debugging. \endlist diff --git a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc index eab5601c25f..413ffe9ef54 100644 --- a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc +++ b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc @@ -8,20 +8,6 @@ \title Refactoring - \e {Code refactoring} is the process of improving and simplifying code - without modifying the existing functionality of an application. You - can easily find and rename symbols and apply predefined actions to - refactor code. - - Refactor code to: - - \list - \li Improve internal quality of your application - \li Improve performance and extensibility - \li Improve code readability and maintainability - \li Simplify code structure - \endlist - To quickly and conveniently apply actions to refactor your code, \l{Apply quick fixes}{select quick fixes in a context menu}. @@ -51,13 +37,6 @@ \image qtcreator-search-cpp-symbols.png \endif - \section1 Finding QML Types - - To find instances of a specific QML type in a project, place the cursor on - the type and select \uicontrol Tools > \uicontrol {QML/JS} > - \uicontrol {Find References to Symbol Under Cursor} or press - \key {Ctrl+Shift+U}. - \section1 Viewing Search Results \QC searches from the following locations: @@ -71,7 +50,7 @@ \endif \endlist - \l{Search Results} shows the location and number of search hits in the + \l{Search Results View} shows the location and number of search hits in the current project. \if defined(qtcreator) diff --git a/doc/qtcreator/src/editors/creator-coding.qdoc b/doc/qtcreator/src/editors/creator-coding.qdoc index 67f8b6ac44d..38c6f3f5963 100644 --- a/doc/qtcreator/src/editors/creator-coding.qdoc +++ b/doc/qtcreator/src/editors/creator-coding.qdoc @@ -36,12 +36,15 @@ key components of \QC. You can use the code editor in the \uicontrol Edit mode. \endif + + \if defined(qtdesignstudio) \li \l{Finding} - Use the incremental and advanced search to search from currently + Use the incremental and advanced search to search in currently open projects or files on the file system or use the locator to browse through projects, files, classes, functions, documentation and file systems. + \endif \li \l{Refactoring} diff --git a/doc/qtcreator/src/editors/creator-diff-editor.qdoc b/doc/qtcreator/src/editors/creator-diff-editor.qdoc index dfeb7f5b4ac..8557cd8bffb 100644 --- a/doc/qtcreator/src/editors/creator-diff-editor.qdoc +++ b/doc/qtcreator/src/editors/creator-diff-editor.qdoc @@ -11,7 +11,7 @@ \page creator-diff-editor.html \if defined(qtdesignstudio) \previouspage qt-quick-toolbars.html - \nextpage creator-finding-overview.html + \nextpage studio-finding.html \else \previouspage creator-macros.html \nextpage creator-clang-codemodel.html diff --git a/doc/qtcreator/src/editors/creator-finding.qdoc b/doc/qtcreator/src/editors/creator-finding.qdoc deleted file mode 100644 index 2ebf1ad0a94..00000000000 --- a/doc/qtcreator/src/editors/creator-finding.qdoc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -// ********************************************************************** -// NOTE: the sections are not ordered by their logical order to avoid -// reshuffling the file each time the index order changes (i.e., often). -// Run the fixnavi.pl script to adjust the links to the index order. -// ********************************************************************** - -/*! - \page creator-finding-overview.html - \if defined(qtdesignstudio) - \previouspage creator-diff-editor.html - \else - \previouspage creator-clang-codemodel.html - \endif - - \nextpage creator-editor-finding.html - - \title Finding - - \list - - \li \l{Finding and Replacing} - - The incremental search highlights the matching strings in the - window while typing and the advanced search enables you to - search from currently open projects or files on the file system. - You can conduct incremental and advanced searches in parallel. - - In addition, you can search for symbols when you want to - refactor code. - - \li \l{Searching with the Locator} - - Use the locator to browse - through projects, files, classes, functions, documentation and - file systems. - - \if defined(qtdesignstudio) - \li \l{Jump to the Code} - - Jump to the code for a specific component directly from - the \uicontrol {2D} view or \uicontrol {Navigator} view. - You can also jump to the code of a particular - \uicontrol {State} or \uicontrol {Connection} from their - corresponding views. - \endif - \endlist - -*/ diff --git a/doc/qtcreator/src/editors/creator-locator.qdoc b/doc/qtcreator/src/editors/creator-locator.qdoc index bcdc5278757..292b35ff30c 100644 --- a/doc/qtcreator/src/editors/creator-locator.qdoc +++ b/doc/qtcreator/src/editors/creator-locator.qdoc @@ -2,9 +2,13 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - \previouspage creator-editor-finding.html \page creator-editor-locator.html + \previouspage creator-how-to-advanced-search.html + \if defined(qtdesignstudio) \nextpage creator-jump-to-the-code.html + \else + \nextpage creator-how-tos.html + \endif \title Searching with the Locator diff --git a/doc/qtcreator/src/editors/creator-only/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-only/creator-coding-edit-mode.qdoc index fdabb4f96c2..8e0105b18be 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-coding-edit-mode.qdoc @@ -65,7 +65,11 @@ The editor toolbar is context sensitive and shows items relevant to the file currently open in the editor. - \image qtcreator-editor-toolbar.webp {Edit mode toolbar} + \image qtcreator-editor-toolbar.webp {Editor toolbar for a C++ source file} + \caption Editor toolbar when a C++ source file is open + + \image qtcreator-editor-toolbar-qml.webp {Editor toolbar for a QML file} + \caption Editor toolbar when a QML file is open \table \header @@ -104,6 +108,10 @@ between \QC and language servers, view server capabilities, and set language server preferences. \li \l {Language Servers} + \row + \li \inlineimage icons/live-preview.png + \li Preview changes to QML code live in your application. + \li \l {Previewing on Desktop} \row \li \inlineimage icons/debugger_singleinstructionmode.png \li Run Clang-Tidy or Clazy to analyze the currently open file. diff --git a/doc/qtcreator/src/editors/creator-only/creator-cpp-quick-fixes.qdoc b/doc/qtcreator/src/editors/creator-only/creator-cpp-quick-fixes.qdoc index 0651d02ae38..7df63851dc7 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-cpp-quick-fixes.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-cpp-quick-fixes.qdoc @@ -328,7 +328,20 @@ \endcode \li String literal + \row + \li Enclose in QByteArrayLiteral() + \li Converts a string to a byte array. For example, rewrites + \code + "abcd" + \endcode + as + + \code + QByteArrayLiteral("abcd") + \endcode + + \li String literal \row \li Mark as Translatable \li Marks a string translatable. For example, rewrites \c "abcd" diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc index 80c50359f69..a89ca3c7ef8 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -238,6 +238,10 @@ \image qtcreator-qml-js-editing.webp {QML/JS Editing preferences} + When using \c qmlls from Qt 6.7 or later, it is recommended + to set \l{QT_QML_GENERATE_QMLLS_INI} to \c{ON} in + \uicontrol {Initial Configuration}. + \sa {Manage Language Servers}{How To: Manage Language Servers}, {Enabling and Disabling Messages}, {Language Servers} */ diff --git a/doc/qtcreator/src/editors/creator-only/creator-markdown-editor.qdoc b/doc/qtcreator/src/editors/creator-only/creator-markdown-editor.qdoc index 1942ec84af7..a5cbf186f99 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-markdown-editor.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-markdown-editor.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 /*! @@ -9,9 +9,9 @@ \title Edit Markdown files - Open \l{https://www.markdownguide.org/basic-syntax/}{Markdown} (.md) files - or select \uicontrol File > \uicontrol {New File} > \uicontrol {General} > - \uicontrol {Markdown File} to create a new file. + Open \l{https://www.markdownguide.org/basic-syntax/}{Markdown} (.md) files, + or go to \uicontrol File > \uicontrol {New File} and select + \uicontrol {General} > \uicontrol {Markdown File} to create a new file. \image qtcreator-markdown-editor.webp {Markdown file in Preview and Editor views} @@ -26,4 +26,25 @@ Use the buttons on the editor toolbar to format text as italic (i), bold (b), or inline code (`), and to create links to web sites (\inlineimage icons/linkicon.png). + + \section1 Move to a line and column + + The line and column indicator shows information about the current cursor + position. Select it to activate the locator, and enter a line and column + number to move there. + + \section1 Follow links to web sites + + To follow a link to a web site in the editor: + + \list 1 + \li Place the cursor on the link. + \li Then, do one of the following: + \list + \li Press \key {Ctrl+Click} (or \key {Cmd+Click} on \macos). + \li Press \key F2. + \li Go to \uicontrol {Follow Symbol Under Cursor} in the context + menu. + \endlist + \endlist */ diff --git a/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc b/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc index 5c1c32810e1..eac59c47407 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-scxml.qdoc @@ -98,7 +98,7 @@ state chart. \endtable - To search from the state chart, select \uicontrol {Search} and start typing + To search in the state chart, select \uicontrol {Search} and start typing in the \uicontrol Filter field. The search checks the whole SCXML tree for attributes that match the search criteria. diff --git a/doc/qtcreator/src/editors/creator-search.qdoc b/doc/qtcreator/src/editors/creator-search.qdoc index a5fd8c9e15a..42ca482a5f3 100644 --- a/doc/qtcreator/src/editors/creator-search.qdoc +++ b/doc/qtcreator/src/editors/creator-search.qdoc @@ -1,29 +1,40 @@ -// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! - \previouspage creator-finding-overview.html \page creator-editor-finding.html - \nextpage creator-editor-locator.html + \if defined(qtdesignstudio) + \previouspage studio-finding.html + \nextpage creator-how-to-advanced-search.html + \else + \previouspage creator-how-tos.html + \endif - \title Finding and Replacing + \ingroup creator-how-to-search + + \title Search in current file + + The incremental search highlights the matching strings in the editor while + you type. To search through the currently open file: \list 1 - \li Press \key {Ctrl+F} or select \uicontrol Edit > + \li Press \key {Ctrl+F} or go to \uicontrol Edit > \uicontrol {Find/Replace} > \uicontrol {Find/Replace}. \li In \uicontrol Find, enter the text you are looking for. - \image qtcreator-find-incremental.png + \image qtcreator-find-from-current-file.webp {Search hits highlighted in editor} - If the text is found, all occurrences are highlighted as you type. + All occurrences of the text are highlighted in the editor as you + type. - \li To go to the next occurrence, click \inlineimage icons/next.png - (\uicontrol {Find Next}), or press \key F3. To go to the previous - occurrence click \inlineimage icons/prev.png + \li To go to the next occurrence, select \inlineimage icons/next.png + (\uicontrol {Find Next}), or press \key F3. + + \li To go to the previous occurrence, select \inlineimage icons/prev.png (\uicontrol {Find Previous}), or press \key {Shift+F3}. \li To select all found occurrences in a file, select @@ -31,9 +42,13 @@ \endlist - You can restrict the search in the \uicontrol Find field by selecting - \inlineimage icons/qtcreator-new-search-icon.png - . Select one or several search criteria: + \note Select text before selecting \uicontrol {Find/Replace} to search only + from the selection. + + \section1 Set search criteria + + To restrict the search in the \uicontrol Find box, select + \inlineimage icons/qtcreator-new-search-icon.png and set search criteria: \list @@ -42,38 +57,33 @@ \li To search only whole words, select \uicontrol {Whole Words Only}. - \li To search using regular expressions, select + \li To search using \l{QRegularExpression}{regular expressions}, select \uicontrol {Use Regular Expressions}. Regular expressions used in \QC - are modeled on Perl regular expressions. For more information on - using regular expressions, see the documentation for the - QRegularExpression Class. + are modeled on Perl regular expressions \endlist - \note If you have selected text before selecting \uicontrol {Find/Replace}, the - search is conducted within the selection. + \section1 Replace text - To replace occurrences of the existing text, enter the new text in the - \uicontrol {Replace with} field. + To replace occurrences of the existing text, enter the new text in + \uicontrol {Replace with}. \list - + \li To replace the selected occurrence, select \uicontrol {Replace}. \li To replace the selected occurrence and move to the next one, - click \uicontrol {Find Next} or press \key {Ctrl+=}. - - \li To replace the selected occurrence and move to the previous one, - click \uicontrol {Find Previous}. - - \li To replace all occurrences in the file, click + select \uicontrol {Replace & Find}. + \li To replace all occurrences in the file, select \uicontrol {Replace All}. - \endlist - The \uicontrol {Preserve Case when Replacing} option can be selected to - preserve the case of the original text when replacing. This option is not - compatible with the \uicontrol {Use Regular Expressions} search option, and will - thus be disabled when regular expressions are used. When the option is used, - the case of the occurrence will be conserved, according to the following + \section1 Preserve case when replacing + + To preserve the case of the original text when replacing, select + \inlineimage icons/qtcreator-new-search-icon.png and then select + \uicontrol {Preserve Case when Replacing}. You cannot use this option + together with \uicontrol {Use Regular Expressions}. + + The case of the of the occurrence is preserved according to the following rules: \list @@ -88,163 +98,127 @@ \li Other occurrences are replaced with the new text as entered. \li If an occurrence and the new text have the same prefix or suffix, - then the case of the prefix and/or suffix are preserved, and the - other rules are applied on the rest of the occurrence only. + the case of the prefix and suffix are preserved, and the + other rules are applied to the rest of the occurrence. \endlist + \section1 Highlight search hits + The locations of search hits, breakpoints, and bookmarks in your document are highlighted on the editor scroll bar. To turn highlighting off, select \preferences > \uicontrol {Text Editor} > \uicontrol Display > \uicontrol {Highlight search results on the scrollbar}. - To search using more advanced options, select \uicontrol Advanced. + \image qtcreator-options-text-editor-display.png {Text Editor Display preferences} - \section1 Advanced Search + \section1 Search globally - To search through projects, files on a file system, files in all project - directories, or currently open files: + Select \uicontrol Advanced to open the \uicontrol {Search Results} view where + you can search in currently open projects or files on the file system. Or, + search for symbols to refactor code. + + \if defined(qtcreator) + \sa {Search}{How To: Search} + \else + \sa {Search in projects or file systems} + \endif + + \sa {Search Results View} +*/ + +/*! + \page creator-how-to-advanced-search.html + \if defined(qtdesignstudio) + \previouspage creator-editor-finding.html + \nextpage creator-editor-locator.html + \else + \previouspage creator-how-tos.html + \endif + + \ingroup creator-how-to-search + + \title Search in projects or file systems + + The search scope and search criteria determine where \QC looks for the search + string, how it matches the string with text, and which results it shows. + + \section1 Search in all projects \list 1 - - \li Press \key {Ctrl+Shift+F} or select \uicontrol Edit > + \li Press \key {Ctrl+Shift+F} or go to \uicontrol Edit > \uicontrol {Find/Replace} > \uicontrol {Advanced Find} > \uicontrol {Open Advanced Find}. - - \li Select the scope of your search: - - \list - - \li \uicontrol {All Projects} searches from all currently open - projects. - - \image qtcreator-search-allprojects.png - - \if defined(qtcreator) - If you cannot find some files, see - \l{Specify project contents} for how - to declare them as a part of the project. - \endif - - \li \uicontrol {Current Project} searches from the project you - are currently editing. - - \li \uicontrol {Files in All Project Directories} searches from - all project directories. - - \li \uicontrol {Files in File System} recursively searches from - the selected directory. - - \image qtcreator-search-filesystem.png - - In the \uicontrol {Search engine} field, select the search - engine to use: - - \list - \li Select \uicontrol Internal to use the \QC search - engine. - - \li Select \uicontrol {Git Grep} to use Git to only - search tracked files in the Git work tree. To - restrict the search to the HEAD, a tag, a local or - remote branch, or a commit hash, enter a reference. - Leave the field empty to search through the file - system. - - \if defined(qtcreator) - \li Select \uicontrol {Silver Searcher} to use the - experimental Silver Searcher plugin. For more - information, see \l{Enabling Silver Searcher}. - \endif - - \endlist - - \li \uicontrol {Current File} searches only from the current - file. - - \li \uicontrol {Open Documents} searches from all open files. - - \endlist - - \li In the \uicontrol {File pattern} field, specify file patterns to + \li In \uicontrol Scope, select \uicontrol {All Projects}. + \image qtcreator-search-all-projects.webp {Search Results view} + \li In \uicontrol {Search for}, enter the string you are looking for. + \li Select options to make the search case sensitive, search only whole + words, or use regular expressions. + \li In \uicontrol {File pattern}, specify file patterns to restrict the search to files that match the pattern. For example, to search for a string only in \c {.cpp} and \c {.h} files, enter \c {*.cpp,*.h}. - - \li In the \uicontrol {Exclusion pattern} field, specify file patterns + \li In \uicontrol {Exclusion pattern}, specify file patterns to omit files from the search. - - \li Enter the text you are looking for and click \uicontrol Search. - - \image qtcreator-search-results-matches.webp {Found matches in Search Results} - - \l {Search Results} shows a list of files that have the searched text. - - \list - - \li To see all occurrences in a file, double-click the file name - in the list. - - \li To go to an occurrence, double-click it. - - \li To repeat the search after you have made changes to the - listed files, for example, select - \uicontrol {Search Again}. - - \endlist - + \li Select \uicontrol Search. \endlist - The search results are stored in the search history from which you can - select earlier searches. - - To clear the search results, select the \inlineimage icons/clean_pane_small.png - (\uicontrol Clear) button. - - To expand and collapse the search results, select the - \uicontrol {Expand All} button. - - To start a new search, select the \inlineimage icons/qtcreator-new-search-icon.png - (\uicontrol {New Search}) button. - - \note You can use \uicontrol {Advanced Find} also to search for symbols. For - more information, see \if defined(qtcreator) - \l{Finding Symbols}. - \else - \l{Finding QML Types}. + If you cannot find some files, see \l{Specify project contents} for + how to declare them as a part of the project. \endif - \if defined(qtcreator) - \section1 Enabling Silver Searcher + \section1 Search in the file system - You can use Silver Searcher as a search engine in \QC if you install - Silver Searcher on the development PC. - - \note Enable the SilverSearcher plugin to use it. - - To use Silver Searcher: + In addition to the options available for searching from all projects, you can + select the search engine to use and the directory to search in. \list 1 - - \li Download and install Silver Searcher from - \l {https://geoff.greer.fm/ag/}{The Silver Searcher} or - \l {https://github.com/ggreer/the_silver_searcher}{GitHub}. - - You might have to build Silver Searcher from sources for some - platforms. - - \li When searching, select \uicontrol {Silver Searcher} in the - \uicontrol {Search engine} field. - - \li If Silver Searcher is not found, you might have installed it in a - location that is not found via the \c{PATH} environment variable. - Select \preferences > \uicontrol Environment > \uicontrol System, - then select \uicontrol Change in the \uicontrol Environment field, - and add the entry \c{PATH=/path/to/bin:${PATH}}. - + \li In \uicontrol Scope, select \uicontrol {Files in File System}. + \image qtcreator-search-file-system.webp {Search Results view} + \li In \uicontrol {Search for}, enter the string you are looking for. + \li In \uicontrol {Search engine}, select the search engine to use: + \list + \li Select \uicontrol Internal to use the \QC search + engine. + \li Select \uicontrol {Git Grep} to use Git to only + search tracked files in the Git work tree. To + restrict the search to the HEAD, a tag, a local or + remote branch, or a commit hash, enter a reference. + Leave the field empty to search through the file + system. + \if defined(qtcreator) + \li Select \uicontrol {Silver Searcher} to use the + experimental Silver Searcher plugin. + \endif + \endlist + \li In \uicontrol Directory, select the directory to search in. + Select \uicontrol Browse to locate the directory or + \uicontrol Current to search in the directory where the currently + active file is. + \li Select \uicontrol Search. \endlist - \sa {Enable and disable plugins} + \section1 Search and replace + + To replace occurrences of the existing text: + + \list 1 + \li Select \uicontrol {Search & Replace}. + \image qtcreator-search-results-reg-exp.webp {Search results when searching and replacing} + \li Enter the new text in \uicontrol {Replace with}. + \li Select \uicontrol Replace. + \endlist + + To preserve the case of the original text when replacing, + select \uicontrol {Preserve case}. The rules listed in + \l {Preserve case when replacing} apply here as well. + + \if defined(qtcreator) + \sa {Search}{How To: Search}, {Finding Symbols}, {Turn on Silver Searcher} + \else + \sa {Search in current file} \endif + + \sa {Search Results View} */ diff --git a/doc/qtcreator/src/howto/creator-external-tools.qdoc b/doc/qtcreator/src/howto/creator-external-tools.qdoc index 3f29dfc57bf..dda7eeb62ae 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-silver-searcher.qdoc b/doc/qtcreator/src/howto/creator-only/creator-how-to-silver-searcher.qdoc new file mode 100644 index 00000000000..b632145832d --- /dev/null +++ b/doc/qtcreator/src/howto/creator-only/creator-how-to-silver-searcher.qdoc @@ -0,0 +1,53 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page creator-how-to-silver-searcher.html + \previouspage creator-how-tos.html + + \ingroup creator-how-to-search + + \title Turn on Silver Searcher + + You can use Silver Searcher as a search engine in \QC if you install + Silver Searcher on the computer. + + \image qtcreator-search-file-system.webp {Files in File System scope in Search Results view} + + \note Enable the SilverSearcher plugin to use it. + + To use Silver Searcher: + + \list 1 + \li Download and install Silver Searcher from + \l {https://geoff.greer.fm/ag/}{The Silver Searcher} or + \l {https://github.com/ggreer/the_silver_searcher}{GitHub}. + + You might have to build Silver Searcher from sources for some + platforms. + \li When searching, select \uicontrol {Silver Searcher} in + \uicontrol {Search engine}. + \endlist + + If \QC cannot find Silver Searcher, you might have installed it in a + location that is not set in the \c{PATH} environment variable. + + \section1 Set location of Silver Searcher + + To tell \QC where Silver Searcher is: + + \list 1 + \li Go to \preferences > \uicontrol Environment > \uicontrol System. + \image qtcreator-preferences-environment-system.webp {System preferences} + \li In \uicontrol Environment, select \uicontrol Change. + \li In \uicontrol {Edit Environment}, add the path to the Silver Searcher + executable: + \badcode + PATH=:${PATH} + \endcode + \image qtcreator-edit-environment.webp {Edit Environment dialog} + \endlist + + \sa {Enable and disable plugins}, {Search}{How To: Search}, + {Batch edit environment settings} +*/ 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 6c3fc7fd84e..3696b292635 100644 --- a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc +++ b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc @@ -65,6 +65,10 @@ \generatelist creator-how-to-lsp + \section2 Search + + \generatelist creator-how-to-search + \section1 Manage Kits \generatelist creator-how-to-manage-kits @@ -77,7 +81,7 @@ \generatelist creator-how-to-projects-create - \section2 Create Files + \section2 Add Files \generatelist creator-how-to-projects-files @@ -224,17 +228,48 @@ */ /*! - \page creator-how-to-jump-to-functions-in-qml-code.html + \page creator-how-to-navigate-qml-code.html \previouspage creator-how-tos.html \ingroup creator-how-to-edit - \title Jump to a function in QML code + \title Move in QML code - Open the \uicontrol Locator with \key {Ctrl+K} and type m, followed by a space. - You can now go directly to any QML method in the file. + Find QML methods and types, and move to the C++ implementation of a QML type. - \sa {Edit Code}{How To: Edit Code}, {Edit Mode} + \section1 Locate QML methods + + To locate a QML method: + + \list 1 + \li Press \key {Ctrl+K} to activate the locator. + \li Type m, followed by a space. + \image qtcreator-locator-m-filter.webp {The m filter in the locator} + \li Double-click a QML method in the list to move to it in the editor. + \endlist + + \section1 Find QML types + + To find instances of a QML type in a project, place the cursor on + the type and and do one of the following: + + \list + \li Press \key {Ctrl+Shift+U}. + \li Go to \uicontrol Tools > \uicontrol {QML/JS} > + \uicontrol {Find References to Symbol Under Cursor}. + \endlist + + \section1 Move between QML and C++ + + To move to the C++ implementation of a QML type in the code editor, place the + cursor on the type and do one of the following: + + \list + \li Press \key F2. + \li Go to \uicontrol {Follow Symbol Under Cursor} in the context menu. + \endlist + + \sa {Edit Code}{How To: Edit Code}, {Edit Mode}, {Searching with the Locator} */ /*! @@ -373,34 +408,43 @@ /*! \page creator-how-to-search-and-replace-using-regexp.html - \previouspage creator-how-to-move-between-open-files.html + \previouspage creator-how-tos.html - \ingroup creator-how-to-edit + \ingroup creator-how-to-search - \title Search and replace across files using a regular expression + \title Search and replace using a regular expression - As an example, say you want to replace equality checks (\c {foo == bar}) - with a function (\c {foo.equals(bar)}): + Search and replace across files using regular expressions in the + \uicontrol {Search Results} view. + + Regular expressions used in \QC are modeled on Perl regular expressions. + For more information about using regular expressions, see + \l QRegularExpression. + + For example, to replace equality checks (\c {foo == bar}) with a function + (\c {foo.equals(bar)}): \list 1 - \li Ensure that any work you have done is committed to version control, - as the changes cannot be undone. - \li Press \key {Ctrl+Shift+F} to bring up the \uicontrol {Advanced Find} - form. - \li Change the scope to whatever is appropriate for your search. - \li Under the \uicontrol {Search for} text field, select - the \uicontrol {Use regular expressions} check box. - \li Enter the following text in the \uicontrol {Search for} text field: + \li Commit your changes to version control, as you cannot undo the + replace action. + \li Press \key {Ctrl+Shift+F} or go to \uicontrol Edit > + \uicontrol {Find/Replace} > \uicontrol {Advanced Find} > + \uicontrol {Open Advanced Find} to open \uicontrol {Search Results}. + \image qtcreator-search-reg-exp.webp {Regular expression in Search Results view} + \li In \uicontrol Scope, select whatever is appropriate for your search. + \li Select \uicontrol {Use regular expressions}. + \li Enter the following text in \uicontrol {Search for}: \badcode if \((.*) == (.*)\) \endcode - \li Press \uicontrol {Search & Replace} to see a list of search results. - \li In the \uicontrol {Replace with} text field, enter the following text: + \li Select \uicontrol {Search & Replace} to see a list of search results. + \image qtcreator-search-results-reg-exp.webp {Search results for the regular expression} + \li In \uicontrol {Replace with}, enter the following text: \badcode if (\1.strictlyEquals(\2)) \endcode - \li Press \uicontrol Replace to replace all instances of the text. + \li Select \uicontrol Replace to replace all instances of the text. \endlist - \sa {Advanced Search}, {Edit Code}{How To: Edit Code}, {Edit Mode} + \sa {Edit Code}{How To: Edit Code}, {Search}{How To: Search}, {Edit Mode} */ diff --git a/doc/qtcreator/src/ios/creator-ios-dev.qdoc b/doc/qtcreator/src/ios/creator-ios-dev.qdoc index 6c9ca24dfea..203ab0ff126 100644 --- a/doc/qtcreator/src/ios/creator-ios-dev.qdoc +++ b/doc/qtcreator/src/ios/creator-ios-dev.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! @@ -11,8 +11,6 @@ You can connect iOS devices to your local machine with a USB cable to run applications built for them from \QC. - \note Deployment, running, and debugging on iOS 17 devices are not supported. - To be able to use \QC on \macos, you must install Xcode, and therefore, you already have the tool chain for building applications for iOS. \QC automatically detects the tool chain and creates the necessary @@ -22,6 +20,14 @@ You only need Qt libraries that are built for iOS. You can install them as part of Qt 5.2, or later. + \section1 iOS 17 Devices + + \QC detects iOS 17 devices, and you can deploy and run applications on them. + + However, \QC cannot access application output. Also, debugging and + profiling are not supported because of limitations of the Apple tool for + accessing devices with iOS 17, and later. + \section1 Configuring Devices The connections between \QC and an iOS device are protected by using a diff --git a/doc/qtcreator/src/linux-mobile/creator-embedded-platforms.qdoc b/doc/qtcreator/src/linux-mobile/creator-embedded-platforms.qdoc index 1d1c863befc..14f642e38ba 100644 --- a/doc/qtcreator/src/linux-mobile/creator-embedded-platforms.qdoc +++ b/doc/qtcreator/src/linux-mobile/creator-embedded-platforms.qdoc @@ -76,7 +76,7 @@ \li \l{Connecting Remote Linux Devices} \li \l{Deploying to Remote Linux} \li \l{Remote Linux Run Settings} - \li \l{Running on Remote Linux Devices} + \li \l{Run on remote Linux devices} \li \l{https://doc.qt.io/qtcreator/creator-overview-qtasam.html} {Qt Creator Plugin for Qt Application Manager} \endlist @@ -110,7 +110,7 @@ \li \l{Connecting QNX Devices} \li \l{Deploying to QNX Neutrino} \li \l{QNX Run Settings} - \li \l{Running on QNX Devices} + \li \l{Run on QNX devices} \li \l{Qt for QNX} \endlist diff --git a/doc/qtcreator/src/linux-mobile/creator-projects-running-generic-linux.qdocinc b/doc/qtcreator/src/linux-mobile/creator-projects-how-to-run-generic-linux.qdoc similarity index 55% rename from doc/qtcreator/src/linux-mobile/creator-projects-running-generic-linux.qdocinc rename to doc/qtcreator/src/linux-mobile/creator-projects-how-to-run-generic-linux.qdoc index 995ad8ce4b9..b78dcd5ca20 100644 --- a/doc/qtcreator/src/linux-mobile/creator-projects-running-generic-linux.qdocinc +++ b/doc/qtcreator/src/linux-mobile/creator-projects-how-to-run-generic-linux.qdoc @@ -1,24 +1,25 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! -//! [running on embedded linux] + \page creator-how-to-run-on-remote-linux.html + \previouspage creator-how-tos.html - \section1 Running on Remote Linux Devices + \ingroup creator-how-to-run - To build the application and run it on a device: + \title Run on remote Linux devices + + To build an application and run it on a device: \list 1 - \li Specify a connection to the device. For more information, see - \l{Connecting Remote Linux Devices}. + \li Specify a connection to the device. - \li Click the \uicontrol Run button. + \li Select \inlineimage icons/run_small.png (\uicontrol Run). \endlist - \QC uses the compiler specified in the project build settings - (tool chain) to build the application. + \QC uses the compiler from the kit (tool chain) to build the application. \QC copies the application files to the connected device and runs the application. The application views are @@ -33,5 +34,6 @@ Debugging works transparently if GDB server is installed on the device and it is compatible with the GDB on the host. -//! [running on embedded linux] + \sa {Connecting Remote Linux Devices}, {Run on many platforms}, {Compilers}, + {Embedded Platforms}, {kit-preferences}{Kits} */ diff --git a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc index f70c2dc9d3f..e69626b35cf 100644 --- a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc +++ b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc @@ -31,7 +31,7 @@ \QC contains the following third-party components: - \generatelist{groupsbymodule attributions-qtcreator-tools} + \generatelist{groupsbymodule attributions-tools} The following third-party components are shipped with binary packages of \QC: diff --git a/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc b/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc index 68ca9e4ef54..115e666d0b9 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc @@ -25,11 +25,11 @@ \li \inlineimage front-ui.png \li \inlineimage front-advanced.png \row - \li \b {\l{IDE Overview}} + \li \b {\l{Overview}} If you have not used an integrated development environment (IDE) before, or want to know what kind of IDE \QC is, go to - \l{IDE Overview}. + \l{Overview}. \li \b {\l{User Interface}} If you have not used \QC before, and want to become familiar diff --git a/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc b/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc index 21e648dcfba..fef448c3f15 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-mobile-platforms.qdoc @@ -44,7 +44,7 @@ \list \li \l{Connecting Android Devices} \li \l{Deploying to Android} - \li \l{Running on Multiple Platforms} + \li \l{Run on many platforms} \li \l{Creating a Mobile Application} \li \l{Debugging on Android Devices} \li \l{Qt for Android} @@ -64,7 +64,7 @@ \list \li \l{Connecting iOS Devices} - \li \l{Running on Multiple Platforms} + \li \l{Run on many platforms} \li \l{Creating a Mobile Application} \li \l{Qt for iOS} \endlist diff --git a/doc/qtcreator/src/overview/creator-only/creator-overview.qdoc b/doc/qtcreator/src/overview/creator-only/creator-overview.qdoc index f951b4b52a7..eb0bcf8ec36 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-overview.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-overview.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 // ********************************************************************** @@ -12,147 +12,243 @@ \page creator-overview.html \nextpage creator-quick-tour.html - \title IDE Overview + \title Overview - \QC is an integrated development environment (IDE) that has tools for - designing and developing applications with the Qt application framework. - With Qt you can develop applications and user interfaces once and deploy - them to several desktop, embedded, and mobile operating systems or - web browsers (experimental). \QC has the tools for accomplishing your tasks + \QC is a cross-platform, complete integrated development environment + (IDE) that you can use to create applications for desktop, embedded, + and mobile operating systems, or web browsers. + + With Qt, you can develop applications and user interfaces once and deploy + them to many platforms. \QC has the tools for accomplishing your tasks throughout the whole application development life-cycle, from creating a - project to deploying the application to the target platforms. + project, designing a UI, and writing code to building applications and + deploying them to the target platforms for running and debugging. - \table - \row - \li \inlineimage front-projects.png - \li \inlineimage front-ui.png - \li \inlineimage front-coding.png - \row - \li \b {Managing Projects} + \image qt-app-dev-flow.webp {Application development life-cycle} + \caption Application development life-cycle - To be able to build and run applications, \QC needs the same - information as a compiler would need. It stores the information - in the project settings. + \section1 Projects - You can share projects with other designers and developers across - different development platforms with a common tool for design, - development, and debugging. + First, you need a \e project. \QC relies on a separate build system, such as + CMake, qmake, or Qbs for building the project. From the build system, \QC + gets most of the information it needs to offer services for writing, editing, + and navigating source code, as well as to deploy and run applications. It + stores additional information in the project settings. - \list - \li \l{Creating Projects} + Share projects with other designers and developers across different + development platforms with a common tool for design, development, and + debugging. - To set up a project, you first have to decide what kind - of an application you want to develop: do you want a user - interface based on \l{User Interfaces} - {Qt Quick or Qt Widgets}. Second, you have to choose the - programming language to implement the application logic: - C++ or Python. - \li \l{Version Control Systems} + \list + \li \l{Creating Projects} - The recommended way to set up a project is to use a - version control system. Store and edit only project - source files and configuration files. Do not store - generated files. - \li \l{Configuring Projects} + To set up a project, you first have to decide what kind + of an application you want to develop: do you want a user + interface based on \l{User Interfaces} + {Qt Quick or Qt Widgets}. Second, you have to choose the + programming language to implement the application logic: + C++ or Python. + \li \l{Version Control Systems} - Installation programs and project wizards create default - configurations for \QC and your projects. You can change - the configurations in the \uicontrol Projects mode. - \endlist - For more information, see \l{Manage Projects} - {How To: Manage Projects}. - \li \b {Designing User Interfaces} + The recommended way to set up a project is to use a + version control system. Store and edit only project + source files and configuration files. Do not store + generated files. + \li \l{Configuring Projects} - To create intuitive, modern-looking, fluid user interfaces, you - can use \l{Qt Quick} and \l{Qt Design Studio Manual}{\QDS}: + Installation programs and project wizards create default + configurations for \QC and your projects. Change the + configurations in the \uicontrol Projects mode. + \endlist - \list - \li \l {\QMLD} + For more information, see \l{Manage Projects}{How To: Manage Projects}. - Or, you can enable the \QMLD plugin to visually edit - \l{UI Files}{UI files} (.ui.qml). - \li \l {Converting UI Projects to Applications} + \section1 User Interfaces - Qt Quick UI Prototype projects (.qmlproject) are useful - for creating user interfaces. To use them for application - development, you have to convert them to Qt Quick - Application projects that have project configuration - files (CMakeLists.txt or .pro), .cpp, and .qrc files. - \li \l {UI Files} + \image heartgame-start.webp {Heart Rate Game} - If you switch between \QC and \QDS or cooperate with - designers on a project, you might encounter .ui.qml files. - They are intended to be edited in \QDS only, so you need - to be careful not to break the code. To visually edit the - files in \QC, enable the \QMLD plugin. - \li \l{Using QML Modules with Plugins} + To create intuitive, modern-looking, fluid user interfaces, use \l{Qt Quick} + and \l{Qt Design Studio Manual}{\QDS}: - You can load C++ plugins for QML to simulate data. - \endlist + \list + \li \l {\QMLD} - If you need a traditional user interface that has a clear - structure and enforces a platform look and feel, use - \l{Qt Widgets} and the integrated \l{\QD}. + Or, enable the \QMLD plugin to visually edit \l{UI Files}{UI files} + (.ui.qml). + \li \l {Converting UI Projects to Applications} - For more information, see - \l{Design UIs}{How To: Design UIs}. - \li \b {\l{Coding}} + Qt Quick UI Prototype projects (.qmlproject) are useful + for creating user interfaces. To use them for application + development, you have to convert them to Qt Quick + Application projects that have project configuration + files (CMakeLists.txt or .pro), .cpp, and .qrc files. + \li \l {UI Files} - As an IDE, \QC differs from a text editor in that it knows how - to build and run applications. It understands the C++ and QML - languages as code, not just as plain text. Therefore, it can - offer useful features, such as semantic highlighting, - checking code syntax, code completion, and refactoring actions. - \QC supports some of these services also for other programming - languages, such as Python, for which a \e {language server} is - available that provides information about the code to IDEs. + If you switch between \QC and \QDS or cooperate with + designers on a project, you might encounter .ui.qml files. + They are intended to be edited in \QDS only, so you need + to be careful not to break the code. To visually edit the + files in \QC, enable the \QMLD plugin. + \li \l{Using QML Modules with Plugins} - For more information, see \l{Edit Code}{How To: Edit Code}. - \row - \li \inlineimage front-preview.png - \li \inlineimage front-testing.png - \li \inlineimage front-publishing.png - \row - \li \b {\l{Building and Running}} + Load C++ plugins for QML to simulate data. + \endlist - \QC integrates cross-platform systems for build - automation: qmake, Qbs, CMake, and Autotools. In addition, you - can import - projects as \e {generic projects} and fully control the steps - and commands used to build the project. + If you need a traditional user interface that has a clear structure and + enforces a platform look and feel, use \l{Qt Widgets} and the integrated + \l{\QD}. - You can build applications for, deploy them to, and run them on - the desktop environment or a \l{glossary-device}{device}. - \l{glossary-buildandrun-kit}{Kits}, build, run, and deployment - settings allow you to quickly switch between different setups and - target platforms. + For more information, see \l{Design UIs}{How To: Design UIs} and + \l{UI Design}. - For more information, see \l{Build and Run} - {How To: Build and Run}. - \li \b {\l{Testing}} + \section1 Code - \QC integrates several external native debuggers that you can use - to inspect the state of your application while debugging. + Writing, editing, and navigating in source code are core tasks in application + development. Therefore, the code editor is one of the key components of \QC. + Use the code editor in the \l {Edit Mode}{Edit mode}. - Devices have limited memory and CPU power, so you should use them - carefully. \QC integrates code analysis tools for detecting - memory leaks, profiling function execution, analyzing CPU use, - and eliminating unnecessary complexity of code. Other tools - provide code coverage and visualize trace events. + As an IDE, \QC differs from a text editor in that it knows how to build and + run applications. It understands the C++ and QML languages as code, not just + as plain text. Therefore, it can offer useful features, such as semantic + highlighting, checking code syntax, code completion, and refactoring actions. - \QC integrates several testing frameworks for unit testing - applications and libraries. You can use \QC to create, build, - and run autotests. + \QC supports some of these services also for other programming languages, + such as Python, for which a \e {language server} is available that provides + information about the code to IDEs. - For more information, see \l{Testing}. - \li \b {Publishing} + \section2 Find - \QC enables you to create installation packages for mobile - devices that you can publish to application stores - and other channels. You must make sure that the package contents - meet the requirements for publishing on the channel. + Use the incremental and advanced search to search in currently open projects + or files on the file system or use the locator to browse through projects, + files, classes, functions, documentation, and file systems. - For more information, see \l{Publishing to Google Play}. -\endtable + \section2 Refactor + \e {Code refactoring} is the process of improving and simplifying code + without modifying the existing functionality of an application. Find + and rename symbols and apply predefined actions to refactor code. + + Refactor code to: + + \list + \li Improve internal quality of your application + \li Improve performance and extensibility + \li Improve code readability and maintainability + \li Simplify code structure + \endlist + + \section2 Configure the Editor + + Configure the text editor to suit your specific needs. Change the fonts, + colors, highlighting, and indentation. + + If you are used to the Vim editor, run the main editor in the + \l {FakeVim Modes and Commands}{FakeVim mode}. + + For more information, see \l{Edit Code}{How To: Edit Code} and \l{Editors}. + + \section1 Build, Deploy, and Run + + Run and deploy Qt applications that you build for different target + platforms or with different compilers, debuggers, or Qt versions. + \l{glossary-buildandrun-kit}{Kits} define the tools, \l{glossary-device} + {device} type and other settings to use when building and running your + project. + + \QC integrates cross-platform systems for build automation: CMake, + qmake, Qbs, and Autotools. In addition, you can import projects as + \e {generic projects} and fully control the steps and commands to + build the project. + + Build applications for, deploy them to, and run them on the desktop + environment or a device. With kits, as well as build, run, and deployment + configurations, you can quickly switch between different setups and + target platforms. + + For more information, see \l{Build and Run}{How To: Build and Run}, + \l{Build Systems}, \l{Build Configurations}, and \l{Run Configurations}. + + \section2 On Devices + + When you install tool chains for device types as part of a Qt distribution, + the build and run configurations for the devices might be set up + automatically. However, you might need to install and configure some + additional software on the devices to be able to connect to them + from the computer. + + Deployment configurations handle the packaging and copying of the necessary + files to a location you want to run the executable at, such as the file + system of a device. + + For more information, see \l{Connecting Devices} and \l{Deploying to Devices}. + + \section2 Preview QML + + Use the QML live preview to preview a QML file or an entire Qt Quick + application on the desktop, as well as on Android and embedded Linux + devices. The changes you make to the UI are instantly visible to you + in the preview. + + For more information, see \l{Validating with Target Hardware}. + + \section1 Debug + + A debugger lets you see what happens \e inside an application while it runs + or when it crashes. A debugger can do the following to help you find errors + in the application: + + \list + \li Start the application with parameters that specify its behavior. + \li Stop the application when conditions are met. + \li Examine what happens when the application stops. + \li Make changes in the application when you fix an error and continue + to find the next one. + \endlist + + \QC integrates several external native debuggers for inspecting the state of + your application while debugging. The debugger plugin automatically selects + a suitable native debugger for each kit from the ones it finds on the + computer. Edit the kits to override this choice. + + Connect devices to your computer to debug processes running on the devices. + + For more information, see \l{Debugging}. + + \section1 Analyze + + Devices have limited memory and CPU power, so you should use them carefully. + \QC integrates code analysis tools for detecting memory leaks, profiling + function execution, analyzing CPU use, and eliminating unnecessary complexity + of code. Other tools provide code coverage and visualize trace events. + + Install and configure the tools on your system to use them from \QC. + However, the QML Profiler is installed as part of \QC for profiling + Qt Quick applications. + + For more information, see \l{Analyzing Code}. + + \section1 Autotest + + Create, build and run Qt tests, Qt Quick tests, Google tests, and Boost tests + to unit test applications and libraries. + + Map AUTs (Application Under Test) to \QC and run Squish test suites + and cases from it. + + For more information, see \l{Running Autotests} and \l{Using Squish}. + + \section1 Publish + + Create installation packages for mobile devices that you publish to + application stores and other channels. You must make sure that the + package contents meet the requirements for publishing on the channel. + + For more information, see \l{Publishing to Google Play}. + + \section1 Qt Tools + + \QC is one of many Qt tools for designing and developing applications. + + \image qt-tools.webp {Tools for Qt application development} + \caption Tools for Qt application development */ diff --git a/doc/qtcreator/src/overview/creator-only/creator-reference.qdoc b/doc/qtcreator/src/overview/creator-only/creator-reference.qdoc index 8ad2729814e..c26df6eb3e5 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-reference.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-reference.qdoc @@ -21,12 +21,12 @@ \section1 Build Configurations + Build configurations have everything you need to compile the sources into + binaries. Build configurations use the tools and settings defined in their + corresponding kit. + \annotatedlist creator-reference-build-configurations - \section1 Run Configurations - - \annotatedlist creator-reference-run-configurations - \section1 Editors \annotatedlist creator-reference-editors @@ -59,6 +59,17 @@ \annotatedlist creator-reference-preferences-text-editor + \section1 Run Configurations + + Run configurations start the application in the location where the + \e {deploy configuration} copied it. By default, when you select + \uicontrol Run, \QC builds the project, deploys it to the device + defined in the kit, and runs it there. If you did not make changes + to the project since you last built and deployed it, \QC simply runs + it again. + + \annotatedlist creator-reference-run-configurations + \section1 UI Design Design UIs with either \l{User Interfaces}{Qt Quick or Qt Widgets}. diff --git a/doc/qtcreator/src/overview/creator-only/creator-testing.qdoc b/doc/qtcreator/src/overview/creator-only/creator-testing.qdoc index ec77c0c54aa..26ef6701d69 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-testing.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-testing.qdoc @@ -20,7 +20,7 @@ \li \l{Debugging} - If you install \QC as part of \QSDK, the GNU Symbolic Debugger + If you install \QC with \QOI, the GNU Symbolic Debugger is installed automatically and you should be ready to start debugging after you create a new project. However, you can change the setup to use debugging tools for Windows, for diff --git a/doc/qtcreator/src/overview/license-LGPLv2.0.txt b/doc/qtcreator/src/overview/license-LGPLv2.0.txt new file mode 100644 index 00000000000..6c972cf1596 --- /dev/null +++ b/doc/qtcreator/src/overview/license-LGPLv2.0.txt @@ -0,0 +1,408 @@ +GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth +Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 +because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public Licenses are +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. + +This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any other +libraries whose authors decide to use it. You can use it for your +libraries, too. + +When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for this +service if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone +to deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you +distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or +for a fee, you must give the recipients all the rights that we gave you. +You must make sure that they, too, receive or can get the source code. +If you link a program with the library, you must provide complete object +files to the recipients so that they can relink them with the library, +after making changes to the library and recompiling it. And you must +show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the +library, and (2) offer you this license which gives you legal permission +to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that +everyone understands that there is no warranty for this free library. If +the library is modified by someone else and passed on, we want its +recipients to know that what they have is not the original version, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that companies distributing free software +will individually obtain patent licenses, thus in effect transforming +the program into proprietary software. To prevent this, we have made it +clear that any patent must be licensed for everyone's free use or not +licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. +This license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to +a program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, +in a textual and legal sense, the linked executable is a combined work, +a derivative of the original library, and the ordinary General Public +License treats it as such. + +Because of this blurred distinction, using the ordinary General Public +License for libraries did not effectively promote software sharing, +because most developers did not use the libraries. We concluded that +weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to +achieve this as regards changes in header files, but we have achieved it +as regards changes in the actual functions of the Library.) The hope is +that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + +Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which + contains a notice placed by the copyright holder or other authorized + party saying it may be distributed under the terms of this Library + General Public License (also called "this License"). Each licensee + is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or + translated straightforwardly into another language. (Hereinafter, + translation is included without limitation in the term + "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, complete source code + means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the library. + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output + from such a program is covered only if its contents constitute a + work based on the Library (independent of the use of the Library in + a tool for writing it). Whether that is true depends on what the + Library does and what the program that uses the Library does. 1. You + may copy and distribute verbatim copies of the Library's complete + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any + warranty; and distribute a copy of this License along with the + Library. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange for + a fee. 2. You may modify your copy or copies of the Library or any + portion of it, thus forming a work based on the Library, and copy + and distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: a) The + modified work must itself be a software library. b) You must cause + the files modified to carry prominent notices stating that you + changed the files and the date of any change. c) You must cause the + whole of the work to be licensed at no charge to all third parties + under the terms of this License. d) If a facility in the modified + Library refers to a function or a table of data to be supplied by an + application program that uses the facility, other than as an + argument passed when the facility is invoked, then you must make a + good faith effort to ensure that, in the event an application does + not supply such function or table, the facility still operates, and + performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, the + square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Library, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work + based on the Library, the distribution of the whole must be on the + terms of this License, whose permissions for other licensees extend + to the entire whole, and thus to each and every part regardless of + who wrote it. + + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, the + intent is to exercise the right to control the distribution of + derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the + Library with the Library (or with a work based on the Library) on a + volume of a storage or distribution medium does not bring the other + work under the scope of this License. 3. You may opt to apply the + terms of the ordinary GNU General Public License instead of this + License to a given copy of the Library. To do this, you must alter + all the notices that refer to this License, so that they refer to + the ordinary GNU General Public License, version 2, instead of to + this License. (If a newer version than version 2 of the ordinary GNU + General Public License has appeared, then you can specify that + version instead if you wish.) Do not make any other change in these + notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to all + subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of the + Library into a program that is not a library. 4. You may copy and + distribute the Library (or a portion or derivative of it, under + Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you accompany it with the + complete corresponding machine-readable source code, which must be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange. + + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy the + source code from the same place satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. 5. A + program that contains no derivative of any portion of the Library, + but is designed to work with the Library by being compiled or linked + with it, is called a "work that uses the Library". Such a work, in + isolation, is not a derivative work of the Library, and therefore + falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a "work that uses + the library". The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file + that is part of the Library, the object code for the work may be a + derivative work of the Library even though the source code is not. + Whether this is true is especially significant if the work can be + linked without the Library, or if the work is itself a library. The + threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a + derivative work. (Executables containing this object code plus + portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. 6. + As an exception to the Sections above, you may also compile or link + a "work that uses the Library" with the Library to produce a work + containing portions of the Library, and distribute that work under + terms of your choice, provided that the terms permit modification of + the work for the customer's own use and reverse engineering for + debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are + covered by this License. You must supply a copy of this License. + If the work during execution displays copyright notices, you + must include the copyright notice for the Library among them, as + well as a reference directing the user to the copy of this + License. Also, you must do one of these things: a) Accompany the + work with the complete corresponding machine-readable source + code for the Library including whatever changes were used in the + work (which must be distributed under Sections 1 and 2 above); + and, if the work is an executable linked with the Library, with + the complete machine-readable "work that uses the Library", as + object code and/or source code, so that the user can modify the + Library and then relink to produce a modified executable + containing the modified Library. (It is understood that the user + who changes the contents of definitions files in the Library + will not necessarily be able to recompile the application to use + the modified definitions.) b) Accompany the work with a written + offer, valid for at least three years, to give the same user the + materials specified in Subsection 6a, above, for a charge no + more than the cost of performing this distribution. c) If + distribution of the work is made by offering access to copy from + a designated place, offer equivalent access to copy the above + specified materials from the same place. d) Verify that the user + has already received a copy of these materials or that you have + already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special exception, + the source code distributed need not include anything that is + normally distributed (in either source or binary form) with the + major components (compiler, kernel, and so on) of the operating + system on which the executable runs, unless that component itself + accompanies the executable. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you + cannot use both them and the Library together in an executable that + you distribute. 7. You may place library facilities that are a work + based on the Library side-by-side in a single library together with + other library facilities not covered by this License, and distribute + such a combined library, provided that the separate distribution of + the work based on the Library and of the other library facilities is + otherwise permitted, and provided that you do these two things: a) + Accompany the combined library with a copy of the same work based on + the Library, uncombined with any other library facilities. This must + be distributed under the terms of the Sections above. b) Give + prominent notice with the combined library of the fact that part of + it is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. 8. You may not copy, + modify, sublicense, link with, or distribute the Library except as + expressly provided under this License. Any attempt otherwise to + copy, modify, sublicense, link with, or distribute the Library is + void, and will automatically terminate your rights under this + License. However, parties who have received copies, or rights, from + you under this License will not have their licenses terminated so + long as such parties remain in full compliance. 9. You are not + required to accept this License, since you have not signed it. + However, nothing else grants you permission to modify or distribute + the Library or its derivative works. These actions are prohibited by + law if you do not accept this License. Therefore, by modifying or + distributing the Library (or any work based on the Library), you + indicate your acceptance of this License to do so, and all its terms + and conditions for copying, distributing or modifying the Library or + works based on it. 10. Each time you redistribute the Library (or + any work based on the Library), the recipient automatically receives + a license from the original licensor to copy, distribute, link with + or modify the Library subject to these terms and conditions. You may + not impose any further restrictions on the recipients' exercise of + the rights granted herein. You are not responsible for enforcing + compliance by third parties to this License. 11. If, as a + consequence of a court judgment or allegation of patent infringement + or for any other reason (not limited to patent issues), conditions + are imposed on you (whether by court order, agreement or otherwise) + that contradict the conditions of this License, they do not excuse + you from the conditions of this License. If you cannot distribute so + as to satisfy simultaneously your obligations under this License and + any other pertinent obligations, then as a consequence you may not + distribute the Library at all. For example, if a patent license + would not permit royalty-free redistribution of the Library by all + those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable + under any particular circumstance, the balance of the section is + intended to apply, and the section as a whole is intended to apply + in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is + willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed + to be a consequence of the rest of this License. 12. If the + distribution and/or use of the Library is restricted in certain + countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Library under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. 13. The + Free Software Foundation may publish revised and/or new versions of + the Library General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Library specifies a version number of this License which applies to + it and "any later version", you have the option of following the + terms and conditions either of that version or of any later version + published by the Free Software Foundation. If the Library does not + specify a license version number, you may choose any version ever + published by the Free Software Foundation. 14. If you wish to + incorporate parts of the Library into other free programs whose + distribution conditions are incompatible with these, write to the + author to ask for permission. For software which is copyrighted by + the Free Software Foundation, write to the Free Software Foundation; + we sometimes make exceptions for this. Our decision will be guided + by the two goals of preserving the free status of all derivatives of + our free software and of promoting the sharing and reuse of software + generally. + + NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, + THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE + COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE + RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. + SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS + REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY + COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE + OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH + HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +END OF TERMS AND CONDITIONS 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 6b953d4401d..d03263d4625 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-compiler-explorer-setup.qdoc b/doc/qtcreator/src/projects/creator-only/creator-how-to-create-compiler-explorer-setup.qdoc index 08bc4764434..b35df2e6707 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-how-to-create-compiler-explorer-setup.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-how-to-create-compiler-explorer-setup.qdoc @@ -1,20 +1,20 @@ -// 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 /*! \page creator-how-to-create-compiler-explorer-sessions.html \previouspage creator-how-tos.html - \ingroup creator-how-to-projects-files + \ingroup creator-how-to-analyze \title Create compiler explorer sessions To create a compiler explorer session for a C++ or Python project: \list 1 - \li Select \uicontrol File > \uicontrol {New File} > - \uicontrol {Compiler Explorer} > \uicontrol C++ or \uicontrol Python - > \uicontrol Choose. + \li Go to \uicontrol File > \uicontrol {New File}. + \li Select \uicontrol {Compiler Explorer} > \uicontrol C++ or + \uicontrol Python > \uicontrol Choose. \li Follow the instructions of the wizard to create an example compiler explorer session as a JSON-based \c .qtce file and to open it. @@ -29,7 +29,7 @@ \page creator-how-to-explore-compiler-code.html \previouspage creator-how-tos.html - \ingroup creator-how-to-build + \ingroup creator-how-to-analyze \title Explore compiler code @@ -45,7 +45,7 @@ To check how a compiler sees C++ or Python code: \list 1 - \li Select \uicontrol Tools > \uicontrol {Compiler Explorer} > + \li Go to \uicontrol Tools > \uicontrol {Compiler Explorer} > \uicontrol {Open Compiler Explorer}. \li In the \uicontrol Language field, select the language to compile. \li In the \uicontrol Compiler field, select a compiler to see the @@ -53,6 +53,9 @@ \li Enter code to see the resulting assembly code. \endlist + Hover the mouse over the assembly code, to have the matching source lines + highlighted. + You can also see the application status and output. To explore several compilers, select \uicontrol {Add Compiler}. 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 00000000000..cb4471aeb5d --- /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-building-running.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-building-running.qdoc index 25951a3e804..3f54c09e1a3 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-building-running.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-building-running.qdoc @@ -37,15 +37,6 @@ the sources into binaries. Build configurations use the tools and settings defined in their corresponding kit. - \li \l{Running on Multiple Platforms} - - \e {Run configurations} start the application in the location - where it was copied by the \e{deploy configuration}. By default, - when you select the \uicontrol Run function, \QC builds the project, - deploys it to the device defined in the kit, and runs it there. However, - if you have not made any changes to the project since you last - built and deployed it, \QC simply runs it again. - \li \l{Deploying to Devices} \e {Deploy configurations} handle the packaging and copying of @@ -63,16 +54,5 @@ \endlist - \section1 Related Topics - - \list - - \li \l{Customizing the Build Process} - - By default, running an application also builds it and deploys it to - a location from where it can be run on the device. You can change - the relationship between the build, run, and deploy configurations. - - \endlist - + \sa {Build and Run}{How To: Build and Run} */ diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc index 6071c329274..13b7d6eb9a9 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-building.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -30,25 +30,28 @@ \list 1 - \li Click the \uicontrol {Build and Run Kit Selector} icon (1) or select + \li Select the \uicontrol {Build and Run Kit Selector} icon or go to \uicontrol Build > \uicontrol {Open Build and Run Kit Selector} to select the build and run \l{glossary-buildandrun-kit}{kit} or an \l{Managing Android Virtual Devices (AVD)}{Android device}. - \image qtcreator-kit-selector.png "Kit selector" + \image qtcreator-kit-selector.webp {Kit selector} \li Choose \uicontrol Build > \uicontrol {Build Project} or press \key {Ctrl+B}. - You can also select the \uicontrol Run button (2) to also deploy and run - the application after building it. + Or, select \inlineimage icons/run_small.png (\uicontrol Run) to + deploy and run the application after building it. \endlist - While the application is being built, the \uicontrol Build button (3) - changes to a \uicontrol {Cancel Build} button. To cancel the build, select + While the application is being built, the \inlineimage icons/build.png + (\uicontrol Build) button changes to a \inlineimage icons/cancel-build.png + (\uicontrol {Cancel Build}) button. To cancel the build, select the button, press \key {Alt+Backspace}, or select \uicontrol Build > - \uicontrol {Cancel Build}. If you selected a build command and + \uicontrol {Cancel Build}. + + If you selected a build command and decide you would also like to run the application, you can select the \uicontrol Run button to schedule running the project after building is done. diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc index 48f1bf87611..15156c42014 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-builds-customizing.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -9,35 +9,48 @@ /*! \page creator-build-process-customizing.html - \previouspage creator-setup-webassembly.html - \nextpage creator-testing.html + \previouspage creator-how-tos.html - \title Customizing the Build Process + \ingroup creator-how-to-build - To configure how projects are built, deployed, and run, select + \title Customize the build process + + To configure how projects are built, deployed, and run, go to \preferences > \uicontrol {Build & Run} > \uicontrol General. - \image qtcreator-project-options-deploy.png "Project General preferences" + \image qtcreator-preferences-build-run-general.webp {Build & Run General preferences} - By default, the \uicontrol {Always deploy project before running it} (1) and - \uicontrol {Build the Whole Project} (2) options are enabled. Therefore, - when you select the \uicontrol Run function, \QC checks for changes in the - project files and also builds and deploys the project if necessary. + By default, \uicontrol {Always deploy project before running it} (1) and + \uicontrol {Build the Whole Project} (2) are selected. Therefore, when + you select \inlineimage icons/run_small.png (\uicontrol Run), \QC checks + for changes in the project files and also builds and deploys the project if + necessary. To deploy applications without building them or to just build the application that you want to run, select the appropriate options - in the \uicontrol {Build before deploying} field. + in \uicontrol {Build before deploying}. + + \section1 Stop applications before building By default, the applications that the project contains are stopped - before rebuilding the project. To stop just the current application, - the applications in the same build directory, all applications, - or no applications, select the appropriate option in the - \uicontrol {Stop applications before building} field. + before rebuilding the project. + + To stop just the current application, the applications in the same build + directory, all applications, or no applications, select the appropriate + option in \uicontrol {Stop applications before building}. + + \section1 Use jom On Windows, you can use \c jom instead of \c nmake for building the project - to distribute the compilation process to multiple CPU cores. You can download - \c jom from \l{http://download.qt.io/official_releases/jom}{Qt Downloads}. - To use \c jom, select the \uicontrol {Use jom instead of nmake} check box. - Deselect the check box if you experience build problems. + to distribute the compilation process to multiple CPU cores. + To use \c jom: + + \list 1 + \li Download \c jom from \l{http://download.qt.io/official_releases/jom} + {Qt Downloads}. + \li Select \uicontrol {Use jom instead of nmake}. + \endlist + + Clear the check box if builds fail. */ diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc index 569342b26e3..60fb9686fd6 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc @@ -198,8 +198,8 @@ directory in the \l {File System} view. Declaring files as a part of the project also makes them visible to the - \l{Searching with the Locator}{locator} and \l{Advanced Search} - {project-wide search}. + \l{Searching with the Locator}{locator} and + \l{Search in projects or file systems}{project-wide search}. \section1 CMake Projects diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc index 161874f4b59..3e48923ad36 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-sharing.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 // ********************************************************************** @@ -20,6 +20,8 @@ has the same XML structure as a \e {.user} file, but only has the settings to share. + \note Use \l{CMake Presets} to share CMake project settings. + \section1 Create a shared settings file The easiest way to create a \e {.shared} file is to copy settings from the @@ -70,5 +72,5 @@ a permanent sticky setting that was created just because you wanted to try something out. - \sa {Configuring Projects} + \sa {Configuring Projects}, {CMake Presets} */ diff --git a/doc/qtcreator/src/projects/creator-projects-running.qdoc b/doc/qtcreator/src/projects/creator-projects-running.qdoc index 9c833bf8e7e..43d80f08c8d 100644 --- a/doc/qtcreator/src/projects/creator-projects-running.qdoc +++ b/doc/qtcreator/src/projects/creator-projects-running.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -9,68 +9,76 @@ /*! \page creator-running-targets.html - \if defined(qtdesignstudio) - \previouspage studio-live-preview.html - \else - \previouspage creator-building-targets.html - \endif - \nextpage creator-deployment.html + \previouspage creator-how-tos.html - \title Running on Multiple Platforms + \ingroup creator-how-to-run + + \title Run on many platforms By default, running an application also builds it and deploys it to a - location from where it can be run on the desktop, on a device emulator or + location from where it can run on the desktop, on a device emulator or simulator, or on a \l{glossary-device}{device} that is connected to - the development PC. + the computer. - To run executable files without deploying them first, select \uicontrol Build > - \uicontrol {Run Without Deployment}. To make this the default option, deselect the - \preferences > \uicontrol {Build & Run} > - \uicontrol General > \uicontrol {Always deploy project before running it} - check box. + \section1 Run applications To run applications: \list 1 - \li Click the \uicontrol {Build and Run Kit Selector} icon (1) or select + \li Select the \uicontrol {Build and Run Kit Selector} icon or go to \uicontrol Build > \uicontrol {Open Build and Run Kit Selector} to select the build and run \l{glossary-buildandrun-kit}{kit}. - \image qtcreator-kit-selector.png "Kit selector" + \image qtcreator-kit-selector.webp {Kit selector} - \li Click the \uicontrol Run button (2). + \li Select \inlineimage icons/run_small.png (\uicontrol Run). \endlist + \section1 Run on mobile and embedded devices + + If you have connected \l{Mobile Platforms}{mobile devices} or + \l{Embedded Platforms}{embedded devices} to the computer + or added virtual devices, such as \l{Managing Android Virtual Devices (AVD)} + {Android Virtual Devices (AVD)}, you can select them in the kit selector. + + Select \uicontrol Manage to manage device settings. For example, you can add + AVDs or manually start disconnected AVDs. + + \section1 Select run targets + If your project has several run targets defined, such as \l{Running Autotests}{tests}, you can select them in the kit selector. - \image qtcreator-kit-selector-run-targets.png "Run targets in the kit selector" + \image qtcreator-kit-selector-run-targets.png {Run targets in the kit selector} - If you have connected \l{Mobile Platforms}{mobile devices} or - \l{Embedded Platforms}{embedded devices} to the development PC - or added virtual devices, such as \l{Managing Android Virtual Devices (AVD)} - {Android Virtual Devices (AVD)}, you can select them in the kit selector. - Select \uicontrol Manage to manage device settings. For example, you can add - AVDs or manually start disconnected AVDs. + \section1 Run without deploying - \l {Application Output} displays the status of the - application while it is running. You can select the \uicontrol Run button - to re-run applications without building them first. This is - useful when developing Qt Quick applications because the QML files are - interpreted at runtime. Therefore, the application does not need to be + To run executable files without deploying them first, select \uicontrol Build > + \uicontrol {Run Without Deployment}. + + To make this the default option, go to \preferences > + \uicontrol {Build & Run} > \uicontrol General, and clear + \uicontrol {Always deploy project before running it}. + + \section1 Run without building + + \l {Application Output} displays the status of the application while it is + running. + + \image qtcreator-application-output.webp {Application Output view} + + Select \inlineimage icons/run_small.png (\uicontrol Run) + to re-run applications without building them first. + + This is useful when developing Qt Quick applications because the QML files + are interpreted at runtime. Therefore, the application does not need to be built again if you edited only QML files. This saves time especially if the application has large image files that would need to be bundled into the resource file before running the application. - \image qtcreator-application-output.webp {Application Output view} - - \include linux-mobile/creator-projects-running-generic-linux.qdocinc running on embedded linux - - \if defined(qtcreator) - - \include qnx/creator-projects-running-qnx.qdocinc running on qnx - \sa {Configure projects for running}, {Run Python applications} - \endif + \sa {Configure projects for running}, {Customize the build process}, + {Run on QNX devices}, {Run on remote Linux devices}, + {Run Python applications}, {Supported Platforms} */ diff --git a/doc/qtcreator/src/python/creator-python-development.qdoc b/doc/qtcreator/src/python/creator-python-development.qdoc index ce2452e34a1..d5cd5fe31c9 100644 --- a/doc/qtcreator/src/python/creator-python-development.qdoc +++ b/doc/qtcreator/src/python/creator-python-development.qdoc @@ -19,9 +19,8 @@ \list \li \l{Set up PySide6} \li \l{Create Qt for Python applications} - \li \l{Select the Python interpreter} - \li \l{Create a virtual environment} - \li \l{Create kits for Python interpreters} + \li \l{Select the Python version} + \li \l{Create kits for Python} \li \l{Use Python interactive shell} \li \l{Configure Python language servers} \li \l{Run Python applications} @@ -48,9 +47,10 @@ \section1 Create Qt for Python applications - You can use wizards to create Qt for Python application projects. The wizards + Use wizards to create Qt for Python application projects. The wizards generate a project file, \c {.pyproject}, that lists the files in the Python - project. They also generate a \c {.py} file that has some boilerplate code. + project. They also generate a \c {.py} file that has some boilerplate code + and \c {reguirements.txt} that stores the PySide version of the generated code. In addition, the widget-based UI wizard creates a \c {.ui} file that has a \QD form, and the Qt Quick Application wizard creates a \c {.qml} file that imports Qt Quick controls. @@ -72,50 +72,31 @@ use \c {.pyqtc} files, but we recommend that you choose \c{.pyproject} files for new projects. - \section1 Select the Python interpreter + \section1 Select the Python version - You select the initial Python interpreter when you use the Qt for Python - Application wizard templates to create Python projects. + The \l{kits-tab}{kits} you select for the project in \uicontrol Projects > + \uicontrol {Build & Run} set the Python version to use. - \image qtcreator-new-qt-for-python-app-widgets-project-details.webp {Define Project Details dialog} + The \l {Edit Mode}{Edit mode} toolbar shows the current Python version. - You can see the current Python interpreter on the \uicontrol Edit mode - toolbar. + \image qtcreator-python-interpreter-edit-mode.webp {Python version on the Edit mode toolbar} - \image qtcreator-python-interpreter-edit-mode.webp {Python interpreter on the Edit mode toolbar} + To use another Python version, activate another kit for the project. - You can change the interpreter to use for a particular project in - \uicontrol Projects > \uicontrol Run > \uicontrol Interpreter. + \section1 Create kits for Python - \image qtcreator-python-run-settings.png {Python run settings} - - To see the available interpreters and choose another interpreter, select the - current interpreter, and then select \uicontrol {Manage Python Interpreters}. - Or, select \preferences > \uicontrol Python > \uicontrol Interpreters. + \QC automatically adds all Python versions it can find to the list of + Python versions in \preferences > \uicontrol Python > \uicontrol Interpreters. + It generates kits for the global Python versions that are not inside a + virtual environment. \image qtcreator-python-interpreters.webp {Python Interpreters in Preferences} - You can add and remove interpreters and clean up references to interpreters - that you uninstalled, but that still appear in the list. + You can add and remove Python versions and clean up references to Python + versions that you uninstalled, but that still appear in the list. - To use the selected Python interpreter by default, select - \uicontrol {Make Default}. - - \section1 Create a virtual environment - - To use a clean \l{https://docs.python.org/3/library/venv.html}{Python} - virtual environment (\c venv) that is independent of your global Python - installation for a Qt for Python project, select the - \uicontrol {Create new virtual environment} check box in the project wizard. - Set the directory where to create the environment in - \uicontrol {Path to virtual environment}. - - \section1 Create kits for Python interpreters - - \QC automatically adds all Python interpreters it can find to the list of - interpreters in \preferences > \uicontrol Python > \uicontrol Interpreters. - It generates \l{kits-tab}{kits} for the global Python interpreters that are - not inside a virtual environment. + To use the selected Python version when opening \c {.py} files that don't + belong to a project, select \uicontrol {Make Default}. To use a virtual environment as a kit, select it in \uicontrol Interpreters, and then select \uicontrol {Generate Kit}. @@ -133,5 +114,6 @@ the file, select \uicontrol {REPL Import *}. \sa {Creating a Qt for Python Application with Qt Widgets}, - {Creating a Qt for Python Application with Qt Quick} + {Creating a Qt for Python Application with Qt Quick}, + {Activate kits for a project} */ diff --git a/doc/qtcreator/src/python/creator-python-run-settings.qdoc b/doc/qtcreator/src/python/creator-python-run-settings.qdoc index 3d5d5eab27b..6c6c3b4fe2b 100644 --- a/doc/qtcreator/src/python/creator-python-run-settings.qdoc +++ b/doc/qtcreator/src/python/creator-python-run-settings.qdoc @@ -35,7 +35,7 @@ you select for a kit in \uicontrol Projects > \uicontrol {Build & Run} > \uicontrol Run > \uicontrol {Run Settings}. - \image qtcreator-python-run-settings.png {Python run settings} + \image qtcreator-python-run-settings.webp {Python run settings} The following table summarizes the settings for running Qt for Python applications. @@ -45,7 +45,7 @@ \li Setting \li Value \row - \li \uicontrol Interpreter + \li \uicontrol Python \li Path to the Python executable. \row \li \uicontrol {Buffered output} diff --git a/doc/qtcreator/src/python/creator-tutorial-python-application-qt-widgets.qdoc b/doc/qtcreator/src/python/creator-tutorial-python-application-qt-widgets.qdoc index ae3ef8b93ec..51275cfea4d 100644 --- a/doc/qtcreator/src/python/creator-tutorial-python-application-qt-widgets.qdoc +++ b/doc/qtcreator/src/python/creator-tutorial-python-application-qt-widgets.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 /*! @@ -28,11 +28,10 @@ class: \list 1 - \li Select \uicontrol File > \uicontrol {New Project} > - \uicontrol {Application (Qt for Python)} > \uicontrol {Empty Window} - > \uicontrol Choose. - - The \uicontrol {Project Location} dialog opens. + \li Go to \uicontrol File > \uicontrol {New Project}. + \li Select \uicontrol {Application (Qt for Python)} > + \uicontrol {Empty Window} > \uicontrol Choose to open the + \uicontrol {Project Location} dialog. \image qtcreator-new-qt-for-python-app-widgets-project-location.webp {Project Location dialog} \li In \uicontrol {Name}, enter the project name. For example, \e {hello_world}. @@ -49,16 +48,14 @@ \li In \uicontrol {Project file}, enter a name for the project file. \li Select \uicontrol{Next} or \uicontrol Continue to open the \uicontrol {Define Project Details} dialog. - \image qtcreator-new-qt-for-python-app-widgets-project-details.webp {Define Project Details dialog} + \image qtcreator-new-qt-for-python-app-project-details.webp {Define Project Details dialog} \li In \uicontrol {PySide version}, select the PySide version of the generated code. - \li In \uicontrol {Interpreter}, select the Python interpreter to use for - the project. - \li Select the \uicontrol {Create new virtual environment} check box to - use a clean \l{https://docs.python.org/3/library/venv.html}{Python} - environment that is independent of your global Python installation. - \li In \uicontrol {Path to virtual environment}, specify the directory - where to create the environment. + \li Select \uicontrol{Next} or \uicontrol Continue to open the + \uicontrol {Kit Selection} dialog. + \image qtcreator-new-project-qt-for-python-kit-selection.webp {Selecting a kit for a Python project} + \li Select Qt for Python kits for building, deploying, and running the + project. \li Select \uicontrol{Next} or \uicontrol Continue. \li Review the project settings, and select \uicontrol {Finish} (on Windows and Linux) or \uicontrol Done (on \macos) to create the @@ -71,6 +68,8 @@ \li \c {hellow_world.pyproject}, which lists the files in the Python project. \li \c {mywidget.py}, which has some boilerplate code for a class. + \li \c {reguirements.txt}, which stores the PySide version of the + generated code. \endlist \section1 Adding Qt Widgets Imports diff --git a/doc/qtcreator/src/python/creator-tutorial-python-application-qtquick.qdoc b/doc/qtcreator/src/python/creator-tutorial-python-application-qtquick.qdoc index 868d500ae6c..9357ad2ea70 100644 --- a/doc/qtcreator/src/python/creator-tutorial-python-application-qtquick.qdoc +++ b/doc/qtcreator/src/python/creator-tutorial-python-application-qtquick.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,16 +18,19 @@ \image qtcreator-new-qt-for-python-app-qt-quick-empty-project-ready.webp {A small Qt Quick application} + For more examples of creating Qt for Python applications, see + \l {https://doc.qt.io/qtforpython/tutorials/index.html} + {Qt for Python Examples and Tutorials}. + \section1 Creating an Empty Project To create a Qt for Python application that has a main QML file: \list 1 - \li Select \uicontrol File > \uicontrol {New Project} > - \uicontrol {Application (Qt for Python)} > - \uicontrol {Qt Quick Application - Empty} > \uicontrol Choose. - - The \uicontrol {Project Location} dialog opens. + \li Go to \uicontrol File > \uicontrol {New Project}. + \li Select \uicontrol {Application (Qt for Python)} > + \uicontrol {Qt Quick Application - Empty} > \uicontrol Choose to + open the \uicontrol {Project Location} dialog. \image qtcreator-new-qt-for-python-app-qt-quick-empty-project-location.webp {Project Location dialog} \li In \uicontrol {Name}, enter the project name. For example, \e {hello_world_quick}. @@ -35,17 +38,14 @@ For example, \c {C:\Qt\examples}. \li Select \uicontrol{Next} (on Windows and Linux) or \uicontrol Continue (on \macos) to open the \uicontrol {Define Project Details} dialog. - \image qtcreator-new-qt-for-python-app-qt-quick-empty-project-details.webp {Define Project Details dialog} + \image qtcreator-new-qt-for-python-app-project-details.webp {Define Project Details dialog} \li In \uicontrol {PySide version}, select the PySide version of the generated code. - \li In \uicontrol {Interpreter}, select the Python interpreter to use for - the project. - \li Select the \uicontrol {Create new virtual environment} check box to - use a clean \l{https://docs.python.org/3/library/venv.html}{Python} - environment that is independent of your global Python installation. - \li In \uicontrol {Path to virtual environment}, specify the directory - where to create the environment. - \li Select \uicontrol{Next} or \uicontrol Continue. + \li Select \uicontrol{Next} or \uicontrol Continue to open the + \uicontrol {Kit Selection} dialog. + \image qtcreator-new-project-qt-for-python-kit-selection.webp {Selecting a kit for a Python project} + \li Select Qt for Python kits for building, deploying, and running the + project. \li Review the project settings, and select \uicontrol {Finish} (on Windows and Linux) or \uicontrol Done (on \macos) to create the project. @@ -58,6 +58,8 @@ project. \li \c {main.py}, which has some boilerplate code. \li \c {main.qml}, which imports Qt Quick controls. + \li \c {reguirements.txt}, which stores the PySide version of the + generated code. \endlist \section1 Adding Qt Quick Imports diff --git a/doc/qtcreator/src/qnx/creator-projects-running-qnx.qdocinc b/doc/qtcreator/src/qnx/creator-projects-how-to-run-qnx.qdoc similarity index 65% rename from doc/qtcreator/src/qnx/creator-projects-running-qnx.qdocinc rename to doc/qtcreator/src/qnx/creator-projects-how-to-run-qnx.qdoc index 0d9bc2c43d5..364ee316bcc 100644 --- a/doc/qtcreator/src/qnx/creator-projects-running-qnx.qdocinc +++ b/doc/qtcreator/src/qnx/creator-projects-how-to-run-qnx.qdoc @@ -1,22 +1,21 @@ -// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! -//! [running on qnx] + \page creator-how-to-run-on-qnx.html + \previouspage creator-how-tos.html - \section1 Running on QNX Devices + \ingroup creator-how-to-run + + \title Run on QNX devices + + To build an application and run it on a device: \list 1 - - \li Connect the device to the development PC or to the Wi-Fi network. - - \li Configure the device and specify a connection to it. For more - information, see \l{Connecting QNX Devices}. - + \li Connect the device to the computer or to the Wi-Fi network. + \li Configure the device and specify a connection to it. \li Make sure that your kit has your QNX device set. - - \li Click the \uicontrol Run button. - + \li Select \inlineimage icons/run_small.png (\uicontrol Run). \endlist \QC uses the compiler specified in the QNX tool chain to build the @@ -25,23 +24,23 @@ \note Debugging is currently only fully supported on Linux and \macos. It is not possible to insert breakpoints during runtime on Windows. - \section2 Troubleshooting Errors + \section1 Troubleshoot errors To support running, debugging, and stopping applications from \QC, the QNX Neutrino RTOS has additional command-line tools and services, as described in \l {Qt for QNX}. - \section3 Debug Output Cannot Be Shown + \section2 Debug output cannot be shown For the command-line output to show up in the \uicontrol{Application Output}, - \QC needs to be able to establish an SSH connection to the device. + \QC has to create an SSH connection to the device. This is only possible if QNX Momentics is not running, and the SSH key configured for the device is a 4096-bit key. If these conditions are not met, you will get an error message saying debug output cannot be shown. - \section3 Cannot Run, Debug, or Stop Applications + \section2 Cannot run, debug, or stop applications The board support package (BSP) for the QNX device might be missing some of the following applications that \QC needs to run, debug, and stop @@ -49,5 +48,6 @@ \c printf, \c ps, \c read, \c sed, \c sleep, \c uname, \c slog2info, and \c cat. -//! [running on qnx] + \sa {Connecting QNX Devices}, {Run on many platforms}, {Compilers}, + {Embedded Platforms}, {kit-preferences}{Kits} */ diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc index 5f2daf2737f..933fadb3a0e 100644 --- a/doc/qtcreator/src/qtcreator-toc.qdoc +++ b/doc/qtcreator/src/qtcreator-toc.qdoc @@ -15,7 +15,7 @@ \list \li \l{Getting Started} \list - \li \l{IDE Overview} + \li \l{Overview} \list \li \l{Creating Projects} \li \l{Configuring Projects} @@ -36,11 +36,6 @@ \li \l{Using Text Editing Macros} \li \l{Comparing Files} \endlist - \li \l{Finding} - \list - \li \l{Finding and Replacing} - \li \l{Searching with the Locator} - \endlist \li \l{Refactoring} \li \l{Configuring the Editor} \li \l{Using GitHub Copilot} @@ -54,7 +49,6 @@ \li \l{Previewing in Browsers} \endlist \li \l{Building for Multiple Platforms} - \li \l{Running on Multiple Platforms} \li \l{Deploying to Devices} \list \li \l{Deploying to Android} @@ -74,7 +68,6 @@ \li \l{Connecting Remote Linux Devices} \li \l{Building Applications for the Web} \endlist - \li \l{Customizing the Build Process} \endlist \li \l{Testing} \list @@ -149,6 +142,8 @@ \generatelist creator-how-to-configure-editors \li Manage Language Servers \generatelist creator-how-to-lsp + \li Search + \generatelist creator-how-to-search \endlist \li Manage Kits \generatelist creator-how-to-manage-kits @@ -157,7 +152,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 7c2d8ce775e..eaceebf177d 100644 --- a/doc/qtcreator/src/qtcreator.qdoc +++ b/doc/qtcreator/src/qtcreator.qdoc @@ -41,7 +41,7 @@ \row \li \b {\l{Getting Started}} \list - \li \l{IDE Overview} + \li \l{Overview} \li \l{User Interface} \li \l{Configuring Qt Creator} \li \l{Building and Running an Example} @@ -50,7 +50,6 @@ \li \b {\l{Coding}} \list \li \l{Writing Code} - \li \l{Finding} \li \l{Refactoring} \li \l{Configuring the Editor} \endlist @@ -58,7 +57,6 @@ \list \li \l{Validating with Target Hardware} \li \l{Building for Multiple Platforms} - \li \l{Running on Multiple Platforms} \li \l{Deploying to Devices} \li \l{Connecting Devices} \endlist diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-states-scxml.qdocinc b/doc/qtcreator/src/qtquick/creator-only/qtquick-states-scxml.qdocinc index 0195f0e1cf2..1f0fd5a8e01 100644 --- a/doc/qtcreator/src/qtquick/creator-only/qtquick-states-scxml.qdocinc +++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-states-scxml.qdocinc @@ -19,7 +19,7 @@ If you add animation to the states, you can \l{Validating with Target Hardware}{preview} - or \l{Running on Multiple Platforms}{run} + or \l{Run on many platforms}{run} the application to test the animation. //! [scxml state machines] diff --git a/doc/qtcreator/src/qtquick/qtquick-live-preview-desktop.qdoc b/doc/qtcreator/src/qtquick/qtquick-live-preview-desktop.qdoc index 4e4e609d94c..2f939c69cb5 100644 --- a/doc/qtcreator/src/qtquick/qtquick-live-preview-desktop.qdoc +++ b/doc/qtcreator/src/qtquick/qtquick-live-preview-desktop.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2019 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,44 +8,44 @@ \title Previewing on Desktop - \if defined(qtcreator) - To preview the currently active QML file on the desktop, select - \uicontrol Build > \uicontrol {QML Preview}. - - \image qtcreator-live-preview.png - \else To preview the currently active QML file on the desktop: \list + \if defined(qtcreator) + \li Select \inlineimage icons/live-preview.png (\uicontrol {Live Preview}) + on the \l{Edit Mode}{editor} toolbar. + \image qtcreator-live-preview.webp {Application running on top of the editor view} + \li Select \uicontrol Build > \uicontrol {QML Preview}. + \endlist + \else \li Select the \uicontrol {Live Preview} button on the top toolbar. \li Press \key {Alt+P}. + \image studio-live-preview.webp \endlist - \image studio-live-preview.webp - \endif + To preview any QML file in the project: - To preview any QML file that belongs to the project, \list \li Select the \uicontrol {Live Preview} button on the top toolbar. - \li Right-click the - filename in the \l Projects view, and select \uicontrol {Preview File}. + \li Right-click the filename in the \l Projects view, and select + \uicontrol {Preview File}. \endlist - \if defined(qtdesignstudio) To preview the whole UI, select \uicontrol {Live Preview} when viewing the main QML file of the project. - To view the UI in different sizes, select the zooming level on the toolbar. + \section1 Overriding the Preview Tool - \section1 Selecting the Preview Tool + By default, the QML runtime is used for previewing. - By default, the QML runtime is used for previewing. To use some - other tool, specify it in the \uicontrol {QML viewer} field in the run - settings of the project in the Projects mode. + To use some other tool: - \note Click \inlineimage icons/settings.png - to access the setting options. - - \image studio-run-settings.png "Run settings" + \list 1 + \li Select \inlineimage icons/settings.png to go to + \uicontrol {Run Settings}. + \image studio-run-settings.webp {Run Settings} + \li In \uicontrol {Override device QML viewer}, select the folder where + the preview tool executable is located. + \endlist \endif */ diff --git a/doc/qtcreator/src/qtquick/qtquick-live-preview.qdoc b/doc/qtcreator/src/qtquick/qtquick-live-preview.qdoc index f27ed7e1c2d..2d2ac0b36b6 100644 --- a/doc/qtcreator/src/qtquick/qtquick-live-preview.qdoc +++ b/doc/qtcreator/src/qtquick/qtquick-live-preview.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! @@ -12,35 +12,35 @@ \title Validating with Target Hardware - You can use the live preview feature to preview a UI file or the entire - UI on the desktop, as well as on embedded Linux - devices. The changes you make to the UI are instantly visible - to you in the preview. + Preview a UI file or the entire UI on the desktop, as well as on embedded + Linux devices to instantly view the changes you make to the UI. On Android + devices, the preview shows the snapshot of your project from the moment + you start the preview on the device, not your changes. - In addition, you can use \QDV to run + \if defined(qtcreator) + \image qtcreator-live-preview.webp {Application running on top of the editor} + \else + \image studio-live-preview.webp + \endif + + Or, use \QDV to run \if defined(qtcreator) \l{Create Qt Quick UI Prototypes}{Qt Quick UI projects} \else applications \endif - in most widely-used web browsers on the desktop and in mobile devices This - enables you to easily share your designs with reviewers who don't have \QC. - - \if defined(qtcreator) - \image qtcreator-live-preview.png - \else - \image studio-live-preview.webp - \endif + in most widely-used web browsers on the desktop and in mobile devices and + share your designs with reviewers who don't have \QC. \list \li \l{Previewing on Desktop} - You can preview individual QML files or the whole UI. + Preview individual QML files or the whole UI. \li \l{Previewing on Devices} \if defined(qtcreator) - You can preview Qt Quick applications on devices that you have - connected to the development PC. For more information, see + Preview Qt Quick applications on devices that you + connect to the development PC. For more information, see \l {Connecting Devices}. \else When you install \QDS, everything you need for previewing on @@ -49,10 +49,9 @@ \endif \if defined(qtdesignstudio) - \li \l{Sharing Applications Online} - You can share applications online and view them in a web browser. + Share applications online and view them in a web browser. \li \l{Viewing Applications on Android} @@ -61,7 +60,7 @@ \else \li \l{Previewing in Browsers} - You can open \l{https://designviewer.qt.io/}{\QDV} + Open \l{https://designviewer.qt.io/}{\QDV} in a browser and load applications to it. \endif \endlist diff --git a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc index 2b4ddbdb942..3b8a7d59cf7 100644 --- a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc +++ b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc @@ -68,7 +68,7 @@ To use an \l{Terminal} {internal terminal}, select \preferences > \uicontrol Terminal > \uicontrol {Use internal terminal}. \endif - \li Search from the selected directory. + \li Search in the selected directory. \li View file properties, such as name, path, MIME type, default editor, line endings, indentation, owner, size, last read and modified dates, and permissions. diff --git a/doc/qtcreator/src/user-interface/creator-how-to-view-output.qdoc b/doc/qtcreator/src/user-interface/creator-how-to-view-output.qdoc index b83a54dbe39..95de069becb 100644 --- a/doc/qtcreator/src/user-interface/creator-how-to-view-output.qdoc +++ b/doc/qtcreator/src/user-interface/creator-how-to-view-output.qdoc @@ -60,9 +60,9 @@ \section1 Find and filter output - To search from output, press \key {Ctrl+F} when the view is active. Enter + To search in output, press \key {Ctrl+F} when the view is active. Enter search criteria in the \uicontrol Find field. For more information, see - \l{Finding and Replacing}. + \l{Search in current file}. To filter output, enter a string in the \uicontrol Filter field. diff --git a/doc/qtcreator/src/user-interface/creator-only/creator-reference-terminal-view.qdoc b/doc/qtcreator/src/user-interface/creator-only/creator-reference-terminal-view.qdoc index 2be2fd8a2c3..dac80681896 100644 --- a/doc/qtcreator/src/user-interface/creator-only/creator-reference-terminal-view.qdoc +++ b/doc/qtcreator/src/user-interface/creator-only/creator-reference-terminal-view.qdoc @@ -15,9 +15,8 @@ application or the \uicontrol {Open Terminal} button to open a terminal, it opens as an output view. - To open the terminal in a separate window, select \preferences > - \uicontrol Terminal, and deselet the \uicontrol {Use internal terminal} - check box. + To open the terminal in a separate window, go to \preferences > + \uicontrol Terminal, and clear \uicontrol {Use internal terminal}. On Linux and \macos, you can set the terminal to open by selecting \preferences > \uicontrol Environment > \uicontrol System. @@ -39,12 +38,14 @@ . \li To select a word in a terminal, double-click it. To select the whole line, - triple-click it. + triple-click it. To select all text, select \uicontrol {Select All} + in the context menu or press \key {Ctrl+A}. \li To open links in a browser, files in the editor, or folders in the \l Projects view, hover the mouse over them, and press \key Ctrl. - \li To \l{Finding and Replacing}{search} through the output, press \key {Ctrl+F}. + \li To \l{Search in current file}{search} through the output, press + \key {Ctrl+F}. \li To make the font larger or smaller, select the \inlineimage icons/plus.png and \inlineimage icons/minus.png diff --git a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc index b0a66c421cc..99e3b469cc1 100644 --- a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc +++ b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc @@ -89,7 +89,7 @@ \li Add and remove subprojects. \li Find unused functions. \endif - \li Search from the selected directory. + \li Search in the selected directory. \li Open a terminal window in the project directory. To specify the terminal to use on Linux and \macos, select \preferences > diff --git a/doc/qtcreator/src/user-interface/creator-reference-output-views.qdoc b/doc/qtcreator/src/user-interface/creator-reference-output-views.qdoc index 06ee12f0c33..60b8b72d5af 100644 --- a/doc/qtcreator/src/user-interface/creator-reference-output-views.qdoc +++ b/doc/qtcreator/src/user-interface/creator-reference-output-views.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 // ********************************************************************** @@ -78,25 +78,87 @@ \ingroup creator-reference-output-views \ingroup studio-reference-output-views - \title Search Results + \title Search Results View - \brief Lets you search through projects, files on a file system or the - currently open files. + \brief Search through projects, files on a file system or the + currently open files and view search results. - The search history (1) stores the search results. You can select earlier - searches from the history. + The search scope determines where \QC searches for the search string: - \image qtcreator-search-results.webp {Search Results - criteria} + \list + \li \uicontrol {All Projects} searches in all projects. + \li \uicontrol {Current Project} searches in the currently active + project. + \li \uicontrol {Files in All Project Directories} recursively searches + in all project directories. + \li \uicontrol {Files in File System} recursively searches in + the selected directory. + \li \uicontrol {Current File} searches only from the current + file. + \li \uicontrol {Open Documents} searches in all open files. + \endlist - The figure below shows an example search result for all - occurrences of the search string in the specified directory. + In \uicontrol {File pattern} and \uicontrol {Exclusion pattern}, specify + file patterns to further restrict the search scope. - \image qtcreator-search-results-matches.webp {Search Results - matches found} + The search criteria determine how \QC matches the search + string with text and which results it shows: - For more information about the different search options, see - \l {Finding and Replacing}. + \list + + \li To consider case, select \uicontrol {Case sensitive}. + \li To search only whole words, select \uicontrol {Whole words only}. + \li To search using \l{QRegularExpression}{regular expressions}, select + \uicontrol {Use regular expressions}. + \endlist + + \image qtcreator-search-file-system.webp {Search Results view with search options} + + \section1 Viewing Search Results + + After you select \uicontrol Search or \uicontrol {Search & Replace}, the view + shows a list of files that have search hits. + + \image qtcreator-search-results-matches.webp {Found matches in Search Results} + + To show search hits in the editor: + + \list + + \li To see all occurrences in a file, double-click the file name + in the list. + + \li To go to an occurrence, double-click it. + \endlist + + To repeat the search after you have made changes to the listed files, + for example, select \uicontrol {Search Again}. + + \section1 Search Results View Toolbar + + The toolbar contains options for searching again and navigating search + results: + + \list + \li To clear the search results, select + \inlineimage icons/clean_pane_small.png (\uicontrol Clear). + \li To expand and collapse the search results, select + \inlineimage icons/qtcreator-expand.png (\uicontrol {Expand All}). + \li To start a new search, select + \inlineimage icons/qtcreator-new-search-icon.png + (\uicontrol {New Search}). + \li If the active project has long paths, select \uicontrol {../} + (\uicontrol {Show Paths in Relation to Active Project}) to show + relative paths. + \li To show the results of earlier searches, select them in + \uicontrol History. + \endlist \sa {View output} + + \if defined(qtcreator) + \sa {Search}{How To: Search} + \endif */ /*! diff --git a/doc/qtcreator/src/user-interface/creator-ui.qdoc b/doc/qtcreator/src/user-interface/creator-ui.qdoc index bf4bb2c455d..d70c94d90ee 100644 --- a/doc/qtcreator/src/user-interface/creator-ui.qdoc +++ b/doc/qtcreator/src/user-interface/creator-ui.qdoc @@ -40,7 +40,7 @@ \li \inlineimage numbers/03.png \li Run button \li Run the application on the selected target platform. - \li \l{Running on Multiple Platforms} + \li \l{Run on many platforms} \row \li \inlineimage numbers/04.png \li Debug button diff --git a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc index 9f5f79f3910..0b0cbb0ee20 100644 --- a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc +++ b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc @@ -309,10 +309,11 @@ \section2 Working with Branches To work with Git branches, select \uicontrol {Branches}. The - \uicontrol {Git Branches} sidebar view shows the checked out - branch in bold and underlined in the list of branches. + \uicontrol {Git Branches} view shows a list of branches, as well + as the differences between your local branches and their origin. + The branch you checked out is shown in bold and underlined. - \image qtcreator-vcs-gitbranch.png {Git Branches sidebar view} + \image qtcreator-git-branches.webp {Git Branches view} Old entries and tags are filtered out of the list of branches by default. To include them, select \inlineimage icons/filtericon.png @@ -332,6 +333,20 @@ To refresh the list of branches, select \inlineimage icons/reload_gray.png (\uicontrol Refresh). + \section3 Adding Branches + + To create a new tracking or non-tracking branch, select + \inlineimage icons/plus.png. + + \image qtcreator-git-add-branch.webp {Add Branch dialog} + + To check out the branch when creating it, select + \uicontrol {Checkout new branch}. + + To track the selected branch, select \uicontrol {Track local branch}. + + \section3 Managing Branches + The context menu for a branch has the following functions: \table diff --git a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc index f53830d29f8..e0ab35464c3 100644 --- a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc +++ b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc @@ -110,7 +110,7 @@ You can now build Qt applications in WebAssembly format and run them in a web browser as described in \l {Building for Multiple Platforms} and - \l{Running on Multiple Platforms}. + \l{Run on many platforms}. \sa {Enable and disable plugins} */ diff --git a/doc/qtdesignstudio/images/studio-run-settings.png b/doc/qtdesignstudio/images/studio-run-settings.png deleted file mode 100644 index 0a8fa23612d..00000000000 Binary files a/doc/qtdesignstudio/images/studio-run-settings.png and /dev/null differ diff --git a/doc/qtdesignstudio/images/studio-run-settings.webp b/doc/qtdesignstudio/images/studio-run-settings.webp new file mode 100644 index 00000000000..48f87751e49 Binary files /dev/null and b/doc/qtdesignstudio/images/studio-run-settings.webp differ diff --git a/doc/qtdesignstudio/src/overviews/studio-finding.qdoc b/doc/qtdesignstudio/src/overviews/studio-finding.qdoc new file mode 100644 index 00000000000..bd1e24a5053 --- /dev/null +++ b/doc/qtdesignstudio/src/overviews/studio-finding.qdoc @@ -0,0 +1,39 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page studio-finding.html + \previouspage creator-diff-editor.html + \nextpage creator-editor-finding.html + + \title Finding + + \list + + \li \l{Search in current file} + + The incremental search highlights the matching strings in the + editor while you type. + + \li \l{Search in projects or file systems} + + With advanced search, you can search in currently open projects or + files on the file system. + + \li \l{Searching with the Locator} + + Use the locator to browse + through projects, files, classes, functions, documentation and + file systems. + + \li \l{Jump to the Code} + + Jump to the code for a specific component directly from + the \uicontrol {2D} view or \uicontrol {Navigator} view. + You can also jump to the code of a particular + \uicontrol {State} or \uicontrol {Connection} from their + corresponding views. + + \endlist + +*/ diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc index 369c05d3fad..c2109082982 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc @@ -213,7 +213,8 @@ \endlist \li \l{Finding} \list - \li \l{Finding and Replacing} + \li \l{Search in current file} + \li \l{Search in projects or file systems} \li \l{Searching with the Locator} \li \l{Jump to the Code} \endlist diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index c1cd5c237e9..0d3c5afb87a 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -1,7 +1,7 @@ var Environment = require("qbs.Environment") var File = require("qbs.File") var FileInfo = require("qbs.FileInfo") -var MinimumLLVMVersion = "8.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers. +var MinimumLLVMVersion = "14.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers. var Process = require("qbs.Process") var Utilities = require("qbs.Utilities") diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs index 1fe9fe91354..cb40782268e 100644 --- a/qbs/modules/qtc/qtc.qbs +++ b/qbs/modules/qtc/qtc.qbs @@ -4,16 +4,16 @@ import qbs.FileInfo import qbs.Utilities Module { - property string qtcreator_display_version: '13.0.0-beta1' + property string qtcreator_display_version: '13.0.0-beta2' property string ide_version_major: '12' property string ide_version_minor: '0' - property string ide_version_release: '82' + property string ide_version_release: '83' property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.' + ide_version_release property string ide_compat_version_major: '12' property string ide_compat_version_minor: '0' - property string ide_compat_version_release: '82' + property string ide_compat_version_release: '83' property string qtcreator_compat_version: ide_compat_version_major + '.' + ide_compat_version_minor + '.' + ide_compat_version_release diff --git a/qt_attributions.json b/qt_attributions.json index 2d18d2f51bc..0a9e762dae1 100644 --- a/qt_attributions.json +++ b/qt_attributions.json @@ -258,9 +258,22 @@ "Description": "Syntax highlighting definition ruby.xml", "Homepage": "https://invent.kde.org/frameworks/syntax-highlighting/-/tree/master/data/syntax", "License": "GNU Lesser General Public License v2.0 or later", - "LicenseFile": "doc/qtcreator/src/overview/license-LGPLv2.1.txt", + "LicenseFile": "doc/qtcreator/src/overview/license-LGPLv2.0.txt", "Copyright": "Copyright (C) 2004 by Sebastian Vuorinen (sebastian dot vuorinen at helsinki dot fi). Copyright (C) 2004 by Stefan Lang (langstefan@gmx.at). Copyright (C) 2008 by Robin Pedersen (robinpeder@gmail.com). Copyright (C) 2011 by Miquel Sabaté (mikisabate@gmail.com)." }, + { + "Id": "ksyntaxhighlighting-toml", + "Name": "KSyntaxHighlighting: toml.xml", + "QDocModule": "qtcreator", + "QtParts": ["tools"], + "QtUsage": "Used for the generic highlighter for text files.", + "Path": "src/libs/3rdparty/syntax-highlighting/data/syntax", + "Description": "Syntax highlighting definition toml.xml", + "Homepage": "https://invent.kde.org/frameworks/syntax-highlighting/-/tree/master/data/syntax", + "License": "GNU Lesser General Public License v2.0", + "LicenseFile": "doc/qtcreator/src/overview/license-LGPLv2.0.txt", + "Copyright": "Copyright (C) flying-sheep@web.de" + }, { "Id": "ksyntaxhighlighting-valgrind-suppression", "Name": "KSyntaxHighlighting: valgrind-suppression.xml", @@ -300,6 +313,19 @@ "LicenseFile": "doc/qtcreator/src/overview/license-LGPLv2.1.txt", "Copyright": "Copyright (C) 2004, Jan Villat . Changes by: 2018 Nibaldo González , 2007 Sebastian Pipping ." }, + { + "Id": "ksyntaxhighlighting-yaml", + "Name": "KSyntaxHighlighting: yaml.xml", + "QDocModule": "qtcreator", + "QtParts": ["tools"], + "QtUsage": "Used for the generic highlighter for text files.", + "Path": "src/libs/3rdparty/syntax-highlighting/data/syntax", + "Description": "Syntax highlighting definition yaml.xml", + "Homepage": "https://invent.kde.org/frameworks/syntax-highlighting/-/tree/master/data/syntax", + "License": "GNU Lesser General Public License v2.1", + "LicenseFile": "doc/qtcreator/src/overview/license-LGPLv2.1.txt", + "Copyright": "Copyright (C) Dr Orlovsky MA (dr.orlovsky@gmail.com), Nibaldo González (nibgonz@gmail.com)" + }, { "Id": "std-span-martinmoene", "Name": "std::span Implementation for C++11 and Later", @@ -375,34 +401,6 @@ "LicenseFile": "src/libs/3rdparty/json/LICENSE.MIT", "Copyright": "Copyright 2013-2022 Niels Lohmann" }, - { - "Id": "litehtml-gumbo", - "Name": "Gumbo", - "QDocModule": "qtcreator", - "QtParts": ["tools"], - "QtUsage": "Used by litehtml.", - "Path": "src/libs/qlitehtml/src/3rdparty/litehtml/src/gumbo", - "Description": "Gumbo is an implementation of the HTML5 parsing algorithm implemented as a pure C99 library with no outside dependencies.", - "Homepage": "https://github.com/google/gumbo-parser", - "Version": "0.10.1", - "License": "Apache License 2.0 AND MIT", - "LicenseFile": "src/libs/qlitehtml/src/3rdparty/litehtml/src/gumbo/LICENSE", - "CopyrightFile": "src/libs/qlitehtml/src/3rdparty/GUMBO-AUTHORS.txt" - }, - { - "Id": "litehtml", - "Name": "litehtml", - "QDocModule": "qtcreator", - "QtParts": ["tools"], - "QtUsage": "Used for the help viewer.", - "Path": "src/libs/qlitehtml/src/3rdparty/litehtml", - "Description": "litehtml is the lightweight HTML rendering engine with CSS2/CSS3 support.", - "Homepage": "https://github.com/litehtml/litehtml", - "Version": "v0.5-64-gdb7f59d", - "License": "BSD 3-Clause \"New\" or \"Revised\" License", - "LicenseFile": "src/libs/qlitehtml/src/3rdparty/litehtml/LICENSE", - "Copyright": "Copyright (c) 2013, Yuri Kobets (tordex)" - }, { "Id": "conan.cmake", "Name": "conan.cmake", diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index d323714ba44..b5fc683cbae 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -11,7 +11,7 @@ from utils import TypeCode sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) -from dumper import DumperBase, SubItem +from dumper import DumperBase, SubItem, Children, DisplayFormat, UnnamedSubItem class FakeVoidType(cdbext.Type): @@ -84,10 +84,9 @@ class Dumper(DumperBase): self.check(isinstance(nativeValue, cdbext.Value)) val = self.Value(self) val.name = nativeValue.name() - val._type = self.fromNativeType(nativeValue.type()) # There is no cdb api for the size of bitfields. # Workaround this issue by parsing the native debugger text for integral types. - if val._type.code == TypeCode.Integral: + if nativeValue.type().code() == TypeCode.Integral: try: integerString = nativeValue.nativeDebuggerValue() except UnicodeDecodeError: @@ -106,16 +105,18 @@ class Dumper(DumperBase): base = 16 else: base = 10 - signed = not val._type.name.startswith('unsigned') + signed = not nativeValue.type().name().startswith('unsigned') try: - val.ldata = int(integerString, base).to_bytes(val._type.size(), + val.ldata = int(integerString, base).to_bytes((nativeValue.type().bitsize() +7) // 8, byteorder='little', signed=signed) except: # read raw memory in case the integerString can not be interpreted pass - if val._type.code == TypeCode.Enum: + if nativeValue.type().code() == TypeCode.Enum: val.ldisplay = self.enumValue(nativeValue) - val.isBaseClass = val.name == val._type.name + elif not nativeValue.type().resolved and nativeValue.type().code() == TypeCode.Struct and not nativeValue.hasChildren(): + val.ldisplay = self.enumValue(nativeValue) + val.isBaseClass = val.name == nativeValue.type().name() val.nativeValue = nativeValue val.laddress = nativeValue.address() val.lbitsize = nativeValue.bitsize() @@ -136,6 +137,9 @@ class Dumper(DumperBase): for f in nativeType.fields()]) return typeId + def nativeValueType(self, nativeValue): + return self.fromNativeType(nativeValue.type()) + def fromNativeType(self, nativeType): self.check(isinstance(nativeType, cdbext.Type)) typeId = self.nativeTypeId(nativeType) @@ -150,51 +154,66 @@ class Dumper(DumperBase): if nativeType.name().startswith(''): code = TypeCode.Function elif nativeType.targetName() != nativeType.name(): - targetType = self.lookupType(nativeType.targetName(), nativeType.moduleId()) - if targetType is not None and targetType is not nativeType: - return self.createPointerType(targetType) + return self.createPointerType(nativeType.targetName()) if code == TypeCode.Array: # cdb reports virtual function tables as arrays those ar handled separetly by # the DumperBase. Declare those types as structs prevents a lookup to a # none existing type if not nativeType.name().startswith('__fptr()') and not nativeType.name().startswith(' 0: namespace = name[:namespaceIndex + 2] + self.qtNamespace = lambda: namespace self.qtCustomEventFunc = self.parseAndEvaluate( '%s!%sQObject::customEvent' % (self.qtCoreModuleName(), namespace)).address() @@ -498,7 +518,7 @@ class Dumper(DumperBase): else: val = self.Value(self) val.laddress = value.pointer() - val._type = value.type.dereference() + val._type = DumperBase.Type(self, value.type.targetName) val.nativeValue = value.nativeValue return val @@ -519,3 +539,424 @@ class Dumper(DumperBase): def symbolAddress(self, symbolName): res = self.nativeParseAndEvaluate(symbolName) return None if res is None else res.address() + + def putItemX(self, value): + #DumperBase.warn('PUT ITEM: %s' % value.stringify()) + + typeobj = value.type # unqualified() + typeName = typeobj.name + + self.addToCache(typeobj) # Fill type cache + + if not value.lIsInScope: + self.putSpecialValue('optimizedout') + #self.putType(typeobj) + #self.putSpecialValue('outofscope') + self.putNumChild(0) + return + + if not isinstance(value, self.Value): + raise RuntimeError('WRONG TYPE IN putItem: %s' % type(self.Value)) + + # Try on possibly typedefed type first. + if self.tryPutPrettyItem(typeName, value): + if typeobj.code == TypeCode.Pointer: + self.putOriginalAddress(value.address()) + else: + self.putAddress(value.address()) + return + + if typeobj.code == TypeCode.Pointer: + self.putFormattedPointer(value) + return + + self.putAddress(value.address()) + if value.lbitsize is not None: + self.putField('size', value.lbitsize // 8) + + if typeobj.code == TypeCode.Function: + #DumperBase.warn('FUNCTION VALUE: %s' % value) + self.putType(typeobj) + self.putSymbolValue(value.pointer()) + self.putNumChild(0) + return + + if typeobj.code == TypeCode.Enum: + #DumperBase.warn('ENUM VALUE: %s' % value.stringify()) + self.putType(typeobj.name) + self.putValue(value.display()) + self.putNumChild(0) + return + + if typeobj.code == TypeCode.Array: + #DumperBase.warn('ARRAY VALUE: %s' % value) + self.putCStyleArray(value) + return + + if typeobj.code == TypeCode.Integral: + #DumperBase.warn('INTEGER: %s %s' % (value.name, value)) + val = value.value() + self.putNumChild(0) + self.putValue(val) + self.putType(typeName) + return + + if typeobj.code == TypeCode.Float: + #DumperBase.warn('FLOAT VALUE: %s' % value) + self.putValue(value.value()) + self.putNumChild(0) + self.putType(typeobj.name) + return + + if typeobj.code in (TypeCode.Reference, TypeCode.RValueReference): + #DumperBase.warn('REFERENCE VALUE: %s' % value) + val = value.dereference() + if val.laddress != 0: + self.putItem(val) + else: + self.putSpecialValue('nullreference') + self.putBetterType(typeName) + return + + if typeobj.code == TypeCode.Complex: + self.putType(typeobj) + self.putValue(value.display()) + self.putNumChild(0) + return + + self.putType(typeName) + + if value.summary is not None and self.useFancy: + self.putValue(self.hexencode(value.summary), 'utf8:1:0') + self.putNumChild(0) + return + + self.putExpandable() + self.putEmptyValue() + #DumperBase.warn('STRUCT GUTS: %s ADDRESS: 0x%x ' % (value.name, value.address())) + if self.showQObjectNames: + #with self.timer(self.currentIName): + self.putQObjectNameValue(value) + if self.isExpanded(): + self.putField('sortable', 1) + with Children(self): + baseIndex = 0 + for item in self.listValueChildren(value): + if item.name.startswith('__vfptr'): + with SubItem(self, '[vptr]'): + # int (**)(void) + self.putType(' ') + self.putSortGroup(20) + self.putValue(item.name) + n = 100 + if self.isExpanded(): + with Children(self): + n = self.putVTableChildren(item, n) + self.putNumChild(n) + continue + + if item.isBaseClass: + baseIndex += 1 + # We cannot use nativeField.name as part of the iname as + # it might contain spaces and other strange characters. + with UnnamedSubItem(self, "@%d" % baseIndex): + self.putField('iname', self.currentIName) + self.putField('name', '[%s]' % item.name) + self.putSortGroup(1000 - baseIndex) + self.putAddress(item.address()) + self.putItem(item) + continue + + + with SubItem(self, item.name): + self.putItem(item) + if self.showQObjectNames: + self.tryPutQObjectGuts(value) + + + def putFormattedPointerX(self, value: DumperBase.Value): + self.putOriginalAddress(value.address()) + pointer = value.pointer() + self.putAddress(pointer) + if pointer == 0: + self.putType(value.type) + self.putValue('0x0') + return + + typeName = value.type.name + + try: + self.readRawMemory(pointer, 1) + except: + # Failure to dereference a pointer should at least + # show the value of a pointer. + #DumperBase.warn('BAD POINTER: %s' % value) + self.putValue('0x%x' % pointer) + self.putType(typeName) + return + + if self.currentIName.endswith('.this'): + self.putDerefedPointer(value) + return + + displayFormat = self.currentItemFormat(value.type.name) + + if value.type.targetName == 'void': + #DumperBase.warn('VOID POINTER: %s' % displayFormat) + self.putType(typeName) + self.putSymbolValue(pointer) + return + + if displayFormat == DisplayFormat.Raw: + # Explicitly requested bald pointer. + #DumperBase.warn('RAW') + self.putType(typeName) + self.putValue('0x%x' % pointer) + self.putExpandable() + if self.currentIName in self.expandedINames: + with Children(self): + with SubItem(self, '*'): + self.putItem(value.dereference()) + return + + limit = self.displayStringLimit + if displayFormat in (DisplayFormat.SeparateLatin1String, DisplayFormat.SeparateUtf8String): + limit = 1000000 + if self.tryPutSimpleFormattedPointer(pointer, typeName, + value.type.targetName, displayFormat, limit): + self.putExpandable() + return + + if DisplayFormat.Array10 <= displayFormat and displayFormat <= DisplayFormat.Array10000: + n = (10, 100, 1000, 10000)[displayFormat - DisplayFormat.Array10] + self.putType(typeName) + self.putItemCount(n) + self.putArrayData(value.pointer(), n, value.type.targetName) + return + + #DumperBase.warn('AUTODEREF: %s' % self.autoDerefPointers) + #DumperBase.warn('INAME: %s' % self.currentIName) + if self.autoDerefPointers: + # Generic pointer type with AutomaticFormat, but never dereference char types: + if value.type.targetName not in ( + 'char', + 'signed char', + 'int8_t', + 'qint8', + 'unsigned char', + 'uint8_t', + 'quint8', + 'wchar_t', + 'CHAR', + 'WCHAR', + 'char8_t', + 'char16_t', + 'char32_t' + ): + self.putDerefedPointer(value) + return + + #DumperBase.warn('GENERIC PLAIN POINTER: %s' % value.type) + #DumperBase.warn('ADDR PLAIN POINTER: 0x%x' % value.laddress) + self.putType(typeName) + self.putSymbolValue(pointer) + self.putExpandable() + if self.currentIName in self.expandedINames: + with Children(self): + with SubItem(self, '*'): + self.putItem(value.dereference()) + + + def putCStyleArray(self, value): + arrayType = value.type + innerType = arrayType.ltarget + address = value.address() + if address: + self.putValue('@0x%x' % address, priority=-1) + else: + self.putEmptyValue() + self.putType(arrayType) + + displayFormat = self.currentItemFormat() + arrayByteSize = arrayType.size() + n = self.arrayItemCountFromTypeName(value.type.name, 100) + + p = value.address() + if displayFormat != DisplayFormat.Raw and p: + if innerType.name in ( + 'char', + 'int8_t', + 'qint8', + 'wchar_t', + 'unsigned char', + 'uint8_t', + 'quint8', + 'signed char', + 'CHAR', + 'WCHAR', + 'char8_t', + 'char16_t', + 'char32_t' + ): + self.putCharArrayHelper(p, n, innerType, self.currentItemFormat(), + makeExpandable=False) + else: + self.tryPutSimpleFormattedPointer(p, arrayType, innerType, + displayFormat, arrayByteSize) + self.putNumChild(n) + + if self.isExpanded(): + if n > 100: + addrStep = innerType.size() + with Children(self, n, innerType, addrBase=address, addrStep=addrStep): + for i in self.childRange(): + self.putSubItem(i, self.createValue(address + i * addrStep, innerType)) + else: + with Children(self): + n = 0 + for item in self.listValueChildren(value): + with SubItem(self, n): + n += 1 + self.putItem(item) + + + def putArrayData(self, base, n, innerType, childNumChild=None): + self.checkIntType(base) + self.checkIntType(n) + addrBase = base + innerType = self.createType(innerType) + innerSize = innerType.size() + self.putNumChild(n) + #DumperBase.warn('ADDRESS: 0x%x INNERSIZE: %s INNERTYPE: %s' % (addrBase, innerSize, innerType)) + enc = innerType.simpleEncoding() + maxNumChild = self.maxArrayCount() + if enc: + self.put('childtype="%s",' % innerType.name) + self.put('addrbase="0x%x",' % addrBase) + self.put('addrstep="0x%x",' % innerSize) + self.put('arrayencoding="%s",' % enc) + self.put('endian="%s",' % self.packCode) + if n > maxNumChild: + self.put('childrenelided="%s",' % n) + n = maxNumChild + self.put('arraydata="') + self.put(self.readMemory(addrBase, n * innerSize)) + self.put('",') + else: + with Children(self, n, innerType, childNumChild, maxNumChild, + addrBase=addrBase, addrStep=innerSize): + for i in self.childRange(): + self.putSubItem(i, self.createValue(addrBase + i * innerSize, innerType)) + + def tryPutSimpleFormattedPointer(self, ptr, typeName, innerType, displayFormat, limit): + if isinstance(innerType, self.Type): + innerType = innerType.name + if displayFormat == DisplayFormat.Automatic: + if innerType in ('char', 'signed char', 'unsigned char', 'uint8_t', 'CHAR'): + # Use UTF-8 as default for char *. + self.putType(typeName) + (length, shown, data) = self.readToFirstZero(ptr, 1, limit) + self.putValue(data, 'utf8', length=length) + if self.isExpanded(): + self.putArrayData(ptr, shown, innerType) + return True + + if innerType in ('wchar_t', 'WCHAR'): + self.putType(typeName) + charSize = self.lookupType('wchar_t').size() + (length, data) = self.encodeCArray(ptr, charSize, limit) + if charSize == 2: + self.putValue(data, 'utf16', length=length) + else: + self.putValue(data, 'ucs4', length=length) + return True + + if displayFormat == DisplayFormat.Latin1String: + self.putType(typeName) + (length, data) = self.encodeCArray(ptr, 1, limit) + self.putValue(data, 'latin1', length=length) + return True + + if displayFormat == DisplayFormat.SeparateLatin1String: + self.putType(typeName) + (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) + (length, data) = self.encodeCArray(ptr, 1, limit) + self.putValue(data, 'utf8', length=length) + return True + + if displayFormat == DisplayFormat.SeparateUtf8String: + self.putType(typeName) + (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) + (length, data) = self.encodeCArray(ptr, 1, limit) + self.putValue(data, 'local8bit', length=length) + return True + + if displayFormat == DisplayFormat.Utf16String: + self.putType(typeName) + (length, data) = self.encodeCArray(ptr, 2, limit) + self.putValue(data, 'utf16', length=length) + return True + + if displayFormat == DisplayFormat.Ucs4String: + self.putType(typeName) + (length, data) = self.encodeCArray(ptr, 4, limit) + self.putValue(data, 'ucs4', length=length) + return True + + return False + + def putDerefedPointer(self, value): + derefValue = value.dereference() + savedCurrentChildType = self.currentChildType + self.currentChildType = value.type.targetName + self.putType(value.type.targetName) + derefValue.name = '*' + derefValue.autoDerefCount = value.autoDerefCount + 1 + + if derefValue.type.code == TypeCode.Pointer: + self.putField('autoderefcount', '{}'.format(derefValue.autoDerefCount)) + + self.putItem(derefValue) + self.currentChildType = savedCurrentChildType + + def extractPointer(self, value): + code = 'I' if self.ptrSize() == 4 else 'Q' + return self.extractSomething(value, code, 8 * self.ptrSize()) + + def createValue(self, datish, typish): + if self.isInt(datish): # Used as address. + return self.createValueFromAddressAndType(datish, typish) + if isinstance(datish, bytes): + val = self.Value(self) + if isinstance(typish, self.Type): + val._type = typish + else: + val._type = self.Type(self, typish) + #DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish))) + val.ldata = datish + val.check() + return val + raise RuntimeError('EXPECTING ADDRESS OR BYTES, GOT %s' % type(datish)) + + def createValueFromAddressAndType(self, address, typish): + val = self.Value(self) + if isinstance(typish, self.Type): + val._type = typish + else: + val._type = self.Type(self, typish) + val.laddress = address + if self.useDynamicType: + val._type = val.type.dynamicType(address) + return val diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index ad25ad2dbeb..836b1860cb2 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -420,7 +420,7 @@ class DumperBase(): def charType(self): result = self.lookupType('char') - self.intType = lambda: result + self.charType = lambda: result return result def ptrSize(self): @@ -635,7 +635,7 @@ class DumperBase(): def putCharArrayValue(self, data, length, charSize, displayFormat=DisplayFormat.Automatic): shown = self.computeLimit(length, self.displayStringLimit) - mem = self.readMemory(data, shown) + mem = self.readMemory(data, shown * charSize) if charSize == 1: if displayFormat in (DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String): encodingType = 'latin1' @@ -3041,7 +3041,7 @@ class DumperBase(): or self.type.name.startswith('unsigned ') \ or self.type.name.find(' unsigned ') != -1 if bitsize is None: - bitsize = self.type.bitsize() + bitsize = self.type.lbitsize return self.extractInteger(bitsize, unsigned) def floatingPoint(self): @@ -3512,26 +3512,40 @@ class DumperBase(): tdata.moduleName = self.moduleName return tdata + @property + def bitsize(self): + if callable(self.lbitsize): + self.lbitsize = self.lbitsize() + return self.lbitsize + class Type(): def __init__(self, dumper, typeId): - self.typeId = typeId + self.typeId = typeId.replace('@', dumper.qtNamespace()) self.dumper = dumper - self.tdata = dumper.typeData.get(typeId, None) - if self.tdata is None: - #DumperBase.warn('USING : %s' % self.typeId) - self.dumper.lookupType(self.typeId) - self.tdata = self.dumper.typeData.get(self.typeId) + self.initialized = False def __str__(self): #return self.typeId return self.stringify() + @property + def tdata(self): + if not self.initialized: + self.initialized = True + self.data = self.dumper.typeData.get(self.typeId, None) + if self.data is None: + #DumperBase.warn('USING : %s' % self.typeId) + self.dumper.lookupType(self.typeId) + self.data = self.dumper.typeData.get(self.typeId) + return self.data + + def setTdata(self, tdata): + self.initialized = True + self.data = tdata + @property def name(self): - tdata = self.dumper.typeData.get(self.typeId) - if tdata is None: - return self.typeId - return tdata.name + return self.typeId if self.tdata is None else self.tdata.name @property def code(self): @@ -3539,7 +3553,7 @@ class DumperBase(): @property def lbitsize(self): - return self.tdata.lbitsize + return self.tdata.bitsize @property def lbitpos(self): @@ -3547,15 +3561,25 @@ class DumperBase(): @property def ltarget(self): + if isinstance(self.tdata.ltarget, str): + self.tdata.ltarget = self.dumper.createType(self.tdata.ltarget) return self.tdata.ltarget + @property + def targetName(self): + if self.tdata.ltarget is None: + return '' + return self.tdata.ltarget if isinstance(self.tdata.ltarget, str) else self.tdata.ltarget.name + @property def moduleName(self): + if callable(self.tdata.moduleName): + self.tdata.moduleName = self.tdata.moduleName() return self.tdata.moduleName def stringify(self): return 'Type(name="%s",bsize=%s,code=%s)' \ - % (self.tdata.name, self.tdata.lbitsize, self.tdata.code) + % (self.tdata.name, self.lbitsize, self.tdata.code) def __getitem__(self, index): if self.dumper.isInt(index): @@ -3659,7 +3683,7 @@ class DumperBase(): def alignment(self): if self.tdata.code == TypeCode.Typedef: - return self.tdata.ltarget.alignment() + return self.ltarget.alignment() if self.tdata.code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum): if self.tdata.name in ('double', 'long long', 'unsigned long long'): # Crude approximation. @@ -3678,7 +3702,7 @@ class DumperBase(): return self.dumper.createPointerType(self) def target(self): - return self.tdata.ltarget + return self.ltarget def stripTypedefs(self): if isinstance(self, self.dumper.Type) and self.code != TypeCode.Typedef: @@ -3687,7 +3711,7 @@ class DumperBase(): return self.ltarget def size(self): - bs = self.bitsize() + bs = self.lbitsize if bs % 8 != 0: DumperBase.warn('ODD SIZE: %s' % self) return (7 + bs) >> 3 @@ -3797,12 +3821,12 @@ class DumperBase(): return val def createPointerType(self, targetType): - if not isinstance(targetType, self.Type): - raise RuntimeError('Expected type in createPointerType(), got %s' + if not isinstance(targetType, (str, self.Type)): + raise RuntimeError('Expected type or str in createPointerType(), got %s' % type(targetType)) - typeId = targetType.typeId + ' *' + typeId = (targetType if isinstance(targetType, str) else targetType.typeId) + ' *' tdata = self.TypeData(self, typeId) - tdata.name = targetType.name + '*' + tdata.name = (targetType if isinstance(targetType, str) else targetType.name) + '*' tdata.lbitsize = 8 * self.ptrSize() tdata.code = TypeCode.Pointer tdata.ltarget = targetType @@ -3927,7 +3951,7 @@ class DumperBase(): tdata = self.typeData.get(typish, None) if tdata is not None: if tdata.lbitsize is not None: - if tdata.lbitsize > 0: + if callable(tdata.lbitsize) or tdata.lbitsize > 0: return self.Type(self, typish) knownType = self.lookupType(typish) @@ -3944,7 +3968,7 @@ class DumperBase(): if typish.endswith('*'): tdata.code = TypeCode.Pointer tdata.lbitsize = 8 * self.ptrSize() - tdata.ltarget = self.createType(typish[:-1].strip()) + tdata.ltarget = typish[:-1].strip() typeobj = self.Type(self, tdata.typeId) #DumperBase.warn('CREATE TYPE: %s' % typeobj.stringify()) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 7558bcdfa47..7809a6a3dcb 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -419,7 +419,7 @@ class Dumper(DumperBase): targetTypeName = typeName[0:pos1].strip() #DumperBase.warn("TARGET TYPENAME: %s" % targetTypeName) targetType = self.fromNativeType(nativeTargetType) - targetType.tdata = targetType.tdata.copy() + targetType.setTdata(targetType.tdata.copy()) targetType.tdata.name = targetTypeName return self.createArrayType(targetType, count) if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x @@ -1583,7 +1583,8 @@ class Dumper(DumperBase): result += ',ignorecount="%d"' % loc.GetIgnoreCount() result += ',file="%s"' % toCString(lineEntry.GetFileSpec()) result += ',line="%d"' % lineEntry.GetLine() - result += ',addr="%s"},' % addr.GetFileAddress() + result += ',addr="%s"' % addr.GetLoadAddress(self.target) + result += ',faddr="%s"},' % addr.GetFileAddress() result += ']' if lineEntry is not None: result += ',file="%s"' % toCString(lineEntry.GetFileSpec()) diff --git a/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml b/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml index 55f367ffb9c..d81dafe7bb3 100644 --- a/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml +++ b/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml @@ -18,7 +18,7 @@ Rectangle { Text { id: text2 color: "#ffffff" - text: qsTrId("Restart") + text: qsTr("Restart") anchors.verticalCenter: parent.verticalCenter font.pixelSize: 12 anchors.horizontalCenter: parent.horizontalCenter diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp index b7b83acf554..5787dfa4953 100644 --- a/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/example/example.cpp @@ -11,7 +11,7 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; // The first subfolder is the libraryName followed by the regular // folder structure: LibraryName/Subfolder - const QUrl url(u"qrc:/ExampleProjectApp/example/example.qml"_qs); + const QUrl url(QStringLiteral("qrc:/ExampleProjectApp/example/example.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp index 155667fb122..07725874746 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp @@ -11,7 +11,7 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; @if !%{HasLoadFromModule} - const QUrl url(u"qrc:/%{JS: value('ProjectName')}/Main.qml"_qs); + const QUrl url(QStringLiteral("qrc:/%{JS: value('ProjectName')}/Main.qml")); @endif @if %{HasFailureSignal} QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/main.cpp index 08698bb6bea..9c5b49e9f00 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/main.cpp @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; @if %{IsQt6} - const QUrl url(u"qrc:/%{JS: value('ProjectName')}/main.qml"_qs); + const QUrl url(QStringLiteral("qrc:/%{JS: value('ProjectName')}/main.qml")); @else const QUrl url(QStringLiteral("qrc:/main.qml")); @endif diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme index a7dcedd104a..c2846fa0940 100644 --- a/share/qtcreator/themes/dark.creatortheme +++ b/share/qtcreator/themes/dark.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=dark.figmatokens ThemeName=Dark PreferredStyles= DefaultTextEditorColorScheme=dark.xml @@ -406,39 +407,6 @@ Debugger_WatchItem_ValueChanged=ffff6666 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - dark mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff8f8f8 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ff1f1f1f -Token_Background_Muted=ff262626 -Token_Background_Subtle=ff2e2e2e -Token_Foreground_Default=ff5a5a5a -Token_Foreground_Muted=ff3e3e3e -Token_Foreground_Subtle=ff303030 -Token_Text_Default=fff8f8f8 -Token_Text_Muted=ffaeaeae -Token_Text_Subtle=ff595959 -Token_Stroke_Strong=ffeeeeee -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ff3a3a3a -Token_Notification_Alert=ffc98014 -Token_Notification_Success=ff1f9b5d -Token_Notification_Neutral=ff016876 -Token_Notification_Danger=ffb22245 - -Welcome_TextColor=text -Welcome_ForegroundPrimaryColor=ffa3a3a3 -Welcome_ForegroundSecondaryColor=ff808080 -Welcome_BackgroundPrimaryColor=normalBackground -Welcome_BackgroundSecondaryColor=shadowBackground -Welcome_HoverColor=ff404040 -Welcome_AccentColor=ff57d658 -Welcome_LinkColor=ff67e668 -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=ff444444 diff --git a/share/qtcreator/themes/dark.figmatokens b/share/qtcreator/themes/dark.figmatokens new file mode 100644 index 00000000000..fdd98e80c10 --- /dev/null +++ b/share/qtcreator/themes/dark.figmatokens @@ -0,0 +1,31 @@ +; Qt Creator Color Tokens - dark mode + +[Colors] + +Token_Basic_Black=ff131313 +Token_Basic_White=fff8f8f8 + +Token_Accent_Default=ff23b26a +Token_Accent_Muted=ff1f9b5d +Token_Accent_Subtle=ff1a8550 + +Token_Background_Default=ff1f1f1f +Token_Background_Muted=ff262626 +Token_Background_Subtle=ff2e2e2e + +Token_Foreground_Default=ff5a5a5a +Token_Foreground_Muted=ff3e3e3e +Token_Foreground_Subtle=ff303030 + +Token_Text_Default=fff8f8f8 +Token_Text_Muted=ffaeaeae +Token_Text_Subtle=ff595959 + +Token_Stroke_Strong=ffeeeeee +Token_Stroke_Muted=ff727272 +Token_Stroke_Subtle=ff3a3a3a + +Token_Notification_Alert=ffc98014 +Token_Notification_Success=ff1f9b5d +Token_Notification_Neutral=ff016876 +Token_Notification_Danger=ffb22245 diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme index 2dee7ab2469..f2c4c7f7a43 100644 --- a/share/qtcreator/themes/default.creatortheme +++ b/share/qtcreator/themes/default.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=light.figmatokens ThemeName=Classic PreferredStyles= @@ -398,39 +399,6 @@ Debugger_WatchItem_ValueChanged=ffc80000 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - light mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff2f2f2 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ffe3e3e3 -Token_Background_Muted=ffeeeeee -Token_Background_Subtle=fffbfbfb -Token_Foreground_Default=ffcdcdcd -Token_Foreground_Muted=ffd5d5d5 -Token_Foreground_Subtle=ffdddddd -Token_Text_Default=ff393939 -Token_Text_Muted=ff7c7c7c -Token_Text_Subtle=ffbebebe -Token_Stroke_Strong=ff464646 -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ffcdcdcd -Token_Notification_Alert=ffeb991f -Token_Notification_Success=ff23b26a -Token_Notification_Neutral=ff0e7887 -Token_Notification_Danger=ffdc1343 - -Welcome_TextColor=ff000000 -Welcome_ForegroundPrimaryColor=shadowBackground -Welcome_ForegroundSecondaryColor=ff939393 -Welcome_BackgroundPrimaryColor=fffafafa -Welcome_BackgroundSecondaryColor=ffffffff -Welcome_HoverColor=ffefefef -Welcome_AccentColor=ff45ce55 -Welcome_LinkColor=ff20a020 -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=darkText Timeline_BackgroundColor1=ffffffff Timeline_BackgroundColor2=fff6f6f6 diff --git a/share/qtcreator/themes/design-light.creatortheme b/share/qtcreator/themes/design-light.creatortheme index 8931b620424..41a9f07ba84 100644 --- a/share/qtcreator/themes/design-light.creatortheme +++ b/share/qtcreator/themes/design-light.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=light.figmatokens ThemeName=Design Light PreferredStyles= @@ -410,39 +411,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - light mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff2f2f2 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ffe3e3e3 -Token_Background_Muted=ffeeeeee -Token_Background_Subtle=fffbfbfb -Token_Foreground_Default=ffcdcdcd -Token_Foreground_Muted=ffd5d5d5 -Token_Foreground_Subtle=ffdddddd -Token_Text_Default=ff393939 -Token_Text_Muted=ff7c7c7c -Token_Text_Subtle=ffbebebe -Token_Stroke_Strong=ff464646 -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ffcdcdcd -Token_Notification_Alert=ffeb991f -Token_Notification_Success=ff23b26a -Token_Notification_Neutral=ff0e7887 -Token_Notification_Danger=ffdc1343 - -Welcome_TextColor=ff000000 -Welcome_ForegroundPrimaryColor=ff404040 -Welcome_ForegroundSecondaryColor=ff727272 -Welcome_BackgroundPrimaryColor=ffeaeaea -Welcome_BackgroundSecondaryColor=ffefefef -Welcome_HoverColor=ffe1e1e1 -Welcome_AccentColor=ff25709a -Welcome_LinkColor=ff104090 -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=fff6f6f6 diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme index e29240a3cf6..11022bd7e5d 100644 --- a/share/qtcreator/themes/design.creatortheme +++ b/share/qtcreator/themes/design.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=dark.figmatokens ThemeName=Design Dark PreferredStyles= DefaultTextEditorColorScheme=creator-dark.xml @@ -414,39 +415,6 @@ Debugger_WatchItem_ValueChanged=ffff6666 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - dark mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff8f8f8 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ff1f1f1f -Token_Background_Muted=ff262626 -Token_Background_Subtle=ff2e2e2e -Token_Foreground_Default=ff5a5a5a -Token_Foreground_Muted=ff3e3e3e -Token_Foreground_Subtle=ff303030 -Token_Text_Default=fff8f8f8 -Token_Text_Muted=ffaeaeae -Token_Text_Subtle=ff595959 -Token_Stroke_Strong=ffeeeeee -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ff3a3a3a -Token_Notification_Alert=ffc98014 -Token_Notification_Success=ff1f9b5d -Token_Notification_Neutral=ff016876 -Token_Notification_Danger=ffb22245 - -Welcome_TextColor=text -Welcome_ForegroundPrimaryColor=ffa3a3a3 -Welcome_ForegroundSecondaryColor=ff808080 -Welcome_BackgroundPrimaryColor=ff242424 -Welcome_BackgroundSecondaryColor=ff1c1c1c -Welcome_HoverColor=ff2b2a2a -Welcome_AccentColor=ff3f8ccc -Welcome_LinkColor=ff5fafef -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=ff444444 diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index 7e94645b743..9737e9cd53e 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=dark.figmatokens ThemeName=Flat Dark PreferredStyles= DefaultTextEditorColorScheme=creator-dark.xml @@ -410,39 +411,6 @@ Debugger_WatchItem_ValueChanged=ffff6666 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - dark mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff8f8f8 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ff1f1f1f -Token_Background_Muted=ff262626 -Token_Background_Subtle=ff2e2e2e -Token_Foreground_Default=ff5a5a5a -Token_Foreground_Muted=ff3e3e3e -Token_Foreground_Subtle=ff303030 -Token_Text_Default=fff8f8f8 -Token_Text_Muted=ffaeaeae -Token_Text_Subtle=ff595959 -Token_Stroke_Strong=ffeeeeee -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ff3a3a3a -Token_Notification_Alert=ffc98014 -Token_Notification_Success=ff1f9b5d -Token_Notification_Neutral=ff016876 -Token_Notification_Danger=ffb22245 - -Welcome_TextColor=text -Welcome_ForegroundPrimaryColor=ff999999 -Welcome_ForegroundSecondaryColor=ff808080 -Welcome_BackgroundPrimaryColor=normalBackground -Welcome_BackgroundSecondaryColor=ff242628 -Welcome_HoverColor=ff404243 -Welcome_AccentColor=ff36c148 -Welcome_LinkColor=ff5fcf4f -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=ff444444 diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index eddf38971d2..1ff8a7a3ff4 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=light.figmatokens ThemeName=Flat Light PreferredStyles= @@ -407,39 +408,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - light mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff2f2f2 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ffe3e3e3 -Token_Background_Muted=ffeeeeee -Token_Background_Subtle=fffbfbfb -Token_Foreground_Default=ffcdcdcd -Token_Foreground_Muted=ffd5d5d5 -Token_Foreground_Subtle=ffdddddd -Token_Text_Default=ff393939 -Token_Text_Muted=ff7c7c7c -Token_Text_Subtle=ffbebebe -Token_Stroke_Strong=ff464646 -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ffcdcdcd -Token_Notification_Alert=ffeb991f -Token_Notification_Success=ff23b26a -Token_Notification_Neutral=ff0e7887 -Token_Notification_Danger=ffdc1343 - -Welcome_TextColor=ff000000 -Welcome_ForegroundPrimaryColor=ff232323 -Welcome_ForegroundSecondaryColor=ff939393 -Welcome_BackgroundPrimaryColor=fffafafa -Welcome_BackgroundSecondaryColor=ffffffff -Welcome_HoverColor=ffefefef -Welcome_AccentColor=ff45ce55 -Welcome_LinkColor=ff20a020 -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=fff6f6f6 diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index 08697334f40..f479077889e 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -1,4 +1,5 @@ [General] +Includes=light.figmatokens ThemeName=Flat PreferredStyles= @@ -405,39 +406,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303 Debugger_Breakpoint_TextMarkColor=ffff4040 -; Qt Creator Color Tokens - light mode -Token_Basic_Black=ff131313 -Token_Basic_White=fff2f2f2 -Token_Accent_Default=ff23b26a -Token_Accent_Muted=ff1f9b5d -Token_Accent_Subtle=ff1a8550 -Token_Background_Default=ffe3e3e3 -Token_Background_Muted=ffeeeeee -Token_Background_Subtle=fffbfbfb -Token_Foreground_Default=ffcdcdcd -Token_Foreground_Muted=ffd5d5d5 -Token_Foreground_Subtle=ffdddddd -Token_Text_Default=ff393939 -Token_Text_Muted=ff7c7c7c -Token_Text_Subtle=ffbebebe -Token_Stroke_Strong=ff464646 -Token_Stroke_Muted=ff727272 -Token_Stroke_Subtle=ffcdcdcd -Token_Notification_Alert=ffeb991f -Token_Notification_Success=ff23b26a -Token_Notification_Neutral=ff0e7887 -Token_Notification_Danger=ffdc1343 - -Welcome_TextColor=ff000000 -Welcome_ForegroundPrimaryColor=shadowBackground -Welcome_ForegroundSecondaryColor=ff939393 -Welcome_BackgroundPrimaryColor=fffafafa -Welcome_BackgroundSecondaryColor=ffffffff -Welcome_HoverColor=ffefefef -Welcome_AccentColor=ff45ce55 -Welcome_LinkColor=ff20a020 -Welcome_DisabledLinkColor=textDisabled - Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground Timeline_BackgroundColor2=fff6f6f6 diff --git a/share/qtcreator/themes/light.figmatokens b/share/qtcreator/themes/light.figmatokens new file mode 100644 index 00000000000..a4d1bfcaa8d --- /dev/null +++ b/share/qtcreator/themes/light.figmatokens @@ -0,0 +1,31 @@ +; Qt Creator Color Tokens - light mode + +[Colors] + +Token_Basic_Black=ff131313 +Token_Basic_White=fff2f2f2 + +Token_Accent_Default=ff23b26a +Token_Accent_Muted=ff1f9b5d +Token_Accent_Subtle=ff1a8550 + +Token_Background_Default=fffcfcfc +Token_Background_Muted=ffefefef +Token_Background_Subtle=ffe7e7e7 + +Token_Foreground_Default=ffcdcdcd +Token_Foreground_Muted=ffd5d5d5 +Token_Foreground_Subtle=ffdddddd + +Token_Text_Default=ff393939 +Token_Text_Muted=ff6a6a6a +Token_Text_Subtle=ffbebebe + +Token_Stroke_Strong=ff464646 +Token_Stroke_Muted=ff727272 +Token_Stroke_Subtle=ffcdcdcd + +Token_Notification_Alert=ffeb991f +Token_Notification_Success=ff23b26a +Token_Notification_Neutral=ff0e7887 +Token_Notification_Danger=ffdc1343 diff --git a/share/qtcreator/translations/qtcreator_da.ts b/share/qtcreator/translations/qtcreator_da.ts index 8421c0a6242..43f21468465 100644 --- a/share/qtcreator/translations/qtcreator_da.ts +++ b/share/qtcreator/translations/qtcreator_da.ts @@ -1717,12 +1717,8 @@ Se Google Test-dokumentation for yderligere information om GTest-filtre.Perf - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - XML-output anbefales, fordi det forhindre parsing-problemer, mens ren tekst er lettere at læse for mennesker. - -Advarsel: Ren tekst mangle nogle informationer, såsom varighed. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + XML-output anbefales, fordi det forhindre parsing-problemer, mens ren tekst er lettere at læse for mennesker.<p>Advarsel: Ren tekst mangle nogle informationer, såsom varighed. Select Run Configuration @@ -18346,8 +18342,8 @@ Id'er skal begynde med et lille bogstav. Simulator start - Cannot start simulator (%1, %2) in current state: %3 - Kan ikke starte simulator (%1, %2) i aktuelle tilstand: %3 + Cannot start simulator (%1, %2) in current state: %3. + Kan ikke starte simulator (%1, %2) i aktuelle tilstand: %3. simulator start diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 89ac1623b2d..b15b6a1af2e 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -12413,10 +12413,8 @@ Weitere Informationen über GTest-Filter finden Sie in der Dokumenation von Goog Auf abgeleitete Qt Quick-Tests überprüfen - Search for Qt Quick tests that are derived from TestCase. -Warning: Enabling this feature significantly increases scan time. - Sucht nach Qt Quick-Tests, die von TestCase abgeleitet sind. -Achtung: Dies erhöht die zum Durchsuchen benötigte Zeit erheblich. + Search for Qt Quick tests that are derived from TestCase.<p>Warning: Enabling this feature significantly increases scan time. + Sucht nach Qt Quick-Tests, die von TestCase abgeleitet sind.<p>Achtung: Dies erhöht die zum Durchsuchen benötigte Zeit erheblich. Benchmark Metrics @@ -12463,12 +12461,8 @@ Achtung: Dies erhöht die zum Durchsuchen benötigte Zeit erheblich.Perf - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - Die XML-Ausgabe ist empfehlenswert, weil sie Probleme beim Einlesen vermeidet. Reiner Text ist hingegen besser lesbar für Menschen. - -Warnung: Reinem Text fehlen manche Informationen, etwa die Dauer. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + Die XML-Ausgabe ist empfehlenswert, weil sie Probleme beim Einlesen vermeidet. Reiner Text ist hingegen besser lesbar für Menschen.<p>Warnung: Reinem Text fehlen manche Informationen, etwa die Dauer. Select Run Configuration @@ -33897,7 +33891,7 @@ Möchten Sie sie überschreiben? Simulator starten - Cannot start simulator (%1, %2) in current state: %3 + Cannot start simulator (%1, %2) in current state: %3. Der Simulator (%1, %2) kann im momentanen Zustand (%3) nicht gestartet werden. diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index adc57cc41ef..fe4d87c0326 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -798,7 +798,7 @@ Une valeur positive augmente la réverbération pour les hautes fréquences et - Axivion + QtC::Axivion Project: Projet : @@ -12063,12 +12063,8 @@ Voir la documentation de Google Test pour plus d'informations sur les filtr Utilise la sortie XML - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - La sortie XML est recommandée : elle évite des problèmes d'analyse, alors que le texte brut est plus lisible pour un humain. - -Avertissement : le texte brut ne contient pas toutes les informations, telle que la durée. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + La sortie XML est recommandée : elle évite des problèmes d'analyse, alors que le texte brut est plus lisible pour un humain.<p>Avertissement : le texte brut ne contient pas toutes les informations, telle que la durée. Verbose benchmarks @@ -12099,10 +12095,8 @@ Avertissement : le texte brut ne contient pas toutes les informations, tell Vérifier la présence de tests dérivés de Qt Quick - Search for Qt Quick tests that are derived from TestCase. -Warning: Enabling this feature significantly increases scan time. - Recherche des tests Qt Quick dérivé de TestCase. -Avertissement : l'activation de cette fonctionnalité augmente significativement le temps de recherche. + Search for Qt Quick tests that are derived from TestCase.<p>Warning: Enabling this feature significantly increases scan time. + Recherche des tests Qt Quick dérivé de TestCase.<p>Avertissement : l'activation de cette fonctionnalité augmente significativement le temps de recherche. Benchmark Metrics @@ -33467,8 +33461,8 @@ Souhaitez-vous les écraser ? - Cannot start simulator (%1, %2) in current state: %3 - Impossible de démarrer le simulateur (%1, %2) dans l'état actuel : %3 + Cannot start simulator (%1, %2) in current state: %3. + Impossible de démarrer le simulateur (%1, %2) dans l'état actuel : %3. simulator start diff --git a/share/qtcreator/translations/qtcreator_hr.ts b/share/qtcreator/translations/qtcreator_hr.ts index 5cb6489b7ed..6d69f112adb 100644 --- a/share/qtcreator/translations/qtcreator_hr.ts +++ b/share/qtcreator/translations/qtcreator_hr.ts @@ -1135,12 +1135,8 @@ Dodatne dokumente o GTest filtrima potraži u Google Test dokumentaciji.Deaktiviraj rukovatelja urušivanja tijekom uklanjanja grešaka - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - Preporuča se XML izlaz, jer izbjegava probleme s raščlanjivanjem, dok je običan tekst čitljiviji za čitanje. - -Upozorenje: Običan tekst propušta neke informacije, kao što je trajanje. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + Preporuča se XML izlaz, jer izbjegava probleme s raščlanjivanjem, dok je običan tekst čitljiviji za čitanje.<p>Upozorenje: Običan tekst propušta neke informacije, kao što je trajanje. Use XML output @@ -4546,8 +4542,8 @@ Dodaj, izmijeni i ukloni filtre dokumenata koji određuju skup dokumentacije pri - Cannot start simulator (%1, %2) in current state: %3 - Nije moguće pokrenuti simulatora (%1, %2) u trenutačnom stanju: %3 + Cannot start simulator (%1, %2) in current state: %3. + Nije moguće pokrenuti simulatora (%1, %2) u trenutačnom stanju: %3. simulator start diff --git a/share/qtcreator/translations/qtcreator_pl.ts b/share/qtcreator/translations/qtcreator_pl.ts index 91aba3691e2..a59ebcb424c 100644 --- a/share/qtcreator/translations/qtcreator_pl.ts +++ b/share/qtcreator/translations/qtcreator_pl.ts @@ -12692,8 +12692,7 @@ See also Google Test settings. - Search for Qt Quick tests that are derived from TestCase. -Warning: Enabling this feature significantly increases scan time. + Search for Qt Quick tests that are derived from TestCase.<p>Warning: Enabling this feature significantly increases scan time. @@ -12713,9 +12712,7 @@ Warning: Enabling this feature significantly increases scan time. Używaj XML na wyjściu - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. @@ -33930,8 +33927,8 @@ Czy nadpisać je? Uruchomienie symulatora - Cannot start simulator (%1, %2) in current state: %3 - Nie można uruchomić symulatora (%1, %2) w bieżącym stanie: %3 + Cannot start simulator (%1, %2) in current state: %3. + Nie można uruchomić symulatora (%1, %2) w bieżącym stanie: %3. simulator start diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index ed5d78ba7a2..ac9a564f8b3 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -2745,12 +2745,8 @@ See Google Test documentation for further information on GTest filters. Логировать сигналы и слоты - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - Рекомендуется вывод в формате XML, так как исключает проблемы при разборе. Простой же текст более удобен для чтения человеком. - -Предупреждение: простой текст не содержит некоторую информацию, например, длительность. + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + Рекомендуется вывод в формате XML, так как исключает проблемы при разборе. Простой же текст более удобен для чтения человеком.<p>Предупреждение: простой текст не содержит некоторую информацию, например, длительность. Select Run Configuration @@ -22984,8 +22980,8 @@ Ids must begin with a lowercase letter. Запустить эмулятор - Cannot start simulator (%1, %2) in current state: %3 - Невозможно запустить эмулятор (%1, %2) в текущем состоянии: %3 + Cannot start simulator (%1, %2) in current state: %3. + Невозможно запустить эмулятор (%1, %2) в текущем состоянии: %3. simulator start diff --git a/share/qtcreator/translations/qtcreator_zh_CN.ts b/share/qtcreator/translations/qtcreator_zh_CN.ts index 4e361b52d34..7526f78c968 100644 --- a/share/qtcreator/translations/qtcreator_zh_CN.ts +++ b/share/qtcreator/translations/qtcreator_zh_CN.ts @@ -2950,12 +2950,8 @@ See Google Test documentation for further information on GTest filters. 使用 XML 输出 - XML output is recommended, because it avoids parsing issues, while plain text is more human readable. - -Warning: Plain text misses some information, such as duration. - 建议使用 XML 输出,它避免了一些解析问题,虽然纯文本可读性更好。 - -警告:纯文本丢失了一些信息,比如持续时间。 + XML output is recommended, because it avoids parsing issues, while plain text is more human readable.<p>Warning: Plain text misses some information, such as duration. + 建议使用 XML 输出,它避免了一些解析问题,虽然纯文本可读性更好。<p>警告:纯文本丢失了一些信息,比如持续时间。 Verbose benchmarks @@ -23217,7 +23213,7 @@ Id必须以小写字母开头。 - Cannot start simulator (%1, %2) in current state: %3 + Cannot start simulator (%1, %2) in current state: %3. diff --git a/src/libs/3rdparty/qtkeychain/qtkeychain.qbs b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs new file mode 100644 index 00000000000..b5f8e7dc131 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/qtkeychain.qbs @@ -0,0 +1,92 @@ +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"]) + cpp.cxxFlags: outer.concat("-Wno-cast-function-type") + files: [ + "gnomekeyring.cpp", + "gnomekeyring_p.h", + "keychain_unix.cpp", + "libsecret.cpp", + "libsecret_p.h", + "plaintextstore.cpp", + "plaintextstore_p.h", + ] + } + } + + Export { + Depends { name: "cpp" } + cpp.includePaths: project.ide_source_tree + "/src/libs/3rdparty/" + } +} diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt index 66c1d919512..ce22946d84f 100644 --- a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt @@ -26,6 +26,7 @@ add_qtc_library(KSyntaxHighlighting src/lib/definitiondownloader.cpp src/lib/definitiondownloader.h src/lib/definitionref_p.h src/lib/definition_p.h + src/lib/dynamicregexpcache_p.h src/lib/foldingregion.cpp src/lib/foldingregion.h src/lib/format.cpp src/lib/format.h src/lib/format_p.h src/lib/htmlhighlighter.cpp src/lib/htmlhighlighter.h @@ -44,7 +45,7 @@ add_qtc_library(KSyntaxHighlighting src/lib/xml_p.h ) -set(export_symbol_declaration DEFINES KF5SyntaxHighlighting_EXPORTS) +set(export_symbol_declaration DEFINES KF6SyntaxHighlighting_EXPORTS) if (QTC_STATIC_BUILD) set(export_symbol_declaration PUBLIC_DEFINES KSYNTAXHIGHLIGHTING_STATIC_DEFINE) endif() diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h index 007fe4acae3..d568d1813d6 100644 --- a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h +++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h @@ -1,12 +1,12 @@ // This file was generated by ecm_setup_version(): DO NOT EDIT! -#ifndef SyntaxHighlighting_VERSION_H -#define SyntaxHighlighting_VERSION_H +#ifndef KSYNTAXHIGHLIGHTING_VERSION_H +#define KSYNTAXHIGHLIGHTING_VERSION_H -#define SyntaxHighlighting_VERSION_STRING "5.103.0" -#define SyntaxHighlighting_VERSION_MAJOR 5 -#define SyntaxHighlighting_VERSION_MINOR 103 -#define SyntaxHighlighting_VERSION_PATCH 0 -#define SyntaxHighlighting_VERSION ((5<<16)|(103<<8)|(0)) +#define KSYNTAXHIGHLIGHTING_VERSION_STRING "5.249.0" +#define KSYNTAXHIGHLIGHTING_VERSION_MAJOR 5 +#define KSYNTAXHIGHLIGHTING_VERSION_MINOR 249 +#define KSYNTAXHIGHLIGHTING_VERSION_PATCH 0 +#define KSYNTAXHIGHLIGHTING_VERSION ((5<<16)|(249<<8)|(0)) #endif diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h index e376e94505e..a7b9e09afa7 100644 --- a/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h +++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/src/lib/ksyntaxhighlighting_export.h @@ -2,14 +2,12 @@ #ifndef KSYNTAXHIGHLIGHTING_EXPORT_H #define KSYNTAXHIGHLIGHTING_EXPORT_H -#include - #ifdef KSYNTAXHIGHLIGHTING_STATIC_DEFINE # define KSYNTAXHIGHLIGHTING_EXPORT # define KSYNTAXHIGHLIGHTING_NO_EXPORT #else # ifndef KSYNTAXHIGHLIGHTING_EXPORT -# ifdef KF5SyntaxHighlighting_EXPORTS +# ifdef KF6SyntaxHighlighting_EXPORTS /* We are building this library */ # define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_EXPORT # else @@ -43,8 +41,6 @@ #define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) __declspec(deprecated(text)) -#define ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) - /* Take any defaults from group settings */ #if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED) && !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) # ifdef KF_NO_DEPRECATED @@ -88,7 +84,7 @@ #define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1 #ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED -# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x56700 +# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KSYNTAXHIGHLIGHTING_VERSION #endif #ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS # define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0 @@ -98,7 +94,7 @@ # ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT # define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT # else -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x56700 +# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_VERSION # endif #endif @@ -107,112 +103,9 @@ #endif #ifdef KSYNTAXHIGHLIGHTING_DEPRECATED -# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) (ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, 0) > KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) +# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) (((major<<16)|(minor<<8)) > KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) #else # define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) 0 #endif -#if KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE >= 0x55700 -# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) -#else -# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) -#endif -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5(minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_##minor(text) -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION(major, minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#major"."#minor". " text) -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#textmajor"."#textminor". " text) -// Not yet implemented for MSVC -#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION(major, minor, text) -#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) - #endif /* KSYNTAXHIGHLIGHTING_EXPORT_H */ - - -#ifndef ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H -#define ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H - - -#define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) __declspec(deprecated(text)) - -#define ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) - -/* Take any defaults from group settings */ -#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED) && !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) -# ifdef KF_NO_DEPRECATED -# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED -# elif defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT) -# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT -# endif -#endif -#if !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) && defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT) -# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT -#endif - -#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS) && !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE) -# ifdef KF_NO_DEPRECATED_WARNINGS -# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS -# elif defined(KF_DEPRECATED_WARNINGS_SINCE) -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE -# endif -#endif -#if !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE) && defined(KF_DEPRECATED_WARNINGS_SINCE) -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE -#endif - -#if defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED) -# undef KSYNTAXHIGHLIGHTING_DEPRECATED -# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT -# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT -#elif defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS) -# define KSYNTAXHIGHLIGHTING_DEPRECATED -# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT -# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT -#else -# define KSYNTAXHIGHLIGHTING_DEPRECATED KSYNTAXHIGHLIGHTING_DECL_DEPRECATED -# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_EXPORT -# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_NO_EXPORT -#endif - -/* No deprecated API had been removed from build */ -#define KSYNTAXHIGHLIGHTING_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 - -#define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1 - -#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED -# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x56700 -#endif -#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0 -#endif - -#ifndef KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE -# ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT -# else -# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x56700 -# endif -#endif - -#ifndef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT -# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0 -#endif - -#ifdef KSYNTAXHIGHLIGHTING_DEPRECATED -# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) (ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, 0) > KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) -#else -# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) 0 -#endif - -#if KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE >= 0x55700 -# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) -#else -# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) -#endif -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5(minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_##minor(text) -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION(major, minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#major"."#minor". " text) -#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#textmajor"."#textminor". " text) -// Not yet implemented for MSVC -#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION(major, minor, text) -#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) - - -#endif /* ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H */ diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile b/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile index 8e9c570084c..227d4cd2cca 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/Pipfile @@ -8,4 +8,5 @@ name = "pypi" [packages] click = "~= 8.0" jinja2 = "~= 3.0" +lxml = "*" PyYAML = "*" diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.xml.tpl b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.xml.tpl index 5f57c8eeacc..48f56f7b607 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.xml.tpl +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.xml.tpl @@ -1,5 +1,5 @@ - @@ -12,7 +12,7 @@ SPDX-FileCopyrightText: 2004 Alexander Neundorf SPDX-FileCopyrightText: 2005 Dominik Haumann SPDX-FileCopyrightText: 2007, 2008, 2013, 2014 Matthew Woehlke - SPDX-FileCopyrightText: 2013-2015, 2017-2020 Alex Turbov + SPDX-FileCopyrightText: 2013-2015, 2017-2023 Alex Turbov SPDX-License-Identifier: LGPL-2.0-or-later --> @@ -26,7 +26,7 @@ + + + + + + + @@ -135,7 +142,7 @@ - + beginRegion="" endRegion="" /> @@ -427,11 +434,22 @@ + + + + + + + + + + + @@ -460,6 +478,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml index 624299346f9..e247237dda4 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/cmake.yaml @@ -1,4 +1,4 @@ -version: 44 +version: 50 global-properties: - ALLOW_DUPLICATE_CUSTOM_TARGETS @@ -112,11 +112,12 @@ target-properties: - AUTOGEN_BUILD_DIR - AUTOGEN_ORIGIN_DEPENDS # Since 3.14 - AUTOGEN_TARGET_DEPENDS - - AUTOMOC_COMPILER_PREDEFINES # Since ??? + - AUTOGEN_USE_SYSTEM_INCLUDE # Since 3.27 + - AUTOMOC_COMPILER_PREDEFINES # Since 3.10 - AUTOMOC_DEPEND_FILTERS - AUTOMOC_EXECUTABLE # Since 3.14 - AUTOMOC_MACRO_NAMES - - AUTOMOC_MOC_OPTIONS # Since ??? + - AUTOMOC_MOC_OPTIONS - AUTOMOC_PATH_PREFIX # Since 3.16 - AUTOMOC - AUTOUIC @@ -154,14 +155,23 @@ target-properties: - _POSTFIX - CROSSCOMPILING_EMULATOR - CUDA_ARCHITECTURES # Since 3.18 + - CUDA_CUBIN_COMPILATION # Since 3.27 + - CUDA_EXTENSIONS + - CUDA_FATBIN_COMPILATION # Since 3.27 + - CUDA_OPTIX_COMPILATION # Since 3.27 - CUDA_PTX_COMPILATION - CUDA_SEPARABLE_COMPILATION - CUDA_RESOLVE_DEVICE_SYMBOLS - CUDA_RUNTIME_LIBRARY # Since 3.17 - - CUDA_EXTENSIONS - CUDA_STANDARD - CUDA_STANDARD_REQUIRED - CXX_EXTENSIONS + - CXX_MODULE_DIRS # Since 3.28 + - CXX_MODULE_DIRS_ # Since 3.28 + - CXX_MODULE_SET # Since 3.28 + - CXX_MODULE_SET_ # Since 3.28 + - CXX_MODULE_SETS # Since 3.28 + - CXX_SCAN_FOR_MODULES # Since 3.28 - CXX_STANDARD - CXX_STANDARD_REQUIRED # - DEBUG_POSTFIX # NOTE: Handled by `_POSTFIX` @@ -170,6 +180,7 @@ target-properties: - DEPLOYMENT_REMOTE_DIRECTORY - DEPRECATION # Since 3.17 - DISABLE_PRECOMPILE_HEADERS # Since 3.16 + - DLL_NAME_WITH_SOVERSION # Since 3.27 - DOTNET_SDK # Since 3.23 - DOTNET_TARGET_FRAMEWORK # Since 3.17 - DOTNET_TARGET_FRAMEWORK_VERSION # Since 3.12 @@ -234,10 +245,12 @@ target-properties: - INSTALL_REMOVE_ENVIRONMENT_RPATH # Since 3.16 - INSTALL_RPATH - INSTALL_RPATH_USE_LINK_PATH + - INTERFACE_AUTOMOC_MACRO_NAMES # Since 3.27 - INTERFACE_AUTOUIC_OPTIONS - INTERFACE_COMPILE_DEFINITIONS - INTERFACE_COMPILE_FEATURES - INTERFACE_COMPILE_OPTIONS + - INTERFACE_CXX_MODULE_SETS # Since 3.28 - INTERFACE_HEADER_SETS # Since 3.23 - INTERFACE_HEADER_SETS_TO_VERIFY # Since 3.24 - INTERFACE_INCLUDE_DIRECTORIES @@ -261,6 +274,7 @@ target-properties: - JOB_POOL_LINK - LABELS - _CLANG_TIDY + - _CLANG_TIDY_EXPORT_FIXES_DIR # Since 3.26 - _COMPILER_LAUNCHER - _CPPCHECK # Since 3.10 - _CPPLINT @@ -451,18 +465,22 @@ test-properties: - FIXTURES_CLEANUP - FIXTURES_REQUIRED - FIXTURES_SETUP + - GENERATED_RESOURCE_SPEC_FILE # Since 3.28 - LABELS - MEASUREMENT - PASS_REGULAR_EXPRESSION - PROCESSOR_AFFINITY # Since 3.12 - PROCESSORS - REQUIRED_FILES + - RESOURCE_GROUPS # Since 3.16 - RESOURCE_LOCK - RUN_SERIAL - SKIP_REGULAR_EXPRESSION # Since 3.16 - SKIP_RETURN_CODE - TIMEOUT - TIMEOUT_AFTER_MATCH + - TIMEOUT_SIGNAL_GRACE_PERIOD # Since 3.27 + - TIMEOUT_SIGNAL_NAME # Since 3.27 - WILL_FAIL - WORKING_DIRECTORY @@ -473,6 +491,7 @@ source-properties: - COMPILE_DEFINITIONS - COMPILE_FLAGS - COMPILE_OPTIONS # Since 3.11 + - CXX_SCAN_FOR_MODULES # Since 3.28 - EXTERNAL_OBJECT - Fortran_FORMAT - Fortran_PREPROCESS # Since 3.18 @@ -490,6 +509,7 @@ source-properties: - SKIP_AUTOMOC - SKIP_AUTORCC - SKIP_AUTOUIC + - SKIP_LINTING # Since 3.27 - SKIP_PRECOMPILE_HEADERS # Since 3.16 - SKIP_UNITY_BUILD_INCLUSION # Since 3.16 - Swift_DEPENDENCIES_FILE # Since 3.15 @@ -535,76 +555,155 @@ install-properties: - CPACK_WIX_ACL generator-expressions: - # Boolean Generator Expressions - # * Logical Operators + # Conditional Expressions + - IF - 0 - 1 - BOOL + # Logical Operators - AND - OR - NOT - # * String Comparisons + # String Comparisons - STREQUAL - EQUAL - - IN_LIST # Since 3.12 + # Version Comparisons - VERSION_LESS - VERSION_GREATER - VERSION_EQUAL - VERSION_LESS_EQUAL - VERSION_GREATER_EQUAL - # * Path Comparisons - - PATH_EQUAL # Since 3.24 - # * Path Queries - # * Path Decomposition - # * Path Transformations - # TODO Need a bit deeper genex parsing to get sub-commands of `PATH` - - PATH # Since 3.24 - # * Variable Queries - - TARGET_EXISTS # Since 3.12 - - CONFIG - - PLATFORM_ID - - C_COMPILER_ID - - CXX_COMPILER_ID - - CUDA_COMPILER_ID # Since 3.15 - - Fortran_COMPILER_ID - - C_COMPILER_VERSION - - CXX_COMPILER_VERSION - - CUDA_COMPILER_VERSION # Since 3.15 - - Fortran_COMPILER_VERSION - - TARGET_POLICY - - COMPILE_FEATURES - - COMPILE_LANG_AND_ID # Since 3.15 - - COMPILE_LANGUAGE - - LINK_LANG_AND_ID # Since 3.18 - - LINK_LANGUAGE # Since 3.18 - - DEVICE_LINK # Since 3.18 - - HOST_LINK # Since 3.18 - - LINK_LIBRARY # Since 3.24 - - LINK_GROUP # Since 3.24 - # String-Valued Generator Expressions - # * Escaped Characters - - ANGLE-R - - COMMA - - SEMICOLON - # * Conditional Expressions - - IF - # * String Transformations + # String Transformations + - LOWER_CASE + - UPPER_CASE + - MAKE_C_IDENTIFIER + # List Expressions + # * List Comparisons + - IN_LIST # Since 3.12 + - name: LIST # Since 3.27 + subcommands: + # * List Queries + - LENGTH + - GET + - SUBLIST + - FIND + # * List Transformations + - JOIN + - APPEND + - PREPEND + - INSERT + - POP_BACK + - POP_FRONT + - REMOVE_ITEM + - REMOVE_AT + - REMOVE_DUPLICATES + - FILTER + - TRANSFORM + - FRANSFORM + # * List Ordering + - REVERSE + - SORT - JOIN - REMOVE_DUPLICATES # Since 3.15 - FILTER # Since 3.15 - - LOWER_CASE - - UPPER_CASE - - GENEX_EVAL # Since 3.12 - - TARGET_GENEX_EVAL # Since 3.12 - # * Variable Queries (NOTE Already included above) - # * Target-Dependent Queries + # Path Expressions + # * Path Comparisons + - PATH_EQUAL # Since 3.24 + - name: PATH # Since 3.24 + subcommands: + # * Path Queries + - HAS_ROOT_NAME + - HAS_ROOT_DIRECTORY + - HAS_ROOT_PATH + - HAS_FILENAME + - HAS_EXTENSION + - HAS_STEM + - HAS_RELATIVE_PART + - HAS_PARENT_PATH + - IS_ABSOLUTE + - IS_RELATIVE + - IS_PREFIX + # * Path Decomposition + - GET_ROOT_NAME + - GET_ROOT_DIRECTORY + - GET_ROOT_PATH + - GET_FILENAME + - GET_EXTENSION + - GET_STEM + - GET_RELATIVE_PART + - GET_PARENT_PATH + # * Path Transformations + - CMAKE_PATH + - APPEND + - REMOVE_FILENAME + - REPLACE_FILENAME + - REMOVE_EXTENSION + - REPLACE_EXTENSION + - NORMAL_PATH + - RELATIVE_PATH + - ABSOLUTE_PATH + # Shell Paths + - SHELL_PATH + # Configuration Expressions + - CONFIG + - OUTPUT_CONFIG # Since 3.20 + - COMMAND_CONFIG # Since 3.20 + # Toolchain And Language Expressions + # * Platform + - PLATFORM_ID + # * Compiler Version + - C_COMPILER_VERSION + - CXX_COMPILER_VERSION + - CUDA_COMPILER_VERSION # Since 3.15 + - OBJC_COMPILER_VERSION # Since 3.16 + - OBJCXX_COMPILER_VERSION # Since 3.16 + - Fortran_COMPILER_VERSION + - HIP_COMPILER_VERSION # Since 3.21 + - ISPC_COMPILER_VERSION # Since 3.19 + # * Compiler Language And ID + - C_COMPILER_ID + - CXX_COMPILER_ID + - CUDA_COMPILER_ID # Since 3.15 + - OBJC_COMPILER_ID # Since 3.16 + - OBJCXX_COMPILER_ID # Since 3.16 + - Fortran_COMPILER_ID + - HIP_COMPILER_ID # Since 3.21 + - ISPC_COMPILER_ID # Since 3.19 + - COMPILE_LANGUAGE # Since 3.3 + - COMPILE_LANG_AND_ID # Since 3.15 + # * Compile Features + - COMPILE_FEATURES + # * Compile Context + - COMPILE_ONLY # Since 3.27 + # * Linker Language And ID + - LINK_LANGUAGE # Since 3.18 + - LINK_LANG_AND_ID # Since 3.18 + # * Link Features + - LINK_LIBRARY # Since 3.24 + - LINK_GROUP # Since 3.24 + # * Link Context + - LINK_ONLY + - DEVICE_LINK # Since 3.18 + - HOST_LINK # Since 3.18 + # Target-Dependent Expressions + - TARGET_EXISTS # Since 3.12 - TARGET_NAME_IF_EXISTS # Since 3.12 + - TARGET_NAME + - TARGET_PROPERTY + - TARGET_OBJECTS + - TARGET_POLICY - TARGET_FILE - TARGET_FILE_BASE_NAME # Since 3.15 - TARGET_FILE_PREFIX # Since 3.15 - TARGET_FILE_SUFFIX # Since 3.15 - TARGET_FILE_NAME - TARGET_FILE_DIR + - TARGET_IMPORT_FILE # Since 3.27 + - TARGET_IMPORT_FILE_BASE_NAME # Since 3.27 + - TARGET_IMPORT_FILE_PREFIX # Since 3.27 + - TARGET_IMPORT_FILE_SUFFIX # Since 3.27 + - TARGET_IMPORT_FILE_NAME # Since 3.27 + - TARGET_IMPORT_FILE_DIR # Since 3.27 - TARGET_LINKER_FILE - TARGET_LINKER_FILE_BASE_NAME # Since 3.15 - TARGET_LINKER_FILE_PREFIX # Since 3.15 @@ -612,7 +711,6 @@ generator-expressions: - TARGET_LINKER_FILE_NAME - TARGET_LINKER_FILE_DIR - TARGET_SONAME_FILE - - TARGET_SONAME_FILE - TARGET_SONAME_FILE_NAME - TARGET_SONAME_FILE_DIR - TARGET_PDB_FILE @@ -622,19 +720,22 @@ generator-expressions: - TARGET_BUNDLE_DIR_NAME # Since 3.24 - TARGET_BUNDLE_DIR - TARGET_BUNDLE_CONTENT_DIR - - TARGET_PROPERTY - TARGET_RUNTIME_DLLS # Since 3.21 - - INSTALL_PREFIX - # Output-Related Expressions - - TARGET_NAME - - LINK_ONLY + - TARGET_RUNTIME_DLL_DIRS # Since 3.27 + # Export And Install Expressions - INSTALL_INTERFACE - BUILD_INTERFACE - - MAKE_C_IDENTIFIER - - TARGET_OBJECTS - - SHELL_PATH - - OUTPUT_CONFIG # Since 3.20 - - COMMAND_CONFIG # Since 3.20 + - BUILD_LOCAL_INTERFACE # Since 3.26 + - INSTALL_PREFIX + # Multi-level Expression Evaluation + - GENEX_EVAL # Since 3.12 + - TARGET_GENEX_EVAL # Since 3.12 + # Escaped Characters + - ANGLE-R + - COMMA + - SEMICOLON + # Deprecated Expressions + # - CONFIGURATION variables: # Variables that Provide Information @@ -686,6 +787,7 @@ variables: - CMAKE_JOB_POOL_LINK - CMAKE_JOB_POOLS # Since 3.11 - CMAKE__COMPILER_AR + - CMAKE__COMPILER_FRONTEND_VARIANT # Since 3.14 - CMAKE__COMPILER_RANLIB - CMAKE_LINK_LIBRARY_SUFFIX - CMAKE_LINK_SEARCH_END_STATIC @@ -735,9 +837,17 @@ variables: - CMAKE_VS_NsightTegra_VERSION - CMAKE_VS_NUGET_PACKAGE_RESTORE # Since 3.23 - CMAKE_VS_PLATFORM_NAME + - CMAKE_VS_PLATFORM_NAME_DEFAULT # Since 3.14.3 - CMAKE_VS_PLATFORM_TOOLSET - CMAKE_VS_PLATFORM_TOOLSET_CUDA - - CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE + - CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR # Since 3.16 + - CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE # Since 3.8 + - CMAKE_VS_PLATFORM_TOOLSET_VERSION # Since 3.12 + - CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER # Since 3.22 + - CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION # Since 3.22 + - CMAKE_VS_TARGET_FRAMEWORK_VERSION # Since 3.22 + - CMAKE_VS_VERSION_BUILD_NUMBER # Since 3.26 + - CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION # Since 3.27 - CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION - CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM # Since 3.19 - CMAKE_XCODE_BUILD_SYSTEM # Since 3.19 @@ -766,6 +876,7 @@ variables: # Variables that Change Behavior - BUILD_SHARED_LIBS - CMAKE_ABSOLUTE_DESTINATION_FILES + - CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY # Since 3.27 - CMAKE_APPBUNDLE_PATH - CMAKE_AUTOMOC_RELAXED_MODE - CMAKE_BACKWARDS_COMPATIBILITY @@ -973,16 +1084,20 @@ variables: - CMAKE_ARCHIVE_OUTPUT_DIRECTORY_ - CMAKE_AUTOGEN_ORIGIN_DEPENDS # Since 3.14 - CMAKE_AUTOGEN_PARALLEL + - CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE # Since 3.27 - CMAKE_AUTOGEN_VERBOSE # Since 3.13 - CMAKE_AUTOMOC - CMAKE_AUTOMOC_DEPEND_FILTERS - CMAKE_AUTOMOC_MOC_OPTIONS - CMAKE_AUTOMOC_PATH_PREFIX # Since 3.16 + - CMAKE_AUTOMOC_EXECUTABLE # Since 3.27 - CMAKE_AUTORCC - CMAKE_AUTORCC_OPTIONS + - CMAKE_AUTORCC_EXECUTABLE # Since 3.27 - CMAKE_AUTOUIC - CMAKE_AUTOUIC_OPTIONS - CMAKE_AUTOUIC_SEARCH_PATHS + - CMAKE_AUTOUIC_EXECUTABLE # Since 3.27 - CMAKE_BUILD_RPATH - CMAKE_BUILD_RPATH_USE_ORIGIN # Since 3.14 - CMAKE_BUILD_WITH_INSTALL_NAME_DIR @@ -993,14 +1108,17 @@ variables: - CMAKE__POSTFIX - CMAKE_CROSS_CONFIGS # Since 3.17 - CMAKE_CTEST_ARGUMENTS # Since 3.17 - - CMAKE_CUDA_SEPARABLE_COMPILATION # Since 3.11 - CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS # Since 3.16 - CMAKE_CUDA_RUNTIME_LIBRARY # Since 3.17 + - CMAKE_CUDA_SEPARABLE_COMPILATION # Since 3.11 + - CMAKE_CXX_SCAN_FOR_MODULES # Since 3.28 - CMAKE_DEBUG_POSTFIX - CMAKE_DEFAULT_BUILD_TYPE # Since 3.17 - CMAKE_DEFAULT_CONFIGS # Since 3.17 - CMAKE_DISABLE_PRECOMPILE_HEADERS # Since 3.17 - - CMAKE_ENABLE_EXPORTS + - CMAKE_DLL_NAME_WITH_SOVERSION # Since 3.27 + # `CMAKE_ENABLE_EXPORTS` has been moved to deprecated section + - CMAKE_EXECUTABLE_ENABLE_EXPORTS # Since 3.27 - CMAKE_EXE_LINKER_FLAGS - CMAKE_EXE_LINKER_FLAGS_ - CMAKE_EXE_LINKER_FLAGS__INIT @@ -1024,8 +1142,8 @@ variables: - CMAKE_INSTALL_RPATH_USE_LINK_PATH - CMAKE_INTERPROCEDURAL_OPTIMIZATION - CMAKE_INTERPROCEDURAL_OPTIMIZATION_ - - CMAKE_IOS_INSTALL_COMBINED - CMAKE__CLANG_TIDY + - CMAKE__CLANG_TIDY_EXPORT_FIXES_DIR # Since 3.26 - CMAKE__COMPILER_LAUNCHER - CMAKE__CPPCHECK # Since 3.10 - CMAKE__CPPLINT @@ -1044,6 +1162,9 @@ variables: - CMAKE_LIBRARY_PATH_FLAG - CMAKE_LINK_DEF_FILE_FLAG - CMAKE_LINK_DEPENDS_NO_SHARED + - CMAKE_LINK_DEPENDS_USE_LINKER # Since 3.27 + - CMAKE_LINK_GROUP_USING_ # Since 3.24 + - CMAKE_LINK_GROUP_USING__SUPPORTED # Since 3.24 - CMAKE_LINK_INTERFACE_LIBRARIES - CMAKE_LINK_LIBRARY_FILE_FLAG - CMAKE_LINK_LIBRARY_FLAG @@ -1072,9 +1193,11 @@ variables: - CMAKE_PCH_INSTANTIATE_TEMPLATES # Since 3.19 - CMAKE_PDB_OUTPUT_DIRECTORY - CMAKE_PDB_OUTPUT_DIRECTORY_ + - CMAKE_PLATFORM_NO_VERSIONED_SONAME # Since 3.1 - CMAKE_POSITION_INDEPENDENT_CODE - CMAKE_RUNTIME_OUTPUT_DIRECTORY - CMAKE_RUNTIME_OUTPUT_DIRECTORY_ + - CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS # Since 3.27 - CMAKE_SHARED_LINKER_FLAGS - CMAKE_SHARED_LINKER_FLAGS_ - CMAKE_SHARED_LINKER_FLAGS__INIT @@ -1095,6 +1218,10 @@ variables: - CMAKE_USE_RELATIVE_PATHS - CMAKE_VERIFY_INTERFACE_HEADER_SETS # Since 3.24 - CMAKE_VISIBILITY_INLINES_HIDDEN + - CMAKE_VS_DEBUGGER_COMMAND # Since 3.27 + - CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS # Since 3.27 + - CMAKE_VS_DEBUGGER_ENVIRONMENT # Since 3.27 + - CMAKE_VS_DEBUGGER_WORKING_DIRECTORY # Since 3.27 - CMAKE_VS_GLOBALS # Since 3.13 - CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD - CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD @@ -1137,6 +1264,7 @@ variables: - CMAKE_Fortran_MODOUT_FLAG - CMAKE_HIP_ARCHITECTURES # Since 3.21 - CMAKE_HIP_EXTENSIONS # Since 3.21 + - CMAKE_HIP_PLATFORM # Since 3.28 - CMAKE_HIP_STANDARD # Since 3.21 - CMAKE_HIP_STANDARD_REQUIRED # Since 3.21 - CMAKE_ISPC_HEADER_DIRECTORY # Since 3.19 @@ -1533,6 +1661,41 @@ variables: - CPACK_COMMAND_HDIUTIL - CPACK_COMMAND_SETFILE - CPACK_COMMAND_REZ + # [built-in]: CPack Inno Setup Generator (Since 3.27) + - CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT + - CPACK_INNOSETUP_ARCHITECTURE + - CPACK_INNOSETUP_INSTALL_ROOT + - CPACK_INNOSETUP_ALLOW_CUSTOM_DIRECTORY + - CPACK_INNOSETUP_PROGRAM_MENU_FOLDER + - CPACK_INNOSETUP_LANGUAGES + - CPACK_INNOSETUP_IGNORE_LICENSE_PAGE + - CPACK_INNOSETUP_IGNORE_README_PAGE + - CPACK_INNOSETUP_PASSWORD + - CPACK_INNOSETUP_USE_MODERN_WIZARD + - CPACK_INNOSETUP_ICON_FILE + - CPACK_INNOSETUP_SETUP_ + - CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS + - CPACK_INNOSETUP_MENU_LINKS + - CPACK_INNOSETUP_CREATE_UNINSTALL_LINK + - CPACK_INNOSETUP_RUN_EXECUTABLES + - CPACK_INNOSETUP__INSTALL_DIRECTORY + - CPACK_INNOSETUP_VERIFY_DOWNLOADS + - CPACK_INNOSETUP_EXECUTABLE + - CPACK_INNOSETUP_EXECUTABLE_ARGUMENTS + - CPACK_INNOSETUP_DEFINE_ + - CPACK_INNOSETUP_EXTRA_SCRIPTS + - CPACK_INNOSETUP_CODE_FILES + # [built-in]: CPack FreeBSD Generator (Since 3.10) + - CPACK_FREEBSD_PACKAGE_NAME + - CPACK_FREEBSD_PACKAGE_COMMENT + - CPACK_FREEBSD_PACKAGE_DESCRIPTION + - CPACK_FREEBSD_PACKAGE_WWW + - CPACK_FREEBSD_PACKAGE_LICENSE + - CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC + - CPACK_FREEBSD_PACKAGE_MAINTAINER + - CPACK_FREEBSD_PACKAGE_ORIGIN + - CPACK_FREEBSD_PACKAGE_CATEGORIES + - CPACK_FREEBSD_PACKAGE_DEPS # -CPackExt (Since 3.13) - CPACK_EXTERNAL_REQUESTED_VERSIONS - CPACK_EXTERNAL_ENABLE_STAGING @@ -1970,6 +2133,7 @@ variables: - CUPS_INCLUDE_DIR # - FindCURL - CURL_NO_CURL_CMAKE + - CURL_USE_STATIC_LIBS # Since 3.28 # - FindCurses - CURSES_CFLAGS - CURSES_HAVE_CURSES_H @@ -1989,7 +2153,6 @@ variables: - CXXTEST_TESTGEN_EXECUTABLE - CXXTEST_TESTGEN_INTERPRETER # - FindCygwin - # - FindDart # - FindDCMTK # - FindDevIL # - FindDoxygen @@ -1997,6 +2160,7 @@ variables: # - FindEnvModules - EnvModules_COMMAND # - FindEXPAT + - EXPAT_USE_STATIC_LIBS # Since 3.28 # - FindFLEX - FLEX_EXECUTABLE # - FindFLTK @@ -2598,6 +2762,11 @@ deprecated-or-internal-variables: - CMAKE_OBJDUMP # Mentioned in "Deprecated and Removed Features" of release notes 3.21 - CMAKE_SYSTEM_ARCH + # Superseded by `CMAKE_EXECUTABLE_ENABLE_EXPORTS` + - CMAKE_ENABLE_EXPORTS + - CMAKE_IOS_INSTALL_COMBINED # Since 3.28 + + # https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html # NOTE Added to syntax file version 14 at 3.15.0 version of CMake @@ -2614,6 +2783,7 @@ environment-variables: - CMAKE_COLOR_DIAGNOSTICS # Since 3.24 - CMAKE_CONFIGURATION_TYPES # Since 3.22 - CMAKE_CONFIG_TYPE + - CMAKE_CROSSCOMPILING_EMULATOR # Since 3.28 - CMAKE_EXPORT_COMPILE_COMMANDS # Since 3.17 - CMAKE_GENERATOR - CMAKE_GENERATOR_INSTANCE @@ -2657,11 +2827,13 @@ environment-variables: # Environment Variables for CTest - CMAKE_CONFIG_TYPE - CTEST_INTERACTIVE_DEBUG_MODE + - CTEST_NO_TESTS_ACTION # Since 3.26 - CTEST_OUTPUT_ON_FAILURE - CTEST_PARALLEL_LEVEL - CTEST_PROGRESS_OUTPUT - CTEST_USE_LAUNCHERS_DEFAULT - DASHBOARD_TEST_FROM_CTEST + # Environment Variables for the CMake curses interface - CCMAKE_COLORS # Here are the `find_package` specific variables described at the # https://cmake.org/cmake/help/latest/command/find_package.html @@ -2731,6 +2903,7 @@ scripting-commands: , OS_RELEASE , OS_VERSION , OS_PLATFORM + , MSYSTEM_PREFIX # Since 3.28 # Since 3.22 , DISTRIB_INFO , DISTRIB_ @@ -3380,6 +3553,8 @@ scripting-commands: , CHECK_START , CHECK_PASS , CHECK_FAIL + # Since 3.26 + , CONFIGURE_LOG ] - name: option @@ -3520,10 +3695,12 @@ project-commands: , COMMENT , DEPFILE , JOB_POOL # Since 3.15 + , JOB_SERVER_AWARE # Since 3.28 , VERBATIM , APPEND , USES_TERMINAL , COMMAND_EXPAND_LISTS + , DEPENDS_EXPLICIT_ONLY # Since 3.27 , TARGET , PRE_BUILD , PRE_LINK @@ -3543,6 +3720,7 @@ project-commands: , COMMENT , DEPFILE , JOB_POOL # Since 3.15 + , JOB_SERVER_AWARE # Since 3.28 , VERBATIM , APPEND , USES_TERMINAL @@ -3587,6 +3765,9 @@ project-commands: , TARGET ] has-target-name-after-kw: TARGET + - + name: cmake_file_api # Since 3.27 + named-args: [QUERY, API_VERSION, CODEMODEL, CACHE, CMAKEFILES, TOOLCHAINS] - name: create_test_sourcelist named-args: [EXTRA_INCLUDE, FUNCTION] @@ -3614,6 +3795,7 @@ project-commands: ASM , ASM-ATT , ASM_NASM + , ASM_MARMASM # Since 3.26 , ASM_MASM , C , CSharp @@ -3650,6 +3832,7 @@ project-commands: property-args: &get_target_property [target-properties] - name: get_test_property + named-args: [DIRECTORY] # Since 3.28 property-args: &get_test_property [test-properties] - name: include_directories @@ -3741,7 +3924,7 @@ project-commands: named-args: [AFTER, BEFORE] - name: link_libraries - named-args: [debug, optimized, general] + special-args: &link_libraries_sa [debug, optimized, general] - name: load_cache named-args: [READ_WITH_PREFIX, EXCLUDE, INCLUDE_INTERNALS] @@ -3793,7 +3976,10 @@ project-commands: first-args-are-targets?: true # NOTE Multiple target args - name: set_tests_properties - named-args: [PROPERTIES] + named-args: [ + DIRECTORY # Since 3.28 + , PROPERTIES + ] property-args: *get_test_property - name: source_group @@ -3888,6 +4074,7 @@ project-commands: , cuda_std_17 , cuda_std_20 , cuda_std_23 # Since 3.21 + , cuda_std_26 # Since 3.25 ] first-arg-is-target?: true - @@ -3913,6 +4100,7 @@ project-commands: - name: target_link_libraries named-args: *target_compile_definitions + special-args: *link_libraries_sa first-arg-is-target?: true - name: target_link_options @@ -3935,6 +4123,10 @@ project-commands: , BASE_DIRS , FILES ] + special-args: [ + HEADERS + , CXX_MODULES # Since 3.28 + ] first-arg-is-target?: true - name: try_compile @@ -3959,6 +4151,9 @@ project-commands: , SOURCE_FROM_CONTENT , SOURCE_FROM_VAR , SOURCE_FROM_FILE + # Since 3.26 + , LOG_DESCRIPTION + , NO_LOG ] - name: try_run @@ -3987,6 +4182,9 @@ project-commands: , NO_CACHE , RUN_OUTPUT_STDOUT_VARIABLE , RUN_OUTPUT_STDERR_VARIABLE + # Since 3.26 + , LOG_DESCRIPTION + , NO_LOG ] ctest-commands: @@ -4150,7 +4348,6 @@ modules: - CTestCoverageCollectGCOV - CTestScriptMode - CTestUseLaunchers - - Dart - DeployQt4 - ExternalData - ExternalProject @@ -4196,7 +4393,6 @@ modules: - FindCVS - FindCxxTest - FindCygwin - - FindDart - FindDCMTK - FindDevIL - FindDoxygen @@ -4339,6 +4535,7 @@ modules: - CMakeExpandImportedTargets - CMakeForceCompiler - CMakeParseArguments + - Dart # Since 3.27 - Documentation - MacroAddFileDependencies - TestCXXAcceptsFlag @@ -4350,6 +4547,7 @@ modules: - WriteCompilerDetectionHeader # Deprecated Find Modules - FindCUDA + - FindDart # Since 3.27 - FindPythonInterp - FindPythonLibs - FindQt @@ -4773,6 +4971,7 @@ standard-module-commands: - BUILD_IN_SOURCE - BUILD_ALWAYS - BUILD_BYPRODUCTS + - BUILD_JOB_SERVER_AWARE # Since 3.28 - INSTALL_COMMAND - TEST_COMMAND - TEST_BEFORE_INSTALL @@ -4800,6 +4999,7 @@ standard-module-commands: - INDEPENDENT_STEP_TARGETS - LIST_SEPARATOR - COMMAND + - INSTALL_BYPRODUCTS # Since 3.26 special-args: [IGNORED, OPTIONAL, REQUIRED, CHECKOUT, REBASE, REBASE_CHECKOUT] property-args: *get_target_property - name: ExternalProject_Get_Property @@ -4814,6 +5014,7 @@ standard-module-commands: - INDEPENDENT - BYPRODUCTS - ALWAYS + - JOB_SERVER_AWARE # Since 3.28 - EXCLUDE_FROM_MAIN - WORKING_DIRECTORY - LOG @@ -4901,7 +5102,10 @@ standard-module-commands: - UPDATE_DISCONNECTED - PATCH_COMMAND - SOURCE_SUBDIR + - OVERRIDE_FIND_PACKAGE + - FIND_PACKAGE_ARGS - SYSTEM + - EXCLUDE_FROM_ALL # Since 3.28 - name: FetchContent_Populate named-args: @@ -5169,7 +5373,12 @@ standard-module-commands: # FindDoxygen - name: doxygen_add_docs - named-args: [ALL, USE_STAMP_FILE, WORKING_DIRECTORY, COMMENT] + named-args: + - ALL + - USE_STAMP_FILE + - WORKING_DIRECTORY + - COMMENT + - CONFIG_FILE # Since 3.27 # FindEnvModules - name: env_module @@ -5248,6 +5457,7 @@ standard-module-commands: named-args: *pkgcm - name: pkg_get_variable + named-args: [DEFINE_VARIABLES] # Since 3.28 # FindProtobuf - name: protobuf_generate_cpp diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-cmake-syntax.py b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-cmake-syntax.py index f500061f47e..0d9597320ee 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-cmake-syntax.py +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-cmake-syntax.py @@ -3,25 +3,31 @@ # # Generate Kate syntax file for CMake # -# SPDX-FileCopyrightText: 2017-2020 Alex Turbov +# SPDX-FileCopyrightText: 2017-2023 Alex Turbov # # To install prerequisites: # -# $ pip install --user click jinja2 pyyaml +# $ pip install --user click jinja2 lxml pyyaml # # To use: # # $ ./generate-cmake-syntax.py cmake.yaml > ../syntax/cmake.xml # + +from __future__ import annotations + +import functools +import re +from dataclasses import dataclass, field + import click import jinja2 -import re import yaml - +import sys from lxml import etree -_TEMPLATED_NAME = re.compile('<[^>]+>') +_TEMPLATED_NAME = re.compile(r'(?:<[^>]+>)') _PROPERTY_KEYS = [ 'global-properties' , 'directory-properties' @@ -33,7 +39,7 @@ _PROPERTY_KEYS = [ ] _KW_RE_LIST = ['kw', 're'] _VAR_KIND_LIST = ['variables', 'deprecated-or-internal-variables', 'environment-variables'] -_CONTROL_FLOW_LIST = set(( +_CONTROL_FLOW_LIST = { 'break' , 'continue' , 'elseif' @@ -45,39 +51,226 @@ _CONTROL_FLOW_LIST = set(( , 'if' , 'return' , 'while' -)) + } +_VAR_REF_ENTITY = '&var_ref_re;' + +_HEURISTICS = [ + ( + {'MAX(_(COUNT|MAJOR|MINOR|PATCH|TWEAK))?', 'MIN(_(COUNT|MAJOR|MINOR|PATCH|TWEAK))?'} + , 'M(AX|IN)(_(COUNT|MAJOR|MINOR|PATCH|TWEAK))?' + ) + , ({'OUTPUTS', 'OUTPUT_(HEADER|SOURCE)'}, 'OUTPUT(S|_(HEADER|SOURCE))') + , ({'PREFIX', 'SUFFIX'}, '(PRE|SUF)FIX') + , ({'CPPCHECK', 'CPPLINT'}, 'CPP(CHECK|LINT)') + , ({'DEPENDS', 'PREDEPENDS'}, '(PRE)?DEPENDS') + , ({'ICON', 'ICONURL'}, 'ICON(URL)?') + , ( + { + '&var%ref%re;(_INIT)?' + , 'DEBUG(_INIT)?' + , 'MINSIZEREL(_INIT)?' + , 'RELEASE(_INIT)?' + , 'RELWITHDEBINFO(_INIT)?' + } + , '(DEBUG|MINSIZEREL|REL(EASE|WITHDEBINFO)|&var%ref%re;)(_INIT)?' + ) + , ({'RELEASE', 'RELWITHDEBINFO'}, 'REL(EASE|WITHDEBINFO)') + , ({'POST', 'POSTUN', 'PRE', 'PREUN'}, 'P(RE|OST)(UN)?') + , ({'AUTOPROV', 'AUTOREQ', 'AUTOREQPROV'}, 'AUTO(PROV|REQ(PROV)?)') + , ({'DEFINITIONS', 'OPTIONS'}, '(DEFINI|OP)TIONS') + , ({'LIB_NAMES', 'LIBRARY'}, 'LIB(_NAMES|RARY)') + , ({'EXTENSIONS', 'EXTRA_FLAGS'}, 'EXT(ENSIONS|RA_FLAGS)') + , ({'DISABLED', 'DISPLAY_NAME'}, 'DIS(ABLED|PLAY_NAME)') + , ({'LIBRARIES', 'LINK_LIBRARIES', 'STATIC_LINK_LIBRARIES'}, '((STATIC_)?LINK_)?LIBRARIES') + , ({'INCLUDE_DIRS', 'LIBRARY_DIRS'}, '(INCLUDE|LIBRARY)_DIRS') + , ({'BINARY_DIR', 'SOURCE_DIR'}, '(BINARY|SOURCE)_DIR') + , ({'CFLAGS(_OTHER)?', 'LDFLAGS(_OTHER)?'}, '(C|LD)FLAGS(_OTHER)?') + , ({'INCLUDE_DIRECTORIES', 'LIBRARIES'}, '(INCLUDE_DIRECTO|LIBRA)RIES') + , ({'POSTFLIGHT_&var%ref%re;_SCRIPT', 'PREFLIGHT_&var%ref%re;_SCRIPT'}, 'P(RE|OST)FLIGHT_&var%ref%re;_SCRIPT') + , ({'DIRECTORIES', 'FRAMEWORK_DIRECTORIES'}, '(FRAMEWORK_)?DIRECTORIES') + , ({'FILE_FLAG', 'FILE'}, 'FILE(_FLAG)?') + , ({'DIR_PERMISSIONS', 'FILE_PERMISSIONS'}, '(DIR|FILE)_PERMISSIONS') + , ({'COMPILER_LAUNCHER', 'LINKER_LAUNCHER'}, '(COMPIL|LINK)ER_LAUNCHER') + , ({'COMPILER', 'COMPILE_(DEFINI|OP)TIONS'}, 'COMPILE(R|_(DEFINI|OP)TIONS)') + , ({'LICENSEURL', 'LICENSE_(EXPRESSION|FILE_NAME)'}, 'LICENSE(URL|_(EXPRESSION|FILE_NAME))') + , ({'NO_SONAME', 'SONAME'}, '(NO_)?SONAME') + , ({'CODE_SIGN_ON_COPY', 'REMOVE_HEADERS_ON_COPY'}, '(CODE_SIGN|REMOVE_HEADERS)_ON_COPY') + , ({'(REFERENCE|REFERENCEPROP_&var%ref%re;_TAG)_&var%ref%re;'}, 'REFERENCE(PROP_&var%ref%re;_TAG)?_&var%ref%re;') + , ({'DISABLE_FIND_PACKAGE', 'REQUIRE_FIND_PACKAGE'}, '(DISABLE|REQUIRE)_FIND_PACKAGE') + , ( + {'GROUP_USING_&var%ref%re;(_SUPPORTED)?', 'LIBRARY_USING_&var%ref%re;(_SUPPORTED)?'} + , '(GROUP|LIBRARY)_USING_&var%ref%re;(_SUPPORTED)?' + ) + , ( + { + 'EXE_LINKER_FLAGS_&var%ref%re;(_INIT)?' + , 'MODULE_LINKER_FLAGS_&var%ref%re;(_INIT)?' + , 'SHARED_LINKER_FLAGS_&var%ref%re;(_INIT)?' + , 'STATIC_LINKER_FLAGS_&var%ref%re;(_INIT)?' + } + , '(EXE|MODULE|SHARED|STATIC)_LINKER_FLAGS_&var%ref%re;(_INIT)?' + ) + , ( + { + 'ARCHIVE_OUTPUT_DIRECTORY' + , 'COMPILE_PDB_OUTPUT_DIRECTORY' + , 'LIBRARY_OUTPUT_DIRECTORY' + , 'PDB_OUTPUT_DIRECTORY' + , 'RUNTIME_OUTPUT_DIRECTORY' + } + , '(ARCHIVE|(COMPILE_)?PDB|LIBRARY|RUNTIME)_OUTPUT_DIRECTORY' + ) + , ( + { + 'ARCHIVE_OUTPUT_(DIRECTORY|NAME)' + , 'LIBRARY_OUTPUT_(DIRECTORY|NAME)' + , 'RUNTIME_OUTPUT_(DIRECTORY|NAME)' + } + , '(ARCHIVE|LIBRARY|RUNTIME)_OUTPUT_(DIRECTORY|NAME)' + ) + , ({'ASM&var_ref_re;', 'ASM&var_ref_re;FLAGS'}, 'ASM&var_ref_re;(FLAGS)?') + , ( + { + 'CMAKE_POLICY_DEFAULT_CMP[0-9]{4}' + , 'CMAKE_POLICY_WARNING_CMP[0-9]{4}' + } + , 'CMAKE_POLICY_(DEFAULT|WARNING)_CMP[0-9]{4}' + ) + , ({'CMAKE_ARGV[0-9]+', 'CMAKE_MATCH_[0-9]+'}, 'CMAKE_(ARGV|MATCH_)[0-9]+') + ] + +@dataclass +class RePartNode: + children: dict[str, RePartNode] = field(default_factory=dict, hash=False) + is_leaf: bool = False -def try_transform_placeholder_string_to_regex(name): +@dataclass +class RegexCollection: + special_cases: list[str] = field(default_factory=list, hash=False) + re_tree: dict[str, RePartNode] = field(default_factory=dict, hash=False) + + def add_case(self, regex: str) -> RegexCollection: + self.special_cases.append(regex) + return self + + def update_tree(self, name_parts: list[str]) -> RegexCollection: + safe_var_ref = _VAR_REF_ENTITY.replace('_', '%') + current = functools.reduce( + lambda current, part: ( + self.re_tree if current is None else current.children + ).setdefault(part, RePartNode()) + , safe_var_ref.join(name_parts).replace(f'{safe_var_ref}_{safe_var_ref}', safe_var_ref).split('_') + , None + ) + current.is_leaf = True + return self + + +def try_transform_placeholder_string_to_regex(state: RegexCollection, name: str): ''' NOTE Some placeholders are not IDs, but numbers... `CMAKE_MATCH_` 4 example ''' - m = _TEMPLATED_NAME.split(name) - if 'CMAKE_MATCH_' in m: - return 'CMAKE_MATCH_[0-9]+' + name_parts = _TEMPLATED_NAME.split(name) + match name_parts: + case ['CMAKE_MATCH_' as head, ''] | ['CMAKE_ARGV' as head, ''] | ['ARGV' as head, '']: + return state.add_case(head + '[0-9]+') - if 'CMAKE_ARGV' in m: - return 'CMAKE_ARGV[0-9]+' + case ['CMAKE_POLICY_DEFAULT_CMP' as head, ''] | ['CMAKE_POLICY_WARNING_CMP' as head, '']: + return state.add_case(head + '[0-9]{4}') - if 'CMAKE_POLICY_DEFAULT_CMP' in m: - return 'CMAKE_POLICY_DEFAULT_CMP[0-9]{4}' + case ['', '__TRYRUN_OUTPUT']: + return state.add_case(f'{_VAR_REF_ENTITY}__TRYRUN_OUTPUT') - if 'CMAKE_POLICY_WARNING_CMP' in m: - return 'CMAKE_POLICY_WARNING_CMP[0-9]{4}' + case (['ASM', ''] | ['ASM', 'FLAGS']) as asm_env: + return state.add_case(f'{asm_env[0]}{_VAR_REF_ENTITY}{asm_env[1]}') - if 'ARGV' in m: - return 'ARGV[0-9]+' + return state.update_tree(name_parts) - return '&var_ref_re;'.join(m) if 1 < len(m) else name + +def is_first_subset_of_second(first, second): + subset = set(first) + fullset = set(second) + return subset.issubset(fullset) + + +def try_optimize_known_alt_groups(groups: list[str]) -> list[str]: + for case in _HEURISTICS: + if is_first_subset_of_second(case[0], groups): + groups = sorted([*filter(lambda item: item not in case[0], groups), case[1]]) + return groups + + +def try_optimize_trailing_var_ref_regex(groups: list[str]) -> list[str]: + tail_var_ref_re = '_' + _VAR_REF_ENTITY.replace('_', '%') + candidates = [*filter(lambda s: s.endswith(tail_var_ref_re), groups)] + return sorted([ + *filter(lambda item: item not in candidates, groups) + , f'({"|".join(try_optimize_known_alt_groups([s[:-len(tail_var_ref_re)] for s in candidates]))}){tail_var_ref_re}' + ]) if len(candidates) > 1 else groups + + +def build_regex(state: list[str], kv: tuple[str, RePartNode]) -> list[str]: + name, value = kv + match (value, len(value.children)): + case (RePartNode(children={}, is_leaf=True), 0): + return [*state, name] + + case (node, sz) if sz > 0: + alt_group = try_optimize_known_alt_groups( + try_optimize_trailing_var_ref_regex( + functools.reduce(build_regex, node.children.items(), []) + ) + ) + + match (len(alt_group), node.is_leaf): + case (1, False): + return [*state, f'{name}_{alt_group[0]}'] + + case (1, True): + return [*state, f'{name}(_{alt_group[0]})?'] + + case (sz, False) if sz > 0: + return [*state, f'{name}_({"|".join(alt_group)})'] + + case (sz, True) if sz > 0: + return [*state, f'{name}(_({"|".join(alt_group)}))?'] + + case _: + raise AssertionError('Zero children?') + + case _: + raise AssertionError(f'NOT MATCHED: {name=}→{value=}') + + return state def try_placeholders_to_regex(names): if not names: return None - l = map(try_transform_placeholder_string_to_regex, names) - l = sorted(l, reverse=True) - return '\\b(?:' + '|'.join(l) + ')\\b' + + data = functools.reduce( + try_transform_placeholder_string_to_regex + , names + , RegexCollection() + ) + + return ( + '\\b(?:' + + '|'.join( + try_optimize_known_alt_groups( + try_optimize_trailing_var_ref_regex( + functools.reduce( + build_regex + , data.re_tree.items() + , data.special_cases + ) + ) + ) + ).replace('%', '_') + + ')\\b' + ) def partition_iterable(fn, iterable): @@ -287,7 +480,8 @@ def cli(input_yaml, template): del data['standard-module-commands'] # Fix node names to be accessible from Jinja template - data['generator_expressions'] = data['generator-expressions'] + data['generator_expressions'] = (ex for ex in data['generator-expressions'] if isinstance(ex, str)) + data['complex_generator_expressions'] = [ex for ex in data['generator-expressions'] if not isinstance(ex, str)] data['deprecated_or_internal_variables'] = data['deprecated-or-internal-variables'] data['environment_variables'] = data['environment-variables'] del data['generator-expressions'] diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-html.pl b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-html.pl new file mode 100644 index 00000000000..a5b9bc9d058 --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-html.pl @@ -0,0 +1,143 @@ +#!/usr/bin/perl + +# This perl script read stdin and write on stdout. It shall be an XML language file. +# +# * If the name of the language is 'HTML', then it creates the language 'PHP (HTML)' +# which shall be used for PHP hl. +# +# * If the name of the language is something else (say '*'), it creates the language '*/PHP'. +# This new language is the same as the old one, but is able to detect PHP everywhere. +# +# This script will correctly set extensions & mimetype, and will replace +# by +# +# Generated languages need a language named 'PHP/PHP', which shall take care of PHP hl itself +# and which will be called every time something like +# License: LGPL + +my $file = ""; + +open(my $input, '<:encoding(UTF-8)', $ARGV[0]) + or die "Could not open file '$ARGV[0]': $!"; + +open(my $output, '>:encoding(UTF-8)', $ARGV[1]) + or die "Could not open file '$ARGV[1]': $!"; + +my $language = $ARGV[1]; +if ($language =~ /-php\.xml$/) +{ + $language = "PHP"; +} +else +{ + $language = "Twig"; +} + +while (<$input>) +{ + $file .= $_; +} + +$warning = "\n\n\n"; + +$file =~ s/(?=]+)priority="[^"]*"/]+)name="[^"]*"/]+)section="[^"]*"/]+)extensions="[^"]*"/]+)mimetype="[^"]*"/]+)*/]+)extensions="[^"]*"/]+)mimetype="[^"]*"/]+)hidden="[^"]*"/]+)section="[^"]*"/]+)mimetype="[^"]*"/]+)name="([^"]*)"/]+)extensions="[^"]*"/.*?<\/list>/$1##$syntaxName<\/include><\/list>/gs; + +$file =~ s/]+)kateversion="[^"]*"///gs; + } +} +elsif ($root == 1 || $ARGV[0] =~ /mustache.xml$/) +{ + $file =~ s/<(?:RegExpr (attribute="Processing Instruction" context="PI"|context="PI" attribute="Processing Instruction")|itemData name="Processing Instruction")[^\/]+\/>|//gs; +} + +my $find_language = "##$language/$language"; +my $language_suffix = "/$language"; +if ($language eq "PHP") +{ + $find_language = "FindPHP"; +} + +$file =~ s/]*)context="([^"#]*)##(?!Alerts|Comments|Doxygen|Modelines)([^"]+)"/]*[^>\/]>)/$1\n/g; +$file =~ s/(]*[^>\/])\s*\/>/$1>\n\n<\/context>/g; + +if ($language eq "PHP") +{ + $findphp = "\n\n\n"; + $file =~ s/(?=<\/contexts\s*>)/$findphp/; +} + +print $output $file; +print $output $warning; diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-nginx-lists.rb b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-nginx-lists.rb new file mode 100644 index 00000000000..577dea47c4c --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-nginx-lists.rb @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby +# +# Generates the keyword lists for directives and variables used in nginx and +# prints them to stdout, ready to be copy & pasted into nginx.xml. +# +# SPDX-FileCopyrightText: 2023 Georg Gadinger +# SPDX-License-Identifier: MIT +# +# Usage: +# % ./generate-nginx-lists.rb +# +# if you want to install the required dependencies provide `INSTALL_GEMS` in +# your ENV: +# % INSTALL_GEMS=1 ./generate-nginx-lists.rb + +require "bundler/inline" + +gemfile(ENV["INSTALL_GEMS"]) do + source "https://rubygems.org" + + gem "nokogiri", "~> 1.14" + gem "faraday", "~> 2.7" + gem "builder", "~> 3.2" +end + +def fetch_vars(url) + Faraday.get(url) + .then { Nokogiri::HTML.parse _1.body } + .css("div#content a[href]") + .map(&:text) + .reject { _1.end_with?("_") } # some vars are just a prefix, ignore those + .sort + .uniq +end + +def build_xml_list(name, url: nil, items: []) + builder = Builder::XmlMarkup.new(indent: 2) + + builder.comment! "see #{url} for a full list of #{name}" + builder.list(name:) do |b| + items.each do |item| + b.item item + end + end +end + +{ + directives: "https://nginx.org/en/docs/dirindex.html", + variables: "https://nginx.org/en/docs/varindex.html", +}.each do |name, url| + items = fetch_vars(url) + + puts build_xml_list(name, url:, items:).gsub(/^/, ' ' * 4) + puts +end diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-php.pl b/src/libs/3rdparty/syntax-highlighting/data/generators/generate-php.pl deleted file mode 100644 index a516332ef2f..00000000000 --- a/src/libs/3rdparty/syntax-highlighting/data/generators/generate-php.pl +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/perl - -# This perl script read stdin and write on stdout. It shall be an XML language file. -# -# * If the name of the language is 'HTML', then it creates the language 'PHP (HTML)' -# which shall be used for PHP hl. -# -# * If the name of the language is something else (say '*'), it creates the language '*/PHP'. -# This new language is the same as the old one, but is able to detect PHP everywhere. -# -# This script will correctly set extensions & mimetype, and will replace -# by -# -# Generated languages need a language named 'PHP/PHP', which shall take care of PHP hl itself -# and which will be called every time something like -# License: LGPL - -my $file = ""; - -open(my $input, '<:encoding(UTF-8)', $ARGV[0]) - or die "Could not open file '$ARGV[0]': $!"; - -open(my $output, '>:encoding(UTF-8)', $ARGV[1]) - or die "Could not open file '$ARGV[1]': $!"; - -while (<$input>) -{ - $file .= $_; -} - -$warning = "\n\n\n"; - -$file =~ s/(?=]+name="HTML"/) -{ - $root = 1; -} - -if ($root == 1) -{ - $file =~ s/]+)name="[^"]*"/]+)section="[^"]*"/]+)extensions="[^"]*"/]+)mimetype="[^"]*"/]+)*/]+hidden="[^"]*"/) { - $file =~ s/]+)name="([^"]*)"/]+)hidden="[^"]*"/]+)name="([^"]*)"/' else sep + return f'{sep}{seq}\n{end}{m[3]}' + + current_at_rules.update(item_extractor.findall(m[2])) + return m[0] + + +css_content = css_filename.read_text() +original_css_content = css_content + +names = f"{'|'.join(css_replacements)}|at-rules(?: definitions)?" +css_content = re.sub(rf'(.*?)(|)', + _css_update_and_extract_items, css_content, flags=re.DOTALL) + +_regexpr_unit_prefix = r'( None: + at_rule_added = new_at_rules - old_at_rules + at_rule_removed = old_at_rules - new_at_rules + nl = '\n ' + if at_rule_added or at_rule_removed: + print(f"""\x1b[31m{language} At-rules requires a manual update +New ({len(at_rule_added)}):\x1b[0m + {nl.join(at_rule_added)} +\x1b[31mRemoved ({len(at_rule_removed)}):\x1b[0m + {nl.join(at_rule_removed)}""") + +show_at_rule_difference('CSS', current_at_rules, at_rules) + +# +# Extract SCSS data +# + +scss_functions:list[str] = [] +scss_at_rules:set[str] = {'@content', '@return'} + +_function_list_extractor = re.compile(r'{% function (.*?) %}') +_function_extractor = re.compile(r"'([-._a-zA-Z0-9]+)\(") +_at_rule_extractor = re.compile(r'@[-a-z0-9]+') + +for md in sorted(scss_dir.glob('source/documentation/modules/**/*.md')): + func_list = _function_list_extractor.findall(md.read_text()) + func_items = set(_function_extractor.findall(''.join(func_list))) + scss_functions.append(f'\n{sep}') + scss_functions.extend(f'{sep}{func}' for func in sorted(func_items - functions)) + +for md in scss_dir.glob('source/documentation/at-rules/**/*.md'): + with open(md) as f: + f.readline() + scss_at_rules.update(_at_rule_extractor.findall(f.readline())) + +subproperties = set( + '-'.join(splitted[i:n]) + for prop in properties + for splitted in (prop.rsplit('-', prop.count('-') - 1) # '-aaa-bbb' -> ['-aaa', 'bbb'] + if prop.startswith('-') + else prop.split('-'), ) # 'aaa-bbb' -> ['aaa', 'bbb'] + for i in range(len(splitted)) + for n in range(i+1, len(splitted)+1) +) + +# +# Update SCSS +# + +scss_current_at_rules = set() + +def _scss_update_and_extract_items(m) -> str: + name = m[1] + + if name == 'functions': + return f""" + functions##CSS + + {f''.join(scss_functions)} + """ + + if name == 'at-rules': + scss_current_at_rules.update(_at_rule_extractor.findall(m[2])) + return m[0] + + # sub-properties + items = f'{sep}'.join(sorted(subproperties - properties)) + return f'{sep}{items}\n ' + +scss_content = scss_filename.read_text() +original_scss_content = scss_content + +scss_content = re.sub(r'(.*?)', + _scss_update_and_extract_items, scss_content, count=3, flags=re.DOTALL) + +scss_content = re.sub(r'', + f'', + scss_content, count=1) + +scss_content = regexpr_unit_extractor.sub('\\1' + "|".join(units), scss_content, 1) + +if original_scss_content != scss_content: + scss_content = update_version(scss_content) + scss_filename.write_text(scss_content) + +show_at_rule_difference('SCSS', scss_current_at_rules, scss_at_rules) diff --git a/src/libs/3rdparty/syntax-highlighting/data/generators/update_less.py b/src/libs/3rdparty/syntax-highlighting/data/generators/update_less.py new file mode 100644 index 00000000000..d509aeabe77 --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/data/generators/update_less.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2023 Jonathan Poelen +# SPDX-License-Identifier: MIT + +from pathlib import Path +from urllib import request +import re +import sys + + +if len(sys.argv) < 1: + print(f'{sys.argv[0]} syntax/less.xml', file=sys.stderr) + exit(1) + +# +# Extract functions +# + +data = request.urlopen('https://lesscss.org/functions/').read().decode() + +functions = re.findall(r'([-_\w\d]+)', data, flags=re.DOTALL) +functions.append('%') + +# +# Update syntax +# + +sep = '\n ' +new_list = f""" + functions##CSS + + + {f'{sep}'.join(sorted(functions))} + """ + +less_filename = Path(sys.argv[1]) +less_content = less_filename.read_text() +original_less_content = less_content +less_content = re.sub(r'.*?', + new_list, less_content, count=1, flags=re.DOTALL) + +if original_less_content != less_content: + less_content = re.sub(' version="(\d+)" ', lambda m: f' version="{int(m[1])+1}" ', + less_content, count=1) + less_filename.write_text(less_content) diff --git a/src/libs/3rdparty/syntax-highlighting/data/schema/language.xsd b/src/libs/3rdparty/syntax-highlighting/data/schema/language.xsd index fdea0dd7521..b6402194144 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/schema/language.xsd +++ b/src/libs/3rdparty/syntax-highlighting/data/schema/language.xsd @@ -6,39 +6,22 @@ SPDX-FileCopyrightText: 2005 Dominik Haumann SPDX-FileCopyrightText: 2008 Wilbert Berendsen - This file describes the XML format used for syntax highlight descriptions - for the Kate text editor (http://kate.kde.org), which is part of the KDE - desktop environment (http://www.kde.org). - You'll find the "Writing a Kate Highlighting XML File HOWTO" at - http://kate.kde.org/doc/hlhowto.php + This file describes the XML format used for syntax highlight descriptions + for the Kate text editor (https://kate-editor.org), which is part of the + KDE desktop environment (https://kde.org). + You'll find the "Working with Syntax Highlighting" at + https://docs.kde.org/stable5/en/kate/katepart/highlight.html - This format is identified using the SYSTEM identifier - SYSTEM "language.dtd" + You can validate your syntax files using "validatehl.sh yourSyntax.xml". + This needs xmllint from the libxml2 XML library. - Files using this format should include a DOCTYPE declaration like this: - - - You can validate your syntax files using "validatehl.sh yourSyntax.xml". - This needs xmllint from the libxml2 XML library. - - In any case, the katehighlightingindexer will validate all files bundled - with KTextEditor during compile time and fail on errors. - - To use your syntax file, copy it to ~/.local/share/katepart5/syntax/ in - your home directory. You have to open a new instance of kwrite/kate to use - the new syntax file. + In any case, the katehighlightingindexer will validate all files bundled + with KTextEditor during compile time and fail on errors. TODO - find a more readable way for the - -dtdvalid stuff, it's just annoying xml comments don't allow it. --> - @@ -160,6 +136,7 @@ + @@ -317,20 +294,18 @@ context specification name: The name of this context specification. Used in '*Context' attributes [optional] attribute: The name of the ItemData to be used for matching text - lineEndContext: Next context if end of line is encountered - lineEmptyContext: Next context if an empty line is encountered [optional] + lineEndContext: Next context if end of line is encountered [optional, default='#stay'] + lineEmptyContext: Next context if an empty line is encountered [optional, default=value of lineEndContext] fallthrough: Use a fallthrough context [optional] deprecated since 5.62 but preserved to maintain compatibility in older versions of KF5 - fallthroughContext: Fall through to this context [optional] + fallthroughContext: Fall through to this context [optional, default='#stay'] dynamic: Dynamic context [boolean, optional] + deprecated since always but preserved to maintain compatibility in older versions of KF5 noIndentationBasedFolding: Python uses indentation based folding. However, Python has parts where - it does not use indentation based folding (e.g. for """ strings). In this case - switch to an own context and set this attribute to true. Then the indentation - based folding will ignore this parts and not change folding markers. [optional] - - TODO: - - Explain fallthrough. - - Make lineEndContext optional, defaults to '#stay'. Reasonable? + it does not use indentation based folding (e.g. for """ strings). In this case + switch to an own context and set this attribute to true. Then the indentation + based folding will ignore this parts and not change folding markers. [optional] + stopEmptyLineContextSwitchLoop: Do not continue the context switching if an empty line is encountered. [boolean, optional, default=false] --> @@ -356,11 +331,11 @@ - + - + @@ -368,8 +343,11 @@ + + + @@ -504,12 +479,9 @@ @@ -523,9 +495,6 @@ String: The string to look for insensitive: Whether the string is matched case INsensitive. [boolean, optional, default=false] dynamic: Uses %1 .. %9 as placeholders for dynamic arguments [boolean, optional, default=false] - - TODO - - What's default of insensitive? I'm not sure... --> @@ -542,9 +511,6 @@ insensitive: Whether the string is matched case INsensitive. [boolean, optional, default=false] weakDeliminator: Add weak deliminators [optional] additionalDeliminator: Add deliminators [optional] - - TODO - - What's default of insensitive? I'm not sure... --> @@ -560,7 +526,7 @@ commonAttributes: Common attributes String: The regular expression pattern insensitive: Whether the text is matched case INsensitive. [boolean, optional, default=false] - minimal: Wheather to use minimal matching for wild cards in the pattern [boolean, optional, default='false'] + minimal: Wheather to use minimal matching for wild cards in the pattern [boolean, optional, default=false] dynamic: Uses %1 .. %9 as placeholders for dynamic arguments [boolean, optional, default=false] --> @@ -584,11 +550,8 @@ @@ -596,7 +559,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml index 84d0cf84183..b3e8334fdaa 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/bash.xml @@ -1,5 +1,5 @@ - @@ -66,7 +66,7 @@ - + @@ -1005,13 +1005,15 @@ - + + - + + @@ -1019,7 +1021,8 @@ - + + @@ -1046,8 +1049,9 @@ - - + + + @@ -1073,7 +1077,7 @@ - + @@ -1081,27 +1085,32 @@ - + + + + + + + - + - - + - + - - + @@ -1262,6 +1271,7 @@ + @@ -1270,6 +1280,8 @@ + + @@ -1277,6 +1289,10 @@ + + + + @@ -1352,7 +1368,7 @@ - + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml index 053d983c343..256619d3ff8 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml @@ -1,5 +1,5 @@ - @@ -12,7 +12,7 @@ SPDX-FileCopyrightText: 2004 Alexander Neundorf SPDX-FileCopyrightText: 2005 Dominik Haumann SPDX-FileCopyrightText: 2007, 2008, 2013, 2014 Matthew Woehlke - SPDX-FileCopyrightText: 2013-2015, 2017-2020 Alex Turbov + SPDX-FileCopyrightText: 2013-2015, 2017-2023 Alex Turbov SPDX-License-Identifier: LGPL-2.0-or-later --> @@ -25,8 +25,8 @@ add_test aux_source_directory build_command + cmake_file_api create_test_sourcelist define_property enable_language @@ -192,6 +193,7 @@ HOST HOSTNAME IS_64BIT + MSYSTEM_PREFIX NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES OS_NAME @@ -729,6 +731,7 @@ CHECK_FAIL CHECK_PASS CHECK_START + CONFIGURE_LOG DEBUG DEPRECATION FATAL_ERROR @@ -849,9 +852,11 @@ COMMAND_EXPAND_LISTS COMMENT DEPENDS + DEPENDS_EXPLICIT_ONLY DEPFILE IMPLICIT_DEPENDS JOB_POOL + JOB_SERVER_AWARE MAIN_DEPENDENCY OUTPUT POST_BUILD @@ -873,6 +878,7 @@ DEPFILE IMPLICIT_DEPENDS JOB_POOL + JOB_SERVER_AWARE SOURCES USES_TERMINAL VERBATIM @@ -914,6 +920,14 @@ PARALLEL_LEVEL TARGET + + API_VERSION + CACHE + CMAKEFILES + CODEMODEL + QUERY + TOOLCHAINS + EXTRA_INCLUDE FUNCTION @@ -937,6 +951,7 @@ ASM ASM-ATT + ASM_MARMASM ASM_MASM ASM_NASM C @@ -965,6 +980,9 @@ DIRECTORY TARGET_DIRECTORY + + DIRECTORY + AFTER BEFORE @@ -1045,7 +1063,7 @@ AFTER BEFORE - + debug general optimized @@ -1085,6 +1103,10 @@ PROPERTIES TARGET_DIRECTORY + + DIRECTORY + PROPERTIES + FILES PREFIX @@ -1112,6 +1134,7 @@ cuda_std_17 cuda_std_20 cuda_std_23 + cuda_std_26 cxx_aggregate_default_initializers cxx_alias_templates cxx_alignas @@ -1206,6 +1229,10 @@ PUBLIC TYPE + + CXX_MODULES + HEADERS + BINARY_DIR CMAKE_FLAGS @@ -1214,7 +1241,9 @@ COPY_FILE_ERROR LINK_LIBRARIES LINK_OPTIONS + LOG_DESCRIPTION NO_CACHE + NO_LOG OUTPUT_VARIABLE PROJECT SOURCES @@ -1234,7 +1263,9 @@ COPY_FILE_ERROR LINK_LIBRARIES LINK_OPTIONS + LOG_DESCRIPTION NO_CACHE + NO_LOG OUTPUT_VARIABLE RUN_OUTPUT_STDERR_VARIABLE RUN_OUTPUT_STDOUT_VARIABLE @@ -1563,6 +1594,7 @@ BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE + BUILD_JOB_SERVER_AWARE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS @@ -1601,6 +1633,7 @@ HTTP_USERNAME INACTIVITY_TIMEOUT INDEPENDENT_STEP_TARGETS + INSTALL_BYPRODUCTS INSTALL_COMMAND INSTALL_DIR LIST_SEPARATOR @@ -1666,6 +1699,7 @@ DEPENDS EXCLUDE_FROM_MAIN INDEPENDENT + JOB_SERVER_AWARE LOG USES_TERMINAL WORKING_DIRECTORY @@ -1708,6 +1742,8 @@ DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME @@ -1725,6 +1761,7 @@ INACTIVITY_TIMEOUT NETRC NETRC_FILE + OVERRIDE_FIND_PACKAGE PATCH_COMMAND SOURCE_SUBDIR SVN_PASSWORD @@ -1946,6 +1983,7 @@ ALL COMMENT + CONFIG_FILE USE_STAMP_FILE WORKING_DIRECTORY @@ -2009,6 +2047,9 @@ REQUIRED STATIC_TARGET + + DEFINE_VARIABLES + DESCRIPTORS EXPORT_MACRO @@ -2081,6 +2122,7 @@ CABLE_INCLUDE_DIR CABLE_TCL_LIBRARY CMAKE_ABSOLUTE_DESTINATION_FILES + CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY CMAKE_AIX_EXPORT_ALL_SYMBOLS CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API @@ -2116,15 +2158,19 @@ CMAKE_ARGC CMAKE_AUTOGEN_ORIGIN_DEPENDS CMAKE_AUTOGEN_PARALLEL + CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE CMAKE_AUTOGEN_VERBOSE CMAKE_AUTOMOC CMAKE_AUTOMOC_DEPEND_FILTERS + CMAKE_AUTOMOC_EXECUTABLE CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_PATH_PREFIX CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC + CMAKE_AUTORCC_EXECUTABLE CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC + CMAKE_AUTOUIC_EXECUTABLE CMAKE_AUTOUIC_OPTIONS CMAKE_AUTOUIC_SEARCH_PATHS CMAKE_BACKWARDS_COMPATIBILITY @@ -2185,6 +2231,7 @@ CMAKE_CXX_EXTENSIONS CMAKE_CXX_LINK_NO_PIE_SUPPORTED CMAKE_CXX_LINK_PIE_SUPPORTED + CMAKE_CXX_SCAN_FOR_MODULES CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES @@ -2200,6 +2247,7 @@ CMAKE_DEPENDS_IN_PROJECT_ONLY CMAKE_DIRECTORY_LABELS CMAKE_DISABLE_PRECOMPILE_HEADERS + CMAKE_DLL_NAME_WITH_SOVERSION CMAKE_DL_LIBS CMAKE_DOTNET_SDK CMAKE_DOTNET_TARGET_FRAMEWORK @@ -2210,9 +2258,9 @@ CMAKE_ECLIPSE_RESOURCE_ENCODING CMAKE_ECLIPSE_VERSION CMAKE_EDIT_COMMAND - CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION + CMAKE_EXECUTABLE_ENABLE_EXPORTS CMAKE_EXECUTABLE_SUFFIX CMAKE_EXECUTE_PROCESS_COMMAND_ECHO CMAKE_EXE_LINKER_FLAGS @@ -2286,6 +2334,7 @@ CMAKE_HIP_EXTENSIONS CMAKE_HIP_LINK_NO_PIE_SUPPORTED CMAKE_HIP_LINK_PIE_SUPPORTED + CMAKE_HIP_PLATFORM CMAKE_HIP_STANDARD CMAKE_HIP_STANDARD_REQUIRED CMAKE_HOST_APPLE @@ -2360,7 +2409,6 @@ CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP CMAKE_INSTALL_UCRT_LIBRARIES CMAKE_INTERPROCEDURAL_OPTIMIZATION - CMAKE_IOS_INSTALL_COMBINED CMAKE_ISPC_HEADER_DIRECTORY CMAKE_ISPC_HEADER_SUFFIX CMAKE_ISPC_INSTRUCTION_SETS @@ -2378,6 +2426,7 @@ CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED + CMAKE_LINK_DEPENDS_USE_LINKER CMAKE_LINK_DIRECTORIES_BEFORE CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARIES_ONLY_TARGETS @@ -2436,6 +2485,7 @@ CMAKE_PCH_INSTANTIATE_TEMPLATES CMAKE_PCH_WARN_INVALID CMAKE_PDB_OUTPUT_DIRECTORY + CMAKE_PLATFORM_NO_VERSIONED_SONAME CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH @@ -2460,6 +2510,7 @@ CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_SCRIPT_MODE_FILE + CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS @@ -2520,6 +2571,10 @@ CMAKE_VERIFY_INTERFACE_HEADER_SETS CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN + CMAKE_VS_DEBUGGER_COMMAND + CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS + CMAKE_VS_DEBUGGER_ENVIRONMENT + CMAKE_VS_DEBUGGER_WORKING_DIRECTORY CMAKE_VS_DEVENV_COMMAND CMAKE_VS_GLOBALS CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD @@ -2529,9 +2584,12 @@ CMAKE_VS_NUGET_PACKAGE_RESTORE CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME + CMAKE_VS_PLATFORM_NAME_DEFAULT CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_PLATFORM_TOOLSET_CUDA + CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE + CMAKE_VS_PLATFORM_TOOLSET_VERSION CMAKE_VS_SDK_EXCLUDE_DIRECTORIES CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES CMAKE_VS_SDK_INCLUDE_DIRECTORIES @@ -2539,6 +2597,11 @@ CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES CMAKE_VS_SDK_REFERENCE_DIRECTORIES CMAKE_VS_SDK_SOURCE_DIRECTORIES + CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER + CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION + CMAKE_VS_TARGET_FRAMEWORK_VERSION + CMAKE_VS_VERSION_BUILD_NUMBER + CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM CMAKE_VS_WINRT_BY_DEFAULT @@ -2653,6 +2716,16 @@ CPACK_EXTERNAL_ENABLE_STAGING CPACK_EXTERNAL_PACKAGE_SCRIPT CPACK_EXTERNAL_REQUESTED_VERSIONS + CPACK_FREEBSD_PACKAGE_CATEGORIES + CPACK_FREEBSD_PACKAGE_COMMENT + CPACK_FREEBSD_PACKAGE_DEPS + CPACK_FREEBSD_PACKAGE_DESCRIPTION + CPACK_FREEBSD_PACKAGE_LICENSE + CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC + CPACK_FREEBSD_PACKAGE_MAINTAINER + CPACK_FREEBSD_PACKAGE_NAME + CPACK_FREEBSD_PACKAGE_ORIGIN + CPACK_FREEBSD_PACKAGE_WWW CPACK_GENERATOR CPACK_IFW_ADMIN_TARGET_DIRECTORY CPACK_IFW_ARCHIVE_COMPRESSION @@ -2701,6 +2774,26 @@ CPACK_IFW_TARGET_DIRECTORY CPACK_IFW_VERBOSE CPACK_INCLUDE_TOPLEVEL_DIRECTORY + CPACK_INNOSETUP_ALLOW_CUSTOM_DIRECTORY + CPACK_INNOSETUP_ARCHITECTURE + CPACK_INNOSETUP_CODE_FILES + CPACK_INNOSETUP_CREATE_UNINSTALL_LINK + CPACK_INNOSETUP_CUSTOM_INSTALL_INSTRUCTIONS + CPACK_INNOSETUP_EXECUTABLE + CPACK_INNOSETUP_EXECUTABLE_ARGUMENTS + CPACK_INNOSETUP_EXTRA_SCRIPTS + CPACK_INNOSETUP_ICON_FILE + CPACK_INNOSETUP_IGNORE_LICENSE_PAGE + CPACK_INNOSETUP_IGNORE_README_PAGE + CPACK_INNOSETUP_INSTALL_ROOT + CPACK_INNOSETUP_LANGUAGES + CPACK_INNOSETUP_MENU_LINKS + CPACK_INNOSETUP_PASSWORD + CPACK_INNOSETUP_PROGRAM_MENU_FOLDER + CPACK_INNOSETUP_RUN_EXECUTABLES + CPACK_INNOSETUP_USE_CMAKE_BOOL_FORMAT + CPACK_INNOSETUP_USE_MODERN_WIZARD + CPACK_INNOSETUP_VERIFY_DOWNLOADS CPACK_INSTALLED_DIRECTORIES CPACK_INSTALL_CMAKE_PROJECTS CPACK_INSTALL_COMMANDS @@ -2988,6 +3081,7 @@ CUDAToolkit_NVCC_EXECUTABLE CUPS_INCLUDE_DIR CURL_NO_CURL_CMAKE + CURL_USE_STATIC_LIBS CURSES_CFLAGS CURSES_HAVE_CURSES_H CURSES_HAVE_NCURSES_CURSES_H @@ -3006,6 +3100,7 @@ DVIPDF_CONVERTER DVIPS_CONVERTER EXECUTABLE_OUTPUT_PATH + EXPAT_USE_STATIC_LIBS EnvModules_COMMAND ExternalData_BINARY_ROOT ExternalData_CUSTOM_ERROR @@ -3434,9 +3529,11 @@ + CMAKE_ENABLE_EXPORTS CMAKE_FILES_DIRECTORY CMAKE_HOME_DIRECTORY CMAKE_INTERNAL_PLATFORM_ABI + CMAKE_IOS_INSTALL_COMBINED CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_OBJDUMP CMAKE_SUPPRESS_DEVELOPER_ERRORS @@ -3463,6 +3560,7 @@ CMAKE_COLOR_DIAGNOSTICS CMAKE_CONFIGURATION_TYPES CMAKE_CONFIG_TYPE + CMAKE_CROSSCOMPILING_EMULATOR CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_FRAMEWORK_PATH CMAKE_GENERATOR @@ -3477,6 +3575,7 @@ CMAKE_TOOLCHAIN_FILE CSFLAGS CTEST_INTERACTIVE_DEBUG_MODE + CTEST_NO_TESTS_ACTION CTEST_OUTPUT_ON_FAILURE CTEST_PARALLEL_LEVEL CTEST_PROGRESS_OUTPUT @@ -3612,6 +3711,7 @@ AUTOGEN_BUILD_DIR AUTOGEN_ORIGIN_DEPENDS AUTOGEN_TARGET_DEPENDS + AUTOGEN_USE_SYSTEM_INCLUDE AUTOMOC AUTOMOC_COMPILER_PREDEFINES AUTOMOC_DEPEND_FILTERS @@ -3647,7 +3747,10 @@ COMPILE_WARNING_AS_ERROR CROSSCOMPILING_EMULATOR CUDA_ARCHITECTURES + CUDA_CUBIN_COMPILATION CUDA_EXTENSIONS + CUDA_FATBIN_COMPILATION + CUDA_OPTIX_COMPILATION CUDA_PTX_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS CUDA_RUNTIME_LIBRARY @@ -3655,6 +3758,10 @@ CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS + CXX_MODULE_DIRS + CXX_MODULE_SET + CXX_MODULE_SETS + CXX_SCAN_FOR_MODULES CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS @@ -3665,6 +3772,7 @@ DEPLOYMENT_REMOTE_DIRECTORY DEPRECATION DISABLE_PRECOMPILE_HEADERS + DLL_NAME_WITH_SOVERSION DOTNET_SDK DOTNET_TARGET_FRAMEWORK DOTNET_TARGET_FRAMEWORK_VERSION @@ -3715,10 +3823,12 @@ INSTALL_REMOVE_ENVIRONMENT_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH + INTERFACE_AUTOMOC_MACRO_NAMES INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS + INTERFACE_CXX_MODULE_SETS INTERFACE_HEADER_SETS INTERFACE_HEADER_SETS_TO_VERIFY INTERFACE_INCLUDE_DIRECTORIES @@ -3896,6 +4006,7 @@ COMPILE_DEFINITIONS COMPILE_FLAGS COMPILE_OPTIONS + CXX_SCAN_FOR_MODULES EXTERNAL_OBJECT Fortran_FORMAT Fortran_PREPROCESS @@ -3913,6 +4024,7 @@ SKIP_AUTOMOC SKIP_AUTORCC SKIP_AUTOUIC + SKIP_LINTING SKIP_PRECOMPILE_HEADERS SKIP_UNITY_BUILD_INCLUSION SYMBOLIC @@ -3952,18 +4064,22 @@ FIXTURES_CLEANUP FIXTURES_REQUIRED FIXTURES_SETUP + GENERATED_RESOURCE_SPEC_FILE LABELS MEASUREMENT PASS_REGULAR_EXPRESSION PROCESSORS PROCESSOR_AFFINITY REQUIRED_FILES + RESOURCE_GROUPS RESOURCE_LOCK RUN_SERIAL SKIP_REGULAR_EXPRESSION SKIP_RETURN_CODE TIMEOUT TIMEOUT_AFTER_MATCH + TIMEOUT_SIGNAL_GRACE_PERIOD + TIMEOUT_SIGNAL_NAME WILL_FAIL WORKING_DIRECTORY @@ -3985,6 +4101,7 @@ + IF 0 1 BOOL @@ -3993,53 +4110,69 @@ NOT STREQUAL EQUAL - IN_LIST VERSION_LESS VERSION_GREATER VERSION_EQUAL VERSION_LESS_EQUAL VERSION_GREATER_EQUAL - PATH_EQUAL - PATH - TARGET_EXISTS - CONFIG - PLATFORM_ID - C_COMPILER_ID - CXX_COMPILER_ID - CUDA_COMPILER_ID - Fortran_COMPILER_ID - C_COMPILER_VERSION - CXX_COMPILER_VERSION - CUDA_COMPILER_VERSION - Fortran_COMPILER_VERSION - TARGET_POLICY - COMPILE_FEATURES - COMPILE_LANG_AND_ID - COMPILE_LANGUAGE - LINK_LANG_AND_ID - LINK_LANGUAGE - DEVICE_LINK - HOST_LINK - LINK_LIBRARY - LINK_GROUP - ANGLE-R - COMMA - SEMICOLON - IF + LOWER_CASE + UPPER_CASE + MAKE_C_IDENTIFIER + IN_LIST JOIN REMOVE_DUPLICATES FILTER - LOWER_CASE - UPPER_CASE - GENEX_EVAL - TARGET_GENEX_EVAL + PATH_EQUAL + SHELL_PATH + CONFIG + OUTPUT_CONFIG + COMMAND_CONFIG + PLATFORM_ID + C_COMPILER_VERSION + CXX_COMPILER_VERSION + CUDA_COMPILER_VERSION + OBJC_COMPILER_VERSION + OBJCXX_COMPILER_VERSION + Fortran_COMPILER_VERSION + HIP_COMPILER_VERSION + ISPC_COMPILER_VERSION + C_COMPILER_ID + CXX_COMPILER_ID + CUDA_COMPILER_ID + OBJC_COMPILER_ID + OBJCXX_COMPILER_ID + Fortran_COMPILER_ID + HIP_COMPILER_ID + ISPC_COMPILER_ID + COMPILE_LANGUAGE + COMPILE_LANG_AND_ID + COMPILE_FEATURES + COMPILE_ONLY + LINK_LANGUAGE + LINK_LANG_AND_ID + LINK_LIBRARY + LINK_GROUP + LINK_ONLY + DEVICE_LINK + HOST_LINK + TARGET_EXISTS TARGET_NAME_IF_EXISTS + TARGET_NAME + TARGET_PROPERTY + TARGET_OBJECTS + TARGET_POLICY TARGET_FILE TARGET_FILE_BASE_NAME TARGET_FILE_PREFIX TARGET_FILE_SUFFIX TARGET_FILE_NAME TARGET_FILE_DIR + TARGET_IMPORT_FILE + TARGET_IMPORT_FILE_BASE_NAME + TARGET_IMPORT_FILE_PREFIX + TARGET_IMPORT_FILE_SUFFIX + TARGET_IMPORT_FILE_NAME + TARGET_IMPORT_FILE_DIR TARGET_LINKER_FILE TARGET_LINKER_FILE_BASE_NAME TARGET_LINKER_FILE_PREFIX @@ -4047,7 +4180,6 @@ TARGET_LINKER_FILE_NAME TARGET_LINKER_FILE_DIR TARGET_SONAME_FILE - TARGET_SONAME_FILE TARGET_SONAME_FILE_NAME TARGET_SONAME_FILE_DIR TARGET_PDB_FILE @@ -4057,18 +4189,67 @@ TARGET_BUNDLE_DIR_NAME TARGET_BUNDLE_DIR TARGET_BUNDLE_CONTENT_DIR - TARGET_PROPERTY TARGET_RUNTIME_DLLS - INSTALL_PREFIX - TARGET_NAME - LINK_ONLY + TARGET_RUNTIME_DLL_DIRS INSTALL_INTERFACE BUILD_INTERFACE - MAKE_C_IDENTIFIER - TARGET_OBJECTS - SHELL_PATH - OUTPUT_CONFIG - COMMAND_CONFIG + BUILD_LOCAL_INTERFACE + INSTALL_PREFIX + GENEX_EVAL + TARGET_GENEX_EVAL + ANGLE-R + COMMA + SEMICOLON + + + LENGTH + GET + SUBLIST + FIND + JOIN + APPEND + PREPEND + INSERT + POP_BACK + POP_FRONT + REMOVE_ITEM + REMOVE_AT + REMOVE_DUPLICATES + FILTER + TRANSFORM + FRANSFORM + REVERSE + SORT + + + HAS_ROOT_NAME + HAS_ROOT_DIRECTORY + HAS_ROOT_PATH + HAS_FILENAME + HAS_EXTENSION + HAS_STEM + HAS_RELATIVE_PART + HAS_PARENT_PATH + IS_ABSOLUTE + IS_RELATIVE + IS_PREFIX + GET_ROOT_NAME + GET_ROOT_DIRECTORY + GET_ROOT_PATH + GET_FILENAME + GET_EXTENSION + GET_STEM + GET_RELATIVE_PART + GET_PARENT_PATH + CMAKE_PATH + APPEND + REMOVE_FILENAME + REPLACE_FILENAME + REMOVE_EXTENSION + REPLACE_EXTENSION + NORMAL_PATH + RELATIVE_PATH + ABSOLUTE_PATH @@ -4126,7 +4307,6 @@ CTestCoverageCollectGCOV CTestScriptMode CTestUseLaunchers - Dart DeployQt4 ExternalData ExternalProject @@ -4171,7 +4351,6 @@ CVS CxxTest Cygwin - Dart DCMTK DevIL Doxygen @@ -4314,6 +4493,7 @@ CMakeExpandImportedTargets CMakeForceCompiler CMakeParseArguments + Dart Documentation MacroAddFileDependencies TestCXXAcceptsFlag @@ -4324,6 +4504,7 @@ WriteBasicConfigVersionFile WriteCompilerDetectionHeader FindCUDA + FindDart FindPythonInterp FindPythonLibs FindQt @@ -4432,6 +4613,7 @@ + @@ -4461,7 +4643,7 @@ - + @@ -4636,7 +4818,7 @@ - + @@ -5227,6 +5409,16 @@ + + + + + + + + + + @@ -5319,6 +5511,7 @@ + @@ -5380,7 +5573,7 @@ - + @@ -5447,7 +5640,7 @@ - + @@ -5530,6 +5723,24 @@ + + + + + + + + + + + + + + + + + + @@ -5562,6 +5773,7 @@ + @@ -6345,6 +6557,16 @@ + + + + + + + + + + @@ -6380,11 +6602,11 @@ - + - + @@ -6409,8 +6631,8 @@ - - + + @@ -6423,7 +6645,7 @@ - + @@ -6549,10 +6771,22 @@ + + + + + + + + + + + + @@ -6582,6 +6816,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/comments.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/comments.xml index cd66a4133d8..011dc8ab215 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/comments.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/comments.xml @@ -1,5 +1,5 @@ - + - - - + + + + + + + ]> - - - + + - + -webkit-line-clamp + -webkit-text-fill-color + -webkit-text-stroke + -webkit-text-stroke-color + -webkit-text-stroke-width accent-color + additive-symbols align-content align-items - alignment-baseline align-self all animation + animation-composition animation-delay animation-direction animation-duration @@ -60,8 +69,8 @@ Changelog: animation-play-state animation-timing-function appearance + ascent-override aspect-ratio - azimuth backdrop-filter backface-visibility background @@ -76,13 +85,8 @@ Changelog: background-position-y background-repeat background-size - baseline-shift - baseline-source - block-ellipsis + base-palette block-size - bookmark-label - bookmark-level - bookmark-state border border-block border-block-color @@ -102,7 +106,6 @@ Changelog: border-bottom-right-radius border-bottom-style border-bottom-width - border-boundary border-collapse border-color border-end-end-radius @@ -149,24 +152,15 @@ Changelog: box-decoration-break box-shadow box-sizing - box-snap break-after break-before break-inside caption-side - caret caret-color - caret-shape - chains clear - clip clip-path - clip-rule color - color-adjust - color-interpolation-filters color-scheme - columns column-count column-fill column-gap @@ -176,6 +170,7 @@ Changelog: column-rule-width column-span column-width + columns contain contain-intrinsic-block-size contain-intrinsic-height @@ -186,30 +181,15 @@ Changelog: container-name container-type content - content-visibility - continue counter-increment counter-reset counter-set - cue - cue-after - cue-before cursor + descent-override direction display - dominant-baseline - elevation empty-cells - fill - fill-break - fill-color - fill-image - fill-opacity - fill-origin - fill-position - fill-repeat - fill-rule - fill-size + fallback filter flex flex-basis @@ -219,12 +199,8 @@ Changelog: flex-shrink flex-wrap float - flood-color - flood-opacity - flow - flow-from - flow-into font + font-display font-family font-feature-settings font-kerning @@ -236,6 +212,7 @@ Changelog: font-stretch font-style font-synthesis + font-synthesis-position font-synthesis-small-caps font-synthesis-style font-synthesis-weight @@ -249,11 +226,8 @@ Changelog: font-variant-position font-variation-settings font-weight - footnote-display - footnote-policy forced-color-adjust gap - glyph-orientation-vertical grid grid-area grid-auto-columns @@ -273,18 +247,12 @@ Changelog: height hyphenate-character hyphenate-limit-chars - hyphenate-limit-last - hyphenate-limit-lines - hyphenate-limit-zone hyphens image-orientation image-rendering - image-resolution - initial-letter - initial-letter-align - initial-letter-wrap + inherits + initial-value inline-size - inline-sizing inset inset-block inset-block-end @@ -296,17 +264,11 @@ Changelog: justify-content justify-items justify-self - leading-trim left letter-spacing - lighting-color line-break - line-clamp - line-grid + line-gap-override line-height - line-height-step - line-padding - line-snap list-style list-style-image list-style-position @@ -322,11 +284,6 @@ Changelog: margin-left margin-right margin-top - margin-trim - marker-end - marker-mid - marker-side - marker-start mask mask-border mask-border-mode @@ -344,28 +301,24 @@ Changelog: mask-repeat mask-size mask-type + math-depth + math-style max-block-size max-height max-inline-size - max-lines max-width min-block-size min-height min-inline-size - min-intrinsic-sizing min-width mix-blend-mode - nav-up - nav-down - nav-left - nav-right + negative object-fit object-position offset offset-anchor offset-distance offset-path - offset-position offset-rotate opacity order @@ -383,11 +336,13 @@ Changelog: overflow-wrap overflow-x overflow-y + override-colors overscroll-behavior overscroll-behavior-block overscroll-behavior-inline overscroll-behavior-x overscroll-behavior-y + pad padding padding-block padding-block-end @@ -403,37 +358,24 @@ Changelog: page-break-after page-break-before page-break-inside + page-orientation paint-order - pause - pause-after - pause-before perspective perspective-origin - pitch - pitch-range place-content place-items place-self - play-during pointer-events position + prefix print-color-adjust quotes - region-fragment + range resize - rest - rest-after - rest-before - richness right rotate - rotation row-gap - ruby-align - ruby-merge - ruby-overhang ruby-position - running scale scroll-behavior scroll-margin @@ -465,58 +407,42 @@ Changelog: scrollbar-gutter scrollbar-width shape-image-threshold - shape-inside shape-margin shape-outside + size + size-adjust speak-as - spatial-navigation-action - spatial-navigation-contain - spatial-navigation-function - speak - speak-header - speak-numeral - speak-punctuation - speech-rate - stress - string-set + src + suffix + symbols + syntax + system tab-size table-layout - text-align-all text-align text-align-last text-combine-upright text-decoration text-decoration-color text-decoration-line - text-decoration-skip - text-decoration-skip-box text-decoration-skip-ink - text-decoration-skip-inset - text-decoration-skip-self - text-decoration-skip-spaces text-decoration-style text-decoration-thickness - text-edge text-emphasis text-emphasis-color text-emphasis-position - text-emphasis-skip text-emphasis-style - text-group-align text-indent text-justify text-orientation text-overflow text-rendering text-shadow - text-space-collapse - text-space-trim - text-spacing text-transform text-underline-offset text-underline-position - text-wrap top + touch-action transform transform-box transform-origin @@ -528,55 +454,50 @@ Changelog: transition-timing-function translate unicode-bidi + unicode-range user-select vertical-align visibility - voice-balance - voice-duration - voice-family - voice-pitch - voice-range - voice-rate - voice-stress - voice-volume - volume white-space widows width will-change - word-boundary-detection - word-boundary-expansion word-break word-spacing - word-wrap - wrap-after - wrap-before - wrap-flow - wrap-inside - wrap-through writing-mode z-index + + + alignment-baseline + baseline-shift + color-interpolation + color-interpolation-filters + dominant-baseline + fill + fill-opacity + fill-rule + flood-color + flood-opacity + marker-end + marker-mid + marker-start + shape-rendering + stop-color + stop-opacity + stroke + stroke-dasharray + stroke-dashoffset + stroke-linecap + stroke-linejoin + stroke-miterlimit + stroke-opacity + text-anchor + vector-effect + + + - -moz-animation - -moz-animation-delay - -moz-animation-direction - -moz-animation-duration - -moz-animation-fill-mode - -moz-animation-iteration-count - -moz-animation-name - -moz-animation-play-state - -moz-animation-timing-function - -moz-appearance - -moz-background-clip - -moz-background-origin - -moz-background-size - -moz-border-image - -moz-border-radius - -moz-border-radius-bottomleft - -moz-border-radius-bottomright - -moz-border-radius-topleft - -moz-border-radius-topright -moz-box-align -moz-box-direction -moz-box-flex @@ -584,80 +505,16 @@ Changelog: -moz-box-ordinal-group -moz-box-orient -moz-box-pack - -moz-box-shadow - -moz-box-sizing -moz-box - -moz-column-count - -moz-column-fill - -moz-column-gap - -moz-column-rule - -moz-column-rule-color - -moz-column-rule-style - -moz-column-rule-width - -moz-columns - -moz-column-width - -moz-hyphens - -moz-opacity - -moz-outline-style - -moz-perspective - -moz-resize - -moz-text-align-last - -moz-text-decoration-color - -moz-text-decoration-line - -moz-text-decoration-style - -moz-transform - -moz-transform-origin - -moz-transform-style - -moz-transition - -moz-transition-delay - -moz-transition-duration - -moz-transition-property - -moz-transition-timing-function - -moz-user-select - -o-background-size -o-linear-gradient - -o-text-overflow - -o-transition - -o-transform-origin konq_bgpos_x konq_bgpos_y - -khtml-background-size - -khtml-border-top-left-radius - -khtml-border-top-right-radius - -khtml-border-bottom-left-radius - -khtml-border-bottom-right-radius - -khtml-border-radius - -khtml-box-shadow - -khtml-opacity - -webkit-appearance - -webkit-animation - -webkit-animation-name - -webkit-animation-duration - -webkit-animation-iteration - -webkit-animation-direction - -webkit-animation-delay - -webkit-animation-play-state - -webkit-animation-fill-mode - -webkit-background-size - -webkit-backface-visibility - -webkit-border-image - -webkit-border-bottom-colors - -webkit-border-left-colors - -webkit-border-radius - -webkit-border-right-colors - -webkit-border-top-colors - -webkit-border-top-left-radius - -webkit-border-top-right-radius - -webkit-border-bottom-left-radius - -webkit-border-bottom-right-radius - -webkit-border-radius-bottomleft - -webkit-border-radius-bottomright -webkit-box-align -webkit-box-direction -webkit-box-flex @@ -665,46 +522,17 @@ Changelog: -webkit-box-orient -webkit-box-pack -webkit-box-reflect - -webkit-box-shadow - -webkit-box-sizing - -webkit-column-count - -webkit-column-gap - -webkit-hyphens -webkit-linear-gradient -webkit-gradient -webkit-overflow-scrolling - -webkit-perspective - -webkit-text-decoration -webkit-text-decoration-skip - -webkit-text-fill-color - -webkit-text-stroke-color - -webkit-text-stroke-width -webkit-text-size-adjust -webkit-tap-highlight-color - -webkit-transform - -webkit-transform-origin - -webkit-transform-style - -webkit-transition - -webkit-transition-property - -webkit-transition-delay - -webkit-transition-duration - -webkit-user-select - zoom - -ms-animation-name - -ms-animation-duration - -ms-animation-iteration - -ms-animation-direction - -ms-animation-delay - -ms-animation-play-state - -ms-animation-fill-mode - -ms-box-sizing -ms-filter -ms-flex -ms-flex-align - -ms-flex-direction - -ms-flex-flow -ms-flex-item-align -ms-flex-line-pack -ms-flex-negative @@ -713,278 +541,537 @@ Changelog: -ms-flex-positive -ms-flex-position -ms-flex-preferred-size - -ms-flex-wrap -ms-interpolation-mode -ms-linear-gradient - -ms-overflow-style -ms-text-size-adjust - -ms-transform - -ms-transition - -ms-user-select auto inherit + initial + revert + revert-layer unset - none - hidden - initial - revert - revert-layer - dotted - dashed - solid - double - groove - ridge - inset - outset - xx-small - x-small - small - medium - large - x-large - xx-large - smaller - larger - italic - oblique - small-caps - normal + -moz-arabic-indic + -moz-bengali + -moz-cjk-earthly-branch + -moz-cjk-heavenly-stem + -moz-devanagari + -moz-gujarati + -moz-gurmukhi + -moz-kannada + -moz-lao + -moz-malayalam + -moz-myanmar + -moz-oriya + -moz-persian + -moz-tamil + -moz-telugu + -moz-thai + absolute + accumulate + add + additive + alias + all + all-petite-caps + all-scroll + all-small-caps + allow-end + alpha + alphabetic + alternate + alternate-reverse + always + anywhere + arabic-indic + armenian + auto-add + auto-fill + auto-fit + avoid + avoid-column + avoid-page + avoid-region + backwards + balance + balance-all + baseline + bengali + bidi-override + bigger + block + block-end + block-start bold bolder - lighter - light - transparent - repeat - repeat-x - repeat-y - no-repeat - baseline - sub - super - top - text-top - middle + border + border-box + both + both-edges bottom - text-bottom - left - right + break-all + break-spaces + break-word + bullets + cambodian + cap-height + capitalize + cell center - justify - konq-center - disc + ch-width circle - square - box + cjk-decimal + cjk-earthly-branch + cjk-heavenly-stem + cjk-ideographic + clip + clone + close-quote + col-resize + collapse + color + color-burn + color-dodge + column + column-reverse + common-ligatures + compact + condensed + contain + content + content-box + contents + context-menu + contextual + copy + cover + crisp-edges + crosshair + currentcolor + cursive + cyclic + dark + darken + dashed decimal decimal-leading-zero - lower-roman - upper-roman - lower-greek - lower-alpha - lower-latin - upper-alpha - upper-latin - hebrew - armenian - georgian - cjk-ideographic - hiragana - katakana - hiragana-iroha - katakana-iroha - list-item - compact - marker - crosshair default - pointer - move + dense + devanagari + diagonal-fractions + difference + disc + disclosure-closed + disclosure-open + discretionary-ligatures + dot + dotted + double + double-circle e-resize - ne-resize - nw-resize - n-resize - se-resize - sw-resize - s-resize - w-resize - text - wait - help - above - absolute - always - avoid - avoid-page - avoid-column - avoid-region - below - bidi-override - blink - both - break-word - capitalize - caption - clip - close-quote - collapse - column - condensed - crop - cross + each-line + ease + ease-in + ease-in-out + ease-out + economy ellipsis - ellipsis-word embed + emoji + end + ethiopic-numeric + ew-resize + ex-height + exact + exclude + exclusion expanded + extends extra-condensed extra-expanded + fade + fallback + false + fangsong + fantasy + fill + fill-box + filled + first + fit-content fixed - hand + flat + flex + flex-end + flex-start + flow + flow-root + force-end + forwards + from-font + from-image + full-size-kana + full-width + georgian + grab + grabbing + grid + groove + gujarati + gurmukhi + hanging + hard-light + hebrew + help + hidden hide - higher - icon + high-quality + hiragana + hiragana-iroha + historical-forms + historical-ligatures + horizontal + horizontal-tb + hue + ic-height + ic-width + infinite + inline + inline-block + inline-end + inline-flex + inline-grid + inline-size + inline-start + inline-table + inset inside + inter-character + inter-word + intersect invert + isolate + isolate-override + italic + japanese-formal + japanese-informal + jump-both + jump-end + jump-none + jump-start + justify + justify-all + kannada + katakana + katakana-iroha + keep-all + keyword + khmer + korean-hangul-formal + korean-hanja-formal + korean-hanja-informal landscape - level + lao + large + larger + last + layout + left + legacy + light + lighten + lighter line-through - loud - lower + linear + lining-nums + local + loose + lower-alpha + lower-armenian + lower-greek + lower-latin + lower-roman lowercase ltr - menu - message-box - mix - narrower + luminance + luminosity + malayalam + mandatory + manipulation + manual + margin-box + match-parent + match-source + math + max-content + medium + min-content + mixed + mongolian + monospace + move + multiply + myanmar + n-resize + ne-resize + nesw-resize + no-clip no-close-quote + no-common-ligatures + no-contextual + no-discretionary-ligatures + no-drop + no-historical-ligatures no-open-quote + no-repeat + none + normal + not-allowed nowrap + ns-resize + numbers + numeric + nw-resize + nwse-resize + oblique + oldstyle-nums + only + open open-quote + optional + ordinal + oriya + outset outside + over + overlay overline + padding + padding-box + paint + painted + pan-down + pan-left + pan-right + pan-up + pan-x + pan-y + paused + persian + petite-caps + pinch-zoom + pixelated + plaintext + pointer portrait + position pre pre-line pre-wrap + preserve-3d + progress + proportional-nums + proportional-width + proximity + recto relative + repeat + repeat-x + repeat-y + replace + reverse + ridge + right + rotate-left + rotate-right + round + row + row-resize + row-reverse rtl + ruby + ruby-base + ruby-base-container + ruby-text + ruby-text-container + running + s-resize + safe + sans-serif + saturation + scale-down + screen scroll + scroll-position + se-resize + self-end + self-start semi-condensed semi-expanded separate + serif + sesame show - small-caption + sideways + sideways-lr + sideways-right + sideways-rl + simp-chinese-formal + simp-chinese-informal + size + slashed-zero + slice + small + small-caps + smaller + smooth + soft-light + solid + space + space-around + space-between + space-evenly + spell-out + square + stable + stacked-fractions + start static - static-position - status-bar + step-end + step-start sticky + stretch + strict + stroke + stroke-box + style + sub + subtract + super + sw-resize + swap + symbolic + system-ui + table + table-caption + table-cell + table-column + table-column-group + table-footer-group + table-header-group + table-row + table-row-group + tabular-nums + tamil + telugu + text + thai thick thin + tibetan + titling-caps + top + trad-chinese-formal + trad-chinese-informal + transparent + triangle + true + ui-monospace + ui-rounded + ui-sans-serif + ui-serif ultra-condensed ultra-expanded + under underline + unicase + unicode + unsafe + upper-alpha + upper-armenian + upper-latin + upper-roman uppercase + upright + use-glyph-orientation + verso + vertical + vertical-lr + vertical-rl + vertical-text + view-box visible - wider - break - serif - sans-serif - cursive - fantasy - monospace - border-box - content-box - -epub-hyphens - contain - cover + visibleFill + visiblePainted + visibleStroke + w-resize + wait + weight + words + wrap + wrap-reverse + x-large + x-small + xx-large + xx-small + xxx-large + zoom-in + zoom-out - - - block - inline - run-in + - flow - flow-root - table - flex - grid - ruby + after-edge + arcs + before-edge + bevel + bounding-box + butt + central + crispEdges + evenodd + fixed-position + freeze + geometricPrecision + ideographic + linearRGB + mathematical + middle + miter + miter-clip + non-rotation + non-scaling-size + non-scaling-stroke + nonzero + optimizeLegibility + optimizeQuality + optimizeSpeed + remove + sRGB + text-after-edge + text-before-edge + text-bottom + text-top - list-item - - table-row-group - table-header-group - table-footer-group - table-row - table-cell - table-column-group - table-column - table-caption - ruby-base - ruby-text - ruby-base-container - ruby-text-container - - contents - - inline-block - inline-table - inline-flex - inline-grid - - - all - ease - ease-in - ease-out - ease-in-out - step-start - step-end - linear - - - infinite - reverse - alternate - alternate-reverse - forwards - backwards - running - paused + + konq-center - black - silver - gray - white - maroon - red - purple - fuchsia - green - lime - olive - yellow - navy - blue - teal - aqua - orange aliceblue antiquewhite + aqua aquamarine azure beige bisque + black blanchedalmond + blue blueviolet brown burlywood @@ -996,7 +1083,6 @@ Changelog: cornsilk crimson cyan - aqua darkblue darkcyan darkgoldenrod @@ -1024,10 +1110,13 @@ Changelog: firebrick floralwhite forestgreen + fuchsia gainsboro ghostwhite gold goldenrod + gray + green greenyellow grey honeydew @@ -1055,10 +1144,11 @@ Changelog: lightslategrey lightsteelblue lightyellow + lime limegreen linen magenta - fuchsia + maroon mediumaquamarine mediumblue mediumorchid @@ -1073,8 +1163,11 @@ Changelog: mistyrose moccasin navajowhite + navy oldlace + olive olivedrab + orange orangered orchid palegoldenrod @@ -1087,7 +1180,9 @@ Changelog: pink plum powderblue + purple rebeccapurple + red rosybrown royalblue saddlebrown @@ -1096,6 +1191,7 @@ Changelog: seagreen seashell sienna + silver skyblue slateblue slategray @@ -1104,225 +1200,186 @@ Changelog: springgreen steelblue tan + teal thistle tomato turquoise violet wheat + white whitesmoke + yellow yellowgreen - rebeccapurple - - ActiveBorder - ActiveCaption - AppWorkspace - Background + + + AccentColor + AccentColorText + ActiveText + ButtonBorder ButtonFace - ButtonHighlight - ButtonShadow ButtonText - CaptionText + Canvas + CanvasText + Field + FieldText GrayText Highlight HighlightText - InactiveBorder - InactiveCaption - InactiveCaptionText - InfoBackground - InfoText - Menu - MenuText - Scrollbar - ThreeDDarkShadow - ThreeDFace - ThreeDHighlight - ThreeDLightShadow - ThreeDShadow - Window - WindowFrame - WindowText + LinkText + Mark + MarkText + VisitedText + - attr - cross-fade - env - fit-content - minmax - path - repeat - url - var - - - abs acos + annotation asin - atan2 atan - calc - clamp - cos - exp - hypot - log - max - min - mod - pow - rem - round - sign - sin - sqrt - tan - - - linear-gradient - radial-gradient - repeating-linear-gradient - repeating-radial-gradient - - - rgb - rgba - hsl - hsla - hwb - lab - lch - oklab - oklch - color - - - toggle - hwb - device-cmyk - color - element - image - image-set - conic-gradient - - - symbols - counter - counters - - - rect - - - inset - circle - ellipse - polygon - - + atan2 + attr blur brightness + calc + character-variant + circle + clamp + color + color-mix + conic-gradient contrast + cos + counter + counters + cross-fade + device-cmyk drop-shadow + ellipse + env + exp + fit-content + format grayscale + hsl hue-rotate + hwb + hypot + image + image-set + inset invert - opacity - saturate - sepia - - - max-content - min-content - repeat - - - cubic-bezier - frames - steps - - + lab + lch + linear-gradient + local + log matrix matrix3d + max + min + minmax + mod + oklab + oklch + opacity + ornaments + paint + path perspective + polygon + pow + radial-gradient + rem + repeat + repeating-conic-gradient + repeating-linear-gradient + repeating-radial-gradient + rgb rotate rotate3d rotateX rotateY rotateZ + round + saturate scale scale3d scaleX scaleY scaleZ + sepia + sign + sin skew skewX skewY + sqrt + styleset + stylistic + swash + symbols + tan + tech translate translate3d translateX translateY translateZ - - - local - format + url + var - - + all print screen speech + - - any-pointer + + -webkit-device-pixel-ratio + -webkit-transform-3d any-hover + any-pointer aspect-ratio color color-gamut color-index display-mode + dynamic-range + forced-colors grid height hover - max-aspect-ratio - max-color - max-color-index - max-device-aspect-ratio - max-device-height - max-device-width + inverted-colors max-height - max-monochrome - max-resolution max-width - min-aspect-ratio - min-color - min-color-index - min-device-aspect-ratio - min-device-height - min-device-width min-height - min-monochrome - min-resolution min-width monochrome orientation + overflow-block + overflow-inline pointer + prefers-color-scheme + prefers-contrast + prefers-reduced-motion resolution - scan + scripting update + video-dynamic-range width - + after backdrop before cue + cue-region file-selector-button first-letter first-line @@ -1332,16 +1389,7 @@ Changelog: selection slotted - - - - - - - value - choices - repeat-item - repeat-index + -moz-progress-bar -moz-range-progress @@ -1360,37 +1408,42 @@ Changelog: - - future - local-link - modal - picture-in-picture - + active any-link autofill + buffering checked + current default defined - + dir disabled empty enabled + first first-child first-of-type focus focus-visible focus-within fullscreen + has host + host-context hover in-range indeterminate invalid + is lang last-child last-of-type + left link + local-link + modal + muted not nth-child nth-last-child @@ -1400,36 +1453,28 @@ Changelog: only-of-type optional out-of-range + paused + picture-in-picture placeholder-shown + playing read-only read-write required + right root scope + seeking + stalled target + user-invalid + user-valid valid visited - - - after - before - cue - first-letter - first-line - selection - - - - has - host - host-context - is - matches - not + volume-locked where - + blank first left @@ -1439,412 +1484,548 @@ Changelog: - @character - @layer - @container @charset - @import - @namespace - - - + @container @font-feature-values - @document + @import + @keyframes + @layer @media + @namespace + @page @supports - + + @color-profile @counter-style - @viewport - @page @font-face - @keyframes - - - - min-width - max-width - width - min-height - max-height - height - zoom - min-zoom - max-zoom - user-zoom - orientation - viewport-fit - - - - size - marks - bleed - - - - font-display - font-family - font-stretch - font-style - font-weight - font-variant - font-feature-settings - font-variation-settings - src - unicode-range - - - - from - to + @font-palette-values + @property + or and only not - - - - - - + + + + + - - - - - - - - + + + + + + + + + + - - + + + + + - - - - - - - - + + + + + + + + - - + + - + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + + + + + + + - - - - - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + - - - + + + + + + - - - - + + + + + + + + - - - + + + + + + + - - - - + + + + + + + + + + + + + - - - - + + - - - - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + - - - + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - + + + + + + + + + + - - + + + + + - - - - - - + + + + + + + - - + + + + + + + - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + @@ -1852,36 +2033,49 @@ Changelog: + + + + + + + + + + - + + + + - + - + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml index 5516c1454b7..da87e4d9170 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml @@ -1,12 +1,12 @@ - ]> - + @@ -598,6 +598,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/dtd.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/dtd.xml index 8093b1c4e81..0526efc6250 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/dtd.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/dtd.xml @@ -1,5 +1,5 @@ - ]> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/gnuassembler.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/gnuassembler.xml index 35b9763277e..26a306c28af 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/gnuassembler.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/gnuassembler.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -79,8 +96,8 @@ - - + + @@ -136,49 +153,40 @@ - - - + + + - - + - - - - - - - - - - - - - + + + - - + + + + - + - + - - - + + + @@ -186,25 +194,35 @@ - + + + + + + + + - + - + - + + + - + + @@ -220,11 +238,11 @@ - + - + @@ -250,8 +268,8 @@ - - + + @@ -259,8 +277,8 @@ - - + + @@ -268,25 +286,25 @@ - - + + - + - + - - + + - + - + @@ -299,7 +317,9 @@ + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml index 849b90e7eee..56a35e80c7c 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml @@ -1,6 +1,6 @@ - - + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/java.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/java.xml index 478fb6ff3e7..aaeef26c3fb 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/java.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/java.xml @@ -1,5 +1,5 @@ - @@ -7,7 +7,7 @@ ]> - + ACTIVE @@ -3705,6 +3705,8 @@ + + abstract class @@ -3714,7 +3716,6 @@ false implements instanceof - @interface interface native new @@ -3730,6 +3731,11 @@ transient true volatile + + non-sealed + permits + record + sealed assert @@ -3748,6 +3754,7 @@ throw try while + yield boolean @@ -3764,6 +3771,25 @@ var void + + + + @Override + @Deprecated + @SuppressWarnings + @SafeVarargs + @FunctionalInterface + @interface + + @Retention + @Documented + @Target + @Inherited + @Repeatable + + + + @@ -3783,6 +3809,7 @@ + @@ -3795,6 +3822,7 @@ + @@ -3831,6 +3859,11 @@ + + + + + @@ -3898,6 +3931,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/javadoc.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/javadoc.xml index 336fedd53c1..84c7841cadf 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/javadoc.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/javadoc.xml @@ -1,6 +1,6 @@ - - + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/json.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/json.xml index 791a8081331..f302ff13692 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/json.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/json.xml @@ -1,5 +1,5 @@ - + - + null @@ -40,7 +40,12 @@ - + + + + + + @@ -57,13 +62,18 @@ - - + + - + + + + + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml index 30b226ada01..c3811c772fb 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml @@ -22,7 +22,7 @@ Example: **bold text and _italic and bold text_** __bold and ~~strikeout and bold~~__ --> - @@ -72,6 +72,10 @@ + + + + @@ -90,7 +94,7 @@ ]> - + @@ -137,9 +141,12 @@ + + + @@ -148,6 +155,16 @@ + + + + + + + + + + @@ -207,6 +224,7 @@ + @@ -226,6 +244,7 @@ + @@ -254,6 +273,8 @@ + + @@ -284,13 +305,14 @@ to check the indentation of the text and determine if the content of the list ends. --> - + + @@ -303,6 +325,12 @@ + + + + + + @@ -312,42 +340,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -450,13 +478,13 @@ - + - + @@ -494,7 +522,7 @@ - + @@ -505,6 +533,8 @@ + + @@ -523,6 +553,7 @@ + @@ -531,8 +562,7 @@ - - + @@ -606,6 +636,7 @@ + @@ -621,6 +652,7 @@ + @@ -629,11 +661,14 @@ + + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/modelines.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/modelines.xml index 43b49f3388c..855bca48029 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/modelines.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/modelines.xml @@ -1,5 +1,5 @@ - diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml index b3822fe7b72..ed843a7d461 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml @@ -1,5 +1,5 @@ - + Add-Content Add-ADComputerServiceAccount @@ -847,11 +790,23 @@ \% \? + + + $Global: + $Local: + $Private: + $Script: + $Using: + $Workflow: + $Alias: + $Env: + $Function: + $Variable: + $_ $True $False - $Env $Null $^ $$ @@ -873,75 +828,176 @@ $Host $OFS + + + + .SYNOPSIS + .DESCRIPTION + .PARAMETER + .EXAMPLE + .INPUTS + .OUTPUTS + .NOTES + .LINK + .COMPONENT + .ROLE + .FUNCTIONALITY + .FORWARDHELPTARGETNAME + .FORWARDHELPCATEGORY + .REMOTEHELPRUNSPACE + .EXTERNALHELP + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - + + + + - - + + - - + + + + + + + - - + + + + + + + + + + + + + + + - - + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/qdocconf.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/qdocconf.xml index b735ca9f4a9..dfd8008d988 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/qdocconf.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/qdocconf.xml @@ -1,5 +1,5 @@ - + - + + @@ -374,6 +375,7 @@ + @@ -387,6 +389,7 @@ + @@ -401,6 +404,7 @@ + @@ -459,6 +463,7 @@ + @@ -595,6 +600,7 @@ + @@ -789,6 +795,7 @@ + @@ -855,6 +862,7 @@ + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/spdx-comments.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/spdx-comments.xml index 7d893119279..2b89fc5ac79 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/spdx-comments.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/spdx-comments.xml @@ -1,5 +1,5 @@ - + + + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/valgrind-suppression.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/valgrind-suppression.xml index 46d8c646f7d..e795aca79f1 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/valgrind-suppression.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/valgrind-suppression.xml @@ -1,5 +1,5 @@ - + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/xml.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/xml.xml index 94a0f473244..da1910e26c3 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/xml.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/xml.xml @@ -1,12 +1,12 @@ - ]> - + diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml index 8b939115947..4129a09bd7e 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libs/3rdparty/syntax-highlighting/data/themes/default.theme b/src/libs/3rdparty/syntax-highlighting/data/themes/default.theme deleted file mode 100644 index e9c5c838d39..00000000000 --- a/src/libs/3rdparty/syntax-highlighting/data/themes/default.theme +++ /dev/null @@ -1,174 +0,0 @@ -{ - "metadata" : { - "revision" : 3, - "name" : "Default" - }, - "text-styles": { - "Normal" : { - "text-color" : "#1f1c1b", - "selected-text-color" : "#ffffff", - "bold" : false, - "italic" : false, - "underline" : false, - "strike-through" : false - }, - "Keyword" : { - "text-color" : "#1f1c1b", - "selected-text-color" : "#ffffff", - "bold" : true - }, - "Function" : { - "text-color" : "#644a9b", - "selected-text-color" : "#452886" - }, - "Variable" : { - "text-color" : "#0057ae", - "selected-text-color" : "#00316e" - }, - "ControlFlow" : { - "text-color" : "#1f1c1b", - "selected-text-color" : "#ffffff", - "bold" : true - }, - "Operator" : { - "text-color" : "#1f1c1b", - "selected-text-color" : "#ffffff" - }, - "BuiltIn" : { - "text-color" : "#644a9b", - "selected-text-color" : "#452886", - "bold" : true - }, - "Extension" : { - "text-color" : "#0095ff", - "selected-text-color" : "#ffffff", - "bold" : true - }, - "Preprocessor" : { - "text-color" : "#006e28", - "selected-text-color" : "#006e28" - }, - "Attribute" : { - "text-color" : "#0057ae", - "selected-text-color" : "#00316e" - }, - "Char" : { - "text-color" : "#924c9d", - "selected-text-color" : "#6c2477" - }, - "SpecialChar" : { - "text-color" : "#3daee9", - "selected-text-color" : "#fcfcfc" - }, - "String" : { - "text-color" : "#bf0303", - "selected-text-color" : "#9c0e0e" - }, - "VerbatimString" : { - "text-color" : "#bf0303", - "selected-text-color" : "#9c0e0e" - }, - "SpecialString" : { - "text-color" : "#ff5500", - "selected-text-color" : "#ff5500" - }, - "Import" : { - "text-color" : "#ff5500", - "selected-text-color" : "#ff5500" - }, - "DataType" : { - "text-color" : "#0057ae", - "selected-text-color" : "#00316e" - }, - "DecVal" : { - "text-color" : "#b08000", - "selected-text-color" : "#805c00" - }, - "BaseN" : { - "text-color" : "#b08000", - "selected-text-color" : "#805c00" - }, - "Float" : { - "text-color" : "#b08000", - "selected-text-color" : "#805c00" - }, - "Constant" : { - "text-color" : "#aa5500", - "selected-text-color" : "#5e2f00" - }, - "Comment" : { - "text-color" : "#898887", - "selected-text-color" : "#5e5d5d" - }, - "Documentation" : { - "text-color" : "#607880", - "selected-text-color" : "#46585e" - }, - "Annotation" : { - "text-color" : "#ca60ca", - "selected-text-color" : "#a44ea4" - }, - "CommentVar" : { - "text-color" : "#0095ff", - "selected-text-color" : "#ffffff" - }, - "RegionMarker" : { - "text-color" : "#0057ae", - "selected-text-color" : "#00316e", - "background-color" : "#e0e9f8" - }, - "Information" : { - "text-color" : "#b08000", - "selected-text-color" : "#805c00" - }, - "Warning" : { - "text-color" : "#bf0303", - "selected-text-color" : "#9c0e0e" - }, - "Alert" : { - "text-color" : "#bf0303", - "selected-text-color" : "#9c0e0e", - "background-color" : "#f7e6e6", - "bold" : true - }, - "Error" : { - "text-color" : "#bf0303", - "selected-text-color" : "#9c0e0e", - "underline" : true - }, - "Others" : { - "text-color" : "#006e28", - "selected-text-color" : "#006e28" - } - }, - "editor-colors": { - "background-color" : "#ffffff", - "code-folding" : "#94caef", - "bracket-matching" : "#ffff00", - "current-line" : "#f8f7f6", - "icon-border" : "#f0f0f0", - "indentation-line" : "#d2d2d2", - "line-numbers" : "#a0a0a0", - "current-line-number" : "#1e1e1e", - "mark-bookmark" : "#0000ff", - "mark-breakpoint-active" : "#ff0000", - "mark-breakpoint-reached" : "#ffff00", - "mark-breakpoint-disabled" : "#ff00ff", - "mark-execution" : "#a0a0a4", - "mark-warning" : "#00ff00", - "mark-error" : "#ff0000", - "modified-lines" : "#fdbc4b", - "replace-highlight" : "#00ff00", - "saved-lines" : "#2ecc71", - "search-highlight" : "#ffff00", - "selection" : "#94caef", - "separator" : "#898887", - "spell-checking" : "#bf0303", - "tab-marker" : "#d2d2d2", - "template-background" : "#d6d2d0", - "template-placeholder" : "#baf8ce", - "template-focused-placeholder" : "#76da98", - "template-read-only-placeholder" : "#f6e6e6", - "word-wrap-marker" : "#ededed" - } -} diff --git a/src/libs/3rdparty/syntax-highlighting/data/themes/theme-data.qrc b/src/libs/3rdparty/syntax-highlighting/data/themes/theme-data.qrc index cf9d658c824..8f4aa6c7e43 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/themes/theme-data.qrc +++ b/src/libs/3rdparty/syntax-highlighting/data/themes/theme-data.qrc @@ -1,26 +1,26 @@ - - - - atom-one-dark.theme - atom-one-light.theme - breeze-dark.theme - breeze-light.theme - ayu-dark.theme - ayu-light.theme - ayu-mirage.theme - dracula.theme - falcon.theme - github-dark.theme - github-light.theme - gruvbox-dark.theme - gruvbox-light.theme - monokai.theme - nord.theme - oblivion.theme - printing.theme - radical.theme - solarized-dark.theme - solarized-light.theme - vim-dark.theme - + + + atom-one-dark.theme + atom-one-light.theme + ayu-dark.theme + ayu-light.theme + ayu-mirage.theme + breeze-dark.theme + breeze-light.theme + dracula.theme + falcon.theme + github-dark.theme + github-light.theme + gruvbox-dark.theme + gruvbox-light.theme + homunculus.theme + monokai.theme + nord.theme + oblivion.theme + printing.theme + radical.theme + solarized-dark.theme + solarized-light.theme + vim-dark.theme + diff --git a/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt index 419b8ed5b7c..9d53a5bc3d5 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/CMakeLists.txt @@ -1,9 +1,9 @@ add_subdirectory(indexer) -if(TARGET Qt${QT_MAJOR_VERSION}::Gui) +if(TARGET Qt6::Gui) add_subdirectory(lib) add_subdirectory(cli) endif() -if(TARGET Qt${QT_MAJOR_VERSION}::Quick) +if(TARGET Qt6::Quick) add_subdirectory(quick) endif() diff --git a/src/libs/3rdparty/syntax-highlighting/src/Messages.sh b/src/libs/3rdparty/syntax-highlighting/src/Messages.sh index 6fb605ddf08..4024d9b74d4 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/Messages.sh +++ b/src/libs/3rdparty/syntax-highlighting/src/Messages.sh @@ -8,4 +8,4 @@ sed -i -e 's/^i18nc/QT_TRANSLATE_NOOP/' rc.cpp grep --no-filename '"name"' ../data/themes/*.theme | \ sed -r -e 's/"name"/QT_TRANSLATE_NOOP("Theme", /; s/://; s/,?$/);/' >> rc.cpp -$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/syntaxhighlighting5_qt.pot +$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/syntaxhighlighting6_qt.pot diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt index 1a4d24d8284..3aa3a8afc3f 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/cli/CMakeLists.txt @@ -1,5 +1,5 @@ -add_executable(kate-syntax-highlighter kate-syntax-highlighter.cpp) -ecm_mark_nongui_executable(kate-syntax-highlighter) -target_link_libraries(kate-syntax-highlighter KF5SyntaxHighlighting) +add_executable(ksyntaxhighlighter6 ksyntaxhighlighter.cpp) +ecm_mark_nongui_executable(ksyntaxhighlighter6) +target_link_libraries(ksyntaxhighlighter6 KF6SyntaxHighlighting) -install(TARGETS kate-syntax-highlighter ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) +install(TARGETS ksyntaxhighlighter6 ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp similarity index 77% rename from src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp rename to src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp index 5ce90e00530..681410cb706 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/cli/ksyntaxhighlighter.cpp @@ -26,7 +26,6 @@ static void applyHighlighter(Highlighter &highlighter, QCommandLineParser &parser, bool fromFileName, const QString &inFileName, - const QCommandLineOption &stdinOption, const QCommandLineOption &outputName, const Ts &...highlightParams) { @@ -38,30 +37,36 @@ static void applyHighlighter(Highlighter &highlighter, if (fromFileName) { highlighter.highlightFile(inFileName, highlightParams...); - } else if (parser.isSet(stdinOption)) { + } else { QFile inFile; inFile.open(stdin, QIODevice::ReadOnly); highlighter.highlightData(&inFile, highlightParams...); - } else { - parser.showHelp(1); } } +static Theme theme(const Repository &repo, const QString &themeName, Repository::DefaultTheme t) +{ + if (themeName.isEmpty()) { + return repo.defaultTheme(t); + } + return repo.theme(themeName); +} + int main(int argc, char **argv) { QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral("kate-syntax-highlighter")); + QCoreApplication::setApplicationName(QStringLiteral("ksyntaxhighlighter")); QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); QCoreApplication::setOrganizationName(QStringLiteral("KDE")); - QCoreApplication::setApplicationVersion(QStringLiteral(SyntaxHighlighting_VERSION_STRING)); - - Repository repo; + QCoreApplication::setApplicationVersion(QStringLiteral(KSYNTAXHIGHLIGHTING_VERSION_STRING)); QCommandLineParser parser; - parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using Kate syntax definitions.")); + parser.setApplicationDescription(app.translate("SyntaxHighlightingCLI", "Command line syntax highlighter using KSyntaxHighlighting syntax definitions.")); parser.addHelpOption(); parser.addVersionOption(); - parser.addPositionalArgument(app.translate("SyntaxHighlightingCLI", "source"), app.translate("SyntaxHighlightingCLI", "The source file to highlight.")); + parser.addPositionalArgument( + app.translate("SyntaxHighlightingCLI", "source"), + app.translate("SyntaxHighlightingCLI", "The source file to highlight. If absent, read the file from stdin and the --syntax option must be used.")); QCommandLineOption listDefs(QStringList() << QStringLiteral("l") << QStringLiteral("list"), app.translate("SyntaxHighlightingCLI", "List all available syntax definitions.")); @@ -85,8 +90,7 @@ int main(int argc, char **argv) QCommandLineOption themeName(QStringList() << QStringLiteral("t") << QStringLiteral("theme"), app.translate("SyntaxHighlightingCLI", "Color theme to use for highlighting."), - app.translate("SyntaxHighlightingCLI", "theme"), - repo.defaultTheme(Repository::LightTheme).name()); + app.translate("SyntaxHighlightingCLI", "theme")); parser.addOption(themeName); QCommandLineOption outputFormatOption( @@ -99,7 +103,7 @@ int main(int argc, char **argv) QCommandLineOption traceOption(QStringList() << QStringLiteral("syntax-trace"), app.translate("SyntaxHighlightingCLI", "Add information to debug a syntax file. Only works with --output-format=ansi or ansi256Colors. Possible " - "values are format, region, context and stackSize."), + "values are format, region, context, stackSize and all."), app.translate("SyntaxHighlightingCLI", "type")); parser.addOption(traceOption); @@ -107,18 +111,20 @@ int main(int argc, char **argv) app.translate("SyntaxHighlightingCLI", "Disable ANSI background for the default color.")); parser.addOption(noAnsiEditorBg); + QCommandLineOption unbufferedAnsi(QStringList() << QStringLiteral("U") << QStringLiteral("unbuffered"), + app.translate("SyntaxHighlightingCLI", "For ansi and ansi256Colors formats, flush the output buffer on each line.")); + parser.addOption(unbufferedAnsi); + QCommandLineOption titleOption( QStringList() << QStringLiteral("T") << QStringLiteral("title"), - app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"Kate Syntax Highlighter\" if reading from stdin)."), + app.translate("SyntaxHighlightingCLI", "Set HTML page's title\n(default: the filename or \"KSyntaxHighlighter\" if reading from stdin)."), app.translate("SyntaxHighlightingCLI", "title")); parser.addOption(titleOption); - QCommandLineOption stdinOption(QStringList() << QStringLiteral("stdin"), - app.translate("SyntaxHighlightingCLI", "Read file from stdin. The -s option must also be used.")); - parser.addOption(stdinOption); - parser.process(app); + Repository repo; + if (parser.isSet(listDefs)) { for (const auto &def : repo.definitions()) { std::cout << qPrintable(def.name()) << std::endl; @@ -177,7 +183,7 @@ int main(int argc, char **argv) return 1; } - QString outputFormat = parser.value(outputFormatOption); + const QString outputFormat = parser.value(outputFormatOption); if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) { QString title; if (parser.isSet(titleOption)) { @@ -186,8 +192,8 @@ int main(int argc, char **argv) HtmlHighlighter highlighter; highlighter.setDefinition(def); - highlighter.setTheme(repo.theme(parser.value(themeName))); - applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, title); + highlighter.setTheme(theme(repo, parser.value(themeName), Repository::LightTheme)); + applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, title); } else { auto AnsiFormat = AnsiHighlighter::AnsiFormat::TrueColor; if (0 == outputFormat.compare(QLatin1String("ansi256Colors"), Qt::CaseInsensitive)) { @@ -197,18 +203,22 @@ int main(int argc, char **argv) return 2; } - auto debugOptions = AnsiHighlighter::TraceOptions(); + AnsiHighlighter::Options options{}; + options |= parser.isSet(noAnsiEditorBg) ? AnsiHighlighter::Option::NoOptions : AnsiHighlighter::Option::UseEditorBackground; + options |= parser.isSet(unbufferedAnsi) ? AnsiHighlighter::Option::Unbuffered : AnsiHighlighter::Option::NoOptions; if (parser.isSet(traceOption)) { - const auto options = parser.values(traceOption); - for (auto const &option : options) { + const auto traceOptions = parser.values(traceOption); + for (auto const &option : traceOptions) { if (option == QStringLiteral("format")) { - debugOptions |= AnsiHighlighter::TraceOption::Format; + options |= AnsiHighlighter::Option::TraceFormat; } else if (option == QStringLiteral("region")) { - debugOptions |= AnsiHighlighter::TraceOption::Region; + options |= AnsiHighlighter::Option::TraceRegion; } else if (option == QStringLiteral("context")) { - debugOptions |= AnsiHighlighter::TraceOption::Context; + options |= AnsiHighlighter::Option::TraceContext; } else if (option == QStringLiteral("stackSize")) { - debugOptions |= AnsiHighlighter::TraceOption::StackSize; + options |= AnsiHighlighter::Option::TraceStackSize; + } else if (option == QStringLiteral("all")) { + options |= AnsiHighlighter::Option::TraceAll; } else { std::cerr << "Unknown trace name." << std::endl; return 2; @@ -218,8 +228,8 @@ int main(int argc, char **argv) AnsiHighlighter highlighter; highlighter.setDefinition(def); - highlighter.setTheme(repo.theme(parser.value(themeName))); - applyHighlighter(highlighter, parser, fromFileName, inFileName, stdinOption, outputName, AnsiFormat, !parser.isSet(noAnsiEditorBg), debugOptions); + highlighter.setTheme(theme(repo, parser.value(themeName), Repository::DarkTheme)); + applyHighlighter(highlighter, parser, fromFileName, inFileName, outputName, AnsiFormat, options); } return 0; diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt index 77a16faf22e..cf6940b7bd5 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/CMakeLists.txt @@ -4,13 +4,8 @@ if(CMAKE_CROSSCOMPILING AND KATEHIGHLIGHTINGINDEXER_EXECUTABLE) add_executable(katehighlightingindexer IMPORTED GLOBAL) set_target_properties(katehighlightingindexer PROPERTIES IMPORTED_LOCATION ${KATEHIGHLIGHTINGINDEXER_EXECUTABLE}) elseif(CMAKE_CROSSCOMPILING) - if (NOT KF5_HOST_TOOLING) - message(FATAL_ERROR "Please provide a prefix with a native Qt build and pass -DKF5_HOST_TOOLING=path") - endif() - - # search native tooling prefix - string(FIND ${KF5_HOST_TOOLING} /lib idx) - string(SUBSTRING ${KF5_HOST_TOOLING} 0 ${idx} NATIVE_PREFIX) + include(ECMQueryQt) + ecm_query_qt(NATIVE_PREFIX QT_HOST_PREFIX) message(STATUS "Building katehighlightingindexer against ${NATIVE_PREFIX}") include(ExternalProject) @@ -19,7 +14,7 @@ elseif(CMAKE_CROSSCOMPILING) CMAKE_ARGS -DKSYNTAXHIGHLIGHTING_USE_GUI=OFF -DECM_DIR=${ECM_DIR} -DCMAKE_PREFIX_PATH=${NATIVE_PREFIX} -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} - -DQT_MAJOR_VERSION=${QT_MAJOR_VERSION} + -DQT_MAJOR_VERSION=6 INSTALL_COMMAND "" BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/native_katehighlightingindexer-prefix/src/native_katehighlightingindexer-build/bin/katehighlightingindexer ) @@ -31,9 +26,11 @@ else() # host build add_executable(katehighlightingindexer katehighlightingindexer.cpp ../lib/worddelimiters.cpp) ecm_mark_nongui_executable(katehighlightingindexer) - if(Qt5XmlPatterns_FOUND AND NOT ECM_ENABLE_SANITIZERS) - target_link_libraries(katehighlightingindexer Qt5::XmlPatterns) + if(XercesC_FOUND) + add_definitions(-DHAS_XERCESC) + kde_target_enable_exceptions(katehighlightingindexer PRIVATE) + target_link_libraries(katehighlightingindexer Qt6::Core XercesC::XercesC) else() - target_link_libraries(katehighlightingindexer Qt${QT_MAJOR_VERSION}::Core) + target_link_libraries(katehighlightingindexer Qt6::Core) endif() endif() diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp index 9c541ef1b42..787747e21c0 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp @@ -12,12 +12,167 @@ #include #include #include +#include #include #include -#ifdef QT_XMLPATTERNS_LIB -#include -#include +#ifdef HAS_XERCESC + +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +using namespace xercesc; + +/* + * Ideas taken from: + * + * author : Boris Kolpackov + * copyright : not copyrighted - public domain + * + * This program uses Xerces-C++ SAX2 parser to load a set of schema files + * and then to validate a set of XML documents against these schemas. To + * build this program you will need Xerces-C++ 3.0.0 or later. For more + * information, see: + * + * http://www.codesynthesis.com/~boris/blog/2010/03/15/validating-external-schemas-xerces-cxx/ + */ + +/** + * Error handler object used during xml schema validation. + */ +class CustomErrorHandler : public ErrorHandler +{ +public: + /** + * Constructor + * @param messages Pointer to the error message string to fill. + */ + CustomErrorHandler(QString *messages) + : m_messages(messages) + { + } + + /** + * Check global success/fail state. + * @return True if there was a failure, false otherwise. + */ + bool failed() const + { + return m_failed; + } + +private: + /** + * Severity classes for error messages. + */ + enum severity { s_warning, s_error, s_fatal }; + + /** + * Wrapper for warning exceptions. + * @param e Exception to handle. + */ + void warning(const SAXParseException &e) override + { + m_failed = true; // be strict, warnings are evil, too! + handle(e, s_warning); + } + + /** + * Wrapper for error exceptions. + * @param e Exception to handle. + */ + void error(const SAXParseException &e) override + { + m_failed = true; + handle(e, s_error); + } + + /** + * Wrapper for fatal error exceptions. + * @param e Exception to handle. + */ + void fatalError(const SAXParseException &e) override + { + m_failed = true; + handle(e, s_fatal); + } + + /** + * Reset the error status to "no error". + */ + void resetErrors() override + { + m_failed = false; + } + + /** + * Generic handler for error/warning/fatal error message exceptions. + * @param e Exception to handle. + * @param s Enum value encoding the message severtity. + */ + void handle(const SAXParseException &e, severity s) + { + // get id to print + const XMLCh *xid(e.getPublicId()); + if (!xid) + xid = e.getSystemId(); + + m_messages << QString::fromUtf16(xid) << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << " " << (s == s_warning ? "warning: " : "error: ") + << QString::fromUtf16(e.getMessage()) << Qt::endl; + } + +private: + /** + * Storage for created error messages in this handler. + */ + QTextStream m_messages; + + /** + * Global error state. True if there was an error, false otherwise. + */ + bool m_failed = false; +}; + +void init_parser(SAX2XMLReaderImpl &parser) +{ + // Commonly useful configuration. + // + parser.setFeature(XMLUni::fgSAX2CoreNameSpaces, true); + parser.setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true); + parser.setFeature(XMLUni::fgSAX2CoreValidation, true); + + // Enable validation. + // + parser.setFeature(XMLUni::fgXercesSchema, true); + parser.setFeature(XMLUni::fgXercesSchemaFullChecking, true); + parser.setFeature(XMLUni::fgXercesValidationErrorAsFatal, true); + + // Use the loaded grammar during parsing. + // + parser.setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); + + // Don't load schemas from any other source (e.g., from XML document's + // xsi:schemaLocation attributes). + // + parser.setFeature(XMLUni::fgXercesLoadSchema, false); + + // Xerces-C++ 3.1.0 is the first version with working multi import + // support. + // + parser.setFeature(XMLUni::fgXercesHandleMultipleImports, true); +} + #endif #include "../lib/worddelimiters_p.h" @@ -152,12 +307,10 @@ public: success = false; } - QSet referencedKeywords; QSet usedAttributeNames; QSet ignoredAttributeNames; - success = checkKeywordsList(definition, referencedKeywords) && success; - success = - checkContexts(definition, referencedKeywords, usedAttributeNames, ignoredAttributeNames, usedContexts, unreachableIncludedRules) && success; + success = checkKeywordsList(definition) && success; + success = checkContexts(definition, usedAttributeNames, ignoredAttributeNames, usedContexts, unreachableIncludedRules) && success; // search for non-existing itemDatas. const auto invalidNames = usedAttributeNames - definition.itemDatas.styleNames; @@ -362,7 +515,7 @@ private: QString content; int line; - friend uint qHash(const Item &item, uint seed = 0) + friend size_t qHash(const Item &item, size_t seed = 0) { return qHash(item.content, seed); } @@ -373,7 +526,7 @@ private: } }; - QVector keywords; + QList keywords; QSet includes; bool parseElement(const QString &filename, QXmlStreamReader &xml) @@ -486,7 +639,7 @@ private: QString weakDeliminator; // rules included by IncludeRules (without IncludeRule) - QVector includedRules; + QList includedRules; // IncludeRules included by IncludeRules QSet includedIncludeRules; @@ -683,9 +836,10 @@ private: ContextName lineEndContext; ContextName lineEmptyContext; ContextName fallthroughContext; - QVector rules; + QList rules; XmlBool dynamic{}; XmlBool fallthrough{}; + XmlBool stopEmptyLineContextSwitchLoop{}; bool parseElement(const QString &filename, QXmlStreamReader &xml) { @@ -697,12 +851,17 @@ private: Parser parser{filename, xml, attr, success}; XmlBool noIndentationBasedFolding{}; - const bool isExtracted = parser.extractString(name, QStringLiteral("name")) || parser.extractString(attribute, QStringLiteral("attribute")) + // clang-format off + const bool isExtracted = parser.extractString(name, QStringLiteral("name")) + || parser.extractString(attribute, QStringLiteral("attribute")) || parser.extractString(lineEndContext.name, QStringLiteral("lineEndContext")) || parser.extractString(lineEmptyContext.name, QStringLiteral("lineEmptyContext")) || parser.extractString(fallthroughContext.name, QStringLiteral("fallthroughContext")) - || parser.extractXmlBool(dynamic, QStringLiteral("dynamic")) || parser.extractXmlBool(fallthrough, QStringLiteral("fallthrough")) + || parser.extractXmlBool(dynamic, QStringLiteral("dynamic")) + || parser.extractXmlBool(fallthrough, QStringLiteral("fallthrough")) + || parser.extractXmlBool(stopEmptyLineContextSwitchLoop, QStringLiteral("stopEmptyLineContextSwitchLoop")) || parser.extractXmlBool(noIndentationBasedFolding, QStringLiteral("noIndentationBasedFolding")); + // clang-format on success = parser.checkIfExtracted(isExtracted); } @@ -717,11 +876,6 @@ private: success = false; } - if (lineEndContext.name.isEmpty()) { - qWarning() << filename << "line" << xml.lineNumber() << "missing attribute: lineEndContext"; - success = false; - } - return success; } }; @@ -747,7 +901,7 @@ private: QString name; int line; - friend uint qHash(const Style &style, uint seed = 0) + friend size_t qHash(const Style &style, size_t seed = 0) { return qHash(style.name, seed); } @@ -802,7 +956,6 @@ private: const Context *firstContext = nullptr; QString filename; WordDelimiters wordDelimiters; - XmlBool casesensitive{}; Version kateVersion{}; QString kateVersionStr; QString languageName; @@ -865,7 +1018,7 @@ private: void resolveIncludeRules() { QSet usedContexts; - QVector contexts; + QList contexts; QMutableMapIterator def(m_definitions); while (def.hasNext()) { @@ -936,7 +1089,7 @@ private: QSet extractUsedContexts() const { QSet usedContexts; - QVector contexts; + QList contexts; QMapIterator def(m_definitions); while (def.hasNext()) { @@ -982,13 +1135,12 @@ private: }; struct IncludedRuleUnreachableBy { - QVector unreachableBy; + QList unreachableBy; bool alwaysUnreachable = true; }; //! Check contexts and rules bool checkContexts(const Definition &definition, - QSet &referencedKeywords, QSet &usedAttributeNames, QSet &ignoredAttributeNames, const QSet &usedContexts, @@ -1018,7 +1170,7 @@ private: usedAttributeNames.insert({context.attribute, context.line}); } - success = checkfallthrough(definition, context) && success; + success = checkContextAttribute(definition, context) && success; success = checkUreachableRules(definition.filename, context, unreachableIncludedRules) && success; success = suggestRuleMerger(definition.filename, context) && success; @@ -1032,7 +1184,7 @@ private: } success = checkLookAhead(rule) && success; success = checkStringDetect(rule) && success; - success = checkKeyword(definition, rule, referencedKeywords) && success; + success = checkKeyword(definition, rule) && success; success = checkRegExpr(filename, rule, context) && success; success = checkDelimiters(definition, rule) && success; } @@ -1047,12 +1199,13 @@ private: //! - dynamic=true but no place holder used? //! - is not . with lookAhead="1" //! - is not ^... without column ou firstNonSpace attribute - //! - is not equivalent to DetectSpaces, DetectChar, Detect2Chars, StringDetect, DetectIdentifier, RangeDetect + //! - is not equivalent to DetectSpaces, DetectChar, Detect2Chars, StringDetect, DetectIdentifier, RangeDetect, LineContinue or AnyChar //! - has no unused captures //! - has no unnecessary quantifier with lookAhead bool checkRegExpr(const QString &filename, const Context::Rule &rule, const Context &context) const { - if (rule.type == Context::Rule::Type::RegExpr) { + // ignore empty regex because the error is raised during xml parsing + if (rule.type == Context::Rule::Type::RegExpr && !rule.string.isEmpty()) { const QRegularExpression regexp(rule.string); if (!checkRegularExpression(rule.filename, regexp, rule.line)) { return false; @@ -1092,13 +1245,21 @@ private: // is RangeDetect static const QRegularExpression isRange(QStringLiteral("^\\^?" REG_CHAR "(?:" - "\\.\\*[?*]?" REG_CHAR "|" - "\\[\\^(" REG_ESCAPE_CHAR "|.)\\]\\*[?*]?\\1" + "\\.\\*[?+]?" REG_CHAR "|" + "\\[\\^(" REG_ESCAPE_CHAR "|.)\\]\\*[?+]?\\1" ")$")); if ((rule.lookAhead == XmlBool::True || rule.minimal == XmlBool::True || rule.string.contains(QStringLiteral(".*?")) || rule.string.contains(QStringLiteral("[^"))) && reg.contains(isRange)) { - qWarning() << filename << "line" << rule.line << "RegExpr should be replaced by RangeDetect:" << rule.string; + qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by RangeDetect:" << rule.string; + return false; + } + + // is AnyChar + static const QRegularExpression isAnyChar(QStringLiteral(R"(^(\^|\((\?:)?)*\[(?!\^)[-\]]?(\\[^0BDPSWbdpswoux]|[^-\]\\])*\]\)*$)")); + if (rule.string.contains(isAnyChar)) { + auto extra = (reg[0] == QLatin1Char('^') || reg[1] == QLatin1Char('^')) ? "with column=\"0\"" : ""; + qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by AnyChar:" << rule.string << extra; return false; } @@ -1106,7 +1267,7 @@ private: static const QRegularExpression isLineContinue(QStringLiteral("^\\^?" REG_CHAR "\\$$")); if (reg.contains(isLineContinue)) { auto extra = (reg[0] == QLatin1Char('^')) ? "with column=\"0\"" : ""; - qWarning() << filename << "line" << rule.line << "RegExpr should be replaced by LineContinue:" << rule.string << extra; + qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by LineContinue:" << rule.string << extra; return false; } @@ -1124,7 +1285,7 @@ private: if (rule.lookAhead == XmlBool::True && rule.minimal != XmlBool::True && reg.contains(isMinimal) && !reg.contains(hasNotGreedy) && (!rule.context.context || !rule.context.context->hasDynamicRule || regexp.captureCount() == 0) && (reg.back() != QLatin1Char('$') || reg.contains(QLatin1Char('|')))) { - qWarning() << filename << "line" << rule.line + qWarning() << rule.filename << "line" << rule.line << "RegExpr should be have minimal=\"1\" or use lazy operator (i.g, '.*' -> '.*?'):" << rule.string; return false; } @@ -1160,8 +1321,8 @@ private: return false; } - // column="0" or firstNonSpace="1" - if (rule.column == -1 && rule.firstNonSpace != XmlBool::True) { + // column="0" + if (rule.column == -1) { // ^ without | // (^sas*) -> ok // (^sa|s*) -> ko @@ -1204,7 +1365,7 @@ private: } if (replace) { - qWarning() << rule.filename << "line" << rule.line << "column=\"0\" or firstNonSpace=\"1\" missing with RegExpr:" << rule.string; + qWarning() << rule.filename << "line" << rule.line << "column=\"0\" missing with RegExpr:" << rule.string; return false; } } @@ -1306,11 +1467,8 @@ private: if (!useCapture) { // is DetectIdentifier - static const QRegularExpression isInsensitiveDetectIdentifier( - QStringLiteral(R"(^(\((\?:)?)?\[((a-z|_){2}|(A-Z|_){2})\]([+][*?]?)?\[((0-9|a-z|_){3}|(0-9|A-Z|_){3})\][*][*?]?(\))?$)")); - static const QRegularExpression isSensitiveDetectIdentifier( - QStringLiteral(R"(^(\((\?:)?)?\[(a-z|A-Z|_){3}\]([+][*?]?)?\[(0-9|a-z|A-Z|_){4}\][*][*?]?(\))?$)")); - auto &isDetectIdentifier = (rule.insensitive == XmlBool::True) ? isInsensitiveDetectIdentifier : isSensitiveDetectIdentifier; + static const QRegularExpression isDetectIdentifier( + QStringLiteral(R"(^(\((\?:)?|\^)*\[(\\p\{L\}|_){2}\]([+][?+]?)?\[(\\p\{N\}|\\p\{L\}|_){3}\][*][?+]?\)*$)")); if (rule.string.contains(isDetectIdentifier)) { qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by DetectIdentifier:" << rule.string; return false; @@ -1357,7 +1515,7 @@ private: static const QRegularExpression unnecessaryQuantifier2(QStringLiteral(R"([*+?]([.][*+?]{0,2})?[)]*$)")); auto &unnecessaryQuantifier = useCapture ? unnecessaryQuantifier1 : unnecessaryQuantifier2; if (rule.lookAhead == XmlBool::True && rule.minimal != XmlBool::True && reg.contains(unnecessaryQuantifier)) { - qWarning() << filename << "line" << rule.line + qWarning() << rule.filename << "line" << rule.line << "Last quantifier is not necessary (i.g., 'xyz*' -> 'xy', 'xyz+.' -> 'xyz.'):" << rule.string; return false; } @@ -1418,19 +1576,13 @@ private: return true; } - //! Search for rules with lookAhead="true" and context="#stay". - //! This would cause an infinite loop. - bool checkfallthrough(const Definition &definition, const Context &context) const + //! Check fallthrough and fallthroughContext. + //! Check kateversion for stopEmptyLineContextSwitchLoop. + bool checkContextAttribute(const Definition &definition, const Context &context) const { bool success = true; if (!context.fallthroughContext.name.isEmpty()) { - if (context.fallthroughContext.stay) { - qWarning() << definition.filename << "line" << context.line << "possible infinite loop due to fallthroughContext=\"#stay\" in context " - << context.name; - success = false; - } - const bool mandatoryFallthroughAttribute = definition.kateVersion < Version{5, 62}; if (context.fallthrough == XmlBool::True && !mandatoryFallthroughAttribute) { qWarning() << definition.filename << "line" << context.line << "fallthrough attribute is unnecessary with kateversion >= 5.62 in context" @@ -1444,6 +1596,12 @@ private: } } + if (context.stopEmptyLineContextSwitchLoop != XmlBool::Unspecified && definition.kateVersion < Version{5, 103}) { + qWarning() << definition.filename << "line" << context.line + << "stopEmptyLineContextSwitchLoop attribute is only valid with kateversion >= 5.103 in context" << context.name; + success = false; + } + return success; } @@ -1478,15 +1636,12 @@ private: return false; } - //! Search for rules with lookAhead="true" and context="#stay". - //! This would cause an infinite loop. - bool checkKeyword(const Definition &definition, const Context::Rule &rule, QSet &referencedKeywords) const + //! Check that keyword rule reference an existing keyword list. + bool checkKeyword(const Definition &definition, const Context::Rule &rule) const { if (rule.type == Context::Rule::Type::keyword) { auto it = definition.keywordsList.find(rule.string); - if (it != definition.keywordsList.end()) { - referencedKeywords.insert(&*it); - } else { + if (it == definition.keywordsList.end()) { qWarning() << rule.filename << "line" << rule.line << "reference of non-existing keyword list:" << rule.string; return false; } @@ -1504,13 +1659,7 @@ private: return true; } - //! Check that StringDetect contains more that 2 characters - //! Fix with following command: - //! \code - //! sed -E - //! '/StringDetect/{/dynamic="(1|true)|insensitive="(1|true)/!{s/StringDetect(.*)String="(.|<|>|"|&)(.|<|>|"|&)"/Detect2Chars\1char="\2" - //! char1="\3"/;t;s/StringDetect(.*)String="(.|<|>|"|&)"/DetectChar\1char="\2"/}}' -i file.xml... - //! \endcode + //! Check that StringDetect contains a placeHolder when dynamic="1" bool checkStringDetect(const Context::Rule &rule) const { if (rule.type == Context::Rule::Type::StringDetect) { @@ -1527,7 +1676,7 @@ private: } //! Check \ and delimiter in a keyword list - bool checkKeywordsList(const Definition &definition, QSet &referencedKeywords) const + bool checkKeywordsList(const Definition &definition) const { bool success = true; @@ -1542,7 +1691,7 @@ private: << " is only available since version \"5.53\". Please, increase kateversion."; success = false; } - success = checkKeywordInclude(definition, include, referencedKeywords) && success; + success = checkKeywordInclude(definition, include) && success; } // Check that keyword list items do not have deliminator character @@ -1562,16 +1711,13 @@ private: } //! Search for non-existing keyword include. - bool checkKeywordInclude(const Definition &definition, const Keywords::Items::Item &include, QSet &referencedKeywords) const + bool checkKeywordInclude(const Definition &definition, const Keywords::Items::Item &include) const { bool containsKeywordName = true; int const idx = include.content.indexOf(QStringLiteral("##")); if (idx == -1) { auto it = definition.keywordsList.find(include.content); containsKeywordName = (it != definition.keywordsList.end()); - if (containsKeywordName) { - referencedKeywords.insert(&*it); - } } else { auto defName = include.content.mid(idx + 2); auto listName = include.content.left(idx); @@ -1644,10 +1790,10 @@ private: } /// Search RuleAndInclude associated with the characters of @p s. - /// \return an empty QVector when at least one character is not found. - QVector find(QStringView s) const + /// \return an empty QList when at least one character is not found. + QList find(QStringView s) const { - QVector result; + QList result; for (QChar c : s) { if (!find(c)) { @@ -1731,8 +1877,8 @@ private: } /// Search RuleAndInclude associated with the characters of @p s. - /// \return an empty QVector when at least one character is not found. - QVector find(QStringView s) const + /// \return an empty QList when at least one character is not found. + QList find(QStringView s) const { for (int i = 0; i < m_size; ++i) { auto result = m_charTables[i]->find(s); @@ -1743,7 +1889,7 @@ private: return result; } } - return QVector(); + return QList(); } /// Associates @p c with a rule. @@ -1785,7 +1931,7 @@ private: // Iterates over all the rules, including those in includedRules struct RuleIterator { - RuleIterator(const QVector &rules, const ObservableRule &endRule) + RuleIterator(const QList &rules, const ObservableRule &endRule) : m_end(&endRule - rules.data()) , m_rules(rules) { @@ -1830,10 +1976,10 @@ private: private: int m_i = 0; - int m_i2; - int m_end; - const QVector &m_rules; - const QVector *m_includedRules = nullptr; + int m_i2 = 0; + const int m_end; + const QList &m_rules; + const QList *m_includedRules = nullptr; }; // Dot regex container that satisfies firstNonSpace and column. @@ -1915,7 +2061,7 @@ private: DotRegex dotRegex; - QVector observedRules; + QList observedRules; observedRules.reserve(context.rules.size()); for (const Context::Rule &rule : context.rules) { const Context::Rule *includeRule = nullptr; @@ -1937,7 +2083,7 @@ private: for (auto &observedRule : observedRules) { const Context::Rule &rule = *observedRule.rule; bool isUnreachable = false; - QVector unreachableBy; + QList unreachableBy; // declare rule as unreachable if ruleAndInclude is not empty auto updateUnreachable1 = [&](RuleAndInclude ruleAndInclude) { @@ -1948,7 +2094,7 @@ private: }; // declare rule as unreachable if ruleAndIncludes is not empty - auto updateUnreachable2 = [&](const QVector &ruleAndIncludes) { + auto updateUnreachable2 = [&](const QList &ruleAndIncludes) { if (!ruleAndIncludes.isEmpty()) { isUnreachable = true; unreachableBy.append(ruleAndIncludes); @@ -2030,6 +2176,8 @@ private: case Context::Rule::Type::Float: updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789."))); updateUnreachable1(floatRule.setRule(rule)); + // check that Float is before Int + updateUnreachable1(Rule4(intRule).setRule(rule)); break; // check if hidden by another DetectIdentifier rule @@ -2629,12 +2777,32 @@ int main(int argc, char *argv[]) return 1; } -#ifdef QT_XMLPATTERNS_LIB - // open schema - QXmlSchema schema; - if (!schema.load(QUrl::fromLocalFile(app.arguments().at(2)))) { +#ifdef HAS_XERCESC + // care for proper init and cleanup + XMLPlatformUtils::Initialize(); + auto cleanup = qScopeGuard(XMLPlatformUtils::Terminate); + + /* + * parse XSD first time and cache it + */ + XMLGrammarPoolImpl xsd(XMLPlatformUtils::fgMemoryManager); + + // create parser for the XSD + SAX2XMLReaderImpl parser(XMLPlatformUtils::fgMemoryManager, &xsd); + init_parser(parser); + QString messages; + CustomErrorHandler eh(&messages); + parser.setErrorHandler(&eh); + + // load grammar into the pool, on error just abort + const auto xsdFile = app.arguments().at(2); + if (!parser.loadGrammar((const char16_t *)xsdFile.utf16(), Grammar::SchemaGrammarType, true) || eh.failed()) { + qWarning("Failed to parse XSD %s: %s", qPrintable(xsdFile), qPrintable(messages)); return 2; } + + // lock the pool, no later modifications wanted! + xsd.lockPool(); #endif const QString hlFilenamesListing = app.arguments().value(3); @@ -2665,10 +2833,20 @@ int main(int argc, char *argv[]) continue; } -#ifdef QT_XMLPATTERNS_LIB - // validate against schema - QXmlSchemaValidator validator(schema); - if (!validator.validate(&hlFile, QUrl::fromLocalFile(hlFile.fileName()))) { +#ifdef HAS_XERCESC + // create parser + SAX2XMLReaderImpl parser(XMLPlatformUtils::fgMemoryManager, &xsd); + init_parser(parser); + QString messages; + CustomErrorHandler eh(&messages); + parser.setErrorHandler(&eh); + + // parse the XML file + parser.parse((const char16_t *)hlFile.fileName().utf16()); + + // report issues + if (eh.failed()) { + qWarning("Failed to validate XML %s: %s", qPrintable(hlFile.fileName()), qPrintable(messages)); anyError = 4; continue; } @@ -2708,6 +2886,10 @@ int main(int argc, char *argv[]) // add boolean one hl[QStringLiteral("hidden")] = attrToBool(xml.attributes().value(QLatin1String("hidden"))); + // keep some strings as UTF-8 for faster translations + hl[QStringLiteral("nameUtf8")] = hl[QStringLiteral("name")].toString().toUtf8(); + hl[QStringLiteral("sectionUtf8")] = hl[QStringLiteral("section")].toString().toUtf8(); + // remember hl hls[QFileInfo(hlFile).fileName()] = hl; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt index fe89fdd715e..2b2845eba4d 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt @@ -1,8 +1,14 @@ -add_library(KF5SyntaxHighlighting) +add_library(KF6SyntaxHighlighting) -ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting5_qt) +set_target_properties(KF6SyntaxHighlighting PROPERTIES + VERSION ${KSYNTAXHIGHLIGHTING_VERSION} + SOVERSION ${KSYNTAXHIGHLIGHTING_SOVERSION} + EXPORT_NAME SyntaxHighlighting +) -target_sources(KF5SyntaxHighlighting PRIVATE +ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting6_qt) + +target_sources(KF6SyntaxHighlighting PRIVATE abstracthighlighter.cpp context.cpp contextswitch.cpp @@ -25,7 +31,7 @@ target_sources(KF5SyntaxHighlighting PRIVATE ${syntax_highlighting_QM_LOADER} $ ) -ecm_qt_declare_logging_category(KF5SyntaxHighlighting +ecm_qt_declare_logging_category(KF6SyntaxHighlighting HEADER ksyntaxhighlighting_logging.h IDENTIFIER KSyntaxHighlighting::Log CATEGORY_NAME kf.syntaxhighlighting @@ -34,25 +40,21 @@ ecm_qt_declare_logging_category(KF5SyntaxHighlighting EXPORT KSYNTAXHIGHLIGHTING ) -ecm_generate_export_header(KF5SyntaxHighlighting +ecm_generate_export_header(KF6SyntaxHighlighting BASE_NAME KSyntaxHighlighting GROUP_BASE_NAME KF VERSION ${KF_VERSION} + USE_VERSION_HEADER DEPRECATED_BASE_VERSION 0 - DEPRECATION_VERSIONS 5.87 + DEPRECATION_VERSIONS EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) -set_target_properties(KF5SyntaxHighlighting PROPERTIES - VERSION ${SyntaxHighlighting_VERSION} - SOVERSION ${SyntaxHighlighting_SOVERSION} - EXPORT_NAME SyntaxHighlighting -) -target_link_libraries(KF5SyntaxHighlighting +target_link_libraries(KF6SyntaxHighlighting PUBLIC - Qt${QT_MAJOR_VERSION}::Gui + Qt6::Gui PRIVATE - Qt${QT_MAJOR_VERSION}::Network + Qt6::Network ) set(Forwarding_Header_Names @@ -74,12 +76,12 @@ ecm_generate_headers(CamelCase_HEADERS OUTPUT_DIR ${CMAKE_BINARY_DIR}/KSyntaxHighlighting/KSyntaxHighlighting ) -target_include_directories(KF5SyntaxHighlighting +target_include_directories(KF6SyntaxHighlighting INTERFACE "$" PUBLIC "$" ) -install(TARGETS KF5SyntaxHighlighting EXPORT KF5SyntaxHighlightingTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) +install(TARGETS KF6SyntaxHighlighting EXPORT KF6SyntaxHighlightingTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CamelCase_HEADERS} @@ -90,17 +92,17 @@ install(FILES if(BUILD_QCH) ecm_add_qch( - KF5SyntaxHighlighting_QCH + KF6SyntaxHighlighting_QCH NAME KSyntaxHighlighting - BASE_NAME KF5SyntaxHighlighting + BASE_NAME KF6SyntaxHighlighting VERSION ${KF_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${SyntaxHighlighting_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS - Qt5Core_QCH - Qt5Gui_QCH + Qt6Core_QCH + Qt6Gui_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS @@ -111,11 +113,3 @@ if(BUILD_QCH) COMPONENT Devel ) endif() -ecm_generate_pri_file( - BASE_NAME KSyntaxHighlighting LIB_NAME - KF5SyntaxHighlighting - DEPS "gui" - FILENAME_VAR PRI_FILENAME - INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF}/KSyntaxHighlighting -) -install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp index ac5d98abfb3..87dabadc7b1 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp @@ -12,6 +12,7 @@ #include "format.h" #include "ksyntaxhighlighting_logging.h" #include "repository.h" +#include "repository_p.h" #include "rule_p.h" #include "state.h" #include "state_p.h" @@ -97,13 +98,6 @@ static inline int firstNonSpaceChar(QStringView text) return text.size(); } -#if KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(5, 87) -State AbstractHighlighter::highlightLine(const QString &text, const State &state) -{ - return highlightLine(QStringView(text), state); -} -#endif - State AbstractHighlighter::highlightLine(QStringView text, const State &state) { Q_D(AbstractHighlighter); @@ -116,43 +110,47 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) return State(); } + // limit the cache for unification to some reasonable size + // we use here at the moment 64k elements to not hog too much memory + // and to make the clearing no big stall + if (defData->unify.size() > 64 * 1024) + defData->unify.clear(); + // verify/initialize state auto newState = state; auto stateData = StateData::get(newState); - const auto definitionId = DefinitionData::get(d->m_definition)->id; - if (!stateData->isEmpty() && stateData->m_defId != definitionId) { + bool isSharedData = true; + if (Q_UNLIKELY(stateData && stateData->m_defId != defData->id)) { qCDebug(Log) << "Got invalid state, resetting."; - stateData->clear(); + stateData = nullptr; } - if (stateData->isEmpty()) { + if (Q_UNLIKELY(!stateData)) { + stateData = StateData::reset(newState); stateData->push(defData->initialContext(), QStringList()); - stateData->m_defId = definitionId; + stateData->m_defId = defData->id; + isSharedData = false; } // process empty lines - if (text.isEmpty()) { + if (Q_UNLIKELY(text.isEmpty())) { /** * handle line empty context switches * guard against endless loops * see https://phabricator.kde.org/D18509 */ int endlessLoopingCounter = 0; - while (!stateData->topContext()->lineEmptyContext().isStay() || !stateData->topContext()->lineEndContext().isStay()) { + while (!stateData->topContext()->lineEmptyContext().isStay()) { /** * line empty context switches */ - if (!stateData->topContext()->lineEmptyContext().isStay()) { - if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) { - /** - * end when trying to #pop the main context - */ - break; - } + if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList(), newState, isSharedData)) { /** - * line end context switches only when lineEmptyContext is #stay. This avoids - * skipping empty lines after a line continuation character (see bug 405903) + * end when trying to #pop the main context */ - } else if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) { + break; + } + + if (stateData->topContext()->stopEmptyLineContextSwitchLoop()) { break; } @@ -165,9 +163,11 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) } auto context = stateData->topContext(); applyFormat(0, 0, context->attributeFormat()); - return newState; + return *defData->unify.insert(newState); } + auto &dynamicRegexpCache = RepositoryPrivate::get(defData->repo)->m_dynamicRegexpCache; + int offset = 0; int beginOffset = 0; bool lineContinuation = false; @@ -178,10 +178,10 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) * - store the result of the first position that matches (or -1 for no match in the full line) in the skipOffsets hash for re-use * - have capturesForLastDynamicSkipOffset as guard for dynamic regexes to invalidate the cache if they might have changed */ - QVarLengthArray, 8> skipOffsets; + QVarLengthArray, 8> skipOffsets; QStringList capturesForLastDynamicSkipOffset; - auto getSkipOffsetValue = [&skipOffsets](Rule *r) -> int { + auto getSkipOffsetValue = [&skipOffsets](const Rule *r) -> int { auto i = std::find_if(skipOffsets.begin(), skipOffsets.end(), [r](const auto &v) { return v.first == r; }); @@ -190,7 +190,7 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) return i->second; }; - auto insertSkipOffset = [&skipOffsets](Rule *r, int i) { + auto insertSkipOffset = [&skipOffsets](const Rule *r, int i) { auto it = std::find_if(skipOffsets.begin(), skipOffsets.end(), [r](const auto &v) { return v.first == r; }); @@ -237,7 +237,8 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) bool isLookAhead = false; int newOffset = 0; const Format *newFormat = nullptr; - for (const auto &rule : stateData->topContext()->rules()) { + for (const auto &ruleShared : stateData->topContext()->rules()) { + auto rule = ruleShared.get(); /** * filter out rules that require a specific column */ @@ -265,29 +266,33 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) } } - /** - * shall we skip application of this rule? two cases: - * - rule can't match at all => currentSkipOffset < 0 - * - rule will only match for some higher offset => currentSkipOffset > offset - * - * we need to invalidate this if we are dynamic and have different captures then last time - */ - if (rule->isDynamic() && (capturesForLastDynamicSkipOffset != stateData->topCaptures())) { - skipOffsets.clear(); - } - const auto currentSkipOffset = getSkipOffsetValue(rule.get()); - if (currentSkipOffset < 0 || currentSkipOffset > offset) { - continue; + int currentSkipOffset = 0; + if (Q_UNLIKELY(rule->hasSkipOffset())) { + /** + * shall we skip application of this rule? two cases: + * - rule can't match at all => currentSkipOffset < 0 + * - rule will only match for some higher offset => currentSkipOffset > offset + * + * we need to invalidate this if we are dynamic and have different captures then last time + */ + if (rule->isDynamic() && (capturesForLastDynamicSkipOffset != stateData->topCaptures())) { + skipOffsets.clear(); + } else { + currentSkipOffset = getSkipOffsetValue(rule); + if (currentSkipOffset < 0 || currentSkipOffset > offset) { + continue; + } + } } - const auto newResult = rule->doMatch(text, offset, stateData->topCaptures()); + auto newResult = rule->doMatch(text, offset, stateData->topCaptures(), dynamicRegexpCache); newOffset = newResult.offset(); /** * update skip offset if new one rules out any later match or is larger than current one */ if (newResult.skipOffset() < 0 || newResult.skipOffset() > currentSkipOffset) { - insertSkipOffset(rule.get(), newResult.skipOffset()); + insertSkipOffset(rule, newResult.skipOffset()); // remember new captures, if dynamic to enforce proper reset above on change! if (rule->isDynamic()) { @@ -316,12 +321,12 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) if (rule->isLookAhead()) { Q_ASSERT(!rule->context().isStay()); - d->switchContext(stateData, rule->context(), newResult.captures()); + d->switchContext(stateData, rule->context(), std::move(newResult.captures()), newState, isSharedData); isLookAhead = true; break; } - d->switchContext(stateData, rule->context(), newResult.captures()); + d->switchContext(stateData, rule->context(), std::move(newResult.captures()), newState, isSharedData); newFormat = rule->attributeFormat().isValid() ? &rule->attributeFormat() : &stateData->topContext()->attributeFormat(); if (newOffset == text.size() && rule->isLineContinue()) { lineContinuation = true; @@ -334,7 +339,7 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) if (newOffset <= offset) { // no matching rule if (stateData->topContext()->fallthrough()) { - d->switchContext(stateData, stateData->topContext()->fallthroughContext(), QStringList()); + d->switchContext(stateData, stateData->topContext()->fallthroughContext(), QStringList(), newState, isSharedData); continue; } @@ -381,7 +386,7 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) { int endlessLoopingCounter = 0; while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) { - if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) { + if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList(), newState, isSharedData)) { break; } @@ -394,18 +399,30 @@ State AbstractHighlighter::highlightLine(QStringView text, const State &state) } } - return newState; + return *defData->unify.insert(newState); } -bool AbstractHighlighterPrivate::switchContext(StateData *data, const ContextSwitch &contextSwitch, const QStringList &captures) +bool AbstractHighlighterPrivate::switchContext(StateData *&data, const ContextSwitch &contextSwitch, QStringList &&captures, State &state, bool &isSharedData) { + const auto popCount = contextSwitch.popCount(); + const auto context = contextSwitch.context(); + if (popCount <= 0 && !context) { + return true; + } + + // a modified state must be detached before modification + if (isSharedData) { + data = StateData::detach(state); + isSharedData = false; + } + // kill as many items as requested from the stack, will always keep the initial context alive! - const bool initialContextSurvived = data->pop(contextSwitch.popCount()); + const bool initialContextSurvived = data->pop(popCount); // if we have a new context to add, push it // then we always "succeed" - if (contextSwitch.context()) { - data->push(contextSwitch.context(), captures); + if (context) { + data->push(context, std::move(captures)); return true; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h index 49cfbf25303..676a0f522ab 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.h @@ -7,20 +7,15 @@ #ifndef KSYNTAXHIGHLIGHTING_ABSTRACTHIGHLIGHTERM_H #define KSYNTAXHIGHLIGHTING_ABSTRACTHIGHLIGHTERM_H +#include "definition.h" #include "ksyntaxhighlighting_export.h" #include - -#include - -QT_BEGIN_NAMESPACE -class QString; -QT_END_NAMESPACE +#include namespace KSyntaxHighlighting { class AbstractHighlighterPrivate; -class Definition; class FoldingRegion; class Format; class State; @@ -106,21 +101,8 @@ public: protected: AbstractHighlighter(); - AbstractHighlighter(AbstractHighlighterPrivate *dd); + KSYNTAXHIGHLIGHTING_NO_EXPORT explicit AbstractHighlighter(AbstractHighlighterPrivate *dd); -#if KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(5, 87) - /** - * @copydoc highlightLine(QStringView,const State&) - * @deprecated since 5.87, use highlightLine(QStringView, const State&) instead. - */ - // no deprecation warning, as removal of this will automatically "port" the using code - State highlightLine(const QString &text, const State &state); -#endif - - // TODO KF6: add an optional void* context argument that is passed through - // to the applyX() calls, so highlighters dealing with some form of line object - // (such as QSyntaxHighlighter or KTextEditor) can avoid some ugly hacks to have - // this context available in their applyX methods /** * Highlight the given line. Call this from your derived class * where appropriate. This will result in any number of applyFormat() diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h index 6128beccfa0..04ac9898f8c 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter_p.h @@ -14,6 +14,7 @@ namespace KSyntaxHighlighting { class ContextSwitch; class StateData; +class State; class AbstractHighlighterPrivate { @@ -22,7 +23,7 @@ public: virtual ~AbstractHighlighterPrivate(); void ensureDefinitionLoaded(); - bool switchContext(StateData *data, const ContextSwitch &contextSwitch, const QStringList &captures); + bool switchContext(StateData *&data, const ContextSwitch &contextSwitch, QStringList &&captures, State &state, bool &isSharedData); Definition m_definition; Theme m_theme; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp index 31678018f9f..e9bea02d1c7 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.cpp @@ -5,6 +5,7 @@ */ #include "ansihighlighter.h" +#include "abstracthighlighter_p.h" #include "context_p.h" #include "definition.h" #include "definition_p.h" @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -783,7 +785,7 @@ GraphLine &lineAtOffset(std::vector &graphLines, int offset) } // disable bold, italic and underline on | -const QLatin1String graphSymbol("\x1b[21;23;24m|"); +const QLatin1String graphSymbol("\x1b[22;23;24m|"); // reverse video const QLatin1String nameStyle("\x1b[7m"); @@ -793,8 +795,8 @@ const QLatin1String nameStyle("\x1b[7m"); class DebugSyntaxHighlighter : public KSyntaxHighlighting::AbstractHighlighter { public: - using TraceOption = KSyntaxHighlighting::AnsiHighlighter::TraceOption; - using TraceOptions = KSyntaxHighlighting::AnsiHighlighter::TraceOptions; + using Option = KSyntaxHighlighting::AnsiHighlighter::Option; + using Options = KSyntaxHighlighting::AnsiHighlighter::Options; void setDefinition(const KSyntaxHighlighting::Definition &def) override { @@ -815,14 +817,14 @@ public: QLatin1String infoStyle, QLatin1String editorBackground, const std::vector> &ansiStyles, - TraceOptions traceOptions) + Options options) { initRegionStyles(ansiStyles); - m_hasFormatTrace = traceOptions.testFlag(TraceOption::Format); - m_hasRegionTrace = traceOptions.testFlag(TraceOption::Region); - m_hasStackSizeTrace = traceOptions.testFlag(TraceOption::StackSize); - m_hasContextTrace = traceOptions.testFlag(TraceOption::Context); + m_hasFormatTrace = options.testFlag(Option::TraceFormat); + m_hasRegionTrace = options.testFlag(Option::TraceRegion); + m_hasStackSizeTrace = options.testFlag(Option::TraceStackSize); + m_hasContextTrace = options.testFlag(Option::TraceContext); const bool hasFormatOrContextTrace = m_hasFormatTrace || m_hasContextTrace || m_hasStackSizeTrace; const bool hasSeparator = hasFormatOrContextTrace && m_hasRegionTrace; @@ -831,6 +833,7 @@ public: bool firstLine = true; State state; QString currentLine; + const bool isUnbuffered = options.testFlag(Option::Unbuffered); while (in.readLineInto(¤tLine)) { auto oldState = state; state = highlightLine(currentLine, state); @@ -864,6 +867,10 @@ public: } m_highlightedFragments.clear(); + + if (isUnbuffered) { + out.flush(); + } } } @@ -970,12 +977,14 @@ private: QString label; if (m_hasStackSizeTrace) { - label += QLatin1Char('(') % QString::number(stateData->size()) % QLatin1Char(')'); + // first state is empty + int stateSize = stateData ? stateData->size() : 0; + label = QLatin1Char('(') % QString::number(stateSize) % QLatin1Char(')'); } if (m_hasContextTrace) { // first state is empty - if (stateData->isEmpty()) { + if (!stateData) { return label + QStringLiteral("[???]"); } @@ -1138,7 +1147,7 @@ private: QString name; int offset; int length; - quint16 formatId; + int formatId; }; struct ContextCaptureHighlighter : KSyntaxHighlighting::AbstractHighlighter { @@ -1168,7 +1177,7 @@ private: int depth; int offset; int bindIndex; - quint16 regionId; + int regionId; State state; }; @@ -1190,7 +1199,7 @@ private: }; } // anonymous namespace -class KSyntaxHighlighting::AnsiHighlighterPrivate +class KSyntaxHighlighting::AnsiHighlighterPrivate : public AbstractHighlighterPrivate { public: QTextStream out; @@ -1201,7 +1210,7 @@ public: }; AnsiHighlighter::AnsiHighlighter() - : d(new AnsiHighlighterPrivate()) + : AbstractHighlighter(new AnsiHighlighterPrivate()) { } @@ -1209,6 +1218,7 @@ AnsiHighlighter::~AnsiHighlighter() = default; void AnsiHighlighter::setOutputFile(const QString &fileName) { + Q_D(AnsiHighlighter); if (d->file.isOpen()) { d->file.close(); } @@ -1218,21 +1228,16 @@ void AnsiHighlighter::setOutputFile(const QString &fileName) return; } d->out.setDevice(&d->file); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - d->out.setCodec("UTF-8"); -#endif } void AnsiHighlighter::setOutputFile(FILE *fileHandle) { + Q_D(AnsiHighlighter); d->file.open(fileHandle, QIODevice::WriteOnly); d->out.setDevice(&d->file); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - d->out.setCodec("UTF-8"); -#endif } -void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format, bool useEditorBackground, TraceOptions traceOptions) +void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format, Options options) { QFileInfo fi(fileName); QFile f(fileName); @@ -1241,19 +1246,21 @@ void AnsiHighlighter::highlightFile(const QString &fileName, AnsiFormat format, return; } - highlightData(&f, format, useEditorBackground, traceOptions); + highlightData(&f, format, options); } -void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useEditorBackground, TraceOptions traceOptions) +void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, Options options) { + Q_D(AnsiHighlighter); + if (!d->out.device()) { qCWarning(Log) << "No output stream defined!"; return; } const auto is256Colors = (format == AnsiFormat::XTerm256Color); - const auto theme = this->theme(); - const auto definition = this->definition(); + const auto &theme = d->m_theme; + const auto &definition = d->m_definition; auto definitions = definition.includedDefinitions(); definitions.append(definition); @@ -1265,6 +1272,8 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE QLatin1String foregroundDefaultColor; QLatin1String backgroundDefaultColor; + const bool useEditorBackground = options.testFlag(Option::UseEditorBackground); + // https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters if (useEditorBackground) { @@ -1277,23 +1286,19 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE backgroundDefaultColor = backgroundColorBuffer.latin1().mid(2); } - // ansiStyles must not be empty for applyFormat to work even with a definition without any context - if (d->ansiStyles.empty()) { - d->ansiStyles.resize(32); - } else { - d->ansiStyles[0].first.clear(); - d->ansiStyles[0].second.clear(); + int maxId = 0; + for (const auto &definition : std::as_const(definitions)) { + for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) { + maxId = qMax(maxId, format.id()); + } } + d->ansiStyles.clear(); + // ansiStyles must not be empty for applyFormat to work even with a definition without any context + d->ansiStyles.resize(maxId + 1); // initialize ansiStyles - for (auto &&definition : std::as_const(definitions)) { - for (auto &&format : std::as_const(DefinitionData::get(definition)->formats)) { - const auto id = format.id(); - if (id >= d->ansiStyles.size()) { - // better than id + 1 to avoid successive allocations - d->ansiStyles.resize(id * 2); - } - + for (const auto &definition : std::as_const(definitions)) { + for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) { AnsiBuffer buffer; buffer.append(QLatin1String("\x1b[")); @@ -1329,7 +1334,8 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE // if there is ANSI style if (buffer.latin1().size() > 2) { buffer.setFinalStyle(); - d->ansiStyles[id].first = buffer.latin1(); + auto &style = d->ansiStyles[format.id()]; + style.first = buffer.latin1(); if (useEditorBackground) { buffer.clear(); @@ -1338,11 +1344,11 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE buffer.append(hasEffect ? QLatin1String("\x1b[0;") : QLatin1String("\x1b[")); buffer.append(backgroundDefaultColor); buffer.setFinalStyle(); - d->ansiStyles[id].second = buffer.latin1(); + style.second = buffer.latin1(); } else if (hasEffect) { buffer.append(QLatin1String("\x1b[")); if (hasBold) { - buffer.append(QLatin1String("21;")); + buffer.append(QLatin1String("22;")); } if (hasItalic) { buffer.append(QLatin1String("23;")); @@ -1354,10 +1360,10 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE buffer.append(QLatin1String("29;")); } buffer.setFinalStyle(); - d->ansiStyles[id].second = buffer.latin1(); + style.second = buffer.latin1(); } } else { - d->ansiStyles[id].second = QStringLiteral("\x1b[0m"); + style.second = QStringLiteral("\x1b[0m"); } } } @@ -1370,13 +1376,11 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE } QTextStream in(dev); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - in.setCodec("UTF-8"); -#endif - if (!traceOptions) { + if (!options.testAnyFlag(Option::TraceAll)) { State state; QString currentLine; + const bool isUnbuffered = options.testFlag(Option::Unbuffered); while (in.readLineInto(¤tLine)) { d->currentLine = currentLine; state = highlightLine(d->currentLine, state); @@ -1386,6 +1390,10 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE } else { d->out << QLatin1Char('\n'); } + + if (isUnbuffered) { + d->out.flush(); + } } } else { AnsiBuffer buffer; @@ -1394,7 +1402,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE buffer.setFinalStyle(); DebugSyntaxHighlighter debugHighlighter; debugHighlighter.setDefinition(definition); - debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, traceOptions); + debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, options); } if (useEditorBackground) { @@ -1408,6 +1416,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE void AnsiHighlighter::applyFormat(int offset, int length, const Format &format) { + Q_D(AnsiHighlighter); auto const &ansiStyle = d->ansiStyles[format.id()]; d->out << ansiStyle.first << d->currentLine.mid(offset, length) << ansiStyle.second; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h index ffb13f38f37..0942aa0242b 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/ansihighlighter.h @@ -11,10 +11,11 @@ #include "ksyntaxhighlighting_export.h" #include -#include #include -#include +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE namespace KSyntaxHighlighting { @@ -29,24 +30,25 @@ public: XTerm256Color, }; - enum class TraceOption { + enum class Option { NoOptions, - Format = 1 << 0, - Region = 1 << 1, - Context = 1 << 2, - StackSize = 1 << 3, + UseEditorBackground = 1 << 0, + Unbuffered = 1 << 1, + + // Options that displays a useful visual aid for syntax creation + TraceFormat = 1 << 2, + TraceRegion = 1 << 3, + TraceContext = 1 << 4, + TraceStackSize = 1 << 5, + TraceAll = TraceFormat | TraceRegion | TraceContext | TraceStackSize, }; - Q_DECLARE_FLAGS(TraceOptions, TraceOption) + Q_DECLARE_FLAGS(Options, Option) AnsiHighlighter(); ~AnsiHighlighter() override; - void highlightFile(const QString &fileName, - AnsiFormat format = AnsiFormat::TrueColor, - bool useEditorBackground = true, - TraceOptions traceOptions = TraceOptions()); - void - highlightData(QIODevice *device, AnsiFormat format = AnsiFormat::TrueColor, bool useEditorBackground = true, TraceOptions traceOptions = TraceOptions()); + void highlightFile(const QString &fileName, AnsiFormat format = AnsiFormat::TrueColor, Options options = Option::UseEditorBackground); + void highlightData(QIODevice *device, AnsiFormat format = AnsiFormat::TrueColor, Options options = Option::UseEditorBackground); void setOutputFile(const QString &fileName); void setOutputFile(FILE *fileHandle); @@ -55,10 +57,10 @@ protected: void applyFormat(int offset, int length, const Format &format) override; private: - std::unique_ptr d; + Q_DECLARE_PRIVATE(AnsiHighlighter) }; } -Q_DECLARE_OPERATORS_FOR_FLAGS(KSyntaxHighlighting::AnsiHighlighter::TraceOptions) +Q_DECLARE_OPERATORS_FOR_FLAGS(KSyntaxHighlighting::AnsiHighlighter::Options) #endif // KSYNTAXHIGHLIGHTING_ANSIHIGHLIGHTER_H diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp index ff5254cb6e5..af269d14d03 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/context.cpp @@ -38,7 +38,15 @@ void Context::resolveContexts(DefinitionData &def, const HighlightingContextData m_lineEndContext.resolve(def, data.lineEndContext); m_lineEmptyContext.resolve(def, data.lineEmptyContext); m_fallthroughContext.resolve(def, data.fallthroughContext); - m_fallthrough = !m_fallthroughContext.isStay(); + m_stopEmptyLineContextSwitchLoop = data.stopEmptyLineContextSwitchLoop; + + /** + * line end context switches only when lineEmptyContext is #stay. This avoids + * skipping empty lines after a line continuation character (see bug 405903) + */ + if (m_lineEmptyContext.isStay()) { + m_lineEmptyContext = m_lineEndContext; + } m_rules.reserve(data.rules.size()); for (const auto &ruleData : data.rules) { @@ -65,6 +73,7 @@ void Context::resolveIncludes(DefinitionData &def) for (auto it = m_rules.begin(); it != m_rules.end();) { const IncludeRules *includeRules = it->get()->castToIncludeRules(); if (!includeRules) { + m_hasDynamicRule = m_hasDynamicRule || it->get()->isDynamic(); ++it; continue; } @@ -111,6 +120,8 @@ void Context::resolveIncludes(DefinitionData &def) context->resolveIncludes(*defData); } + m_hasDynamicRule = m_hasDynamicRule || context->m_hasDynamicRule; + /** * handle included attribute * transitive closure: we might include attributes included from somewhere else diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h index 7e077b5a244..8cf0f1bfaba 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/context_p.h @@ -16,10 +16,6 @@ #include -QT_BEGIN_NAMESPACE -class QXmlStreamReader; -QT_END_NAMESPACE - namespace KSyntaxHighlighting { class DefinitionData; @@ -52,7 +48,17 @@ public: bool fallthrough() const { - return m_fallthrough; + return !m_fallthroughContext.isStay(); + } + + bool hasDynamicRule() const + { + return m_hasDynamicRule; + } + + bool stopEmptyLineContextSwitchLoop() const + { + return m_stopEmptyLineContextSwitchLoop; } const ContextSwitch &fallthroughContext() const @@ -96,7 +102,8 @@ private: Format m_attributeFormat; ResolveState m_resolveState = Unresolved; - bool m_fallthrough = false; + bool m_hasDynamicRule = false; + bool m_stopEmptyLineContextSwitchLoop = true; bool m_indentationBasedFolding; }; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp index 670dfddedb6..e2cca6da712 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include @@ -43,13 +41,8 @@ DefinitionData::DefinitionData() DefinitionData::~DefinitionData() = default; -DefinitionData *DefinitionData::get(const Definition &def) -{ - return def.d.get(); -} - Definition::Definition() - : d(new DefinitionData) + : d(std::make_shared()) { d->q = *this; } @@ -63,6 +56,9 @@ Definition &Definition::operator=(const Definition &) = default; Definition::Definition(std::shared_ptr &&dd) : d(std::move(dd)) { + if (!d) { + Definition().d.swap(d); + } } bool Definition::operator==(const Definition &other) const @@ -92,7 +88,10 @@ QString Definition::name() const QString Definition::translatedName() const { - return QCoreApplication::instance()->translate("Language", d->name.toUtf8().constData()); + if (d->translatedName.isEmpty()) { + d->translatedName = QCoreApplication::instance()->translate("Language", d->nameUtf8.isEmpty() ? d->name.toUtf8().constData() : d->nameUtf8.constData()); + } + return d->translatedName; } QString Definition::section() const @@ -102,15 +101,19 @@ QString Definition::section() const QString Definition::translatedSection() const { - return QCoreApplication::instance()->translate("Language Section", d->section.toUtf8().constData()); + if (d->translatedSection.isEmpty()) { + d->translatedSection = QCoreApplication::instance()->translate("Language Section", + d->sectionUtf8.isEmpty() ? d->section.toUtf8().constData() : d->sectionUtf8.constData()); + } + return d->translatedSection; } -QVector Definition::mimeTypes() const +QList Definition::mimeTypes() const { return d->mimetypes; } -QVector Definition::extensions() const +QList Definition::extensions() const { return d->extensions; } @@ -218,12 +221,12 @@ bool Definition::setKeywordList(const QString &name, const QStringList &content) } } -QVector Definition::formats() const +QList Definition::formats() const { d->load(); // sort formats so that the order matches the order of the itemDatas in the xml files. - auto formatList = QVector::fromList(d->formats.values()); + auto formatList = d->formats.values(); std::sort(formatList.begin(), formatList.end(), [](const KSyntaxHighlighting::Format &lhs, const KSyntaxHighlighting::Format &rhs) { return lhs.id() < rhs.id(); }); @@ -231,13 +234,13 @@ QVector Definition::formats() const return formatList; } -QVector Definition::includedDefinitions() const +QList Definition::includedDefinitions() const { d->load(); // init worklist and result used as guard with this definition - QVector queue{d.get()}; - QVector definitions{*this}; + QList queue{d.get()}; + QList definitions{*this}; while (!queue.empty()) { const auto *def = queue.back(); queue.pop_back(); @@ -275,7 +278,7 @@ QPair Definition::multiLineCommentMarker() const return {d->multiLineCommentStartMarker, d->multiLineCommentEndMarker}; } -QVector> Definition::characterEncodings() const +QList> Definition::characterEncodings() const { d->load(); return d->characterEncodings; @@ -394,7 +397,11 @@ void DefinitionData::clear() characterEncodings.clear(); fileName.clear(); + nameUtf8.clear(); + translatedName.clear(); section.clear(); + sectionUtf8.clear(); + translatedSection.clear(); style.clear(); indenter.clear(); author.clear(); @@ -405,6 +412,9 @@ void DefinitionData::clear() version = 0.0f; priority = 0; hidden = false; + + // purge our cache that is used to unify states + unify.clear(); } bool DefinitionData::loadMetaData(const QString &definitionFileName) @@ -433,7 +443,9 @@ bool DefinitionData::loadMetaData(const QString &definitionFileName) bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj) { name = obj.value(QLatin1String("name")).toString(); + nameUtf8 = obj.value(QLatin1String("name")).toByteArray(); section = obj.value(QLatin1String("section")).toString(); + sectionUtf8 = obj.value(QLatin1String("section")).toByteArray(); version = obj.value(QLatin1String("version")).toInteger(); priority = obj.value(QLatin1String("priority")).toInteger(); style = obj.value(QLatin1String("style")).toString(); @@ -444,13 +456,10 @@ bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj) fileName = file; const auto exts = obj.value(QLatin1String("extensions")).toString(); - for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { - extensions.push_back(ext); - } + extensions = exts.split(QLatin1Char(';'), Qt::SkipEmptyParts); + const auto mts = obj.value(QLatin1String("mimetype")).toString(); - for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { - mimetypes.push_back(mt); - } + mimetypes = mts.split(QLatin1Char(';'), Qt::SkipEmptyParts); return true; } @@ -805,10 +814,10 @@ bool DefinitionData::checkKateVersion(QStringView verStr) qCWarning(Log) << "Skipping" << fileName << "due to having no valid kateversion attribute:" << verStr; return false; } - const auto major = verStr.left(idx).toString().toInt(); - const auto minor = verStr.mid(idx + 1).toString().toInt(); + const auto major = verStr.left(idx).toInt(); + const auto minor = verStr.mid(idx + 1).toInt(); - if (major > SyntaxHighlighting_VERSION_MAJOR || (major == SyntaxHighlighting_VERSION_MAJOR && minor > SyntaxHighlighting_VERSION_MINOR)) { + if (major > KSYNTAXHIGHLIGHTING_VERSION_MAJOR || (major == KSYNTAXHIGHLIGHTING_VERSION_MAJOR && minor > KSYNTAXHIGHLIGHTING_VERSION_MINOR)) { qCWarning(Log) << "Skipping" << fileName << "due to being too new, version:" << verStr; return false; } @@ -834,34 +843,20 @@ void DefinitionData::addImmediateIncludedDefinition(const Definition &def) DefinitionRef::DefinitionRef() = default; -DefinitionRef::DefinitionRef(const Definition &def) +DefinitionRef::DefinitionRef(const Definition &def) noexcept : d(def.d) { } -DefinitionRef::DefinitionRef(Definition &&def) - : d(std::move(def.d)) -{ -} - -DefinitionRef &DefinitionRef::operator=(const Definition &def) +DefinitionRef &DefinitionRef::operator=(const Definition &def) noexcept { d = def.d; return *this; } -DefinitionRef &DefinitionRef::operator=(Definition &&def) -{ - d = std::move(def.d); - return *this; -} - Definition DefinitionRef::definition() const { - if (!d.expired()) { - return Definition(d.lock()); - } - return Definition(); + return Definition(d.lock()); } bool DefinitionRef::operator==(const DefinitionRef &other) const @@ -873,3 +868,5 @@ bool DefinitionRef::operator==(const Definition &other) const { return !d.owner_before(other.d) && !other.d.owner_before(d); } + +#include "moc_definition.cpp" diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h index 05757ea52a3..e69492bee42 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.h @@ -10,16 +10,12 @@ #include "ksyntaxhighlighting_export.h" +#include #include -#include +#include #include #include -QT_BEGIN_NAMESPACE -class QChar; -class QString; -QT_END_NAMESPACE - namespace KSyntaxHighlighting { class Context; @@ -185,13 +181,13 @@ public: /** * Mime types associated with this syntax definition. */ - QVector mimeTypes() const; + QList mimeTypes() const; /** * File extensions associated with this syntax definition. * The returned list contains wildcards. */ - QVector extensions() const; + QList extensions() const; /** * Returns the definition version. @@ -360,7 +356,7 @@ public: * The order of the Format items equals the order of the itemDatas in the xml file. * @since 5.49 */ - QVector formats() const; + QList formats() const; /** * Returns a list of Definitions that are referenced with the IncludeRules rule. @@ -369,7 +365,7 @@ public: * * @since 5.49 */ - QVector includedDefinitions() const; + QList includedDefinitions() const; /** * Returns the marker that starts a single line comment. @@ -400,7 +396,7 @@ public: * the string \"{A} represents the character Ä. * @since 5.50 */ - QVector> characterEncodings() const; + QList> characterEncodings() const; /** * @} @@ -409,14 +405,14 @@ public: private: friend class DefinitionData; friend class DefinitionRef; - explicit Definition(std::shared_ptr &&dd); + KSYNTAXHIGHLIGHTING_NO_EXPORT explicit Definition(std::shared_ptr &&dd); std::shared_ptr d; }; } QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Definition, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Definition, Q_RELOCATABLE_TYPE); QT_END_NAMESPACE #endif diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h index 542f255b321..ec00b318970 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h @@ -10,11 +10,13 @@ #include "definitionref_p.h" #include "highlightingdata_p.hpp" +#include "state.h" #include "worddelimiters_p.h" #include +#include +#include #include -#include #include @@ -36,7 +38,10 @@ public: DefinitionData(const DefinitionData &) = delete; DefinitionData &operator=(const DefinitionData &) = delete; - static DefinitionData *get(const Definition &def); + static DefinitionData *get(const Definition &def) + { + return def.d.get(); + } bool isLoaded() const; bool loadMetaData(const QString &definitionFileName); @@ -80,9 +85,9 @@ public: std::vector contexts; QHash formats; // data loaded from xml file and emptied after loading contexts - QVector contextDatas; + QList contextDatas; // Definition referenced by IncludeRules and ContextSwitch - QVector immediateIncludedDefinitions; + QList immediateIncludedDefinitions; WordDelimiters wordDelimiters; WordDelimiters wordWrapDelimiters; bool keywordIsLoaded = false; @@ -93,21 +98,28 @@ public: CommentPosition singleLineCommentPosition = CommentPosition::StartOfLine; QString multiLineCommentStartMarker; QString multiLineCommentEndMarker; - QVector> characterEncodings; + QList> characterEncodings; QString fileName; QString name = QStringLiteral(QT_TRANSLATE_NOOP("Language", "None")); + QByteArray nameUtf8; + mutable QString translatedName; QString section; + QByteArray sectionUtf8; + mutable QString translatedSection; QString style; QString indenter; QString author; QString license; - QVector mimetypes; - QVector extensions; + QList mimetypes; + QList extensions; Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive; int version = 0; int priority = 0; bool hidden = false; + + // cache that is used to unify states in AbstractHighlighter::highlightLine + mutable QSet unify; }; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp index c1335789dc9..88ba5d77591 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitiondownloader.cpp @@ -169,8 +169,8 @@ DefinitionDownloader::~DefinitionDownloader() void DefinitionDownloader::start() { - const QString url = QLatin1String("https://www.kate-editor.org/syntax/update-") + QString::number(SyntaxHighlighting_VERSION_MAJOR) + QLatin1Char('.') - + QString::number(SyntaxHighlighting_VERSION_MINOR) + QLatin1String(".xml"); + const QString url = QLatin1String("https://www.kate-editor.org/syntax/update-") + QString::number(KSYNTAXHIGHLIGHTING_VERSION_MAJOR) + QLatin1Char('.') + + QString::number(KSYNTAXHIGHLIGHTING_VERSION_MINOR) + QLatin1String(".xml"); auto req = QNetworkRequest(QUrl(url)); req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); auto reply = d->nam->get(req); @@ -178,3 +178,5 @@ void DefinitionDownloader::start() d->definitionListDownloadFinished(reply); }); } + +#include "moc_definitiondownloader.cpp" diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h index 0bd805624dd..a7ef08f614f 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definitionref_p.h @@ -30,10 +30,8 @@ class DefinitionRef { public: DefinitionRef(); - explicit DefinitionRef(const Definition &def); - explicit DefinitionRef(Definition &&def); - DefinitionRef &operator=(const Definition &def); - DefinitionRef &operator=(Definition &&def); + explicit DefinitionRef(const Definition &def) noexcept; + DefinitionRef &operator=(const Definition &def) noexcept; Definition definition() const; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h new file mode 100644 index 00000000000..dcef97a8416 --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/dynamicregexpcache_p.h @@ -0,0 +1,39 @@ +/* + SPDX-FileCopyrightText: 2023 Jonathan Poelen + + SPDX-License-Identifier: MIT +*/ + +#ifndef KSYNTAXHIGHLIGHTING_DYNAMICREGEXPCACHE_P_H +#define KSYNTAXHIGHLIGHTING_DYNAMICREGEXPCACHE_P_H + +#include +#include +#include + +#include + +namespace KSyntaxHighlighting +{ + +class DynamicRegexpCache +{ +public: + const QRegularExpression &compileRegexp(QString &&pattern, QRegularExpression::PatternOptions patternOptions) + { + const auto key = std::pair{std::move(pattern), patternOptions}; + if (const auto regexp = m_cache.object(key)) { + return *regexp; + } + auto regexp = new QRegularExpression(key.first, patternOptions); + m_cache.insert(key, regexp); + return *regexp; + } + +private: + QCache, QRegularExpression> m_cache; +}; + +} + +#endif diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp index 3bca63eecda..9ed625b12ed 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.cpp @@ -8,36 +8,39 @@ using namespace KSyntaxHighlighting; -static_assert(sizeof(FoldingRegion) == 2, "FoldingRegion is size-sensitive to frequent use in KTextEditor!"); +static_assert(sizeof(FoldingRegion) == sizeof(int), "FoldingRegion is size-sensitive to frequent use in KTextEditor!"); -FoldingRegion::FoldingRegion() - : m_type(None) - , m_id(0) -{ -} +FoldingRegion::FoldingRegion() = default; -FoldingRegion::FoldingRegion(Type type, quint16 id) - : m_type(type) - , m_id(id) +FoldingRegion::FoldingRegion(Type type, int id) + : m_idWithType((type == End) ? -id : id) { } bool FoldingRegion::operator==(const FoldingRegion &other) const { - return m_id == other.m_id && m_type == other.m_type; + return m_idWithType == other.m_idWithType; } bool FoldingRegion::isValid() const { - return type() != None; + return m_idWithType != 0; } -quint16 FoldingRegion::id() const +int FoldingRegion::id() const { - return m_id; + return (m_idWithType < 0) ? -m_idWithType : m_idWithType; } FoldingRegion::Type FoldingRegion::type() const { - return static_cast(m_type); + if (isValid()) { + return (m_idWithType < 0) ? End : Begin; + } + return None; +} + +FoldingRegion FoldingRegion::sibling() const +{ + return isValid() ? FoldingRegion(type() ? End : Begin, id()) : FoldingRegion(); } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h index ca4cacafb25..e2a9e1fc680 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/foldingregion.h @@ -22,7 +22,7 @@ public: * Defines whether a FoldingRegion starts or ends a folding region. */ enum Type { - //! Used internally as indicator for invalid FoldingRegion%s. + //! Used internally as indicator for an invalid FoldingRegion. None, //! Indicates the start of a FoldingRegion. Begin, @@ -64,7 +64,7 @@ public: * brace, you need to do kind of a reference counting to find the correct * closing brace. */ - quint16 id() const; + int id() const; /** * Returns whether this is the begin or end of a region. @@ -74,12 +74,21 @@ public: */ Type type() const; + /** + * Returns the matching start or end region. + * + * @note Will return invalid region for an invalid region. + * + * @since 6.0 + */ + FoldingRegion sibling() const; + private: friend class Rule; - FoldingRegion(Type type, quint16 id); + KSYNTAXHIGHLIGHTING_NO_EXPORT FoldingRegion(Type type, int id); - quint16 m_type : 2; - quint16 m_id : 14; + // 0 is invalid, positive begin, negative end + int m_idWithType = 0; }; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp index 518a1e9ee9e..2259cd34115 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp @@ -98,7 +98,7 @@ QString Format::name() const return d->name; } -quint16 Format::id() const +int Format::id() const { return d->id; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.h b/src/libs/3rdparty/syntax-highlighting/src/lib/format.h index 496a54e42cb..397a1bab01c 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.h @@ -13,12 +13,6 @@ #include -QT_BEGIN_NAMESPACE -class QColor; -class QString; -class QXmlStreamReader; -QT_END_NAMESPACE - namespace KSyntaxHighlighting { class FormatPrivate; @@ -54,7 +48,7 @@ public: * the repository is reloaded (which also invalidatess the corresponding * Definition anyway). */ - quint16 id() const; + int id() const; /** Returns the underlying TextStyle of this Format. * Every Theme::TextStyle is visually defined by a Theme. A Format uses one @@ -192,7 +186,7 @@ private: } QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Format, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Format, Q_RELOCATABLE_TYPE); QT_END_NAMESPACE #endif // KSYNTAXHIGHLIGHTING_FORMAT_H diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h index d8770f1ef7c..ea74531445e 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format_p.h @@ -13,6 +13,10 @@ #include #include +QT_BEGIN_NAMESPACE +class QXmlStreamReader; +QT_END_NAMESPACE + namespace KSyntaxHighlighting { class FormatPrivate : public QSharedData @@ -21,6 +25,11 @@ public: FormatPrivate() = default; static FormatPrivate *detachAndGet(Format &format); + static std::intptr_t ptrId(const Format &format) + { + return std::intptr_t(format.d.data()); + } + TextStyleData styleOverride(const Theme &theme) const; void load(QXmlStreamReader &reader); @@ -33,7 +42,7 @@ public: QString name; TextStyleData style; Theme::TextStyle defaultStyle = Theme::Normal; - quint16 id = 0; + int id = 0; bool spellCheck = true; }; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp index adb1c346c13..d95ad43b7fe 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata.cpp @@ -379,6 +379,7 @@ void HighlightingContextData::load(const QString &defName, QXmlStreamReader &rea lineEmptyContext = reader.attributes().value(QLatin1String("lineEmptyContext")).toString(); fallthroughContext = reader.attributes().value(QLatin1String("fallthroughContext")).toString(); noIndentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("noIndentationBasedFolding"))); + stopEmptyLineContextSwitchLoop = Xml::attrToBool(reader.attributes().value(QLatin1String("stopEmptyLineContextSwitchLoop"))); rules.reserve(8); diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp index 80aeaf49340..f49227dbf96 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/highlightingdata_p.hpp @@ -208,6 +208,7 @@ public: std::vector rules; + bool stopEmptyLineContextSwitchLoop = false; bool noIndentationBasedFolding = false; }; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp index 1f68e33d3e4..928ae149d1b 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.cpp @@ -6,7 +6,9 @@ */ #include "htmlhighlighter.h" +#include "abstracthighlighter_p.h" #include "definition.h" +#include "definition_p.h" #include "format.h" #include "ksyntaxhighlighting_logging.h" #include "state.h" @@ -14,21 +16,22 @@ #include #include +#include #include -#include using namespace KSyntaxHighlighting; -class KSyntaxHighlighting::HtmlHighlighterPrivate +class KSyntaxHighlighting::HtmlHighlighterPrivate : public AbstractHighlighterPrivate { public: std::unique_ptr out; std::unique_ptr file; QString currentLine; + std::vector htmlStyles; }; HtmlHighlighter::HtmlHighlighter() - : d(new HtmlHighlighterPrivate()) + : AbstractHighlighter(new HtmlHighlighterPrivate()) { } @@ -38,27 +41,21 @@ HtmlHighlighter::~HtmlHighlighter() void HtmlHighlighter::setOutputFile(const QString &fileName) { + Q_D(HtmlHighlighter); d->file.reset(new QFile(fileName)); if (!d->file->open(QFile::WriteOnly | QFile::Truncate)) { qCWarning(Log) << "Failed to open output file" << fileName << ":" << d->file->errorString(); return; } d->out.reset(new QTextStream(d->file.get())); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) d->out->setEncoding(QStringConverter::Utf8); -#else - d->out->setCodec("UTF-8"); -#endif } void HtmlHighlighter::setOutputFile(FILE *fileHandle) { + Q_D(HtmlHighlighter); d->out.reset(new QTextStream(fileHandle, QIODevice::WriteOnly)); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) d->out->setEncoding(QStringConverter::Utf8); -#else - d->out->setCodec("UTF-8"); -#endif } void HtmlHighlighter::highlightFile(const QString &fileName, const QString &title) @@ -79,7 +76,7 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl /** * @brief toHtmlRgba - * Converts QColor -> rgba(r, g, b, a) if there is an alpha channel + * Converts QColor -> #RRGGBBAA if there is an alpha channel * otherwise it will just return the hexcode. This is because QColor * outputs #AARRGGBB, whereas browser support #RRGGBBAA. * @@ -91,22 +88,24 @@ static QString toHtmlRgbaString(const QColor &color) if (color.alpha() == 0xFF) { return color.name(); } - - QString rgba = QStringLiteral("rgba("); - rgba.append(QString::number(color.red())); - rgba.append(QLatin1Char(',')); - rgba.append(QString::number(color.green())); - rgba.append(QLatin1Char(',')); - rgba.append(QString::number(color.blue())); - rgba.append(QLatin1Char(',')); - // this must be alphaF - rgba.append(QString::number(color.alphaF())); - rgba.append(QLatin1Char(')')); - return rgba; + static const char16_t digits[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + QChar hexcode[9]; + hexcode[0] = QLatin1Char('#'); + hexcode[1] = digits[color.red() >> 4]; + hexcode[2] = digits[color.red() & 0xf]; + hexcode[3] = digits[color.green() >> 4]; + hexcode[4] = digits[color.green() & 0xf]; + hexcode[5] = digits[color.blue() >> 4]; + hexcode[6] = digits[color.blue() & 0xf]; + hexcode[7] = digits[color.alpha() >> 4]; + hexcode[8] = digits[color.alpha() & 0xf]; + return QString(hexcode, 9); } void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title) { + Q_D(HtmlHighlighter); + if (!d->out) { qCWarning(Log) << "No output stream defined!"; return; @@ -114,29 +113,73 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title) QString htmlTitle; if (title.isEmpty()) { - htmlTitle = QStringLiteral("Kate Syntax Highlighter"); + htmlTitle = QStringLiteral("KSyntaxHighlighter"); } else { htmlTitle = title.toHtmlEscaped(); } + const auto &theme = d->m_theme; + const auto &definition = d->m_definition; + + auto definitions = definition.includedDefinitions(); + definitions.append(definition); + + int maxId = 0; + for (const auto &definition : std::as_const(definitions)) { + for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) { + maxId = qMax(maxId, format.id()); + } + } + d->htmlStyles.clear(); + // htmlStyles must not be empty for applyFormat to work even with a definition without any context + d->htmlStyles.resize(maxId + 1); + + // initialize htmlStyles + for (const auto &definition : std::as_const(definitions)) { + for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) { + auto &buffer = d->htmlStyles[format.id()]; + if (format.hasTextColor(theme)) { + buffer += QStringLiteral("color:") + toHtmlRgbaString(format.textColor(theme)) + QStringLiteral(";"); + } + if (format.hasBackgroundColor(theme)) { + buffer += QStringLiteral("background-color:") + toHtmlRgbaString(format.backgroundColor(theme)) + QStringLiteral(";"); + } + if (format.isBold(theme)) { + buffer += QStringLiteral("font-weight:bold;"); + } + if (format.isItalic(theme)) { + buffer += QStringLiteral("font-style:italic;"); + } + if (format.isUnderline(theme)) { + buffer += QStringLiteral("text-decoration:underline;"); + } + if (format.isStrikeThrough(theme)) { + buffer += QStringLiteral("text-decoration:line-through;"); + } + + if (!buffer.isEmpty()) { + buffer.insert(0, QStringLiteral("'; + } + } + } + State state; *d->out << "\n"; *d->out << "\n"; *d->out << "\n"; *d->out << "" << htmlTitle << "\n"; - *d->out << "\n"; + *d->out << "\n"; *d->out << "out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme().editorColor(Theme::BackgroundColor))); - if (theme().textColor(Theme::Normal)) { - *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme().textColor(Theme::Normal))); + *d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme.editorColor(Theme::BackgroundColor))); + if (theme.textColor(Theme::Normal)) { + *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme.textColor(Theme::Normal))); } *d->out << "\">
\n";
 
     QTextStream in(dev);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-    in.setCodec("UTF-8");
-#endif
     while (in.readLineInto(&d->currentLine)) {
         state = highlightLine(d->currentLine, state);
         *d->out << "\n";
@@ -155,38 +198,24 @@ void HtmlHighlighter::applyFormat(int offset, int length, const Format &format)
         return;
     }
 
-    // collect potential output, cheaper than thinking about "is there any?"
-    QVarLengthArray formatOutput;
-    if (format.hasTextColor(theme())) {
-        formatOutput << QStringLiteral("color:") << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";");
-    }
-    if (format.hasBackgroundColor(theme())) {
-        formatOutput << QStringLiteral("background-color:") << toHtmlRgbaString(format.backgroundColor(theme())) << QStringLiteral(";");
-    }
-    if (format.isBold(theme())) {
-        formatOutput << QStringLiteral("font-weight:bold;");
-    }
-    if (format.isItalic(theme())) {
-        formatOutput << QStringLiteral("font-style:italic;");
-    }
-    if (format.isUnderline(theme())) {
-        formatOutput << QStringLiteral("text-decoration:underline;");
-    }
-    if (format.isStrikeThrough(theme())) {
-        formatOutput << QStringLiteral("text-decoration:line-through;");
+    Q_D(HtmlHighlighter);
+
+    auto const &htmlStyle = d->htmlStyles[format.id()];
+
+    if (!htmlStyle.isEmpty()) {
+        *d->out << htmlStyle;
     }
 
-    if (!formatOutput.isEmpty()) {
-        *d->out << "out << out;
-        }
-        *d->out << "\">";
+    for (QChar ch : QStringView(d->currentLine).mid(offset, length)) {
+        if (ch == u'<')
+            *d->out << QStringLiteral("<");
+        else if (ch == u'&')
+            *d->out << QStringLiteral("&");
+        else
+            *d->out << ch;
     }
 
-    *d->out << d->currentLine.mid(offset, length).toHtmlEscaped();
-
-    if (!formatOutput.isEmpty()) {
-        *d->out << "";
+    if (!htmlStyle.isEmpty()) {
+        *d->out << QStringLiteral("");
     }
 }
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
index 8754057345d..741cb851031 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/htmlhighlighter.h
@@ -10,10 +10,11 @@
 #include "abstracthighlighter.h"
 #include "ksyntaxhighlighting_export.h"
 
-#include 
 #include 
 
-#include 
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
 
 namespace KSyntaxHighlighting
 {
@@ -35,7 +36,7 @@ protected:
     void applyFormat(int offset, int length, const Format &format) override;
 
 private:
-    std::unique_ptr d;
+    Q_DECLARE_PRIVATE(HtmlHighlighter)
 };
 }
 
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
index 133b6d28ac5..847f6af6d46 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
@@ -47,7 +47,7 @@ bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) c
     /**
      * search with right predicate
      */
-    return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), KeywordComparator{caseSensitive});
+    return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), str, KeywordComparator{caseSensitive});
 }
 
 void KeywordList::load(QXmlStreamReader &reader)
@@ -103,10 +103,7 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive
     /**
      * fill vector with refs to keywords
      */
-    vectorToSort.reserve(m_keywords.size());
-    for (const auto &keyword : std::as_const(m_keywords)) {
-        vectorToSort.push_back(keyword);
-    }
+    vectorToSort.assign(m_keywords.constBegin(), m_keywords.constEnd());
 
     /**
      * sort with right predicate
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
index 1e0f7c61027..7112d4e291b 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/matchresult_p.h
@@ -41,9 +41,9 @@ public:
      * @param offset offset of match
      * @param captures captures of the match
      */
-    explicit MatchResult(const int offset, const QStringList &captures)
+    explicit MatchResult(const int offset, QStringList &&captures)
         : m_offset(offset)
-        , m_captures(captures)
+        , m_captures(std::move(captures))
     {
     }
 
@@ -69,7 +69,7 @@ public:
      * Captures of the match.
      * @return captured text of this match
      */
-    const QStringList &captures() const
+    QStringList &captures()
     {
         return m_captures;
     }
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
index a12d4ba1a3a..07c28454c5b 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
@@ -77,9 +77,9 @@ Definition findHighestPriorityDefinitionIf(const QMap &defs
 }
 
 template
-QVector findDefinitionsIf(const QMap &defs, UnaryPredicate predicate)
+QList findDefinitionsIf(const QMap &defs, UnaryPredicate predicate)
 {
-    QVector matches;
+    QList matches;
     std::copy_if(defs.cbegin(), defs.cend(), std::back_inserter(matches), predicate);
     std::stable_sort(matches.begin(), matches.end(), [](const Definition &lhs, const Definition &rhs) {
         return lhs.priority() > rhs.priority();
@@ -127,7 +127,7 @@ Definition Repository::definitionForFileName(const QString &fileName) const
     return findHighestPriorityDefinitionIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
 }
 
-QVector Repository::definitionsForFileName(const QString &fileName) const
+QList Repository::definitionsForFileName(const QString &fileName) const
 {
     return findDefinitionsIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
 }
@@ -137,22 +137,22 @@ Definition Repository::definitionForMimeType(const QString &mimeType) const
     return findHighestPriorityDefinitionIf(d->m_defs, anyMimeTypeEquals(mimeType));
 }
 
-QVector Repository::definitionsForMimeType(const QString &mimeType) const
+QList Repository::definitionsForMimeType(const QString &mimeType) const
 {
     return findDefinitionsIf(d->m_defs, anyMimeTypeEquals(mimeType));
 }
 
-QVector Repository::definitions() const
+QList Repository::definitions() const
 {
     return d->m_sortedDefs;
 }
 
-QVector Repository::themes() const
+QList Repository::themes() const
 {
     return d->m_themes;
 }
 
-static auto lowerBoundTheme(const QVector &themes, QStringView themeName)
+static auto lowerBoundTheme(const QList &themes, QStringView themeName)
 {
     return std::lower_bound(themes.begin(), themes.end(), themeName, [](const Theme &lhs, QStringView rhs) {
         return lhs.name() < rhs;
@@ -177,42 +177,32 @@ Theme Repository::defaultTheme(Repository::DefaultTheme t) const
     return theme(QStringLiteral("Breeze Light"));
 }
 
-Theme Repository::defaultTheme(Repository::DefaultTheme t)
-{
-    return std::as_const(*this).defaultTheme(t);
-}
-
 Theme Repository::themeForPalette(const QPalette &palette) const
 {
     const auto base = palette.color(QPalette::Base);
+    const auto highlight = palette.color(QPalette::Highlight).rgb();
 
-    // find themes with matching background colors
-    QVector matchingThemes;
+    // find themes with matching background and highlight colors
+    const Theme *firstMatchingTheme = nullptr;
     for (const auto &theme : std::as_const(d->m_themes)) {
-        const auto background = theme.editorColor(KSyntaxHighlighting::Theme::EditorColorRole::BackgroundColor);
+        const auto background = theme.editorColor(Theme::EditorColorRole::BackgroundColor);
         if (background == base.rgb()) {
-            matchingThemes.append(&theme);
-        }
-    }
-    if (!matchingThemes.empty()) {
-        // if there's multiple, search for one with a matching highlight color
-        const auto highlight = palette.color(QPalette::Highlight);
-        for (const auto *theme : std::as_const(matchingThemes)) {
-            auto selection = theme->editorColor(KSyntaxHighlighting::Theme::EditorColorRole::TextSelection);
-            if (selection == highlight.rgb()) {
-                return *theme;
+            // find theme with a matching highlight color
+            auto selection = theme.editorColor(Theme::EditorColorRole::TextSelection);
+            if (selection == highlight) {
+                return theme;
+            }
+            if (!firstMatchingTheme) {
+                firstMatchingTheme = &theme;
             }
         }
-        return *matchingThemes.first();
+    }
+    if (firstMatchingTheme) {
+        return *firstMatchingTheme;
     }
 
     // fallback to just use the default light or dark theme
-    return defaultTheme((base.lightness() < 128) ? KSyntaxHighlighting::Repository::DarkTheme : KSyntaxHighlighting::Repository::LightTheme);
-}
-
-Theme Repository::themeForPalette(const QPalette &palette)
-{
-    return std::as_const(*this).themeForPalette(palette);
+    return defaultTheme((base.lightness() < 128) ? Repository::DarkTheme : Repository::LightTheme);
 }
 
 void RepositoryPrivate::load(Repository *repo)
@@ -238,12 +228,6 @@ void RepositoryPrivate::load(Repository *repo)
                                                      QStandardPaths::LocateDirectory)) {
         loadSyntaxFolder(repo, dir);
     }
-
-    // backward compatibility with Kate
-    for (const auto &dir :
-         QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) {
-        loadSyntaxFolder(repo, dir);
-    }
 #endif
 
     // default resources are always used, this is the one location that has a index cbor file
@@ -377,25 +361,27 @@ void RepositoryPrivate::addTheme(const Theme &theme)
     }
 }
 
-quint16 RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName)
+int RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName)
 {
     const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName));
     if (it != m_foldingRegionIds.constEnd()) {
         return it.value();
     }
+    Q_ASSERT(m_foldingRegionId < std::numeric_limits::max());
     m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId);
     return m_foldingRegionId;
 }
 
-quint16 RepositoryPrivate::nextFormatId()
+int RepositoryPrivate::nextFormatId()
 {
-    Q_ASSERT(m_formatId < std::numeric_limits::max());
+    Q_ASSERT(m_formatId < std::numeric_limits::max());
     return ++m_formatId;
 }
 
 void Repository::reload()
 {
-    qCDebug(Log) << "Reloading syntax definitions!";
+    Q_EMIT aboutToReload();
+
     for (const auto &def : std::as_const(d->m_sortedDefs)) {
         DefinitionData::get(def)->clear();
     }
@@ -410,6 +396,8 @@ void Repository::reload()
     d->m_formatId = 0;
 
     d->load(this);
+
+    Q_EMIT reloaded();
 }
 
 void Repository::addCustomSearchPath(const QString &path)
@@ -418,7 +406,9 @@ void Repository::addCustomSearchPath(const QString &path)
     reload();
 }
 
-QVector Repository::customSearchPaths() const
+QList Repository::customSearchPaths() const
 {
     return d->m_customSearchPaths;
 }
+
+#include "moc_repository.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
index 7c74753bfe3..612ba54d6a4 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
@@ -9,7 +9,8 @@
 
 #include "ksyntaxhighlighting_export.h"
 
-#include 
+#include 
+#include 
 #include 
 
 #include 
@@ -76,13 +77,6 @@ class Theme;
  *    map to $HOME/.local5/share/org.kde.syntax-highlighting/syntax and
  *    /usr/share/org.kde.syntax-highlighting/syntax.
  *
- * -# Next, for backwards compatibility with Kate, all syntax highlighting
- *    files are loaded that are located in
- *    QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory);
- *    Again, under Unix, this uses $XDG_DATA_HOME and $XDG_DATA_DIRS, which
- *    could map to $HOME/.local5/share/katepart5/syntax and
- *    /usr/share/katepart5/syntax.
- *
  * -# Then, all files compiled into the library through resources are loaded.
  *    The internal resource path is ":/org.kde.syntax-highlighting/syntax".
  *    This path should never be touched by other applications.
@@ -124,8 +118,12 @@ class Theme;
  * @see Definition, Theme, AbstractHighlighter
  * @since 5.28
  */
-class KSYNTAXHIGHLIGHTING_EXPORT Repository
+class KSYNTAXHIGHLIGHTING_EXPORT Repository : public QObject
 {
+    Q_OBJECT
+    Q_PROPERTY(QList definitions READ definitions NOTIFY reloaded)
+    Q_PROPERTY(QList themes READ themes NOTIFY reloaded)
+
 public:
     /**
      * Create a new syntax definition repository.
@@ -148,7 +146,7 @@ public:
      *       Therefore, only the string "JavaScript" will return a valid
      *       Definition file.
      */
-    Definition definitionForName(const QString &defName) const;
+    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const;
 
     /**
      * Returns the best matching Definition for the file named @p fileName.
@@ -159,7 +157,7 @@ public:
      * If no match is found, Definition::isValid() of the returned instance
      * returns false.
      */
-    Definition definitionForFileName(const QString &fileName) const;
+    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const;
 
     /**
      * Returns all Definition%s for the file named @p fileName sorted by priority.
@@ -168,7 +166,7 @@ public:
      *
      * @since 5.56
      */
-    QVector definitionsForFileName(const QString &fileName) const;
+    Q_INVOKABLE QList definitionsForFileName(const QString &fileName) const;
 
     /**
      * Returns the best matching Definition to the type named @p mimeType
@@ -178,34 +176,34 @@ public:
      *
      * @since 5.50
      */
-    Definition definitionForMimeType(const QString &mimeType) const;
+    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const;
 
     /**
      * Returns all Definition%s to the type named @p mimeType sorted by priority
      *
      * @since 5.56
      */
-    QVector definitionsForMimeType(const QString &mimeType) const;
+    Q_INVOKABLE QList definitionsForMimeType(const QString &mimeType) const;
 
     /**
      * Returns all available Definition%s.
      * Definition%ss are ordered by translated section and translated names,
      * for consistent displaying.
      */
-    QVector definitions() const;
+    Q_INVOKABLE QList definitions() const;
 
     /**
      * Returns all available color themes.
      * The returned list should never be empty.
      */
-    QVector themes() const;
+    Q_INVOKABLE QList themes() const;
 
     /**
      * Returns the theme called @p themeName.
      * If the requested theme cannot be found, the retunred Theme is invalid,
      * see Theme::isValid().
      */
-    Theme theme(const QString &themeName) const;
+    Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const;
 
     /**
      * Built-in default theme types.
@@ -217,21 +215,14 @@ public:
         //! Theme with a dark background color.
         DarkTheme
     };
+    Q_ENUM(DefaultTheme)
 
     /**
      * Returns a default theme instance of the given type.
      * The returned Theme is guaranteed to be a valid theme.
      * @since 5.79
      */
-    Theme defaultTheme(DefaultTheme t = LightTheme) const;
-
-    /**
-     * Returns a default theme instance of the given type.
-     * The returned Theme is guaranteed to be a valid theme.
-     *
-     * KF6: remove in favor of const variant
-     */
-    Theme defaultTheme(DefaultTheme t = LightTheme);
+    Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t = LightTheme) const;
 
     /**
      * Returns the best matching theme for the given palette
@@ -239,14 +230,6 @@ public:
      **/
     Theme themeForPalette(const QPalette &palette) const;
 
-    /**
-     * Returns the best matching theme for the given palette
-     * @since 5.77
-     *
-     * KF6: remove in favor of const variant
-     **/
-    Theme themeForPalette(const QPalette &palette);
-
     /**
      * Reloads the repository.
      * This is a moderately expensive operations and should thus only be
@@ -278,7 +261,20 @@ public:
      * @see addCustomSearchPath()
      * @since 5.39
      */
-    QVector customSearchPaths() const;
+    QList customSearchPaths() const;
+
+Q_SIGNALS:
+    /**
+     * This signal is emitted before the reload is started.
+     * @since 6.0
+     */
+    void aboutToReload();
+
+    /**
+     * This signal is emitted when the reload is finished.
+     * @since 6.0
+     */
+    void reloaded();
 
 private:
     Q_DISABLE_COPY(Repository)
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h
index 447cfae6990..bb9f8ba0820 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository_p.h
@@ -8,11 +8,11 @@
 #define KSYNTAXHIGHLIGHTING_REPOSITORY_P_H
 
 #include 
-#include 
+#include 
+#include 
+#include 
 
-QT_BEGIN_NAMESPACE
-class QString;
-QT_END_NAMESPACE
+#include "dynamicregexpcache_p.h"
 
 namespace KSyntaxHighlighting
 {
@@ -36,22 +36,24 @@ public:
     void loadThemeFolder(const QString &path);
     void addTheme(const Theme &theme);
 
-    quint16 foldingRegionId(const QString &defName, const QString &foldName);
-    quint16 nextFormatId();
+    int foldingRegionId(const QString &defName, const QString &foldName);
+    int nextFormatId();
 
-    QVector m_customSearchPaths;
+    QList m_customSearchPaths;
 
     // sorted map to have deterministic iteration order for e.g. definitionsForFileName
     QMap m_defs;
 
     // this vector is sorted by translated sections/names
-    QVector m_sortedDefs;
+    QList m_sortedDefs;
 
-    QVector m_themes;
+    QList m_themes;
 
-    QHash, quint16> m_foldingRegionIds;
-    quint16 m_foldingRegionId = 0;
-    quint16 m_formatId = 0;
+    QHash, int> m_foldingRegionIds;
+    int m_foldingRegionId = 0;
+    int m_formatId = 0;
+
+    DynamicRegexpCache m_dynamicRegexpCache;
 };
 }
 
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
index 1d02bd6ac34..186ed16120d 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
@@ -1,20 +1,19 @@
 /*
     SPDX-FileCopyrightText: 2016 Volker Krause 
     SPDX-FileCopyrightText: 2018 Christoph Cullmann 
-    SPDX-FileCopyrightText: 2020 Jonathan Poelen 
+    SPDX-FileCopyrightText: 2020 Jonathan Poelen 
 
     SPDX-License-Identifier: MIT
 */
 
 #include "context_p.h"
 #include "definition_p.h"
+#include "dynamicregexpcache_p.h"
 #include "ksyntaxhighlighting_logging.h"
 #include "rule_p.h"
 #include "worddelimiters_p.h"
 #include "xml_p.h"
 
-#include 
-
 using namespace KSyntaxHighlighting;
 
 // QChar::isDigit() match any digit in unicode (romain numeral, etc)
@@ -90,8 +89,8 @@ static int matchEscapedChar(QStringView text, int offset)
 static QString replaceCaptures(const QString &pattern, const QStringList &captures, bool quote)
 {
     auto result = pattern;
-    for (int i = captures.size() - 1; i >= 1; --i) {
-        result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i)) : captures.at(i));
+    for (int i = captures.size(); i >= 1; --i) {
+        result.replace(QLatin1Char('%') + QString::number(i), quote ? QRegularExpression::escape(captures.at(i - 1)) : captures.at(i - 1));
     }
     return result;
 }
@@ -233,7 +232,7 @@ AnyChar::AnyChar(const HighlightingContextData::Rule::AnyChar &data)
 {
 }
 
-MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (m_chars.contains(text.at(offset))) {
         return offset + 1;
@@ -243,15 +242,15 @@ MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &)
 
 DetectChar::DetectChar(const HighlightingContextData::Rule::DetectChar &data)
     : m_char(data.char1)
-    , m_captureIndex(data.dynamic ? data.char1.digitValue() : 0)
+    , m_captureIndex((data.dynamic ? data.char1.digitValue() : 0) - 1)
 {
     m_dynamic = data.dynamic;
 }
 
-MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const
 {
     if (m_dynamic) {
-        if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) {
+        if (m_captureIndex == -1 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) {
             return offset;
         }
         if (text.at(offset) == captures.at(m_captureIndex).at(0)) {
@@ -272,7 +271,7 @@ Detect2Chars::Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &da
 {
 }
 
-MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (text.size() - offset < 2) {
         return offset;
@@ -283,7 +282,7 @@ MatchResult Detect2Chars::doMatch(QStringView text, int offset, const QStringLis
     return offset;
 }
 
-MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) {
         return offset;
@@ -299,7 +298,7 @@ MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStrin
     return text.size();
 }
 
-MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     while (offset < text.size() && text.at(offset).isSpace()) {
         ++offset;
@@ -313,7 +312,7 @@ Float::Float(DefinitionData &def, const HighlightingContextData::Rule::Float &da
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
 }
 
-MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Float::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
         return offset;
@@ -358,7 +357,7 @@ MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) co
     return expOffset;
 }
 
-MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (text.size() < offset + 3) {
         return offset;
@@ -393,7 +392,7 @@ HlCHex::HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
 }
 
-MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
         return offset;
@@ -427,7 +426,7 @@ HlCOct::HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
 }
 
-MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
         return offset;
@@ -453,7 +452,7 @@ MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) c
     return offset;
 }
 
-MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     return matchEscapedChar(text, offset);
 }
@@ -464,7 +463,7 @@ IncludeRules::IncludeRules(const HighlightingContextData::Rule::IncludeRules &da
 {
 }
 
-MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     Q_UNUSED(text);
     qCWarning(Log) << "Unresolved include rule";
@@ -477,7 +476,7 @@ Int::Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data)
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
 }
 
-MatchResult Int::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult Int::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (offset > 0 && !m_wordDelimiters.contains(text.at(offset - 1))) {
         return offset;
@@ -521,9 +520,10 @@ KeywordListRule::KeywordListRule(const KeywordList &keywordList, DefinitionData
     , m_caseSensitivity(data.hasCaseSensitivityOverride ? data.caseSensitivityOverride : keywordList.caseSensitivity())
 {
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
+    m_hasSkipOffset = true;
 }
 
-MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     auto newOffset = offset;
     while (text.size() > newOffset && !m_wordDelimiters.contains(text.at(newOffset))) {
@@ -546,7 +546,7 @@ LineContinue::LineContinue(const HighlightingContextData::Rule::LineContinue &da
 {
 }
 
-MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (offset == text.size() - 1 && text.at(offset) == m_char) {
         return offset + 1;
@@ -560,7 +560,7 @@ RangeDetect::RangeDetect(const HighlightingContextData::Rule::RangeDetect &data)
 {
 }
 
-MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (text.size() - offset < 2) {
         return offset;
@@ -591,25 +591,16 @@ static QRegularExpression::PatternOptions makePattenOptions(const HighlightingCo
 
 static void resolveRegex(QRegularExpression ®exp, Context *context)
 {
-    if (!regexp.isValid()) {
-        // DontCaptureOption with back reference capture is an error, remove this option then try again
+    bool enableCapture = context && context->hasDynamicRule();
+
+    // disable DontCaptureOption when reference a context with dynamic rule or
+    // with invalid regex because DontCaptureOption with back reference capture is an error
+    if (enableCapture || !regexp.isValid()) {
         regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption);
-
-        if (!regexp.isValid()) {
-            qCDebug(Log) << "Invalid regexp:" << regexp.pattern();
-        }
-
-        return;
     }
 
-    // disable DontCaptureOption when reference a context with dynamic rule
-    if (context) {
-        for (const Rule::Ptr &rule : context->rules()) {
-            if (rule->isDynamic()) {
-                regexp.setPatternOptions(regexp.patternOptions() & ~QRegularExpression::DontCaptureOption);
-                break;
-            }
-        }
+    if (!regexp.isValid()) {
+        qCDebug(Log) << "Invalid regexp:" << regexp.pattern();
     }
 }
 
@@ -618,15 +609,25 @@ static MatchResult regexMatch(const QRegularExpression ®exp, QStringView text
     /**
      * match the pattern
      */
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+    const auto result = regexp.matchView(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption);
+#else
     const auto result = regexp.match(text, offset, QRegularExpression::NormalMatch, QRegularExpression::DontCheckSubjectStringMatchOption);
+#endif
     if (result.capturedStart() == offset) {
         /**
          * we only need to compute the captured texts if we have real capture groups
          * highlightings should only address %1..%.., see e.g. replaceCaptures
          * DetectChar ignores %0, too
          */
-        if (result.lastCapturedIndex() > 0) {
-            return MatchResult(offset + result.capturedLength(), result.capturedTexts());
+        int lastCapturedIndex = result.lastCapturedIndex();
+        if (lastCapturedIndex > 0) {
+            QStringList captures;
+            captures.reserve(lastCapturedIndex);
+            // ignore the capturing group number 0
+            for (int i = 1; i <= lastCapturedIndex; ++i)
+                captures.push_back(result.captured(i));
+            return MatchResult(offset + result.capturedLength(), std::move(captures));
         }
 
         /**
@@ -645,20 +646,17 @@ static MatchResult regexMatch(const QRegularExpression ®exp, QStringView text
 RegExpr::RegExpr(const HighlightingContextData::Rule::RegExpr &data)
     : m_regexp(data.pattern, makePattenOptions(data))
 {
+    m_hasSkipOffset = true;
 }
 
 void RegExpr::resolve()
 {
-    if (m_isResolved) {
-        return;
-    }
-
     m_isResolved = true;
 
     resolveRegex(m_regexp, context().context());
 }
 
-MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (Q_UNLIKELY(!m_isResolved)) {
         const_cast(this)->resolve();
@@ -672,14 +670,11 @@ DynamicRegExpr::DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &dat
     , m_patternOptions(makePattenOptions(data))
 {
     m_dynamic = true;
+    m_hasSkipOffset = true;
 }
 
 void DynamicRegExpr::resolve()
 {
-    if (m_isResolved) {
-        return;
-    }
-
     m_isResolved = true;
 
     QRegularExpression regexp(m_pattern, m_patternOptions);
@@ -687,7 +682,7 @@ void DynamicRegExpr::resolve()
     m_patternOptions = regexp.patternOptions();
 }
 
-MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const
 {
     if (Q_UNLIKELY(!m_isResolved)) {
         const_cast(this)->resolve();
@@ -696,8 +691,8 @@ MatchResult DynamicRegExpr::doMatch(QStringView text, int offset, const QStringL
     /**
      * create new pattern with right instantiation
      */
-    const QRegularExpression regexp(replaceCaptures(m_pattern, captures, true), m_patternOptions);
-
+    auto pattern = replaceCaptures(m_pattern, captures, true);
+    auto ®exp = dynamicRegexpCache.compileRegexp(std::move(pattern), m_patternOptions);
     return regexMatch(regexp, text, offset);
 }
 
@@ -707,7 +702,7 @@ StringDetect::StringDetect(const HighlightingContextData::Rule::StringDetect &da
 {
 }
 
-MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     return matchString(m_string, text, offset, m_caseSensitivity);
 }
@@ -719,7 +714,7 @@ DynamicStringDetect::DynamicStringDetect(const HighlightingContextData::Rule::St
     m_dynamic = true;
 }
 
-MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures) const
+MatchResult DynamicStringDetect::doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &) const
 {
     /**
      * for dynamic case: create new pattern with right instantiation
@@ -736,7 +731,7 @@ WordDetect::WordDetect(DefinitionData &def, const HighlightingContextData::Rule:
     resolveAdditionalWordDelimiters(m_wordDelimiters, data.wordDelimiters);
 }
 
-MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &) const
+MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const
 {
     if (text.size() - offset < m_word.size()) {
         return offset;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h
index 7536d92e803..bc5f367ad67 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule_p.h
@@ -27,6 +27,7 @@ namespace KSyntaxHighlighting
 class WordDelimiters;
 class DefinitionData;
 class IncludeRules;
+class DynamicRegexpCache;
 
 class Rule
 {
@@ -83,7 +84,15 @@ public:
         return m_type == Type::LineContinue;
     }
 
-    virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const = 0;
+    // If true, then the rule uses the skipOffset parameter of MatchResult.
+    // This is used by AbstractHighlighter::highlightLine() to look for a rule
+    // in the skipOffsets cache only if it can be found there.
+    bool hasSkipOffset() const
+    {
+        return m_hasSkipOffset;
+    }
+
+    virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const = 0;
 
     static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName);
 
@@ -98,6 +107,7 @@ private:
         IncludeRules,
     };
 
+private:
     Format m_attributeFormat;
     ContextSwitch m_context;
     int m_column = -1;
@@ -108,6 +118,7 @@ private:
     bool m_lookAhead = false;
 
 protected:
+    bool m_hasSkipOffset = false;
     bool m_dynamic = false;
 };
 
@@ -117,10 +128,10 @@ public:
     AnyChar(const HighlightingContextData::Rule::AnyChar &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
-    QString m_chars;
+    WordDelimiters m_chars;
 };
 
 class DetectChar final : public Rule
@@ -129,7 +140,7 @@ public:
     DetectChar(const HighlightingContextData::Rule::DetectChar &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QChar m_char;
@@ -142,7 +153,7 @@ public:
     Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QChar m_char1;
@@ -152,13 +163,13 @@ private:
 class DetectIdentifier final : public Rule
 {
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 };
 
 class DetectSpaces final : public Rule
 {
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 };
 
 class Float final : public Rule
@@ -167,7 +178,7 @@ public:
     Float(DefinitionData &def, const HighlightingContextData::Rule::Float &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
@@ -189,7 +200,7 @@ public:
     }
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QString m_contextName;
@@ -202,7 +213,7 @@ public:
     Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
@@ -211,7 +222,7 @@ private:
 class HlCChar final : public Rule
 {
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 };
 
 class HlCHex final : public Rule
@@ -220,7 +231,7 @@ public:
     HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
@@ -232,7 +243,7 @@ public:
     HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
@@ -241,7 +252,7 @@ private:
 class HlCStringChar final : public Rule
 {
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 };
 
 class KeywordListRule final : public Rule
@@ -252,7 +263,7 @@ public:
     static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule::Keyword &data, QStringView lookupContextName);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
@@ -266,7 +277,7 @@ public:
     LineContinue(const HighlightingContextData::Rule::LineContinue &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QChar m_char;
@@ -278,7 +289,7 @@ public:
     RangeDetect(const HighlightingContextData::Rule::RangeDetect &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QChar m_begin;
@@ -291,7 +302,7 @@ public:
     RegExpr(const HighlightingContextData::Rule::RegExpr &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     void resolve();
@@ -305,7 +316,7 @@ public:
     DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     void resolve();
@@ -320,7 +331,7 @@ public:
     StringDetect(const HighlightingContextData::Rule::StringDetect &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QString m_string;
@@ -333,7 +344,7 @@ public:
     DynamicStringDetect(const HighlightingContextData::Rule::StringDetect &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     QString m_string;
@@ -346,7 +357,7 @@ public:
     WordDetect(DefinitionData &def, const HighlightingContextData::Rule::WordDetect &data);
 
 protected:
-    MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
+    MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
 
 private:
     WordDelimiters m_wordDelimiters;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
index fc44a6dbd4c..dca58b35b7c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state.cpp
@@ -1,4 +1,4 @@
-/*
+/*
     SPDX-FileCopyrightText: 2016 Volker Krause 
     SPDX-FileCopyrightText: 2018 Christoph Cullmann 
 
@@ -14,36 +14,23 @@
 
 using namespace KSyntaxHighlighting;
 
-StateData *StateData::get(State &state)
+StateData *StateData::reset(State &state)
 {
-    // create state data on demand, to make default state construction cheap
-    if (!state.d) {
-        state.d = new StateData();
-    } else {
-        state.d.detach();
-    }
+    auto *p = new StateData();
+    state.d.reset(p);
+    return p;
+}
+
+StateData *StateData::detach(State &state)
+{
+    state.d.detach();
     return state.d.data();
 }
 
-bool StateData::isEmpty() const
-{
-    return m_contextStack.isEmpty();
-}
-
-void StateData::clear()
-{
-    m_contextStack.clear();
-}
-
-int StateData::size() const
-{
-    return m_contextStack.size();
-}
-
-void StateData::push(Context *context, const QStringList &captures)
+void StateData::push(Context *context, QStringList &&captures)
 {
     Q_ASSERT(context);
-    m_contextStack.push_back(qMakePair(context, captures));
+    m_contextStack.push_back(StackValue{context, std::move(captures)});
 }
 
 bool StateData::pop(int popCount)
@@ -54,42 +41,23 @@ bool StateData::pop(int popCount)
     }
 
     // keep the initial context alive in any case
-    Q_ASSERT(!isEmpty());
-    const bool initialContextSurvived = m_contextStack.size() > popCount;
+    Q_ASSERT(!m_contextStack.empty());
+    const bool initialContextSurvived = int(m_contextStack.size()) > popCount;
     m_contextStack.resize(std::max(1, int(m_contextStack.size()) - popCount));
     return initialContextSurvived;
 }
 
-Context *StateData::topContext() const
-{
-    Q_ASSERT(!isEmpty());
-    return m_contextStack.last().first;
-}
+State::State() = default;
 
-const QStringList &StateData::topCaptures() const
-{
-    Q_ASSERT(!isEmpty());
-    return m_contextStack.last().second;
-}
+State::State(State &&other) noexcept = default;
 
-State::State()
-{
-}
+State::State(const State &other) noexcept = default;
 
-State::State(const State &other)
-    : d(other.d)
-{
-}
+State::~State() = default;
 
-State::~State()
-{
-}
+State &State::operator=(State &&other) noexcept = default;
 
-State &State::operator=(const State &other)
-{
-    d = other.d;
-    return *this;
-}
+State &State::operator=(const State &other) noexcept = default;
 
 bool State::operator==(const State &other) const
 {
@@ -104,8 +72,13 @@ bool State::operator!=(const State &other) const
 
 bool State::indentationBasedFoldingEnabled() const
 {
-    if (!d || d->m_contextStack.isEmpty()) {
+    if (!d || d->m_contextStack.empty()) {
         return false;
     }
-    return d->m_contextStack.last().first->indentationBasedFoldingEnabled();
+    return d->m_contextStack.back().context->indentationBasedFoldingEnabled();
+}
+
+std::size_t KSyntaxHighlighting::qHash(const State &state, std::size_t seed)
+{
+    return state.d ? qHashMulti(seed, *state.d) : 0;
 }
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state.h b/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
index 726ff32a884..3003a9b7cbf 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state.h
@@ -10,11 +10,15 @@
 #include "ksyntaxhighlighting_export.h"
 
 #include 
+#include 
 
 namespace KSyntaxHighlighting
 {
+class State;
 class StateData;
 
+KSYNTAXHIGHLIGHTING_EXPORT std::size_t qHash(const State &state, std::size_t seed = 0);
+
 /** Opaque handle to the state of the highlighting engine.
  *  This needs to be fed into AbstractHighlighter for every line of text
  *  and allows concrete highlighter implementations to store state per
@@ -29,9 +33,11 @@ public:
      *  in a document.
      */
     State();
-    State(const State &other);
+    State(State &&other) noexcept;
+    State(const State &other) noexcept;
     ~State();
-    State &operator=(const State &rhs);
+    State &operator=(State &&rhs) noexcept;
+    State &operator=(const State &rhs) noexcept;
 
     /** Compares two states for equality.
      *  For two equal states and identical text input, AbstractHighlighter
@@ -56,13 +62,13 @@ public:
 
 private:
     friend class StateData;
+    KSYNTAXHIGHLIGHTING_EXPORT friend std::size_t qHash(const State &, std::size_t);
     QExplicitlySharedDataPointer d;
 };
-
 }
 
 QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::State, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::State, Q_RELOCATABLE_TYPE);
 QT_END_NAMESPACE
 
 #endif // KSYNTAXHIGHLIGHTING_STATE_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
index 0248330304f..9971f7f6602 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/state_p.h
@@ -8,8 +8,10 @@
 #ifndef KSYNTAXHIGHLIGHTING_STATE_P_H
 #define KSYNTAXHIGHLIGHTING_STATE_P_H
 
+#include 
+
 #include 
-#include 
+#include 
 
 #include "definitionref_p.h"
 
@@ -21,15 +23,25 @@ class StateData : public QSharedData
 {
     friend class State;
     friend class AbstractHighlighter;
+    friend std::size_t qHash(const StateData &, std::size_t);
 
 public:
     StateData() = default;
-    static StateData *get(State &state);
 
-    bool isEmpty() const;
-    void clear();
-    int size() const;
-    void push(Context *context, const QStringList &captures);
+    static StateData *reset(State &state);
+    static StateData *detach(State &state);
+
+    static StateData *get(const State &state)
+    {
+        return state.d.data();
+    }
+
+    std::size_t size() const
+    {
+        return m_contextStack.size();
+    }
+
+    void push(Context *context, QStringList &&captures);
 
     /**
      * Pop the number of elements given from the top of the current stack.
@@ -39,8 +51,25 @@ public:
      */
     bool pop(int popCount);
 
-    Context *topContext() const;
-    const QStringList &topCaptures() const;
+    Context *topContext() const
+    {
+        return m_contextStack.back().context;
+    }
+
+    const QStringList &topCaptures() const
+    {
+        return m_contextStack.back().captures;
+    }
+
+    struct StackValue {
+        Context *context;
+        QStringList captures;
+
+        bool operator==(const StackValue &other) const
+        {
+            return context == other.context && captures == other.captures;
+        }
+    };
 
 private:
     /**
@@ -51,9 +80,18 @@ private:
     /**
      * the context stack combines the active context + valid captures
      */
-    QVector> m_contextStack;
+    std::vector m_contextStack;
 };
 
+inline std::size_t qHash(const StateData::StackValue &stackValue, std::size_t seed = 0)
+{
+    return qHashMulti(seed, stackValue.context, stackValue.captures);
+}
+
+inline std::size_t qHash(const StateData &k, std::size_t seed = 0)
+{
+    return qHashMulti(seed, k.m_defId, qHashRange(k.m_contextStack.begin(), k.m_contextStack.end(), seed));
+}
 }
 
 #endif
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
index 4754da22c61..70b26a79bf8 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
@@ -7,10 +7,13 @@
 #include "syntaxhighlighter.h"
 #include "abstracthighlighter_p.h"
 #include "definition.h"
+#include "definition_p.h"
 #include "foldingregion.h"
 #include "format.h"
+#include "format_p.h"
 #include "state.h"
 #include "theme.h"
+#include "themedata_p.h"
 
 Q_DECLARE_METATYPE(QTextBlock)
 
@@ -22,14 +25,26 @@ class TextBlockUserData : public QTextBlockUserData
 {
 public:
     State state;
-    QVector foldingRegions;
+    QList foldingRegions;
 };
 
 class SyntaxHighlighterPrivate : public AbstractHighlighterPrivate
 {
 public:
     static FoldingRegion foldingRegion(const QTextBlock &startBlock);
-    QVector foldingRegions;
+    void initTextFormat(QTextCharFormat &tf, const Format &format);
+    void computeTextFormats();
+
+    struct TextFormat {
+        QTextCharFormat tf;
+        /**
+         * id to check that the format belongs to the definition
+         */
+        std::intptr_t ptrId;
+    };
+
+    QList foldingRegions;
+    std::vector tfs;
 };
 
 }
@@ -48,6 +63,52 @@ FoldingRegion SyntaxHighlighterPrivate::foldingRegion(const QTextBlock &startBlo
     return FoldingRegion();
 }
 
+void SyntaxHighlighterPrivate::initTextFormat(QTextCharFormat &tf, const Format &format)
+{
+    // always set the foreground color to avoid palette issues
+    tf.setForeground(format.textColor(m_theme));
+
+    if (format.hasBackgroundColor(m_theme)) {
+        tf.setBackground(format.backgroundColor(m_theme));
+    }
+    if (format.isBold(m_theme)) {
+        tf.setFontWeight(QFont::Bold);
+    }
+    if (format.isItalic(m_theme)) {
+        tf.setFontItalic(true);
+    }
+    if (format.isUnderline(m_theme)) {
+        tf.setFontUnderline(true);
+    }
+    if (format.isStrikeThrough(m_theme)) {
+        tf.setFontStrikeOut(true);
+    }
+}
+
+void SyntaxHighlighterPrivate::computeTextFormats()
+{
+    auto definitions = m_definition.includedDefinitions();
+    definitions.append(m_definition);
+
+    int maxId = 0;
+    for (const auto &definition : std::as_const(definitions)) {
+        for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+            maxId = qMax(maxId, format.id());
+        }
+    }
+    tfs.clear();
+    tfs.resize(maxId + 1);
+
+    // initialize tfs
+    for (const auto &definition : std::as_const(definitions)) {
+        for (const auto &format : std::as_const(DefinitionData::get(definition)->formats)) {
+            auto &tf = tfs[format.id()];
+            tf.ptrId = FormatPrivate::ptrId(format);
+            initTextFormat(tf.tf, format);
+        }
+    }
+}
+
 SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
     : QSyntaxHighlighter(parent)
     , AbstractHighlighter(new SyntaxHighlighterPrivate)
@@ -68,13 +129,27 @@ SyntaxHighlighter::~SyntaxHighlighter()
 
 void SyntaxHighlighter::setDefinition(const Definition &def)
 {
-    const auto needsRehighlight = definition() != def;
-    AbstractHighlighter::setDefinition(def);
+    Q_D(SyntaxHighlighter);
+
+    const auto needsRehighlight = d->m_definition != def;
+    if (DefinitionData::get(d->m_definition) != DefinitionData::get(def)) {
+        d->m_definition = def;
+        d->tfs.clear();
+    }
     if (needsRehighlight) {
         rehighlight();
     }
 }
 
+void SyntaxHighlighter::setTheme(const Theme &theme)
+{
+    Q_D(SyntaxHighlighter);
+    if (ThemeData::get(d->m_theme) != ThemeData::get(theme)) {
+        d->m_theme = theme;
+        d->tfs.clear();
+    }
+}
+
 bool SyntaxHighlighter::startsFoldingRegion(const QTextBlock &startBlock) const
 {
     return SyntaxHighlighterPrivate::foldingRegion(startBlock).type() == FoldingRegion::Begin;
@@ -92,13 +167,13 @@ QTextBlock SyntaxHighlighter::findFoldingRegionEnd(const QTextBlock &startBlock)
         if (!data) {
             continue;
         }
-        for (auto it = data->foldingRegions.constBegin(); it != data->foldingRegions.constEnd(); ++it) {
-            if ((*it).id() != region.id()) {
+        for (const auto &foldingRegion : std::as_const(data->foldingRegions)) {
+            if (foldingRegion.id() != region.id()) {
                 continue;
             }
-            if ((*it).type() == FoldingRegion::End) {
+            if (foldingRegion.type() == FoldingRegion::End) {
                 --depth;
-            } else if ((*it).type() == FoldingRegion::Begin) {
+            } else if (foldingRegion.type() == FoldingRegion::Begin) {
                 ++depth;
             }
             if (depth == 0) {
@@ -114,30 +189,31 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
 {
     Q_D(SyntaxHighlighter);
 
-    State state;
+    static const State emptyState;
+    const State *previousState = &emptyState;
     if (currentBlock().position() > 0) {
         const auto prevBlock = currentBlock().previous();
         const auto prevData = dynamic_cast(prevBlock.userData());
         if (prevData) {
-            state = prevData->state;
+            previousState = &prevData->state;
         }
     }
     d->foldingRegions.clear();
-    state = highlightLine(text, state);
+    auto newState = highlightLine(text, *previousState);
 
     auto data = dynamic_cast(currentBlockUserData());
     if (!data) { // first time we highlight this
         data = new TextBlockUserData;
-        data->state = state;
+        data->state = std::move(newState);
         data->foldingRegions = d->foldingRegions;
         setCurrentBlockUserData(data);
         return;
     }
 
-    if (data->state == state && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here
+    if (data->state == newState && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here
         return;
     }
-    data->state = state;
+    data->state = std::move(newState);
     data->foldingRegions = d->foldingRegions;
 
     const auto nextBlock = currentBlock().next();
@@ -146,40 +222,35 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
     }
 }
 
-void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format)
+void SyntaxHighlighter::applyFormat(int offset, int length, const Format &format)
 {
     if (length == 0) {
         return;
     }
 
-    QTextCharFormat tf;
-    // always set the foreground color to avoid palette issues
-    tf.setForeground(format.textColor(theme()));
+    Q_D(SyntaxHighlighter);
 
-    if (format.hasBackgroundColor(theme())) {
-        tf.setBackground(format.backgroundColor(theme()));
-    }
-    if (format.isBold(theme())) {
-        tf.setFontWeight(QFont::Bold);
-    }
-    if (format.isItalic(theme())) {
-        tf.setFontItalic(true);
-    }
-    if (format.isUnderline(theme())) {
-        tf.setFontUnderline(true);
-    }
-    if (format.isStrikeThrough(theme())) {
-        tf.setFontStrikeOut(true);
+    if (Q_UNLIKELY(d->tfs.empty())) {
+        d->computeTextFormats();
     }
 
-    QSyntaxHighlighter::setFormat(offset, length, tf);
+    const auto id = static_cast(format.id());
+    // This doesn't happen when format comes from the definition.
+    // But as the user can override the function to pass any format, this is a possible scenario.
+    if (id < d->tfs.size() && d->tfs[id].ptrId == FormatPrivate::ptrId(format)) {
+        QSyntaxHighlighter::setFormat(offset, length, d->tfs[id].tf);
+    } else {
+        QTextCharFormat tf;
+        d->initTextFormat(tf, format);
+        QSyntaxHighlighter::setFormat(offset, length, tf);
+    }
 }
 
 void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion region)
 {
     Q_UNUSED(offset);
     Q_UNUSED(length);
-    [[maybe_unused]] Q_D(SyntaxHighlighter);
+    Q_D(SyntaxHighlighter);
 
     if (region.type() == FoldingRegion::Begin) {
         d->foldingRegions.push_back(region);
@@ -196,3 +267,5 @@ void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion regio
         d->foldingRegions.push_back(region);
     }
 }
+
+#include "moc_syntaxhighlighter.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
index a57455d9baa..c19cb798dd1 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.h
@@ -32,6 +32,7 @@ public:
     ~SyntaxHighlighter() override;
 
     void setDefinition(const Definition &def) override;
+    void setTheme(const Theme &theme) override;
 
     /** Returns whether there is a folding region beginning at @p startBlock.
      *  This only considers syntax-based folding regions,
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
index b23852f337a..c54bb38b180 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.cpp
@@ -103,3 +103,5 @@ QRgb Theme::editorColor(EditorColorRole role) const
 {
     return m_data->editorColor(role);
 }
+
+#include "moc_theme.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
index 37f9de1694b..c3fb0e6b6e6 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/theme.h
@@ -67,11 +67,6 @@ class KSYNTAXHIGHLIGHTING_EXPORT Theme
     Q_PROPERTY(QString name READ name)
     Q_PROPERTY(QString translatedName READ translatedName)
 public:
-    // TODO KF6:
-    // - make TextStyle an enum class
-    // - move out of Theme into KSyntaxHighlighting
-    // - do the same for EditorColorRole
-
     /**
      * Default styles that can be referenced from syntax definition XML files.
      * Make sure to choose readable colors with good contrast especially in
@@ -342,7 +337,7 @@ private:
     /**
      * Constructor taking a shared ThemeData instance.
      */
-    explicit Theme(ThemeData *data);
+    KSYNTAXHIGHLIGHTING_NO_EXPORT explicit Theme(ThemeData *data);
     friend class RepositoryPrivate;
     friend class ThemeData;
 
@@ -356,7 +351,7 @@ private:
 }
 
 QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Theme, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Theme, Q_RELOCATABLE_TYPE);
 QT_END_NAMESPACE
 
 #endif // KSYNTAXHIGHLIGHTING_THEME_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
index 4f77dcc494f..9d42d03db03 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata.cpp
@@ -18,11 +18,6 @@
 
 using namespace KSyntaxHighlighting;
 
-ThemeData *ThemeData::get(const Theme &theme)
-{
-    return theme.m_data.data();
-}
-
 ThemeData::ThemeData()
 {
     memset(m_editorColors, 0, sizeof(m_editorColors));
@@ -87,9 +82,18 @@ bool ThemeData::load(const QString &filePath)
         return false;
     }
     const QByteArray jsonData = loadFile.readAll();
+    // look for metadata object
+    int metaDataStart = jsonData.indexOf("\"metadata\"");
+    int start = jsonData.indexOf('{', metaDataStart);
+    int end = jsonData.indexOf("}", metaDataStart);
+    if (start < 0 || end < 0) {
+        qCWarning(Log) << "Failed to parse theme file" << filePath << ":"
+                       << "no metadata object found";
+        return false;
+    }
 
     QJsonParseError parseError;
-    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData.mid(start, (end + 1) - start), &parseError);
     if (parseError.error != QJsonParseError::NoError) {
         qCWarning(Log) << "Failed to parse theme file" << filePath << ":" << parseError.errorString();
         return false;
@@ -97,13 +101,34 @@ bool ThemeData::load(const QString &filePath)
 
     m_filePath = filePath;
 
-    QJsonObject obj = jsonDoc.object();
-
     // read metadata
-    const QJsonObject metadata = obj.value(QLatin1String("metadata")).toObject();
+    QJsonObject metadata = jsonDoc.object();
     m_name = metadata.value(QLatin1String("name")).toString();
     m_revision = metadata.value(QLatin1String("revision")).toInt();
+    return true;
+}
 
+void ThemeData::loadComplete()
+{
+    if (m_completelyLoaded) {
+        return;
+    }
+    m_completelyLoaded = true;
+
+    QFile loadFile(m_filePath);
+    if (!loadFile.open(QIODevice::ReadOnly)) {
+        return;
+    }
+    const QByteArray jsonData = loadFile.readAll();
+
+    QJsonParseError parseError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+    if (parseError.error != QJsonParseError::NoError) {
+        qCWarning(Log) << "Failed to parse theme file" << m_filePath << ":" << parseError.errorString();
+        return;
+    }
+
+    QJsonObject obj = jsonDoc.object();
     // read text styles
     const auto metaEnumStyle = QMetaEnum::fromType();
     const QJsonObject textStyles = obj.value(QLatin1String("text-styles")).toObject();
@@ -162,7 +187,7 @@ bool ThemeData::load(const QString &filePath)
         }
     }
 
-    return true;
+    return;
 }
 
 QString ThemeData::name() const
@@ -187,6 +212,9 @@ QString ThemeData::filePath() const
 
 TextStyleData ThemeData::textStyle(Theme::TextStyle style) const
 {
+    if (!m_completelyLoaded) {
+        const_cast(this)->loadComplete();
+    }
     return m_textStyles[style];
 }
 
@@ -232,12 +260,18 @@ bool ThemeData::isStrikeThrough(Theme::TextStyle style) const
 
 QRgb ThemeData::editorColor(Theme::EditorColorRole role) const
 {
+    if (!m_completelyLoaded) {
+        const_cast(this)->loadComplete();
+    }
     Q_ASSERT(static_cast(role) >= 0 && static_cast(role) <= static_cast(Theme::TemplateReadOnlyPlaceholder));
     return m_editorColors[role];
 }
 
 TextStyleData ThemeData::textStyleOverride(const QString &definitionName, const QString &attributeName) const
 {
+    if (!m_completelyLoaded) {
+        const_cast(this)->loadComplete();
+    }
     auto it = m_textStyleOverrides.find(definitionName);
     if (it != m_textStyleOverrides.end()) {
         return it->value(attributeName);
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
index 4ce87f0aaf9..6ee772f172c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/themedata_p.h
@@ -24,7 +24,10 @@ namespace KSyntaxHighlighting
 class ThemeData : public QSharedData
 {
 public:
-    static ThemeData *get(const Theme &theme);
+    static ThemeData *get(const Theme &theme)
+    {
+        return theme.m_data.data();
+    }
 
     /**
      * Default constructor, creating an uninitialized ThemeData instance.
@@ -37,6 +40,8 @@ public:
      */
     bool load(const QString &filePath);
 
+    void loadComplete();
+
     /**
      * Returns the unique name of this Theme.
      */
@@ -140,6 +145,8 @@ private:
     //! on disk (in a read-only or a writeable location).
     QString m_filePath;
 
+    bool m_completelyLoaded = false;
+
     //! TextStyles
     std::vector m_textStyles;
 
@@ -154,7 +161,7 @@ private:
 }
 
 QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(KSyntaxHighlighting::TextStyleData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KSyntaxHighlighting::TextStyleData, Q_RELOCATABLE_TYPE);
 QT_END_NAMESPACE
 
 #endif // KSYNTAXHIGHLIGHTING_THEMEDATA_P_H
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
index c5401a57cc9..ce55cd4b293 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters.cpp
@@ -16,6 +16,12 @@ WordDelimiters::WordDelimiters()
     }
 }
 
+WordDelimiters::WordDelimiters(QStringView str)
+    : asciiDelimiters{}
+{
+    append(str);
+}
+
 bool WordDelimiters::contains(QChar c) const
 {
     if (c.unicode() < 128) {
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h
index ccad679a4ef..c23670d6344 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/worddelimiters_p.h
@@ -26,6 +26,11 @@ class WordDelimiters
 public:
     WordDelimiters();
 
+    /**
+     * Initialize with a default delimiters.
+     */
+    explicit WordDelimiters(QStringView str);
+
     /**
      * Returns @c true if @p c is a word delimiter; otherwise returns @c false.
      */
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
index 9277c2aee7d..1fb92ad2201 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/CMakeLists.txt
@@ -7,11 +7,10 @@ ecm_add_qml_module(kquicksyntaxhighlightingplugin URI "org.kde.syntaxhighlightin
 target_sources(kquicksyntaxhighlightingplugin PRIVATE
     kquicksyntaxhighlightingplugin.cpp
     kquicksyntaxhighlighter.cpp
-    repositorywrapper.cpp
 )
 target_link_libraries(kquicksyntaxhighlightingplugin PRIVATE
-    KF5SyntaxHighlighting
-    Qt${QT_MAJOR_VERSION}::Quick
+    KF6SyntaxHighlighting
+    Qt6::Quick
 )
 
 ecm_finalize_qml_module(kquicksyntaxhighlightingplugin DESTINATION ${KDE_INSTALL_QMLDIR})
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
index eb795b1468e..19cfbacf58c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.cpp
@@ -49,7 +49,7 @@ QVariant KQuickSyntaxHighlighter::definition() const
 void KQuickSyntaxHighlighter::setDefinition(const QVariant &definition)
 {
     Definition def;
-    if (definition.type() == QVariant::String) {
+    if (definition.userType() == QMetaType::QString) {
         def = unwrappedRepository()->definitionForName(definition.toString());
     } else {
         def = definition.value();
@@ -73,9 +73,9 @@ QVariant KQuickSyntaxHighlighter::theme() const
 void KQuickSyntaxHighlighter::setTheme(const QVariant &theme)
 {
     Theme t;
-    if (theme.type() == QVariant::String) {
+    if (theme.userType() == QMetaType::QString) {
         t = unwrappedRepository()->theme(theme.toString());
-    } else if (theme.type() == QVariant::Int) {
+    } else if (theme.userType() == QMetaType::Int) {
         t = unwrappedRepository()->defaultTheme(static_cast(theme.toInt()));
     } else {
         t = theme.value();
@@ -89,12 +89,12 @@ void KQuickSyntaxHighlighter::setTheme(const QVariant &theme)
     }
 }
 
-RepositoryWrapper *KQuickSyntaxHighlighter::repository() const
+Repository *KQuickSyntaxHighlighter::repository() const
 {
     return m_repository;
 }
 
-void KQuickSyntaxHighlighter::setRepository(RepositoryWrapper *repository)
+void KQuickSyntaxHighlighter::setRepository(Repository *repository)
 {
     if (m_repository == repository) {
         return;
@@ -106,7 +106,9 @@ void KQuickSyntaxHighlighter::setRepository(RepositoryWrapper *repository)
 Repository *KQuickSyntaxHighlighter::unwrappedRepository() const
 {
     if (m_repository) {
-        return m_repository->m_repository;
+        return m_repository;
     }
     return defaultRepository();
 }
+
+#include "moc_kquicksyntaxhighlighter.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
index 211f80d37f5..b45c26339f2 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlighter.h
@@ -8,8 +8,6 @@
 #ifndef KQUICKSYNTAXHIGHLIGHTER_H
 #define KQUICKSYNTAXHIGHLIGHTER_H
 
-#include "repositorywrapper.h"
-
 #include 
 #include 
 
@@ -29,7 +27,7 @@ class KQuickSyntaxHighlighter : public QObject
     Q_PROPERTY(QObject *textEdit READ textEdit WRITE setTextEdit NOTIFY textEditChanged)
     Q_PROPERTY(QVariant definition READ definition WRITE setDefinition NOTIFY definitionChanged)
     Q_PROPERTY(QVariant theme READ theme WRITE setTheme NOTIFY themeChanged)
-    Q_PROPERTY(RepositoryWrapper *repository READ repository WRITE setRepository NOTIFY repositoryChanged)
+    Q_PROPERTY(KSyntaxHighlighting::Repository *repository READ repository WRITE setRepository NOTIFY repositoryChanged)
 
 public:
     explicit KQuickSyntaxHighlighter(QObject *parent = nullptr);
@@ -44,8 +42,8 @@ public:
     QVariant theme() const;
     void setTheme(const QVariant &theme);
 
-    RepositoryWrapper *repository() const;
-    void setRepository(RepositoryWrapper *repository);
+    KSyntaxHighlighting::Repository *repository() const;
+    void setRepository(KSyntaxHighlighting::Repository *repository);
 
 Q_SIGNALS:
     void textEditChanged() const;
@@ -59,7 +57,7 @@ private:
     QObject *m_textEdit;
     KSyntaxHighlighting::Definition m_definition;
     KSyntaxHighlighting::Theme m_theme;
-    RepositoryWrapper *m_repository = nullptr;
+    KSyntaxHighlighting::Repository *m_repository = nullptr;
     KSyntaxHighlighting::SyntaxHighlighter *m_highlighter = nullptr;
 };
 
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
index 9aeb503ec5d..5eb06862df8 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/quick/kquicksyntaxhighlightingplugin.cpp
@@ -7,7 +7,6 @@
 
 #include "kquicksyntaxhighlightingplugin.h"
 #include "kquicksyntaxhighlighter.h"
-#include "repositorywrapper.h"
 
 #include 
 #include 
@@ -30,17 +29,18 @@ void KQuickSyntaxHighlightingPlugin::registerTypes(const char *uri)
 {
     Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.syntaxhighlighting"));
     qRegisterMetaType();
-    qRegisterMetaType>();
+    qRegisterMetaType>();
     qRegisterMetaType();
-    qRegisterMetaType>();
+    qRegisterMetaType>();
     qmlRegisterType(uri, 1, 0, "SyntaxHighlighter");
-    qmlRegisterUncreatableType(uri, 1, 0, "Definition", {});
-    qmlRegisterUncreatableType(uri, 1, 0, "Theme", {});
-    qmlRegisterSingletonType(uri, 1, 0, "Repository", [](auto engine, auto scriptEngine) {
+    qmlRegisterUncreatableMetaObject(Definition::staticMetaObject, uri, 1, 0, "Definition", {});
+    qmlRegisterUncreatableMetaObject(Theme::staticMetaObject, uri, 1, 0, "Theme", {});
+    qmlRegisterSingletonType(uri, 1, 0, "Repository", [](auto engine, auto scriptEngine) {
         (void)engine;
-        (void)scriptEngine;
-        auto repo = new RepositoryWrapper;
-        repo->m_repository = defaultRepository();
-        return repo;
+        auto repo = defaultRepository();
+        scriptEngine->setObjectOwnership(repo, QJSEngine::CppOwnership);
+        return defaultRepository();
     });
 }
+
+#include "moc_kquicksyntaxhighlightingplugin.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
deleted file mode 100644
index 733c799ed13..00000000000
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-    SPDX-FileCopyrightText: 2021 Volker Krause 
-
-    SPDX-License-Identifier: MIT
-*/
-
-#include "repositorywrapper.h"
-
-#include 
-#include 
-#include 
-
-using namespace KSyntaxHighlighting;
-
-RepositoryWrapper::RepositoryWrapper(QObject *parent)
-    : QObject(parent)
-{
-}
-
-Definition RepositoryWrapper::definitionForName(const QString &defName) const
-{
-    return m_repository->definitionForName(defName);
-}
-
-Definition RepositoryWrapper::definitionForFileName(const QString &fileName) const
-{
-    return m_repository->definitionForFileName(fileName);
-}
-
-QVector RepositoryWrapper::definitionsForFileName(const QString &fileName) const
-{
-    return m_repository->definitionsForFileName(fileName);
-}
-
-Definition RepositoryWrapper::definitionForMimeType(const QString &mimeType) const
-{
-    return m_repository->definitionForMimeType(mimeType);
-}
-
-QVector RepositoryWrapper::definitionsForMimeType(const QString &mimeType) const
-{
-    return m_repository->definitionsForMimeType(mimeType);
-}
-
-QVector RepositoryWrapper::definitions() const
-{
-    return m_repository->definitions();
-}
-
-QVector RepositoryWrapper::themes() const
-{
-    return m_repository->themes();
-}
-
-Theme RepositoryWrapper::theme(const QString &themeName) const
-{
-    return m_repository->theme(themeName);
-}
-
-Theme RepositoryWrapper::defaultTheme(DefaultTheme t) const
-{
-    return m_repository->defaultTheme(static_cast(t));
-}
-
-#include "moc_repositorywrapper.cpp"
diff --git a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h b/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
deleted file mode 100644
index d4fb8d251cc..00000000000
--- a/src/libs/3rdparty/syntax-highlighting/src/quick/repositorywrapper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-    SPDX-FileCopyrightText: 2021 Volker Krause 
-
-    SPDX-License-Identifier: MIT
-*/
-
-#ifndef REPOSITORYWRAPPER_H
-#define REPOSITORYWRAPPER_H
-
-#include 
-
-namespace KSyntaxHighlighting
-{
-class Definition;
-class Repository;
-class Theme;
-}
-
-// TODO KF6: merge this into KSyntaxHighlighting::Repository
-class RepositoryWrapper : public QObject
-{
-    Q_OBJECT
-    // TODO KF6: NOTIFY on reload
-    Q_PROPERTY(QVector definitions READ definitions CONSTANT)
-    Q_PROPERTY(QVector themes READ themes CONSTANT)
-public:
-    explicit RepositoryWrapper(QObject *parent = nullptr);
-
-    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const;
-    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const;
-    Q_INVOKABLE QVector definitionsForFileName(const QString &fileName) const;
-    Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const;
-    Q_INVOKABLE QVector definitionsForMimeType(const QString &mimeType) const;
-    QVector definitions() const;
-
-    QVector themes() const;
-    Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const;
-    enum DefaultTheme { LightTheme, DarkTheme };
-    Q_ENUM(DefaultTheme)
-    Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t = LightTheme) const;
-
-    KSyntaxHighlighting::Repository *m_repository = nullptr;
-};
-
-#endif // REPOSITORYWRAPPER_H
diff --git a/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs b/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
index 2df844c71cd..b0495897677 100644
--- a/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
+++ b/src/libs/3rdparty/syntax-highlighting/syntax-highlighting.qbs
@@ -25,7 +25,7 @@ Project {
         name: "KSyntaxHighlighting_bundled"
         condition: !qtc.preferSystemSyntaxHighlighting || !Qt.KSyntaxHighlighting.present
 
-        cpp.defines: base.concat("KF5SyntaxHighlighting_EXPORTS")
+        cpp.defines: base.concat("KF6SyntaxHighlighting_EXPORTS")
         cpp.includePaths: [
             product.sourceDirectory + "/src/lib/",
             product.sourceDirectory + "/autogenerated/include/",
@@ -58,6 +58,7 @@ Project {
                 "definitiondownloader.cpp",
                 "definitiondownloader.h",
                 "definitionref_p.h",
+                "dynamicregexpcache_p.h",
                 "foldingregion.cpp",
                 "foldingregion.h",
                 "format.cpp",
diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs
index ffc3017cba0..a6426d4ae47 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/nanotrace.cpp b/src/libs/nanotrace/nanotrace.cpp
index c5adeb4d724..8a96b125845 100644
--- a/src/libs/nanotrace/nanotrace.cpp
+++ b/src/libs/nanotrace/nanotrace.cpp
@@ -1,5 +1,5 @@
 // Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 
 #include "nanotrace.h"
diff --git a/src/libs/nanotrace/nanotrace.h b/src/libs/nanotrace/nanotrace.h
index ed17797e344..76b0120ae1a 100644
--- a/src/libs/nanotrace/nanotrace.h
+++ b/src/libs/nanotrace/nanotrace.h
@@ -1,5 +1,5 @@
 // Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 #pragma once
 
diff --git a/src/libs/nanotrace/nanotraceglobals.h b/src/libs/nanotrace/nanotraceglobals.h
index 40a55131bc2..145b8ad003e 100644
--- a/src/libs/nanotrace/nanotraceglobals.h
+++ b/src/libs/nanotrace/nanotraceglobals.h
@@ -1,5 +1,5 @@
 // Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 #pragma once
 
diff --git a/src/libs/nanotrace/nanotracehr.cpp b/src/libs/nanotrace/nanotracehr.cpp
index b2295202209..07d2ff95ac1 100644
--- a/src/libs/nanotrace/nanotracehr.cpp
+++ b/src/libs/nanotrace/nanotracehr.cpp
@@ -1,5 +1,5 @@
 // Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 #include "nanotracehr.h"
 
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h
index 1e1a8dd23f1..7856ea3582f 100644
--- a/src/libs/nanotrace/nanotracehr.h
+++ b/src/libs/nanotrace/nanotracehr.h
@@ -1,5 +1,5 @@
 // Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 #pragma once
 
diff --git a/src/libs/nanotrace/python/figures.py b/src/libs/nanotrace/python/figures.py
index cb806ea40d6..7f92a3b57ee 100644
--- a/src/libs/nanotrace/python/figures.py
+++ b/src/libs/nanotrace/python/figures.py
@@ -1,5 +1,5 @@
 # Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 import pandas as pd
 import plotly.graph_objects as go
 import plotly.subplots as sp
diff --git a/src/libs/nanotrace/python/nanotrace.py b/src/libs/nanotrace/python/nanotrace.py
index 880f17d7bfc..a173c3c52b7 100644
--- a/src/libs/nanotrace/python/nanotrace.py
+++ b/src/libs/nanotrace/python/nanotrace.py
@@ -1,5 +1,5 @@
 # Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 import reader as rd
 import figures as fgs
 
diff --git a/src/libs/nanotrace/python/reader.py b/src/libs/nanotrace/python/reader.py
index 023bddb15f7..ed6b8b5b1e1 100644
--- a/src/libs/nanotrace/python/reader.py
+++ b/src/libs/nanotrace/python/reader.py
@@ -1,5 +1,5 @@
 # Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 import os
 import io
 import json
diff --git a/src/libs/qlitehtml b/src/libs/qlitehtml
index b8f6617f22a..7e8eb0f5eae 160000
--- a/src/libs/qlitehtml
+++ b/src/libs/qlitehtml
@@ -1 +1 @@
-Subproject commit b8f6617f22a7bd0bf3da2e75d1613e1346b974f0
+Subproject commit 7e8eb0f5eaee53b0aeb04208bdaba74fcffc3a3f
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index aac0de9ab1e..a525c6c3054 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 c57cba7e46e..ae3d8e0e6c4 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/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index d2407bb1137..36f2cd802db 100644
--- a/src/libs/qmljs/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -427,6 +427,10 @@ QFuture PluginDumper::loadDependencies(const FileP
 
     Utils::onFinished(loadQmlTypeDescription(dependenciesPaths), const_cast(this),
             [this, iface, visited](const QFuture &typesFuture) {
+        if (typesFuture.resultCount() == 0 || typesFuture.isCanceled()) {
+            iface->reportCanceled();
+            return;
+        }
         PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
         FilePaths newDependencies = FileUtils::toFilePathList(typesResult.dependencies);
 
@@ -565,6 +569,9 @@ void PluginDumper::loadQmltypesFile(const FilePaths &qmltypesFilePaths,
     Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this,
             [this, qmltypesFilePaths, libraryPath, libraryInfo]
             (const QFuture &typesFuture) {
+        if (typesFuture.isCanceled() || typesFuture.resultCount() == 0)
+            return;
+
         PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
         if (!typesResult.dependencies.isEmpty())
         {
@@ -572,6 +579,9 @@ void PluginDumper::loadQmltypesFile(const FilePaths &qmltypesFilePaths,
                                                QSharedPointer>()), this,
                               [typesResult, libraryInfo, libraryPath, this] (const QFuture &loadFuture)
             {
+                if (loadFuture.isCanceled() || loadFuture.resultCount() == 0)
+                    return;
+
                 PluginDumper::DependencyInfo loadResult = loadFuture.result();
                 QStringList errors = typesResult.errors;
                 QStringList warnings = typesResult.errors;
diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt
index 97307164f65..4359d79d546 100644
--- a/src/libs/qtcreatorcdbext/CMakeLists.txt
+++ b/src/libs/qtcreatorcdbext/CMakeLists.txt
@@ -205,7 +205,7 @@ if (_library_enabled)
   # Deploy lldb.exe and its Python dependency
   find_package(Clang QUIET)
   if (LLVM_TOOLS_BINARY_DIR AND LLVM_LIBRARY_DIRS)
-    foreach(lldb_file lldb.exe lldb-vscode.exe liblldb.dll python311.zip python311.dll)
+    foreach(lldb_file lldb.exe lldb-dap.exe liblldb.dll python311.zip python311.dll)
       if (EXISTS ${LLVM_TOOLS_BINARY_DIR}/${lldb_file})
         install(FILES ${LLVM_TOOLS_BINARY_DIR}/${lldb_file}
                 DESTINATION bin/clang/bin
diff --git a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp
index bf3c379272d..68b9eb334c9 100644
--- a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp
+++ b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp
@@ -101,6 +101,9 @@ static PyObject *cdbext_resolveSymbol(PyObject *, PyObject *args) // -> Value
     if (!PyArg_ParseTuple(args, "s", &pattern))
         Py_RETURN_NONE;
 
+    if (debugPyCdbextModule)
+        DebugPrint() << "resolve symbol: " << pattern;
+
     CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
     auto rc = PyList_New(0);
 
@@ -132,6 +135,9 @@ static PyObject *cdbext_getNameByAddress(PyObject *, PyObject *args)
     if (!PyArg_ParseTuple(args, "K", &address))
         Py_RETURN_NONE;
 
+    if (debugPyCdbextModule)
+        DebugPrint() << "name by address: " << address;
+
     CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
 
     PyObject* ret = NULL;
@@ -153,6 +159,9 @@ static PyObject *cdbext_getAddressByName(PyObject *, PyObject *args)
     if (!PyArg_ParseTuple(args, "s", &name))
         Py_RETURN_NONE;
 
+    if (debugPyCdbextModule)
+        DebugPrint() << "address by name: " << name;
+
     CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
 
     ULONG64 address = 0;
@@ -177,6 +186,14 @@ static PyObject *cdbext_listOfLocals(PyObject *, PyObject *args) // -> [ Value ]
         Py_RETURN_NONE;
 
     const std::string partialVariable(partialVariablesC);
+
+    if (debugPyCdbextModule) {
+        if (partialVariable.empty())
+            DebugPrint() << "list of locals";
+        else
+            DebugPrint() << "list of locals with partial variable: " << partialVariable;
+    }
+
     IDebugSymbolGroup2 *symbolGroup = nullptr;
     auto locals = PyList_New(0);
     if (partialVariable.empty()) {
diff --git a/src/libs/qtcreatorcdbext/pytype.cpp b/src/libs/qtcreatorcdbext/pytype.cpp
index 0621793b7e0..9345c1d91af 100644
--- a/src/libs/qtcreatorcdbext/pytype.cpp
+++ b/src/libs/qtcreatorcdbext/pytype.cpp
@@ -121,6 +121,9 @@ static std::string stripPointerType(const std::string &typeNameIn)
     std::string typeName = typeNameIn;
     if (typeName.back() == '*') {
         typeName.pop_back();
+        trimBack(typeName);
+        if (endsWith(typeName, "const"))
+            typeName = typeName.erase(typeName.size() - 5, 5);
     } else {
         const auto arrayPosition = typeName.find_first_of('[');
         if (arrayPosition != std::string::npos
@@ -296,35 +299,19 @@ int PyType::code() const
         return std::nullopt;
     };
 
-    if (!resolve())
-        return parseTypeName(name()).value_or(TypeCodeUnresolvable);
-
-    if (m_tag < 0) {
-        if (const std::optional typeCode = parseTypeName(name()))
-            return *typeCode;
-
-        IDebugSymbolGroup2 *sg = 0;
-        if (FAILED(ExtensionCommandContext::instance()->symbols()->CreateSymbolGroup2(&sg)))
-            return TypeCodeStruct;
-
-        const std::string helperValueName = SymbolGroupValue::pointedToSymbolName(0, name(true));
-        ULONG index = DEBUG_ANY_ID;
-        if (SUCCEEDED(sg->AddSymbol(helperValueName.c_str(), &index)))
-            m_tag = PyValue(index, sg).tag();
-        sg->Release();
+    if (m_tag >= 0) {
+        switch (m_tag) {
+        case SymTagUDT: return TypeCodeStruct;
+        case SymTagEnum: return TypeCodeEnum;
+        case SymTagTypedef: return TypeCodeTypedef;
+        case SymTagFunctionType: return TypeCodeFunction;
+        case SymTagPointerType: return TypeCodePointer;
+        case SymTagArrayType: return TypeCodeArray;
+        case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat;
+        default: break;
+        }
     }
-    switch (m_tag) {
-    case SymTagUDT: return TypeCodeStruct;
-    case SymTagEnum: return TypeCodeEnum;
-    case SymTagTypedef: return TypeCodeTypedef;
-    case SymTagFunctionType: return TypeCodeFunction;
-    case SymTagPointerType: return TypeCodePointer;
-    case SymTagArrayType: return TypeCodeArray;
-    case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat;
-    default: break;
-    }
-
-    return TypeCodeStruct;
+    return parseTypeName(name()).value_or(TypeCodeStruct);
 }
 
 PyType PyType::target() const
@@ -533,6 +520,7 @@ PY_FUNC_RET_OBJECT_LIST(fields, PY_OBJ_NAME)
 PY_FUNC_RET_STD_STRING(module, PY_OBJ_NAME)
 PY_FUNC(moduleId, PY_OBJ_NAME, "K")
 PY_FUNC(arrayElements, PY_OBJ_NAME, "k")
+PY_FUNC_RET_BOOL(resolved, PY_OBJ_NAME)
 PY_FUNC_DECL(templateArguments, PY_OBJ_NAME)
 {
     PY_IMPL_GUARD;
@@ -568,6 +556,8 @@ static PyMethodDef typeMethods[] = {
      "Returns the number of elements in an array or 0 for non array types"},
     {"templateArguments",   PyCFunction(templateArguments),     METH_NOARGS,
      "Returns all template arguments."},
+    {"resolved",            PyCFunction(resolved),              METH_NOARGS,
+     "Returns whether the type is resolved"},
 
     {NULL}  /* Sentinel */
 };
diff --git a/src/libs/qtcreatorcdbext/pytype.h b/src/libs/qtcreatorcdbext/pytype.h
index 8b05fffe0ad..b71eae1ab02 100644
--- a/src/libs/qtcreatorcdbext/pytype.h
+++ b/src/libs/qtcreatorcdbext/pytype.h
@@ -29,6 +29,7 @@ public:
     std::string module() const;
     ULONG64 moduleId() const;
     int arrayElements() const;
+    bool resolved() const { return m_resolved.value_or(false); }
 
     struct TemplateArgument
     {
diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp
index 67a6f36817d..c6e87d27746 100644
--- a/src/libs/solutions/tasking/tasktree.cpp
+++ b/src/libs/solutions/tasking/tasktree.cpp
@@ -7,10 +7,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 using namespace std::chrono;
@@ -1178,6 +1180,8 @@ GroupItem workflowPolicy(WorkflowPolicy policy)
     return Group::workflowPolicy(policy);
 }
 
+const GroupItem nullItem = GroupItem({});
+
 const GroupItem sequential = parallelLimit(1);
 const GroupItem parallel = parallelLimit(0);
 
@@ -1189,6 +1193,17 @@ const GroupItem stopOnSuccessOrError = workflowPolicy(WorkflowPolicy::StopOnSucc
 const GroupItem finishAllAndSuccess = workflowPolicy(WorkflowPolicy::FinishAllAndSuccess);
 const GroupItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError);
 
+// Please note the thread_local keyword below guarantees a separate instance per thread.
+// The s_activeTaskTrees is currently used internally only and is not exposed in the public API.
+// It serves for withLog() implementation now. Add a note here when a new usage is introduced.
+static thread_local QList s_activeTaskTrees = {};
+
+static TaskTree *activeTaskTree()
+{
+    QT_ASSERT(s_activeTaskTrees.size(), return nullptr);
+    return s_activeTaskTrees.back();
+}
+
 DoneResult toDoneResult(bool success)
 {
     return success ? DoneResult::Success : DoneResult::Error;
@@ -1400,8 +1415,8 @@ void GroupItem::addChildren(const QList &children)
     }
 }
 
-GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout,
-                                 const std::function &handler)
+ExecutableItem ExecutableItem::withTimeout(milliseconds timeout,
+                                           const std::function &handler) const
 {
     const auto onSetup = [timeout](milliseconds &timeoutData) { timeoutData = timeout; };
     return Group {
@@ -1412,7 +1427,41 @@ GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout,
             handler ? TimeoutTask(onSetup, [handler] { handler(); }, CallDoneIf::Success)
                     : TimeoutTask(onSetup)
         },
-        item
+        *this
+    };
+}
+
+static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateWithMs); }
+
+ExecutableItem ExecutableItem::withLog(const QString &logName) const
+{
+    const auto header = [logName] {
+        return QString("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName);
+    };
+    struct LogStorage
+    {
+        time_point start;
+        int asyncCount = 0;
+    };
+    const Storage storage;
+    return Group {
+        storage,
+        onGroupSetup([storage, header] {
+            storage->start = system_clock::now();
+            storage->asyncCount = activeTaskTree()->asyncCount();
+            qDebug().noquote() << header() << "started.";
+        }),
+        *this,
+        onGroupDone([storage, header](DoneWith result) {
+            const auto elapsed = duration_cast(system_clock::now() - storage->start);
+            const int asyncCountDiff = activeTaskTree()->asyncCount() - storage->asyncCount;
+            QT_CHECK(asyncCountDiff >= 0);
+            const QMetaEnum doneWithEnum = QMetaEnum::fromType();
+            const QString syncType = asyncCountDiff ? QString("asynchronously")
+                                                    : QString("synchronously");
+            qDebug().noquote().nospace() << header() << " finished " << syncType << " with "
+                << doneWithEnum.valueToKey(int(result)) << " within " << elapsed.count() << "ms.";
+        })
     };
 }
 
@@ -1425,16 +1474,26 @@ class RuntimeTask;
 class ExecutionContextActivator
 {
 public:
-    ExecutionContextActivator(RuntimeIteration *iteration) { activateContext(iteration); }
-    ExecutionContextActivator(RuntimeContainer *container) { activateContext(container); }
+    ExecutionContextActivator(RuntimeIteration *iteration) {
+        activateTaskTree(iteration);
+        activateContext(iteration);
+    }
+    ExecutionContextActivator(RuntimeContainer *container) {
+        activateTaskTree(container);
+        activateContext(container);
+    }
     ~ExecutionContextActivator() {
         for (int i = m_activeStorages.size() - 1; i >= 0; --i) // iterate in reverse order
             m_activeStorages[i].m_storageData->threadData().popStorage();
         for (int i = m_activeLoops.size() - 1; i >= 0; --i) // iterate in reverse order
             m_activeLoops[i].m_loopData->threadData().popIteration();
+        QT_ASSERT(s_activeTaskTrees.size(), return);
+        s_activeTaskTrees.pop_back();
     }
 
 private:
+    void activateTaskTree(RuntimeIteration *iteration);
+    void activateTaskTree(RuntimeContainer *container);
     void activateContext(RuntimeIteration *iteration);
     void activateContext(RuntimeContainer *container);
     QList m_activeLoops;
@@ -1488,9 +1547,8 @@ public:
 
     void start();
     void stop();
+    void bumpAsyncCount();
     void advanceProgress(int byValue);
-    void emitStartedAndProgress();
-    void emitProgress();
     void emitDone(DoneWith result);
     void callSetupHandler(StorageBase storage, StoragePtr storagePtr) {
         callStorageHandler(storage, storagePtr, &StorageHandler::m_setupHandler);
@@ -1550,6 +1608,7 @@ public:
     TaskTree *q = nullptr;
     Guard m_guard;
     int m_progressValue = 0;
+    int m_asyncCount = 0;
     QSet m_storages;
     QHash m_storageHandlers;
     std::optional m_root;
@@ -1664,6 +1723,16 @@ static bool isProgressive(RuntimeContainer *container)
     return iteration ? iteration->m_isProgressive : true;
 }
 
+void ExecutionContextActivator::activateTaskTree(RuntimeIteration *iteration)
+{
+    activateTaskTree(iteration->m_container);
+}
+
+void ExecutionContextActivator::activateTaskTree(RuntimeContainer *container)
+{
+    s_activeTaskTrees.push_back(container->m_containerNode.m_taskTreePrivate->q);
+}
+
 void ExecutionContextActivator::activateContext(RuntimeIteration *iteration)
 {
     std::optional loop = iteration->loop();
@@ -1694,8 +1763,14 @@ void TaskTreePrivate::start()
 {
     QT_ASSERT(m_root, return);
     QT_ASSERT(!m_runtimeRoot, return);
+    m_asyncCount = 0;
     m_progressValue = 0;
-    emitStartedAndProgress();
+    {
+        GuardLocker locker(m_guard);
+        emit q->started();
+        emit q->asyncCountChanged(m_asyncCount);
+        emit q->progressValueChanged(m_progressValue);
+    }
     // TODO: check storage handlers for not existing storages in tree
     for (auto it = m_storageHandlers.cbegin(); it != m_storageHandlers.cend(); ++it) {
         QT_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
@@ -1703,6 +1778,7 @@ void TaskTreePrivate::start()
     }
     m_runtimeRoot.reset(new RuntimeTask{*m_root});
     start(m_runtimeRoot.get());
+    bumpAsyncCount();
 }
 
 void TaskTreePrivate::stop()
@@ -1715,6 +1791,15 @@ void TaskTreePrivate::stop()
     emitDone(DoneWith::Cancel);
 }
 
+void TaskTreePrivate::bumpAsyncCount()
+{
+    if (!m_runtimeRoot)
+        return;
+    ++m_asyncCount;
+    GuardLocker locker(m_guard);
+    emit q->asyncCountChanged(m_asyncCount);
+}
+
 void TaskTreePrivate::advanceProgress(int byValue)
 {
     if (byValue == 0)
@@ -1722,18 +1807,6 @@ void TaskTreePrivate::advanceProgress(int byValue)
     QT_CHECK(byValue > 0);
     QT_CHECK(m_progressValue + byValue <= m_root->taskCount());
     m_progressValue += byValue;
-    emitProgress();
-}
-
-void TaskTreePrivate::emitStartedAndProgress()
-{
-    GuardLocker locker(m_guard);
-    emit q->started();
-    emit q->progressValueChanged(m_progressValue);
-}
-
-void TaskTreePrivate::emitProgress()
-{
     GuardLocker locker(m_guard);
     emit q->progressValueChanged(m_progressValue);
 }
@@ -1849,6 +1922,8 @@ SetupResult TaskTreePrivate::start(RuntimeContainer *container)
     if (startAction == SetupResult::Continue
         && (containerNode.m_children.empty()
             || (containerNode.m_loop && !invokeLoopHandler(container)))) {
+        if (isProgressive(container))
+            advanceProgress(containerNode.m_taskCount);
         startAction = toSetupResult(container->m_successBit);
     }
     return continueStart(container, startAction);
@@ -2033,10 +2108,12 @@ SetupResult TaskTreePrivate::start(RuntimeTask *node)
         node->m_task.release()->deleteLater();
         RuntimeIteration *parentIteration = node->m_parentIteration;
         parentIteration->deleteChild(node);
-        if (parentIteration->m_container->isStarting())
+        if (parentIteration->m_container->isStarting()) {
             *unwindAction = toSetupResult(result);
-        else
+        } else {
             childDone(parentIteration, result);
+            bumpAsyncCount();
+        }
     });
 
     node->m_task->start();
@@ -2957,6 +3034,38 @@ DoneWith TaskTree::runBlocking(const Group &recipe, const QFuture &future,
     return taskTree.runBlocking(future);
 }
 
+/*!
+    Returns the current real count of asynchronous chains of invocations.
+
+    The returned value indicates how many times the control returns to the caller's
+    event loop while the task tree is running. Initially, this value is 0.
+    If the execution of the task tree finishes fully synchronously, this value remains 0.
+    If the task tree contains any asynchronous tasks that are successfully started during
+    a call to start(), this value is bumped to 1 just before the call to start() finishes.
+    Later, when any asynchronous task finishes and any possible continuations are started,
+    this value is bumped again. The bumping continues until the task tree finishes.
+    When the task tree emits the done() signal, the bumping stops.
+    The asyncCountChanged() signal is emitted on every bump of this value.
+
+    \sa asyncCountChanged()
+*/
+int TaskTree::asyncCount() const
+{
+    return d->m_asyncCount;
+}
+
+/*!
+    \fn void TaskTree::asyncCountChanged(int count)
+
+    This signal is emitted when the running task tree is about to return control to the caller's
+    event loop. When the task tree is started, this signal is emitted with \a count value of 0,
+    and emitted later on every asyncCount() value bump with an updated \a count value.
+    Every signal sent (except the initial one with the value of 0) guarantees that the task tree
+    is still running asynchronously after the emission.
+
+    \sa asyncCount()
+*/
+
 /*!
     Returns the number of asynchronous tasks contained in the stored recipe.
 
@@ -3002,7 +3111,7 @@ int TaskTree::taskCount() const
     When the task tree is started, this number is set to \c 0.
     When the task tree is finished, this number always equals progressMaximum().
 
-    \sa progressMaximum()
+    \sa progressMaximum(), progressValueChanged()
 */
 int TaskTree::progressValue() const
 {
diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h
index 181f91e85d1..8ea255303ba 100644
--- a/src/libs/solutions/tasking/tasktree.h
+++ b/src/libs/solutions/tasking/tasktree.h
@@ -261,8 +261,6 @@ protected:
     static GroupItem groupHandler(const GroupHandler &handler) { return GroupItem({handler}); }
     static GroupItem parallelLimit(int limit) { return GroupItem({{}, limit}); }
     static GroupItem workflowPolicy(WorkflowPolicy policy) { return GroupItem({{}, {}, policy}); }
-    static GroupItem withTimeout(const GroupItem &item, std::chrono::milliseconds timeout,
-                                 const std::function &handler = {});
 
     // Checks if Function may be invoked with Args and if Function's return type is Result.
     template  &handler = {}) const;
+    ExecutableItem withLog(const QString &logName) const;
+
+protected:
+    ExecutableItem() = default;
+    ExecutableItem(const TaskHandler &handler) : GroupItem(handler) {}
+};
+
+class TASKING_EXPORT Group : public ExecutableItem
 {
 public:
     Group(const QList &children) { addChildren(children); }
@@ -304,11 +314,6 @@ public:
     using GroupItem::parallelLimit;  // Default: 1 (sequential). 0 means unlimited (parallel).
     using GroupItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError.
 
-    GroupItem withTimeout(std::chrono::milliseconds timeout,
-                          const std::function &handler = {}) const {
-        return GroupItem::withTimeout(*this, timeout, handler);
-    }
-
 private:
     template 
     static GroupSetupHandler wrapGroupSetup(Handler &&handler)
@@ -366,6 +371,8 @@ static GroupItem onGroupDone(Handler &&handler, CallDoneIf callDoneIf = CallDone
 TASKING_EXPORT GroupItem parallelLimit(int limit);
 TASKING_EXPORT GroupItem workflowPolicy(WorkflowPolicy policy);
 
+TASKING_EXPORT extern const GroupItem nullItem;
+
 TASKING_EXPORT extern const GroupItem sequential;
 TASKING_EXPORT extern const GroupItem parallel;
 
@@ -385,7 +392,7 @@ public:
 };
 
 // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount()
-class TASKING_EXPORT Sync final : public GroupItem
+class TASKING_EXPORT Sync final : public ExecutableItem
 {
 public:
     template 
@@ -429,7 +436,7 @@ private:
 };
 
 template 
-class CustomTask final : public GroupItem
+class CustomTask final : public ExecutableItem
 {
 public:
     using Task = typename Adapter::TaskType;
@@ -443,16 +450,10 @@ public:
     template 
     CustomTask(SetupHandler &&setup = TaskSetupHandler(), DoneHandler &&done = TaskDoneHandler(),
                CallDoneIf callDoneIf = CallDoneIf::SuccessOrError)
-        : GroupItem({&createAdapter, wrapSetup(std::forward(setup)),
-                     wrapDone(std::forward(done)), callDoneIf})
+        : ExecutableItem({&createAdapter, wrapSetup(std::forward(setup)),
+                          wrapDone(std::forward(done)), callDoneIf})
     {}
 
-    GroupItem withTimeout(std::chrono::milliseconds timeout,
-                          const std::function &handler = {}) const
-    {
-        return GroupItem::withTimeout(*this, timeout, handler);
-    }
-
 private:
     static Adapter *createAdapter() { return new Adapter; }
 
@@ -540,6 +541,7 @@ public:
     static DoneWith runBlocking(const Group &recipe, const QFuture &future,
         std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
 
+    int asyncCount() const;
     int taskCount() const;
     int progressMaximum() const { return taskCount(); }
     int progressValue() const; // all finished / skipped / stopped tasks, groups itself excluded
@@ -564,6 +566,7 @@ public:
 signals:
     void started();
     void done(DoneWith result);
+    void asyncCountChanged(int count);
     void progressValueChanged(int value); // updated whenever task finished / skipped / stopped
 
 private:
diff --git a/src/libs/solutions/terminal/terminalview.cpp b/src/libs/solutions/terminal/terminalview.cpp
index 08a85d4f119..0cebe6d9b99 100644
--- a/src/libs/solutions/terminal/terminalview.cpp
+++ b/src/libs/solutions/terminal/terminalview.cpp
@@ -1199,6 +1199,9 @@ void TerminalView::mouseReleaseEvent(QMouseEvent *event)
 
 void TerminalView::mouseDoubleClickEvent(QMouseEvent *event)
 {
+    if (event->button() != Qt::LeftButton)
+        return;
+
     if (d->m_allowMouseTracking) {
         d->m_surface->mouseMove(toGridPos(event), event->modifiers());
         d->m_surface->mouseButton(event->button(), true, event->modifiers());
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index 9f11f3fc83c..eb2eaed9ddc 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 2098c68d1c0..b72fc2060e3 100644
--- a/src/libs/utils/aspects.cpp
+++ b/src/libs/utils/aspects.cpp
@@ -2518,9 +2518,20 @@ TriStateAspect::TriStateAspect(AspectContainer *container,
 {
     setDisplayStyle(DisplayStyle::ComboBox);
     setDefaultValue(TriState::Default);
-    addOption(onString.isEmpty() ? Tr::tr("Enable") : onString);
-    addOption(offString.isEmpty() ? Tr::tr("Disable") : offString);
-    addOption(defaultString.isEmpty() ? Tr::tr("Leave at Default") : defaultString);
+    SelectionAspect::addOption({});
+    SelectionAspect::addOption({});
+    SelectionAspect::addOption({});
+    setOptionTexts(onString, offString, defaultString);
+}
+
+void TriStateAspect::setOptionTexts(const QString &onString,
+                                    const QString &offString,
+                                    const QString &defaultString)
+{
+    QTC_ASSERT(d->m_options.size() == 3, return);
+    d->m_options[0].displayName = onString.isEmpty() ? Tr::tr("Enable") : onString;
+    d->m_options[1].displayName = offString.isEmpty() ? Tr::tr("Disable") : offString;
+    d->m_options[2].displayName = defaultString.isEmpty() ? Tr::tr("Leave at Default") : defaultString;
 }
 
 TriState TriStateAspect::value() const
diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h
index d4d1f704e02..cb885cc495a 100644
--- a/src/libs/utils/aspects.h
+++ b/src/libs/utils/aspects.h
@@ -554,7 +554,6 @@ protected:
     void bufferToGui() override;
     bool guiToBuffer() override;
 
-private:
     std::unique_ptr d;
 };
 
@@ -812,6 +811,13 @@ public:
 
     TriState defaultValue() const;
     void setDefaultValue(TriState setting);
+
+    void setOptionTexts(const QString &onString,
+                        const QString &offString,
+                        const QString &defaultString);
+private:
+    void addOption(const QString &displayName, const QString &toolTip = {}) = delete;
+    void addOption(const Option &option) = delete;
 };
 
 class QTCREATOR_UTILS_EXPORT StringListAspect : public TypedAspect
diff --git a/src/libs/utils/async.h b/src/libs/utils/async.h
index e1aacb126ef..af6fb3fd85d 100644
--- a/src/libs/utils/async.h
+++ b/src/libs/utils/async.h
@@ -54,7 +54,7 @@ auto asyncRun(Function &&function, Args &&...args)
 template 
 const QFuture &onResultReady(const QFuture &future, R *receiver, void(R::*member)(const T &))
 {
-    auto watcher = new QFutureWatcher();
+    auto watcher = new QFutureWatcher(receiver);
     QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
     QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, receiver, [=](int index) {
         (receiver->*member)(watcher->future().resultAt(index));
@@ -72,7 +72,7 @@ const QFuture &onResultReady(const QFuture &future, R *receiver, void(R::*
 template 
 const QFuture &onResultReady(const QFuture &future, QObject *guard, Function f)
 {
-    auto watcher = new QFutureWatcher();
+    auto watcher = new QFutureWatcher(guard);
     QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
     QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, guard, [f, watcher](int index) {
         f(watcher->future().resultAt(index));
@@ -90,7 +90,7 @@ template
 const QFuture &onFinished(const QFuture &future,
                              R *receiver, void (R::*member)(const QFuture &))
 {
-    auto watcher = new QFutureWatcher();
+    auto watcher = new QFutureWatcher(receiver);
     QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
     QObject::connect(watcher, &QFutureWatcherBase::finished, receiver,
                      [=] { (receiver->*member)(watcher->future()); });
@@ -107,7 +107,7 @@ const QFuture &onFinished(const QFuture &future,
 template
 const QFuture &onFinished(const QFuture &future, QObject *guard, Function f)
 {
-    auto watcher = new QFutureWatcher();
+    auto watcher = new QFutureWatcher(guard);
     QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
     QObject::connect(watcher, &QFutureWatcherBase::finished, guard, [f, watcher] {
         f(watcher->future());
diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp
index 39bdc736e09..a38a098d380 100644
--- a/src/libs/utils/devicefileaccess.cpp
+++ b/src/libs/utils/devicefileaccess.cpp
@@ -568,8 +568,8 @@ static bool checkToRefuseRemoveStandardLocationDirectory(const QString &dirPath,
 {
     if (QStandardPaths::standardLocations(location).contains(dirPath)) {
         if (error) {
-            *error = Tr::tr("Refusing to remove your %1 directory.").arg(
-                QStandardPaths::displayName(location));
+            *error = Tr::tr("Refusing to remove the standard directory \"%1\".")
+                         .arg(QStandardPaths::displayName(location));
         }
         return false;
     }
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index b1143c7fab4..be43f2a2062 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(), key});
 }
 
-void Environment::modify(const NameValueItems &items)
+void Environment::modify(const EnvironmentItems &items)
 {
     addItem(Item{std::in_place_index_t(), items});
 }
@@ -485,7 +485,7 @@ const NameValueDictionary &Environment::resolved() const
             break;
         }
         case Modify: {
-            NameValueItems items = std::get(item);
+            EnvironmentItems items = std::get(item);
             m_dict.modify(items);
             break;
         }
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index 542343aa2a9..1b6b7d2c0e0 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;
@@ -117,7 +117,7 @@ public:
         QString,                                     // UnsetValue (key)
         std::tuple, // PrependOrSet (key, value, separator)
         std::tuple, // 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 8a2c444cc42..376d1ea08c5 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;
-
 class Environment;
-using EnvironmentItem = NameValueItem;
-using EnvironmentItems = NameValueItems;
+class EnvironmentItem;
+using EnvironmentItems = QList;
 
-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 13329597846..6ac9b356406 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 
+#include 
+#include 
+#include 
+#include 
 
 namespace Utils {
 
-Environment EnvironmentModel::baseEnvironment() const
+namespace Internal {
+
+class EnvironmentModelPrivate
 {
-    return Environment(baseNameValueDictionary());
+public:
+    void updateResultNameValueDictionary()
+    {
+        m_resultNameValueDictionary = m_baseNameValueDictionary;
+        m_resultNameValueDictionary.modify(m_items);
+        // Add removed variables again and mark them as "" 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(""));
+        }
+    }
+
+    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())
+{}
+
+EnvironmentModel::~EnvironmentModel() = default;
+
+QString EnvironmentModel::indexToVariable(const QModelIndex &index) const
+{
+    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 "" 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(""));
+                    value.append(QLatin1String(""));
+                }
+            }
+            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  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 
+    // 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 ¤t) 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 82bf98d43f5..07670bd13fc 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 
+
+#include 
 
 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 ¤t) 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 d;
 };
 
 } // namespace Utils
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp
index f6d3dad3623..dd57cd6b5a0 100644
--- a/src/libs/utils/macroexpander.cpp
+++ b/src/libs/utils/macroexpander.cpp
@@ -375,7 +375,7 @@ void MacroExpander::registerIntVariable(const QByteArray &variable,
  * Convenience function to register several variables with the same \a prefix, that have a file
  * as a value. Takes the prefix and registers variables like \c{prefix:FilePath} and
  * \c{prefix:Path}, with descriptions that start with the given \a heading.
- * For example \c{registerFileVariables("CurrentDocument", tr("Current Document"))} registers
+ * For example \c{registerFileVariables("CurrentDocument", Tr::tr("Current Document"))} registers
  * variables such as \c{CurrentDocument:FilePath} with description
  * "Current Document: Full path including file name."
  *
diff --git a/src/libs/utils/namevaluedictionary.cpp b/src/libs/utils/namevaluedictionary.cpp
index 05ff4761dd1..d93298b3f15 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 722558f8912..87d81249704 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 adc7ff5afc9..3f4cdbd4b2c 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(list, [](const NameValueItem &item) {
+    return Utils::transform(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(list, [](const QVariant &item) {
+    return Utils::transform(list, [](const QVariant &item) {
         return itemFromVariantList(item.toList());
     });
 }
 
-QVariantList NameValueItem::toVariantList(const NameValueItems &list)
+QVariantList EnvironmentItem::toVariantList(const EnvironmentItems &list)
 {
-    return Utils::transform(list, [](const NameValueItem &item) {
+    return Utils::transform(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 62ba9d25baf..6ad5ed03791 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 57327c4ebed..00000000000
--- 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 
-#include 
-#include 
-#include 
-#include 
-
-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 "" 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(""));
-        }
-    }
-
-    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())
-{}
-
-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 "" 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(""));
-                    value.append(QLatin1String(""));
-                }
-            }
-            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  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 
-    // 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 ¤t) 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 84c1f2cece9..00000000000
--- 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 
-
-#include 
-
-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 ¤t) 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 d;
-};
-
-} // namespace Utils
diff --git a/src/libs/utils/namevaluesdialog.cpp b/src/libs/utils/namevaluesdialog.cpp
index 4f9537655ef..43511fe57f0 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 NameValuesDialog::getNameValueItems(QWidget *parent,
-                                                                    const NameValueItems &initial,
+std::optional 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 af847bb5a1d..a1e884fe5b5 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;
-    static std::optional getNameValueItems(QWidget *parent = nullptr,
-                                                             const NameValueItems &initial = {},
+    static std::optional 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 ef2ccbc9a08..620adc137c3 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 
@@ -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 bf0f1b27f74..e06560f1896 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/process.cpp b/src/libs/utils/process.cpp
index 4eacb28986f..5bf44513654 100644
--- a/src/libs/utils/process.cpp
+++ b/src/libs/utils/process.cpp
@@ -847,7 +847,9 @@ public:
     qint64 m_applicationMainThreadId = 0;
     ProcessResultData m_resultData;
 
-    QTextCodec *m_codec = QTextCodec::codecForLocale();
+    QTextCodec *m_stdOutCodec = QTextCodec::codecForLocale();
+    QTextCodec *m_stdErrCodec = QTextCodec::codecForLocale();
+
     ProcessResult m_result = ProcessResult::StartFailed;
     ChannelBuffer m_stdOut;
     ChannelBuffer m_stdErr;
@@ -1102,9 +1104,9 @@ void ProcessPrivate::sendControlSignal(ControlSignal controlSignal)
 void ProcessPrivate::clearForRun()
 {
     m_stdOut.clearForRun();
-    m_stdOut.codec = m_codec;
+    m_stdOut.codec = m_stdOutCodec;
     m_stdErr.clearForRun();
-    m_stdErr.codec = m_codec;
+    m_stdErr.codec = m_stdErrCodec;
     m_result = ProcessResult::StartFailed;
     m_startTimestamp = {};
     m_doneTimestamp = {};
@@ -1663,8 +1665,7 @@ QString Process::exitMessage(const CommandLine &command, ProcessResult result,
     case ProcessResult::Canceled:
         // TODO: We might want to format it nicely when bigger than 1 second, e.g. 1,324 s.
         //       Also when it's bigger than 1 minute, 1 hour, etc...
-        return Tr::tr("The command \"%1\" was canceled after (%2 ms).")
-            .arg(cmd).arg(duration.count());
+        return Tr::tr("The command \"%1\" was canceled after %2 ms.").arg(cmd).arg(duration.count());
     }
     return {};
 }
@@ -1729,13 +1730,13 @@ QByteArray Process::rawStdErr() const
 QString Process::stdOut() const
 {
     QTC_CHECK(d->m_stdOut.keepRawData);
-    return d->m_codec->toUnicode(d->m_stdOut.rawData);
+    return d->m_stdOutCodec->toUnicode(d->m_stdOut.rawData);
 }
 
 QString Process::stdErr() const
 {
     QTC_CHECK(d->m_stdErr.keepRawData);
-    return d->m_codec->toUnicode(d->m_stdErr.rawData);
+    return d->m_stdErrCodec->toUnicode(d->m_stdErr.rawData);
 }
 
 QString Process::cleanedStdOut() const
@@ -1850,7 +1851,20 @@ void ChannelBuffer::handleRest()
 void Process::setCodec(QTextCodec *c)
 {
     QTC_ASSERT(c, return);
-    d->m_codec = c;
+    d->m_stdOutCodec = c;
+    d->m_stdErrCodec = c;
+}
+
+void Process::setStdOutCodec(QTextCodec *c)
+{
+    QTC_ASSERT(c, return);
+    d->m_stdOutCodec = c;
+}
+
+void Process::setStdErrCodec(QTextCodec *c)
+{
+    QTC_ASSERT(c, return);
+    d->m_stdErrCodec = c;
 }
 
 void Process::setTimeOutMessageBoxEnabled(bool v)
diff --git a/src/libs/utils/process.h b/src/libs/utils/process.h
index d425f76eed3..694c1a12a86 100644
--- a/src/libs/utils/process.h
+++ b/src/libs/utils/process.h
@@ -148,8 +148,10 @@ public:
     void runBlocking(std::chrono::seconds timeout = std::chrono::seconds(10),
                      EventLoopMode eventLoopMode = EventLoopMode::Off);
 
-    // TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel()
-    void setCodec(QTextCodec *c);
+    void setCodec(QTextCodec *c); // for stdOut and stdErr
+    void setStdOutCodec(QTextCodec *c);
+    void setStdErrCodec(QTextCodec *c);
+
     void setTimeOutMessageBoxEnabled(bool);
 
     void setStdOutCallback(const TextChannelCallback &callback);
diff --git a/src/libs/utils/processhelper.cpp b/src/libs/utils/processhelper.cpp
index 2ca23fe138d..6045b77bec1 100644
--- a/src/libs/utils/processhelper.cpp
+++ b/src/libs/utils/processhelper.cpp
@@ -59,9 +59,6 @@ void ProcessStartHandler::setWindowsSpecificStartupFlags(bool belowNormalPriorit
                                                          bool createConsoleWindow)
 {
 #ifdef Q_OS_WIN
-    if (!belowNormalPriority && !createConsoleWindow)
-        return;
-
     m_process->setCreateProcessArgumentsModifier(
         [belowNormalPriority, createConsoleWindow](QProcess::CreateProcessArguments *args) {
             if (createConsoleWindow) {
@@ -71,6 +68,8 @@ void ProcessStartHandler::setWindowsSpecificStartupFlags(bool belowNormalPriorit
 
             if (belowNormalPriority)
                 args->flags |= BELOW_NORMAL_PRIORITY_CLASS;
+
+            args->flags |= CREATE_DEFAULT_ERROR_MODE;
         });
 #else // Q_OS_WIN
     Q_UNUSED(belowNormalPriority)
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index ffb7efc417c..23beeb4b3ff 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -933,7 +933,17 @@ QColor StyleHelper::ensureReadableOn(const QColor &background, const QColor &des
     return foreground;
 }
 
-static QStringList brandFontFamilies()
+static const QStringList &applicationFontFamilies()
+{
+    const static QStringList families = [] {
+        const QLatin1String familyName("Inter");
+        // Font is either installed in the system, or was loaded from share/qtcreator/fonts/
+        return QFontDatabase::hasFamily(familyName) ? QStringList(familyName) : QStringList();
+    }();
+    return families;
+}
+
+static const QStringList &brandFontFamilies()
 {
     const static QStringList families = []{
         const int id = QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
@@ -959,10 +969,14 @@ static const UiFontMetrics& uiFontMetrics(StyleHelper::UiElement element)
         {StyleHelper::UiElementH5,                  {14, 16, QFont::DemiBold}},
         {StyleHelper::UiElementH6,                  {12, 14, QFont::DemiBold}},
         {StyleHelper::UiElementH6Capital,           {12, 14, QFont::DemiBold}},
+        {StyleHelper::UiElementBody1,               {14, 20, QFont::Light}},
+        {StyleHelper::UiElementBody2,               {12, 20, QFont::Light}},
+        {StyleHelper::UiElementButtonMedium,        {12, 16, QFont::Bold}},
+        {StyleHelper::UiElementButtonSmall,         {10, 12, QFont::Bold}},
         {StyleHelper::UiElementCaptionStrong,       {10, 12, QFont::DemiBold}},
         {StyleHelper::UiElementCaption,             {10, 12, QFont::Normal}},
-        {StyleHelper::UIElementIconStandard,        {12, 16, QFont::Normal}},
-        {StyleHelper::UIElementIconActive,          {12, 16, QFont::DemiBold}},
+        {StyleHelper::UiElementIconStandard,        {12, 16, QFont::Medium}},
+        {StyleHelper::UiElementIconActive,          {12, 16, QFont::DemiBold}},
     };
     QTC_ASSERT(metrics.count(element) > 0, return metrics.at(StyleHelper::UiElementCaptionStrong));
     return metrics.at(element);
@@ -983,8 +997,10 @@ QFont StyleHelper::uiFont(UiElement element)
     case UiElementH3:
     case UiElementH6Capital:
         font.setCapitalization(QFont::AllUppercase);
-        break;
+        [[fallthrough]];
     default:
+        if (!applicationFontFamilies().isEmpty())
+            font.setFamilies(applicationFontFamilies());
         break;
     }
 
diff --git a/src/libs/utils/stylehelper.h b/src/libs/utils/stylehelper.h
index 4b986c68313..7d434925e66 100644
--- a/src/libs/utils/stylehelper.h
+++ b/src/libs/utils/stylehelper.h
@@ -42,15 +42,15 @@ constexpr char C_TOOLBAR_ACTIONWIDGET[] = "toolbar_actionWidget";
 constexpr char C_QT_SCALE_FACTOR_ROUNDING_POLICY[] = "QT_SCALE_FACTOR_ROUNDING_POLICY";
 
 namespace SpacingTokens {
-    constexpr int VPaddingXXS = 4;   // Top and bottom padding within the component
-    constexpr int HPaddingXXS = 4;   // Left and right padding within the component
-    constexpr int VGapXXS = 4;       // Vertical Space between TEXT LINE within the Component
-    constexpr int HGapXXS = 4;       // Horizontal Space between elements within the Component
+    constexpr int VPaddingXxs = 4;   // Top and bottom padding within the component
+    constexpr int HPaddingXxs = 4;   // Left and right padding within the component
+    constexpr int VGapXxs = 4;       // Vertical Space between TEXT LINE within the Component
+    constexpr int HGapXxs = 4;       // Horizontal Space between elements within the Component
 
-    constexpr int VPaddingXS = 8;
-    constexpr int HPaddingXS = 8;
-    constexpr int VGapXS = 4;
-    constexpr int HGapXS = 8;
+    constexpr int VPaddingXs = 8;
+    constexpr int HPaddingXs = 8;
+    constexpr int VGapXs = 4;
+    constexpr int HGapXs = 8;
 
     constexpr int VPaddingS = 8;
     constexpr int HPaddingS = 16;
@@ -62,10 +62,15 @@ namespace SpacingTokens {
     constexpr int VGapM = 4;
     constexpr int HGapM = 16;
 
-    constexpr int VPaddingL = 12;
+    constexpr int VPaddingL = 16;
     constexpr int HPaddingL = 24;
     constexpr int VGapL = 8;
     constexpr int HGapL = 16;
+
+    constexpr int ExPaddingGapS = 2;
+    constexpr int ExPaddingGapM = 6;
+    constexpr int ExPaddingGapL = 12;
+    constexpr int ExVPaddingGapXl = 24;
 }
 
 enum ToolbarStyle {
@@ -82,10 +87,14 @@ enum UiElement {
     UiElementH5,
     UiElementH6,
     UiElementH6Capital,
+    UiElementBody1,
+    UiElementBody2,
+    UiElementButtonMedium,
+    UiElementButtonSmall,
     UiElementCaptionStrong,
     UiElementCaption,
-    UIElementIconStandard,
-    UIElementIconActive,
+    UiElementIconStandard,
+    UiElementIconActive,
 };
 
 // Height of the project explorer navigation bar
diff --git a/src/libs/utils/theme/theme.cpp b/src/libs/utils/theme/theme.cpp
index 8800c85eb80..9b24078f86a 100644
--- a/src/libs/utils/theme/theme.cpp
+++ b/src/libs/utils/theme/theme.cpp
@@ -245,7 +245,6 @@ void Theme::readSettingsInternal(QSettings &settings)
         QMetaEnum e = m.enumerator(m.indexOfEnumerator("Flag"));
         for (int i = 0, total = e.keyCount(); i < total; ++i) {
             const QString key = QLatin1String(e.key(i));
-            QTC_ASSERT(settings.contains(key), return );
             d->flags[i] = settings.value(key).toBool();
         }
         settings.endGroup();
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
index 2e4d61d943b..65d0ee91eaf 100644
--- a/src/libs/utils/theme/theme.h
+++ b/src/libs/utils/theme/theme.h
@@ -247,18 +247,6 @@ public:
         Token_Notification_Neutral,
         Token_Notification_Danger,
 
-        /* Welcome Plugin */
-
-        Welcome_TextColor,
-        Welcome_ForegroundPrimaryColor,
-        Welcome_ForegroundSecondaryColor,
-        Welcome_BackgroundPrimaryColor,
-        Welcome_BackgroundSecondaryColor,
-        Welcome_HoverColor,
-        Welcome_AccentColor,
-        Welcome_LinkColor,
-        Welcome_DisabledLinkColor,
-
         /* Timeline Library */
         Timeline_TextColor,
         Timeline_BackgroundColor1,
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index d7ccd1d6761..7bf55d8f247 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 21a20ff645c..fae6c64bbe3 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -126,6 +126,15 @@ static QString ndkPackageMarker()
     return QLatin1String(Constants::ndkPackageName) + ";";
 }
 
+static QString platformsPackageMarker()
+{
+    return QLatin1String(Constants::platformsPackageName) + ";";
+}
+
+static QString buildToolsPackageMarker()
+{
+    return QLatin1String(Constants::buildToolsPackageName) + ";";
+}
 
 //////////////////////////////////
 // AndroidConfig
@@ -951,15 +960,59 @@ bool AndroidConfig::sdkToolsOk() const
     return exists && writable && sdkToolsExist;
 }
 
+static QStringList packagesExcludingBuiltWithDefaults(const QStringList &packages)
+{
+    return Utils::filtered(packages, [] (const QString &p) {
+        return !p.startsWith(ndkPackageMarker()) && !p.startsWith(platformsPackageMarker())
+               && !p.startsWith(buildToolsPackageMarker()); });
+}
+
+static QString essentialBuiltWithBuildToolsPackage(int builtWithApiVersion)
+{
+    // For build-tools, to avoid the situation of potentially having the essential packages
+    // invalidated whenever a new minor version is released, check if any version with major
+    // version matching builtWith apiVersion and use it as essential, otherwise use the any
+    // other one that has an minimum major version of builtWith apiVersion.
+    const BuildToolsList buildTools =
+        AndroidConfigurations::sdkManager()->filteredBuildTools(builtWithApiVersion);
+    const BuildToolsList apiBuildTools
+        = Utils::filtered(buildTools, [builtWithApiVersion] (const BuildTools *pkg) {
+              return pkg->revision().majorVersion() == builtWithApiVersion; });
+    const QString installedBuildTool = [apiBuildTools] () -> QString {
+        for (const BuildTools *pkg : apiBuildTools) {
+            if (pkg->state() == AndroidSdkPackage::Installed)
+                return pkg->sdkStylePath();
+        }
+        return {};
+    }();
+
+    if (installedBuildTool.isEmpty()) {
+        if (!apiBuildTools.isEmpty())
+            return apiBuildTools.first()->sdkStylePath();
+        else if (!buildTools.isEmpty())
+            return buildTools.first()->sdkStylePath();
+        // This means there's  something wrong with sdkmanager, return a default version anyway
+        else
+            return buildToolsPackageMarker() + QString::number(builtWithApiVersion) + ".0.0";
+    }
+
+    return installedBuildTool;
+}
+
 QStringList AndroidConfig::essentialsFromQtVersion(const QtVersion &version) const
 {
     if (auto androidQtVersion = dynamic_cast(&version)) {
         bool ok;
         const AndroidQtVersion::BuiltWith bw = androidQtVersion->builtWith(&ok);
         if (ok) {
-            const QString ndkPackage = ndkPackageMarker() + bw.ndkVersion.toString();
-            return QStringList(ndkPackage)
-                   + packagesWithoutNdks(m_defaultSdkDepends.essentialPackages);
+            QStringList builtWithPackages;
+            builtWithPackages.append(ndkPackageMarker() + bw.ndkVersion.toString());
+            const QString apiVersion = QString::number(bw.apiVersion);
+            builtWithPackages.append(platformsPackageMarker() + "android-" + apiVersion);
+            builtWithPackages.append(essentialBuiltWithBuildToolsPackage(bw.apiVersion));
+
+            return builtWithPackages + packagesExcludingBuiltWithDefaults(
+                       m_defaultSdkDepends.essentialPackages);
         }
     }
 
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index e2b15e6358d..813b6a924c0 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -78,6 +78,8 @@ const Utils::Id AndroidAvdPath = "AndroidAvdPath";
 // SDK Tools
 const char cmdlineToolsName[] = "cmdline-tools";
 const char ndkPackageName[] = "ndk";
+const char platformsPackageName[] = "platforms";
+const char buildToolsPackageName[] = "build-tools";
 
 // For AndroidQtVersion
 const char ArmToolsDisplayName[] = "arm";
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp
index 6cba25a0179..d18f645165f 100644
--- a/src/plugins/android/androidrunnerworker.cpp
+++ b/src/plugins/android/androidrunnerworker.cpp
@@ -819,15 +819,13 @@ void AndroidRunnerWorker::removeForwardPort(const QString &port)
 
 void AndroidRunnerWorker::onProcessIdChanged(PidUserPair pidUser)
 {
-    qint64 pid = pidUser.first;
-    qint64 user = pidUser.second;
     // Don't write to m_psProc from a different thread
     QTC_ASSERT(QThread::currentThread() == thread(), return);
     qCDebug(androidRunWorkerLog) << "Process ID changed from:" << m_processPID
-                                 << "to:" << pid;
-    m_processPID = pid;
-    m_processUser = user;
-    if (pid == -1) {
+                                 << "to:" << pidUser.first;
+    m_processPID = pidUser.first;
+    m_processUser = pidUser.second;
+    if (m_processPID == -1) {
         emit remoteProcessFinished(QLatin1String("\n\n") + Tr::tr("\"%1\" died.")
                                    .arg(m_packageName));
         // App died/killed. Reset log, monitor, jdb & gdbserver/lldb-server processes.
@@ -852,7 +850,10 @@ void AndroidRunnerWorker::onProcessIdChanged(PidUserPair pidUser)
         QTC_ASSERT(m_psIsAlive, return);
         m_psIsAlive->setObjectName("IsAliveProcess");
         m_psIsAlive->setProcessChannelMode(QProcess::MergedChannels);
-        connect(m_psIsAlive.get(), &Process::done, this, [this] { onProcessIdChanged({-1, -1}); });
+        connect(m_psIsAlive.get(), &Process::done, this, [this] {
+            m_psIsAlive.release()->deleteLater();
+            onProcessIdChanged({-1, -1});
+        });
     }
 }
 
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index c952ff90978..029cfd83524 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -405,7 +405,10 @@ void AndroidSdkManagerPrivate::reloadSdkPackages()
     if (m_packageListingSuccessful) {
         SdkManagerOutputParser parser(m_allPackages);
         parser.parsePackageListing(packageListing);
+    } else {
+        qCWarning(sdkManagerLog) << "Failed parsing packages:" << packageListing;
     }
+
     emit m_sdkManager.packageReloadFinished();
 }
 
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index ca0ff057dfb..c75ba299c5b 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -13,13 +13,14 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -203,6 +204,56 @@ enum OpenSslValidation {
     OpenSslCmakeListsPathExists
 };
 
+static expected_str testJavaC(const FilePath &jdkPath)
+{
+    if (!jdkPath.isReadableDir())
+        return make_unexpected(Tr::tr("The selected path does not exist or is not readable."));
+
+    const QString javacCommand("javac");
+    const QString versionParameter("-version");
+    constexpr int requiredMajorVersion = 17;
+    const FilePath bin = jdkPath / "bin" / (javacCommand + QTC_HOST_EXE_SUFFIX);
+
+    if (!bin.isExecutableFile())
+        return make_unexpected(
+            Tr::tr("Could not find \"%1\" in the selected path.")
+                .arg(bin.toUserOutput()));
+
+    QVersionNumber jdkVersion;
+
+    Process javacProcess;
+    const CommandLine cmd(bin, {versionParameter});
+    javacProcess.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels);
+    javacProcess.setCommand(cmd);
+    javacProcess.runBlocking();
+
+    const QString stdOut = javacProcess.stdOut().trimmed();
+
+    if (javacProcess.exitCode() != 0)
+        return make_unexpected(
+            Tr::tr("The selected path does not contain a valid JDK. (%1 failed: %2)")
+                .arg(cmd.toUserOutput())
+                .arg(stdOut));
+
+    // We expect "javac " where  is "major.minor.patch"
+    const QString outputPrefix = javacCommand + " ";
+    if (!stdOut.startsWith(outputPrefix))
+        return make_unexpected(Tr::tr("Unexpected output from \"%1\": %2")
+                                   .arg(cmd.toUserOutput())
+                                   .arg(stdOut));
+
+    jdkVersion = QVersionNumber::fromString(stdOut.mid(outputPrefix.length()).split('\n').first());
+
+    if (jdkVersion.isNull() || jdkVersion.majorVersion() != requiredMajorVersion) {
+        return make_unexpected(Tr::tr("Unsupported JDK version (needs to be %1): %2 (parsed: %3)")
+                                   .arg(requiredMajorVersion)
+                                   .arg(stdOut)
+                                   .arg(jdkVersion.toString()));
+    }
+
+    return {};
+}
+
 AndroidSettingsWidget::AndroidSettingsWidget()
 {
     setWindowTitle(Tr::tr("Android Configuration"));
@@ -307,6 +358,15 @@ AndroidSettingsWidget::AndroidSettingsWidget()
                                          Tr::tr("OpenSSL settings have errors."),
                                          openSslDetailsWidget);
 
+    m_openJdkLocationPathChooser->setValidationFunction([](const QString &s) {
+        return Utils::asyncRun([s]() -> expected_str {
+            expected_str test = testJavaC(FilePath::fromUserInput(s));
+            if (!test)
+                return make_unexpected(test.error());
+            return s;
+        });
+    });
+
     connect(m_openJdkLocationPathChooser, &PathChooser::rawPathChanged,
             this, &AndroidSettingsWidget::validateJdk);
     if (androidConfig().openJDKLocation().isEmpty())
@@ -533,10 +593,9 @@ bool AndroidSettingsWidget::isDefaultNdkSelected() const
 void AndroidSettingsWidget::validateJdk()
 {
     androidConfig().setOpenJDKLocation(m_openJdkLocationPathChooser->filePath());
-    bool jdkPathExists = androidConfig().openJDKLocation().exists();
-    const FilePath bin = androidConfig().openJDKLocation()
-                                        .pathAppended("bin/javac" QTC_HOST_EXE_SUFFIX);
-    m_androidSummary->setPointValid(JavaPathExistsAndWritableRow, jdkPathExists && bin.exists());
+    expected_str test = testJavaC(androidConfig().openJDKLocation());
+
+    m_androidSummary->setPointValid(JavaPathExistsAndWritableRow, test.has_value());
 
     updateUI();
 
diff --git a/src/plugins/autotest/catch/catchcodeparser.cpp b/src/plugins/autotest/catch/catchcodeparser.cpp
index 186dde5ea1b..f9d6b19ed04 100644
--- a/src/plugins/autotest/catch/catchcodeparser.cpp
+++ b/src/plugins/autotest/catch/catchcodeparser.cpp
@@ -79,14 +79,16 @@ void CatchCodeParser::handleIdentifier()
                || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_SIG") {
         handleParameterizedTestCase(false);
     } else if (unprefixed == "TEST_CASE_METHOD") {
-        handleFixtureOrRegisteredTestCase(true);
+        handleFixtureOrRegisteredTestCase(/*fixture=*/true, /*scenario=*/false);
+    } else if (unprefixed == "SCENARIO_METHOD") {
+        handleFixtureOrRegisteredTestCase(/*fixture=*/true, /*scenario=*/true);
     } else if (unprefixed == "TEMPLATE_TEST_CASE_METHOD_SIG"
                || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"
                || unprefixed == "TEMPLATE_TEST_CASE_METHOD"
                || unprefixed == "TEMPLATE_LIST_TEST_CASE_METHOD") {
         handleParameterizedTestCase(true);
     } else if (unprefixed == "METHOD_AS_TEST_CASE" || unprefixed == "REGISTER_TEST_CASE") {
-        handleFixtureOrRegisteredTestCase(false);
+        handleFixtureOrRegisteredTestCase(/*fixture=*/false, /*scenario=*/false);
     }
 }
 
@@ -124,7 +126,7 @@ void CatchCodeParser::handleParameterizedTestCase(bool isFixture)
     if (!skipCommentsUntil(T_LPAREN))
         return;
 
-    if (isFixture && !skipFixtureParameter())
+    if (isFixture && !skipParameter())
         return;
 
     CatchTestCodeLocationAndType locationAndType
@@ -154,18 +156,13 @@ void CatchCodeParser::handleParameterizedTestCase(bool isFixture)
     m_testCases.append(locationAndType);
 }
 
-void CatchCodeParser::handleFixtureOrRegisteredTestCase(bool isFixture)
+void CatchCodeParser::handleFixtureOrRegisteredTestCase(bool isFixture, bool isScenario)
 {
     if (!skipCommentsUntil(T_LPAREN))
         return;
 
-    if (isFixture) {
-        if (!skipFixtureParameter())
+    if (!skipParameter())
             return;
-    } else {
-        if (!skipFunctionParameter())
-            return;
-    }
 
     CatchTestCodeLocationAndType locationAndType
             = locationAndTypeFromToken(m_tokens.at(m_currentIndex));
@@ -183,6 +180,9 @@ void CatchCodeParser::handleFixtureOrRegisteredTestCase(bool isFixture)
     if (stoppedAt != T_RPAREN)
         return;
 
+    if (isScenario)
+        testCaseName.prepend("Scenario: "); // use a flag?
+
     locationAndType.m_name = testCaseName;
     locationAndType.tags = parseTags(tagsString);
     if (isFixture)
@@ -245,19 +245,12 @@ Kind CatchCodeParser::skipUntilCorrespondingRParen()
     return T_ERROR;
 }
 
-bool CatchCodeParser::skipFixtureParameter()
-{
-    if (!skipCommentsUntil(T_IDENTIFIER))
-        return false;
-    return skipCommentsUntil(T_COMMA);
-}
-
-bool CatchCodeParser::skipFunctionParameter()
+bool CatchCodeParser::skipParameter()
 {
     if (!skipCommentsUntil(T_IDENTIFIER))
         return false;
     if (skipCommentsUntil(T_COLON_COLON))
-        return skipFunctionParameter();
+        return skipParameter();
 
     return skipCommentsUntil(T_COMMA);
 }
diff --git a/src/plugins/autotest/catch/catchcodeparser.h b/src/plugins/autotest/catch/catchcodeparser.h
index 9315b3ccc2c..4bebb16bce8 100644
--- a/src/plugins/autotest/catch/catchcodeparser.h
+++ b/src/plugins/autotest/catch/catchcodeparser.h
@@ -22,13 +22,12 @@ private:
     void handleIdentifier();
     void handleTestCase(bool isScenario);
     void handleParameterizedTestCase(bool isFixture);
-    void handleFixtureOrRegisteredTestCase(bool isFixture);
+    void handleFixtureOrRegisteredTestCase(bool isFixture, bool isScenario);
 
     QString getStringLiteral(CPlusPlus::Kind &stoppedAtKind);
     bool skipCommentsUntil(CPlusPlus::Kind nextExpectedKind);   // moves currentIndex if succeeds
     CPlusPlus::Kind skipUntilCorrespondingRParen();             // moves currentIndex
-    bool skipFixtureParameter();
-    bool skipFunctionParameter();
+    bool skipParameter();
 
     const QByteArray &m_source;
     const CPlusPlus::LanguageFeatures &m_features;
diff --git a/src/plugins/autotest/catch/catchtestparser.cpp b/src/plugins/autotest/catch/catchtestparser.cpp
index 96f536a9055..bc2f4e0644e 100644
--- a/src/plugins/autotest/catch/catchtestparser.cpp
+++ b/src/plugins/autotest/catch/catchtestparser.cpp
@@ -29,7 +29,9 @@ static bool isCatchTestCaseMacro(const QString ¯oName)
         QStringLiteral("TEMPLATE_TEST_CASE_SIG"), QStringLiteral("TEMPLATE_PRODUCT_TEST_CASE_SIG"),
         QStringLiteral("TEST_CASE_METHOD"), QStringLiteral("TEMPLATE_TEST_CASE_METHOD"),
         QStringLiteral("TEMPLATE_PRODUCT_TEST_CASE_METHOD"),
-        QStringLiteral("TEST_CASE_METHOD"), QStringLiteral("TEMPLATE_TEST_CASE_METHOD_SIG"),
+        QStringLiteral("TEST_CASE_METHOD"),
+        QStringLiteral("SCENARIO_METHOD"),
+        QStringLiteral("TEMPLATE_TEST_CASE_METHOD_SIG"),
         QStringLiteral("TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"),
         QStringLiteral("TEMPLATE_TEST_CASE_METHOD"),
         QStringLiteral("TEMPLATE_LIST_TEST_CASE_METHOD"),
@@ -105,7 +107,7 @@ bool CatchTestParser::processDocument(QPromise &promise,
 
     if (!hasCatchNames(doc)) {
         static const QRegularExpression regex("\\b(CATCH_)?"
-                                              "(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
+                                              "(SCENARIO(_METHOD)?|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
                                               "TEMPLATE_TEST_CASE(_METHOD)?_SIG|"
                                               "TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|"
                                               "TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|"
diff --git a/src/plugins/autotest/qtest/datataglocatorfilter.cpp b/src/plugins/autotest/qtest/datataglocatorfilter.cpp
index bb0745d189e..e6a436666ce 100644
--- a/src/plugins/autotest/qtest/datataglocatorfilter.cpp
+++ b/src/plugins/autotest/qtest/datataglocatorfilter.cpp
@@ -70,7 +70,7 @@ DataTagLocatorFilter::DataTagLocatorFilter()
 {
     setId("Locate Qt Test data tags");
     setDisplayName(Tr::tr("Locate Qt Test data tags"));
-    setDescription(Tr::tr("Locates a Qt Test data tag found inside the active project."));
+    setDescription(Tr::tr("Locates Qt Test data tags found inside the active project."));
     setDefaultShortcutString("qdt");
     setPriority(Medium);
     using namespace ProjectExplorer;
diff --git a/src/plugins/autotest/qtest/qttestframework.cpp b/src/plugins/autotest/qtest/qttestframework.cpp
index 009acc81ab1..17970e19d70 100644
--- a/src/plugins/autotest/qtest/qttestframework.cpp
+++ b/src/plugins/autotest/qtest/qttestframework.cpp
@@ -73,9 +73,10 @@ QtTestFramework::QtTestFramework()
     useXMLOutput.setSettingsKey("UseXMLOutput");
     useXMLOutput.setDefaultValue(true);
     useXMLOutput.setLabelText(Tr::tr("Use XML output"));
-    useXMLOutput.setToolTip(Tr::tr("XML output is recommended, because it avoids parsing issues, "
-                                   "while plain text is more human readable.\n\nWarning: "
-                                   "Plain text misses some information, such as duration."));
+    useXMLOutput.setToolTip(""
+                            + Tr::tr("XML output is recommended, because it avoids parsing issues, "
+                                     "while plain text is more human readable.

Warning: " + "Plain text misses some information, such as duration.")); verboseBench.setSettingsKey("VerboseBench"); verboseBench.setLabelText(Tr::tr("Verbose benchmarks")); @@ -98,18 +99,22 @@ QtTestFramework::QtTestFramework() quickCheckForDerivedTests.setDefaultValue(false); quickCheckForDerivedTests.setLabelText(Tr::tr("Check for derived Qt Quick tests")); quickCheckForDerivedTests.setToolTip( - Tr::tr("Search for Qt Quick tests that are derived from TestCase.\nWarning: Enabling this " - "feature significantly increases scan time.")); + "" + + Tr::tr( + "Search for Qt Quick tests that are derived from TestCase.

Warning: Enabling this " + "feature significantly increases scan time.")); parseMessages.setSettingsKey("ParseMessages"); parseMessages.setDefaultValue(false); parseMessages.setLabelText(Tr::tr("Find user-defined locations")); parseMessages.setToolTip( - Tr::tr("Parse messages for the pattern \"file://filepath:line\", where \":line\" is " - "optional, and use this as location information.\n" - "Warning: If the patterns are used in code, the location information for debug " - "messages and other messages might improve,\n" - "at the risk of some incorrect locations and lower performance.")); + "" + + Tr::tr("Parse messages for the following pattern and use it as location information:" + "

file://filepath:line
" + "where \":line\" is optional." + "

Warning: If the patterns are used in code, the location information for debug " + "messages and other messages might improve," + "at the risk of some incorrect locations and lower performance.")); readSettings(); maxWarnings.setEnabler(&limitWarnings); diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 1824b316d59..9962a08c621 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -55,6 +55,7 @@ TestCodeParser::TestCodeParser() m_qmlEditorRev.remove(filePath); }); m_reparseTimer.setSingleShot(true); + m_reparseTimer.setInterval(1000); connect(&m_reparseTimer, &QTimer::timeout, this, &TestCodeParser::parsePostponedFiles); connect(&m_taskTreeRunner, &TaskTreeRunner::aboutToStart, this, [this](TaskTree *taskTree) { if (m_withTaskProgress) { @@ -238,27 +239,10 @@ bool TestCodeParser::postponed(const QSet &filePaths) if (filePaths.size() == 1) { if (m_reparseTimerTimedOut) return false; - const FilePath filePath = *filePaths.begin(); - switch (m_postponedFiles.size()) { - case 0: - m_postponedFiles.insert(filePath); - m_reparseTimer.setInterval(1000); - m_reparseTimer.start(); - return true; - case 1: - if (m_postponedFiles.contains(filePath)) { - m_reparseTimer.start(); - return true; - } - Q_FALLTHROUGH(); - default: - m_postponedFiles.insert(filePath); - m_reparseTimer.stop(); - m_reparseTimer.setInterval(0); - m_reparseTimerTimedOut = false; - m_reparseTimer.start(); - return true; - } + + m_postponedFiles.insert(*filePaths.begin()); + m_reparseTimer.start(); + return true; } return false; case PartialParse: @@ -377,7 +361,7 @@ void TestCodeParser::scanForTests(const QSet &filePaths, return true; return cppSnapshot.contains(fn); }); - m_withTaskProgress = filteredFiles.size() > 5; + m_withTaskProgress = isFullParse || filteredFiles.size() > 20; qCDebug(LOG) << "Starting scan of" << filteredFiles.size() << "(" << files.size() << ")" << "files with" << codeParsers.size() << "parsers"; diff --git a/src/plugins/axivion/CMakeLists.txt b/src/plugins/axivion/CMakeLists.txt index faba40706c8..561ad680e61 100644 --- a/src/plugins/axivion/CMakeLists.txt +++ b/src/plugins/axivion/CMakeLists.txt @@ -1,15 +1,19 @@ add_qtc_plugin(Axivion PLUGIN_DEPENDS Core ProjectExplorer TextEditor - DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils + DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils qtkeychain SOURCES axivion.qrc axivionoutputpane.cpp axivionoutputpane.h axivionplugin.cpp axivionplugin.h - axivionprojectsettings.h axivionprojectsettings.cpp + axivionprojectsettings.cpp axivionprojectsettings.h axivionsettings.cpp axivionsettings.h axiviontr.h + credentialquery.h credentialquery.cpp dashboard/dto.cpp dashboard/dto.h dashboard/concat.cpp dashboard/concat.h dashboard/error.h dashboard/error.cpp + dashboard/error.cpp dashboard/error.h + dynamiclistmodel.cpp dynamiclistmodel.h + issueheaderview.cpp issueheaderview.h ) diff --git a/src/plugins/axivion/axivion.qbs b/src/plugins/axivion/axivion.qbs index 7d215259b8e..0e808f65806 100644 --- a/src/plugins/axivion/axivion.qbs +++ b/src/plugins/axivion/axivion.qbs @@ -4,10 +4,11 @@ QtcPlugin { name: "Axivion" Depends { name: "Core" } + Depends { name: "ExtensionSystem" } Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } - Depends { name: "ExtensionSystem" } Depends { name: "Utils" } + Depends { name: "qtkeychain" } Depends { name: "Qt.widgets" } Depends { name: "Qt.network" } @@ -22,6 +23,12 @@ QtcPlugin { "axivionsettings.cpp", "axivionsettings.h", "axiviontr.h", + "credentialquery.cpp", + "credentialquery.h", + "dynamiclistmodel.cpp", + "dynamiclistmodel.h", + "issueheaderview.cpp", + "issueheaderview.h", ] cpp.includePaths: base.concat(["."]) // needed for the generated stuff below diff --git a/src/plugins/axivion/axivion.qrc b/src/plugins/axivion/axivion.qrc index c0d56f8f7b0..d1e41e3cdb3 100644 --- a/src/plugins/axivion/axivion.qrc +++ b/src/plugins/axivion/axivion.qrc @@ -2,17 +2,21 @@ images/axivion.png images/axivion@2x.png - images/button-av.png - images/button-av@2x.png - images/button-cl.png - images/button-cl@2x.png - images/button-cy.png - images/button-cy@2x.png - images/button-de.png - images/button-de@2x.png - images/button-mv.png - images/button-mv@2x.png - images/button-sv.png - images/button-sv@2x.png + images/button-AV.png + images/button-AV@2x.png + images/button-CL.png + images/button-CL@2x.png + images/button-CY.png + images/button-CY@2x.png + images/button-DE.png + images/button-DE@2x.png + images/button-MV.png + images/button-MV@2x.png + images/button-SV.png + images/button-SV@2x.png + images/sortAsc.png + images/sortAsc@2x.png + images/sortDesc.png + images/sortDesc@2x.png diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index a9fb3a4e3f4..70e44057e9f 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -6,17 +6,21 @@ #include "axivionplugin.h" #include "axiviontr.h" #include "dashboard/dto.h" +#include "issueheaderview.h" +#include "dynamiclistmodel.h" #include +#include #include #include #include +#include +#include #include #include -#include #include #include @@ -28,9 +32,7 @@ #include #include #include -#include #include -#include #include #include @@ -59,22 +61,24 @@ DashboardWidget::DashboardWidget(QWidget *parent) : QScrollArea(parent) { QWidget *widget = new QWidget(this); - QVBoxLayout *layout = new QVBoxLayout(widget); - QFormLayout *projectLayout = new QFormLayout; m_project = new QLabel(this); - projectLayout->addRow(Tr::tr("Project:"), m_project); m_loc = new QLabel(this); - projectLayout->addRow(Tr::tr("Lines of code:"), m_loc); m_timestamp = new QLabel(this); - projectLayout->addRow(Tr::tr("Analysis timestamp:"), m_timestamp); - layout->addLayout(projectLayout); - layout->addSpacing(10); - auto row = new QHBoxLayout; + m_gridLayout = new QGridLayout; - row->addLayout(m_gridLayout); - row->addStretch(1); - layout->addLayout(row); - layout->addStretch(1); + + using namespace Layouting; + Column { + Form { + Tr::tr("Project:"), m_project, br, + Tr::tr("Lines of code:"), m_loc, br, + Tr::tr("Analysis timestamp:"), m_timestamp + }, + Space(10), + Row { m_gridLayout, st }, + st + }.attachTo(widget); + setWidget(widget); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setWidgetResizable(true); @@ -187,32 +191,59 @@ void DashboardWidget::updateUi() addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row); } -class IssueTreeItem final : public StaticTreeItem +struct LinkWithColumns +{ + Link link; + QList columns; +}; + +class IssueListItem final : public ListItem { public: - IssueTreeItem(const QStringList &data, const QStringList &toolTips) - : StaticTreeItem(data, toolTips) + IssueListItem(int row, const QString &id, const QStringList &data, const QStringList &toolTips) + : ListItem(row) + , m_id(id) + , m_data(data) + , m_toolTips(toolTips) {} - void setLinks(const Links &links) { m_links = links; } + void setLinks(const QList &links) { m_links = links; } + + QVariant data(int column, int role) const + { + if (role == Qt::DisplayRole && column >= 0 && column < m_data.size()) + return m_data.at(column); + if (role == Qt::ToolTipRole && column >= 0 && column < m_toolTips.size()) + return m_toolTips.at(column); + return {}; + } bool setData(int column, const QVariant &value, int role) final { - if (role == BaseTreeView::ItemActivatedRole && !m_links.isEmpty()) { - // TODO for now only simple - just the first.. - Link link = m_links.first(); - Project *project = ProjectManager::startupProject(); - FilePath baseDir = project ? project->projectDirectory() : FilePath{}; - link.targetFilePath = baseDir.resolvePath(link.targetFilePath); - if (link.targetFilePath.exists()) - EditorManager::openEditorAt(link); + if (role == BaseTreeView::ItemActivatedRole) { + if (!m_links.isEmpty()) { + Link link + = Utils::findOr(m_links, m_links.first(), [column](const LinkWithColumns &link) { + return link.columns.contains(column); + }).link; + Project *project = ProjectManager::startupProject(); + FilePath baseDir = project ? project->projectDirectory() : FilePath{}; + link.targetFilePath = baseDir.resolvePath(link.targetFilePath); + if (link.targetFilePath.exists()) + EditorManager::openEditorAt(link); + } + if (!m_id.isEmpty()) + fetchIssueInfo(m_id); return true; } - return StaticTreeItem::setData(column, value, role); + return ListItem::setData(column, value, role); } private: - Links m_links; + const QString m_id; + QStringList m_data; + QStringList m_toolTips; + QList m_links; }; class IssuesWidget : public QScrollArea @@ -220,23 +251,23 @@ class IssuesWidget : public QScrollArea public: explicit IssuesWidget(QWidget *parent = nullptr); void updateUi(); - void setTableDto(const Dto::TableInfoDto &dto); - void addIssues(const Dto::IssueTableDto &dto); private: + void updateTable(); + void addIssues(const Dto::IssueTableDto &dto, int startRow); void onSearchParameterChanged(); void updateBasicProjectInfo(std::optional info); - void updateTableView(); + void setFiltersEnabled(bool enabled); IssueListSearch searchFromUi() const; + void fetchTable(); void fetchIssues(const IssueListSearch &search); - void fetchMoreIssues(); + void onFetchRequested(int startRow, int limit); QString m_currentPrefix; QString m_currentProject; std::optional m_currentTableInfo; QHBoxLayout *m_typesLayout = nullptr; QButtonGroup *m_typesButtonGroup = nullptr; - QHBoxLayout *m_filtersLayout = nullptr; QPushButton *m_addedFilter = nullptr; QPushButton *m_removedFilter = nullptr; QComboBox *m_ownerFilter = nullptr; @@ -245,9 +276,9 @@ private: QLineEdit *m_pathGlobFilter = nullptr; // FancyLineEdit instead? QLabel *m_totalRows = nullptr; BaseTreeView *m_issuesView = nullptr; - TreeModel<> *m_issuesModel = nullptr; + IssueHeaderView *m_headerView = nullptr; + DynamicListModel *m_issuesModel = nullptr; int m_totalRowCount = 0; - int m_lastRequestedOffset = 0; QStringList m_userNames; QStringList m_versionDates; TaskTreeRunner m_taskTreeRunner; @@ -257,79 +288,73 @@ IssuesWidget::IssuesWidget(QWidget *parent) : QScrollArea(parent) { QWidget *widget = new QWidget(this); - QVBoxLayout *layout = new QVBoxLayout(widget); // row with issue types (-> depending on choice, tables below change) // and a selectable range (start version, end version) // row with added/removed and some filters (assignee, path glob, (named filter)) // table, columns depend on chosen issue type - QHBoxLayout *top = new QHBoxLayout; - layout->addLayout(top); m_typesButtonGroup = new QButtonGroup(this); m_typesButtonGroup->setExclusive(true); m_typesLayout = new QHBoxLayout; - top->addLayout(m_typesLayout); - top->addStretch(1); + m_versionStart = new QComboBox(this); m_versionStart->setMinimumContentsLength(25); - top->addWidget(m_versionStart); + connect(m_versionStart, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged); + m_versionEnd = new QComboBox(this); m_versionEnd->setMinimumContentsLength(25); - connect(m_versionStart, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged); connect(m_versionEnd, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged); - top->addWidget(m_versionEnd); - top->addStretch(1); - m_filtersLayout = new QHBoxLayout; + m_addedFilter = new QPushButton(this); m_addedFilter->setIcon(trendIcon(1, 0)); m_addedFilter->setText("0"); m_addedFilter->setCheckable(true); - m_filtersLayout->addWidget(m_addedFilter); - m_removedFilter = new QPushButton(this); - m_removedFilter->setIcon(trendIcon(0, 1)); - m_removedFilter->setText("0"); - m_removedFilter->setCheckable(true); - m_filtersLayout->addWidget(m_removedFilter); connect(m_addedFilter, &QPushButton::clicked, this, [this](bool checked) { if (checked && m_removedFilter->isChecked()) m_removedFilter->setChecked(false); onSearchParameterChanged(); }); + + m_removedFilter = new QPushButton(this); + m_removedFilter->setIcon(trendIcon(0, 1)); + m_removedFilter->setText("0"); + m_removedFilter->setCheckable(true); connect(m_removedFilter, &QPushButton::clicked, this, [this](bool checked) { if (checked && m_addedFilter->isChecked()) m_addedFilter->setChecked(false); onSearchParameterChanged(); }); - m_filtersLayout->addSpacing(1); + m_ownerFilter = new QComboBox(this); m_ownerFilter->setToolTip(Tr::tr("Owner")); m_ownerFilter->setMinimumContentsLength(25); connect(m_ownerFilter, &QComboBox::activated, this, &IssuesWidget::onSearchParameterChanged); - m_filtersLayout->addWidget(m_ownerFilter); + m_pathGlobFilter = new QLineEdit(this); m_pathGlobFilter->setPlaceholderText(Tr::tr("Path globbing")); connect(m_pathGlobFilter, &QLineEdit::textEdited, this, &IssuesWidget::onSearchParameterChanged); - m_filtersLayout->addWidget(m_pathGlobFilter); - layout->addLayout(m_filtersLayout); + m_issuesView = new BaseTreeView(this); + m_issuesView->setFrameShape(QFrame::StyledPanel); // Bring back Qt default + m_issuesView->setFrameShadow(QFrame::Sunken); // Bring back Qt default + m_headerView = new IssueHeaderView(this); + connect(m_headerView, &IssueHeaderView::sortTriggered, + this, &IssuesWidget::onSearchParameterChanged); + m_issuesView->setHeader(m_headerView); m_issuesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_issuesView->enableColumnHiding(); - m_issuesModel = new TreeModel; + m_issuesModel = new DynamicListModel(this); m_issuesView->setModel(m_issuesModel); - auto sb = m_issuesView->verticalScrollBar(); - if (QTC_GUARD(sb)) { - connect(sb, &QAbstractSlider::valueChanged, sb, [this, sb](int value) { - if (value >= sb->maximum() - 50) { - if (m_issuesModel->rowCount() < m_totalRowCount) - fetchMoreIssues(); - } - }); - } - layout->addWidget(m_issuesView); + connect(m_issuesModel, &DynamicListModel::fetchRequested, this, &IssuesWidget::onFetchRequested); m_totalRows = new QLabel(Tr::tr("Total rows:"), this); - QHBoxLayout *bottom = new QHBoxLayout; - layout->addLayout(bottom); - bottom->addStretch(1); - bottom->addWidget(m_totalRows); + + using namespace Layouting; + Column { + Row { m_typesLayout, st, m_versionStart, m_versionEnd, st }, + Row { m_addedFilter, m_removedFilter, Space(1), m_ownerFilter, m_pathGlobFilter }, + m_issuesView, + Row { st, m_totalRows } + }.attachTo(widget); + setWidget(widget); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setWidgetResizable(true); @@ -337,7 +362,7 @@ IssuesWidget::IssuesWidget(QWidget *parent) void IssuesWidget::updateUi() { - m_filtersLayout->setEnabled(false); + setFiltersEnabled(false); std::optional projectInfo = Internal::projectInfo(); updateBasicProjectInfo(projectInfo); @@ -347,57 +372,88 @@ void IssuesWidget::updateUi() if (info.versions.empty()) // add some warning/information? return; - m_filtersLayout->setEnabled(true); + setFiltersEnabled(true); // avoid refetching existing data if (!m_currentPrefix.isEmpty() || m_issuesModel->rowCount()) return; if (info.issueKinds.size()) m_currentPrefix = info.issueKinds.front().prefix; - updateTableView(); + fetchTable(); } -void IssuesWidget::setTableDto(const Dto::TableInfoDto &dto) +static Qt::Alignment alignmentFromString(const QString &str) { - m_currentTableInfo.emplace(dto); + if (str == "left") + return Qt::AlignLeft; + if (str == "right") + return Qt::AlignRight; + if (str == "center") + return Qt::AlignHCenter; + return Qt::AlignLeft; +} + +void IssuesWidget::updateTable() +{ + if (!m_currentTableInfo) + return; - // update issues table layout - for now just simple approach - TreeModel<> *issuesModel = new TreeModel; QStringList columnHeaders; QStringList hiddenColumns; - for (const Dto::ColumnInfoDto &column : dto.columns) { + QList sortableColumns; + QList columnWidths; + QList alignments; + for (const Dto::ColumnInfoDto &column : m_currentTableInfo->columns) { columnHeaders << column.header.value_or(column.key); if (!column.showByDefault) hiddenColumns << column.key; + sortableColumns << column.canSort; + columnWidths << column.width; + alignments << alignmentFromString(column.alignment); } m_addedFilter->setText("0"); m_removedFilter->setText("0"); m_totalRows->setText(Tr::tr("Total rows:")); - issuesModel->setHeader(columnHeaders); - - auto oldModel = m_issuesModel; - m_issuesModel = issuesModel; - m_issuesView->setModel(issuesModel); - delete oldModel; + m_issuesModel->clear(); + m_issuesModel->setHeader(columnHeaders); + m_issuesModel->setAlignments(alignments); + m_headerView->setSortableColumns(sortableColumns); + m_headerView->setColumnWidths(columnWidths); int counter = 0; for (const QString &header : std::as_const(columnHeaders)) m_issuesView->setColumnHidden(counter++, hiddenColumns.contains(header)); + m_headerView->resizeSections(QHeaderView::ResizeToContents); } -static Links linksForIssue(const std::map &issueRow) +static QList linksForIssue(const std::map &issueRow, + const std::vector &columnInfos) { - Links links; + QList links; auto end = issueRow.end(); - auto findAndAppend = [&links, &issueRow, &end](const QString &path, const QString &line) { + auto findColumn = [columnInfos](const QString &columnKey) { + int col = 0; + for (auto it = columnInfos.cbegin(), end = columnInfos.cend(); it != end; ++it) { + if (it->key == columnKey) + return col; + ++col; + } + return -1; + }; + auto findAndAppend = [&links, &issueRow, &findColumn, &end](const QString &path, + const QString &line) { + QList columns; auto it = issueRow.find(path); if (it != end) { Link link{ FilePath::fromUserInput(it->second.getString()) }; + columns.append(findColumn(it->first)); it = issueRow.find(line); - if (it != end) + if (it != end) { link.targetLine = it->second.getDouble(); - links.append(link); + columns.append(findColumn(it->first)); + } + links.append({link, columns}); } }; // do these always? or just for their "expected" kind @@ -410,11 +466,12 @@ static Links linksForIssue(const std::map &issueRow) return links; } -void IssuesWidget::addIssues(const Dto::IssueTableDto &dto) +void IssuesWidget::addIssues(const Dto::IssueTableDto &dto, int startRow) { QTC_ASSERT(m_currentTableInfo.has_value(), return); if (dto.totalRowCount.has_value()) { m_totalRowCount = dto.totalRowCount.value(); + m_issuesModel->setExpectedRowCount(m_totalRowCount); m_totalRows->setText(Tr::tr("Total rows:") + ' ' + QString::number(m_totalRowCount)); } if (dto.totalAddedCount.has_value()) @@ -424,21 +481,32 @@ void IssuesWidget::addIssues(const Dto::IssueTableDto &dto) const std::vector &tableColumns = m_currentTableInfo->columns; const std::vector> &rows = dto.rows; + QList items; for (const auto &row : rows) { + QString id; QStringList data; + QStringList toolTips; for (const auto &column : tableColumns) { const auto it = row.find(column.key); if (it != row.end()) { QString value = anyToSimpleString(it->second); - if (column.key == "id") + if (column.key == "id") { value.prepend(m_currentPrefix); + id = value; + } + toolTips << value; + if (column.key.toLower().endsWith("path")) { + const FilePath fp = FilePath::fromUserInput(value); + value = QString("%1 [%2]").arg(fp.fileName(), fp.path()); + } data << value; } } - IssueTreeItem *it = new IssueTreeItem(data, data); - it->setLinks(linksForIssue(row)); - m_issuesModel->rootItem()->appendChild(it); + IssueListItem *it = new IssueListItem(startRow++, id, data, toolTips); + it->setLinks(linksForIssue(row, tableColumns)); + items.append(it); } + m_issuesModel->setItems(items); } void IssuesWidget::onSearchParameterChanged() @@ -447,10 +515,9 @@ void IssuesWidget::onSearchParameterChanged() m_removedFilter->setText("0"); m_totalRows->setText(Tr::tr("Total rows:")); - m_issuesModel->rootItem()->removeChildren(); + m_issuesModel->clear(); // new "first" time lookup m_totalRowCount = 0; - m_lastRequestedOffset = 0; IssueListSearch search = searchFromUi(); search.computeTotalRowCount = true; fetchIssues(search); @@ -497,12 +564,12 @@ void IssuesWidget::updateBasicProjectInfo(std::optional inf int buttonId = 0; for (const Dto::IssueKindInfoDto &kind : issueKinds) { auto button = new QToolButton(this); - button->setIcon(iconForIssue(kind.prefix)); + button->setIcon(iconForIssue(kind.getOptionalPrefixEnum())); button->setToolTip(kind.nicePluralName); button->setCheckable(true); connect(button, &QToolButton::clicked, this, [this, prefix = kind.prefix]{ m_currentPrefix = prefix; - updateTableView(); + fetchTable(); }); m_typesButtonGroup->addButton(button, ++buttonId); m_typesLayout->addWidget(button); @@ -534,25 +601,14 @@ void IssuesWidget::updateBasicProjectInfo(std::optional inf m_versionStart->setCurrentIndex(m_versionDates.count() - 1); } -void IssuesWidget::updateTableView() +void IssuesWidget::setFiltersEnabled(bool enabled) { - QTC_ASSERT(!m_currentPrefix.isEmpty(), return); - // fetch table dto and apply, on done fetch first data for the selected issues - const auto tableHandler = [this](const Dto::TableInfoDto &dto) { setTableDto(dto); }; - const auto setupHandler = [this](TaskTree *) { m_issuesView->showProgressIndicator(); }; - const auto doneHandler = [this](DoneWith result) { - if (result == DoneWith::Error) { - m_issuesView->hideProgressIndicator(); - return; - } - // first time lookup... should we cache and maybe represent old data? - m_totalRowCount = 0; - m_lastRequestedOffset = 0; - IssueListSearch search = searchFromUi(); - search.computeTotalRowCount = true; - fetchIssues(search); - }; - m_taskTreeRunner.start(tableInfoRecipe(m_currentPrefix, tableHandler), setupHandler, doneHandler); + m_addedFilter->setEnabled(enabled); + m_removedFilter->setEnabled(enabled); + m_ownerFilter->setEnabled(enabled); + m_versionStart->setEnabled(enabled); + m_versionEnd->setEnabled(enabled); + m_pathGlobFilter->setEnabled(enabled); } IssueListSearch IssuesWidget::searchFromUi() const @@ -570,143 +626,168 @@ IssueListSearch IssuesWidget::searchFromUi() const search.state = "added"; else if (m_removedFilter->isChecked()) search.state = "removed"; + if (int column = m_headerView->currentSortColumn() != -1) { + QTC_ASSERT(m_currentTableInfo, return search); + QTC_ASSERT((ulong)column < m_currentTableInfo->columns.size(), return search); + search.sort = m_currentTableInfo->columns.at(m_headerView->currentSortColumn()).key + + (m_headerView->currentSortOrder() == SortOrder::Ascending ? " asc" : " desc"); + } + return search; } +void IssuesWidget::fetchTable() +{ + QTC_ASSERT(!m_currentPrefix.isEmpty(), return); + // fetch table dto and apply, on done fetch first data for the selected issues + const auto tableHandler = [this](const Dto::TableInfoDto &dto) { + m_currentTableInfo.emplace(dto); + }; + const auto setupHandler = [this](TaskTree *) { + m_totalRowCount = 0; + m_currentTableInfo.reset(); + m_issuesView->showProgressIndicator(); + }; + const auto doneHandler = [this](DoneWith result) { + if (result == DoneWith::Error) { + m_issuesView->hideProgressIndicator(); + return; + } + // first time lookup... should we cache and maybe represent old data? + updateTable(); + IssueListSearch search = searchFromUi(); + search.computeTotalRowCount = true; + fetchIssues(search); + }; + m_taskTreeRunner.start(tableInfoRecipe(m_currentPrefix, tableHandler), setupHandler, doneHandler); +} + void IssuesWidget::fetchIssues(const IssueListSearch &search) { - const auto issuesHandler = [this](const Dto::IssueTableDto &dto) { addIssues(dto); }; + const auto issuesHandler = [this, startRow = search.offset](const Dto::IssueTableDto &dto) { + addIssues(dto, startRow); + }; const auto setupHandler = [this](TaskTree *) { m_issuesView->showProgressIndicator(); }; const auto doneHandler = [this](DoneWith) { m_issuesView->hideProgressIndicator(); }; m_taskTreeRunner.start(issueTableRecipe(search, issuesHandler), setupHandler, doneHandler); } -void IssuesWidget::fetchMoreIssues() +void IssuesWidget::onFetchRequested(int startRow, int limit) { - if (m_lastRequestedOffset == m_issuesModel->rowCount()) + if (m_taskTreeRunner.isRunning()) return; IssueListSearch search = searchFromUi(); - m_lastRequestedOffset = m_issuesModel->rowCount(); - search.offset = m_lastRequestedOffset; + search.offset = startRow; + search.limit = limit; fetchIssues(search); } -AxivionOutputPane::AxivionOutputPane(QObject *parent) - : IOutputPane(parent) +class AxivionOutputPane final : public IOutputPane { - setId("Axivion"); - setDisplayName(Tr::tr("Axivion")); - setPriorityInStatusBar(-50); +public: + explicit AxivionOutputPane(QObject *parent) + : IOutputPane(parent) + { + setId("Axivion"); + setDisplayName(Tr::tr("Axivion")); + setPriorityInStatusBar(-50); - m_outputWidget = new QStackedWidget; - DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget); - m_outputWidget->addWidget(dashboardWidget); - IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget); - m_outputWidget->addWidget(issuesWidget); - QTextBrowser *browser = new QTextBrowser(m_outputWidget); - m_outputWidget->addWidget(browser); -} + m_outputWidget = new QStackedWidget; + DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget); + m_outputWidget->addWidget(dashboardWidget); + IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget); + m_outputWidget->addWidget(issuesWidget); -AxivionOutputPane::~AxivionOutputPane() -{ - if (!m_outputWidget->parent()) - delete m_outputWidget; -} + QPalette pal = m_outputWidget->palette(); + pal.setColor(QPalette::Window, creatorTheme()->color(Theme::Color::BackgroundColorNormal)); + m_outputWidget->setPalette(pal); -QWidget *AxivionOutputPane::outputWidget(QWidget *parent) -{ - if (m_outputWidget) - m_outputWidget->setParent(parent); - else - QTC_CHECK(false); - return m_outputWidget; -} + m_showDashboard = new QToolButton(m_outputWidget); + m_showDashboard->setIcon(Icons::HOME_TOOLBAR.icon()); + m_showDashboard->setToolTip(Tr::tr("Show dashboard")); + m_showDashboard->setCheckable(true); + m_showDashboard->setChecked(true); + connect(m_showDashboard, &QToolButton::clicked, this, [this] { + QTC_ASSERT(m_outputWidget, return); + m_outputWidget->setCurrentIndex(0); + }); -QList AxivionOutputPane::toolBarWidgets() const -{ - QList buttons; - auto showDashboard = new QToolButton(m_outputWidget); - showDashboard->setIcon(Icons::HOME_TOOLBAR.icon()); - showDashboard->setToolTip(Tr::tr("Show dashboard")); - connect(showDashboard, &QToolButton::clicked, this, [this]{ - QTC_ASSERT(m_outputWidget, return); - m_outputWidget->setCurrentIndex(0); - }); - buttons.append(showDashboard); - auto showIssues = new QToolButton(m_outputWidget); - showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon()); - showIssues->setToolTip(Tr::tr("Search for issues")); - connect(showIssues, &QToolButton::clicked, this, [this]{ - QTC_ASSERT(m_outputWidget, return); - m_outputWidget->setCurrentIndex(1); - if (auto issues = static_cast(m_outputWidget->widget(1))) - issues->updateUi(); - }); - buttons.append(showIssues); - return buttons; -} + m_showIssues = new QToolButton(m_outputWidget); + m_showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon()); + m_showIssues->setToolTip(Tr::tr("Search for issues")); + m_showIssues->setCheckable(true); + connect(m_showIssues, &QToolButton::clicked, this, [this] { + QTC_ASSERT(m_outputWidget, return); + m_outputWidget->setCurrentIndex(1); + if (auto issues = static_cast(m_outputWidget->widget(1))) + issues->updateUi(); + }); -void AxivionOutputPane::clearContents() -{ -} - -void AxivionOutputPane::setFocus() -{ -} - -bool AxivionOutputPane::hasFocus() const -{ - return false; -} - -bool AxivionOutputPane::canFocus() const -{ - return true; -} - -bool AxivionOutputPane::canNavigate() const -{ - return true; -} - -bool AxivionOutputPane::canNext() const -{ - return false; -} - -bool AxivionOutputPane::canPrevious() const -{ - return false; -} - -void AxivionOutputPane::goToNext() -{ -} - -void AxivionOutputPane::goToPrev() -{ -} - -void AxivionOutputPane::updateDashboard() -{ - if (auto dashboard = static_cast(m_outputWidget->widget(0))) { - dashboard->updateUi(); - m_outputWidget->setCurrentIndex(0); - if (dashboard->hasProject()) - flash(); + connect(m_outputWidget, &QStackedWidget::currentChanged, this, [this](int idx) { + m_showDashboard->setChecked(idx == 0); + m_showIssues->setChecked(idx == 1); + }); } -} -void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml) -{ - if (auto browser = static_cast(m_outputWidget->widget(2))) { - browser->setText(ruleHtml); - if (!ruleHtml.isEmpty()) { - m_outputWidget->setCurrentIndex(2); - popup(IOutputPane::NoModeSwitch); + ~AxivionOutputPane() + { + if (!m_outputWidget->parent()) + delete m_outputWidget; + } + + QWidget *outputWidget(QWidget *parent) final + { + if (m_outputWidget) + m_outputWidget->setParent(parent); + else + QTC_CHECK(false); + return m_outputWidget; + } + + QList toolBarWidgets() const final + { + return {m_showDashboard, m_showIssues}; + } + + void clearContents() final {} + void setFocus() final {} + bool hasFocus() const final { return false; } + bool canFocus() const final { return true; } + bool canNavigate() const final { return true; } + bool canNext() const final { return false; } + bool canPrevious() const final { return false; } + void goToNext() final {} + void goToPrev() final {} + + void updateDashboard() + { + if (auto dashboard = static_cast(m_outputWidget->widget(0))) { + dashboard->updateUi(); + m_outputWidget->setCurrentIndex(0); + if (dashboard->hasProject()) + flash(); } } + +private: + QStackedWidget *m_outputWidget = nullptr; + QToolButton *m_showDashboard = nullptr; + QToolButton *m_showIssues = nullptr; +}; + + +static QPointer theAxivionOutputPane; + +void setupAxivionOutputPane(QObject *guard) +{ + theAxivionOutputPane = new AxivionOutputPane(guard); +} + +void updateDashboard() +{ + QTC_ASSERT(theAxivionOutputPane, return); + theAxivionOutputPane->updateDashboard(); } } // Axivion::Internal diff --git a/src/plugins/axivion/axivionoutputpane.h b/src/plugins/axivion/axivionoutputpane.h index 140d50b7235..a13b125c183 100644 --- a/src/plugins/axivion/axivionoutputpane.h +++ b/src/plugins/axivion/axivionoutputpane.h @@ -3,38 +3,11 @@ #pragma once -#include - -QT_BEGIN_NAMESPACE -class QStackedWidget; -QT_END_NAMESPACE +#include namespace Axivion::Internal { -class AxivionOutputPane : public Core::IOutputPane -{ - Q_OBJECT -public: - explicit AxivionOutputPane(QObject *parent = nullptr); - ~AxivionOutputPane(); - - // IOutputPane interface - QWidget *outputWidget(QWidget *parent) override; - QList toolBarWidgets() const override; - void clearContents() override; - void setFocus() override; - bool hasFocus() const override; - bool canFocus() const override; - bool canNavigate() const override; - bool canNext() const override; - bool canPrevious() const override; - void goToNext() override; - void goToPrev() override; - - void updateDashboard(); - void updateAndShowRule(const QString &ruleHtml); -private: - QStackedWidget *m_outputWidget = nullptr; -}; +void setupAxivionOutputPane(QObject *guard); +void updateDashboard(); } // Axivion::Internal diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index cd8fca0a0c5..06c0d72aac4 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -7,13 +7,16 @@ #include "axivionprojectsettings.h" #include "axivionsettings.h" #include "axiviontr.h" +#include "credentialquery.h" #include "dashboard/dto.h" #include "dashboard/error.h" #include #include #include +#include #include +#include #include #include @@ -31,19 +34,26 @@ #include #include +#include +#include #include #include #include #include +#include +#include #include #include #include +#include #include +#include #include -constexpr char AxivionTextMarkId[] = "AxivionTextMark"; +constexpr char s_axivionTextMarkId[] = "AxivionTextMark"; +constexpr char s_axivionKeychainService[] = "keychain.axivion.qtcreator"; using namespace Core; using namespace ProjectExplorer; @@ -53,18 +63,21 @@ using namespace Utils; namespace Axivion::Internal { -QIcon iconForIssue(const QString &prefix) +QIcon iconForIssue(const std::optional &issueKind) { - static QHash prefixToIcon; - auto it = prefixToIcon.find(prefix); + if (!issueKind) + return {}; - if (it == prefixToIcon.end()) { - Icon icon({{FilePath::fromString(":/axivion/images/button-" + prefix.toLower() + ".png"), - Theme::PaletteButtonText}}, - Icon::Tint); - it = prefixToIcon.insert(prefix, icon.icon()); - } - return it.value(); + static QHash prefixToIcon; + + auto it = prefixToIcon.constFind(*issueKind); + if (it != prefixToIcon.constEnd()) + return *it; + + const QLatin1String prefix = Dto::IssueKindMeta::enumToStr(*issueKind); + const Icon icon({{FilePath::fromString(":/axivion/images/button-" + prefix + ".png"), + Theme::PaletteButtonText}}, Icon::Tint); + return prefixToIcon.insert(*issueKind, icon.icon()).value(); } QString anyToSimpleString(const Dto::Any &any) @@ -96,6 +109,61 @@ QString anyToSimpleString(const Dto::Any &any) return {}; } +static QString apiTokenDescription() +{ + const QString ua = "Axivion" + QCoreApplication::applicationName() + "Plugin/" + + QCoreApplication::applicationVersion(); + QString user = Utils::qtcEnvironmentVariable("USERNAME"); + if (user.isEmpty()) + user = Utils::qtcEnvironmentVariable("USER"); + return "Automatically created by " + ua + " on " + user + "@" + QSysInfo::machineHostName(); +} + +static QString credentialKey() +{ + const auto escape = [](const QString &string) { + QString escaped = string; + return escaped.replace('\\', "\\\\").replace('@', "\\@"); + }; + return escape(settings().server.username) + '@' + escape(settings().server.dashboard); +} + +template +struct GetDtoStorage +{ + QUrl url; + std::optional credential; + std::optional dtoData; +}; + +template +struct PostDtoStorage +{ + QUrl url; + std::optional credential; + QByteArray csrfToken; + QByteArray writeData; + std::optional dtoData; +}; + +static DashboardInfo toDashboardInfo(const GetDtoStorage &dashboardStorage) +{ + const Dto::DashboardInfoDto &infoDto = *dashboardStorage.dtoData; + const QVersionNumber versionNumber = infoDto.dashboardVersionNumber + ? QVersionNumber::fromString(*infoDto.dashboardVersionNumber) : QVersionNumber(); + + QStringList projects; + QHash projectUrls; + + if (infoDto.projects) { + for (const Dto::ProjectReferenceDto &project : *infoDto.projects) { + projects.push_back(project.name); + projectUrls.insert(project.name, project.url); + } + } + return {dashboardStorage.url, versionNumber, projects, projectUrls, infoDto.checkCredentialsUrl}; +} + QString IssueListSearch::toQuery() const { if (kind.isEmpty()) @@ -118,18 +186,24 @@ QString IssueListSearch::toQuery() const QString::fromUtf8((QUrl::toPercentEncoding(owner))))); } if (!filter_path.isEmpty()) { - result.append(QString("&filter_path=%1").arg( + result.append(QString("&filter_any path=%1").arg( QString::fromUtf8(QUrl::toPercentEncoding(filter_path)))); } if (!state.isEmpty()) result.append(QString("&state=%1").arg(state)); if (computeTotalRowCount) result.append("&computeTotalRowCount=true"); + if (!sort.isEmpty()) + result.append(QString("&sort=%1").arg( + QString::fromUtf8(QUrl::toPercentEncoding(sort)))); return result; } +enum class ServerAccess { Unknown, NoAuthorization, WithAuthorization }; + class AxivionPluginPrivate : public QObject { + Q_OBJECT public: AxivionPluginPrivate(); void handleSslErrors(QNetworkReply *reply, const QList &errors); @@ -141,9 +215,18 @@ public: void clearAllMarks(); void handleIssuesForFile(const Dto::FileViewDto &fileView); void fetchIssueInfo(const QString &id); + void setIssueDetails(const QString &issueDetailsHtml); + void handleAnchorClicked(const QUrl &url); +signals: + void issueDetailsChanged(const QString &issueDetailsHtml); + +public: + // TODO: Should be set to Unknown on server address change in settings. + ServerAccess m_serverAccess = ServerAccess::Unknown; + // TODO: Should be cleared on username change in settings. + std::optional m_apiToken; NetworkAccessManager m_networkAccessManager; - AxivionOutputPane m_axivionOutputPane; std::optional m_dashboardInfo; std::optional m_currentProjectInfo; Project *m_project = nullptr; @@ -158,13 +241,16 @@ static AxivionPluginPrivate *dd = nullptr; class AxivionTextMark : public TextMark { public: - AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue) - : TextMark(filePath, issue.startLine, {Tr::tr("Axivion"), AxivionTextMarkId}) + AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue, + std::optional color) + : TextMark(filePath, issue.startLine, {"Axivion", s_axivionTextMarkId}) { const QString markText = issue.description; const QString id = issue.kind + QString::number(issue.id.value_or(-1)); - setToolTip(id + markText); - setIcon(iconForIssue(issue.kind)); + setToolTip(id + '\n' + markText); + setIcon(iconForIssue(issue.getOptionalKindEnum())); + if (color) + setColor(*color); setPriority(TextMark::NormalPriority); setLineAnnotation(markText); setActionsProvider([id] { @@ -247,7 +333,7 @@ void AxivionPluginPrivate::onStartupProjectChanged(Project *project) m_project = project; clearAllMarks(); m_currentProjectInfo = {}; - m_axivionOutputPane.updateDashboard(); + updateDashboard(); if (!m_project) return; @@ -259,40 +345,39 @@ void AxivionPluginPrivate::onStartupProjectChanged(Project *project) static QUrl urlForProject(const QString &projectName) { - QString dashboard = settings().server.dashboard; - if (!dashboard.endsWith(QLatin1Char('/'))) - dashboard += QLatin1Char('/'); - return QUrl(dashboard).resolved(QStringLiteral("api/projects/")).resolved(projectName); + if (!dd->m_dashboardInfo) + return {}; + return dd->m_dashboardInfo->source.resolved(QString("api/projects/")).resolved(projectName); } static constexpr int httpStatusCodeOk = 200; constexpr char s_htmlContentType[] = "text/html"; constexpr char s_jsonContentType[] = "application/json"; +static bool isServerAccessEstablished() +{ + return dd->m_serverAccess == ServerAccess::NoAuthorization + || (dd->m_serverAccess == ServerAccess::WithAuthorization && dd->m_apiToken); +} + static Group fetchHtmlRecipe(const QUrl &url, const std::function &handler) { - struct StorageData - { - QByteArray credentials; - }; + // TODO: Refactor so that it's a common code with fetchDataRecipe(). + const auto onQuerySetup = [url](NetworkQuery &query) { + if (!isServerAccessEstablished()) + return SetupResult::StopWithError; // TODO: start authorizationRecipe()? - const Storage storage; - - const auto onCredentialSetup = [storage] { - storage->credentials = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8(); - }; - - const auto onQuerySetup = [storage, url](NetworkQuery &query) { QNetworkRequest request(url); request.setRawHeader("Accept", s_htmlContentType); - request.setRawHeader("Authorization", storage->credentials); + if (dd->m_serverAccess == ServerAccess::WithAuthorization && dd->m_apiToken) + request.setRawHeader("Authorization", "AxToken " + *dd->m_apiToken); 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 = [url, handler](const NetworkQuery &query, DoneWith doneWith) { QNetworkReply *reply = query.reply(); const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -309,45 +394,36 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function -static Group fetchDataRecipe(const QUrl &url, - const std::function &handler) +template typename DtoStorageType> +static Group dtoRecipe(const Storage> &dtoStorage) { - struct StorageData - { - QByteArray credentials; - QByteArray serializableData; - }; + const Storage storage; - const Storage storage; - - const auto onCredentialSetup = [storage] { - storage->credentials = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8(); - }; - - const auto onNetworkQuerySetup = [storage, url](NetworkQuery &query) { - QNetworkRequest request(url); + const auto onNetworkQuerySetup = [dtoStorage](NetworkQuery &query) { + QNetworkRequest request(dtoStorage->url); request.setRawHeader("Accept", s_jsonContentType); - request.setRawHeader("Authorization", storage->credentials); + if (dtoStorage->credential) // Unauthorized access otherwise + request.setRawHeader("Authorization", *dtoStorage->credential); const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() + "Plugin/" + QCoreApplication::applicationVersion().toUtf8(); request.setRawHeader("X-Axivion-User-Agent", ua); + + if constexpr (std::is_same_v, PostDtoStorage>) { + request.setRawHeader("Content-Type", "application/json"); + request.setRawHeader("AX-CSRF-Token", dtoStorage->csrfToken); + query.setWriteData(dtoStorage->writeData); + query.setOperation(NetworkOperation::Post); + } + query.setRequest(request); query.setNetworkAccessManager(&dd->m_networkAccessManager); - return SetupResult::Continue; }; - const auto onNetworkQueryDone = [storage, url](const NetworkQuery &query, DoneWith doneWith) { + const auto onNetworkQueryDone = [storage, dtoStorage](const NetworkQuery &query, + DoneWith doneWith) { QNetworkReply *reply = query.reply(); const QNetworkReply::NetworkError error = reply->error(); const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -359,7 +435,8 @@ static Group fetchDataRecipe(const QUrl &url, .toLower(); if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk && contentType == s_jsonContentType) { - storage->serializableData = reply->readAll(); + *storage = reply->readAll(); + dtoStorage->url = reply->url(); return DoneResult::Success; } @@ -380,79 +457,269 @@ static Group fetchDataRecipe(const QUrl &url, } return NetworkError(reply->url(), error, reply->errorString()); }; - - MessageManager::writeFlashing(QStringLiteral("Axivion: %1").arg(getError().message())); + MessageManager::writeDisrupting(QString("Axivion: %1").arg(getError().message())); return DoneResult::Error; }; - const auto onDeserializeSetup = [storage](Async &task) { - const auto deserialize = [](QPromise &promise, const QByteArray &input) { - promise.addResult(SerializableType::deserialize(input)); + const auto onDeserializeSetup = [storage](Async> &task) { + const auto deserialize = [](QPromise> &promise, const QByteArray &input) { + promise.addResult(DtoType::deserializeExpected(input)); }; task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer()); - task.setConcurrentCallData(deserialize, storage->serializableData); + task.setConcurrentCallData(deserialize, *storage); }; - const auto onDeserializeDone = [handler](const Async &task, - DoneWith doneWith) { - if (doneWith == DoneWith::Success) - handler(task.future().result()); + const auto onDeserializeDone = [dtoStorage](const Async> &task, + DoneWith doneWith) { + if (doneWith == DoneWith::Success && task.isResultAvailable()) { + const auto result = task.result(); + if (result) { + dtoStorage->dtoData = *result; + return DoneResult::Success; + } + MessageManager::writeFlashing(QString("Axivion: %1").arg(result.error())); + } else { + MessageManager::writeFlashing(QString("Axivion: %1") + .arg(Tr::tr("Unknown Dto structure deserialization error."))); + } + return DoneResult::Error; + }; + + return { + storage, + NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone), + AsyncTask>(onDeserializeSetup, onDeserializeDone) + }; +} + +static QString credentialOperationMessage(CredentialOperation operation) +{ + switch (operation) { + case CredentialOperation::Get: + return Tr::tr("The ApiToken cannot be read in a secure way."); + case CredentialOperation::Set: + return Tr::tr("The ApiToken cannot be stored in a secure way."); + case CredentialOperation::Delete: + return Tr::tr("The ApiToken cannot be deleted in a secure way."); + } + return {}; +} + +static void handleCredentialError(const CredentialQuery &credential) +{ + const QString keyChainMessage = credential.errorString().isEmpty() ? QString() + : QString(" %1").arg(Tr::tr("Key chain message: \"%1\".").arg(credential.errorString())); + MessageManager::writeFlashing(QString("Axivion: %1") + .arg(credentialOperationMessage(credential.operation()) + keyChainMessage)); +} + +static Group authorizationRecipe() +{ + const Storage> unauthorizedDashboardStorage; + const auto onUnauthorizedGroupSetup = [unauthorizedDashboardStorage] { + if (isServerAccessEstablished()) + return SetupResult::StopWithSuccess; + + unauthorizedDashboardStorage->url = QUrl(settings().server.dashboard); + return SetupResult::Continue; + }; + const auto onUnauthorizedGroupDone = [unauthorizedDashboardStorage] { + if (unauthorizedDashboardStorage->dtoData) { + dd->m_serverAccess = ServerAccess::NoAuthorization; + dd->m_dashboardInfo = toDashboardInfo(*unauthorizedDashboardStorage); + } else { + dd->m_serverAccess = ServerAccess::WithAuthorization; + } + return DoneResult::Success; + }; + + const auto onCredentialLoopCondition = [](int) { + return dd->m_serverAccess == ServerAccess::WithAuthorization && !dd->m_apiToken; + }; + const auto onGetCredentialSetup = [](CredentialQuery &credential) { + credential.setOperation(CredentialOperation::Get); + credential.setService(s_axivionKeychainService); + credential.setKey(credentialKey()); + }; + const auto onGetCredentialDone = [](const CredentialQuery &credential, DoneWith result) { + if (result == DoneWith::Success) + dd->m_apiToken = credential.data(); + else + handleCredentialError(credential); + // TODO: In case of an error we are multiplying the ApiTokens on Axivion server for each + // Creator run, but at least things should continue to work OK in the current session. + return DoneResult::Success; + }; + + const Storage passwordStorage; + const Storage> dashboardStorage; + const auto onPasswordGroupSetup = [passwordStorage, dashboardStorage] { + if (dd->m_apiToken) + return SetupResult::StopWithSuccess; + + bool ok = false; + const QString text(Tr::tr("Enter the password for:\nDashboard: %1\nUser: %2") + .arg(settings().server.dashboard, settings().server.username)); + *passwordStorage = QInputDialog::getText(ICore::mainWindow(), + Tr::tr("Axivion Server Password"), text, QLineEdit::Password, {}, &ok); + if (!ok) + return SetupResult::StopWithError; + + const QString credential = settings().server.username + ':' + *passwordStorage; + dashboardStorage->credential = "Basic " + credential.toUtf8().toBase64(); + dashboardStorage->url = QUrl(settings().server.dashboard); + return SetupResult::Continue; + }; + + const Storage> apiTokenStorage; + const auto onApiTokenGroupSetup = [passwordStorage, dashboardStorage, apiTokenStorage] { + if (!dashboardStorage->dtoData) + return SetupResult::StopWithSuccess; + + dd->m_dashboardInfo = toDashboardInfo(*dashboardStorage); + + const Dto::DashboardInfoDto &dashboardDto = *dashboardStorage->dtoData; + if (!dashboardDto.userApiTokenUrl) + return SetupResult::StopWithError; + + apiTokenStorage->credential = dashboardStorage->credential; + apiTokenStorage->url + = dd->m_dashboardInfo->source.resolved(*dashboardDto.userApiTokenUrl); + apiTokenStorage->csrfToken = dashboardDto.csrfToken.toUtf8(); + const Dto::ApiTokenCreationRequestDto requestDto{*passwordStorage, "IdePlugin", + apiTokenDescription(), 0}; + apiTokenStorage->writeData = requestDto.serialize(); + return SetupResult::Continue; + }; + + const auto onSetCredentialSetup = [apiTokenStorage](CredentialQuery &credential) { + if (!apiTokenStorage->dtoData || !apiTokenStorage->dtoData->token) + return SetupResult::StopWithSuccess; + + dd->m_apiToken = apiTokenStorage->dtoData->token->toUtf8(); + credential.setOperation(CredentialOperation::Set); + credential.setService(s_axivionKeychainService); + credential.setKey(credentialKey()); + credential.setData(*dd->m_apiToken); + return SetupResult::Continue; + }; + const auto onSetCredentialDone = [](const CredentialQuery &credential) { + handleCredentialError(credential); + // TODO: In case of an error we are multiplying the ApiTokens on Axivion server for each + // Creator run, but at least things should continue to work OK in the current session. + return DoneResult::Success; + }; + + const auto onDashboardGroupSetup = [dashboardStorage] { + if (dd->m_dashboardInfo || dd->m_serverAccess != ServerAccess::WithAuthorization + || !dd->m_apiToken) { + return SetupResult::StopWithSuccess; // Unauthorized access should have collect dashboard before + } + dashboardStorage->credential = "AxToken " + *dd->m_apiToken; + dashboardStorage->url = QUrl(settings().server.dashboard); + return SetupResult::Continue; + }; + const auto onDeleteCredentialSetup = [dashboardStorage](CredentialQuery &credential) { + if (dashboardStorage->dtoData) { + dd->m_dashboardInfo = toDashboardInfo(*dashboardStorage); + return SetupResult::StopWithSuccess; + } + dd->m_apiToken = {}; + MessageManager::writeFlashing(QString("Axivion: %1") + .arg(Tr::tr("The stored ApiToken is not valid anymore, removing it."))); + credential.setOperation(CredentialOperation::Delete); + credential.setService(s_axivionKeychainService); + credential.setKey(credentialKey()); + return SetupResult::Continue; + }; + + return { + Group { + unauthorizedDashboardStorage, + onGroupSetup(onUnauthorizedGroupSetup), + dtoRecipe(unauthorizedDashboardStorage), + onGroupDone(onUnauthorizedGroupDone) + }, + Group { + LoopUntil(onCredentialLoopCondition), + CredentialQueryTask(onGetCredentialSetup, onGetCredentialDone), + Group { + passwordStorage, + dashboardStorage, + onGroupSetup(onPasswordGroupSetup), + Group { // GET DashboardInfoDto + finishAllAndSuccess, + dtoRecipe(dashboardStorage) + }, + Group { // POST ApiTokenCreationRequestDto, GET ApiTokenInfoDto. + apiTokenStorage, + onGroupSetup(onApiTokenGroupSetup), + dtoRecipe(apiTokenStorage), + CredentialQueryTask(onSetCredentialSetup, onSetCredentialDone, CallDoneIf::Error) + } + }, + Group { + finishAllAndSuccess, + dashboardStorage, + onGroupSetup(onDashboardGroupSetup), + dtoRecipe(dashboardStorage), + CredentialQueryTask(onDeleteCredentialSetup) + } + } + }; +} + +template +static Group fetchDataRecipe(const QUrl &url, const std::function &handler) +{ + const Storage> dtoStorage; + + const auto onDtoSetup = [dtoStorage, url] { + if (!isServerAccessEstablished()) + return SetupResult::StopWithError; + + if (dd->m_serverAccess == ServerAccess::WithAuthorization && dd->m_apiToken) + dtoStorage->credential = "AxToken " + *dd->m_apiToken; + dtoStorage->url = url; + return SetupResult::Continue; + }; + const auto onDtoDone = [dtoStorage, handler] { + if (dtoStorage->dtoData) + handler(*dtoStorage->dtoData); }; const Group recipe { - storage, - Sync(onCredentialSetup), - NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone), - AsyncTask(onDeserializeSetup, onDeserializeDone) - }; - - return recipe; -} - -static DashboardInfo toDashboardInfo(const QUrl &source, const Dto::DashboardInfoDto &infoDto) -{ - const QVersionNumber versionNumber = infoDto.dashboardVersionNumber - ? QVersionNumber::fromString(*infoDto.dashboardVersionNumber) : QVersionNumber(); - - QStringList projects; - QHash projectUrls; - - if (infoDto.projects) { - for (const Dto::ProjectReferenceDto &project : *infoDto.projects) { - projects.push_back(project.name); - projectUrls.insert(project.name, project.url); + authorizationRecipe(), + Group { + dtoStorage, + onGroupSetup(onDtoSetup), + dtoRecipe(dtoStorage), + onGroupDone(onDtoDone) } - } - return {source, versionNumber, projects, projectUrls, infoDto.checkCredentialsUrl}; + }; + return recipe; } Group dashboardInfoRecipe(const DashboardInfoHandler &handler) { const auto onSetup = [handler] { if (dd->m_dashboardInfo) { - if (handler) - handler(*dd->m_dashboardInfo); + handler(*dd->m_dashboardInfo); return SetupResult::StopWithSuccess; } return SetupResult::Continue; }; - const auto onDone = [handler] { - if (handler) - handler(make_unexpected(QString("Error"))); // TODO: Collect error message in the storage. - }; - - const QUrl url(settings().server.dashboard); - - const auto resultHandler = [handler, url](const Dto::DashboardInfoDto &data) { - dd->m_dashboardInfo = toDashboardInfo(url, data); - if (handler) + const auto onDone = [handler](DoneWith result) { + if (result == DoneWith::Success && dd->m_dashboardInfo) handler(*dd->m_dashboardInfo); + else + handler(make_unexpected(QString("Error"))); // TODO: Collect error message in the storage. }; const Group root { onGroupSetup(onSetup), // Stops if cache exists. - fetchDataRecipe(url, resultHandler), - onGroupDone(onDone, CallDoneIf::Error) + authorizationRecipe(), + onGroupDone(onDone) }; return root; } @@ -467,7 +734,6 @@ Group issueTableRecipe(const IssueListSearch &search, const IssueTableHandler &h const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/') .resolved(QString("issues" + query)); - return fetchDataRecipe(url, handler); } @@ -486,10 +752,6 @@ Group issueHtmlRecipe(const QString &issueId, const HtmlHandler &handler) { QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected? - QString dashboard = settings().server.dashboard; - if (!dashboard.endsWith(QLatin1Char('/'))) - dashboard += QLatin1Char('/'); - const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/') .resolved(QString("issues/")) .resolved(QString(issueId + '/')) @@ -506,31 +768,37 @@ void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName) clearAllMarks(); if (projectName.isEmpty()) { m_currentProjectInfo = {}; - m_axivionOutputPane.updateDashboard(); + updateDashboard(); return; } const auto onTaskTreeSetup = [this, projectName](TaskTree &taskTree) { - if (!m_dashboardInfo) + if (!m_dashboardInfo) { + MessageManager::writeDisrupting(QString("Axivion: %1") + .arg(Tr::tr("Fetching DashboardInfo error."))); return SetupResult::StopWithError; + } const auto it = m_dashboardInfo->projectUrls.constFind(projectName); - if (it == m_dashboardInfo->projectUrls.constEnd()) + if (it == m_dashboardInfo->projectUrls.constEnd()) { + MessageManager::writeDisrupting(QString("Axivion: %1") + .arg(Tr::tr("The DashboardInfo doesn't contain project \"%1\".").arg(projectName))); return SetupResult::StopWithError; + } const auto handler = [this](const Dto::ProjectInfoDto &data) { m_currentProjectInfo = data; - m_axivionOutputPane.updateDashboard(); + updateDashboard(); handleOpenedDocs(); }; - const QUrl url(settings().server.dashboard); - taskTree.setRecipe(fetchDataRecipe(url.resolved(*it), handler)); + taskTree.setRecipe( + fetchDataRecipe(m_dashboardInfo->source.resolved(*it), handler)); return SetupResult::Continue; }; const Group root { - dashboardInfoRecipe(), + authorizationRecipe(), TaskTreeTask(onTaskTreeSetup) }; m_taskTreeRunner.start(root); @@ -553,12 +821,19 @@ void AxivionPluginPrivate::fetchIssueInfo(const QString &id) const int idx = htmlText.indexOf("

"); if (idx >= 0) fixedHtml = "" + htmlText.mid(idx); - dd->m_axivionOutputPane.updateAndShowRule(QString::fromUtf8(fixedHtml)); + + NavigationWidget::activateSubWidget("Axivion.Issue", Side::Right); + dd->setIssueDetails(QString::fromUtf8(fixedHtml)); }; m_issueInfoRunner.start(issueHtmlRecipe(id, ruleHandler)); } +void AxivionPluginPrivate::setIssueDetails(const QString &issueDetailsHtml) +{ + emit issueDetailsChanged(issueDetailsHtml); +} + void AxivionPluginPrivate::handleOpenedDocs() { const QList openDocuments = DocumentModel::openedDocuments(); @@ -579,7 +854,8 @@ void AxivionPluginPrivate::onDocumentOpened(IDocument *doc) return; const FilePath filePath = doc->filePath().relativeChildPath(m_project->projectDirectory()); - QTC_ASSERT(!filePath.isEmpty(), return); + if (filePath.isEmpty()) + return; // Empty is fine const auto handler = [this](const Dto::FileViewDto &data) { if (data.lineMarkers.empty()) @@ -610,7 +886,7 @@ void AxivionPluginPrivate::onDocumentClosed(IDocument *doc) const TextMarks &marks = document->marks(); for (TextMark *mark : marks) { - if (mark->category().id == AxivionTextMarkId) + if (mark->category().id == s_axivionTextMarkId) delete mark; } } @@ -625,15 +901,76 @@ void AxivionPluginPrivate::handleIssuesForFile(const Dto::FileViewDto &fileView) return; const FilePath filePath = project->projectDirectory().pathAppended(fileView.fileName); - + std::optional color = std::nullopt; + if (settings().highlightMarks()) + color.emplace(Theme::Color(Theme::Bookmarks_TextMarkColor)); // FIXME! 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, marker); + new AxivionTextMark(filePath, marker, color); } } +void AxivionPluginPrivate::handleAnchorClicked(const QUrl &url) +{ + QTC_ASSERT(dd, return); + QTC_ASSERT(dd->m_project, return); + if (!url.scheme().isEmpty()) { + const QString detail = Tr::tr("The activated link appears to be external.\n" + "Do you want to open \"%1\" with its default application?") + .arg(url.toString()); + const QMessageBox::StandardButton pressed + = CheckableMessageBox::question(Core::ICore::dialogParent(), + Tr::tr("Open External Links"), + detail, + Key("AxivionOpenExternalLinks")); + if (pressed == QMessageBox::Yes) + QDesktopServices::openUrl(url); + return; + } + const QUrlQuery query(url); + if (query.isEmpty()) + return; + Link link; + if (const QString path = query.queryItemValue("filename", QUrl::FullyDecoded); !path.isEmpty()) + link.targetFilePath = m_project->projectDirectory().pathAppended(path); + if (const QString line = query.queryItemValue("line"); !line.isEmpty()) + link.targetLine = line.toInt(); + // column entry is wrong - so, ignore it + if (link.hasValidTarget() && link.targetFilePath.exists()) + EditorManager::openEditorAt(link); +} + +class AxivionIssueWidgetFactory final : public INavigationWidgetFactory +{ +public: + AxivionIssueWidgetFactory() + { + setDisplayName(Tr::tr("Axivion")); + setId("Axivion.Issue"); + setPriority(555); + } + + NavigationView createWidget() final + { + QTC_ASSERT(dd, return {}); + QTextBrowser *browser = new QTextBrowser; + browser->setOpenLinks(false); + NavigationView view; + view.widget = browser; + connect(dd, &AxivionPluginPrivate::issueDetailsChanged, browser, &QTextBrowser::setHtml); + connect(browser, &QTextBrowser::anchorClicked, + dd, &AxivionPluginPrivate::handleAnchorClicked); + return view; + } +}; + +void setupAxivionIssueWidgetFactory() +{ + static AxivionIssueWidgetFactory issueWidgetFactory; +} + class AxivionPlugin final : public ExtensionSystem::IPlugin { Q_OBJECT @@ -648,9 +985,12 @@ class AxivionPlugin final : public ExtensionSystem::IPlugin void initialize() final { + setupAxivionOutputPane(this); + dd = new AxivionPluginPrivate; AxivionProjectSettings::setupProjectPanel(); + setupAxivionIssueWidgetFactory(); connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged, dd, &AxivionPluginPrivate::onStartupProjectChanged); @@ -661,6 +1001,12 @@ class AxivionPlugin final : public ExtensionSystem::IPlugin } }; +void fetchIssueInfo(const QString &id) +{ + QTC_ASSERT(dd, return); + dd->fetchIssueInfo(id); +} + } // Axivion::Internal #include "axivionplugin.moc" diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h index 1d5245a5034..39783a956da 100644 --- a/src/plugins/axivion/axivionplugin.h +++ b/src/plugins/axivion/axivionplugin.h @@ -23,6 +23,8 @@ namespace Utils { class FilePath; } namespace Axivion::Internal { +constexpr int DefaultSearchLimit = 2048; + struct IssueListSearch { QString kind; @@ -31,8 +33,9 @@ struct IssueListSearch QString versionEnd; QString owner; QString filter_path; + QString sort; int offset = 0; - int limit = 150; + int limit = DefaultSearchLimit; bool computeTotalRowCount = false; QString toQuery() const; @@ -70,8 +73,9 @@ void fetchProjectInfo(const QString &projectName); std::optional projectInfo(); bool handleCertificateIssue(); -QIcon iconForIssue(const QString &prefix); +QIcon iconForIssue(const std::optional &issueKind); QString anyToSimpleString(const Dto::Any &any); +void fetchIssueInfo(const QString &id); } // Axivion::Internal diff --git a/src/plugins/axivion/axivionprojectsettings.cpp b/src/plugins/axivion/axivionprojectsettings.cpp index 14d47eca53a..8cd63ba7ac0 100644 --- a/src/plugins/axivion/axivionprojectsettings.cpp +++ b/src/plugins/axivion/axivionprojectsettings.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -117,34 +118,33 @@ AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(Project *project) setUseGlobalSettingsCheckBoxVisible(false); setUseGlobalSettingsLabelVisible(true); setGlobalSettingsId("Axivion.Settings.General"); // FIXME move id to constants - // setup ui - auto verticalLayout = new QVBoxLayout(this); - verticalLayout->setContentsMargins(0, 0, 0, 0); m_linkedProject = new QLabel(this); - verticalLayout->addWidget(m_linkedProject); m_dashboardProjects = new QTreeWidget(this); m_dashboardProjects->setHeaderHidden(true); m_dashboardProjects->setRootIsDecorated(false); - verticalLayout->addWidget(new QLabel(Tr::tr("Dashboard projects:"))); - verticalLayout->addWidget(m_dashboardProjects); m_infoLabel = new InfoLabel(this); m_infoLabel->setVisible(false); - verticalLayout->addWidget(m_infoLabel); - auto horizontalLayout = new QHBoxLayout; - horizontalLayout->setContentsMargins(0, 0, 0, 0); m_fetchProjects = new QPushButton(Tr::tr("Fetch Projects")); - horizontalLayout->addWidget(m_fetchProjects); + m_link = new QPushButton(Tr::tr("Link Project")); m_link->setEnabled(false); - horizontalLayout->addWidget(m_link); + m_unlink = new QPushButton(Tr::tr("Unlink Project")); m_unlink->setEnabled(false); - horizontalLayout->addWidget(m_unlink); - verticalLayout->addLayout(horizontalLayout); + + using namespace Layouting; + Column { + noMargin, + m_linkedProject, + Tr::tr("Dashboard projects:"), + m_dashboardProjects, + m_infoLabel, + Row { m_fetchProjects, m_link, m_unlink, st } + }.attachTo(this); connect(m_dashboardProjects, &QTreeWidget::itemSelectionChanged, this, &AxivionProjectSettingsWidget::updateEnabledStates); @@ -220,8 +220,7 @@ void AxivionProjectSettingsWidget::updateUi() void AxivionProjectSettingsWidget::updateEnabledStates() { - const bool hasDashboardSettings = !settings().server.dashboard.isEmpty() - && !settings().server.token.isEmpty(); + const bool hasDashboardSettings = !settings().server.dashboard.isEmpty(); const bool linked = !m_projectSettings->dashboardProjectName().isEmpty(); const bool linkable = m_dashboardProjects->topLevelItemCount() && !m_dashboardProjects->selectedItems().isEmpty(); diff --git a/src/plugins/axivion/axivionsettings.cpp b/src/plugins/axivion/axivionsettings.cpp index 3d95673b9c0..9b24fa51f02 100644 --- a/src/plugins/axivion/axivionsettings.cpp +++ b/src/plugins/axivion/axivionsettings.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -25,18 +26,9 @@ using namespace Utils; namespace Axivion::Internal { -AxivionServer::AxivionServer(const Id &id, const QString &dashboard, - const QString &description, const QString &token) - : id(id) - , dashboard(dashboard) - , description(description) - , token(token) -{} - bool AxivionServer::operator==(const AxivionServer &other) const { - return id == other.id && dashboard == other.dashboard - && description == other.description && token == other.token; + return id == other.id && dashboard == other.dashboard && username == other.username; } bool AxivionServer::operator!=(const AxivionServer &other) const @@ -49,11 +41,16 @@ QJsonObject AxivionServer::toJson() const QJsonObject result; result.insert("id", id.toString()); result.insert("dashboard", dashboard); - result.insert("description", description); - result.insert("token", token); + result.insert("username", username); return result; } +static QString fixUrl(const QString &url) +{ + const QString trimmed = Utils::trimBack(url, ' '); + return trimmed.endsWith('/') ? trimmed : trimmed + '/'; +} + AxivionServer AxivionServer::fromJson(const QJsonObject &json) { const AxivionServer invalidServer; @@ -63,14 +60,10 @@ AxivionServer AxivionServer::fromJson(const QJsonObject &json) const QJsonValue dashboard = json.value("dashboard"); if (dashboard == QJsonValue::Undefined) return invalidServer; - const QJsonValue description = json.value("description"); - if (description == QJsonValue::Undefined) + const QJsonValue username = json.value("username"); + if (username == QJsonValue::Undefined) return invalidServer; - const QJsonValue token = json.value("token"); - if (token == QJsonValue::Undefined) - return invalidServer; - return { Id::fromString(id.toString()), dashboard.toString(), - description.toString(), token.toString() }; + return {Id::fromString(id.toString()), fixUrl(dashboard.toString()), username.toString()}; } static FilePath tokensFilePath() @@ -113,6 +106,10 @@ AxivionSettings::AxivionSettings() { setSettingsGroup("Axivion"); + highlightMarks.setSettingsKey("HighlightMarks"); + highlightMarks.setLabelText(Tr::tr("Highlight marks")); + highlightMarks.setToolTip(Tr::tr("Marks issues on the scroll bar.")); + highlightMarks.setDefaultValue(false); AspectContainer::readSettings(); server = readTokenFile(tokensFilePath()); @@ -164,8 +161,7 @@ private: Mode m_mode = Display; Id m_id; StringAspect m_dashboardUrl; - StringAspect m_description; - StringAspect m_token; + StringAspect m_username; BoolAspect m_valid; }; @@ -176,25 +172,20 @@ DashboardSettingsWidget::DashboardSettingsWidget(Mode mode, QWidget *parent, QPu auto labelStyle = mode == Display ? StringAspect::LabelDisplay : StringAspect::LineEditDisplay; m_dashboardUrl.setLabelText(Tr::tr("Dashboard URL:")); m_dashboardUrl.setDisplayStyle(labelStyle); - m_dashboardUrl.setValidationFunction([](FancyLineEdit *edit, QString *){ + m_dashboardUrl.setValidationFunction([](FancyLineEdit *edit, QString *) { return isUrlValid(edit->text()); }); - m_description.setLabelText(Tr::tr("Description:")); - m_description.setDisplayStyle(labelStyle); - m_description.setPlaceHolderText(Tr::tr("Non-empty description")); - m_token.setLabelText(Tr::tr("Access token:")); - m_token.setDisplayStyle(labelStyle); - m_token.setPlaceHolderText(Tr::tr("IDE Access Token")); - m_token.setVisible(mode == Edit); + m_username.setLabelText(Tr::tr("Username:")); + m_username.setDisplayStyle(labelStyle); + m_username.setPlaceHolderText(Tr::tr("User name")); using namespace Layouting; Form { m_dashboardUrl, br, - m_description, br, - m_token, br, - mode == Edit ? normalMargin : noMargin + m_username, br, + noMargin }.attachTo(this); if (mode == Edit) { @@ -204,8 +195,7 @@ DashboardSettingsWidget::DashboardSettingsWidget(Mode mode, QWidget *parent, QPu ok->setEnabled(m_valid()); }; connect(&m_dashboardUrl, &BaseAspect::changed, this, checkValidity); - connect(&m_description, &BaseAspect::changed, this, checkValidity); - connect(&m_token, &BaseAspect::changed, this, checkValidity); + connect(&m_username, &BaseAspect::changed, this, checkValidity); } } @@ -216,9 +206,8 @@ AxivionServer DashboardSettingsWidget::dashboardServer() const result.id = m_id; else result.id = m_mode == Edit ? Id::fromName(QUuid::createUuid().toByteArray()) : m_id; - result.dashboard = m_dashboardUrl(); - result.description = m_description(); - result.token = m_token(); + result.dashboard = fixUrl(m_dashboardUrl()); + result.username = m_username(); return result; } @@ -226,13 +215,12 @@ void DashboardSettingsWidget::setDashboardServer(const AxivionServer &server) { m_id = server.id; m_dashboardUrl.setValue(server.dashboard); - m_description.setValue(server.description); - m_token.setValue(server.token); + m_username.setValue(server.username); } bool DashboardSettingsWidget::isValid() const { - return !m_token().isEmpty() && !m_description().isEmpty() && isUrlValid(m_dashboardUrl()); + return isUrlValid(m_dashboardUrl()); } class AxivionSettingsWidget : public IOptionsPageWidget @@ -256,10 +244,15 @@ AxivionSettingsWidget::AxivionSettingsWidget() m_dashboardDisplay = new DashboardSettingsWidget(DashboardSettingsWidget::Display, this); m_dashboardDisplay->setDashboardServer(settings().server); m_edit = new QPushButton(Tr::tr("Edit..."), this); - Row { - Form { - m_dashboardDisplay, br, - }, Column { m_edit, st } + Column { + Row { + Form { + m_dashboardDisplay, br + }, st, + Column { m_edit }, + }, + Space(10), br, + Row { settings().highlightMarks }, st }.attachTo(this); connect(m_edit, &QPushButton::clicked, this, &AxivionSettingsWidget::showEditServerDialog); diff --git a/src/plugins/axivion/axivionsettings.h b/src/plugins/axivion/axivionsettings.h index 5f0beb55522..257b4056c56 100644 --- a/src/plugins/axivion/axivionsettings.h +++ b/src/plugins/axivion/axivionsettings.h @@ -17,10 +17,6 @@ namespace Axivion::Internal { class AxivionServer { public: - AxivionServer() = default; - AxivionServer(const Utils::Id &id, const QString &dashboardUrl, - const QString &description, const QString &token); - bool operator==(const AxivionServer &other) const; bool operator!=(const AxivionServer &other) const; @@ -29,8 +25,7 @@ public: Utils::Id id; QString dashboard; - QString description; - QString token; + QString username; bool validateCert = true; }; @@ -43,6 +38,7 @@ public: void toSettings() const; AxivionServer server; // shall we have more than one? + Utils::BoolAspect highlightMarks{this}; }; AxivionSettings &settings(); diff --git a/src/plugins/axivion/axiviontr.h b/src/plugins/axivion/axiviontr.h index 1f3475cb456..48798aaa2ad 100644 --- a/src/plugins/axivion/axiviontr.h +++ b/src/plugins/axivion/axiviontr.h @@ -9,7 +9,7 @@ namespace Axivion { struct Tr { - Q_DECLARE_TR_FUNCTIONS(Axivion) + Q_DECLARE_TR_FUNCTIONS(QtC::Axivion) }; } // Axivion diff --git a/src/plugins/axivion/credentialquery.cpp b/src/plugins/axivion/credentialquery.cpp new file mode 100644 index 00000000000..14aabc3958e --- /dev/null +++ b/src/plugins/axivion/credentialquery.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "credentialquery.h" + +#include + +using namespace QKeychain; +using namespace Tasking; + +namespace Axivion::Internal { + +CredentialQueryTaskAdapter::~CredentialQueryTaskAdapter() = default; + +void CredentialQueryTaskAdapter::start() +{ + Job *job = nullptr; + ReadPasswordJob *reader = nullptr; + + switch (task()->m_operation) { + case CredentialOperation::Get: { + job = reader = new ReadPasswordJob(task()->m_service); + break; + } + case CredentialOperation::Set: { + WritePasswordJob *writer = new WritePasswordJob(task()->m_service); + if (task()->m_data) + writer->setBinaryData(*task()->m_data); + job = writer; + break; + } + case CredentialOperation::Delete: + job = new DeletePasswordJob(task()->m_service); + break; + } + + job->setAutoDelete(false); + job->setKey(task()->m_key); + m_guard.reset(job); + + connect(job, &Job::finished, this, [this, reader](Job *job) { + const bool success = job->error() == NoError || job->error() == EntryNotFound; + if (!success) + task()->m_errorString = job->errorString(); + else if (reader && job->error() == NoError) + task()->m_data = reader->binaryData(); + emit done(toDoneResult(success)); + m_guard.release()->deleteLater(); + }); + job->start(); +} + +} // Axivion::Internal diff --git a/src/plugins/axivion/credentialquery.h b/src/plugins/axivion/credentialquery.h new file mode 100644 index 00000000000..b5ea338c3bd --- /dev/null +++ b/src/plugins/axivion/credentialquery.h @@ -0,0 +1,43 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace Axivion::Internal { + +enum class CredentialOperation { Get, Set, Delete }; + +class CredentialQuery +{ +public: + void setOperation(CredentialOperation operation) { m_operation = operation; } + void setService(const QString &service) { m_service = service; } + void setKey(const QString &key) { m_key = key; } + void setData(const QByteArray &data) { m_data = data; } + + CredentialOperation operation() const { return m_operation; } + std::optional data() const { return m_data; } + QString errorString() const { return m_errorString; } + +private: + CredentialOperation m_operation = CredentialOperation::Get; + QString m_service; + QString m_key; + std::optional m_data; // Used for input when Set and for output when Get. + QString m_errorString; + friend class CredentialQueryTaskAdapter; +}; + +class CredentialQueryTaskAdapter : public Tasking::TaskAdapter +{ +private: + ~CredentialQueryTaskAdapter(); + void start() final; + std::unique_ptr m_guard; +}; + +using CredentialQueryTask = Tasking::CustomTask; + +} // Axivion::Internal diff --git a/src/plugins/axivion/dashboard/dto.cpp b/src/plugins/axivion/dashboard/dto.cpp index 11494e67aef..747ea2d03da 100644 --- a/src/plugins/axivion/dashboard/dto.cpp +++ b/src/plugins/axivion/dashboard/dto.cpp @@ -77,7 +77,8 @@ namespace Axivion::Internal::Dto { // throws Axivion::Internal::Dto::invalid_dto_exception template - [[noreturn]] static void throw_json_type_conversion(QJsonValue::Type type) { + [[noreturn]] static void throw_json_type_conversion(QJsonValue::Type type) + { throw_invalid_dto_exception(concat({ "Error parsing JSON: Cannot convert type ", to_std_string(type) @@ -86,7 +87,8 @@ namespace Axivion::Internal::Dto { // throws Axivion::Internal::Dto::invalid_dto_exception template - [[noreturn]] static void throw_json_value_conversion(const V &raw_value) { + [[noreturn]] static void throw_json_value_conversion(const V &raw_value) + { throw_invalid_dto_exception(concat({ "Error parsing JSON: Cannot convert raw value ", to_std_string(raw_value) @@ -127,6 +129,26 @@ namespace Axivion::Internal::Dto { return de_serializer::deserialize(json); } + template + static Utils::expected_str deserializeExp(const QByteArray &json) + { + try { + return T::deserialize(json); + } catch (const Dto::invalid_dto_exception &e) { + return Utils::make_unexpected(QString::fromUtf8(e.what())); + } + } + + template> + static std::optional strToOptionalEn(QAnyStringView str) + { + try { + return M::strToEnum(str); + } catch (const std::range_error &) { + return std::nullopt; + } + } + // throws Axivion::Internal::Dto::invalid_dto_exception template static T deserialize_bytes(const QByteArray &json) @@ -158,6 +180,7 @@ namespace Axivion::Internal::Dto { return de_serializer::serialize(value); } + // throws std::domain_error template static QByteArray serialize_bytes(const T &value) { @@ -522,7 +545,8 @@ namespace Axivion::Internal::Dto { })); } - static QJsonValue serialize(const Any &value) { + static QJsonValue serialize(const Any &value) + { if (value.isNull()) return serialize_json(nullptr); if (value.isString()) @@ -548,6 +572,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str Any::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + Any::Any() {} Any::Any(QString value) : data(std::move(value)) {} @@ -647,10 +676,10 @@ namespace Axivion::Internal::Dto { // version - constexpr std::array ApiVersion::number{7,7,2,13780}; - const QLatin1String ApiVersion::string{"7.7.2.13780"}; - const QLatin1String ApiVersion::name{"7.7.2"}; - const QLatin1String ApiVersion::timestamp{"2024-01-10 07:39:35 +00:00"}; + constexpr std::array ApiVersion::number{7,7,3,3857}; + const QLatin1String ApiVersion::string{"7.7.3.13857"}; + const QLatin1String ApiVersion::name{"7.7.3"}; + const QLatin1String ApiVersion::timestamp{"2024-02-07 09:28:43 +00:00"}; // AnalyzedFileDto @@ -663,7 +692,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static AnalyzedFileDto deserialize(const QJsonValue &json) { + static AnalyzedFileDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, analyzedFileKeyPath), @@ -672,7 +702,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const AnalyzedFileDto &value) { + static QJsonValue serialize(const AnalyzedFileDto &value) + { QJsonObject jo; serialize_field(jo, analyzedFileKeyPath, value.path); serialize_field(jo, analyzedFileKeyIsSystemHeader, value.isSystemHeader); @@ -690,6 +721,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str AnalyzedFileDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + AnalyzedFileDto::AnalyzedFileDto( QString path, std::optional isSystemHeader, @@ -700,7 +736,6 @@ namespace Axivion::Internal::Dto { languageName(std::move(languageName)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray AnalyzedFileDto::serialize() const { return serialize_bytes(*this); @@ -740,6 +775,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown ApiTokenType str: ", to_std_string(str) })); } + std::optional ApiTokenTypeMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String ApiTokenTypeMeta::enumToStr(ApiTokenType e) { switch (e) @@ -772,7 +812,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ChangePasswordFormDto deserialize(const QJsonValue &json) { + static ChangePasswordFormDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, changePasswordFormKeyCurrentPassword), @@ -780,7 +821,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ChangePasswordFormDto &value) { + static QJsonValue serialize(const ChangePasswordFormDto &value) + { QJsonObject jo; serialize_field(jo, changePasswordFormKeyCurrentPassword, value.currentPassword); serialize_field(jo, changePasswordFormKeyNewPassword, value.newPassword); @@ -797,6 +839,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ChangePasswordFormDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ChangePasswordFormDto::ChangePasswordFormDto( QString currentPassword, QString newPassword @@ -805,7 +852,6 @@ namespace Axivion::Internal::Dto { newPassword(std::move(newPassword)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ChangePasswordFormDto::serialize() const { return serialize_bytes(*this); @@ -860,6 +906,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown ColumnType str: ", to_std_string(str) })); } + std::optional ColumnTypeMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String ColumnTypeMeta::enumToStr(ColumnType e) { switch (e) @@ -899,7 +950,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ColumnTypeOptionDto deserialize(const QJsonValue &json) { + static ColumnTypeOptionDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, columnTypeOptionKeyKey), @@ -908,7 +960,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ColumnTypeOptionDto &value) { + static QJsonValue serialize(const ColumnTypeOptionDto &value) + { QJsonObject jo; serialize_field(jo, columnTypeOptionKeyKey, value.key); serialize_field(jo, columnTypeOptionKeyDisplayName, value.displayName); @@ -926,6 +979,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ColumnTypeOptionDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ColumnTypeOptionDto::ColumnTypeOptionDto( QString key, std::optional displayName, @@ -936,7 +994,6 @@ namespace Axivion::Internal::Dto { displayColor(std::move(displayColor)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ColumnTypeOptionDto::serialize() const { return serialize_bytes(*this); @@ -951,14 +1008,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static CommentRequestDto deserialize(const QJsonValue &json) { + static CommentRequestDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, commentRequestKeyText) }; } - static QJsonValue serialize(const CommentRequestDto &value) { + static QJsonValue serialize(const CommentRequestDto &value) + { QJsonObject jo; serialize_field(jo, commentRequestKeyText, value.text); return { jo }; @@ -974,13 +1033,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str CommentRequestDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + CommentRequestDto::CommentRequestDto( QString text ) : text(std::move(text)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray CommentRequestDto::serialize() const { return serialize_bytes(*this); @@ -995,14 +1058,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static CsrfTokenDto deserialize(const QJsonValue &json) { + static CsrfTokenDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, csrfTokenKeyCsrfToken) }; } - static QJsonValue serialize(const CsrfTokenDto &value) { + static QJsonValue serialize(const CsrfTokenDto &value) + { QJsonObject jo; serialize_field(jo, csrfTokenKeyCsrfToken, value.csrfToken); return { jo }; @@ -1018,13 +1083,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str CsrfTokenDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + CsrfTokenDto::CsrfTokenDto( QString csrfToken ) : csrfToken(std::move(csrfToken)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray CsrfTokenDto::serialize() const { return serialize_bytes(*this); @@ -1043,7 +1112,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static EntityDto deserialize(const QJsonValue &json) { + static EntityDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, entityKeyId), @@ -1054,7 +1124,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const EntityDto &value) { + static QJsonValue serialize(const EntityDto &value) + { QJsonObject jo; serialize_field(jo, entityKeyId, value.id); serialize_field(jo, entityKeyName, value.name); @@ -1074,6 +1145,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str EntityDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + EntityDto::EntityDto( QString id, QString name, @@ -1088,7 +1164,6 @@ namespace Axivion::Internal::Dto { line(std::move(line)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray EntityDto::serialize() const { return serialize_bytes(*this); @@ -1111,7 +1186,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ErrorDto deserialize(const QJsonValue &json) { + static ErrorDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, errorKeyDashboardVersionNumber), @@ -1126,7 +1202,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ErrorDto &value) { + static QJsonValue serialize(const ErrorDto &value) + { QJsonObject jo; serialize_field(jo, errorKeyDashboardVersionNumber, value.dashboardVersionNumber); serialize_field(jo, errorKeyType, value.type); @@ -1150,6 +1227,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ErrorDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ErrorDto::ErrorDto( std::optional dashboardVersionNumber, QString type, @@ -1172,7 +1254,6 @@ namespace Axivion::Internal::Dto { data(std::move(data)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ErrorDto::serialize() const { return serialize_bytes(*this); @@ -1193,7 +1274,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueCommentDto deserialize(const QJsonValue &json) { + static IssueCommentDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueCommentKeyUsername), @@ -1206,7 +1288,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueCommentDto &value) { + static QJsonValue serialize(const IssueCommentDto &value) + { QJsonObject jo; serialize_field(jo, issueCommentKeyUsername, value.username); serialize_field(jo, issueCommentKeyUserDisplayName, value.userDisplayName); @@ -1228,6 +1311,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueCommentDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueCommentDto::IssueCommentDto( QString username, QString userDisplayName, @@ -1246,7 +1334,6 @@ namespace Axivion::Internal::Dto { commentDeletionId(std::move(commentDeletionId)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueCommentDto::serialize() const { return serialize_bytes(*this); @@ -1291,6 +1378,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown IssueKind str: ", to_std_string(str) })); } + std::optional IssueKindMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String IssueKindMeta::enumToStr(IssueKind e) { switch (e) @@ -1359,6 +1451,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown IssueKindForNamedFilterCreation str: ", to_std_string(str) })); } + std::optional IssueKindForNamedFilterCreationMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String IssueKindForNamedFilterCreationMeta::enumToStr(IssueKindForNamedFilterCreation e) { switch (e) @@ -1400,7 +1497,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueSourceLocationDto deserialize(const QJsonValue &json) { + static IssueSourceLocationDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueSourceLocationKeyFileName), @@ -1413,7 +1511,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueSourceLocationDto &value) { + static QJsonValue serialize(const IssueSourceLocationDto &value) + { QJsonObject jo; serialize_field(jo, issueSourceLocationKeyFileName, value.fileName); serialize_field(jo, issueSourceLocationKeyRole, value.role); @@ -1435,6 +1534,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueSourceLocationDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueSourceLocationDto::IssueSourceLocationDto( QString fileName, std::optional role, @@ -1453,7 +1557,6 @@ namespace Axivion::Internal::Dto { endColumn(std::move(endColumn)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueSourceLocationDto::serialize() const { return serialize_bytes(*this); @@ -1469,7 +1572,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueTagDto deserialize(const QJsonValue &json) { + static IssueTagDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueTagKeyTag), @@ -1477,7 +1581,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueTagDto &value) { + static QJsonValue serialize(const IssueTagDto &value) + { QJsonObject jo; serialize_field(jo, issueTagKeyTag, value.tag); serialize_field(jo, issueTagKeyColor, value.color); @@ -1494,6 +1599,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueTagDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueTagDto::IssueTagDto( QString tag, QString color @@ -1502,7 +1612,6 @@ namespace Axivion::Internal::Dto { color(std::move(color)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueTagDto::serialize() const { return serialize_bytes(*this); @@ -1522,7 +1631,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueTagTypeDto deserialize(const QJsonValue &json) { + static IssueTagTypeDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueTagTypeKeyId), @@ -1534,7 +1644,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueTagTypeDto &value) { + static QJsonValue serialize(const IssueTagTypeDto &value) + { QJsonObject jo; serialize_field(jo, issueTagTypeKeyId, value.id); serialize_field(jo, issueTagTypeKeyText, value.text); @@ -1555,6 +1666,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueTagTypeDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueTagTypeDto::IssueTagTypeDto( QString id, std::optional text, @@ -1571,7 +1687,6 @@ namespace Axivion::Internal::Dto { selected(std::move(selected)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueTagTypeDto::serialize() const { return serialize_bytes(*this); @@ -1611,6 +1726,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown MessageSeverity str: ", to_std_string(str) })); } + std::optional MessageSeverityMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String MessageSeverityMeta::enumToStr(MessageSeverity e) { switch (e) @@ -1645,7 +1765,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static MetricDto deserialize(const QJsonValue &json) { + static MetricDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, metricKeyName), @@ -1655,7 +1776,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const MetricDto &value) { + static QJsonValue serialize(const MetricDto &value) + { QJsonObject jo; serialize_field(jo, metricKeyName, value.name); serialize_field(jo, metricKeyDisplayName, value.displayName); @@ -1674,6 +1796,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str MetricDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + MetricDto::MetricDto( QString name, QString displayName, @@ -1686,7 +1813,6 @@ namespace Axivion::Internal::Dto { maxValue(std::move(maxValue)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray MetricDto::serialize() const { return serialize_bytes(*this); @@ -1707,7 +1833,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static MetricValueTableRowDto deserialize(const QJsonValue &json) { + static MetricValueTableRowDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, metricValueTableRowKeyMetric), @@ -1720,7 +1847,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const MetricValueTableRowDto &value) { + static QJsonValue serialize(const MetricValueTableRowDto &value) + { QJsonObject jo; serialize_field(jo, metricValueTableRowKeyMetric, value.metric); serialize_field(jo, metricValueTableRowKeyPath, value.path); @@ -1742,6 +1870,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str MetricValueTableRowDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + MetricValueTableRowDto::MetricValueTableRowDto( QString metric, std::optional path, @@ -1760,7 +1893,6 @@ namespace Axivion::Internal::Dto { entityId(std::move(entityId)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray MetricValueTableRowDto::serialize() const { return serialize_bytes(*this); @@ -1790,6 +1922,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown NamedFilterType str: ", to_std_string(str) })); } + std::optional NamedFilterTypeMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String NamedFilterTypeMeta::enumToStr(NamedFilterType e) { switch (e) @@ -1817,14 +1954,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static NamedFilterVisibilityDto deserialize(const QJsonValue &json) { + static NamedFilterVisibilityDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>>(jo, namedFilterVisibilityKeyGroups) }; } - static QJsonValue serialize(const NamedFilterVisibilityDto &value) { + static QJsonValue serialize(const NamedFilterVisibilityDto &value) + { QJsonObject jo; serialize_field(jo, namedFilterVisibilityKeyGroups, value.groups); return { jo }; @@ -1840,13 +1979,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str NamedFilterVisibilityDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + NamedFilterVisibilityDto::NamedFilterVisibilityDto( std::optional> groups ) : groups(std::move(groups)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray NamedFilterVisibilityDto::serialize() const { return serialize_bytes(*this); @@ -1862,7 +2005,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ProjectReferenceDto deserialize(const QJsonValue &json) { + static ProjectReferenceDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, projectReferenceKeyName), @@ -1870,7 +2014,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ProjectReferenceDto &value) { + static QJsonValue serialize(const ProjectReferenceDto &value) + { QJsonObject jo; serialize_field(jo, projectReferenceKeyName, value.name); serialize_field(jo, projectReferenceKeyUrl, value.url); @@ -1887,6 +2032,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ProjectReferenceDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ProjectReferenceDto::ProjectReferenceDto( QString name, QString url @@ -1895,7 +2045,6 @@ namespace Axivion::Internal::Dto { url(std::move(url)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ProjectReferenceDto::serialize() const { return serialize_bytes(*this); @@ -1912,7 +2061,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static RuleDto deserialize(const QJsonValue &json) { + static RuleDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, ruleKeyName), @@ -1921,7 +2071,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const RuleDto &value) { + static QJsonValue serialize(const RuleDto &value) + { QJsonObject jo; serialize_field(jo, ruleKeyName, value.name); serialize_field(jo, ruleKeyOriginal_name, value.original_name); @@ -1939,6 +2090,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str RuleDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + RuleDto::RuleDto( QString name, QString original_name, @@ -1949,7 +2105,6 @@ namespace Axivion::Internal::Dto { disabled(std::move(disabled)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray RuleDto::serialize() const { return serialize_bytes(*this); @@ -1974,6 +2129,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown SortDirection str: ", to_std_string(str) })); } + std::optional SortDirectionMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String SortDirectionMeta::enumToStr(SortDirection e) { switch (e) @@ -2014,6 +2174,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown TableCellAlignment str: ", to_std_string(str) })); } + std::optional TableCellAlignmentMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String TableCellAlignmentMeta::enumToStr(TableCellAlignment e) { switch (e) @@ -2043,7 +2208,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ToolsVersionDto deserialize(const QJsonValue &json) { + static ToolsVersionDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, toolsVersionKeyName), @@ -2052,7 +2218,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ToolsVersionDto &value) { + static QJsonValue serialize(const ToolsVersionDto &value) + { QJsonObject jo; serialize_field(jo, toolsVersionKeyName, value.name); serialize_field(jo, toolsVersionKeyNumber, value.number); @@ -2070,6 +2237,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ToolsVersionDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ToolsVersionDto::ToolsVersionDto( QString name, QString number, @@ -2080,7 +2252,6 @@ namespace Axivion::Internal::Dto { buildDate(std::move(buildDate)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ToolsVersionDto::serialize() const { return serialize_bytes(*this); @@ -2110,6 +2281,11 @@ namespace Axivion::Internal::Dto { throw std::range_error(concat({ "Unknown UserRefType str: ", to_std_string(str) })); } + std::optional UserRefTypeMeta::strToOptionalEnum(QAnyStringView str) + { + return strToOptionalEn(str); + } + QLatin1String UserRefTypeMeta::enumToStr(UserRefType e) { switch (e) @@ -2139,7 +2315,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static VersionKindCountDto deserialize(const QJsonValue &json) { + static VersionKindCountDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, versionKindCountKeyTotal), @@ -2148,7 +2325,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const VersionKindCountDto &value) { + static QJsonValue serialize(const VersionKindCountDto &value) + { QJsonObject jo; serialize_field(jo, versionKindCountKeyTotal, value.Total); serialize_field(jo, versionKindCountKeyAdded, value.Added); @@ -2166,6 +2344,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str VersionKindCountDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + VersionKindCountDto::VersionKindCountDto( qint32 Total, qint32 Added, @@ -2176,7 +2359,6 @@ namespace Axivion::Internal::Dto { Removed(std::move(Removed)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray VersionKindCountDto::serialize() const { return serialize_bytes(*this); @@ -2199,7 +2381,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static AnalysisVersionDto deserialize(const QJsonValue &json) { + static AnalysisVersionDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, analysisVersionKeyDate), @@ -2214,7 +2397,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const AnalysisVersionDto &value) { + static QJsonValue serialize(const AnalysisVersionDto &value) + { QJsonObject jo; serialize_field(jo, analysisVersionKeyDate, value.date); serialize_field(jo, analysisVersionKeyLabel, value.label); @@ -2238,6 +2422,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str AnalysisVersionDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + AnalysisVersionDto::AnalysisVersionDto( QString date, std::optional label, @@ -2260,7 +2449,6 @@ namespace Axivion::Internal::Dto { cloneRatio(std::move(cloneRatio)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray AnalysisVersionDto::serialize() const { return serialize_bytes(*this); @@ -2278,7 +2466,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ApiTokenCreationRequestDto deserialize(const QJsonValue &json) { + static ApiTokenCreationRequestDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, apiTokenCreationRequestKeyPassword), @@ -2288,7 +2477,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ApiTokenCreationRequestDto &value) { + static QJsonValue serialize(const ApiTokenCreationRequestDto &value) + { QJsonObject jo; serialize_field(jo, apiTokenCreationRequestKeyPassword, value.password); serialize_field(jo, apiTokenCreationRequestKeyType, value.type); @@ -2307,6 +2497,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ApiTokenCreationRequestDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ApiTokenCreationRequestDto::ApiTokenCreationRequestDto( QString password, QString type, @@ -2351,7 +2546,6 @@ namespace Axivion::Internal::Dto { type = ApiTokenTypeMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ApiTokenCreationRequestDto::serialize() const { return serialize_bytes(*this); @@ -2378,7 +2572,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ApiTokenInfoDto deserialize(const QJsonValue &json) { + static ApiTokenInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, apiTokenInfoKeyId), @@ -2397,7 +2592,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ApiTokenInfoDto &value) { + static QJsonValue serialize(const ApiTokenInfoDto &value) + { QJsonObject jo; serialize_field(jo, apiTokenInfoKeyId, value.id); serialize_field(jo, apiTokenInfoKeyUrl, value.url); @@ -2425,6 +2621,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ApiTokenInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ApiTokenInfoDto::ApiTokenInfoDto( QString id, QString url, @@ -2505,7 +2706,6 @@ namespace Axivion::Internal::Dto { type = ApiTokenTypeMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ApiTokenInfoDto::serialize() const { return serialize_bytes(*this); @@ -2529,7 +2729,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ColumnInfoDto deserialize(const QJsonValue &json) { + static ColumnInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, columnInfoKeyKey), @@ -2545,7 +2746,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ColumnInfoDto &value) { + static QJsonValue serialize(const ColumnInfoDto &value) + { QJsonObject jo; serialize_field(jo, columnInfoKeyKey, value.key); serialize_field(jo, columnInfoKeyHeader, value.header); @@ -2570,6 +2772,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ColumnInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ColumnInfoDto::ColumnInfoDto( QString key, std::optional header, @@ -2658,7 +2865,6 @@ namespace Axivion::Internal::Dto { type = ColumnTypeMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ColumnInfoDto::serialize() const { return serialize_bytes(*this); @@ -2687,7 +2893,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static DashboardInfoDto deserialize(const QJsonValue &json) { + static DashboardInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, dashboardInfoKeyMainUrl), @@ -2708,7 +2915,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const DashboardInfoDto &value) { + static QJsonValue serialize(const DashboardInfoDto &value) + { QJsonObject jo; serialize_field(jo, dashboardInfoKeyMainUrl, value.mainUrl); serialize_field(jo, dashboardInfoKeyDashboardVersion, value.dashboardVersion); @@ -2738,6 +2946,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str DashboardInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + DashboardInfoDto::DashboardInfoDto( std::optional mainUrl, QString dashboardVersion, @@ -2772,7 +2985,6 @@ namespace Axivion::Internal::Dto { csrfTokenUrl(std::move(csrfTokenUrl)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray DashboardInfoDto::serialize() const { return serialize_bytes(*this); @@ -2787,14 +2999,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueCommentListDto deserialize(const QJsonValue &json) { + static IssueCommentListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, issueCommentListKeyComments) }; } - static QJsonValue serialize(const IssueCommentListDto &value) { + static QJsonValue serialize(const IssueCommentListDto &value) + { QJsonObject jo; serialize_field(jo, issueCommentListKeyComments, value.comments); return { jo }; @@ -2810,13 +3024,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueCommentListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueCommentListDto::IssueCommentListDto( std::vector comments ) : comments(std::move(comments)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueCommentListDto::serialize() const { return serialize_bytes(*this); @@ -2833,7 +3051,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueKindInfoDto deserialize(const QJsonValue &json) { + static IssueKindInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueKindInfoKeyPrefix), @@ -2842,7 +3061,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueKindInfoDto &value) { + static QJsonValue serialize(const IssueKindInfoDto &value) + { QJsonObject jo; serialize_field(jo, issueKindInfoKeyPrefix, value.prefix); serialize_field(jo, issueKindInfoKeyNiceSingularName, value.niceSingularName); @@ -2860,6 +3080,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueKindInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueKindInfoDto::IssueKindInfoDto( QString prefix, QString niceSingularName, @@ -2900,7 +3125,6 @@ namespace Axivion::Internal::Dto { prefix = IssueKindMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueKindInfoDto::serialize() const { return serialize_bytes(*this); @@ -2915,14 +3139,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueTagTypeListDto deserialize(const QJsonValue &json) { + static IssueTagTypeListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, issueTagTypeListKeyTags) }; } - static QJsonValue serialize(const IssueTagTypeListDto &value) { + static QJsonValue serialize(const IssueTagTypeListDto &value) + { QJsonObject jo; serialize_field(jo, issueTagTypeListKeyTags, value.tags); return { jo }; @@ -2938,13 +3164,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueTagTypeListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueTagTypeListDto::IssueTagTypeListDto( std::vector tags ) : tags(std::move(tags)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueTagTypeListDto::serialize() const { return serialize_bytes(*this); @@ -2967,7 +3197,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static LineMarkerDto deserialize(const QJsonValue &json) { + static LineMarkerDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, lineMarkerKeyKind), @@ -2982,7 +3213,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const LineMarkerDto &value) { + static QJsonValue serialize(const LineMarkerDto &value) + { QJsonObject jo; serialize_field(jo, lineMarkerKeyKind, value.kind); serialize_field(jo, lineMarkerKeyId, value.id); @@ -3006,6 +3238,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str LineMarkerDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + LineMarkerDto::LineMarkerDto( QString kind, std::optional id, @@ -3070,7 +3307,6 @@ namespace Axivion::Internal::Dto { kind = IssueKindMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray LineMarkerDto::serialize() const { return serialize_bytes(*this); @@ -3086,7 +3322,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static RepositoryUpdateMessageDto deserialize(const QJsonValue &json) { + static RepositoryUpdateMessageDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, repositoryUpdateMessageKeySeverity), @@ -3094,7 +3331,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const RepositoryUpdateMessageDto &value) { + static QJsonValue serialize(const RepositoryUpdateMessageDto &value) + { QJsonObject jo; serialize_field(jo, repositoryUpdateMessageKeySeverity, value.severity); serialize_field(jo, repositoryUpdateMessageKeyMessage, value.message); @@ -3111,6 +3349,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str RepositoryUpdateMessageDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + RepositoryUpdateMessageDto::RepositoryUpdateMessageDto( QString severity, QString message @@ -3147,7 +3390,6 @@ namespace Axivion::Internal::Dto { severity = MessageSeverityMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray RepositoryUpdateMessageDto::serialize() const { return serialize_bytes(*this); @@ -3162,14 +3404,16 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static RuleListDto deserialize(const QJsonValue &json) { + static RuleListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, ruleListKeyRules) }; } - static QJsonValue serialize(const RuleListDto &value) { + static QJsonValue serialize(const RuleListDto &value) + { QJsonObject jo; serialize_field(jo, ruleListKeyRules, value.rules); return { jo }; @@ -3185,13 +3429,17 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str RuleListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + RuleListDto::RuleListDto( std::vector rules ) : rules(std::move(rules)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray RuleListDto::serialize() const { return serialize_bytes(*this); @@ -3207,7 +3455,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static SortInfoDto deserialize(const QJsonValue &json) { + static SortInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, sortInfoKeyKey), @@ -3215,7 +3464,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const SortInfoDto &value) { + static QJsonValue serialize(const SortInfoDto &value) + { QJsonObject jo; serialize_field(jo, sortInfoKeyKey, value.key); serialize_field(jo, sortInfoKeyDirection, value.direction); @@ -3232,6 +3482,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str SortInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + SortInfoDto::SortInfoDto( QString key, QString direction @@ -3268,7 +3523,6 @@ namespace Axivion::Internal::Dto { direction = SortDirectionMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray SortInfoDto::serialize() const { return serialize_bytes(*this); @@ -3286,7 +3540,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static UserRefDto deserialize(const QJsonValue &json) { + static UserRefDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, userRefKeyName), @@ -3296,7 +3551,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const UserRefDto &value) { + static QJsonValue serialize(const UserRefDto &value) + { QJsonObject jo; serialize_field(jo, userRefKeyName, value.name); serialize_field(jo, userRefKeyDisplayName, value.displayName); @@ -3315,6 +3571,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str UserRefDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + UserRefDto::UserRefDto( QString name, QString displayName, @@ -3361,7 +3622,6 @@ namespace Axivion::Internal::Dto { type = UserRefTypeMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray UserRefDto::serialize() const { return serialize_bytes(*this); @@ -3377,7 +3637,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static AnalyzedFileListDto deserialize(const QJsonValue &json) { + static AnalyzedFileListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, analyzedFileListKeyVersion), @@ -3385,7 +3646,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const AnalyzedFileListDto &value) { + static QJsonValue serialize(const AnalyzedFileListDto &value) + { QJsonObject jo; serialize_field(jo, analyzedFileListKeyVersion, value.version); serialize_field(jo, analyzedFileListKeyRows, value.rows); @@ -3402,6 +3664,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str AnalyzedFileListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + AnalyzedFileListDto::AnalyzedFileListDto( AnalysisVersionDto version, std::vector rows @@ -3410,7 +3677,6 @@ namespace Axivion::Internal::Dto { rows(std::move(rows)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray AnalyzedFileListDto::serialize() const { return serialize_bytes(*this); @@ -3426,7 +3692,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static EntityListDto deserialize(const QJsonValue &json) { + static EntityListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, entityListKeyVersion), @@ -3434,7 +3701,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const EntityListDto &value) { + static QJsonValue serialize(const EntityListDto &value) + { QJsonObject jo; serialize_field(jo, entityListKeyVersion, value.version); serialize_field(jo, entityListKeyEntities, value.entities); @@ -3451,6 +3719,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str EntityListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + EntityListDto::EntityListDto( std::optional version, std::vector entities @@ -3459,7 +3732,6 @@ namespace Axivion::Internal::Dto { entities(std::move(entities)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray EntityListDto::serialize() const { return serialize_bytes(*this); @@ -3477,7 +3749,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static FileViewDto deserialize(const QJsonValue &json) { + static FileViewDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, fileViewKeyFileName), @@ -3487,7 +3760,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const FileViewDto &value) { + static QJsonValue serialize(const FileViewDto &value) + { QJsonObject jo; serialize_field(jo, fileViewKeyFileName, value.fileName); serialize_field(jo, fileViewKeyVersion, value.version); @@ -3506,6 +3780,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str FileViewDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + FileViewDto::FileViewDto( QString fileName, std::optional version, @@ -3518,7 +3797,6 @@ namespace Axivion::Internal::Dto { lineMarkers(std::move(lineMarkers)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray FileViewDto::serialize() const { return serialize_bytes(*this); @@ -3539,7 +3817,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueDto deserialize(const QJsonValue &json) { + static IssueDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, issueKeyKind), @@ -3552,7 +3831,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueDto &value) { + static QJsonValue serialize(const IssueDto &value) + { QJsonObject jo; serialize_field(jo, issueKeyKind, value.kind); serialize_field(jo, issueKeyId, value.id); @@ -3574,6 +3854,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueDto::IssueDto( QString kind, qint64 id, @@ -3630,7 +3915,6 @@ namespace Axivion::Internal::Dto { kind = IssueKindMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueDto::serialize() const { return serialize_bytes(*this); @@ -3652,7 +3936,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static IssueTableDto deserialize(const QJsonValue &json) { + static IssueTableDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, issueTableKeyStartVersion), @@ -3666,7 +3951,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const IssueTableDto &value) { + static QJsonValue serialize(const IssueTableDto &value) + { QJsonObject jo; serialize_field(jo, issueTableKeyStartVersion, value.startVersion); serialize_field(jo, issueTableKeyEndVersion, value.endVersion); @@ -3689,6 +3975,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str IssueTableDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + IssueTableDto::IssueTableDto( std::optional startVersion, AnalysisVersionDto endVersion, @@ -3709,7 +4000,6 @@ namespace Axivion::Internal::Dto { totalRemovedCount(std::move(totalRemovedCount)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray IssueTableDto::serialize() const { return serialize_bytes(*this); @@ -3725,7 +4015,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static MetricListDto deserialize(const QJsonValue &json) { + static MetricListDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, metricListKeyVersion), @@ -3733,7 +4024,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const MetricListDto &value) { + static QJsonValue serialize(const MetricListDto &value) + { QJsonObject jo; serialize_field(jo, metricListKeyVersion, value.version); serialize_field(jo, metricListKeyMetrics, value.metrics); @@ -3750,6 +4042,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str MetricListDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + MetricListDto::MetricListDto( std::optional version, std::vector metrics @@ -3758,7 +4055,6 @@ namespace Axivion::Internal::Dto { metrics(std::move(metrics)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray MetricListDto::serialize() const { return serialize_bytes(*this); @@ -3777,7 +4073,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static MetricValueRangeDto deserialize(const QJsonValue &json) { + static MetricValueRangeDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, metricValueRangeKeyStartVersion), @@ -3788,7 +4085,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const MetricValueRangeDto &value) { + static QJsonValue serialize(const MetricValueRangeDto &value) + { QJsonObject jo; serialize_field(jo, metricValueRangeKeyStartVersion, value.startVersion); serialize_field(jo, metricValueRangeKeyEndVersion, value.endVersion); @@ -3808,6 +4106,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str MetricValueRangeDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + MetricValueRangeDto::MetricValueRangeDto( AnalysisVersionDto startVersion, AnalysisVersionDto endVersion, @@ -3822,7 +4125,6 @@ namespace Axivion::Internal::Dto { values(std::move(values)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray MetricValueRangeDto::serialize() const { return serialize_bytes(*this); @@ -3838,7 +4140,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static MetricValueTableDto deserialize(const QJsonValue &json) { + static MetricValueTableDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, metricValueTableKeyColumns), @@ -3846,7 +4149,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const MetricValueTableDto &value) { + static QJsonValue serialize(const MetricValueTableDto &value) + { QJsonObject jo; serialize_field(jo, metricValueTableKeyColumns, value.columns); serialize_field(jo, metricValueTableKeyRows, value.rows); @@ -3863,6 +4167,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str MetricValueTableDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + MetricValueTableDto::MetricValueTableDto( std::vector columns, std::vector rows @@ -3871,7 +4180,6 @@ namespace Axivion::Internal::Dto { rows(std::move(rows)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray MetricValueTableDto::serialize() const { return serialize_bytes(*this); @@ -3890,7 +4198,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static NamedFilterCreateDto deserialize(const QJsonValue &json) { + static NamedFilterCreateDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, namedFilterCreateKeyDisplayName), @@ -3901,7 +4210,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const NamedFilterCreateDto &value) { + static QJsonValue serialize(const NamedFilterCreateDto &value) + { QJsonObject jo; serialize_field(jo, namedFilterCreateKeyDisplayName, value.displayName); serialize_field(jo, namedFilterCreateKeyKind, value.kind); @@ -3921,6 +4231,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str NamedFilterCreateDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + NamedFilterCreateDto::NamedFilterCreateDto( QString displayName, QString kind, @@ -3969,7 +4284,6 @@ namespace Axivion::Internal::Dto { kind = IssueKindForNamedFilterCreationMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray NamedFilterCreateDto::serialize() const { return serialize_bytes(*this); @@ -3994,7 +4308,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static NamedFilterInfoDto deserialize(const QJsonValue &json) { + static NamedFilterInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, namedFilterInfoKeyKey), @@ -4011,7 +4326,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const NamedFilterInfoDto &value) { + static QJsonValue serialize(const NamedFilterInfoDto &value) + { QJsonObject jo; serialize_field(jo, namedFilterInfoKeyKey, value.key); serialize_field(jo, namedFilterInfoKeyDisplayName, value.displayName); @@ -4037,6 +4353,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str NamedFilterInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + NamedFilterInfoDto::NamedFilterInfoDto( QString key, QString displayName, @@ -4111,7 +4432,6 @@ namespace Axivion::Internal::Dto { type = NamedFilterTypeMeta::enumToStr(newValue); } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray NamedFilterInfoDto::serialize() const { return serialize_bytes(*this); @@ -4129,7 +4449,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static NamedFilterUpdateDto deserialize(const QJsonValue &json) { + static NamedFilterUpdateDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, namedFilterUpdateKeyName), @@ -4139,7 +4460,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const NamedFilterUpdateDto &value) { + static QJsonValue serialize(const NamedFilterUpdateDto &value) + { QJsonObject jo; serialize_field(jo, namedFilterUpdateKeyName, value.name); serialize_field(jo, namedFilterUpdateKeyFilters, value.filters); @@ -4158,6 +4480,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str NamedFilterUpdateDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + NamedFilterUpdateDto::NamedFilterUpdateDto( std::optional name, std::optional> filters, @@ -4170,7 +4497,6 @@ namespace Axivion::Internal::Dto { visibility(std::move(visibility)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray NamedFilterUpdateDto::serialize() const { return serialize_bytes(*this); @@ -4191,7 +4517,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static ProjectInfoDto deserialize(const QJsonValue &json) { + static ProjectInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, projectInfoKeyName), @@ -4204,7 +4531,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const ProjectInfoDto &value) { + static QJsonValue serialize(const ProjectInfoDto &value) + { QJsonObject jo; serialize_field(jo, projectInfoKeyName, value.name); serialize_field(jo, projectInfoKeyIssueFilterHelp, value.issueFilterHelp); @@ -4226,6 +4554,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str ProjectInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + ProjectInfoDto::ProjectInfoDto( QString name, std::optional issueFilterHelp, @@ -4244,7 +4577,6 @@ namespace Axivion::Internal::Dto { hasHiddenIssues(std::move(hasHiddenIssues)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray ProjectInfoDto::serialize() const { return serialize_bytes(*this); @@ -4261,7 +4593,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static RepositoryUpdateResponseDto deserialize(const QJsonValue &json) { + static RepositoryUpdateResponseDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field>(jo, repositoryUpdateResponseKeyMessages), @@ -4270,7 +4603,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const RepositoryUpdateResponseDto &value) { + static QJsonValue serialize(const RepositoryUpdateResponseDto &value) + { QJsonObject jo; serialize_field(jo, repositoryUpdateResponseKeyMessages, value.messages); serialize_field(jo, repositoryUpdateResponseKeyHasErrors, value.hasErrors); @@ -4288,6 +4622,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str RepositoryUpdateResponseDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + RepositoryUpdateResponseDto::RepositoryUpdateResponseDto( std::vector messages, bool hasErrors, @@ -4298,7 +4637,6 @@ namespace Axivion::Internal::Dto { hasWarnings(std::move(hasWarnings)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray RepositoryUpdateResponseDto::serialize() const { return serialize_bytes(*this); @@ -4318,7 +4656,8 @@ namespace Axivion::Internal::Dto { { public: // throws Axivion::Internal::Dto::invalid_dto_exception - static TableInfoDto deserialize(const QJsonValue &json) { + static TableInfoDto deserialize(const QJsonValue &json) + { const QJsonObject jo = toJsonObject(json); return { deserialize_field(jo, tableInfoKeyTableDataUri), @@ -4330,7 +4669,8 @@ namespace Axivion::Internal::Dto { }; } - static QJsonValue serialize(const TableInfoDto &value) { + static QJsonValue serialize(const TableInfoDto &value) + { QJsonObject jo; serialize_field(jo, tableInfoKeyTableDataUri, value.tableDataUri); serialize_field(jo, tableInfoKeyIssueBaseViewUri, value.issueBaseViewUri); @@ -4351,6 +4691,11 @@ namespace Axivion::Internal::Dto { return deserialize_bytes(json); } + Utils::expected_str TableInfoDto::deserializeExpected(const QByteArray &json) + { + return deserializeExp(json); + } + TableInfoDto::TableInfoDto( QString tableDataUri, std::optional issueBaseViewUri, @@ -4367,7 +4712,6 @@ namespace Axivion::Internal::Dto { axivionDefaultFilter(std::move(axivionDefaultFilter)) { } - // throws Axivion::Internal::Dto::invalid_dto_exception QByteArray TableInfoDto::serialize() const { return serialize_bytes(*this); diff --git a/src/plugins/axivion/dashboard/dto.h b/src/plugins/axivion/dashboard/dto.h index fea5ab4ee18..4543df7d541 100644 --- a/src/plugins/axivion/dashboard/dto.h +++ b/src/plugins/axivion/dashboard/dto.h @@ -14,6 +14,8 @@ * /projects/libs/dashboard_cpp_api/generator/generate_dashboard_cpp_api.py */ +#include + #include #include #include @@ -70,6 +72,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static Any deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + Any(); Any(QString value); @@ -171,6 +175,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static AnalyzedFileDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + AnalyzedFileDto( QString path, std::optional isSystemHeader, @@ -219,6 +225,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static ApiTokenType strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(ApiTokenType e); ApiTokenTypeMeta() = delete; @@ -245,6 +253,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ChangePasswordFormDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ChangePasswordFormDto( QString currentPassword, QString newPassword @@ -295,6 +305,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static ColumnType strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(ColumnType e); ColumnTypeMeta() = delete; @@ -332,6 +344,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ColumnTypeOptionDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ColumnTypeOptionDto( QString key, std::optional displayName, @@ -356,6 +370,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static CommentRequestDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + CommentRequestDto( QString text ); @@ -384,6 +400,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static CsrfTokenDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + CsrfTokenDto( QString csrfToken ); @@ -427,6 +445,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static EntityDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + EntityDto( QString id, QString name, @@ -544,6 +564,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ErrorDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ErrorDto( std::optional dashboardVersionNumber, QString type, @@ -613,6 +635,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueCommentDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueCommentDto( QString username, QString userDisplayName, @@ -654,6 +678,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static IssueKind strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(IssueKind e); IssueKindMeta() = delete; @@ -690,6 +716,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static IssueKindForNamedFilterCreation strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(IssueKindForNamedFilterCreation e); IssueKindForNamedFilterCreationMeta() = delete; @@ -759,6 +787,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueSourceLocationDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueSourceLocationDto( QString fileName, std::optional role, @@ -795,6 +825,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueTagDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueTagDto( QString tag, QString color @@ -851,6 +883,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueTagTypeDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueTagTypeDto( QString id, std::optional text, @@ -893,6 +927,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static MessageSeverity strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(MessageSeverity e); MessageSeverityMeta() = delete; @@ -937,6 +973,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static MetricDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + MetricDto( QString name, QString displayName, @@ -996,6 +1034,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static MetricValueTableRowDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + MetricValueTableRowDto( QString metric, std::optional path, @@ -1033,6 +1073,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static NamedFilterType strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(NamedFilterType e); NamedFilterTypeMeta() = delete; @@ -1062,6 +1104,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static NamedFilterVisibilityDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + NamedFilterVisibilityDto( std::optional> groups ); @@ -1089,6 +1133,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ProjectReferenceDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ProjectReferenceDto( QString name, QString url @@ -1127,6 +1173,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static RuleDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + RuleDto( QString name, QString original_name, @@ -1157,6 +1205,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static SortDirection strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(SortDirection e); SortDirectionMeta() = delete; @@ -1187,6 +1237,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static TableCellAlignment strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(TableCellAlignment e); TableCellAlignmentMeta() = delete; @@ -1218,6 +1270,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ToolsVersionDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ToolsVersionDto( QString name, QString number, @@ -1253,6 +1307,8 @@ namespace Axivion::Internal::Dto // Throws std::range_error static UserRefType strToEnum(QAnyStringView str); + static std::optional strToOptionalEnum(QAnyStringView str); + static QLatin1String enumToStr(UserRefType e); UserRefTypeMeta() = delete; @@ -1284,6 +1340,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static VersionKindCountDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + VersionKindCountDto( qint32 Total, qint32 Added, @@ -1392,6 +1450,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static AnalysisVersionDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + AnalysisVersionDto( QString date, std::optional label, @@ -1450,6 +1510,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ApiTokenCreationRequestDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ApiTokenCreationRequestDto( QString password, QString type, @@ -1568,6 +1630,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ApiTokenInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ApiTokenInfoDto( QString id, QString url, @@ -1693,6 +1757,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ColumnInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ColumnInfoDto( QString key, std::optional header, @@ -1726,7 +1792,7 @@ namespace Axivion::Internal::Dto void setAlignmentEnum(TableCellAlignment newValue); - // Throws std::range_error + // Throws std::range_error ColumnType getTypeEnum() const; std::optional getOptionalTypeEnum() const; @@ -1859,6 +1925,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static DashboardInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + DashboardInfoDto( std::optional mainUrl, QString dashboardVersion, @@ -1895,6 +1963,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueCommentListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueCommentListDto( std::vector comments ); @@ -1929,6 +1999,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueKindInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueKindInfoDto( QString prefix, QString niceSingularName, @@ -1966,6 +2038,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueTagTypeListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueTagTypeListDto( std::vector tags ); @@ -2056,6 +2130,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static LineMarkerDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + LineMarkerDto( QString kind, std::optional id, @@ -2115,6 +2191,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static RepositoryUpdateMessageDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + RepositoryUpdateMessageDto( QString severity, QString message @@ -2150,6 +2228,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static RuleListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + RuleListDto( std::vector rules ); @@ -2179,6 +2259,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static SortInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + SortInfoDto( QString key, QString direction @@ -2235,6 +2317,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static UserRefDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + UserRefDto( QString name, QString displayName, @@ -2279,6 +2363,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static AnalyzedFileListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + AnalyzedFileListDto( AnalysisVersionDto version, std::vector rows @@ -2307,6 +2393,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static EntityListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + EntityListDto( std::optional version, std::vector entities @@ -2355,6 +2443,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static FileViewDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + FileViewDto( QString fileName, std::optional version, @@ -2418,6 +2508,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueDto( QString kind, qint64 id, @@ -2532,6 +2624,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static IssueTableDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + IssueTableDto( std::optional startVersion, AnalysisVersionDto endVersion, @@ -2566,6 +2660,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static MetricListDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + MetricListDto( std::optional version, std::vector metrics @@ -2617,6 +2713,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static MetricValueRangeDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + MetricValueRangeDto( AnalysisVersionDto startVersion, AnalysisVersionDto endVersion, @@ -2650,6 +2748,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static MetricValueTableDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + MetricValueTableDto( std::vector columns, std::vector rows @@ -2712,6 +2812,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static NamedFilterCreateDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + NamedFilterCreateDto( QString displayName, QString kind, @@ -2834,6 +2936,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static NamedFilterInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + NamedFilterInfoDto( QString key, QString displayName, @@ -2924,6 +3028,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static NamedFilterUpdateDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + NamedFilterUpdateDto( std::optional name, std::optional> filters, @@ -2983,6 +3089,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static ProjectInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + ProjectInfoDto( QString name, std::optional issueFilterHelp, @@ -3024,6 +3132,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static RepositoryUpdateResponseDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + RepositoryUpdateResponseDto( std::vector messages, bool hasErrors, @@ -3091,6 +3201,8 @@ namespace Axivion::Internal::Dto // Throws Axivion::Internal::Dto::invalid_dto_exception static TableInfoDto deserialize(const QByteArray &json); + static Utils::expected_str deserializeExpected(const QByteArray &json); + TableInfoDto( QString tableDataUri, std::optional issueBaseViewUri, diff --git a/src/plugins/axivion/dynamiclistmodel.cpp b/src/plugins/axivion/dynamiclistmodel.cpp new file mode 100644 index 00000000000..7c5262132b8 --- /dev/null +++ b/src/plugins/axivion/dynamiclistmodel.cpp @@ -0,0 +1,193 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "dynamiclistmodel.h" + +#include "axivionplugin.h" +#include "axiviontr.h" + +#include +#include + +namespace Axivion::Internal { + +DynamicListModel::DynamicListModel(QObject *parent) + : QAbstractItemModel(parent) +{ + m_fetchMoreTimer.setSingleShot(true); + m_fetchMoreTimer.setInterval(50); + connect(&m_fetchMoreTimer, &QTimer::timeout, this, &DynamicListModel::fetchNow); +} + +DynamicListModel::~DynamicListModel() +{ + clear(); +} + +QModelIndex DynamicListModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) + return {}; + if (row < m_expectedRowCount.value_or(m_children.size())) { + auto it = m_children.constFind(row); + return createIndex(row, column, it != m_children.constEnd() ? it.value() : nullptr); + } + return {}; +} + +QModelIndex DynamicListModel::parent(const QModelIndex &/*child*/) const +{ + return {}; +} + +int DynamicListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) // for simplicity only single level + return 0; + + return m_expectedRowCount.value_or(m_children.size()); +} + +int DynamicListModel::columnCount(const QModelIndex &/*parent*/) const +{ + return m_columnCount; +} + +QVariant DynamicListModel::data(const QModelIndex &index, int role) const +{ + const int row = index.row(); + if (!index.isValid() || row < 0 || row > m_expectedRowCount.value_or(m_children.size())) + return {}; + + auto item = m_children.constFind(row); + if (item != m_children.cend()) { + if (role == Qt::TextAlignmentRole) { + if (!m_alignments.isEmpty() && index.column() < m_alignments.size()) + return QVariant::fromValue(m_alignments.at(index.column())); + } + return item.value()->data(index.column(), role); + } + + if ((row < m_lastFetch || row > m_lastFetchEnd) && (row < m_fetchStart || row > m_fetchEnd)) + const_cast(this)->onNeedFetch(row); + if (role == Qt::DisplayRole && index.column() == 0) + return Tr::tr("Fetching..."); // TODO improve/customize? + if (role == Qt::ForegroundRole && index.column() == 0) + return Utils::creatorTheme()->color(Utils::Theme::TextColorDisabled); + return {}; +} + +bool DynamicListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + auto found = m_children.constFind(index.row()); + if (found == m_children.constEnd()) + return false; + return found.value()->setData(index.column(), value, role); +} + +QVariant DynamicListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < m_header.size()) + return m_header.at(section); + return {}; +} + +void DynamicListModel::setItems(const QList &items) +{ + m_lastFetchEnd = -1; // FIXME wrong.. better a callback? - should happen for failed requests too + // for simplicity we assume an ordered list and no non-existing items between first and last + if (items.isEmpty()) + return; + // to keep it simple here, we expect the expectedRowCount to be set *before* adding items + QTC_ASSERT(m_expectedRowCount, setExpectedRowCount(items.size())); + if (int lastRow = items.last()->row; lastRow > *m_expectedRowCount) + m_expectedRowCount.emplace(lastRow); + + emit layoutAboutToBeChanged(); + auto end = m_children.end(); + for (ListItem *it : items) { + auto found = m_children.find(it->row); // check for old data to be removed + ListItem *old = nullptr; + if (found != end) + old = found.value(); + m_children.insert(it->row, it); + delete old; + } + emit dataChanged(indexForItem(items.first()), indexForItem(items.last())); + emit layoutChanged(); +} + +void DynamicListModel::clear() +{ + beginResetModel(); + qDeleteAll(m_children); + m_children.clear(); + m_expectedRowCount.reset(); + endResetModel(); +} + +void DynamicListModel::setExpectedRowCount(int expected) +{ + QTC_ASSERT(expected >= m_children.size(), return); + if (expected == m_children.size()) + return; + beginInsertRows({}, m_children.size(), expected); + m_expectedRowCount.emplace(expected); + endInsertRows(); +} + +void DynamicListModel::setHeader(const QStringList &header) +{ + m_header = header; + m_columnCount = m_header.size(); +} + +void DynamicListModel::setAlignments(const QList &alignments) +{ + m_alignments = alignments; +} + +QModelIndex DynamicListModel::indexForItem(const ListItem *item) const +{ + QTC_ASSERT(item, return {}); + auto found = m_children.constFind(item->row); + if (found == m_children.cend()) + return {}; + QTC_ASSERT(found.value() == item, return {}); + return createIndex(item->row, 0, item); +} + +void DynamicListModel::onNeedFetch(int row) +{ + m_fetchStart = row; + m_fetchEnd = row + DefaultSearchLimit; + if (m_fetchStart < 0) + return; + m_fetchMoreTimer.start(); +} + +void DynamicListModel::fetchNow() +{ + const int old = m_lastFetch; + m_lastFetch = m_fetchStart; // we need the "original" fetch request to avoid endless loop + m_lastFetchEnd = m_fetchStart + DefaultSearchLimit; + + if (old != -1) { + const int diff = old - m_fetchStart; + if (0 < diff && diff < DefaultSearchLimit) { + m_fetchStart = qMax(old - DefaultSearchLimit, 0); + } else if (0 > diff && diff > - DefaultSearchLimit) { + m_fetchStart = old + DefaultSearchLimit; + if (m_expectedRowCount && m_fetchStart > *m_expectedRowCount) + m_fetchStart = *m_expectedRowCount; + } + } + + QTC_CHECK(m_expectedRowCount ? m_fetchStart <= *m_expectedRowCount + : m_fetchStart >= m_children.size()); + emit fetchRequested(m_fetchStart, DefaultSearchLimit); + m_fetchStart = -1; + m_fetchEnd = -1; +} + +} // namespace Axivion::Internal diff --git a/src/plugins/axivion/dynamiclistmodel.h b/src/plugins/axivion/dynamiclistmodel.h new file mode 100644 index 00000000000..d60f9f16159 --- /dev/null +++ b/src/plugins/axivion/dynamiclistmodel.h @@ -0,0 +1,69 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include +#include +#include +#include + +#include + +namespace Axivion::Internal { + +class ListItem +{ +public: + explicit ListItem(int row) : row(row) {} + virtual ~ListItem() = default; + virtual bool setData(int /*column*/, const QVariant &/*value*/, int /*role*/) { return false; } + virtual QVariant data(int /*column*/, int /*role*/) const { return {}; } + + const int row; +}; + +class DynamicListModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit DynamicListModel(QObject *parent = nullptr); + ~DynamicListModel(); + + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &child) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex&, const QVariant &value, int role) override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + void setItems(const QList &items); + void clear(); + + void setExpectedRowCount(int expected); + void setHeader(const QStringList &header); + void setAlignments(const QList &alignments); + + QModelIndex indexForItem(const ListItem *item) const; + +signals: + void fetchRequested(int startRow, int limit); + +private: + void onNeedFetch(int row); + void fetchNow(); + + QHash m_children; + QStringList m_header; + QList m_alignments; + QTimer m_fetchMoreTimer; + std::optional m_expectedRowCount = {}; + int m_fetchStart = -1; + int m_fetchEnd = -1; + int m_lastFetch = -1; + int m_lastFetchEnd = -1; + int m_columnCount = 0; +}; + +} // namespace Axivion::Internal diff --git a/src/plugins/axivion/images/button-av.png b/src/plugins/axivion/images/button-AV.png similarity index 100% rename from src/plugins/axivion/images/button-av.png rename to src/plugins/axivion/images/button-AV.png diff --git a/src/plugins/axivion/images/button-av@2x.png b/src/plugins/axivion/images/button-AV@2x.png similarity index 100% rename from src/plugins/axivion/images/button-av@2x.png rename to src/plugins/axivion/images/button-AV@2x.png diff --git a/src/plugins/axivion/images/button-cl.png b/src/plugins/axivion/images/button-CL.png similarity index 100% rename from src/plugins/axivion/images/button-cl.png rename to src/plugins/axivion/images/button-CL.png diff --git a/src/plugins/axivion/images/button-cl@2x.png b/src/plugins/axivion/images/button-CL@2x.png similarity index 100% rename from src/plugins/axivion/images/button-cl@2x.png rename to src/plugins/axivion/images/button-CL@2x.png diff --git a/src/plugins/axivion/images/button-cy.png b/src/plugins/axivion/images/button-CY.png similarity index 100% rename from src/plugins/axivion/images/button-cy.png rename to src/plugins/axivion/images/button-CY.png diff --git a/src/plugins/axivion/images/button-cy@2x.png b/src/plugins/axivion/images/button-CY@2x.png similarity index 100% rename from src/plugins/axivion/images/button-cy@2x.png rename to src/plugins/axivion/images/button-CY@2x.png diff --git a/src/plugins/axivion/images/button-de.png b/src/plugins/axivion/images/button-DE.png similarity index 100% rename from src/plugins/axivion/images/button-de.png rename to src/plugins/axivion/images/button-DE.png diff --git a/src/plugins/axivion/images/button-de@2x.png b/src/plugins/axivion/images/button-DE@2x.png similarity index 100% rename from src/plugins/axivion/images/button-de@2x.png rename to src/plugins/axivion/images/button-DE@2x.png diff --git a/src/plugins/axivion/images/button-mv.png b/src/plugins/axivion/images/button-MV.png similarity index 100% rename from src/plugins/axivion/images/button-mv.png rename to src/plugins/axivion/images/button-MV.png diff --git a/src/plugins/axivion/images/button-mv@2x.png b/src/plugins/axivion/images/button-MV@2x.png similarity index 100% rename from src/plugins/axivion/images/button-mv@2x.png rename to src/plugins/axivion/images/button-MV@2x.png diff --git a/src/plugins/axivion/images/button-sv.png b/src/plugins/axivion/images/button-SV.png similarity index 100% rename from src/plugins/axivion/images/button-sv.png rename to src/plugins/axivion/images/button-SV.png diff --git a/src/plugins/axivion/images/button-sv@2x.png b/src/plugins/axivion/images/button-SV@2x.png similarity index 100% rename from src/plugins/axivion/images/button-sv@2x.png rename to src/plugins/axivion/images/button-SV@2x.png diff --git a/src/plugins/axivion/images/sortAsc.png b/src/plugins/axivion/images/sortAsc.png new file mode 100644 index 00000000000..c9072972790 Binary files /dev/null and b/src/plugins/axivion/images/sortAsc.png differ diff --git a/src/plugins/axivion/images/sortAsc@2x.png b/src/plugins/axivion/images/sortAsc@2x.png new file mode 100644 index 00000000000..b99d922b32c Binary files /dev/null and b/src/plugins/axivion/images/sortAsc@2x.png differ diff --git a/src/plugins/axivion/images/sortDesc.png b/src/plugins/axivion/images/sortDesc.png new file mode 100644 index 00000000000..a92d018d4e1 Binary files /dev/null and b/src/plugins/axivion/images/sortDesc.png differ diff --git a/src/plugins/axivion/images/sortDesc@2x.png b/src/plugins/axivion/images/sortDesc@2x.png new file mode 100644 index 00000000000..9991ff2955a Binary files /dev/null and b/src/plugins/axivion/images/sortDesc@2x.png differ diff --git a/src/plugins/axivion/issueheaderview.cpp b/src/plugins/axivion/issueheaderview.cpp new file mode 100644 index 00000000000..ce432eb1265 --- /dev/null +++ b/src/plugins/axivion/issueheaderview.cpp @@ -0,0 +1,148 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "issueheaderview.h" + +#include + +#include +#include + +namespace Axivion::Internal { + +constexpr int ICON_SIZE = 16; + +static QIcon iconForSorted(SortOrder order) +{ + const Utils::Icon UNSORTED( + {{":/axivion/images/sortAsc.png", Utils::Theme::IconsDisabledColor}, + {":/axivion/images/sortDesc.png", Utils::Theme::IconsDisabledColor}}); + const Utils::Icon SORT_ASC( + {{":/axivion/images/sortAsc.png", Utils::Theme::PaletteText}, + {":/axivion/images/sortDesc.png", Utils::Theme::IconsDisabledColor}}); + const Utils::Icon SORT_DESC( + {{":/axivion/images/sortAsc.png", Utils::Theme::IconsDisabledColor}, + {":/axivion/images/sortDesc.png", Utils::Theme::PaletteText}}); + static const QIcon unsorted = UNSORTED.icon(); + static const QIcon sortedAsc = SORT_ASC.icon(); + static const QIcon sortedDesc = SORT_DESC.icon(); + + switch (order) { + case SortOrder::None: + return unsorted; + case SortOrder::Ascending: + return sortedAsc; + case SortOrder::Descending: + return sortedDesc; + } + return {}; +} + +void IssueHeaderView::setSortableColumns(const QList &sortable) +{ + m_sortableColumns = sortable; + int oldIndex = m_currentSortIndex; + m_currentSortIndex = -1; + m_currentSortOrder = SortOrder::None; + if (oldIndex != -1) + headerDataChanged(Qt::Horizontal, oldIndex, oldIndex); +} + +int IssueHeaderView::currentSortColumn() const +{ + return m_currentSortOrder == SortOrder::None ? -1 : m_currentSortIndex; +} + +void IssueHeaderView::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + const QPoint position = event->position().toPoint(); + const int y = position.y(); + if (y > 1 && y < height() - 2) { // TODO improve + const int pos = position.x(); + const int logical = logicalIndexAt(pos); + m_lastToggleLogicalPos = logical; + const int margin = style()->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, this); + const int end = sectionViewportPosition(logical) + sectionSize(logical) - margin; + const int start = end - ICON_SIZE; + m_maybeToggleSort = start < pos && end > pos; + } + } + QHeaderView::mousePressEvent(event); +} + +void IssueHeaderView::mouseReleaseEvent(QMouseEvent *event) +{ + bool dontSkip = !m_dragging && m_maybeToggleSort; + m_dragging = false; + m_maybeToggleSort = false; + + if (dontSkip) { + const QPoint position = event->position().toPoint(); + const int y = position.y(); + const int logical = logicalIndexAt(position.x()); + if (logical == m_lastToggleLogicalPos + && logical > -1 && logical < m_sortableColumns.size()) { + if (m_sortableColumns.at(logical)) { // ignore non-sortable + if (y < height() / 2) // TODO improve + onToggleSort(logical, SortOrder::Ascending); + else + onToggleSort(logical, SortOrder::Descending); + } + } + } + m_lastToggleLogicalPos = -1; + QHeaderView::mouseReleaseEvent(event); +} + +void IssueHeaderView::mouseMoveEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + m_dragging = true; + QHeaderView::mouseMoveEvent(event); +} + +void IssueHeaderView::onToggleSort(int index, SortOrder order) +{ + if (m_currentSortIndex == index) + m_currentSortOrder = (order == m_currentSortOrder) ? SortOrder::None : order; + else + m_currentSortOrder = order; + + int oldIndex = m_currentSortIndex; + m_currentSortIndex = index; + if (oldIndex != -1) + headerDataChanged(Qt::Horizontal, oldIndex, oldIndex); + headerDataChanged(Qt::Horizontal, index, index); + emit sortTriggered(); +} + +QSize IssueHeaderView::sectionSizeFromContents(int logicalIndex) const +{ + const QSize oldSize = QHeaderView::sectionSizeFromContents(logicalIndex); + const QSize newSize = logicalIndex < m_columnWidths.size() + ? QSize(qMax(m_columnWidths.at(logicalIndex), oldSize.width()), oldSize.height()) : oldSize; + + const int margin = style()->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, this); + // add icon size and margin (default resize handle margin + 1) + return QSize{newSize.width() + ICON_SIZE + margin, qMax(newSize.height(), ICON_SIZE)}; +} + +void IssueHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const +{ + painter->save(); + QHeaderView::paintSection(painter, rect, logicalIndex); + painter->restore(); + if (logicalIndex < 0 || logicalIndex >= m_sortableColumns.size()) + return; + if (!m_sortableColumns.at(logicalIndex)) + return; + + const int margin = style()->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, this); + const QIcon icon = iconForSorted(logicalIndex == m_currentSortIndex ? m_currentSortOrder : SortOrder::None); + const int offset = qMax((rect.height() - ICON_SIZE), 0) / 2; + const QRect iconRect(rect.left() + rect.width() - ICON_SIZE - margin, offset, ICON_SIZE, ICON_SIZE); + icon.paint(painter, iconRect); +} + +} // namespace Axivion::Internal diff --git a/src/plugins/axivion/issueheaderview.h b/src/plugins/axivion/issueheaderview.h new file mode 100644 index 00000000000..c1c8230440c --- /dev/null +++ b/src/plugins/axivion/issueheaderview.h @@ -0,0 +1,45 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include +#include + +namespace Axivion::Internal { + +enum class SortOrder { None, Ascending, Descending }; + +class IssueHeaderView : public QHeaderView +{ + Q_OBJECT +public: + explicit IssueHeaderView(QWidget *parent = nullptr) : QHeaderView(Qt::Horizontal, parent) {} + void setSortableColumns(const QList &sortable); + void setColumnWidths(const QList &widths) { m_columnWidths = widths; } + + SortOrder currentSortOrder() const { return m_currentSortOrder; } + int currentSortColumn() const; + +signals: + void sortTriggered(); + +protected: + void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override; + QSize sectionSizeFromContents(int logicalIndex) const override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + +private: + void onToggleSort(int index, SortOrder order); + bool m_dragging = false; + bool m_maybeToggleSort = false; + int m_lastToggleLogicalPos = -1; + int m_currentSortIndex = -1; + SortOrder m_currentSortOrder = SortOrder::None; + QList m_sortableColumns; + QList m_columnWidths; +}; + +} // namespace Axivion::Internal diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index e5e5142370d..46aa5848f7c 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -207,11 +207,11 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP "--clang-tidy=0"}}; if (settings.workerThreadLimit() != 0) cmd.addArg("-j=" + QString::number(settings.workerThreadLimit())); - if (indexingEnabled && settings.clangdVersion() >= QVersionNumber(15)) { + if (indexingEnabled && Utils::clangdVersion(clangdExePath) >= QVersionNumber(15)) { cmd.addArg("--background-index-priority=" + ClangdSettings::priorityToString(indexingPriority)); } - if (settings.clangdVersion() >= QVersionNumber(16)) + if (Utils::clangdVersion(clangdExePath) >= QVersionNumber(16)) cmd.addArg("--rename-file-limit=0"); if (!jsonDbDir.isEmpty()) cmd.addArg("--compile-commands-dir=" + clangdExePath.withNewMappedPath(jsonDbDir).path()); diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp index dd63565bd56..c5bc3d72354 100644 --- a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp +++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp @@ -386,8 +386,6 @@ void doSemanticHighlighting( } if (isOutputParameter(token)) styles.mixinStyles.push_back(C_OUTPUT_ARGUMENT); - qCDebug(clangdLogHighlight) << "adding highlighting result" - << token.line << token.column << token.length << int(styles.mainStyle); return HighlightingResult(token.line, token.column, token.length, styles); }; @@ -420,6 +418,8 @@ void doSemanticHighlighting( } QList virtualRanges; for (const HighlightingResult &r : results) { + qCDebug(clangdLogHighlight) + << '\t' << r.line << r.column << r.length << int(r.textStyles.mainStyle); if (r.textStyles.mainStyle != C_VIRTUAL_METHOD) continue; const Position startPos(r.line - 1, r.column - 1); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 53d0e6f3784..477ab9104b9 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -293,10 +293,7 @@ ClangModelManagerSupport::ClangModelManagerSupport() new ClangdQuickFixFactory(); // memory managed by CppEditor::g_cppQuickFixFactories } -ClangModelManagerSupport::~ClangModelManagerSupport() -{ - m_generatorSynchronizer.waitForFinished(); -} +ClangModelManagerSupport::~ClangModelManagerSupport() = default; void ClangModelManagerSupport::followSymbol(const CursorInEditor &data, const LinkHandler &processLinkCallback, diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index a598bea8bbd..67fc12868cb 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -94,10 +94,10 @@ private: void scheduleClientRestart(ClangdClient *client); static ClangdClient *clientWithProject(const ProjectExplorer::Project *project); - Utils::FutureSynchronizer m_generatorSynchronizer; QList> m_clientsToRestart; QTimer * const m_clientRestartTimer; QHash m_potentialShadowDocuments; + Utils::FutureSynchronizer m_generatorSynchronizer; // Keep me last }; } // namespace Internal diff --git a/src/plugins/clangformat/CMakeLists.txt b/src/plugins/clangformat/CMakeLists.txt index f1dc569333f..30bc50dd2c3 100644 --- a/src/plugins/clangformat/CMakeLists.txt +++ b/src/plugins/clangformat/CMakeLists.txt @@ -1,5 +1,5 @@ add_qtc_plugin(ClangFormat - CONDITION TARGET ${CLANG_FORMAT_LIB} AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 10.0.0 AND (QTC_CLANG_BUILDMODE_MATCH OR CLANGTOOLING_LINK_CLANG_DYLIB) + CONDITION TARGET ${CLANG_FORMAT_LIB} AND LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 14.0.0 AND (QTC_CLANG_BUILDMODE_MATCH OR CLANGTOOLING_LINK_CLANG_DYLIB) DEPENDS Utils Qt::Widgets ${CLANG_FORMAT_LIB} PLUGIN_DEPENDS Core TextEditor CppEditor ProjectExplorer SOURCES diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index 2de357b1124..1d5dc2730c3 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -42,11 +42,7 @@ static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style, ReplacementsToKeep replacementsToKeep) { style.MaxEmptyLinesToKeep = 100; -#if LLVM_VERSION_MAJOR >= 13 style.SortIncludes = clang::format::FormatStyle::SI_Never; -#else - style.SortIncludes = false; -#endif #if LLVM_VERSION_MAJOR >= 16 style.SortUsingDeclarations = clang::format::FormatStyle::SUD_Never; #else diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 98de3370228..99b8302d369 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -227,8 +227,6 @@ void ClangFormatConfigWidget::initEditor(TextEditor::ICodeStylePreferences *code QShortcut *saveSC = new QShortcut(QKeySequence("Ctrl+S"), this); connect(saveSC, &QShortcut::activated, this, [this] { apply(); }); - - m_editorScrollArea->show(); } void ClangFormatConfigWidget::initPreview(TextEditor::ICodeStylePreferences *codeStyle) diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index 6d16ebe9aa1..747c30c2a57 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -42,49 +42,35 @@ clang::format::FormatStyle calculateQtcStyle() #if LLVM_VERSION_MAJOR >= 15 style.AlignConsecutiveAssignments = {false, false, false, false, false}; style.AlignConsecutiveDeclarations = {false, false, false, false, false}; -#elif LLVM_VERSION_MAJOR >= 12 +#else style.AlignConsecutiveAssignments = FormatStyle::ACS_None; style.AlignConsecutiveDeclarations = FormatStyle::ACS_None; -#else - style.AlignConsecutiveAssignments = false; - style.AlignConsecutiveDeclarations = false; #endif style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; -#if LLVM_VERSION_MAJOR >= 11 style.AlignOperands = FormatStyle::OAS_Align; -#else - style.AlignOperands = true; -#endif #if LLVM_VERSION_MAJOR >= 16 style.AlignTrailingComments = {FormatStyle::TCAS_Always, 0}; #else style.AlignTrailingComments = true; #endif style.AllowAllParametersOfDeclarationOnNextLine = true; -#if LLVM_VERSION_MAJOR >= 10 style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; -#else - style.AllowShortBlocksOnASingleLine = false; -#endif style.AllowShortCaseLabelsOnASingleLine = false; style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; -#if LLVM_VERSION_MAJOR >= 9 style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; -#else - style.AllowShortIfStatementsOnASingleLine = false; -#endif style.AllowShortLoopsOnASingleLine = false; - style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; style.AlwaysBreakBeforeMultilineStrings = false; +#if LLVM_VERSION_MAJOR >= 19 + style.BreakAfterReturnType = FormatStyle::RTBS_None; + style.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; +#else + style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; +#endif style.BinPackArguments = false; style.BinPackParameters = false; style.BraceWrapping.AfterClass = true; -#if LLVM_VERSION_MAJOR >= 10 style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Never; -#else - style.BraceWrapping.AfterControlStatement = false; -#endif style.BraceWrapping.AfterEnum = false; style.BraceWrapping.AfterFunction = true; style.BraceWrapping.AfterNamespace = false; @@ -119,11 +105,7 @@ clang::format::FormatStyle calculateQtcStyle() style.ExperimentalAutoDetectBinPacking = false; style.FixNamespaceComments = true; style.ForEachMacros = {"forever", "foreach", "Q_FOREACH", "BOOST_FOREACH"}; -#if LLVM_VERSION_MAJOR >= 12 style.IncludeStyle.IncludeCategories = {{"^= 13 style.SortIncludes = FormatStyle::SI_CaseSensitive; -#else - style.SortIncludes = true; -#endif #if LLVM_VERSION_MAJOR >= 16 style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; #else @@ -166,11 +144,7 @@ clang::format::FormatStyle calculateQtcStyle() style.SpaceInEmptyParentheses = false; #endif style.SpacesBeforeTrailingComments = 1; -#if LLVM_VERSION_MAJOR >= 13 style.SpacesInAngles = FormatStyle::SIAS_Never; -#else - style.SpacesInAngles = false; -#endif style.SpacesInContainerLiterals = false; #if LLVM_VERSION_MAJOR >= 17 style.SpacesInParens = FormatStyle::SIPO_Never; @@ -225,9 +199,7 @@ void fromCppCodeStyleSettings(clang::format::FormatStyle &style, style.BreakBeforeBraces = FormatStyle::BS_Custom; style.IndentCaseLabels = settings.indentSwitchLabels; -#if LLVM_VERSION_MAJOR >= 11 style.IndentCaseBlocks = settings.indentBlocksRelativeToSwitchLabels; -#endif if (settings.extraPaddingForConditionsIfConfusingAlign) style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp index 06cdb8cdd5a..d503f80d63b 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -191,7 +191,7 @@ void DocumentClangToolRunner::run() vfso().update(); const ClangDiagnosticConfig config = diagnosticConfig(runSettings.diagnosticConfigId()); const Environment env = projectBuildEnvironment(project); - QList tasks{parallel}; + QList tasks; const auto addClangTool = [this, &runSettings, &config, &env, &tasks](ClangToolType tool) { if (!toolEnabled(tool, config, runSettings)) return; @@ -204,7 +204,7 @@ void DocumentClangToolRunner::run() if (includeDir.isEmpty() || clangVersion.isEmpty()) return; const AnalyzeUnits units{{m_fileInfo, includeDir, clangVersion}}; - auto diagnosticFilter = [mappedPath = vfso().autoSavedFilePath(m_document)]( + const auto diagnosticFilter = [mappedPath = vfso().autoSavedFilePath(m_document)]( const FilePath &path) { return path == mappedPath; }; const AnalyzeInputData input{tool, runSettings, @@ -225,7 +225,7 @@ void DocumentClangToolRunner::run() return; cleanup.dismiss(); - m_taskTreeRunner.start(tasks); + m_taskTreeRunner.start({parallel, tasks}); } static void updateLocation(Debugger::DiagnosticLocation &location) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 7318c7a791f..25352f0b5d6 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -7,6 +7,7 @@ #include "cmakeprojectconstants.h" #include "cmakeprojectimporter.h" #include "cmakeprojectmanagertr.h" +#include "presetsmacros.h" #include #include @@ -301,6 +302,18 @@ void CMakeProject::readPresets() m_presetsData = combinePresets(cmakePresetsData, cmakeUserPresetsData); setupBuildPresets(m_presetsData); + + for (const auto &configPreset : m_presetsData.configurePresets) { + if (configPreset.hidden.value()) + continue; + + if (configPreset.condition) { + if (!CMakePresets::Macros::evaluatePresetCondition(configPreset, projectFilePath())) + continue; + } + m_presetsData.havePresets = true; + break; + } } bool CMakeProject::setupTarget(Target *t) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index 450d1540102..52ed82f8d77 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -201,8 +201,6 @@ FilePaths CMakeProjectImporter::presetCandidates() } } - m_hasCMakePresets = !candidates.isEmpty(); - return candidates; } @@ -223,7 +221,7 @@ Target *CMakeProjectImporter::preferredTarget(const QList &possibleTar bool CMakeProjectImporter::filter(ProjectExplorer::Kit *k) const { - if (!m_hasCMakePresets) + if (!m_project->presetsData().havePresets) return true; const auto presetConfigItem = CMakeConfigurationKitAspect::cmakePresetConfigItem(k); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h index 82e1835ba7b..63c2403f4b4 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h @@ -49,7 +49,6 @@ private: const CMakeProject *m_project; Utils::TemporaryDirectory m_presetsTempDir; - bool m_hasCMakePresets = false; }; #ifdef WITH_TESTS diff --git a/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp b/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp index d814ee81350..28668b3567d 100644 --- a/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp +++ b/src/plugins/cmakeprojectmanager/cmakespecificsettings.cpp @@ -93,16 +93,16 @@ CMakeSpecificSettings::CMakeSpecificSettings() "UseJunctionsForSourceAndBuildDirectories"); useJunctionsForSourceAndBuildDirectories.setDefaultValue(false); useJunctionsForSourceAndBuildDirectories.setLabelText(::CMakeProjectManager::Tr::tr( - "Use Junctions for CMake configuration and build operations")); + "Use junctions for CMake configuration and build operations")); useJunctionsForSourceAndBuildDirectories.setVisible(Utils::HostOsInfo().isWindowsHost()); useJunctionsForSourceAndBuildDirectories.setToolTip(::CMakeProjectManager::Tr::tr( - "Create and use junctions for the source and build directories. This helps to overcome " + "Create and use junctions for the source and build directories to overcome " "issues with long paths on Windows.

" - "They are stored under C:\\ProgramData\\QtCreator\\Links (overridable via " - "QTC_CMAKE_JUNCTIONS_DIR environment variable).

" - "With QTC_CMAKE_JUNCTIONS_HASH_LENGTH the MD5 hash key length can be shortened " + "Junctions are stored under C:\\ProgramData\\QtCreator\\Links (overridable via " + "the QTC_CMAKE_JUNCTIONS_DIR environment variable).

" + "With QTC_CMAKE_JUNCTIONS_HASH_LENGTH, you can shorten the MD5 hash key length " "to a value smaller than the default length value of 32.

" - "They are used for CMake configure, build and install operations.")); + "Junctions are used for CMake configure, build and install operations.")); readSettings(); } diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp index 16473a6e79a..e20c3c58eba 100644 --- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -69,6 +70,7 @@ typedef struct _REPARSE_DATA_BUFFER { #endif using namespace Core; +using namespace ProjectExplorer; using namespace Utils; namespace CMakeProjectManager { @@ -451,8 +453,19 @@ FilePath CMakeToolManager::mappedFilePath(const FilePath &path) if (path.needsDevice()) return path; - Internal::settings(); - if (!Internal::settings().useJunctionsForSourceAndBuildDirectories()) + auto project = ProjectManager::startupProject(); + auto environment = Environment::systemEnvironment(); + if (project) + environment.modify(project->additionalEnvironment()); + const bool enableJunctions + = QVariant( + environment.value_or("QTC_CMAKE_USE_JUNCTIONS", + Internal::settings().useJunctionsForSourceAndBuildDirectories() + ? "1" + : "0")) + .toBool(); + + if (!enableJunctions) return path; if (!d->m_junctionsDir.isDir()) @@ -583,14 +596,17 @@ CMakeToolManagerPrivate::CMakeToolManagerPrivate() m_junctionsDir = FilePath::fromString(*std::min_element(locations.begin(), locations.end())) .pathAppended("QtCreator/Links"); - if (Utils::qtcEnvironmentVariableIsSet("QTC_CMAKE_JUNCTIONS_DIR")) { - m_junctionsDir = FilePath::fromUserInput( - Utils::qtcEnvironmentVariable("QTC_CMAKE_JUNCTIONS_DIR")); - } - if (Utils::qtcEnvironmentVariableIsSet("QTC_CMAKE_JUNCTIONS_HASH_LENGTH")) { + auto project = ProjectManager::startupProject(); + auto environment = Environment::systemEnvironment(); + if (project) + environment.modify(project->additionalEnvironment()); + + if (environment.hasKey("QTC_CMAKE_JUNCTIONS_DIR")) + m_junctionsDir = FilePath::fromUserInput(environment.value("QTC_CMAKE_JUNCTIONS_DIR")); + + if (environment.hasKey("QTC_CMAKE_JUNCTIONS_HASH_LENGTH")) { bool ok = false; - const int hashLength - = Utils::qtcEnvironmentVariableIntValue("QTC_CMAKE_JUNCTIONS_HASH_LENGTH", &ok); + const int hashLength = environment.value("QTC_CMAKE_JUNCTIONS_HASH_LENGTH").toInt(&ok); if (ok && hashLength >= 4 && hashLength < 32) m_junctionsHashLength = hashLength; } diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index d573fcf6a68..ad1e600124d 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -301,8 +301,24 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, continue; const FilePath buildDir = relativeLibs ? buildDirectory : currentBuildDir; - FilePath tmp = buildDir.resolvePath(part); + std::optional dllName; + if (buildDir.osType() == OsTypeWindows && (f.role == "libraries")) { + // Skip object libraries on Windows. This case can happen with static qml plugins + if (part.endsWith(".obj") || part.endsWith(".o")) + continue; + + // Only consider dlls, not static libraries + for (const QString &suffix : + {QString(".lib"), QString(".dll.a"), QString(".a")}) { + if (part.endsWith(suffix) && !dllName) + dllName = FilePath::fromUserInput( + part.chopped(suffix.length()).append(".dll")) + .fileName(); + } + } + + FilePath tmp = buildDir.resolvePath(part); if (f.role == "libraries") tmp = tmp.parentDir(); @@ -312,19 +328,20 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, // "/usr/local/lib" since these are usually in the standard search // paths. There probably are more, but the naming schemes are arbitrary // so we'd need to ask the linker ("ld --verbose | grep SEARCH_DIR"). - if (buildDir.osType() == OsTypeWindows - || !isChildOf(tmp, - {"/lib", - "/lib64", - "/usr/lib", - "/usr/lib64", - "/usr/local/lib"})) { + if (buildDir.osType() != OsTypeWindows + && !isChildOf(tmp, + {"/lib", "/lib64", "/usr/lib", "/usr/lib64", "/usr/local/lib"})) librarySeachPaths.append(tmp); + + if (buildDir.osType() == OsTypeWindows && dllName) { + if (tmp.pathAppended(*dllName).exists()) + librarySeachPaths.append(tmp); + // Libraries often have their import libs in ../lib and the // actual dll files in ../bin on windows. Qt is one example of that. if (tmp.fileName() == "lib" && buildDir.osType() == OsTypeWindows) { const FilePath path = tmp.parentDir().pathAppended("bin"); - if (path.isDir()) + if (path.isDir() && path.pathAppended(*dllName).exists()) librarySeachPaths.append(path); } } diff --git a/src/plugins/cmakeprojectmanager/presetsparser.h b/src/plugins/cmakeprojectmanager/presetsparser.h index 20d36e389ec..6df09014af3 100644 --- a/src/plugins/cmakeprojectmanager/presetsparser.h +++ b/src/plugins/cmakeprojectmanager/presetsparser.h @@ -140,6 +140,7 @@ class PresetsData { public: int version = 0; + bool havePresets = false; QVersionNumber cmakeMinimimRequired; QHash vendor; std::optional include; diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 914c6f705f0..ebe7ff44753 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -332,11 +332,7 @@ CompilationDatabaseBuildSystem::CompilationDatabaseBuildSystem(Target *target) this, &CompilationDatabaseBuildSystem::updateDeploymentData); } -CompilationDatabaseBuildSystem::~CompilationDatabaseBuildSystem() -{ - m_parserWatcher.cancel(); - m_parserWatcher.waitForFinished(); -} +CompilationDatabaseBuildSystem::~CompilationDatabaseBuildSystem() = default; void CompilationDatabaseBuildSystem::triggerParsing() { diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h index 25561f5aac1..2b8faec0208 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h @@ -13,8 +13,6 @@ #include -#include - namespace ProjectExplorer { class Kit; class ProjectUpdater; @@ -51,7 +49,6 @@ public: void updateDeploymentData(); void buildTreeAndProjectParts(); - QFutureWatcher m_parserWatcher; std::unique_ptr m_cppCodeModelUpdater; MimeBinaryCache m_mimeBinaryCache; QByteArray m_projectFileHash; diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp index 5f860956026..4ab893a9e6c 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp @@ -8,9 +8,12 @@ #include +#include + #include #include +#include #include #include @@ -187,6 +190,7 @@ void CompilationDbParser::start() "CompilationDatabase.Parse"); ++m_runningParserJobs; m_parserWatcher.setFuture(future); + ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(future); } void CompilationDbParser::stop() diff --git a/src/plugins/compilerexplorer/CMakeLists.txt b/src/plugins/compilerexplorer/CMakeLists.txt index 55368044706..361bba8ec76 100644 --- a/src/plugins/compilerexplorer/CMakeLists.txt +++ b/src/plugins/compilerexplorer/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_plugin(CompilerExplorer PLUGIN_DEPENDS Core ProjectExplorer TextEditor - DEPENDS Qt::Network TerminalLib Spinner + DEPENDS Qt::Network TerminalLib SOURCES api/config.h api/compile.cpp diff --git a/src/plugins/compilerexplorer/api/compile.h b/src/plugins/compilerexplorer/api/compile.h index ce346fe2bde..8caefff83bc 100644 --- a/src/plugins/compilerexplorer/api/compile.h +++ b/src/plugins/compilerexplorer/api/compile.h @@ -6,16 +6,12 @@ #include "compiler.h" #include "config.h" -#include "../compilerexploreraspects.h" - -#include -#include - #include #include #include #include -#include +#include +#include namespace CompilerExplorer::Api { diff --git a/src/plugins/compilerexplorer/api/compiler.h b/src/plugins/compilerexplorer/api/compiler.h index 070817206e2..5e728ae19ca 100644 --- a/src/plugins/compilerexplorer/api/compiler.h +++ b/src/plugins/compilerexplorer/api/compiler.h @@ -6,9 +6,7 @@ #include "config.h" #include -#include #include -#include #include #include diff --git a/src/plugins/compilerexplorer/api/language.h b/src/plugins/compilerexplorer/api/language.h index 85780b7466a..431f01d8d36 100644 --- a/src/plugins/compilerexplorer/api/language.h +++ b/src/plugins/compilerexplorer/api/language.h @@ -6,7 +6,6 @@ #include "config.h" #include -#include #include #include diff --git a/src/plugins/compilerexplorer/api/library.h b/src/plugins/compilerexplorer/api/library.h index 07e8a117341..e63ccaf4874 100644 --- a/src/plugins/compilerexplorer/api/library.h +++ b/src/plugins/compilerexplorer/api/library.h @@ -7,7 +7,6 @@ #include #include -#include #include #include diff --git a/src/plugins/compilerexplorer/compilerexplorereditor.cpp b/src/plugins/compilerexplorer/compilerexplorereditor.cpp index 9b9eb242ed9..0defb331636 100644 --- a/src/plugins/compilerexplorer/compilerexplorereditor.cpp +++ b/src/plugins/compilerexplorer/compilerexplorereditor.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plugins/compilerexplorer/compilerexplorersettings.cpp b/src/plugins/compilerexplorer/compilerexplorersettings.cpp index defa10ff698..291624aac40 100644 --- a/src/plugins/compilerexplorer/compilerexplorersettings.cpp +++ b/src/plugins/compilerexplorer/compilerexplorersettings.cpp @@ -12,7 +12,6 @@ #include #include -#include namespace CompilerExplorer { @@ -306,7 +305,6 @@ CompilerExplorerSettings::CompilerExplorerSettings() { setAutoApply(false); setSettingsKey("CompilerExplorer"); - m_networkAccessManager = std::make_unique(); compilerExplorerUrl.setSettingsKey("CompilerExplorerUrl"); compilerExplorerUrl.setLabelText(Tr::tr("Compiler Explorer URL:")); diff --git a/src/plugins/compilerexplorer/compilerexplorersettings.h b/src/plugins/compilerexplorer/compilerexplorersettings.h index e196249d117..4b3ac849a2c 100644 --- a/src/plugins/compilerexplorer/compilerexplorersettings.h +++ b/src/plugins/compilerexplorer/compilerexplorersettings.h @@ -7,11 +7,10 @@ #include "compilerexploreraspects.h" #include +#include #include -#include - namespace CompilerExplorer { class SourceSettings; class CompilerSettings; @@ -40,11 +39,8 @@ public: Api::Config apiConfig() const { - return Api::Config(m_networkAccessManager.get(), compilerExplorerUrl()); + return Api::Config(Utils::NetworkAccessManager::instance(), compilerExplorerUrl()); } - -private: - std::unique_ptr m_networkAccessManager; }; class SourceSettings : public Utils::AspectContainer, diff --git a/src/plugins/coreplugin/core.qrc b/src/plugins/coreplugin/core.qrc index ff855e3f4b8..239bd946121 100644 --- a/src/plugins/coreplugin/core.qrc +++ b/src/plugins/coreplugin/core.qrc @@ -1,5 +1,9 @@ + images/expandarrow.png + images/expandarrow@2x.png + images/search.png + images/search@2x.png images/settingscategory_core.png images/settingscategory_core@2x.png images/settingscategory_design.png diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 49ca2fec8af..c5623134814 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -41,6 +43,7 @@ #include #include +#include #include #include #include @@ -136,6 +139,30 @@ void CorePlugin::loadMimeFromPlugin(const ExtensionSystem::PluginSpec *plugin) Utils::addMimeTypes(plugin->name() + ".mimetypes", mimetypeString.trimmed().toUtf8()); } +static void initProxyAuthDialog() +{ + QObject::connect(Utils::NetworkAccessManager::instance(), + &QNetworkAccessManager::proxyAuthenticationRequired, + Utils::NetworkAccessManager::instance(), + [](const QNetworkProxy &, QAuthenticator *authenticator) { + static bool doNotAskAgain = false; + + std::optional> answer + = Utils::PasswordDialog::getUserAndPassword( + Tr::tr("Proxy Authentication Required"), + authenticator->realm(), + Tr::tr("Do not ask again."), + {}, + &doNotAskAgain, + Core::ICore::dialogParent()); + + if (answer) { + authenticator->setUser(answer->first); + authenticator->setPassword(answer->second); + } + }); +} + bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) { // register all mime types from all plugins @@ -145,6 +172,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) loadMimeFromPlugin(plugin); } + initProxyAuthDialog(); + if (ThemeEntry::availableThemes().isEmpty()) { *errorMessage = Tr::tr("No themes found in installation."); return false; @@ -234,9 +263,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) [] { return QUuid::createUuid().toString(); }); expander->registerPrefix("#:", Tr::tr("A comment."), [](const QString &) { return QString(); }); - expander->registerPrefix("Asciify:", Tr::tr("Convert string into pure ascii."), - [expander] (const QString &s) { - return asciify(expander->expand(s)); }); + expander->registerPrefix("Asciify:", + Tr::tr("Convert string to pure ASCII."), + [expander](const QString &s) { return asciify(expander->expand(s)); }); Utils::PathChooser::setAboutToShowContextMenuHandler(&CorePlugin::addToPathChooserContextMenu); @@ -283,13 +312,13 @@ static void registerActionsForOptions() const Id commandId = generateOpenPageCommandId(page); if (!commandId.isValid()) continue; - const QString actionTitle = Tr::tr("%1 > %2 Preferences...") - .arg(categoryDisplay.value(page->category()), page->displayName()); - auto action = new QAction(actionTitle, m_instance); - QObject::connect(action, &QAction::triggered, m_instance, [id = page->id()] { - ICore::showOptionsDialog(id); - }); - ActionManager::registerAction(action, commandId); + + ActionBuilder(m_instance, commandId) + .setText(Tr::tr("%1 > %2 Preferences...") + .arg(categoryDisplay.value(page->category()), page->displayName())) + .addOnTriggered(m_instance, [id = page->id()] { + ICore::showOptionsDialog(id); + }); } } diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 10cec9f79ba..6ec37a6cb8c 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -579,7 +579,7 @@ void EditorManagerPrivate::init() // Go back in navigation history ActionBuilder goBack(this, Constants::GO_BACK); goBack.setIcon(Utils::Icons::PREV.icon()); - goBack.setText(Core::Tr::tr("Go Back")); + goBack.setText(::Core::Tr::tr("Go Back")); goBack.bindContextAction(&m_goBackAction); goBack.setContext(editDesignContext); goBack.setDefaultKeySequence(::Core::Tr::tr("Ctrl+Alt+Left"), ::Core::Tr::tr("Alt+Left")); @@ -589,7 +589,7 @@ void EditorManagerPrivate::init() // Go forward in navigation history ActionBuilder goForward(this, Constants::GO_FORWARD); goForward.setIcon(Utils::Icons::NEXT.icon()); - goForward.setText(Core::Tr::tr("Go Forward")); + goForward.setText(::Core::Tr::tr("Go Forward")); goForward.bindContextAction(&m_goForwardAction); goForward.setContext(editDesignContext); goForward.setDefaultKeySequence(::Core::Tr::tr("Ctrl+Alt+Right"), ::Core::Tr::tr("Alt+Right")); @@ -618,7 +618,7 @@ void EditorManagerPrivate::init() splitSideBySide.setText(::Core::Tr::tr("Split Side by Side")); splitSideBySide.bindContextAction(&m_splitSideBySideAction); splitSideBySide.setContext(editManagerContext); - splitSideBySide.setDefaultKeySequence(::Core::Tr::tr("Meta+E,3"), Core::Tr::tr("Ctrl+E,3")); + splitSideBySide.setDefaultKeySequence(::Core::Tr::tr("Meta+E,3"), ::Core::Tr::tr("Ctrl+E,3")); splitSideBySide.addToContainer(Constants::M_WINDOW, Constants::G_WINDOW_SPLIT); splitSideBySide.addOnTriggered(this, &EditorManager::splitSideBySide); diff --git a/src/plugins/coreplugin/editormanager/editorwindow.cpp b/src/plugins/coreplugin/editormanager/editorwindow.cpp index 3e23a7285ed..fbd60ebc15b 100644 --- a/src/plugins/coreplugin/editormanager/editorwindow.cpp +++ b/src/plugins/coreplugin/editormanager/editorwindow.cpp @@ -47,9 +47,11 @@ EditorWindow::EditorWindow(QWidget *parent) : static int windowId = 0; + const Utils::Id windowContext + = Utils::Id("EditorManager.ExternalWindow.").withSuffix(++windowId); ICore::registerWindow(this, - Context(Utils::Id("EditorManager.ExternalWindow.").withSuffix(++windowId), - Constants::C_EDITORMANAGER)); + Context(windowContext, Constants::C_EDITORMANAGER), + Context(windowContext)); connect(m_area, &EditorArea::windowTitleNeedsUpdate, this, &EditorWindow::updateWindowTitle); diff --git a/src/plugins/coreplugin/find/ifindfilter.cpp b/src/plugins/coreplugin/find/ifindfilter.cpp index a849598cfdd..704f827bf83 100644 --- a/src/plugins/coreplugin/find/ifindfilter.cpp +++ b/src/plugins/coreplugin/find/ifindfilter.cpp @@ -92,7 +92,7 @@ using namespace Utils; Returns the name of the find filter or scope as presented to the user. This is the name that appears in the scope selection combo box, for example. - Always return a translatable string. That is, use \c tr() for the return + Always return a translatable string. That is, use \c {Tr::tr()} for the return value. */ diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp index abee4c08ab0..54462f30512 100644 --- a/src/plugins/coreplugin/icore.cpp +++ b/src/plugins/coreplugin/icore.cpp @@ -1011,14 +1011,15 @@ void ICore::removeAdditionalContext(const Context &context) Registers a \a window with the specified \a context. Registered windows are shown in the \uicontrol Window menu and get registered for the various window related actions, like the minimize, zoom, fullscreen and close - actions. + actions. The context for the actions is \a context by default, but can be + overridden with \a actionContext. Whenever the application focus is in \a window, its \a context is made active. */ -void ICore::registerWindow(QWidget *window, const Context &context) +void ICore::registerWindow(QWidget *window, const Context &context, const Context &actionContext) { - new WindowSupport(window, context); // deletes itself when widget is destroyed + new WindowSupport(window, context, actionContext); // deletes itself when widget is destroyed } /*! @@ -1970,14 +1971,32 @@ void ICorePrivate::registerDefaultActions() toggleMenubarAction.addToContainer(Constants::M_VIEW, Constants::G_VIEW_VIEWS); toggleMenubarAction.addOnToggled(this, [](bool visible) { if (!visible) { - const QString keys = ActionManager::command(Constants::TOGGLE_MENUBAR) - ->keySequence().toString(QKeySequence::NativeText); - CheckableMessageBox::information(Core::ICore::dialogParent(), - Tr::tr("Hide Menu Bar"), - Tr::tr("This will hide the menu bar completely. " - "You can show it again by typing %1.") - .arg(keys), - Key("ToogleMenuBarHint")); + auto keySequenceAndText = [](const Utils::Id &actionName) { + const auto command = ActionManager::command(actionName); + + const QString keySequence = command->keySequence().toString( + QKeySequence::NativeText); + const QString text = command->action()->text(); + + return QPair(keySequence, text); + }; + + auto [menuBarKeys, menuBarText] = keySequenceAndText(Constants::TOGGLE_MENUBAR); + auto [actionsFromMenuKeys, actionsFromMenuText] = keySequenceAndText( + "Locator.Actions from the menu"); + + CheckableMessageBox::information( + Core::ICore::dialogParent(), + Tr::tr("Hide Menu Bar"), + Tr::tr("This will hide the menu bar completely. " + "You can show it again by typing %1." + "

" + "Or, trigger the \"%2\" action from the \"%3\" locator filter (%4).") + .arg(menuBarKeys) + .arg(menuBarText) + .arg(actionsFromMenuText) + .arg(actionsFromMenuKeys), + Key("ToogleMenuBarHint")); } globalMenuBar()->setVisible(visible); }); diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h index 215cb94ba86..8c713e156f4 100644 --- a/src/plugins/coreplugin/icore.h +++ b/src/plugins/coreplugin/icore.h @@ -98,7 +98,9 @@ public: static void addContextObject(IContext *context); static void removeContextObject(IContext *context); - static void registerWindow(QWidget *window, const Context &context); + static void registerWindow(QWidget *window, + const Context &context, + const Context &actionContext = {}); static void restartTrimmer(); enum OpenFilesFlags { diff --git a/src/plugins/coreplugin/images/expandarrow.png b/src/plugins/coreplugin/images/expandarrow.png new file mode 100644 index 00000000000..c463d0236d1 Binary files /dev/null and b/src/plugins/coreplugin/images/expandarrow.png differ diff --git a/src/plugins/coreplugin/images/expandarrow@2x.png b/src/plugins/coreplugin/images/expandarrow@2x.png new file mode 100644 index 00000000000..9b8341673fe Binary files /dev/null and b/src/plugins/coreplugin/images/expandarrow@2x.png differ diff --git a/src/plugins/coreplugin/images/search.png b/src/plugins/coreplugin/images/search.png new file mode 100644 index 00000000000..398e2fe2bb1 Binary files /dev/null and b/src/plugins/coreplugin/images/search.png differ diff --git a/src/plugins/coreplugin/images/search@2x.png b/src/plugins/coreplugin/images/search@2x.png new file mode 100644 index 00000000000..aaae492449a Binary files /dev/null and b/src/plugins/coreplugin/images/search@2x.png differ diff --git a/src/plugins/coreplugin/iwelcomepage.cpp b/src/plugins/coreplugin/iwelcomepage.cpp index 3eb63d80312..beef33f40d6 100644 --- a/src/plugins/coreplugin/iwelcomepage.cpp +++ b/src/plugins/coreplugin/iwelcomepage.cpp @@ -3,25 +3,8 @@ #include "iwelcomepage.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -using namespace Utils; - namespace Core { -const char WITHACCENTCOLOR_PROPERTY_NAME[] = "_withAccentColor"; - static QList g_welcomePages; const QList IWelcomePage::allWelcomePages() @@ -39,171 +22,4 @@ IWelcomePage::~IWelcomePage() g_welcomePages.removeOne(this); } -QPalette WelcomePageFrame::buttonPalette(bool isActive, bool isCursorInside, bool forText) -{ - QPalette pal; - pal.setBrush(QPalette::Window, {}); - pal.setBrush(QPalette::WindowText, {}); - - Theme *theme = Utils::creatorTheme(); - if (isActive) { - if (forText) { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_ForegroundPrimaryColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_BackgroundPrimaryColor)); - } else { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_AccentColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_AccentColor)); - } - } else { - if (isCursorInside) { - if (forText) { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_HoverColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_TextColor)); - } else { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_HoverColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_ForegroundSecondaryColor)); - } - } else { - if (forText) { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_ForegroundPrimaryColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_TextColor)); - } else { - pal.setColor(QPalette::Window, theme->color(Theme::Welcome_BackgroundPrimaryColor)); - pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_ForegroundSecondaryColor)); - } - } - } - return pal; -} - -WelcomePageFrame::WelcomePageFrame(QWidget *parent) - : QWidget(parent) -{ - setContentsMargins(1, 1, 1, 1); -} - -void WelcomePageFrame::paintEvent(QPaintEvent *event) -{ - QWidget::paintEvent(event); - QPainter p(this); - - qDrawPlainRect(&p, rect(), palette().color(QPalette::WindowText), 1); - - if (property(WITHACCENTCOLOR_PROPERTY_NAME).toBool()) { - const int accentRectWidth = 10; - const QRect accentRect = rect().adjusted(width() - accentRectWidth, 0, 0, 0); - p.fillRect(accentRect, creatorTheme()->color(Theme::Welcome_AccentColor)); - } -} - -class WelcomePageButtonPrivate -{ -public: - explicit WelcomePageButtonPrivate(WelcomePageButton *parent) - : q(parent) {} - bool isActive() const; - void doUpdate(bool cursorInside); - - WelcomePageButton *q; - QHBoxLayout *m_layout = nullptr; - QLabel *m_label = nullptr; - - std::function onClicked; - std::function activeChecker; -}; - -WelcomePageButton::WelcomePageButton(QWidget *parent) - : WelcomePageFrame(parent), d(new WelcomePageButtonPrivate(this)) -{ - setAutoFillBackground(true); - setPalette(buttonPalette(false, false, false)); - setContentsMargins(0, 1, 0, 1); - - d->m_label = new QLabel(this); - d->m_label->setPalette(buttonPalette(false, false, true)); - d->m_label->setAlignment(Qt::AlignCenter); - - d->m_layout = new QHBoxLayout; - d->m_layout->setSpacing(0); - d->m_layout->addWidget(d->m_label); - setSize(SizeLarge); - setLayout(d->m_layout); -} - -WelcomePageButton::~WelcomePageButton() -{ - delete d; -} - -void WelcomePageButton::mousePressEvent(QMouseEvent *) -{ - if (d->onClicked) - d->onClicked(); -} - -void WelcomePageButton::enterEvent(QEnterEvent *) -{ - d->doUpdate(true); -} - -void WelcomePageButton::leaveEvent(QEvent *) -{ - d->doUpdate(false); -} - -bool WelcomePageButtonPrivate::isActive() const -{ - return activeChecker && activeChecker(); -} - -void WelcomePageButtonPrivate::doUpdate(bool cursorInside) -{ - const bool active = isActive(); - q->setPalette(WelcomePageFrame::buttonPalette(active, cursorInside, false)); - const QPalette lpal = WelcomePageFrame::buttonPalette(active, cursorInside, true); - m_label->setPalette(lpal); - q->update(); -} - -void WelcomePageButton::setText(const QString &text) -{ - d->m_label->setText(text); -} - -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); -} - -void WelcomePageButton::setWithAccentColor(bool withAccent) -{ - setProperty(WITHACCENTCOLOR_PROPERTY_NAME, withAccent); -} - -void WelcomePageButton::setActiveChecker(const std::function &value) -{ - d->activeChecker = value; -} - -void WelcomePageButton::recheckActive() -{ - bool isActive = d->isActive(); - d->doUpdate(isActive); -} - -void WelcomePageButton::click() -{ - if (d->onClicked) - d->onClicked(); -} - -void WelcomePageButton::setOnClicked(const std::function &value) -{ - d->onClicked = value; - if (d->isActive()) - click(); -} - } // namespace Core diff --git a/src/plugins/coreplugin/iwelcomepage.h b/src/plugins/coreplugin/iwelcomepage.h index 9a64dd3a701..1f59a791195 100644 --- a/src/plugins/coreplugin/iwelcomepage.h +++ b/src/plugins/coreplugin/iwelcomepage.h @@ -7,13 +7,10 @@ #include -#include #include -#include - QT_BEGIN_NAMESPACE -class QPixmap; +class QWidget; QT_END_NAMESPACE namespace Core { @@ -37,43 +34,4 @@ public: static const QList allWelcomePages(); }; -class WelcomePageButtonPrivate; - -class CORE_EXPORT WelcomePageFrame : public QWidget -{ -public: - WelcomePageFrame(QWidget *parent); - - void paintEvent(QPaintEvent *event) override; - - static QPalette buttonPalette(bool isActive, bool isCursorInside, bool forText); -}; - -class CORE_EXPORT WelcomePageButton : public WelcomePageFrame -{ -public: - enum Size { - SizeSmall, - SizeLarge, - }; - - explicit WelcomePageButton(QWidget *parent = nullptr); - ~WelcomePageButton() override; - - void mousePressEvent(QMouseEvent *) override; - void enterEvent(QEnterEvent *) override; - void leaveEvent(QEvent *) override; - - void setText(const QString &text); - void setSize(enum Size); - void setWithAccentColor(bool withAccent); - void setOnClicked(const std::function &value); - void setActiveChecker(const std::function &value); - void recheckActive(); - void click(); - -private: - WelcomePageButtonPrivate *d; -}; - } // Core diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index 95b8dc5be8f..55aa984c08d 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -213,17 +213,15 @@ void Locator::updateFilterActions() if (filter->shortcutString().isEmpty() || filter->isHidden()) continue; Id filterId = filter->id(); - Id actionId = filter->actionId(); QAction *action = nullptr; if (!actionCopy.contains(filterId)) { // register new action - action = new QAction(filter->displayName(), this); - Command *cmd = ActionManager::registerAction(action, actionId); - cmd->setAttribute(Command::CA_UpdateText); - cmd->setDefaultKeySequence(filter->defaultKeySequence()); - connect(action, &QAction::triggered, this, [filter] { - LocatorManager::showFilter(filter); - }); + ActionBuilder(this, filter->actionId()) + .setText(filter->displayName()) + .bindContextAction(&action) + .setCommandAttribute(Command::CA_UpdateText) + .setDefaultKeySequence(filter->defaultKeySequence()) + .addOnTriggered(this, [filter] { LocatorManager::showFilter(filter); }); } else { action = actionCopy.take(filterId); action->setText(filter->displayName()); diff --git a/src/plugins/coreplugin/loggingviewer.cpp b/src/plugins/coreplugin/loggingviewer.cpp index 5e83c76df3e..d6aad897148 100644 --- a/src/plugins/coreplugin/loggingviewer.cpp +++ b/src/plugins/coreplugin/loggingviewer.cpp @@ -559,10 +559,16 @@ private: const QString timestamp = QDateTime::currentDateTime().toString("HH:mm:ss.zzz"); - if (rowCount() >= 1000000) // limit log to 1000000 items - destroyItem(itemForIndex(index(0, 0))); + auto append = [this, timestamp, type, category, msg] { + if (rowCount() >= 1000000) // limit log to 1000000 items + destroyItem(itemForIndex(index(0, 0))); + appendItem(LogEntry{timestamp, messageTypeToString(type), category, msg}); + }; - appendItem(LogEntry{timestamp, messageTypeToString(type), category, msg}); + if (QThread::currentThread() != thread()) + QMetaObject::invokeMethod(this, append, Qt::QueuedConnection); + else + append(); } private: diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp index a6e83474cf7..48ba6224182 100644 --- a/src/plugins/coreplugin/outputpanemanager.cpp +++ b/src/plugins/coreplugin/outputpanemanager.cpp @@ -230,16 +230,17 @@ void IOutputPane::setupContext(const Context &context, QWidget *widget) m_context->setWidget(widget); ICore::addContextObject(m_context); - const auto zoomInAction = new QAction(this); - Core::ActionManager::registerAction(zoomInAction, Constants::ZOOM_IN, m_context->context()); - connect(zoomInAction, &QAction::triggered, this, [this] { emit zoomInRequested(1); }); - const auto zoomOutAction = new QAction(this); - Core::ActionManager::registerAction(zoomOutAction, Constants::ZOOM_OUT, m_context->context()); - connect(zoomOutAction, &QAction::triggered, this, [this] { emit zoomOutRequested(1); }); - const auto resetZoomAction = new QAction(this); - Core::ActionManager::registerAction(resetZoomAction, Constants::ZOOM_RESET, - m_context->context()); - connect(resetZoomAction, &QAction::triggered, this, &IOutputPane::resetZoomRequested); + ActionBuilder(this, Constants::ZOOM_IN) + .setContext(context) + .addOnTriggered(this, [this] { emit zoomInRequested(1); }); + + ActionBuilder(this, Constants::ZOOM_OUT) + .setContext(context) + .addOnTriggered(this, [this] { emit zoomOutRequested(1); }); + + ActionBuilder(this, Constants::ZOOM_RESET) + .setContext(context) + .addOnTriggered(this, &IOutputPane::resetZoomRequested); } void IOutputPane::setZoomButtonsEnabled(bool enabled) diff --git a/src/plugins/coreplugin/session.cpp b/src/plugins/coreplugin/session.cpp index c188f6812c3..921046ffed4 100644 --- a/src/plugins/coreplugin/session.cpp +++ b/src/plugins/coreplugin/session.cpp @@ -267,6 +267,11 @@ QDateTime SessionManager::lastActiveTime(const QString &session) return d->m_lastActiveTimes.value(session); } +int SessionManager::sessionsCount() +{ + return d->m_sessions.count(); +} + FilePath SessionManager::sessionNameToFileName(const QString &session) { return ICore::userResourcePath(session + ".qws"); diff --git a/src/plugins/coreplugin/session.h b/src/plugins/coreplugin/session.h index 962db5172b5..ef51228b018 100644 --- a/src/plugins/coreplugin/session.h +++ b/src/plugins/coreplugin/session.h @@ -34,6 +34,7 @@ public: static QStringList sessions(); static QDateTime sessionDateTime(const QString &session); static QDateTime lastActiveTime(const QString &session); + static int sessionsCount(); static bool createSession(const QString &session); diff --git a/src/plugins/coreplugin/welcomepagehelper.cpp b/src/plugins/coreplugin/welcomepagehelper.cpp index 44fc75270dd..c1cf35beb3d 100644 --- a/src/plugins/coreplugin/welcomepagehelper.cpp +++ b/src/plugins/coreplugin/welcomepagehelper.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -26,36 +27,34 @@ #include + +QT_BEGIN_NAMESPACE +void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); +QT_END_NAMESPACE + using namespace Utils; namespace Core { using namespace WelcomePageHelpers; +using namespace StyleHelper::SpacingTokens; static QColor themeColor(Theme::Color role) { return creatorTheme()->color(role); } -static QFont sizedFont(int size, const QWidget *widget) -{ - QFont f = widget->font(); - f.setPixelSize(size); - return f; -} - namespace WelcomePageHelpers { -QWidget *panelBar(QWidget *parent) +void setBackgroundColor(QWidget *widget, Theme::Color colorRole) { - auto frame = new QWidget(parent); - frame->setAutoFillBackground(true); - frame->setMinimumWidth(WelcomePageHelpers::HSpacing); - QPalette pal; - pal.setBrush(QPalette::Window, {}); - pal.setColor(QPalette::Window, themeColor(Theme::Welcome_BackgroundPrimaryColor)); - frame->setPalette(pal); - return frame; + QPalette palette = creatorTheme()->palette(); + const QPalette::ColorRole role = QPalette::Window; + palette.setBrush(role, {}); + palette.setColor(role, creatorTheme()->color(colorRole)); + widget->setPalette(palette); + widget->setBackgroundRole(role); + widget->setAutoFillBackground(true); } void drawCardBackground(QPainter *painter, const QRectF &rect, @@ -77,30 +76,351 @@ void drawCardBackground(QPainter *painter, const QRectF &rect, painter->restore(); } +QWidget *createRule(Qt::Orientation orientation, QWidget *parent) +{ + auto rule = new QWidget(parent); + if (orientation == Qt::Horizontal) + rule->setFixedHeight(1); + else + rule->setFixedWidth(1); + setBackgroundColor(rule, Theme::Token_Stroke_Subtle); + return rule; +} + } // namespace WelcomePageHelpers -SearchBox::SearchBox(QWidget *parent) - : WelcomePageFrame(parent) +enum WidgetState { + WidgetStateDefault, + WidgetStateChecked, + WidgetStateHovered, +}; + +static const TextFormat &buttonTF(Button::Role role, WidgetState state) { - setAutoFillBackground(true); + using namespace WelcomePageHelpers; + static const TextFormat mediumPrimaryTF + {Theme::Token_Basic_White, StyleHelper::UiElement::UiElementButtonMedium, + Qt::AlignCenter | Qt::TextDontClip}; + static const TextFormat mediumSecondaryTF + {Theme::Token_Text_Default, mediumPrimaryTF.uiElement, mediumPrimaryTF.drawTextFlags}; + static const TextFormat smallPrimaryTF + {mediumPrimaryTF.themeColor, StyleHelper::UiElement::UiElementButtonSmall, + mediumPrimaryTF.drawTextFlags}; + static const TextFormat smallSecondaryTF + {mediumSecondaryTF.themeColor, smallPrimaryTF.uiElement, smallPrimaryTF.drawTextFlags}; + static const TextFormat smallListDefaultTF + {Theme::Token_Text_Default, StyleHelper::UiElement::UiElementIconStandard, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip}; + static const TextFormat smallListCheckedTF + {smallListDefaultTF.themeColor, StyleHelper::UiElement::UiElementIconActive, + smallListDefaultTF.drawTextFlags}; + static const TextFormat smallLinkDefaultTF + {Theme::Token_Text_Default, smallListDefaultTF.uiElement, smallListDefaultTF.drawTextFlags}; + static const TextFormat smallLinkHoveredTF + {Theme::Token_Accent_Default, smallListCheckedTF.uiElement, + smallLinkDefaultTF.drawTextFlags}; - m_lineEdit = new FancyLineEdit; - m_lineEdit->setFiltering(true); - m_lineEdit->setFrame(false); - m_lineEdit->setMinimumHeight(33); - m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false); + switch (role) { + case Button::MediumPrimary: return mediumPrimaryTF; + case Button::MediumSecondary: return mediumSecondaryTF; + case Button::SmallPrimary: return smallPrimaryTF; + case Button::SmallSecondary: return smallSecondaryTF; + case Button::SmallList: return (state == WidgetStateDefault) ? smallListDefaultTF + : smallListCheckedTF; + case Button::SmallLink: return (state == WidgetStateDefault) ? smallLinkDefaultTF + : smallLinkHoveredTF; + } + return mediumPrimaryTF; +} - QPalette pal = buttonPalette(false, false, true); - // for the margins - pal.setColor(QPalette::Window, m_lineEdit->palette().color(QPalette::Base)); - // for macOS dark mode - pal.setColor(QPalette::WindowText, themeColor(Theme::Welcome_ForegroundPrimaryColor)); - pal.setColor(QPalette::Text, themeColor(Theme::Welcome_TextColor)); +Button::Button(const QString &text, Role role, QWidget *parent) + : QPushButton(text, parent) + , m_role(role) +{ + // Prevent QMacStyle::subElementRect(SE_PushButtonLayoutItem) from changing our geometry + setFlat(true); + + updateMargins(); + if (m_role == SmallList) + setCheckable(true); + else if (m_role == SmallLink) + setCursor(Qt::PointingHandCursor); +} + +QSize Button::minimumSizeHint() const +{ + const TextFormat &tf = buttonTF(m_role, WidgetStateHovered); + const QFontMetrics fm(tf.font()); + const QSize textS = fm.size(Qt::TextShowMnemonic, text()); + const QMargins margins = contentsMargins(); + return {margins.left() + textS.width() + margins.right(), + margins.top() + tf.lineHeight() + margins.bottom()}; +} + +void Button::paintEvent(QPaintEvent *event) +{ + // Without pixmap + // +----------------+----------------+----------------+ + // | |(VPadding[S|XS])| | + // | +----------------+----------------+ + // |(HPadding[S|XS])|