diff --git a/dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch b/dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch index 6f22014ad3a..27b2e2a01e4 100644 --- a/dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch +++ b/dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch @@ -505,10 +505,10 @@ index c788abb881..ed4773b132 100644 +clang_PrintingPolicy_setProperty +clang_PrintingPolicy_dispose diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp -index f2a96d6be6..a9f5ee1da4 100644 +index f2a96d6be6..342fbd5279 100644 --- a/tools/clang/unittests/libclang/LibclangTest.cpp +++ b/tools/clang/unittests/libclang/LibclangTest.cpp -@@ -572,3 +572,33 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) { +@@ -572,3 +572,35 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) { EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU)); DisplayDiagnostics(); } @@ -536,6 +536,8 @@ index f2a96d6be6..a9f5ee1da4 100644 + for (unsigned Value = 0; Value < 2; ++Value) { + for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) { + auto Property = static_cast(I); ++ if (Property == CXPrintingPolicy_ConstantsAsWritten || Property == CXPrintingPolicy_SuppressImplicitBase) ++ continue; // These are not yet in clang 5.0. + + clang_PrintingPolicy_setProperty(Policy, Property, Value); + EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property)); diff --git a/doc/api/first-plugin.qdoc b/doc/api/first-plugin.qdoc index a4e04d7c81a..c56b3c9c561 100644 --- a/doc/api/first-plugin.qdoc +++ b/doc/api/first-plugin.qdoc @@ -96,12 +96,10 @@ \li \uicontrol Copyright is a one-line, short copyright string. - \li \uicontrol License is a multi-line license text (but - shouldn't be pages over pages long, since the interface - doesn't allow nice reading of long texts). + \li \uicontrol License is a license text. - \li \uicontrol{Description} is a relatively short, but possibly - multi-line description of what the plugin does. + \li \uicontrol{Description} is a short description of what the + plugin does. \li \uicontrol URL is a website where the user can find more information about the plugin and/or organization providing diff --git a/doc/api/images/firstplugin-kitselection.png b/doc/api/images/firstplugin-kitselection.png index 354c2115515..4dd77864363 100644 Binary files a/doc/api/images/firstplugin-kitselection.png and b/doc/api/images/firstplugin-kitselection.png differ diff --git a/doc/api/images/firstplugin-nameandpath.png b/doc/api/images/firstplugin-nameandpath.png index 131af981610..6a1c4d3e415 100644 Binary files a/doc/api/images/firstplugin-nameandpath.png and b/doc/api/images/firstplugin-nameandpath.png differ diff --git a/doc/api/images/firstplugin-pluginsetup.png b/doc/api/images/firstplugin-pluginsetup.png index 1ce6fd9146e..b48fe2f3fc4 100644 Binary files a/doc/api/images/firstplugin-pluginsetup.png and b/doc/api/images/firstplugin-pluginsetup.png differ diff --git a/doc/api/images/firstplugin-summary.png b/doc/api/images/firstplugin-summary.png index ca1a65f3c48..457da208dbc 100644 Binary files a/doc/api/images/firstplugin-summary.png and b/doc/api/images/firstplugin-summary.png differ diff --git a/doc/api/images/firstplugin-wizard.png b/doc/api/images/firstplugin-wizard.png index 30b445bb5ae..0c0df4f7fb5 100644 Binary files a/doc/api/images/firstplugin-wizard.png and b/doc/api/images/firstplugin-wizard.png differ diff --git a/doc/images/qtcreator-autotests-options.png b/doc/images/qtcreator-autotests-options.png index e019c2cc912..9e1879bb55e 100644 Binary files a/doc/images/qtcreator-autotests-options.png and b/doc/images/qtcreator-autotests-options.png differ diff --git a/doc/images/qtcreator-debugger-expressions.png b/doc/images/qtcreator-debugger-expressions.png new file mode 100644 index 00000000000..84a3abbefd7 Binary files /dev/null and b/doc/images/qtcreator-debugger-expressions.png differ diff --git a/doc/images/qtcreator-gerrit-push.png b/doc/images/qtcreator-gerrit-push.png new file mode 100644 index 00000000000..0a831f21971 Binary files /dev/null and b/doc/images/qtcreator-gerrit-push.png differ diff --git a/doc/images/qtcreator-heob-output.png b/doc/images/qtcreator-heob-output.png new file mode 100644 index 00000000000..6c9e1287acb Binary files /dev/null and b/doc/images/qtcreator-heob-output.png differ diff --git a/doc/images/qtcreator-heob-settings.png b/doc/images/qtcreator-heob-settings.png new file mode 100644 index 00000000000..4f591860b9c Binary files /dev/null and b/doc/images/qtcreator-heob-settings.png differ diff --git a/doc/images/qtcreator-heob.png b/doc/images/qtcreator-heob.png new file mode 100644 index 00000000000..c3b75ec8479 Binary files /dev/null and b/doc/images/qtcreator-heob.png differ diff --git a/doc/images/qtcreator-locals-expressions.png b/doc/images/qtcreator-locals-expressions.png deleted file mode 100644 index 7196babe81d..00000000000 Binary files a/doc/images/qtcreator-locals-expressions.png and /dev/null differ diff --git a/doc/images/qtcreator-locals.png b/doc/images/qtcreator-locals.png new file mode 100644 index 00000000000..81b407d9731 Binary files /dev/null and b/doc/images/qtcreator-locals.png differ diff --git a/doc/images/qtcreator-watcher.png b/doc/images/qtcreator-watcher.png index 242c06be4de..97b150b5897 100644 Binary files a/doc/images/qtcreator-watcher.png and b/doc/images/qtcreator-watcher.png differ diff --git a/doc/src/analyze/cpu-usage-analyzer.qdoc b/doc/src/analyze/cpu-usage-analyzer.qdoc index 5395808d762..a43d8ac1dc5 100644 --- a/doc/src/analyze/cpu-usage-analyzer.qdoc +++ b/doc/src/analyze/cpu-usage-analyzer.qdoc @@ -31,7 +31,7 @@ /*! \contentspage {Qt Creator Manual} - \previouspage creator-clang-static-analyzer.html + \previouspage creator-heob.html \page creator-cpu-usage-analyzer.html \nextpage creator-autotest.html diff --git a/doc/src/analyze/creator-analyze.qdoc b/doc/src/analyze/creator-analyze.qdoc index 3353eb12828..7e1a76e2894 100644 --- a/doc/src/analyze/creator-analyze.qdoc +++ b/doc/src/analyze/creator-analyze.qdoc @@ -71,6 +71,11 @@ Objective-C programs by using the experimental plugin that integrates the Clang Static Analyzer source code analysis tool. + \li \l{Detecting Memory Leaks with Heob} + + You can use the Heob heap observer on Windows to detect buffer + overruns and memory leaks. + \li \l{Analyzing CPU Usage}{CPU Usage Analyzer} You can analyze the CPU usage of embedded applications and Linux diff --git a/doc/src/analyze/creator-clang-static-analyzer.qdoc b/doc/src/analyze/creator-clang-static-analyzer.qdoc index 2c09fa0a759..521b4da8640 100644 --- a/doc/src/analyze/creator-clang-static-analyzer.qdoc +++ b/doc/src/analyze/creator-clang-static-analyzer.qdoc @@ -33,7 +33,7 @@ \contentspage {Qt Creator Manual} \previouspage creator-running-valgrind-remotely.html \page creator-clang-static-analyzer.html - \nextpage creator-cpu-usage-analyzer.html + \nextpage creator-heob.html \title Using Clang Static Analyzer diff --git a/doc/src/analyze/creator-heob.qdoc b/doc/src/analyze/creator-heob.qdoc new file mode 100644 index 00000000000..d8c2fae57cf --- /dev/null +++ b/doc/src/analyze/creator-heob.qdoc @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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. +** +****************************************************************************/ + +// ********************************************************************** +// NOTE: the sections are not ordered by their logical order to avoid +// reshuffling the file each time the index order changes (i.e., often). +// Run the fixnavi.pl script to adjust the links to the index order. +// ********************************************************************** + +/*! + \contentspage {Qt Creator Manual} + \previouspage creator-clang-static-analyzer.html + \page creator-heob.html + \nextpage creator-cpu-usage-analyzer.html + + \title Detecting Memory Leaks with Heob + + \QC integrates the \l{https://github.com/ssbssa/heob}{Heob} heap observer + for detecting buffer overruns and memory leaks. You must download and + install Heob to run it from \QC. + + To run Heob on the currently open project: + + \list 1 + + \li Select \uicontrol Analyze > \uicontrol Heob. + + \li In the \uicontrol {Heob path} field, enter the path to the Heob + executable. + + \li Specify additional settings for running the checks. For more + information about the available options, see + \l{Specifying Heob Settings}. + + \li Select \uicontrol OK to run Heob. + + \endlist + + \QC runs the application, and then it runs Heob in a console window. + + \image qtcreator-heob.png + + Heob raises an access violation on buffer overruns and provides stack traces + of the offending instruction and buffer allocation. The results are + displayed when Heob exits normally. + + \image qtcreator-heob-output.png + + \section1 Specifying Heob Settings + + To specify settings for Heob, select \uicontrol Analyze > \uicontrol Heob. + + \image qtcreator-heob-settings.png + + In the \uicontrol {Extra arguments} field, enter additional arguments for + running Heob. To list the available arguments in the Heob console, enter + \c -H in this field and press \key Enter. + + For example, use the \c -oleaks.html option to record leak data in an HTML + file. Together with this option, you can use the \c -g2 option to group the + leaks visually in the file and the \c -L1024 option to record leak contents + up to 1024 bytes in the file. For example, \c {-oleaks.html -g2 -L1024} + + Select \uicontrol Save to save the current settings as default. + + The following sections describe the available options in more detail. + + \section2 Recording Results + + The results of the checks are displayed in the \uicontrol Memcheck view and + recorded in a file. You can specify the file name in the + \uicontrol {XML output file} field. Heob creates the file in the project + directory. + + You can use the process identifier (PID) as a variable in the file name. + For example, \c leaks-%p.xml. This injects Heob into the child processes, + as well. + + Other variables you can use are \c %P for the parent PID and \c %n for the + application name. + + If you use variables, \QC cannot open the file automatically, but you can + open it from the project directory. + + \section2 Handling Exceptions + + In the \uicontrol {Handle exceptions} list, select \uicontrol Off to use the + standard exception handler and have the debugger automatically attached if + the application crashes. This works only if you register \QC is as a + post-mortem debugger by selecting \uicontrol Tools > \uicontrol Options > + \uicontrol Debugger > \uicontrol General > + \uicontrol {Use Qt Creator for post-mortem debugging}. + + Select \uicontrol On to use the Heob exception handler that checks the + reason and location of the crash and detects whether it occurred because of + buffer overrun. + + Select \uicontrol Only to disable all Heob functions, except installing the + exception handler. If the application crashes, only a stack trace of the + crash is displayed. Therefore, this option is mostly useful when using Heob + on the console or running it for child processes, as well. + + \section2 Raising Exceptions on Errors + + Select the \uicontrol {Raise breakpoint exception on error} check + box to display errors when the application runs. + + If the option is disabled, errors such as \e {double free}, \e {free of + invalid pointer}, and \e {not enough memory} just write all collected data + into the results file and you will only see them at the end of the + application run. + + If the option is enabled, the application stops at the error location. + This is mostly useful when used with the \uicontrol {Run with debugger} + option, which runs Heob under the debugger. + + \section2 Protecting Pages + + In the \uicontrol {Page protection} list, select \uicontrol Off to use + standard memory allocation functions and enable only memory leak detection. + + Select \uicontrol After to place a protected page at the end of each + allocated block and throw an exception if it is accessed. Select + \uicontrol Before to place a protected page before each allocated block. + These options consume memory and slow down the checks, and are therefore + recommended only for 64-bit or short-running programs. + + Select \uicontrol {Freed memory protection} to protect all allocation pages + when freed, so that their address space can never be used again. This is + useful for \e use-after-free and \e double-free detection. However, the + available memory address space can run out fast for 32-bit programs. + + \section2 Handling Leak Data + + In the \uicontrol {Leak details} list, determine how to handle the + collected leak data when the process exits. Selecting \uicontrol None means + that no leak data is collected. If you activate leak type detection, Heob + might need more time to collect the data when the process exits. + + Select \uicontrol Simple to write all memory that was not freed into the + results file. + + Select \uicontrol {Detect Leak Types} to parse all static and global memory + blocks for references to the leaks. The reachable blocks are marked + \e reachable and recursively checked for other references. If references are + found, the blocks are marked \e {indirectly reachable}. The remaining blocks + are checked for references to each other and marked either + \e {indirectly lost} or \e {jointly lost} (if the blocks reference each + other). The blocks that have no references at all are marked \e lost. + Select \uicontrol {Detect Leak Types (Show Reachable)} to also record the + the reachable blocks in the results file. + + Select \uicontrol {Fuzzy Detect Leak Types} to mark memory blocks + \e reachable or \e {indirectly lost} if they contain references to any + address. This option is useful when used with some custom allocators (such + as \c av_malloc() in \c ffmpeg) that keep only an address somewhere inside + the allocation block and do not refer directly to the start of an allocated + block. Select \uicontrol {Detect Leak Types (Show Reachable)} to also + record the reachable blocks in the results file. + + In the \uicontrol {Minimum leak size} list, select the size of + leaks to detect in bytes. + + In the \uicontrol {Control leak recording} list, select \uicontrol Off to + record all leaks. You cannot change leak recording while it is running. + + To start Heob without starting leak recording, select + \uicontrol {On (Start Disabled)}. In the Heob console, turn recording + \uicontrol on or \uicontrol off, \uicontrol clear all results, or + select \uicontrol show to record all current leaks into the results file. + Open the file to see its contents before the process exits. + + To start leak recording when Heob starts and still have the option to + control the recording, select \uicontrol {On (Start Enabled)}. +*/ diff --git a/doc/src/analyze/creator-valgrind-overview.qdoc b/doc/src/analyze/creator-valgrind-overview.qdoc index d42fd6fd43d..774c933d756 100644 --- a/doc/src/analyze/creator-valgrind-overview.qdoc +++ b/doc/src/analyze/creator-valgrind-overview.qdoc @@ -67,7 +67,7 @@ \list - \li \l{Detecting Memory Leaks} + \li \l{Detecting Memory Leaks with Memcheck} \li \l{Profiling Function Execution} diff --git a/doc/src/analyze/creator-valgrind.qdoc b/doc/src/analyze/creator-valgrind.qdoc index 9623c2b8749..ce1ed1f3452 100644 --- a/doc/src/analyze/creator-valgrind.qdoc +++ b/doc/src/analyze/creator-valgrind.qdoc @@ -35,7 +35,7 @@ \page creator-analyzer.html \nextpage creator-cache-profiler.html - \title Detecting Memory Leaks + \title Detecting Memory Leaks with Memcheck You can use the Memcheck tool included in the Valgrind tool suite to detect problems that are related to memory management in applications. You can use @@ -43,7 +43,9 @@ application is interrupted and you can debug it. \note You can install and run Memcheck locally on Linux. You can run - it on a remote host or device from any development machine. + it on a remote host or device from any development machine. On Windows, + you can use the \l{Detecting Memory Leaks with Heob}{Heob} heap observer to + receive similar results. After you download and install Valgrind tools, you can use Memcheck from \QC. diff --git a/doc/src/debugger/creator-debugger-example.qdoc b/doc/src/debugger/creator-debugger-example.qdoc index 610508c1e2c..a43afe684cd 100644 --- a/doc/src/debugger/creator-debugger-example.qdoc +++ b/doc/src/debugger/creator-debugger-example.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -65,7 +65,7 @@ \li To view the base classes and data members of the TextFinder class, - go to the \uicontrol {Locals and Expressions} view. + go to the \uicontrol Locals view. \image qtcreator-watcher.png diff --git a/doc/src/debugger/creator-debugger-setup.qdoc b/doc/src/debugger/creator-debugger-setup.qdoc index c64b2d79234..f851833ba12 100644 --- a/doc/src/debugger/creator-debugger-setup.qdoc +++ b/doc/src/debugger/creator-debugger-setup.qdoc @@ -170,67 +170,68 @@ \section1 Installing Native Debuggers - Check the table below for the supported versions and other important - information about installing native debuggers. + The following sections provide information about installing native + debuggers. - \table - \header - \li Native Debugger - \li Notes - \row - \li GDB - \li On Windows, use the Python-enabled GDB versions that is bundled - with the Qt package or comes with recent versions of MinGW. On - most Linux distributions the GDB builds shipped with the system - are sufficient. You can also build your own. Follow the - instructions in \l{http://wiki.qt.io/QtCreator_Build_Gdb} - {Building GDB}. Builds of GDB shipped with Xcode on \macos are no - longer supported. + \section2 GDB - \row - \li Debugging tools for Windows - \li To use the CDB debugger, you must install the - \e{Debugging tools for Windows}. You can download them from - \l{https://developer.microsoft.com/windows/downloads/windows-10-sdk} - {Download and Install Debugging Tools for Windows} as part of the Windows SDK. + On Windows, use the Python-enabled GDB versions that is bundled + with the Qt package or comes with recent versions of MinGW. On + most Linux distributions, the GDB builds shipped with the system + are sufficient. - \note Visual Studio does not include the Debugging tools needed, - and therefore, you must install them separately. + You can also build your own GDB, as instructed in + \l{http://wiki.qt.io/QtCreator_Build_Gdb}{Building GDB}. - The pre-built \QSDK for Windows makes use of the library if it - is present on the system. When manually building \QC using - the Microsoft Visual C++ Compiler, the build process checks for - the required files in - \c{"%ProgramFiles%\Debugging Tools for Windows"}. + Builds of GDB shipped with Xcode on \macos are no longer supported. - It is highly recommended that you add the Symbol Server provided - by Microsoft to the symbol search path of the debugger. The - Symbol Server provides you with debugging informaton for the - operating system libraries for debugging Windows applications. - For more information, see - \l{Setting CDB Paths on Windows}. + \section2 Debugging Tools for Windows - \row - \li Debugging tools for \macos - \li The Qt binary distribution contains both debug and release - variants of the libraries. But you have to explicitly tell the - runtime linker that you want to use the debug libraries even if - your application is compiled as debug, as release is the default - library. + To use the CDB debugger, you must install the + \e{Debugging tools for Windows}. You can download them from + \l{https://developer.microsoft.com/windows/downloads/windows-10-sdk} + {Download and Install Debugging Tools for Windows} as part of the Windows + SDK. - If you use a qmake based project in \QC, you can set a flag in - your \l{glossary-run-config}{run configuration}, in - \uicontrol Projects mode. In the run configuration, select - \uicontrol{Use debug version of frameworks}. + \note Visual Studio does not include the Debugging tools needed, + and therefore, you must install them separately. - For more detailed information about debugging on \macos, - see: \l{http://developer.apple.com/library/mac/#technotes/tn2124/_index.html#//apple_ref/doc/uid/DTS10003391} - {Mac OS X Debugging Magic}. + In addition, you must select \uicontrol {Qt Creator CDB Debugger Support} + (in \uicontrol Qt > \uicontrol Tools > \uicontrol {\QC}) when you install + Qt or the stand-alone \QC. - \row - \li LLDB - \li We recommend using the LLDB version that is delivered with Xcode 5. - \endtable + When manually building \QC using + the Microsoft Visual C++ Compiler, the build process checks for + the required files in + \c{"%ProgramFiles%\Debugging Tools for Windows"}. + + It is highly recommended that you add the Symbol Server provided + by Microsoft to the symbol search path of the debugger. The + Symbol Server provides you with debugging informaton for the + operating system libraries for debugging Windows applications. + For more information, see + \l{Setting CDB Paths on Windows}. + + \section2 Debugging Tools for \macos + + The Qt binary distribution contains both debug and release + variants of the libraries. But you have to explicitly tell the + runtime linker that you want to use the debug libraries even if + your application is compiled as debug, as release is the default + library. + + If you use a qmake based project in \QC, you can set a flag in + your \l{glossary-run-config}{run configuration}, in + \uicontrol Projects mode. In the run configuration, select + \uicontrol{Use debug version of frameworks}. + + For more detailed information about debugging on \macos, + see: \l{http://developer.apple.com/library/mac/#technotes/tn2124/_index.html#//apple_ref/doc/uid/DTS10003391} + {Mac OS X Debugging Magic}. + + \section2 LLDB + + We recommend using the LLDB version that is delivered with the latest Xcode. \section1 Mapping Source Paths diff --git a/doc/src/debugger/creator-debugger.qdoc b/doc/src/debugger/creator-debugger.qdoc index 7a569838d93..c882b114fc2 100644 --- a/doc/src/debugger/creator-debugger.qdoc +++ b/doc/src/debugger/creator-debugger.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -679,11 +679,10 @@ \section1 Local Variables and Function Parameters - The Locals view consists of two parts: the \uicontrol Locals pane at the top - and the \uicontrol {Return Value} pane at the bottom. The - \uicontrol {Return Value} is only visible if it is not empty. + The Locals view consists of the \uicontrol Locals pane and the + \uicontrol {Return Value} pane (hidden when empty). - \image qtcreator-locals-expressions.png "Locals view" + \image qtcreator-locals.png "Locals view" Whenever a program stops under the control of the debugger, it retrieves information about the topmost stack frame and displays it in the @@ -694,7 +693,7 @@ pane displays the value returned by the function. - \section1 Evaluating Expresssion + \section1 Evaluating Expressions To compute values of arithmetic expressions or function calls, use expression evaluators in the \uicontrol Expressions view. To insert a new @@ -703,6 +702,8 @@ \uicontrol {Add New Expression Evaluator} from the context menu, or drag and drop an expression from the code editor. + \image qtcreator-debugger-expressions.png + \note Expression evaluators are powerful, but slow down debugger operation significantly. It is advisable to not use them excessively, and to remove unneeded expression evaluators as soon as possible. @@ -1070,7 +1071,7 @@ \li \c d of type \c Dumper, an object containing the current settings and providing facilities to build up an object representing a part of - the \uicontrol {Locals and Expressions} view. + the \uicontrol Locals and \uicontrol Expressions views. \li \c value of type \c Value, wrapping either a \l{https://sourceware.org/gdb/onlinedocs/gdb/Values-From-Inferior.html} @@ -1082,7 +1083,7 @@ The \c{qdump__*} function has to feed the Dumper object with certain information that is used to build up the object and its children's display - in the \uicontrol {Locals and Expressions} view. + in the \uicontrol Locals and \uicontrol Expressions views. Example: @@ -1099,6 +1100,16 @@ avoid direct access to the \c gdb.* and \c lldb.* namespaces and use the functions of the \c Dumper class instead. + To get to the base instance of the object in the debugging helper, use the + \c value.base() function or the following example code: + + \code + def qdump__A(d, value): + t = value.members(True)[0].type + dptr, base_v = value.split('p{%s}' % t.name) + d.putItem(base_v) + \endcode + Debugging helpers can be set up to be called whenever a type name matches a regular expression. To do so, the debugging helper's function name must begin with \c{qdump__} (with two underscore characters). In addition, @@ -1122,8 +1133,9 @@ A debugging helper creates a description of the displayed data item in a format that is similar to GDB/MI and JSON. - For each line in the \uicontrol {Locals and Expressions} view, a string like - the following needs to be created and channeled to the debugger plugin. + For each line in the \uicontrol Locals and \uicontrol Expressions views, a + string like the following needs to be created and channeled to the debugger + plugin. \code { iname='some internal name', # optional @@ -1575,18 +1587,18 @@ \section1 Pointer Variable Members Are Not Displayed Directly - When you use the \uicontrol {Locals and Expressions} view to inspect a + When you use the \uicontrol Locals and \uicontrol Expressions views to inspect a pointer variable and expand the variable tree item, another tree item level is displayed. To directly display the members of the pointer variable, select \uicontrol {Dereference Pointers Automatically} in the context - menu in the \uicontrol {Locals and Expressions} view. + menu in the \uicontrol Locals and \uicontrol Expressions views. \section1 Structure Members Are Not Sorted According to Structure Layout By default, structure members are displayed in alphabetic order. To inspect the real layout in memory, deselect \uicontrol {Sort Members of Classes and Structs Alphabetically} in the - context menu in the \uicontrol {Locals and Expressions} view. + context menu in the \uicontrol Locals and \uicontrol Expressions views. \section1 Built-in Debugger Is Slow During Startup and Runtime diff --git a/doc/src/howto/creator-autotest.qdoc b/doc/src/howto/creator-autotest.qdoc index ac54307b659..bba2ce6a85a 100644 --- a/doc/src/howto/creator-autotest.qdoc +++ b/doc/src/howto/creator-autotest.qdoc @@ -218,14 +218,18 @@ test list for the currently active test frameworks when you edit tests. To refresh the view, select \uicontrol {Rescan Tests} in the context menu. - You can add filters to specify the directories within the current project - to scan for tests. Select \uicontrol Tools > \uicontrol Options > - \uicontrol {Testing} > \uicontrol General > \uicontrol Add, and - specify paths to the directories to scan for tests. Wildcards are not - supported in the filter expressions. + To group related test cases for an active test framework, select + \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} > + \uicontrol General, and then select the \uicontrol Group check box next to + the framework name in the \uicontrol {Active Test Frameworks} list. \image qtcreator-autotests-options.png + You can add filters to specify the directories within the current project + to scan for tests. Select the \uicontrol {Global Filters} check box, and + the select \uicontrol Add to specify paths to the directories to scan for + tests. Wildcards are not supported in the filter expressions. + To show or hide init and cleanup or data functions in the \uicontrol Tests view, select \inlineimage filtericon.png (\uicontrol {Filter Test Tree}), and then select \uicontrol {Show Init and diff --git a/doc/src/qtcreator-toc.qdoc b/doc/src/qtcreator-toc.qdoc index a4048aff8f6..8b30ace545f 100644 --- a/doc/src/qtcreator-toc.qdoc +++ b/doc/src/qtcreator-toc.qdoc @@ -177,11 +177,12 @@ \li \l{Profiling QML Applications} \li \l{Using Valgrind Code Analysis Tools} \list - \li \l{Detecting Memory Leaks} + \li \l{Detecting Memory Leaks with Memcheck} \li \l{Profiling Function Execution} \li \l{Running Valgrind Tools on External Applications} \endlist \li \l{Using Clang Static Analyzer} + \li \l{Detecting Memory Leaks with Heob} \li \l{Analyzing CPU Usage} \endlist \li \l{Running Autotests} diff --git a/doc/src/vcs/creator-vcs-git.qdoc b/doc/src/vcs/creator-vcs-git.qdoc index 56d77d969f8..d2e364055e9 100644 --- a/doc/src/vcs/creator-vcs-git.qdoc +++ b/doc/src/vcs/creator-vcs-git.qdoc @@ -299,6 +299,13 @@ \uicontrol Git > \uicontrol {Remote Repository} > \uicontrol {Push to Gerrit}. + \image qtcreator-gerrit-push.png + + Select the \uicontrol {Draft/private} check box to push changes that are + only visible to you and the reviewers. If you are using Gerrit 2.15 or + later, you can select the \uicontrol {Work-in-progress} check box to push + changes that do not generate email notifications. + To view the same information about each change as in the Gerrit web interface, select \uicontrol Tools > \uicontrol Git > \uicontrol {Remote Repository} > \uicontrol Gerrit. diff --git a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs index ed754e43da9..845ce4139c6 100644 --- a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs +++ b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs @@ -16,6 +16,7 @@ Module { : ["$ORIGIN/..", "$ORIGIN/../" + qtc.ide_library_path] property string resourcesInstallDir: qtc.ide_data_path + "/qbs" property string pluginsInstallDir: qtc.ide_plugin_path + "/qbs/plugins" + property string qmlTypeDescriptionsInstallDir: qtc.ide_data_path + "/qml-type-descriptions" property string appInstallDir: qtc.ide_bin_path property string libexecInstallDir: qtc.ide_libexec_path property bool installHtml: false diff --git a/share/qtcreator/debugger/creatortypes.py b/share/qtcreator/debugger/creatortypes.py index 182057e2556..c93646a31d6 100644 --- a/share/qtcreator/debugger/creatortypes.py +++ b/share/qtcreator/debugger/creatortypes.py @@ -258,6 +258,14 @@ def qdump__ProjectExplorer__FolderNode(d, value): d.putStringValue(value["m_displayName"]) d.putPlainChildren(value) +def qdump__ProjectExplorer__ToolChain(d, value): + d.putStringValue(value["d"]["m_displayName"]) + d.putPlainChildren(value) + +def qdump__ProjectExplorer__Kit(d, value): + d.putStringValue(value["d"]["m_unexpandedDisplayName"]) + d.putPlainChildren(value) + def qdump__ProjectExplorer__ProjectNode(d, value): qdump__ProjectExplorer__FolderNode(d, value) diff --git a/share/qtcreator/qml-type-descriptions/qbs-bundle.json b/share/qtcreator/qml-type-descriptions/qbs-bundle.json index a6f70ed7928..cf230cdefee 100644 --- a/share/qtcreator/qml-type-descriptions/qbs-bundle.json +++ b/share/qtcreator/qml-type-descriptions/qbs-bundle.json @@ -1,14 +1,32 @@ { "name": "qbs", "searchPaths": [ - "$(QBS_IMPORT_PATH)"], + "$(QBS_IMPORT_PATH)" + ], "installPaths": [ - "$(QBS_IMPORT_PATH)"], + "$(QBS_IMPORT_PATH)" + ], "implicitImports": [ - "__javascriptQt5__"], + "__javascriptQt5__" + ], "supportedImports": [ - "qbs.base 1.0", - "qbs 1.0", - "qbs.fileinfo 1.0", - "qbs.probe 1.0"] + "qbs", + "qbs.BinaryFile", + "qbs.BundleTools", + "qbs.DarwinTools", + "qbs.Environment", + "qbs.File", + "qbs.FileInfo", + "qbs.ModUtils", + "qbs.PathTools", + "qbs.Probes", + "qbs.Process", + "qbs.PropertyList", + "qbs.TemporaryDir", + "qbs.TextFile", + "qbs.UnixUtils", + "qbs.Utilities", + "qbs.WindowsUtils", + "qbs.Xml" + ] } diff --git a/share/qtcreator/qml-type-descriptions/qbs.qmltypes b/share/qtcreator/qml-type-descriptions/qbs.qmltypes index 718baa6a04b..4038d271cb3 100644 --- a/share/qtcreator/qml-type-descriptions/qbs.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qbs.qmltypes @@ -60,6 +60,7 @@ Module { Property { name: "fileTags"; type: "string"; isList: true } Property { name: "fileTagsFilter"; type: "string"; isList: true } Property { name: "files"; type: "string"; isList: true } + Property { name: "filesAreTargets"; type: "bool" } Property { name: "name"; type: "string" } Property { name: "overrideTags"; type: "bool" } Property { name: "prefix"; type: "string" } @@ -72,6 +73,7 @@ Module { Property { name: "condition"; type: "bool" } Property { name: "name"; type: "string" } Property { name: "present"; type: "bool" } + Property { name: "priority"; type: "int" } Property { name: "setupBuildEnvironment"; type: "QVariant" } Property { name: "setupRunEnvironment"; type: "QVariant" } Property { name: "validate"; type: "bool" } @@ -187,6 +189,7 @@ Module { name: "SubProject" exports: [ "qbs/SubProject 1.0" ] prototype: "QQuickItem" + Property { name: "condition"; type: "bool" } Property { name: "filePath"; type: "string" } Property { name: "inheritProperties"; type: "bool" } } @@ -201,3 +204,4 @@ Module { Property { name: "prepare"; type: "QVariant" } } } + diff --git a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes index 70003d049f9..4f914d45989 100644 --- a/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qmlproject.qmltypes @@ -70,4 +70,7 @@ Module { ] Property { name: "filter"; type: "string" } } + Component { + name: "Environment" + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml index c0177032b77..80ab3d39faa 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionButton.qml @@ -157,7 +157,7 @@ Item { } Controls.MenuItem { - text: qsTr("Insert keyframe") + text: qsTr("Insert Keyframe") visible: hasActiveTimeline onTriggered: insertKeyframe(backendValue.name) } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml index de97df46b80..602d442be18 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml @@ -237,11 +237,11 @@ Section { } CheckBox { - text: qsTr("Prefer Shaping") + text: qsTr("Prefer shaping") Layout.fillWidth: true backendValue: (backendValues.font_preferShaping === undefined) ? dummyBackendValue : backendValues.font_preferShaping tooltip: qsTr("Sometimes, a font will apply complex rules to a set of characters in order to display them correctly.\n" + - "In some writing systems, such as Brahmic scripts, this is required in order for the text to be legible, but in e.g." + + "In some writing systems, such as Brahmic scripts, this is required in order for the text to be legible, whereas in" + "Latin script,\n it is merely a cosmetic feature. Setting the preferShaping property to false will disable all such features\nwhen they are not required, which will improve performance in most cases.") } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml index 152d17eb0bc..917cad87342 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/StandardTextSection.qml @@ -131,7 +131,7 @@ Section { Label { - text: qsTr("Line Height") + text: qsTr("Line height") tooltip: qsTr("Sets the line height for the text.") } diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.pro b/share/qtcreator/templates/wizards/autotest/files/tst.pro index 4731fb8cc61..a973d1a9cbb 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst.pro +++ b/share/qtcreator/templates/wizards/autotest/files/tst.pro @@ -13,7 +13,19 @@ CONFIG += qt warn_on depend_includepath testcase TEMPLATE = app SOURCES += %{TestCaseFileWithCppSuffix} -@else +@endif +@if "%{TestFrameWork}" == "QtQuickTest" +CONFIG += warn_on qmltestcase + +TEMPLATE = app + +DISTFILES += \\ + %{TestCaseFileWithQmlSuffix} + +SOURCES += \\ + %{MainCppName} +@endif +@if "%{TestFrameWork}" == "GTest" include(gtest_dependency.pri) TEMPLATE = app diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.qbs b/share/qtcreator/templates/wizards/autotest/files/tst.qbs index 33f15226af3..cb7076a0ace 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst.qbs +++ b/share/qtcreator/templates/wizards/autotest/files/tst.qbs @@ -17,6 +17,7 @@ CppApplication { ] @else consoleApplication: true +@endif @if "%{TestFrameWork}" == "GTest" property string googletestDir: { @@ -28,7 +29,6 @@ CppApplication { return Environment.getEnv("GOOGLETEST_DIR") } } -@endif @if "%{GTestCXX11}" == "true" cpp.cxxLanguageVersion: "c++11" @@ -52,4 +52,24 @@ CppApplication { ].concat(googleCommon.getGTestAll(googletestDir)) .concat(googleCommon.getGMockAll(googletestDir)) @endif +@if "%{TestFrameWork}" == "QtQuickTest" + Depends { name: "cpp" } + Depends { name: "Qt.core" } + Depends { + condition: Qt.core.versionMajor > 4 + name: "Qt.qmltest" + } + + Group { + name: "main application" + files: [ "%{MainCppName}" ] + } + + Group { + name: "qml test files" + files: "%{TestCaseFileWithQmlSuffix}" + } + + cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\\"" + path + "\\"") +@endif } diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.txt b/share/qtcreator/templates/wizards/autotest/files/tst.txt index 8c13344d41c..239e7087f8e 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst.txt +++ b/share/qtcreator/templates/wizards/autotest/files/tst.txt @@ -13,6 +13,7 @@ find_package(Qt5Gui REQUIRED) SET(CMAKE_AUTOMOC ON) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) ENABLE_TESTING() add_executable(${PROJECT_NAME} %{TestCaseFileWithCppSuffix}) @@ -24,7 +25,26 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui Qt5::Test) target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Test) @endif -@else +@endif +@if "%{TestFrameWork}" == "QtQuickTest" +find_package(Qt5QuickTest REQUIRED) + +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_STANDARD_REQUIRED ON) +ENABLE_TESTING() + +# no need to copy around qml test files for shadow builds - just set the respective define +add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") + +add_executable(${PROJECT_NAME} %{MainCppName}) +add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME}) + +target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::QuickTest) + +@endif +@if "%{TestFrameWork}" == "GTest" @if "%{GTestCXX11}" == "true" add_definitions(-DGTEST_LANGUAGE_CXX11) diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp b/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp index 2e25da44ead..d918350551d 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp +++ b/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp @@ -1,3 +1,8 @@ +@if "%{TestFrameWork}" == "QtQuickTest" +#include + +QUICK_TEST_MAIN(example) +@else %{Cpp:LicenseTemplate}\ #include "%{TestCaseFileWithHeaderSuffix}" @@ -8,3 +13,4 @@ int main(int argc, char *argv[]) ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } +@endif diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl new file mode 100644 index 00000000000..5d3da10b700 --- /dev/null +++ b/share/qtcreator/templates/wizards/autotest/files/tst_qml.tmpl @@ -0,0 +1,19 @@ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "%{TestCaseName}" + +@if "%{GenerateInitAndCleanup}" == "true" + function initTestCase() { + } + + function cleanupTestCase() { + } + +@endif + function test_case1() { + compare(1 + 1, 2, "sanity check"); + verify(true); + } +} diff --git a/share/qtcreator/templates/wizards/autotest/wizard.json b/share/qtcreator/templates/wizards/autotest/wizard.json index 8b2c5489773..6fad990403e 100644 --- a/share/qtcreator/templates/wizards/autotest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/wizard.json @@ -39,6 +39,10 @@ { "key": "TestCaseFileWithCppSuffix", "value": "%{JS: 'tst_%{TestCaseName}.'.toLowerCase() + Util.preferredSuffix('text/x-c++src') }" + }, + { + "key": "TestCaseFileWithQmlSuffix", + "value": "%{JS: 'tst_%{TestCaseName}.qml'.toLowerCase() }" } ], @@ -73,9 +77,14 @@ "value": "QtTest" }, { - "trKey": "Googletest", + "trKey": "Google Test", "value": "GTest" + }, + { + "trKey": "Qt Quick Test", + "value": "QtQuickTest" } + ] } }, @@ -107,7 +116,7 @@ { "name": "GenerateInitAndCleanup", "trDisplayName": "Generate initialization and cleanup code", - "visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}", + "visible": "%{JS: [ 'QtTest', 'QtQuickTest' ].indexOf('%{TestFrameWork}') >= 0 }", "type": "CheckBox", "data": { "checked": false @@ -174,7 +183,7 @@ "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", - "requiredFeatures": [ "%{JS: ('%{BuildSystem}' == 'cmake' && '%{TestFrameWork}' == 'QtTest') ? 'QtSupport.Wizards.FeatureQt.5' : 'QtSupport.Wizards.FeatureQt' }" ] + "requiredFeatures": [ "%{JS: (('%{BuildSystem}' === 'cmake' && '%{TestFrameWork}' === 'QtTest') || '%{TestFrameWork}' === 'QtQuickTest') ? 'QtSupport.Wizards.FeatureQt.5' : 'QtSupport.Wizards.FeatureQt' }" ] } }, { @@ -237,7 +246,13 @@ { "source": "files/tst_main.cpp", "target": "%{MainCppName}", - "condition": "%{JS: '%{TestFrameWork}' == 'GTest'}", + "condition": "%{JS: ['GTest', 'QtQuickTest'].indexOf('%{TestFrameWork}') >= 0}", + "openInEditor": true + }, + { + "source": "files/tst_qml.tmpl", + "target": "%{TestCaseFileWithQmlSuffix}", + "condition": "%{JS: '%{TestFrameWork}' === 'QtQuickTest'}", "openInEditor": true }, { diff --git a/share/qtcreator/templates/wizards/files/scxml/wizard.json b/share/qtcreator/templates/wizards/files/scxml/wizard.json index 893662337d8..4e9e8706379 100644 --- a/share/qtcreator/templates/wizards/files/scxml/wizard.json +++ b/share/qtcreator/templates/wizards/files/scxml/wizard.json @@ -8,7 +8,7 @@ "trDisplayCategory": "Modeling", "iconText": "scxml", "platformIndependent": true, - "enabled": "%{JS: [ %{Plugins} ].indexOf('QtSupport') >= 0}", + "enabled": "%{JS: [ %{Plugins} ].indexOf('ScxmlEditor') >= 0}", "options": [ diff --git a/share/qtcreator/templates/wizards/projects/plainc/wizard.json b/share/qtcreator/templates/wizards/projects/plainc/wizard.json index 7905965c6d0..56361be81d5 100644 --- a/share/qtcreator/templates/wizards/projects/plainc/wizard.json +++ b/share/qtcreator/templates/wizards/projects/plainc/wizard.json @@ -7,7 +7,7 @@ "trDisplayName": "Plain C Application", "trDisplayCategory": "Non-Qt Project", "icon": "../../global/consoleapplication.png", - "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", + "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0 && ([ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0)}", "options": [ diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json index 76384fa55b1..bf48c26108e 100644 --- a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json +++ b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json @@ -7,7 +7,7 @@ "trDisplayName": "Plain C++ Application", "trDisplayCategory": "Non-Qt Project", "icon": "../../global/consoleapplication.png", - "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", + "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0 && ([ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0)}", "options": [ diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp index a562da6d5d5..986dcd606f1 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp @@ -20,25 +20,9 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QQmlApplicationEngine engine; - - const QUrl mainQml(QStringLiteral("qrc:/main.qml")); - - // Catch the objectCreated signal, so that we can determine if the root component was loaded - // successfully. If not, then the object created from it will be null. The root component may - // get loaded asynchronously. - const QMetaObject::Connection connection = QObject::connect( - &engine, &QQmlApplicationEngine::objectCreated, - &app, [&](QObject *object, const QUrl &url) { - if (url != mainQml) - return; - - if (!object) - app.exit(-1); - else - QObject::disconnect(connection); - }, Qt::QueuedConnection); - - engine.load(mainQml); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; return app.exec(); } diff --git a/share/share.qbs b/share/share.qbs index c5ee2b1c394..c9293911158 100644 --- a/share/share.qbs +++ b/share/share.qbs @@ -27,6 +27,10 @@ Product { "themes/**/*", "welcomescreen/**/*" ] + excludeFiles: [ + "qml-type-descriptions/qbs-bundle.json", + "qml-type-descriptions/qbs.qmltypes", + ] } Group { diff --git a/src/app/main.cpp b/src/app/main.cpp index e9a863946a3..cf33b466757 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -158,8 +158,8 @@ static inline int askMsgSendFailed() { return QMessageBox::question(0, QApplication::translate("Application","Could not send message"), QCoreApplication::translate("Application", "Unable to send command line arguments " - "to the already running instance. It appears to be not " - "responding. Do you want to start a new instance of " + "to the already running instance. It does not appear to " + "be responding. Do you want to start a new instance of " "%1?").arg(Core::Constants::IDE_DISPLAY_NAME), QMessageBox::Yes | QMessageBox::No | QMessageBox::Retry, QMessageBox::Retry); diff --git a/src/libs/clangsupport/processcreator.cpp b/src/libs/clangsupport/processcreator.cpp index 9b21ba298e3..dfc7f56d9fd 100644 --- a/src/libs/clangsupport/processcreator.cpp +++ b/src/libs/clangsupport/processcreator.cpp @@ -85,7 +85,7 @@ void ProcessCreator::checkIfProcessPathExists() const { if (!QFileInfo::exists(m_processPath)) { const QString messageTemplate = QCoreApplication::translate("ProcessCreator", - "Executable does not exists: %1"); + "Executable does not exist: %1"); throwProcessException(messageTemplate.arg(m_processPath)); } } @@ -101,7 +101,7 @@ void ProcessCreator::dispatchProcessError(QProcess *process) const switch (process->error()) { case QProcess::UnknownError: { const QString message = QCoreApplication::translate("ProcessCreator", - "Unknown error happend."); + "Unknown error occurred."); throwProcessException(message); }; case QProcess::Crashed: { @@ -116,7 +116,7 @@ void ProcessCreator::dispatchProcessError(QProcess *process) const }; case QProcess::Timedout: { const QString message = QCoreApplication::translate("ProcessCreator", - "Process timeouted."); + "Process timed out."); throwProcessException(message); }; case QProcess::WriteError: { diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp index 944c25e1d16..63f070235f4 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp @@ -515,6 +515,7 @@ bool DiagramSceneModel::exportSvg(const QString &fileName, bool selectedElements return true; #else // QT_NO_SVG Q_UNUSED(fileName); + Q_UNUSED(selectedElements); return false; #endif // QT_NO_SVG } diff --git a/src/libs/qmldebug/qmldebugconnectionmanager.cpp b/src/libs/qmldebug/qmldebugconnectionmanager.cpp index bb1c0ebde86..a13cb0f3ccc 100644 --- a/src/libs/qmldebug/qmldebugconnectionmanager.cpp +++ b/src/libs/qmldebug/qmldebugconnectionmanager.cpp @@ -217,7 +217,7 @@ void QmlDebugConnectionManager::destroyConnection() void QmlDebugConnectionManager::qmlDebugConnectionOpened() { - logState(tr("Debug connection opened")); + logState(tr("Debug connection opened.")); QTC_ASSERT(m_connection, return); QTC_ASSERT(m_connection->isConnected(), return); stopConnectionTimer(); @@ -226,7 +226,7 @@ void QmlDebugConnectionManager::qmlDebugConnectionOpened() void QmlDebugConnectionManager::qmlDebugConnectionClosed() { - logState(tr("Debug connection closed")); + logState(tr("Debug connection closed.")); QTC_ASSERT(m_connection, return); QTC_ASSERT(!m_connection->isConnected(), return); destroyConnection(); @@ -235,7 +235,7 @@ void QmlDebugConnectionManager::qmlDebugConnectionClosed() void QmlDebugConnectionManager::qmlDebugConnectionFailed() { - logState(tr("Debug connection failed")); + logState(tr("Debug connection failed.")); QTC_ASSERT(m_connection, return); QTC_ASSERT(!m_connection->isConnected(), /**/); diff --git a/src/libs/timeline/qml/TimelineContent.qml b/src/libs/timeline/qml/TimelineContent.qml index aae9b122294..cc5a1a79955 100644 --- a/src/libs/timeline/qml/TimelineContent.qml +++ b/src/libs/timeline/qml/TimelineContent.qml @@ -68,7 +68,6 @@ ScrollView { // switch to non-interactive ourselves, though. property bool stayInteractive: true onStayInteractiveChanged: flick.interactive = stayInteractive - onWidthChanged: scroll() Flickable { id: flick @@ -89,6 +88,15 @@ ScrollView { recursionGuard = false; } + // Logically we should bind to scroller.width above as we use scroller.width in scroll(). + // However, this width changes before scroller.width when the window is resized and if we + // don't explicitly set contentX here, for some reason an automatic change in contentX is + // triggered after this width has changed, but before scroller.width changes. This would be + // indistinguishabe from a manual flick by the user and thus changes the range position. We + // don't want to change the range position on resizing the window. Therefore we bind to this + // width. + onWidthChanged: scroll() + // Update the zoom control on scrolling. onContentXChanged: guarded(function() { var newStartTime = contentX * zoomer.rangeDuration / scroller.width diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index ca50d58baee..3c53e09b2a4 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -66,7 +66,8 @@ static bool isQmake(const QString &path) QFileInfo fi(path); if (BuildableHelperLibrary::isQtChooser(fi)) fi.setFile(BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget())); - + if (!fi.exists() || fi.isDir()) + return false; return !BuildableHelperLibrary::qtVersionForQMake(fi.absoluteFilePath()).isEmpty(); } @@ -154,7 +155,7 @@ QStringList BuildableHelperLibrary::possibleQMakeCommands() // On Unix some distributions renamed qmake with a postfix to avoid clashes // On OS X, Qt 4 binary packages also has renamed qmake. There are also symbolic links that are // named "qmake", but the file dialog always checks against resolved links (native Cocoa issue) - return QStringList(QLatin1String("qmake*")); + return QStringList(HostOsInfo::withExecutableSuffix("qmake*")); } // Copy helper source files to a target directory, replacing older files. diff --git a/src/libs/utils/removefiledialog.ui b/src/libs/utils/removefiledialog.ui index 88314065b8f..7d0b7b9de03 100644 --- a/src/libs/utils/removefiledialog.ui +++ b/src/libs/utils/removefiledialog.ui @@ -80,7 +80,7 @@ - &Remove from Version Control + &Remove from version control diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp index d02aab782b9..4c96ed95cca 100644 --- a/src/libs/utils/settingsaccessor.cpp +++ b/src/libs/utils/settingsaccessor.cpp @@ -640,7 +640,7 @@ QVariant SettingsAccessor::retrieveSharedSettings() const QString SettingsAccessor::differentEnvironmentMsg(const QString &projectName) { return QApplication::translate("Utils::EnvironmentIdAccessor", - "Settings File for \"%1\" from a different Environment?") + "Settings File for \"%1\" from a Different Environment?") .arg(projectName); } diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp index d41cb693cda..140d94977d6 100644 --- a/src/libs/utils/winutils.cpp +++ b/src/libs/utils/winutils.cpp @@ -26,10 +26,10 @@ #include "winutils.h" #include "qtcassert.h" -// Enable WinAPI Windows XP and later +// Enable WinAPI Windows Vista and later #ifdef Q_OS_WIN #undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 +#define _WIN32_WINNT 0x0600 // Needed for QueryFullProcessImageName #include #endif @@ -168,6 +168,23 @@ QTCREATOR_UTILS_EXPORT bool is64BitWindowsBinary(const QString &binaryIn) #endif } +QTCREATOR_UTILS_EXPORT QString imageName(quint32 processId) +{ + QString result; +#ifdef Q_OS_WIN + HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId); + if (handle == NULL) + return result; + + wchar_t path[MAX_PATH]; + DWORD pathLen = MAX_PATH; + if (QueryFullProcessImageName(handle, 0, path, &pathLen)) + result = QString::fromUtf16(reinterpret_cast(path)); + CloseHandle(handle); +#endif + return result; +} + WindowsCrashDialogBlocker::WindowsCrashDialogBlocker() #ifdef Q_OS_WIN : silenceErrorMode(SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS), diff --git a/src/libs/utils/winutils.h b/src/libs/utils/winutils.h index 6bb75f97d6e..314cce673d3 100644 --- a/src/libs/utils/winutils.h +++ b/src/libs/utils/winutils.h @@ -44,6 +44,9 @@ QTCREATOR_UTILS_EXPORT bool is64BitWindowsSystem(); // Check for a 64bit binary. QTCREATOR_UTILS_EXPORT bool is64BitWindowsBinary(const QString &binary); +// Get the path to the executable for a given PID. +QTCREATOR_UTILS_EXPORT QString imageName(quint32 processId); + // // RAII class to temporarily prevent windows crash messages from popping up using the // application-global (!) error mode. diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 2a4673f2133..06bcbebd899 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -558,9 +558,8 @@ ClangCompletionAssistProcessor::extractLineColumn(int position) int line = -1, column = -1; ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column); - const QTextBlock block = m_interface->textDocument()->findBlock(position); - const QString stringOnTheLeft = block.text().left(column); - column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns + + column = Utils::clangColumn(m_interface->textDocument()->findBlock(position), column); return {line, column}; } diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index 261d196b0b4..44b8db7334d 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -64,6 +64,9 @@ int positionInText(QTextDocument *textDocument, { auto textBlock = textDocument->findBlockByNumber( static_cast(sourceLocationContainer.line()) - 1); + // 'sourceLocationContainer' already has the CppEditor column converted from + // the utf8 byte offset from the beginning of the line provided by clang. + // - 1 is required for 0-based columns. const int column = static_cast(sourceLocationContainer.column()) - 1; return textBlock.position() + column; } diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index de6efd6fc59..3fc9ed6baf7 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -356,9 +356,7 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams ¶m if (!isCursorOnIdentifier(params.textCursor)) return defaultCursorInfoFuture(); - const QTextBlock block = params.textCursor.document()->findBlockByNumber(line - 1); - const QString stringOnTheLeft = block.text().left(column); - column = stringOnTheLeft.toUtf8().size() + 1; // '+ 1' is for 1-based columns + column = Utils::clangColumn(params.textCursor.document()->findBlockByNumber(line - 1), column); const CppTools::SemanticInfo::LocalUseMap localUses = CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column); diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 25993805ffb..037080c4224 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -43,6 +43,7 @@ #include #include #include +#include using namespace ClangCodeModel; using namespace ClangCodeModel::Internal; @@ -190,5 +191,15 @@ void setLastSentDocumentRevision(const QString &filePath, uint revision) document->sendTracker().setLastSentRevision(int(revision)); } +int clangColumn(const QTextBlock &line, int cppEditorColumn) +{ + // (1) cppEditorColumn is the actual column shown by CppEditor. + // (2) The return value is the column in Clang which is the utf8 byte offset from the beginning + // of the line. + // Here we convert column from (1) to (2). + // '+ 1' is for 1-based columns + return line.text().left(cppEditorColumn).toUtf8().size() + 1; +} + } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index edd26ba7552..a67d40b18ac 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -27,6 +27,10 @@ #include +QT_BEGIN_NAMESPACE +class QTextBlock; +QT_END_NAMESPACE + namespace CppTools { class CppEditorDocumentHandle; } @@ -46,6 +50,7 @@ CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath); CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath); bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); QString projectPartIdForFile(const QString &filePath); +int clangColumn(const QTextBlock &lineText, int cppEditorColumn); } // namespace Utils } // namespace Clang diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 679e06b99fe..6f94ce23d2f 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -71,6 +72,40 @@ using namespace Utils; static Q_LOGGING_CATEGORY(LOG, "qtc.clangstaticanalyzer.runcontrol") +static QStringList splitArgs(QString &argsString) +{ + QStringList result; + Utils::QtcProcess::ArgIterator it(&argsString); + while (it.next()) + result.append(it.value()); + return result; +} + +template +static QStringList extraOptions(const char(&environment)[Size]) +{ + if (!qEnvironmentVariableIsSet(environment)) + return QStringList(); + QString arguments = QString::fromLocal8Bit(qgetenv(environment)); + return splitArgs(arguments); +} + +static QStringList extraClangStaticAnalyzerPrependOptions() { + constexpr char csaPrependOptions[] = "QTC_CLANG_CSA_CMD_PREPEND"; + static const QStringList options = extraOptions(csaPrependOptions); + if (!options.isEmpty()) + qWarning() << "ClangStaticAnalyzer options are prepended with " << options.toVector(); + return options; +} + +static QStringList extraClangStaticAnalyzerAppendOptions() { + constexpr char csaAppendOptions[] = "QTC_CLANG_CSA_CMD_APPEND"; + static const QStringList options = extraOptions(csaAppendOptions); + if (!options.isEmpty()) + qWarning() << "ClangStaticAnalyzer options are appended with " << options.toVector(); + return options; +} + namespace ClangStaticAnalyzer { namespace Internal { @@ -303,7 +338,9 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVectorindex(sourceRow, 0, sourceParent); + for (int i = 0; i < sourceModel()->rowCount(sourceCategoryIndex); ++i) + if (filterAcceptsRow(i, sourceCategoryIndex)) + return true; + return false; + } + QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent); - Core::IWizardFactory *wizard = factoryOfItem(qobject_cast(sourceModel())->itemFromIndex(sourceIndex)); + Core::IWizardFactory *wizard = + factoryOfItem(qobject_cast(sourceModel())->itemFromIndex(sourceIndex)); if (wizard) return wizard->isAvailable(m_platform); @@ -95,51 +112,6 @@ private: Core::Id m_platform; }; -class TwoLevelProxyModel : public QAbstractProxyModel -{ -// Q_OBJECT -public: - TwoLevelProxyModel(QObject *parent = nullptr): QAbstractProxyModel(parent) {} - - QModelIndex index(int row, int column, const QModelIndex &parent) const override - { - QModelIndex ourModelIndex = sourceModel()->index(row, column, mapToSource(parent)); - return createIndex(row, column, ourModelIndex.internalPointer()); - } - - QModelIndex parent(const QModelIndex &index) const override - { - return mapFromSource(mapToSource(index).parent()); - } - - int rowCount(const QModelIndex &index) const override - { - if (index.isValid() && index.parent().isValid() && !index.parent().parent().isValid()) - return 0; - else - return sourceModel()->rowCount(mapToSource(index)); - } - - int columnCount(const QModelIndex &index) const override - { - return sourceModel()->columnCount(mapToSource(index)); - } - - QModelIndex mapFromSource (const QModelIndex &index) const override - { - if (!index.isValid()) - return QModelIndex(); - return createIndex(index.row(), index.column(), index.internalPointer()); - } - - QModelIndex mapToSource (const QModelIndex &index) const override - { - if (!index.isValid()) - return QModelIndex(); - return static_cast(sourceModel())->createIndex(index.row(), index.column(), index.internalPointer()); - } -}; - #define ROW_HEIGHT 24 class FancyTopLevelDelegate : public QItemDelegate @@ -209,12 +181,11 @@ NewDialog::NewDialog(QWidget *parent) : m_okButton->setText(tr("Choose...")); m_model = new QStandardItemModel(this); - m_twoLevelProxyModel = new TwoLevelProxyModel(this); - m_twoLevelProxyModel->setSourceModel(m_model); + m_filterProxyModel = new PlatformFilterProxyModel(this); m_filterProxyModel->setSourceModel(m_model); - m_ui->templateCategoryView->setModel(m_twoLevelProxyModel); + m_ui->templateCategoryView->setModel(m_filterProxyModel); m_ui->templateCategoryView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_ui->templateCategoryView->setItemDelegate(new FancyTopLevelDelegate); @@ -269,7 +240,10 @@ void NewDialog::setWizardFactories(QList factories, m_dummyIcon = QIcon(":/utils/images/wizardicon-file.png"); QSet availablePlatforms = IWizardFactory::allAvailablePlatforms(); - m_ui->comboBox->addItem(tr("All Templates"), Id().toSetting()); + + const bool allowAllTemplates = ICore::settings()->value(ALLOW_ALL_TEMPLATES, true).toBool(); + if (allowAllTemplates) + m_ui->comboBox->addItem(tr("All Templates"), Id().toSetting()); foreach (Id platform, availablePlatforms) { const QString displayNameForPlatform = IWizardFactory::displayNameForPlatform(platform); @@ -279,6 +253,10 @@ void NewDialog::setWizardFactories(QList factories, m_ui->comboBox->setCurrentIndex(0); // "All templates" m_ui->comboBox->setEnabled(!availablePlatforms.isEmpty()); + const bool showPlatformFilter = ICore::settings()->value(SHOW_PLATOFORM_FILTER, true).toBool(); + if (!showPlatformFilter) + m_ui->comboBox->hide(); + foreach (IWizardFactory *factory, factories) { QStandardItem *kindItem; switch (factory->kind()) { @@ -309,21 +287,23 @@ void NewDialog::showDialog() m_ui->comboBox->setCurrentIndex(index); } + static_cast(m_filterProxyModel)->manualReset(); + if (!lastCategory.isEmpty()) foreach (QStandardItem* item, m_categoryItems) { if (item->data(Qt::UserRole) == lastCategory) - idx = m_twoLevelProxyModel->mapToSource(m_model->indexFromItem(item)); + idx = m_filterProxyModel->mapFromSource(m_model->indexFromItem(item)); } if (!idx.isValid()) - idx = m_twoLevelProxyModel->index(0,0, m_twoLevelProxyModel->index(0,0)); + idx = m_filterProxyModel->index(0,0, m_filterProxyModel->index(0,0)); m_ui->templateCategoryView->setCurrentIndex(idx); // We need to set ensure that the category has default focus m_ui->templateCategoryView->setFocus(Qt::NoFocusReason); - for (int row = 0; row < m_twoLevelProxyModel->rowCount(); ++row) - m_ui->templateCategoryView->setExpanded(m_twoLevelProxyModel->index(row, 0), true); + for (int row = 0; row < m_filterProxyModel->rowCount(); ++row) + m_ui->templateCategoryView->setExpanded(m_filterProxyModel->index(row, 0), true); // Ensure that item description is visible on first show currentItemChanged(m_ui->templatesView->rootIndex().child(0,0)); @@ -426,7 +406,7 @@ void NewDialog::addItem(QStandardItem *topLevelCategoryItem, IWizardFactory *fac void NewDialog::currentCategoryChanged(const QModelIndex &index) { if (index.parent() != m_model->invisibleRootItem()->index()) { - QModelIndex sourceIndex = m_twoLevelProxyModel->mapToSource(index); + QModelIndex sourceIndex = m_filterProxyModel->mapToSource(index); sourceIndex = m_filterProxyModel->mapFromSource(sourceIndex); m_ui->templatesView->setRootIndex(sourceIndex); // Focus the first item by default @@ -472,8 +452,9 @@ void NewDialog::currentItemChanged(const QModelIndex &index) void NewDialog::saveState() { - QModelIndex idx = m_ui->templateCategoryView->currentIndex(); - QStandardItem *currentItem = m_model->itemFromIndex(m_twoLevelProxyModel->mapToSource(idx)); + const QModelIndex filterIdx = m_ui->templateCategoryView->currentIndex(); + const QModelIndex idx = m_filterProxyModel->mapToSource(filterIdx); + QStandardItem *currentItem = m_model->itemFromIndex(idx); if (currentItem) ICore::settings()->setValue(QLatin1String(LAST_CATEGORY_KEY), currentItem->data(Qt::UserRole)); diff --git a/src/plugins/coreplugin/dialogs/newdialog.h b/src/plugins/coreplugin/dialogs/newdialog.h index 9461efae261..f5ab0d6324c 100644 --- a/src/plugins/coreplugin/dialogs/newdialog.h +++ b/src/plugins/coreplugin/dialogs/newdialog.h @@ -81,7 +81,6 @@ private: Ui::NewDialog *m_ui; QStandardItemModel *m_model; - QAbstractProxyModel *m_twoLevelProxyModel; QSortFilterProxyModel *m_filterProxyModel; QPushButton *m_okButton; QIcon m_dummyIcon; diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp index 6255101dca0..6f88a9188a2 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.cpp +++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp @@ -27,14 +27,15 @@ #include #include -#include +#include namespace Core { namespace Internal { enum JavaScriptAction { - ResetEngine = QVariant::UserType + 1 + ResetEngine = QVariant::UserType + 1, + AbortEngine }; JavaScriptFilter::JavaScriptFilter() @@ -43,6 +44,13 @@ JavaScriptFilter::JavaScriptFilter() setDisplayName(tr("Evaluate JavaScript")); setIncludedByDefault(false); setShortcutString("="); + m_abortTimer.setSingleShot(true); + m_abortTimer.setInterval(1000); + connect(&m_abortTimer, &QTimer::timeout, this, [this] { + m_aborted = true; + if (m_engine && m_engine->isEvaluating()) + m_engine->abortEvaluation(); + }); } JavaScriptFilter::~JavaScriptFilter() @@ -55,6 +63,8 @@ void JavaScriptFilter::prepareSearch(const QString &entry) if (!m_engine) setupEngine(); + m_aborted = false; + m_abortTimer.start(); } QList JavaScriptFilter::matchesFor( @@ -67,11 +77,15 @@ QList JavaScriptFilter::matchesFor( entries.append({this, tr("Reset Engine"), QVariant(ResetEngine, nullptr)}); } else { const QString result = m_engine->evaluate(entry).toString(); - const QString expression = entry + " = " + result; - - entries.append({this, expression, QVariant()}); - entries.append({this, tr("Copy to clipboard: %1").arg(result), result}); - entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression}); + if (m_aborted) { + const QString message = entry + " = " + tr("Engine aborted after timeout."); + entries.append({this, message, QVariant(AbortEngine, nullptr)}); + } else { + const QString expression = entry + " = " + result; + entries.append({this, expression, QVariant()}); + entries.append({this, tr("Copy to clipboard: %1").arg(result), result}); + entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression}); + } } return entries; @@ -104,7 +118,7 @@ void JavaScriptFilter::refresh(QFutureInterface &future) void JavaScriptFilter::setupEngine() { - m_engine.reset(new QJSEngine); + m_engine.reset(new QScriptEngine); m_engine->evaluate( "function abs(x) { return Math.abs(x); }\n" "function acos(x) { return Math.acos(x); }\n" diff --git a/src/plugins/coreplugin/locator/javascriptfilter.h b/src/plugins/coreplugin/locator/javascriptfilter.h index 9bf3ac51949..feaf326036b 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.h +++ b/src/plugins/coreplugin/locator/javascriptfilter.h @@ -27,10 +27,12 @@ #include +#include + #include QT_BEGIN_NAMESPACE -class QJSEngine; +class QScriptEngine; QT_END_NAMESPACE namespace Core { @@ -53,7 +55,9 @@ public: private: void setupEngine(); - mutable std::unique_ptr m_engine; + mutable std::unique_ptr m_engine; + QTimer m_abortTimer; + bool m_aborted = false; }; } // namespace Internal diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index ce51887b225..f34ae39c9b7 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -75,7 +75,9 @@ class LocatorData public: LocatorManager m_locatorManager; +#ifdef WITH_JAVASCRIPTFILTER JavaScriptFilter m_javaScriptFilter; +#endif OpenDocumentsFilter m_openDocumentsFilter; FileSystemFilter m_fileSystemFilter; ExecuteFilter m_executeFilter; @@ -124,7 +126,6 @@ void Locator::initialize() auto locatorWidget = LocatorManager::createLocatorInputWidget(ICore::mainWindow()); StatusBarManager::addStatusBarWidget(locatorWidget, StatusBarManager::First, Context("LocatorWidget")); - connect(ICore::instance(), &ICore::saveSettingsRequested, this, &Locator::saveSettings); } diff --git a/src/plugins/coreplugin/locator/locator.pri b/src/plugins/coreplugin/locator/locator.pri index 183d7fde515..c5f2cfaf9c2 100644 --- a/src/plugins/coreplugin/locator/locator.pri +++ b/src/plugins/coreplugin/locator/locator.pri @@ -15,8 +15,7 @@ HEADERS += \ $$PWD/executefilter.h \ $$PWD/locatorsearchutils.h \ $$PWD/locatorsettingspage.h \ - $$PWD/externaltoolsfilter.h \ - $$PWD/javascriptfilter.h + $$PWD/externaltoolsfilter.h SOURCES += \ $$PWD/locator.cpp \ @@ -33,7 +32,18 @@ SOURCES += \ $$PWD/locatorsearchutils.cpp \ $$PWD/locatorsettingspage.cpp \ $$PWD/externaltoolsfilter.cpp \ - $$PWD/javascriptfilter.cpp + +qtHaveModule(script) { + QT *= script + + DEFINES += WITH_JAVASCRIPTFILTER + + HEADERS += \ + $$PWD/javascriptfilter.h + + SOURCES += \ + $$PWD/javascriptfilter.cpp +} FORMS += \ $$PWD/filesystemfilter.ui \ diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index fd3ff84f843..ee76cdebf91 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -411,6 +411,7 @@ void MainWindow::registerDefaultContainers() filemenu->appendGroup(Constants::G_FILE_OPEN); filemenu->appendGroup(Constants::G_FILE_PROJECT); filemenu->appendGroup(Constants::G_FILE_SAVE); + filemenu->appendGroup(Constants::G_FILE_EXPORT); filemenu->appendGroup(Constants::G_FILE_CLOSE); filemenu->appendGroup(Constants::G_FILE_PRINT); filemenu->appendGroup(Constants::G_FILE_OTHER); @@ -465,6 +466,7 @@ void MainWindow::registerDefaultActions() // File menu separators mfile->addSeparator(Constants::G_FILE_SAVE); + mfile->addSeparator(Constants::G_FILE_EXPORT); mfile->addSeparator(Constants::G_FILE_PRINT); mfile->addSeparator(Constants::G_FILE_CLOSE); mfile->addSeparator(Constants::G_FILE_OTHER); @@ -620,6 +622,30 @@ void MainWindow::registerDefaultActions() medit->addAction(cmd, Constants::G_EDIT_OTHER); tmpaction->setEnabled(false); + // Zoom In Action + icon = QIcon::hasThemeIcon("zoom-in") ? QIcon::fromTheme("zoom-in") + : Utils::Icons::ZOOMIN_TOOLBAR.icon(); + tmpaction = new QAction(icon, tr("Zoom In"), this); + cmd = ActionManager::registerAction(tmpaction, Constants::ZOOM_IN); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl++"))); + tmpaction->setEnabled(false); + + // Zoom Out Action + icon = QIcon::hasThemeIcon("zoom-out") ? QIcon::fromTheme("zoom-out") + : Utils::Icons::ZOOMOUT_TOOLBAR.icon(); + tmpaction = new QAction(icon, tr("Zoom Out"), this); + cmd = ActionManager::registerAction(tmpaction, Constants::ZOOM_OUT); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+-"))); + tmpaction->setEnabled(false); + + // Zoom Reset Action + icon = QIcon::hasThemeIcon("zoom-original") ? QIcon::fromTheme("zoom-original") + : Utils::Icons::EYE_OPEN_TOOLBAR.icon(); + tmpaction = new QAction(icon, tr("Original Size"), this); + cmd = ActionManager::registerAction(tmpaction, Constants::ZOOM_RESET); + cmd->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Meta+0") : tr("Ctrl+0"))); + tmpaction->setEnabled(false); + // Options Action mtools->appendGroup(Constants::G_TOOLS_OPTIONS); mtools->addSeparator(Constants::G_TOOLS_OPTIONS); diff --git a/src/plugins/cpptools/refactoringengineinterface.h b/src/plugins/cpptools/refactoringengineinterface.h index 84ecf501abf..fa9435bf77a 100644 --- a/src/plugins/cpptools/refactoringengineinterface.h +++ b/src/plugins/cpptools/refactoringengineinterface.h @@ -31,7 +31,6 @@ #include #include -#include #include #include diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp index 8cd7d41bbe1..07f5e1658fe 100644 --- a/src/plugins/debugger/debuggerprotocol.cpp +++ b/src/plugins/debugger/debuggerprotocol.cpp @@ -438,7 +438,7 @@ void extractGdbVersion(const QString &msg, const QChar dot(QLatin1Char('.')); const bool ignoreParenthesisContent = msg.contains(QLatin1String("rubenvb")) - || msg.contains(QLatin1String("openSUSE")); + || msg.contains(QLatin1String("SUSE")); const QChar parOpen(QLatin1Char('(')); const QChar parClose(QLatin1Char(')')); diff --git a/src/plugins/git/gerrit/gerritpushdialog.cpp b/src/plugins/git/gerrit/gerritpushdialog.cpp index b18354905ee..17e36c4fd25 100644 --- a/src/plugins/git/gerrit/gerritpushdialog.cpp +++ b/src/plugins/git/gerrit/gerritpushdialog.cpp @@ -226,22 +226,22 @@ void GerritPushDialog::onRemoteChanged(bool force) m_currentSupportsWip = supportsWip; m_ui->wipCheckBox->setEnabled(supportsWip); if (supportsWip) { - m_ui->wipCheckBox->setToolTip(tr("Checked - Mark change as WIP\n" - "Unchecked - Mark change as ready\n" - "Partially checked - Do not change current state")); + m_ui->wipCheckBox->setToolTip(tr("Checked - Mark change as WIP.\n" + "Unchecked - Mark change as ready for review.\n" + "Partially checked - Do not change current state.")); m_ui->draftCheckBox->setTristate(true); if (m_ui->draftCheckBox->checkState() != Qt::Checked) m_ui->draftCheckBox->setCheckState(Qt::PartiallyChecked); - m_ui->draftCheckBox->setToolTip(tr("Checked - Mark change as private\n" - "Unchecked - Unmark change as private\n" - "Partially checked - Do not change current state")); + m_ui->draftCheckBox->setToolTip(tr("Checked - Mark change as private.\n" + "Unchecked - Remove mark.\n" + "Partially checked - Do not change current state.")); } else { - m_ui->wipCheckBox->setToolTip(tr("Supported on Gerrit 2.15 and up")); + m_ui->wipCheckBox->setToolTip(tr("Supported on Gerrit 2.15 and later.")); m_ui->draftCheckBox->setTristate(false); if (m_ui->draftCheckBox->checkState() != Qt::Checked) m_ui->draftCheckBox->setCheckState(Qt::Unchecked); - m_ui->draftCheckBox->setToolTip(tr("Checked - Mark change as draft\n" - "Unchecked - Unmark change as draft")); + m_ui->draftCheckBox->setToolTip(tr("Checked - The change is a draft.\n" + "Unchecked - The change is not a draft.")); } } diff --git a/src/plugins/git/gerrit/gerritpushdialog.ui b/src/plugins/git/gerrit/gerritpushdialog.ui index a72b8d82a61..ff06a8da0f7 100644 --- a/src/plugins/git/gerrit/gerritpushdialog.ui +++ b/src/plugins/git/gerrit/gerritpushdialog.ui @@ -82,14 +82,14 @@ Unchecked - Unmark change as private Semi-checked - Do not change current state - &Draft/Private + &Draft/private - &Work-In-Progress + &Work-in-progress true diff --git a/src/plugins/imageviewer/imageviewer.cpp b/src/plugins/imageviewer/imageviewer.cpp index b891524d1c7..7c98b7bb6ba 100644 --- a/src/plugins/imageviewer/imageviewer.cpp +++ b/src/plugins/imageviewer/imageviewer.cpp @@ -33,10 +33,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -107,14 +109,14 @@ void ImageViewer::ctor() {QLatin1String(":/utils/images/desktopdevicesmall.png"), Utils::Theme::IconsBaseColor}}); d->ui_toolbar.toolButtonBackground->setIcon(backgroundIcon.icon()); d->ui_toolbar.toolButtonOutline->setIcon(Utils::Icons::BOUNDING_RECT.icon()); - d->ui_toolbar.toolButtonZoomIn->setIcon(Utils::Icons::ZOOMIN_TOOLBAR.icon()); - d->ui_toolbar.toolButtonZoomOut->setIcon(Utils::Icons::ZOOMOUT_TOOLBAR.icon()); + d->ui_toolbar.toolButtonZoomIn->setIcon( + Core::ActionManager::command(Core::Constants::ZOOM_IN)->action()->icon()); + d->ui_toolbar.toolButtonZoomOut->setIcon( + Core::ActionManager::command(Core::Constants::ZOOM_OUT)->action()->icon()); + d->ui_toolbar.toolButtonOriginalSize->setIcon( + Core::ActionManager::command(Core::Constants::ZOOM_RESET)->action()->icon()); d->ui_toolbar.toolButtonFitToScreen->setIcon(Utils::Icons::FITTOVIEW_TOOLBAR.icon()); - d->ui_toolbar.toolButtonOriginalSize->setIcon(Utils::Icons::EYE_OPEN_TOOLBAR.icon()); // icons update - try to use system theme - updateButtonIconByTheme(d->ui_toolbar.toolButtonZoomIn, QLatin1String("zoom-in")); - updateButtonIconByTheme(d->ui_toolbar.toolButtonZoomOut, QLatin1String("zoom-out")); - updateButtonIconByTheme(d->ui_toolbar.toolButtonOriginalSize, QLatin1String("zoom-original")); updateButtonIconByTheme(d->ui_toolbar.toolButtonFitToScreen, QLatin1String("zoom-fit-best")); // a display - something is on the background updateButtonIconByTheme(d->ui_toolbar.toolButtonBackground, QLatin1String("video-display")); @@ -123,9 +125,9 @@ void ImageViewer::ctor() updateButtonIconByTheme(d->ui_toolbar.toolButtonOutline, QLatin1String("emblem-photos")); d->ui_toolbar.toolButtonExportImage->setCommandId(Constants::ACTION_EXPORT_IMAGE); - d->ui_toolbar.toolButtonZoomIn->setCommandId(Constants::ACTION_ZOOM_IN); - d->ui_toolbar.toolButtonZoomOut->setCommandId(Constants::ACTION_ZOOM_OUT); - d->ui_toolbar.toolButtonOriginalSize->setCommandId(Constants::ACTION_ORIGINAL_SIZE); + d->ui_toolbar.toolButtonZoomIn->setCommandId(Core::Constants::ZOOM_IN); + d->ui_toolbar.toolButtonZoomOut->setCommandId(Core::Constants::ZOOM_OUT); + d->ui_toolbar.toolButtonOriginalSize->setCommandId(Core::Constants::ZOOM_RESET); d->ui_toolbar.toolButtonFitToScreen->setCommandId(Constants::ACTION_FIT_TO_SCREEN); d->ui_toolbar.toolButtonBackground->setCommandId(Constants::ACTION_BACKGROUND); d->ui_toolbar.toolButtonOutline->setCommandId(Constants::ACTION_OUTLINE); diff --git a/src/plugins/imageviewer/imageviewerconstants.h b/src/plugins/imageviewer/imageviewerconstants.h index 496d3a8d6a9..1fac9a69067 100644 --- a/src/plugins/imageviewer/imageviewerconstants.h +++ b/src/plugins/imageviewer/imageviewerconstants.h @@ -33,9 +33,6 @@ const char IMAGEVIEWER_ID[] = "Editors.ImageViewer"; const char IMAGEVIEWER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Image Viewer"); const char ACTION_EXPORT_IMAGE[] = "ImageViewer.ExportImage"; -const char ACTION_ZOOM_IN[] = "ImageViewer.ZoomIn"; -const char ACTION_ZOOM_OUT[] = "ImageViewer.ZoomOut"; -const char ACTION_ORIGINAL_SIZE[] = "ImageViewer.OriginalSize"; const char ACTION_FIT_TO_SCREEN[] = "ImageViewer.FitToScreen"; const char ACTION_BACKGROUND[] = "ImageViewer.Background"; const char ACTION_OUTLINE[] = "ImageViewer.Outline"; diff --git a/src/plugins/imageviewer/imageviewerplugin.cpp b/src/plugins/imageviewer/imageviewerplugin.cpp index f3059caf1ad..dbed73f0825 100644 --- a/src/plugins/imageviewer/imageviewerplugin.cpp +++ b/src/plugins/imageviewer/imageviewerplugin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -62,22 +63,19 @@ static inline ImageViewer *currentImageViewer() void ImageViewerPlugin::extensionsInitialized() { - QAction *a = registerNewAction(Constants::ACTION_ZOOM_IN, tr("Zoom In"), - QKeySequence(tr("Ctrl++"))); + QAction *a = registerNewAction(Core::Constants::ZOOM_IN); connect(a, &QAction::triggered, this, []() { if (ImageViewer *iv = currentImageViewer()) iv->zoomIn(); }); - a = registerNewAction(Constants::ACTION_ZOOM_OUT, tr("Zoom Out"), - QKeySequence(tr("Ctrl+-"))); + a = registerNewAction(Core::Constants::ZOOM_OUT); connect(a, &QAction::triggered, this, []() { if (ImageViewer *iv = currentImageViewer()) iv->zoomOut(); }); - a = registerNewAction(Constants::ACTION_ORIGINAL_SIZE, tr("Original Size"), - QKeySequence(Core::useMacShortcuts ? tr("Meta+0") : tr("Ctrl+0"))); + a = registerNewAction(Core::Constants::ZOOM_RESET); connect(a, &QAction::triggered, this, []() { if (ImageViewer *iv = currentImageViewer()) iv->resetToOriginalSize(); @@ -125,7 +123,8 @@ QAction *ImageViewerPlugin::registerNewAction(Core::Id id, Core::Context context(Constants::IMAGEVIEWER_ID); QAction *action = new QAction(title, this); Core::Command *command = Core::ActionManager::registerAction(action, id, context); - command->setDefaultKeySequence(key); + if (!key.isEmpty()) + command->setDefaultKeySequence(key); return action; } diff --git a/src/plugins/imageviewer/imageviewerplugin.h b/src/plugins/imageviewer/imageviewerplugin.h index 83868edc118..88d671a3e9d 100644 --- a/src/plugins/imageviewer/imageviewerplugin.h +++ b/src/plugins/imageviewer/imageviewerplugin.h @@ -28,12 +28,12 @@ #include +#include #include #include QT_BEGIN_NAMESPACE class QAction; -class QKeySequence; QT_END_NAMESPACE namespace Core { class Id; } @@ -55,7 +55,8 @@ public: void extensionsInitialized(); private: - QAction *registerNewAction(Core::Id id, const QString &title, const QKeySequence &key); + QAction *registerNewAction(Core::Id id, const QString &title = QString(), + const QKeySequence &key = QKeySequence()); QPointer m_factory; }; diff --git a/src/plugins/modeleditor/actionhandler.cpp b/src/plugins/modeleditor/actionhandler.cpp index 7af2c6c5fbc..1e3d5563a46 100644 --- a/src/plugins/modeleditor/actionhandler.cpp +++ b/src/plugins/modeleditor/actionhandler.cpp @@ -58,9 +58,6 @@ public: QAction *synchronizeBrowserAction = nullptr; QAction *exportDiagramAction = nullptr; QAction *exportSelectedElementsAction = nullptr; - QAction *zoomInAction = nullptr; - QAction *zoomOutAction = nullptr; - QAction *resetZoomAction = nullptr; }; ActionHandler::ActionHandler(const Core::Context &context, QObject *parent) @@ -135,92 +132,63 @@ QAction *ActionHandler::exportSelectedElementsAction() const return d->exportSelectedElementsAction; } -QAction *ActionHandler::zoomInAction() const -{ - return d->zoomInAction; -} - -QAction *ActionHandler::zoomOutAction() const -{ - return d->zoomOutAction; -} - -QAction *ActionHandler::resetZoom() const -{ - return d->resetZoomAction; -} - void ActionHandler::createActions() { Core::ActionContainer *medit = Core::ActionManager::actionContainer(Core::Constants::M_EDIT); + Core::ActionContainer *mfile = Core::ActionManager::actionContainer(Core::Constants::M_FILE); - d->undoAction = registerCommand(Core::Constants::UNDO, [this]() { undo(); }, d->context)->action(); - d->redoAction = registerCommand(Core::Constants::REDO, [this]() { redo(); }, d->context)->action(); - d->cutAction = registerCommand(Core::Constants::CUT, [this]() { cut(); }, d->context)->action(); - d->copyAction = registerCommand(Core::Constants::COPY, [this]() { copy(); }, d->context)->action(); - d->pasteAction = registerCommand(Core::Constants::PASTE, [this]() { paste(); }, d->context)->action(); + d->undoAction = registerCommand(Core::Constants::UNDO, &ModelEditor::undo, d->context)->action(); + d->redoAction = registerCommand(Core::Constants::REDO, &ModelEditor::redo, d->context)->action(); + d->cutAction = registerCommand(Core::Constants::CUT, &ModelEditor::cut, d->context)->action(); + d->copyAction = registerCommand(Core::Constants::COPY, &ModelEditor::copy, d->context)->action(); + d->pasteAction = registerCommand(Core::Constants::PASTE, &ModelEditor::paste, d->context)->action(); Core::Command *removeCommand = registerCommand( - Constants::REMOVE_SELECTED_ELEMENTS, [this]() { removeSelectedElements(); }, d->context, true, + Constants::REMOVE_SELECTED_ELEMENTS, &ModelEditor::removeSelectedElements, d->context, tr("&Remove"), QKeySequence::Delete); medit->addAction(removeCommand, Core::Constants::G_EDIT_COPYPASTE); d->removeAction = removeCommand->action(); Core::Command *deleteCommand = registerCommand( - Constants::DELETE_SELECTED_ELEMENTS, [this]() { deleteSelectedElements(); }, d->context, true, + Constants::DELETE_SELECTED_ELEMENTS, &ModelEditor::deleteSelectedElements, d->context, tr("&Delete"), QKeySequence("Ctrl+D")); medit->addAction(deleteCommand, Core::Constants::G_EDIT_COPYPASTE); d->deleteAction = deleteCommand->action(); - d->selectAllAction = registerCommand(Core::Constants::SELECTALL, [this]() { selectAll(); }, d->context)->action(); - - Core::ActionContainer *menuModelEditor = Core::ActionManager::createMenu(Constants::MENU_ID); - menuModelEditor->menu()->setTitle(tr("Model Editor")); - Core::ActionContainer *menuTools = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); - menuTools->addMenu(menuModelEditor); + d->selectAllAction = registerCommand(Core::Constants::SELECTALL, &ModelEditor::selectAll, d->context)->action(); Core::Command *exportDiagramCommand = registerCommand( - Constants::EXPORT_DIAGRAM, [this]() { exportDiagram(); }, d->context, true, + Constants::EXPORT_DIAGRAM, &ModelEditor::exportDiagram, d->context, tr("Export Diagram...")); - menuModelEditor->addAction(exportDiagramCommand); + exportDiagramCommand->setAttribute(Core::Command::CA_Hide); + mfile->addAction(exportDiagramCommand, Core::Constants::G_FILE_EXPORT); d->exportDiagramAction = exportDiagramCommand->action(); Core::Command *exportSelectedElementsCommand = registerCommand( - Constants::EXPORT_SELECTED_ELEMENTS, [this]() { exportSelectedElements(); }, d->context, true, + Constants::EXPORT_SELECTED_ELEMENTS, &ModelEditor::exportSelectedElements, d->context, tr("Export Selected Elements...")); - menuModelEditor->addAction(exportSelectedElementsCommand); + exportSelectedElementsCommand->setAttribute(Core::Command::CA_Hide); + mfile->addAction(exportSelectedElementsCommand, Core::Constants::G_FILE_EXPORT); d->exportSelectedElementsAction = exportSelectedElementsCommand->action(); - menuModelEditor->addSeparator(d->context); - - Core::Command *zoomInCommand = registerCommand( - Constants::ZOOM_IN, [this]() { zoomIn(); }, d->context, true, - tr("Zoom In"), QKeySequence("Ctrl++")); - menuModelEditor->addAction(zoomInCommand); - d->zoomInAction = zoomInCommand->action(); - - Core::Command *zoomOutCommand = registerCommand( - Constants::ZOOM_OUT, [this]() { zoomOut(); }, d->context, true, - tr("Zoom Out"), QKeySequence("Ctrl+-")); - menuModelEditor->addAction(zoomOutCommand); - d->zoomOutAction = zoomOutCommand->action(); - - Core::Command *resetZoomCommand = registerCommand( - Constants::RESET_ZOOM, [this]() { resetZoom(); }, d->context, true, - tr("Reset Zoom"), QKeySequence("Ctrl+0")); - menuModelEditor->addAction(resetZoomCommand); - d->zoomOutAction = resetZoomCommand->action(); + registerCommand(Core::Constants::ZOOM_IN, &ModelEditor::zoomIn, d->context); + registerCommand(Core::Constants::ZOOM_OUT, &ModelEditor::zoomOut, d->context); + registerCommand(Core::Constants::ZOOM_RESET, &ModelEditor::resetZoom, d->context); d->openParentDiagramAction = registerCommand( - Constants::OPEN_PARENT_DIAGRAM, [this]() { openParentDiagram(); }, Core::Context(), true, - tr("Open Parent Diagram"), QKeySequence("Ctrl+Shift+P"))->action(); - d->openParentDiagramAction->setIcon(QIcon(":/modeleditor/up.png")); - registerCommand(Constants::ACTION_ADD_PACKAGE, nullptr, Core::Context(), true, tr("Add Package")); - registerCommand(Constants::ACTION_ADD_COMPONENT, nullptr, Core::Context(), true, tr("Add Component")); - registerCommand(Constants::ACTION_ADD_CLASS, nullptr, Core::Context(), true, tr("Add Class")); - registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, nullptr, Core::Context(), true, tr("Add Canvas Diagram")); + Constants::OPEN_PARENT_DIAGRAM, &ModelEditor::openParentDiagram, Core::Context(), + tr("Open Parent Diagram"), QKeySequence("Ctrl+Shift+P"), + QIcon(":/modeleditor/up.png"))->action(); + registerCommand(Constants::ACTION_ADD_PACKAGE, nullptr, Core::Context(), tr("Add Package"), + QKeySequence(), QIcon(":/modelinglib/48x48/package.png")); + registerCommand(Constants::ACTION_ADD_COMPONENT, nullptr, Core::Context(), tr("Add Component"), + QKeySequence(), QIcon(":/modelinglib/48x48/component.png")); + registerCommand(Constants::ACTION_ADD_CLASS, nullptr, Core::Context(), tr("Add Class"), + QKeySequence(), QIcon(":/modelinglib/48x48/class.png")); + registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, nullptr, Core::Context(), tr("Add Canvas Diagram"), + QKeySequence(), QIcon(":/modelinglib/48x48/canvas-diagram.png")); d->synchronizeBrowserAction = registerCommand( - Constants::ACTION_SYNC_BROWSER, nullptr, Core::Context(), true, + Constants::ACTION_SYNC_BROWSER, nullptr, Core::Context(), tr("Synchronize Browser and Diagram") + "
" - + tr("Press && Hold for options") + "")->action(); - d->synchronizeBrowserAction->setIcon(Utils::Icons::LINK.icon()); + + tr("Press && Hold for options") + "", QKeySequence(), + Utils::Icons::LINK.icon())->action(); d->synchronizeBrowserAction->setCheckable(true); auto editPropertiesAction = new QAction(tr("Edit Element Properties"), Core::ICore::mainWindow()); @@ -236,69 +204,6 @@ void ActionHandler::createActions() connect(editItemAction, &QAction::triggered, this, &ActionHandler::onEditItem); } -void ActionHandler::undo() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->undo(); -} - -void ActionHandler::redo() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->redo(); -} - -void ActionHandler::cut() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->cut(); -} - -void ActionHandler::copy() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->copy(); -} - -void ActionHandler::paste() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->paste(); -} - -void ActionHandler::removeSelectedElements() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->removeSelectedElements(); -} - -void ActionHandler::deleteSelectedElements() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->deleteSelectedElements(); -} - -void ActionHandler::selectAll() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->selectAll(); -} - -void ActionHandler::openParentDiagram() -{ - auto editor = dynamic_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->openParentDiagram(); -} - void ActionHandler::onEditProperties() { auto editor = qobject_cast(Core::EditorManager::currentEditor()); @@ -313,51 +218,27 @@ void ActionHandler::onEditItem() editor->editSelectedItem(); } -void ActionHandler::exportDiagram() +std::function invokeOnCurrentModelEditor(void (ModelEditor::*function)()) { - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->exportDiagram(false); + return [function] { + auto editor = qobject_cast(Core::EditorManager::currentEditor()); + if (editor) + (editor->*function)(); + }; } -void ActionHandler::exportSelectedElements() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->exportDiagram(true); -} - -void ActionHandler::zoomIn() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->zoomIn(); -} - -void ActionHandler::zoomOut() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->zoomOut(); -} - -void ActionHandler::resetZoom() -{ - auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (editor) - editor->resetZoom(); -} - -Core::Command *ActionHandler::registerCommand(const Core::Id &id, const std::function &slot, - const Core::Context &context, bool scriptable, const QString &title, - const QKeySequence &keySequence) +Core::Command *ActionHandler::registerCommand(const Core::Id &id, void (ModelEditor::*function)(), + const Core::Context &context, const QString &title, + const QKeySequence &keySequence, const QIcon &icon) { auto action = new QAction(title, this); - Core::Command *command = Core::ActionManager::registerAction(action, id, context, scriptable); + if (!icon.isNull()) + action->setIcon(icon); + Core::Command *command = Core::ActionManager::registerAction(action, id, context, /*scriptable=*/true); if (!keySequence.isEmpty()) command->setDefaultKeySequence(keySequence); - if (slot) - connect(action, &QAction::triggered, this, slot); + if (function) + connect(action, &QAction::triggered, this, invokeOnCurrentModelEditor(function)); return command; } diff --git a/src/plugins/modeleditor/actionhandler.h b/src/plugins/modeleditor/actionhandler.h index bdcdc81fcaf..192a665839c 100644 --- a/src/plugins/modeleditor/actionhandler.h +++ b/src/plugins/modeleditor/actionhandler.h @@ -25,10 +25,11 @@ #pragma once -#include - #include +#include +#include + #include QT_BEGIN_NAMESPACE @@ -43,6 +44,8 @@ class Command; namespace ModelEditor { namespace Internal { +class ModelEditor; + class ActionHandler : public QObject { @@ -73,27 +76,13 @@ public: void createActions(); private: - void undo(); - void redo(); - void cut(); - void copy(); - void paste(); - void removeSelectedElements(); - void deleteSelectedElements(); - void selectAll(); - void openParentDiagram(); void onEditProperties(); void onEditItem(); - void exportDiagram(); - void exportSelectedElements(); - void zoomIn(); - void zoomOut(); - void resetZoom(); - Core::Command *registerCommand(const Core::Id &id, const std::function &slot, - const Core::Context &context, - bool scriptable = true, const QString &title = QString(), - const QKeySequence &keySequence = QKeySequence()); + Core::Command *registerCommand(const Core::Id &id, void (ModelEditor::*function)(), + const Core::Context &context, const QString &title = QString(), + const QKeySequence &keySequence = QKeySequence(), + const QIcon &icon = QIcon()); private: ActionHandlerPrivate *d; diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp index 6af7b79e3c3..6cbd513eb74 100644 --- a/src/plugins/modeleditor/modeleditor.cpp +++ b/src/plugins/modeleditor/modeleditor.cpp @@ -69,6 +69,8 @@ #include "qmt/tasks/diagramscenecontroller.h" #include "qmt/tasks/finddiagramvisitor.h" +#include +#include #include #include #include @@ -323,22 +325,27 @@ void ModelEditor::init(QWidget *parent) toolbarLayout->addWidget(d->diagramSelector, 1); toolbarLayout->addStretch(1); - toolbarLayout->addWidget( - createToolbarCommandButton(Constants::ACTION_ADD_PACKAGE, [this]() { onAddPackage(); }, - QIcon(":/modelinglib/48x48/package.png"), - tr("Add Package"), d->toolbar)); - toolbarLayout->addWidget( - createToolbarCommandButton(Constants::ACTION_ADD_COMPONENT, [this]() { onAddComponent(); }, - QIcon(":/modelinglib/48x48/component.png"), - tr("Add Component"), d->toolbar)); - toolbarLayout->addWidget( - createToolbarCommandButton(Constants::ACTION_ADD_CLASS, [this]() { onAddClass(); }, - QIcon(":/modelinglib/48x48/class.png"), - tr("Add Class"), d->toolbar)); - toolbarLayout->addWidget( - createToolbarCommandButton(Constants::ACTION_ADD_CANVAS_DIAGRAM, [this]() { onAddCanvasDiagram(); }, - QIcon(":/modelinglib/48x48/canvas-diagram.png"), - tr("Add Canvas Diagram"), d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_RESET, + [this]() { resetZoom(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_IN, + [this]() { zoomIn(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_OUT, + [this]() { zoomOut(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_PACKAGE, + [this]() { onAddPackage(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_COMPONENT, + [this]() { onAddComponent(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_CLASS, + [this]() { onAddClass(); }, + d->toolbar)); + toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_CANVAS_DIAGRAM, + [this]() { onAddCanvasDiagram(); }, + d->toolbar)); toolbarLayout->addSpacing(20); auto syncToggleButton = new Core::CommandButton(Constants::ACTION_SYNC_BROWSER, d->toolbar); @@ -569,7 +576,17 @@ void ModelEditor::editSelectedItem() onEditSelectedElement(); } -void ModelEditor::exportDiagram(bool selectedElements) +void ModelEditor::exportDiagram() +{ + exportToImage(/*selectedElements=*/false); +} + +void ModelEditor::exportSelectedElements() +{ + exportToImage(/*selectedElements=*/true); +} + +void ModelEditor::exportToImage(bool selectedElements) { qmt::MDiagram *diagram = currentDiagram(); if (diagram) { @@ -797,18 +814,18 @@ void ModelEditor::expandModelTreeToDepth(int depth) d->modelTreeView->expandToDepth(depth); } -QToolButton *ModelEditor::createToolbarCommandButton(const Core::Id &id, const std::function &slot, - const QIcon &icon, const QString &toolTipBase, +QToolButton *ModelEditor::createToolbarCommandButton(const Core::Id &id, + const std::function &slot, QWidget *parent) { - auto button = new Core::CommandButton(id, parent); - auto action = new QAction(button); - action->setIcon(icon); - action->setToolTip(toolTipBase); - button->setDefaultAction(action); - //button->setIcon(icon); - //button->setToolTipBase(toolTipBase); - connect(button, &Core::CommandButton::clicked, this, slot); + Core::Command *command = Core::ActionManager::command(id); + QTC_CHECK(command); + const QString text = command ? command->description() : QString(); + auto action = new QAction(text, this); + action->setIcon(command ? command->action()->icon() : QIcon()); + auto button = Core::Command::toolButtonWithAppendedShortcut(action, command); + button->setParent(parent); + connect(button, &QToolButton::clicked, this, slot); return button; } diff --git a/src/plugins/modeleditor/modeleditor.h b/src/plugins/modeleditor/modeleditor.h index ed7eed431f7..639f7fab389 100644 --- a/src/plugins/modeleditor/modeleditor.h +++ b/src/plugins/modeleditor/modeleditor.h @@ -87,7 +87,8 @@ public: void openParentDiagram(); void editProperties(); void editSelectedItem(); - void exportDiagram(bool selectedElements); + void exportDiagram(); + void exportSelectedElements(); void zoomIn(); void zoomOut(); void resetZoom(); @@ -103,9 +104,9 @@ private: void showProperties(qmt::MDiagram *diagram, const QList &diagramElements); void clearProperties(); void expandModelTreeToDepth(int depth); - QToolButton *createToolbarCommandButton(const Core::Id &id, const std::function &slot, - const QIcon &icon, - const QString &toolTipBase, QWidget *parent); + QToolButton *createToolbarCommandButton(const Core::Id &id, + const std::function &slot, + QWidget *parent); bool updateButtonIconByTheme(QAbstractButton *button, const QString &name); void showZoomIndicator(); @@ -158,6 +159,8 @@ private: void synchronizeDiagramWithBrowser(); void synchronizeBrowserWithDiagram(const qmt::MDiagram *diagram); + void exportToImage(bool selectedElements); + private: ModelEditorPrivate *d; }; diff --git a/src/plugins/modeleditor/modeleditor_constants.h b/src/plugins/modeleditor/modeleditor_constants.h index fc30438c736..74e99eecc4b 100644 --- a/src/plugins/modeleditor/modeleditor_constants.h +++ b/src/plugins/modeleditor/modeleditor_constants.h @@ -25,6 +25,8 @@ #pragma once +#include + namespace ModelEditor { namespace Constants { @@ -37,9 +39,6 @@ const char OPEN_PARENT_DIAGRAM[] = "ModelEditor.OpenParentDiagram"; const char MENU_ID[] = "ModelEditor.Menu"; const char EXPORT_DIAGRAM[] = "ModelEditor.ExportDiagram"; const char EXPORT_SELECTED_ELEMENTS[] = "ModelEditor.ExportSelectedElements"; -const char ZOOM_IN[] = "ModelEditor.ZoomIn"; -const char ZOOM_OUT[] = "ModelEditor.ZoomOut"; -const char RESET_ZOOM[] = "ModelEditor.ResetZoom"; const char ACTION_ADD_PACKAGE[] = "ModelEditor.Action.AddPackage"; const char ACTION_ADD_COMPONENT[] = "ModelEditor.Action.AddComponent"; const char ACTION_ADD_CLASS[] = "ModelEditor.Action.AddClass"; diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp index 035a0457296..b0d95c64746 100644 --- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp +++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp @@ -54,40 +54,6 @@ namespace Internal { #ifdef Q_OS_WIN -// Resolve QueryFullProcessImageNameW out of kernel32.dll due -// to incomplete MinGW import libs and it not being present -// on Windows XP. -static BOOL queryFullProcessImageName(HANDLE h, DWORD flags, LPWSTR buffer, DWORD *size) -{ - // Resolve required symbols from the kernel32.dll - typedef BOOL (WINAPI *QueryFullProcessImageNameWProtoType) - (HANDLE, DWORD, LPWSTR, PDWORD); - static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0; - if (!queryFullProcessImageNameW) { - QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0); - if (kernel32Lib.isLoaded() || kernel32Lib.load()) - queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW"); - } - if (!queryFullProcessImageNameW) - return FALSE; - // Read out process - return (*queryFullProcessImageNameW)(h, flags, buffer, size); -} - -static QString imageName(DWORD processId) -{ - QString rc; - HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId); - if (handle == INVALID_HANDLE_VALUE) - return rc; - WCHAR buffer[MAX_PATH]; - DWORD bufSize = MAX_PATH; - if (queryFullProcessImageName(handle, 0, buffer, &bufSize)) - rc = QString::fromUtf16(reinterpret_cast(buffer)); - CloseHandle(handle); - return rc; -} - LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent) : DeviceProcessList(device, parent) , m_myPid(GetCurrentProcessId()) @@ -108,7 +74,7 @@ QList LocalProcessList::getLocalProcesses() DeviceProcessItem p; p.pid = pe.th32ProcessID; // Image has the absolute path, but can fail. - const QString image = imageName(pe.th32ProcessID); + const QString image = Utils::imageName(pe.th32ProcessID); p.exe = p.cmdLine = image.isEmpty() ? QString::fromWCharArray(pe.szExeFile) : image; diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs index bfa79ea5192..54fbf015dae 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs +++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs @@ -1,8 +1,10 @@ import qbs 1.0 +import qbs.File import qbs.FileInfo QtcPlugin { name: "QbsProjectManager" + type: base.concat(["qmltype-update"]) property var externalQbsIncludes: project.useExternalQbs ? [project.qbs_install_dir + "/include/qbs"] : [] @@ -116,5 +118,42 @@ QtcPlugin { "qbsrunconfiguration.cpp", "qbsrunconfiguration.h", ] + + // QML typeinfo stuff + property bool updateQmlTypeInfo: useInternalQbsProducts + Group { + condition: !updateQmlTypeInfo + name: "qbs qml type info" + qbs.install: true + qbs.installDir: FileInfo.joinPaths(qtc.ide_data_path, "qtcreator", + "qml-type-descriptions") + prefix: FileInfo.joinPaths(project.ide_source_tree, "share", "qtcreator", + "qml-type-descriptions") + '/' + files: [ + "qbs-bundle.json", + "qbs.qmltypes", + ] + } + + Depends { name: "qbs resources" } + Rule { + condition: updateQmlTypeInfo + inputsFromDependencies: ["qbs qml type descriptions", "qbs qml type bundle"] + Artifact { + filePath: "dummy." + input.fileName + fileTags: ["qmltype-update"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "Updating " + input.fileName + " in Qt Creator repository"; + cmd.sourceCode = function() { + var targetFilePath = FileInfo.joinPaths(project.ide_source_tree, "share", + "qtcreator", "qml-type-descriptions", + input.fileName); + File.copy(input.filePath, targetFilePath); + } + return cmd; + } + } } diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp index 7745ef29f1f..5ae16c73c1a 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp @@ -51,7 +51,11 @@ static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfigur QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *target) : AndroidRunConfiguration(target, ANDROID_RC_ID_PREFIX) -{} +{ + connect(target->project(), &Project::parsingFinished, this, [this]() { + updateDisplayName(); + }); +} QString QmakeAndroidRunConfiguration::extraId() const { @@ -72,7 +76,6 @@ bool QmakeAndroidRunConfiguration::fromMap(const QVariantMap &map) if (!extraId.isEmpty()) m_proFilePath = Utils::FileName::fromString(extraId); - setDefaultDisplayName(defaultDisplayName()); return true; } @@ -86,17 +89,15 @@ QVariantMap QmakeAndroidRunConfiguration::toMap() const return map; } -QString QmakeAndroidRunConfiguration::defaultDisplayName() +void QmakeAndroidRunConfiguration::updateDisplayName() { QmakeProject *project = qmakeProject(); const QmakeProjectManager::QmakeProFileNode *root = project->rootProjectNode(); if (root) { const QmakeProjectManager::QmakeProFileNode *node = root->findProFileFor(m_proFilePath); if (node) // should always be found - return node->displayName(); + setDefaultDisplayName(node->displayName()); } - - return QString(); } QString QmakeAndroidRunConfiguration::disabledReason() const diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h index 9132006cfd7..d4c5d458177 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h @@ -49,7 +49,7 @@ private: QString extraId() const final; bool fromMap(const QVariantMap &map) override; QVariantMap toMap() const override; - QString defaultDisplayName(); + void updateDisplayName(); QmakeProjectManager::QmakeProject *qmakeProject() const; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 2016fd909c1..6751ebf6e38 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -416,7 +416,7 @@ void ItemLibraryWidget::addResources() if (!fileNames.isEmpty()) { const auto directory = QFileDialog::getExistingDirectory(this, - tr("Target Direcotry"), + tr("Target Directory"), document->fileName().parentDir().toString()); for (const QString &fileName : fileNames) { @@ -425,7 +425,7 @@ void ItemLibraryWidget::addResources() postfix.remove(0, 1); if (fileName.endsWith(postfix)) if (!handler.operation(fileName, directory)) - Core::AsynchronousMessageBox::warning(tr("Failed to add File"), tr("Could not add %1 to project.").arg(fileName)); + Core::AsynchronousMessageBox::warning(tr("Failed to Add File"), tr("Could not add %1 to project.").arg(fileName)); } } } diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp index 6926f7a9b3f..ef96d0c1616 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp @@ -25,19 +25,23 @@ #include "navigatorwidget.h" #include "navigatorview.h" -#include "qmldesignerconstants.h" -#include "qmldesignericons.h" + #include +#include +#include +#include #include -#include -#include #include -#include +#include #include -#include +#include +#include +#include + #include #include +#include namespace QmlDesigner { @@ -54,18 +58,43 @@ NavigatorWidget::NavigatorWidget(NavigatorView *view) : m_treeView->setDefaultDropAction(Qt::LinkAction); m_treeView->setHeaderHidden(true); - QVBoxLayout *layout = new QVBoxLayout; + auto layout = new QVBoxLayout; layout->setSpacing(0); layout->setMargin(0); - layout->addWidget(m_treeView); + auto tabBar = new QTabBar(this); + tabBar->addTab(tr("Navigator")); + tabBar->addTab(tr("Project")); + tabBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + QWidget *spacer = new QWidget(this); + spacer->setObjectName(QStringLiteral("itemLibrarySearchInputSpacer")); + spacer->setFixedHeight(4); + + layout->addWidget(tabBar); + layout->addWidget(spacer); + + auto stackedWidget = new QStackedWidget(this); + stackedWidget->addWidget(m_treeView); + +#ifndef QMLDESIGNER_TEST + auto projectManager = QmlDesignerPlugin::instance()->createProjectExplorerWidget(this); + + QTC_ASSERT(projectManager, ;); + if (projectManager) + stackedWidget->addWidget(projectManager); +#endif + + connect(tabBar, &QTabBar::currentChanged, stackedWidget, &QStackedWidget::setCurrentIndex); + + layout->addWidget(stackedWidget); setLayout(layout); setWindowTitle(tr("Navigator", "Title of navigator view")); #ifndef QMLDESIGNER_TEST - setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/stylesheet.css"))))); - m_treeView->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css"))))); + setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css")))); + m_treeView->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")))); #endif } diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 7a48b4b0b6a..acbcd19bab3 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -72,6 +72,12 @@ const char SB_PROJECTS[] = "Projects"; const char SB_FILESYSTEM[] = "FileSystem"; const char SB_OPENDOCUMENTS[] = "OpenDocuments"; +static void hideToolButtons(QList &buttons) +{ + foreach (QToolButton *button, buttons) + button->hide(); +} + namespace QmlDesigner { namespace Internal { @@ -169,6 +175,32 @@ void DesignModeWidget::toggleRightSidebar() m_rightSideBar->setVisible(!m_rightSideBar->isVisible()); } +QWidget *DesignModeWidget::createProjectExplorerWidget(QWidget *parent) +{ + QList factories = + ExtensionSystem::PluginManager::getObjects(); + + Core::NavigationView navigationView; + navigationView.widget = nullptr; + + foreach (Core::INavigationWidgetFactory *factory, factories) { + if (factory->id() == "Projects") { + navigationView = factory->createWidget(); + hideToolButtons(navigationView.dockToolBarWidgets); + } + } + + if (navigationView.widget) { + QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"); + sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css"); + sheet += "QLabel { background-color: #4f4f4f; }"; + navigationView.widget->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet))); + navigationView.widget->setParent(parent); + } + + return navigationView.widget; +} + void DesignModeWidget::readSettings() { QSettings *settings = Core::ICore::settings(); @@ -221,12 +253,6 @@ void DesignModeWidget::switchTextOrForm() m_centralTabWidget->switchTo(viewManager().widget("TextEditor")); } -static void hideToolButtons(QList &buttons) -{ - foreach (QToolButton *button, buttons) - button->hide(); -} - void DesignModeWidget::setup() { auto &actionManager = viewManager().designerActionManager(); diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h index ce585a381b2..f392058b762 100644 --- a/src/plugins/qmldesigner/designmodewidget.h +++ b/src/plugins/qmldesigner/designmodewidget.h @@ -85,6 +85,8 @@ public: void toggleLeftSidebar(); void toggleRightSidebar(); + static QWidget *createProjectExplorerWidget(QWidget *parent); + private: // functions enum InitializeStatus { NotInitialized, Initializing, Initialized }; diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp index 46acbeb8a69..9a92bb0852b 100644 --- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp +++ b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp @@ -34,6 +34,9 @@ #include "dynamicpropertiesmodel.h" #include "theme.h" +#include +#include + #include #include #include @@ -66,7 +69,12 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) : ui->tabBar->addTab(tr("Connections", "Title of connection view")); ui->tabBar->addTab(tr("Bindings", "Title of connection view")); ui->tabBar->addTab(tr("Properties", "Title of dynamic properties view")); - ui->tabBar->addTab(tr("Backends", "Title of dynamic properties view")); + + auto settings = QmlDesignerPlugin::instance()->settings(); + + if (!settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) + ui->tabBar->addTab(tr("Backends", "Title of dynamic properties view")); + ui->tabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); const QString themedScrollBarCss = Theme::replaceCssColors( diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 32e09403424..3d89f35784c 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -455,6 +455,11 @@ Internal::DesignModeWidget *QmlDesignerPlugin::mainWidget() const return nullptr; } +QWidget *QmlDesignerPlugin::createProjectExplorerWidget(QWidget *parent) const +{ + return Internal::DesignModeWidget::createProjectExplorerWidget(parent); +} + void QmlDesignerPlugin::switchToTextModeDeferred() { QTimer::singleShot(0, this, [] () { diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h index 1106c7d9744..cf4a212feae 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.h +++ b/src/plugins/qmldesigner/qmldesignerplugin.h @@ -82,6 +82,8 @@ public: DesignDocument *currentDesignDocument() const; Internal::DesignModeWidget *mainWidget() const; + QWidget *createProjectExplorerWidget(QWidget *parent) const; + void switchToTextModeDeferred(); void emitCurrentTextEditorChanged(Core::IEditor *editor); diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp index e415ec2f19e..dee2e0d9fbd 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp @@ -47,6 +47,28 @@ namespace QmlProfiler { namespace Internal { +const int DEFAULT_SORT_COLUMN = 2; + +struct SortPreserver { + SortPreserver(Utils::TreeView *view) : view(view) + { + const QHeaderView *header = view->header(); + column = header->sortIndicatorSection(); + order = header->sortIndicatorOrder(); + view->setSortingEnabled(false); + } + + ~SortPreserver() + { + view->setSortingEnabled(true); + view->sortByColumn(column, order); + } + + int column; + Qt::SortOrder order; + Utils::TreeView *view; +}; + struct Colors { Colors () : noteBackground(QColor("orange")), defaultBackground(QColor("white")) {} QColor noteBackground; @@ -374,7 +396,6 @@ public: QList m_fieldShown; QHash m_columnIndex; // maps field enum to column index bool m_showExtendedStatistics; - int m_firstNumericColumn; }; QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView( @@ -384,8 +405,6 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView( setViewDefaults(this); setObjectName(QLatin1String("QmlProfilerEventsTable")); - setSortingEnabled(false); - d->m_model = new QStandardItemModel(this); d->m_model->setSortRole(SortRole); setModel(d->m_model); @@ -396,7 +415,6 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView( this, &QmlProfilerStatisticsMainView::buildModel); connect(d->model, &QmlProfilerStatisticsModel::notesAvailable, this, &QmlProfilerStatisticsMainView::updateNotes); - d->m_firstNumericColumn = 0; d->m_showExtendedStatistics = false; setFieldViewable(Name, true); @@ -412,6 +430,9 @@ QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainView( setFieldViewable(MedianTime, true); setFieldViewable(Details, true); + setSortingEnabled(true); + sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder); + buildModel(); } @@ -438,18 +459,15 @@ void QmlProfilerStatisticsMainView::setFieldViewable(Fields field, bool show) void QmlProfilerStatisticsMainView::setHeaderLabels() { int fieldIndex = 0; - d->m_firstNumericColumn = 0; d->m_columnIndex.clear(); if (d->m_fieldShown[Name]) { d->m_columnIndex[Name] = fieldIndex; d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Location))); - d->m_firstNumericColumn++; } if (d->m_fieldShown[Type]) { d->m_columnIndex[Type] = fieldIndex; d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); - d->m_firstNumericColumn++; } if (d->m_fieldShown[TimeInPercent]) { d->m_columnIndex[TimeInPercent] = fieldIndex; @@ -521,11 +539,10 @@ bool QmlProfilerStatisticsMainView::showExtendedStatistics() const void QmlProfilerStatisticsMainView::clear() { + SortPreserver sorter(this); d->m_model->clear(); d->m_model->setColumnCount(d->getFieldCount()); - setHeaderLabels(); - setSortingEnabled(false); } int QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate::getFieldCount() @@ -540,12 +557,13 @@ int QmlProfilerStatisticsMainView::QmlProfilerStatisticsMainViewPrivate::getFiel void QmlProfilerStatisticsMainView::buildModel() { clear(); - parseModel(); - setShowExtendedStatistics(d->m_showExtendedStatistics); - setRootIsDecorated(false); - setSortingEnabled(true); - sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); + { + SortPreserver sorter(this); + parseModel(); + setShowExtendedStatistics(d->m_showExtendedStatistics); + setRootIsDecorated(false); + } expandAll(); if (d->m_fieldShown[Name]) @@ -839,7 +857,6 @@ QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView( Utils::TreeView(parent), d(new QmlProfilerStatisticsRelativesViewPrivate(this)) { setViewDefaults(this); - setSortingEnabled(false); d->model = model; QStandardItemModel *itemModel = new QStandardItemModel(this); itemModel->setSortRole(SortRole); @@ -847,6 +864,9 @@ QmlProfilerStatisticsRelativesView::QmlProfilerStatisticsRelativesView( setRootIsDecorated(false); updateHeader(); + setSortingEnabled(true); + sortByColumn(DEFAULT_SORT_COLUMN, Qt::DescendingOrder); + connect(this, &QAbstractItemView::activated, this, &QmlProfilerStatisticsRelativesView::jumpToItem); @@ -862,12 +882,11 @@ QmlProfilerStatisticsRelativesView::~QmlProfilerStatisticsRelativesView() void QmlProfilerStatisticsRelativesView::displayType(int typeIndex) { + SortPreserver sorter(this); rebuildTree(d->model->getData(typeIndex)); updateHeader(); resizeColumnToContents(0); - setSortingEnabled(true); - sortByColumn(2); } void QmlProfilerStatisticsRelativesView::rebuildTree( @@ -929,6 +948,7 @@ void QmlProfilerStatisticsRelativesView::rebuildTree( void QmlProfilerStatisticsRelativesView::clear() { if (treeModel()) { + SortPreserver sorter(this); treeModel()->clear(); updateHeader(); } diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp index 6154ecd3d72..01054df1271 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp @@ -127,6 +127,13 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FileName &fi OtherFileFilterItem *otherFileFilterItem = new OtherFileFilterItem(projectItem); setupFileFilterItem(otherFileFilterItem, childNode); projectItem->appendContent(otherFileFilterItem); + } else if (childNode->name() == "Environment") { + const auto properties = childNode->properties(); + auto i = properties.constBegin(); + while (i != properties.constEnd()) { + projectItem->addToEnviroment(i.key(), i.value().toString()); + ++i; + } } else { qWarning() << "Unknown type:" << childNode->name(); } diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp index 8e9e99475fc..b462bf48b86 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp @@ -106,4 +106,14 @@ bool QmlProjectItem::matchesFile(const QString &filePath) const return false; } +QList QmlProjectItem::environment() const +{ + return m_environment; +} + +void QmlProjectItem::addToEnviroment(const QString &key, const QString &value) +{ + m_environment.append(Utils::EnvironmentItem(key, value)); +} + } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h index 757e5714687..e3c65e7ef13 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h @@ -25,6 +25,8 @@ #pragma once +#include + #include #include #include @@ -60,6 +62,9 @@ public: void appendContent(QmlProjectContentItem *item) { m_content.append(item); } + QList environment() const; + void addToEnviroment(const QString &key, const QString &value); + signals: void qmlFilesChanged(const QSet &, const QSet &); @@ -69,6 +74,7 @@ protected: QStringList m_importPaths; QStringList m_absoluteImportPaths; QString m_mainFile; + QList m_environment; QList m_content; // content property }; diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 2f9ab498daa..471ef4a13b5 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -213,6 +213,13 @@ Utils::FileName QmlProject::targetFile(const Utils::FileName &sourceFile, return Utils::FileName::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative))); } +QList QmlProject::environment() const +{ + if (m_projectItem) + return m_projectItem.data()->environment(); + return {}; +} + bool QmlProject::validProjectFile() const { return !m_projectItem.isNull(); diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index c1b667d21a1..4ecd7b226e6 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -30,6 +30,8 @@ #include +#include + #include namespace ProjectExplorer { class RunConfiguration; } @@ -65,6 +67,8 @@ public: Utils::FileName targetDirectory(const ProjectExplorer::Target *target) const; Utils::FileName targetFile(const Utils::FileName &sourceFile, const ProjectExplorer::Target *target) const; + + QList environment() const; QStringList customImportPaths() const; bool addFiles(const QStringList &filePaths); diff --git a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp b/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp index 626c8895518..5cc6fe9988c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp @@ -25,6 +25,8 @@ #include "qmlprojectenvironmentaspect.h" +#include "qmlproject.h" + #include #include #include @@ -57,6 +59,10 @@ Utils::Environment QmlProjectEnvironmentAspect::baseEnvironment() const if (base == static_cast(KitEnvironmentBase)) runConfiguration()->target()->kit()->addToEnvironment(env); + QmlProject *project = qobject_cast(runConfiguration()->target()->project()); + if (project) + env.modify(project->environment()); + return env; } diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index f2286bdc3c6..e715d1364d2 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -69,7 +69,8 @@ using namespace ProjectExplorer; using namespace Utils; static const char QTVERSIONAUTODETECTED[] = "isAutodetected"; -static const char QTVERSIONAUTODETECTIONSOURCE []= "autodetectionSource"; +static const char QTVERSIONAUTODETECTIONSOURCE[] = "autodetectionSource"; +static const char QTVERSION_OVERRIDE_FEATURES[] = "overrideFeatures"; static const char QTVERSIONQMAKEPATH[] = "QMakePath"; static const char QTVERSIONSOURCEPATH[] = "SourcePath"; @@ -227,6 +228,7 @@ BaseQtVersion::BaseQtVersion(const BaseQtVersion &other) : m_qtConfigValues(other.m_qtConfigValues), m_unexpandedDisplayName(other.m_unexpandedDisplayName), m_autodetectionSource(other.m_autodetectionSource), + m_overrideFeatures(other.m_overrideFeatures), m_sourcePath(other.m_sourcePath), m_mkspec(other.m_mkspec), m_mkspecFullPath(other.m_mkspecFullPath), @@ -662,6 +664,7 @@ void BaseQtVersion::fromMap(const QVariantMap &map) m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); if (m_isAutodetected) m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString(); + m_overrideFeatures = Core::Id::fromStringList(map.value(QTVERSION_OVERRIDE_FEATURES).toStringList()); QString string = map.value(QTVERSIONQMAKEPATH).toString(); if (string.startsWith('~')) string.remove(0, 1).prepend(QDir::homePath()); @@ -688,6 +691,9 @@ QVariantMap BaseQtVersion::toMap() const result.insert(QTVERSIONAUTODETECTED, isAutodetected()); if (isAutodetected()) result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource()); + if (!m_overrideFeatures.isEmpty()) + result.insert(QTVERSION_OVERRIDE_FEATURES, Core::Id::toStringList(m_overrideFeatures)); + result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString()); return result; } @@ -1359,6 +1365,13 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar finder->setAdditionalSearchDirectories(additionalSearchDirectories); } +QSet BaseQtVersion::features() const +{ + if (m_overrideFeatures.isEmpty()) + return availableFeatures(); + return m_overrideFeatures; +} + void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const { Q_UNUSED(k); diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h index 8b23d827f3d..e71f9b3a071 100644 --- a/src/plugins/qtsupport/baseqtversion.h +++ b/src/plugins/qtsupport/baseqtversion.h @@ -205,7 +205,6 @@ public: static QString defaultUnexpandedDisplayName(const Utils::FileName &qmakePath, bool fromPath = false); - virtual QSet availableFeatures() const; virtual QSet targetDeviceTypes() const = 0; virtual QList validateKit(const ProjectExplorer::Kit *k); @@ -237,7 +236,9 @@ public: static void populateQmlFileFinder(Utils::FileInProjectFinder *finder, const ProjectExplorer::Target *target); + QSet features() const; protected: + virtual QSet availableFeatures() const; BaseQtVersion(); BaseQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString()); BaseQtVersion(const BaseQtVersion &other); @@ -294,6 +295,7 @@ private: QString m_unexpandedDisplayName; QString m_autodetectionSource; + QSet m_overrideFeatures; mutable Utils::FileName m_sourcePath; mutable Utils::FileName m_qtSources; diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 972df564a87..3437ed7116e 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -231,7 +231,7 @@ Kit::Predicate QtKitInformation::qtVersionPredicate(const QSet &requir return false; if (max.majorVersion > -1 && current > max) return false; - return version->availableFeatures().contains(required); + return version->features().contains(required); }; } @@ -244,7 +244,7 @@ QSet QtKitInformation::supportedPlatforms(const Kit *k) const QSet QtKitInformation::availableFeatures(const Kit *k) const { BaseQtVersion *version = QtKitInformation::qtVersion(k); - return version ? version->availableFeatures() : QSet(); + return version ? version->features() : QSet(); } } // namespace QtSupport diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp index 5796800951d..4d3f31db813 100644 --- a/src/plugins/remotelinux/remotelinuxplugin.cpp +++ b/src/plugins/remotelinux/remotelinuxplugin.cpp @@ -27,6 +27,7 @@ #include "embeddedlinuxqtversionfactory.h" #include "genericlinuxdeviceconfigurationfactory.h" +#include "remotelinux_constants.h" #include "remotelinuxqmltoolingsupport.h" #include "remotelinuxcustomrunconfiguration.h" #include "remotelinuxdebugsupport.h" @@ -42,6 +43,9 @@ #include "tarpackagecreationstep.h" #include "uploadandinstalltarpackagestep.h" +#include +#include + using namespace ProjectExplorer; namespace RemoteLinux { @@ -99,9 +103,16 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments, dd = new RemoteLinuxPluginPrivate; auto constraint = [](RunConfiguration *runConfig) { + const Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId( + runConfig->target()->kit()); + + if (devType != Constants::GenericLinuxOsType) + return false; + const Core::Id id = runConfig->id(); return id == RemoteLinuxCustomRunConfiguration::runConfigId() - || id.name().startsWith(RemoteLinuxRunConfiguration::IdPrefix); + || id.name().startsWith(RemoteLinuxRunConfiguration::IdPrefix) + || id.name().startsWith("QmlProjectManager.QmlRunConfiguration"); }; using namespace ProjectExplorer::Constants; diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index d007f3580fb..3b6b372fe24 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -98,6 +98,8 @@ #include #include +#include + #include #endif @@ -744,7 +746,7 @@ void MemcheckTool::heobAction() } } if (!hasLocalRc) { - const QString msg = tr("Heob: No local run configuration available"); + const QString msg = tr("Heob: No local run configuration available."); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); return; @@ -753,7 +755,7 @@ void MemcheckTool::heobAction() || abi.os() != Abi::WindowsOS || abi.binaryFormat() != Abi::PEFormat || (abi.wordWidth() != 32 && abi.wordWidth() != 64)) { - const QString msg = tr("Heob: No toolchain available"); + const QString msg = tr("Heob: No toolchain available."); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); return; @@ -766,13 +768,13 @@ void MemcheckTool::heobAction() // target executable if (executable.isEmpty()) { - const QString msg = tr("Heob: No executable set"); + const QString msg = tr("Heob: No executable set."); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); return; } if (!QFile::exists(executable)) { - const QString msg = tr("Heob: Can't find %1").arg(executable); + const QString msg = tr("Heob: Cannot find %1.").arg(executable); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); return; @@ -853,7 +855,7 @@ void MemcheckTool::heobAction() CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED | CREATE_NEW_CONSOLE, envPtr, reinterpret_cast(workingDirectory.utf16()), &si, &pi)) { DWORD e = GetLastError(); - const QString msg = tr("Heob: Can't create %1 process (%2)").arg(heob).arg(qt_error_string(e)); + const QString msg = tr("Heob: Cannot create %1 process (%2).").arg(heob).arg(qt_error_string(e)); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); return; @@ -1114,13 +1116,13 @@ void MemcheckTool::engineFinished() const int issuesFound = updateUiAfterFinishedHelper(); Debugger::showPermanentStatusMessage( - tr("Memory Analyzer Tool finished, %n issues were found.", 0, issuesFound)); + tr("Memory Analyzer Tool finished. %n issues were found.", 0, issuesFound)); } void MemcheckTool::loadingExternalXmlLogFileFinished() { const int issuesFound = updateUiAfterFinishedHelper(); - QString statusMessage = tr("Log file processed, %n issues were found.", 0, issuesFound); + QString statusMessage = tr("Log file processed. %n issues were found.", 0, issuesFound); if (!m_exitMsg.isEmpty()) statusMessage += ' ' + m_exitMsg; Debugger::showPermanentStatusMessage(statusMessage); @@ -1503,15 +1505,7 @@ void HeobData::processFinished() debugger->setStartMode(AttachExternal); debugger->setCloseMode(DetachAtClose); debugger->setContinueAfterAttach(true); - - HANDLE p = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, m_data[1]); - if (p != NULL) { - wchar_t path[MAX_PATH]; - DWORD pathLen = MAX_PATH; - if (QueryFullProcessImageName(p, 0, path, &pathLen)) - debugger->setInferiorExecutable(QString::fromWCharArray(path)); - CloseHandle(p); - } + debugger->setInferiorExecutable(Utils::imageName(m_data[1])); connect(m_runControl, &RunControl::started, this, &HeobData::debugStarted); connect(m_runControl, &RunControl::stopped, this, &HeobData::debugStopped); @@ -1530,21 +1524,21 @@ void HeobData::processFinished() break; case HEOB_PROCESS_FAIL: - exitMsg = tr("Can't create target process"); + exitMsg = tr("Cannot create target process."); if (m_data[1]) exitMsg += " (" + qt_error_string(m_data[1]) + ')'; break; case HEOB_WRONG_BITNESS: - exitMsg = tr("Wrong bitness"); + exitMsg = tr("Wrong bitness."); break; case HEOB_PROCESS_KILLED: - exitMsg = tr("Process killed"); + exitMsg = tr("Process killed."); break; case HEOB_NO_CRT: - exitMsg = tr("Only works with dynamically linked CRT"); + exitMsg = tr("Only works with dynamically linked CRT."); break; case HEOB_EXCEPTION: @@ -1553,15 +1547,15 @@ void HeobData::processFinished() break; case HEOB_OUT_OF_MEMORY: - exitMsg = tr("Not enough memory to keep track of allocations"); + exitMsg = tr("Not enough memory to keep track of allocations."); break; case HEOB_UNEXPECTED_END: - exitMsg = tr("Unexpected end of application"); + exitMsg = tr("Application stopped unexpectedly."); break; case HEOB_CONSOLE: - exitMsg = tr("Extra console"); + exitMsg = tr("Extra console."); break; case HEOB_HELP: @@ -1570,11 +1564,11 @@ void HeobData::processFinished() return; default: - exitMsg = tr("Unknown exit reason"); + exitMsg = tr("Unknown exit reason."); break; } } else { - exitMsg = tr("Unexpected end of heob"); + exitMsg = tr("Heob stopped unexpectedly."); } if (needErrorMsg) { @@ -1613,7 +1607,7 @@ void HeobData::sendHeobAttachPid(DWORD pid) } } - const QString msg = tr("Heob: Failure in process attach handshake (%1)").arg(qt_error_string(e)); + const QString msg = tr("Heob: Failure in process attach handshake (%1).").arg(qt_error_string(e)); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); deleteLater(); diff --git a/src/shared/qbs b/src/shared/qbs index 8355ba92901..8e396382646 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 8355ba92901715bc9366c9a0218fa756ae457408 +Subproject commit 8e396382646a9e1a3efb57bc77e303f90b7c80c0 diff --git a/src/tools/clangbackend/source/clangbackend_global.h b/src/tools/clangbackend/source/clangbackend_global.h index 31425c07173..927141e01f3 100644 --- a/src/tools/clangbackend/source/clangbackend_global.h +++ b/src/tools/clangbackend/source/clangbackend_global.h @@ -41,4 +41,9 @@ enum class PreferredTranslationUnit # define IS_PRETTY_DECL_SUPPORTED #endif +// CLANG-UPGRADE-CHECK: Remove IS_INVALIDDECL_SUPPORTED once we require clang >= 7.0 +#if defined(CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED) || CINDEX_VERSION_MINOR >= 46 +# define IS_INVALIDDECL_SUPPORTED +#endif + } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/source/commandlinearguments.cpp b/src/tools/clangbackend/source/commandlinearguments.cpp index a7f29b870fd..5d8e616ad1c 100644 --- a/src/tools/clangbackend/source/commandlinearguments.cpp +++ b/src/tools/clangbackend/source/commandlinearguments.cpp @@ -28,30 +28,74 @@ #include "clangfilepath.h" #include +#include #include #include +#include #include +static QList splitArgs(QString &argsString) +{ + QList result; + Utils::QtcProcess::ArgIterator it(&argsString); + while (it.next()) + result.append(it.value().toUtf8()); + return result; +} + +template +static QList extraOptions(const char(&environment)[Size]) +{ + if (!qEnvironmentVariableIsSet(environment)) + return QList(); + QString arguments = QString::fromLocal8Bit(qgetenv(environment)); + return splitArgs(arguments); +} + +static QList extraClangCodeModelPrependOptions() { + constexpr char ccmPrependOptions[] = "QTC_CLANG_CCM_CMD_PREPEND"; + static const QList options = extraOptions(ccmPrependOptions); + if (!options.isEmpty()) + qWarning() << "ClangCodeModel options are prepended with " << options; + return options; +} + +static QList extraClangCodeModelAppendOptions() { + constexpr char ccmAppendOptions[] = "QTC_CLANG_CCM_CMD_APPEND"; + static const QList options = extraOptions(ccmAppendOptions); + if (!options.isEmpty()) + qWarning() << "ClangCodeModel options are appended with " << options; + return options; +} + namespace ClangBackEnd { CommandLineArguments::CommandLineArguments(const char *filePath, const Utf8StringVector &projectPartArguments, const Utf8StringVector &fileArguments, bool addVerboseOption) + : m_prependArgs(extraClangCodeModelPrependOptions()), + m_appendArgs(extraClangCodeModelAppendOptions()) { - const auto elementsToReserve = projectPartArguments.size() - + uint(fileArguments.size()) - + (addVerboseOption ? 1 : 0); - m_arguments.reserve(elementsToReserve); + const int elementsToReserve = m_prependArgs.size() + + projectPartArguments.size() + + fileArguments.size() + + (addVerboseOption ? 1 : 0) + + m_appendArgs.size(); + m_arguments.reserve(static_cast(elementsToReserve)); + for (const auto &argument : m_prependArgs) + m_arguments.push_back(argument.constData()); for (const auto &argument : projectPartArguments) m_arguments.push_back(argument.constData()); for (const auto &argument : fileArguments) m_arguments.push_back(argument.constData()); if (addVerboseOption) m_arguments.push_back("-v"); + for (const auto &argument : m_appendArgs) + m_arguments.push_back(argument.constData()); m_nativeFilePath = FilePath::toNativeSeparators(Utf8String::fromUtf8(filePath)); m_arguments.push_back(m_nativeFilePath.constData()); } diff --git a/src/tools/clangbackend/source/commandlinearguments.h b/src/tools/clangbackend/source/commandlinearguments.h index aa0b2bafbfe..711e69420fb 100644 --- a/src/tools/clangbackend/source/commandlinearguments.h +++ b/src/tools/clangbackend/source/commandlinearguments.h @@ -47,6 +47,8 @@ public: private: Utf8String m_nativeFilePath; + const QList m_prependArgs; + const QList m_appendArgs; std::vector m_arguments; }; diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp index 7978e914b21..516244aa9e0 100644 --- a/src/tools/clangbackend/source/cursor.cpp +++ b/src/tools/clangbackend/source/cursor.cpp @@ -29,6 +29,8 @@ #include "sourcelocation.h" #include "sourcerange.h" +#include "clangbackend_global.h" + #include namespace ClangBackEnd { @@ -103,6 +105,15 @@ bool Cursor::isDeclaration() const return clang_isDeclaration(kind()); } +bool Cursor::isInvalidDeclaration() const +{ +#ifdef IS_INVALIDDECL_SUPPORTED + return clang_isInvalidDeclaration(cxCursor); +#else + return false; +#endif +} + bool Cursor::isLocalVariable() const { switch (semanticParent().kind()) { diff --git a/src/tools/clangbackend/source/cursor.h b/src/tools/clangbackend/source/cursor.h index b13ae52d867..dd2b59302be 100644 --- a/src/tools/clangbackend/source/cursor.h +++ b/src/tools/clangbackend/source/cursor.h @@ -63,6 +63,7 @@ public: bool isStaticMethod() const; bool isCompoundType() const; bool isDeclaration() const; + bool isInvalidDeclaration() const; bool isLocalVariable() const; bool isReference() const; bool isExpression() const; diff --git a/src/tools/clangbackend/source/sourcelocation.cpp b/src/tools/clangbackend/source/sourcelocation.cpp index 41f68a9ae6f..77fd9e61da4 100644 --- a/src/tools/clangbackend/source/sourcelocation.cpp +++ b/src/tools/clangbackend/source/sourcelocation.cpp @@ -100,6 +100,9 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr); if (!contents) return; + // (1) column in SourceLocation is the actual column shown by CppEditor. + // (2) column in Clang is the utf8 byte offset from the beginning of the line. + // Here we convert column from (2) to (1). column_ = static_cast(QString::fromUtf8(&contents[lineStart], static_cast(column_)).size()); } diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp index ef89a2424a0..36ee9a2a33b 100644 --- a/src/tools/clangbackend/source/tokeninfo.cpp +++ b/src/tools/clangbackend/source/tokeninfo.cpp @@ -330,8 +330,10 @@ void TokenInfo::typeKind(const Cursor &cursor) void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) { - const CXCursorKind kind = cursor.kind(); + if (cursor.isInvalidDeclaration()) + return; + const CXCursorKind kind = cursor.kind(); switch (kind) { case CXCursor_Destructor: case CXCursor_Constructor: diff --git a/tests/unit/unittest/conditionally-disabled-tests.h b/tests/unit/unittest/conditionally-disabled-tests.h index 8f55db10d7a..3cac7591352 100644 --- a/tests/unit/unittest/conditionally-disabled-tests.h +++ b/tests/unit/unittest/conditionally-disabled-tests.h @@ -39,3 +39,9 @@ #else # define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) DISABLED_##x #endif + +#ifdef IS_INVALIDDECL_SUPPORTED +# define DISABLED_WITHOUT_INVALIDDECL_PATCH(x) x +#else +# define DISABLED_WITHOUT_INVALIDDECL_PATCH(x) DISABLED_##x +#endif diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp index 778d74cc264..9f9a42f278b 100644 --- a/tests/unit/unittest/data/highlightingmarks.cpp +++ b/tests/unit/unittest/data/highlightingmarks.cpp @@ -590,3 +590,5 @@ class WithVirtualFunctionDefined { }; namespace NFoo { namespace NBar { namespace NTest { class NamespaceTypeSpelling; } } } + +Undeclared u; diff --git a/tests/unit/unittest/tokeninfos-test.cpp b/tests/unit/unittest/tokeninfos-test.cpp index 5e8f160af7d..bfd3bf22fa3 100644 --- a/tests/unit/unittest/tokeninfos-test.cpp +++ b/tests/unit/unittest/tokeninfos-test.cpp @@ -1256,6 +1256,20 @@ TEST_F(TokenInfos, NamespaceTypeSpelling) ASSERT_THAT(container.extraInfo().semanticParentTypeSpelling, Utf8StringLiteral("NFoo::NBar::NTest")); } +TEST_F(TokenInfos, DISABLED_WITHOUT_INVALIDDECL_PATCH(TypeNameOfInvalidDeclarationIsInvalid)) +{ + const auto infos = translationUnit.tokenInfosInRange(sourceRange(592, 14)); + + ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Invalid)); +} + +TEST_F(TokenInfos, DISABLED_WITHOUT_INVALIDDECL_PATCH(VariableNameOfInvalidDeclarationIsInvalid)) +{ + const auto infos = translationUnit.tokenInfosInRange(sourceRange(592, 14)); + + ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Invalid)); +} + Data *TokenInfos::d; void TokenInfos::SetUpTestCase()