diff --git a/doc/qtcreator/images/qtcreator-analyzer-settings.png b/doc/qtcreator/images/qtcreator-analyzer-settings.png index b2c1cdc4127..6caf4073026 100644 Binary files a/doc/qtcreator/images/qtcreator-analyzer-settings.png and b/doc/qtcreator/images/qtcreator-analyzer-settings.png differ diff --git a/doc/qtcreator/images/qtcreator-build-settings-default.png b/doc/qtcreator/images/qtcreator-build-settings-default.png index 3ca79641a6b..2f5fb01edff 100644 Binary files a/doc/qtcreator/images/qtcreator-build-settings-default.png and b/doc/qtcreator/images/qtcreator-build-settings-default.png differ diff --git a/doc/qtcreator/images/qtcreator-build-settings-qbs.png b/doc/qtcreator/images/qtcreator-build-settings-qbs.png index 4aba9efc58d..a5b3caed834 100644 Binary files a/doc/qtcreator/images/qtcreator-build-settings-qbs.png and b/doc/qtcreator/images/qtcreator-build-settings-qbs.png differ diff --git a/doc/qtcreator/images/qtcreator-build-steps-conan-install.png b/doc/qtcreator/images/qtcreator-build-steps-conan-install.png index 09ab3549aa2..b70814dcafa 100644 Binary files a/doc/qtcreator/images/qtcreator-build-steps-conan-install.png and b/doc/qtcreator/images/qtcreator-build-steps-conan-install.png differ diff --git a/doc/qtcreator/images/qtcreator-build-steps.png b/doc/qtcreator/images/qtcreator-build-steps.png index 3ccf931360c..96c84bbc846 100644 Binary files a/doc/qtcreator/images/qtcreator-build-steps.png and b/doc/qtcreator/images/qtcreator-build-steps.png differ diff --git a/doc/qtcreator/images/qtcreator-kits-meson.png b/doc/qtcreator/images/qtcreator-kits-meson.png new file mode 100644 index 00000000000..23e1b46b59e Binary files /dev/null and b/doc/qtcreator/images/qtcreator-kits-meson.png differ diff --git a/doc/qtcreator/images/qtcreator-mesonexecutable.png b/doc/qtcreator/images/qtcreator-mesonexecutable.png index bfaa7cc1bd6..bda46f4f114 100644 Binary files a/doc/qtcreator/images/qtcreator-mesonexecutable.png and b/doc/qtcreator/images/qtcreator-mesonexecutable.png differ diff --git a/doc/qtcreator/images/qtcreator-options-clang-compilers.png b/doc/qtcreator/images/qtcreator-options-clang-compilers.png new file mode 100644 index 00000000000..04dd4bfd7fb Binary files /dev/null and b/doc/qtcreator/images/qtcreator-options-clang-compilers.png differ diff --git a/doc/qtcreator/images/qtcreator-options-cpp-compilers.png b/doc/qtcreator/images/qtcreator-options-cpp-compilers.png new file mode 100644 index 00000000000..ca2f1f6fa12 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-options-cpp-compilers.png differ diff --git a/doc/qtcreator/images/qtcreator-options-qcc-compilers.png b/doc/qtcreator/images/qtcreator-options-qcc-compilers.png new file mode 100644 index 00000000000..3b8630f6728 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-options-qcc-compilers.png differ diff --git a/doc/qtcreator/images/qtcreator-valgrind-callgrind-options.png b/doc/qtcreator/images/qtcreator-valgrind-callgrind-options.png index 82684f645b9..98601706556 100644 Binary files a/doc/qtcreator/images/qtcreator-valgrind-callgrind-options.png and b/doc/qtcreator/images/qtcreator-valgrind-callgrind-options.png differ diff --git a/doc/qtcreator/images/qtcreator-valgrind-callgrind-toolbar.png b/doc/qtcreator/images/qtcreator-valgrind-callgrind-toolbar.png new file mode 100644 index 00000000000..9ee00dc9018 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-valgrind-callgrind-toolbar.png differ diff --git a/doc/qtcreator/images/qtcreator-valgrind-callgrind.png b/doc/qtcreator/images/qtcreator-valgrind-callgrind.png index e57038a1517..8721c62c587 100644 Binary files a/doc/qtcreator/images/qtcreator-valgrind-callgrind.png and b/doc/qtcreator/images/qtcreator-valgrind-callgrind.png differ diff --git a/doc/qtcreator/images/qtcreator-valgrind-memcheck-options.png b/doc/qtcreator/images/qtcreator-valgrind-memcheck-options.png index a102b61367a..8855d7a6d85 100644 Binary files a/doc/qtcreator/images/qtcreator-valgrind-memcheck-options.png and b/doc/qtcreator/images/qtcreator-valgrind-memcheck-options.png differ diff --git a/doc/qtcreator/images/qtcreator-valgrind-memcheck.png b/doc/qtcreator/images/qtcreator-valgrind-memcheck.png index 8bcbcbc404b..8131846ef53 100644 Binary files a/doc/qtcreator/images/qtcreator-valgrind-memcheck.png and b/doc/qtcreator/images/qtcreator-valgrind-memcheck.png differ diff --git a/doc/qtcreator/src/analyze/creator-valgrind.qdoc b/doc/qtcreator/src/analyze/creator-valgrind.qdoc index da0952f3175..249879fa5d1 100644 --- a/doc/qtcreator/src/analyze/creator-valgrind.qdoc +++ b/doc/qtcreator/src/analyze/creator-valgrind.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -76,10 +76,23 @@ Click a line to view where a memory leak occurred and a stack trace that shows what caused it. + As an alternative to collecting data, you can select \inlineimage open.png + to load an external log file in XML format into the \uicontrol Memcheck + view. + \image qtcreator-valgrind-memcheck.png "Memcheck view" Move the mouse on a row to view more information about the function. + To move between rows, select \inlineimage prev.png + or \inlineimage next.png + . + + To filter the results, select \inlineimage filtericon.png + , and then select the types of issues to display in the view. You + can view and hide definite and possible memory leaks, uninitialized + values, invalid calls to \c free(), and external errors. + For more information about using Memcheck, see \l{http://valgrind.org/docs/manual/quick-start.html#quick-start.mcrun} {Interpreting Memcheck's Output} in the Valgrind documentation. @@ -90,6 +103,13 @@ separately for each project in the \l{Specifying Run Settings}{run settings} of the project. + To specify global settings for Valgrind, select \uicontrol Tools > + \uicontrol Options > \uicontrol Analyzer. The \uicontrol + {Memcheck Memory Analysis Options} group contains Memcheck options. + + In \uicontrol {Extra Memcheck arguments}, specify additional arguments + for launching the executable. + Stack traces can get quite large and confusing, and therefore, reading them from the bottom up can help. If the stack trace is not big enough or it is too big, select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer @@ -160,26 +180,7 @@ You can run Callgrind on a remote Linux machine or device from any development machine. - To analyze applications: - - \list 1 - - \li In the \uicontrol Projects mode, select a release build configuration. - - \li Select \uicontrol Debug to open the \uicontrol Debug mode, and then - select \uicontrol Callgrind on the toolbar. - - \li Select the - \inlineimage qtcreator-analyze-start-button.png "Start button" - button to start the application. - - \li Use the application to analyze it. - - \li Select the \inlineimage stop_small.png "Stop button" - button to view the results of the analysis in the \uicontrol Profile - view. - - \endlist + \section1 Building Apps for Profiling Callgrind records the call history of functions that are executed when the application is run. It collects the number of instructions that are @@ -188,10 +189,6 @@ also use cache simulation or branch prediction to gather information about the runtime behavior of an application. - Double-click a function to view information about the calling functions in - the \uicontrol Callers view and about the called functions in the \uicontrol Callees - view. - Since the run-time characteristics of debug and release \l{glossary-build-config}{build configurations} differ significantly, analytical findings for one build configuration may @@ -207,12 +204,84 @@ options for GCC are: \c{-g -O2}. It is advisable to use such a setup for Callgrind profiling. + \section1 Collecting Data - \image qtcreator-valgrind-callgrind.png "Profile view" + To analyze applications: - To view the data in KCachegrind, select the \inlineimage kcachegrind.png - (\uicontrol {Open Results in KCachegrind}) button on the toolbar. \QC - launches KCachegrind and loads the data into it for visualization. + \list 1 + + \li In the \uicontrol Projects mode, select a release build configuration. + + \li Select \uicontrol Debug to open the \uicontrol Debug mode, and then + select \uicontrol Callgrind on the toolbar. + + \image qtcreator-valgrind-callgrind-toolbar.png "Callgrind view toolbar" + + \li Select the + \inlineimage qtcreator-analyze-start-button.png "Start button" + button to start the application. + + \li Use the application to analyze it. + + \li Select the \inlineimage stop_small.png "Stop button" + button to view the results of the analysis in the + \uicontrol Functions view. + + \endlist + + Select \inlineimage icons/pause-icon.png + to speed up program execution during profiling by pausing event + logging. No events are counted while logging is paused. + + Select \inlineimage reload_gray.png + to reset all event counters. + + Select \inlineimage clean_pane_small.png + to discard all collected data. + + Select \inlineimage kcachegrind.png + to view the data in KCachegrind. \QC launches KCachegrind + and loads the data into it for visualization. + + \section1 Viewing Collected Data + + The results of the analysis are displayed in the \uicontrol Callgrind views. + You can detach views and move them around. To revert the changes, select + \uicontrol Views > \uicontrol {Reset to Default Layout}. + + Select \uicontrol Views to show and hide views and view + titles. The \uicontrol Visualization view is hidden by + default. Select \inlineimage redo.png + to refresh the data displayed in it when it is shown. + + As an alternative to collecting data, you can select \inlineimage open.png + to load an external log file into the \uicontrol Callgrind views. + + \image qtcreator-valgrind-callgrind.png "Callgrind views" + + Enter a string in the \uicontrol Filter field to filter the results. + + Move the cursor on a function in the \uicontrol Functions view for more + information about it. + + Double-click a function to view information about the calling functions in + the \uicontrol Callers view and about the called functions in the + \uicontrol Callees view. + + Select \inlineimage prev.png + or \inlineimage next.png + To move between functions in the \uicontrol Callee view. + + To set the cost format, select \uicontrol $. You can view absolute + or relative costs, as well as relative costs to parent. Select + \inlineimage filtericon.png + to view only profiling info that originated from the project. + + To properly handle recursive or circular function calls, enable cycle + detection by selecting \uicontrol O. + + To remove template parameter lists when displaying function names, select + \uicontrol <>. \section1 Selecting Profiling Options @@ -220,7 +289,7 @@ separately for each project in the \l{Specifying Run Settings}{run settings} of the project. - To specify settings for Valgrind, select \uicontrol Tools > + To specify global settings for Valgrind, select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer. The \uicontrol {Callgrind Profiling Options} group contains Callgrind options. @@ -229,12 +298,21 @@ In the \uicontrol {KCachegrind executable} field, enter the path to the KCachegrind executable to launch. - In the \uicontrol {Result view: Minimum event cost} - field, limit the amount of results the profiler gives you to increase - profiler performance. + In \uicontrol {Extra Callgrind arguments}, specify additional arguments + for launching the executable. - You can collect information about the system call times and the number of - global bus events of the event type \c Ge that are executed. + In the \uicontrol {Result view: Minimum event cost} and + \uicontrol {Visualization: Minimum event cost} fields, + limit the amount of results the profiler presents and + visualizes to increase profiler performance. + + To show additional information about events in tooltips, select + \uicontrol {Show additional information for events in tooltips}. + + To collect information about the system call times, select + \uicontrol {Collect system call time}. To collect the number of + global bus events of the event type \c Ge that are executed, + select \uicontrol {Collect global bus events}. \section2 Enabling Full Cache Simulation diff --git a/doc/qtcreator/src/conan/creator-projects-conan-building.qdoc b/doc/qtcreator/src/conan/creator-projects-conan-building.qdoc index 20e0c4159bd..836748e3b03 100644 --- a/doc/qtcreator/src/conan/creator-projects-conan-building.qdoc +++ b/doc/qtcreator/src/conan/creator-projects-conan-building.qdoc @@ -47,4 +47,7 @@ The \uicontrol {Conan install} field displays the effective build command. You can add arguments for the command in the \uicontrol {Additional arguments} field. + + Select \uicontrol {Build missing} to build packages from source if binary + packages are not found. */ diff --git a/doc/qtcreator/src/conan/creator-projects-conan.qdoc b/doc/qtcreator/src/conan/creator-projects-conan.qdoc index abaf4139393..fc20640b861 100644 --- a/doc/qtcreator/src/conan/creator-projects-conan.qdoc +++ b/doc/qtcreator/src/conan/creator-projects-conan.qdoc @@ -50,7 +50,9 @@ sources. Because the client has a local cache for package storage, you can work offline, as long as no new packages are needed from remote servers. - To use Conan, install it by using the Qt installer. + To use Conan, install it by using the Qt installer or the tools provided by + your operating system. For example, on Windows, you can use the + \c {choco install conan} or \{pip install conan} command. To enable the experimental Conan plugin, select \uicontrol Help > \uicontrol {About Plugins} > \uicontrol Utilities > \uicontrol Conan. @@ -63,4 +65,7 @@ Then, you must edit the build settings of the project to specify the location of the file and the contents of the Conan install command. For more information, see \l {Conan Build Steps}. + + Alternatively, you can automatically set up the Conan package manager for + use with CMake. For more information, see \l{Using CMake with Conan}. */ diff --git a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc index d0e569543ec..00114ade7bc 100644 --- a/doc/qtcreator/src/editors/creator-code-refactoring.qdoc +++ b/doc/qtcreator/src/editors/creator-code-refactoring.qdoc @@ -57,6 +57,10 @@ \image qtcreator-find-references-to-symbol-under-cursor.png "Search results for finding references to symbols" + To view the same results color-coded according to the access type, such as + read, write, or declaration, select \uicontrol Tools > \uicontrol {C++} > + \uicontrol {Find References with Access Type}. + \note You can also select \uicontrol Edit > \uicontrol {Find/Replace} > \uicontrol {Advanced Find} > \uicontrol {C++ Symbols} to search for classes, functions, enums, and declarations (including type aliases) either diff --git a/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc b/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc index 852c6018fd0..dcf1a3996e2 100644 --- a/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc +++ b/doc/qtcreator/src/meson/creator-projects-meson-building.qdoc @@ -29,7 +29,7 @@ \title Meson Build Configuration - \image qtcreator-meson-build-settings.png + \image qtcreator-meson-build-settings.png "Meson build settings" Settings are grouped by category by Meson. All items are user modifiable except \c backend which is forced to Ninja, \c {buildtype}, \c debug as well @@ -45,6 +45,8 @@ \note Any modified setting will remain in bold until \uicontrol {Apply configuration changes} is selected. + For more information about using Meson, see \l{Setting Up Meson}. + \section1 Meson Build Steps \QC builds Meson projects by running \c {ninja -v target}. @@ -52,7 +54,7 @@ You can add arguments and targets for the build command in \uicontrol {Build Steps}. - \image qtcreator-meson-build-steps.png + \image qtcreator-meson-build-steps.png "Meson build steps" The build errors and warnings are parsed and displayed in the \uicontrol Issues output pane. @@ -62,7 +64,7 @@ When building with Meson, you can add arguments and targets for the clean command in \uicontrol {Clean Steps}. - \image qtcreator-meson-clean-steps.png + \image qtcreator-meson-clean-steps.png "Meson clean steps" The build errors and warnings are parsed and displayed in the \uicontrol Issues output pane. diff --git a/doc/qtcreator/src/meson/creator-projects-meson.qdoc b/doc/qtcreator/src/meson/creator-projects-meson.qdoc index bffec6b41e7..f7865ee225b 100644 --- a/doc/qtcreator/src/meson/creator-projects-meson.qdoc +++ b/doc/qtcreator/src/meson/creator-projects-meson.qdoc @@ -73,7 +73,7 @@ \uicontrol Tools > \uicontrol Options > \uicontrol Kits > \uicontrol Kits tab to add the Meson and Ninja tools to a build and run kit: - \image qtcreator-kits.png + \image qtcreator-kits-meson.png "Setting Meson executable in Kit options" For more information, see \l {Adding Kits}. diff --git a/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc b/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc index 2cf107f1ed2..f7bcd6765bb 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-build-settings-qmake.qdoc @@ -89,9 +89,13 @@ \QC project wizard templates create Qt Quick projects that can be compiled because they are set up to use the Qt Resource System. To compile QML code, - select \uicontrol Enable in the \uicontrol {Use qmlcachegen} field. To + select \uicontrol Enable in the \uicontrol {Qt Quick Compiler} field. To use default settings, select \uicontrol {Leave at Default}. + You can specify default behavior for compiling QML code in \uicontrol Tools + > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol Qmake > + \uicontrol {Use qmlcachegen}. + \section1 qmake Build Steps \QC builds qmake projects by running the \c make or \c nmake command from @@ -109,6 +113,9 @@ \uicontrol {Override MAKEFLAGS} check box to override existing MAKEFLAGS variables. + Select \uicontrol {Disable in subdirectories} to execute the build step + only for a top-level build. + Select \uicontrol {Add Build Step} > \uicontrol {IncrediBuild for Linux} or \uicontrol {IncrediBuild for Windows} to accelerate builds by using \l{IncrediBuild Build Configuration}{IncrediBuild}. diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc index 17995bffb15..e03e367aba0 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-compilers.qdoc @@ -54,18 +54,6 @@ \list - \li GNU Compiler Collection (GCC) is a compiler for Linux and - \macos. - - \li \MinGW (Minimalist GNU for Windows) is a native software port of GCC - and GNU Binutils for use in the development of native Microsoft - Windows applications on Windows. \MinGW is distributed together with - \QC and Qt for Windows. - - \li ICC (Intel C++ Compiler) is a group of C and C++ compilers. - Only the GCC-compatible variant, available for Linux and \macos, - is currently supported by \QC. - \li Clang is a C, C++, Objective C, and Objective C++ front-end for the LLVM compiler for Windows, Linux, and \macos. @@ -73,6 +61,21 @@ is an alternative command-line interface to Clang that is compatible with the Visual C++ compiler, \c cl.exe. + \li GNU Compiler Collection (GCC) is a compiler for Linux and + \macos. + + \li ICC (Intel C++ Compiler) is a group of C and C++ compilers. + Only the GCC-compatible variant, available for Linux and \macos, + is currently supported by \QC. + + \li \MinGW (Minimalist GNU for Windows) is a native software port of GCC + and GNU Binutils for use in the development of native Microsoft + Windows applications on Windows. \MinGW is distributed together with + \QC and Qt for Windows. + + \li MSVC (Microsoft Visual C++ Compiler) is a C++ compiler that is + installed with Microsoft Visual Studio. + \li Nim is the Nim Compiler for Windows, Linux, and \macos. \li QCC is the interface for compiling C++ applications for QNX. @@ -100,6 +103,9 @@ \endlist + The emscripten compiler is tool chain for compiling to + \l{Building Applications for the Web}{WebAssembly}. + \section1 Redetecting Compilers When \QC finds an x86_64 GCC compiler, it sets up an instance for the native @@ -118,31 +124,37 @@ to the directory where the compiler is located and select the application binary interface (ABI) version from the list of available versions. You can also create a custom ABI definition. - For QCC, also specify the path to the QNX Software Development Platform (SDP). + For QCC, also specify the path to the QNX Software Development Platform + (SDP) in the \uicontrol {SPD path} field. To enable Microsoft Visual C++ Compilers (MSVC) and clang-cl to find system headers, libraries, and the linker, \QC executes them inside a command prompt where the environment has been set up using \c {vcvarsall.bat}. For these compilers, you also specify the path to the script that sets up the - command prompt. + command prompt in the \uicontrol Initialization field. You specify the compiler to use for each kit in \uicontrol Tools > \uicontrol Options > \uicontrol Kits. - To add C or C++ compilers: + To add a C or C++ compiler, select \uicontrol Tools > \uicontrol Options > + \uicontrol Kits > \uicontrol Compilers > \uicontrol Add. Select a compiler + in the list, and then select \uicontrol C or \uicontrol C++. - \list 1 + To clone the selected compiler, select \uicontrol Clone. - \li Select \uicontrol Tools > \uicontrol Options > - \uicontrol Kits > \uicontrol Compilers > \uicontrol Add, - then select a compiler in the list, and then select \uicontrol C or - \uicontrol C++ to add a C or C++ compiler. + The settings to specify depend on the compiler: - To clone the selected compiler, select \uicontrol Clone. + \list \li In the \uicontrol Name field, enter a name for the compiler to identify it in \QC. + \image qtcreator-options-cpp-compilers.png "Adding a clang-cl compiler" + + \li In the \uicontrol Initialization field, select the + \c {vcvarsall.bat} file for setting up the command + prompt to use. + \li In the \uicontrol {Compiler path} field, enter the path to the directory where the compiler is located. @@ -154,7 +166,16 @@ the linker that specify the architecture on the target platform. The linker flags are used only when building with Qbs. - The other settings to specify depend on the compiler. + \image qtcreator-options-clang-compilers.png "Adding a Clang compiler" + + \li In the \uicontrol {Parent toolchain} field, select a \MinGW + compiler, which is needed because Clang does not have its own + standard library. + + \li In the \uicontrol {SPD path} field, specify the path to the QNX + Software Development Platform (SDP). + + \image qtcreator-options-qcc-compilers.png "Adding a QCC compiler" \li In the \uicontrol ABI field, provide an identification for the target architecture. This is used to warn about ABI mismatches diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc index 8ffef125ea1..64ab2f468ec 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build-qbs.qdoc @@ -48,6 +48,9 @@ more information, see \l{Using the Performance Analyzer}. To use default settings, select \uicontrol {Leave at Default}. + For more information about the QML and Qt Quick options, see + \l{Compiling QML}. + For more information about configuring Qbs, see \l{Setting Up Qbs}. \section1 Qbs Build Steps diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc index f802f89f0da..22cab734906 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-run-analyze.qdocinc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -45,9 +45,19 @@ \image qtcreator-analyzer-settings.png "Valgrind Settings" + \li In \uicontrol {Valgrind executable}, specify the path to the + Valgrind executable. + + \li In \uicontrol {Valgrind arguments}, specify additional arguments + for Valgrind. + + \li In \uicontrol {Detect self-modifying code}, select whether to + detect self-modifying code and where to detect it: only on stack, + everywhere, or everywhere except in file-backend mappings. + \endlist - For more information about the settings, see: + For more information about the CallGrind and MemCheck settings, see: \list diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc index 109be0f8483..e05b586aca5 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-targets.qdoc @@ -212,7 +212,8 @@ \list 1 - \li Select \uicontrol Change next to the + \li In \uicontrol Tools > \uicontrol Options > \uicontrol Kits, select + the kit, and then select \uicontrol Change next to the \uicontrol {Additional Qbs Profile Settings} field to open the \uicontrol {Custom Properties} dialog. diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc index 421755c3153..bab4568bbae 100644 --- a/doc/qtcreator/src/qtcreator-toc.qdoc +++ b/doc/qtcreator/src/qtcreator-toc.qdoc @@ -102,6 +102,7 @@ \li \l{Developing Qt Quick Applications} \list \li \l {Creating Qt Quick Projects} + \li \l {Using \QMLD} \li \l {Converting UI Projects to Applications} \li \l {UI Files} \li \l {Using QML Modules with Plugins} diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc b/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc index 3f05a77c06f..065ac60d262 100644 --- a/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc +++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-app-development.qdoc @@ -61,6 +61,11 @@ You can use wizards to create Qt Quick projects. + \li \l {Using \QMLD} + + You can enable the \QMLD plugin to visually edit + \l{UI Files}{UI files} (.ui.qml). + \li \l {Converting UI Projects to Applications} Qt Quick UI projects (.qmlproject) are useful for creating user @@ -73,7 +78,7 @@ If you switch between \QC and \QDS or cooperate with designers on a project, you might encounter .ui.qml files. They are intended to be edited in \QDS only, so you need to be careful not to break the - code. + code. To visually edit the files in \QC, enable the \QMLD plugin. \li \l{Using QML Modules with Plugins} diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc b/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc index b69f1dc22db..cea341db4b8 100644 --- a/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc +++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-creating.qdoc @@ -32,7 +32,7 @@ /*! \previouspage creator-visual-editor.html \page quick-projects.html - \nextpage quick-converting-ui-projects.html + \nextpage creator-qtquickdesigner-plugin.html \title Creating Qt Quick Projects diff --git a/doc/qtcreator/src/qtquick/creator-only/qtquick-designer-plugin.qdoc b/doc/qtcreator/src/qtquick/creator-only/qtquick-designer-plugin.qdoc new file mode 100644 index 00000000000..3a86a15bb7a --- /dev/null +++ b/doc/qtcreator/src/qtquick/creator-only/qtquick-designer-plugin.qdoc @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Creator documentation. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** +****************************************************************************/ + +/*! + \page creator-qtquickdesigner-plugin.html + \previouspage quick-projects.html + \nextpage quick-converting-ui-projects.html + + \title Using \QMLD + + We recommend that you use a separate visual editor, + \l{Qt Design Studio Manual}{\QDS} to open and edit + \l{UI Files}{UI files} (.ui.qml). + + However, you can enable the \QMLD plugin in \QC for editing + UI files. The functionality is restricted and not all \QDS + features are supported. + + To use \QMLD, switch to the \uicontrol Design mode when a ui.qml or or .qml + file is open. + + For more information about using \QMLD, see \l{Qt Design Studio Manual}. + + \section1 Enabling the \QMLD Plugin + + To enable the \QMLD plugin: + + \list 1 + \li Select \uicontrol Help > \uicontrol {About Plugins} > + \uicontrol {Qt Quick} > \uicontrol {QmlDesigner}. + \li Select \uicontrol {Restart Now} to restart \QC and load the plugin. + \endlist +*/ diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc index 2988954af91..7a94f9054ec 100644 --- a/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc +++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc @@ -40,8 +40,11 @@ layers that are imported into \QDS as separate files. \li Use descriptive and unique IDs to avoid duplicate asset names and IDs in the generated UI. + \li Use XD Components and instances to reuse the UI elements. \endlist + \note Although \QBXD preserves the XD Component and instance's relationship, overrides + and states are not yet supported. To use the fonts that you use in Adobe XD also in \QDS, you need to import them to \QDS as assets. \QDS deploys them to devices when you preview the @@ -60,11 +63,15 @@ The following design elements might not be exported as expected. \list - \li Components + \li Component states + \li Component overrides \li Prototype \li Repeat Grid \endlist + \note Adobe XD's plugin API support is incomplete. Specifically, the support + for XD Components is limited. This might change in the future and \QBXD might + extend the XD Component support. \section2 Using Artboards @@ -120,6 +127,8 @@ properties will be ignored if \uicontrol {Component} is defined for a text layer, but explicit properties defined in the \uicontrol {Properties} field will be applied. + \li Select the \uicontrol {Render Text} check box to render the text layer + as an image \li In the \uicontrol {Imports} field, enter additional import statements to have them added to the generated code file. For example, to use Qt Quick Controls 2.3, you need the import statement @@ -134,10 +143,13 @@ bounding rectangle. \li Select the \uicontrol Visible check box to determine the visibility of the layer in the generated UI in \QDS. - \li Select \uicontrol Export to export the document into a .qtbridge - archive. + \li Select \uicontrol Export to launch the export dialog to export the document + into a .qtbridge archive. \endlist + \note XD Components can not be skipped and Text layers can only be merged when + \uicontrol {Render Text} is selected. + \section2 Export Defaults @@ -145,9 +157,9 @@ By default: \list - \li Artboards are exported as \e components. - \li Immediate children of an Artboard and Text layers are exported as - \e child. + \li Artboards and XD Components are exported as \e components. + \li Component instances, Text layers and immediate children of an Artboard + are exported as \e child. \li Any layer not falling under the aforementioned criteria is exported as \e merged. \li Images are exported as PNGs by default with no Hi-DPI images. diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 34d96265286..545457ccbec 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -893,19 +893,31 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() // Key number is selected so that it is unlikely to conflict other ImageContainer use. auto imgContainer = ImageContainer(-1, renderImage, 2100000000); - // send the rendered image to creator process - nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView, - QVariant::fromValue(imgContainer)}); + // If we have only one or no render queued, send the result to the creator side. + // Otherwise, we'll hold on that until we have rendered all pending frames to ensure sent + // results are correct. + if (m_need3DEditViewRender <= 1) { + nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView, + QVariant::fromValue(imgContainer)}); +#ifdef QUICK3D_PARTICLES_MODULE + if (m_need3DEditViewRender == 0 && ViewConfig::isParticleViewMode() + && m_particleAnimationDriver && m_particleAnimationDriver->isAnimating()) { + m_need3DEditViewRender = 1; + } +#endif + } + if (m_need3DEditViewRender > 0) { - m_render3DEditViewTimer.start(0); + // We queue another render even if the requested render count was one, because another + // render is needed to ensure gizmo geometries are properly updated. + // Note that while in theory this seems that we shouldn't need to send the image to + // creator side when m_need3DEditViewRender is one, we need to do it to ensure + // smooth operation when objects are moved via drag, which triggers new renders + // continueously. + m_render3DEditViewTimer.start(17); // 16.67ms = ~60fps, rounds up to 17 --m_need3DEditViewRender; } -#ifdef QUICK3D_PARTICLES_MODULE - if (ViewConfig::isParticleViewMode() - && m_particleAnimationDriver && m_particleAnimationDriver->isAnimating()) { - m_need3DEditViewRender++; - } -#endif + #ifdef FPS_COUNTER // Force constant rendering for accurate fps count if (!m_render3DEditViewTimer.isActive()) @@ -1981,8 +1993,8 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c break; case View3DActionCommand::CameraToggle: updatedState.insert("usePerspective", command.isEnabled()); - // It can take a couple frames to properly update icon gizmo positions, so render 3 frames - renderCount = 3; + // It can take a couple frames to properly update icon gizmo positions + renderCount = 2; break; case View3DActionCommand::OrientationToggle: updatedState.insert("globalOrientation", command.isEnabled()); @@ -1994,11 +2006,9 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c updatedState.insert("showGrid", command.isEnabled()); break; #ifdef QUICK3D_PARTICLES_MODULE - case View3DActionCommand::Edit3DParticleModeToggle: - updatedState.insert("enableParticleViewMode", command.isEnabled()); - break; case View3DActionCommand::ParticlesPlay: m_particleAnimationPlaying = command.isEnabled(); + updatedState.insert("particlePlay", command.isEnabled()); if (m_particleAnimationPlaying) { m_particleAnimationDriver->reset(); m_particleAnimationDriver->restart(); @@ -2230,8 +2240,8 @@ void Qt5InformationNodeInstanceServer::update3DViewState(const Update3dViewState auto helper = qobject_cast(m_3dHelper); if (helper) helper->storeToolState(helper->globalStateId(), helper->rootSizeKey(), QVariant(command.size()), 0); - // Queue three renders to make sure icon gizmos update properly - render3DEditView(3); + // Queue two renders to make sure all gizmos update properly + render3DEditView(2); } } #else diff --git a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml index 87a63dcefe8..7399db69149 100644 --- a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml +++ b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml @@ -127,6 +127,7 @@ Item { Image { id: statusIcon + Layout.alignment: Qt.AlignTop asynchronous: false } @@ -191,25 +192,29 @@ Item { SC.ComboBox { // Screen Size ComboBox id: screenSizeComboBox actionIndicatorVisible: false - currentIndex: 1 + currentIndex: -1 model: screenSizeModel textRole: "display" width: parent.width font.pixelSize: DialogValues.defaultPixelSize onActivated: (index) => { - // NOTE: item 0 is activated when the screenSizeModel is reset - dialogBox.setScreenSizeIndex(index); + dialogBox.setScreenSizeIndex(index); - var r = screenSizeModel.screenSizes(index); - widthField.realValue = r.width; - heightField.realValue = r.height; - } + var size = screenSizeModel.screenSizes(index); + widthField.realValue = size.width; + heightField.realValue = size.height; + } Connections { target: screenSizeModel function onModelReset() { - screenSizeComboBox.activated(screenSizeComboBox.currentIndex) + var newIndex = screenSizeComboBox.currentIndex > -1 + ? screenSizeComboBox.currentIndex + : dialogBox.screenSizeIndex() + + screenSizeComboBox.currentIndex = newIndex + screenSizeComboBox.activated(newIndex) } } } // Screen Size ComboBox diff --git a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/NewProjectView.qml b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/NewProjectView.qml index 049b955420c..3b72dc1b83f 100644 --- a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/NewProjectView.qml +++ b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/NewProjectView.qml @@ -134,6 +134,7 @@ GridView { width: DialogValues.projectItemWidth height: DialogValues.projectItemHeight + background: null function fontIconCode(index) { var code = projectModel.fontIconCode(index) diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme index 357fdf2b263..070b76211f3 100644 --- a/share/qtcreator/themes/dark.creatortheme +++ b/share/qtcreator/themes/dark.creatortheme @@ -155,8 +155,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ff323232 +DSBackgroundColorNormal=ff1f1f1f ;DS controls theme END diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme index 9a7729b9cf0..43a894ce89c 100644 --- a/share/qtcreator/themes/default.creatortheme +++ b/share/qtcreator/themes/default.creatortheme @@ -146,8 +146,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ffeaeaea +DSBackgroundColorNormal=ffd8d8d8 ;DS controls theme END diff --git a/share/qtcreator/themes/design-light.creatortheme b/share/qtcreator/themes/design-light.creatortheme index 197070dc9bc..8d1c929bc28 100644 --- a/share/qtcreator/themes/design-light.creatortheme +++ b/share/qtcreator/themes/design-light.creatortheme @@ -160,8 +160,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ffeaeaea +DSBackgroundColorNormal=ffd8d8d8 ;DS controls theme END diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index 26d1827bc88..e64136dc6e9 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -159,8 +159,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ff323232 +DSBackgroundColorNormal=ff1f1f1f ;DS controls theme END diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index c7704cfb783..dc894638f32 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -155,8 +155,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ffeaeaea +DSBackgroundColorNormal=ffd8d8d8 ;DS controls theme END diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index 17e3b1aafd0..b4769cbe741 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -153,8 +153,8 @@ DStoolTipText=ffdadada DSUnimportedModuleColor=ffe33c2e -DSBackgroundColorAlternate=alternateBackground -DSBackgroundColorNormal=normalBackground +DSBackgroundColorAlternate=ff323232 +DSBackgroundColorNormal=ff1f1f1f ;DS controls theme END diff --git a/src/libs/qmleditorwidgets/contextpanewidgetrectangle.cpp b/src/libs/qmleditorwidgets/contextpanewidgetrectangle.cpp index 8202c8be84b..3e3e62c3d58 100644 --- a/src/libs/qmleditorwidgets/contextpanewidgetrectangle.cpp +++ b/src/libs/qmleditorwidgets/contextpanewidgetrectangle.cpp @@ -209,7 +209,7 @@ void ContextPaneWidgetRectangle::onColorNoneClicked() if (ui->colorNone->isChecked()) { ui->colorGradient->setEnabled(isGradientEditingEnabled()); emit removeAndChangeProperty(QLatin1String("gradient"), QLatin1String("color"), - QLatin1String("transparent"), true); + QLatin1String("\"transparent\""), true); } ui->colorGradient->setEnabled(isGradientEditingEnabled()); } diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index f22c10ac46b..f4c09ab1327 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -1324,6 +1324,7 @@ QAction *BoolAspect::action() auto act = BaseAspect::action(); // Creates it. act->setCheckable(true); act->setChecked(value()); + act->setToolTip(toolTip()); connect(act, &QAction::triggered, this, [this](bool newValue) { // The check would be nice to have in simple conditions, but if we // have an action that's used both on a settings page and as action diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp index 6e180496375..e5189759b03 100644 --- a/src/libs/utils/projectintropage.cpp +++ b/src/libs/utils/projectintropage.cpp @@ -61,6 +61,7 @@ public: Ui::ProjectIntroPage m_ui; bool m_complete = false; QRegularExpressionValidator m_projectNameValidator; + QString m_projectNameValidatorUserMessage; bool m_forceSubProject = false; FilePaths m_projectDirectories; }; @@ -124,10 +125,11 @@ void ProjectIntroPage::setFilePath(const FilePath &path) d->m_ui.pathChooser->setFilePath(path); } -void ProjectIntroPage::setProjectNameRegularExpression(const QRegularExpression ®Ex) +void ProjectIntroPage::setProjectNameRegularExpression(const QRegularExpression ®Ex, const QString &userErrorMessage) { Q_ASSERT_X(regEx.isValid(), Q_FUNC_INFO, qPrintable(regEx.errorString())); d->m_projectNameValidator.setRegularExpression(regEx); + d->m_projectNameValidatorUserMessage = userErrorMessage; } void ProjectIntroPage::setProjectName(const QString &name) @@ -263,8 +265,10 @@ bool ProjectIntroPage::validateProjectName(const QString &name, QString *errorMe // a more detailed error message if (validatorState != QValidator::Acceptable && (pos == -1 || pos >= name.count())) { if (errorMessage) { - *errorMessage = tr("Name does not match \"%1\".").arg( - d->m_projectNameValidator.regularExpression().pattern()); + if (d->m_projectNameValidatorUserMessage.isEmpty()) + *errorMessage = tr("Project name is invalid."); + else + *errorMessage = d->m_projectNameValidatorUserMessage; } return false; } diff --git a/src/libs/utils/projectintropage.h b/src/libs/utils/projectintropage.h index 0bccd91f2b1..ea755d671ed 100644 --- a/src/libs/utils/projectintropage.h +++ b/src/libs/utils/projectintropage.h @@ -80,7 +80,7 @@ public slots: void setProjectName(const QString &name); void setDescription(const QString &description); void setUseAsDefaultPath(bool u); - void setProjectNameRegularExpression(const QRegularExpression ®Ex); + void setProjectNameRegularExpression(const QRegularExpression ®Ex, const QString &userErrorMessage); private: void slotChanged(); diff --git a/src/plugins/android/androidqmlpreviewworker.cpp b/src/plugins/android/androidqmlpreviewworker.cpp index 5eb0c887d7c..ced1c06f5fa 100644 --- a/src/plugins/android/androidqmlpreviewworker.cpp +++ b/src/plugins/android/androidqmlpreviewworker.cpp @@ -75,7 +75,8 @@ ApkInfo::ApkInfo() : ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A}), appId(APP_ID), uploadDir("/data/local/tmp/" APP_ID "/"), - activityId(APP_ID "/org.qtproject.qt5.android.bindings.QtActivity"), + // TODO Add possibility to run Qt5 built version of Qt Design Viewer + activityId(APP_ID "/org.qtproject.qt.android.bindings.QtActivity"), name("Qt Design Viewer") { } diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp index 266f77cf038..1b24191ccc3 100644 --- a/src/plugins/android/createandroidmanifestwizard.cpp +++ b/src/plugins/android/createandroidmanifestwizard.cpp @@ -227,7 +227,10 @@ void ChooseDirectoryPage::initializePage() "The files in the Android package source directory are copied to the build directory's " "Android directory and the default files are overwritten.")); - m_androidPackageSourceDir->setFilePath(bti.projectFilePath / "android"); + const FilePath projectPath = bti.projectFilePath.isFile() + ? bti.projectFilePath.parentDir() : bti.projectFilePath; + + m_androidPackageSourceDir->setFilePath(projectPath / "android"); connect(m_androidPackageSourceDir, &PathChooser::rawPathChanged, this, &ChooseDirectoryPage::checkPackageSourceDir); } else { diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index fe686a973f0..6c22612259f 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -1096,7 +1096,7 @@ public: const QString &type = {}); void handleSemanticTokens(TextDocument *doc, const QList &tokens, - int version); + int version, bool force); enum class AstCallbackMode { SyncIfPossible, AlwaysAsync }; using TextDocOrFile = const Utils::variant; @@ -1294,8 +1294,8 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler); setSymbolStringifier(displayNameFromDocumentSymbol); setSemanticTokensHandler([this](TextDocument *doc, const QList &tokens, - int version) { - d->handleSemanticTokens(doc, tokens, version); + int version, bool force) { + d->handleSemanticTokens(doc, tokens, version, force); }); hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response, const DocumentUri &uri) { @@ -2659,7 +2659,7 @@ static void semanticHighlighter(QFutureInterface &future, // in the semantic tokens nor in the AST. void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, const QList &tokens, - int version) + int version, bool force) { SubtaskTimer t(highlightingTimer); qCDebug(clangdLog) << "handling LSP tokens" << doc->filePath() << tokens.size(); @@ -2670,7 +2670,7 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, } const auto previous = previousTokens.find(doc); if (previous != previousTokens.end()) { - if (previous->first == tokens && previous->second == version) { + if (!force && previous->first == tokens && previous->second == version) { qCDebug(clangdLogHighlight) << "tokens and version same as last time; nothing to do"; return; } @@ -3669,12 +3669,11 @@ void ExtraHighlightingResultsCollector::visitNode(const AstNode &node) if (m_future.isCanceled()) return; switch (node.fileStatus(m_filePath)) { - case AstNode::FileStatus::Foreign: - return; case AstNode::FileStatus::Ours: case AstNode::FileStatus::Unknown: collectFromNode(node); [[fallthrough]]; + case AstNode::FileStatus::Foreign: case ClangCodeModel::Internal::AstNode::FileStatus::Mixed: { const auto children = node.children(); if (!children) diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 19fb1d7685b..de4cdc988d1 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -1252,6 +1252,10 @@ void ClangdTestHighlighting::test_data() QTest::newRow("simple return") << 841 << 12 << 841 << 15 << QList{C_LOCAL} << 0; QTest::newRow("lambda parameter") << 847 << 49 << 847 << 52 << QList{C_PARAMETER, C_DECLARATION} << 0; + QTest::newRow("string literal passed to macro from same file") << 853 << 32 << 853 << 38 + << QList{C_STRING} << 0; + QTest::newRow("string literal passed to macro from header file") << 854 << 32 << 854 << 38 + << QList{C_STRING} << 0; } void ClangdTestHighlighting::test() diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp index 7f0db946955..5d57a235bc6 100644 --- a/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp +++ b/src/plugins/clangcodemodel/test/data/highlighting/highlighting.cpp @@ -846,3 +846,10 @@ void testConstRefAutoLambdaArgs() { useContainer(FooPtrVector(), [](const auto &arg) {}); } + +#define USE_STRING(s) (s) +void useString() +{ + const char *s = USE_STRING("TEXT"); + s = USE_STRING_FROM_HEADER("TEXT"); +} diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h b/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h index e69de29bb2d..13985c0d3e1 100644 --- a/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h +++ b/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h @@ -0,0 +1 @@ +#define USE_STRING_FROM_HEADER(s) (s) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 0973bbc519a..cd537172c8e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -285,6 +286,13 @@ void CMakeBuildStep::setupOutputFormatter(Utils::OutputFormatter *formatter) formatter->addLineParser(progressParser); cmakeParser->setSourceDirectory(project()->projectDirectory().toString()); formatter->addLineParsers({cmakeParser, new GnuMakeParser}); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit()); + OutputTaskParser *xcodeBuildParser = nullptr; + if (tc && tc->targetAbi().os() == Abi::DarwinOS) { + xcodeBuildParser = new XcodebuildParser; + formatter->addLineParser(xcodeBuildParser); + progressParser->setRedirectionDetector(xcodeBuildParser); + } const QList additionalParsers = kit()->createOutputParsers(); for (Utils::OutputLineParser * const p : additionalParsers) p->setRedirectionDetector(progressParser); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index dac623ebe82..1d0914c2b31 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -1014,7 +1014,7 @@ const QList CMakeBuildSystem::appTargets() const BuildTargetInfo bti; bti.displayName = ct.title; bti.targetFilePath = ct.executable; - bti.projectFilePath = ct.sourceDirectory.stringAppended("/"); + bti.projectFilePath = ct.sourceDirectory.cleanPath(); bti.workingDirectory = ct.workingDirectory; bti.buildKey = buildKey; bti.usesTerminal = !ct.linksToQtGui; diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp index bd5556d215c..53bec6a52af 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp @@ -159,7 +159,6 @@ CMakeConfigItem::Type CMakeConfigItem::typeStringToType(const QByteArray &type) if (type == "INTERNAL") return CMakeConfigItem::INTERNAL; - QTC_CHECK(type == "UNINITIALIZED"); return CMakeConfigItem::UNINITIALIZED; } diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 70edbbabb4e..29e420dfcdd 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -87,6 +87,7 @@ const char ZOOM_OUT[] = "QtCreator.ZoomOut"; const char ZOOM_RESET[] = "QtCreator.ZoomReset"; const char NEW[] = "QtCreator.New"; +const char NEW_FILE[] = "QtCreator.NewFile"; const char OPEN[] = "QtCreator.Open"; const char OPEN_WITH[] = "QtCreator.OpenWith"; const char REVERTTOSAVED[] = "QtCreator.RevertToSaved"; diff --git a/src/plugins/coreplugin/locator/locatormanager.cpp b/src/plugins/coreplugin/locator/locatormanager.cpp index 6506f3b74b8..5c1bb0a0b54 100644 --- a/src/plugins/coreplugin/locator/locatormanager.cpp +++ b/src/plugins/coreplugin/locator/locatormanager.cpp @@ -54,6 +54,9 @@ static LocatorWidget *locatorWidget() { static QPointer popup; QWidget *window = ICore::dialogParent()->window(); + // if that is a popup, try to find a better one + if (window->windowFlags() & Qt::Popup && window->parentWidget()) + window = window->parentWidget()->window(); if (auto *widget = Aggregation::query(window)) { if (popup) popup->close(); diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp index 19a6b1f3757..4f6f666a633 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.cpp +++ b/src/plugins/coreplugin/locator/locatorwidget.cpp @@ -360,21 +360,40 @@ void LocatorPopup::updateWindow() bool LocatorPopup::event(QEvent *event) { - if (event->type() == QEvent::ParentChange) + if (event->type() == QEvent::ParentChange) { updateWindow(); - else if (event->type() == QEvent::Show) + } else if (event->type() == QEvent::Show) { // make sure the popup has correct position before it becomes visible doUpdateGeometry(); - else if (event->type() == QEvent::LayoutRequest) + } else if (event->type() == QEvent::LayoutRequest) { // completion list resizes after first items are shown --> LayoutRequest QMetaObject::invokeMethod(this, &LocatorPopup::doUpdateGeometry, Qt::QueuedConnection); + } else if (event->type() == QEvent::ShortcutOverride) { + // if we (the popup) has focus, we need to handle escape manually (Windows) + auto ke = static_cast(event); + if (ke->modifiers() == Qt::NoModifier && ke->key() == Qt::Key_Escape) + event->accept(); + } else if (event->type() == QEvent::KeyPress) { + // if we (the popup) has focus, we need to handle escape manually (Windows) + auto ke = static_cast(event); + if (ke->modifiers() == Qt::NoModifier && ke->key() == Qt::Key_Escape) + hide(); + } return QWidget::event(event); } bool LocatorPopup::eventFilter(QObject *watched, QEvent *event) { - if (watched == m_window && event->type() == QEvent::Resize) + if (watched == m_tree && event->type() == QEvent::FocusOut) { + // if the tree had focus and another application is brought to foreground, + // we need to hide the popup because it otherwise stays on top of + // everything else (even other applications) (Windows) + auto fe = static_cast(event); + if (fe->reason() == Qt::ActiveWindowFocusReason && !QApplication::activeWindow()) + hide(); + } else if (watched == m_window && event->type() == QEvent::Resize) { doUpdateGeometry(); + } return QWidget::eventFilter(watched, event); } @@ -412,6 +431,7 @@ LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent) m_tree->setFrameStyle(QFrame::NoFrame); // tool tip already includes a frame m_tree->setModel(locatorWidget->model()); m_tree->setTextElideMode(Qt::ElideMiddle); + m_tree->installEventFilter(this); auto layout = new QVBoxLayout; layout->setSizeConstraint(QLayout::SetMinimumSize); diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 83d5a257a57..d2043b733ae 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -527,7 +527,9 @@ void MainWindow::registerDefaultActions() // New File Action QIcon icon = QIcon::fromTheme(QLatin1String("document-new"), Utils::Icons::NEWFILE.icon()); - QString newActionText = isQtDesignStudio() ? tr("&New Project...") : tr("&New File or Project..."); + + const bool isQDS = isQtDesignStudio(); + const QString newActionText = isQDS ? tr("&New Project...") : tr("&New File or Project..."); m_newAction = new QAction(icon, newActionText, this); cmd = ActionManager::registerAction(m_newAction, Constants::NEW); cmd->setDefaultKeySequence(QKeySequence::New); @@ -541,6 +543,24 @@ void MainWindow::registerDefaultActions() } }); + if (isQDS) { + auto action = new QAction(icon, tr("New File..."), this); + cmd = ActionManager::registerAction(action, Constants::NEW_FILE); + mfile->addAction(cmd, Constants::G_FILE_NEW); + connect(action, &QAction::triggered, this, []() { + if (!ICore::isNewItemDialogRunning()) { + ICore::showNewItemDialog( + tr("New File", "Title of dialog"), + Utils::filtered(Core::IWizardFactory::allWizardFactories(), + Utils::equal(&Core::IWizardFactory::kind, + Core::IWizardFactory::FileWizard)), + FilePath()); + } else { + ICore::raiseWindow(ICore::newItemDialog()); + } + }); + } + // Open Action icon = QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon()); m_openAction = new QAction(icon, tr("&Open File or Project..."), this); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 509804edf3f..d38613898fc 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -834,6 +834,7 @@ QToolButton *PerspectivePrivate::setupToolButton(QAction *action) auto toolButton = new QToolButton(m_innerToolBar); toolButton->setProperty("panelwidget", true); toolButton->setDefaultAction(action); + toolButton->setToolTip(action->toolTip()); m_innerToolBarLayout->addWidget(toolButton); return toolButton; } diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index 5c3097ca907..cc33e0445a8 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -34,8 +34,6 @@ #include #include -enum { debug = 0 }; - namespace Debugger { namespace Internal { diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index f4b4439dae9..fd54d777005 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -136,10 +136,15 @@ void LanguageClientManager::clientStarted(Client *client) qCDebug(Log) << "client started: " << client->name() << client; QTC_ASSERT(managerInstance, return); QTC_ASSERT(client, return); - if (managerInstance->m_shuttingDown) + if (managerInstance->m_shuttingDown) { clientFinished(client); - else - client->initialize(); + return; + } + client->initialize(); + const QList &clientDocs + = managerInstance->m_clientForDocument.keys(client); + for (TextEditor::TextDocument *document : clientDocs) + client->openDocument(document); } void LanguageClientManager::clientFinished(Client *client) diff --git a/src/plugins/languageclient/semantichighlightsupport.cpp b/src/plugins/languageclient/semantichighlightsupport.cpp index 5132cd9326a..260cabd7e49 100644 --- a/src/plugins/languageclient/semantichighlightsupport.cpp +++ b/src/plugins/languageclient/semantichighlightsupport.cpp @@ -261,7 +261,7 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument) void SemanticTokenSupport::rehighlight() { for (const Utils::FilePath &filePath : m_tokens.keys()) - highlight(filePath); + highlight(filePath, true); } void addModifiers(int key, @@ -369,6 +369,8 @@ void SemanticTokenSupport::setAdditionalTokenTypeStyles( SemanticRequestTypes SemanticTokenSupport::supportedSemanticRequests(TextDocument *document) const { + if (!m_client->documentOpen(document)) + return SemanticRequestType::None; auto supportedRequests = [&](const QJsonObject &options) -> SemanticRequestTypes { TextDocumentRegistrationOptions docOptions(options); if (docOptions.isValid() @@ -472,7 +474,7 @@ void SemanticTokenSupport::handleSemanticTokensDelta( highlight(filePath); } -void SemanticTokenSupport::highlight(const Utils::FilePath &filePath) +void SemanticTokenSupport::highlight(const Utils::FilePath &filePath, bool force) { TextDocument *doc = TextDocument::textDocumentForFilePath(filePath); if (!doc || LanguageClientManager::clientForDocument(doc) != m_client) @@ -515,7 +517,7 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath) } } - m_tokensHandler(doc, expandedTokens, versionedTokens.version); + m_tokensHandler(doc, expandedTokens, versionedTokens.version, force); return; } int line = 1; diff --git a/src/plugins/languageclient/semantichighlightsupport.h b/src/plugins/languageclient/semantichighlightsupport.h index 110b14f23b0..1f205fe7813 100644 --- a/src/plugins/languageclient/semantichighlightsupport.h +++ b/src/plugins/languageclient/semantichighlightsupport.h @@ -56,7 +56,7 @@ inline bool operator==(const ExpandedSemanticToken &t1, const ExpandedSemanticTo && t1.type == t2.type && t1.modifiers == t2.modifiers; } using SemanticTokensHandler = std::function &, int)>; + const QList &, int, bool)>; namespace SemanticHighligtingSupport { @@ -99,7 +99,7 @@ private: void handleSemanticTokensDelta(const Utils::FilePath &filePath, const LanguageServerProtocol::SemanticTokensDeltaResult &result, int documentVersion); - void highlight(const Utils::FilePath &filePath); + void highlight(const Utils::FilePath &filePath, bool force = false); void updateFormatHash(); void currentEditorChanged(); void onCurrentEditorChanged(Core::IEditor *editor); diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 858b0126eb7..4a21ece87bc 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -1046,7 +1046,7 @@ bool McuSupportOptions::kitUpToDate(const Kit *kit, const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage) { return kitQulVersion(kit) == mcuTarget->qulVersion() && - kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()) == qtForMCUsSdkPackage->path(); + kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() == qtForMCUsSdkPackage->path().toUserOutput(); } void McuSupportOptions::deletePackagesAndTargets() diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp index dad6e9539e9..c0349814e0a 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp @@ -195,6 +195,7 @@ bool KitsPageFactory::validateData(Utils::Id typeId, const QVariant &data, QStri // -------------------------------------------------------------------- static const char KEY_PROJECT_NAME_VALIDATOR[] = "projectNameValidator"; +static const char KEY_PROJECT_NAME_VALIDATOR_USER_MESSAGE[] = "trProjectNameValidatorUserMessage"; ProjectPageFactory::ProjectPageFactory() { @@ -215,10 +216,13 @@ Utils::WizardPage *ProjectPageFactory::create(JsonWizard *wizard, Utils::Id type page->setDescription(wizard->expander()->expand(description)); QString projectNameValidator = tmp.value(QLatin1String(KEY_PROJECT_NAME_VALIDATOR)).toString(); + QString projectNameValidatorUserMessage + = JsonWizardFactory::localizedString(tmp.value(QLatin1String(KEY_PROJECT_NAME_VALIDATOR_USER_MESSAGE))); + if (!projectNameValidator.isEmpty()) { QRegularExpression regularExpression(projectNameValidator); if (regularExpression.isValid()) - page->setProjectNameRegularExpression(regularExpression); + page->setProjectNameRegularExpression(regularExpression, projectNameValidatorUserMessage); } return page; diff --git a/src/plugins/projectexplorer/xcodebuildparser.cpp b/src/plugins/projectexplorer/xcodebuildparser.cpp index d967cd40b38..8b538472cdc 100644 --- a/src/plugins/projectexplorer/xcodebuildparser.cpp +++ b/src/plugins/projectexplorer/xcodebuildparser.cpp @@ -54,13 +54,14 @@ XcodebuildParser::XcodebuildParser() OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, OutputFormat type) { + static const QStringList notesPatterns({"note: Build preparation complete", + "note: Building targets in parallel", + "note: Planning build"}); const QString lne = rightTrimmed(line); if (type == StdOutFormat) { QRegularExpressionMatch match = m_buildRe.match(line); - if (match.hasMatch()) { + if (match.hasMatch() || notesPatterns.contains(lne)) { m_xcodeBuildParserState = InXcodebuild; - m_lastTarget = match.captured(2); - m_lastProject = match.captured(3); return Status::Done; } if (m_xcodeBuildParserState == InXcodebuild @@ -89,7 +90,6 @@ OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, Outpu if (match.hasMatch()) { ++m_fatalErrorCount; m_xcodeBuildParserState = UnknownXcodebuildState; - // unfortunately the m_lastTarget, m_lastProject might not be in sync scheduleTask(CompileTask(Task::Error, tr("Xcodebuild failed.")), 1); } if (m_xcodeBuildParserState == OutsideXcodebuild) @@ -193,6 +193,19 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data() << Tasks() << QString() << XcodebuildParser::OutsideXcodebuild; + QTest::newRow("switch outside->in->outside (new)") + << XcodebuildParser::OutsideXcodebuild + << QString::fromLatin1("outside\n" + "note: Build preparation complete\n" + "in xcodebuild\n" + "in xcodebuild2\n" + "** BUILD SUCCEEDED **\n" + "outside2") + << OutputParserTester::STDOUT + << QString::fromLatin1("outside\noutside2\n") << QString::fromLatin1("in xcodebuild\nin xcodebuild2\n") + << Tasks() + << QString() + << XcodebuildParser::OutsideXcodebuild; QTest::newRow("switch Unknown->in->outside") << XcodebuildParser::UnknownXcodebuildState << QString::fromLatin1("unknown\n" diff --git a/src/plugins/projectexplorer/xcodebuildparser.h b/src/plugins/projectexplorer/xcodebuildparser.h index 0c31e27cddd..f7197322acc 100644 --- a/src/plugins/projectexplorer/xcodebuildparser.h +++ b/src/plugins/projectexplorer/xcodebuildparser.h @@ -56,8 +56,6 @@ private: const QRegularExpression m_successRe; const QRegularExpression m_buildRe; XcodebuildStatus m_xcodeBuildParserState = OutsideXcodebuild; - QString m_lastTarget; - QString m_lastProject; #if defined WITH_TESTS friend class XcodebuildParserTester; diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp index a3cc9528348..be1c5f9dd26 100644 --- a/src/plugins/qmakeprojectmanager/profileeditor.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp @@ -229,7 +229,10 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor, QDir dir(textDocument()->filePath().toFileInfo().absolutePath()); QString fileName = dir.filePath(buffer); QFileInfo fi(fileName); - if (fi.exists()) { + if (Utils::HostOsInfo::isWindowsHost() && fileName.startsWith("//")) { + // Windows network paths are not supported here since checking for their existence can + // lock the gui thread. See: QTCREATORBUG-26579 + } else if (fi.exists()) { if (fi.isDir()) { QDir subDir(fi.absoluteFilePath()); QString subProject = subDir.filePath(subDir.dirName() + QLatin1String(".pro")); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index c6fa4a0bdb5..1c944f49a94 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -108,6 +108,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) const QString orientationKey = QStringLiteral("globalOrientation"); const QString editLightKey = QStringLiteral("showEditLight"); const QString gridKey = QStringLiteral("showGrid"); + const QString particlesPlayKey = QStringLiteral("particlePlay"); if (sceneState.contains(sceneKey)) { qint32 newActiveScene = sceneState[sceneKey].value(); @@ -151,6 +152,11 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) m_showGridAction->action()->setChecked(sceneState[gridKey].toBool()); else m_showGridAction->action()->setChecked(false); + + if (sceneState.contains(particlesPlayKey)) + m_particlesPlayAction->action()->setChecked(sceneState[particlesPlayKey].toBool()); + else + m_particlesPlayAction->action()->setChecked(true); } void Edit3DView::modelAttached(Model *model) diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index bc45647b605..cede56f299d 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -101,7 +101,7 @@ bool SubComponentManager::addImport(const Import &import, int index) } if (importExists) { - if (index == -1) + if (index == -1 || index > m_imports.size()) m_imports.append(import); else m_imports.insert(index, import); diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp index c4a2bae6178..a46315310a2 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp @@ -32,6 +32,7 @@ #include +#include #include namespace QmlDesigner { @@ -53,30 +54,28 @@ Storage::Version convertVersion(QmlDom::Version version) Utils::PathString convertUri(const QString &uri) { - Utils::PathString path{QStringView{uri.begin() + 7, uri.end()}}; - if (path.endsWith("/.")) - return path; - if (path.endsWith("/")) { - path += "."; - return path; - } + QStringView localPath{uri.begin() + 7, uri.end()}; - path += "/."; - return path; + std::filesystem::path path{ + std::u16string_view{localPath.utf16(), static_cast(localPath.size())}}; + + auto x = std::filesystem::weakly_canonical(path); + + return Utils::PathString{x.generic_string()}; } void addImports(Storage::Imports &imports, const QList &qmlImports, SourceId sourceId, - SourceContextId sourceContextId, - QmlDocumentParser::PathCache &pathCache, + const QString &directoryPath, QmlDocumentParser::ProjectStorage &storage) { for (const QmlDom::Import &qmlImport : qmlImports) { if (qmlImport.uri == u"file://.") { - auto moduleId = storage.moduleId(pathCache.sourceContextPath(sourceContextId)); + auto moduleId = storage.moduleId(Utils::PathString{directoryPath}); imports.emplace_back(moduleId, Storage::Version{}, sourceId); } else if (qmlImport.uri.startsWith(u"file://")) { + auto x = convertUri(qmlImport.uri); auto moduleId = storage.moduleId(convertUri(qmlImport.uri)); imports.emplace_back(moduleId, Storage::Version{}, sourceId); } else { @@ -144,7 +143,7 @@ void addEnumeraton(Storage::Type &type, const QmlDom::Component &component) Storage::Type QmlDocumentParser::parse(const QString &sourceContent, Storage::Imports &imports, SourceId sourceId, - SourceContextId sourceContextId) + const QString &directoryPath) { Storage::Type type; @@ -155,9 +154,11 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent, QmlDom::DomItem items; + QString filePath{directoryPath + "/foo.qml"}; + environment.loadFile( - {}, - {}, + filePath, + filePath, sourceContent, QDateTime{}, [&](QmlDom::Path, const QmlDom::DomItem &, const QmlDom::DomItem &newItems) { @@ -185,7 +186,7 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent, type.prototype = Storage::ImportedType{Utils::SmallString{qmlObject.name()}}; - addImports(imports, qmlFile->imports(), sourceId, sourceContextId, m_pathCache, m_storage); + addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage); addPropertyDeclarations(type, qmlObject); addFunctionAndSignalDeclarations(type, qmlObject); diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h index e2dd2434058..c256f74309a 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h @@ -46,18 +46,16 @@ public: using ProjectStorage = QmlDesigner::ProjectStorage; using PathCache = QmlDesigner::SourcePathCache; - QmlDocumentParser(PathCache &pathCache, ProjectStorage &storage) - : m_pathCache{pathCache} - , m_storage{storage} + QmlDocumentParser(ProjectStorage &storage) + : m_storage{storage} {} - virtual Storage::Type parse(const QString &sourceContent, - Storage::Imports &imports, - SourceId sourceId, - SourceContextId sourceContextId); + Storage::Type parse(const QString &sourceContent, + Storage::Imports &imports, + SourceId sourceId, + const QString &directoryPath); private: - PathCache &m_pathCache; ProjectStorage &m_storage; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index 24faa267397..25fadb23940 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -56,13 +57,26 @@ bool operator==(const GeneratableFile &left, const GeneratableFile &right) return (left.filePath == right.filePath && left.content == right.content); } +enum ProjectDirectoryError { + NoError = 0, + MissingContentDir = 1<<1, + MissingImportDir = 1<<2, + MissingCppDir = 1<<3, + MissingMainCMake = 1<<4, + MissingMainQml = 1<<5, + MissingAppMainQml = 1<<6, + MissingQmlModules = 1<<7, + MissingMainCpp = 1<<8, + MissingMainCppHeader = 1<<9 +}; + QVector queuedFiles; void generateMenuEntry() { Core::ActionContainer *buildMenu = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT); - auto action = new QAction("Generate CMakeLists.txt files"); + auto action = new QAction(QCoreApplication::tr("Generate CMakeLists.txt Files")); QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists); Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists"); buildMenu->addAction(cmd, ProjectExplorer::Constants::G_BUILD_RUN); @@ -76,8 +90,16 @@ void generateMenuEntry() void onGenerateCmakeLists() { - queuedFiles.clear(); FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory(); + + int projectDirErrors = isProjectCorrectlyFormed(rootDir); + if (projectDirErrors != NoError) { + showProjectDirErrorDialog(projectDirErrors); + if (isErrorFatal(projectDirErrors)) + return; + } + + queuedFiles.clear(); GenerateCmakeLists::generateCmakes(rootDir); GenerateEntryPoints::generateMainCpp(rootDir); GenerateEntryPoints::generateMainQml(rootDir); @@ -85,6 +107,57 @@ void onGenerateCmakeLists() writeQueuedFiles(); } +bool isErrorFatal(int error) +{ + if (error & MissingContentDir || + error & MissingImportDir || + error & MissingCppDir || + error & MissingAppMainQml) + return true; + + return false; +} + +const char DIRNAME_CONTENT[] = "content"; +const char DIRNAME_IMPORT[] = "imports"; +const char DIRNAME_CPP[] = "src"; + +const char FILENAME_CMAKELISTS[] = "CMakeLists.txt"; +const char FILENAME_APPMAINQML[] = "App.qml"; +const char FILENAME_MAINQML[] = "main.qml"; +const char FILENAME_MAINCPP[] = "main.cpp"; +const char FILENAME_MAINCPP_HEADER[] = "import_qml_plugins.h"; +const char FILENAME_MODULES[] = "qmlmodules"; + +int isProjectCorrectlyFormed(const FilePath &rootDir) +{ + int errors = NoError; + + if (!rootDir.pathAppended(DIRNAME_CONTENT).exists()) + errors |= MissingContentDir; + if (!rootDir.pathAppended(DIRNAME_CONTENT).pathAppended(FILENAME_APPMAINQML).exists()) + errors |= MissingAppMainQml; + + if (!rootDir.pathAppended(DIRNAME_IMPORT).exists()) + errors |= MissingImportDir; + + if (!rootDir.pathAppended(DIRNAME_CPP).exists()) + errors |= MissingCppDir; + if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP).exists()) + errors |= MissingMainCpp; + if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP_HEADER).exists()) + errors |= MissingMainCppHeader; + + if (!rootDir.pathAppended(FILENAME_CMAKELISTS).exists()) + errors |= MissingMainCMake; + if (!rootDir.pathAppended(FILENAME_MODULES).exists()) + errors |= MissingQmlModules; + if (!rootDir.pathAppended(FILENAME_MAINQML).exists()) + errors |= MissingMainQml; + + return errors; +} + void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles) { QtConcurrent::blockingFilter(queuedFiles, [confirmedFiles](const GeneratableFile &qf) { @@ -92,6 +165,65 @@ void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles) }); } +const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::tr( + "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1"); +const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::tr( + "The project is not properly structured for automatically generating CMake files.\n\nThe following files will be created:\n\n%1"); +const QString WARNING_TITLE_FATAL = QCoreApplication::tr( + "Cannot Generate CMake Files"); +const QString WARNING_TITLE_NONFATAL = QCoreApplication::tr( + "Problems with Generating CMake Files"); + +void showProjectDirErrorDialog(int error) +{ + QString fatalList; + QString nonFatalList; + + if (error & MissingContentDir) + fatalList.append(QString(DIRNAME_CONTENT) + "\n"); + if (error & MissingAppMainQml) + fatalList.append(QString(DIRNAME_CONTENT) + + QDir::separator() + + QString(FILENAME_APPMAINQML) + + "\n"); + if (error & MissingCppDir) + fatalList.append(QString(DIRNAME_CPP) + "\n"); + if (error & MissingImportDir) + fatalList.append(QString(DIRNAME_IMPORT) + "\n"); + + if (error & MissingMainCMake) + nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n"); + if (error & MissingQmlModules) + nonFatalList.append(QString(FILENAME_MODULES) + "\n"); + + if (error & MissingMainQml) + nonFatalList.append(QString(FILENAME_MAINQML) + "\n"); + + if (error & MissingMainCpp) + nonFatalList.append(QString(DIRNAME_CPP) + + QDir::separator() + + QString(FILENAME_MAINCPP) + + "\n"); + if (error & MissingMainCppHeader) + nonFatalList.append(QString(DIRNAME_CPP) + + QDir::separator() + + QString(FILENAME_MAINCPP_HEADER) + + "\n"); + + bool isFatal = isErrorFatal(error); + + if (isFatal) { + QMessageBox::critical(nullptr, + WARNING_TITLE_FATAL, + WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList + nonFatalList)); + } + else { + QMessageBox::warning(nullptr, + WARNING_TITLE_NONFATAL, + WARNING_MISSING_STRUCTURE_NONFATAL.arg(nonFatalList)); + } +} + bool showConfirmationDialog(const Utils::FilePath &rootDir) { Utils::FilePaths files; @@ -114,6 +246,7 @@ bool queueFile(const FilePath &filePath, const QString &fileContent) GeneratableFile file; file.filePath = filePath; file.content = fileContent; + file.fileExists = filePath.exists(); queuedFiles.append(file); return true; @@ -159,9 +292,10 @@ QStringList moduleNames; const QDir::Filters FILES_ONLY = QDir::Files; const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot; -const char CMAKEFILENAME[] = "CMakeLists.txt"; const char QMLDIRFILENAME[] = "qmldir"; -const char MODULEFILENAME[] = "qmlmodules"; + +const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl"; +const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl"; bool generateCmakes(const FilePath &rootDir) { @@ -177,9 +311,6 @@ bool generateCmakes(const FilePath &rootDir) return true; } -const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl"; -const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl"; - void generateMainCmake(const FilePath &rootDir) { //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all. @@ -194,7 +325,7 @@ void generateMainCmake(const FilePath &rootDir) modulesAsPlugins.append(" " + moduleName + "plugin\n"); QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins); - GenerateCmake::queueFile(rootDir.pathAppended(MODULEFILENAME), moduleFileContent); + GenerateCmake::queueFile(rootDir.pathAppended(GenerateCmake::FILENAME_MODULES), moduleFileContent); } const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n"; @@ -336,14 +467,14 @@ QStringList getDirectoryTreeResources(const FilePath &dir) void queueCmakeFile(const FilePath &dir, const QString &content) { - FilePath filePath = dir.pathAppended(CMAKEFILENAME); + FilePath filePath = dir.pathAppended(GenerateCmake::FILENAME_CMAKELISTS); GenerateCmake::queueFile(filePath, content); } bool isFileBlacklisted(const QString &fileName) { return (!fileName.compare(QMLDIRFILENAME) || - !fileName.compare(CMAKEFILENAME)); + !fileName.compare(GenerateCmake::FILENAME_CMAKELISTS)); } } @@ -358,18 +489,15 @@ bool generateEntryPointFiles(const FilePath &dir) } const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl"; -const char MAIN_CPPFILE_DIR[] = "src"; -const char MAIN_CPPFILE_NAME[] = "main.cpp"; const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl"; -const char MAIN_CPPFILE_HEADER_NAME[] = "import_qml_plugins.h"; const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n"; bool generateMainCpp(const FilePath &dir) { - FilePath srcDir = dir.pathAppended(MAIN_CPPFILE_DIR); + FilePath srcDir = dir.pathAppended(GenerateCmake::DIRNAME_CPP); QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH); - FilePath cppFilePath = srcDir.pathAppended(MAIN_CPPFILE_NAME); + FilePath cppFilePath = srcDir.pathAppended(GenerateCmake::FILENAME_MAINCPP); bool cppOk = GenerateCmake::queueFile(cppFilePath, cppContent); QString modulesAsPlugins; @@ -379,19 +507,18 @@ bool generateMainCpp(const FilePath &dir) QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH) .arg(modulesAsPlugins); - FilePath headerFilePath = srcDir.pathAppended(MAIN_CPPFILE_HEADER_NAME); + FilePath headerFilePath = srcDir.pathAppended(GenerateCmake::FILENAME_MAINCPP_HEADER); bool headerOk = GenerateCmake::queueFile(headerFilePath, headerContent); return cppOk && headerOk; } -const char MAIN_QMLFILE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl"; -const char MAIN_QMLFILE_NAME[] = "main.qml"; +const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl"; bool generateMainQml(const FilePath &dir) { - QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_PATH); - FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME); + QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH); + FilePath filePath = dir.pathAppended(GenerateCmake::FILENAME_MAINQML); return GenerateCmake::queueFile(filePath, content); } diff --git a/src/plugins/qmldesigner/generatecmakelists.h b/src/plugins/qmldesigner/generatecmakelists.h index b9f225e9465..794610a53f8 100644 --- a/src/plugins/qmldesigner/generatecmakelists.h +++ b/src/plugins/qmldesigner/generatecmakelists.h @@ -34,13 +34,17 @@ namespace GenerateCmake { struct GeneratableFile { Utils::FilePath filePath; QString content; + bool fileExists; }; bool operator==(const GeneratableFile &left, const GeneratableFile &right); void generateMenuEntry(); void onGenerateCmakeLists(); +bool isErrorFatal(int error); +int isProjectCorrectlyFormed(const Utils::FilePath &rootDir); void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles); +void showProjectDirErrorDialog(int error); bool showConfirmationDialog(const Utils::FilePath &rootDir); bool queueFile(const Utils::FilePath &filePath, const QString &fileContent); bool writeFile(const GeneratableFile &file); diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp index 4902ac52361..6bd695ac72b 100644 --- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp +++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp @@ -222,8 +222,8 @@ QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent) bool skipDeploy = false; const Kit *kit = SessionManager::startupTarget()->kit(); if (SessionManager::startupTarget() && kit) - skipDeploy = kit-> - supportedPlatforms().contains(Android::Constants::ANDROID_DEVICE_TYPE); + skipDeploy = kit->supportedPlatforms().contains(Android::Constants::ANDROID_DEVICE_TYPE) + || DeviceTypeKitAspect::deviceTypeId(kit) == Android::Constants::ANDROID_DEVICE_TYPE; ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE, skipDeploy); }); menu->addAction( diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp index 7b5b90e3b1c..98526014955 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -91,13 +92,14 @@ QmlProjectPlugin::~QmlProjectPlugin() void QmlProjectPlugin::openQDS(const Utils::FilePath &fileName) { - const QString &qdsPath = QmlProjectPlugin::qdsInstallationEntry(); + const Utils::FilePath &qdsPath = QmlProjectPlugin::qdsInstallationEntry(); bool qdsStarted = false; //-a and -client arguments help to append project to open design studio application if (Utils::HostOsInfo::isMacHost()) - qdsStarted = QProcess::startDetached("/usr/bin/open", {"-a", qdsPath, fileName.toString()}); + qdsStarted = Utils::QtcProcess::startDetached( + {"/usr/bin/open", {"-a", qdsPath.path(), fileName.toString()}}); else - qdsStarted = QProcess::startDetached(qdsPath, {"-client", fileName.toString()}); + qdsStarted = Utils::QtcProcess::startDetached({qdsPath, {"-client", fileName.toString()}}); if (!qdsStarted) { QMessageBox::warning(Core::ICore::dialogParent(), @@ -106,17 +108,17 @@ void QmlProjectPlugin::openQDS(const Utils::FilePath &fileName) } } -QString QmlProjectPlugin::qdsInstallationEntry() +Utils::FilePath QmlProjectPlugin::qdsInstallationEntry() { QSettings *settings = Core::ICore::settings(); const QString qdsInstallationEntry = "QML/Designer/DesignStudioInstallation"; //set in installer - return settings->value(qdsInstallationEntry).toString(); + return Utils::FilePath::fromUserInput(settings->value(qdsInstallationEntry).toString()); } bool QmlProjectPlugin::qdsInstallationExists() { - return Utils::FilePath::fromString(qdsInstallationEntry()).exists(); + return qdsInstallationEntry().exists(); } Utils::FilePath findQmlProject(const Utils::FilePath &folder) diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.h b/src/plugins/qmlprojectmanager/qmlprojectplugin.h index 260512c5df3..92df42532cb 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.h +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.h @@ -41,7 +41,7 @@ public: ~QmlProjectPlugin() final; static void openQDS(const Utils::FilePath &fileName); - static QString qdsInstallationEntry(); + static Utils::FilePath qdsInstallationEntry(); static bool qdsInstallationExists(); private: diff --git a/src/plugins/studiowelcome/qdsnewdialog.cpp b/src/plugins/studiowelcome/qdsnewdialog.cpp index b031a083bcf..62def1d397e 100644 --- a/src/plugins/studiowelcome/qdsnewdialog.cpp +++ b/src/plugins/studiowelcome/qdsnewdialog.cpp @@ -101,7 +101,7 @@ QdsNewDialog::QdsNewDialog(QWidget *parent) QObject::connect(&m_wizard, &WizardHandler::projectCanBeCreated, this, &QdsNewDialog::onProjectCanBeCreatedChanged); QObject::connect(&m_wizard, &WizardHandler::wizardCreationFailed, this, [this]() { - QMessageBox::critical(m_dialog, "New project", "Failed to initialize data"); + QMessageBox::critical(m_dialog, tr("New project"), tr("Failed to initialize data")); reject(); delete this; }); @@ -195,6 +195,11 @@ void QdsNewDialog::setScreenSizeIndex(int index) m_qmlScreenSizeIndex = index; } +int QdsNewDialog::screenSizeIndex() const +{ + return m_wizard.screenSizeIndex(); +} + void QdsNewDialog::setTargetQtVersion(int index) { m_wizard.setTargetQtVersionIndex(index); diff --git a/src/plugins/studiowelcome/qdsnewdialog.h b/src/plugins/studiowelcome/qdsnewdialog.h index ede50bc97a7..8e331bd125e 100644 --- a/src/plugins/studiowelcome/qdsnewdialog.h +++ b/src/plugins/studiowelcome/qdsnewdialog.h @@ -66,6 +66,7 @@ public: Q_INVOKABLE QString currentProjectQmlPath() const; Q_INVOKABLE void setScreenSizeIndex(int index); // called when ComboBox item is "activated" + Q_INVOKABLE int screenSizeIndex() const; Q_INVOKABLE void setTargetQtVersion(int index); Q_INVOKABLE QString chooseProjectLocation(); diff --git a/src/plugins/studiowelcome/wizardhandler.cpp b/src/plugins/studiowelcome/wizardhandler.cpp index fce7aa120f9..c8c6c85d12e 100644 --- a/src/plugins/studiowelcome/wizardhandler.cpp +++ b/src/plugins/studiowelcome/wizardhandler.cpp @@ -174,6 +174,15 @@ void WizardHandler::setScreenSizeIndex(int index) cbfield->selectRow(index); } +int WizardHandler::screenSizeIndex() const +{ + auto *field = m_detailsPage->jsonField("ScreenFactor"); + auto *cbfield = dynamic_cast(field); + QTC_ASSERT(cbfield, return -1); + + return cbfield->selectedRow(); +} + void WizardHandler::setTargetQtVersionIndex(int index) { auto *field = m_detailsPage->jsonField("TargetQtVersion"); diff --git a/src/plugins/studiowelcome/wizardhandler.h b/src/plugins/studiowelcome/wizardhandler.h index a828d595f66..ad9424bc441 100644 --- a/src/plugins/studiowelcome/wizardhandler.h +++ b/src/plugins/studiowelcome/wizardhandler.h @@ -50,6 +50,7 @@ public: //TODO: location should not be needed in reset() -- only when creating the project void reset(const ProjectItem &projectInfo, int projectSelection, const Utils::FilePath &location); void setScreenSizeIndex(int index); + int screenSizeIndex() const; void setTargetQtVersionIndex(int index); bool haveTargetQtVersion() const; void setStyleIndex(int index); diff --git a/src/plugins/webassembly/webassemblyrunconfiguration.cpp b/src/plugins/webassembly/webassemblyrunconfiguration.cpp index 123887caf7b..29bd1b5d047 100644 --- a/src/plugins/webassembly/webassemblyrunconfiguration.cpp +++ b/src/plugins/webassembly/webassemblyrunconfiguration.cpp @@ -55,14 +55,20 @@ static FilePath pythonInterpreter(const Environment &env) return {}; } -static CommandLine emrunCommand(Target *target, const QString &browser, const QString &port) +static FilePath htmlFileInDir(const FilePath &dir) { - if (BuildConfiguration *bc = target->activeBuildConfiguration()) { + const FilePaths htmlFiles = dir.dirEntries(QStringList("*.html"), QDir::Files); + return htmlFiles.isEmpty() ? FilePath() : htmlFiles.first(); +} + +static CommandLine emrunCommand(const RunConfiguration *rc, const QString &browser, + const QString &port) +{ + if (BuildConfiguration *bc = rc->target()->activeBuildConfiguration()) { const Environment env = bc->environment(); const FilePath emrun = env.searchInPath("emrun"); const FilePath emrunPy = emrun.absolutePath().pathAppended(emrun.baseName() + ".py"); - const FilePath html = - bc->buildDirectory().pathAppended(target->project()->displayName() + ".html"); + const FilePath html = htmlFileInDir(bc->buildDirectory()); return CommandLine(pythonInterpreter(env), { emrunPy.path(), @@ -91,8 +97,8 @@ public: effectiveEmrunCall->setDisplayStyle(StringAspect::TextEditDisplay); effectiveEmrunCall->setReadOnly(true); - setUpdater([target, effectiveEmrunCall, webBrowserAspect] { - effectiveEmrunCall->setValue(emrunCommand(target, + setUpdater([this, effectiveEmrunCall, webBrowserAspect] { + effectiveEmrunCall->setValue(emrunCommand(this, webBrowserAspect->currentBrowser(), "").toUserOutput()); }); @@ -122,7 +128,7 @@ public: setStarter([this, runControl, portsGatherer] { Runnable r; - r.command = emrunCommand(runControl->target(), + r.command = emrunCommand(runControl->runConfiguration(), runControl->aspect()->currentBrowser(), QString::number(portsGatherer->findEndPoint().port())); SimpleTargetRunner::doStart(r, {}); diff --git a/tests/unit/unittest/qmldocumentparser-test.cpp b/tests/unit/unittest/qmldocumentparser-test.cpp index 451003ba33c..1e890c6fc69 100644 --- a/tests/unit/unittest/qmldocumentparser-test.cpp +++ b/tests/unit/unittest/qmldocumentparser-test.cpp @@ -129,17 +129,17 @@ protected: QmlDesigner::ProjectStorage storage{database, database.isInitialized()}; QmlDesigner::SourcePathCache> sourcePathCache{ storage}; - QmlDesigner::QmlDocumentParser parser{sourcePathCache, storage}; + QmlDesigner::QmlDocumentParser parser{storage}; Storage::Imports imports; SourceId qmlFileSourceId{sourcePathCache.sourceId("path/to/qmlfile.qml")}; SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)}; - SourceId directorySourceId{sourcePathCache.sourceId("path/to/.")}; - ModuleId directoryModuleId{&directorySourceId}; + QString directoryPath{"/path/to"}; + ModuleId directoryModuleId{storage.moduleId("/path/to")}; }; TEST_F(QmlDocumentParser, Prototype) { - auto type = parser.parse("Example{}", imports, qmlFileSourceId, qmlFileSourceContextId); + auto type = parser.parse("Example{}", imports, qmlFileSourceId, directoryPath); ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example"))); } @@ -150,7 +150,7 @@ TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype) auto type = parser.parse("import Example as Example\n Example.Item{}", imports, qmlFileSourceId, - qmlFileSourceContextId); + directoryPath); ASSERT_THAT(type, HasPrototype(Storage::QualifiedImportedType( @@ -159,10 +159,7 @@ TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype) TEST_F(QmlDocumentParser, Properties) { - auto type = parser.parse("Example{\n property int foo\n}", - imports, - qmlFileSourceId, - qmlFileSourceContextId); + auto type = parser.parse("Example{\n property int foo\n}", imports, qmlFileSourceId, directoryPath); ASSERT_THAT(type.propertyDeclarations, UnorderedElementsAre(IsPropertyDeclaration("foo", @@ -170,16 +167,18 @@ TEST_F(QmlDocumentParser, Properties) Storage::PropertyDeclarationTraits::None))); } -TEST_F(QmlDocumentParser, DISABLED_Imports) +TEST_F(QmlDocumentParser, Imports) { - ModuleId fooDirectoryModuleId = storage.moduleId("path/to/foo/."); + ModuleId fooDirectoryModuleId = storage.moduleId("/path/foo"); ModuleId qmlModuleId = storage.moduleId("QML"); ModuleId qtQmlModuleId = storage.moduleId("QtQml"); ModuleId qtQuickModuleId = storage.moduleId("QtQuick"); - auto type = parser.parse("import QtQuick\n import \"../foo\"\nExample{}", + auto type = parser.parse(R"(import QtQuick + import "../foo" + Example{})", imports, qmlFileSourceId, - qmlFileSourceContextId); + directoryPath); ASSERT_THAT(imports, UnorderedElementsAre( @@ -196,7 +195,7 @@ TEST_F(QmlDocumentParser, Functions) "Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}", imports, qmlFileSourceId, - qmlFileSourceContextId); + directoryPath); ASSERT_THAT(type.functionDeclarations, UnorderedElementsAre(AllOf(IsFunctionDeclaration("otherFunction", ""), @@ -212,7 +211,7 @@ TEST_F(QmlDocumentParser, Signals) auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}", imports, qmlFileSourceId, - qmlFileSourceContextId); + directoryPath); ASSERT_THAT(type.signalDeclarations, UnorderedElementsAre(AllOf(IsSignalDeclaration("someSignal"), @@ -229,7 +228,7 @@ TEST_F(QmlDocumentParser, Enumeration) "State{On,Off}\n}", imports, qmlFileSourceId, - qmlFileSourceContextId); + directoryPath); ASSERT_THAT(type.enumerationDeclarations, UnorderedElementsAre(