diff options
author | Eike Ziller <eike.ziller@qt.io> | 2023-06-09 11:24:29 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2023-06-09 11:24:29 +0200 |
commit | 375db16ac431b326a7c87e009f861875050a4247 (patch) | |
tree | 8dd29c7f109cbab6af7522c1616b544ff3a865b8 | |
parent | 804ad5a7f646739839bb3d4ef62a4771ba6fa1e1 (diff) | |
parent | 45abf54a611ae6c5dbd997d0ad5ab0a943b90f5a (diff) |
Merge remote-tracking branch 'origin/11.0'
Change-Id: I87b22a73427cf9fc1b96075dc0db769ed3d3621c
269 files changed, 2815 insertions, 1497 deletions
diff --git a/dist/changelog/changes-11.0.0.md b/dist/changelog/changes-11.0.0.md index 5600390c09..3286082636 100644 --- a/dist/changelog/changes-11.0.0.md +++ b/dist/changelog/changes-11.0.0.md @@ -14,6 +14,7 @@ General ------- * Added a `Terminal` view (QTCREATORBUG-8511) + ([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-output-panes.html#terminal)) * Opt-out via `Preferences` > `Terminal` preferences * Added support for * different shells, colors, fonts, and multiple tabs @@ -53,6 +54,7 @@ Editing * Added experimental support for GitHub Copilot ([GitHub documentation](https://github.com/features/copilot)) + ([Qt Creator documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-copilot.html)) * Added missing actions for opening the `Call Hierarchy` (QTCREATORBUG-28839, QTCREATORBUG-28842) diff --git a/doc/qtcreator/images/icons/copilot.png b/doc/qtcreator/images/icons/copilot.png Binary files differnew file mode 100644 index 0000000000..94f0b72415 --- /dev/null +++ b/doc/qtcreator/images/icons/copilot.png diff --git a/doc/qtcreator/images/icons/terminal-close.png b/doc/qtcreator/images/icons/terminal-close.png Binary files differnew file mode 100644 index 0000000000..861c01a6d2 --- /dev/null +++ b/doc/qtcreator/images/icons/terminal-close.png diff --git a/doc/qtcreator/images/icons/terminal-create.png b/doc/qtcreator/images/icons/terminal-create.png Binary files differnew file mode 100644 index 0000000000..02e8fb2185 --- /dev/null +++ b/doc/qtcreator/images/icons/terminal-create.png diff --git a/doc/qtcreator/images/qtcreator-copilot.gif b/doc/qtcreator/images/qtcreator-copilot.gif Binary files differnew file mode 100644 index 0000000000..452b102a3c --- /dev/null +++ b/doc/qtcreator/images/qtcreator-copilot.gif diff --git a/doc/qtcreator/images/qtcreator-options-environment-interface.png b/doc/qtcreator/images/qtcreator-options-environment-interface.png Binary files differdeleted file mode 100644 index 41374d1b5d..0000000000 --- a/doc/qtcreator/images/qtcreator-options-environment-interface.png +++ /dev/null diff --git a/doc/qtcreator/images/qtcreator-output-panes-taskbar.png b/doc/qtcreator/images/qtcreator-output-panes-taskbar.png Binary files differdeleted file mode 100644 index e6430e4569..0000000000 --- a/doc/qtcreator/images/qtcreator-output-panes-taskbar.png +++ /dev/null diff --git a/doc/qtcreator/images/qtcreator-output-panes-taskbar.webp b/doc/qtcreator/images/qtcreator-output-panes-taskbar.webp Binary files differnew file mode 100644 index 0000000000..27b5517cb4 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-output-panes-taskbar.webp diff --git a/doc/qtcreator/images/qtcreator-output-terminal.webp b/doc/qtcreator/images/qtcreator-output-terminal.webp Binary files differnew file mode 100644 index 0000000000..ac3f444cef --- /dev/null +++ b/doc/qtcreator/images/qtcreator-output-terminal.webp diff --git a/doc/qtcreator/images/qtcreator-preferences-copilot.webp b/doc/qtcreator/images/qtcreator-preferences-copilot.webp Binary files differnew file mode 100644 index 0000000000..bd0422e534 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-preferences-copilot.webp diff --git a/doc/qtcreator/images/qtcreator-preferences-environment-interface.webp b/doc/qtcreator/images/qtcreator-preferences-environment-interface.webp Binary files differnew file mode 100644 index 0000000000..d6d5098bc6 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-preferences-environment-interface.webp diff --git a/doc/qtcreator/images/qtcreator-preferences-terminal.webp b/doc/qtcreator/images/qtcreator-preferences-terminal.webp Binary files differnew file mode 100644 index 0000000000..5772f8ee94 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-preferences-terminal.webp diff --git a/doc/qtcreator/images/qtcreator-python-install.webp b/doc/qtcreator/images/qtcreator-python-install.webp Binary files differnew file mode 100644 index 0000000000..519c4b79d6 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-python-install.webp diff --git a/doc/qtcreator/images/qtcreator-python-wizard-define-python-interpreter.webp b/doc/qtcreator/images/qtcreator-python-wizard-define-python-interpreter.webp Binary files differnew file mode 100644 index 0000000000..8621040267 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-python-wizard-define-python-interpreter.webp diff --git a/doc/qtcreator/images/qtcreator-terminal-python.webp b/doc/qtcreator/images/qtcreator-terminal-python.webp Binary files differnew file mode 100644 index 0000000000..30fd14cd81 --- /dev/null +++ b/doc/qtcreator/images/qtcreator-terminal-python.webp diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index 82d3530d2b..fb7cc429f4 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -29,6 +29,12 @@ \if defined(qtcreator) \image qtcreator-editortoolbar-symbols.webp {Edit mode toolbar} + + To add more space around the toolbar items, select \uicontrol Edit > + \uicontrol Preferences > \uicontrol Environment > \uicontrol Interface, and + then select \uicontrol Relaxed in the \uicontrol {Toolbar style} field. + + \image qtcreator-preferences-environment-interface.webp {Interface tab in Environment preferences} \else \image studio-edit-mode.png \endif diff --git a/doc/qtcreator/src/editors/creator-coding.qdoc b/doc/qtcreator/src/editors/creator-coding.qdoc index 6823bf1c8f..e7b44dd57e 100644 --- a/doc/qtcreator/src/editors/creator-coding.qdoc +++ b/doc/qtcreator/src/editors/creator-coding.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -79,6 +79,19 @@ programming languages besides C++. In addition, it integrates diagnostics from the language server. + \li \l {Using GitHub Copilot} + + The experimental Copilot plugin integrates + \l{https://github.com/features/copilot}{GitHub Copilot} into \QC. + You can view suggestions from Copilot in the code editor. + + \li \l{Developing Qt for Python Applications} + + To support developing Qt for Python applications, \QC lets you + set up Qt for Python, use project wizards to create Qt for + Python applications, write Python code, and run and debug the + applications. + \li \l{Editing MIME Types} \QC uses the MIME type of a file to determine which mode and editor diff --git a/doc/qtcreator/src/editors/creator-locator.qdoc b/doc/qtcreator/src/editors/creator-locator.qdoc index e5a55f8d6a..c7add7c980 100644 --- a/doc/qtcreator/src/editors/creator-locator.qdoc +++ b/doc/qtcreator/src/editors/creator-locator.qdoc @@ -74,6 +74,11 @@ \section2 Locating Files + You can locate files in the local file system or on connected devices. By + default, the file system filter shows the files in the same folder as the + currently open file and lets you navigate the file system. Also, it shows + items that let you switch to another device root. + For example, to open a QML file called \e HelloWorld.qml in the currently open project using the locator: @@ -143,16 +148,19 @@ such as \c {Utils::*View}. \endif - \section2 Creating Files from Locator + \section2 Creating Files and Directories from Locator To create a new file and open it in the editor, type \c f followed by \key Space, followed by path and file name, and then press - \key Enter. + \key Enter or select \uicontrol {Create and Open File}. To create a + directory, select \uicontrol {Create Directory}. + + \section2 Opening Sessions from Locator You can use the filter that triggers menu commands to open \l{Managing Sessions}{sessions}. Enter \c {t yoursess} or \c {t sess yoursess} to trigger \uicontrol File > - \uicontrol Sessions > \e yoursessionname. + \uicontrol Sessions > \e <session_name>. \section2 Default Filters diff --git a/doc/qtcreator/src/editors/creator-only/creator-copilot.qdoc b/doc/qtcreator/src/editors/creator-only/creator-copilot.qdoc new file mode 100644 index 0000000000..69f3a35454 --- /dev/null +++ b/doc/qtcreator/src/editors/creator-only/creator-copilot.qdoc @@ -0,0 +1,96 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \previouspage creator-language-servers.html + \page creator-copilot.html + \nextpage creator-python-development.html + + \title Using GitHub Copilot + + The experimental Copilot plugin integrates + \l{https://github.com/features/copilot}{GitHub Copilot} into \QC. + You can view suggestions from Copilot in the \uicontrol Edit mode. + + \section1 Requirements + + To use the Copilot plugin, you need: + + \list + \li An active \l{https://docs.github.com/en/billing/managing-billing-for-github-copilot/about-billing-for-github-copilot} + {GitHub Copilot subscription}. + \li GitHub Copilot Neovim plugin installed, as described in + \l{https://docs.github.com/en/copilot/getting-started-with-github-copilot?tool=neovim} + {About GitHub Copilot and Neovim}. + \endlist + + \section1 Enabling the Copilot Plugin + + To enable the Copilot plugin: + + \list 1 + \li Select \uicontrol Help > \uicontrol {About Plugins} > + \uicontrol Utilities > \uicontrol Copilot to enable the plugin. + \li Select \uicontrol {Restart Now} to restart \QC and load the plugin. + \endlist + + \section1 Setting Copilot Preferences + + To set preferences for using Copilot: + + \list 1 + \li Select \uicontrol Edit > \uicontrol Preferences > + \uicontrol Copilot. + \image qtcreator-preferences-copilot.webp {Copilot tab in Preferences} + \li Select \uicontrol {Sign In} to sign into your subscription, activate + your device, and authorize the GitHub Copilot plugin. + + The button turns into a \uicontrol {Sign Out} button. + \li Select the \uicontrol {Enable Copilot} check box to use Copilot. + \li In the \uicontrol {Node.js path} field, enter the full path to the + Node.js executable. + \li In the \uicontrol {Path to agent.js} field, enter the path to + agent.js in the Copilot Neovim plugin. + \li Select the \uicontrol {Request completions automatically} checkbox to + receive suggestions for the current text cursor position when you + make changes. + \endlist + + \section1 Pair-Programming with Copilot + + When you write code in the \l {Working in Edit Mode}{Edit} mode and + \uicontrol {Request completions automatically} is enabled, Copilot + automatically makes suggestions when you type. + + \image qtcreator-copilot.gif {Receiving suggestions from Copilot in the editor} + + To manually request a suggestion at the current editor's cursor position, + select \uicontrol {Request Copilot Suggestion} in the context menu. + + Hover the mouse over a suggestion to show a toolbar with + \inlineimage icons/prev.png + and \inlineimage icons/next.png + buttons for cycling between Copilot suggestions. + + To apply a suggestion as a whole, select \uicontrol Apply or press + the \key Tab key. + + To apply a suggestion word-by-word, select \uicontrol {Apply Word} + or press \key {Alt+Right}. + + \section1 Enabling and Disabling Copilot + + You can enable and disable the Copilot plugin either globally for all + projects or at project level for a particular project. + + To enable or disable Copilot suggestions globally, select the + \inlineimage icons/copilot.png + (\uicontrol {Toggle Copilot}) button. This also sets the value of the + \uicontrol {Enable Copilot} check box in \uicontrol Edit > + \uicontrol Preferences accordingly. + + To enable or disable Copilot suggestions for a particular project, + select \uicontrol Projects > \uicontrol {Project Settings} > + \uicontrol Copilot, and then select or deselect the + \uicontrol {Enable Copilot} check box. +*/ 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 348845a7bd..43697c0f6d 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -1,10 +1,10 @@ -// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \previouspage creator-markdown-editor.html \page creator-language-servers.html - \nextpage creator-mime-types.html + \nextpage creator-copilot.html \title Using Language Servers diff --git a/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc b/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc index 7436a9c32a..17fb6d3276 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-mime-types.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -8,7 +8,7 @@ // ********************************************************************** /*! - \previouspage creator-language-servers.html + \previouspage creator-python-development.html \page creator-mime-types.html \nextpage creator-modeling.html diff --git a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc index ef5d0cca4c..0bef6d3498 100644 --- a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc +++ b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -58,7 +58,7 @@ in context menus} check box indicates whether the platform default value is \c on or \c off. - \image qtcreator-options-environment-interface.png "Interface tab in the Environment preferences" + \image qtcreator-preferences-environment-interface.webp {Interface tab in Environment preferences} \section1 Configuring Keyboard Shortcuts @@ -234,7 +234,7 @@ \li Alt+O \row \li Maximize output views - \li Alt+9 + \li Alt+Shift+9 \row \li Move to next item in output \li F6 @@ -433,6 +433,8 @@ \row \li Find references to symbol under cursor \li Ctrl+Shift+U + \note If this keyboard shortcut does not work on Linux, see + \l {Editing Issues}. \row \li Follow symbol under cursor 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 e380c1e6e8..afc1450be8 100644 --- a/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc +++ b/doc/qtcreator/src/howto/creator-only/creator-how-tos.qdoc @@ -96,7 +96,7 @@ a build, detailed output from the compiler, status of a program when it is executed, debug output, or search results. - \image qtcreator-output-panes-taskbar.png "Output on the taskbar" + \image qtcreator-output-panes-taskbar.webp "Output on the taskbar" To view different types of output, use the following shortcuts: diff --git a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc index b2dc857e45..a782558ebd 100644 --- a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc +++ b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc @@ -239,7 +239,9 @@ For console applications that require input, select \uicontrol Projects > \uicontrol {Run Settings} > \uicontrol {Run in terminal}. To specify the terminal to use, select \uicontrol Edit > \uicontrol Preferences > - \uicontrol Environment > \uicontrol System. + \uicontrol Environment > \uicontrol System. To use an \l{Terminal} + {internal terminal}, select \uicontrol Edit > \uicontrol Preferences + > \uicontrol Terminal > \uicontrol {Use internal terminal}. \b {On Windows:} Output is displayed differently for \e{console applications} and \e{GUI applications}. diff --git a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc index 9a09a24b09..80b7466214 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc @@ -1,4 +1,4 @@ -// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // ********************************************************************** @@ -68,6 +68,23 @@ \li Code completion does not support typedefs for nested classes. + \li When developing on Linux, the \key {Ctrl+Shift+U} keyboard shortcut + might not work because it conflicts with a shortcut of the + Intelligent Input Bus (ibus). You can change the shortcut for finding + references to the symbol under the cursor either in \QC or in ibus. + + To set another \l {Keyboard Shortcuts}{keyboard shortcut} + in \QC, select \uicontrol Edit > \uicontrol Preferences > + \uicontrol Environment > \uicontrol Keyboard. + + To change the shortcut in ibus, enter the following command on the + command line to start ibus setup: + \badcode + ibus-setup + \endcode + + Then, change the unicode code point shortcut in the \uicontrol Emoji + tab to something else than \key {<Control><Shift>u}. \endlist \section1 Projects Issues diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc index 27fe9ade25..c3f3688e89 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-desktop.qdocinc @@ -21,7 +21,10 @@ For console applications, check the \uicontrol{Run in terminal} check box. To specify the terminal to use on Linux and \macos, select \uicontrol Edit - > \uicontrol Preferences > \uicontrol Environment > \uicontrol System. + > \uicontrol Preferences > \uicontrol Environment > \uicontrol System. To use + an \l{Terminal}{internal terminal}, select \uicontrol Edit > + \uicontrol Preferences > \uicontrol Terminal > + \uicontrol {Use internal terminal}. To run with special environment variables set up, select them in the \uicontrol {Run Environment} section. For more information, see diff --git a/doc/qtcreator/src/python/creator-python-development.qdoc b/doc/qtcreator/src/python/creator-python-development.qdoc new file mode 100644 index 0000000000..75865bd679 --- /dev/null +++ b/doc/qtcreator/src/python/creator-python-development.qdoc @@ -0,0 +1,96 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page creator-python-development.html + \previouspage creator-copilot.html + \nextpage creator-mime-types.html + + \title Developing Qt for Python Applications + + \l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you + to use Qt 6 API in Python applications. You can use the PySide6 modules + to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI}, + and \l {Qt Widgets}. + + The following sections describe using \QC for developing with Qt for Python: + + \list + \li \l{Creating Widget-Based Qt for Python Applications} + {Creating Qt for Python Applications} + \li \l{Setting Up PySide6} + \li \l{Selecting the Python Interpreter} + \li \l{Creating a Virtual Environment} + \li \l{Using Python Interactive Shell} + \li \l{Python Language Server} + \li \l{Running Python Projects} + \li \l{Specifying Run Settings for Python Projects} + \li \l{PDB} + \li \l{Launching the Debugger} + \endlist + + For more information about developing with Qt for Python, including + limitations, see \l {https://doc.qt.io/qtforpython/index.html} + {Qt for Python}. + + \section1 Setting Up PySide6 + + If you have not installed the required version of PySide6, \QC prompts you to + do so when you open a .py file. + + \image qtcreator-python-install.webp {Prompts to install PySide6 and Python language server} + + Further, \QC prompts you to install the \l {Python Language Server} + {Python language server} that offers services such as code completion + and annotations. Select \uicontrol Install to install PySide6 and the + language server. + + \section1 Selecting the Python Interpreter + + You select the initial Python interpreter when you use the Qt for Python + Application wizard templates to create Python projects. + + \image qtcreator-python-wizard-define-python-interpreter.webp {Define Python Interpreter wizard page} + + You can see the current Python interpreter on the \uicontrol Edit mode + toolbar. + + \image qtcreator-python-interpreter-edit-mode.webp {Python interpreter on the Edit mode toolbar} + + You can change the interpreter to use for a particular project in + \uicontrol Projects > \uicontrol Run > \uicontrol Interpreter. + + \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 \uicontrol Edit > \uicontrol Preferences > \uicontrol Python > + \uicontrol Interpreters. + + \image qtcreator-python-interpreters.png {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. In addition, you + can set the interpreter to use by default. + + \section1 Creating a Virtual Environment + + To create a virtual environment (\c venv) when you use the Qt for + Python Application wizard templates to create Python projects, select + the \uicontrol {Create new virtual environment} check box on the + \uicontrol {Define Python Interpreter} wizard page. Specify the + directory where to create the environment in + \uicontrol {Path to virtual environment}. + + \section1 Using Python Interactive Shell + + You can write Python code in the Edit mode. Select \uicontrol REPL on the + toolbar to start the \l{https://pythonprogramminglanguage.com/repl/} + {Python interactive shell} in the \l Terminal pane. + + \image qtcreator-terminal-python.webp {Python shell on the taskbar} + + To start the shell and import the current file as a module, select + \uicontrol {REPL Import File}. To also import all functions from + the file, select \uicontrol {REPL Import *}. +*/ diff --git a/doc/qtcreator/src/python/creator-python-project.qdocinc b/doc/qtcreator/src/python/creator-python-project.qdocinc index 0ef6bb2d3f..80887fc978 100644 --- a/doc/qtcreator/src/python/creator-python-project.qdocinc +++ b/doc/qtcreator/src/python/creator-python-project.qdocinc @@ -1,4 +1,4 @@ -// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! @@ -6,38 +6,12 @@ \section2 Creating Widget-Based Qt for Python Applications - \l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you - to use Qt 6 API in Python applications. You can use the PySide6 modules - to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI}, - and \l {Qt Widgets}. - - If you have not installed PySide6, \QC prompts you to install it after - you create the project. Further, it prompts you to install the - \l {Python Language Server}{Python language server} that offers services - such as code completion and annotations. Select \uicontrol Install to install - PySide6 and the language server. - - You can see the current Python interpreter on the \uicontrol Edit mode - toolbar. - - \image qtcreator-python-interpreter-edit-mode.webp {Python interpreter on the Edit mode toolbar} - - To see the available interpreters and change their paths, select - the interpreter, and then select \uicontrol {Manage Python Interpreters}. - Or, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Python > - \uicontrol Interpreters. - - \image qtcreator-python-interpreters.png {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. In addition, you - can set the interpreter to use by default. - The Qt for Python Application wizards generate a \c {.pyproject} file that - lists the files in the Python project and a \c {.py} file that has - some boilerplate 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 has Qt Quick controls. + lists the files in the \l{Developing Qt for Python Applications}{Python} + project and a \c {.py} file that has some boilerplate 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. The \c{.pyproject} files are JSON-based configuration files that replace the previously used \c {.pyqtc} configuration files. You can still open and @@ -49,7 +23,7 @@ the PySide version, class name, base class, and source file for the class. - \image qtcreator-python-wizard-app-window.png {Qt for Python wizard for creating a widget-based UI} + \image qtcreator-python-wizard-app-window.png {Define Class wizard page} The wizard adds the imports to the source file for access to the QApplication, the base class you selected in the Qt @@ -121,13 +95,8 @@ \endcode You can now modify the boilerplate code in the Edit mode to develop your - Python application. Select \uicontrol REPL on the toolbar to start the - \l{https://pythonprogramminglanguage.com/repl/}{Python interactive shell}. - To start the shell and import the current file as a module, select - \uicontrol {REPL Import File}. To also import all functions from - the file, select \uicontrol {REPL Import *}. - - Always regenerate the Python code after modifying a UI file. + Python application. Always regenerate the Python code after modifying a + UI file. Open the .ui file in the \uicontrol Design mode to create a widget-based UI in \QD. diff --git a/doc/qtcreator/src/python/creator-python-run.qdocinc b/doc/qtcreator/src/python/creator-python-run.qdocinc index d1f96a7eeb..2356607a83 100644 --- a/doc/qtcreator/src/python/creator-python-run.qdocinc +++ b/doc/qtcreator/src/python/creator-python-run.qdocinc @@ -23,7 +23,7 @@ You can specify settings for running Qt for Python applications: - \image qtcreator-python-run-settings.png + \image qtcreator-python-run-settings.png {Python run settings} \list \li In the \uicontrol Interpreter field, specify the path to the diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc index e18f60632b..b9649bb2b4 100644 --- a/doc/qtcreator/src/qtcreator-toc.qdoc +++ b/doc/qtcreator/src/qtcreator-toc.qdoc @@ -130,6 +130,8 @@ \endlist \li \l{Editing Markdown Files} \li \l{Using Language Servers} + \li \l{Using GitHub Copilot} + \li \l{Developing Qt for Python Applications} \li \l{Editing MIME Types} \li \l{Modeling} \li \l{Editing State Charts} 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 e47328e744..c8ef1ee206 100644 --- a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc +++ b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc @@ -60,7 +60,9 @@ \li Open a terminal window in the selected directory or in the directory that has the file. To specify the terminal to use on Linux and \macos, select \uicontrol Edit > \uicontrol Preferences > - \uicontrol Environment > \uicontrol System. + \uicontrol Environment > \uicontrol System. To use an \l{Terminal} + {internal terminal}, select \uicontrol Edit > \uicontrol Preferences + > \uicontrol Terminal > \uicontrol {Use internal terminal}. \li Search from the selected directory. \li View file properties, such as name, path, MIME type, default editor, line endings, indentation, owner, size, last read and modified diff --git a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc index b0a98a8163..84453cf61b 100644 --- a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc +++ b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc @@ -84,6 +84,9 @@ \li Open a terminal window in the project directory. To specify the terminal to use on Linux and \macos, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Environment > \uicontrol System. + To use an \l{Terminal}{internal terminal}, select \uicontrol Edit > + \uicontrol Preferences > \uicontrol Terminal > + \uicontrol {Use internal terminal}. \li Open a terminal window in the project directory that you configured for building or running the project. \li Expand or collapse the tree view to show or hide all files and diff --git a/doc/qtcreator/src/user-interface/creator-ui.qdoc b/doc/qtcreator/src/user-interface/creator-ui.qdoc index 315720275a..031e15cedb 100644 --- a/doc/qtcreator/src/user-interface/creator-ui.qdoc +++ b/doc/qtcreator/src/user-interface/creator-ui.qdoc @@ -143,7 +143,7 @@ > \uicontrol Environment, and then select a theme in the \uicontrol Theme field. - \image qtcreator-options-environment-interface.png "Interface preferences" + \image qtcreator-preferences-environment-interface.webp {Interface preferences} \section1 Changing Languages @@ -376,13 +376,17 @@ \list - \li \uicontrol{Issues} + \li \l {Issues} - \li \uicontrol{Search Results} + \li \l {Search Results} - \li \uicontrol{Application Output} + \li \l {Application Output} - \li \uicontrol{Compile Output} + \li \l {Compile Output} + + \if defined(qtcreator) + \li \l {Terminal} + \endif \li \uicontrol {QML Debugger Console} @@ -396,7 +400,7 @@ \li \l{Using Squish}{Squish} test results and Squish Server and Runner logs - \li \uicontrol {To-Do Entries} + \li \l {To-Do Entries} \endif @@ -404,7 +408,7 @@ Output is available on the taskbar in all \l{Selecting Modes}{modes}. - \image qtcreator-output-panes-taskbar.png "Output on the taskbar" + \image qtcreator-output-panes-taskbar.webp "Output on the taskbar" You can view output in the following ways: @@ -415,7 +419,8 @@ \li Select \inlineimage icons/output-pane-menu.png , and then select the view to open. \li Select \uicontrol View > \uicontrol Output. - The menu items also display the keyboard shortcuts that you can use. + The menu items also display the \l{Keyboard Shortcuts} + {keyboard shortcuts} that you can use. \endlist To maximize an open output view, select the \inlineimage icons/arrowup.png @@ -447,7 +452,7 @@ \uicontrol Preferences > \uicontrol Environment > \uicontrol Interface, and then select the codec in the \uicontrol {Text codec for tools} field. - \image qtcreator-options-environment-interface.png "Interface tab in the Environment preferences" + \image qtcreator-preferences-environment-interface.webp {Interface tab in Environment preferences} \section1 Finding and Filtering Output @@ -644,6 +649,101 @@ \endlist \if defined(qtcreator) + + \section1 Terminal + + When you select the \uicontrol {Run in Terminal} check box and run an + application or the \uicontrol {Open Terminal} button to open a terminal, + the default terminal opens. On Linux and \macos, you can set the default + terminal by selecting \uicontrol Edit > \uicontrol Preferences > + \uicontrol Environment > \uicontrol System. + + To open the terminal on the taskbar instead of in a separate window, select + \uicontrol Edit > \uicontrol Preferences > \uicontrol Terminal > + \uicontrol {Use internal terminal}. + + \image qtcreator-output-terminal.webp {Terminal pane} + + To clear the terminal, select \inlineimage icons/clean_pane_small.png + (\uicontrol Clear). + + To close the current terminal, select \inlineimage icons/terminal-close.png + . + + To open new terminals as tabs, select \inlineimage icons/terminal-create.png + . + + To move between terminals, select the tabs or \inlineimage icons/arrowup.png + and \inlineimage icons/arrowdown.png + . + + To select a word in a terminal, double-click it. To select the whole line, + triple-click it. + + 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. + + To \l{Finding and Replacing}{search} through the output, press \key {Ctrl+F}. + + To make the font larger or smaller, select the \inlineimage icons/plus.png + and \inlineimage icons/minus.png + buttons. You can also change the font size in terminal preferences. + + To open terminal preferences, select \inlineimage icons/settings.png + (\uicontrol Configure). + + Most of the \QC keyboard shortcuts are disabled in the terminal, except the + ones for opening terminal preferences or the locator and quitting \QC. To + send the escape key to the terminal instead of closing the terminal, select + \uicontrol {Shift+Esc}. You can also specify that the escape key is sent to + the terminal in terminal preferences. + + \section2 Setting Terminal Preferences + + To set preferences for the internal terminal, select \uicontrol Edit > + \uicontrol Preferences > \uicontrol Terminal, or select the + \uicontrol Configure button in the \uicontrol Terminal pane. + + \image qtcreator-preferences-terminal.webp {Terminal tab in Preferences} + + \table + \header + \li Option + \li Value + \row + \li \uicontrol {Use internal terminal} + \li Open the \uicontrol Terminal pane when you select + \uicontrol {Run in Terminal} or \uicontrol {Open Terminal}. + \row + \li \uicontrol {Send escape key to terminal} + \li Send the escape key to the terminal instead of closing the terminal. + \row + \li \uicontrol {Audible bell} + \li Play an audible bell when the a bell character is received. + \row + \li \uicontrol {Allow blinking cursor} + \li Allow the cursor to blink. + \row + \li \uicontrol {Font} + \li Select the \uicontrol {Font family} and \uicontrol Size for the text + in the terminal. You can also use the \inlineimage icons/plus.png + and \inlineimage icons/minus.png buttons in the \uicontrol Terminal + pane to change the font size. + \row + \li \uicontrol {Colors} + \li Set colors for the \uicontrol Terminal pane \uicontrol Foreground, + \uicontrol Background, \uicontrol Selection, and + \uicontrol {Find match}. + \row + \li \uicontrol {Default shell} + \li Set the full path to the default terminal executable in + \uicontrol {Shell path} and the arguments to pass to the shell + in \uicontrol {Shell arguments}. + \endtable + + To use an existing color scheme, select \uicontrol {Load Theme}. To revert + color changes, select \uicontrol {Reset Theme}. + \section1 To-Do Entries \uicontrol {To-Do Entries} lists the BUG, FIXME, NOTE, TODO, and diff --git a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf index f9722725e8..5bcfe70d40 100644 --- a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf +++ b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf @@ -51,6 +51,7 @@ excludedirs += ../../qtcreator/examples/accelbubble \ ../../qtcreator/src/meson \ ../../qtcreator/src/overview/creator-only \ ../../qtcreator/src/projects \ + ../../qtcreator/src/python \ ../../qtcreator/src/qnx \ ../../qtcreator/src/qtquick/creator-only \ ../../qtcreator/src/vcs/creator-only \ diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json index 42b2d1ec0c..806787d459 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json @@ -162,6 +162,11 @@ "condition": "%{QdsProjectStyle}" }, { + "source": "%{QdsWizardPath}/common/insight.tpl", + "target": "%{ProjectDirectory}/insight", + "condition": "%{QdsProjectStyle}" + }, + { "source": "%{QdsWizardPath}/common/main.qml", "target": "%{ProjectDirectory}/main.qml", "condition": "%{QdsProjectStyle}" diff --git a/src/app/main.cpp b/src/app/main.cpp index 3a2cb5bfaa..e6a7bdcd7e 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -586,7 +586,7 @@ int main(int argc, char **argv) QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)); QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME); - auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); }); + const QScopeGuard cleanup([] { Utils::Singleton::deleteAll(); }); const QStringList pluginArguments = app.arguments(); @@ -647,7 +647,7 @@ int main(int argc, char **argv) for (QString locale : std::as_const(uiLanguages)) { locale = QLocale(locale).name(); if (translator.load("qtcreator_" + locale, creatorTrPath)) { - const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + const QString &qtTrPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); const QString &qtTrFile = QLatin1String("qt_") + locale; // Binary installer puts Qt tr files into creatorTrPath if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) { diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index fc1b72cb7d..deafe432b6 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -25,7 +25,7 @@ #include "cppassert.h" -#include <utils/executeondestruction.h> +#include <QScopeGuard> #include <cctype> @@ -756,9 +756,9 @@ void Lexer::scanStringLiteral(Token *tok, unsigned char hint) void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) { - Utils::ExecuteOnDestruction suffixCleaner; - if (!control()) - suffixCleaner.reset([this] { _expectedRawStringSuffix.clear(); }); + QScopeGuard cleanup([this] { _expectedRawStringSuffix.clear(); }); + if (control()) + cleanup.dismiss(); const char *yytext = _currentChar; @@ -827,7 +827,7 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) tok->f.kind = T_RAW_STRING_LITERAL; if (!control() && !closed) { - suffixCleaner.reset([]{}); + cleanup.dismiss(); s._tokenKind = tok->f.kind; _expectedRawStringSuffix.prepend(')'); _expectedRawStringSuffix.append('"'); diff --git a/src/libs/advanceddockingsystem/dockwidgettab.cpp b/src/libs/advanceddockingsystem/dockwidgettab.cpp index 4531e0da2d..1775da373f 100644 --- a/src/libs/advanceddockingsystem/dockwidgettab.cpp +++ b/src/libs/advanceddockingsystem/dockwidgettab.cpp @@ -187,7 +187,7 @@ namespace ADS void DockWidgetTabPrivate::moveTab(QMouseEvent *event) { event->accept(); - QPoint distance = event->globalPos() - m_globalDragStartMousePosition; + QPoint distance = event->globalPosition().toPoint() - m_globalDragStartMousePosition; distance.setY(0); auto targetPos = distance + m_tabDragStartPosition; targetPos.rx() = qMax(targetPos.x(), 0); @@ -294,7 +294,7 @@ namespace ADS { if (event->button() == Qt::LeftButton) { event->accept(); - d->saveDragStartMousePosition(event->globalPos()); + d->saveDragStartMousePosition(event->globalPosition().toPoint()); d->m_dragState = DraggingMousePressed; emit clicked(); return; @@ -314,7 +314,7 @@ namespace ADS case DraggingTab: // End of tab moving, emit signal if (d->m_dockArea) { - emit moved(event->globalPos()); + emit moved(event->globalPosition().toPoint()); } break; @@ -354,7 +354,7 @@ namespace ADS auto mappedPos = mapToParent(event->pos()); bool mouseOutsideBar = (mappedPos.x() < 0) || (mappedPos.x() > parentWidget()->rect().right()); // Maybe a fixed drag distance is better here ? - int dragDistanceY = qAbs(d->m_globalDragStartMousePosition.y() - event->globalPos().y()); + int dragDistanceY = qAbs(d->m_globalDragStartMousePosition.y() - event->globalPosition().toPoint().y()); if (dragDistanceY >= DockManager::startDragDistance() || mouseOutsideBar) { // If this is the last dock area in a dock container with only // one single dock widget it does not make sense to move it to a new @@ -382,7 +382,7 @@ namespace ADS } return; } else if (d->m_dockArea->openDockWidgetsCount() > 1 - && (event->globalPos() - d->m_globalDragStartMousePosition).manhattanLength() + && (event->globalPosition().toPoint() - d->m_globalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving { // If we start dragging the tab, we save its initial position to @@ -502,7 +502,7 @@ namespace ADS // sense to move it to a new floating widget and leave this one empty if ((!d->m_dockArea->dockContainer()->isFloating() || d->m_dockArea->dockWidgetsCount() > 1) && d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) { - d->saveDragStartMousePosition(event->globalPos()); + d->saveDragStartMousePosition(event->globalPosition().toPoint()); d->startFloating(DraggingInactive); } diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index ef27d9eace..f4e8dbdbd0 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -30,7 +30,6 @@ #include <cplusplus/Literals.h> #include <cplusplus/cppassert.h> -#include <utils/executeondestruction.h> #include <utils/filepath.h> #include <utils/scopedswap.h> @@ -40,6 +39,7 @@ #include <QLoggingCategory> #include <QTime> #include <QPair> +#include <QScopeGuard> #include <cctype> #include <deque> @@ -1513,14 +1513,15 @@ bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken> Q_ASSERT(tk); Q_ASSERT(actuals); - ExecuteOnDestruction removeBlockedName; - if (m_state.m_tokenBuffer) { - removeBlockedName.reset([this] { - if (m_state.m_tokenBuffer && !m_state.m_tokenBuffer->blockedMacroNames.empty()) - m_state.m_tokenBuffer->blockedMacroNames.pop_back(); - }); + QScopeGuard cleanup([this] { + if (m_state.m_tokenBuffer && !m_state.m_tokenBuffer->blockedMacroNames.empty()) + m_state.m_tokenBuffer->blockedMacroNames.pop_back(); + }); + + if (m_state.m_tokenBuffer) m_state.m_tokenBuffer->blockedMacroNames.push_back(parentMacroName); - } + else + cleanup.dismiss(); lex(tk); // consume the identifier diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index ae2dbf8903..45b9807958 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -10,6 +10,17 @@ #include "pluginspec.h" #include "pluginspec_p.h" +#include <utils/algorithm.h> +#include <utils/benchmarker.h> +#include <utils/fileutils.h> +#include <utils/futuresynchronizer.h> +#include <utils/hostosinfo.h> +#include <utils/mimeutils.h> +#include <utils/process.h> +#include <utils/qtcassert.h> +#include <utils/qtcsettings.h> +#include <utils/threadutils.h> + #include <QCoreApplication> #include <QCryptographicHash> #include <QDateTime> @@ -23,23 +34,12 @@ #include <QMessageBox> #include <QMetaProperty> #include <QPushButton> +#include <QScopeGuard> #include <QSysInfo> #include <QTextStream> #include <QTimer> #include <QWriteLocker> -#include <utils/algorithm.h> -#include <utils/benchmarker.h> -#include <utils/executeondestruction.h> -#include <utils/fileutils.h> -#include <utils/futuresynchronizer.h> -#include <utils/hostosinfo.h> -#include <utils/mimeutils.h> -#include <utils/process.h> -#include <utils/qtcassert.h> -#include <utils/qtcsettings.h> -#include <utils/threadutils.h> - #ifdef WITH_TESTS #include <utils/hostosinfo.h> #include <QTest> @@ -399,7 +399,7 @@ static QString filled(const QString &s, int min) QString PluginManager::systemInformation() { QString result; - CommandLine qtDiag(FilePath::fromString(QLibraryInfo::location(QLibraryInfo::BinariesPath)) + CommandLine qtDiag(FilePath::fromString(QLibraryInfo::path(QLibraryInfo::BinariesPath)) .pathAppended("qtdiag").withExecutableSuffix()); Process qtDiagProc; qtDiagProc.setCommand(qtDiag); @@ -1268,8 +1268,7 @@ void PluginManagerPrivate::startTests() continue; // plugin not loaded const QVector<QObject *> testObjects = plugin->createTestObjects(); - ExecuteOnDestruction deleteTestObjects([&]() { qDeleteAll(testObjects); }); - Q_UNUSED(deleteTestObjects) + const QScopeGuard cleanup([&] { qDeleteAll(testObjects); }); const bool hasDuplicateTestObjects = testObjects.size() != Utils::filteredUnique(testObjects).size(); diff --git a/src/libs/qmleditorwidgets/contextpanewidget.cpp b/src/libs/qmleditorwidgets/contextpanewidget.cpp index 8d675bf95b..93d124b6a5 100644 --- a/src/libs/qmleditorwidgets/contextpanewidget.cpp +++ b/src/libs/qmleditorwidgets/contextpanewidget.cpp @@ -44,7 +44,7 @@ DragWidget::DragWidget(QWidget *parent) : QFrame(parent) void DragWidget::mousePressEvent(QMouseEvent * event) { if (event->button() == Qt::LeftButton) { - m_startPos = event->globalPos() - parentWidget()->mapToGlobal((pos())); + m_startPos = event->globalPosition().toPoint() - parentWidget()->mapToGlobal((pos())); m_opacityEffect = new QGraphicsOpacityEffect; setGraphicsEffect(m_opacityEffect); event->accept(); @@ -77,7 +77,7 @@ void DragWidget::mouseMoveEvent(QMouseEvent * event) { if (event->buttons() & Qt::LeftButton) { if (m_startPos != QPoint(-1, -1)) { - QPoint newPos = parentWidget()->mapFromGlobal(event->globalPos() - m_startPos); + QPoint newPos = parentWidget()->mapFromGlobal(event->globalPosition().toPoint() - m_startPos); newPos.setX(limit(newPos.x(), 20, parentWidget()->width() - 20 - width())); newPos.setY(limit(newPos.y(), 2, parentWidget()->height() - 20 - height())); diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 51be467387..78d93fb6c5 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -649,6 +649,7 @@ QList<StaticAnalysis::Type> Check::defaultDisabledMessages() HintBinaryOperatorSpacing, HintOneStatementPerLine, HintExtraParentheses, + WarnAliasReferRootHierarchy, // QmlDesigner related WarnImperativeCodeNotEditableInVisualDesigner, @@ -748,6 +749,7 @@ void Check::enableQmlDesignerChecks() enableMessage(WarnReferenceToParentItemNotSupportedByVisualDesigner); enableMessage(ErrUnsupportedRootTypeInVisualDesigner); enableMessage(ErrInvalidIdeInVisualDesigner); + enableMessage(WarnAliasReferRootHierarchy); //## triggers too often ## check.enableMessage(StaticAnalysis::WarnUndefinedValueForVisualDesigner); } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 6bcfe7ee25..66a670d1b8 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -114,9 +114,9 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent) qRegisterMetaType<QmlJS::PathsAndLanguages>("QmlJS::PathsAndLanguages"); m_defaultProjectInfo.qtQmlPath = - FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)); + FilePath::fromUserInput(QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)); m_defaultProjectInfo.qmllsPath = ModelManagerInterface::qmllsForBinPath( - FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::BinariesPath)), + FilePath::fromUserInput(QLibraryInfo::path(QLibraryInfo::BinariesPath)), QLibraryInfo::version()); m_defaultProjectInfo.qtVersionString = QLibraryInfo::version().toString(); diff --git a/src/libs/solutions/tasking/CMakeLists.txt b/src/libs/solutions/tasking/CMakeLists.txt index f70c910e04..926343e9c8 100644 --- a/src/libs/solutions/tasking/CMakeLists.txt +++ b/src/libs/solutions/tasking/CMakeLists.txt @@ -5,7 +5,9 @@ add_qtc_library(Tasking OBJECT SOURCES barrier.cpp barrier.h concurrentcall.h - networkquery.cpp networkquery.h + networkquery.cpp tasking_global.h tasktree.cpp tasktree.h + EXPLICIT_MOC + networkquery.h ) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 2a4c7cefd9..43a47121b2 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1750,9 +1750,9 @@ TaskTree::TaskTree() { } -TaskTree::TaskTree(const Group &root) : TaskTree() +TaskTree::TaskTree(const Group &recipe) : TaskTree() { - setupRoot(root); + setRecipe(recipe); } TaskTree::~TaskTree() @@ -1763,27 +1763,27 @@ TaskTree::~TaskTree() delete d; } -void TaskTree::setupRoot(const Group &root) +void TaskTree::setRecipe(const Group &recipe) { QTC_ASSERT(!isRunning(), qWarning("The TaskTree is already running, ignoring..."); return); - QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The setupRoot() is called from one of the" - "TaskTree handlers, ingoring..."); return); + QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The setRecipe() is called from one of the" + "TaskTree handlers, ignoring..."); return); d->m_storages.clear(); - d->m_root.reset(new TaskNode(d, root, nullptr)); + d->m_root.reset(new TaskNode(d, recipe, nullptr)); } void TaskTree::start() { QTC_ASSERT(!isRunning(), qWarning("The TaskTree is already running, ignoring..."); return); QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The start() is called from one of the" - "TaskTree handlers, ingoring..."); return); + "TaskTree handlers, ignoring..."); return); d->start(); } void TaskTree::stop() { QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The stop() is called from one of the" - "TaskTree handlers, ingoring..."); return); + "TaskTree handlers, ignoring..."); return); d->stop(); } diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index dcd7b86ac1..11cc2708dd 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -378,10 +378,10 @@ class TASKING_EXPORT TaskTree final : public QObject public: TaskTree(); - TaskTree(const Group &root); + TaskTree(const Group &recipe); ~TaskTree(); - void setupRoot(const Group &root); + void setRecipe(const Group &recipe); void start(); void stop(); diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index aa6a3e199e..a0ec62ac24 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -43,7 +43,6 @@ add_qtc_library(Utils environmentfwd.h environmentmodel.cpp environmentmodel.h execmenu.cpp execmenu.h - executeondestruction.h expected.h externalterminalprocessimpl.cpp externalterminalprocessimpl.h fadingindicator.cpp fadingindicator.h diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 999385e1ca..5ba4922d66 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2347,7 +2347,7 @@ void IntegersAspect::setDefaultValue(const QList<int> &value) */ TextDisplay::TextDisplay(AspectContainer *container) - : BaseAspect(container) + : BaseAspect(container), d(new Internal::TextDisplayPrivate) {} /*! diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp index 3ccbf1f86e..14d1725784 100644 --- a/src/libs/utils/basetreeview.cpp +++ b/src/libs/utils/basetreeview.cpp @@ -587,7 +587,7 @@ ItemViewEvent::ItemViewEvent(QEvent *ev, QAbstractItemView *view) case QEvent::DragEnter: case QEvent::DragMove: case QEvent::Drop: - m_pos = static_cast<QDropEvent *>(ev)->pos(); + m_pos = static_cast<QDropEvent *>(ev)->position().toPoint(); m_index = view->indexAt(m_pos); break; default: diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index cafd5b0452..a134cb785d 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -31,7 +31,7 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser) int pos = output.indexOf(toolDir); if (pos == -1) return {}; - pos += toolDir.count(); + pos += toolDir.size(); int end = output.indexOf('\"', pos); if (end == -1) return {}; diff --git a/src/libs/utils/deviceshell.cpp b/src/libs/utils/deviceshell.cpp index f96c5da8f2..99ddecdeec 100644 --- a/src/libs/utils/deviceshell.cpp +++ b/src/libs/utils/deviceshell.cpp @@ -8,7 +8,6 @@ #include "qtcassert.h" #include <QLoggingCategory> -#include <QScopeGuard> Q_LOGGING_CATEGORY(deviceShellLog, "qtc.utils.deviceshell", QtWarningMsg) diff --git a/src/libs/utils/differ.cpp b/src/libs/utils/differ.cpp index 9dc2ce8454..f929efbeeb 100644 --- a/src/libs/utils/differ.cpp +++ b/src/libs/utils/differ.cpp @@ -24,8 +24,8 @@ namespace Utils { static int commonPrefix(const QString &text1, const QString &text2) { int i = 0; - const int text1Count = text1.count(); - const int text2Count = text2.count(); + const int text1Count = text1.size(); + const int text2Count = text2.size(); const int maxCount = qMin(text1Count, text2Count); while (i < maxCount) { if (text1.at(i) != text2.at(i)) @@ -38,8 +38,8 @@ static int commonPrefix(const QString &text1, const QString &text2) static int commonSuffix(const QString &text1, const QString &text2) { int i = 0; - const int text1Count = text1.count(); - const int text2Count = text2.count(); + const int text1Count = text1.size(); + const int text2Count = text2.size(); const int maxCount = qMin(text1Count, text2Count); while (i < maxCount) { if (text1.at(text1Count - i - 1) != text2.at(text2Count - i - 1)) @@ -52,8 +52,8 @@ static int commonSuffix(const QString &text1, const QString &text2) static int commonOverlap(const QString &text1, const QString &text2) { int i = 0; - const int text1Count = text1.count(); - const int text2Count = text2.count(); + const int text1Count = text1.size(); + const int text2Count = text2.size(); const int maxCount = qMin(text1Count, text2Count); while (i < maxCount) { if (QStringView(text1).mid(text1Count - maxCount + i) == QStringView(text2).left(maxCount - i)) @@ -66,7 +66,7 @@ static int commonOverlap(const QString &text1, const QString &text2) static QList<Diff> decode(const QList<Diff> &diffList, const QStringList &lines) { QList<Diff> newDiffList; - newDiffList.reserve(diffList.count()); + newDiffList.reserve(diffList.size()); for (const Diff &diff : diffList) { QString text; for (QChar c : diff.text) { @@ -80,7 +80,7 @@ static QList<Diff> decode(const QList<Diff> &diffList, const QStringList &lines) static QList<Diff> squashEqualities(const QList<Diff> &diffList) { - if (diffList.count() < 3) // we need at least 3 items + if (diffList.size() < 3) // we need at least 3 items return diffList; QList<Diff> newDiffList; @@ -88,20 +88,20 @@ static QList<Diff> squashEqualities(const QList<Diff> &diffList) Diff thisDiff = diffList.at(1); Diff nextDiff = diffList.at(2); int i = 2; - while (i < diffList.count()) { + while (i < diffList.size()) { if (prevDiff.command == Diff::Equal && nextDiff.command == Diff::Equal) { if (thisDiff.text.endsWith(prevDiff.text)) { thisDiff.text = prevDiff.text - + thisDiff.text.left(thisDiff.text.count() - - prevDiff.text.count()); + + thisDiff.text.left(thisDiff.text.size() + - prevDiff.text.size()); nextDiff.text = prevDiff.text + nextDiff.text; } else if (thisDiff.text.startsWith(nextDiff.text)) { prevDiff.text += nextDiff.text; - thisDiff.text = thisDiff.text.mid(nextDiff.text.count()) + thisDiff.text = thisDiff.text.mid(nextDiff.text.size()) + nextDiff.text; i++; - if (i < diffList.count()) + if (i < diffList.size()) nextDiff = diffList.at(i); newDiffList.append(prevDiff); } else { @@ -113,11 +113,11 @@ static QList<Diff> squashEqualities(const QList<Diff> &diffList) prevDiff = thisDiff; thisDiff = nextDiff; i++; - if (i < diffList.count()) + if (i < diffList.size()) nextDiff = diffList.at(i); } newDiffList.append(prevDiff); - if (i == diffList.count()) + if (i == diffList.size()) newDiffList.append(thisDiff); return newDiffList; } @@ -132,9 +132,9 @@ static QList<Diff> cleanupOverlaps(const QList<Diff> &diffList) // DEL(XXXXABC), INS(DEFXXXX) -> INS(DEF), EQ(XXXX), DEL(ABC) QList<Diff> newDiffList; int i = 0; - while (i < diffList.count()) { + while (i < diffList.size()) { Diff thisDiff = diffList.at(i); - Diff nextDiff = i < diffList.count() - 1 + Diff nextDiff = i < diffList.size() - 1 ? diffList.at(i + 1) : Diff(Diff::Equal); if (thisDiff.command == Diff::Delete @@ -142,9 +142,9 @@ static QList<Diff> cleanupOverlaps(const QList<Diff> &diffList) const int delInsOverlap = commonOverlap(thisDiff.text, nextDiff.text); const int insDelOverlap = commonOverlap(nextDiff.text, thisDiff.text); if (delInsOverlap >= insDelOverlap) { - if (delInsOverlap > thisDiff.text.count() / 2 - || delInsOverlap > nextDiff.text.count() / 2) { - thisDiff.text = thisDiff.text.left(thisDiff.text.count() - delInsOverlap); + if (delInsOverlap > thisDiff.text.size() / 2 + || delInsOverlap > nextDiff.text.size() / 2) { + thisDiff.text = thisDiff.text.left(thisDiff.text.size() - delInsOverlap); const Diff equality(Diff::Equal, nextDiff.text.left(delInsOverlap)); nextDiff.text = nextDiff.text.mid(delInsOverlap); newDiffList.append(thisDiff); @@ -155,9 +155,9 @@ static QList<Diff> cleanupOverlaps(const QList<Diff> &diffList) newDiffList.append(nextDiff); } } else { - if (insDelOverlap > thisDiff.text.count() / 2 - || insDelOverlap > nextDiff.text.count() / 2) { - nextDiff.text = nextDiff.text.left(nextDiff.text.count() - insDelOverlap); + if (insDelOverlap > thisDiff.text.size() / 2 + || insDelOverlap > nextDiff.text.size() / 2) { + nextDiff.text = nextDiff.text.left(nextDiff.text.size() - insDelOverlap); const Diff equality(Diff::Equal, thisDiff.text.left(insDelOverlap)); thisDiff.text = thisDiff.text.mid(insDelOverlap); newDiffList.append(nextDiff); @@ -186,7 +186,7 @@ static int cleanupSemanticsScore(const QString &text1, const QString &text2) if (text1.isEmpty() || text2.isEmpty()) // Edges return 6; - const QChar char1 = text1[text1.count() - 1]; + const QChar char1 = text1[text1.size() - 1]; const QChar char2 = text2[0]; const bool nonAlphaNumeric1 = !char1.isLetterOrNumber(); const bool nonAlphaNumeric2 = !char2.isLetterOrNumber(); @@ -256,19 +256,19 @@ QList<Diff> Differ::moveWhitespaceIntoEqualities(const QList<Diff> &input) { QList<Diff> output = input; - for (int i = 0; i < output.count(); i++) { + for (int i = 0; i < output.size(); i++) { Diff diff = output[i]; if (diff.command != Diff::Equal) { if (i > 0) { // check previous equality Diff &previousDiff = output[i - 1]; - const int previousDiffCount = previousDiff.text.count(); + const int previousDiffCount = previousDiff.text.size(); if (previousDiff.command == Diff::Equal && previousDiffCount && isWhitespace(previousDiff.text.at(previousDiffCount - 1))) { // previous diff ends with whitespace int j = 0; - while (j < diff.text.count()) { + while (j < diff.text.size()) { if (!isWhitespace(diff.text.at(j))) break; ++j; @@ -280,10 +280,10 @@ QList<Diff> Differ::moveWhitespaceIntoEqualities(const QList<Diff> &input) } } } - if (i < output.count() - 1) { // check next equality - const int diffCount = diff.text.count(); + if (i < output.size() - 1) { // check next equality + const int diffCount = diff.text.size(); Diff &nextDiff = output[i + 1]; - const int nextDiffCount = nextDiff.text.count(); + const int nextDiffCount = nextDiff.text.size(); if (nextDiff.command == Diff::Equal && nextDiffCount && (isWhitespace(nextDiff.text.at(0)) || isNewLine(nextDiff.text.at(0)))) { @@ -331,7 +331,7 @@ static QString encodeReducedWhitespace(const QString &input, int inputIndex = 0; int outputIndex = 0; - while (inputIndex < input.count()) { + while (inputIndex < input.size()) { QChar c = input.at(inputIndex); if (isWhitespace(c)) { @@ -339,7 +339,7 @@ static QString encodeReducedWhitespace(const QString &input, codeMap->insert(outputIndex, QString(c)); ++inputIndex; - while (inputIndex < input.count()) { + while (inputIndex < input.size()) { QChar reducedChar = input.at(inputIndex); if (!isWhitespace(reducedChar)) @@ -372,10 +372,10 @@ static QList<Diff> decodeReducedWhitespace(const QList<Diff> &input, auto it = codeMap.constBegin(); const auto itEnd = codeMap.constEnd(); for (Diff diff : input) { - const int diffCount = diff.text.count(); + const int diffCount = diff.text.size(); while ((it != itEnd) && (it.key() < counter + diffCount)) { const int reversePosition = diffCount + counter - it.key(); - const int updatedDiffCount = diff.text.count(); + const int updatedDiffCount = diff.text.size(); diff.text.replace(updatedDiffCount - reversePosition, 1, it.value()); ++it; } @@ -502,8 +502,8 @@ static QString encodeExpandedWhitespace(const QString &leftEquality, rightCodeMap->clear(); QString output; - const int leftCount = leftEquality.count(); - const int rightCount = rightEquality.count(); + const int leftCount = leftEquality.size(); + const int rightCount = rightEquality.size(); int leftIndex = 0; int rightIndex = 0; while (leftIndex < leftCount && rightIndex < rightCount) { @@ -534,8 +534,8 @@ static QString encodeExpandedWhitespace(const QString &leftEquality, } if (!leftWhitespaces.isEmpty() && !rightWhitespaces.isEmpty()) { - const int replacementPosition = output.count(); - const int replacementSize = qMax(leftWhitespaces.count(), rightWhitespaces.count()); + const int replacementPosition = output.size(); + const int replacementSize = qMax(leftWhitespaces.size(), rightWhitespaces.size()); const QString replacement(replacementSize, ' '); leftCodeMap->insert(replacementPosition, {replacementSize, leftWhitespaces}); rightCodeMap->insert(replacementPosition, {replacementSize, rightWhitespaces}); @@ -574,14 +574,14 @@ static QList<Diff> decodeExpandedWhitespace(const QList<Diff> &input, auto it = codeMap.constBegin(); const auto itEnd = codeMap.constEnd(); for (Diff diff : input) { - const int diffCount = diff.text.count(); + const int diffCount = diff.text.size(); while ((it != itEnd) && (it.key() < counter + diffCount)) { const int replacementSize = it.value().first; const int reversePosition = diffCount + counter - it.key(); if (reversePosition < replacementSize) return QList<Diff>(); // replacement exceeds one Diff const QString replacement = it.value().second; - const int updatedDiffCount = diff.text.count(); + const int updatedDiffCount = diff.text.size(); diff.text.replace(updatedDiffCount - reversePosition, replacementSize, replacement); ++it; @@ -619,8 +619,8 @@ static bool diffWithWhitespaceExpandedInEqualities(const QList<Diff> &leftInput, leftOutput->clear(); rightOutput->clear(); - const int leftCount = leftInput.count(); - const int rightCount = rightInput.count(); + const int leftCount = leftInput.size(); + const int rightCount = rightInput.size(); int l = 0; int r = 0; @@ -649,10 +649,10 @@ static bool diffWithWhitespaceExpandedInEqualities(const QList<Diff> &leftInput, // join code map positions with common maps for (auto it = leftCodeMap.cbegin(), end = leftCodeMap.cend(); it != end; ++it) - commonLeftCodeMap.insert(leftText.count() + it.key(), it.value()); + commonLeftCodeMap.insert(leftText.size() + it.key(), it.value()); for (auto it = rightCodeMap.cbegin(), end = rightCodeMap.cend(); it != end; ++it) - commonRightCodeMap.insert(rightText.count() + it.key(), it.value()); + commonRightCodeMap.insert(rightText.size() + it.key(), it.value()); leftText.append(commonEquality); rightText.append(commonEquality); @@ -739,8 +739,8 @@ void Differ::ignoreWhitespaceBetweenEqualities(const QList<Diff> &leftInput, leftOutput->clear(); rightOutput->clear(); - const int leftCount = leftInput.count(); - const int rightCount = rightInput.count(); + const int leftCount = leftInput.size(); + const int rightCount = rightInput.size(); int l = 0; int r = 0; @@ -836,8 +836,8 @@ void Differ::diffBetweenEqualities(const QList<Diff> &leftInput, leftOutput->clear(); rightOutput->clear(); - const int leftCount = leftInput.count(); - const int rightCount = rightInput.count(); + const int leftCount = leftInput.size(); + const int rightCount = rightInput.size(); int l = 0; int r = 0; @@ -1000,8 +1000,8 @@ QList<Diff> Differ::preprocess1AndDiff(const QString &text1, const QString &text const int suffixCount = commonSuffix(newText1, newText2); if (suffixCount) { suffix = newText1.right(suffixCount); - newText1 = newText1.left(newText1.count() - suffixCount); - newText2 = newText2.left(newText2.count() - suffixCount); + newText1 = newText1.left(newText1.size() - suffixCount); + newText2 = newText2.left(newText2.size() - suffixCount); } QList<Diff> diffList = preprocess2AndDiff(newText1, newText2); if (prefixCount) @@ -1025,28 +1025,27 @@ QList<Diff> Differ::preprocess2AndDiff(const QString &text1, const QString &text return diffList; } - if (text1.count() != text2.count()) - { - const QString longtext = text1.count() > text2.count() ? text1 : text2; - const QString shorttext = text1.count() > text2.count() ? text2 : text1; + if (text1.size() != text2.size()) { + const QString longtext = text1.size() > text2.size() ? text1 : text2; + const QString shorttext = text1.size() > text2.size() ? text2 : text1; const int i = longtext.indexOf(shorttext); if (i != -1) { - const Diff::Command command = (text1.count() > text2.count()) + const Diff::Command command = (text1.size() > text2.size()) ? Diff::Delete : Diff::Insert; diffList.append(Diff(command, longtext.left(i))); diffList.append(Diff(Diff::Equal, shorttext)); - diffList.append(Diff(command, longtext.mid(i + shorttext.count()))); + diffList.append(Diff(command, longtext.mid(i + shorttext.size()))); return diffList; } - if (shorttext.count() == 1) { + if (shorttext.size() == 1) { diffList.append(Diff(Diff::Delete, text1)); diffList.append(Diff(Diff::Insert, text2)); return diffList; } } - if (m_currentDiffMode != Differ::CharMode && text1.count() > 80 && text2.count() > 80) + if (m_currentDiffMode != Differ::CharMode && text1.size() > 80 && text2.size() > 80) return diffNonCharMode(text1, text2); return diffMyers(text1, text2); @@ -1054,8 +1053,8 @@ QList<Diff> Differ::preprocess2AndDiff(const QString &text1, const QString &text QList<Diff> Differ::diffMyers(const QString &text1, const QString &text2) { - const int n = text1.count(); - const int m = text2.count(); + const int n = text1.size(); + const int m = text2.size(); const bool odd = (n + m) % 2; const int D = odd ? (n + m) / 2 + 1 : (n + m) / 2; const int delta = n - m; @@ -1191,12 +1190,12 @@ QList<Diff> Differ::diffNonCharMode(const QString &text1, const QString &text2) QString lastDelete; QString lastInsert; QList<Diff> newDiffList; - for (int i = 0; i <= diffList.count(); i++) { + for (int i = 0; i <= diffList.size(); i++) { if (m_future && m_future->isCanceled()) { m_currentDiffMode = diffMode; return {}; } - const Diff diffItem = i < diffList.count() + const Diff diffItem = i < diffList.size() ? diffList.at(i) : Diff(Diff::Equal); // dummy, ensure we process to the end // even when diffList doesn't end with equality @@ -1240,14 +1239,14 @@ int Differ::findSubtextEnd(const QString &text, if (m_currentDiffMode == Differ::LineMode) { int subtextEnd = text.indexOf('\n', subtextStart); if (subtextEnd == -1) - subtextEnd = text.count() - 1; + subtextEnd = text.size() - 1; return ++subtextEnd; } else if (m_currentDiffMode == Differ::WordMode) { if (!text.at(subtextStart).isLetter()) return subtextStart + 1; int i = subtextStart + 1; - const int count = text.count(); + const int count = text.size(); while (i < count && text.at(i).isLetter()) i++; return i; @@ -1262,7 +1261,7 @@ QString Differ::encode(const QString &text, int subtextStart = 0; int subtextEnd = -1; QString codes; - while (subtextEnd < text.count()) { + while (subtextEnd < text.size()) { subtextEnd = findSubtextEnd(text, subtextStart); const QString line = text.mid(subtextStart, subtextEnd - subtextStart); subtextStart = subtextEnd; @@ -1271,8 +1270,8 @@ QString Differ::encode(const QString &text, codes += QChar(static_cast<ushort>(lineToCode->value(line))); } else { lines->append(line); - lineToCode->insert(line, lines->count() - 1); - codes += QChar(static_cast<ushort>(lines->count() - 1)); + lineToCode->insert(line, lines->size() - 1); + codes += QChar(static_cast<ushort>(lines->size() - 1)); } } return codes; @@ -1283,8 +1282,8 @@ QList<Diff> Differ::merge(const QList<Diff> &diffList) QString lastDelete; QString lastInsert; QList<Diff> newDiffList; - for (int i = 0; i <= diffList.count(); i++) { - Diff diff = i < diffList.count() + for (int i = 0; i <= diffList.size(); i++) { + Diff diff = i < diffList.size() ? diffList.at(i) : Diff(Diff::Equal); // dummy, ensure we process to the end // even when diffList doesn't end with equality @@ -1314,8 +1313,8 @@ QList<Diff> Differ::merge(const QList<Diff> &diffList) const int suffixCount = commonSuffix(lastDelete, lastInsert); if (suffixCount) { const QString suffix = lastDelete.right(suffixCount); - lastDelete = lastDelete.left(lastDelete.count() - suffixCount); - lastInsert = lastInsert.left(lastInsert.count() - suffixCount); + lastDelete = lastDelete.left(lastDelete.size() - suffixCount); + lastInsert = lastInsert.left(lastInsert.size() - suffixCount); diff.text.prepend(suffix); } @@ -1342,7 +1341,7 @@ QList<Diff> Differ::merge(const QList<Diff> &diffList) } QList<Diff> squashedDiffList = squashEqualities(newDiffList); - if (squashedDiffList.count() != newDiffList.count()) + if (squashedDiffList.size() != newDiffList.size()) return merge(squashedDiffList); return squashedDiffList; @@ -1363,8 +1362,8 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) int inserts = 0; // equality index, equality data QList<EqualityData> equalities; - for (int i = 0; i <= diffList.count(); i++) { - const Diff diff = i < diffList.count() + for (int i = 0; i <= diffList.size(); i++) { + const Diff diff = i < diffList.size() ? diffList.at(i) : Diff(Diff::Equal); // dummy, ensure we process to the end // even when diffList doesn't end with equality @@ -1374,10 +1373,10 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) previousData.deletesAfter = deletes; previousData.insertsAfter = inserts; } - if (i < diffList.count()) { // don't insert dummy + if (i < diffList.size()) { // don't insert dummy EqualityData data; data.equalityIndex = i; - data.textCount = diff.text.count(); + data.textCount = diff.text.size(); data.deletesBefore = deletes; data.insertsBefore = inserts; equalities.append(data); @@ -1386,15 +1385,15 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) } } else { if (diff.command == Diff::Delete) - deletes += diff.text.count(); + deletes += diff.text.size(); else if (diff.command == Diff::Insert) - inserts += diff.text.count(); + inserts += diff.text.size(); } } QMap<int, bool> equalitiesToBeSplit; int i = 0; - while (i < equalities.count()) { + while (i < equalities.size()) { const EqualityData &data = equalities.at(i); if (data.textCount <= qMax(data.deletesBefore, data.insertsBefore) && data.textCount <= qMax(data.deletesAfter, data.insertsAfter)) { @@ -1403,7 +1402,7 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) previousData.deletesAfter += data.textCount + data.deletesAfter; previousData.insertsAfter += data.textCount + data.insertsAfter; } - if (i < equalities.count() - 1) { + if (i < equalities.size() - 1) { EqualityData &nextData = equalities[i + 1]; nextData.deletesBefore += data.textCount + data.deletesBefore; nextData.insertsBefore += data.textCount + data.insertsBefore; @@ -1418,7 +1417,7 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) } QList<Diff> newDiffList; - for (int i = 0; i < diffList.count(); i++) { + for (int i = 0; i < diffList.size(); i++) { const Diff &diff = diffList.at(i); if (equalitiesToBeSplit.contains(i)) { newDiffList.append(Diff(Diff::Delete, diff.text)); @@ -1433,7 +1432,7 @@ QList<Diff> Differ::cleanupSemantics(const QList<Diff> &diffList) QList<Diff> Differ::cleanupSemanticsLossless(const QList<Diff> &diffList) { - if (diffList.count() < 3) // we need at least 3 items + if (diffList.size() < 3) // we need at least 3 items return diffList; QList<Diff> newDiffList; @@ -1441,7 +1440,7 @@ QList<Diff> Differ::cleanupSemanticsLossless(const QList<Diff> &diffList) Diff thisDiff = diffList.at(1); Diff nextDiff = diffList.at(2); int i = 2; - while (i < diffList.count()) { + while (i < diffList.size()) { if (prevDiff.command == Diff::Equal && nextDiff.command == Diff::Equal) { @@ -1453,9 +1452,9 @@ QList<Diff> Differ::cleanupSemanticsLossless(const QList<Diff> &diffList) // Shift the edit as far left as possible const int suffixCount = commonSuffix(equality1, edit); if (suffixCount) { - const QString commonString = edit.mid(edit.count() - suffixCount); - equality1 = equality1.left(equality1.count() - suffixCount); - edit = commonString + edit.left(edit.count() - suffixCount); + const QString commonString = edit.mid(edit.size() - suffixCount); + equality1 = equality1.left(equality1.size() - suffixCount); + edit = commonString + edit.left(edit.size() - suffixCount); equality2 = commonString + equality2; } @@ -1488,7 +1487,7 @@ QList<Diff> Differ::cleanupSemanticsLossless(const QList<Diff> &diffList) newDiffList.append(prevDiff); // append modified equality1 if (bestEquality2.isEmpty()) { i++; - if (i < diffList.count()) + if (i < diffList.size()) nextDiff = diffList.at(i); // omit equality2 } } else { @@ -1497,11 +1496,11 @@ QList<Diff> Differ::cleanupSemanticsLossless(const QList<Diff> &diffList) prevDiff = thisDiff; thisDiff = nextDiff; i++; - if (i < diffList.count()) + if (i < diffList.size()) nextDiff = diffList.at(i); } newDiffList.append(prevDiff); - if (i == diffList.count()) + if (i == diffList.size()) newDiffList.append(thisDiff); return newDiffList; } diff --git a/src/libs/utils/executeondestruction.h b/src/libs/utils/executeondestruction.h deleted file mode 100644 index 82832afb9a..0000000000 --- a/src/libs/utils/executeondestruction.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include <functional> - -namespace Utils { - -class ExecuteOnDestruction -{ -public: - ExecuteOnDestruction() noexcept : destructionCode([] {}) {} - ExecuteOnDestruction(std::function<void()> code) : destructionCode(std::move(code)) {} - ~ExecuteOnDestruction() { if (destructionCode) destructionCode(); } - - void reset(std::function<void()> code) { destructionCode = std::move(code); } - -private: - std::function<void()> destructionCode; -}; - -} // Utils diff --git a/src/libs/utils/filenamevalidatinglineedit.cpp b/src/libs/utils/filenamevalidatinglineedit.cpp index 5602e72d1a..47721b2312 100644 --- a/src/libs/utils/filenamevalidatinglineedit.cpp +++ b/src/libs/utils/filenamevalidatinglineedit.cpp @@ -151,12 +151,12 @@ bool FileNameValidatingLineEdit::validateFileNameExtension(const QString &fileNa if (!requiredExtensions.isEmpty()) { for (const QString &requiredExtension : requiredExtensions) { QString extension = QLatin1Char('.') + requiredExtension; - if (fileName.endsWith(extension, Qt::CaseSensitive) && extension.count() < fileName.count()) + if (fileName.endsWith(extension, Qt::CaseSensitive) && extension.size() < fileName.size()) return true; } if (errorMessage) { - if (requiredExtensions.count() == 1) + if (requiredExtensions.size() == 1) *errorMessage = Tr::tr("File extension %1 is required:").arg(requiredExtensions.first()); else *errorMessage = Tr::tr("File extensions %1 are required:").arg(requiredExtensions.join(QLatin1String(", "))); diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 2cecc2810b..0c6a321c71 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -133,7 +133,7 @@ bool FileSaverBase::write(const QByteArray &bytes) { if (m_hasError) return false; - return setResult(m_file->write(bytes) == bytes.count()); + return setResult(m_file->write(bytes) == bytes.size()); } bool FileSaverBase::setResult(bool ok) diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp index a8b144dbdb..22d55e23bf 100644 --- a/src/libs/utils/highlightingitemdelegate.cpp +++ b/src/libs/utils/highlightingitemdelegate.cpp @@ -201,7 +201,7 @@ void HighlightingItemDelegate::drawText(QPainter *painter, static QString replaceNewLine(QString text) { static const QChar nl = '\n'; - for (int i = 0; i < text.count(); ++i) + for (int i = 0; i < text.size(); ++i) if (text.at(i) == nl) text[i] = QChar::LineSeparator; return text; diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp index 4dc18b23f6..3ab7d92e9a 100644 --- a/src/libs/utils/macroexpander.cpp +++ b/src/libs/utils/macroexpander.cpp @@ -77,7 +77,7 @@ public: MacroExpander::PrefixFunction pf = it.value(); if (found) *found = true; - return pf(QString::fromUtf8(variable.mid(it.key().count()))); + return pf(QString::fromUtf8(variable.mid(it.key().size()))); } } if (found) diff --git a/src/libs/utils/networkaccessmanager.cpp b/src/libs/utils/networkaccessmanager.cpp index 53de288fab..81ca77379e 100644 --- a/src/libs/utils/networkaccessmanager.cpp +++ b/src/libs/utils/networkaccessmanager.cpp @@ -4,13 +4,9 @@ #include "networkaccessmanager.h" #include <QCoreApplication> -#include <QLibraryInfo> #include <QLocale> #include <QNetworkReply> - -#ifdef Q_OS_UNIX -#include <sys/utsname.h> -#endif +#include <QSysInfo> /*! \class Utils::NetworkAccessManager @@ -75,5 +71,4 @@ QNetworkReply* NetworkAccessManager::createRequest(Operation op, const QNetworkR return QNetworkAccessManager::createRequest(op, req, outgoingData); } - } // namespace utils diff --git a/src/libs/utils/networkaccessmanager.h b/src/libs/utils/networkaccessmanager.h index bd6987474c..725757c2fe 100644 --- a/src/libs/utils/networkaccessmanager.h +++ b/src/libs/utils/networkaccessmanager.h @@ -7,10 +7,6 @@ #include <QNetworkAccessManager> -QT_BEGIN_NAMESPACE -class QUrl; -QT_END_NAMESPACE - namespace Utils { class QTCREATOR_UTILS_EXPORT NetworkAccessManager : public QNetworkAccessManager diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index 2bcdffb586..f8b3d8cec7 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -449,7 +449,7 @@ void OutputFormatter::append(const QString &text, const QTextCharFormat &format) d->cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); startPos = crPos + 1; } - if (startPos < text.count()) + if (startPos < text.size()) d->cursor.insertText(text.mid(startPos), format); } diff --git a/src/libs/utils/process.cpp b/src/libs/utils/process.cpp index 85d3fa54ed..970b0b4a29 100644 --- a/src/libs/utils/process.cpp +++ b/src/libs/utils/process.cpp @@ -66,7 +66,7 @@ public: return std::invoke(std::forward<Function>(function), std::forward<Args>(args)...); QElapsedTimer timer; timer.start(); - auto cleanup = qScopeGuard([this, &timer] { + const QScopeGuard cleanup([this, &timer] { const qint64 currentNsecs = timer.nsecsElapsed(); const bool mainThread = isMainThread(); const int hitThisAll = m_hitThisAll.fetch_add(1) + 1; @@ -134,7 +134,7 @@ private: } static QString formatField(int number, int fieldWidth, const QString &suffix = {}) { - return QString("%1%2").arg(number, fieldWidth - suffix.count()).arg(suffix); + return QString("%1%2").arg(number, fieldWidth - suffix.size()).arg(suffix); } static int toMs(quint64 nsesc) // nanoseconds to miliseconds diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp index dba9a801e4..0b1a0a6355 100644 --- a/src/libs/utils/projectintropage.cpp +++ b/src/libs/utils/projectintropage.cpp @@ -303,7 +303,7 @@ bool ProjectIntroPage::validateProjectName(const QString &name, QString *errorMe // if pos is set by validate it is cought at the bottom where it shows // a more detailed error message - if (validatorState != QValidator::Acceptable && (pos == -1 || pos >= name.count())) { + if (validatorState != QValidator::Acceptable && (pos == -1 || pos >= name.size())) { if (errorMessage) { if (d->m_projectNameValidatorUserMessage.isEmpty()) *errorMessage = Tr::tr("Project name is invalid."); diff --git a/src/libs/utils/templateengine.cpp b/src/libs/utils/templateengine.cpp index e5636960de..a917ea27cb 100644 --- a/src/libs/utils/templateengine.cpp +++ b/src/libs/utils/templateengine.cpp @@ -235,9 +235,9 @@ QString TemplateEngine::processText(MacroExpander *expander, const QString &inpu // Expand \n, \t and handle line continuation: QString result; - result.reserve(out.count()); + result.reserve(out.size()); bool isEscaped = false; - for (int i = 0; i < out.count(); ++i) { + for (int i = 0; i < out.size(); ++i) { const QChar c = out.at(i); if (isEscaped) { diff --git a/src/libs/utils/terminalcommand.cpp b/src/libs/utils/terminalcommand.cpp index 102fc42e05..bb1492515f 100644 --- a/src/libs/utils/terminalcommand.cpp +++ b/src/libs/utils/terminalcommand.cpp @@ -112,7 +112,14 @@ const char kTerminalExecuteOptionsKey[] = "General/Terminal/ExecuteOptions"; TerminalCommand TerminalCommand::terminalEmulator() { if (s_settings && HostOsInfo::isAnyUnixHost() && s_settings->contains(kTerminalCommandKey)) { - return {FilePath::fromSettings(s_settings->value(kTerminalCommandKey)), + FilePath command = FilePath::fromSettings(s_settings->value(kTerminalCommandKey)); + + // TODO Remove some time after Qt Creator 11 + // Work around Qt Creator <= 10 writing the default terminal to the settings. + if (HostOsInfo::isMacHost() && command.endsWith("openTerminal.py")) + command = FilePath::fromString("Terminal.app"); + + return {command, s_settings->value(kTerminalOpenOptionsKey).toString(), s_settings->value(kTerminalExecuteOptionsKey).toString()}; } diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index df23fc3ba2..d117b7057c 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -109,7 +109,6 @@ Project { "environmentmodel.h", "execmenu.cpp", "execmenu.h", - "executeondestruction.h", "externalterminalprocessimpl.cpp", "externalterminalprocessimpl.h", "fadingindicator.cpp", diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 65ef869558..529f7ab0ca 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -264,13 +264,13 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa m_extraAppParams = runControl->commandLine().arguments(); if (auto aspect = runControl->aspect(Constants::ANDROID_AM_START_ARGS)) { - QTC_CHECK(aspect->value.type() == QVariant::String); + QTC_CHECK(aspect->value.typeId() == QVariant::String); const QString startArgs = aspect->value.toString(); m_amStartExtraArgs = ProcessArgs::splitArgs(startArgs, OsTypeOtherUnix); } if (auto aspect = runControl->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) { - QTC_CHECK(aspect->value.type() == QVariant::String); + QTC_CHECK(aspect->value.typeId() == QVariant::String); const QStringList commands = aspect->value.toString().split('\n', Qt::SkipEmptyParts); for (const QString &shellCmd : commands) m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd)); @@ -341,7 +341,7 @@ bool AndroidRunnerWorker::uploadDebugServer(const QString &debugServerFileName) } const QString tempDebugServerPath = tempDebugServerPathTemplate.arg(count); - auto cleanUp = qScopeGuard([this, tempDebugServerPath] { + const QScopeGuard cleanup([this, tempDebugServerPath] { if (!runAdb({"shell", "rm", "-f", tempDebugServerPath})) qCDebug(androidRunWorkerLog) << "Debug server cleanup failed."; }); diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index 70df35e663..9f10e06846 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -54,10 +54,10 @@ static QString formatResult(double value) QString beforeDecimalPoint = QString::number(value, 'f', 0); QString afterDecimalPoint = QString::number(value, 'f', 20); - afterDecimalPoint.remove(0, beforeDecimalPoint.count() + 1); + afterDecimalPoint.remove(0, beforeDecimalPoint.size() + 1); - const int beforeUse = qMin(beforeDecimalPoint.count(), significantDigits); - const int beforeRemove = beforeDecimalPoint.count() - beforeUse; + const int beforeUse = qMin(beforeDecimalPoint.size(), significantDigits); + const int beforeRemove = beforeDecimalPoint.size() - beforeUse; beforeDecimalPoint.chop(beforeRemove); for (int i = 0; i < beforeRemove; ++i) @@ -67,12 +67,12 @@ static QString formatResult(double value) if (beforeDecimalPoint == QString("0") && !afterDecimalPoint.isEmpty()) { ++afterUse; int i = 0; - while (i < afterDecimalPoint.count() && afterDecimalPoint.at(i) == '0') + while (i < afterDecimalPoint.size() && afterDecimalPoint.at(i) == '0') ++i; afterUse += i; } - const int afterRemove = afterDecimalPoint.count() - afterUse; + const int afterRemove = afterDecimalPoint.size() - afterUse; afterDecimalPoint.chop(afterRemove); QString result = beforeDecimalPoint; diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index ba226f63b5..ae3aed3548 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -124,7 +124,7 @@ QList<QWidget *> AxivionOutputPane::toolBarWidgets() const { QList<QWidget *> buttons; auto showDashboard = new QToolButton(m_outputWidget); - showDashboard->setIcon(Utils::Icons::ONLINE_TOOLBAR.icon()); + showDashboard->setIcon(Utils::Icons::HOME_TOOLBAR.icon()); showDashboard->setToolTip(Tr::tr("Show dashboard")); connect(showDashboard, &QToolButton::clicked, this, [this]{ QTC_ASSERT(m_outputWidget, return); diff --git a/src/plugins/beautifier/generalsettings.cpp b/src/plugins/beautifier/generalsettings.cpp index 2f7dc4c3a0..b0da1fc2d4 100644 --- a/src/plugins/beautifier/generalsettings.cpp +++ b/src/plugins/beautifier/generalsettings.cpp @@ -56,6 +56,7 @@ GeneralSettings::GeneralSettings() st }; }); + readSettings(); } QList<MimeType> GeneralSettings::allowedMimeTypes() const diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 070653c702..49851b25b9 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -230,14 +230,22 @@ public: void enableCodeActionsInline() {insert(u"codeActionsInline", true);} }; +class InactiveRegionsCapabilities : public JsonObject +{ +public: + using JsonObject::JsonObject; + void enableInactiveRegionsSupport() { insert(u"inactiveRegions", true); } +}; + class ClangdTextDocumentClientCapabilities : public TextDocumentClientCapabilities { public: using TextDocumentClientCapabilities::TextDocumentClientCapabilities; - void setPublishDiagnostics(const DiagnosticsCapabilities &caps) { insert(u"publishDiagnostics", caps); } + void setInactiveRegionsCapabilities(const InactiveRegionsCapabilities &caps) + { insert(u"inactiveRegionsCapabilities", caps); } }; static qint64 getRevision(const TextDocument *doc) @@ -428,6 +436,9 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c diagnostics.enableCategorySupport(); diagnostics.enableCodeActionsInline(); clangdTextCaps.setPublishDiagnostics(diagnostics); + InactiveRegionsCapabilities inactiveRegions; + inactiveRegions.enableInactiveRegionsSupport(); + clangdTextCaps.setInactiveRegionsCapabilities(inactiveRegions); std::optional<TextDocumentClientCapabilities::CompletionCapabilities> completionCaps = textCaps->completion(); if (completionCaps) @@ -456,6 +467,9 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c const Utils::FilePath &filePath) { gatherHelpItemForTooltip(response, filePath); }); + registerCustomMethod(inactiveRegionsMethodName(), [this](const JsonRpcMessage &msg) { + handleInactiveRegions(this, msg); + }); connect(this, &Client::workDone, this, [this, p = QPointer(project)](const ProgressToken &token) { @@ -692,7 +706,8 @@ class ClangdDiagnosticManager : public LanguageClient::DiagnosticManager return Utils::filtered(diagnostics, [](const Diagnostic &diag){ const Diagnostic::Code code = diag.code().value_or(Diagnostic::Code()); const QString * const codeString = std::get_if<QString>(&code); - return !codeString || *codeString != "drv_unknown_argument"; + return !codeString || (*codeString != "drv_unknown_argument" + && !codeString->startsWith("drv_unsupported_opt")); }); } diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp index e1b82ab377..f93d8302bd 100644 --- a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp +++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp @@ -330,6 +330,8 @@ void doSemanticHighlighting( styles.mainStyle = C_TYPE; } else if (token.type == "modifier") { styles.mainStyle = C_KEYWORD; + } else if (token.type == "label") { + styles.mainStyle = C_LABEL; } else if (token.type == "typeParameter") { // clangd reports both type and non-type template parameters as type parameters, // but the latter can be distinguished by the readonly modifier. @@ -396,7 +398,10 @@ void doSemanticHighlighting( } }; auto results = QtConcurrent::blockingMapped<HighlightingResults>(tokens, safeToResult); - const QList<BlockRange> ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents); + const bool handleInactiveCode = clangdMajorVersion < 17; + QList<BlockRange> ifdefedOutBlocks; + if (handleInactiveCode) + ifdefedOutBlocks = cleanupDisabledCode(results, &doc, docContents); ExtraHighlightingResultsCollector(promise, results, filePath, ast, &doc, docContents, clangdVersion).collect(); Utils::erase(results, [](const HighlightingResult &res) { @@ -405,10 +410,12 @@ void doSemanticHighlighting( }); if (!promise.isCanceled()) { qCInfo(clangdLogHighlight) << "reporting" << results.size() << "highlighting results"; - QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] { - if (textDocument && textDocument->document()->revision() == docRevision) - textDocument->setIfdefedOutBlocks(ifdefedOutBlocks); - }, Qt::QueuedConnection); + if (handleInactiveCode) { + QMetaObject::invokeMethod(textDocument, [textDocument, ifdefedOutBlocks, docRevision] { + if (textDocument && textDocument->document()->revision() == docRevision) + textDocument->setIfdefedOutBlocks(ifdefedOutBlocks); + }, Qt::QueuedConnection); + } QList<Range> virtualRanges; for (const HighlightingResult &r : results) { if (r.textStyles.mainStyle != C_VIRTUAL_METHOD) @@ -953,4 +960,45 @@ void ExtraHighlightingResultsCollector::visitNode(const ClangdAstNode &node) m_currentFileStatus = prevFileStatus; } +class InactiveRegionsParams : public JsonObject +{ +public: + using JsonObject::JsonObject; + + DocumentUri uri() const { return TextDocumentIdentifier(value(u"textDocument")).uri(); } + QList<Range> inactiveRegions() const { return array<Range>(u"regions"); } +}; + +class InactiveRegionsNotification : public Notification<InactiveRegionsParams> +{ +public: + explicit InactiveRegionsNotification(const InactiveRegionsParams ¶ms) + : Notification(inactiveRegionsMethodName(), params) {} + using Notification::Notification; +}; + +void handleInactiveRegions(LanguageClient::Client *client, const JsonRpcMessage &msg) +{ + const auto params = InactiveRegionsNotification(msg.toJsonObject()).params(); + if (!params) + return; + TextDocument * const doc = client->documentForFilePath( + params->uri().toFilePath(client->hostPathMapper())); + if (!doc) + return; + const QList<Range> inactiveRegions = params->inactiveRegions(); + QList<BlockRange> ifdefedOutBlocks; + for (const Range &r : inactiveRegions) { + const int startPos = r.start().toPositionInDocument(doc->document()); + const int endPos = r.end().toPositionInDocument(doc->document()) + 1; + ifdefedOutBlocks.emplaceBack(startPos, endPos); + } + doc->setIfdefedOutBlocks(ifdefedOutBlocks); +} + +QString inactiveRegionsMethodName() +{ + return "textDocument/inactiveRegions"; +} + } // namespace ClangCodeModel::Internal diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.h b/src/plugins/clangcodemodel/clangdsemantichighlighting.h index a7f667d459..285ba2323e 100644 --- a/src/plugins/clangcodemodel/clangdsemantichighlighting.h +++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.h @@ -12,7 +12,11 @@ template <typename T> class QPromise; QT_END_NAMESPACE -namespace LanguageClient { class ExpandedSemanticToken; } +namespace LanguageClient { +class Client; +class ExpandedSemanticToken; +} +namespace LanguageServerProtocol { class JsonRpcMessage; } namespace TextEditor { class HighlightingResult; class TextDocument; @@ -36,4 +40,9 @@ void doSemanticHighlighting( const TaskTimer &taskTimer ); + +QString inactiveRegionsMethodName(); +void handleInactiveRegions(LanguageClient::Client *client, + const LanguageServerProtocol::JsonRpcMessage &msg); + } // namespace ClangCodeModel::Internal diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index f236fa81b0..d5d7868137 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -230,7 +230,7 @@ QString DiagnosticTextInfo::option() const return QString(); const int index = m_squareBracketStartIndex + 1; - return m_text.mid(index, m_text.count() - index - 1); + return m_text.mid(index, m_text.size() - index - 1); } QString DiagnosticTextInfo::category() const diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index a90126c00e..a102f1d352 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -1225,8 +1225,10 @@ void ClangdTestHighlighting::test_data() << QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketClose); QTest::newRow("macro in struct") << 795 << 9 << 795 << 14 << QList<int>{C_MACRO, C_DECLARATION} << 0; - QTest::newRow("#ifdef'ed out code") << 800 << 1 << 800 << 17 - << QList<int>{C_DISABLED_CODE} << 0; + if (client()->versionNumber() < QVersionNumber(17)) { + QTest::newRow("#ifdef'ed out code") << 800 << 1 << 800 << 17 + << QList<int>{C_DISABLED_CODE} << 0; + } QTest::newRow("static function call (object)") << 819 << 5 << 819 << 6 << QList<int>{C_LOCAL} << 0; QTest::newRow("static function call (argument)") << 819 << 18 << 819 << 19 @@ -1302,6 +1304,9 @@ void ClangdTestHighlighting::test_data() QTest::newRow("concept definition") << 1053 << 30 << 1053 << 42 << QList<int>{C_TYPE, C_DECLARATION} << 0; QTest::newRow("concept use") << 1054 << 29 << 1054 << 41 << QList<int>{C_TYPE} << 0; + QTest::newRow("label declaration") << 242 << 1 << 242 << 11 + << QList<int>{C_LABEL, C_DECLARATION} << 0; + QTest::newRow("label use") << 244 << 10 << 244 << 20 << QList<int>{C_LABEL} << 0; } void ClangdTestHighlighting::test() diff --git a/src/plugins/clangformat/clangformatfile.cpp b/src/plugins/clangformat/clangformatfile.cpp index f0c4809913..fc1659b976 100644 --- a/src/plugins/clangformat/clangformatfile.cpp +++ b/src/plugins/clangformat/clangformatfile.cpp @@ -158,8 +158,6 @@ CppEditor::CppCodeStyleSettings ClangFormatFile::toCppCodeStyleSettings( settings.indentSwitchLabels = style.IndentCaseLabels; #if LLVM_VERSION_MAJOR >= 11 settings.indentBlocksRelativeToSwitchLabels = style.IndentCaseBlocks; - settings.indentStatementsRelativeToSwitchLabels = style.IndentCaseBlocks; - settings.indentControlFlowRelativeToSwitchLabels = style.IndentCaseBlocks; #endif if (style.DerivePointerAlignment && ClangFormatSettings::instance().mode() == ClangFormatSettings::Mode::Formatting) { @@ -200,9 +198,7 @@ void ClangFormatFile::fromCppCodeStyleSettings(const CppEditor::CppCodeStyleSett m_style.IndentCaseLabels = settings.indentSwitchLabels; #if LLVM_VERSION_MAJOR >= 11 - m_style.IndentCaseBlocks = settings.indentBlocksRelativeToSwitchLabels - || settings.indentStatementsRelativeToSwitchLabels - || settings.indentControlFlowRelativeToSwitchLabels; + m_style.IndentCaseBlocks = settings.indentBlocksRelativeToSwitchLabels; #endif if (settings.extraPaddingForConditionsIfConfusingAlign) diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp index 0672d43054..34ecf11e9a 100644 --- a/src/plugins/clangtools/clangtoolsunittests.cpp +++ b/src/plugins/clangtools/clangtoolsunittests.cpp @@ -23,7 +23,6 @@ #include <qtsupport/qtkitinformation.h> #include <utils/environment.h> -#include <utils/executeondestruction.h> #include <utils/fileutils.h> #include <QSignalSpy> diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp index 93cd27bac3..8dab531dcb 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -158,7 +158,7 @@ void DocumentClangToolRunner::run() if (m_projectSettingsUpdate) disconnect(m_projectSettingsUpdate); m_taskTree.reset(); - QScopeGuard guard([this] { finalize(); }); + QScopeGuard cleanup([this] { finalize(); }); auto isEditorForCurrentDocument = [this](const IEditor *editor) { return editor->document() == m_document; @@ -216,7 +216,7 @@ void DocumentClangToolRunner::run() if (tasks.isEmpty()) return; - guard.dismiss(); + cleanup.dismiss(); m_taskTree.reset(new TaskTree(tasks)); connect(m_taskTree.get(), &TaskTree::done, this, &DocumentClangToolRunner::finalize); connect(m_taskTree.get(), &TaskTree::errorOccurred, this, &DocumentClangToolRunner::finalize); diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp index e8ff40b310..2646c5c580 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp @@ -215,13 +215,13 @@ bool CMakeConfigItem::less(const CMakeConfigItem &a, const CMakeConfigItem &b) CMakeConfigItem CMakeConfigItem::fromString(const QString &s) { // Strip comments (only at start of line!): - int commentStart = s.count(); - for (int i = 0; i < s.count(); ++i) { + int commentStart = s.size(); + for (int i = 0; i < s.size(); ++i) { const QChar c = s.at(i); if (c == ' ' || c == '\t') continue; else if ((c == '#') - || (c == '/' && i < s.count() - 1 && s.at(i + 1) == '/')) { + || (c == '/' && i < s.size() - 1 && s.at(i + 1) == '/')) { commentStart = i; break; } else { @@ -234,7 +234,7 @@ CMakeConfigItem CMakeConfigItem::fromString(const QString &s) int firstPos = -1; int colonPos = -1; int equalPos = -1; - for (int i = 0; i < line.count(); ++i) { + for (int i = 0; i < line.size(); ++i) { const QChar c = s.at(i); if (firstPos < 0 && !c.isSpace()) { firstPos = i; @@ -272,10 +272,10 @@ CMakeConfigItem CMakeConfigItem::fromString(const QString &s) static QByteArray trimCMakeCacheLine(const QByteArray &in) { int start = 0; - while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t')) + while (start < in.size() && (in.at(start) == ' ' || in.at(start) == '\t')) ++start; - return in.mid(start, in.count() - start - 1); + return in.mid(start, in.size() - start - 1); } static QByteArrayList splitCMakeCacheLine(const QByteArray &line) { @@ -371,15 +371,15 @@ CMakeConfig CMakeConfig::fromFile(const Utils::FilePath &cacheFile, QString *err if (pieces.isEmpty()) continue; - QTC_ASSERT(pieces.count() == 3, continue); + QTC_ASSERT(pieces.size() == 3, continue); const QByteArray key = pieces.at(0); const QByteArray type = pieces.at(1); const QByteArray value = pieces.at(2); if (key.endsWith("-ADVANCED") && value == "1") { - advancedSet.insert(key.left(key.count() - 9 /* "-ADVANCED" */)); + advancedSet.insert(key.left(key.size() - 9 /* "-ADVANCED" */)); } else if (key.endsWith("-STRINGS") && CMakeConfigItem::typeStringToType(type) == CMakeConfigItem::INTERNAL) { - valuesMap[key.left(key.count() - 8) /* "-STRINGS" */] = value; + valuesMap[key.left(key.size() - 8) /* "-STRINGS" */] = value; } else { CMakeConfigItem::Type t = CMakeConfigItem::typeStringToType(type); result << CMakeConfigItem(key, t, documentation, value); @@ -387,7 +387,7 @@ CMakeConfig CMakeConfig::fromFile(const Utils::FilePath &cacheFile, QString *err } // Set advanced flags: - for (int i = 0; i < result.count(); ++i) { + for (int i = 0; i < result.size(); ++i) { CMakeConfigItem &item = result[i]; item.isAdvanced = advancedSet.contains(item.key); diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index 5193661e57..4bbe75b77c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -157,7 +157,7 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, // find the beginning of a filename QString buffer; - int beginPos = column; + int beginPos = column - 1; while (beginPos >= 0) { if (isValidFileNameChar(block, beginPos)) { buffer.prepend(block.at(beginPos)); @@ -169,7 +169,7 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, // find the end of a filename int endPos = column; - while (endPos < block.count()) { + while (endPos < block.size()) { if (isValidFileNameChar(block, endPos)) { buffer.append(block.at(endPos)); endPos++; diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index def549f580..54add7395f 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -75,22 +75,15 @@ public: m_comboBox->setEnabled(false); m_comboBox->setToolTip(ki->description()); - const QList<CMakeTool *> tools = CMakeToolManager::cmakeTools(); - for (const CMakeTool *tool : tools) - cmakeToolAdded(tool->id()); - - updateComboBox(); refresh(); + connect(m_comboBox, &QComboBox::currentIndexChanged, this, &CMakeKitAspectWidget::currentCMakeToolChanged); CMakeToolManager *cmakeMgr = CMakeToolManager::instance(); - connect(cmakeMgr, &CMakeToolManager::cmakeAdded, - this, &CMakeKitAspectWidget::cmakeToolAdded); - connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, - this, &CMakeKitAspectWidget::cmakeToolRemoved); - connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, - this, &CMakeKitAspectWidget::cmakeToolUpdated); + connect(cmakeMgr, &CMakeToolManager::cmakeAdded, this, &CMakeKitAspectWidget::refresh); + connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, this, &CMakeKitAspectWidget::refresh); + connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, this, &CMakeKitAspectWidget::refresh); } ~CMakeKitAspectWidget() override @@ -112,69 +105,48 @@ private: void refresh() override { - CMakeTool *tool = CMakeKitAspect::cmakeTool(m_kit); - m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1); - } + const GuardLocker locker(m_ignoreChanges); + m_comboBox->clear(); - int indexOf(Id id) - { - for (int i = 0; i < m_comboBox->count(); ++i) { - if (id == Id::fromSetting(m_comboBox->itemData(i))) - return i; - } - return -1; - } + IDeviceConstPtr device = BuildDeviceKitAspect::device(kit()); + const FilePath rootPath = device->rootPath(); - void updateComboBox() - { - // remove unavailable cmake tool: - int pos = indexOf(Id()); - if (pos >= 0) - m_comboBox->removeItem(pos); + const auto list = CMakeToolManager::cmakeTools(); + + m_comboBox->setEnabled(!list.isEmpty()); - if (m_comboBox->count() == 0) { + if (list.isEmpty()) { m_comboBox->addItem(Tr::tr("<No CMake Tool available>"), Id().toSetting()); - m_comboBox->setEnabled(false); - } else { - m_comboBox->setEnabled(true); + return; } - } - void cmakeToolAdded(Id id) - { - const CMakeTool *tool = CMakeToolManager::findById(id); - QTC_ASSERT(tool, return); + const QList<CMakeTool *> same = Utils::filtered(list, [rootPath](CMakeTool *item) { + return item->cmakeExecutable().isSameDevice(rootPath); + }); + const QList<CMakeTool *> other = Utils::filtered(list, [rootPath](CMakeTool *item) { + return !item->cmakeExecutable().isSameDevice(rootPath); + }); - m_comboBox->addItem(tool->displayName(), tool->id().toSetting()); - updateComboBox(); - refresh(); - } + for (CMakeTool *item : same) + m_comboBox->addItem(item->displayName(), item->id().toSetting()); - void cmakeToolUpdated(Id id) - { - const int pos = indexOf(id); - QTC_ASSERT(pos >= 0, return); + if (!same.isEmpty() && !other.isEmpty()) + m_comboBox->insertSeparator(m_comboBox->count()); - const CMakeTool *tool = CMakeToolManager::findById(id); - QTC_ASSERT(tool, return); + for (CMakeTool *item : other) + m_comboBox->addItem(item->displayName(), item->id().toSetting()); - m_comboBox->setItemText(pos, tool->displayName()); + CMakeTool *tool = CMakeKitAspect::cmakeTool(m_kit); + m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1); } - void cmakeToolRemoved(Id id) + int indexOf(Id id) { - const int pos = indexOf(id); - QTC_ASSERT(pos >= 0, return); - - { - // do not handle the current index changed signal - const GuardLocker locker(m_ignoreChanges); - m_comboBox->removeItem(pos); + for (int i = 0; i < m_comboBox->count(); ++i) { + if (id == Id::fromSetting(m_comboBox->itemData(i))) + return i; } - - // update the checkbox and set the current index - updateComboBox(); - refresh(); + return -1; } void currentCMakeToolChanged(int index) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index 3a7a7e6c53..4fef3bda46 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -431,7 +431,7 @@ static QVector<ToolChainDescription> extractToolChainsFromCache(const CMakeConfi for (const CMakeConfigItem &i : config) { if (!i.key.startsWith("CMAKE_") || !i.key.endsWith("_COMPILER")) continue; - const QByteArray language = i.key.mid(6, i.key.count() - 6 - 9); // skip "CMAKE_" and "_COMPILER" + const QByteArray language = i.key.mid(6, i.key.size() - 6 - 9); // skip "CMAKE_" and "_COMPILER" Id languageId; if (language == "CXX") { haveCCxxCompiler = true; diff --git a/src/plugins/copilot/Copilot.json.in b/src/plugins/copilot/Copilot.json.in index 55ff6f6bf4..ae5853c212 100644 --- a/src/plugins/copilot/Copilot.json.in +++ b/src/plugins/copilot/Copilot.json.in @@ -2,7 +2,7 @@ \"Name\" : \"Copilot\", \"Version\" : \"$$QTCREATOR_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", - \"Experimental\" : true, + \"DisabledByDefault\" : true, \"Vendor\" : \"The Qt Company Ltd\", \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", diff --git a/src/plugins/copilot/copilothoverhandler.cpp b/src/plugins/copilot/copilothoverhandler.cpp index 135cbd8390..d17ec073b2 100644 --- a/src/plugins/copilot/copilothoverhandler.cpp +++ b/src/plugins/copilot/copilothoverhandler.cpp @@ -15,6 +15,7 @@ #include <utils/utilsicons.h> #include <QPushButton> +#include <QScopeGuard> #include <QToolBar> #include <QToolButton> @@ -117,7 +118,7 @@ void CopilotHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - auto reportNone = qScopeGuard([&] { report(Priority_None); }); + QScopeGuard cleanup([&] { report(Priority_None); }); if (!editorWidget->suggestionVisible()) return; @@ -133,7 +134,7 @@ void CopilotHoverHandler::identifyMatch(TextEditorWidget *editorWidget, if (completions.isEmpty()) return; - reportNone.dismiss(); + cleanup.dismiss(); report(Priority_Suggestion); } diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 81262f5ebf..261146797b 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -3325,7 +3325,7 @@ IEditor *EditorManager::openEditorWithContents(Id editorId, EditorManager::gotoOtherSplit(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - const auto cleanup = qScopeGuard(&QApplication::restoreOverrideCursor); + const QScopeGuard cleanup(&QApplication::restoreOverrideCursor); const QString title = makeTitleUnique(titlePattern); diff --git a/src/plugins/coreplugin/find/findtoolwindow.cpp b/src/plugins/coreplugin/find/findtoolwindow.cpp index 0125671d34..d1e3a9fd23 100644 --- a/src/plugins/coreplugin/find/findtoolwindow.cpp +++ b/src/plugins/coreplugin/find/findtoolwindow.cpp @@ -65,6 +65,7 @@ FindToolWindow::FindToolWindow(QWidget *parent) m_searchTerm = new FancyLineEdit(this); m_searchTerm->setFiltering(true); + m_searchTerm->setPlaceholderText({}); m_searchLabel = new QLabel(this); m_searchLabel->setText(Tr::tr("Search f&or:", nullptr)); diff --git a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp index dcaf86ecb9..274d79499a 100644 --- a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp +++ b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp @@ -28,7 +28,7 @@ static std::pair<int, QString> lineNumberInfo(const QStyleOptionViewItem &option if (lineNumber < 1) return {0, {}}; const QString lineNumberText = QString::number(lineNumber); - const int lineNumberDigits = qMax(minimumLineNumberDigits, lineNumberText.count()); + const int lineNumberDigits = qMax(minimumLineNumberDigits, lineNumberText.size()); const int fontWidth = option.fontMetrics.horizontalAdvance(QString(lineNumberDigits, QLatin1Char('0'))); const QStyle *style = option.widget ? option.widget->style() : QApplication::style(); return {lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 19b66e6449..eab29faf7d 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -107,6 +107,7 @@ GeneralSettingsWidget::GeneralSettingsWidget(GeneralSettings *q) Form form; form.addRow({Tr::tr("Color:"), m_colorButton, resetColorButton, st}); form.addRow({Tr::tr("Theme:"), m_themeChooser}); + form.addRow({Tr::tr("Toolbar style:"), m_toolbarStyleBox, st}); form.addRow({Tr::tr("Language:"), m_languageBox, st}); if (!Utils::HostOsInfo::isMacHost()) { @@ -125,7 +126,6 @@ GeneralSettingsWidget::GeneralSettingsWidget(GeneralSettings *q) form.addRow({empty, m_showShortcutsInContextMenus}); form.addRow({Row{m_resetWarningsButton, st}}); form.addRow({Tr::tr("Text codec for tools:"), m_codecBox, st}); - form.addRow({Tr::tr("Toolbar Style:"), m_toolbarStyleBox, st}); Column{Group{title(Tr::tr("User Interface")), form}}.attachTo(this); fillLanguageBox(); @@ -152,7 +152,7 @@ GeneralSettingsWidget::GeneralSettingsWidget(GeneralSettings *q) static bool hasQmFilesForLocale(const QString &locale, const QString &creatorTrPath) { - static const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + static const QString qtTrPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); const QString trFile = QLatin1String("/qt_") + locale + QLatin1String(".qm"); return QFile::exists(qtTrPath + trFile) || QFile::exists(creatorTrPath + trFile); diff --git a/src/plugins/coreplugin/helpitem.cpp b/src/plugins/coreplugin/helpitem.cpp index 7245a4769b..cbe0998e03 100644 --- a/src/plugins/coreplugin/helpitem.cpp +++ b/src/plugins/coreplugin/helpitem.cpp @@ -177,7 +177,7 @@ QString HelpItem::extractContent(bool extended) const // include separators for major vs minor vs patch version. static QVersionNumber qtVersionHeuristic(const QString &digits) { - if (digits.count() > 6 || digits.count() < 3) + if (digits.size() > 6 || digits.size() < 3) return {}; // suspicious version number for (const QChar &digit : digits) @@ -188,7 +188,7 @@ static QVersionNumber qtVersionHeuristic(const QString &digits) // When we have 4 digits, we split it like: ABCD -> A.BC.D // When we have 5 digits, we split it like: ABCDE -> A.BC.DE // When we have 6 digits, we split it like: ABCDEF -> AB.CD.EF - switch (digits.count()) { + switch (digits.size()) { case 3: return QVersionNumber(digits.mid(0, 1).toInt(), digits.mid(1, 1).toInt(), diff --git a/src/plugins/coreplugin/ioutputpane.h b/src/plugins/coreplugin/ioutputpane.h index f3ae7fa0b8..9193699ca4 100644 --- a/src/plugins/coreplugin/ioutputpane.h +++ b/src/plugins/coreplugin/ioutputpane.h @@ -92,6 +92,8 @@ protected: void setupContext(const Context &context, QWidget *widget); void setZoomButtonsEnabled(bool enabled); + IContext *m_context = nullptr; + private: virtual void updateFilter(); @@ -108,7 +110,6 @@ private: QAction *m_filterActionCaseSensitive = nullptr; QAction *m_invertFilterAction = nullptr; Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr; - IContext *m_context = nullptr; bool m_filterRegexp = false; bool m_invertFilter = false; Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive; diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 0a4665361d..74ad227e97 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -490,7 +490,7 @@ void LocatorMatcher::start() } }; - d->m_taskTree->setupRoot(root); + d->m_taskTree->setRecipe(root); const auto onFinish = [this](bool success) { return [this, success] { diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp index 3656d67320..b179b32316 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.cpp +++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp @@ -15,7 +15,6 @@ #include <QJSEngine> #include <QPair> #include <QPointer> -#include <QScopeGuard> #include <chrono> diff --git a/src/plugins/coreplugin/loggingmanager.cpp b/src/plugins/coreplugin/loggingmanager.cpp index 665bf42556..608e7ce470 100644 --- a/src/plugins/coreplugin/loggingmanager.cpp +++ b/src/plugins/coreplugin/loggingmanager.cpp @@ -105,7 +105,7 @@ static QList<FilterRuleSpec> fetchOriginalRules() }; Utils::FilePath iniFile = Utils::FilePath::fromString( - QLibraryInfo::location(QLibraryInfo::DataPath)).pathAppended("qtlogging.ini"); + QLibraryInfo::path(QLibraryInfo::DataPath)).pathAppended("qtlogging.ini"); if (iniFile.exists()) appendRulesFromFile(iniFile.toString()); diff --git a/src/plugins/coreplugin/loggingviewer.cpp b/src/plugins/coreplugin/loggingviewer.cpp index 63fba41a4d..742e65a34c 100644 --- a/src/plugins/coreplugin/loggingviewer.cpp +++ b/src/plugins/coreplugin/loggingviewer.cpp @@ -591,7 +591,7 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const { // should we just let it continue without temporarily disabling? const bool enabled = m_manager->isEnabled(); - const auto cleanup = qScopeGuard([this, enabled] { m_manager->setEnabled(enabled); }); + const QScopeGuard cleanup([this, enabled] { m_manager->setEnabled(enabled); }); if (enabled) m_manager->setEnabled(false); const Utils::FilePath fp = Utils::FileUtils::getSaveFilePath(ICore::dialogParent(), diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 2d7ec70c8e..c93710ff58 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -63,6 +63,7 @@ #include <utils/stylehelper.h> #include <utils/theme/theme.h> #include <utils/touchbar/touchbar.h> +#include <utils/terminalcommand.h> #include <utils/utilsicons.h> #include <QAbstractProxyModel> @@ -1228,6 +1229,14 @@ void MainWindow::saveSettings() EditorManagerPrivate::saveSettings(); m_leftNavigationWidget->saveSettings(settings); m_rightNavigationWidget->saveSettings(settings); + + // TODO Remove some time after Qt Creator 11 + // Work around Qt Creator <= 10 writing the default terminal to the settings. + // TerminalCommand writes the terminal to the settings when changing it, which usually is + // enough. But because of the bug in Qt Creator <= 10 we want to clean up the settings + // even if the user never touched the terminal setting. + if (HostOsInfo::isMacHost()) + TerminalCommand::setTerminalEmulator(TerminalCommand::terminalEmulator()); } void MainWindow::saveWindowSettings() diff --git a/src/plugins/coreplugin/mimetypesettings.cpp b/src/plugins/coreplugin/mimetypesettings.cpp index 116fcf4a06..e3dac8ded9 100644 --- a/src/plugins/coreplugin/mimetypesettings.cpp +++ b/src/plugins/coreplugin/mimetypesettings.cpp @@ -83,9 +83,7 @@ public: class MimeTypeSettingsModel : public QAbstractTableModel { public: - enum class Role { - DefaultHandler = Qt::UserRole - }; + enum class Role { DefaultHandler = Qt::UserRole, MimeType }; MimeTypeSettingsModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {} @@ -158,6 +156,8 @@ QVariant MimeTypeSettingsModel::data(const QModelIndex &modelIndex, int role) co } } return QVariant(); + } else if (role == int(Role::MimeType)) { + return QVariant::fromValue(m_mimeTypes.at(modelIndex.row())); } return QVariant(); } @@ -222,6 +222,37 @@ void MimeTypeSettingsModel::resetUserDefaults() endResetModel(); } +class MimeFilterModel : public QSortFilterProxyModel +{ +public: + explicit MimeFilterModel(QObject *parent = nullptr); + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +}; + +MimeFilterModel::MimeFilterModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ +} + +bool MimeFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + const QModelIndex &index = sourceModel()->index(source_row, 0, source_parent); + const MimeType mt + = sourceModel()->data(index, int(MimeTypeSettingsModel::Role::MimeType)).value<MimeType>(); + const QModelIndex &handlerIndex = sourceModel()->index(source_row, 1, source_parent); + const QString handlerText = sourceModel()->data(handlerIndex, Qt::DisplayRole).toString(); + + const QStringList matchStrings = mt.globPatterns() << mt.name() << handlerText; + const QRegularExpression regex = filterRegularExpression(); + for (const QString &str : matchStrings) { + if (regex.match(str).hasMatch()) + return true; + } + return false; +} + // MimeTypeSettingsPrivate class MimeTypeSettingsPrivate : public QObject { @@ -256,7 +287,7 @@ public: static UserMimeTypeHash m_userModifiedMimeTypes; // these are already in mime database MimeTypeSettingsModel *m_model; - QSortFilterProxyModel *m_filterModel; + MimeFilterModel *m_filterModel; UserMimeTypeHash m_pendingModifiedMimeTypes; // currently edited in the options page QString m_filterPattern; QPointer<QWidget> m_widget; @@ -277,10 +308,11 @@ MimeTypeSettingsPrivate::UserMimeTypeHash MimeTypeSettingsPrivate::m_userModifie MimeTypeSettingsPrivate::MimeTypeSettingsPrivate() : m_model(new MimeTypeSettingsModel(this)) - , m_filterModel(new QSortFilterProxyModel(this)) + , m_filterModel(new MimeFilterModel(this)) { m_filterModel->setSourceModel(m_model); m_filterModel->setFilterKeyColumn(-1); + m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); connect(ICore::instance(), &ICore::saveSettingsRequested, this, &MimeTypeSettingsPrivate::writeUserModifiedMimeTypes); } @@ -317,6 +349,7 @@ void MimeTypeSettingsPrivate::configureUi(QWidget *w) auto filterLineEdit = new FancyLineEdit; filterLineEdit->setObjectName("filterLineEdit"); filterLineEdit->setFiltering(true); + m_filterModel->setFilterWildcard({}); m_mimeTypesTreeView = new QTreeView; m_mimeTypesTreeView->setObjectName("mimeTypesTreeView"); diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp index e1bac00a88..9608ed6caf 100644 --- a/src/plugins/coreplugin/modemanager.cpp +++ b/src/plugins/coreplugin/modemanager.cpp @@ -99,7 +99,7 @@ static int indexOf(Id id) void ModeManagerPrivate::showMenu(int index, QMouseEvent *event) { QTC_ASSERT(m_modes.at(index)->menu(), return); - m_modes.at(index)->menu()->popup(event->globalPos()); + m_modes.at(index)->menu()->popup(event->globalPosition().toPoint()); } ModeManager::ModeManager(Internal::MainWindow *mainWindow, diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp index f9da6ee59f..4b5e60b2fc 100644 --- a/src/plugins/coreplugin/vcsmanager.cpp +++ b/src/plugins/coreplugin/vcsmanager.cpp @@ -80,7 +80,7 @@ public: QTC_ASSERT((topLevel.isEmpty() && !vc) || (!topLevel.isEmpty() && vc), return); FilePath tmpDir = dir; - while (tmpDir.toString().count() >= topLevelString.count() && !tmpDir.isEmpty()) { + while (tmpDir.toString().size() >= topLevelString.size() && !tmpDir.isEmpty()) { m_cachedMatches.insert(tmpDir, {vc, topLevel}); // if no vc was found, this might mean we're inside a repo internal directory (.git) // Cache only input directory, not parents @@ -237,7 +237,7 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const FilePath &inpu for (auto i = allThatCanManage.constBegin(); i != allThatCanManage.constEnd(); ++i) { const QString firstString = i->first.toString(); // If topLevel was already cached for another VC, skip this one - if (tmpDir.toString().count() < firstString.count()) + if (tmpDir.toString().size() < firstString.size()) continue; d->cache(i->second, i->first, tmpDir); tmpDir = i->first.parentDir(); @@ -458,7 +458,7 @@ static FileHash makeHash(const QStringList &list) FileHash result; for (const QString &i : list) { QStringList parts = i.split(QLatin1Char(':')); - QTC_ASSERT(parts.count() == 2, continue); + QTC_ASSERT(parts.size() == 2, continue); result.insert(FilePath::fromString(QString::fromLatin1(TEST_PREFIX) + parts.at(0)), FilePath::fromString(QString::fromLatin1(TEST_PREFIX) + parts.at(1))); } @@ -547,7 +547,7 @@ void CorePlugin::testVcsManager() // qDebug() << "Expecting:" << result; const QStringList split = result.split(QLatin1Char(':')); - QCOMPARE(split.count(), 4); + QCOMPARE(split.size(), 4); QVERIFY(split.at(3) == QLatin1String("*") || split.at(3) == QLatin1String("-")); diff --git a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp index 8e551fd15b..f4df1fcd0c 100644 --- a/src/plugins/cppeditor/builtineditordocumentprocessor.cpp +++ b/src/plugins/cppeditor/builtineditordocumentprocessor.cpp @@ -254,8 +254,10 @@ void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr d qCDebug(log) << "document parsed" << document->filePath() << document->editorRevision(); // Emit ifdefed out blocks - const auto ifdefoutBlocks = toTextEditorBlocks(document->skippedBlocks()); - emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks); + if (!m_semanticHighlightingChecker || m_semanticHighlightingChecker()) { + const auto ifdefoutBlocks = toTextEditorBlocks(document->skippedBlocks()); + emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks); + } // Store parser warnings m_codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument()); diff --git a/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp b/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp index 8e7e1b8f84..6863603c95 100644 --- a/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp +++ b/src/plugins/cppeditor/clangdiagnosticconfigswidget.cpp @@ -8,7 +8,6 @@ #include "wrappablelineedit.h" #include <utils/environment.h> -#include <utils/executeondestruction.h> #include <utils/infolabel.h> #include <utils/layoutbuilder.h> #include <utils/stringutils.h> @@ -21,6 +20,7 @@ #include <QLabel> #include <QPushButton> #include <QPushButton> +#include <QScopeGuard> #include <QTabWidget> #include <QTreeView> @@ -323,7 +323,7 @@ void ClangDiagnosticConfigsWidget::sync() return; disconnectClangOnlyOptionsChanged(); - ExecuteOnDestruction e([this] { connectClangOnlyOptionsChanged(); }); + const QScopeGuard cleanup([this] { connectClangOnlyOptionsChanged(); }); // Update main button row const ClangDiagnosticConfig &config = currentConfig(); diff --git a/src/plugins/cppeditor/compileroptionsbuilder.cpp b/src/plugins/cppeditor/compileroptionsbuilder.cpp index 5f09212121..8b7dd11b2d 100644 --- a/src/plugins/cppeditor/compileroptionsbuilder.cpp +++ b/src/plugins/cppeditor/compileroptionsbuilder.cpp @@ -875,7 +875,8 @@ void CompilerOptionsBuilder::evaluateCompilerFlags() || option.startsWith("/M", Qt::CaseSensitive) || option.startsWith(includeUserPathOption) || option.startsWith(includeSystemPathOption) - || option.startsWith(includeUserPathOptionWindows)) { + || option.startsWith(includeUserPathOptionWindows) + || option.startsWith("-flto")) { // Optimization and run-time flags. continue; } diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp index 268dab9643..c587654e7e 100644 --- a/src/plugins/cppeditor/cppautocompleter.cpp +++ b/src/plugins/cppeditor/cppautocompleter.cpp @@ -20,8 +20,8 @@ #include <texteditor/textdocument.h> #include <texteditor/texteditor.h> #include <texteditor/texteditorsettings.h> -#include <utils/executeondestruction.h> +#include <QScopeGuard> #include <QtTest> #endif // WITH_TESTS @@ -267,9 +267,7 @@ void AutoCompleterTest::testAutoComplete() QVERIFY(text.contains(QLatin1Char('|'))); - Utils::ExecuteOnDestruction guard([](){ - Core::EditorManager::closeAllEditors(false); - }); + const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); }); QTextCursor tc = openEditor(text); QVERIFY(!tc.isNull()); @@ -328,9 +326,7 @@ void AutoCompleterTest::testSurroundWithSelection() QVERIFY(text.count(QLatin1Char('|')) == 2); - Utils::ExecuteOnDestruction guard([](){ - Core::EditorManager::closeAllEditors(false); - }); + const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); }); QTextCursor tc = openEditor(text); QVERIFY(!tc.isNull()); @@ -363,9 +359,7 @@ void AutoCompleterTest::testAutoBackspace() QVERIFY(text.contains(QLatin1Char('|'))); - Utils::ExecuteOnDestruction guard([](){ - Core::EditorManager::closeAllEditors(false); - }); + const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); }); QTextCursor tc = openEditor(text); QVERIFY(!tc.isNull()); @@ -405,9 +399,7 @@ void AutoCompleterTest::testInsertParagraph() QVERIFY(text.contains(QLatin1Char('|'))); - Utils::ExecuteOnDestruction guard([](){ - Core::EditorManager::closeAllEditors(false); - }); + const QScopeGuard cleanup([] { Core::EditorManager::closeAllEditors(false); }); QTextCursor tc = openEditor(text); QVERIFY(!tc.isNull()); diff --git a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp index c59fd475bd..efcbd51569 100644 --- a/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp +++ b/src/plugins/cppeditor/cppbuiltinmodelmanagersupport.cpp @@ -16,12 +16,12 @@ #include <app/app_version.h> #include <coreplugin/messagemanager.h> #include <texteditor/basehoverhandler.h> -#include <utils/executeondestruction.h> #include <utils/qtcassert.h> #include <utils/textutils.h> #include <QCoreApplication> #include <QFile> +#include <QScopeGuard> #include <QTextDocument> using namespace Core; @@ -42,7 +42,7 @@ private: return; } - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); QTextCursor tc(editorWidget->document()); tc.setPosition(pos); diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index 328b2c2346..a1d01575c5 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -23,7 +23,6 @@ #include <texteditor/textdocumentlayout.h> #include <texteditor/texteditorsettings.h> -#include <utils/executeondestruction.h> #include <utils/infobar.h> #include <utils/mimeutils.h> #include <utils/minimizableinfobars.h> @@ -31,6 +30,7 @@ #include <utils/utilsicons.h> #include <QApplication> +#include <QScopeGuard> #include <QTextDocument> const char NO_PROJECT_CONFIGURATION[] = "NoProject"; @@ -437,47 +437,45 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, bool autoSave) { - ExecuteOnDestruction resetSettingsOnScopeExit; + if (!indenter()->formatOnSave() || autoSave) + return TextEditor::TextDocument::save(errorString, filePath, autoSave); - if (indenter()->formatOnSave() && !autoSave) { - auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout()); - const int documentRevision = layout->lastSaveRevision; + auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout()); + const int documentRevision = layout->lastSaveRevision; - TextEditor::RangesInLines editedRanges; - TextEditor::RangeInLines lastRange{-1, -1}; - for (int i = 0; i < document()->blockCount(); ++i) { - const QTextBlock block = document()->findBlockByNumber(i); - if (block.revision() == documentRevision) { - if (lastRange.startLine != -1) - editedRanges.push_back(lastRange); + TextEditor::RangesInLines editedRanges; + TextEditor::RangeInLines lastRange{-1, -1}; + for (int i = 0; i < document()->blockCount(); ++i) { + const QTextBlock block = document()->findBlockByNumber(i); + if (block.revision() == documentRevision) { + if (lastRange.startLine != -1) + editedRanges.push_back(lastRange); - lastRange.startLine = lastRange.endLine = -1; - continue; - } - - // block.revision() != documentRevision - if (lastRange.startLine == -1) - lastRange.startLine = block.blockNumber() + 1; - lastRange.endLine = block.blockNumber() + 1; + lastRange.startLine = lastRange.endLine = -1; + continue; } - if (lastRange.startLine != -1) - editedRanges.push_back(lastRange); + // block.revision() != documentRevision + if (lastRange.startLine == -1) + lastRange.startLine = block.blockNumber() + 1; + lastRange.endLine = block.blockNumber() + 1; + } - if (!editedRanges.empty()) { - QTextCursor cursor(document()); - cursor.joinPreviousEditBlock(); - indenter()->format(editedRanges); - cursor.endEditBlock(); - } + if (lastRange.startLine != -1) + editedRanges.push_back(lastRange); - TextEditor::StorageSettings settings = storageSettings(); - resetSettingsOnScopeExit.reset( - [this, defaultSettings = settings]() { setStorageSettings(defaultSettings); }); - settings.m_cleanWhitespace = false; - setStorageSettings(settings); + if (!editedRanges.empty()) { + QTextCursor cursor(document()); + cursor.joinPreviousEditBlock(); + indenter()->format(editedRanges); + cursor.endEditBlock(); } + TextEditor::StorageSettings settings = storageSettings(); + const QScopeGuard cleanup([this, settings] { setStorageSettings(settings); }); + settings.m_cleanWhitespace = false; + setStorageSettings(settings); + return TextEditor::TextDocument::save(errorString, filePath, autoSave); } diff --git a/src/plugins/cppeditor/cppmodelmanager_test.cpp b/src/plugins/cppeditor/cppmodelmanager_test.cpp index c3fb341646..cb292293e4 100644 --- a/src/plugins/cppeditor/cppmodelmanager_test.cpp +++ b/src/plugins/cppeditor/cppmodelmanager_test.cpp @@ -20,11 +20,11 @@ #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectmanager.h> -#include <utils/executeondestruction.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> #include <QDebug> +#include <QScopeGuard> #include <QtTest> #define VERIFY_DOCUMENT_REVISION(document, expectedRevision) \ @@ -1085,9 +1085,7 @@ void ModelManagerTest::testRenameIncludesInEditor() Core::IEditor *editor = Core::EditorManager::openEditor(mainFile); QVERIFY(editor); EditorCloser editorCloser(editor); - Utils::ExecuteOnDestruction saveAllFiles([](){ - Core::DocumentManager::saveAllModifiedDocumentsSilently(); - }); + const QScopeGuard cleanup([] { Core::DocumentManager::saveAllModifiedDocumentsSilently(); }); QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1); QVERIFY(modelManager->isCppEditor(editor)); QVERIFY(modelManager->workingCopy().get(mainFile)); diff --git a/src/plugins/cppeditor/cppqtstyleindenter.cpp b/src/plugins/cppeditor/cppqtstyleindenter.cpp index adf514f6e7..cbcaad47a2 100644 --- a/src/plugins/cppeditor/cppqtstyleindenter.cpp +++ b/src/plugins/cppeditor/cppqtstyleindenter.cpp @@ -58,7 +58,7 @@ static bool isElectricInLine(const QChar ch, const QString &text) case '<': case '>': { // Electric if at line beginning (after space indentation) - for (int i = 0, len = text.count(); i < len; ++i) { + for (int i = 0, len = text.size(); i < len; ++i) { if (!text.at(i).isSpace()) return text.at(i) == ch; } diff --git a/src/plugins/cppeditor/cpptoolstestcase.cpp b/src/plugins/cppeditor/cpptoolstestcase.cpp index 706423c051..810f66db49 100644 --- a/src/plugins/cppeditor/cpptoolstestcase.cpp +++ b/src/plugins/cppeditor/cpptoolstestcase.cpp @@ -26,7 +26,6 @@ #include <texteditor/storagesettings.h> #include <utils/environment.h> -#include <utils/executeondestruction.h> #include <utils/fileutils.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> @@ -376,11 +375,8 @@ ProjectOpenerAndCloser::~ProjectOpenerAndCloser() return; bool hasGcFinished = false; - QMetaObject::Connection connection; - Utils::ExecuteOnDestruction disconnect([&]() { QObject::disconnect(connection); }); - connection = QObject::connect(CppModelManager::instance(), &CppModelManager::gcFinished, [&]() { - hasGcFinished = true; - }); + auto connection = QObject::connect(CppModelManager::instance(), &CppModelManager::gcFinished, + [&hasGcFinished] { hasGcFinished = true; }); for (Project *project : std::as_const(m_openProjects)) ProjectExplorerPlugin::unloadProject(project); @@ -389,6 +385,8 @@ ProjectOpenerAndCloser::~ProjectOpenerAndCloser() t.start(); while (!hasGcFinished && t.elapsed() <= 30000) QCoreApplication::processEvents(); + + QObject::disconnect(connection); } ProjectInfo::ConstPtr ProjectOpenerAndCloser::open(const FilePath &projectFile, diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp index 6c282b879c..0c5c43e83a 100644 --- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp +++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp @@ -8,13 +8,13 @@ #include <projectexplorer/projectnodes.h> #include <projectexplorer/projecttree.h> #include <texteditor/texteditor.h> -#include <utils/executeondestruction.h> #include <utils/fileutils.h> #include <utils/mimeutils.h> #include <utils/qtcassert.h> #include <utils/tooltip/tooltip.h> #include <QPoint> +#include <QScopeGuard> #include <QTextBlock> #include <QXmlStreamReader> @@ -148,7 +148,7 @@ void ResourcePreviewHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); if (editorWidget->extraSelectionTooltip(pos).isEmpty()) { const QTextBlock tb = editorWidget->document()->findBlock(pos); diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 35915f9755..180b2c0a07 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -84,9 +84,9 @@ public: { TextMark::updateLineNumber(lineNumber); QTC_ASSERT(m_bp, return); - m_bp->setLineNumber(lineNumber); + m_bp->setTextPosition({lineNumber, -1}); if (GlobalBreakpoint gbp = m_bp->globalBreakpoint()) - gbp->m_params.lineNumber = lineNumber; + gbp->m_params.textPosition.line = lineNumber; } void updateFilePath(const FilePath &fileName) final @@ -107,7 +107,7 @@ public: if (!gbp) return; BreakpointParameters params = gbp->m_params; - params.lineNumber = line; + params.textPosition.line = line; gbp->deleteBreakpoint(); BreakpointManager::createBreakpoint(params); } @@ -643,7 +643,7 @@ void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data) data->enabled = m_checkBoxEnabled->isChecked(); if (partsMask & FileAndLinePart) { - data->lineNumber = m_lineEditLineNumber->text().toInt(); + data->textPosition.line = m_lineEditLineNumber->text().toInt(); data->pathUsage = static_cast<BreakpointPathUsage>(m_comboBoxPathUsage->currentIndex()); data->fileName = m_pathChooserFileName->filePath(); } @@ -683,7 +683,7 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data) if (mask & FileAndLinePart) { m_pathChooserFileName->setFilePath(data.fileName); - m_lineEditLineNumber->setText(QString::number(data.lineNumber)); + m_lineEditLineNumber->setText(QString::number(data.textPosition.line)); } if (mask & FunctionPart) @@ -889,7 +889,7 @@ BreakHandler::BreakHandler(DebuggerEngine *engine) bool BreakpointParameters::isLocatedAt(const FilePath &file, int line, const FilePath &markerFile) const { - return lineNumber == line && (fileName == file || fileName == markerFile); + return textPosition.line == line && (fileName == file || fileName == markerFile); } static bool isSimilarTo(const BreakpointParameters ¶ms, const BreakpointParameters &needle) @@ -911,7 +911,7 @@ static bool isSimilarTo(const BreakpointParameters ¶ms, const BreakpointPara // FIXME: breaks multiple breakpoints at the same location if (!params.fileName.isEmpty() && params.fileName == needle.fileName - && params.lineNumber == needle.lineNumber) + && params.textPosition == needle.textPosition) return true; return false; @@ -1064,7 +1064,7 @@ QVariant BreakpointItem::data(int column, int role) const return empty; } if (role == Qt::UserRole + 1) - return m_parameters.lineNumber; + return m_parameters.textPosition.line; break; case BreakpointAddressColumn: if (role == Qt::DisplayRole) { @@ -1121,7 +1121,7 @@ void BreakpointItem::addToCommand(DebuggerCommand *cmd) const cmd->arg("oneshot", requested.oneShot); cmd->arg("enabled", requested.enabled); cmd->arg("file", requested.fileName.path()); - cmd->arg("line", requested.lineNumber); + cmd->arg("line", requested.textPosition.line); cmd->arg("address", requested.address); cmd->arg("expression", requested.expression); } @@ -1186,12 +1186,13 @@ void BreakHandler::requestSubBreakpointEnabling(const SubBreakpoint &sbp, bool e } } -void BreakpointItem::setMarkerFileAndLine(const FilePath &fileName, int lineNumber) +void BreakpointItem::setMarkerFileAndPosition(const FilePath &fileName, + const Text::Position &textPosition) { - if (m_parameters.fileName == fileName && m_parameters.lineNumber == lineNumber) + if (m_parameters.fileName == fileName && m_parameters.textPosition == textPosition) return; m_parameters.fileName = fileName; - m_parameters.lineNumber = lineNumber; + m_parameters.textPosition = textPosition; destroyMarker(); updateMarker(); update(); @@ -1258,7 +1259,8 @@ void BreakHandler::removeDisassemblerMarker(const Breakpoint &bp) static bool matches(const Location &loc, const BreakpointParameters &bp) { - if (loc.fileName() == bp.fileName && loc.lineNumber() == bp.lineNumber && bp.lineNumber > 0) + if (loc.fileName() == bp.fileName && loc.textPosition() == bp.textPosition + && bp.textPosition.line > 0) return true; if (loc.address() == bp.address && bp.address > 0) return true; @@ -1836,9 +1838,9 @@ FilePath BreakpointItem::markerFileName() const int BreakpointItem::markerLineNumber() const { - if (m_parameters.lineNumber > 0) - return m_parameters.lineNumber; - return requestedParameters().lineNumber; + if (m_parameters.textPosition.line > 0) + return m_parameters.textPosition.line; + return requestedParameters().textPosition.line; } const BreakpointParameters &BreakpointItem::requestedParameters() const @@ -1869,7 +1871,9 @@ bool BreakpointItem::needsChange() const return true; if (oparams.command != m_parameters.command) return true; - if (oparams.type == BreakpointByFileAndLine && oparams.lineNumber != m_parameters.lineNumber) + if (oparams.type == BreakpointByFileAndLine && oparams.textPosition != m_parameters.textPosition) + return true; + if (oparams.pathUsage != m_parameters.pathUsage) return true; // FIXME: Too strict, functions may have parameter lists, or not. // if (m_params.type == BreakpointByFunction && m_params.functionName != m_response.functionName) @@ -1950,8 +1954,8 @@ QString BreakpointItem::toolTip() const << "</td><td>" << m_parameters.fileName.toUserOutput() << "</td></tr>" << "<tr><td>" << Tr::tr("Line Number:") - << "</td><td>" << requested.lineNumber - << "</td><td>" << m_parameters.lineNumber << "</td></tr>"; + << "</td><td>" << requested.textPosition.line + << "</td><td>" << m_parameters.textPosition.line << "</td></tr>"; } if (requested.type == BreakpointByFunction || m_parameters.type == BreakpointByFileAndLine) { str << "<tr><td>" << Tr::tr("Module:") @@ -2163,12 +2167,12 @@ QVariant GlobalBreakpointItem::data(int column, int role) const break; case BreakpointLineColumn: if (role == Qt::DisplayRole) { - if (m_params.lineNumber > 0) - return m_params.lineNumber; + if (m_params.textPosition.line > 0) + return m_params.textPosition.line; return empty; } if (role == Qt::UserRole + 1) - return m_params.lineNumber; + return m_params.textPosition.line; break; case BreakpointAddressColumn: if (role == Qt::DisplayRole) { @@ -2270,9 +2274,9 @@ void GlobalBreakpointItem::removeBreakpointFromModel() void GlobalBreakpointItem::updateLineNumber(int lineNumber) { - if (m_params.lineNumber == lineNumber) + if (m_params.textPosition.line == lineNumber) return; - m_params.lineNumber = lineNumber; + m_params.textPosition.line = lineNumber; update(); } @@ -2294,7 +2298,7 @@ FilePath GlobalBreakpointItem::markerFileName() const int GlobalBreakpointItem::markerLineNumber() const { - return m_params.lineNumber; + return m_params.textPosition.line; } void GlobalBreakpointItem::updateMarker() @@ -2306,7 +2310,7 @@ void GlobalBreakpointItem::updateMarker() return; } - const int line = m_params.lineNumber; + const int line = m_params.textPosition.line; if (m_marker) { if (m_params.fileName != m_marker->filePath()) m_marker->updateFilePath(m_params.fileName); @@ -2373,7 +2377,7 @@ QString GlobalBreakpointItem::toolTip() const << "</td><td>" << m_params.fileName.toUserOutput() << "</td></tr>" << "<tr><td>" << Tr::tr("Line Number:") - << "</td><td>" << m_params.lineNumber; + << "</td><td>" << m_params.textPosition.line; } if (m_params.type == BreakpointByFunction || m_params.type == BreakpointByFileAndLine) { str << "<tr><td>" << Tr::tr("Module:") @@ -2487,7 +2491,7 @@ void BreakpointManager::setOrRemoveBreakpoint(const ContextData &location, const data.tracepoint = !tracePointMessage.isEmpty(); data.message = tracePointMessage; data.fileName = location.fileName; - data.lineNumber = location.lineNumber; + data.textPosition = location.textPosition; } else if (location.type == LocationByAddress) { data.type = BreakpointByAddress; data.tracepoint = !tracePointMessage.isEmpty(); @@ -2513,7 +2517,7 @@ GlobalBreakpoint BreakpointManager::findBreakpointFromContext(const ContextData GlobalBreakpoint bestMatch; theBreakpointManager->forItemsAtLevel<1>([&](const GlobalBreakpoint &gbp) { if (location.type == LocationByFile) { - if (gbp->m_params.isLocatedAt(location.fileName, location.lineNumber, FilePath())) { + if (gbp->m_params.isLocatedAt(location.fileName, location.textPosition.line, FilePath())) { matchLevel = 2; bestMatch = gbp; } else if (matchLevel < 2) { @@ -2522,7 +2526,7 @@ GlobalBreakpoint BreakpointManager::findBreakpointFromContext(const ContextData for (Breakpoint bp : handler->breakpoints()) { if (bp->globalBreakpoint() == gbp) { if (bp->fileName() == location.fileName - && bp->lineNumber() == location.lineNumber) { + && bp->textPosition() == location.textPosition) { matchLevel = 1; bestMatch = gbp; } @@ -2768,8 +2772,8 @@ void BreakpointManager::saveSessionData() map.insert("type", params.type); if (!params.fileName.isEmpty()) map.insert("filename", params.fileName.toSettings()); - if (params.lineNumber) - map.insert("linenumber", params.lineNumber); + if (params.textPosition.line) + map.insert("linenumber", params.textPosition.line); if (!params.functionName.isEmpty()) map.insert("funcname", params.functionName); if (params.address) @@ -2815,7 +2819,7 @@ void BreakpointManager::loadSessionData() params.fileName = FilePath::fromSettings(v); v = map.value("linenumber"); if (v.isValid()) - params.lineNumber = v.toString().toInt(); + params.textPosition.line = v.toString().toInt(); v = map.value("condition"); if (v.isValid()) params.condition = v.toString(); diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 0b939a011f..e850151c3b 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -98,7 +98,8 @@ public: QIcon icon(bool withLocationMarker = false) const; - void setMarkerFileAndLine(const Utils::FilePath &fileName, int lineNumber); + void setMarkerFileAndPosition(const Utils::FilePath &fileName, + const Utils::Text::Position &textPosition); bool needsChange() const; SubBreakpoint findOrCreateSubBreakpoint(const QString &responseId); @@ -128,14 +129,14 @@ public: QString message() const { return m_parameters.message; } QString command() const { return m_parameters.command; } quint64 address() const { return m_parameters.address; } - int lineNumber() const { return m_parameters.lineNumber; } + Utils::Text::Position textPosition() const { return m_parameters.textPosition; } bool isEnabled() const { return m_parameters.enabled; } bool isWatchpoint() const { return m_parameters.isWatchpoint(); } bool isTracepoint() const { return m_parameters.isTracepoint(); } bool isOneShot() const { return m_parameters.oneShot; } bool isPending() const { return m_parameters.pending; } - void setLineNumber(int lineNumber) { m_parameters.lineNumber = lineNumber; } + void setTextPosition(const Utils::Text::Position pos) { m_parameters.textPosition = pos; } void setFileName(const Utils::FilePath &fileName) { m_parameters.fileName = fileName; } void setFunctionName(const QString &functionName) { m_parameters.functionName = functionName; } void setPending(bool pending); diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 79e2badf7b..2fe9b2da36 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -27,7 +27,7 @@ namespace Internal { BreakpointParameters::BreakpointParameters(BreakpointType t) : type(t), enabled(true), pathUsage(BreakpointPathUsageEngineDefault), - ignoreCount(0), lineNumber(0), address(0), size(0), + ignoreCount(0), address(0), size(0), bitpos(0), bitsize(0), threadSpec(-1), tracepoint(false), oneShot(false) {} @@ -48,7 +48,7 @@ BreakpointParts BreakpointParameters::differencesTo parts |= ConditionPart; if (ignoreCount != rhs.ignoreCount) parts |= IgnoreCountPart; - if (lineNumber != rhs.lineNumber) + if (textPosition != rhs.textPosition) parts |= FileAndLinePart; if (address != rhs.address) parts |= AddressPart; @@ -73,7 +73,7 @@ bool BreakpointParameters::isValid() const { switch (type) { case BreakpointByFileAndLine: - return !fileName.isEmpty() && lineNumber > 0; + return !fileName.isEmpty() && textPosition.line > 0; case BreakpointByFunction: return !functionName.isEmpty(); case WatchpointAtAddress: @@ -116,7 +116,7 @@ void BreakpointParameters::updateLocation(const QString &location) { if (!location.isEmpty()) { int pos = location.indexOf(':'); - lineNumber = location.mid(pos + 1).toInt(); + textPosition.line = location.mid(pos + 1).toInt(); // FIXME: Handle column QString file = location.left(pos); if (file.startsWith('"') && file.endsWith('"')) file = file.mid(1, file.size() - 2); @@ -164,8 +164,8 @@ QString BreakpointParameters::toString() const ts << "Type: " << type; switch (type) { case BreakpointByFileAndLine: - ts << " FileName: " << fileName << ':' << lineNumber - << " PathUsage: " << pathUsage; + ts << " FileName: " << fileName << ':' << textPosition.line; + ts << " PathUsage: " << pathUsage; break; case BreakpointByFunction: case BreakpointOnQmlSignalEmit: @@ -295,7 +295,7 @@ void BreakpointParameters::updateFromGdbOutput(const GdbMi &bkpt, const Utils::F } else if (child.hasName("fullname")) { fullName = child.data(); } else if (child.hasName("line")) { - lineNumber = child.toInt(); + textPosition.line = child.toInt(); } else if (child.hasName("cond")) { // gdb 6.3 likes to "rewrite" conditions. Just accept that fact. condition = child.data(); diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index b5ea0628da..af96f43d05 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -7,6 +7,7 @@ #include <QString> #include <utils/filepath.h> +#include <utils/textutils.h> namespace Debugger { namespace Internal { @@ -139,7 +140,7 @@ public: Utils::FilePath fileName;//!< Short name of source file. QString condition; //!< Condition associated with breakpoint. int ignoreCount; //!< Ignore count associated with breakpoint. - int lineNumber; //!< Line in source file. + Utils::Text::Position textPosition; //!< Line and column in source file. quint64 address; //!< Address for address based data breakpoints. QString expression; //!< Expression for expression based data breakpoints. uint size; //!< Size of watched area for data breakpoints. diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 7c70a3c31b..c60052452a 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -818,7 +818,7 @@ void CdbEngine::executeRunToLine(const ContextData &data) } else { bp.type =BreakpointByFileAndLine; bp.fileName = data.fileName; - bp.lineNumber = data.lineNumber; + bp.textPosition = data.textPosition; } runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings), BuiltinCommand, @@ -854,7 +854,7 @@ void CdbEngine::executeJumpToLine(const ContextData &data) // Jump to source line: Resolve source line address and go to that location QString cmd; StringInputStream str(cmd); - str << "? `" << data.fileName.toUserOutput() << ':' << data.lineNumber << '`'; + str << "? `" << data.fileName.toUserOutput() << ':' << data.textPosition.line << '`'; runCommand({cmd, BuiltinCommand, [this, data](const DebuggerResponse &r) { handleJumpToLineAddressResolution(r, data); }}); } @@ -891,7 +891,7 @@ void CdbEngine::handleJumpToLineAddressResolution(const DebuggerResponse &respon const quint64 address = answer.toULongLong(&ok, 16); if (ok && address) { jumpToAddress(address); - gotoLocation(Location(context.fileName, context.lineNumber)); + gotoLocation(Location(context.fileName, context.textPosition)); } } @@ -2505,8 +2505,9 @@ void CdbEngine::insertBreakpoint(const Breakpoint &bp) if (!m_autoBreakPointCorrection && parameters.type == BreakpointByFileAndLine && debuggerSettings()->cdbBreakPointCorrection.value()) { - response.lineNumber = int(lineCorrection->fixLineNumber(parameters.fileName, - unsigned(parameters.lineNumber))); + response.textPosition.line = + int(lineCorrection->fixLineNumber(parameters.fileName, + unsigned(parameters.textPosition.line))); QString cmd = cdbAddBreakpointCommand(response, m_sourcePathMappings, responseId); runCommand({cmd, BuiltinCommand, handleBreakInsertCB}); } else { @@ -2979,7 +2980,7 @@ BreakpointParameters CdbEngine::parseBreakPoint(const GdbMi &gdbmi) result.fileName = Utils::FilePath::fromUserInput(mappedFile.fileName); const GdbMi lineNumber = gdbmi["srcline"]; if (lineNumber.isValid()) - result.lineNumber = lineNumber.data().toULongLong(nullptr, 0); + result.textPosition.line = lineNumber.data().toULongLong(nullptr, 0); } const GdbMi addressG = gdbmi["address"]; if (addressG.isValid()) @@ -3036,7 +3037,7 @@ void CdbEngine::handleBreakPoints(const DebuggerResponse &response) currentResponse.pending = reportedResponse.pending; currentResponse.enabled = reportedResponse.enabled; currentResponse.fileName = reportedResponse.fileName; - currentResponse.lineNumber = reportedResponse.lineNumber; + currentResponse.textPosition = reportedResponse.textPosition; formatCdbBreakPointResponse(bp->modelId(), responseId, currentResponse, str); if (debugBreakpoints) qDebug(" Setting for %s: %s\n", qPrintable(responseId), @@ -3053,7 +3054,7 @@ void CdbEngine::handleBreakPoints(const DebuggerResponse &response) currentResponse.pending = reportedResponse.pending; currentResponse.enabled = reportedResponse.enabled; currentResponse.fileName = reportedResponse.fileName; - currentResponse.lineNumber = reportedResponse.lineNumber; + currentResponse.textPosition = reportedResponse.textPosition; Breakpoint bp = sub->breakpoint(); QTC_ASSERT(bp, continue); formatCdbBreakPointResponse(bp->modelId(), responseId, currentResponse, str); diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.cpp b/src/plugins/debugger/cdb/cdbparsehelpers.cpp index 2749c0445a..dfea07a6c2 100644 --- a/src/plugins/debugger/cdb/cdbparsehelpers.cpp +++ b/src/plugins/debugger/cdb/cdbparsehelpers.cpp @@ -161,7 +161,8 @@ QString cdbAddBreakpointCommand(const BreakpointParameters &bpIn, str << '`'; if (!params.module.isEmpty()) str << params.module << '!'; - str << cdbBreakPointFileName(params, sourcePathMapping) << ':' << params.lineNumber << '`'; + str << cdbBreakPointFileName(params, sourcePathMapping) + << ':' << params.textPosition.line << '`'; break; case WatchpointAtAddress: { // Read/write, no space here const unsigned size = params.size ? params.size : 1; diff --git a/src/plugins/debugger/dap/dapengine.cpp b/src/plugins/debugger/dap/dapengine.cpp index 9db7c0f7e5..3f31129a5a 100644 --- a/src/plugins/debugger/dap/dapengine.cpp +++ b/src/plugins/debugger/dap/dapengine.cpp @@ -281,7 +281,7 @@ static QJsonObject createBreakpoint(const Breakpoint &breakpoint) return QJsonObject(); QJsonObject bp; - bp["line"] = params.lineNumber; + bp["line"] = params.textPosition.line; bp["source"] = QJsonObject{{"name", params.fileName.fileName()}, {"path", params.fileName.path()}}; return bp; @@ -622,7 +622,7 @@ void DapEngine::handleOutput(const QJsonDocument &data) QString id = QString::number(body.value("hitBreakpointIds").toArray().first().toInteger()); const BreakpointParameters ¶ms = breakHandler()->findBreakpointByResponseId(id)->requestedParameters(); - gotoLocation(Location(params.fileName, params.lineNumber)); + gotoLocation(Location(params.fileName, params.textPosition)); } if (state() == InferiorStopRequested) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 27c1373c99..0c80b0cf9f 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -142,7 +142,7 @@ static bool debuggerActionsEnabledHelper(DebuggerState state) Location::Location(const StackFrame &frame, bool marker) { m_fileName = frame.file; - m_lineNumber = frame.line; + m_textPosition = {frame.line, -1}; m_needsMarker = marker; m_functionName = frame.function; m_hasDebugInfo = frame.isUsable(); @@ -1075,7 +1075,7 @@ void DebuggerEngine::gotoLocation(const Location &loc) return; } const FilePath file = loc.fileName(); - const int line = loc.lineNumber(); + const int line = loc.textPosition().line; bool newEditor = false; IEditor *editor = EditorManager::openEditor(file, Id(), diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index ac91ecb644..783fa9b9f1 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -219,12 +219,14 @@ public: Location(quint64 address) { m_address = address; } Location(const Utils::FilePath &file) { m_fileName = file; } Location(const Utils::FilePath &file, int line, bool marker = true) - { m_lineNumber = line; m_fileName = file; m_needsMarker = marker; } + { m_textPosition = {line, -1}; m_fileName = file; m_needsMarker = marker; } + Location(const Utils::FilePath &file, const Utils::Text::Position &pos, bool marker = true) + { m_textPosition = pos; m_fileName = file; m_needsMarker = marker; } Location(const StackFrame &frame, bool marker = true); Utils::FilePath fileName() const { return m_fileName; } QString functionName() const { return m_functionName; } QString from() const { return m_from; } - int lineNumber() const { return m_lineNumber; } + Utils::Text::Position textPosition() const { return m_textPosition; } void setNeedsRaise(bool on) { m_needsRaise = on; } void setNeedsMarker(bool on) { m_needsMarker = on; } void setFileName(const Utils::FilePath &fileName) { m_fileName = fileName; } @@ -240,7 +242,7 @@ private: bool m_needsMarker = false; bool m_needsRaise = true; bool m_hasDebugInfo = true; - int m_lineNumber = -1; + Utils::Text::Position m_textPosition; Utils::FilePath m_fileName; QString m_functionName; QString m_from; diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp index b1ba6bf1d5..f2c149ad5a 100644 --- a/src/plugins/debugger/debuggerkitinformation.cpp +++ b/src/plugins/debugger/debuggerkitinformation.cpp @@ -78,7 +78,25 @@ private: const GuardLocker locker(m_ignoreChanges); m_comboBox->clear(); m_comboBox->addItem(Tr::tr("None"), QString()); - for (const DebuggerItem &item : DebuggerItemManager::debuggers()) + + IDeviceConstPtr device = BuildDeviceKitAspect::device(kit()); + const Utils::FilePath path = device->rootPath(); + const QList<DebuggerItem> list = DebuggerItemManager::debuggers(); + + const QList<DebuggerItem> same = Utils::filtered(list, [path](const DebuggerItem &item) { + return item.command().isSameDevice(path); + }); + const QList<DebuggerItem> other = Utils::filtered(list, [path](const DebuggerItem &item) { + return !item.command().isSameDevice(path); + }); + + for (const DebuggerItem &item : same) + m_comboBox->addItem(item.displayName(), item.id()); + + if (!same.isEmpty() && !other.isEmpty()) + m_comboBox->insertSeparator(m_comboBox->count()); + + for (const DebuggerItem &item : other) m_comboBox->addItem(item.displayName(), item.id()); const DebuggerItem *item = DebuggerKitAspect::debugger(m_kit); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 7ccc808b08..dffa503c45 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -110,6 +110,7 @@ #include <QMessageBox> #include <QPointer> #include <QPushButton> +#include <QScopeGuard> #include <QSettings> #include <QStackedWidget> #include <QTextBlock> @@ -125,8 +126,6 @@ #include <cppeditor/cpptoolstestcase.h> #include <cppeditor/projectinfo.h> -#include <utils/executeondestruction.h> - #include <QTest> #include <QSignalSpy> #include <QTestEventLoop> @@ -603,8 +602,8 @@ public: } else { //: Message tracepoint: %1 file, %2 line %3 function hit. message = Tr::tr("%1:%2 %3() hit").arg(data.fileName.fileName()). - arg(data.lineNumber). - arg(cppFunctionAt(data.fileName, data.lineNumber)); + arg(data.textPosition.line). + arg(cppFunctionAt(data.fileName, data.textPosition.line)); } QInputDialog dialog; // Create wide input dialog. dialog.setWindowFlags(dialog.windowFlags() & ~(Qt::MSWindowsFixedSizeDialogHint)); @@ -1881,7 +1880,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget, if (engine->hasCapability(RunToLineCapability)) { auto act = menu->addAction(args.address ? Tr::tr("Run to Address 0x%1").arg(args.address, 0, 16) - : Tr::tr("Run to Line %1").arg(args.lineNumber)); + : Tr::tr("Run to Line %1").arg(args.textPosition.line)); connect(act, &QAction::triggered, this, [args, engine] { QTC_ASSERT(engine, return); engine->executeRunToLine(args); @@ -1890,7 +1889,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget, if (engine->hasCapability(JumpToLineCapability)) { auto act = menu->addAction(args.address ? Tr::tr("Jump to Address 0x%1").arg(args.address, 0, 16) - : Tr::tr("Jump to Line %1").arg(args.lineNumber)); + : Tr::tr("Jump to Line %1").arg(args.textPosition.line)); connect(act, &QAction::triggered, this, [args, engine] { QTC_ASSERT(engine, return); engine->executeJumpToLine(args); @@ -2338,7 +2337,7 @@ void DebuggerUnitTests::testStateMachine() BuildManager::buildProjectWithDependencies(ProjectManager::startupProject()); loop.exec(); - ExecuteOnDestruction guard([] { EditorManager::closeAllEditors(false); }); + const QScopeGuard cleanup([] { EditorManager::closeAllEditors(false); }); RunConfiguration *rc = ProjectManager::startupRunConfiguration(); QVERIFY(rc); diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h index d06a95c736..702da98c9a 100644 --- a/src/plugins/debugger/debuggerprotocol.h +++ b/src/plugins/debugger/debuggerprotocol.h @@ -12,6 +12,7 @@ #include <QVector> #include <utils/filepath.h> +#include <utils/textutils.h> namespace Utils { class ProcessHandle; } @@ -326,7 +327,7 @@ public: public: LocationType type = UnknownLocation; Utils::FilePath fileName; - int lineNumber = 0; + Utils::Text::Position textPosition; quint64 address = 0; }; diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index 8efea0c487..90b5f4edb1 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -173,7 +173,7 @@ public: void DraggableLabel::mousePressEvent(QMouseEvent * event) { if (active && event->button() == Qt::LeftButton) { - m_moveStartPos = event->globalPos(); + m_moveStartPos = event->globalPosition().toPoint(); event->accept(); } QLabel::mousePressEvent(event); @@ -190,7 +190,7 @@ void DraggableLabel::mouseMoveEvent(QMouseEvent * event) { if (active && (event->buttons() & Qt::LeftButton)) { if (m_moveStartPos != QPoint(-1, -1)) { - const QPoint newPos = event->globalPos(); + const QPoint newPos = event->globalPosition().toPoint(); const QPoint offset = newPos - m_moveStartPos; m_target->move(m_target->pos() + offset); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index f69c9f72d7..e5052d1b89 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1123,7 +1123,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) const GdbMi frame = data["frame"]; // Jump over well-known frames. - static int stepCounter = 0; + //static int stepCounter = 0; if (debuggerSettings()->skipKnownFrames.value()) { if (reason == "end-stepping-range" || reason == "function-finished") { //showMessage(frame.toString()); @@ -1131,19 +1131,19 @@ void GdbEngine::handleStopResponse(const GdbMi &data) QString fileName = frame["file"].data(); if (isLeavableFunction(funcName, fileName)) { //showMessage(_("LEAVING ") + funcName); - ++stepCounter; + //++stepCounter; executeStepOut(); return; } if (isSkippableFunction(funcName, fileName)) { //showMessage(_("SKIPPING ") + funcName); - ++stepCounter; + //++stepCounter; executeStepIn(false); return; } //if (stepCounter) // qDebug() << "STEPCOUNTER:" << stepCounter; - stepCounter = 0; + //stepCounter = 0; } } @@ -1211,9 +1211,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (Breakpoint bp = breakHandler()->findBreakpointByResponseId(nr)) { const FilePath &bpFileName = bp->fileName(); if (!bpFileName.isEmpty()) - bp->setMarkerFileAndLine(bpFileName, lineNumber); + bp->setMarkerFileAndPosition(bpFileName, {lineNumber, -1}); else if (!fileName.isEmpty()) - bp->setMarkerFileAndLine(fileName, lineNumber); + bp->setMarkerFileAndPosition(fileName, {lineNumber, -1}); } } @@ -1946,13 +1946,13 @@ void GdbEngine::executeRunToLine(const ContextData &data) CHECK_STATE(InferiorStopOk); setTokenBarrier(); notifyInferiorRunRequested(); - showStatusMessage(Tr::tr("Run to line %1 requested...").arg(data.lineNumber), 5000); + showStatusMessage(Tr::tr("Run to line %1 requested...").arg(data.textPosition.line), 5000); #if 1 QString loc; if (data.address) loc = addressSpec(data.address); else - loc = '"' + breakLocation(data.fileName) + '"' + ':' + QString::number(data.lineNumber); + loc = '"' + breakLocation(data.fileName) + '"' + ':' + QString::number(data.textPosition.line); runCommand({"tbreak " + loc}); runCommand({"continue", NativeCommand|RunRequest, CB(handleExecuteRunToLine)}); @@ -1980,7 +1980,7 @@ void GdbEngine::executeJumpToLine(const ContextData &data) if (data.address) loc = addressSpec(data.address); else - loc = '"' + breakLocation(data.fileName) + '"' + ':' + QString::number(data.lineNumber); + loc = '"' + breakLocation(data.fileName) + '"' + ':' + QString::number(data.textPosition.line); runCommand({"tbreak " + loc}); notifyInferiorRunRequested(); @@ -2086,7 +2086,7 @@ QString GdbEngine::breakpointLocation(const BreakpointParameters &data) // The argument is simply a C-quoted version of the argument to the // non-MI "break" command, including the "original" quoting it wants. return "\"\\\"" + GdbMi::escapeCString(fileName) + "\\\":" - + QString::number(data.lineNumber) + '"'; + + QString::number(data.textPosition.line) + '"'; } QString GdbEngine::breakpointLocation2(const BreakpointParameters &data) @@ -2097,7 +2097,7 @@ QString GdbEngine::breakpointLocation2(const BreakpointParameters &data) const QString fileName = usage == BreakpointUseFullPath ? data.fileName.path() : breakLocation(data.fileName); - return GdbMi::escapeCString(fileName) + ':' + QString::number(data.lineNumber); + return GdbMi::escapeCString(fileName) + ':' + QString::number(data.textPosition.line); } void GdbEngine::handleInsertInterpreterBreakpoint(const DebuggerResponse &response, @@ -2236,7 +2236,7 @@ void GdbEngine::handleBreakInsert1(const DebuggerResponse &response, const Break // Older version of gdb don't know the -a option to set tracepoints // ^error,msg="mi_cmd_break_insert: Unknown option ``a''" const QString fileName = bp->fileName().toString(); - const int lineNumber = bp->lineNumber(); + const int lineNumber = bp->textPosition().line; DebuggerCommand cmd("trace \"" + GdbMi::escapeCString(fileName) + "\":" + QString::number(lineNumber), NeedsTemporaryStop); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 09b5d6eaec..f7667e40e2 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -416,7 +416,7 @@ void LldbEngine::executeRunToLine(const ContextData &data) notifyInferiorRunRequested(); DebuggerCommand cmd("executeRunToLocation"); cmd.arg("file", data.fileName.path()); - cmd.arg("line", data.lineNumber); + cmd.arg("line", data.textPosition.line); cmd.arg("address", data.address); runCommand(cmd); } @@ -433,7 +433,7 @@ void LldbEngine::executeJumpToLine(const ContextData &data) { DebuggerCommand cmd("executeJumpToLocation"); cmd.arg("file", data.fileName.path()); - cmd.arg("line", data.lineNumber); + cmd.arg("line", data.textPosition.line); cmd.arg("address", data.address); runCommand(cmd); } @@ -561,7 +561,7 @@ void LldbEngine::updateBreakpointData(const Breakpoint &bp, const GdbMi &bkpt, b bp->setCondition(fromHex(bkpt["condition"].data())); bp->setHitCount(bkpt["hitcount"].toInt()); bp->setFileName(FilePath::fromUserInput(bkpt["file"].data())); - bp->setLineNumber(bkpt["line"].toInt()); + bp->setTextPosition({bkpt["line"].toInt(), -1}); GdbMi locations = bkpt["locations"]; const int numChild = locations.childCount(); @@ -574,7 +574,7 @@ void LldbEngine::updateBreakpointData(const Breakpoint &bp, const GdbMi &bkpt, b loc->params.address = location["addr"].toAddress(); loc->params.functionName = location["function"].data(); loc->params.fileName = FilePath::fromUserInput(location["file"].data()); - loc->params.lineNumber = location["line"].toInt(); + loc->params.textPosition.line = location["line"].toInt(); loc->displayName = QString("%1.%2").arg(bp->responseId()).arg(locid); } bp->setPending(false); diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index 4a0fea3f16..e192a7d90a 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -257,7 +257,7 @@ void AttachCoreDialog::accepted() [=](const auto &task) { d->symbolFileResult = task.result(); }}, }; - d->taskTree.setupRoot(root); + d->taskTree.setRecipe(root); d->taskTree.start(); d->progressLabel->setText(Tr::tr("Copying files to device...")); diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index accf32d0e6..8b548b9d3d 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -220,7 +220,7 @@ void PdbEngine::insertBreakpoint(const Breakpoint &bp) if (params.type == BreakpointByFunction) loc = params.functionName; else - loc = params.fileName.toString() + ':' + QString::number(params.lineNumber); + loc = params.fileName.toString() + ':' + QString::number(params.textPosition.line); postDirectCommand("break " + loc); } @@ -476,7 +476,7 @@ void PdbEngine::handleOutput2(const QString &data) QTC_ASSERT(bp, continue); bp->setResponseId(bpnr); bp->setFileName(fileName); - bp->setLineNumber(lineNumber); + bp->setTextPosition({lineNumber, -1}); bp->adjustMarker(); bp->setPending(false); notifyBreakpointInsertOk(bp); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 033069c116..c0ecaf4849 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -603,10 +603,10 @@ void QmlEngine::executeRunToLine(const ContextData &data) { QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); showStatusMessage(Tr::tr("Run to line %1 (%2) requested...") - .arg(data.lineNumber) + .arg(data.textPosition.line) .arg(data.fileName.toString()), 5000); - d->setBreakpoint(SCRIPTREGEXP, data.fileName.toString(), true, data.lineNumber); + d->setBreakpoint(SCRIPTREGEXP, data.fileName.toString(), true, data.textPosition.line); clearExceptionSelection(); d->continueDebugging(Continue); @@ -658,7 +658,7 @@ void QmlEngine::insertBreakpoint(const Breakpoint &bp) } else if (requested.type == BreakpointByFileAndLine) { d->setBreakpoint(SCRIPTREGEXP, requested.fileName.toString(), - requested.enabled, requested.lineNumber, 0, + requested.enabled, requested.textPosition.line, 0, requested.condition, requested.ignoreCount); } else if (requested.type == BreakpointOnQmlSignalEmit) { @@ -716,7 +716,7 @@ void QmlEngine::updateBreakpoint(const Breakpoint &bp) } else { d->clearBreakpoint(bp); d->setBreakpoint(SCRIPTREGEXP, requested.fileName.toString(), - requested.enabled, requested.lineNumber, 0, + requested.enabled, requested.textPosition.line, 0, requested.condition, requested.ignoreCount); d->breakpointsSync.insert(d->sequence, bp); } @@ -776,7 +776,7 @@ void QmlEngine::assignValueInDebugger(WatchItem *item, const QString &expression, const QVariant &editValue) { if (!expression.isEmpty()) { - QTC_CHECK(editValue.type() == QVariant::String); + QTC_CHECK(editValue.typeId() == QVariant::String); QVariant value; QString val = editValue.toString(); if (item->type == "boolean") @@ -855,7 +855,7 @@ static ConsoleItem *constructLogItemTree(const QVariant &result, QString text; ConsoleItem *item = nullptr; - if (result.type() == QVariant::Map) { + if (result.typeId() == QVariant::Map) { if (key.isEmpty()) text = "Object"; else @@ -1727,7 +1727,7 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data) //The breakpoint requested line should be same as //actual line if (bp && bp->state() != BreakpointInserted) { - bp->setLineNumber(line); + bp->setTextPosition({line, -1}); bp->setPending(false); engine->notifyBreakpointInsertOk(bp); } @@ -1865,7 +1865,7 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data) setBreakpoint(SCRIPTREGEXP, params.fileName.toString(), params.enabled, - params.lineNumber, + params.textPosition.line, newColumn, params.condition, params.ignoreCount); @@ -1889,7 +1889,7 @@ void QmlEnginePrivate::messageReceived(const QByteArray &data) bp->setFunctionName(invocationText); } if (bp->state() != BreakpointInserted) { - bp->setLineNumber(breakData.value("sourceLine").toInt() + 1); + bp->setTextPosition({breakData.value("sourceLine").toInt() + 1, -1}); bp->setPending(false); engine->notifyBreakpointInsertOk(bp); } diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp index 4b632c0f0d..712b66e5b3 100644 --- a/src/plugins/debugger/qml/qmlinspectoragent.cpp +++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp @@ -221,7 +221,7 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value, if (m_objectTreeQueryIds.contains(queryId)) { m_objectTreeQueryIds.removeOne(queryId); - if (value.type() == QVariant::List) { + if (value.typeId() == QVariant::List) { const QVariantList objList = value.toList(); for (const QVariant &var : objList) { // TODO: check which among the list is the actual @@ -289,7 +289,7 @@ static void sortChildrenIfNecessary(WatchItem *propertiesWatch) static bool insertChildren(WatchItem *parent, const QVariant &value) { - switch (value.type()) { + switch (value.typeId()) { case QVariant::Map: { const QVariantMap map = value.toMap(); for (auto it = map.begin(), end = map.end(); it != end; ++it) { diff --git a/src/plugins/debugger/sourceutils.cpp b/src/plugins/debugger/sourceutils.cpp index 2149821662..82f1929bb8 100644 --- a/src/plugins/debugger/sourceutils.cpp +++ b/src/plugins/debugger/sourceutils.cpp @@ -315,14 +315,14 @@ ContextData getLocationContext(TextDocument *document, int lineNumber) if (ln > 0) { data.type = LocationByFile; data.fileName = Utils::FilePath::fromString(fileName); - data.lineNumber = ln; + data.textPosition.line = ln; } } } } else { data.type = LocationByFile; data.fileName = document->filePath(); - data.lineNumber = lineNumber; + data.textPosition.line = lineNumber; } return data; } @@ -381,13 +381,13 @@ static void setValueAnnotationsHelper(BaseTextEditor *textEditor, if (!cppDocument) // For non-C++ documents. return; - const int firstLine = firstRelevantLine(cppDocument, loc.lineNumber(), 1); + const int firstLine = firstRelevantLine(cppDocument, loc.textPosition().line, 1); if (firstLine < 1) return; CPlusPlus::ExpressionUnderCursor expressionUnderCursor(cppDocument->languageFeatures()); QTextCursor tc = widget->textCursor(); - for (int lineNumber = loc.lineNumber(); lineNumber >= firstLine; --lineNumber) { + for (int lineNumber = loc.textPosition().line; lineNumber >= firstLine; --lineNumber) { const QTextBlock block = textDocument->document()->findBlockByNumber(lineNumber - 1); tc.setPosition(block.position()); for (; !tc.atBlockEnd(); tc.movePosition(QTextCursor::NextCharacter)) { diff --git a/src/plugins/debugger/uvsc/uvscengine.cpp b/src/plugins/debugger/uvsc/uvscengine.cpp index 06450651de..8efa0fc293 100644 --- a/src/plugins/debugger/uvsc/uvscengine.cpp +++ b/src/plugins/debugger/uvsc/uvscengine.cpp @@ -359,7 +359,7 @@ void UvscEngine::insertBreakpoint(const Breakpoint &bp) // Add file name. expression += "\\" + requested.fileName.toString(); // Add line number. - expression += "\\" + QString::number(requested.lineNumber); + expression += "\\" + QString::number(requested.textPosition.line); } handleInsertBreakpoint(expression, bp); @@ -777,7 +777,7 @@ void UvscEngine::handleInsertBreakpoint(const QString &exp, const Breakpoint &bp bp->setPending(false); bp->setResponseId(QString::number(tickMark)); bp->setAddress(address); - bp->setLineNumber(line); + bp->setTextPosition(Text::Position{int(line), -1}); bp->setFileName(FilePath::fromString(fileName)); bp->setFunctionName(function); notifyBreakpointInsertOk(bp); diff --git a/src/plugins/debugger/uvsc/uvscutils.cpp b/src/plugins/debugger/uvsc/uvscutils.cpp index c08e28e4fd..b7fecfb248 100644 --- a/src/plugins/debugger/uvsc/uvscutils.cpp +++ b/src/plugins/debugger/uvsc/uvscutils.cpp @@ -73,8 +73,8 @@ QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd) bkPtr->type = type; bkPtr->count = 1; bkPtr->accessSize = 0; - bkPtr->expressionLength = asciiExp.count() + 1; - bkPtr->commandLength = asciiCmd.count() + 1; + bkPtr->expressionLength = asciiExp.size() + 1; + bkPtr->commandLength = asciiCmd.size() + 1; return buffer; } @@ -185,7 +185,7 @@ QString adjustHexValue(QString hex, const QString &type) return QString::number(v); } else { const bool isUnsigned = type.startsWith("unsigned"); - switch (data.count()) { + switch (data.size()) { case 1: if (isUnsigned) { quint8 v = 0; diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index 881e6a30eb..fd9a78187c 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -86,7 +86,7 @@ void FormEditorPlugin::initialize() if (!locale.isEmpty()) { auto qtr = new QTranslator(this); const QString creatorTrPath = ICore::resourcePath("translations").toString(); - const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + const QString qtTrPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); const QString trFile = "designer_" + locale; if (qtr->load(trFile, qtTrPath) || qtr->load(trFile, creatorTrPath)) QCoreApplication::installTranslator(qtr); diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index 75a21d0b5d..58bb62258a 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -340,7 +340,7 @@ static QString addConstRefIfNeeded(const QString &argument) "long", "short", "char", "signed", "unsigned", "qint64", "quint64"}); - for (int i = 0; i < nonConstRefs.count(); i++) { + for (int i = 0; i < nonConstRefs.size(); i++) { const QString &nonConstRef = nonConstRefs.at(i); if (argument == nonConstRef || argument.startsWith(nonConstRef + ' ')) return argument; @@ -351,7 +351,7 @@ static QString addConstRefIfNeeded(const QString &argument) static QString formatArgument(const QString &argument) { QString formattedArgument = argument; - int i = argument.count(); + int i = argument.size(); while (i > 0) { // from the end of the "argument" string i--; const QChar c = argument.at(i); // take the char @@ -374,8 +374,8 @@ static QString addParameterNames(const QString &functionSignature, const QString if (lastParen != -1) argumentsString.truncate(lastParen); const QStringList arguments = argumentsString.split(',', Qt::SkipEmptyParts); - const int pCount = parameterNames.count(); - const int aCount = arguments.count(); + const int pCount = parameterNames.size(); + const int aCount = arguments.size(); for (int i = 0; i < aCount; ++i) { if (i > 0) functionName += ", "; diff --git a/src/plugins/diffeditor/diffeditor.cpp b/src/plugins/diffeditor/diffeditor.cpp index 929c30c339..ddf91b4e1e 100644 --- a/src/plugins/diffeditor/diffeditor.cpp +++ b/src/plugins/diffeditor/diffeditor.cpp @@ -51,8 +51,7 @@ using namespace Core; using namespace TextEditor; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { class DescriptionEditorWidget : public TextEditorWidget { @@ -618,7 +617,6 @@ void DiffEditor::showDiffView(IDiffView *view) setupView(view); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal #include "diffeditor.moc" diff --git a/src/plugins/diffeditor/diffeditor.h b/src/plugins/diffeditor/diffeditor.h index 49922d323e..24f89d5503 100644 --- a/src/plugins/diffeditor/diffeditor.h +++ b/src/plugins/diffeditor/diffeditor.h @@ -18,9 +18,8 @@ QT_END_NAMESPACE namespace TextEditor { class TextEditorWidget; } -namespace DiffEditor { +namespace DiffEditor::Internal { -namespace Internal { class DescriptionEditorWidget; class DiffEditorDocument; class IDiffView; @@ -95,5 +94,4 @@ private: bool m_showDescription = true; }; -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffeditorcontroller.cpp b/src/plugins/diffeditor/diffeditorcontroller.cpp index 1ab7bfccb2..4756afc782 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorcontroller.cpp @@ -124,15 +124,18 @@ void DiffEditorController::reloadFinished(bool success) m_document->endReload(success); } -void DiffEditorController::setStartupFile(const QString &startupFile) +void DiffEditorController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection) { - m_document->setStartupFile(startupFile); + Q_UNUSED(menu) + Q_UNUSED(fileIndex) + Q_UNUSED(chunkIndex) + Q_UNUSED(selection) } -void DiffEditorController::requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection) +void DiffEditorController::setStartupFile(const QString &startupFile) { - emit chunkActionsRequested(menu, fileIndex, chunkIndex, selection); + m_document->setStartupFile(startupFile); } bool DiffEditorController::chunkExists(int fileIndex, int chunkIndex) const diff --git a/src/plugins/diffeditor/diffeditorcontroller.h b/src/plugins/diffeditor/diffeditorcontroller.h index 1f791b2dcb..1fddc31c4d 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.h +++ b/src/plugins/diffeditor/diffeditorcontroller.h @@ -19,7 +19,10 @@ namespace Utils { class FilePath; } namespace DiffEditor { -namespace Internal { class DiffEditorDocument; } +namespace Internal { +class DiffEditorDocument; +class DiffEditorWidgetController; +} class ChunkSelection; @@ -30,12 +33,9 @@ public: explicit DiffEditorController(Core::IDocument *document); void requestReload(); - bool isReloading() const; Utils::FilePath workingDirectory() const; void setWorkingDirectory(const Utils::FilePath &directory); - int contextLineCount() const; - bool ignoreWhitespace() const; enum PatchOption { NoOption = 0, @@ -43,23 +43,19 @@ public: AddPrefix = 2 }; Q_DECLARE_FLAGS(PatchOptions, PatchOption) - QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection, - PatchOptions options) const; - static Core::IDocument *findOrCreateDocument(const QString &vcsId, - const QString &displayName); + static Core::IDocument *findOrCreateDocument(const QString &vcsId, const QString &displayName); static DiffEditorController *controller(Core::IDocument *document); - void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection); +protected: + bool isReloading() const; + int contextLineCount() const; + bool ignoreWhitespace() const; bool chunkExists(int fileIndex, int chunkIndex) const; Core::IDocument *document() const; + QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection, + PatchOptions options) const; -signals: - void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection); - -protected: // Core functions: void setReloadRecipe(const Tasking::Group &recipe) { m_reloadRecipe = recipe; } void setDiffFiles(const QList<FileData> &diffFileList); @@ -71,6 +67,9 @@ protected: private: void reloadFinished(bool success); + friend class Internal::DiffEditorWidgetController; + virtual void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection); Internal::DiffEditorDocument *const m_document; QString m_displayName; diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index 1d43064d60..ed89d69c4f 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -24,8 +24,7 @@ using namespace Core; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { DiffEditorDocument::DiffEditorDocument() : Core::BaseTextDocument() @@ -388,5 +387,4 @@ void DiffEditorDocument::endReload(bool success) emit reloadFinished(success); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffeditorfactory.cpp b/src/plugins/diffeditor/diffeditorfactory.cpp index a771fda53a..70537dd3f7 100644 --- a/src/plugins/diffeditor/diffeditorfactory.cpp +++ b/src/plugins/diffeditor/diffeditorfactory.cpp @@ -15,8 +15,7 @@ using namespace Core; using namespace TextEditor; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { DiffEditorFactory::DiffEditorFactory() : descriptionHandler { @@ -50,5 +49,4 @@ DiffEditorFactory::DiffEditorFactory() : setEditorCreator([] { return new DiffEditor(new DiffEditorDocument); }); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffeditorfactory.h b/src/plugins/diffeditor/diffeditorfactory.h index bebabb208a..e39f0fc46f 100644 --- a/src/plugins/diffeditor/diffeditorfactory.h +++ b/src/plugins/diffeditor/diffeditorfactory.h @@ -7,8 +7,7 @@ #include <texteditor/texteditoractionhandler.h> -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { class DiffEditorFactory : public Core::IEditorFactory { @@ -22,5 +21,4 @@ private: TextEditor::TextEditorActionHandler rightHandler; }; -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 867217d86d..3112170bc4 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -29,8 +29,7 @@ using namespace Core; using namespace TextEditor; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { class ReloadInput { public: @@ -133,7 +132,7 @@ DiffFilesController::DiffFilesController(IDocument *document) tasks.append(AsyncTask<FileData>(std::bind(setupDiff, _1, inputList.at(i)), std::bind(onDiffDone, _1, i))); } - taskTree.setupRoot(tasks); + taskTree.setRecipe(tasks); }; const auto onTreeDone = [this, storage] { const QList<std::optional<FileData>> &results = *storage; @@ -535,8 +534,7 @@ void DiffEditorPlugin::initialize() d = new DiffEditorPluginPrivate; } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal #ifdef WITH_TESTS diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index 17b6a2d430..9888628daa 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -6,8 +6,7 @@ #include <coreplugin/diffservice.h> #include <extensionsystem/iplugin.h> -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { class DiffEditorServiceImpl : public QObject, public Core::DiffService { @@ -46,5 +45,4 @@ private slots: #endif // WITH_TESTS }; -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index e3f321c7c4..0f3a57ee08 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -29,8 +29,7 @@ using namespace Core; using namespace TextEditor; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { DiffEditorWidgetController::DiffEditorWidgetController(QWidget *diffEditorWidget) : QObject(diffEditorWidget) @@ -280,7 +279,7 @@ void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int const ChunkSelection &selection) { if (DiffEditorController *controller = m_document->controller()) - controller->requestChunkActions(menu, fileIndex, chunkIndex, selection); + controller->addExtraActions(menu, fileIndex, chunkIndex, selection); } void DiffEditorWidgetController::updateCannotDecodeInfo() @@ -330,6 +329,4 @@ DiffEditorInput::DiffEditorInput(DiffEditorWidgetController *controller) , m_charFormat{&controller->m_charFormat[LeftSide], &controller->m_charFormat[RightSide]} { } - -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/diffview.cpp b/src/plugins/diffeditor/diffview.cpp index 686f9798b2..1b513aefc3 100644 --- a/src/plugins/diffeditor/diffview.cpp +++ b/src/plugins/diffeditor/diffview.cpp @@ -14,8 +14,7 @@ #include <QCoreApplication> -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { IDiffView::IDiffView(QObject *parent) : QObject(parent) { } @@ -230,5 +229,4 @@ void SideBySideView::setSync(bool sync) m_widget->setHorizontalSync(sync); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/selectabletexteditorwidget.cpp b/src/plugins/diffeditor/selectabletexteditorwidget.cpp index bbf0480a6b..e0c95f6abd 100644 --- a/src/plugins/diffeditor/selectabletexteditorwidget.cpp +++ b/src/plugins/diffeditor/selectabletexteditorwidget.cpp @@ -13,8 +13,7 @@ using namespace TextEditor; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { SelectableTextEditorWidget::SelectableTextEditorWidget(Utils::Id id, QWidget *parent) : TextEditorWidget(parent) @@ -142,5 +141,4 @@ void SelectableTextEditorWidget::paintBlock(QPainter *painter, TextEditorWidget::paintBlock(painter, block, offset, newSelections, clipRect); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/selectabletexteditorwidget.h b/src/plugins/diffeditor/selectabletexteditorwidget.h index ca128aa28e..4b0d465204 100644 --- a/src/plugins/diffeditor/selectabletexteditorwidget.h +++ b/src/plugins/diffeditor/selectabletexteditorwidget.h @@ -7,8 +7,7 @@ namespace TextEditor { class DisplaySettings; } -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { class DiffSelection { @@ -46,5 +45,4 @@ private: DiffSelections m_diffSelections; }; -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index d2f58f83ac..341edce733 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -35,8 +35,7 @@ using namespace Utils; using namespace std::placeholders; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { static DiffSide oppositeSide(DiffSide side) { @@ -316,7 +315,7 @@ static SideBySideDiffOutput diffOutput(QPromise<SideBySideShowResults> &promise, addChunkLine(RightSide, -2); blockNumber++; } else { - for (int j = 0; j < contextFileData.chunks.count(); j++) { + for (int j = 0; j < contextFileData.chunks.size(); j++) { const ChunkData &chunkData = contextFileData.chunks.at(j); int leftLineNumber = chunkData.startingLineNumber[LeftSide]; @@ -331,7 +330,7 @@ static SideBySideDiffOutput diffOutput(QPromise<SideBySideShowResults> &promise, blockNumber++; } - const int rows = chunkData.rows.count(); + const int rows = chunkData.rows.size(); output.side[LeftSide].diffData.m_chunkInfo.setChunkIndex(blockNumber, rows, j); output.side[RightSide].diffData.m_chunkInfo.setChunkIndex(blockNumber, rows, j); @@ -342,11 +341,11 @@ static SideBySideDiffOutput diffOutput(QPromise<SideBySideShowResults> &promise, } } - if (j == contextFileData.chunks.count() - 1) { // the last chunk + if (j == contextFileData.chunks.size() - 1) { // the last chunk int skippedLines = -2; if (chunkData.contextChunk) { // if it's context chunk - skippedLines = chunkData.rows.count(); + skippedLines = chunkData.rows.size(); } else if (!contextFileData.lastChunkAtTheEndOfFile && !contextFileData.contextChunksIncluded) { // if not a context chunk and not a chunk at the end of file @@ -381,7 +380,7 @@ void SideDiffData::setLineNumber(int blockNumber, int lineNumber) { const QString lineNumberString = QString::number(lineNumber); m_lineNumbers.insert(blockNumber, lineNumber); - m_lineNumberDigits = qMax(m_lineNumberDigits, lineNumberString.count()); + m_lineNumberDigits = qMax(m_lineNumberDigits, lineNumberString.size()); } void SideDiffData::setFileInfo(int blockNumber, const DiffFileInfo &fileInfo) @@ -986,7 +985,7 @@ void SideBySideDiffEditorWidget::setFontSettings(const FontSettings &fontSetting void SideBySideDiffEditorWidget::jumpToOriginalFileRequested(DiffSide side, int diffFileIndex, int lineNumber, int columnNumber) { - if (diffFileIndex < 0 || diffFileIndex >= m_controller.m_contextFileData.count()) + if (diffFileIndex < 0 || diffFileIndex >= m_controller.m_contextFileData.size()) return; const FileData fileData = m_controller.m_contextFileData.at(diffFileIndex); @@ -1007,7 +1006,7 @@ void SideBySideDiffEditorWidget::jumpToOriginalFileRequested(DiffSide side, int int thisLineNumber = chunkData.startingLineNumber[side]; int otherLineNumber = chunkData.startingLineNumber[otherSide]; - for (int j = 0; j < chunkData.rows.count(); j++) { + for (int j = 0; j < chunkData.rows.size(); j++) { const RowData rowData = chunkData.rows.at(j); if (rowData.line[side].textLineType == TextLineData::TextLine) thisLineNumber++; @@ -1104,7 +1103,6 @@ void SideBySideDiffEditorWidget::syncCursor(SideDiffEditorWidget *source, SideDi dest->horizontalScrollBar()->setValue(oldHSliderPos); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal #include "sidebysidediffeditorwidget.moc" diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp index bb64e61d5b..d5633d50ec 100644 --- a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp +++ b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp @@ -28,8 +28,7 @@ using namespace Core; using namespace TextEditor; using namespace Utils; -namespace DiffEditor { -namespace Internal { +namespace DiffEditor::Internal { UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent) : SelectableTextEditorWidget("DiffEditor.UnifiedDiffEditor", parent) @@ -226,7 +225,7 @@ QString UnifiedDiffEditorWidget::lineNumber(int blockNumber) const const QString line = lineExists ? QString::number(m_data.m_lineNumbers[side].value(blockNumber).first) : QString(); - lineNumberString += QString(m_data.m_lineNumberDigits[side] - line.count(), ' ') + line; + lineNumberString += QString(m_data.m_lineNumberDigits[side] - line.size(), ' ') + line; }; addSideNumber(LeftSide, leftLineExists); lineNumberString += '|'; @@ -263,7 +262,7 @@ void UnifiedDiffData::setLineNumber(DiffSide side, int blockNumber, int lineNumb QTC_ASSERT(side < SideCount, return); const QString lineNumberString = QString::number(lineNumber); m_lineNumbers[side].insert(blockNumber, {lineNumber, rowNumberInChunk}); - m_lineNumberDigits[side] = qMax(m_lineNumberDigits[side], lineNumberString.count()); + m_lineNumberDigits[side] = qMax(m_lineNumberDigits[side], lineNumberString.size()); } QString UnifiedDiffData::setChunk(const DiffEditorInput &input, const ChunkData &chunkData, @@ -589,5 +588,4 @@ void UnifiedDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex) verticalScrollBar()->setValue(blockNumber); } -} // namespace Internal -} // namespace DiffEditor +} // namespace DiffEditor::Internal diff --git a/src/plugins/git/commitdata.cpp b/src/plugins/git/commitdata.cpp index 172d30e2c5..1bc66adf0d 100644 --- a/src/plugins/git/commitdata.cpp +++ b/src/plugins/git/commitdata.cpp @@ -91,7 +91,7 @@ bool operator<(const CommitData::StateFilePair &a, const CommitData::StateFilePa bool CommitData::checkLine(const QString &stateInfo, const QString &file) { - QTC_ASSERT(stateInfo.count() == 2, return false); + QTC_ASSERT(stateInfo.size() == 2, return false); if (stateInfo == "??") { files.push_back({FileStates(UntrackedFile), file}); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 4f2bdc4912..69cf636e72 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -112,6 +112,38 @@ static QString branchesDisplay(const QString &prefix, QStringList *branches, boo /////////////////////////////// +static void stage(DiffEditorController *diffController, const QString &patch, bool revert) +{ + TemporaryFile patchFile("git-patchfile"); + if (!patchFile.open()) + return; + + const FilePath baseDir = diffController->workingDirectory(); + QTextCodec *codec = EditorManager::defaultTextCodec(); + const QByteArray patchData = codec ? codec->fromUnicode(patch) : patch.toLocal8Bit(); + patchFile.write(patchData); + patchFile.close(); + + QStringList args = {"--cached"}; + if (revert) + args << "--reverse"; + QString errorMessage; + if (GitClient::instance()->synchronousApplyPatch(baseDir, patchFile.fileName(), + &errorMessage, args)) { + if (errorMessage.isEmpty()) { + if (revert) + VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully unstaged")); + else + VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully staged")); + } else { + VcsOutputWindow::appendError(errorMessage); + } + diffController->requestReload(); + } else { + VcsOutputWindow::appendError(errorMessage); + } +} + class GitBaseDiffEditorController : public VcsBaseDiffEditorController { Q_OBJECT @@ -120,6 +152,50 @@ protected: explicit GitBaseDiffEditorController(IDocument *document); QStringList addConfigurationArguments(const QStringList &args) const; + +private: + void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection) final + { + menu->addSeparator(); + + auto stageChunk = [this, fileIndex, chunkIndex](DiffEditorController::PatchOptions options, + const DiffEditor::ChunkSelection &selection) { + options |= DiffEditorController::AddPrefix; + const QString patch = makePatch(fileIndex, chunkIndex, selection, options); + stage(this, patch, options & Revert); + }; + + QAction *stageChunkAction = menu->addAction(Tr::tr("Stage Chunk")); + connect(stageChunkAction, &QAction::triggered, this, [stageChunk] { + stageChunk(DiffEditorController::NoOption, {}); + }); + QAction *stageLinesAction = menu->addAction(Tr::tr("Stage Selection (%n Lines)", "", + selection.selectedRowsCount())); + connect(stageLinesAction, &QAction::triggered, this, [stageChunk, selection] { + stageChunk(DiffEditorController::NoOption, selection); + }); + QAction *unstageChunkAction = menu->addAction(Tr::tr("Unstage Chunk")); + connect(unstageChunkAction, &QAction::triggered, this, [stageChunk] { + stageChunk(DiffEditorController::Revert, {}); + }); + QAction *unstageLinesAction = menu->addAction(Tr::tr("Unstage Selection (%n Lines)", "", + selection.selectedRowsCount())); + connect(unstageLinesAction, &QAction::triggered, this, [stageChunk, selection] { + stageChunk(DiffEditorController::Revert, selection); + }); + + if (selection.isNull()) { + stageLinesAction->setVisible(false); + unstageLinesAction->setVisible(false); + } + if (!chunkExists(fileIndex, chunkIndex)) { + stageChunkAction->setEnabled(false); + stageLinesAction->setEnabled(false); + unstageChunkAction->setEnabled(false); + unstageLinesAction->setEnabled(false); + } + } }; class GitDiffEditorController : public GitBaseDiffEditorController @@ -446,7 +522,7 @@ ShowController::ShowController(IDocument *document, const QString &id) tasks.append(ProcessTask(std::bind(setupFollow, _1, parents.at(i)), std::bind(onFollowDone, _1, i))); } - taskTree.setupRoot(tasks); + taskTree.setRecipe(tasks); }; const auto setupDiff = [this, id](Process &process) { @@ -850,95 +926,6 @@ QTextCodec *GitClient::encoding(GitClient::EncodingType encodingType, const File } } -void GitClient::chunkActionsRequested(DiffEditor::DiffEditorController *controller, - QMenu *menu, int fileIndex, int chunkIndex, - const DiffEditor::ChunkSelection &selection) const -{ - QPointer<DiffEditor::DiffEditorController> diffController(controller); - - auto stageChunk = [this](QPointer<DiffEditor::DiffEditorController> diffController, - int fileIndex, int chunkIndex, DiffEditorController::PatchOptions options, - const DiffEditor::ChunkSelection &selection) { - if (diffController.isNull()) - return; - - options |= DiffEditorController::AddPrefix; - const QString patch = diffController->makePatch(fileIndex, chunkIndex, selection, options); - stage(diffController, patch, options & Revert); - }; - - menu->addSeparator(); - QAction *stageChunkAction = menu->addAction(Tr::tr("Stage Chunk")); - connect(stageChunkAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::NoOption, DiffEditor::ChunkSelection()); - }); - QAction *stageLinesAction = menu->addAction(Tr::tr("Stage Selection (%n Lines)", "", selection.selectedRowsCount())); - connect(stageLinesAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex, selection] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::NoOption, selection); - }); - QAction *unstageChunkAction = menu->addAction(Tr::tr("Unstage Chunk")); - connect(unstageChunkAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::Revert, DiffEditor::ChunkSelection()); - }); - QAction *unstageLinesAction = menu->addAction(Tr::tr("Unstage Selection (%n Lines)", "", selection.selectedRowsCount())); - connect(unstageLinesAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex, selection] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::Revert, - selection); - }); - if (selection.isNull()) { - stageLinesAction->setVisible(false); - unstageLinesAction->setVisible(false); - } - if (!diffController || !diffController->chunkExists(fileIndex, chunkIndex)) { - stageChunkAction->setEnabled(false); - stageLinesAction->setEnabled(false); - unstageChunkAction->setEnabled(false); - unstageLinesAction->setEnabled(false); - } -} - -void GitClient::stage(DiffEditor::DiffEditorController *diffController, - const QString &patch, bool revert) const -{ - TemporaryFile patchFile("git-patchfile"); - if (!patchFile.open()) - return; - - const FilePath baseDir = diffController->workingDirectory(); - QTextCodec *codec = EditorManager::defaultTextCodec(); - const QByteArray patchData = codec - ? codec->fromUnicode(patch) : patch.toLocal8Bit(); - patchFile.write(patchData); - patchFile.close(); - - QStringList args = {"--cached"}; - if (revert) - args << "--reverse"; - QString errorMessage; - if (synchronousApplyPatch(baseDir, patchFile.fileName(), - &errorMessage, args)) { - if (errorMessage.isEmpty()) { - if (revert) - VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully unstaged")); - else - VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully staged")); - } else { - VcsOutputWindow::appendError(errorMessage); - } - diffController->requestReload(); - } else { - VcsOutputWindow::appendError(errorMessage); - } -} - void GitClient::requestReload(const QString &documentId, const FilePath &source, const QString &title, const FilePath &workingDirectory, std::function<GitBaseDiffEditorController *(IDocument *)> factory) const @@ -956,10 +943,6 @@ void GitClient::requestReload(const QString &documentId, const FilePath &source, using namespace std::placeholders; - connect(controller, &DiffEditorController::chunkActionsRequested, this, - std::bind(&GitClient::chunkActionsRequested, this, controller, _1, _2, _3, _4), - Qt::DirectConnection); - VcsBase::setSource(document, sourceCopy); EditorManager::activateEditorForDocument(document); controller->requestReload(); @@ -2405,7 +2388,7 @@ QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryUR const int pos = line.lastIndexOf(pattern); if (pos != -1) { branchFound = true; - const QString branchName = line.mid(pos + pattern.count()); + const QString branchName = line.mid(pos + pattern.size()); if (!headFound && line.startsWith(headSha)) { branches[0] = branchName; headFound = true; @@ -2816,7 +2799,7 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory, if (state & (ModifiedFile | AddedFile | DeletedFile | TypeChangedFile)) { filesToReset.append(file); } else if (state & (RenamedFile | CopiedFile)) { - const QString newFile = file.mid(file.indexOf(renameSeparator) + renameSeparator.count()); + const QString newFile = file.mid(file.indexOf(renameSeparator) + renameSeparator.size()); filesToReset.append(newFile); } } else if (state & UnmergedFile && checked) { diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 398b1c1cc8..3604eb9f3c 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -21,7 +21,6 @@ #include <QWidget> QT_BEGIN_NAMESPACE -class QProcessEnvironment; class QMenu; QT_END_NAMESPACE @@ -363,12 +362,6 @@ private: static GitSettings &settings(); void finishSubmoduleUpdate(); - void chunkActionsRequested(DiffEditor::DiffEditorController *controller, - QMenu *menu, int fileIndex, int chunkIndex, - const DiffEditor::ChunkSelection &selection) const; - - void stage(DiffEditor::DiffEditorController *diffController, - const QString &patch, bool revert) const; void requestReload(const QString &documentId, const Utils::FilePath &source, const QString &title, const Utils::FilePath &workingDirectory, diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index 7329b3dad6..9ad9052867 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -182,7 +182,7 @@ HelpPluginPrivate::HelpPluginPrivate() auto qtr = new QTranslator(this); auto qhelptr = new QTranslator(this); const QString creatorTrPath = ICore::resourcePath("translations").toString(); - const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + const QString qtTrPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); const QString trFile = QLatin1String("assistant_") + locale; const QString helpTrFile = QLatin1String("qt_help_") + locale; if (qtr->load(trFile, qtTrPath) || qtr->load(trFile, creatorTrPath)) diff --git a/src/plugins/imageviewer/exportdialog.cpp b/src/plugins/imageviewer/exportdialog.cpp index 3595d525cb..d9a0460c98 100644 --- a/src/plugins/imageviewer/exportdialog.cpp +++ b/src/plugins/imageviewer/exportdialog.cpp @@ -24,8 +24,9 @@ #include <QSpinBox> #include <QToolButton> -namespace ImageViewer { -namespace Internal { +using namespace Utils; + +namespace ImageViewer::Internal { enum { exportMinimumSize = 1, exportMaximumSize = 2000 }; @@ -98,10 +99,10 @@ void ExportDialog::accept() QMessageBox::warning(this, windowTitle(), m_pathChooser->errorMessage()); return; } - const QString fileName = exportFileName(); - if (QFileInfo::exists(fileName)) { + const FilePath filePath = exportFileName(); + if (filePath.exists()) { const QString question = Tr::tr("%1 already exists.\nWould you like to overwrite it?") - .arg(QDir::toNativeSeparators(fileName)); + .arg(filePath.toUserOutput()); if (QMessageBox::question(this, windowTitle(), question, QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return; } @@ -156,14 +157,14 @@ void ExportDialog::exportHeightChanged(int height) setExportWidthBlocked(square ? height : qRound(qreal(height) * m_aspectRatio)); } -QString ExportDialog::exportFileName() const +FilePath ExportDialog::exportFileName() const { - return m_pathChooser->filePath().toString(); + return m_pathChooser->filePath(); } -void ExportDialog::setExportFileName(const QString &f) +void ExportDialog::setExportFileName(const FilePath &f) { - m_pathChooser->setFilePath(Utils::FilePath::fromString(f)); + m_pathChooser->setFilePath(f); } ExportData ExportDialog::exportData() const @@ -171,5 +172,4 @@ ExportData ExportDialog::exportData() const return {exportFileName(), exportSize()}; } -} // namespace Internal -} // namespace ImageViewer +} // ImageViewer::Internal diff --git a/src/plugins/imageviewer/exportdialog.h b/src/plugins/imageviewer/exportdialog.h index b251a2ab65..5868cc7ef7 100644 --- a/src/plugins/imageviewer/exportdialog.h +++ b/src/plugins/imageviewer/exportdialog.h @@ -7,7 +7,10 @@ QT_FORWARD_DECLARE_CLASS(QSpinBox) -namespace Utils { class PathChooser; } +namespace Utils { +class FilePath; +class PathChooser; +} // Utils namespace ImageViewer::Internal { @@ -21,8 +24,8 @@ public: QSize exportSize() const; void setExportSize(const QSize &); - QString exportFileName() const; - void setExportFileName(const QString &); + Utils::FilePath exportFileName() const; + void setExportFileName(const Utils::FilePath &); ExportData exportData() const; diff --git a/src/plugins/imageviewer/imageview.cpp b/src/plugins/imageviewer/imageview.cpp index 9a2af284f4..01d9b3968f 100644 --- a/src/plugins/imageviewer/imageview.cpp +++ b/src/plugins/imageviewer/imageview.cpp @@ -40,6 +40,8 @@ const char kSettingsBackground[] = "ShowBackground"; const char kSettingsOutline[] = "ShowOutline"; const char kSettingsFitToScreen[] = "FitToScreen"; +using namespace Utils; + namespace ImageViewer { namespace Constants { const qreal DEFAULT_SCALE_FACTOR = 1.2; @@ -157,25 +159,24 @@ QImage ImageView::renderSvg(const QSize &imageSize) const bool ImageView::exportSvg(const ExportData &ed) { - const bool result = renderSvg(ed.size).save(ed.fileName); + const bool result = renderSvg(ed.size).save(ed.filePath.toFSPathString()); if (result) { const QString message = Tr::tr("Exported \"%1\", %2x%3, %4 bytes") - .arg(QDir::toNativeSeparators(ed.fileName)) + .arg(ed.filePath.toUserOutput()) .arg(ed.size.width()).arg(ed.size.height()) - .arg(QFileInfo(ed.fileName).size()); + .arg(ed.filePath.fileSize()); Core::MessageManager::writeDisrupting(message); } else { - const QString message = Tr::tr("Could not write file \"%1\".").arg(QDir::toNativeSeparators(ed.fileName)); + const QString message = Tr::tr("Could not write file \"%1\".").arg(ed.filePath.toUserOutput()); QMessageBox::critical(this, Tr::tr("Export Image"), message); } return result; } #ifndef QT_NO_SVG -static QString suggestedExportFileName(const QFileInfo &fi) +static FilePath suggestedExportFileName(const FilePath &fi) { - return fi.absolutePath() + QLatin1Char('/') + fi.baseName() - + QStringLiteral(".png"); + return fi.absolutePath().pathAppended(fi.baseName() + ".png"); } #endif @@ -195,11 +196,11 @@ void ImageView::exportImage() auto svgItem = qgraphicsitem_cast<QGraphicsSvgItem *>(m_imageItem); QTC_ASSERT(svgItem, return); - const QFileInfo origFi = m_file->filePath().toFileInfo(); + const FilePath origPath = m_file->filePath(); ExportDialog exportDialog(this); - exportDialog.setWindowTitle(Tr::tr("Export %1").arg(origFi.fileName())); + exportDialog.setWindowTitle(Tr::tr("Export %1").arg(origPath.fileName())); exportDialog.setExportSize(svgSize()); - exportDialog.setExportFileName(suggestedExportFileName(origFi)); + exportDialog.setExportFileName(suggestedExportFileName(origPath)); while (exportDialog.exec() == QDialog::Accepted && !exportSvg(exportDialog.exportData())) {} #endif // !QT_NO_SVG @@ -210,14 +211,13 @@ void ImageView::exportMultiImages() #ifndef QT_NO_SVG QTC_ASSERT(qgraphicsitem_cast<QGraphicsSvgItem *>(m_imageItem), return); - const QFileInfo origFi = m_file->filePath().toFileInfo(); + const FilePath origPath = m_file->filePath(); const QSize size = svgSize(); - const QString title = - Tr::tr("Export a Series of Images from %1 (%2x%3)") - .arg(origFi.fileName()).arg(size.width()).arg(size.height()); + const QString title = Tr::tr("Export a Series of Images from %1 (%2x%3)") + .arg(origPath.fileName()).arg(size.width()).arg(size.height()); MultiExportDialog multiExportDialog; multiExportDialog.setWindowTitle(title); - multiExportDialog.setExportFileName(suggestedExportFileName(origFi)); + multiExportDialog.setExportFileName(suggestedExportFileName(origPath)); multiExportDialog.setSvgSize(size); multiExportDialog.suggestSizes(); diff --git a/src/plugins/imageviewer/imageview.h b/src/plugins/imageviewer/imageview.h index 0538b58b1a..6bee8e3243 100644 --- a/src/plugins/imageviewer/imageview.h +++ b/src/plugins/imageviewer/imageview.h @@ -4,6 +4,8 @@ #pragma once +#include <utils/filepath.h> + #include <QGraphicsView> QT_FORWARD_DECLARE_CLASS(QImage) @@ -17,7 +19,7 @@ namespace ImageViewer::Internal { class ImageViewerFile; struct ExportData { - QString fileName; + Utils::FilePath filePath; QSize size; }; diff --git a/src/plugins/imageviewer/multiexportdialog.cpp b/src/plugins/imageviewer/multiexportdialog.cpp index 0befd2fe37..1b526c9b11 100644 --- a/src/plugins/imageviewer/multiexportdialog.cpp +++ b/src/plugins/imageviewer/multiexportdialog.cpp @@ -15,8 +15,6 @@ #include <utils/utilsicons.h> #include <QDialogButtonBox> -#include <QDir> -#include <QFileInfo> #include <QFormLayout> #include <QLabel> #include <QLineEdit> @@ -27,6 +25,8 @@ #include <QToolButton> #include <QWidgetAction> +using namespace Utils; + namespace ImageViewer::Internal { static const int standardIconSizesValues[] = {16, 24, 32, 48, 64, 128, 256}; @@ -95,11 +95,11 @@ static QVector<QSize> stringToSizes(const QString &s) return result; } -static QString fileNameForSize(QString pattern, const QSize &s) +static FilePath fileNameForSize(QString pattern, const QSize &s) { pattern.replace("%1", QString::number(s.width())); pattern.replace("%2", QString::number(s.height())); - return pattern; + return FilePath::fromString(pattern); } // Helpers for writing/reading the user-specified size specifications @@ -236,7 +236,7 @@ void MultiExportDialog::suggestSizes() QVector<ExportData> MultiExportDialog::exportData() const { const QVector<QSize> sizeList = sizes(); - const QString pattern = exportFileName(); + const QString pattern = exportFileName().toString(); QVector<ExportData> result; result.reserve(sizeList.size()); for (const QSize &s : sizeList) @@ -268,7 +268,7 @@ void MultiExportDialog::accept() Tr::tr("Invalid size specification: %1").arg(sizeSpec)); return; } - if (data.size() > 1 && data.at(0).fileName == data.at(1).fileName) { + if (data.size() > 1 && data.at(0).filePath == data.at(1).filePath) { QMessageBox::warning(this, windowTitle(), Tr::tr("The file name must contain one of the placeholders %1, %2.") .arg(QString("%1"), QString("%2"))); @@ -277,17 +277,17 @@ void MultiExportDialog::accept() writeSettings(m_svgSize, sizeSpec); - QStringList existingFiles; + FilePaths existingFiles; for (const ExportData &d : data) { - if (QFileInfo::exists(d.fileName)) - existingFiles.append(d.fileName); + if (d.filePath.exists()) + existingFiles.append(d.filePath); } if (!existingFiles.isEmpty()) { const QString message = existingFiles.size() == 1 ? Tr::tr("The file %1 already exists.\nWould you like to overwrite it?") - .arg(QDir::toNativeSeparators(existingFiles.constFirst())) + .arg(existingFiles.constFirst().toUserOutput()) : Tr::tr("The files %1 already exist.\nWould you like to overwrite them?") - .arg(QDir::toNativeSeparators(existingFiles.join(", "))); + .arg(FilePath::formatFilePaths(existingFiles, ", ")); QMessageBox messageBox(QMessageBox::Question, windowTitle(), message, QMessageBox::Yes | QMessageBox::No, this); if (messageBox.exec() != QMessageBox::Yes) @@ -297,17 +297,21 @@ void MultiExportDialog::accept() QDialog::accept(); } -QString MultiExportDialog::exportFileName() const +FilePath MultiExportDialog::exportFileName() const { - return m_pathChooser->filePath().toString(); + return m_pathChooser->filePath(); } -void MultiExportDialog::setExportFileName(QString f) +void MultiExportDialog::setExportFileName(const FilePath &filePath) { - const int lastDot = f.lastIndexOf('.'); - if (lastDot != -1) - f.insert(lastDot, "-%1"); - m_pathChooser->setFilePath(Utils::FilePath::fromString(f)); + FilePath f = filePath; + QString ff = f.path(); + const int lastDot = ff.lastIndexOf('.'); + if (lastDot != -1) { + ff.insert(lastDot, "-%1"); + f = f.withNewPath(ff); + }; + m_pathChooser->setFilePath(f); } } // ImageViewer:Internal diff --git a/src/plugins/imageviewer/multiexportdialog.h b/src/plugins/imageviewer/multiexportdialog.h index 75fcaae3df..bd8ed32b1a 100644 --- a/src/plugins/imageviewer/multiexportdialog.h +++ b/src/plugins/imageviewer/multiexportdialog.h @@ -4,14 +4,16 @@ #pragma once #include <QDialog> - #include <QPair> #include <QSize> #include <QVector> QT_FORWARD_DECLARE_CLASS(QLineEdit) -namespace Utils { class PathChooser; } +namespace Utils { +class FilePath; +class PathChooser; +} // Utils namespace ImageViewer::Internal { @@ -19,12 +21,11 @@ struct ExportData; class MultiExportDialog : public QDialog { - Q_OBJECT public: explicit MultiExportDialog(QWidget *parent = nullptr); - QString exportFileName() const; - void setExportFileName(QString); + Utils::FilePath exportFileName() const; + void setExportFileName(const Utils::FilePath &); void accept() override; diff --git a/src/plugins/insight/insightwidget.cpp b/src/plugins/insight/insightwidget.cpp index aaf152bea3..03a46b0344 100644 --- a/src/plugins/insight/insightwidget.cpp +++ b/src/plugins/insight/insightwidget.cpp @@ -51,7 +51,7 @@ InsightWidget::InsightWidget(InsightView *insightView, InsightModel *insightMode engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); engine()->addImportPath(qmlSourcesPath() + "/imports"); - m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F11), this); + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F11), this); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, diff --git a/src/plugins/ios/iosdeploystep.cpp b/src/plugins/ios/iosdeploystep.cpp index 7bf9d7cbe0..2995f290ff 100644 --- a/src/plugins/ios/iosdeploystep.cpp +++ b/src/plugins/ios/iosdeploystep.cpp @@ -46,11 +46,11 @@ private: void doRun() final; void doCancel() final; - void handleIsTransferringApp(IosToolHandler *handler, const QString &bundlePath, + void handleIsTransferringApp(IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, int progress, int maxProgress, const QString &info); - void handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, - IosToolHandler::OpStatus status); + void handleDidTransferApp(IosToolHandler *handler, const FilePath &bundlePath, + const QString &deviceId, IosToolHandler::OpStatus status); void handleFinished(IosToolHandler *handler); void handleErrorMsg(IosToolHandler *handler, const QString &msg); void updateDisplayNames(); @@ -133,7 +133,7 @@ void IosDeployStep::doRun() connect(m_toolHandler, &IosToolHandler::errorMsg, this, &IosDeployStep::handleErrorMsg); checkProvisioningProfile(); - m_toolHandler->requestTransferApp(m_bundlePath.toString(), m_deviceType.identifier); + m_toolHandler->requestTransferApp(m_bundlePath, m_deviceType.identifier); } void IosDeployStep::doCancel() @@ -151,7 +151,7 @@ void IosDeployStep::cleanup() m_expectFail = false; } -void IosDeployStep::handleIsTransferringApp(IosToolHandler *handler, const QString &bundlePath, +void IosDeployStep::handleIsTransferringApp(IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, int progress, int maxProgress, const QString &info) { @@ -160,7 +160,7 @@ void IosDeployStep::handleIsTransferringApp(IosToolHandler *handler, const QStri emit this->progress(progress * 100 / maxProgress, info); } -void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath, +void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, IosToolHandler::OpStatus status) { Q_UNUSED(handler); Q_UNUSED(bundlePath); Q_UNUSED(deviceId) diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 828bb65c00..9b1f2d0486 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -81,7 +81,7 @@ public: void setCppDebugging(bool cppDebug); void setQmlDebugging(QmlDebug::QmlDebugServicesPreset qmlDebugServices); - QString bundlePath(); + Utils::FilePath bundlePath() const; QString deviceId(); IosToolHandler::RunKind runType(); bool cppDebug() const; @@ -101,9 +101,9 @@ public: bool isAppRunning() const; private: - void handleGotServerPorts(Ios::IosToolHandler *handler, const QString &bundlePath, + void handleGotServerPorts(Ios::IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, Port gdbPort, Port qmlPort); - void handleGotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath, + void handleGotInferiorPid(Ios::IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, qint64 pid); void handleAppOutput(Ios::IosToolHandler *handler, const QString &output); void handleErrorMsg(Ios::IosToolHandler *handler, const QString &msg); @@ -111,7 +111,7 @@ private: void handleFinished(Ios::IosToolHandler *handler); IosToolHandler *m_toolHandler = nullptr; - QString m_bundleDir; + FilePath m_bundleDir; IDeviceConstPtr m_device; IosDeviceType m_deviceType; bool m_cppDebug = false; @@ -130,7 +130,7 @@ IosRunner::IosRunner(RunControl *runControl) stopRunningRunControl(runControl); const IosDeviceTypeAspect::Data *data = runControl->aspect<IosDeviceTypeAspect>(); QTC_ASSERT(data, return); - m_bundleDir = data->bundleDirectory.toString(); + m_bundleDir = data->bundleDirectory; m_device = DeviceKitAspect::device(runControl->kit()); m_deviceType = data->deviceType; } @@ -150,7 +150,7 @@ void IosRunner::setQmlDebugging(QmlDebug::QmlDebugServicesPreset qmlDebugService m_qmlDebugServices = qmlDebugServices; } -QString IosRunner::bundlePath() +FilePath IosRunner::bundlePath() const { return m_bundleDir; } @@ -192,9 +192,9 @@ void IosRunner::start() m_cleanExit = false; m_qmlServerPort = Port(); - if (!QFileInfo::exists(m_bundleDir)) { + if (!m_bundleDir.exists()) { TaskHub::addTask(DeploymentTask(Task::Warning, - Tr::tr("Could not find %1.").arg(m_bundleDir))); + Tr::tr("Could not find %1.").arg(m_bundleDir.toUserOutput()))); reportFailure(); return; } @@ -247,7 +247,7 @@ void IosRunner::stop() m_toolHandler->stop(); } -void IosRunner::handleGotServerPorts(IosToolHandler *handler, const QString &bundlePath, +void IosRunner::handleGotServerPorts(IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, Port gdbPort, Port qmlPort) { @@ -278,7 +278,7 @@ void IosRunner::handleGotServerPorts(IosToolHandler *handler, const QString &bun reportFailure(Tr::tr("Could not get necessary ports for the debugger connection.")); } -void IosRunner::handleGotInferiorPid(IosToolHandler *handler, const QString &bundlePath, +void IosRunner::handleGotInferiorPid(IosToolHandler *handler, const FilePath &bundlePath, const QString &deviceId, qint64 pid) { // Called when debugging on Simulator. diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index 0e4545bf1d..18cc42d44e 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -20,7 +20,6 @@ #include <utils/temporarydirectory.h> #include <QDir> -#include <QFileInfo> #include <QFutureWatcher> #include <QJsonArray> #include <QJsonDocument> @@ -42,6 +41,8 @@ static Q_LOGGING_CATEGORY(toolHandlerLog, "qtc.ios.toolhandler", QtWarningMsg) +using namespace Utils; + namespace Ios { namespace Internal { @@ -166,9 +167,9 @@ class IosToolHandlerPrivate public: explicit IosToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q); virtual ~IosToolHandlerPrivate(); - virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId, + virtual void requestTransferApp(const FilePath &bundlePath, const QString &deviceId, int timeout = 1000) = 0; - virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs, + virtual void requestRunApp(const FilePath &bundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runKind, const QString &deviceId, int timeout = 1000) = 0; virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000) = 0; @@ -176,15 +177,15 @@ public: virtual void stop(int errorCode) = 0; // signals - void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, + void isTransferringApp(const FilePath &bundlePath, const QString &deviceId, int progress, int maxProgress, const QString &info); - void didTransferApp(const QString &bundlePath, const QString &deviceId, + void didTransferApp(const FilePath &bundlePath, const QString &deviceId, IosToolHandler::OpStatus status); - void didStartApp(const QString &bundlePath, const QString &deviceId, + void didStartApp(const FilePath &bundlePath, const QString &deviceId, IosToolHandler::OpStatus status); - void gotServerPorts(const QString &bundlePath, const QString &deviceId, Utils::Port gdbPort, - Utils::Port qmlPort); - void gotInferiorPid(const QString &bundlePath, const QString &deviceId, qint64 pid); + void gotServerPorts(const FilePath &bundlePath, const QString &deviceId, Port gdbPort, + Port qmlPort); + void gotInferiorPid(const FilePath &bundlePath, const QString &deviceId, qint64 pid); void deviceInfo(const QString &deviceId, const IosToolHandler::Dict &info); void appOutput(const QString &output); void errorMsg(const QString &msg); @@ -193,7 +194,7 @@ public: protected: IosToolHandler *q; QString m_deviceId; - QString m_bundlePath; + FilePath m_bundlePath; IosToolHandler::RunKind m_runKind = IosToolHandler::NormalRun; IosDeviceType m_devType; }; @@ -219,9 +220,9 @@ public: // IosToolHandlerPrivate overrides public: - void requestTransferApp(const QString &bundlePath, const QString &deviceId, + void requestTransferApp(const FilePath &bundlePath, const QString &deviceId, int timeout = 1000) override; - void requestRunApp(const QString &bundlePath, const QStringList &extraArgs, + void requestRunApp(const FilePath &bundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runKind, const QString &deviceId, int timeout = 1000) override; void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override; @@ -287,9 +288,9 @@ public: // IosToolHandlerPrivate overrides public: - void requestTransferApp(const QString &appBundlePath, const QString &deviceIdentifier, + void requestTransferApp(const FilePath &appBundlePath, const QString &deviceIdentifier, int timeout = 1000) override; - void requestRunApp(const QString &appBundlePath, const QStringList &extraArgs, + void requestRunApp(const FilePath &appBundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runKind, const QString &deviceIdentifier, int timeout = 1000) override; void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override; @@ -317,31 +318,31 @@ IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType, IosToolHandlerPrivate::~IosToolHandlerPrivate() = default; // signals -void IosToolHandlerPrivate::isTransferringApp(const QString &bundlePath, const QString &deviceId, +void IosToolHandlerPrivate::isTransferringApp(const FilePath &bundlePath, const QString &deviceId, int progress, int maxProgress, const QString &info) { emit q->isTransferringApp(q, bundlePath, deviceId, progress, maxProgress, info); } -void IosToolHandlerPrivate::didTransferApp(const QString &bundlePath, const QString &deviceId, +void IosToolHandlerPrivate::didTransferApp(const FilePath &bundlePath, const QString &deviceId, Ios::IosToolHandler::OpStatus status) { emit q->didTransferApp(q, bundlePath, deviceId, status); } -void IosToolHandlerPrivate::didStartApp(const QString &bundlePath, const QString &deviceId, +void IosToolHandlerPrivate::didStartApp(const FilePath &bundlePath, const QString &deviceId, IosToolHandler::OpStatus status) { emit q->didStartApp(q, bundlePath, deviceId, status); } -void IosToolHandlerPrivate::gotServerPorts(const QString &bundlePath, const QString &deviceId, - Utils::Port gdbPort, Utils::Port qmlPort) +void IosToolHandlerPrivate::gotServerPorts(const FilePath &bundlePath, const QString &deviceId, + Port gdbPort, Port qmlPort) { emit q->gotServerPorts(q, bundlePath, deviceId, gdbPort, qmlPort); } -void IosToolHandlerPrivate::gotInferiorPid(const QString &bundlePath, const QString &deviceId, +void IosToolHandlerPrivate::gotInferiorPid(const FilePath &bundlePath, const QString &deviceId, qint64 pid) { emit q->gotInferiorPid(q, bundlePath, deviceId, pid); @@ -674,7 +675,7 @@ IosDeviceToolHandlerPrivate::~IosDeviceToolHandlerPrivate() } } -void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, +void IosDeviceToolHandlerPrivate::requestTransferApp(const FilePath &bundlePath, const QString &deviceId, int timeout) { m_bundlePath = bundlePath; @@ -682,7 +683,7 @@ void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, QString tmpDeltaPath = Utils::TemporaryDirectory::masterDirectoryFilePath().pathAppended("ios").toString(); QStringList args; args << QLatin1String("--id") << deviceId << QLatin1String("--bundle") - << bundlePath << QLatin1String("--timeout") << QString::number(timeout) + << bundlePath.path() << QLatin1String("--timeout") << QString::number(timeout) << QLatin1String("--install") << QLatin1String("--delta-path") << tmpDeltaPath; @@ -690,7 +691,7 @@ void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, start(IosToolHandler::iosDeviceToolPath(), args); } -void IosDeviceToolHandlerPrivate::requestRunApp(const QString &bundlePath, +void IosDeviceToolHandlerPrivate::requestRunApp(const FilePath &bundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runType, const QString &deviceId, int timeout) @@ -700,7 +701,7 @@ void IosDeviceToolHandlerPrivate::requestRunApp(const QString &bundlePath, m_runKind = runType; QStringList args; args << QLatin1String("--id") << deviceId << QLatin1String("--bundle") - << bundlePath << QLatin1String("--timeout") << QString::number(timeout); + << bundlePath.path() << QLatin1String("--timeout") << QString::number(timeout); switch (runType) { case IosToolHandler::NormalRun: args << QLatin1String("--run"); @@ -789,7 +790,7 @@ IosSimulatorToolHandlerPrivate::IosSimulatorToolHandlerPrivate(const IosDeviceTy std::bind(&IosToolHandlerPrivate::appOutput, this, _1)); } -void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &appBundlePath, +void IosSimulatorToolHandlerPrivate::requestTransferApp(const FilePath &appBundlePath, const QString &deviceIdentifier, int timeout) { Q_UNUSED(timeout) @@ -817,7 +818,7 @@ void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &appBundle SimulatorControl::startSimulator(m_deviceId), q, onSimulatorStart)); } -void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath, +void IosSimulatorToolHandlerPrivate::requestRunApp(const FilePath &appBundlePath, const QStringList &extraArgs, IosToolHandler::RunKind runType, const QString &deviceIdentifier, int timeout) @@ -828,10 +829,9 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath, m_deviceId = m_devType.identifier; m_runKind = runType; - Utils::FilePath appBundle = Utils::FilePath::fromString(m_bundlePath); - if (!appBundle.exists()) { + if (!m_bundlePath.exists()) { errorMsg(Tr::tr("Application launch on simulator failed. Invalid bundle path %1") - .arg(m_bundlePath)); + .arg(m_bundlePath.toUserOutput())); didStartApp(m_bundlePath, m_deviceId, Ios::IosToolHandler::Failure); return; } @@ -901,15 +901,13 @@ void IosSimulatorToolHandlerPrivate::installAppOnSimulator() }; isTransferringApp(m_bundlePath, m_deviceId, 20, 100, ""); - auto installFuture = SimulatorControl::installApp(m_deviceId, - Utils::FilePath::fromString(m_bundlePath)); + auto installFuture = SimulatorControl::installApp(m_deviceId, m_bundlePath); futureSynchronizer.addFuture(Utils::onResultReady(installFuture, q, onResponseAppInstall)); } void IosSimulatorToolHandlerPrivate::launchAppOnSimulator(const QStringList &extraArgs) { - const Utils::FilePath appBundle = Utils::FilePath::fromString(m_bundlePath); - const QString bundleId = SimulatorControl::bundleIdentifier(appBundle); + const QString bundleId = SimulatorControl::bundleIdentifier(m_bundlePath); const bool debugRun = m_runKind == IosToolHandler::DebugRun; bool captureConsole = IosConfigurations::xcodeVersion() >= QVersionNumber(8); std::shared_ptr<QTemporaryFile> stdoutFile; @@ -1012,13 +1010,13 @@ void IosToolHandler::stop() d->stop(-1); } -void IosToolHandler::requestTransferApp(const QString &bundlePath, const QString &deviceId, +void IosToolHandler::requestTransferApp(const FilePath &bundlePath, const QString &deviceId, int timeout) { d->requestTransferApp(bundlePath, deviceId, timeout); } -void IosToolHandler::requestRunApp(const QString &bundlePath, const QStringList &extraArgs, +void IosToolHandler::requestRunApp(const FilePath &bundlePath, const QStringList &extraArgs, RunKind runType, const QString &deviceId, int timeout) { d->requestRunApp(bundlePath, extraArgs, runType, deviceId, timeout); diff --git a/src/plugins/ios/iostoolhandler.h b/src/plugins/ios/iostoolhandler.h index 4d6c4bee78..a85e3250b4 100644 --- a/src/plugins/ios/iostoolhandler.h +++ b/src/plugins/ios/iostoolhandler.h @@ -3,6 +3,7 @@ #pragma once +#include <utils/filepath.h> #include <utils/port.h> #include <QObject> @@ -35,24 +36,24 @@ public: explicit IosToolHandler(const Internal::IosDeviceType &type, QObject *parent = nullptr); ~IosToolHandler() override; - void requestTransferApp(const QString &bundlePath, const QString &deviceId, int timeout = 1000); - void requestRunApp(const QString &bundlePath, const QStringList &extraArgs, RunKind runType, + void requestTransferApp(const Utils::FilePath &bundlePath, const QString &deviceId, int timeout = 1000); + void requestRunApp(const Utils::FilePath &bundlePath, const QStringList &extraArgs, RunKind runType, const QString &deviceId, int timeout = 1000); void requestDeviceInfo(const QString &deviceId, int timeout = 1000); bool isRunning() const; void stop(); signals: - void isTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath, + void isTransferringApp(Ios::IosToolHandler *handler, const Utils::FilePath &bundlePath, const QString &deviceId, int progress, int maxProgress, const QString &info); - void didTransferApp(Ios::IosToolHandler *handler, const QString &bundlePath, + void didTransferApp(Ios::IosToolHandler *handler, const Utils::FilePath &bundlePath, const QString &deviceId, Ios::IosToolHandler::OpStatus status); - void didStartApp(Ios::IosToolHandler *handler, const QString &bundlePath, + void didStartApp(Ios::IosToolHandler *handler, const Utils::FilePath &bundlePath, const QString &deviceId, Ios::IosToolHandler::OpStatus status); - void gotServerPorts(Ios::IosToolHandler *handler, const QString &bundlePath, + void gotServerPorts(Ios::IosToolHandler *handler, const Utils::FilePath &bundlePath, const QString &deviceId, Utils::Port gdbPort, Utils::Port qmlPort); - void gotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath, + void gotInferiorPid(Ios::IosToolHandler *handler, const Utils::FilePath &bundlePath, const QString &deviceId, qint64 pid); void deviceInfo(Ios::IosToolHandler *handler, const QString &deviceId, const Ios::IosToolHandler::Dict &info); diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 130961ebd1..bb5a4594dc 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -313,6 +313,7 @@ public: AssistProviders m_clientProviders; QMap<TextEditor::TextDocument *, AssistProviders> m_resetAssistProvider; QHash<TextEditor::TextEditorWidget *, LanguageServerProtocol::MessageId> m_highlightRequests; + QHash<QString, Client::CustomMethodHandler> m_customHandlers; static const int MaxRestarts = 5; int m_restartsLeft = MaxRestarts; QTimer m_restartCountResetTimer; @@ -1921,6 +1922,12 @@ void ClientPrivate::handleMethod(const QString &method, const MessageId &id, con error.setMessage(QString("The client cannot handle the method '%1'.").arg(method)); response.setError(error); sendResponse(response); + } else { + const auto customHandler = m_customHandlers.constFind(method); + if (customHandler != m_customHandlers.constEnd()) { + (*customHandler)(message); + return; + } } // we got a request and handled it somewhere above but we missed to generate a response for it @@ -2136,6 +2143,11 @@ DocumentUri Client::hostPathToServerUri(const Utils::FilePath &path) const }); } +void Client::registerCustomMethod(const QString &method, const CustomMethodHandler &handler) +{ + d->m_customHandlers.insert(method, handler); +} + } // namespace LanguageClient #include <client.moc> diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index 2ddd155a9f..9c934ea161 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -169,6 +169,11 @@ public: Utils::FilePath serverUriToHostPath(const LanguageServerProtocol::DocumentUri &uri) const; LanguageServerProtocol::DocumentUri hostPathToServerUri(const Utils::FilePath &path) const; + // custom methods + using CustomMethodHandler = std::function<void( + const LanguageServerProtocol::JsonRpcMessage &message)>; + void registerCustomMethod(const QString &method, const CustomMethodHandler &handler); + // logging enum class LogTarget { Console, Ui }; void setLogTarget(LogTarget target); diff --git a/src/plugins/languageclient/clientrequesttask.cpp b/src/plugins/languageclient/clientrequesttask.cpp index ed3ddaff2c..6da5be5704 100644 --- a/src/plugins/languageclient/clientrequesttask.cpp +++ b/src/plugins/languageclient/clientrequesttask.cpp @@ -3,8 +3,6 @@ #include "clientrequesttask.h" -#include <QScopeGuard> - using namespace LanguageServerProtocol; namespace LanguageClient { diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index 50a3807189..86485ff8aa 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -28,7 +28,6 @@ #include <texteditor/textmark.h> #include <utils/algorithm.h> -#include <utils/executeondestruction.h> #include <utils/theme/theme.h> #include <utils/utilsicons.h> diff --git a/src/plugins/marketplace/productlistmodel.cpp b/src/plugins/marketplace/productlistmodel.cpp index 36b047abc2..1de5a4b833 100644 --- a/src/plugins/marketplace/productlistmodel.cpp +++ b/src/plugins/marketplace/productlistmodel.cpp @@ -4,7 +4,6 @@ #include "productlistmodel.h" #include <utils/algorithm.h> -#include <utils/executeondestruction.h> #include <utils/networkaccessmanager.h> #include <utils/qtcassert.h> @@ -19,6 +18,7 @@ #include <QNetworkRequest> #include <QPixmapCache> #include <QRegularExpression> +#include <QScopeGuard> #include <QTimer> #include <QUrl> #include <QVBoxLayout> @@ -107,7 +107,7 @@ void SectionedProducts::updateCollections() void SectionedProducts::onFetchCollectionsFinished(QNetworkReply *reply) { QTC_ASSERT(reply, return); - Utils::ExecuteOnDestruction replyDeleter([reply]() { reply->deleteLater(); }); + const QScopeGuard cleanup([reply] { reply->deleteLater(); }); if (reply->error() == QNetworkReply::NoError) { const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); @@ -141,7 +141,7 @@ void SectionedProducts::onFetchSingleCollectionFinished(QNetworkReply *reply) emit toggleProgressIndicator(false); QTC_ASSERT(reply, return); - Utils::ExecuteOnDestruction replyDeleter([reply]() { reply->deleteLater(); }); + const QScopeGuard cleanup([reply] { reply->deleteLater(); }); QList<Core::ListItem *> productsForCollection; if (reply->error() == QNetworkReply::NoError) { @@ -259,7 +259,7 @@ void SectionedProducts::fetchNextImage() void SectionedProducts::onImageDownloadFinished(QNetworkReply *reply) { QTC_ASSERT(reply, return); - Utils::ExecuteOnDestruction replyDeleter([reply]() { reply->deleteLater(); }); + const QScopeGuard cleanup([reply] { reply->deleteLater(); }); if (reply->error() == QNetworkReply::NoError) { const QByteArray data = reply->readAll(); diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index a05a3771b0..b303a7acae 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -316,6 +316,9 @@ void McuSupportOptionsWidget::apply() m_settingsHandler->setAutomaticKitCreation(m_options.automaticKitCreationEnabled()); m_options.sdkRepository.expandVariablesAndWildcards(); + if (m_mcuTargetsComboBox->count() == 0) + return; + QMessageBox warningPopup(QMessageBox::Icon::Warning, Tr::tr("Warning"), Tr::tr("Unable to apply changes in Devices > MCU."), diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp index 32be37048e..f4d5fba031 100644 --- a/src/plugins/projectexplorer/buildstep.cpp +++ b/src/plugins/projectexplorer/buildstep.cpp @@ -150,8 +150,10 @@ QWidget *BuildStep::doCreateConfigWidget() for (BaseAspect *aspect : std::as_const(*this)) connect(aspect, &BaseAspect::changed, widget, recreateSummary); - connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, - widget, recreateSummary); + if (buildConfiguration()) { + connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, + widget, recreateSummary); + } recreateSummary(); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 50f552444b..12ff8e3cac 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -142,6 +142,7 @@ public: FilePath debugServerPath; FilePath debugDumperPath = Core::ICore::resourcePath("debugger/"); FilePath qmlRunCommand; + bool qmlRunCommandChecked = false; bool emptyCommandAllowed = false; QList<Icon> deviceIcons; @@ -603,12 +604,20 @@ void IDevice::setDebugServerPath(const FilePath &path) FilePath IDevice::qmlRunCommand() const { + if (!d->qmlRunCommandChecked) { + d->qmlRunCommandChecked = true; + QString runtime = d->qmlRunCommand.path(); + if (runtime.isEmpty()) + runtime = "qml"; + d->qmlRunCommand = searchExecutableInPath(runtime); + } return d->qmlRunCommand; } void IDevice::setQmlRunCommand(const FilePath &path) { d->qmlRunCommand = path; + d->qmlRunCommandChecked = false; } void IDevice::setExtraData(Id kind, const QVariant &data) diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp index 49a9571189..acb32043dc 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp @@ -150,7 +150,7 @@ QVariant JsonFieldPage::Field::toSettings() const JsonFieldPage::Field *JsonFieldPage::Field::parse(const QVariant &input, QString *errorMessage) { - if (input.type() != QVariant::Map) { + if (input.typeId() != QVariant::Map) { *errorMessage = Tr::tr("Field is not an object."); return nullptr; } @@ -393,7 +393,7 @@ QDebug &operator<<(QDebug &debug, const JsonFieldPage::Field &field) bool LabelField::parseData(const QVariant &data, QString *errorMessage) { - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("Label (\"%1\") data is not an object.").arg(name()); return false; } @@ -431,7 +431,7 @@ bool SpacerField::parseData(const QVariant &data, QString *errorMessage) if (data.isNull()) return true; - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("Spacer (\"%1\") data is not an object.").arg(name()); return false; } @@ -476,7 +476,7 @@ bool LineEditField::parseData(const QVariant &data, QString *errorMessage) if (data.isNull()) return true; - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("LineEdit (\"%1\") data is not an object.").arg(name()); return false; } @@ -673,7 +673,7 @@ bool TextEditField::parseData(const QVariant &data, QString *errorMessage) if (data.isNull()) return true; - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("TextEdit (\"%1\") data is not an object.") .arg(name()); return false; @@ -756,7 +756,7 @@ bool PathChooserField::parseData(const QVariant &data, QString *errorMessage) if (data.isNull()) return true; - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("PathChooser data is not an object."); return false; } @@ -861,7 +861,7 @@ bool CheckBoxField::parseData(const QVariant &data, QString *errorMessage) if (data.isNull()) return true; - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("CheckBox (\"%1\") data is not an object.").arg(name()); return false; } @@ -950,12 +950,12 @@ QVariant CheckBoxField::toSettings() const std::unique_ptr<QStandardItem> createStandardItemFromListItem(const QVariant &item, QString *errorMessage) { - if (item.type() == QVariant::List) { + if (item.typeId() == QVariant::List) { *errorMessage = Tr::tr("No JSON lists allowed inside List items."); return {}; } auto standardItem = std::make_unique<QStandardItem>(); - if (item.type() == QVariant::Map) { + if (item.typeId() == QVariant::Map) { QVariantMap tmp = item.toMap(); const QString key = JsonWizardFactory::localizedString(consumeValue(tmp, "trKey", QString()).toString()); const QVariant value = consumeValue(tmp, "value", key); @@ -985,7 +985,7 @@ ListField::~ListField() = default; bool ListField::parseData(const QVariant &data, QString *errorMessage) { - if (data.type() != QVariant::Map) { + if (data.typeId() != QVariant::Map) { *errorMessage = Tr::tr("%1 (\"%2\") data is not an object.").arg(type(), name()); return false; } @@ -1011,7 +1011,7 @@ bool ListField::parseData(const QVariant &data, QString *errorMessage) *errorMessage = Tr::tr("%1 (\"%2\") \"items\" missing.").arg(type(), name()); return false; } - if (value.type() != QVariant::List) { + if (value.typeId() != QVariant::List) { *errorMessage = Tr::tr("%1 (\"%2\") \"items\" is not a JSON list.").arg(type(), name()); return false; } diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp index b0d370d13c..27bad16e8c 100644 --- a/src/plugins/projectexplorer/kit.cpp +++ b/src/plugins/projectexplorer/kit.cpp @@ -578,7 +578,7 @@ QString Kit::toHtml(const Tasks &additional, const QString &extraText) const const KitAspect::ItemList list = aspect->toUserOutput(this); for (const KitAspect::Item &j : list) { QString contents = j.second; - if (contents.count() > 256) { + if (contents.size() > 256) { int pos = contents.lastIndexOf("<br>", 256); if (pos < 0) // no linebreak, so cut early. pos = 80; diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp index fc8039b402..e5cfd9f5d7 100644 --- a/src/plugins/projectexplorer/kitinformation.cpp +++ b/src/plugins/projectexplorer/kitinformation.cpp @@ -239,6 +239,8 @@ private: void refresh() override { + IDeviceConstPtr device = BuildDeviceKitAspect::device(kit()); + const GuardLocker locker(m_ignoreChanges); const QList<Id> keys = m_languageComboboxMap.keys(); for (const Id l : keys) { @@ -248,8 +250,21 @@ private: cb->clear(); cb->addItem(Tr::tr("<No compiler>"), QByteArray()); - for (ToolChain *tc : ltcList) - cb->addItem(tc->displayName(), tc->id()); + const QList<ToolChain *> same = Utils::filtered(ltcList, [device](ToolChain *tc) { + return tc->compilerCommand().isSameDevice(device->rootPath()); + }); + const QList<ToolChain *> other = Utils::filtered(ltcList, [device](ToolChain *tc) { + return !tc->compilerCommand().isSameDevice(device->rootPath()); + }); + + for (ToolChain *item : same) + cb->addItem(item->displayName(), item->id()); + + if (!same.isEmpty() && !other.isEmpty()) + cb->insertSeparator(cb->count()); + + for (ToolChain *item : other) + cb->addItem(item->displayName(), item->id()); cb->setEnabled(cb->count() > 1 && !m_isReadOnly); const int index = indexOf(cb, ToolChainKitAspect::toolChain(m_kit, l)); @@ -471,10 +486,9 @@ void ToolChainKitAspect::setup(Kit *k) // ID is not found: Might be an ABI string... lockToolchains = false; const QString abi = QString::fromUtf8(id); - const Toolchains possibleTcs = ToolChainManager::toolchains( - [abi, l](const ToolChain *t) { - return t->targetAbi().toString() == abi && t->language() == l; - }); + const Toolchains possibleTcs = ToolChainManager::toolchains([abi, l](const ToolChain *t) { + return t->targetAbi().toString() == abi && t->language() == l; + }); ToolChain *bestTc = nullptr; for (ToolChain *tc : possibleTcs) { if (!bestTc || tc->priority() > bestTc->priority()) diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index ee9ffea832..028706fa2d 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -4,6 +4,7 @@ #include "makestep.h" #include "buildconfiguration.h" +#include "devicesupport/idevice.h" #include "gnumakeparser.h" #include "kitinformation.h" #include "processparameters.h" @@ -46,65 +47,58 @@ MakeStep::MakeStep(BuildStepList *parent, Id id) setCommandLineProvider([this] { return effectiveMakeCommand(Execution); }); - m_makeCommandAspect = addAspect<FilePathAspect>(); - m_makeCommandAspect->setSettingsKey(id.withSuffix(MAKE_COMMAND_SUFFIX).toString()); - m_makeCommandAspect->setExpectedKind(PathChooser::ExistingCommand); - m_makeCommandAspect->setBaseFileName(PathChooser::homePath()); - m_makeCommandAspect->setHistoryCompleter("PE.MakeCommand.History"); + m_makeCommandAspect.setSettingsKey(id.withSuffix(MAKE_COMMAND_SUFFIX).toString()); + m_makeCommandAspect.setExpectedKind(PathChooser::ExistingCommand); + m_makeCommandAspect.setBaseFileName(PathChooser::homePath()); + m_makeCommandAspect.setHistoryCompleter("PE.MakeCommand.History"); - m_userArgumentsAspect = addAspect<StringAspect>(); - m_userArgumentsAspect->setSettingsKey(id.withSuffix(MAKE_ARGUMENTS_SUFFIX).toString()); - m_userArgumentsAspect->setLabelText(Tr::tr("Make arguments:")); - m_userArgumentsAspect->setDisplayStyle(StringAspect::LineEditDisplay); + m_userArgumentsAspect.setSettingsKey(id.withSuffix(MAKE_ARGUMENTS_SUFFIX).toString()); + m_userArgumentsAspect.setLabelText(Tr::tr("Make arguments:")); + m_userArgumentsAspect.setDisplayStyle(StringAspect::LineEditDisplay); - m_userJobCountAspect = addAspect<IntegerAspect>(); - m_userJobCountAspect->setSettingsKey(id.withSuffix(JOBCOUNT_SUFFIX).toString()); - m_userJobCountAspect->setLabel(Tr::tr("Parallel jobs:")); - m_userJobCountAspect->setRange(1, 999); - m_userJobCountAspect->setValue(defaultJobCount()); - m_userJobCountAspect->setDefaultValue(defaultJobCount()); + m_jobCountAspect.setSettingsKey(id.withSuffix(JOBCOUNT_SUFFIX).toString()); + m_jobCountAspect.setLabel(Tr::tr("Parallel jobs:")); + m_jobCountAspect.setRange(1, 999); + m_jobCountAspect.setValue(defaultJobCount()); + m_jobCountAspect.setDefaultValue(defaultJobCount()); const QString text = Tr::tr("Override MAKEFLAGS"); - m_overrideMakeflagsAspect = addAspect<BoolAspect>(); - m_overrideMakeflagsAspect->setSettingsKey(id.withSuffix(OVERRIDE_MAKEFLAGS_SUFFIX).toString()); - m_overrideMakeflagsAspect->setLabel(text, BoolAspect::LabelPlacement::AtCheckBox); + m_overrideMakeflagsAspect.setSettingsKey(id.withSuffix(OVERRIDE_MAKEFLAGS_SUFFIX).toString()); + m_overrideMakeflagsAspect.setLabel(text, BoolAspect::LabelPlacement::AtCheckBox); - m_nonOverrideWarning = addAspect<TextDisplay>(); - m_nonOverrideWarning->setText("<html><body><p>" + + m_nonOverrideWarning.setText("<html><body><p>" + Tr::tr("<code>MAKEFLAGS</code> specifies parallel jobs. Check \"%1\" to override.") .arg(text) + "</p></body></html>"); - m_nonOverrideWarning->setIconType(InfoLabel::Warning); + m_nonOverrideWarning.setIconType(InfoLabel::Warning); - m_disabledForSubdirsAspect = addAspect<BoolAspect>(); - m_disabledForSubdirsAspect->setSettingsKey(id.withSuffix(".disabledForSubdirs").toString()); - m_disabledForSubdirsAspect->setLabel(Tr::tr("Disable in subdirectories:")); - m_disabledForSubdirsAspect->setToolTip(Tr::tr("Runs this step only for a top-level build.")); + m_disabledForSubdirsAspect.setSettingsKey(id.withSuffix(".disabledForSubdirs").toString()); + m_disabledForSubdirsAspect.setLabel(Tr::tr("Disable in subdirectories:")); + m_disabledForSubdirsAspect.setToolTip(Tr::tr("Runs this step only for a top-level build.")); - m_buildTargetsAspect = addAspect<MultiSelectionAspect>(); - m_buildTargetsAspect->setSettingsKey(id.withSuffix(BUILD_TARGETS_SUFFIX).toString()); - m_buildTargetsAspect->setLabelText(Tr::tr("Targets:")); + m_buildTargetsAspect.setSettingsKey(id.withSuffix(BUILD_TARGETS_SUFFIX).toString()); + m_buildTargetsAspect.setLabelText(Tr::tr("Targets:")); const auto updateMakeLabel = [this] { const FilePath defaultMake = defaultMakeCommand(); const QString labelText = defaultMake.isEmpty() ? Tr::tr("Make:") : Tr::tr("Override %1:").arg(defaultMake.toUserOutput()); - m_makeCommandAspect->setLabelText(labelText); + m_makeCommandAspect.setLabelText(labelText); }; updateMakeLabel(); - connect(m_makeCommandAspect, &StringAspect::changed, this, updateMakeLabel); + connect(&m_makeCommandAspect, &StringAspect::changed, this, updateMakeLabel); } void MakeStep::setSelectedBuildTarget(const QString &buildTarget) { - m_buildTargetsAspect->setValue({buildTarget}); + m_buildTargetsAspect.setValue({buildTarget}); } void MakeStep::setAvailableBuildTargets(const QStringList &buildTargets) { - m_buildTargetsAspect->setAllValues(buildTargets); + m_buildTargetsAspect.setAllValues(buildTargets); } bool MakeStep::init() @@ -158,8 +152,11 @@ FilePath MakeStep::defaultMakeCommand() const const Environment env = makeEnvironment(); for (const ToolChain *tc : preferredToolChains(kit())) { FilePath make = tc->makeCommand(env); - if (!make.isEmpty()) - return mapFromBuildDeviceToGlobalPath(make); + if (!make.isEmpty()) { + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(kit()); + QTC_ASSERT(dev, return {}); + return dev->filePath(make.path()); + } } return {}; } @@ -183,7 +180,7 @@ bool MakeStep::isJobCountSupported() const bool MakeStep::jobCountOverridesMakeflags() const { - return m_overrideMakeflagsAspect->value(); + return m_overrideMakeflagsAspect(); } static std::optional<int> argsJobCount(const QString &str) @@ -216,12 +213,12 @@ bool MakeStep::makeflagsJobCountMismatch() const if (!env.hasKey(MAKEFLAGS)) return false; std::optional<int> makeFlagsJobCount = argsJobCount(env.expandedValueForKey(MAKEFLAGS)); - return makeFlagsJobCount.has_value() && *makeFlagsJobCount != m_userJobCountAspect->value(); + return makeFlagsJobCount.has_value() && *makeFlagsJobCount != m_jobCountAspect(); } bool MakeStep::enabledForSubDirs() const { - return !m_disabledForSubdirsAspect->value(); + return !m_disabledForSubdirsAspect(); } bool MakeStep::makeflagsContainsJobCount() const @@ -255,7 +252,7 @@ Environment MakeStep::makeEnvironment() const void MakeStep::setMakeCommand(const FilePath &command) { - m_makeCommandAspect->setFilePath(command); + m_makeCommandAspect.setFilePath(command); } int MakeStep::defaultJobCount() @@ -269,17 +266,17 @@ QStringList MakeStep::jobArguments() const || (makeflagsContainsJobCount() && !jobCountOverridesMakeflags())) { return {}; } - return {"-j" + QString::number(m_userJobCountAspect->value())}; + return {"-j" + QString::number(m_jobCountAspect())}; } QString MakeStep::userArguments() const { - return m_userArgumentsAspect->value(); + return m_userArgumentsAspect(); } void MakeStep::setUserArguments(const QString &args) { - m_userArgumentsAspect->setValue(args); + m_userArgumentsAspect.setValue(args); } QStringList MakeStep::displayArguments() const @@ -289,7 +286,7 @@ QStringList MakeStep::displayArguments() const FilePath MakeStep::makeCommand() const { - return m_makeCommandAspect->filePath(); + return m_makeCommandAspect(); } FilePath MakeStep::makeExecutable() const @@ -306,7 +303,7 @@ CommandLine MakeStep::effectiveMakeCommand(MakeCommandType type) const cmd.addArgs(displayArguments()); cmd.addArgs(userArguments(), CommandLine::Raw); cmd.addArgs(jobArguments()); - cmd.addArgs(m_buildTargetsAspect->value()); + cmd.addArgs(m_buildTargetsAspect.value()); return cmd; } @@ -316,7 +313,7 @@ QWidget *MakeStep::createConfigWidget() Layouting::Form builder; builder.addRow({m_makeCommandAspect}); builder.addRow({m_userArgumentsAspect}); - builder.addRow({m_userJobCountAspect, m_overrideMakeflagsAspect, m_nonOverrideWarning}); + builder.addRow({m_jobCountAspect, m_overrideMakeflagsAspect, m_nonOverrideWarning}); if (m_disablingForSubDirsSupported) builder.addRow({m_disabledForSubdirsAspect}); builder.addRow({m_buildTargetsAspect}); @@ -350,23 +347,23 @@ QWidget *MakeStep::createConfigWidget() auto updateDetails = [this] { const bool jobCountVisible = isJobCountSupported(); - m_userJobCountAspect->setVisible(jobCountVisible); - m_overrideMakeflagsAspect->setVisible(jobCountVisible); + m_jobCountAspect.setVisible(jobCountVisible); + m_overrideMakeflagsAspect.setVisible(jobCountVisible); const bool jobCountEnabled = !userArgsContainsJobCount(); - m_userJobCountAspect->setEnabled(jobCountEnabled); - m_overrideMakeflagsAspect->setEnabled(jobCountEnabled); - m_nonOverrideWarning->setVisible(makeflagsJobCountMismatch() + m_jobCountAspect.setEnabled(jobCountEnabled); + m_overrideMakeflagsAspect.setEnabled(jobCountEnabled); + m_nonOverrideWarning.setVisible(makeflagsJobCountMismatch() && !jobCountOverridesMakeflags()); }; updateDetails(); - connect(m_makeCommandAspect, &StringAspect::changed, widget, updateDetails); - connect(m_userArgumentsAspect, &StringAspect::changed, widget, updateDetails); - connect(m_userJobCountAspect, &IntegerAspect::changed, widget, updateDetails); - connect(m_overrideMakeflagsAspect, &BoolAspect::changed, widget, updateDetails); - connect(m_buildTargetsAspect, &BaseAspect::changed, widget, updateDetails); + connect(&m_makeCommandAspect, &StringAspect::changed, widget, updateDetails); + connect(&m_userArgumentsAspect, &StringAspect::changed, widget, updateDetails); + connect(&m_jobCountAspect, &IntegerAspect::changed, widget, updateDetails); + connect(&m_overrideMakeflagsAspect, &BoolAspect::changed, widget, updateDetails); + connect(&m_buildTargetsAspect, &BaseAspect::changed, widget, updateDetails); connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged, widget, updateDetails); @@ -382,7 +379,7 @@ QWidget *MakeStep::createConfigWidget() QStringList MakeStep::availableTargets() const { - return m_buildTargetsAspect->allValues(); + return m_buildTargetsAspect.allValues(); } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h index 2f12894ea6..d26820d90c 100644 --- a/src/plugins/projectexplorer/makestep.h +++ b/src/plugins/projectexplorer/makestep.h @@ -59,26 +59,18 @@ protected: void supportDisablingForSubdirs() { m_disablingForSubDirsSupported = true; } virtual QStringList displayArguments() const; - Utils::StringAspect *makeCommandAspect() const { return m_makeCommandAspect; } - Utils::MultiSelectionAspect *buildTargetsAspect() const { return m_buildTargetsAspect; } - Utils::StringAspect *userArgumentsAspect() const { return m_userArgumentsAspect; } - Utils::BoolAspect *overrideMakeflagsAspect() const { return m_overrideMakeflagsAspect; } - Utils::TextDisplay *nonOverrideWarning() const { return m_nonOverrideWarning; } - Utils::IntegerAspect *jobCountAspect() const { return m_userJobCountAspect; } - Utils::BoolAspect *disabledForSubdirsAspect() const { return m_disabledForSubdirsAspect; } - + Utils::FilePathAspect m_makeCommandAspect{this}; + Utils::MultiSelectionAspect m_buildTargetsAspect{this}; + Utils::StringAspect m_userArgumentsAspect{this}; + Utils::BoolAspect m_overrideMakeflagsAspect{this}; + Utils::TextDisplay m_nonOverrideWarning{this}; + Utils::IntegerAspect m_jobCountAspect{this}; + Utils::BoolAspect m_disabledForSubdirsAspect{this}; private: static int defaultJobCount(); QStringList jobArguments() const; - Utils::MultiSelectionAspect *m_buildTargetsAspect = nullptr; - Utils::StringAspect *m_makeCommandAspect = nullptr; - Utils::StringAspect *m_userArgumentsAspect = nullptr; - Utils::IntegerAspect *m_userJobCountAspect = nullptr; - Utils::BoolAspect *m_overrideMakeflagsAspect = nullptr; - Utils::BoolAspect *m_disabledForSubdirsAspect = nullptr; - Utils::TextDisplay *m_nonOverrideWarning = nullptr; bool m_disablingForSubDirsSupported = false; }; diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp index 841be31731..4aad7c4a39 100644 --- a/src/plugins/projectexplorer/projectconfiguration.cpp +++ b/src/plugins/projectexplorer/projectconfiguration.cpp @@ -6,7 +6,6 @@ #include "kitinformation.h" #include "target.h" -#include <projectexplorer/devicesupport/idevice.h> #include <utils/algorithm.h> #include <utils/qtcassert.h> @@ -108,13 +107,6 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map) return true; } -FilePath ProjectConfiguration::mapFromBuildDeviceToGlobalPath(const FilePath &path) const -{ - IDevice::ConstPtr dev = BuildDeviceKitAspect::device(kit()); - QTC_ASSERT(dev, return path); - return dev->filePath(path.path()); -} - Id ProjectExplorer::idFromMap(const QVariantMap &map) { return Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY))); diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h index 8c5dac1d90..790d9ebf6b 100644 --- a/src/plugins/projectexplorer/projectconfiguration.h +++ b/src/plugins/projectexplorer/projectconfiguration.h @@ -54,8 +54,6 @@ public: static QString settingsIdKey(); - Utils::FilePath mapFromBuildDeviceToGlobalPath(const Utils::FilePath &path) const; - signals: void displayNameChanged(); void toolTipChanged(); diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index 9805e654b7..64fabcb30a 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -436,6 +436,8 @@ void FlatModel::handleProjectAdded(Project *project) { QTC_ASSERT(project, return); + auto oldName = project->displayName(); + project->setProperty("_q_oldProjectName", oldName); connect(project, &Project::anyParsingStarted, this, [this, project]() { if (nodeForProject(project)) @@ -443,8 +445,28 @@ void FlatModel::handleProjectAdded(Project *project) }); connect(project, &Project::anyParsingFinished, this, [this, project]() { - if (nodeForProject(project)) + auto wrapper = nodeForProject(project); + if (wrapper) { + // In case the project was renamed, change the name in expand data as well + // FIXME: Redesign node expansion so that it does not rely on display name of a node + auto oldName = project->property("_q_oldProjectName").toString(); + auto currentName = project->displayName(); + if (oldName != currentName) { + project->setProperty("_q_oldProjectName", currentName); + auto node = wrapper->m_node; + ExpandData oldData(node->filePath().toString(), oldName); + ExpandData newData(oldData.path, currentName); + auto it = m_toExpand.find(oldData); + if (it != m_toExpand.end()) { + m_toExpand.erase(it); + m_toExpand.insert(newData); + emit requestExpansion(wrapper->index()); + } else if (m_toExpand.contains(newData)) { + emit requestExpansion(wrapper->index()); + } + } parsingStateChanged(project); + } emit ProjectTree::instance()->nodeActionsChanged(); }); addOrRebuildProjectModel(project); diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index 4eef637077..5def44f948 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -535,7 +535,7 @@ public: projectModel->resetProjects(); }); contextMenu.addAction(action); - contextMenu.exec(mouseEvent->globalPos()); + contextMenu.exec(mouseEvent->globalPosition().toPoint()); return true; } } diff --git a/src/plugins/projectexplorer/rawprojectpart.cpp b/src/plugins/projectexplorer/rawprojectpart.cpp index 31147c3803..81d4951ed0 100644 --- a/src/plugins/projectexplorer/rawprojectpart.cpp +++ b/src/plugins/projectexplorer/rawprojectpart.cpp @@ -45,9 +45,10 @@ void RawProjectPart::setFiles(const QStringList &files, this->getMimeType = getMimeType; } -static QString trimTrailingSlashes(const QString &path) { +static QString trimTrailingSlashes(const QString &path) +{ QString p = path; - while (p.endsWith('/') && p.count() > 1) { + while (p.endsWith('/') && p.size() > 1) { p.chop(1); } return p; diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index ce28582d55..5a15579446 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -386,7 +386,7 @@ void ArgumentsAspect::fromMap(const QVariantMap &map) { QVariant args = map.value(settingsKey()); // Until 3.7 a QStringList was stored for Remote Linux - if (args.type() == QVariant::StringList) + if (args.typeId() == QVariant::StringList) m_arguments = ProcessArgs::joinArgs(args.toStringList(), OsTypeLinux); else m_arguments = args.toString(); diff --git a/src/plugins/projectexplorer/taskfile.cpp b/src/plugins/projectexplorer/taskfile.cpp index c967521d89..b6a95c0325 100644 --- a/src/plugins/projectexplorer/taskfile.cpp +++ b/src/plugins/projectexplorer/taskfile.cpp @@ -79,9 +79,9 @@ static QStringList parseRawLine(const QByteArray &raw) static QString unescape(const QString &input) { QString result; - for (int i = 0; i < input.count(); ++i) { + for (int i = 0; i < input.size(); ++i) { if (input.at(i) == '\\') { - if (i == input.count() - 1) + if (i == input.size() - 1) continue; if (input.at(i + 1) == 'n') { result.append('\n'); @@ -123,16 +123,16 @@ static bool parseTaskFile(QString *errorString, const FilePath &name) Task::TaskType type = Task::Unknown; int line = -1; - if (chunks.count() == 1) { + if (chunks.size() == 1) { description = chunks.at(0); - } else if (chunks.count() == 2) { + } else if (chunks.size() == 2) { type = typeFrom(chunks.at(0)); description = chunks.at(1); - } else if (chunks.count() == 3) { + } else if (chunks.size() == 3) { file = chunks.at(0); type = typeFrom(chunks.at(1)); description = chunks.at(2); - } else if (chunks.count() >= 4) { + } else if (chunks.size() >= 4) { file = chunks.at(0); bool ok; line = chunks.at(1).toInt(&ok); diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp index ae900ea818..5a765cb537 100644 --- a/src/plugins/projectexplorer/userfileaccessor.cpp +++ b/src/plugins/projectexplorer/userfileaccessor.cpp @@ -455,7 +455,7 @@ QVariantMap UserFileVersion14Upgrader::upgrade(const QVariantMap &map) { QVariantMap result; for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) { - if (it.value().type() == QVariant::Map) + if (it.value().typeId() == QVariant::Map) result.insert(it.key(), upgrade(it.value().toMap())); else if (it.key() == "AutotoolsProjectManager.AutotoolsBuildConfiguration.BuildDirectory" || it.key() == "CMakeProjectManager.CMakeBuildConfiguration.BuildDirectory" @@ -710,7 +710,7 @@ QVariantMap UserFileVersion17Upgrader::upgrade(const QVariantMap &map) QVariant UserFileVersion17Upgrader::process(const QVariant &entry) { - switch (entry.type()) { + switch (entry.typeId()) { case QVariant::List: { QVariantList result; for (const QVariant &item : entry.toList()) @@ -738,7 +738,7 @@ QVariantMap UserFileVersion18Upgrader::upgrade(const QVariantMap &map) QVariant UserFileVersion18Upgrader::process(const QVariant &entry) { - switch (entry.type()) { + switch (entry.typeId()) { case QVariant::List: return Utils::transform(entry.toList(), &UserFileVersion18Upgrader::process); case QVariant::Map: @@ -792,7 +792,7 @@ QVariant UserFileVersion19Upgrader::process(const QVariant &entry, const QString "QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath"}; static const QStringList dyldKeys = {"Qbs.RunConfiguration.UseDyldImageSuffix", "QmakeProjectManager.QmakeRunConfiguration.UseDyldImageSuffix"}; - switch (entry.type()) { + switch (entry.typeId()) { case QVariant::List: return Utils::transform(entry.toList(), std::bind(&UserFileVersion19Upgrader::process, std::placeholders::_1, path)); @@ -827,7 +827,7 @@ QVariantMap UserFileVersion20Upgrader::upgrade(const QVariantMap &map) QVariant UserFileVersion20Upgrader::process(const QVariant &entry) { - switch (entry.type()) { + switch (entry.typeId()) { case QVariant::List: return Utils::transform(entry.toList(), &UserFileVersion20Upgrader::process); case QVariant::Map: @@ -853,7 +853,7 @@ QVariantMap UserFileVersion21Upgrader::upgrade(const QVariantMap &map) QVariant UserFileVersion21Upgrader::process(const QVariant &entry) { - switch (entry.type()) { + switch (entry.typeId()) { case QVariant::List: return Utils::transform(entry.toList(), &UserFileVersion21Upgrader::process); case QVariant::Map: { diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp index c17d3d9193..1a3e15fdd5 100644 --- a/src/plugins/qmakeprojectmanager/profileeditor.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp @@ -142,7 +142,7 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor, bool doBackwardScan = true; if (posCurlyPwd >= 0) { - const int end = chunkStart + posCurlyPwd + curlyPwd.count(); + const int end = chunkStart + posCurlyPwd + curlyPwd.size(); const int start = chunkStart + posCurlyPwd; if (start <= column && end >= column) { buffer = pwd; @@ -151,7 +151,7 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor, doBackwardScan = false; } } else if (posPwd >= 0) { - const int end = chunkStart + posPwd + pwd.count(); + const int end = chunkStart + posPwd + pwd.size(); const int start = chunkStart + posPwd; if (start <= column && end >= column) { buffer = pwd; @@ -173,19 +173,19 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor, if (doBackwardScan && beginPos > 0 - && block.mid(beginPos - 1, pwd.count()) == pwd - && (block.at(beginPos + pwd.count() - 1) == '/' || block.at(beginPos + pwd.count() - 1) == '\\')) { + && block.mid(beginPos - 1, pwd.size()) == pwd + && (block.at(beginPos + pwd.size() - 1) == '/' || block.at(beginPos + pwd.size() - 1) == '\\')) { buffer.prepend("$$"); beginPos -= 2; } else if (doBackwardScan - && beginPos >= curlyPwd.count() - 1 - && block.mid(beginPos - curlyPwd.count() + 1, curlyPwd.count()) == curlyPwd) { + && beginPos >= curlyPwd.size() - 1 + && block.mid(beginPos - curlyPwd.size() + 1, curlyPwd.size()) == curlyPwd) { buffer.prepend(pwd); - beginPos -= curlyPwd.count(); + beginPos -= curlyPwd.size(); } // find the end of a filename - while (endPos < block.count()) { + while (endPos < block.size()) { QChar c = block.at(endPos); if (isValidFileNameChar(c)) { buffer.append(c); diff --git a/src/plugins/qmakeprojectmanager/profilehoverhandler.cpp b/src/plugins/qmakeprojectmanager/profilehoverhandler.cpp index 2ab532cd56..3080888780 100644 --- a/src/plugins/qmakeprojectmanager/profilehoverhandler.cpp +++ b/src/plugins/qmakeprojectmanager/profilehoverhandler.cpp @@ -8,8 +8,8 @@ #include <coreplugin/helpmanager.h> #include <texteditor/texteditor.h> #include <utils/htmldocextractor.h> -#include <utils/executeondestruction.h> +#include <QScopeGuard> #include <QTextBlock> #include <QUrl> @@ -28,7 +28,7 @@ void ProFileHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidg int pos, ReportPriority report) { - ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); m_docFragment.clear(); m_manualKind = UnknownManual; diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index 9da9f7f65a..c494f5544a 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -643,33 +643,29 @@ QString QmakeBuildConfiguration::extractSpecFromArguments(QString *args, if (parsedSpec.isEmpty()) return {}; - FilePath baseMkspecDir = FilePath::fromUserInput(version->hostDataPath().toString() - + "/mkspecs"); - baseMkspecDir = FilePath::fromString(baseMkspecDir.toFileInfo().canonicalFilePath()); + const FilePath baseMkspecDir = version->hostDataPath().pathAppended("mkspecs") + .canonicalPath(); // if the path is relative it can be // relative to the working directory (as found in the Makefiles) // or relatively to the mkspec directory // if it is the former we need to get the canonical form // for the other one we don't need to do anything - if (parsedSpec.toFileInfo().isRelative()) { - if (QFileInfo::exists(directory.path() + QLatin1Char('/') + parsedSpec.toString())) - parsedSpec = FilePath::fromUserInput(directory.path() + QLatin1Char('/') + parsedSpec.toString()); + if (parsedSpec.isRelativePath()) { + FilePath mkspecs = directory.pathAppended(parsedSpec.path()); + if (mkspecs.exists()) + parsedSpec = mkspecs; else - parsedSpec = FilePath::fromUserInput(baseMkspecDir.toString() + QLatin1Char('/') + parsedSpec.toString()); + parsedSpec = baseMkspecDir.pathAppended(parsedSpec.path()); } - QFileInfo f2 = parsedSpec.toFileInfo(); - while (f2.isSymLink()) { - parsedSpec = FilePath::fromString(f2.symLinkTarget()); - f2.setFile(parsedSpec.toString()); - } + for (int i = 0; i < 5 && parsedSpec.isSymLink(); ++i) + parsedSpec = parsedSpec.symLinkTarget(); if (parsedSpec.isChildOf(baseMkspecDir)) { parsedSpec = parsedSpec.relativeChildPath(baseMkspecDir); } else { - FilePath sourceMkSpecPath = FilePath::fromString(version->sourcePath().toString() - + QLatin1String("/mkspecs")); + FilePath sourceMkSpecPath = version->sourcePath().pathAppended("mkspecs"); if (parsedSpec.isChildOf(sourceMkSpecPath)) parsedSpec = parsedSpec.relativeChildPath(sourceMkSpecPath); } diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index 14110cc699..9a8a611c66 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -59,7 +59,7 @@ bool AssetsLibraryWidget::eventFilter(QObject *obj, QEvent *event) } else if (event->type() == QMouseEvent::MouseMove) { if (!m_assetsToDrag.isEmpty() && m_assetsView->model()) { QMouseEvent *me = static_cast<QMouseEvent *>(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { + if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 10) { QMimeData *mimeData = new QMimeData; mimeData->setData(Constants::MIME_TYPE_ASSETS, m_assetsToDrag.join(',').toUtf8()); @@ -133,7 +133,7 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon setStyleSheet(Theme::replaceCssColors( QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css")))); - m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6), this); + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F6), this); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &AssetsLibraryWidget::reloadQmlSource); connect(this, &AssetsLibraryWidget::extFilesDrop, diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 77976993e4..7243225c88 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -635,7 +635,7 @@ public: const auto selection = selectionContext(); bool showMenu = false; - auto cleanup = qScopeGuard([&]{ menu()->setEnabled(showMenu); }); + const QScopeGuard cleanup([&]{ menu()->setEnabled(showMenu); }); if (!selection.isValid()) return; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 9cc9576bc6..4c15cce8d7 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -61,7 +61,7 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event) if (m_materialToDrag) { QMouseEvent *me = static_cast<QMouseEvent *>(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20 + if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20 && m_materialToDrag->isDownloaded()) { QByteArray data; QMimeData *mimeData = new QMimeData; @@ -76,7 +76,7 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event) } } else if (m_textureToDrag) { QMouseEvent *me = static_cast<QMouseEvent *>(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20 + if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20 && m_textureToDrag->isDownloaded()) { QMimeData *mimeData = new QMimeData; mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE, @@ -140,7 +140,7 @@ ContentLibraryWidget::ContentLibraryWidget() setStyleSheet(Theme::replaceCssColors( QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css")))); - m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F11), this); + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F11), this); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ContentLibraryWidget::reloadQmlSource); QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_CONTENTLIBRARY_TIME); diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp index 8082ba5c3d..819a52d215 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp @@ -341,14 +341,14 @@ void GraphicsView::keyPressEvent(QKeyEvent *event) void GraphicsView::mousePressEvent(QMouseEvent *event) { - if (m_playhead.mousePress(globalToScene(event->globalPos()))) { + if (m_playhead.mousePress(globalToScene(event->globalPosition().toPoint()))) { m_dragging = true; return; } Shortcut shortcut(event); if (shortcut == m_style.shortcuts.insertKeyframe) { - m_scene->insertKeyframe(globalToRaster(event->globalPos()).x()); + m_scene->insertKeyframe(globalToRaster(event->globalPosition().toPoint()).x()); return; } @@ -371,7 +371,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event) void GraphicsView::mouseMoveEvent(QMouseEvent *event) { - if (m_playhead.mouseMove(globalToScene(event->globalPos()), this)) + if (m_playhead.mouseMove(globalToScene(event->globalPosition().toPoint()), this)) return; QGraphicsView::mouseMoveEvent(event); diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp index 2f1a44d2f5..dfebbefc96 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp @@ -38,7 +38,7 @@ void Selector::mousePress(QMouseEvent *event, GraphicsView *view, GraphicsScene { m_shortcut = Shortcut(event); - QPointF click = view->globalToScene(event->globalPos()); + QPointF click = view->globalToScene(event->globalPosition().toPoint()); if (SelectableItem *sitem = scene->intersect(click)) { KeyframeItem *kitem = qobject_cast<KeyframeItem *>(sitem); @@ -54,8 +54,8 @@ void Selector::mousePress(QMouseEvent *event, GraphicsView *view, GraphicsScene applyPreSelection(scene); // Init selection tools. - m_mouseInit = event->globalPos(); - m_mouseCurr = event->globalPos(); + m_mouseInit = event->globalPosition().toPoint(); + m_mouseCurr = event->globalPosition().toPoint(); m_lasso = QPainterPath(click); m_lasso.closeSubpath(); @@ -72,17 +72,17 @@ void Selector::mouseMove(QMouseEvent *event, if (m_mouseInit.isNull()) return; - if ((event->globalPos() - m_mouseInit).manhattanLength() < QApplication::startDragDistance()) + if ((event->globalPosition().toPoint() - m_mouseInit).manhattanLength() < QApplication::startDragDistance()) return; - QPointF delta = event->globalPos() - m_mouseCurr; + QPointF delta = event->globalPosition().toPoint() - m_mouseCurr; if (m_shortcut == m_shortcuts.newSelection || m_shortcut == m_shortcuts.addToSelection || m_shortcut == m_shortcuts.removeFromSelection || m_shortcut == m_shortcuts.toggleSelection) { if (scene->hasActiveItem()) return; - select(m_tool, view->globalToScene(event->globalPos()), scene); + select(m_tool, view->globalToScene(event->globalPosition().toPoint()), scene); event->accept(); view->viewport()->update(); @@ -91,13 +91,13 @@ void Selector::mouseMove(QMouseEvent *event, double bigger = std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y(); double factor = bigger / view->width(); view->setZoomX(view->zoomX() + factor, m_mouseInit); - m_mouseCurr = event->globalPos(); + m_mouseCurr = event->globalPosition().toPoint(); event->accept(); } else if (m_shortcut == m_shortcuts.pan) { view->scrollContent(-delta.x(), -delta.y()); playhead.resize(view); - m_mouseCurr = event->globalPos(); + m_mouseCurr = event->globalPosition().toPoint(); } } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index f98284f61d..445372e24b 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -77,7 +77,7 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event) } else if (event->type() == QMouseEvent::MouseMove) { if (m_itemToDrag.isValid()) { QMouseEvent *me = static_cast<QMouseEvent *>(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { + if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 10) { ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>(); // For drag to be handled correctly, we must have the component properly imported // beforehand, so we import the module immediately when the drag starts diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index d0c5483bdd..e2bb82216b 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -95,7 +95,7 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) if (m_materialToDrag.isValid() || m_textureToDrag.isValid()) { QMouseEvent *me = static_cast<QMouseEvent *>(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { + if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20) { bool isMaterial = m_materialToDrag.isValid(); QMimeData *mimeData = new QMimeData; QByteArray internalId; diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index 96e0107290..55c587f3cb 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -59,7 +59,7 @@ MaterialEditorView::MaterialEditorView(ExternalDependenciesInterface &externalDe , m_stackedWidget(new QStackedWidget) , m_dynamicPropertiesModel(new DynamicPropertiesModel(true, this)) { - m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F7), m_stackedWidget); + m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F7), m_stackedWidget); connect(m_updateShortcut, &QShortcut::activated, this, &MaterialEditorView::reloadQml); m_ensureMatLibTimer.callOnTimeout([this] { @@ -149,7 +149,7 @@ void MaterialEditorView::changeValue(const QString &name) if (name == "state" && castedValue.toString() == "base state") castedValue = ""; - if (castedValue.type() == QVariant::Color) { + if (castedValue.typeId() == QVariant::Color) { QColor color = castedValue.value<QColor>(); QColor newColor = QColor(color.name()); newColor.setAlpha(color.alpha()); @@ -161,9 +161,9 @@ void MaterialEditorView::changeValue(const QString &name) } else { // QVector*D(0, 0, 0) detects as null variant though it is valid value if (castedValue.isValid() - && (!castedValue.isNull() || castedValue.type() == QVariant::Vector2D - || castedValue.type() == QVariant::Vector3D - || castedValue.type() == QVariant::Vector4D)) { + && (!castedValue.isNull() || castedValue.typeId() == QVariant::Vector2D + || castedValue.typeId() == QVariant::Vector3D + || castedValue.typeId() == QVariant::Vector4D)) { commitVariantValueToModel(propertyName, castedValue); } } diff --git a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp index e9fa8b4925..a955a81c0e 100644 --- a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp +++ b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp @@ -288,7 +288,7 @@ bool NameItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *, const QS if (event->type() == QEvent::MouseButtonRelease) { auto mouseEvent = static_cast<QMouseEvent *>(event); if (mouseEvent->button() == Qt::RightButton) { - openContextMenu(index, mouseEvent->globalPos()); + openContextMenu(index, mouseEvent->globalPosition().toPoint()); mouseEvent->accept(); return true; } diff --git a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp index 5ccab3165d..f2f5ba7706 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/colorpalettebackend.cpp @@ -340,14 +340,14 @@ void ColorPaletteBackend::releaseEyeDropper() bool ColorPaletteBackend::handleEyeDropperMouseMove(QMouseEvent *e) { - updateEyeDropperPosition(e->globalPos()); + updateEyeDropperPosition(e->globalPosition().toPoint()); return true; } bool ColorPaletteBackend::handleEyeDropperMouseButtonRelease(QMouseEvent *e) { if (e->button() == Qt::LeftButton) - emit currentColorChanged(grabScreenColor(e->globalPos())); + emit currentColorChanged(grabScreenColor(e->globalPosition().toPoint())); else emit eyeDropperRejected(); @@ -364,7 +364,7 @@ bool ColorPaletteBackend::handleEyeDropperKeyPress(QKeyEvent *e) } //else #endif //if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { - // emit currentColorChanged(grabScreenColor(e->globalPos())); + // emit currentColorChanged(grabScreenColor(e->globalPosition().toPoint())); // releaseEyeDropper(); //} e->accept(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp index 689753ff8b..977488a107 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp @@ -330,7 +330,7 @@ void DynamicPropertyRow::commitValue(const QVariant &value) return; m_lock = true; - auto unlock = qScopeGuard([this] { m_lock = false; }); + const QScopeGuard cleanup([this] { m_lock = false; }); auto view = propertiesModel->view(); RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__); @@ -371,7 +371,7 @@ void DynamicPropertyRow::commitExpression(const QString &expression) } m_lock = true; - auto unlock = qScopeGuard([this] { m_lock = false; }); + const QScopeGuard cleanup([this] { m_lock = false; }); auto view = propertiesModel->view(); RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__); @@ -426,7 +426,7 @@ void DynamicPropertyRow::resetValue() } } else { m_lock = true; - auto unlock = qScopeGuard([this] { m_lock = false; }); + const QScopeGuard cleanup([this] { m_lock = false; }); RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__); try { diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index a81560f566..67ee0ec15c 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp @@ -306,7 +306,7 @@ QString GradientModel::readGradientOrientation() const void GradientModel::setupModel() { m_locked = true; - auto guard = qScopeGuard([&] { m_locked = false; }); + const QScopeGuard cleanup([&] { m_locked = false; }); beginResetModel(); endResetModel(); @@ -329,7 +329,7 @@ void GradientModel::setAnchorBackend(const QVariant &anchorBackend) setupModel(); m_locked = true; - auto guard = qScopeGuard([&] { m_locked = false; }); + const QScopeGuard cleanup([&] { m_locked = false; }); emit anchorBackendChanged(); emit hasGradientChanged(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 5dff76453a..2cf47789e4 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -29,16 +29,17 @@ #include <utils/hostosinfo.h> #include <utils/qtcassert.h> +#include <QApplication> #include <QCoreApplication> +#include <QDebug> #include <QDir> -#include <QFileSystemWatcher> #include <QFileInfo> -#include <QDebug> +#include <QFileSystemWatcher> #include <QQuickItem> -#include <QTimer> -#include <QShortcut> -#include <QApplication> +#include <QScopeGuard> #include <QScopedPointer> +#include <QShortcut> +#include <QTimer> enum { debug = false @@ -71,9 +72,9 @@ PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache, m_qmlDir = PropertyEditorQmlBackend::propertyEditorResourcesPath(); if (Utils::HostOsInfo::isMacHost()) - m_updateShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_F3), m_stackedWidget); + m_updateShortcut = new QShortcut(QKeySequence(Qt::ALT | Qt::Key_F3), m_stackedWidget); else - m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F3), m_stackedWidget); + m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F3), m_stackedWidget); connect(m_updateShortcut, &QShortcut::activated, this, &PropertyEditorView::reloadQml); m_stackedWidget->setStyleSheet(Theme::replaceCssColors( @@ -201,7 +202,7 @@ void PropertyEditorView::changeValue(const QString &name) if (name == "state" && castedValue.toString() == "base state") castedValue = ""; - if (castedValue.type() == QVariant::Color) { + if (castedValue.typeId() == QVariant::Color) { QColor color = castedValue.value<QColor>(); QColor newColor = QColor(color.name()); newColor.setAlpha(color.alpha()); @@ -214,9 +215,9 @@ void PropertyEditorView::changeValue(const QString &name) } else { // QVector*D(0, 0, 0) detects as null variant though it is valid value if (castedValue.isValid() - && (!castedValue.isNull() || castedValue.type() == QVariant::Vector2D - || castedValue.type() == QVariant::Vector3D - || castedValue.type() == QVariant::Vector4D)) { + && (!castedValue.isNull() || castedValue.typeId() == QVariant::Vector2D + || castedValue.typeId() == QVariant::Vector3D + || castedValue.typeId() == QVariant::Vector4D)) { commitVariantValueToModel(propertyName, castedValue); } } @@ -241,10 +242,10 @@ void PropertyEditorView::changeExpression(const QString &propertyName) if (noValidSelection()) return; - QScopeGuard unlock([&](){ m_locked = false; }); + const QScopeGuard cleanup([&] { m_locked = false; }); m_locked = true; - executeInTransaction("PropertyEditorView::changeExpression", [this, name](){ + executeInTransaction("PropertyEditorView::changeExpression", [this, name] { PropertyName underscoreName(name); underscoreName.replace('.', '_'); diff --git a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp index b32e0e6926..9f22d5118a 100644 --- a/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp +++ b/src/plugins/qmldesigner/components/richtexteditor/richtexteditor.cpp @@ -13,7 +13,6 @@ #include <QFileDialog> #include <QPainter> #include <QPointer> -#include <QScopeGuard> #include <QStyle> #include <QStyleFactory> #include <QTextTable> @@ -332,7 +331,7 @@ void RichTextEditor::setupTextActions() fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); mergeFormatOnWordOrSelection(fmt); }); - m_actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B); + m_actionTextBold->setShortcut(Qt::CTRL | Qt::Key_B); QFont bold; bold.setBold(true); m_actionTextBold->setFont(bold); @@ -345,7 +344,7 @@ void RichTextEditor::setupTextActions() fmt.setFontItalic(checked); mergeFormatOnWordOrSelection(fmt); }); - m_actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I); + m_actionTextItalic->setShortcut(Qt::CTRL | Qt::Key_I); QFont italic; italic.setItalic(true); m_actionTextItalic->setFont(italic); @@ -358,7 +357,7 @@ void RichTextEditor::setupTextActions() fmt.setFontUnderline(checked); mergeFormatOnWordOrSelection(fmt); }); - m_actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U); + m_actionTextUnderline->setShortcut(Qt::CTRL | Qt::Key_U); QFont underline; underline.setUnderline(true); m_actionTextUnderline->setFont(underline); @@ -418,25 +417,25 @@ void RichTextEditor::setupAlignActions() { const QIcon leftIcon(getIcon(Theme::Icon::textAlignLeft)); m_actionAlignLeft = ui->toolBar->addAction(leftIcon, tr("&Left"), [this]() { ui->textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); }); - m_actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); + m_actionAlignLeft->setShortcut(Qt::CTRL | Qt::Key_L); m_actionAlignLeft->setCheckable(true); m_actionAlignLeft->setPriority(QAction::LowPriority); const QIcon centerIcon(getIcon(Theme::Icon::textAlignCenter)); m_actionAlignCenter = ui->toolBar->addAction(centerIcon, tr("C&enter"), [this]() { ui->textEdit->setAlignment(Qt::AlignHCenter); }); - m_actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E); + m_actionAlignCenter->setShortcut(Qt::CTRL | Qt::Key_E); m_actionAlignCenter->setCheckable(true); m_actionAlignCenter->setPriority(QAction::LowPriority); const QIcon rightIcon(getIcon(Theme::Icon::textAlignRight)); m_actionAlignRight = ui->toolBar->addAction(rightIcon, tr("&Right"), [this]() { ui->textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); }); - m_actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R); + m_actionAlignRight->setShortcut(Qt::CTRL | Qt::Key_R); m_actionAlignRight->setCheckable(true); m_actionAlignRight->setPriority(QAction::LowPriority); const QIcon fillIcon(getIcon(Theme::Icon::textFullJustification)); m_actionAlignJustify = ui->toolBar->addAction(fillIcon, tr("&Justify"), [this]() { ui->textEdit->setAlignment(Qt::AlignJustify); }); - m_actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); + m_actionAlignJustify->setShortcut(Qt::CTRL | Qt::Key_J); m_actionAlignJustify->setCheckable(true); m_actionAlignJustify->setPriority(QAction::LowPriority); @@ -550,7 +549,7 @@ void RichTextEditor::setupTableActions() m_actionTableSettings = ui->toolBar->addAction(tableIcon, tr("&Table Settings"), [this](bool checked) { ui->tableBar->setVisible(checked); }); - m_actionTableSettings->setShortcut(Qt::CTRL + Qt::Key_T); + m_actionTableSettings->setShortcut(Qt::CTRL | Qt::Key_T); m_actionTableSettings->setCheckable(true); m_actionTableSettings->setPriority(QAction::LowPriority); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 2b64138387..ea9bed7489 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -23,6 +23,7 @@ #include <QDebug> #include <QMessageBox> #include <QRegularExpression> +#include <QScopeGuard> #include <cmath> #include <memory> @@ -331,7 +332,7 @@ void StatesEditorView::setWhenCondition(int internalNodeId, const QString &condi return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -351,7 +352,7 @@ void StatesEditorView::resetWhenCondition(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -369,7 +370,7 @@ void StatesEditorView::setStateAsDefault(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -389,7 +390,7 @@ void StatesEditorView::resetDefaultState() return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); try { if (acitveStatesGroupNode().hasProperty("state")) @@ -411,7 +412,7 @@ void StatesEditorView::setAnnotation(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -438,7 +439,7 @@ void StatesEditorView::removeAnnotation(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -580,7 +581,7 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); for (const VariantProperty &property : propertyList) { if (property.name() == "name" diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp index 0501747d98..5c12772752 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp @@ -81,7 +81,7 @@ StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView, engine()->addImportPath(qmlSourcesPath()); engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); - m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F4), this); + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F4), this); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &StatesEditorWidget::reloadQmlSource); setResizeMode(QQuickWidget::SizeRootObjectToView); diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp index c263a51096..b35bd21477 100644 --- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp @@ -29,8 +29,10 @@ #include "stateseditorwidget.h" #include <QDebug> -#include <QRegularExpression> #include <QMessageBox> +#include <QRegularExpression> +#include <QScopeGuard> + #include <cmath> #include <memory> @@ -572,7 +574,7 @@ void StatesEditorView::setWhenCondition(int internalNodeId, const QString &condi return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -592,7 +594,7 @@ void StatesEditorView::resetWhenCondition(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -612,7 +614,7 @@ void StatesEditorView::setStateAsDefault(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -632,7 +634,7 @@ void StatesEditorView::resetDefaultState() return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); try { if (activeStatesGroupNode().hasProperty("state")) @@ -654,7 +656,7 @@ void StatesEditorView::setAnnotation(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -683,7 +685,7 @@ void StatesEditorView::removeAnnotation(int internalNodeId) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (hasModelNodeForInternalId(internalNodeId)) { QmlModelState state(modelNodeForInternalId(internalNodeId)); @@ -869,7 +871,7 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); for (const VariantProperty &property : propertyList) { if (property.name() == "name" @@ -948,7 +950,7 @@ void StatesEditorView::moveStates(int from, int to) return; m_block = true; - auto guard = qScopeGuard([&]() { m_block = false; }); + const QScopeGuard cleanup([&] { m_block = false; }); if (!activeStatesGroupNode().hasNodeListProperty("states")) return; diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp index f3fd945ae6..e07ba02ae0 100644 --- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp +++ b/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp @@ -106,7 +106,7 @@ StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView, engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); engine()->addImportPath(qmlSourcesPath() + "/imports"); - m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F10), this); + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F10), this); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &StatesEditorWidget::reloadQmlSource); setObjectName(Constants::OBJECT_NAME_STATES_EDITOR); diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp index a4132d0eb7..221de40509 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp @@ -57,7 +57,7 @@ TextureEditorView::TextureEditorView(AsynchronousImageCache &imageCache, , m_stackedWidget(new QStackedWidget) , m_dynamicPropertiesModel(new DynamicPropertiesModel(true, this)) { - m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F12), m_stackedWidget); + m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F12), m_stackedWidget); connect(m_updateShortcut, &QShortcut::activated, this, &TextureEditorView::reloadQml); m_ensureMatLibTimer.callOnTimeout([this] { @@ -153,9 +153,9 @@ void TextureEditorView::changeValue(const QString &name) } else { // QVector*D(0, 0, 0) detects as null variant though it is valid value if (castedValue.isValid() - && (!castedValue.isNull() || castedValue.type() == QVariant::Vector2D - || castedValue.type() == QVariant::Vector3D - || castedValue.type() == QVariant::Vector4D)) { + && (!castedValue.isNull() || castedValue.typeId() == QVariant::Vector2D + || castedValue.typeId() == QVariant::Vector3D + || castedValue.typeId() == QVariant::Vector4D)) { commitVariantValueToModel(propertyName, castedValue); } } diff --git a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp index 30d100f350..a9fa1ebd19 100644 --- a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp @@ -83,7 +83,7 @@ static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int * { int counter = 0; - while (counter < id.count()) { + while (counter < id.size()) { bool canConvertToInteger = false; int newNumber = id.right(counter + 1).toInt(&canConvertToInteger); if (canConvertToInteger) @@ -94,7 +94,7 @@ static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int * counter++; } - *baseId = id.left(id.count() - counter); + *baseId = id.left(id.size() - counter); } static void setupIdRenamingHash(const ModelNode &modelNode, QHash<QString, QString> &idRenamingHash, AbstractView *view) diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp index c283bf5b26..af9b6a2425 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp @@ -49,7 +49,7 @@ inline static QString doubleToString(const PropertyName &propertyName, double d) static QString unicodeEscape(const QString &stringValue) { - if (stringValue.count() == 1) { + if (stringValue.size() == 1) { ushort code = stringValue.at(0).unicode(); bool isUnicode = code <= 127; if (isUnicode) { @@ -289,7 +289,7 @@ QString QmlTextGenerator::escape(const QString &value) { QString result = value; - if (value.count() == 6 && value.startsWith("\\u")) //Do not dobule escape unicode chars + if (value.size() == 6 && value.startsWith("\\u")) //Do not dobule escape unicode chars return result; result.replace(QStringLiteral("\\"), QStringLiteral("\\\\")); diff --git a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp index 2a6b9f0fbf..90891cbc8c 100644 --- a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp @@ -65,7 +65,7 @@ static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int * { int counter = 0; - while (counter < id.count()) { + while (counter < id.size()) { bool canConvertToInteger = false; int newNumber = id.right(counter + 1).toInt(&canConvertToInteger); if (canConvertToInteger) @@ -76,7 +76,7 @@ static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int * counter++; } - *baseId = id.left(id.count() - counter); + *baseId = id.left(id.size() - counter); } void StylesheetMerger::syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, bool skipDuplicates) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index ac89c54acd..3b5df397ea 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -165,7 +165,7 @@ bool isHexDigit(ushort c) QString fixEscapedUnicodeChar(const QString &value) //convert "\u2939" { - if (value.count() == 6 && value.at(0) == QLatin1Char('\\') && value.at(1) == QLatin1Char('u') && + if (value.size() == 6 && value.at(0) == QLatin1Char('\\') && value.at(1) == QLatin1Char('u') && isHexDigit(value.at(2).unicode()) && isHexDigit(value.at(3).unicode()) && isHexDigit(value.at(4).unicode()) && isHexDigit(value.at(5).unicode())) { return convertUnicode(value.at(2).unicode(), value.at(3).unicode(), value.at(4).unicode(), value.at(5).unicode()); @@ -655,7 +655,7 @@ public: { QStringList astValueList = astValue.split(QStringLiteral(".")); - if (astValueList.count() == 2) { + if (astValueList.size() == 2) { //Check for global Qt enums if (astValueList.constFirst() == QStringLiteral("Qt") && globalQtEnums().contains(astValueList.constLast())) @@ -1022,7 +1022,7 @@ Document::MutablePtr TextToModelMerger::createParsedDocument(const QUrl &url, co bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceHandler) { QmlJS::ScopeChain::setSkipmakeComponentChain(true); - QScopeGuard unSkip([]() { QmlJS::ScopeChain::setSkipmakeComponentChain(false); }); + const QScopeGuard cleanup([] { QmlJS::ScopeChain::setSkipmakeComponentChain(false); }); qCInfo(rewriterBenchmark) << Q_FUNC_INFO; diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp index 079cc0a326..e52c0c7058 100644 --- a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp +++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp @@ -205,7 +205,7 @@ void PuppetEnvironmentBuilder::addImportPaths() const } if (m_availablePuppetType == PuppetType::Fallback) - importPaths.prepend(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)); + importPaths.prepend(QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)); constexpr auto pathSep = Utils::HostOsInfo::pathListSeparator(); m_environment.appendOrSet("QML2_IMPORT_PATH", importPaths.join(pathSep), pathSep); diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp index 4d327b5491..81b8a32a08 100644 --- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp +++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp @@ -335,12 +335,12 @@ void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPa { ::QmlProjectManager::QmlBuildSystem *buildSystem = getQmlBuildSystem(target); - const Utils::FilePath pojectDirectoryPath = buildSystem->canonicalProjectDir(); + const Utils::FilePath projectDirectoryPath = buildSystem->canonicalProjectDir(); const QStringList importPaths = buildSystem->importPaths(); - const QDir pojectDirectory(pojectDirectoryPath.toString()); + const QDir projectDirectory(projectDirectoryPath.toString()); for (const QString &importPath : importPaths) - qmldirPaths.push_back(QDir::cleanPath(pojectDirectory.absoluteFilePath(importPath)) + qmldirPaths.push_back(QDir::cleanPath(projectDirectory.absoluteFilePath(importPath)) + "/qmldir"); } diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 72b9c73869..3f7d3a5c11 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -23,7 +23,6 @@ #include <qmljs/parser/qmljsastfwd_p.h> #include <qmljs/qmljsutils.h> #include <texteditor/texteditor.h> -#include <utils/executeondestruction.h> #include <utils/qrcparser.h> #include <utils/tooltip/tooltip.h> @@ -31,6 +30,7 @@ #include <QList> #include <QRegularExpression> #include <QRegularExpressionMatch> +#include <QScopeGuard> using namespace Core; using namespace QmlJS; @@ -175,7 +175,7 @@ bool QmlJSHoverHandler::setQmlTypeHelp(const ScopeChain &scopeChain, const Docum void QmlJSHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); reset(); diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 914a4f7794..23834e82aa 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -201,9 +201,9 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject( projectInfo.qmllsPath = ModelManagerInterface::qmllsForBinPath(qtVersion->hostBinPath(), v); projectInfo.qtVersionString = qtVersion->qtVersionString(); } else if (!activeKit || !activeKit->value(QtSupport::SuppliesQtQuickImportPath::id(), false).toBool()) { - projectInfo.qtQmlPath = FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)); + projectInfo.qtQmlPath = FilePath::fromUserInput(QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)); projectInfo.qmllsPath = ModelManagerInterface::qmllsForBinPath( - FilePath::fromUserInput(QLibraryInfo::location(QLibraryInfo::BinariesPath)), QLibraryInfo::version()); + FilePath::fromUserInput(QLibraryInfo::path(QLibraryInfo::BinariesPath)), QLibraryInfo::version()); projectInfo.qtVersionString = QLatin1String(qVersion()); } diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp index d71836319c..4cf135f0be 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp @@ -177,7 +177,7 @@ void QmlProfilerDetailsRewriterTest::seedRewriter() QmlJS::PathsAndLanguages lPaths; lPaths.maybeInsert( - Utils::FilePath::fromString(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)), + Utils::FilePath::fromString(QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)), QmlJS::Dialect::Qml); QmlJS::ModelManagerInterface::importScan(QmlJS::ModelManagerInterface::workingCopy(), lPaths, m_modelManager, false); diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp index 4ccb9ad48f..20052b45e4 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp @@ -108,7 +108,7 @@ void QmlBuildSystem::updateDeploymentData() ProjectExplorer::DeploymentData deploymentData; for (const auto &file : m_projectItem->files()) { - deploymentData.addFile(file, targetFile(file).parentDir().toString()); + deploymentData.addFile(file, targetFile(file).parentDir().path()); } setDeploymentData(deploymentData); @@ -160,9 +160,7 @@ void QmlBuildSystem::triggerParsing() Utils::FilePath QmlBuildSystem::canonicalProjectDir() const { - return BuildSystem::target() - ->project() - ->projectFilePath() + return projectFilePath() .canonicalPath() .normalizedPathName() .parentDir(); @@ -188,10 +186,11 @@ void QmlBuildSystem::refresh(RefreshOptions options) QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->defaultProjectInfoForProject(project(), project()->files(Project::HiddenRccFolders)); - const QStringList searchPaths = makeAbsolute(canonicalProjectDir(), customImportPaths()); - for (const QString &searchPath : searchPaths) - projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath), + + for (const QString &searchPath : customImportPaths()) { + projectInfo.importPaths.maybeInsert(projectDirectory().pathAppended(searchPath), QmlJS::Dialect::Qml); + } modelManager->updateProjectInfo(projectInfo, project()); @@ -370,22 +369,23 @@ bool QmlBuildSystem::setMainUiFileInMainFile(const Utils::FilePath &newMainUiFil Utils::FilePath QmlBuildSystem::targetDirectory() const { - if (DeviceTypeKitAspect::deviceTypeId(kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) - return canonicalProjectDir(); - - return m_projectItem ? Utils::FilePath::fromString(m_projectItem->targetDirectory()) - : Utils::FilePath(); + Utils::FilePath result; + if (DeviceTypeKitAspect::deviceTypeId(kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + result = canonicalProjectDir(); + } else if (IDevice::ConstPtr device = DeviceKitAspect::device(kit())) { + if (m_projectItem) + result = device->filePath(m_projectItem->targetDirectory()); + } + return result; } Utils::FilePath QmlBuildSystem::targetFile(const Utils::FilePath &sourceFile) const { - const QDir sourceDir(m_projectItem ? m_projectItem->sourceDirectory().path() - : canonicalProjectDir().toString()); - const QDir targetDir(targetDirectory().toString()); - const QString relative = sourceDir.relativeFilePath(sourceFile.toString()); - return Utils::FilePath::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative))); + const Utils::FilePath sourceDir = m_projectItem ? m_projectItem->sourceDirectory() + : canonicalProjectDir(); + const Utils::FilePath relative = sourceFile.relativePathFrom(sourceDir); + return targetDirectory().resolvePath(relative); } - void QmlBuildSystem::setSupportedLanguages(QStringList languages) { m_projectItem->setSupportedLanguages(languages); @@ -396,18 +396,6 @@ void QmlBuildSystem::setPrimaryLanguage(QString language) m_projectItem->setPrimaryLanguage(language); } -QStringList QmlBuildSystem::makeAbsolute(const Utils::FilePath &path, - const QStringList &relativePaths) -{ - if (path.isEmpty()) - return relativePaths; - - const QDir baseDir(path.toString()); - return Utils::transform(relativePaths, [&baseDir](const QString &path) { - return QDir::cleanPath(baseDir.absoluteFilePath(path)); - }); -} - void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed) { if (m_blockFilesUpdate) { diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h index d275481f53..0a0e9cfcba 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h @@ -89,9 +89,6 @@ public: bool addFiles(const QStringList &filePaths); void refreshProjectFile(); - static Utils::FilePath activeMainFilePath(); - static QStringList makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths); - void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed); bool blockFilesUpdate() const; diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp index 5d328fd934..349c23a6cf 100644 --- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp @@ -210,7 +210,7 @@ void QmlMainFileAspect::changeCurrentFile(Core::IEditor *editor) bool QmlMainFileAspect::isQmlFilePresent() { bool qmlFileFound = false; - if (mainScriptSource() == FileInEditor) { + if (mainScriptSource() == FileInEditor && !mainScript().isEmpty()) { IDocument *document = EditorManager::currentDocument(); const MimeType mainScriptMimeType = mimeTypeForFile(mainScript()); if (document) { diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 756a0707d4..77db8b073f 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -91,11 +91,9 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id) // arguments from .qmlproject file const QmlBuildSystem *bs = qobject_cast<QmlBuildSystem *>(target->buildSystem()); - const QStringList importPaths = QmlBuildSystem::makeAbsolute(bs->targetDirectory(), - bs->customImportPaths()); - for (const QString &importPath : importPaths) { + for (const QString &importPath : bs->customImportPaths()) { cmd.addArg("-I"); - cmd.addArg(importPath); + cmd.addArg(bs->targetDirectory().pathAppended(importPath).path()); } for (const QString &fileSelector : bs->customFileSelectors()) { @@ -114,8 +112,9 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id) } const FilePath main = bs->targetFile(mainScript()); + if (!main.isEmpty()) - cmd.addArg(main.nativePath()); + cmd.addArg(main.path()); return cmd; }); diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp index d9eb88273e..856f8740a6 100644 --- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp +++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp @@ -228,7 +228,7 @@ GroupItem QnxDeployQtLibrariesDialogPrivate::chmodTree() QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); } - tree.setupRoot(chmodList); + tree.setRecipe(chmodList); }; return TaskTreeTask{setupChmodHandler}; } diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 179649c53b..d6f2efacef 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -2101,8 +2101,7 @@ static QByteArray scanQtBinaryForBuildString(const FilePath &library) static QStringList extractFieldsFromBuildString(const QByteArray &buildString) { - if (buildString.isEmpty() - || buildString.count() > 4096) + if (buildString.isEmpty() || buildString.size() > 4096) return QStringList(); const QRegularExpression buildStringMatcher("^Qt " @@ -2131,7 +2130,7 @@ static QStringList extractFieldsFromBuildString(const QByteArray &buildString) const QString endian = abiInfo.takeFirst(); QTC_ASSERT(endian.endsWith("_endian"), return QStringList()); - result.append(endian.left(endian.count() - 7)); // without the "_endian" + result.append(endian.left(endian.size() - 7)); // without the "_endian" result.append(abiInfo.takeFirst()); // pointer @@ -2161,7 +2160,7 @@ static QStringList extractFieldsFromBuildString(const QByteArray &buildString) static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &probableAbi) { QStringList buildStringData = extractFieldsFromBuildString(buildString); - if (buildStringData.count() != 9) + if (buildStringData.size() != 9) return probableAbi; const QString compiler = buildStringData.at(8); diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 7fab3fbbcc..18d6d7b9c8 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -9,6 +9,7 @@ #include "qttestparser.h" #include "qtversionmanager.h" +#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/task.h> #include <projectexplorer/toolchain.h> @@ -16,6 +17,7 @@ #include <utils/algorithm.h> #include <utils/buildablehelperlibrary.h> +#include <utils/guard.h> #include <utils/layoutbuilder.h> #include <utils/macroexpander.h> #include <utils/qtcassert.h> @@ -37,18 +39,20 @@ public: m_combo->setSizePolicy(QSizePolicy::Ignored, m_combo->sizePolicy().verticalPolicy()); m_combo->addItem(Tr::tr("None"), -1); - QList<int> versionIds = Utils::transform(QtVersionManager::versions(), &QtVersion::uniqueId); - versionsChanged(versionIds, QList<int>(), QList<int>()); - m_manageButton = createManageButton(Constants::QTVERSION_SETTINGS_PAGE_ID); refresh(); m_combo->setToolTip(ki->description()); - connect(m_combo, &QComboBox::currentIndexChanged, - this, &QtKitAspectWidget::currentWasChanged); - connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged, - this, &QtKitAspectWidget::versionsChanged); + connect(m_combo, &QComboBox::currentIndexChanged, this, [this] { + if (!m_ignoreChanges.isLocked()) + currentWasChanged(m_combo->currentIndex()); + }); + + connect(QtVersionManager::instance(), + &QtVersionManager::qtVersionsChanged, + this, + &QtKitAspectWidget::refresh); } ~QtKitAspectWidget() final @@ -69,6 +73,30 @@ private: void refresh() final { + const GuardLocker locker(m_ignoreChanges); + m_combo->clear(); + + IDeviceConstPtr device = BuildDeviceKitAspect::device(kit()); + const FilePath deviceRoot = device->rootPath(); + + const QtVersions versions = QtVersionManager::versions(); + + const QList<QtVersion *> same = Utils::filtered(versions, [device](QtVersion *qt) { + return qt->qmakeFilePath().isSameDevice(device->rootPath()); + }); + const QList<QtVersion *> other = Utils::filtered(versions, [device](QtVersion *qt) { + return !qt->qmakeFilePath().isSameDevice(device->rootPath()); + }); + + for (QtVersion *item : same) + m_combo->addItem(item->displayName(), item->uniqueId()); + + if (!same.isEmpty() && !other.isEmpty()) + m_combo->insertSeparator(m_combo->count()); + + for (QtVersion *item : other) + m_combo->addItem(item->displayName(), item->uniqueId()); + m_combo->setCurrentIndex(findQtVersion(QtKitAspect::qtVersionId(m_kit))); } @@ -82,27 +110,6 @@ private: return name; } - void versionsChanged(const QList<int> &added, const QList<int> &removed, const QList<int> &changed) - { - for (const int id : added) { - QtVersion *v = QtVersionManager::version(id); - QTC_CHECK(v); - QTC_CHECK(findQtVersion(id) < 0); - m_combo->addItem(itemNameFor(v), id); - } - for (const int id : removed) { - int pos = findQtVersion(id); - if (pos >= 0) // We do not include invalid Qt versions, so do not try to remove those. - m_combo->removeItem(pos); - } - for (const int id : changed) { - QtVersion *v = QtVersionManager::version(id); - int pos = findQtVersion(id); - QTC_CHECK(pos >= 0); - m_combo->setItemText(pos, itemNameFor(v)); - } - } - void currentWasChanged(int idx) { QtKitAspect::setQtVersionId(m_kit, m_combo->itemData(idx).toInt()); @@ -117,6 +124,7 @@ private: return -1; } + Guard m_ignoreChanges; QComboBox *m_combo; QWidget *m_manageButton; }; diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 92b439ea1a..fba6b8154f 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -969,20 +969,13 @@ void QtOptionsPageWidget::linkWithQt() bool askForRestart = false; QDialog dialog(Core::ICore::dialogParent()); dialog.setWindowTitle(title); - auto layout = new QVBoxLayout; - dialog.setLayout(layout); auto tipLabel = new QLabel(linkingPurposeText()); tipLabel->setWordWrap(true); - layout->addWidget(tipLabel); - auto pathLayout = new QHBoxLayout; - layout->addLayout(pathLayout); auto pathLabel = new QLabel(Tr::tr("Qt installation path:")); pathLabel->setToolTip( Tr::tr("Choose the Qt installation directory, or a directory that contains \"%1\".") .arg(settingsFile(""))); - pathLayout->addWidget(pathLabel); auto pathInput = new PathChooser; - pathLayout->addWidget(pathInput); pathInput->setExpectedKind(PathChooser::ExistingDirectory); pathInput->setBaseDirectory(FilePath::fromString(QCoreApplication::applicationDirPath())); pathInput->setPromptDialogTitle(title); @@ -997,8 +990,17 @@ void QtOptionsPageWidget::linkWithQt() pathInput->setFilePath(currentLink ? *currentLink : defaultQtInstallationPath()); pathInput->setAllowPathFromDevice(true); auto buttons = new QDialogButtonBox; - layout->addStretch(10); - layout->addWidget(buttons); + + using namespace Layouting; + Column { + tipLabel, + Form { + Tr::tr("Qt installation path:"), pathInput, br, + }, + st, + buttons, + }.attachTo(&dialog); + auto linkButton = buttons->addButton(Tr::tr("Link with Qt"), QDialogButtonBox::AcceptRole); connect(linkButton, &QPushButton::clicked, &dialog, &QDialog::accept); auto cancelButton = buttons->addButton(Tr::tr("Cancel"), QDialogButtonBox::RejectRole); @@ -1022,6 +1024,7 @@ void QtOptionsPageWidget::linkWithQt() connect(pathInput, &PathChooser::validChanged, linkButton, &QPushButton::setEnabled); linkButton->setEnabled(pathInput->isValid()); + dialog.setMinimumWidth(520); dialog.exec(); if (dialog.result() == QDialog::Accepted) { const std::optional<FilePath> settingsDir = settingsDirForQtDir(pathInput->baseDirectory(), diff --git a/src/plugins/qtsupport/qtparser.cpp b/src/plugins/qtsupport/qtparser.cpp index 25ab360482..2708b19c5e 100644 --- a/src/plugins/qtsupport/qtparser.cpp +++ b/src/plugins/qtsupport/qtparser.cpp @@ -89,6 +89,21 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils: scheduleTask(task, 1); return {Status::Done, linkSpecs}; } + + if (lne.startsWith(QLatin1String("Error:"))) { + constexpr int matchLength = 6; + CompileTask task(Task::TaskType::Error, line.mid(matchLength).trimmed()); + scheduleTask(task, 1); + return Status::Done; + } + + if (lne.startsWith(QLatin1String("Warning:"))) { + constexpr int matchLength = 8; + CompileTask task(Task::TaskType::Warning, line.mid(matchLength).trimmed()); + scheduleTask(task, 1); + return Status::Done; + } + return Status::NotHandled; } @@ -205,6 +220,15 @@ void QtSupportPlugin::testQtOutputParser_data() QLatin1String("dropping duplicate messages"), Utils::FilePath::fromUserInput(QLatin1String("/some/place/qtcreator_fr.qm")), -1)) << QString(); + QTest::newRow("qmlsc warning") // QTCREATORBUG-28720 + << QString::fromUtf8("Warning: Main.qml:4:1: Warnings occurred while importing module " + "\"QtQuick.Controls\": [import]\"") + << OutputParserTester::STDERR << QString() << QString() + << (Tasks() << CompileTask(Task::Warning, + QString::fromUtf8( + "Main.qml:4:1: Warnings occurred while importing module " + "\"QtQuick.Controls\": [import]\""))) + << QString(); } void QtSupportPlugin::testQtOutputParser() diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 714404ec5b..4449284ea6 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -184,7 +184,7 @@ GroupItem GenericDirectUploadStep::statTree(const TreeStorage<UploadStorage> &st QTC_ASSERT(file.isValid(), continue); statList.append(statTask(storagePtr, file, statEndHandler)); } - tree.setupRoot({statList}); + tree.setRecipe({statList}); }; return TaskTreeTask(setupHandler); } @@ -261,7 +261,7 @@ GroupItem GenericDirectUploadStep::chmodTree(const TreeStorage<UploadStorage> &s QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); } - tree.setupRoot({chmodList}); + tree.setRecipe({chmodList}); }; return TaskTreeTask(setupChmodHandler); } diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index cc44dddb3c..61939f2095 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -40,7 +40,6 @@ #include <QMutex> #include <QReadWriteLock> #include <QRegularExpression> -#include <QScopeGuard> #include <QTemporaryDir> #include <QThread> #include <QTimer> @@ -978,7 +977,6 @@ LinuxDevice::LinuxDevice() addDeviceAction({Tr::tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { device->openTerminal(Environment(), FilePath()); }}); - setQmlRunCommand(filePath("qml")); } void LinuxDevice::_setOsType(Utils::OsType osType) diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index 42f0467c94..a93fccba41 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -41,13 +41,13 @@ const char CustomCommandLineAspectId[] = "RemoteLinux.MakeInstall.CustomCommandL MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent, id) { - makeCommandAspect()->setVisible(false); - buildTargetsAspect()->setVisible(false); - userArgumentsAspect()->setVisible(false); - overrideMakeflagsAspect()->setVisible(false); - nonOverrideWarning()->setVisible(false); - jobCountAspect()->setVisible(false); - disabledForSubdirsAspect()->setVisible(false); + m_makeCommandAspect.setVisible(false); + m_buildTargetsAspect.setVisible(false); + m_userArgumentsAspect.setVisible(false); + m_overrideMakeflagsAspect.setVisible(false); + m_nonOverrideWarning.setVisible(false); + m_jobCountAspect.setVisible(false); + m_disabledForSubdirsAspect.setVisible(false); // FIXME: Hack, Part#1: If the build device is not local, start with a temp dir // inside the build dir. On Docker that's typically shared with the host. diff --git a/src/plugins/scxmleditor/common/sizegrip.cpp b/src/plugins/scxmleditor/common/sizegrip.cpp index 096fbc80a1..a2651fdb85 100644 --- a/src/plugins/scxmleditor/common/sizegrip.cpp +++ b/src/plugins/scxmleditor/common/sizegrip.cpp @@ -23,7 +23,7 @@ void SizeGrip::resizeEvent(QResizeEvent *e) void SizeGrip::mousePressEvent(QMouseEvent *e) { QWidget::mousePressEvent(e); - m_startPoint = e->globalPos(); + m_startPoint = e->globalPosition().toPoint(); m_startRect = parentWidget()->rect(); m_mouseDown = true; checkCursor(e->pos()); @@ -32,7 +32,7 @@ void SizeGrip::mousePressEvent(QMouseEvent *e) void SizeGrip::mouseMoveEvent(QMouseEvent *e) { if (m_mouseDown) { - QPoint p = e->globalPos() - m_startPoint; + QPoint p = e->globalPosition().toPoint() - m_startPoint; parentWidget()->resize(m_startRect.width() + p.x(), m_startRect.height() + p.y()); } else { checkCursor(e->pos()); diff --git a/src/plugins/scxmleditor/common/treeview.cpp b/src/plugins/scxmleditor/common/treeview.cpp index 0a0d76ee95..4e2b6aad6b 100644 --- a/src/plugins/scxmleditor/common/treeview.cpp +++ b/src/plugins/scxmleditor/common/treeview.cpp @@ -37,5 +37,5 @@ void TreeView::mousePressEvent(QMouseEvent *event) { QTreeView::mousePressEvent(event); if (event->button() == Qt::RightButton) - emit rightButtonClicked(currentIndex(), event->globalPos()); + emit rightButtonClicked(currentIndex(), event->globalPosition().toPoint()); } diff --git a/src/plugins/squish/squishrunnerprocess.cpp b/src/plugins/squish/squishrunnerprocess.cpp index ca1e330a7c..fbbf7a57b3 100644 --- a/src/plugins/squish/squishrunnerprocess.cpp +++ b/src/plugins/squish/squishrunnerprocess.cpp @@ -6,9 +6,9 @@ #include "squishtr.h" #include <debugger/breakhandler.h> -#include <utils/executeondestruction.h> #include <QLoggingCategory> +#include <QScopeGuard> Q_LOGGING_CATEGORY(runnerLOG, "qtc.squish.squishrunner", QtWarningMsg) @@ -153,7 +153,7 @@ void SquishRunnerProcess::onStdOutput(const QString &lineIn) void SquishRunnerProcess::handleMultiLineOutput(OutputMode mode) { - Utils::ExecuteOnDestruction atExit([this]{ + const QScopeGuard cleanup([this] { m_multiLineContent.clear(); m_context.clear(); }); diff --git a/src/plugins/terminal/CMakeLists.txt b/src/plugins/terminal/CMakeLists.txt index 69da526cdc..c7b64cc8ad 100644 --- a/src/plugins/terminal/CMakeLists.txt +++ b/src/plugins/terminal/CMakeLists.txt @@ -9,6 +9,7 @@ add_qtc_plugin(Terminal scrollback.cpp scrollback.h shellintegration.cpp shellintegration.h shellmodel.cpp shellmodel.h + shortcutmap.cpp shortcutmap.h terminal.qrc terminalconstants.h terminalicons.h diff --git a/src/plugins/terminal/images/keyboardlock.png b/src/plugins/terminal/images/keyboardlock.png Binary files differnew file mode 100644 index 0000000000..167f10a56b --- /dev/null +++ b/src/plugins/terminal/images/keyboardlock.png diff --git a/src/plugins/terminal/images/keyboardlock@2x.png b/src/plugins/terminal/images/keyboardlock@2x.png Binary files differnew file mode 100644 index 0000000000..a095404451 --- /dev/null +++ b/src/plugins/terminal/images/keyboardlock@2x.png diff --git a/src/plugins/terminal/shortcutmap.cpp b/src/plugins/terminal/shortcutmap.cpp new file mode 100644 index 0000000000..72023e808a --- /dev/null +++ b/src/plugins/terminal/shortcutmap.cpp @@ -0,0 +1,564 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +// COPIED FROM qshortcutmap.cpp + +#include "shortcutmap.h" + +#include <utils/qtcassert.h> + +#include <algorithm> + +#include <QGuiApplication> +#include <QKeyEvent> +#include <QLoggingCategory> +#include <QWindow> + +Q_LOGGING_CATEGORY(lcShortcutMap, "terminal.shortcutmap", QtWarningMsg) + +namespace Terminal::Internal { + +/* \internal + Entry data for ShortcutMap + Contains: + Keysequence for entry + Pointer to parent owning the sequence +*/ +struct ShortcutEntry +{ + ShortcutEntry() + : keyseq(0) + , context(Qt::WindowShortcut) + , enabled(false) + , autorepeat(1) + , id(0) + , owner(nullptr) + , contextMatcher(nullptr) + {} + + ShortcutEntry(const QKeySequence &k) + : keyseq(k) + , context(Qt::WindowShortcut) + , enabled(false) + , autorepeat(1) + , id(0) + , owner(nullptr) + , contextMatcher(nullptr) + {} + + ShortcutEntry(QObject *o, + const QKeySequence &k, + Qt::ShortcutContext c, + int i, + bool a, + ShortcutMap::ContextMatcher m) + : keyseq(k) + , context(c) + , enabled(true) + , autorepeat(a) + , id(i) + , owner(o) + , contextMatcher(m) + {} + + bool correctContext() const { return contextMatcher(owner, context); } + + bool operator<(const ShortcutEntry &f) const { return keyseq < f.keyseq; } + + QKeySequence keyseq; + Qt::ShortcutContext context; + bool enabled : 1; + bool autorepeat : 1; + signed int id; + QObject *owner; + ShortcutMap::ContextMatcher contextMatcher; +}; + +/* \internal + Private data for ShortcutMap +*/ +class ShortcutMapPrivate +{ + Q_DECLARE_PUBLIC(ShortcutMap) + +public: + ShortcutMapPrivate(ShortcutMap *parent) + : q_ptr(parent) + , currentId(0) + , ambigCount(0) + , currentState(QKeySequence::NoMatch) + { + identicals.reserve(10); + currentSequences.reserve(10); + } + ShortcutMap *q_ptr; // Private's parent + + QList<ShortcutEntry> sequences; // All sequences! + + int currentId; // Global shortcut ID number + int ambigCount; // Index of last enabled ambiguous dispatch + QKeySequence::SequenceMatch currentState; + QList<QKeySequence> currentSequences; // Sequence for the current state + QList<QKeySequence> newEntries; + QKeySequence prevSequence; // Sequence for the previous identical match + QList<const ShortcutEntry *> identicals; // Last identical matches +}; + +/*! \internal + ShortcutMap constructor. +*/ +ShortcutMap::ShortcutMap() + : d_ptr(new ShortcutMapPrivate(this)) +{ + resetState(); +} + +/*! \internal + ShortcutMap destructor. +*/ +ShortcutMap::~ShortcutMap() {} + +/*! \internal + Adds a shortcut to the global map. + Returns the id of the newly added shortcut. +*/ +int ShortcutMap::addShortcut(QObject *owner, + const QKeySequence &key, + Qt::ShortcutContext context, + ContextMatcher matcher) +{ + QTC_ASSERT(owner, return 0); // "ShortcutMap::addShortcut", "All shortcuts need an owner"); + QTC_ASSERT(!key.isEmpty(), + return 0); // "ShortcutMap::addShortcut", "Cannot add keyless shortcuts to map"); + Q_D(ShortcutMap); + + ShortcutEntry newEntry(owner, key, context, --(d->currentId), true, matcher); + const auto it = std::upper_bound(d->sequences.begin(), d->sequences.end(), newEntry); + d->sequences.insert(it, newEntry); // Insert sorted + qCDebug(lcShortcutMap).nospace() << "ShortcutMap::addShortcut(" << owner << ", " << key << ", " + << context << ") added shortcut with ID " << d->currentId; + return d->currentId; +} + +/*! \internal + Removes a shortcut from the global map. + If \a owner is \nullptr, all entries in the map with the key sequence specified + is removed. If \a key is null, all sequences for \a owner is removed from + the map. If \a id is 0, any identical \a key sequences owned by \a owner + are removed. + Returns the number of sequences removed from the map. +*/ + +int ShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key) +{ + Q_D(ShortcutMap); + int itemsRemoved = 0; + bool allOwners = (owner == nullptr); + bool allKeys = key.isEmpty(); + bool allIds = id == 0; + + auto debug = qScopeGuard([&]() { + qCDebug(lcShortcutMap).nospace() + << "ShortcutMap::removeShortcut(" << id << ", " << owner << ", " << key << ") removed " + << itemsRemoved << " shortcuts(s)"; + }); + + // Special case, remove everything + if (allOwners && allKeys && allIds) { + itemsRemoved = d->sequences.size(); + d->sequences.clear(); + return itemsRemoved; + } + + int i = d->sequences.size() - 1; + while (i >= 0) { + const ShortcutEntry &entry = d->sequences.at(i); + int entryId = entry.id; + if ((allOwners || entry.owner == owner) && (allIds || entry.id == id) + && (allKeys || entry.keyseq == key)) { + d->sequences.removeAt(i); + ++itemsRemoved; + } + if (id == entryId) + return itemsRemoved; + --i; + } + return itemsRemoved; +} + +/*! \internal + Resets the state of the statemachine to NoMatch +*/ +void ShortcutMap::resetState() +{ + Q_D(ShortcutMap); + d->currentState = QKeySequence::NoMatch; + clearSequence(d->currentSequences); +} + +/*! \internal + Returns the current state of the statemachine +*/ +QKeySequence::SequenceMatch ShortcutMap::state() +{ + Q_D(ShortcutMap); + return d->currentState; +} + +/*! \internal + Uses nextState(QKeyEvent) to check for a grabbed shortcut. + + If so, it is dispatched using dispatchEvent(). + + Returns true if a shortcut handled the event. + + \sa nextState, dispatchEvent +*/ +bool ShortcutMap::tryShortcut(QKeyEvent *e) +{ + Q_D(ShortcutMap); + + if (e->key() == Qt::Key_unknown) + return false; + + QKeySequence::SequenceMatch previousState = state(); + + switch (nextState(e)) { + case QKeySequence::NoMatch: + // In the case of going from a partial match to no match we handled the + // event, since we already stated that we did for the partial match. But + // in the normal case of directly going to no match we say we didn't. + return previousState == QKeySequence::PartialMatch; + case QKeySequence::PartialMatch: + // For a partial match we don't know yet if we will handle the shortcut + // but we need to say we did, so that we get the follow-up key-presses. + return true; + case QKeySequence::ExactMatch: { + // Save number of identical matches before dispatching + // to keep ShortcutMap and tryShortcut reentrant. + const int identicalMatches = d->identicals.size(); + resetState(); + dispatchEvent(e); + // If there are no identicals we've only found disabled shortcuts, and + // shouldn't say that we handled the event. + return identicalMatches > 0; + } + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + Q_UNREACHABLE_RETURN(false); +#else + return false; +#endif +} + +/*! \internal + Returns the next state of the statemachine + If return value is SequenceMatch::ExactMatch, then a call to matches() + will return a QObjects* list of all matching objects for the last matching + sequence. +*/ +QKeySequence::SequenceMatch ShortcutMap::nextState(QKeyEvent *e) +{ + Q_D(ShortcutMap); + // Modifiers can NOT be shortcuts... + if (e->key() >= Qt::Key_Shift && e->key() <= Qt::Key_ScrollLock) + return d->currentState; + + QKeySequence::SequenceMatch result = QKeySequence::NoMatch; + + // We start fresh each time.. + d->identicals.clear(); + + result = find(e); + if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) { + // Try to find a match without keypad modifier + result = find(e, Qt::KeypadModifier); + } + if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) { + // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab + if (e->key() == Qt::Key_Backtab) { + QKeyEvent pe = QKeyEvent(e->type(), Qt::Key_Tab, e->modifiers(), e->text()); + result = find(&pe); + } + } + + // Does the new state require us to clean up? + if (result == QKeySequence::NoMatch) + clearSequence(d->currentSequences); + d->currentState = result; + + qCDebug(lcShortcutMap).nospace() << "ShortcutMap::nextState(" << e << ") = " << result; + return result; +} + +/*! \internal + Determines if an enabled shortcut has a matching key sequence. +*/ +bool ShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const +{ + Q_D(const ShortcutMap); + ShortcutEntry entry(seq); // needed for searching + const auto itEnd = d->sequences.cend(); + auto it = std::lower_bound(d->sequences.cbegin(), itEnd, entry); + + for (; it != itEnd; ++it) { + if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch + && (*it).correctContext() && (*it).enabled) { + return true; + } + } + + //end of the loop: we didn't find anything + return false; +} + +/*! \internal + Returns the next state of the statemachine, based + on the new key event \a e. + Matches are appended to the list of identicals, + which can be access through matches(). + \sa matches +*/ +QKeySequence::SequenceMatch ShortcutMap::find(QKeyEvent *e, int ignoredModifiers) +{ + Q_D(ShortcutMap); + if (!d->sequences.size()) + return QKeySequence::NoMatch; + + createNewSequences(e, d->newEntries, ignoredModifiers); + qCDebug(lcShortcutMap) << "Possible shortcut key sequences:" << d->newEntries; + + // Should never happen + if (d->newEntries == d->currentSequences) { + QTC_ASSERT(e->key() != Qt::Key_unknown || e->text().size(), return QKeySequence::NoMatch); + //"ShortcutMap::find", + // "New sequence to find identical to previous"); + return QKeySequence::NoMatch; + } + + // Looking for new identicals, scrap old + d->identicals.clear(); + + bool partialFound = false; + bool identicalDisabledFound = false; + QList<QKeySequence> okEntries; + int result = QKeySequence::NoMatch; + for (int i = d->newEntries.size() - 1; i >= 0; --i) { + ShortcutEntry entry(d->newEntries.at(i)); // needed for searching + qCDebug(lcShortcutMap) << "- checking entry" << entry.id << entry.keyseq; + const auto itEnd = d->sequences.constEnd(); + auto it = std::lower_bound(d->sequences.constBegin(), itEnd, entry); + + int oneKSResult = QKeySequence::NoMatch; + int tempRes = QKeySequence::NoMatch; + do { + if (it == itEnd) + break; + tempRes = matches(entry.keyseq, (*it).keyseq); + oneKSResult = qMax(oneKSResult, tempRes); + qCDebug(lcShortcutMap) << " - matches returned" << tempRes << "for" << entry.keyseq + << it->keyseq << "- correctContext()?" << it->correctContext(); + if (tempRes != QKeySequence::NoMatch && (*it).correctContext()) { + if (tempRes == QKeySequence::ExactMatch) { + if ((*it).enabled) + d->identicals.append(&*it); + else + identicalDisabledFound = true; + } else if (tempRes == QKeySequence::PartialMatch) { + // We don't need partials, if we have identicals + if (d->identicals.size()) + break; + // We only care about enabled partials, so we don't consume + // key events when all partials are disabled! + partialFound |= (*it).enabled; + } + } + ++it; + // If we got a valid match on this run, there might still be more keys to check against, + // so we'll loop once more. If we get NoMatch, there's guaranteed no more possible + // matches in the shortcutmap. + } while (tempRes != QKeySequence::NoMatch); + + // If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the + // previous list. If this match is equal or better than the last match, append to the list + if (oneKSResult > result) { + okEntries.clear(); + qCDebug(lcShortcutMap) + << "Found better match (" << d->newEntries << "), clearing key sequence list"; + } + if (oneKSResult && oneKSResult >= result) { + okEntries << d->newEntries.at(i); + qCDebug(lcShortcutMap) << "Added ok key sequence" << d->newEntries; + } + } + + if (d->identicals.size()) { + result = QKeySequence::ExactMatch; + } else if (partialFound) { + result = QKeySequence::PartialMatch; + } else if (identicalDisabledFound) { + result = QKeySequence::ExactMatch; + } else { + clearSequence(d->currentSequences); + result = QKeySequence::NoMatch; + } + if (result != QKeySequence::NoMatch) + d->currentSequences = okEntries; + qCDebug(lcShortcutMap) << "Returning shortcut match == " << result; + return QKeySequence::SequenceMatch(result); +} + +/*! \internal + Clears \a seq to an empty QKeySequence. + Same as doing (the slower) + \snippet code/src_gui_kernel_shortcutmap.cpp 0 +*/ +void ShortcutMap::clearSequence(QList<QKeySequence> &ksl) +{ + ksl.clear(); + d_func()->newEntries.clear(); +} + +static QList<int> extractKeyFromEvent(QKeyEvent *e) +{ + QList<int> result; + if (e->key() && (e->key() != Qt::Key_unknown)) + result << e->keyCombination().toCombined(); + else if (!e->text().isEmpty()) + result << int(e->text().at(0).unicode() + (int) e->modifiers()); + return result; +} + +/*! \internal + Alters \a seq to the new sequence state, based on the + current sequence state, and the new key event \a e. +*/ +void ShortcutMap::createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, int ignoredModifiers) +{ + Q_D(ShortcutMap); + + QList<int> possibleKeys = extractKeyFromEvent(e); + qCDebug(lcShortcutMap) << "Creating new sequences for" << e + << "with ignoredModifiers=" << Qt::KeyboardModifiers(ignoredModifiers); + int pkTotal = possibleKeys.size(); + if (!pkTotal) + return; + + int ssActual = d->currentSequences.size(); + int ssTotal = qMax(1, ssActual); + // Resize to possible permutations of the current sequence(s). + ksl.resize(pkTotal * ssTotal); + + int index = ssActual ? d->currentSequences.at(0).count() : 0; + for (int pkNum = 0; pkNum < pkTotal; ++pkNum) { + for (int ssNum = 0; ssNum < ssTotal; ++ssNum) { + int i = (pkNum * ssTotal) + ssNum; + QKeySequence &curKsl = ksl[i]; + if (ssActual) { + const QKeySequence &curSeq = d->currentSequences.at(ssNum); + curKsl = QKeySequence(curSeq[0], curSeq[1], curSeq[2], curSeq[3]); + } else { + curKsl = QKeySequence(QKeyCombination::fromCombined(0)); + } + + std::array<QKeyCombination, 4> cur = {curKsl[0], curKsl[1], curKsl[2], curKsl[3]}; + cur[index] = QKeyCombination::fromCombined(possibleKeys.at(pkNum) & ~ignoredModifiers); + curKsl = QKeySequence(cur[0], cur[1], cur[2], cur[3]); + } + } +} + +/*! \internal + Basically the same function as QKeySequence::matches(const QKeySequence &seq) const + only that is specially handles Key_hyphen as Key_Minus, as people mix these up all the time and + they conceptually the same. +*/ +QKeySequence::SequenceMatch ShortcutMap::matches(const QKeySequence &seq1, + const QKeySequence &seq2) const +{ + uint userN = seq1.count(), seqN = seq2.count(); + + if (userN > seqN) + return QKeySequence::NoMatch; + + // If equal in length, we have a potential ExactMatch sequence, + // else we already know it can only be partial. + QKeySequence::SequenceMatch match = (userN == seqN ? QKeySequence::ExactMatch + : QKeySequence::PartialMatch); + + for (uint i = 0; i < userN; ++i) { + int userKey = seq1[i].toCombined(), sequenceKey = seq2[i].toCombined(); + if ((userKey & Qt::Key_unknown) == Qt::Key_hyphen) + userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus; + if ((sequenceKey & Qt::Key_unknown) == Qt::Key_hyphen) + sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus; + if (userKey != sequenceKey) + return QKeySequence::NoMatch; + } + return match; +} + +/*! \internal + Returns the list of ShortcutEntry's matching the last Identical state. +*/ +QList<const ShortcutEntry *> ShortcutMap::matches() const +{ + Q_D(const ShortcutMap); + return d->identicals; +} + +/*! \internal + Dispatches QShortcutEvents to widgets who grabbed the matched key sequence. +*/ +void ShortcutMap::dispatchEvent(QKeyEvent *e) +{ + Q_D(ShortcutMap); + if (!d->identicals.size()) + return; + + const QKeySequence &curKey = d->identicals.at(0)->keyseq; + if (d->prevSequence != curKey) { + d->ambigCount = 0; + d->prevSequence = curKey; + } + // Find next + const ShortcutEntry *current = nullptr, *next = nullptr; + int i = 0, enabledShortcuts = 0; + QList<const ShortcutEntry *> ambiguousShortcuts; + while (i < d->identicals.size()) { + current = d->identicals.at(i); + if (current->enabled || !next) { + ++enabledShortcuts; + if (lcShortcutMap().isDebugEnabled()) + ambiguousShortcuts.append(current); + if (enabledShortcuts > d->ambigCount + 1) + break; + next = current; + } + ++i; + } + d->ambigCount = (d->identicals.size() == i ? 0 : d->ambigCount + 1); + // Don't trigger shortcut if we're autorepeating and the shortcut is + // grabbed with not accepting autorepeats. + if (!next || (e->isAutoRepeat() && !next->autorepeat)) + return; + // Dispatch next enabled + if (lcShortcutMap().isDebugEnabled()) { + if (ambiguousShortcuts.size() > 1) { + qCDebug(lcShortcutMap) + << "The following shortcuts are about to be activated ambiguously:"; + for (const ShortcutEntry *entry : std::as_const(ambiguousShortcuts)) + qCDebug(lcShortcutMap).nospace() + << "- " << entry->keyseq << " (belonging to " << entry->owner << ")"; + } + + qCDebug(lcShortcutMap).nospace() + << "ShortcutMap::dispatchEvent(): Sending QShortcutEvent(\"" << next->keyseq.toString() + << "\", " << next->id << ", " << static_cast<bool>(enabledShortcuts > 1) + << ") to object(" << next->owner << ')'; + } + QShortcutEvent se(next->keyseq, next->id, enabledShortcuts > 1); + QCoreApplication::sendEvent(const_cast<QObject *>(next->owner), &se); +} + +} // namespace Terminal::Internal diff --git a/src/plugins/terminal/shortcutmap.h b/src/plugins/terminal/shortcutmap.h new file mode 100644 index 0000000000..e3de7e01bd --- /dev/null +++ b/src/plugins/terminal/shortcutmap.h @@ -0,0 +1,52 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +// COPIED FROM shortcutmap_p.h +#pragma once + +#include <QKeySequence> +#include <QObject> + +class QKeyEvent; +class QObject; + +namespace Terminal::Internal { + +struct ShortcutEntry; +class ShortcutMapPrivate; + +class ShortcutMap +{ + Q_DECLARE_PRIVATE(ShortcutMap) +public: + ShortcutMap(); + ~ShortcutMap(); + + typedef bool (*ContextMatcher)(QObject *object, Qt::ShortcutContext context); + + int addShortcut(QObject *owner, + const QKeySequence &key, + Qt::ShortcutContext context, + ContextMatcher matcher); + int removeShortcut(int id, QObject *owner, const QKeySequence &key = QKeySequence()); + + QKeySequence::SequenceMatch state(); + + bool tryShortcut(QKeyEvent *e); + bool hasShortcutForKeySequence(const QKeySequence &seq) const; + +private: + void resetState(); + QKeySequence::SequenceMatch nextState(QKeyEvent *e); + void dispatchEvent(QKeyEvent *e); + + QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0); + QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const; + QList<const ShortcutEntry *> matches() const; + void createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, int ignoredModifiers); + void clearSequence(QList<QKeySequence> &ksl); + + QScopedPointer<ShortcutMapPrivate> d_ptr; +}; + +} // namespace Terminal::Internal diff --git a/src/plugins/terminal/terminal.qbs b/src/plugins/terminal/terminal.qbs index 300c1acf19..f9b3409beb 100644 --- a/src/plugins/terminal/terminal.qbs +++ b/src/plugins/terminal/terminal.qbs @@ -21,6 +21,8 @@ QtcPlugin { "shellmodel.h", "shellintegration.cpp", "shellintegration.h", + "shortcutmap.cpp", + "shortcutmap.h", "terminal.qrc", "terminalconstants.h", "terminalicons.h", diff --git a/src/plugins/terminal/terminal.qrc b/src/plugins/terminal/terminal.qrc index 63c28169df..60981bc2f9 100644 --- a/src/plugins/terminal/terminal.qrc +++ b/src/plugins/terminal/terminal.qrc @@ -1,5 +1,7 @@ <RCC> <qresource prefix="/terminal"> + <file>images/keyboardlock.png</file> + <file>images/keyboardlock@2x.png</file> <file>images/settingscategory_terminal.png</file> <file>images/settingscategory_terminal@2x.png</file> <file>images/terminal.png</file> diff --git a/src/plugins/terminal/terminalicons.h b/src/plugins/terminal/terminalicons.h index ca503f50f9..911bf90486 100644 --- a/src/plugins/terminal/terminalicons.h +++ b/src/plugins/terminal/terminalicons.h @@ -15,4 +15,11 @@ static Utils::Icon CLOSE_TERMINAL_ICON( {{":/terminal/images/terminal.png", Utils::Theme::IconsBaseColor}, {":/utils/images/iconoverlay_close_small.png", Utils::Theme::IconsStopToolBarColor}}); +static Utils::Icon LOCK_KEYBOARD_ICON( + {{":/terminal/images/keyboardlock.png", Utils::Theme::IconsBaseColor}, + {":/codemodel/images/private.png", Utils::Theme::IconsBaseColor}}); + +static Utils::Icon UNLOCK_KEYBOARD_ICON( + {{":/terminal/images/keyboardlock.png", Utils::Theme::IconsBaseColor}}); + } // namespace Terminal diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index 965e3ba651..71e979282b 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -4,6 +4,7 @@ #include "terminalpane.h" #include "shellmodel.h" +#include "shortcutmap.h" #include "terminalconstants.h" #include "terminalicons.h" #include "terminalsettings.h" @@ -36,9 +37,9 @@ using namespace Core; TerminalPane::TerminalPane(QObject *parent) : IOutputPane(parent) - , m_context("Terminal.Pane", Core::Constants::C_GLOBAL_CUTOFF) + , m_selfContext("Terminal.Pane") { - setupContext(m_context, &m_tabWidget); + setupContext(m_selfContext, &m_tabWidget); setZoomButtonsEnabled(true); connect(this, &IOutputPane::zoomInRequested, this, [this] { @@ -52,6 +53,9 @@ TerminalPane::TerminalPane(QObject *parent) initActions(); + m_lockKeyboardButton = new QToolButton(); + m_lockKeyboardButton->setDefaultAction(&lockKeyboard); + m_newTerminalButton = new QToolButton(); m_newTerminalButton->setDefaultAction(&newTerminal); @@ -75,10 +79,10 @@ TerminalPane::TerminalPane(QObject *parent) .toString(QKeySequence::NativeText); if (TerminalSettings::instance().sendEscapeToTerminal.value()) { m_escSettingButton->setText(escKey); - m_escSettingButton->setToolTip(Tr::tr("Sending ESC to terminal instead of Qt Creator")); + m_escSettingButton->setToolTip(Tr::tr("Sending Esc to terminal instead of Qt Creator")); } else { m_escSettingButton->setText(shiftEsc); - m_escSettingButton->setToolTip(Tr::tr("Press %1 to send ESC to terminal").arg(shiftEsc)); + m_escSettingButton->setToolTip(Tr::tr("Press %1 to send Esc to terminal").arg(shiftEsc)); } }; @@ -110,8 +114,6 @@ static std::optional<FilePath> startupProjectDirectory() void TerminalPane::openTerminal(const OpenTerminalParameters ¶meters) { OpenTerminalParameters parametersCopy{parameters}; - if (!m_isVisible) - emit showPage(IOutputPane::ModeSwitch); if (!parametersCopy.workingDirectory) { const std::optional<FilePath> projectDir = startupProjectDirectory(); @@ -124,9 +126,20 @@ void TerminalPane::openTerminal(const OpenTerminalParameters ¶meters) } const auto terminalWidget = new TerminalWidget(&m_tabWidget, parametersCopy); + + using namespace Constants; + terminalWidget->unlockGlobalAction("Coreplugin.OutputPane.minmax"); + terminalWidget->unlockGlobalAction(Core::Constants::LOCATE); + terminalWidget->unlockGlobalAction(NEWTERMINAL); + terminalWidget->unlockGlobalAction(NEXTTERMINAL); + terminalWidget->unlockGlobalAction(PREVTERMINAL); + m_tabWidget.setCurrentIndex(m_tabWidget.addTab(terminalWidget, Tr::tr("Terminal"))); setupTerminalWidget(terminalWidget); + if (!m_isVisible) + emit showPage(IOutputPane::ModeSwitch); + m_tabWidget.currentWidget()->setFocus(); emit navigateStateUpdate(); @@ -134,11 +147,14 @@ void TerminalPane::openTerminal(const OpenTerminalParameters ¶meters) void TerminalPane::addTerminal(TerminalWidget *terminal, const QString &title) { - if (!m_isVisible) - emit showPage(IOutputPane::ModeSwitch); m_tabWidget.setCurrentIndex(m_tabWidget.addTab(terminal, title)); setupTerminalWidget(terminal); + if (!m_isVisible) + emit showPage(IOutputPane::ModeSwitch); + + terminal->setFocus(); + emit navigateStateUpdate(); } @@ -229,6 +245,23 @@ void TerminalPane::initActions() { createShellMenu(); + lockKeyboard.setCheckable(true); + lockKeyboard.setChecked(TerminalSettings::instance().lockKeyboard()); + + auto updateLockKeyboard = [this](bool locked) { + TerminalSettings::instance().lockKeyboard.setValue(locked); + if (locked) { + lockKeyboard.setIcon(LOCK_KEYBOARD_ICON.icon()); + lockKeyboard.setToolTip(Tr::tr("Keyboard shortcuts will be sent to the Terminal")); + } else { + lockKeyboard.setIcon(UNLOCK_KEYBOARD_ICON.icon()); + lockKeyboard.setToolTip(Tr::tr("Keyboard shortcuts will be sent to Qt Creator")); + } + }; + + updateLockKeyboard(TerminalSettings::instance().lockKeyboard()); + connect(&lockKeyboard, &QAction::toggled, this, updateLockKeyboard); + newTerminal.setText(Tr::tr("New Terminal")); newTerminal.setIcon(NEW_TERMINAL_ICON.icon()); newTerminal.setToolTip(Tr::tr("Create a new Terminal.")); @@ -242,25 +275,22 @@ void TerminalPane::initActions() using namespace Constants; - ActionManager::registerAction(&newTerminal, NEWTERMINAL, m_context) - ->setDefaultKeySequences({QKeySequence( - HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") : QLatin1String("Ctrl+Shift+T"))}); + Command *cmd = ActionManager::registerAction(&newTerminal, NEWTERMINAL, m_selfContext); + cmd->setDefaultKeySequences({QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") : QLatin1String("Ctrl+Shift+T"))}); - ActionManager::registerAction(&nextTerminal, NEXTTERMINAL, m_context) + ActionManager::registerAction(&nextTerminal, NEXTTERMINAL, m_selfContext) ->setDefaultKeySequences( {QKeySequence("Alt+Tab"), QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+[") : QLatin1String("Ctrl+PgUp"))}); - ActionManager::registerAction(&prevTerminal, PREVTERMINAL, m_context) + ActionManager::registerAction(&prevTerminal, PREVTERMINAL, m_selfContext) ->setDefaultKeySequences( {QKeySequence("Alt+Shift+Tab"), QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+]") : QLatin1String("Ctrl+PgDown"))}); - m_minMax = TerminalWidget::unlockGlobalAction("Coreplugin.OutputPane.minmax", m_context); - m_locate = TerminalWidget::unlockGlobalAction(Core::Constants::LOCATE, m_context); - connect(&newTerminal, &QAction::triggered, this, [this] { openTerminal({}); }); connect(&closeTerminal, &QAction::triggered, this, [this] { removeTab(m_tabWidget.currentIndex()); @@ -303,10 +333,11 @@ void TerminalPane::createShellMenu() QList<QWidget *> TerminalPane::toolBarWidgets() const { QList<QWidget *> widgets = IOutputPane::toolBarWidgets(); + widgets.prepend(m_newTerminalButton); widgets.prepend(m_closeTerminalButton); - return widgets << m_openSettingsButton << m_escSettingButton; + return widgets << m_openSettingsButton << m_lockKeyboardButton << m_escSettingButton; } QString TerminalPane::displayName() const diff --git a/src/plugins/terminal/terminalpane.h b/src/plugins/terminal/terminalpane.h index 21f15168f2..8a24e1cf30 100644 --- a/src/plugins/terminal/terminalpane.h +++ b/src/plugins/terminal/terminalpane.h @@ -62,18 +62,17 @@ private: QToolButton *m_closeTerminalButton{nullptr}; QToolButton *m_openSettingsButton{nullptr}; QToolButton *m_escSettingButton{nullptr}; - - UnlockedGlobalAction m_minMax; - UnlockedGlobalAction m_locate; + QToolButton *m_lockKeyboardButton{nullptr}; QAction newTerminal; QAction nextTerminal; QAction prevTerminal; QAction closeTerminal; + QAction lockKeyboard; QMenu m_shellMenu; - Core::Context m_context; + Core::Context m_selfContext; bool m_widgetInitialized{false}; bool m_isVisible{false}; diff --git a/src/plugins/terminal/terminalsettings.h b/src/plugins/terminal/terminalsettings.h index 4550bbce2a..1c07f9ab03 100644 --- a/src/plugins/terminal/terminalsettings.h +++ b/src/plugins/terminal/terminalsettings.h @@ -32,6 +32,7 @@ public: Utils::BoolAspect sendEscapeToTerminal{this}; Utils::BoolAspect audibleBell{this}; + Utils::BoolAspect lockKeyboard{this}; }; } // Terminal diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 12a0521857..86171f1882 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -252,28 +252,74 @@ void TerminalWidget::setupColors() update(); } -void TerminalWidget::setupActions() +static bool contextMatcher(QObject *, Qt::ShortcutContext) { - ActionManager::registerAction(&m_copy, Constants::COPY, m_context); - ActionManager::registerAction(&m_paste, Constants::PASTE, m_context); - ActionManager::registerAction(&m_close, Core::Constants::CLOSE, m_context); - ActionManager::registerAction(&m_clearTerminal, Constants::CLEAR_TERMINAL, m_context); - ActionManager::registerAction(&m_clearSelection, Constants::CLEARSELECTION, m_context); - ActionManager::registerAction(&m_moveCursorWordLeft, Constants::MOVECURSORWORDLEFT, m_context); - ActionManager::registerAction(&m_moveCursorWordRight, Constants::MOVECURSORWORDRIGHT, m_context); + return true; +} - connect(&m_copy, &QAction::triggered, this, &TerminalWidget::copyToClipboard); - connect(&m_paste, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); - connect(&m_close, &QAction::triggered, this, &TerminalWidget::closeTerminal); - connect(&m_clearTerminal, &QAction::triggered, this, &TerminalWidget::clearContents); - connect(&m_clearSelection, &QAction::triggered, this, &TerminalWidget::clearSelection); - connect(&m_moveCursorWordLeft, &QAction::triggered, this, &TerminalWidget::moveCursorWordLeft); - connect(&m_moveCursorWordRight, &QAction::triggered, this, &TerminalWidget::moveCursorWordRight); +void TerminalWidget::registerShortcut(Command *cmd) +{ + QTC_ASSERT(cmd, return); + auto addShortCut = [this, cmd] { + for (const auto &keySequence : cmd->keySequences()) { + if (!keySequence.isEmpty()) { + m_shortcutMap.addShortcut(cmd->action(), + keySequence, + Qt::ShortcutContext::WindowShortcut, + contextMatcher); + } + } + }; + auto removeShortCut = [this, cmd] { m_shortcutMap.removeShortcut(0, cmd->action()); }; + addShortCut(); - m_exit = unlockGlobalAction(Core::Constants::EXIT, m_context); - m_options = unlockGlobalAction(Core::Constants::OPTIONS, m_context); - m_settings = unlockGlobalAction("Preferences.Terminal.General", m_context); - m_findInDocument = unlockGlobalAction(Core::Constants::FIND_IN_DOCUMENT, m_context); + connect(cmd, &Command::keySequenceChanged, this, [addShortCut, removeShortCut]() { + removeShortCut(); + addShortCut(); + }); +} + +RegisteredAction TerminalWidget::registerAction(Id commandId, const Context &context) +{ + QAction *action = new QAction; + Command *cmd = ActionManager::registerAction(action, commandId, context); + + registerShortcut(cmd); + + return RegisteredAction(action, [commandId](QAction *a) { + ActionManager::unregisterAction(a, commandId); + delete a; + }); +} + +void TerminalWidget::setupActions() +{ + m_copy = registerAction(Constants::COPY, m_context); + m_paste = registerAction(Constants::PASTE, m_context); + m_close = registerAction(Core::Constants::CLOSE, m_context); + m_clearTerminal = registerAction(Constants::CLEAR_TERMINAL, m_context); + m_clearSelection = registerAction(Constants::CLEARSELECTION, m_context); + m_moveCursorWordLeft = registerAction(Constants::MOVECURSORWORDLEFT, m_context); + m_moveCursorWordRight = registerAction(Constants::MOVECURSORWORDRIGHT, m_context); + + connect(m_copy.get(), &QAction::triggered, this, &TerminalWidget::copyToClipboard); + connect(m_paste.get(), &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); + connect(m_close.get(), &QAction::triggered, this, &TerminalWidget::closeTerminal); + connect(m_clearTerminal.get(), &QAction::triggered, this, &TerminalWidget::clearContents); + connect(m_clearSelection.get(), &QAction::triggered, this, &TerminalWidget::clearSelection); + connect(m_moveCursorWordLeft.get(), + &QAction::triggered, + this, + &TerminalWidget::moveCursorWordLeft); + connect(m_moveCursorWordRight.get(), + &QAction::triggered, + this, + &TerminalWidget::moveCursorWordRight); + + unlockGlobalAction(Core::Constants::EXIT); + unlockGlobalAction(Core::Constants::OPTIONS); + unlockGlobalAction("Preferences.Terminal.General"); + unlockGlobalAction(Core::Constants::FIND_IN_DOCUMENT); } void TerminalWidget::closeTerminal() @@ -401,7 +447,7 @@ void TerminalWidget::updateCopyState() if (!hasFocus()) return; - m_copy.setEnabled(m_selection.has_value()); + m_copy->setEnabled(m_selection.has_value()); } void TerminalWidget::setFont(const QFont &font) @@ -928,6 +974,9 @@ void TerminalWidget::paintCursor(QPainter &p) const auto cursor = m_surface->cursor(); + if (!m_preEditString.isEmpty()) + cursor.shape = Internal::Cursor::Shape::Underline; + const bool blinkState = !cursor.blink || m_cursorBlinkState || !TerminalSettings::instance().allowBlinkingCursor.value(); @@ -973,9 +1022,13 @@ void TerminalWidget::paintPreedit(QPainter &p) const QRectF rect = QRectF(gridToGlobal(cursor.position), gridToGlobal({cursor.position.x(), cursor.position.y()}, true, true)); - p.fillRect(rect, QColor::fromRgb(0, 0, 0)); - p.setPen(Qt::white); - p.drawText(rect, m_preEditString); + rect.setWidth(viewport()->width() - rect.x()); + + p.setPen(toQColor(ColorIndex::Foreground)); + QFont f = font(); + f.setUnderline(true); + p.setFont(f); + p.drawText(rect, Qt::TextDontClip | Qt::TextWrapAnywhere, m_preEditString); } } @@ -1095,7 +1148,7 @@ void TerminalWidget::keyPressEvent(QKeyEvent *event) } if (m_selection) - m_clearSelection.trigger(); + m_clearSelection->trigger(); else { QAction *returnAction = ActionManager::command(Core::Constants::S_RETURNTOEDITOR) ->actionForContext(Core::Constants::C_GLOBAL); @@ -1286,7 +1339,7 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event) contextMenu->addSeparator(); contextMenu->addAction(configureAction); - contextMenu->popup(event->globalPos()); + contextMenu->popup(event->globalPosition().toPoint()); } else if (m_selection) { copyToClipboard(); setSelection(std::nullopt); @@ -1489,6 +1542,11 @@ void TerminalWidget::showEvent(QShowEvent *event) bool TerminalWidget::event(QEvent *event) { + if (TerminalSettings::instance().lockKeyboard() && event->type() == QEvent::ShortcutOverride) { + event->accept(); + return true; + } + if (event->type() == QEvent::Paint) { QPainter p(this); p.fillRect(QRect(QPoint(0, 0), size()), m_currentColors[ColorIndex::Background]); @@ -1496,12 +1554,16 @@ bool TerminalWidget::event(QEvent *event) } if (event->type() == QEvent::KeyPress) { - QKeyEvent *k = (QKeyEvent *) event; + auto k = static_cast<QKeyEvent *>(event); + + if (TerminalSettings::instance().lockKeyboard() && m_shortcutMap.tryShortcut(k)) + return true; + keyPressEvent(k); return true; } if (event->type() == QEvent::KeyRelease) { - QKeyEvent *k = (QKeyEvent *) event; + auto k = static_cast<QKeyEvent *>(event); keyReleaseEvent(k); return true; } @@ -1548,21 +1610,11 @@ void TerminalWidget::initActions() ActionManager::registerAction(&clearTerminal, Constants::CLEAR_TERMINAL, context); } -UnlockedGlobalAction TerminalWidget::unlockGlobalAction(const Utils::Id &commandId, - const Context &context) +void TerminalWidget::unlockGlobalAction(const Utils::Id &commandId) { - QAction *srcAction = ActionManager::command(commandId)->actionForContext( - Core::Constants::C_GLOBAL); - - ProxyAction *proxy = ProxyAction::proxyActionWithIcon(srcAction, srcAction->icon()); - ActionManager::registerAction(proxy, commandId, context); - - UnlockedGlobalAction registeredAction(proxy, [commandId](QAction *a) { - ActionManager::unregisterAction(a, commandId); - delete a; - }); - - return registeredAction; + Command *cmd = ActionManager::command(commandId); + QTC_ASSERT(cmd, return); + registerShortcut(cmd); } } // namespace Terminal diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index 4b82e4355a..11cd9335cc 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -3,12 +3,14 @@ #pragma once +#include "shortcutmap.h" #include "terminalsearch.h" #include "terminalsurface.h" #include <aggregation/aggregate.h> #include <coreplugin/icontext.h> +#include <coreplugin/actionmanager/command.h> #include <utils/link.h> #include <utils/process.h> @@ -24,7 +26,7 @@ namespace Terminal { -using UnlockedGlobalAction = std::unique_ptr<QAction, std::function<void(QAction *)>>; +using RegisteredAction = std::unique_ptr<QAction, std::function<void(QAction *)>>; class TerminalWidget : public QAbstractScrollArea { @@ -90,8 +92,7 @@ public: static void initActions(); - [[nodiscard]] static UnlockedGlobalAction unlockGlobalAction(const Utils::Id &commandId, - const Core::Context &context); + void unlockGlobalAction(const Utils::Id &commandId); signals: void started(qint64 pid); @@ -188,6 +189,9 @@ protected: void updateCopyState(); + RegisteredAction registerAction(Utils::Id commandId, const Core::Context &context); + void registerShortcut(Core::Command *command); + private: Core::Context m_context; std::unique_ptr<Utils::Process> m_process; @@ -239,18 +243,15 @@ private: Aggregation::Aggregate *m_aggregate{nullptr}; SearchHit m_lastSelectedHit{}; - QAction m_copy; - QAction m_paste; - QAction m_clearSelection; - QAction m_clearTerminal; - QAction m_moveCursorWordLeft; - QAction m_moveCursorWordRight; - QAction m_close; - - UnlockedGlobalAction m_findInDocument; - UnlockedGlobalAction m_exit; - UnlockedGlobalAction m_options; - UnlockedGlobalAction m_settings; + RegisteredAction m_copy; + RegisteredAction m_paste; + RegisteredAction m_clearSelection; + RegisteredAction m_clearTerminal; + RegisteredAction m_moveCursorWordLeft; + RegisteredAction m_moveCursorWordRight; + RegisteredAction m_close; + + Internal::ShortcutMap m_shortcutMap; }; } // namespace Terminal diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt index 048cd40b1d..2a99947b93 100644 --- a/src/plugins/texteditor/CMakeLists.txt +++ b/src/plugins/texteditor/CMakeLists.txt @@ -115,5 +115,6 @@ extend_qtc_plugin(TextEditor CONDITION WITH_TESTS SOURCES codeassist/codeassist_test.cpp codeassist/codeassist_test.h + highlighter_test.cpp highlighter_test.h texteditor_test.cpp ) diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 203ecc36e2..45949fb886 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -121,7 +121,7 @@ void BaseHoverHandler::process(TextEditorWidget *widget, int pos, ReportPriority void BaseHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - const auto cleanup = qScopeGuard([this, report] { report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); QString tooltip = editorWidget->extraSelectionTooltip(pos); if (!tooltip.isEmpty()) diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 0da6571da8..0bdf34efab 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -158,7 +158,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, bool isUpdate) { // make sure to cleanup old proposals if we cannot find a new assistant - auto cleanup = qScopeGuard([this] { destroyContext(); }); + QScopeGuard cleanup([this] { destroyContext(); }); if (isWaitingForProposal()) cancelCurrentRequest(); diff --git a/src/plugins/texteditor/colorpreviewhoverhandler.cpp b/src/plugins/texteditor/colorpreviewhoverhandler.cpp index 1a66392c55..7e3134e8c2 100644 --- a/src/plugins/texteditor/colorpreviewhoverhandler.cpp +++ b/src/plugins/texteditor/colorpreviewhoverhandler.cpp @@ -335,7 +335,7 @@ static QColor colorFromFuncAndArgs(const QString &func, const QStringList &args) void ColorPreviewHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - const auto cleanup = qScopeGuard([this, report] { report(priority()); }); + const QScopeGuard cleanup([this, report] { report(priority()); }); if (editorWidget->extraSelectionTooltip(pos).isEmpty()) { const QTextBlock tb = editorWidget->document()->findBlock(pos); diff --git a/src/plugins/texteditor/highlighter_test.cpp b/src/plugins/texteditor/highlighter_test.cpp new file mode 100644 index 0000000000..f0652a780b --- /dev/null +++ b/src/plugins/texteditor/highlighter_test.cpp @@ -0,0 +1,195 @@ +// 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 "syntaxhighlighter.h" + +#include "highlighter_test.h" + +#include "fontsettings.h" +#include "textdocument.h" +#include "texteditor.h" +#include "texteditorsettings.h" + +#include <coreplugin/coreconstants.h> +#include <coreplugin/editormanager/editormanager.h> +#include <utils/mimeutils.h> + +#include <QtTest/QtTest> + +namespace TextEditor::Internal { + +constexpr auto json = R"( +{ + "name": "Test", + "scope": "source.test", + "uuid": "test", + "patterns": [ + { + "match": "a", + "name": "keyword.test" + } + ] +} +)"; + +void GenerigHighlighterTests::initTestCase() +{ + QString title = "test.json"; + + Core::IEditor *editor = Core::EditorManager::openEditorWithContents( + Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &title, json); + QVERIFY(editor); + m_editor = qobject_cast<BaseTextEditor *>(editor); + m_editor->editorWidget()->configureGenericHighlighter(Utils::mimeTypeForName("application/json")); + QVERIFY(m_editor); + m_editor->textDocument()->syntaxHighlighter()->rehighlight(); +} + +using FormatRanges = QList<QTextLayout::FormatRange>; + +QTextCharFormat toFormat(const TextStyle &style) +{ + const static FontSettings fontSettings = TextEditorSettings::fontSettings(); + auto format = fontSettings.toTextCharFormat(style); + if (style == C_FUNCTION) + format.setFontWeight(QFont::Bold); // is explicitly set by the ksyntax format definition + if (style == C_TEXT) { + format = QTextCharFormat(); + format.setFontWeight(QFont::Bold); // is explicitly set by the ksyntax format definition + } + return format; +}; + +void GenerigHighlighterTests::testHighlight_data() +{ + QTest::addColumn<int>("blockNumber"); + QTest::addColumn<QList<QTextLayout::FormatRange>>("formatRanges"); + + // clang-format off + QTest::addRow("0:<empty block>") + << 0 + << FormatRanges(); + QTest::addRow("1:{") + << 1 + << FormatRanges{{0, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("2: \"name\": \"Test\",") + << 2 + << FormatRanges{{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 6, toFormat(C_TYPE)}, + {10, 1, toFormat(C_FUNCTION)}, + {11, 1, toFormat(C_VISUAL_WHITESPACE)}, + {12, 6, toFormat(C_STRING)}, + {18, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("3: \"scope\": \"source.test\",") + << 3 + << FormatRanges{{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 7, toFormat(C_TYPE)}, + {11, 1, toFormat(C_FUNCTION)}, + {12, 1, toFormat(C_VISUAL_WHITESPACE)}, + {13, 13, toFormat(C_STRING)}, + {26, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("4: \"uuid\": \"test\",") + << 4 + << FormatRanges{{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 6, toFormat(C_TYPE)}, + {10, 1, toFormat(C_FUNCTION)}, + {11, 1, toFormat(C_VISUAL_WHITESPACE)}, + {12, 6, toFormat(C_STRING)}, + {18, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("5: \"patterns\": [") + << 5 + << FormatRanges{{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 10, toFormat(C_TYPE)}, + {14, 1, toFormat(C_FUNCTION)}, + {15, 1, toFormat(C_VISUAL_WHITESPACE)}, + {16, 1, toFormat(C_TEXT)}}; + QTest::addRow("6: {") + << 6 + << FormatRanges{{0, 8, toFormat(C_VISUAL_WHITESPACE)}, + {8, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("7: \"match\": \"a\",") + << 7 + << FormatRanges{{0, 12, toFormat(C_VISUAL_WHITESPACE)}, + {12, 7, toFormat(C_TYPE)}, + {19, 1, toFormat(C_FUNCTION)}, + {20, 1, toFormat(C_VISUAL_WHITESPACE)}, + {21, 3, toFormat(C_STRING)}, + {24, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("8: \"name\": \"keyword.test\"") + << 8 + << FormatRanges{{0, 12, toFormat(C_VISUAL_WHITESPACE)}, + {12, 6, toFormat(C_TYPE)}, + {18, 1, toFormat(C_FUNCTION)}, + {19, 1, toFormat(C_VISUAL_WHITESPACE)}, + {20, 14, toFormat(C_STRING)}}; + QTest::addRow("9: }") + << 9 + << FormatRanges{{0, 8, toFormat(C_VISUAL_WHITESPACE)}, + {8, 1, toFormat(C_FUNCTION)}}; + QTest::addRow("10: ]") + << 10 + << FormatRanges{{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 1, toFormat(C_TEXT)}}; + QTest::addRow("11:}") + << 11 + << FormatRanges{{0, 1, toFormat(C_FUNCTION)}}; + // clang-format on +} + +void compareFormats(const QTextLayout::FormatRange &actual, const QTextLayout::FormatRange &expected) +{ + QCOMPARE(actual.start, expected.start); + QCOMPARE(actual.length, expected.length); + QCOMPARE(actual.format.foreground(), expected.format.foreground()); + QCOMPARE(actual.format.background(), expected.format.background()); + QCOMPARE(actual.format.fontWeight(), expected.format.fontWeight()); + QCOMPARE(actual.format.fontItalic(), expected.format.fontItalic()); + QCOMPARE(actual.format.underlineStyle(), expected.format.underlineStyle()); + QCOMPARE(actual.format.underlineColor(), expected.format.underlineColor()); +} + +void GenerigHighlighterTests::testHighlight() +{ + QFETCH(int, blockNumber); + QFETCH(FormatRanges, formatRanges); + + QTextBlock block = m_editor->textDocument()->document()->findBlockByNumber(blockNumber); + QVERIFY(block.isValid()); + + const QList<QTextLayout::FormatRange> actualFormats = block.layout()->formats(); + // full hash calculation for QTextCharFormat fails so just check the important entries of format + QCOMPARE(actualFormats.size(), formatRanges.size()); + for (int i = 0; i < formatRanges.size(); ++i) + compareFormats(actualFormats.at(i), formatRanges.at(i)); +} + +void GenerigHighlighterTests::testChange() +{ + QTextBlock block = m_editor->textDocument()->document()->findBlockByNumber(10); + QVERIFY(block.isValid()); + + QTextCursor c(block); + c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor); + c.removeSelectedText(); + m_editor->textDocument()->document()->undo(); + + block = m_editor->textDocument()->document()->findBlockByNumber(10); + QVERIFY(block.isValid()); + + const FormatRanges formatRanges = {{0, 4, toFormat(C_VISUAL_WHITESPACE)}, + {4, 1, toFormat(C_TEXT)}}; + const QList<QTextLayout::FormatRange> actualFormats = block.layout()->formats(); + // full hash calculation for QTextCharFormat fails so just check the important entries of format + QCOMPARE(actualFormats.size(), formatRanges.size()); + for (int i = 0; i < formatRanges.size(); ++i) + compareFormats(actualFormats.at(i), formatRanges.at(i)); +} + +void GenerigHighlighterTests::cleanupTestCase() +{ + if (m_editor) + Core::EditorManager::closeEditors({m_editor}); + QVERIFY(Core::EditorManager::currentEditor() == nullptr); +} + +} // namespace TextEditor::Internal diff --git a/src/plugins/texteditor/highlighter_test.h b/src/plugins/texteditor/highlighter_test.h new file mode 100644 index 0000000000..30c2848c5c --- /dev/null +++ b/src/plugins/texteditor/highlighter_test.h @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include <QObject> + +namespace TextEditor { class BaseTextEditor; } + +namespace TextEditor::Internal { + +class GenerigHighlighterTests : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void testHighlight_data(); + void testHighlight(); + void testChange(); + void cleanupTestCase(); + +private: + TextEditor::BaseTextEditor *m_editor = nullptr; +}; + +} // namespace TextEditor::Internal diff --git a/src/plugins/texteditor/snippets/snippet.cpp b/src/plugins/texteditor/snippets/snippet.cpp index 74a4dc543c..0b3bd080e7 100644 --- a/src/plugins/texteditor/snippets/snippet.cpp +++ b/src/plugins/texteditor/snippets/snippet.cpp @@ -189,7 +189,7 @@ SnippetParseResult Snippet::parse(const QString &snippet) if (!errorMessage.isEmpty()) return {SnippetParseError{errorMessage, {}, -1}}; - const int count = preprocessedSnippet.count(); + const int count = preprocessedSnippet.size(); NameMangler *mangler = nullptr; QMap<QString, int> variableIndexes; @@ -404,7 +404,7 @@ void Internal::TextEditorPlugin::testSnippetParsing() QCOMPARE(manglerId, expected.manglerId); }; - for (int i = 0; i < parts.count(); ++i) + for (int i = 0; i < parts.size(); ++i) rangesCompare(snippet.parts.at(i), parts.at(i)); } #endif diff --git a/src/plugins/texteditor/textdocumentlayout.cpp b/src/plugins/texteditor/textdocumentlayout.cpp index 703f9563bf..08c1e21117 100644 --- a/src/plugins/texteditor/textdocumentlayout.cpp +++ b/src/plugins/texteditor/textdocumentlayout.cpp @@ -596,6 +596,8 @@ bool TextDocumentLayout::updateSuggestion(const QTextBlock &block, { if (TextSuggestion *suggestion = TextDocumentLayout::suggestion(block)) { auto positionInBlock = position - block.position(); + if (positionInBlock < suggestion->position()) + return false; const QString start = block.text().left(positionInBlock); const QString end = block.text().mid(positionInBlock); const QString replacement = suggestion->document()->firstBlock().text(); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 97c878e442..33323b3b76 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -1426,7 +1426,7 @@ void TextEditorWidgetPrivate::print(QPrinter *printer) return; doc = doc->clone(doc); - const auto cleanup = qScopeGuard([doc] { delete doc; }); + const QScopeGuard cleanup([doc] { delete doc; }); QTextOption opt = doc->defaultTextOption(); opt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -2546,7 +2546,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) { ICore::restartTrimmer(); - auto clearBlockSelectionGuard = qScopeGuard([&]() { d->clearBlockSelection(); }); + QScopeGuard cleanup([&] { d->clearBlockSelection(); }); if (!isModifier(e) && mouseHidingEnabled()) viewport()->setCursor(Qt::BlankCursor); @@ -2825,7 +2825,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) } if (blockSelectionOperation != QTextCursor::NoMove) { - clearBlockSelectionGuard.dismiss(); + cleanup.dismiss(); d->handleMoveBlockSelection(blockSelectionOperation); } else if (!d->cursorMoveKeyEvent(e)) { QTextCursor cursor = textCursor(); @@ -5275,7 +5275,7 @@ void TextEditorWidgetPrivate::paintTextMarks(QPainter &painter, const ExtraAreaP int yoffset = blockBoundingRect.top(); painter.save(); - const auto cleanup = qScopeGuard([&painter, size, yoffset, xoffset, overrideIcon] { + const QScopeGuard cleanup([&painter, size, yoffset, xoffset, overrideIcon] { if (!overrideIcon.isNull()) { const QRect r(xoffset, yoffset, size, size); overrideIcon.paint(&painter, r, Qt::AlignCenter); diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 071e0b5fc2..fa8441f29e 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -226,6 +226,8 @@ Project { files: [ "codeassist/codeassist_test.cpp", "codeassist/codeassist_test.h", + "highlighter_test.cpp", + "highlighter_test.h", "texteditor_test.cpp", ] } diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index 4d5c2268d1..f82155c0a5 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -22,6 +22,7 @@ #ifdef WITH_TESTS #include "codeassist/codeassist_test.h" +#include "highlighter_test.h" #endif #include <coreplugin/actionmanager/actioncontainer.h> @@ -149,6 +150,7 @@ void TextEditorPlugin::initialize() #ifdef WITH_TESTS addTest<CodeAssistTests>(); + addTest<GenerigHighlighterTests>(); #endif } diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index 4891d9e8fd..985817720a 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -122,6 +122,7 @@ void UpdateInfoPlugin::startCheckForUpdates() const auto doSetup = [this](Process &process, const QStringList &args) { process.setCommand({d->m_maintenanceTool, args}); + process.setLowPriority(); }; const auto doCleanup = [this] { d->m_taskTree.release()->deleteLater(); diff --git a/src/plugins/vcsbase/submiteditorwidget.cpp b/src/plugins/vcsbase/submiteditorwidget.cpp index 00b4200580..38548d63f5 100644 --- a/src/plugins/vcsbase/submiteditorwidget.cpp +++ b/src/plugins/vcsbase/submiteditorwidget.cpp @@ -263,7 +263,7 @@ void SubmitEditorWidget::registerActions(QAction *editorUndoAction, QAction *edi d->m_submitButton = new QActionPushButton(submitAction); d->buttonLayout->addWidget(d->m_submitButton); if (!d->m_submitShortcut) - d->m_submitShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this); + d->m_submitShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Return), this); connect(d->m_submitShortcut, &QShortcut::activated, submitAction, [submitAction] { if (submitAction->isEnabled()) diff --git a/src/shared/designerintegrationv2/sizehandlerect.cpp b/src/shared/designerintegrationv2/sizehandlerect.cpp index 111b14b256..4a775eaeae 100644 --- a/src/shared/designerintegrationv2/sizehandlerect.cpp +++ b/src/shared/designerintegrationv2/sizehandlerect.cpp @@ -78,7 +78,7 @@ void SizeHandleRect::mousePressEvent(QMouseEvent *e) return; m_startSize = m_curSize = m_resizable->size(); - m_startPos = m_curPos = m_resizable->mapFromGlobal(e->globalPos()); + m_startPos = m_curPos = m_resizable->mapFromGlobal(e->globalPosition().toPoint()); if (debugSizeHandle) qDebug() << "SizeHandleRect::mousePressEvent" << m_startSize << m_startPos << m_curPos; @@ -94,7 +94,7 @@ void SizeHandleRect::mouseMoveEvent(QMouseEvent *e) // causes the handle and the mouse cursor to become out of sync // once a min/maxSize limit is hit. When the cursor reenters the valid // areas, it will now snap to it. - m_curPos = m_resizable->mapFromGlobal(e->globalPos()); + m_curPos = m_resizable->mapFromGlobal(e->globalPosition().toPoint()); QSize delta = QSize(m_curPos.x() - m_startPos.x(), m_curPos.y() - m_startPos.y()); switch (m_dir) { case Right: diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index 2c162eaa35..13a4fe5b91 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -3604,6 +3604,42 @@ id="use3673" transform="matrix(-1,0,0,1,2258,0)" /> </g> + <g + id="src/plugins/terminal/images/keyboardlock" + transform="translate(845,88.5)" + style="display:inline"> + <use + style="display:inline" + transform="translate(1137,43.5)" + height="100%" + width="100%" + id="use1952-7" + xlink:href="#backgroundRect" + y="0" + x="0" /> + <rect + style="fill:none;stroke:#000000" + id="rect11662" + width="13" + height="13" + x="1122.5" + y="481" + rx="2.5" /> + <rect + style="fill:none;stroke:#000000" + id="rect11664" + width="9" + height="8" + x="1124.5" + y="483" + rx="1.3" /> + <path + style="fill:none;stroke:#000000" + d="m 1131,485 h -2 c -0.5,0 -1.5,0 -1.5,1 0,1 1,1 1.5,1 0.5,0 1.5,0 1.5,1 0,1 -1,1 -1.5,1 h -2" + id="path5086-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cczczcc" /> + </g> </g> <g inkscape:groupmode="layer" diff --git a/src/tools/process_stub/main.cpp b/src/tools/process_stub/main.cpp index f606b06369..d5fdc2f408 100644 --- a/src/tools/process_stub/main.cpp +++ b/src/tools/process_stub/main.cpp @@ -48,20 +48,16 @@ std::optional<QStringList> environmentVariables; QProcess inferiorProcess; int inferiorId{0}; -#ifndef Q_OS_WIN - #ifdef Q_OS_DARWIN // A memory mapped helper to retrieve the pid of the inferior process in debugMode static int *shared_child_pid = nullptr; #endif -using OSSocketNotifier = QSocketNotifier; -#else +#ifdef Q_OS_WIN Q_PROCESS_INFORMATION *win_process_information = nullptr; -using OSSocketNotifier = QWinEventNotifier; #endif -// Helper to read a single character from stdin in testMode -OSSocketNotifier *stdInNotifier; + +bool waitingForExitKeyPress = false; QThread processThread; @@ -77,8 +73,10 @@ std::optional<int> readEnvFile(); void setupControlSocket(); void setupSignalHandlers(); void startProcess(const QString &program, const QStringList &arguments, const QString &workingDir); -void readKey(); +void onKeyPress(std::function<void()> callback); void sendSelfPid(); +void killInferior(); +void resumeInferior(); int main(int argc, char *argv[]) { @@ -117,7 +115,15 @@ int main(int argc, char *argv[]) if (debugMode) { qDebug() << "Press 'c' to continue or 'k' to kill, followed by 'enter'"; - readKey(); + + onKeyPress([] { + char ch; + std::cin >> ch; + if (ch == 'k') + killInferior(); + else + resumeInferior(); + }); } return a.exec(); @@ -169,15 +175,20 @@ void sendErrChDir() void doExit(int exitCode) { + if (waitingForExitKeyPress) + exit(exitCode); + if (controlSocket.state() == QLocalSocket::ConnectedState && controlSocket.bytesToWrite()) controlSocket.waitForBytesWritten(1000); if (!commandLineParser.value("wait").isEmpty()) { - std::cout << commandLineParser.value("wait").toStdString(); - std::cin.get(); - } + std::cout << commandLineParser.value("wait").toStdString() << std::endl; - exit(exitCode); + waitingForExitKeyPress = true; + onKeyPress([exitCode] { doExit(exitCode); }); + } else { + exit(exitCode); + } } void onInferiorFinished(int exitCode, QProcess::ExitStatus status) @@ -550,23 +561,15 @@ void setupControlSocket() controlSocket.connectToServer(commandLineParser.value("socket")); } -void onStdInReadyRead() -{ - char ch; - std::cin >> ch; - if (ch == 'k') { - killInferior(); - } else { - resumeInferior(); - } -} - -void readKey() +void onKeyPress(std::function<void()> callback) { #ifdef Q_OS_WIN - stdInNotifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE)); + // On windows, QWinEventNotifier() doesn't work for stdin, so we have to use a thread instead. + QThread *thread = QThread::create([] { std::cin.ignore(); }); + thread->start(); + QObject::connect(thread, &QThread::finished, &controlSocket, callback); #else - stdInNotifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read); + static auto stdInNotifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read); + QObject::connect(stdInNotifier, &QSocketNotifier::activated, callback); #endif - QObject::connect(stdInNotifier, &OSSocketNotifier::activated, &onStdInReadyRead); } diff --git a/src/tools/processlauncher/processlauncher-main.cpp b/src/tools/processlauncher/processlauncher-main.cpp index 0629ec3c6d..980839cd8a 100644 --- a/src/tools/processlauncher/processlauncher-main.cpp +++ b/src/tools/processlauncher/processlauncher-main.cpp @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) return 1; } - auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); }); + const QScopeGuard cleanup([] { Utils::Singleton::deleteAll(); }); Utils::Internal::LauncherSocketHandler launcher(app.arguments().constLast()); QTimer::singleShot(0, &launcher, &Utils::Internal::LauncherSocketHandler::start); diff --git a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp index 8a982f5cdd..48b42e7029 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp @@ -374,7 +374,7 @@ void ObjectNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentIn QVariant ObjectNodeInstance::convertSpecialCharacter(const QVariant& value) const { QVariant specialCharacterConvertedValue = value; - if (value.type() == QVariant::String) { + if (value.typeId() == QVariant::String) { QString string = value.toString(); string.replace(QLatin1String("\\n"), QLatin1String("\n")); string.replace(QLatin1String("\\t"), QLatin1String("\t")); @@ -472,7 +472,7 @@ void ObjectNodeInstance::setPropertyVariant(const PropertyName &name, const QVar QVariant oldValue = property.read(); - if (oldValue.type() == QVariant::Url) { + if (oldValue.typeId() == QVariant::Url) { QUrl url = oldValue.toUrl(); QString path = url.toLocalFile(); if (QFileInfo::exists(path) && nodeInstanceServer() && !path.isEmpty()) @@ -489,7 +489,7 @@ void ObjectNodeInstance::setPropertyVariant(const PropertyName &name, const QVar qDebug() << "ObjectNodeInstance.setPropertyVariant: Cannot be written: " << object() << name << adjustedValue; QVariant newValue = property.read(); - if (newValue.type() == QVariant::Url) { + if (newValue.typeId() == QVariant::Url) { QUrl url = newValue.toUrl(); QString path = url.toLocalFile(); if (QFileInfo::exists(path) && nodeInstanceServer() && !path.isEmpty()) @@ -579,9 +579,9 @@ void ObjectNodeInstance::refreshProperty(const PropertyName &name) else property.write(resetValue(name)); - if (oldValue.type() == QVariant::Url) { + if (oldValue.typeId() == QVariant::Url) { QByteArray key = oldValue.toUrl().toEncoded(QUrl::UrlFormattingOption(0x100)); - QString pixmapKey = QString::fromUtf8(key.constData(), key.count()); + QString pixmapKey = QString::fromUtf8(key.constData(), key.size()); QPixmapCache::remove(pixmapKey); } @@ -851,7 +851,7 @@ static inline QString fixComponentPathForIncompatibleQt(const QString &component if (componentPath.contains(importString)) { int index = componentPath.indexOf(importString) + 8; const QString relativeImportPath = componentPath.right(componentPath.length() - index); - QString fixedComponentPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) + relativeImportPath; + QString fixedComponentPath = QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) + relativeImportPath; fixedComponentPath.replace(QLatin1Char('\\'), QLatin1Char('/')); if (QFileInfo::exists(fixedComponentPath)) return fixedComponentPath; diff --git a/src/tools/sdktool/addqtoperation.cpp b/src/tools/sdktool/addqtoperation.cpp index ee48c1e5ec..61e19855ff 100644 --- a/src/tools/sdktool/addqtoperation.cpp +++ b/src/tools/sdktool/addqtoperation.cpp @@ -270,7 +270,7 @@ QVariantMap AddQtData::addQt(const QVariantMap &map) const for (QVariantMap::const_iterator i = map.begin(); i != map.end(); ++i) { if (!i.key().startsWith(QLatin1String(PREFIX))) continue; - QString number = i.key().mid(QString::fromLatin1(PREFIX).count()); + QString number = i.key().mid(QString::fromLatin1(PREFIX).size()); bool ok; int count = number.toInt(&ok); if (ok && count >= versionCount) diff --git a/src/tools/sdktool/sdkpersistentsettings.cpp b/src/tools/sdktool/sdkpersistentsettings.cpp index 4ca9b5e370..34b139e232 100644 --- a/src/tools/sdktool/sdkpersistentsettings.cpp +++ b/src/tools/sdktool/sdkpersistentsettings.cpp @@ -316,7 +316,7 @@ bool SdkFileSaverBase::write(const QByteArray &bytes) { if (m_hasError) return false; - return setResult(m_file->write(bytes) == bytes.count()); + return setResult(m_file->write(bytes) == bytes.size()); } bool SdkFileSaverBase::setResult(bool ok) diff --git a/tests/auto/qml/codemodel/check/tst_check.cpp b/tests/auto/qml/codemodel/check/tst_check.cpp index 56ccdfd2a3..befb363ae4 100644 --- a/tests/auto/qml/codemodel/check/tst_check.cpp +++ b/tests/auto/qml/codemodel/check/tst_check.cpp @@ -73,7 +73,7 @@ void tst_Check::initTestCase() ModelManagerInterface *modelManager = ModelManagerInterface::instance(); PathsAndLanguages lPaths; - QStringList paths(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)); + QStringList paths(QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath)); for (auto p: paths) lPaths.maybeInsert(Utils::FilePath::fromString(p), Dialect::Qml); ModelManagerInterface::importScan(ModelManagerInterface::workingCopy(), lPaths, diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 69d87e8188..64442529b4 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -509,7 +509,7 @@ void tst_Tasking::testTree_data() createSuccessTask(3), createSuccessTask(4) }; - taskTree.setupRoot(nestedRoot); + taskTree.setRecipe(nestedRoot); CustomStorage *activeStorage = storage.activeStorage(); auto collectSubLog = [activeStorage](CustomStorage *subTreeStorage){ activeStorage->m_log += subTreeStorage->m_log; diff --git a/tests/auto/utils/process/processtestapp/main.cpp b/tests/auto/utils/process/processtestapp/main.cpp index 91952c2528..34923c407a 100644 --- a/tests/auto/utils/process/processtestapp/main.cpp +++ b/tests/auto/utils/process/processtestapp/main.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) #endif QCoreApplication app(argc, argv); - auto cleanup = qScopeGuard([] { Singleton::deleteAll(); }); + const QScopeGuard cleanup([] { Singleton::deleteAll(); }); TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX"); diff --git a/tests/auto/utils/process/processtestapp/processtestapp.cpp b/tests/auto/utils/process/processtestapp/processtestapp.cpp index 3905d0a22b..6cf7510eb7 100644 --- a/tests/auto/utils/process/processtestapp/processtestapp.cpp +++ b/tests/auto/utils/process/processtestapp/processtestapp.cpp @@ -33,7 +33,7 @@ void ProcessTestApp::invokeSubProcess() { ProcessTestApp processTestApp; int returnValue = 1; - auto cleanup = qScopeGuard([&returnValue] { + const QScopeGuard cleanup([&returnValue] { QMetaObject::invokeMethod(qApp, [returnValue] { qApp->exit(returnValue); }, Qt::QueuedConnection); diff --git a/tests/manual/tasking/imagescaling/imagescaling.cpp b/tests/manual/tasking/imagescaling/imagescaling.cpp index 362a30287e..e3acda749b 100644 --- a/tests/manual/tasking/imagescaling/imagescaling.cpp +++ b/tests/manual/tasking/imagescaling/imagescaling.cpp @@ -3,19 +3,24 @@ #include "imagescaling.h" #include "downloaddialog.h" +#include <tasking/concurrentcall.h> +#include <tasking/networkquery.h> -#include <QNetworkReply> +using namespace Tasking; Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDialog(this)) { resize(800, 600); - addUrlsButton = new QPushButton(tr("Add URLs")); + QPushButton *addUrlsButton = new QPushButton(tr("Add URLs")); connect(addUrlsButton, &QPushButton::clicked, this, &Images::process); cancelButton = new QPushButton(tr("Cancel")); cancelButton->setEnabled(false); - connect(cancelButton, &QPushButton::clicked, this, &Images::cancel); + connect(cancelButton, &QPushButton::clicked, this, [this] { + statusBar->showMessage(tr("Canceled.")); + taskTree.reset(); + }); QHBoxLayout *buttonLayout = new QHBoxLayout(); buttonLayout->addWidget(addUrlsButton); @@ -32,141 +37,77 @@ Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDi mainLayout->addStretch(); mainLayout->addWidget(statusBar); setLayout(mainLayout); - - connect(&scalingWatcher, &QFutureWatcher<QList<QImage>>::finished, - this, &Images::scaleFinished); } -Images::~Images() +static void scale(QPromise<QImage> &promise, const QByteArray &data) { - cancel(); + const auto image = QImage::fromData(data); + if (image.isNull()) + promise.future().cancel(); + else + promise.addResult(image.scaled(100, 100, Qt::KeepAspectRatio)); } void Images::process() { - // Clean previous state - replies.clear(); - addUrlsButton->setEnabled(false); - - if (downloadDialog->exec() == QDialog::Accepted) { + if (downloadDialog->exec() != QDialog::Accepted) + return; - const auto urls = downloadDialog->getUrls(); - if (urls.empty()) - return; + const auto urls = downloadDialog->getUrls(); + initLayout(urls.size()); + const auto onRootSetup = [this] { + statusBar->showMessage(tr("Downloading and Scaling...")); cancelButton->setEnabled(true); - - initLayout(urls.size()); - - downloadFuture = download(urls); - statusBar->showMessage(tr("Downloading...")); - - downloadFuture - .then([this](auto) { - cancelButton->setEnabled(false); - updateStatus(tr("Scaling...")); - scalingWatcher.setFuture(QtConcurrent::run(Images::scaled, - downloadFuture.results())); - }) - .onCanceled([this] { - updateStatus(tr("Download has been canceled.")); - }) - .onFailed([this](QNetworkReply::NetworkError error) { - updateStatus(tr("Download finished with error: %1").arg(error)); - // Abort all pending requests - abortDownload(); - }) - .onFailed([this](const std::exception &ex) { - updateStatus(tr(ex.what())); - }) - .then([this]() { - cancelButton->setEnabled(false); - addUrlsButton->setEnabled(true); - }); - } -} - -void Images::cancel() -{ - statusBar->showMessage(tr("Canceling...")); - - downloadFuture.cancel(); - abortDownload(); -} - -void Images::scaleFinished() -{ - const OptionalImages result = scalingWatcher.result(); - if (result.has_value()) { - const auto scaled = result.value(); - showImages(scaled); - updateStatus(tr("Finished")); - } else { - updateStatus(tr("Failed to extract image data.")); - } - addUrlsButton->setEnabled(true); -} - -QFuture<QByteArray> Images::download(const QList<QUrl> &urls) -{ - QSharedPointer<QPromise<QByteArray>> promise(new QPromise<QByteArray>()); - promise->start(); - - for (const auto &url : urls) { - QSharedPointer<QNetworkReply> reply(qnam.get(QNetworkRequest(url))); - replies.push_back(reply); - - QtFuture::connect(reply.get(), &QNetworkReply::finished).then([=] { - if (promise->isCanceled()) { - if (!promise->future().isFinished()) - promise->finish(); - return; - } - - if (reply->error() != QNetworkReply::NoError) { - if (!promise->future().isFinished()) - throw reply->error(); - } - promise->addResult(reply->readAll()); - - // Report finished on the last download - if (promise->future().resultCount() == urls.size()) - promise->finish(); - }).onFailed([promise] (QNetworkReply::NetworkError error) { - promise->setException(std::make_exception_ptr(error)); - promise->finish(); - }).onFailed([promise] { - const auto ex = std::make_exception_ptr( - std::runtime_error("Unknown error occurred while downloading.")); - promise->setException(ex); - promise->finish(); - }); + }; + const auto onRootDone = [this] { + statusBar->showMessage(tr("Finished.")); + cancelButton->setEnabled(false); + }; + QList<GroupItem> tasks { + finishAllAndDone, + parallel, + onGroupSetup(onRootSetup), + onGroupDone(onRootDone) + }; + + int i = 0; + for (const QUrl &url : urls) { + TreeStorage<QByteArray> storage; + + const auto onDownloadSetup = [this, url](NetworkQuery &query) { + query.setNetworkAccessManager(&qnam); + query.setRequest(QNetworkRequest(url)); + }; + const auto onDownloadDone = [storage](const NetworkQuery &query) { + *storage = query.reply()->readAll(); + }; + const auto onDownloadError = [this, i](const NetworkQuery &query) { + labels[i]->setText(tr("Download\nError.\nCode: %1.").arg(query.reply()->error())); + }; + + const auto onScalingSetup = [storage](ConcurrentCall<QImage> &data) { + data.setConcurrentCallData(&scale, *storage); + }; + const auto onScalingDone = [this, i](const ConcurrentCall<QImage> &data) { + labels[i]->setPixmap(QPixmap::fromImage(data.result())); + }; + const auto onScalingError = [this, i](const ConcurrentCall<QImage> &) { + labels[i]->setText(tr("Image\nData\nError.")); + }; + + const Group group { + Storage(storage), + NetworkQueryTask(onDownloadSetup, onDownloadDone, onDownloadError), + ConcurrentCallTask<QImage>(onScalingSetup, onScalingDone, onScalingError) + }; + tasks.append(group); + ++i; } - return promise->future(); -} - -Images::OptionalImages Images::scaled(const QList<QByteArray> &data) -{ - QList<QImage> scaled; - for (const auto &imgData : data) { - QImage image; - image.loadFromData(imgData); - if (image.isNull()) - return std::nullopt; - - scaled.push_back(image.scaled(100, 100, Qt::KeepAspectRatio)); - } - - return scaled; -} - -void Images::showImages(const QList<QImage> &images) -{ - for (int i = 0; i < images.size(); ++i) { - labels[i]->setAlignment(Qt::AlignCenter); - labels[i]->setPixmap(QPixmap::fromImage(images[i])); - } + taskTree.reset(new TaskTree(tasks)); + connect(taskTree.get(), &TaskTree::done, this, [this] { taskTree.release()->deleteLater(); }); + taskTree->start(); } void Images::initLayout(qsizetype count) @@ -186,19 +127,9 @@ void Images::initLayout(qsizetype count) for (int j = 0; j < dim; ++j) { QLabel *imageLabel = new QLabel; imageLabel->setFixedSize(100, 100); + imageLabel->setAlignment(Qt::AlignCenter); imagesLayout->addWidget(imageLabel, i, j); labels.append(imageLabel); } } } - -void Images::updateStatus(const QString &msg) -{ - statusBar->showMessage(msg); -} - -void Images::abortDownload() -{ - for (auto reply : replies) - reply->abort(); -} diff --git a/tests/manual/tasking/imagescaling/imagescaling.h b/tests/manual/tasking/imagescaling/imagescaling.h index d3409e60a0..91e89c13b2 100644 --- a/tests/manual/tasking/imagescaling/imagescaling.h +++ b/tests/manual/tasking/imagescaling/imagescaling.h @@ -4,10 +4,9 @@ #ifndef IMAGESCALING_H #define IMAGESCALING_H -#include <QtWidgets> -#include <QtConcurrent> #include <QNetworkAccessManager> -#include <optional> +#include <QtWidgets> +#include <tasking/tasktree.h> class DownloadDialog; class Images : public QWidget @@ -15,27 +14,11 @@ class Images : public QWidget Q_OBJECT public: Images(QWidget *parent = nullptr); - ~Images(); - - void initLayout(qsizetype count); - - QFuture<QByteArray> download(const QList<QUrl> &urls); - void updateStatus(const QString &msg); - void showImages(const QList<QImage> &images); - void abortDownload(); - -public slots: - void process(); - void cancel(); - -private slots: - void scaleFinished(); private: - using OptionalImages = std::optional<QList<QImage>>; - static OptionalImages scaled(const QList<QByteArray> &data); + void process(); + void initLayout(qsizetype count); - QPushButton *addUrlsButton; QPushButton *cancelButton; QVBoxLayout *mainLayout; QList<QLabel *> labels; @@ -44,9 +27,7 @@ private: DownloadDialog *downloadDialog; QNetworkAccessManager qnam; - QList<QSharedPointer<QNetworkReply>> replies; - QFuture<QByteArray> downloadFuture; - QFutureWatcher<OptionalImages> scalingWatcher; + std::unique_ptr<Tasking::TaskTree> taskTree; }; #endif // IMAGESCALING_H diff --git a/tests/system/suite_tools/tst_git_clone/test.py b/tests/system/suite_tools/tst_git_clone/test.py index c41ee6fd98..42473264f7 100644 --- a/tests/system/suite_tools/tst_git_clone/test.py +++ b/tests/system/suite_tools/tst_git_clone/test.py @@ -43,7 +43,7 @@ def verifyVersionControlView(targetDir, canceled): vcsLog = str(waitForObject("{type='Core::OutputWindow' unnamed='1' visible='1' " "window=':Qt Creator_Core::Internal::MainWindow'}").plainText) test.log("Clone log is: %s" % vcsLog) - test.verify("Running in " + targetDir + ":" in vcsLog, + test.verify('Running in "' + targetDir + '":' in vcsLog, "Searching for target directory in clone log") test.verify(" ".join(["clone", "--progress", cloneUrl, cloneDir]) in vcsLog, "Searching for git parameters in clone log") diff --git a/tests/unit/unittest/unittests-main.cpp b/tests/unit/unittest/unittests-main.cpp index af6f5db4fb..e2b83c0941 100644 --- a/tests/unit/unittest/unittests-main.cpp +++ b/tests/unit/unittest/unittests-main.cpp @@ -13,7 +13,6 @@ #include <QGuiApplication> #include <QLoggingCategory> -#include <QScopeGuard> #ifdef WITH_BENCHMARKS #include <benchmark/benchmark.h> |