diff options
author | Tim Jenssen <tim.jenssen@qt.io> | 2023-06-07 12:06:26 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2023-06-07 12:07:21 +0200 |
commit | a6d1b594a48090b6804e9d4b08ae9af10733a3e8 (patch) | |
tree | 464f69f9f06d9dbdb00ffc59cd45380b1ab915c1 | |
parent | 69244a7a3aba1f2381655032dff0f36611b9edc8 (diff) | |
parent | ad5e8392fe867e6e0af15cd8f209753f60e8cac0 (diff) |
Merge remote-tracking branch 'origin/11.0' into qds/dev
Change-Id: I79a272471b3400eec0a0fa9fca175d1d4a8c0a13
184 files changed, 1972 insertions, 989 deletions
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-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-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/src/editors/creator-coding.qdoc b/doc/qtcreator/src/editors/creator-coding.qdoc index 6823bf1c8f..23fd888d57 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,12 @@ 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{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..16dcf80d4b --- /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-mime-types.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..662b3c0fa2 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-copilot.html \page creator-mime-types.html \nextpage creator-modeling.html diff --git a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc index 57bb973bb2..0f6e7fd58a 100644 --- a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc +++ b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc @@ -482,8 +482,9 @@ \row \li Add Class Member \li Adds a member declaration for the class member being - initialized if it is not yet declared. You must enter - the data type of the member. + initialized if it is not yet declared. If \QC cannot + automatically detect the data type of the member, you + must add it. \li Identifier \row \li Create Implementations for Member Functions diff --git a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc index ef5d0cca4c..c763d587ae 100644 --- a/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc +++ b/doc/qtcreator/src/howto/creator-keyboard-shortcuts.qdoc @@ -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 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/projects/creator-only/creator-projects-opening.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc index d06989e66f..85d0490392 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc @@ -99,4 +99,7 @@ \image qtcreator-toggle-progress-bar.webp {Toggle Progress Details button} + You can drag the progress bar to another position. The position is saved for + later. Select the \inlineimage icons/pin.png + (\uicontrol Pin) button to pin the progress bar back to the toggle button. */ 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/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc index e18f60632b..3215f40270 100644 --- a/doc/qtcreator/src/qtcreator-toc.qdoc +++ b/doc/qtcreator/src/qtcreator-toc.qdoc @@ -130,6 +130,7 @@ \endlist \li \l{Editing Markdown Files} \li \l{Using Language Servers} + \li \l{Using GitHub Copilot} \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..c4ba6cad41 100644 --- a/doc/qtcreator/src/user-interface/creator-ui.qdoc +++ b/doc/qtcreator/src/user-interface/creator-ui.qdoc @@ -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 @@ -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/src/app/main.cpp b/src/app/main.cpp index 3a2cb5bfaa..ec40152292 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -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/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index ae2dbf8903..b567d75325 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -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); diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 16b17b0fae..4b79bdafcc 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -369,61 +369,62 @@ LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerpri QByteArray LibraryInfo::calculateFingerprint() const { QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(reinterpret_cast<const char *>(&_status), sizeof(_status)); + auto addData = [&hash](auto p, size_t len) { + hash.addData(QByteArrayView(reinterpret_cast<const char *>(p), len)); + }; + + addData(&_status, sizeof(_status)); int len = _components.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Component &component : _components) { len = component.fileName.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(component.fileName.constData()), - len * sizeofQChar); - hash.addData(reinterpret_cast<const char *>(&component.majorVersion), sizeof(component.majorVersion)); - hash.addData(reinterpret_cast<const char *>(&component.minorVersion), sizeof(component.minorVersion)); + addData(&len, sizeof(len)); + addData(component.fileName.constData(), len * sizeofQChar); + addData(&component.majorVersion, sizeof(component.majorVersion)); + addData(&component.minorVersion, sizeof(component.minorVersion)); len = component.typeName.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(component.typeName.constData()), - component.typeName.size() * sizeofQChar); + addData(&len, sizeof(len)); + addData(component.typeName.constData(), component.typeName.size() * sizeofQChar); int flags = (component.singleton ? (1 << 0) : 0) + (component.internal ? (1 << 1) : 0); - hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags)); + addData(&flags, sizeof(flags)); } len = _plugins.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Plugin &plugin : _plugins) { len = plugin.path.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(plugin.path.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(plugin.path.constData(), len * sizeofQChar); len = plugin.name.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(plugin.name.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(plugin.name.constData(), len * sizeofQChar); } len = _typeinfos.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QString &typeinfo : _typeinfos) { len = typeinfo.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(typeinfo.constData()), - len * sizeofQChar); + addData(&len, sizeof(len)); + addData(typeinfo.constData(), len * sizeofQChar); } len = _metaObjects.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); QList<QByteArray> metaFingerprints; for (const LanguageUtils::FakeMetaObject::ConstPtr &metaObject : _metaObjects) metaFingerprints.append(metaObject->fingerprint()); std::sort(metaFingerprints.begin(), metaFingerprints.end()); for (const QByteArray &fp : std::as_const(metaFingerprints)) hash.addData(fp); - hash.addData(reinterpret_cast<const char *>(&_dumpStatus), sizeof(_dumpStatus)); + addData(&_dumpStatus, sizeof(_dumpStatus)); len = _dumpError.size(); // localization dependent (avoid?) - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); - hash.addData(reinterpret_cast<const char *>(_dumpError.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(_dumpError.constData(), len * sizeofQChar); len = _moduleApis.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const ModuleApiInfo &moduleInfo : _moduleApis) moduleInfo.addToHash(hash); // make it order independent? len = _imports.size(); - hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Import &import : _imports) hash.addData(import.module.toUtf8()); // import order matters, keep order-dependent 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 5beed2fe5b..f70c910e04 100644 --- a/src/libs/solutions/tasking/CMakeLists.txt +++ b/src/libs/solutions/tasking/CMakeLists.txt @@ -1,9 +1,11 @@ add_qtc_library(Tasking OBJECT # Never add dependencies to non-Qt libraries for this library - DEPENDS Qt::Core + DEPENDS Qt::Concurrent Qt::Core Qt::Network PUBLIC_DEFINES TASKING_LIBRARY SOURCES barrier.cpp barrier.h + concurrentcall.h + networkquery.cpp networkquery.h tasking_global.h tasktree.cpp tasktree.h ) diff --git a/src/libs/solutions/tasking/barrier.h b/src/libs/solutions/tasking/barrier.h index 6939da5b36..6f1afe39b0 100644 --- a/src/libs/solutions/tasking/barrier.h +++ b/src/libs/solutions/tasking/barrier.h @@ -34,7 +34,7 @@ private: int m_current = -1; }; -class TASKING_EXPORT BarrierTaskAdapter : public Tasking::TaskAdapter<Barrier> +class TASKING_EXPORT BarrierTaskAdapter : public TaskAdapter<Barrier> { public: BarrierTaskAdapter() { connect(task(), &Barrier::done, this, &TaskInterface::done); } diff --git a/src/libs/solutions/tasking/concurrentcall.h b/src/libs/solutions/tasking/concurrentcall.h new file mode 100644 index 0000000000..d779915944 --- /dev/null +++ b/src/libs/solutions/tasking/concurrentcall.h @@ -0,0 +1,100 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "tasking_global.h" + +#include "tasktree.h" + +#include <QtConcurrent> + +namespace Tasking { + +// This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace +// is independent on Qt::Concurrent. +// Possibly, it could be placed inside Qt::Concurrent library, as a wrapper around +// QtConcurrent::run() call. + +template <typename ResultType> +class ConcurrentCall +{ + Q_DISABLE_COPY_MOVE(ConcurrentCall) + +public: + ConcurrentCall() = default; + template <typename Function, typename ...Args> + void setConcurrentCallData(Function &&function, Args &&...args) + { + return wrapConcurrent(std::forward<Function>(function), std::forward<Args>(args)...); + } + void setThreadPool(QThreadPool *pool) { m_threadPool = pool; } + ResultType result() const + { + return m_future.resultCount() ? m_future.result() : ResultType(); + } + QFuture<ResultType> future() const { return m_future; } + +private: + template <typename Function, typename ...Args> + void wrapConcurrent(Function &&function, Args &&...args) + { + m_startHandler = [=] { + if (m_threadPool) + return QtConcurrent::run(m_threadPool, function, args...); + return QtConcurrent::run(function, args...); + }; + } + + template <typename Function, typename ...Args> + void wrapConcurrent(std::reference_wrapper<const Function> &&wrapper, Args &&...args) + { + m_startHandler = [=] { + if (m_threadPool) { + return QtConcurrent::run(m_threadPool, + std::forward<const Function>(wrapper.get()), args...); + } + return QtConcurrent::run(std::forward<const Function>(wrapper.get()), args...); + }; + } + + template <typename T> + friend class ConcurrentCallTaskAdapter; + + std::function<QFuture<ResultType>()> m_startHandler; + QThreadPool *m_threadPool = nullptr; + QFuture<ResultType> m_future; +}; + +template <typename ResultType> +class ConcurrentCallTaskAdapter : public TaskAdapter<ConcurrentCall<ResultType>> +{ +public: + ~ConcurrentCallTaskAdapter() { + if (m_watcher) { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + } + + void start() { + if (!this->task()->m_startHandler) { + emit this->done(false); // TODO: Add runtime assert + return; + } + m_watcher.reset(new QFutureWatcher<ResultType>); + this->connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] { + emit this->done(!m_watcher->isCanceled()); + m_watcher.release()->deleteLater(); + }); + this->task()->m_future = this->task()->m_startHandler(); + m_watcher->setFuture(this->task()->m_future); + } + +private: + std::unique_ptr<QFutureWatcher<ResultType>> m_watcher; +}; + +} // namespace Tasking + +TASKING_DECLARE_TEMPLATE_TASK(ConcurrentCallTask, Tasking::ConcurrentCallTaskAdapter); diff --git a/src/libs/solutions/tasking/networkquery.cpp b/src/libs/solutions/tasking/networkquery.cpp new file mode 100644 index 0000000000..292d3c7d4a --- /dev/null +++ b/src/libs/solutions/tasking/networkquery.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "networkquery.h" + +#include <QNetworkAccessManager> + +namespace Tasking { + +void NetworkQuery::start() +{ + if (m_reply) { + qWarning("The NetworkQuery is already running. Ignoring the call to start()."); + return; + } + if (!m_manager) { + qWarning("Can't start the NetworkQuery without the QNetworkAccessManager. " + "Stopping with an error."); + emit done(false); + return; + } + m_reply.reset(m_manager->get(m_request)); + connect(m_reply.get(), &QNetworkReply::finished, this, [this] { + disconnect(m_reply.get(), nullptr, this, nullptr); + emit done(m_reply->error() == QNetworkReply::NoError); + m_reply.release()->deleteLater(); + }); + if (m_reply->isRunning()) + emit started(); +} + +NetworkQuery::~NetworkQuery() +{ + if (m_reply) + m_reply->abort(); +} + +} // namespace Tasking diff --git a/src/libs/solutions/tasking/networkquery.h b/src/libs/solutions/tasking/networkquery.h new file mode 100644 index 0000000000..faf482df90 --- /dev/null +++ b/src/libs/solutions/tasking/networkquery.h @@ -0,0 +1,55 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#pragma once + +#include "tasking_global.h" + +#include "tasktree.h" + +#include <QNetworkReply> +#include <QNetworkRequest> + +#include <memory> + +QT_BEGIN_NAMESPACE +class QNetworkAccessManager; +QT_END_NAMESPACE + +namespace Tasking { + +// This class introduces the dependency to Qt::Network, otherwise Tasking namespace +// is independent on Qt::Network. +// Possibly, it could be placed inside Qt::Network library, as a wrapper around QNetworkReply. + +class TASKING_EXPORT NetworkQuery final : public QObject +{ + Q_OBJECT + +public: + ~NetworkQuery(); + void setRequest(const QNetworkRequest &request) { m_request = request; } + void setNetworkAccessManager(QNetworkAccessManager *manager) { m_manager = manager; } + QNetworkReply *reply() const { return m_reply.get(); } + void start(); + +signals: + void started(); + void done(bool success); + +private: + QNetworkRequest m_request; + QNetworkAccessManager *m_manager = nullptr; + std::unique_ptr<QNetworkReply> m_reply; +}; + +class TASKING_EXPORT NetworkQueryTaskAdapter : public TaskAdapter<NetworkQuery> +{ +public: + NetworkQueryTaskAdapter() { connect(task(), &NetworkQuery::done, this, &TaskInterface::done); } + void start() final { task()->start(); } +}; + +} // namespace Tasking + +TASKING_DECLARE_TASK(NetworkQueryTask, Tasking::NetworkQueryTaskAdapter); diff --git a/src/libs/solutions/tasking/tasking.qbs b/src/libs/solutions/tasking/tasking.qbs index 8697b9c009..fa0a5ebacc 100644 --- a/src/libs/solutions/tasking/tasking.qbs +++ b/src/libs/solutions/tasking/tasking.qbs @@ -1,11 +1,14 @@ QtcLibrary { name: "Tasking" - Depends { name: "Qt"; submodules: ["core"] } + Depends { name: "Qt"; submodules: ["concurrent", "core", "network"] } cpp.defines: base.concat("TASKING_LIBRARY") files: [ "barrier.cpp", "barrier.h", + "concurrentcall.h", + "networkquery.cpp", + "networkquery.h", "tasking_global.h", "tasktree.cpp", "tasktree.h", diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index f9fe58375e..2a4c7cefd9 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -43,11 +43,11 @@ private: }; /*! - \class Tasking::TaskItem + \class Tasking::GroupItem \inheaderfile solutions/tasking/tasktree.h \inmodule QtCreator \ingroup mainclasses - \brief The TaskItem class represents the basic element for composing nested tree structures. + \brief The GroupItem class represents the basic element for composing nested tree structures. */ /*! @@ -246,7 +246,7 @@ private: */ /*! - \typealias TaskItem::GroupSetupHandler + \typealias GroupItem::GroupSetupHandler Type alias for \c std::function<TaskAction()>. @@ -277,7 +277,7 @@ private: */ /*! - \typealias TaskItem::GroupEndHandler + \typealias GroupItem::GroupEndHandler Type alias for \c std::function\<void()\>. @@ -290,13 +290,14 @@ private: */ /*! - \fn template <typename SetupHandler> TaskItem onGroupSetup(SetupHandler &&handler) + \fn template <typename SetupHandler> GroupItem onGroupSetup(SetupHandler &&handler) Constructs a group's element holding the group setup handler. The \a handler is invoked whenever the group starts. The passed \a handler is either of \c std::function<TaskAction()> or \c std::function<void()> - type. For more information on possible argument type, refer to \l {TaskItem::GroupSetupHandler}. + type. For more information on possible argument type, refer to + \l {GroupItem::GroupSetupHandler}. When the \a handler is invoked, none of the group's child tasks are running yet. @@ -304,7 +305,7 @@ private: after the storages are constructed, so that the \a handler may already perform some initial modifications to the active storages. - \sa TaskItem::GroupSetupHandler, onGroupDone, onGroupError + \sa GroupItem::GroupSetupHandler, onGroupDone, onGroupError */ /*! @@ -319,9 +320,9 @@ private: before the storages are destructed, so that the \a handler may still perform a last read of the active storages' data. - \sa TaskItem::GroupEndHandler, onGroupSetup, onGroupError + \sa GroupItem::GroupEndHandler, onGroupSetup, onGroupError */ -TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler) +GroupItem onGroupDone(const GroupItem::GroupEndHandler &handler) { return Group::onGroupDone(handler); } @@ -338,9 +339,9 @@ TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler) before the storages are destructed, so that the \a handler may still perform a last read of the active storages' data. - \sa TaskItem::GroupEndHandler, onGroupSetup, onGroupDone + \sa GroupItem::GroupEndHandler, onGroupSetup, onGroupDone */ -TaskItem onGroupError(const TaskItem::GroupEndHandler &handler) +GroupItem onGroupError(const GroupItem::GroupEndHandler &handler) { return Group::onGroupError(handler); } @@ -386,7 +387,7 @@ TaskItem onGroupError(const TaskItem::GroupEndHandler &handler) \sa sequential, parallel */ -TaskItem parallelLimit(int limit) +GroupItem parallelLimit(int limit) { return Group::parallelLimit(qMax(limit, 0)); } @@ -399,21 +400,21 @@ TaskItem parallelLimit(int limit) \sa stopOnError, continueOnError, stopOnDone, continueOnDone, stopOnFinished, finishAllAndDone, finishAllAndError, WorkflowPolicy */ -TaskItem workflowPolicy(WorkflowPolicy policy) +GroupItem workflowPolicy(WorkflowPolicy policy) { return Group::workflowPolicy(policy); } -const TaskItem sequential = parallelLimit(1); -const TaskItem parallel = parallelLimit(0); +const GroupItem sequential = parallelLimit(1); +const GroupItem parallel = parallelLimit(0); -const TaskItem stopOnError = workflowPolicy(WorkflowPolicy::StopOnError); -const TaskItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError); -const TaskItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); -const TaskItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); -const TaskItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); -const TaskItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); -const TaskItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError); +const GroupItem stopOnError = workflowPolicy(WorkflowPolicy::StopOnError); +const GroupItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError); +const GroupItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); +const GroupItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); +const GroupItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); +const GroupItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); +const GroupItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError); static TaskAction toTaskAction(bool success) { @@ -483,11 +484,11 @@ void TreeStorageBase::activateStorage(int id) const m_storageData->m_activeStorage = id; } -void TaskItem::addChildren(const QList<TaskItem> &children) +void GroupItem::addChildren(const QList<GroupItem> &children) { QTC_ASSERT(m_type == Type::Group, qWarning("Only Group may have children, skipping..."); return); - for (const TaskItem &child : children) { + for (const GroupItem &child : children) { switch (child.m_type) { case Type::Group: m_children.append(child); @@ -534,7 +535,7 @@ void TaskItem::addChildren(const QList<TaskItem> &children) } } -void TaskItem::setTaskSetupHandler(const TaskSetupHandler &handler) +void GroupItem::setTaskSetupHandler(const TaskSetupHandler &handler) { if (!handler) { qWarning("Setting empty Setup Handler is no-op, skipping..."); @@ -545,7 +546,7 @@ void TaskItem::setTaskSetupHandler(const TaskSetupHandler &handler) m_taskHandler.m_setupHandler = handler; } -void TaskItem::setTaskDoneHandler(const TaskEndHandler &handler) +void GroupItem::setTaskDoneHandler(const TaskEndHandler &handler) { if (!handler) { qWarning("Setting empty Done Handler is no-op, skipping..."); @@ -556,7 +557,7 @@ void TaskItem::setTaskDoneHandler(const TaskEndHandler &handler) m_taskHandler.m_doneHandler = handler; } -void TaskItem::setTaskErrorHandler(const TaskEndHandler &handler) +void GroupItem::setTaskErrorHandler(const TaskEndHandler &handler) { if (!handler) { qWarning("Setting empty Error Handler is no-op, skipping..."); @@ -567,8 +568,8 @@ void TaskItem::setTaskErrorHandler(const TaskEndHandler &handler) m_taskHandler.m_errorHandler = handler; } -TaskItem TaskItem::withTimeout(const TaskItem &item, milliseconds timeout, - const GroupEndHandler &handler) +GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout, + const GroupEndHandler &handler) { const TimeoutTask::EndHandler taskHandler = handler ? [handler](const milliseconds &) { handler(); } : TimeoutTask::EndHandler(); @@ -640,7 +641,7 @@ class TaskContainer Q_DISABLE_COPY_MOVE(TaskContainer) public: - TaskContainer(TaskTreePrivate *taskTreePrivate, const TaskItem &task, + TaskContainer(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer) : m_constData(taskTreePrivate, task, parentNode, parentContainer, this) {} TaskAction start(); @@ -653,7 +654,7 @@ public: bool isStarting() const { return isRunning() && m_runtimeData->m_startGuard.isLocked(); } struct ConstData { - ConstData(TaskTreePrivate *taskTreePrivate, const TaskItem &task, TaskNode *parentNode, + ConstData(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer, TaskContainer *thisContainer); ~ConstData() { qDeleteAll(m_children); } TaskTreePrivate * const m_taskTreePrivate = nullptr; @@ -662,7 +663,7 @@ public: const int m_parallelLimit = 1; const WorkflowPolicy m_workflowPolicy = WorkflowPolicy::StopOnError; - const TaskItem::GroupHandler m_groupHandler; + const GroupItem::GroupHandler m_groupHandler; const QList<TreeStorageBase> m_storageList; const QList<TaskNode *> m_children; const int m_taskCount = 0; @@ -693,7 +694,7 @@ class TaskNode Q_DISABLE_COPY_MOVE(TaskNode) public: - TaskNode(TaskTreePrivate *taskTreePrivate, const TaskItem &task, + TaskNode(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskContainer *parentContainer) : m_taskHandler(task.taskHandler()) , m_container(taskTreePrivate, task, this, parentContainer) @@ -711,7 +712,7 @@ public: TaskTree *taskTree() const { return m_container.m_constData.m_taskTreePrivate->q; } private: - const TaskItem::TaskHandler m_taskHandler; + const GroupItem::TaskHandler m_taskHandler; TaskContainer m_container; std::unique_ptr<TaskInterface> m_task; }; @@ -831,16 +832,16 @@ ReturnType invokeHandler(TaskContainer *container, Handler &&handler, Args &&... } static QList<TaskNode *> createChildren(TaskTreePrivate *taskTreePrivate, TaskContainer *container, - const TaskItem &task) + const GroupItem &task) { QList<TaskNode *> result; - const QList<TaskItem> &children = task.children(); - for (const TaskItem &child : children) + const QList<GroupItem> &children = task.children(); + for (const GroupItem &child : children) result.append(new TaskNode(taskTreePrivate, child, container)); return result; } -TaskContainer::ConstData::ConstData(TaskTreePrivate *taskTreePrivate, const TaskItem &task, +TaskContainer::ConstData::ConstData(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer, TaskContainer *thisContainer) : m_taskTreePrivate(taskTreePrivate) @@ -1035,7 +1036,7 @@ void TaskContainer::stop() void TaskContainer::invokeEndHandler() { - const TaskItem::GroupHandler &groupHandler = m_constData.m_groupHandler; + const GroupItem::GroupHandler &groupHandler = m_constData.m_groupHandler; if (m_runtimeData->m_successBit && groupHandler.m_doneHandler) invokeHandler(this, groupHandler.m_doneHandler); else if (!m_runtimeData->m_successBit && groupHandler.m_errorHandler) @@ -1539,7 +1540,7 @@ void TaskNode::invokeEndHandler(bool success) static QByteArray load(const QString &fileName) { ... } static void save(const QString &fileName, const QByteArray &array) { ... } - static TaskItem copyRecipe(const QString &source, const QString &destination) + static GroupItem copyRecipe(const QString &source, const QString &destination) { struct CopyStorage { // [1] custom inter-task struct QByteArray content; // [2] custom inter-task data diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 647c680b5b..dcd7b86ac1 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -123,7 +123,7 @@ enum class TaskAction }; Q_ENUM_NS(TaskAction); -class TASKING_EXPORT TaskItem +class TASKING_EXPORT GroupItem { public: // Internal, provided by QTC_DECLARE_CUSTOM_TASK @@ -156,7 +156,7 @@ public: std::optional<WorkflowPolicy> m_workflowPolicy = {}; }; - QList<TaskItem> children() const { return m_children; } + QList<GroupItem> children() const { return m_children; } GroupData groupData() const { return m_groupData; } QList<TreeStorageBase> storageList() const { return m_storageList; } TaskHandler taskHandler() const { return m_taskHandler; } @@ -169,58 +169,58 @@ protected: TaskHandler }; - TaskItem() = default; - TaskItem(const GroupData &data) + GroupItem() = default; + GroupItem(const GroupData &data) : m_type(Type::GroupData) , m_groupData(data) {} - TaskItem(const TreeStorageBase &storage) + GroupItem(const TreeStorageBase &storage) : m_type(Type::Storage) , m_storageList{storage} {} - TaskItem(const TaskHandler &handler) + GroupItem(const TaskHandler &handler) : m_type(Type::TaskHandler) , m_taskHandler(handler) {} - void addChildren(const QList<TaskItem> &children); + void addChildren(const QList<GroupItem> &children); void setTaskSetupHandler(const TaskSetupHandler &handler); void setTaskDoneHandler(const TaskEndHandler &handler); void setTaskErrorHandler(const TaskEndHandler &handler); - static TaskItem groupHandler(const GroupHandler &handler) { return TaskItem({handler}); } - static TaskItem parallelLimit(int limit) { return TaskItem({{}, limit}); } - static TaskItem workflowPolicy(WorkflowPolicy policy) { return TaskItem({{}, {}, policy}); } - static TaskItem withTimeout(const TaskItem &item, std::chrono::milliseconds timeout, + static GroupItem groupHandler(const GroupHandler &handler) { return GroupItem({handler}); } + static GroupItem parallelLimit(int limit) { return GroupItem({{}, limit}); } + static GroupItem workflowPolicy(WorkflowPolicy policy) { return GroupItem({{}, {}, policy}); } + static GroupItem withTimeout(const GroupItem &item, std::chrono::milliseconds timeout, const GroupEndHandler &handler = {}); private: Type m_type = Type::Group; - QList<TaskItem> m_children; + QList<GroupItem> m_children; GroupData m_groupData; QList<TreeStorageBase> m_storageList; TaskHandler m_taskHandler; }; -class TASKING_EXPORT Group : public TaskItem +class TASKING_EXPORT Group : public GroupItem { public: - Group(const QList<TaskItem> &children) { addChildren(children); } - Group(std::initializer_list<TaskItem> children) { addChildren(children); } + Group(const QList<GroupItem> &children) { addChildren(children); } + Group(std::initializer_list<GroupItem> children) { addChildren(children); } // GroupData related: template <typename SetupHandler> - static TaskItem onGroupSetup(SetupHandler &&handler) { + static GroupItem onGroupSetup(SetupHandler &&handler) { return groupHandler({wrapGroupSetup(std::forward<SetupHandler>(handler))}); } - static TaskItem onGroupDone(const GroupEndHandler &handler) { + static GroupItem onGroupDone(const GroupEndHandler &handler) { return groupHandler({{}, handler}); } - static TaskItem onGroupError(const GroupEndHandler &handler) { + static GroupItem onGroupError(const GroupEndHandler &handler) { return groupHandler({{}, {}, handler}); } - using TaskItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel). - using TaskItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError. + using GroupItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel). + using GroupItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError. - TaskItem withTimeout(std::chrono::milliseconds timeout, - const GroupEndHandler &handler = {}) const { - return TaskItem::withTimeout(*this, timeout, handler); + GroupItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return GroupItem::withTimeout(*this, timeout, handler); } private: @@ -244,31 +244,31 @@ private: }; template <typename SetupHandler> -static TaskItem onGroupSetup(SetupHandler &&handler) +static GroupItem onGroupSetup(SetupHandler &&handler) { return Group::onGroupSetup(std::forward<SetupHandler>(handler)); } -TASKING_EXPORT TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler); -TASKING_EXPORT TaskItem onGroupError(const TaskItem::GroupEndHandler &handler); -TASKING_EXPORT TaskItem parallelLimit(int limit); -TASKING_EXPORT TaskItem workflowPolicy(WorkflowPolicy policy); +TASKING_EXPORT GroupItem onGroupDone(const GroupItem::GroupEndHandler &handler); +TASKING_EXPORT GroupItem onGroupError(const GroupItem::GroupEndHandler &handler); +TASKING_EXPORT GroupItem parallelLimit(int limit); +TASKING_EXPORT GroupItem workflowPolicy(WorkflowPolicy policy); -TASKING_EXPORT extern const TaskItem sequential; -TASKING_EXPORT extern const TaskItem parallel; +TASKING_EXPORT extern const GroupItem sequential; +TASKING_EXPORT extern const GroupItem parallel; -TASKING_EXPORT extern const TaskItem stopOnError; -TASKING_EXPORT extern const TaskItem continueOnError; -TASKING_EXPORT extern const TaskItem stopOnDone; -TASKING_EXPORT extern const TaskItem continueOnDone; -TASKING_EXPORT extern const TaskItem stopOnFinished; -TASKING_EXPORT extern const TaskItem finishAllAndDone; -TASKING_EXPORT extern const TaskItem finishAllAndError; +TASKING_EXPORT extern const GroupItem stopOnError; +TASKING_EXPORT extern const GroupItem continueOnError; +TASKING_EXPORT extern const GroupItem stopOnDone; +TASKING_EXPORT extern const GroupItem continueOnDone; +TASKING_EXPORT extern const GroupItem stopOnFinished; +TASKING_EXPORT extern const GroupItem finishAllAndDone; +TASKING_EXPORT extern const GroupItem finishAllAndError; -class TASKING_EXPORT Storage : public TaskItem +class TASKING_EXPORT Storage : public GroupItem { public: - Storage(const TreeStorageBase &storage) : TaskItem(storage) { } + Storage(const TreeStorageBase &storage) : GroupItem(storage) { } }; // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount() @@ -281,7 +281,7 @@ public: private: template<typename Function> - static QList<TaskItem> init(Function &&function) { + static QList<GroupItem> init(Function &&function) { constexpr bool isInvocable = std::is_invocable_v<std::decay_t<Function>>; static_assert(isInvocable, "Sync element: The synchronous function can't take any arguments."); @@ -310,17 +310,17 @@ private: }; template <typename Adapter> -class CustomTask : public TaskItem +class CustomTask : public GroupItem { public: using Task = typename Adapter::Type; using EndHandler = std::function<void(const Task &)>; static Adapter *createAdapter() { return new Adapter; } - CustomTask() : TaskItem({&createAdapter}) {} + CustomTask() : GroupItem({&createAdapter}) {} template <typename SetupFunction> CustomTask(SetupFunction &&function, const EndHandler &done = {}, const EndHandler &error = {}) - : TaskItem({&createAdapter, wrapSetup(std::forward<SetupFunction>(function)), - wrapEnd(done), wrapEnd(error)}) {} + : GroupItem({&createAdapter, wrapSetup(std::forward<SetupFunction>(function)), + wrapEnd(done), wrapEnd(error)}) {} template <typename SetupFunction> CustomTask &onSetup(SetupFunction &&function) { @@ -336,14 +336,14 @@ public: return *this; } - TaskItem withTimeout(std::chrono::milliseconds timeout, - const GroupEndHandler &handler = {}) const { - return TaskItem::withTimeout(*this, timeout, handler); + GroupItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return GroupItem::withTimeout(*this, timeout, handler); } private: template<typename SetupFunction> - static TaskItem::TaskSetupHandler wrapSetup(SetupFunction &&function) { + static GroupItem::TaskSetupHandler wrapSetup(SetupFunction &&function) { static constexpr bool isDynamic = std::is_same_v<TaskAction, std::invoke_result_t<std::decay_t<SetupFunction>, typename Adapter::Type &>>; constexpr bool isVoid = std::is_same_v<void, diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 57d358a7c1..999385e1ca 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2320,7 +2320,7 @@ QList<int> IntegersAspect::value() const void IntegersAspect::setValue(const QList<int> &value) { - BaseAspect::setValue(transform(value, &QVariant::fromValue<int>)); + BaseAspect::setValue(transform(value, [](int i) { return QVariant::fromValue<int>(i); })); } QList<int> IntegersAspect::defaultValue() const @@ -2331,7 +2331,7 @@ QList<int> IntegersAspect::defaultValue() const void IntegersAspect::setDefaultValue(const QList<int> &value) { - BaseAspect::setDefaultValue(transform(value, &QVariant::fromValue<int>)); + BaseAspect::setDefaultValue(transform(value, [](int i) { return QVariant::fromValue<int>(i); })); } 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/filestreamer.cpp b/src/libs/utils/filestreamer.cpp index 693849b7c5..eb9e057c1a 100644 --- a/src/libs/utils/filestreamer.cpp +++ b/src/libs/utils/filestreamer.cpp @@ -30,7 +30,7 @@ public: void start() { QTC_ASSERT(!m_taskTree, return); - const TaskItem task = m_filePath.needsDevice() ? remoteTask() : localTask(); + const GroupItem task = m_filePath.needsDevice() ? remoteTask() : localTask(); m_taskTree.reset(new TaskTree({task})); const auto finalize = [this](bool success) { m_taskTree.release()->deleteLater(); @@ -49,8 +49,8 @@ protected: std::unique_ptr<TaskTree> m_taskTree; private: - virtual TaskItem remoteTask() = 0; - virtual TaskItem localTask() = 0; + virtual GroupItem remoteTask() = 0; + virtual GroupItem localTask() = 0; }; static void localRead(QPromise<QByteArray> &promise, const FilePath &filePath) @@ -84,7 +84,7 @@ signals: void readyRead(const QByteArray &newData); private: - TaskItem remoteTask() final { + GroupItem remoteTask() final { const auto setup = [this](Process &process) { const QStringList args = {"if=" + m_filePath.path()}; const FilePath dd = m_filePath.withNewPath("dd"); @@ -96,7 +96,7 @@ private: }; return ProcessTask(setup); } - TaskItem localTask() final { + GroupItem localTask() final { const auto setup = [this](Async<QByteArray> &async) { async.setConcurrentCallData(localRead, m_filePath); Async<QByteArray> *asyncPtr = &async; @@ -251,7 +251,7 @@ signals: void started(); private: - TaskItem remoteTask() final { + GroupItem remoteTask() final { const auto setup = [this](Process &process) { m_writeBuffer = new WriteBuffer(false, &process); connect(m_writeBuffer, &WriteBuffer::writeRequested, &process, &Process::writeRaw); @@ -272,7 +272,7 @@ private: }; return ProcessTask(setup, finalize, finalize); } - TaskItem localTask() final { + GroupItem localTask() final { const auto setup = [this](Async<void> &async) { m_writeBuffer = new WriteBuffer(isBuffered(), &async); async.setConcurrentCallData(localWrite, m_filePath, m_writeData, m_writeBuffer); @@ -390,7 +390,7 @@ public: StreamResult m_streamResult = StreamResult::FinishedWithError; std::unique_ptr<TaskTree> m_taskTree; - TaskItem task() { + GroupItem task() { if (m_streamerMode == StreamMode::Reader) return readerTask(); if (m_streamerMode == StreamMode::Writer) @@ -399,7 +399,7 @@ public: } private: - TaskItem readerTask() { + GroupItem readerTask() { const auto setup = [this](FileStreamReader &reader) { m_readBuffer.clear(); reader.setFilePath(m_source); @@ -409,14 +409,14 @@ private: }; return FileStreamReaderTask(setup); } - TaskItem writerTask() { + GroupItem writerTask() { const auto setup = [this](FileStreamWriter &writer) { writer.setFilePath(m_destination); writer.setWriteData(m_writeBuffer); }; return FileStreamWriterTask(setup); } - TaskItem transferTask() { + GroupItem transferTask() { const auto setup = [this](Async<void> &async) { async.setConcurrentCallData(transfer, m_source, m_destination); }; 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/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index bea7faafd3..94aa80f02c 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -676,24 +676,22 @@ LayoutItem st() LayoutItem noMargin() { - LayoutItem item; - item.onAdd = [](LayoutBuilder &builder) { - if (auto layout = builder.stack.last().layout) - layout->setContentsMargins(0, 0, 0, 0); - else if (auto widget = builder.stack.last().widget) - widget->setContentsMargins(0, 0, 0, 0); - }; - return item; + return customMargin({}); } LayoutItem normalMargin() { + return customMargin({9, 9, 9, 9}); +} + +LayoutItem customMargin(const QMargins &margin) +{ LayoutItem item; - item.onAdd = [](LayoutBuilder &builder) { + item.onAdd = [margin](LayoutBuilder &builder) { if (auto layout = builder.stack.last().layout) - layout->setContentsMargins(9, 9, 9, 9); + layout->setContentsMargins(margin); else if (auto widget = builder.stack.last().widget) - widget->setContentsMargins(9, 9, 9, 9); + widget->setContentsMargins(margin); }; return item; } diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index 1f774ba146..4a75613989 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -19,6 +19,7 @@ QT_BEGIN_NAMESPACE class QLayout; +class QMargins; class QObject; class QWidget; template <class T> T qobject_cast(QObject *object); @@ -202,6 +203,7 @@ QTCREATOR_UTILS_EXPORT LayoutItem empty(); QTCREATOR_UTILS_EXPORT LayoutItem hr(); QTCREATOR_UTILS_EXPORT LayoutItem noMargin(); QTCREATOR_UTILS_EXPORT LayoutItem normalMargin(); +QTCREATOR_UTILS_EXPORT LayoutItem customMargin(const QMargins &margin); QTCREATOR_UTILS_EXPORT LayoutItem withFormAlignment(); // "Setters" 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/process.cpp b/src/libs/utils/process.cpp index 85d3fa54ed..e1302671e3 100644 --- a/src/libs/utils/process.cpp +++ b/src/libs/utils/process.cpp @@ -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/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 8553702432..e78be57965 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -35,7 +35,7 @@ using namespace ProjectExplorer; static bool isProjectParsing() { const BuildSystem *bs = ProjectManager::startupBuildSystem(); - return bs && bs->isParsing(); + return bs && (bs->isParsing() || bs->isWaitingForParse()); } TestCodeParser::TestCodeParser() @@ -360,7 +360,7 @@ void TestCodeParser::scanForTests(const QSet<FilePath> &filePaths, using namespace Tasking; - QList<TaskItem> tasks{parallelLimit(std::max(QThread::idealThreadCount() / 4, 1))}; + QList<GroupItem> tasks{parallelLimit(std::max(QThread::idealThreadCount() / 4, 1))}; for (const FilePath &file : filteredFiles) { const auto setup = [this, codeParsers, file](Async<TestParseResultPtr> &async) { async.setConcurrentCallData(parseFileForTests, codeParsers, file); diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 5c53d742e6..23912f15d9 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -347,7 +347,7 @@ void TestRunner::runTestsHelper() std::unique_ptr<TestOutputReader> m_outputReader; }; - QList<TaskItem> tasks{finishAllAndDone}; + QList<GroupItem> tasks{finishAllAndDone}; for (ITestConfiguration *config : m_selectedTests) { QTC_ASSERT(config, continue); 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/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 42e77c11a3..a14fb81b90 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -17,6 +17,7 @@ #include <coreplugin/icore.h> #include <coreplugin/messagemanager.h> #include <coreplugin/session.h> +#include <coreplugin/vcsmanager.h> #include <cppeditor/cppcodemodelsettings.h> #include <cppeditor/cppeditorconstants.h> @@ -686,6 +687,7 @@ void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client) // for the respective project to force re-parsing of open documents and re-indexing. // While this is not 100% bullet-proof, chances are good that in a typical session-based // workflow, e.g. a git branch switch will hit at least one open file. +// We also look for repository changes explicitly. void ClangModelManagerSupport::watchForExternalChanges() { connect(DocumentManager::instance(), &DocumentManager::filesChangedExternally, @@ -709,6 +711,23 @@ void ClangModelManagerSupport::watchForExternalChanges() return; } }); + + connect(VcsManager::instance(), &VcsManager::repositoryChanged, + this, [this](const FilePath &repoDir) { + if (sessionModeEnabled()) { + if (ClangdClient * const client = clientForProject(nullptr)) + scheduleClientRestart(client); + return; + } + for (const Project * const project : ProjectManager::projects()) { + const FilePath &projectDir = project->projectDirectory(); + if (repoDir == projectDir || repoDir.isChildOf(projectDir) + || projectDir.isChildOf(repoDir)) { + if (ClangdClient * const client = clientForProject(project)) + scheduleClientRestart(client); + } + } + }); } // If Qt Creator changes a file that is not open (e.g. as part of a quickfix), we have to 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/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 11353b04ae..39de004ac8 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -183,7 +183,7 @@ void ClangToolRunWorker::start() m_filesAnalyzed.clear(); m_filesNotAnalyzed.clear(); - QList<TaskItem> tasks{parallelLimit(qMax(1, m_runSettings.parallelJobs()))}; + QList<GroupItem> tasks{parallelLimit(qMax(1, m_runSettings.parallelJobs()))}; for (const AnalyzeUnit &unit : std::as_const(unitsToProcess)) { if (!m_diagnosticConfig.isEnabled(tool) && !m_runSettings.hasConfigFileForSourceFile(unit.file)) { diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 3e2c7a6c11..6681a9133d 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -101,9 +101,9 @@ static FilePath createOutputFilePath(const FilePath &dirPath, const FilePath &fi return {}; } -TaskItem clangToolTask(const AnalyzeInputData &input, - const AnalyzeSetupHandler &setupHandler, - const AnalyzeOutputHandler &outputHandler) +GroupItem clangToolTask(const AnalyzeInputData &input, + const AnalyzeSetupHandler &setupHandler, + const AnalyzeOutputHandler &outputHandler) { struct ClangToolStorage { QString name; diff --git a/src/plugins/clangtools/clangtoolrunner.h b/src/plugins/clangtools/clangtoolrunner.h index 3a0f59f341..a8d1204c22 100644 --- a/src/plugins/clangtools/clangtoolrunner.h +++ b/src/plugins/clangtools/clangtoolrunner.h @@ -10,7 +10,7 @@ #include <utils/environment.h> -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace ClangTools { namespace Internal { @@ -50,9 +50,9 @@ struct AnalyzeOutputData using AnalyzeSetupHandler = std::function<bool()>; using AnalyzeOutputHandler = std::function<void(const AnalyzeOutputData &)>; -Tasking::TaskItem clangToolTask(const AnalyzeInputData &input, - const AnalyzeSetupHandler &setupHandler, - const AnalyzeOutputHandler &outputHandler); +Tasking::GroupItem clangToolTask(const AnalyzeInputData &input, + const AnalyzeSetupHandler &setupHandler, + const AnalyzeOutputHandler &outputHandler); } // namespace Internal } // namespace ClangTools 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 3de2c6d55c..93cd27bac3 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -190,7 +190,7 @@ void DocumentClangToolRunner::run() vfso().update(); const ClangDiagnosticConfig config = diagnosticConfig(runSettings.diagnosticConfigId()); const Environment env = projectBuildEnvironment(project); - QList<TaskItem> tasks{parallel}; + QList<GroupItem> tasks{parallel}; const auto addClangTool = [this, &runSettings, &config, &env, &tasks](ClangToolType tool) { if (!toolEnabled(tool, config, runSettings)) return; diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp index e8ff40b310..baa884d9f2 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp @@ -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) { @@ -377,9 +377,9 @@ CMakeConfig CMakeConfig::fromFile(const Utils::FilePath &cacheFile, QString *err 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); diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index 5193661e57..3411fd85b5 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)); 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/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp index bfc62c3d18..15765698cb 100644 --- a/src/plugins/coreplugin/actionmanager/commandmappings.cpp +++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp @@ -6,18 +6,17 @@ #include <coreplugin/coreplugintr.h> #include <coreplugin/dialogs/shortcutsettings.h> -#include <utils/headerviewstretcher.h> #include <utils/fancylineedit.h> +#include <utils/headerviewstretcher.h> +#include <utils/layoutbuilder.h> #include <utils/qtcassert.h> #include <QDebug> #include <QGroupBox> -#include <QHBoxLayout> #include <QLabel> #include <QPointer> #include <QPushButton> #include <QTreeWidgetItem> -#include <QVBoxLayout> Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*) @@ -32,13 +31,10 @@ public: CommandMappingsPrivate(CommandMappings *parent) : q(parent) { - groupBox = new QGroupBox(parent); - groupBox->setTitle(::Core::Tr::tr("Command Mappings")); - - filterEdit = new FancyLineEdit(groupBox); + filterEdit = new FancyLineEdit; filterEdit->setFiltering(true); - commandList = new QTreeWidget(groupBox); + commandList = new QTreeWidget; commandList->setRootIsDecorated(false); commandList->setUniformRowHeights(true); commandList->setSortingEnabled(true); @@ -49,33 +45,28 @@ public: item->setText(1, ::Core::Tr::tr("Label")); item->setText(0, ::Core::Tr::tr("Command")); - defaultButton = new QPushButton(::Core::Tr::tr("Reset All"), groupBox); + defaultButton = new QPushButton(::Core::Tr::tr("Reset All")); defaultButton->setToolTip(::Core::Tr::tr("Reset all to default.")); - resetButton = new QPushButton(::Core::Tr::tr("Reset"), groupBox); + resetButton = new QPushButton(::Core::Tr::tr("Reset")); resetButton->setToolTip(::Core::Tr::tr("Reset to default.")); resetButton->setVisible(false); - importButton = new QPushButton(::Core::Tr::tr("Import..."), groupBox); - exportButton = new QPushButton(::Core::Tr::tr("Export..."), groupBox); - - auto hboxLayout1 = new QHBoxLayout(); - hboxLayout1->addWidget(defaultButton); - hboxLayout1->addWidget(resetButton); - hboxLayout1->addStretch(); - hboxLayout1->addWidget(importButton); - hboxLayout1->addWidget(exportButton); - - auto hboxLayout = new QHBoxLayout(); - hboxLayout->addWidget(filterEdit); - - auto vboxLayout1 = new QVBoxLayout(groupBox); - vboxLayout1->addLayout(hboxLayout); - vboxLayout1->addWidget(commandList); - vboxLayout1->addLayout(hboxLayout1); - - auto vboxLayout = new QVBoxLayout(parent); - vboxLayout->addWidget(groupBox); + importButton = new QPushButton(::Core::Tr::tr("Import...")); + exportButton = new QPushButton(::Core::Tr::tr("Export...")); + + using namespace Layouting; + Column { + Group { + title(::Core::Tr::tr("Command Mappings")), + bindTo(&groupBox), + Column { + filterEdit, + commandList, + Row { defaultButton, resetButton, st, importButton, exportButton }, + }, + }, + }.attachTo(parent); q->connect(exportButton, &QPushButton::clicked, q, &CommandMappings::exportAction); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index e7147e94ce..81262f5ebf 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -42,7 +42,6 @@ #include <utils/algorithm.h> #include <utils/checkablemessagebox.h> #include <utils/environment.h> -#include <utils/executeondestruction.h> #include <utils/filepath.h> #include <utils/hostosinfo.h> #include <utils/infobar.h> @@ -70,6 +69,7 @@ #include <QPushButton> #include <QRegularExpression> #include <QRegularExpressionMatch> +#include <QScopeGuard> #include <QSet> #include <QSettings> #include <QSplitter> @@ -3325,9 +3325,7 @@ IEditor *EditorManager::openEditorWithContents(Id editorId, EditorManager::gotoOtherSplit(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - Utils::ExecuteOnDestruction appRestoreCursor(&QApplication::restoreOverrideCursor); - Q_UNUSED(appRestoreCursor) - + const auto cleanup = qScopeGuard(&QApplication::restoreOverrideCursor); const QString title = makeTitleUnique(titlePattern); 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/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 3a84a0b548..0a4665361d 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -450,7 +450,7 @@ void LocatorMatcher::start() collectorStorage->m_collector = nullptr; }; - QList<TaskItem> parallelTasks {parallelLimit(d->m_parallelLimit)}; + QList<GroupItem> parallelTasks {parallelLimit(d->m_parallelLimit)}; const auto onSetup = [this, collectorStorage](const TreeStorage<LocatorStorage> &storage, int index) { @@ -597,7 +597,7 @@ QString ILocatorFilter::shortcutString() const \internal Sets the refresh recipe for refreshing cached data. */ -void ILocatorFilter::setRefreshRecipe(const std::optional<TaskItem> &recipe) +void ILocatorFilter::setRefreshRecipe(const std::optional<GroupItem> &recipe) { m_refreshRecipe = recipe; } @@ -606,7 +606,7 @@ void ILocatorFilter::setRefreshRecipe(const std::optional<TaskItem> &recipe) Returns the refresh recipe for refreshing cached data. By default, the locator filter has no recipe set, so that it won't be refreshed. */ -std::optional<TaskItem> ILocatorFilter::refreshRecipe() const +std::optional<GroupItem> ILocatorFilter::refreshRecipe() const { return m_refreshRecipe; } diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index b008c12bb5..fbc68bc647 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -139,7 +139,7 @@ class CORE_EXPORT LocatorMatcherTask final public: // The main task. Initial data (searchTerm) should be taken from storage.input(). // Results reporting is done via the storage.reportOutput(). - Tasking::TaskItem task = Tasking::Group{}; + Tasking::GroupItem task = Tasking::Group{}; // When constructing the task, don't place the storage inside the task above. Tasking::TreeStorage<LocatorStorage> storage; @@ -270,8 +270,8 @@ protected: virtual void saveState(QJsonObject &object) const; virtual void restoreState(const QJsonObject &object); - void setRefreshRecipe(const std::optional<Tasking::TaskItem> &recipe); - std::optional<Tasking::TaskItem> refreshRecipe() const; + void setRefreshRecipe(const std::optional<Tasking::GroupItem> &recipe); + std::optional<Tasking::GroupItem> refreshRecipe() const; static bool isOldSetting(const QByteArray &state); @@ -289,7 +289,7 @@ private: QString m_description; QString m_defaultShortcut; std::optional<QString> m_defaultSearchText; - std::optional<Tasking::TaskItem> m_refreshRecipe; + std::optional<Tasking::GroupItem> m_refreshRecipe; QKeySequence m_defaultKeySequence; bool m_defaultIncludedByDefault = false; bool m_includedByDefault = m_defaultIncludedByDefault; diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index 2deaef9fe0..cefce35a5b 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -381,7 +381,7 @@ void Locator::refresh(const QList<ILocatorFilter *> &filters) m_refreshingFilters = Utils::filteredUnique(m_refreshingFilters + filters); using namespace Tasking; - QList<TaskItem> tasks{parallel}; + QList<GroupItem> tasks{parallel}; for (ILocatorFilter *filter : std::as_const(m_refreshingFilters)) { const auto task = filter->refreshRecipe(); if (!task.has_value()) 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 a81ed5936d..63fba41a4d 100644 --- a/src/plugins/coreplugin/loggingviewer.cpp +++ b/src/plugins/coreplugin/loggingviewer.cpp @@ -11,7 +11,6 @@ #include <utils/algorithm.h> #include <utils/basetreeview.h> -#include <utils/executeondestruction.h> #include <utils/fileutils.h> #include <utils/listmodel.h> #include <utils/qtcassert.h> @@ -33,6 +32,7 @@ #include <QMessageBox> #include <QPushButton> #include <QRegularExpression> +#include <QScopeGuard> #include <QSortFilterProxyModel> #include <QStyledItemDelegate> #include <QToolButton> @@ -591,7 +591,7 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const { // should we just let it continue without temporarily disabling? const bool enabled = m_manager->isEnabled(); - Utils::ExecuteOnDestruction exec([this, enabled] { m_manager->setEnabled(enabled); }); + const auto cleanup = qScopeGuard([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/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/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/cppprojectupdater.cpp b/src/plugins/cppeditor/cppprojectupdater.cpp index c92d091396..e4b57c90c5 100644 --- a/src/plugins/cppeditor/cppprojectupdater.cpp +++ b/src/plugins/cppeditor/cppprojectupdater.cpp @@ -64,7 +64,7 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo, if (async.isResultAvailable()) storage->projectInfo = async.result(); }; - QList<TaskItem> tasks{parallel}; + QList<GroupItem> tasks{parallel}; tasks.append(AsyncTask<ProjectInfo::ConstPtr>(setupInfoGenerator, onInfoGeneratorDone)); for (QPointer<ExtraCompiler> compiler : compilers) { if (compiler && compiler->isDirty()) 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..d3a74d5d30 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -603,8 +603,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 +1881,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 +1890,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); 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/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/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/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 99ceef2f0a..867217d86d 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -128,7 +128,7 @@ DiffFilesController::DiffFilesController(IDocument *document) outputList->resize(inputList.size()); using namespace std::placeholders; - QList<TaskItem> tasks {parallel, finishAllAndDone}; + QList<GroupItem> tasks {parallel, finishAllAndDone}; for (int i = 0; i < inputList.size(); ++i) { tasks.append(AsyncTask<FileData>(std::bind(setupDiff, _1, inputList.at(i)), std::bind(onDiffDone, _1, i))); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 935b56291f..4f2bdc4912 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -441,7 +441,7 @@ ShowController::ShowController(IDocument *document, const QString &id) }; using namespace std::placeholders; - QList<TaskItem> tasks {parallel, continueOnDone, onGroupError(onFollowsError)}; + QList<GroupItem> tasks {parallel, continueOnDone, onGroupError(onFollowsError)}; for (int i = 0, total = parents.size(); i < total; ++i) { tasks.append(ProcessTask(std::bind(setupFollow, _1, parents.at(i)), std::bind(onFollowDone, _1, i))); 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/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/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/buildprogress.cpp b/src/plugins/projectexplorer/buildprogress.cpp index a78b8a1b79..7166ab474d 100644 --- a/src/plugins/projectexplorer/buildprogress.cpp +++ b/src/plugins/projectexplorer/buildprogress.cpp @@ -60,8 +60,8 @@ BuildProgress::BuildProgress(TaskWindow *taskWindow, Qt::Orientation orientation m_errorLabel->setProperty("_q_custom_style_disabled", QVariant(true)); m_warningLabel->setProperty("_q_custom_style_disabled", QVariant(true)); - m_errorIcon->setAlignment(Qt::AlignRight); - m_warningIcon->setAlignment(Qt::AlignRight); + m_errorIcon->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_warningIcon->setAlignment(Qt::AlignRight | Qt::AlignVCenter); m_errorIcon->setPixmap(Utils::Icons::CRITICAL_TOOLBAR.pixmap()); m_warningIcon->setPixmap(Utils::Icons::WARNING_TOOLBAR.pixmap()); 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/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index 0094bf0b68..8d6159541e 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -43,6 +43,16 @@ QVariantMap BuildStepList::toMap() const { QVariantMap map; + { + // Only written for compatibility reasons within the 4.11 cycle + const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id"; + const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName"; + const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName"; + map.insert(QLatin1String(CONFIGURATION_ID_KEY), m_id.toSetting()); + map.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); + map.insert(QLatin1String(DEFAULT_DISPLAY_NAME_KEY), displayName()); + } + // Save build steps map.insert(QString::fromLatin1(STEPS_COUNT_KEY), m_steps.count()); for (int i = 0; i < m_steps.count(); ++i) 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/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index 67bb4a63fc..bbd34a798f 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -137,7 +137,7 @@ QThreadPool *ExtraCompiler::extraCompilerThreadPool() return s_extraCompilerThreadPool(); } -TaskItem ExtraCompiler::compileFileItem() +GroupItem ExtraCompiler::compileFileItem() { return taskItemImpl(fromFileProvider()); } @@ -326,7 +326,7 @@ ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const FilePat ExtraCompiler(project, source, targets, parent) { } -TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider) +GroupItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider) { const auto setupTask = [=](Async<FileNameToContentsHash> &async) { async.setThreadPool(extraCompilerThreadPool()); diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h index 1dbda0e424..82bd9070f2 100644 --- a/src/plugins/projectexplorer/extracompiler.h +++ b/src/plugins/projectexplorer/extracompiler.h @@ -24,7 +24,7 @@ class QPromise; class QThreadPool; QT_END_NAMESPACE -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace Utils { class Process; } namespace ProjectExplorer { @@ -49,7 +49,7 @@ public: Utils::FilePaths targets() const; void forEachTarget(std::function<void(const Utils::FilePath &)> func) const; - Tasking::TaskItem compileFileItem(); + Tasking::GroupItem compileFileItem(); void compileFile(); bool isDirty() const; void block(); @@ -75,7 +75,7 @@ private: void compileContent(const QByteArray &content); void compileImpl(const ContentProvider &provider); void compileIfDirty(); - virtual Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0; + virtual Tasking::GroupItem taskItemImpl(const ContentProvider &provider) = 0; const std::unique_ptr<ExtraCompilerPrivate> d; }; @@ -101,7 +101,7 @@ protected: virtual Tasks parseIssues(const QByteArray &stdErr); private: - Tasking::TaskItem taskItemImpl(const ContentProvider &provider) final; + Tasking::GroupItem taskItemImpl(const ContentProvider &provider) final; void runInThread(QPromise<FileNameToContentsHash> &promise, const Utils::FilePath &cmd, const Utils::FilePath &workDir, const QStringList &args, const ContentProvider &provider, diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp index 49a9571189..9e73aa479e 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; } 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/python/pythonproject.cpp b/src/plugins/python/pythonproject.cpp index a29847ac7b..e9d503037d 100644 --- a/src/plugins/python/pythonproject.cpp +++ b/src/plugins/python/pythonproject.cpp @@ -52,12 +52,12 @@ public: QString name() const override { return QLatin1String("python"); } bool saveRawFileList(const QStringList &rawFileList); - bool saveRawList(const QStringList &rawList, const QString &fileName); + bool saveRawList(const QStringList &rawList, const FilePath &filePath); void parse(); QStringList processEntries(const QStringList &paths, QHash<QString, QString> *map = nullptr) const; - bool writePyProjectFile(const QString &fileName, QString &content, + bool writePyProjectFile(const FilePath &filePath, QString &content, const QStringList &rawList, QString *errorMessage); void triggerParsing() final; @@ -90,14 +90,13 @@ private: static QJsonObject readObjJson(const FilePath &projectFile, QString *errorMessage) { - QFile file(projectFile.toString()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - *errorMessage = Tr::tr("Unable to open \"%1\" for reading: %2") - .arg(projectFile.toUserOutput(), file.errorString()); - return QJsonObject(); + const expected_str<QByteArray> fileContentsResult = projectFile.fileContents(); + if (!fileContentsResult) { + *errorMessage = fileContentsResult.error(); + return {}; } - const QByteArray content = file.readAll(); + const QByteArray content = *fileContentsResult; // This assumes the project file is formed with only one field called // 'files' that has a list associated of the files to include in the project. @@ -268,25 +267,24 @@ void PythonBuildSystem::triggerParsing() bool PythonBuildSystem::saveRawFileList(const QStringList &rawFileList) { - const bool result = saveRawList(rawFileList, projectFilePath().toString()); + const bool result = saveRawList(rawFileList, projectFilePath()); // refresh(PythonProject::Files); return result; } -bool PythonBuildSystem::saveRawList(const QStringList &rawList, const QString &fileName) +bool PythonBuildSystem::saveRawList(const QStringList &rawList, const FilePath &filePath) { - const FilePath filePath = FilePath::fromString(fileName); - FileChangeBlocker changeGuarg(filePath); + const FileChangeBlocker changeGuarg(filePath); bool result = false; // New project file - if (fileName.endsWith(".pyproject")) { + if (filePath.endsWith(".pyproject")) { FileSaver saver(filePath, QIODevice::ReadOnly | QIODevice::Text); if (!saver.hasError()) { QString content = QTextStream(saver.file()).readAll(); if (saver.finalize(ICore::dialogParent())) { QString errorMessage; - result = writePyProjectFile(fileName, content, rawList, &errorMessage); + result = writePyProjectFile(filePath, content, rawList, &errorMessage); if (!errorMessage.isEmpty()) MessageManager::writeDisrupting(errorMessage); } @@ -305,13 +303,13 @@ bool PythonBuildSystem::saveRawList(const QStringList &rawList, const QString &f return result; } -bool PythonBuildSystem::writePyProjectFile(const QString &fileName, QString &content, - const QStringList &rawList, QString *errorMessage) +bool PythonBuildSystem::writePyProjectFile(const FilePath &filePath, QString &content, + const QStringList &rawList, QString *errorMessage) { - QFile file(fileName); + QFile file(filePath.toString()); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - *errorMessage = Tr::tr("Unable to open \"%1\" for reading: %2") - .arg(fileName, file.errorString()); + *errorMessage = Tr::tr("Unable to open \"%1\" for writing: %2") + .arg(filePath.toUserOutput(), file.errorString()); return false; } diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 0da8bebaad..27e29e497e 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -330,7 +330,7 @@ void QMakeStep::doRun() emit buildConfiguration()->buildDirectoryInitialized(); }; - QList<TaskItem> processList = {ProcessTask(setupQMake, onProcessDone, onProcessError)}; + QList<GroupItem> processList = {ProcessTask(setupQMake, onProcessDone, onProcessError)}; if (m_runMakeQmake) processList << ProcessTask(setupMakeQMake, onProcessDone, onProcessError); processList << onGroupDone(onDone); diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index d77dfc7589..bbfcf9d37c 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -1092,7 +1092,7 @@ extend_qtc_plugin(assetexporterplugin extend_qtc_plugin(assetexporterplugin SOURCES_PREFIX assetexporterplugin SOURCES - assetexportdialog.h assetexportdialog.cpp assetexportdialog.ui + assetexportdialog.h assetexportdialog.cpp assetexporter.h assetexporter.cpp assetexporterplugin.h assetexporterplugin.cpp assetexporterview.h assetexporterview.cpp diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp index e9b5ab7082..6484506897 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp @@ -1,19 +1,24 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #include "assetexportdialog.h" -#include "ui_assetexportdialog.h" +#include "../qmldesignertr.h" #include "assetexportpluginconstants.h" #include "filepathmodel.h" #include <coreplugin/fileutils.h> #include <coreplugin/icore.h> + #include <projectexplorer/task.h> #include <projectexplorer/taskhub.h> #include <projectexplorer/project.h> #include <projectexplorer/projectmanager.h> -#include <utils/fileutils.h> + +#include <utils/detailswidget.h> +#include <utils/layoutbuilder.h> #include <utils/outputformatter.h> +#include <utils/pathchooser.h> #include <QCheckBox> #include <QPushButton> @@ -22,13 +27,21 @@ #include <QDialogButtonBox> #include <QMessageBox> #include <QScrollBar> +#include <QGridLayout> +#include <QProgressBar> +#include <QLabel> +#include <QStackedWidget> #include <algorithm> #include <cmath> -namespace { -static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString &str, - Utils::OutputFormat format) { +using namespace ProjectExplorer; +using namespace Utils; + +namespace QmlDesigner { + +static void addFormattedMessage(OutputFormatter *formatter, const QString &str, OutputFormat format) +{ if (!formatter) return; @@ -42,79 +55,81 @@ static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString if (isAtBottom) scroll->setValue(scroll->maximum()); } -} - -using namespace ProjectExplorer; -namespace QmlDesigner { -AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath, +AssetExportDialog::AssetExportDialog(const FilePath &exportPath, AssetExporter &assetExporter, FilePathModel &model, QWidget *parent) : QDialog(parent), m_assetExporter(assetExporter), m_filePathModel(model), - m_ui(new Ui::AssetExportDialog), m_filesView(new QListView), m_exportLogs(new QPlainTextEdit), m_outputFormatter(new Utils::OutputFormatter()) { - m_ui->setupUi(this); + resize(768, 480); + setWindowTitle(Tr::tr("Export Components")); + + m_stackedWidget = new QStackedWidget; + + m_exportProgress = new QProgressBar; + m_exportProgress->setRange(0,0); + + auto optionsWidget = new QWidget; + + auto advancedOptions = new DetailsWidget; + advancedOptions->setSummaryText(tr("Advanced Options")); + advancedOptions->setWidget(optionsWidget); + + m_buttonBox = new QDialogButtonBox; + m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Close); - m_ui->exportPath->setExpectedKind(Utils::PathChooser::Kind::SaveFile); - m_ui->exportPath->setFilePath( + m_exportPath = new PathChooser; + m_exportPath->setExpectedKind(PathChooser::Kind::SaveFile); + m_exportPath->setFilePath( exportPath.pathAppended( ProjectExplorer::ProjectManager::startupProject()->displayName() + ".metadata" )); - m_ui->exportPath->setPromptDialogTitle(tr("Choose Export File")); - m_ui->exportPath->setPromptDialogFilter(tr("Metadata file (*.metadata)")); - m_ui->exportPath->lineEdit()->setReadOnly(true); - m_ui->exportPath->addButton(tr("Open"), this, [this]() { - Core::FileUtils::showInGraphicalShell(Core::ICore::dialogParent(), m_ui->exportPath->filePath()); + m_exportPath->setPromptDialogTitle(tr("Choose Export File")); + m_exportPath->setPromptDialogFilter(tr("Metadata file (*.metadata)")); + m_exportPath->lineEdit()->setReadOnly(true); + m_exportPath->addButton(tr("Open"), this, [this]() { + Core::FileUtils::showInGraphicalShell(Core::ICore::dialogParent(), m_exportPath->filePath()); }); - auto optionsWidget = new QWidget; - m_ui->advancedOptions->setSummaryText(tr("Advanced Options")); - m_ui->advancedOptions->setWidget(optionsWidget); - auto optionsLayout = new QHBoxLayout(optionsWidget); - optionsLayout->setContentsMargins(8, 8, 8, 8); - m_exportAssetsCheck = new QCheckBox(tr("Export assets"), this); m_exportAssetsCheck->setChecked(true); - optionsLayout->addWidget(m_exportAssetsCheck); m_perComponentExportCheck = new QCheckBox(tr("Export components separately"), this); m_perComponentExportCheck->setChecked(false); - optionsLayout->addWidget(m_perComponentExportCheck); - optionsLayout->addStretch(); - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); - m_ui->stackedWidget->addWidget(m_filesView); + m_stackedWidget->addWidget(m_filesView); m_filesView->setModel(&m_filePathModel); m_exportLogs->setReadOnly(true); m_outputFormatter->setPlainTextEdit(m_exportLogs); - m_ui->stackedWidget->addWidget(m_exportLogs); + m_stackedWidget->addWidget(m_exportLogs); switchView(false); - connect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, [this]() { - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + connect(m_buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, [this]() { + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); m_assetExporter.cancel(); }); - m_exportBtn = m_ui->buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); + m_exportBtn = m_buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); m_exportBtn->setEnabled(false); connect(m_exportBtn, &QPushButton::clicked, this, &AssetExportDialog::onExport); connect(&m_filePathModel, &FilePathModel::modelReset, this, [this]() { - m_ui->exportProgress->setRange(0, 1000); - m_ui->exportProgress->setValue(0); + m_exportProgress->setRange(0, 1000); + m_exportProgress->setValue(0); m_exportBtn->setEnabled(true); }); - connect(m_ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, [this]() { + connect(m_buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, [this]() { close(); }); - m_ui->buttonBox->button(QDialogButtonBox::Close)->setVisible(false); + m_buttonBox->button(QDialogButtonBox::Close)->setVisible(false); connect(&m_assetExporter, &AssetExporter::stateChanged, this, &AssetExportDialog::onExportStateChanged); @@ -123,7 +138,22 @@ AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath, connect(TaskHub::instance(), &TaskHub::taskAdded, this, &AssetExportDialog::onTaskAdded); - m_ui->exportProgress->setRange(0,0); + using namespace Layouting; + + Column { + m_exportAssetsCheck, + m_perComponentExportCheck, + st, + noMargin(), + }.attachTo(optionsWidget); + + Column { + Form { Tr::tr("Export path:"), m_exportPath }, + advancedOptions, + m_stackedWidget, + m_exportProgress, + m_buttonBox, + }.attachTo(this); } AssetExportDialog::~AssetExportDialog() @@ -139,7 +169,7 @@ void AssetExportDialog::onExport() TaskHub::clearTasks(Constants::TASK_CATEGORY_ASSET_EXPORT); m_exportLogs->clear(); - Utils::FilePath selectedPath = m_ui->exportPath->filePath(); + Utils::FilePath selectedPath = m_exportPath->filePath(); Utils::FilePath exportPath = m_perComponentExportCheck->isChecked() ? (selectedPath.isDir() ? selectedPath : selectedPath.parentDir()) : selectedPath; @@ -154,28 +184,28 @@ void AssetExportDialog::onExportStateChanged(AssetExporter::ParsingState newStat switch (newState) { case AssetExporter::ParsingState::ExportingDone: m_exportBtn->setVisible(false); - m_ui->buttonBox->button(QDialogButtonBox::Close)->setVisible(true); + m_buttonBox->button(QDialogButtonBox::Close)->setVisible(true); break; default: break; } m_exportBtn->setEnabled(newState == AssetExporter::ParsingState::ExportingDone); - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_assetExporter.isBusy()); + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_assetExporter.isBusy()); } void AssetExportDialog::updateExportProgress(double value) { value = std::max(0.0, std::min(1.0, value)); - m_ui->exportProgress->setValue(std::round(value * 1000)); + m_exportProgress->setValue(std::round(value * 1000)); } void AssetExportDialog::switchView(bool showExportView) { if (showExportView) - m_ui->stackedWidget->setCurrentWidget(m_exportLogs); + m_stackedWidget->setCurrentWidget(m_exportLogs); else - m_ui->stackedWidget->setCurrentWidget(m_filesView); + m_stackedWidget->setCurrentWidget(m_filesView); } void AssetExportDialog::onTaskAdded(const ProjectExplorer::Task &task) diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h index dacab052d4..bf277f82bb 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h @@ -1,25 +1,28 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #pragma once + #include "assetexporter.h" +#include <utils/filepath.h> + #include <QDialog> #include <QStringListModel> -#include "utils/fileutils.h" - -#include <memory> - QT_BEGIN_NAMESPACE class QPushButton; class QCheckBox; +class QDialogButtonBox; class QListView; class QPlainTextEdit; +class QProgressBar; +class QStackedWidget; QT_END_NAMESPACE - namespace Utils { class OutputFormatter; +class PathChooser; } namespace ProjectExplorer { @@ -27,7 +30,7 @@ class Task; } namespace QmlDesigner { -namespace Ui { class AssetExportDialog; } + class FilePathModel; class AssetExportDialog : public QDialog @@ -49,13 +52,16 @@ private: private: AssetExporter &m_assetExporter; FilePathModel &m_filePathModel; - std::unique_ptr<Ui::AssetExportDialog> m_ui; QPushButton *m_exportBtn = nullptr; QCheckBox *m_exportAssetsCheck = nullptr; QCheckBox *m_perComponentExportCheck = nullptr; QListView *m_filesView = nullptr; QPlainTextEdit *m_exportLogs = nullptr; Utils::OutputFormatter *m_outputFormatter = nullptr; + Utils::PathChooser *m_exportPath = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; + QStackedWidget *m_stackedWidget = nullptr; + QProgressBar *m_exportProgress = nullptr; }; -} +} // QmlDesigner diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui deleted file mode 100644 index fa80758867..0000000000 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>QmlDesigner::AssetExportDialog</class> - <widget class="QDialog" name="QmlDesigner::AssetExportDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>768</width> - <height>480</height> - </rect> - </property> - <property name="windowTitle"> - <string>Export Components</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Export path:</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QStackedWidget" name="stackedWidget"/> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QProgressBar" name="exportProgress"> - <property name="maximum"> - <number>1000</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item row="1" column="0" colspan="2"> - <widget class="Utils::DetailsWidget" name="advancedOptions" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>8</height> - </size> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="Utils::PathChooser" name="exportPath" native="true"/> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>Utils::PathChooser</class> - <extends>QWidget</extends> - <header location="global">utils/pathchooser.h</header> - <container>1</container> - </customwidget> - <customwidget> - <class>Utils::DetailsWidget</class> - <extends>QWidget</extends> - <header location="global">utils/detailswidget.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> 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/qmldesignerbase/qmldesignerbaseplugin.cpp b/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp index c59fcbb2ea..703c1cf760 100644 --- a/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp +++ b/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp @@ -21,7 +21,7 @@ class QmlDesignerBasePlugin::Data public: DesignerSettings settings; StudioStyle *style = nullptr; - StudioConfigSettingsPage studioConfigSettingsPage; + std::unique_ptr<StudioConfigSettingsPage> studioConfigSettingsPage; Data() : settings(Core::ICore::settings()) @@ -54,13 +54,14 @@ QStyle *QmlDesignerBasePlugin::style() StudioConfigSettingsPage *QmlDesignerBasePlugin::studioConfigSettingsPage() { - return &global->d->studioConfigSettingsPage; + return global->d->studioConfigSettingsPage.get(); } bool QmlDesignerBasePlugin::initialize(const QStringList &, QString *) { d = std::make_unique<Data>(); - + if (Core::ICore::settings()->value("QML/Designer/StandAloneMode", false).toBool()) + d->studioConfigSettingsPage = std::make_unique<StudioConfigSettingsPage>(); return true; } 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..559bdeb198 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp @@ -107,9 +107,8 @@ void QmlBuildSystem::updateDeploymentData() } ProjectExplorer::DeploymentData deploymentData; - for (const auto &file : m_projectItem->files()) { - deploymentData.addFile(file, targetFile(file).parentDir().toString()); - } + for (const auto &file : m_projectItem->files()) + deploymentData.addFile(file, m_projectItem->targetDirectory()); setDeploymentData(deploymentData); } @@ -160,9 +159,7 @@ void QmlBuildSystem::triggerParsing() Utils::FilePath QmlBuildSystem::canonicalProjectDir() const { - return BuildSystem::target() - ->project() - ->projectFilePath() + return projectFilePath() .canonicalPath() .normalizedPathName() .parentDir(); @@ -188,10 +185,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(projectFilePath().pathAppended(searchPath), QmlJS::Dialect::Qml); + } modelManager->updateProjectInfo(projectInfo, project()); @@ -370,22 +368,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 +395,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 1cce1650ce..77db8b073f 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -61,7 +61,7 @@ private: FilePath qmlRuntimeFilePath() const; void createQtVersionAspect(); - StringAspect *m_qmlViewerAspect = nullptr; + FilePathAspect *m_qmlViewerAspect = nullptr; QmlMainFileAspect *m_qmlMainFileAspect = nullptr; QmlMultiLanguageAspect *m_multiLanguageAspect = nullptr; SelectionAspect *m_qtversionAspect = nullptr; @@ -71,10 +71,9 @@ private: QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id) : RunConfiguration(target, id) { - m_qmlViewerAspect = addAspect<StringAspect>(); + m_qmlViewerAspect = addAspect<FilePathAspect>(); m_qmlViewerAspect->setLabelText(Tr::tr("Override device QML viewer:")); m_qmlViewerAspect->setPlaceHolderText(qmlRuntimeFilePath().toUserOutput()); - m_qmlViewerAspect->setDisplayStyle(StringAspect::PathChooserDisplay); m_qmlViewerAspect->setHistoryCompleter("QmlProjectManager.viewer.history"); m_qmlViewerAspect->setSettingsKey(Constants::QML_VIEWER_KEY); @@ -92,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()) { @@ -115,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 a5cc9cdad8..d9eb88273e 100644 --- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp +++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp @@ -90,11 +90,11 @@ public: private: Group deployRecipe(); - TaskItem checkDirTask(); - TaskItem removeDirTask(); - TaskItem uploadTask(); - TaskItem chmodTask(const DeployableFile &file); - TaskItem chmodTree(); + GroupItem checkDirTask(); + GroupItem removeDirTask(); + GroupItem uploadTask(); + GroupItem chmodTask(const DeployableFile &file); + GroupItem chmodTree(); enum class CheckResult { RemoveDir, SkipRemoveDir, Abort }; CheckResult m_checkResult = CheckResult::Abort; @@ -117,7 +117,7 @@ QList<DeployableFile> collectFilesToUpload(const DeployableFile &deployable) return collected; } -TaskItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() { const auto setupHandler = [this](Process &process) { m_deployLogWindow->appendPlainText(Tr::tr("Checking existence of \"%1\"") @@ -145,7 +145,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() return ProcessTask(setupHandler, doneHandler, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() { const auto setupHandler = [this](Process &process) { if (m_checkResult != CheckResult::RemoveDir) @@ -162,7 +162,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::uploadTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::uploadTask() { const auto setupHandler = [this](FileTransfer &transfer) { if (m_deployableFiles.isEmpty()) { @@ -196,7 +196,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::uploadTask() return FileTransferTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file) +GroupItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file) { const auto setupHandler = [=](Process &process) { process.setCommand({m_device->filePath("chmod"), @@ -215,7 +215,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTree() +GroupItem QnxDeployQtLibrariesDialogPrivate::chmodTree() { const auto setupChmodHandler = [=](TaskTree &tree) { QList<DeployableFile> filesToChmod; @@ -223,7 +223,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTree() if (file.isExecutable()) filesToChmod << file; } - QList<TaskItem> chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList<GroupItem> chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 179649c53b..4720718a86 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 " 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/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 6074eaabaa..714404ec5b 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -75,13 +75,13 @@ public: using FilesToStat = std::function<QList<DeployableFile>(UploadStorage *)>; using StatEndHandler = std::function<void(UploadStorage *, const DeployableFile &, const QDateTime &)>; - TaskItem statTask(UploadStorage *storage, const DeployableFile &file, - StatEndHandler statEndHandler); - TaskItem statTree(const TreeStorage<UploadStorage> &storage, FilesToStat filesToStat, - StatEndHandler statEndHandler); - TaskItem uploadTask(const TreeStorage<UploadStorage> &storage); - TaskItem chmodTask(const DeployableFile &file); - TaskItem chmodTree(const TreeStorage<UploadStorage> &storage); + GroupItem statTask(UploadStorage *storage, const DeployableFile &file, + StatEndHandler statEndHandler); + GroupItem statTree(const TreeStorage<UploadStorage> &storage, FilesToStat filesToStat, + StatEndHandler statEndHandler); + GroupItem uploadTask(const TreeStorage<UploadStorage> &storage); + GroupItem chmodTask(const DeployableFile &file); + GroupItem chmodTree(const TreeStorage<UploadStorage> &storage); IncrementalDeployment m_incremental = IncrementalDeployment::NotSupported; bool m_ignoreMissingFiles = false; @@ -156,9 +156,9 @@ QDateTime GenericDirectUploadStep::timestampFromStat(const DeployableFile &file, return QDateTime::fromSecsSinceEpoch(secsSinceEpoch); } -TaskItem GenericDirectUploadStep::statTask(UploadStorage *storage, - const DeployableFile &file, - StatEndHandler statEndHandler) +GroupItem GenericDirectUploadStep::statTask(UploadStorage *storage, + const DeployableFile &file, + StatEndHandler statEndHandler) { const auto setupHandler = [=](Process &process) { // We'd like to use --format=%Y, but it's not supported by busybox. @@ -173,13 +173,13 @@ TaskItem GenericDirectUploadStep::statTask(UploadStorage *storage, return ProcessTask(setupHandler, endHandler, endHandler); } -TaskItem GenericDirectUploadStep::statTree(const TreeStorage<UploadStorage> &storage, - FilesToStat filesToStat, StatEndHandler statEndHandler) +GroupItem GenericDirectUploadStep::statTree(const TreeStorage<UploadStorage> &storage, + FilesToStat filesToStat, StatEndHandler statEndHandler) { const auto setupHandler = [=](TaskTree &tree) { UploadStorage *storagePtr = storage.activeStorage(); const QList<DeployableFile> files = filesToStat(storagePtr); - QList<TaskItem> statList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList<GroupItem> statList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(files)) { QTC_ASSERT(file.isValid(), continue); statList.append(statTask(storagePtr, file, statEndHandler)); @@ -189,7 +189,7 @@ TaskItem GenericDirectUploadStep::statTree(const TreeStorage<UploadStorage> &sto return TaskTreeTask(setupHandler); } -TaskItem GenericDirectUploadStep::uploadTask(const TreeStorage<UploadStorage> &storage) +GroupItem GenericDirectUploadStep::uploadTask(const TreeStorage<UploadStorage> &storage) { const auto setupHandler = [this, storage](FileTransfer &transfer) { if (storage->filesToUpload.isEmpty()) { @@ -229,7 +229,7 @@ TaskItem GenericDirectUploadStep::uploadTask(const TreeStorage<UploadStorage> &s return FileTransferTask(setupHandler, {}, errorHandler); } -TaskItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) +GroupItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) { const auto setupHandler = [=](Process &process) { process.setCommand({deviceConfiguration()->filePath("chmod"), @@ -248,7 +248,7 @@ TaskItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem GenericDirectUploadStep::chmodTree(const TreeStorage<UploadStorage> &storage) +GroupItem GenericDirectUploadStep::chmodTree(const TreeStorage<UploadStorage> &storage) { const auto setupChmodHandler = [=](TaskTree &tree) { QList<DeployableFile> filesToChmod; @@ -256,7 +256,7 @@ TaskItem GenericDirectUploadStep::chmodTree(const TreeStorage<UploadStorage> &st if (file.isExecutable()) filesToChmod << file; } - QList<TaskItem> chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList<GroupItem> chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index cc44dddb3c..59af192eaa 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -978,7 +978,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/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 37aea36112..5392fb4245 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -34,20 +34,20 @@ public: QStringList commandsToTest() const; - TaskItem echoTask(const QString &contents) const; - TaskItem unameTask() const; - TaskItem gathererTask() const; - TaskItem transferTask(FileTransferMethod method, - const TreeStorage<TransferStorage> &storage) const; - TaskItem transferTasks() const; - TaskItem commandTask(const QString &commandName) const; - TaskItem commandTasks() const; + GroupItem echoTask(const QString &contents) const; + GroupItem unameTask() const; + GroupItem gathererTask() const; + GroupItem transferTask(FileTransferMethod method, + const TreeStorage<TransferStorage> &storage) const; + GroupItem transferTasks() const; + GroupItem commandTask(const QString &commandName) const; + GroupItem commandTasks() const; GenericLinuxDeviceTester *q = nullptr; IDevice::Ptr m_device; std::unique_ptr<TaskTree> m_taskTree; QStringList m_extraCommands; - QList<TaskItem> m_extraTests; + QList<GroupItem> m_extraTests; }; QStringList GenericLinuxDeviceTesterPrivate::commandsToTest() const @@ -90,7 +90,7 @@ QStringList GenericLinuxDeviceTesterPrivate::commandsToTest() const return commands; } -TaskItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) const +GroupItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) const { const auto setup = [this, contents](Process &process) { emit q->progressMessage(Tr::tr("Sending echo to device...")); @@ -114,7 +114,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) cons return ProcessTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::unameTask() const +GroupItem GenericLinuxDeviceTesterPrivate::unameTask() const { const auto setup = [this](Process &process) { emit q->progressMessage(Tr::tr("Checking kernel version...")); @@ -136,7 +136,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::unameTask() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::gathererTask() const +GroupItem GenericLinuxDeviceTesterPrivate::gathererTask() const { const auto setup = [this](DeviceUsedPortsGatherer &gatherer) { emit q->progressMessage(Tr::tr("Checking if specified ports are available...")); @@ -164,8 +164,8 @@ TaskItem GenericLinuxDeviceTesterPrivate::gathererTask() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method, - const TreeStorage<TransferStorage> &storage) const +GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method, + const TreeStorage<TransferStorage> &storage) const { const auto setup = [this, method](FileTransfer &transfer) { emit q->progressMessage(Tr::tr("Checking whether \"%1\" works...") @@ -216,7 +216,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method return FileTransferTestTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::transferTasks() const +GroupItem GenericLinuxDeviceTesterPrivate::transferTasks() const { TreeStorage<TransferStorage> storage; return Group { @@ -231,7 +231,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::transferTasks() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName) const +GroupItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName) const { const auto setup = [this, commandName](Process &process) { emit q->progressMessage(Tr::tr("%1...").arg(commandName)); @@ -252,9 +252,9 @@ TaskItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName return ProcessTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::commandTasks() const +GroupItem GenericLinuxDeviceTesterPrivate::commandTasks() const { - QList<TaskItem> tasks {continueOnError}; + QList<GroupItem> tasks {continueOnError}; tasks.append(onGroupSetup([this] { emit q->progressMessage(Tr::tr("Checking if required commands are available...")); })); @@ -279,7 +279,7 @@ void GenericLinuxDeviceTester::setExtraCommandsToTest(const QStringList &extraCo d->m_extraCommands = extraCommands; } -void GenericLinuxDeviceTester::setExtraTests(const QList<TaskItem> &extraTests) +void GenericLinuxDeviceTester::setExtraTests(const QList<GroupItem> &extraTests) { d->m_extraTests = extraTests; } @@ -295,7 +295,7 @@ void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguratio d->m_taskTree.release()->deleteLater(); }; - QList<TaskItem> taskItems = { + QList<GroupItem> taskItems = { d->echoTask("Hello"), // No quoting necessary d->echoTask("Hello Remote World!"), // Checks quoting, too. d->unameTask(), diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h index 3fda1ecb3a..787d22fd10 100644 --- a/src/plugins/remotelinux/linuxdevicetester.h +++ b/src/plugins/remotelinux/linuxdevicetester.h @@ -7,7 +7,7 @@ #include <projectexplorer/devicesupport/idevice.h> -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace RemoteLinux { @@ -22,7 +22,7 @@ public: ~GenericLinuxDeviceTester() override; void setExtraCommandsToTest(const QStringList &extraCommands); - void setExtraTests(const QList<Tasking::TaskItem> &extraTests); + void setExtraTests(const QList<Tasking::GroupItem> &extraTests); void testDevice(const ProjectExplorer::IDevice::Ptr &deviceConfiguration) override; void stopTest() override; diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp index 84eb47b8cc..317b08bb77 100644 --- a/src/plugins/remotelinux/rsyncdeploystep.cpp +++ b/src/plugins/remotelinux/rsyncdeploystep.cpp @@ -35,8 +35,8 @@ public: private: bool isDeploymentNecessary() const final; Group deployRecipe() final; - TaskItem mkdirTask(); - TaskItem transferTask(); + GroupItem mkdirTask(); + GroupItem transferTask(); mutable FilesToTransfer m_files; bool m_ignoreMissingFiles = false; @@ -85,7 +85,7 @@ bool RsyncDeployStep::isDeploymentNecessary() const return !m_files.empty(); } -TaskItem RsyncDeployStep::mkdirTask() +GroupItem RsyncDeployStep::mkdirTask() { const auto setupHandler = [this](Process &process) { QStringList remoteDirs; @@ -113,7 +113,7 @@ TaskItem RsyncDeployStep::mkdirTask() return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem RsyncDeployStep::transferTask() +GroupItem RsyncDeployStep::transferTask() { const auto setupHandler = [this](FileTransfer &transfer) { transfer.setTransferMethod(FileTransferMethod::Rsync); diff --git a/src/plugins/remotelinux/tarpackagedeploystep.cpp b/src/plugins/remotelinux/tarpackagedeploystep.cpp index 6b50ca4dce..6deaea9066 100644 --- a/src/plugins/remotelinux/tarpackagedeploystep.cpp +++ b/src/plugins/remotelinux/tarpackagedeploystep.cpp @@ -55,8 +55,8 @@ private: QString remoteFilePath() const; bool isDeploymentNecessary() const final; Group deployRecipe() final; - TaskItem uploadTask(); - TaskItem installTask(); + GroupItem uploadTask(); + GroupItem installTask(); FilePath m_packageFilePath; }; @@ -71,7 +71,7 @@ bool TarPackageDeployStep::isDeploymentNecessary() const return hasLocalFileChanged(DeployableFile(m_packageFilePath, {})); } -TaskItem TarPackageDeployStep::uploadTask() +GroupItem TarPackageDeployStep::uploadTask() { const auto setupHandler = [this](FileTransfer &transfer) { const FilesToTransfer files {{m_packageFilePath, @@ -90,7 +90,7 @@ TaskItem TarPackageDeployStep::uploadTask() return FileTransferTask(setupHandler, doneHandler, errorHandler); } -TaskItem TarPackageDeployStep::installTask() +GroupItem TarPackageDeployStep::installTask() { const auto setupHandler = [this](Process &process) { const QString cmdLine = QLatin1String("cd / && tar xvf ") + remoteFilePath() diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index 1a2f5e55e8..7880bd78eb 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,6 +3,8 @@ #include "silversearcherparser.h" +#include <QPromise> + using namespace Utils; namespace SilverSearcher { diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 61a8e429d6..b919bf2939 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -105,9 +105,10 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */) return; auto studioWelcomePlugin = qobject_cast<StudioWelcome::Internal::StudioWelcomePlugin *>(plugin); - - if (studioWelcomePlugin) { - QObject::connect(QmlDesigner::QmlDesignerBasePlugin::studioConfigSettingsPage(), + QmlDesigner::StudioConfigSettingsPage *settingsPage + = QmlDesigner::QmlDesignerBasePlugin::studioConfigSettingsPage(); + if (studioWelcomePlugin && settingsPage) { + QObject::connect(settingsPage, &QmlDesigner::StudioConfigSettingsPage::examplesDownloadPathChanged, this, &DataModelDownloader::targetPathMustChange); diff --git a/src/plugins/terminal/shellintegration.cpp b/src/plugins/terminal/shellintegration.cpp index d8e26f94ce..d981dc7269 100644 --- a/src/plugins/terminal/shellintegration.cpp +++ b/src/plugins/terminal/shellintegration.cpp @@ -85,7 +85,8 @@ void ShellIntegration::onOsc(int cmd, const VTermStringFragment &fragment) emit currentDirChanged(FilePath::fromUserInput(value.toString()).path()); } else if (cmd == 7) { - emit currentDirChanged(FilePath::fromUserInput(d).path()); + const QString decoded = QUrl::fromPercentEncoding(d.toUtf8()); + emit currentDirChanged(FilePath::fromUserInput(decoded).path()); } else if (cmd == 133) { qCDebug(integrationLog) << "OSC 133:" << data; } else if (cmd == 633 && command.length() == 1) { diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index 7e9cae7539..965e3ba651 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -87,9 +87,10 @@ TerminalPane::TerminalPane(QObject *parent) updateEscButton(); - connect(m_escSettingButton, &QToolButton::toggled, this, [this] { + connect(m_escSettingButton, &QToolButton::toggled, this, [this, updateEscButton] { TerminalSettings::instance().sendEscapeToTerminal.setValue(m_escSettingButton->isChecked()); TerminalSettings::instance().writeSettings(ICore::settings()); + updateEscButton(); }); connect(&TerminalSettings::instance(), &TerminalSettings::applied, this, updateEscButton); diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 5027d39029..b08038ee29 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -72,7 +72,7 @@ static constexpr std::chrono::milliseconds minRefreshInterval = 1s / 30; TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) : QAbstractScrollArea(parent) - , m_context(Utils::Id("TerminalWidget_").withSuffix((size_t) this)) + , m_context(Utils::Id("TerminalWidget_").withSuffix(QString::number((uintptr_t) this))) , m_openParameters(openParameters) , m_lastFlush(std::chrono::system_clock::now()) , m_lastDoubleClick(std::chrono::system_clock::now()) @@ -252,23 +252,40 @@ void TerminalWidget::setupColors() update(); } +static RegisteredAction registerAction(Id commandId, const Context &context) +{ + QAction *action = new QAction; + ActionManager::registerAction(action, commandId, context); + + return RegisteredAction(action, [commandId](QAction *a) { + ActionManager::unregisterAction(a, commandId); + delete a; + }); +} + void TerminalWidget::setupActions() { - 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); - - 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); + 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); m_exit = unlockGlobalAction(Core::Constants::EXIT, m_context); m_options = unlockGlobalAction(Core::Constants::OPTIONS, m_context); @@ -401,7 +418,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) @@ -1095,7 +1112,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); diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index 4b82e4355a..78e50db7ff 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -25,6 +25,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 { @@ -239,13 +240,13 @@ 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; + RegisteredAction m_copy; + RegisteredAction m_paste; + RegisteredAction m_clearSelection; + RegisteredAction m_clearTerminal; + RegisteredAction m_moveCursorWordLeft; + RegisteredAction m_moveCursorWordRight; + RegisteredAction m_close; UnlockedGlobalAction m_findInDocument; UnlockedGlobalAction m_exit; 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/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 99f37d05ea..285d42fd3d 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -29,6 +29,7 @@ #include <QSettings> #include <QHash> #include <QPair> +#include <QPromise> #include <QStringListModel> #include <QFutureWatcher> #include <QPointer> diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 9bb3d97f7d..203ecc36e2 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -4,10 +4,10 @@ #include "basehoverhandler.h" #include "texteditor.h" -#include <utils/executeondestruction.h> #include <utils/qtcassert.h> #include <utils/tooltip/tooltip.h> +#include <QScopeGuard> #include <QVBoxLayout> namespace TextEditor { @@ -121,7 +121,7 @@ void BaseHoverHandler::process(TextEditorWidget *widget, int pos, ReportPriority void BaseHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const auto cleanup = qScopeGuard([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 430b7252cd..0da6571da8 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -18,13 +18,13 @@ #include <coreplugin/editormanager/editormanager.h> #include <extensionsystem/pluginmanager.h> #include <utils/algorithm.h> -#include <utils/executeondestruction.h> #include <utils/qtcassert.h> #include <QKeyEvent> #include <QList> #include <QObject> #include <QScopedPointer> +#include <QScopeGuard> #include <QTimer> using namespace TextEditor::Internal; @@ -158,7 +158,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, bool isUpdate) { // make sure to cleanup old proposals if we cannot find a new assistant - Utils::ExecuteOnDestruction earlyReturnContextClear([this] { destroyContext(); }); + auto cleanup = qScopeGuard([this] { destroyContext(); }); if (isWaitingForProposal()) cancelCurrentRequest(); @@ -179,7 +179,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, QTC_ASSERT(assistInterface, return); // We got an assist provider and interface so no need to reset the current context anymore - earlyReturnContextClear.reset({}); + cleanup.dismiss(); m_assistKind = kind; m_requestProvider = provider; diff --git a/src/plugins/texteditor/colorpreviewhoverhandler.cpp b/src/plugins/texteditor/colorpreviewhoverhandler.cpp index 181ba28e96..1a66392c55 100644 --- a/src/plugins/texteditor/colorpreviewhoverhandler.cpp +++ b/src/plugins/texteditor/colorpreviewhoverhandler.cpp @@ -5,12 +5,12 @@ #include "texteditor.h" #include <coreplugin/icore.h> -#include <utils/executeondestruction.h> #include <utils/tooltip/tooltip.h> #include <utils/qtcassert.h> -#include <QPoint> #include <QColor> +#include <QPoint> +#include <QScopeGuard> #include <QTextBlock> using namespace Core; @@ -333,10 +333,9 @@ static QColor colorFromFuncAndArgs(const QString &func, const QStringList &args) } void ColorPreviewHoverHandler::identifyMatch(TextEditorWidget *editorWidget, - int pos, - ReportPriority report) + int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const auto cleanup = qScopeGuard([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/markdowneditor.cpp b/src/plugins/texteditor/markdowneditor.cpp index 9c89636df8..90ca41283e 100644 --- a/src/plugins/texteditor/markdowneditor.cpp +++ b/src/plugins/texteditor/markdowneditor.cpp @@ -30,7 +30,7 @@ const char MARKDOWNVIEWER_MIME_TYPE[] = "text/markdown"; const char MARKDOWNVIEWER_TEXTEDITOR_RIGHT[] = "Markdown.TextEditorRight"; const char MARKDOWNVIEWER_SHOW_EDITOR[] = "Markdown.ShowEditor"; const char MARKDOWNVIEWER_SHOW_PREVIEW[] = "Markdown.ShowPreview"; -const bool kTextEditorRightDefault = true; +const bool kTextEditorRightDefault = false; const bool kShowEditorDefault = true; const bool kShowPreviewDefault = true; @@ -67,8 +67,8 @@ public: context->setContext(Core::Context(MARKDOWNVIEWER_TEXT_CONTEXT)); Core::ICore::addContextObject(context); + m_splitter->addWidget(m_textEditorWidget); // sets splitter->focusWidget() on non-Windows m_splitter->addWidget(m_previewWidget); - m_splitter->addWidget(m_textEditorWidget); setContext(Core::Context(MARKDOWNVIEWER_ID)); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index ecb617aed7..2c8ff59701 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -50,7 +50,6 @@ #include <utils/algorithm.h> #include <utils/camelcasecursor.h> #include <utils/dropsupport.h> -#include <utils/executeondestruction.h> #include <utils/fadingindicator.h> #include <utils/filesearch.h> #include <utils/fileutils.h> @@ -91,9 +90,10 @@ #include <QPropertyAnimation> #include <QDrag> #include <QRegularExpression> -#include <QSequentialAnimationGroup> +#include <QScopeGuard> #include <QScreen> #include <QScrollBar> +#include <QSequentialAnimationGroup> #include <QShortcut> #include <QStyle> #include <QStyleFactory> @@ -1435,7 +1435,7 @@ void TextEditorWidgetPrivate::print(QPrinter *printer) return; doc = doc->clone(doc); - Utils::ExecuteOnDestruction docDeleter([doc]() { delete doc; }); + const auto cleanup = qScopeGuard([doc] { delete doc; }); QTextOption opt = doc->defaultTextOption(); opt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -5284,7 +5284,7 @@ void TextEditorWidgetPrivate::paintTextMarks(QPainter &painter, const ExtraAreaP int yoffset = blockBoundingRect.top(); painter.save(); - Utils::ExecuteOnDestruction eod([&painter, size, yoffset, xoffset, overrideIcon]() { + const auto cleanup = qScopeGuard([&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 749cbbbec6..4891d9e8fd 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -135,7 +135,7 @@ void UpdateInfoPlugin::startCheckForUpdates() d->m_updateOutput = process.cleanedStdOut(); }; - QList<TaskItem> tasks { ProcessTask(setupUpdate, updateDone) }; + QList<GroupItem> tasks { ProcessTask(setupUpdate, updateDone) }; if (d->m_settings.checkForQtVersions) { const auto setupPackages = [doSetup](Process &process) { doSetup(process, {"se", "qt[.]qt[0-9][.][0-9]+$", "-g", "*=false,ifw.package.*=true"}); diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp index d286164b5b..e0c4ba4af6 100644 --- a/src/plugins/vcsbase/commonvcssettings.cpp +++ b/src/plugins/vcsbase/commonvcssettings.cpp @@ -6,18 +6,13 @@ #include "vcsbaseconstants.h" #include "vcsbasetr.h" -#include <coreplugin/icore.h> -#include <coreplugin/iversioncontrol.h> #include <coreplugin/vcsmanager.h> -#include <utils/algorithm.h> #include <utils/environment.h> #include <utils/hostosinfo.h> #include <utils/layoutbuilder.h> -#include <QDebug> -#include <QPushButton> - +using namespace Core; using namespace Utils; namespace VcsBase::Internal { @@ -33,10 +28,24 @@ static QString sshPasswordPromptDefault() return QLatin1String("ssh-askpass"); } +static CommonVcsSettings *s_instance; + +CommonVcsSettings &commonSettings() +{ + return *s_instance; +} + CommonVcsSettings::CommonVcsSettings() { + s_instance = this; + setSettingsGroup("VCS"); - setAutoApply(false); + setId(Constants::VCS_COMMON_SETTINGS_ID); + setDisplayName(Tr::tr("General")); + setCategory(Constants::VCS_SETTINGS_CATEGORY); + // The following act as blueprint for other pages in the same category: + setDisplayCategory(Tr::tr("Version Control")); + setCategoryIconPath(":/vcsbase/images/settingscategory_vcs.png"); nickNameMailMap.setSettingsKey("NickNameMailMap"); nickNameMailMap.setExpectedKind(PathChooser::File); @@ -76,69 +85,37 @@ CommonVcsSettings::CommonVcsSettings() lineWrapWidth.setSettingsKey("LineWrapWidth"); lineWrapWidth.setSuffix(Tr::tr(" characters")); lineWrapWidth.setDefaultValue(72); -} - -// CommonSettingsWidget - -class CommonSettingsWidget final : public Core::IOptionsPageWidget -{ -public: - CommonSettingsWidget(CommonOptionsPage *page) - { - CommonVcsSettings &s = page->settings(); - - auto cacheResetButton = new QPushButton(Tr::tr("Reset VCS Cache")); - cacheResetButton->setToolTip(Tr::tr("Reset information about which " - "version control system handles which directory.")); - - auto updatePath = [&s] { - Environment env; - env.appendToPath(Core::VcsManager::additionalToolsPath()); - s.sshPasswordPrompt.setEnvironment(env); - }; + setLayouter([this] { using namespace Layouting; - Column { - Row { s.lineWrap, s.lineWrapWidth, st }, + return Column { + Row { lineWrap, lineWrapWidth, st }, Form { - s.submitMessageCheckScript, br, - s.nickNameMailMap, br, - s.nickNameFieldListFile, br, - s.sshPasswordPrompt, br, - {}, cacheResetButton + submitMessageCheckScript, br, + nickNameMailMap, br, + nickNameFieldListFile, br, + sshPasswordPrompt, br, + empty, + PushButton { + text(Tr::tr("Reset VCS Cache")), + tooltip(Tr::tr("Reset information about which " + "version control system handles which directory.")), + onClicked(&VcsManager::clearVersionControlCache) + } } - }.attachTo(this); - - updatePath(); - - connect(Core::VcsManager::instance(), &Core::VcsManager::configurationChanged, - this, updatePath); - connect(cacheResetButton, &QPushButton::clicked, - Core::VcsManager::instance(), &Core::VcsManager::clearVersionControlCache); - - setOnApply([&s] { - if (s.isDirty()) { - s.apply(); - s.writeSettings(Core::ICore::settings()); - emit s.settingsChanged(); - } - }); - } -}; + }; + }); -// CommonOptionsPage + auto updatePath = [this] { + Environment env; + env.appendToPath(VcsManager::additionalToolsPath()); + sshPasswordPrompt.setEnvironment(env); + }; -CommonOptionsPage::CommonOptionsPage() -{ - m_settings.readSettings(Core::ICore::settings()); + updatePath(); + connect(VcsManager::instance(), &VcsManager::configurationChanged, this, updatePath); - setId(Constants::VCS_COMMON_SETTINGS_ID); - setDisplayName(Tr::tr("General")); - setCategory(Constants::VCS_SETTINGS_CATEGORY); - // The following act as blueprint for other pages in the same category: - setDisplayCategory(Tr::tr("Version Control")); - setCategoryIconPath(":/vcsbase/images/settingscategory_vcs.png"); - setWidgetCreator([this] { return new CommonSettingsWidget(this); }); + readSettings(); } } // VcsBase::Internal diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h index a5005f252a..0f591b2711 100644 --- a/src/plugins/vcsbase/commonvcssettings.h +++ b/src/plugins/vcsbase/commonvcssettings.h @@ -4,15 +4,12 @@ #pragma once #include <coreplugin/dialogs/ioptionspage.h> - -#include <utils/aspects.h> +#include <coreplugin/iversioncontrol.h> namespace VcsBase::Internal { -class CommonVcsSettings : public Utils::AspectContainer +class CommonVcsSettings : public Core::PagedSettings { - Q_OBJECT - public: CommonVcsSettings(); @@ -26,20 +23,8 @@ public: Utils::BoolAspect lineWrap{this}; Utils::IntegerAspect lineWrapWidth{this}; - -signals: - void settingsChanged(); }; -class CommonOptionsPage final : public Core::IOptionsPage -{ -public: - CommonOptionsPage(); - - CommonVcsSettings &settings() { return m_settings; } - -private: - CommonVcsSettings m_settings; -}; +CommonVcsSettings &commonSettings(); } // VcsBase::Internal diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index 696e96b291..b60abaeb5f 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -45,7 +45,7 @@ TreeStorage<QString> VcsBaseDiffEditorController::inputStorage() const return d->m_inputStorage; } -TaskItem VcsBaseDiffEditorController::postProcessTask() +GroupItem VcsBaseDiffEditorController::postProcessTask() { const auto setupDiffProcessor = [this](Async<QList<FileData>> &async) { const QString *storage = inputStorage().activeStorage(); diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h index 63976bc26c..e4b8880506 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h @@ -29,7 +29,7 @@ public: protected: Tasking::TreeStorage<QString> inputStorage() const; - Tasking::TaskItem postProcessTask(); + Tasking::GroupItem postProcessTask(); void setupCommand(Utils::Process &process, const QStringList &args) const; diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index b72657cdb3..b73f97dd79 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -750,7 +750,7 @@ FilePath source(IDocument *document) void setProcessEnvironment(Environment *e) { - const QString prompt = Internal::VcsPlugin::instance()->settings().sshPasswordPrompt.value(); + const QString prompt = Internal::commonSettings().sshPasswordPrompt().path(); if (!prompt.isEmpty()) e->set("SSH_ASKPASS", prompt); } diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 5ddab0da77..03eaa49c85 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -103,11 +103,6 @@ namespace VcsBase { using namespace Internal; using namespace Utils; -static inline QString submitMessageCheckScript() -{ - return VcsPlugin::instance()->settings().submitMessageCheckScript.value(); -} - class VcsBaseSubmitEditorPrivate { public: @@ -176,15 +171,15 @@ void VcsBaseSubmitEditor::setParameters(const VcsBaseSubmitEditorParameters &par connect(descriptionEdit, &QTextEdit::textChanged, this, &VcsBaseSubmitEditor::fileContentsChanged); - const CommonVcsSettings &settings = VcsPlugin::instance()->settings(); + const CommonVcsSettings &settings = commonSettings(); // Add additional context menu settings - if (!settings.submitMessageCheckScript.value().isEmpty() + if (!settings.submitMessageCheckScript().isEmpty() || !settings.nickNameMailMap.value().isEmpty()) { auto sep = new QAction(this); sep->setSeparator(true); d->m_widget->addDescriptionEditContextMenuAction(sep); // Run check action - if (!settings.submitMessageCheckScript.value().isEmpty()) { + if (!settings.submitMessageCheckScript().isEmpty()) { auto checkAction = new QAction(Tr::tr("Check Message"), this); connect(checkAction, &QAction::triggered, this, &VcsBaseSubmitEditor::slotCheckSubmitMessage); @@ -203,7 +198,7 @@ void VcsBaseSubmitEditor::setParameters(const VcsBaseSubmitEditorParameters &par // wrapping. etc slotUpdateEditorSettings(); - connect(VcsPlugin::instance(), &VcsPlugin::settingsChanged, + connect(&settings, &CommonVcsSettings::changed, this, &VcsBaseSubmitEditor::slotUpdateEditorSettings); connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, [this] { @@ -229,9 +224,8 @@ VcsBaseSubmitEditor::~VcsBaseSubmitEditor() void VcsBaseSubmitEditor::slotUpdateEditorSettings() { - const CommonVcsSettings &s = VcsPlugin::instance()->settings(); - setLineWrapWidth(s.lineWrapWidth()); - setLineWrap(s.lineWrap()); + setLineWrapWidth(commonSettings().lineWrapWidth()); + setLineWrap(commonSettings().lineWrap()); } // Return a trimmed list of non-empty field texts @@ -527,7 +521,7 @@ void VcsBaseSubmitEditor::slotCheckSubmitMessage() bool VcsBaseSubmitEditor::checkSubmitMessage(QString *errorMessage) const { - const QString checkScript = submitMessageCheckScript(); + const QString checkScript = commonSettings().submitMessageCheckScript.value(); if (checkScript.isEmpty()) return true; QApplication::setOverrideCursor(Qt::WaitCursor); diff --git a/src/plugins/vcsbase/vcsplugin.cpp b/src/plugins/vcsbase/vcsplugin.cpp index 0596f406b8..c61c8e0bec 100644 --- a/src/plugins/vcsbase/vcsplugin.cpp +++ b/src/plugins/vcsbase/vcsplugin.cpp @@ -40,7 +40,7 @@ public: explicit VcsPluginPrivate(VcsPlugin *plugin) : q(plugin) { - QObject::connect(&m_settingsPage.settings(), &CommonVcsSettings::settingsChanged, + QObject::connect(&m_settings, &AspectContainer::changed, [this] { slotSettingsChanged(); }); slotSettingsChanged(); } @@ -57,7 +57,7 @@ public: void populateNickNameModel() { QString errorMessage; - if (!NickNameDialog::populateModelFromMailCapFile(m_settingsPage.settings().nickNameMailMap.filePath(), + if (!NickNameDialog::populateModelFromMailCapFile(m_settings.nickNameMailMap(), m_nickNameModel, &errorMessage)) { qWarning("%s", qPrintable(errorMessage)); @@ -71,7 +71,7 @@ public: } VcsPlugin *q; - CommonOptionsPage m_settingsPage; + CommonVcsSettings m_settings; QStandardItemModel *m_nickNameModel = nullptr; }; @@ -101,9 +101,6 @@ void VcsPlugin::initialize() return result; }); - connect(&d->m_settingsPage.settings(), &CommonVcsSettings::settingsChanged, - this, &VcsPlugin::settingsChanged); - JsonWizardFactory::registerPageFactory(new Internal::VcsConfigurationPageFactory); JsonWizardFactory::registerPageFactory(new Internal::VcsCommandPageFactory); @@ -146,11 +143,6 @@ VcsPlugin *VcsPlugin::instance() return m_instance; } -CommonVcsSettings &VcsPlugin::settings() const -{ - return d->m_settingsPage.settings(); -} - /* Delayed creation/update of the nick name model. */ QStandardItemModel *VcsPlugin::nickNameModel() { diff --git a/src/plugins/vcsbase/vcsplugin.h b/src/plugins/vcsbase/vcsplugin.h index 6d4b35c11f..44be10b23e 100644 --- a/src/plugins/vcsbase/vcsplugin.h +++ b/src/plugins/vcsbase/vcsplugin.h @@ -15,8 +15,6 @@ class VcsBaseSubmitEditor; namespace Internal { -class CommonVcsSettings; - class VcsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT @@ -30,15 +28,12 @@ public: static VcsPlugin *instance(); - CommonVcsSettings &settings() const; - // Model of user nick names used for the submit // editor. Stored centrally here to achieve delayed // initialization and updating on settings change. QStandardItemModel *nickNameModel(); signals: - void settingsChanged(); void submitEditorAboutToClose(VcsBase::VcsBaseSubmitEditor *e, bool *result); private: diff --git a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp index 8a982f5cdd..26999ef2a2 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp @@ -581,7 +581,7 @@ void ObjectNodeInstance::refreshProperty(const PropertyName &name) if (oldValue.type() == 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/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/CMakeLists.txt b/tests/auto/solutions/tasking/CMakeLists.txt index a425250a5a..f55c3b1c7b 100644 --- a/tests/auto/solutions/tasking/CMakeLists.txt +++ b/tests/auto/solutions/tasking/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_solutions_tasking - DEPENDS Tasking + DEPENDS Tasking Qt::Network SOURCES tst_tasking.cpp ) diff --git a/tests/auto/solutions/tasking/tasking.qbs b/tests/auto/solutions/tasking/tasking.qbs index f099edb370..d6ffa88492 100644 --- a/tests/auto/solutions/tasking/tasking.qbs +++ b/tests/auto/solutions/tasking/tasking.qbs @@ -1,6 +1,7 @@ QtcAutotest { name: "Tasking autotest" + Depends { name: "Qt"; submodules: ["network"] } Depends { name: "Tasking" } files: "tst_tasking.cpp" diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 294bea71b7..69d87e8188 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -197,8 +197,8 @@ public: TASKING_DECLARE_TASK(TickAndDoneTask, TickAndDoneTaskAdapter); template <typename SharedBarrierType> -TaskItem createBarrierAdvance(const TreeStorage<CustomStorage> &storage, - const SharedBarrierType &barrier, int taskId) +GroupItem createBarrierAdvance(const TreeStorage<CustomStorage> &storage, + const SharedBarrierType &barrier, int taskId) { return TickAndDoneTask([storage, barrier, taskId](TickAndDone &tickAndDone) { tickAndDone.setInterval(1ms); @@ -253,7 +253,7 @@ void tst_Tasking::testTree_data() }; const auto createTask = [storage, setupTask, setupDone, setupError]( - int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { + int taskId, bool successTask, milliseconds timeout = 0ms) -> GroupItem { if (successTask) return TestTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); const Group root { diff --git a/tests/auto/utils/async/tst_async.cpp b/tests/auto/utils/async/tst_async.cpp index 5d4a81dc96..0e8bc1e2b0 100644 --- a/tests/auto/utils/async/tst_async.cpp +++ b/tests/auto/utils/async/tst_async.cpp @@ -500,7 +500,7 @@ void tst_Async::mapReduce_data() using SetupHandler = std::function<void(Async<int> &task, int input)>; using DoneHandler = std::function<void()>; - const auto createTask = [=](const TaskItem &executeMode, + const auto createTask = [=](const GroupItem &executeMode, const SetupHandler &setupHandler, const DoneHandler &doneHandler) { return Group { diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs index 66c480c7a6..35d08815d2 100644 --- a/tests/manual/manual.qbs +++ b/tests/manual/manual.qbs @@ -15,6 +15,7 @@ Project { "shootout/shootout.qbs", "subdirfileiterator/subdirfileiterator.qbs", "tasking/demo/demo.qbs", + "tasking/imagescaling/imagescaling.qbs", "widgets/widgets.qbs", ] } diff --git a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp index 882a9993a2..50bbd222c9 100644 --- a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp +++ b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp @@ -128,7 +128,7 @@ private slots: async.setConcurrentCallData(generate, parentPath, templateFile, s_treeDepth); }; }; - QList<TaskItem> tasks {parallel}; + QList<GroupItem> tasks {parallel}; for (int i = 0; i < tasksCount; ++i) { const QString dirName = QString("%1%2").arg(s_dirPrefix).arg(i); QVERIFY(parentDir.mkdir(dirName)); @@ -153,7 +153,7 @@ private slots: async.setConcurrentCallData(removeTree, parentPath); }; }; - QList<TaskItem> tasks {parallel}; + QList<GroupItem> tasks {parallel}; const int tasksCount = QThread::idealThreadCount(); for (int i = 0; i < tasksCount; ++i) { const QString dirName = QString("%1%2").arg(s_dirPrefix).arg(i); diff --git a/tests/manual/tasking/CMakeLists.txt b/tests/manual/tasking/CMakeLists.txt index a16f5f1220..a27004eb3e 100644 --- a/tests/manual/tasking/CMakeLists.txt +++ b/tests/manual/tasking/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(demo) +add_subdirectory(imagescaling) diff --git a/tests/manual/tasking/demo/CMakeLists.txt b/tests/manual/tasking/demo/CMakeLists.txt index bdd790cd89..7597e74d60 100644 --- a/tests/manual/tasking/demo/CMakeLists.txt +++ b/tests/manual/tasking/demo/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_test(tst_tasking_demo MANUALTEST - DEPENDS Tasking Qt::Widgets + DEPENDS Tasking Qt::Widgets Qt::Network SOURCES demo.qrc main.cpp diff --git a/tests/manual/tasking/demo/demo.qbs b/tests/manual/tasking/demo/demo.qbs index 2a54143c41..9cf856bca2 100644 --- a/tests/manual/tasking/demo/demo.qbs +++ b/tests/manual/tasking/demo/demo.qbs @@ -4,7 +4,7 @@ QtcManualtest { name: "Tasking demo" type: ["application"] - Depends { name: "Qt"; submodules: ["widgets"] } + Depends { name: "Qt"; submodules: ["network", "widgets"] } Depends { name: "Tasking" } files: [ diff --git a/tests/manual/tasking/demo/main.cpp b/tests/manual/tasking/demo/main.cpp index c4b885efe2..807def8e45 100644 --- a/tests/manual/tasking/demo/main.cpp +++ b/tests/manual/tasking/demo/main.cpp @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) std::unique_ptr<TaskTree> taskTree; - const auto createTask = [](TaskWidget *widget) -> TaskItem { + const auto createTask = [](TaskWidget *widget) -> GroupItem { const auto setupTask = [](TaskWidget *widget) { return [widget](milliseconds &taskObject) { taskObject = milliseconds{widget->busyTime() * 1000}; diff --git a/tests/manual/tasking/demo/taskwidget.cpp b/tests/manual/tasking/demo/taskwidget.cpp index 6bc68db1a1..97d3d2b9ef 100644 --- a/tests/manual/tasking/demo/taskwidget.cpp +++ b/tests/manual/tasking/demo/taskwidget.cpp @@ -158,7 +158,7 @@ void GroupWidget::updateExecuteMode() m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode)); } -TaskItem GroupWidget::executeMode() const +GroupItem GroupWidget::executeMode() const { return m_executeMode == ExecuteMode::Sequential ? sequential : parallel; } @@ -174,7 +174,7 @@ void GroupWidget::updateWorkflowPolicy() m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy)); } -TaskItem GroupWidget::workflowPolicy() const +GroupItem GroupWidget::workflowPolicy() const { return Tasking::workflowPolicy(m_workflowPolicy); } diff --git a/tests/manual/tasking/demo/taskwidget.h b/tests/manual/tasking/demo/taskwidget.h index 3ce210eb0d..a737e315a4 100644 --- a/tests/manual/tasking/demo/taskwidget.h +++ b/tests/manual/tasking/demo/taskwidget.h @@ -62,10 +62,10 @@ public: GroupWidget(); void setExecuteMode(ExecuteMode mode); - Tasking::TaskItem executeMode() const; + Tasking::GroupItem executeMode() const; void setWorkflowPolicy(Tasking::WorkflowPolicy policy); - Tasking::TaskItem workflowPolicy() const; + Tasking::GroupItem workflowPolicy() const; private: void updateExecuteMode(); diff --git a/tests/manual/tasking/imagescaling/CMakeLists.txt b/tests/manual/tasking/imagescaling/CMakeLists.txt new file mode 100644 index 0000000000..cfa8121b92 --- /dev/null +++ b/tests/manual/tasking/imagescaling/CMakeLists.txt @@ -0,0 +1,11 @@ +add_qtc_test(tst_tasking_imagescaling + MANUALTEST + DEPENDS Tasking Qt::Concurrent Qt::Network Qt::Widgets + SOURCES + downloaddialog.cpp + downloaddialog.h + downloaddialog.ui + imagescaling.cpp + imagescaling.h + main.cpp +) diff --git a/tests/manual/tasking/imagescaling/downloaddialog.cpp b/tests/manual/tasking/imagescaling/downloaddialog.cpp new file mode 100644 index 0000000000..3547b88058 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "downloaddialog.h" +#include "ui_downloaddialog.h" + +#include <QUrl> + +DownloadDialog::DownloadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::DownloadDialog) +{ + ui->setupUi(this); + + ui->urlLineEdit->setPlaceholderText(tr("Enter the URL of an image to download")); + + connect(ui->addUrlButton, &QPushButton::clicked, this, [this] { + const auto text = ui->urlLineEdit->text(); + if (!text.isEmpty()) { + ui->urlListWidget->addItem(text); + ui->urlLineEdit->clear(); + } + }); + connect(ui->urlListWidget, &QListWidget::itemSelectionChanged, this, [this] { + ui->removeUrlButton->setEnabled(!ui->urlListWidget->selectedItems().empty()); + }); + connect(ui->clearUrlsButton, &QPushButton::clicked, ui->urlListWidget, &QListWidget::clear); + connect(ui->removeUrlButton, &QPushButton::clicked, this, + [this] { qDeleteAll(ui->urlListWidget->selectedItems()); }); +} + +DownloadDialog::~DownloadDialog() +{ + delete ui; +} + +QList<QUrl> DownloadDialog::getUrls() const +{ + QList<QUrl> urls; + for (auto row = 0; row < ui->urlListWidget->count(); ++row) + urls.push_back(QUrl(ui->urlListWidget->item(row)->text())); + return urls; +} diff --git a/tests/manual/tasking/imagescaling/downloaddialog.h b/tests/manual/tasking/imagescaling/downloaddialog.h new file mode 100644 index 0000000000..cc15d08189 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.h @@ -0,0 +1,29 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DOWNLOADDIALOG_H +#define DOWNLOADDIALOG_H + +#include <QDialog> + +QT_BEGIN_NAMESPACE +namespace Ui { +class DownloadDialog; +} +QT_END_NAMESPACE + +class DownloadDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DownloadDialog(QWidget *parent = nullptr); + ~DownloadDialog(); + + QList<QUrl> getUrls() const; + +private: + Ui::DownloadDialog *ui; +}; + +#endif // DOWNLOADDIALOG_H diff --git a/tests/manual/tasking/imagescaling/downloaddialog.ui b/tests/manual/tasking/imagescaling/downloaddialog.ui new file mode 100644 index 0000000000..c85a063568 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.ui @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DownloadDialog</class> + <widget class="QDialog" name="DownloadDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>489</width> + <height>333</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLineEdit" name="urlLineEdit"/> + </item> + <item> + <widget class="QListWidget" name="urlListWidget"/> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QPushButton" name="addUrlButton"> + <property name="text"> + <string>Add URL</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeUrlButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Remove URL</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="clearUrlsButton"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DownloadDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DownloadDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tests/manual/tasking/imagescaling/imagescaling.cpp b/tests/manual/tasking/imagescaling/imagescaling.cpp new file mode 100644 index 0000000000..e3acda749b --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.cpp @@ -0,0 +1,135 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imagescaling.h" +#include "downloaddialog.h" +#include <tasking/concurrentcall.h> +#include <tasking/networkquery.h> + +using namespace Tasking; + +Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDialog(this)) +{ + resize(800, 600); + + 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, [this] { + statusBar->showMessage(tr("Canceled.")); + taskTree.reset(); + }); + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + buttonLayout->addWidget(addUrlsButton); + buttonLayout->addWidget(cancelButton); + buttonLayout->addStretch(); + + statusBar = new QStatusBar(); + + imagesLayout = new QGridLayout(); + + mainLayout = new QVBoxLayout(); + mainLayout->addLayout(buttonLayout); + mainLayout->addLayout(imagesLayout); + mainLayout->addStretch(); + mainLayout->addWidget(statusBar); + setLayout(mainLayout); +} + +static void scale(QPromise<QImage> &promise, const QByteArray &data) +{ + const auto image = QImage::fromData(data); + if (image.isNull()) + promise.future().cancel(); + else + promise.addResult(image.scaled(100, 100, Qt::KeepAspectRatio)); +} + +void Images::process() +{ + if (downloadDialog->exec() != QDialog::Accepted) + return; + + const auto urls = downloadDialog->getUrls(); + initLayout(urls.size()); + + const auto onRootSetup = [this] { + statusBar->showMessage(tr("Downloading and Scaling...")); + cancelButton->setEnabled(true); + }; + 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; + } + + taskTree.reset(new TaskTree(tasks)); + connect(taskTree.get(), &TaskTree::done, this, [this] { taskTree.release()->deleteLater(); }); + taskTree->start(); +} + +void Images::initLayout(qsizetype count) +{ + // Clean old images + QLayoutItem *child; + while ((child = imagesLayout->takeAt(0)) != nullptr) { + child->widget()->setParent(nullptr); + delete child->widget(); + delete child; + } + labels.clear(); + + // Init the images layout for the new images + const auto dim = int(qSqrt(qreal(count))) + 1; + for (int i = 0; i < dim; ++i) { + 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); + } + } +} diff --git a/tests/manual/tasking/imagescaling/imagescaling.h b/tests/manual/tasking/imagescaling/imagescaling.h new file mode 100644 index 0000000000..91e89c13b2 --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.h @@ -0,0 +1,33 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef IMAGESCALING_H +#define IMAGESCALING_H + +#include <QNetworkAccessManager> +#include <QtWidgets> +#include <tasking/tasktree.h> + +class DownloadDialog; +class Images : public QWidget +{ +Q_OBJECT +public: + Images(QWidget *parent = nullptr); + +private: + void process(); + void initLayout(qsizetype count); + + QPushButton *cancelButton; + QVBoxLayout *mainLayout; + QList<QLabel *> labels; + QGridLayout *imagesLayout; + QStatusBar *statusBar; + DownloadDialog *downloadDialog; + + QNetworkAccessManager qnam; + std::unique_ptr<Tasking::TaskTree> taskTree; +}; + +#endif // IMAGESCALING_H diff --git a/tests/manual/tasking/imagescaling/imagescaling.qbs b/tests/manual/tasking/imagescaling/imagescaling.qbs new file mode 100644 index 0000000000..ea0698c729 --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.qbs @@ -0,0 +1,18 @@ +import qbs.FileInfo + +QtcManualtest { + name: "Tasking imagescaling" + type: ["application"] + + Depends { name: "Qt"; submodules: ["concurrent", "network", "widgets"] } + Depends { name: "Tasking" } + + files: [ + "downloaddialog.cpp", + "downloaddialog.h", + "downloaddialog.ui", + "imagescaling.cpp", + "imagescaling.h", + "main.cpp", + ] +} diff --git a/tests/manual/tasking/imagescaling/main.cpp b/tests/manual/tasking/imagescaling/main.cpp new file mode 100644 index 0000000000..a3ae6491f0 --- /dev/null +++ b/tests/manual/tasking/imagescaling/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imagescaling.h" +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QApplication app(argc,argv); + app.setOrganizationName("QtProject"); + app.setApplicationName(QObject::tr("Image Downloading and Scaling")); + + Images imageView; + imageView.setWindowTitle(QObject::tr("Image Downloading and Scaling")); + imageView.show(); + + return app.exec(); +} diff --git a/tests/system/suite_QMLS/tst_QMLS04/test.py b/tests/system/suite_QMLS/tst_QMLS04/test.py index 2c96939151..435d993cb2 100644 --- a/tests/system/suite_QMLS/tst_QMLS04/test.py +++ b/tests/system/suite_QMLS/tst_QMLS04/test.py @@ -48,12 +48,10 @@ def main(): pass # open MyComponent.qml file for verification docOpened = openDocument(myCompTE) - # Work around QTCREATORBUG-28985 - test.xverify(docOpened, "Was MyComponent.qml properly generated in project explorer?") - saveAndExit() - return - # The workaround will be removed in master branch - # Following dead code left in intentionally to still allow merging forward changes in it. + if not test.verify(docOpened, "Was MyComponent.qml properly generated in project explorer?"): + test.fatal("Could not open MyComponent.qml.") + saveAndExit() + return editorArea = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") codeText = str(editorArea.plainText) # there should be Text item in new file |