Merge remote-tracking branch 'origin/4.9'
Change-Id: I7d1912cd5c4d824fd40d3454c5f1bb796f2c21d8
@@ -8,7 +8,7 @@ The standalone binary packages support the following platforms:
|
||||
|
||||
* Windows 7 or later
|
||||
* (K)Ubuntu Linux 16.04 (64-bit) or later
|
||||
* macOS 10.11 or later
|
||||
* macOS 10.12 or later
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -221,6 +221,11 @@ Remote Linux
|
||||
(QTCREATORBUG-21225)
|
||||
* Fixed issue with killing remote process (QTCREATORBUG-19941)
|
||||
|
||||
Boot to Qt
|
||||
|
||||
* Removed ADB-based Boot to Qt plugin that provided support for
|
||||
Boot to Qt versions 5.8, and earlier.
|
||||
|
||||
Credits for these changes go to:
|
||||
Aaron Barany
|
||||
Alessandro Portale
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
|
||||
@@ -20,7 +20,8 @@ imagedirs = ../images \
|
||||
../../src/plugins/qmldesigner/components/formeditor \
|
||||
../../src/plugins/qmldesigner/components/navigator \
|
||||
../../src/plugins/scxmleditor/common/images \
|
||||
../../src/plugins/texteditor/images
|
||||
../../src/plugins/texteditor/images \
|
||||
../../src/plugins/valgrind/images
|
||||
|
||||
exampledirs = ../examples
|
||||
examples.fileextensions += *.qml *.svg
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -149,13 +149,17 @@
|
||||
|
||||
You can use the Callgrind tool included in the
|
||||
\l{http://valgrind.org/info/tools.html}{Valgrind tool suite} to detect
|
||||
problems that are related to executing functions.
|
||||
problems that are related to executing functions. In addition, you
|
||||
can load the data files generated by Callgrind into the
|
||||
\l{https://kcachegrind.github.io/html/Home.html}{KCachegrind}
|
||||
profile data visualization tool for browsing the performance results.
|
||||
|
||||
After you download and install Valgrind tools, you can use Callgrind from
|
||||
\QC.
|
||||
After you download and install Valgrind tools and KCachegrind, you can use
|
||||
Callgrind and KCachegrind from \QC.
|
||||
|
||||
\note You can install and run Callgrind locally on Linux. You can run
|
||||
it on a remote Linux machine or device from any development machine.
|
||||
\note You can install and run Callgrind and KCachegrind locally on Linux.
|
||||
You can run Callgrind on a remote Linux machine or device from any
|
||||
development machine.
|
||||
|
||||
To analyze applications:
|
||||
|
||||
@@ -207,6 +211,10 @@
|
||||
|
||||
\image qtcreator-valgrind-callgrind.png "Profile view"
|
||||
|
||||
To view the data in KCachegrind, select the \inlineimage kcachegrind.png
|
||||
(\uicontrol {Open Results in KCachegrind}) button on the toolbar. \QC
|
||||
launches KCachegrind and loads the data into it for visualization.
|
||||
|
||||
\section1 Selecting Profiling Options
|
||||
|
||||
You can specify analyzer settings either globally for all projects or
|
||||
@@ -218,6 +226,9 @@
|
||||
|
||||
\image qtcreator-valgrind-callgrind-options.png "Valgrind options"
|
||||
|
||||
In the \uicontrol {KCachegrind executable} field, enter the path to the
|
||||
KCachegrind executable to launch.
|
||||
|
||||
In the \uicontrol {Result view: Minimum event cost}
|
||||
field, limit the amount of results the profiler gives you to increase
|
||||
profiler performance.
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
\section2 Automatic Formatting and Indentation
|
||||
|
||||
The experimental Clang Format plugin uses the
|
||||
The Clang Format plugin uses the
|
||||
\l{https://clang.llvm.org/docs/LibFormat.html}{LibFormat}
|
||||
library for automatic formatting and indentation.
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
\list
|
||||
\li Clang code model (globally or at project level)
|
||||
\li Clang tools (globally or at project level)
|
||||
\li \l{Using Clang Tools}{Clang tools} (globally or at project level)
|
||||
\endlist
|
||||
|
||||
\section1 Configuring Clang Code Model
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -97,6 +97,6 @@
|
||||
retrieve the code snippet by selecting \uicontrol Tools >
|
||||
\uicontrol {Code Pasting} > \uicontrol {Fetch Snippet}. If they have the
|
||||
project currently opened in \QC, they can apply and test the change by
|
||||
choosing \uicontrol Tools > \uicontrol Git > \uicontrol {Patch} >
|
||||
\uicontrol {Apply from Editor}.
|
||||
choosing \uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository}
|
||||
> \uicontrol Patch > \uicontrol {Apply from Editor}.
|
||||
*/
|
||||
|
||||
@@ -145,6 +145,9 @@
|
||||
\li To hide source files which are automatically generated by the build
|
||||
system, select \uicontrol {Filter Tree > Hide Generated Files}.
|
||||
|
||||
\li To hide directories that do not contain any files, select
|
||||
\uicontrol {Filter Tree} > \uicontrol {Hide Empty Directories}.
|
||||
|
||||
\li To stop synchronizing the position in the project tree with the file
|
||||
currently opened in the editor, deselect \inlineimage linkicon.png
|
||||
(\uicontrol {Synchronize with Editor}). You can specify a keyboard
|
||||
@@ -190,7 +193,8 @@
|
||||
|
||||
For managing files and directories, the same functions are available as in
|
||||
the \uicontrol {File System} view. In addition, you can remove and rename
|
||||
files.
|
||||
files, as well as compare the selected file with the currently open file
|
||||
in the diff editor. For more information, see \l{Comparing Files}.
|
||||
|
||||
//! [projects view]
|
||||
|
||||
|
||||
@@ -124,10 +124,11 @@
|
||||
|
||||
For more information, see \l{Defining Color Schemes}.
|
||||
|
||||
Generic highlighting is based on highlight definition files that are
|
||||
provided by the
|
||||
\l{http://kate-editor.org/2005/03/24/writing-a-syntax-highlighting-file/}
|
||||
{Kate Editor}. You can download highlight definition files for use with \QC.
|
||||
Generic highlighting is provided by
|
||||
\l{https://api.kde.org/frameworks/syntax-highlighting/html/index.html}
|
||||
{KSyntaxHighlighting}, which is the syntax highlighting engine for Kate
|
||||
syntax definitions. \QC comes with most of the commonly used syntax files,
|
||||
and you can download additional files.
|
||||
|
||||
To download and use highlight definition files, select \uicontrol Tools >
|
||||
\uicontrol Options > \uicontrol {Text Editor} > \uicontrol {Generic Highlighter}.
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
languages as code, not just as plain text. This enables it to
|
||||
provide you with useful features, such as semantic highlighting,
|
||||
checking code syntax, code completion, and refactoring actions.
|
||||
In addition, the experimental language server plugin provides
|
||||
some of these services for other programming languages, such as
|
||||
Python, for which a \e {language server} is available that
|
||||
provides information about the code to IDEs.
|
||||
For more information, see \l{Coding}.
|
||||
\row
|
||||
\li \inlineimage creator_buildingrunning.png
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
\endlist
|
||||
|
||||
\li \macos 10.11 or later with the following:
|
||||
\li \macos 10.12 or later with the following:
|
||||
|
||||
\list
|
||||
|
||||
@@ -117,9 +117,9 @@
|
||||
Either Windows 7 or later or Ubuntu Linux 64-bit 12.04 LTS or later is
|
||||
required to install and use Qt for Device Creation. For more information
|
||||
about the requirements for the development host, see the
|
||||
\l{http://doc.qt.io/QtForDeviceCreation/qtee-installation-guide.html}
|
||||
{Installation Guide} in the
|
||||
\l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
|
||||
\l{https://doc.qt.io/QtForDeviceCreation/b2qt-installation-guides.html}
|
||||
{Installation Guides} in the
|
||||
\l{https://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
|
||||
documentation.
|
||||
|
||||
\section1 Compiling from Source
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -56,9 +56,13 @@
|
||||
hardware.
|
||||
|
||||
For more information about the supported device groups and reference devices,
|
||||
see \l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
|
||||
{Supported Platforms} in the \l{http://doc.qt.io/QtForDeviceCreation/index.html}
|
||||
{Qt for Device Creation} documentation.
|
||||
see \l{https://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
|
||||
{Reference Target Devices and Development Hosts} in the
|
||||
\l{https://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
|
||||
documentation.
|
||||
|
||||
\note Since \QC 4.9, only Boot to Qt version 5.9 and later are supported.
|
||||
To develop for earlier Boot to Qt versions, use \QC 4.8.
|
||||
|
||||
\section2 Mobile Devices
|
||||
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
\li Clang is a C, C++, Objective C, and Objective C++ front-end for the
|
||||
LLVM compiler for Windows, Linux, and \macos.
|
||||
|
||||
\li \l{https://clang.llvm.org/docs/UsersManual.html#clang-cl}{clang-cl}
|
||||
is an alternative command-line interface to Clang that is compatible
|
||||
with the Visual C++ compiler, \c cl.exe.
|
||||
|
||||
\li Nim is the Nim Compiler for Windows, Linux, and \macos.
|
||||
|
||||
\li QCC is the interface for compiling C++ applications for QNX.
|
||||
@@ -76,6 +80,12 @@
|
||||
versions. You can also create a custom ABI definition.
|
||||
For QCC, also specify the path to the QNX Software Development Platform (SDP).
|
||||
|
||||
To enable Microsoft Visual C++ Compilers (MSVC) and clang-cl to find system
|
||||
headers, libraries, and the linker, \QC executes them inside a command
|
||||
prompt where the environment has been set up using \c {vcvarsall.bat}. For
|
||||
these compilers, you also specify the path to the script that sets up the
|
||||
command prompt.
|
||||
|
||||
You specify the compiler to use for each kit in \uicontrol Tools >
|
||||
\uicontrol Options > \uicontrol Kits.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -86,4 +86,8 @@
|
||||
the shell or the device. Usually, you can leave this field empty.
|
||||
|
||||
\endlist
|
||||
|
||||
To remove the selected manually added debugger, select \uicontrol Remove.
|
||||
The debugger is removed from the list when you select \uicontrol Apply.
|
||||
Until then, you can cancel the deletion by clicking \uicontrol Restore.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -58,6 +58,10 @@
|
||||
select the \uicontrol Options link, or select \uicontrol Tools >
|
||||
\uicontrol Options > \uicontrol Kits.
|
||||
|
||||
Qt for Python projects rely on the \l{Using Language Servers}
|
||||
{experimental language server client} for code completion,
|
||||
highlighting, and other useful features.
|
||||
|
||||
If \QC cannot find an existing build for a particular \l{glossary-buildandrun-kit}{kit},
|
||||
it starts out
|
||||
from a clean slate, and creates new debug and release build configurations
|
||||
@@ -79,8 +83,8 @@
|
||||
\li Select \uicontrol File > \uicontrol {Open File or Project}
|
||||
(\key Ctrl+O or \key Cmd+O on \macos) and select the project file
|
||||
for the project to open: \e {.pro} (qmake), \e {CMakeLists.txt}
|
||||
(CMake), \e {.qbs} (Qbs), or \e {Makefile.am} (Autotools,
|
||||
experimental).
|
||||
(CMake), \e {.qbs} (Qbs), \e {pyproject} (Python), or
|
||||
\e {Makefile.am} (Autotools, experimental).
|
||||
|
||||
\li In the \uicontrol {Configure Project} tab, select kits for building and running your
|
||||
project, and click \uicontrol {Configure Project}.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -48,6 +48,16 @@
|
||||
switch between them. In addition, you can import and export code style
|
||||
settings.
|
||||
|
||||
\image qtcreator-projects-code-style.png "Code Style settings in Projects mode"
|
||||
|
||||
Alternatively, you can enable the Clang Format plugin to enforce
|
||||
the code style specified in a \c {.clang-format} file. It uses the
|
||||
\l{https://clang.llvm.org/docs/LibFormat.html}{LibFormat} library for
|
||||
automatic code formatting and indentation. For more information, see
|
||||
\l {Automatic Formatting and Indentation}.
|
||||
|
||||
\image qtcreator-code-style-clang-format.png "Clang Format Code Style settings in Projects mode"
|
||||
|
||||
To specify global code style settings sets for C++ files, select
|
||||
\uicontrol {Tools > Options > C++}.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -117,4 +117,6 @@
|
||||
\image qmldesigner-run-custom-exe.png "Run settings for custom executables"
|
||||
|
||||
\include qtquick/creator-projects-settings-run-qtquick.qdocinc run settings qt quick ui
|
||||
\include python/creator-python-run.qdocinc run settings python
|
||||
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -53,6 +53,10 @@
|
||||
|
||||
\li Bare Metal Device
|
||||
|
||||
\li Boot2Qt Device (commercial only)
|
||||
|
||||
\li \l {Emulator}{Boot2Qt Emulator Device} (commercial only)
|
||||
|
||||
\li Generic Linux Device
|
||||
|
||||
\li iOS Device
|
||||
@@ -61,6 +65,12 @@
|
||||
|
||||
\li QNX Device
|
||||
|
||||
\li Windows Phone
|
||||
|
||||
\li Windows Phone Emulator
|
||||
|
||||
\li Windows Runtime (local)
|
||||
|
||||
\endlist
|
||||
|
||||
To add kits:
|
||||
@@ -95,6 +105,9 @@
|
||||
|
||||
\li In the \uicontrol Device field, select a device.
|
||||
|
||||
\li In the \uicontrol {Emulator skin} field, select the skin to use for
|
||||
the \l {Emulator}{Boot2Qt Emulator Device}.
|
||||
|
||||
\li In the \uicontrol Sysroot field, specify the directory where the device
|
||||
image is located. If you are not cross-compiling, leave this field
|
||||
empty.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -85,5 +85,6 @@
|
||||
|
||||
\if defined(qtcreator)
|
||||
\include qnx/creator-projects-running-qnx.qdocinc running on qnx
|
||||
\include python/creator-python-run.qdocinc running python
|
||||
\endif
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
//! [running python]
|
||||
\section1 Running Python Projects
|
||||
|
||||
You can execute Qt for Python applications directly from \QC. If you
|
||||
used the \l{Creating Qt for Python Applications}{new project wizard}
|
||||
to create the application project, the \c main.py file is automatically
|
||||
executed when you select the \uicontrol Run button.
|
||||
|
||||
You can specify another file to execute in the
|
||||
\l{Specifying Run Settings for Python Projects}{run settings}
|
||||
of the project.
|
||||
|
||||
//! [running python]
|
||||
|
||||
|
||||
//! [run settings python]
|
||||
|
||||
\section1 Specifying Run Settings for Python Projects
|
||||
|
||||
You can specify settings for running Qt for Python applications:
|
||||
|
||||
\image qtcreator-python-run-settings.png
|
||||
|
||||
\list
|
||||
\li In the \uicontrol Interpreter field, specify the path to the
|
||||
Python executable.
|
||||
\li In the \uicontrol Script field, you can see the path to the
|
||||
main file of the project that will be run.
|
||||
\li In the \uicontrol {Command line arguments} field, specify
|
||||
command line arguments to be passed to the executable.
|
||||
\endlist
|
||||
|
||||
If you want to run some other Python file than \c main.py, create a custom
|
||||
executable run configuration:
|
||||
|
||||
\image qtcreator-python-run-settings-custom-executable.png
|
||||
|
||||
\list 1
|
||||
\li Select \uicontrol Add > \uicontrol {Custom Executable}.
|
||||
\li In the \uicontrol Executable field, specify the path to the
|
||||
Python executable.
|
||||
\li In the \uicontrol {Command line arguments} field, select
|
||||
the Python file to run.
|
||||
\endlist
|
||||
|
||||
//! [run settings python]
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -212,6 +212,11 @@
|
||||
|
||||
To zoom into an event range, double-click it.
|
||||
|
||||
To narrow down the current range in the \uicontrol Timeline,
|
||||
\uicontrol Statistics, and \uicontrol {Flame Graph} views, right-click
|
||||
the range and select \uicontrol {Analyze Current Range}. To return to
|
||||
the full range, select \uicontrol {Analyze Full Range} in the context menu.
|
||||
|
||||
To remove an event range, close the \uicontrol Selection dialog.
|
||||
|
||||
\section2 Understanding the Data
|
||||
@@ -556,10 +561,9 @@
|
||||
|
||||
Click on an event to move to it in the source code in the code editor.
|
||||
|
||||
When you select an event in the \uicontrol Timeline view, information about it is
|
||||
displayed in the \uicontrol Statistics view. To view an event range in the
|
||||
\uicontrol Statistics view, select \uicontrol {Analyze Current Range}
|
||||
in the context menu in the \uicontrol Timeline view.
|
||||
When you select an event in the \uicontrol Timeline view, information about
|
||||
it is displayed in the \uicontrol Statistics and \uicontrol {Flame Graph}
|
||||
views.
|
||||
|
||||
To copy the contents of one view or row to the clipboard, select
|
||||
\uicontrol {Copy Table} or \uicontrol {Copy Row} in the context menu.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -41,9 +41,16 @@
|
||||
|
||||
In addition to the standard version control system functions described in
|
||||
\l {Using Common Functions}, you can select \uicontrol Tools >
|
||||
\uicontrol CVS > \uicontrol Edit to open a file for editing.
|
||||
\uicontrol CVS > \uicontrol Edit to set a file as writable, notify
|
||||
watchers that the file is being edited, and watch for actions performed
|
||||
on the file by other users.
|
||||
|
||||
To discard the changes that you made in a file, select \uicontrol Unedit.
|
||||
To discard the changes that you made in a file, notify watchers that
|
||||
the file is no longer being edited, and set the file as read-only,
|
||||
select \uicontrol Unedit.
|
||||
|
||||
To unedit files in the local directory, as well as recursively in all
|
||||
subdirectories, select \uicontrol {Unedit Repository}.
|
||||
|
||||
To specify the CVS root directory, select \uicontrol Tools >
|
||||
\uicontrol Options > \uicontrol {Version Control} > \uicontrol CVS, and then
|
||||
|
||||
@@ -72,6 +72,11 @@
|
||||
\li \l{Using Perforce}{Perforce}
|
||||
\li \l{http://www.perforce.com}
|
||||
\li Server version 2006.1 and later
|
||||
|
||||
Disabled by default. To enable the plugin, select
|
||||
\uicontrol Help > \uicontrol {About Plugins} >
|
||||
\uicontrol {Version Control} > \uicontrol Perforce,
|
||||
and then restart \QC.
|
||||
\row
|
||||
\li \l{Using Subversion}{Subversion}
|
||||
\li \l{http://subversion.apache.org/}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"QtCharts 2.3",
|
||||
"QtDataVisualization 1.0",
|
||||
"QtDataVisualization 1.3",
|
||||
"QtGamePad 1.12",
|
||||
"QtGamepad 1.12",
|
||||
"QtGraphicalEffects 1.0",
|
||||
"QtMultimedia 5.0",
|
||||
"QtMultimedia 5.2",
|
||||
|
||||
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 490 B After Width: | Height: | Size: 311 B |
@@ -80,7 +80,6 @@
|
||||
"name": "QtVersion",
|
||||
"trDisplayName": "Minimal required Qt version:",
|
||||
"type": "ComboBox",
|
||||
"visible": false,
|
||||
"data":
|
||||
{
|
||||
"index": 1,
|
||||
|
||||
@@ -41,6 +41,7 @@ DoubleTabWidget2ndTabInactiveTextColor=ff000000
|
||||
EditorPlaceholderColor=ffe0dcd8
|
||||
FancyToolBarSeparatorColor=60ffffff
|
||||
FancyTabBarBackgroundColor=ffff0000
|
||||
FancyTabBarSelectedBackgroundColor=ffff0000
|
||||
FancyTabWidgetDisabledSelectedTextColor=textDisabled
|
||||
FancyTabWidgetDisabledUnselectedTextColor=textDisabled
|
||||
FancyTabWidgetEnabledSelectedTextColor=ff3c3c3c
|
||||
|
||||
@@ -18536,11 +18536,11 @@ Gibt an, wie sich die Rücktaste bezüglich Einrückung verhält.
|
||||
</message>
|
||||
<message>
|
||||
<source>Show help tooltips using keyboard shortcut (Alt)</source>
|
||||
<translation>Zeige Tooltips mit Hilfe unter Verwendung des Tastaturkürzels (Alt-Taste)</translation>
|
||||
<translation>Hilfe-Tooltips mit der Tastatur aufrufen (Alt-Taste)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show help tooltips using the mouse:</source>
|
||||
<translation>Zeige Tooltips mit Hilfe unter Verwendung der Maus:</translation>
|
||||
<translation>Hilfe-Tooltips mit der Maus aufrufen:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cleans whitespace in entire document instead of only for changed parts.</source>
|
||||
|
||||
@@ -921,12 +921,11 @@ protected:
|
||||
|
||||
bool visit(PatternElement *ast) override
|
||||
{
|
||||
if (!ast->isVariableDeclaration())
|
||||
return false;
|
||||
|
||||
out(ast->identifierToken);
|
||||
if (ast->initializer) {
|
||||
out(" = ");
|
||||
if (ast->isVariableDeclaration())
|
||||
out(" = ");
|
||||
accept(ast->initializer);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -232,7 +232,7 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
|
||||
} else if (name == QLatin1String("exports")) {
|
||||
readExports(script, fmo);
|
||||
} else if (name == QLatin1String("exportMetaObjectRevisions")) {
|
||||
//readMetaObjectRevisions(script, fmo);
|
||||
readMetaObjectRevisions(script, fmo);
|
||||
} else if (name == QLatin1String("attachedType")) {
|
||||
fmo->setAttachedTypeName(readStringBinding(script));
|
||||
} else if (name == QLatin1String("isSingleton")) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "progressindicator.h"
|
||||
#include "treemodel.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDebug>
|
||||
@@ -39,6 +40,7 @@
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QSettings>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Utils {
|
||||
@@ -596,11 +598,23 @@ ItemViewEvent::ItemViewEvent(QEvent *ev, QAbstractItemView *view)
|
||||
m_selectedRows.append(current);
|
||||
}
|
||||
}
|
||||
|
||||
auto fixIndex = [view](QModelIndex idx) {
|
||||
QAbstractItemModel *model = view->model();
|
||||
while (auto proxy = qobject_cast<QSortFilterProxyModel *>(model)) {
|
||||
idx = proxy->mapToSource(idx);
|
||||
model = proxy->sourceModel();
|
||||
}
|
||||
return idx;
|
||||
};
|
||||
|
||||
m_sourceModelIndex = fixIndex(m_index);
|
||||
m_selectedRows = Utils::transform(m_selectedRows, fixIndex);
|
||||
}
|
||||
|
||||
QModelIndexList ItemViewEvent::currentOrSelectedRows() const
|
||||
{
|
||||
return m_selectedRows.isEmpty() ? QModelIndexList() << m_index : m_selectedRows;
|
||||
return m_selectedRows.isEmpty() ? QModelIndexList() << m_sourceModelIndex : m_selectedRows;
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
@@ -135,6 +135,7 @@ public:
|
||||
QPoint pos() const { return m_pos; }
|
||||
QPoint globalPos() const { return m_view->mapToGlobal(m_pos); }
|
||||
QModelIndex index() const { return m_index; }
|
||||
QModelIndex sourceModelIndex() const { return m_sourceModelIndex; }
|
||||
QModelIndexList selectedRows() const { return m_selectedRows; }
|
||||
QModelIndexList currentOrSelectedRows() const;
|
||||
|
||||
@@ -143,6 +144,7 @@ private:
|
||||
QWidget *m_view = nullptr;
|
||||
QPoint m_pos;
|
||||
QModelIndex m_index;
|
||||
QModelIndex m_sourceModelIndex;
|
||||
QModelIndexList m_selectedRows;
|
||||
};
|
||||
|
||||
|
||||
@@ -523,6 +523,21 @@ bool FancyMainWindow::autoHideTitleBars() const
|
||||
return d->m_autoHideTitleBars.isChecked();
|
||||
}
|
||||
|
||||
void FancyMainWindow::setAutoHideTitleBars(bool on)
|
||||
{
|
||||
d->m_autoHideTitleBars.setChecked(on);
|
||||
}
|
||||
|
||||
bool FancyMainWindow::isCentralWidgetShown() const
|
||||
{
|
||||
return d->m_showCentralWidget.isChecked();
|
||||
}
|
||||
|
||||
void FancyMainWindow::showCentralWidget(bool on)
|
||||
{
|
||||
d->m_showCentralWidget.setChecked(on);
|
||||
}
|
||||
|
||||
void FancyMainWindow::addDockActionsToMenu(QMenu *menu)
|
||||
{
|
||||
QList<QAction *> actions;
|
||||
|
||||
@@ -66,6 +66,10 @@ public:
|
||||
void addDockActionsToMenu(QMenu *menu);
|
||||
|
||||
bool autoHideTitleBars() const;
|
||||
void setAutoHideTitleBars(bool on);
|
||||
|
||||
bool isCentralWidgetShown() const;
|
||||
void showCentralWidget(bool on);
|
||||
|
||||
signals:
|
||||
// Emitted by resetLayoutAction(). Connect to a slot
|
||||
|
||||
@@ -86,7 +86,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLin
|
||||
m_description = line;
|
||||
if (m_iteration > 1)
|
||||
m_description.append(' ' + tr("(iteration %1)").arg(m_iteration));
|
||||
TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
|
||||
TestResultPtr testResult = TestResultPtr(new GTestResult(id(), m_projectFile, QString()));
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(m_description);
|
||||
reportResult(testResult);
|
||||
|
||||
@@ -72,7 +72,7 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
|
||||
if (m_testSetName == gtOther->m_testSetName) {
|
||||
const Result::Type otherResult = other->result();
|
||||
if (otherResult == Result::MessageInternal || otherResult == Result::MessageLocation)
|
||||
return result() != Result::MessageLocation;
|
||||
return result() != Result::MessageInternal && result() != Result::MessageLocation;
|
||||
}
|
||||
if (m_iteration != gtOther->m_iteration)
|
||||
return false;
|
||||
|
||||
@@ -47,6 +47,7 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
|
||||
|
||||
// This is a separate pass, don't do it unless it's the full formatting.
|
||||
style.FixNamespaceComments = false;
|
||||
style.AlignTrailingComments = false;
|
||||
|
||||
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
|
||||
return;
|
||||
@@ -118,13 +119,11 @@ void trimRHSWhitespace(const QTextBlock &block)
|
||||
const int extraSpaceCount = static_cast<int>(std::distance(initialText.rbegin(), lastNonSpace));
|
||||
|
||||
QTextCursor cursor(block);
|
||||
cursor.beginEditBlock();
|
||||
cursor.movePosition(QTextCursor::Right,
|
||||
QTextCursor::MoveAnchor,
|
||||
initialText.size() - extraSpaceCount);
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, extraSpaceCount);
|
||||
cursor.removeSelectedText();
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
|
||||
QTextBlock reverseFindLastEmptyBlock(QTextBlock start)
|
||||
@@ -139,7 +138,13 @@ QTextBlock reverseFindLastEmptyBlock(QTextBlock start)
|
||||
return start;
|
||||
}
|
||||
|
||||
enum class CharacterContext { AfterComma, LastAfterComma, NewStatement, Continuation, Unknown };
|
||||
enum class CharacterContext {
|
||||
AfterComma,
|
||||
LastAfterComma,
|
||||
NewStatementOrContinuation,
|
||||
IfOrElseWithoutScope,
|
||||
Unknown
|
||||
};
|
||||
|
||||
QChar findFirstNonWhitespaceCharacter(const QTextBlock ¤tBlock)
|
||||
{
|
||||
@@ -150,10 +155,42 @@ QChar findFirstNonWhitespaceCharacter(const QTextBlock ¤tBlock)
|
||||
return currentPos < doc->characterCount() ? doc->characterAt(currentPos) : QChar::Null;
|
||||
}
|
||||
|
||||
int findMatchingOpeningParen(const QTextBlock &blockEndingWithClosingParen)
|
||||
{
|
||||
const QTextDocument *doc = blockEndingWithClosingParen.document();
|
||||
int currentPos = blockEndingWithClosingParen.position()
|
||||
+ blockEndingWithClosingParen.text().lastIndexOf(')');
|
||||
int parenBalance = 1;
|
||||
|
||||
while (currentPos > 0 && parenBalance > 0) {
|
||||
--currentPos;
|
||||
if (doc->characterAt(currentPos) == ')')
|
||||
++parenBalance;
|
||||
if (doc->characterAt(currentPos) == '(')
|
||||
--parenBalance;
|
||||
}
|
||||
|
||||
if (parenBalance == 0)
|
||||
return currentPos;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool comesDirectlyAfterIf(const QTextDocument *doc, int pos)
|
||||
{
|
||||
--pos;
|
||||
while (pos > 0 && doc->characterAt(pos).isSpace())
|
||||
--pos;
|
||||
return pos > 0 && doc->characterAt(pos) == 'f' && doc->characterAt(pos - 1) == 'i';
|
||||
}
|
||||
|
||||
CharacterContext characterContext(const QTextBlock ¤tBlock,
|
||||
const QTextBlock &previousNonEmptyBlock)
|
||||
{
|
||||
const QString prevLineText = previousNonEmptyBlock.text().trimmed();
|
||||
if (prevLineText.isEmpty())
|
||||
return CharacterContext::NewStatementOrContinuation;
|
||||
|
||||
const QChar firstNonWhitespaceChar = findFirstNonWhitespaceCharacter(currentBlock);
|
||||
if (prevLineText.endsWith(',')) {
|
||||
// We don't need to add comma in case it's the last argument.
|
||||
@@ -162,12 +199,15 @@ CharacterContext characterContext(const QTextBlock ¤tBlock,
|
||||
return CharacterContext::AfterComma;
|
||||
}
|
||||
|
||||
if (prevLineText.endsWith(';') || prevLineText.endsWith('{') || prevLineText.endsWith('}')
|
||||
|| firstNonWhitespaceChar == QChar::Null) {
|
||||
return CharacterContext::NewStatement;
|
||||
if (prevLineText.endsWith("else"))
|
||||
return CharacterContext::IfOrElseWithoutScope;
|
||||
if (prevLineText.endsWith(')')) {
|
||||
const int pos = findMatchingOpeningParen(previousNonEmptyBlock);
|
||||
if (pos >= 0 && comesDirectlyAfterIf(previousNonEmptyBlock.document(), pos))
|
||||
return CharacterContext::IfOrElseWithoutScope;
|
||||
}
|
||||
|
||||
return CharacterContext::Continuation;
|
||||
return CharacterContext::NewStatementOrContinuation;
|
||||
}
|
||||
|
||||
bool nextBlockExistsAndEmpty(const QTextBlock ¤tBlock)
|
||||
@@ -181,20 +221,18 @@ bool nextBlockExistsAndEmpty(const QTextBlock ¤tBlock)
|
||||
|
||||
QByteArray dummyTextForContext(CharacterContext context, bool closingBraceBlock)
|
||||
{
|
||||
if (closingBraceBlock
|
||||
&& (context == CharacterContext::NewStatement
|
||||
|| context == CharacterContext::Continuation)) {
|
||||
if (closingBraceBlock && context == CharacterContext::NewStatementOrContinuation)
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
switch (context) {
|
||||
case CharacterContext::AfterComma:
|
||||
return "a,";
|
||||
case CharacterContext::NewStatement:
|
||||
return "a;";
|
||||
case CharacterContext::Continuation:
|
||||
case CharacterContext::LastAfterComma:
|
||||
return "& a &";
|
||||
return "a";
|
||||
case CharacterContext::IfOrElseWithoutScope:
|
||||
return ";";
|
||||
case CharacterContext::NewStatementOrContinuation:
|
||||
return "/**/";
|
||||
case CharacterContext::Unknown:
|
||||
default:
|
||||
QTC_ASSERT(false, return "";);
|
||||
@@ -202,7 +240,7 @@ QByteArray dummyTextForContext(CharacterContext context, bool closingBraceBlock)
|
||||
}
|
||||
|
||||
// Add extra text in case of the empty line or the line starting with ')'.
|
||||
// Track such extra pieces of text in isInsideModifiedLine().
|
||||
// Track such extra pieces of text in isInsideDummyTextInLine().
|
||||
int forceIndentWithExtraText(QByteArray &buffer,
|
||||
CharacterContext &charContext,
|
||||
const QTextBlock &block,
|
||||
@@ -265,7 +303,7 @@ int forceIndentWithExtraText(QByteArray &buffer,
|
||||
return extraLength;
|
||||
}
|
||||
|
||||
bool isInsideModifiedLine(const QString &originalLine, const QString &modifiedLine, int column)
|
||||
bool isInsideDummyTextInLine(const QString &originalLine, const QString &modifiedLine, int column)
|
||||
{
|
||||
// Detect the cases when we have inserted extra text into the line to get the indentation.
|
||||
return originalLine.length() < modifiedLine.length() && column != modifiedLine.length() + 1
|
||||
@@ -291,7 +329,7 @@ TextEditor::Replacements utf16Replacements(const QTextDocument *doc,
|
||||
const QString bufferLineText
|
||||
= Utils::Text::utf16LineTextInUtf8Buffer(utf8Buffer,
|
||||
static_cast<int>(replacement.getOffset()));
|
||||
if (isInsideModifiedLine(lineText, bufferLineText, lineColUtf16.column))
|
||||
if (isInsideDummyTextInLine(lineText, bufferLineText, lineColUtf16.column))
|
||||
continue;
|
||||
|
||||
lineColUtf16.column = std::min(lineColUtf16.column, lineText.length() + 1);
|
||||
@@ -319,14 +357,12 @@ void applyReplacements(QTextDocument *doc, const TextEditor::Replacements &repla
|
||||
int fullOffsetShift = 0;
|
||||
QTextCursor editCursor(doc);
|
||||
for (const TextEditor::Replacement &replacement : replacements) {
|
||||
editCursor.beginEditBlock();
|
||||
editCursor.setPosition(replacement.offset + fullOffsetShift);
|
||||
editCursor.movePosition(QTextCursor::NextCharacter,
|
||||
QTextCursor::KeepAnchor,
|
||||
replacement.length);
|
||||
editCursor.removeSelectedText();
|
||||
editCursor.insertText(replacement.text);
|
||||
editCursor.endEditBlock();
|
||||
fullOffsetShift += replacement.text.length() - replacement.length;
|
||||
}
|
||||
}
|
||||
@@ -510,8 +546,11 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
|
||||
ranges = clang::tooling::calculateRangesAfterReplacements(clangReplacements, ranges);
|
||||
|
||||
clang::format::FormattingAttemptStatus status;
|
||||
const clang::tooling::Replacements formatReplacements
|
||||
= reformat(style, *changedCode, ranges, m_fileName.toString().toStdString(), &status);
|
||||
const clang::tooling::Replacements formatReplacements = reformat(style,
|
||||
*changedCode,
|
||||
ranges,
|
||||
assumedFileName,
|
||||
&status);
|
||||
clangReplacements = clangReplacements.merge(formatReplacements);
|
||||
|
||||
const TextEditor::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements);
|
||||
@@ -533,7 +572,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo
|
||||
|
||||
startBlock = reverseFindLastEmptyBlock(startBlock);
|
||||
const int startBlockPosition = startBlock.position();
|
||||
if (startBlock.position() > 0) {
|
||||
if (startBlockPosition > 0) {
|
||||
trimRHSWhitespace(startBlock.previous());
|
||||
if (cursorPositionInEditor >= 0)
|
||||
cursorPositionInEditor += startBlock.position() - startBlockPosition;
|
||||
@@ -548,9 +587,9 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo
|
||||
// Format before current position only in case the cursor is inside the indented block.
|
||||
// So if cursor position is less then the block position then the current line is before
|
||||
// the indented block - don't trigger extra formatting in this case.
|
||||
// cursorPositionInEditor == -1 means the consition matches automatically.
|
||||
// cursorPositionInEditor == -1 means the condition matches automatically.
|
||||
|
||||
// Format only before newline or complete statement not to break code.
|
||||
// Format only before complete statement not to break code.
|
||||
replacementsToKeep = ReplacementsToKeep::IndentAndBefore;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,11 +125,17 @@ void ClangFormatConfigWidget::initialize()
|
||||
if (lastItem->spacerItem())
|
||||
m_ui->verticalLayout->removeItem(lastItem);
|
||||
|
||||
m_ui->clangFormatOptionsTable->setEnabled(true);
|
||||
if (!m_ui->overrideDefault->isChecked()) {
|
||||
m_ui->clangFormatOptionsTable->hide();
|
||||
m_preview->hide();
|
||||
m_ui->verticalLayout->addStretch(1);
|
||||
return;
|
||||
if (m_project) {
|
||||
m_ui->clangFormatOptionsTable->hide();
|
||||
m_preview->hide();
|
||||
m_ui->verticalLayout->addStretch(1);
|
||||
return;
|
||||
} else {
|
||||
// Show the fallback configuration only globally.
|
||||
m_ui->clangFormatOptionsTable->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->clangFormatOptionsTable->show();
|
||||
@@ -145,6 +151,7 @@ void ClangFormatConfigWidget::initialize()
|
||||
if (!currentProject || !projectConfigExists()) {
|
||||
m_ui->projectHasClangFormat->hide();
|
||||
} else {
|
||||
m_ui->projectHasClangFormat->show();
|
||||
m_ui->projectHasClangFormat->setText(
|
||||
tr("Current project has its own overridden .clang-format file "
|
||||
"and can be configured in Projects > Code Style > C++."));
|
||||
@@ -189,7 +196,7 @@ void ClangFormatConfigWidget::apply()
|
||||
}
|
||||
settings.write();
|
||||
|
||||
if (!m_ui->overrideDefault->isChecked())
|
||||
if (!m_ui->clangFormatOptionsTable->isVisible())
|
||||
return;
|
||||
|
||||
const QString text = m_ui->clangFormatOptionsTable->toPlainText();
|
||||
|
||||
@@ -293,8 +293,11 @@ static QByteArray configBaseStyleName(const QString &configFile)
|
||||
static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings)
|
||||
{
|
||||
QString configFile = configForFile(fileName, checkForSettings);
|
||||
if (configFile.isEmpty())
|
||||
return constructStyle();
|
||||
if (configFile.isEmpty()) {
|
||||
// If no configuration is found create a global one (if it does not yet exist) and use it.
|
||||
createStyleFileIfNeeded(true);
|
||||
configFile = globalPath().appendPath(Constants::SETTINGS_FILE_NAME).toString();
|
||||
}
|
||||
|
||||
fileName = assumedPathForConfig(configFile);
|
||||
Expected<FormatStyle> style = format::getStyle("file",
|
||||
|
||||
@@ -215,10 +215,13 @@ void FancyTabBar::mousePressEvent(QMouseEvent *event)
|
||||
// menu arrow clicked
|
||||
emit menuTriggered(index, event);
|
||||
} else {
|
||||
m_currentIndex = index;
|
||||
update();
|
||||
// update tab bar before showing widget
|
||||
QTimer::singleShot(0, this, [this]() { emit currentChanged(m_currentIndex); });
|
||||
if (index != m_currentIndex) {
|
||||
emit currentAboutToChange(index);
|
||||
m_currentIndex = index;
|
||||
update();
|
||||
// update tab bar before showing widget
|
||||
QTimer::singleShot(0, this, [this]() { emit currentChanged(m_currentIndex); });
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -396,6 +399,7 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
|
||||
void FancyTabBar::setCurrentIndex(int index)
|
||||
{
|
||||
if (isTabEnabled(index) && index != m_currentIndex) {
|
||||
emit currentAboutToChange(index);
|
||||
m_currentIndex = index;
|
||||
update();
|
||||
emit currentChanged(m_currentIndex);
|
||||
@@ -520,6 +524,7 @@ FancyTabWidget::FancyTabWidget(QWidget *parent)
|
||||
mainLayout->addLayout(vlayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(m_tabBar, &FancyTabBar::currentAboutToChange, this, &FancyTabWidget::currentAboutToShow);
|
||||
connect(m_tabBar, &FancyTabBar::currentChanged, this, &FancyTabWidget::showWidget);
|
||||
connect(m_tabBar, &FancyTabBar::menuTriggered, this, &FancyTabWidget::menuTriggered);
|
||||
}
|
||||
@@ -598,7 +603,7 @@ void FancyTabWidget::addCornerWidget(QWidget *widget)
|
||||
|
||||
int FancyTabWidget::currentIndex() const
|
||||
{
|
||||
return m_modesStack->currentIndex();
|
||||
return m_tabBar->currentIndex();
|
||||
}
|
||||
|
||||
QStatusBar *FancyTabWidget::statusBar() const
|
||||
@@ -613,7 +618,6 @@ void FancyTabWidget::setCurrentIndex(int index)
|
||||
|
||||
void FancyTabWidget::showWidget(int index)
|
||||
{
|
||||
emit currentAboutToShow(index);
|
||||
m_modesStack->setCurrentIndex(index);
|
||||
QWidget *w = m_modesStack->currentWidget();
|
||||
if (QTC_GUARD(w)) {
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
QRect tabRect(int index) const;
|
||||
|
||||
signals:
|
||||
void currentAboutToChange(int index);
|
||||
void currentChanged(int index);
|
||||
void menuTriggered(int index, QMouseEvent *event);
|
||||
|
||||
|
||||
@@ -44,10 +44,12 @@
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
#include <texteditor/icodestylepreferencesfactory.h>
|
||||
#include <texteditor/storagesettings.h>
|
||||
#include <texteditor/textdocumentlayout.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <utils/executeondestruction.h>
|
||||
#include <utils/mimetypes/mimedatabase.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/runextensions.h>
|
||||
@@ -448,6 +450,8 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
|
||||
|
||||
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
|
||||
{
|
||||
Utils::ExecuteOnDestruction resetSettingsOnScopeExit;
|
||||
|
||||
if (indenter()->formatOnSave() && !autoSave) {
|
||||
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||
const int documentRevision = layout->lastSaveRevision;
|
||||
@@ -479,6 +483,12 @@ bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool
|
||||
indenter()->format(editedRanges);
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
|
||||
TextEditor::StorageSettings settings = storageSettings();
|
||||
resetSettingsOnScopeExit.reset(
|
||||
[this, defaultSettings = settings]() { setStorageSettings(defaultSettings); });
|
||||
settings.m_cleanWhitespace = false;
|
||||
setStorageSettings(settings);
|
||||
}
|
||||
|
||||
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
|
||||
|
||||
@@ -1661,8 +1661,8 @@ bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev)
|
||||
// Delete by file: Find indices of breakpoints of the same file.
|
||||
QList<Breakpoint> breakpointsInFile;
|
||||
QString file;
|
||||
if (Breakpoint bp = itemForIndexAtLevel<1>(ev.index())) {
|
||||
const QModelIndex index = ev.index().sibling(ev.index().row(), BreakpointFileColumn);
|
||||
if (Breakpoint bp = itemForIndexAtLevel<1>(ev.sourceModelIndex())) {
|
||||
const QModelIndex index = ev.sourceModelIndex().sibling(ev.sourceModelIndex().row(), BreakpointFileColumn);
|
||||
if (!file.isEmpty()) {
|
||||
for (int i = 0; i != rowCount(); ++i)
|
||||
if (index.data().toString() == file)
|
||||
@@ -2626,7 +2626,7 @@ bool BreakpointManager::contextMenuEvent(const ItemViewEvent &ev)
|
||||
// Delete by file: Find indices of breakpoints of the same file.
|
||||
GlobalBreakpoints breakpointsInFile;
|
||||
QString file;
|
||||
if (GlobalBreakpoint gbp = itemForIndexAtLevel<1>(ev.index())) {
|
||||
if (GlobalBreakpoint gbp = itemForIndexAtLevel<1>(ev.sourceModelIndex())) {
|
||||
if (!file.isEmpty()) {
|
||||
for (int i = 0; i != rowCount(); ++i)
|
||||
if (gbp->markerFileName() == file)
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <coreplugin/messagebox.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <coreplugin/progressmanager/futureprogress.h>
|
||||
|
||||
@@ -280,12 +281,16 @@ public:
|
||||
m_disassemblerAgent(engine),
|
||||
m_toolTipManager(engine)
|
||||
{
|
||||
m_logWindow = new LogWindow(m_engine); // Needed before start()
|
||||
m_logWindow->setObjectName(DOCKWIDGET_OUTPUT);
|
||||
m_debuggerName = DebuggerEngine::tr("Debugger");
|
||||
|
||||
connect(action(EnableReverseDebugging), &SavedAction::valueChanged,
|
||||
this, [this] { updateState(true); });
|
||||
m_logWindow = new LogWindow(m_engine); // Needed before start()
|
||||
m_logWindow->setObjectName("Debugger.Dock.Output");
|
||||
|
||||
connect(action(EnableReverseDebugging), &SavedAction::valueChanged, this, [this] {
|
||||
updateState();
|
||||
if (m_companionEngine)
|
||||
m_companionEngine->d->updateState();
|
||||
});
|
||||
static int contextCount = 0;
|
||||
m_context = Context(Id("Debugger.Engine.").withSuffix(++contextCount));
|
||||
|
||||
@@ -370,17 +375,15 @@ public:
|
||||
if (!m_perspective)
|
||||
return;
|
||||
|
||||
delete m_perspective;
|
||||
Perspective *perspective = m_perspective;
|
||||
m_perspective = nullptr;
|
||||
|
||||
EngineManager::unregisterEngine(m_engine);
|
||||
|
||||
// Give up ownership on claimed breakpoints.
|
||||
m_breakHandler.releaseAllBreakpoints();
|
||||
m_toolTipManager.deregisterEngine();
|
||||
m_memoryAgents.handleDebuggerFinished();
|
||||
|
||||
setBusyCursor(false);
|
||||
// This triggers activity in the EngineManager which
|
||||
// recognizes the rampdown by the m_perpective == nullptr above.
|
||||
perspective->destroy();
|
||||
delete perspective;
|
||||
}
|
||||
|
||||
void updateReturnViewHeader(int section, int, int newSize)
|
||||
@@ -446,13 +449,13 @@ public:
|
||||
void setInitialActionStates();
|
||||
void setBusyCursor(bool on);
|
||||
void cleanupViews();
|
||||
void updateState(bool alsoUpdateCompanion);
|
||||
void updateState();
|
||||
void updateReverseActions();
|
||||
|
||||
DebuggerEngine *m_engine = nullptr; // Not owned.
|
||||
QString m_runId;
|
||||
QString m_debuggerName;
|
||||
Perspective *m_perspective = nullptr;
|
||||
QPointer<Perspective> m_perspective;
|
||||
DebuggerRunParameters m_runParameters;
|
||||
IDevice::ConstPtr m_device;
|
||||
|
||||
@@ -550,16 +553,17 @@ public:
|
||||
void DebuggerEnginePrivate::setupViews()
|
||||
{
|
||||
const DebuggerRunParameters &rp = m_runParameters;
|
||||
const QString engineId = EngineManager::registerEngine(m_engine);
|
||||
|
||||
QTC_CHECK(!m_perspective);
|
||||
|
||||
m_perspective = new Perspective("Debugger.Perspective." + m_runId + '.' + m_debuggerName,
|
||||
const QString perspectiveId = "Debugger.Perspective." + m_runId + '.' + m_debuggerName;
|
||||
const QString settingsId = "Debugger.Perspective." + m_debuggerName;
|
||||
|
||||
m_perspective = new Perspective(perspectiveId,
|
||||
m_engine->displayName(),
|
||||
Debugger::Constants::PRESET_PERSPECTIVE_ID,
|
||||
m_debuggerName);
|
||||
m_perspective->setShouldPersistChecker([this] {
|
||||
return EngineManager::isLastOf(m_debuggerName);
|
||||
});
|
||||
settingsId);
|
||||
|
||||
m_progress.setProgressRange(0, 1000);
|
||||
FutureProgress *fp = ProgressManager::addTask(m_progress.future(),
|
||||
@@ -627,7 +631,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_engine, &DebuggerEngine::reloadModules,
|
||||
Qt::QueuedConnection);
|
||||
m_modulesWindow = addSearch(m_modulesView);
|
||||
m_modulesWindow->setObjectName(DOCKWIDGET_MODULES);
|
||||
m_modulesWindow->setObjectName("Debugger.Dock.Modules." + engineId);
|
||||
m_modulesWindow->setWindowTitle(tr("&Modules"));
|
||||
|
||||
m_registerView = new BaseTreeView;
|
||||
@@ -638,7 +642,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_engine, &DebuggerEngine::reloadRegisters,
|
||||
Qt::QueuedConnection);
|
||||
m_registerWindow = addSearch(m_registerView);
|
||||
m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
|
||||
m_registerWindow->setObjectName("Debugger.Dock.Register." + engineId);
|
||||
m_registerWindow->setWindowTitle(tr("Reg&isters"));
|
||||
|
||||
m_stackView = new StackTreeView;
|
||||
@@ -646,7 +650,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_stackView->setSettings(settings, "Debugger.StackView");
|
||||
m_stackView->setIconSize(QSize(10, 10));
|
||||
m_stackWindow = addSearch(m_stackView);
|
||||
m_stackWindow->setObjectName(DOCKWIDGET_STACK);
|
||||
m_stackWindow->setObjectName("Debugger.Dock.Stack." + engineId);
|
||||
m_stackWindow->setWindowTitle(tr("&Stack"));
|
||||
|
||||
m_sourceFilesView = new BaseTreeView;
|
||||
@@ -657,7 +661,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_engine, &DebuggerEngine::reloadSourceFiles,
|
||||
Qt::QueuedConnection);
|
||||
m_sourceFilesWindow = addSearch(m_sourceFilesView);
|
||||
m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES);
|
||||
m_sourceFilesWindow->setObjectName("Debugger.Dock.SourceFiles." + engineId);
|
||||
m_sourceFilesWindow->setWindowTitle(tr("Source Files"));
|
||||
|
||||
m_threadsView = new BaseTreeView;
|
||||
@@ -667,7 +671,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_threadsView->setIconSize(QSize(10, 10));
|
||||
m_threadsView->setSpanColumn(ThreadData::FunctionColumn);
|
||||
m_threadsWindow = addSearch(m_threadsView);
|
||||
m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
|
||||
m_threadsWindow->setObjectName("Debugger.Dock.Threads." + engineId);
|
||||
m_threadsWindow->setWindowTitle(tr("&Threads"));
|
||||
|
||||
m_returnView = new WatchTreeView{ReturnType};
|
||||
@@ -681,26 +685,26 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_localsView->setModel(m_watchHandler.model());
|
||||
m_localsView->setSettings(settings, "Debugger.LocalsView");
|
||||
m_localsWindow = addSearch(m_localsView);
|
||||
m_localsWindow->setObjectName("CppDebugLocals");
|
||||
m_localsWindow->setObjectName("Debugger.Dock.Locals." + engineId);
|
||||
m_localsWindow->setWindowTitle(tr("Locals"));
|
||||
|
||||
m_inspectorView = new WatchTreeView{InspectType};
|
||||
m_inspectorView->setModel(m_watchHandler.model());
|
||||
m_inspectorView->setSettings(settings, "Debugger.LocalsView"); // sic! same as locals view.
|
||||
m_inspectorWindow = addSearch(m_inspectorView);
|
||||
m_inspectorWindow->setObjectName("Inspector");
|
||||
m_inspectorWindow->setObjectName("Debugger.Dock.Inspector." + engineId);
|
||||
m_inspectorWindow->setWindowTitle(tr("Locals"));
|
||||
|
||||
m_watchersView = new WatchTreeView{WatchersType};
|
||||
m_watchersView->setModel(m_watchHandler.model());
|
||||
m_watchersView->setSettings(settings, "Debugger.WatchersView");
|
||||
m_watchersWindow = addSearch(m_watchersView);
|
||||
m_watchersWindow->setObjectName("CppDebugWatchers");
|
||||
m_watchersWindow->setObjectName("Debugger.Dock.Watchers." + engineId);
|
||||
m_watchersWindow->setWindowTitle(tr("&Expressions"));
|
||||
|
||||
m_localsAndInspectorWindow = new LocalsAndInspectorWindow(
|
||||
m_localsWindow, m_inspectorWindow, m_returnWindow);
|
||||
m_localsAndInspectorWindow->setObjectName(DOCKWIDGET_LOCALS_AND_INSPECTOR);
|
||||
m_localsAndInspectorWindow->setObjectName("Debugger.Dock.LocalsAndInspector." + engineId);
|
||||
m_localsAndInspectorWindow->setWindowTitle(m_localsWindow->windowTitle());
|
||||
|
||||
// Locals
|
||||
@@ -718,7 +722,7 @@ void DebuggerEnginePrivate::setupViews()
|
||||
m_breakView->setModel(m_breakHandler.model());
|
||||
m_breakView->setRootIsDecorated(true);
|
||||
m_breakWindow = addSearch(m_breakView);
|
||||
m_breakWindow->setObjectName(DOCKWIDGET_BREAK);
|
||||
m_breakWindow->setObjectName("Debugger.Dock.Break." + engineId);
|
||||
m_breakWindow->setWindowTitle(tr("&Breakpoints"));
|
||||
|
||||
m_perspective->useSubPerspectiveSwitcher(EngineManager::engineChooser());
|
||||
@@ -845,7 +849,6 @@ void DebuggerEnginePrivate::setupViews()
|
||||
DebuggerEngine::DebuggerEngine()
|
||||
: d(new DebuggerEnginePrivate(this))
|
||||
{
|
||||
updateState(false);
|
||||
}
|
||||
|
||||
DebuggerEngine::~DebuggerEngine()
|
||||
@@ -1018,7 +1021,6 @@ void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
|
||||
|
||||
void DebuggerEngine::start()
|
||||
{
|
||||
EngineManager::registerEngine(this);
|
||||
d->m_watchHandler.resetWatchers();
|
||||
d->setInitialActionStates();
|
||||
setState(EngineSetupRequested);
|
||||
@@ -1114,7 +1116,7 @@ void DebuggerEngine::abortDebugger()
|
||||
|
||||
void DebuggerEngine::updateUi(bool isCurrentEngine)
|
||||
{
|
||||
updateState(false);
|
||||
updateState();
|
||||
if (isCurrentEngine) {
|
||||
gotoCurrentLocation();
|
||||
} else {
|
||||
@@ -1317,7 +1319,7 @@ void DebuggerEngine::notifyInferiorSpontaneousStop()
|
||||
{
|
||||
showMessage("NOTE: INFERIOR SPONTANEOUS STOP");
|
||||
QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
|
||||
EngineManager::activateEngine(this);
|
||||
d->m_perspective->select();
|
||||
showMessage(tr("Stopped."), StatusBar);
|
||||
setState(InferiorStopOk);
|
||||
if (boolSetting(RaiseOnInterrupt))
|
||||
@@ -1384,10 +1386,12 @@ void DebuggerEnginePrivate::setInitialActionStates()
|
||||
m_threadLabel->setEnabled(false);
|
||||
}
|
||||
|
||||
void DebuggerEnginePrivate::updateState(bool alsoUpdateCompanion)
|
||||
void DebuggerEnginePrivate::updateState()
|
||||
{
|
||||
if (!m_perspective)
|
||||
// Can happen in mixed debugging.
|
||||
if (!m_threadLabel)
|
||||
return;
|
||||
QTC_ASSERT(m_threadLabel, return);
|
||||
|
||||
const DebuggerState state = m_state;
|
||||
const bool companionPreventsAction = m_engine->companionPreventsActions();
|
||||
@@ -1397,7 +1401,7 @@ void DebuggerEnginePrivate::updateState(bool alsoUpdateCompanion)
|
||||
// visible, possibly disabled.
|
||||
if (state == DebuggerNotReady) {
|
||||
// Happens when companion starts, otherwise this should not happen.
|
||||
QTC_CHECK(m_companionEngine);
|
||||
//QTC_CHECK(m_companionEngine);
|
||||
m_interruptAction.setVisible(true);
|
||||
m_interruptAction.setEnabled(false);
|
||||
m_continueAction.setVisible(false);
|
||||
@@ -1527,9 +1531,6 @@ void DebuggerEnginePrivate::updateState(bool alsoUpdateCompanion)
|
||||
|| state == DebuggerFinished
|
||||
|| state == InferiorUnrunnable;
|
||||
setBusyCursor(!notbusy);
|
||||
|
||||
if (alsoUpdateCompanion && m_companionEngine)
|
||||
m_companionEngine->updateState(false);
|
||||
}
|
||||
|
||||
void DebuggerEnginePrivate::updateReverseActions()
|
||||
@@ -1688,9 +1689,9 @@ void DebuggerEngine::notifyInferiorExited()
|
||||
d->doShutdownEngine();
|
||||
}
|
||||
|
||||
void DebuggerEngine::updateState(bool alsoUpdateCompanion)
|
||||
void DebuggerEngine::updateState()
|
||||
{
|
||||
d->updateState(alsoUpdateCompanion);
|
||||
d->updateState();
|
||||
}
|
||||
|
||||
WatchTreeView *DebuggerEngine::inspectorView()
|
||||
@@ -1791,17 +1792,28 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
|
||||
if (!forced && !isAllowedTransition(oldState, state))
|
||||
qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg;
|
||||
|
||||
if (state == EngineRunRequested)
|
||||
if (state == EngineRunRequested) {
|
||||
emit engineStarted();
|
||||
d->m_perspective->select();
|
||||
}
|
||||
|
||||
showMessage(msg, LogDebug);
|
||||
|
||||
d->updateState(true);
|
||||
d->updateState();
|
||||
if (d->m_companionEngine)
|
||||
d->m_companionEngine->d->updateState();
|
||||
|
||||
if (oldState != d->m_state)
|
||||
emit EngineManager::instance()->engineStateChanged(this);
|
||||
|
||||
if (state == DebuggerFinished) {
|
||||
d->setBusyCursor(false);
|
||||
|
||||
// Give up ownership on claimed breakpoints.
|
||||
d->m_breakHandler.releaseAllBreakpoints();
|
||||
d->m_toolTipManager.deregisterEngine();
|
||||
d->m_memoryAgents.handleDebuggerFinished();
|
||||
|
||||
d->destroyPerspective();
|
||||
emit engineFinished();
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ protected:
|
||||
void notifyInferiorStopFailed();
|
||||
|
||||
public:
|
||||
void updateState(bool alsoUpdateCompanion);
|
||||
void updateState();
|
||||
QString formatStartParameters() const;
|
||||
WatchTreeView *inspectorView();
|
||||
void updateLocalsWindow(bool showReturn);
|
||||
|
||||
@@ -28,24 +28,6 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// DebuggerMainWindow dock widget names
|
||||
const char DOCKWIDGET_BREAKPOINTMANAGER[] = "Debugger.Docks.BreakpointManager";
|
||||
const char DOCKWIDGET_ENGINEMANAGER[] = "Debugger.Docks.Snapshots";
|
||||
const char DOCKWIDGET_GLOBALLOG[] = "Debugger.Docks.GlobalLog";
|
||||
|
||||
const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break";
|
||||
const char DOCKWIDGET_MODULES[] = "Debugger.Docks.Modules";
|
||||
const char DOCKWIDGET_REGISTER[] = "Debugger.Docks.Register";
|
||||
const char DOCKWIDGET_OUTPUT[] = "Debugger.Docks.Output";
|
||||
const char DOCKWIDGET_STACK[] = "Debugger.Docks.Stack";
|
||||
const char DOCKWIDGET_SOURCE_FILES[] = "Debugger.Docks.SourceFiles";
|
||||
const char DOCKWIDGET_THREADS[] = "Debugger.Docks.Threads";
|
||||
const char DOCKWIDGET_LOCALS_AND_INSPECTOR[] = "Debugger.Docks.LocalsAndInspector";
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
|
||||
namespace Constants {
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QDockWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMenu>
|
||||
#include <QScrollArea>
|
||||
#include <QStackedWidget>
|
||||
@@ -62,37 +63,57 @@
|
||||
using namespace Debugger;
|
||||
using namespace Core;
|
||||
|
||||
Q_LOGGING_CATEGORY(perspectivesLog, "qtc.utils.perspectives", QtWarningMsg)
|
||||
|
||||
namespace Utils {
|
||||
|
||||
const int SettingsVersion = 3;
|
||||
|
||||
const char LAST_PERSPECTIVE_KEY[] = "LastPerspective";
|
||||
const char OWNED_BY_PERSPECTIVE[] = "OwnedByPerspective";
|
||||
const char MAINWINDOW_KEY[] = "Debugger.MainWindow";
|
||||
const char AUTOHIDE_TITLEBARS_KEY[] = "AutoHideTitleBars";
|
||||
const char SHOW_CENTRALWIDGET_KEY[] = "ShowCentralWidget";
|
||||
const char STATE_KEY[] = "State";
|
||||
const char CHANGED_DOCK_KEY[] = "ChangedDocks";
|
||||
|
||||
static DebuggerMainWindow *theMainWindow = nullptr;
|
||||
|
||||
class DockOperation
|
||||
{
|
||||
public:
|
||||
void setupLayout();
|
||||
QString name() const { QTC_ASSERT(widget, return QString()); return widget->objectName(); }
|
||||
|
||||
Core::Id commandId;
|
||||
QPointer<QWidget> widget;
|
||||
QString anchorDockId;
|
||||
QPointer<QDockWidget> dock;
|
||||
QPointer<QWidget> anchorWidget;
|
||||
Perspective::OperationType operationType = Perspective::Raise;
|
||||
bool visibleByDefault = true;
|
||||
bool visibleByUser = true;
|
||||
Qt::DockWidgetArea area = Qt::BottomDockWidgetArea;
|
||||
};
|
||||
|
||||
class PerspectivePrivate
|
||||
{
|
||||
public:
|
||||
void showToolBar();
|
||||
void hideToolBar();
|
||||
void showInnerToolBar();
|
||||
void hideInnerToolBar();
|
||||
void restoreLayout();
|
||||
void saveLayout();
|
||||
void resetPerspective();
|
||||
void populatePerspective();
|
||||
void depopulatePerspective();
|
||||
void saveAsLastUsedPerspective();
|
||||
Context context() const;
|
||||
|
||||
QString settingsId() const;
|
||||
QToolButton *setupToolButton(QAction *action);
|
||||
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QString m_parentPerspectiveId;
|
||||
QString m_subPerspectiveType;
|
||||
QString m_settingsId;
|
||||
QVector<DockOperation> m_dockOperations;
|
||||
QPointer<QWidget> m_centralWidget;
|
||||
Perspective::Callback m_aboutToActivateCallback;
|
||||
@@ -100,8 +121,6 @@ public:
|
||||
QHBoxLayout *m_innerToolBarLayout = nullptr;
|
||||
QPointer<QWidget> m_switcher;
|
||||
QString m_lastActiveSubPerspectiveId;
|
||||
QHash<QString, QVariant> m_nonPersistenSettings;
|
||||
Perspective::ShouldPersistChecker m_shouldPersistChecker;
|
||||
};
|
||||
|
||||
class DebuggerMainWindowPrivate : public QObject
|
||||
@@ -118,20 +137,30 @@ public:
|
||||
void registerPerspective(Perspective *perspective);
|
||||
void resetCurrentPerspective();
|
||||
int indexInChooser(Perspective *perspective) const;
|
||||
void fixupLayoutIfNeeded();
|
||||
void updatePerspectiveChooserWidth();
|
||||
|
||||
void cleanDocks();
|
||||
void setCentralWidget(QWidget *widget);
|
||||
|
||||
QDockWidget *dockForWidget(QWidget *widget) const;
|
||||
|
||||
void setCurrentPerspective(Perspective *perspective)
|
||||
{
|
||||
m_currentPerspective = perspective;
|
||||
}
|
||||
|
||||
DebuggerMainWindow *q = nullptr;
|
||||
Perspective *m_currentPerspective = nullptr;
|
||||
QPointer<Perspective> m_currentPerspective = nullptr;
|
||||
QComboBox *m_perspectiveChooser = nullptr;
|
||||
QStackedWidget *m_centralWidgetStack = nullptr;
|
||||
QHBoxLayout *m_subPerspectiveSwitcherLayout = nullptr;
|
||||
QHBoxLayout *m_innerToolsLayout = nullptr;
|
||||
QWidget *m_editorPlaceHolder = nullptr;
|
||||
QPointer<QWidget> m_editorPlaceHolder;
|
||||
Utils::StatusLabel *m_statusLabel = nullptr;
|
||||
QDockWidget *m_toolBarDock = nullptr;
|
||||
|
||||
QList<Perspective *> m_perspectives;
|
||||
QList<QPointer<Perspective>> m_perspectives;
|
||||
QSet<QString> m_persistentChangedDocks;
|
||||
};
|
||||
|
||||
DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
|
||||
@@ -211,10 +240,9 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
|
||||
m_toolBarDock = dock;
|
||||
q->addDockWidget(Qt::BottomDockWidgetArea, m_toolBarDock);
|
||||
|
||||
connect(viewButton, &QAbstractButton::clicked, [this, viewButton] {
|
||||
QMenu menu;
|
||||
q->addDockActionsToMenu(&menu);
|
||||
menu.exec(viewButton->mapToGlobal(QPoint()));
|
||||
connect(viewButton, &QAbstractButton::clicked, this, [this, viewButton] {
|
||||
ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
|
||||
viewsMenu->menu()->exec(viewButton->mapToGlobal(QPoint()));
|
||||
});
|
||||
|
||||
connect(closeButton, &QAbstractButton::clicked, [] {
|
||||
@@ -256,6 +284,19 @@ DebuggerMainWindow::DebuggerMainWindow()
|
||||
"Debugger.Views.ResetSimple", debugcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
|
||||
|
||||
connect(ICore::instance(), &ICore::saveSettingsRequested, this, [this] {
|
||||
// There's one saveSettings triggered after plugin loading intentionally.
|
||||
// We do not want to save anything at that time.
|
||||
static bool firstOne = true;
|
||||
if (firstOne) {
|
||||
qCDebug(perspectivesLog) << "FIRST SAVE SETTINGS REQUEST IGNORED";
|
||||
firstOne = false;
|
||||
} else {
|
||||
qCDebug(perspectivesLog) << "SAVING SETTINGS";
|
||||
savePersistentSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DebuggerMainWindow::~DebuggerMainWindow()
|
||||
@@ -263,6 +304,12 @@ DebuggerMainWindow::~DebuggerMainWindow()
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
|
||||
viewsMenu->menu()->exec(ev->globalPos());
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::ensureMainWindowExists()
|
||||
{
|
||||
if (!theMainWindow)
|
||||
@@ -271,6 +318,8 @@ void DebuggerMainWindow::ensureMainWindowExists()
|
||||
|
||||
void DebuggerMainWindow::doShutdown()
|
||||
{
|
||||
QTC_ASSERT(theMainWindow, return);
|
||||
|
||||
delete theMainWindow;
|
||||
theMainWindow = nullptr;
|
||||
}
|
||||
@@ -286,9 +335,12 @@ void DebuggerMainWindowPrivate::registerPerspective(Perspective *perspective)
|
||||
|
||||
void DebuggerMainWindowPrivate::destroyPerspective(Perspective *perspective)
|
||||
{
|
||||
if (perspective == m_currentPerspective) {
|
||||
depopulateCurrentPerspective();
|
||||
m_currentPerspective = nullptr;
|
||||
qCDebug(perspectivesLog) << "ABOUT TO DESTROY PERSPECTIVE" << perspective->id();
|
||||
|
||||
const bool wasCurrent = perspective == m_currentPerspective;
|
||||
if (wasCurrent) {
|
||||
qCDebug(perspectivesLog) << "RAMPING IT DOWN FIRST AS IT WAS CURRENT" << perspective->id();
|
||||
perspective->rampDownAsCurrent();
|
||||
}
|
||||
|
||||
m_perspectives.removeAll(perspective);
|
||||
@@ -298,6 +350,31 @@ void DebuggerMainWindowPrivate::destroyPerspective(Perspective *perspective)
|
||||
const int idx = indexInChooser(perspective);
|
||||
if (idx != -1)
|
||||
m_perspectiveChooser->removeItem(idx);
|
||||
|
||||
for (DockOperation &op : perspective->d->m_dockOperations) {
|
||||
if (op.commandId.isValid())
|
||||
ActionManager::unregisterAction(op.dock->toggleViewAction(), op.commandId);
|
||||
if (op.dock) {
|
||||
theMainWindow->removeDockWidget(op.dock);
|
||||
op.widget->setParent(nullptr); // Prevent deletion
|
||||
op.dock->setParent(nullptr);
|
||||
delete op.dock;
|
||||
op.dock = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasCurrent) {
|
||||
if (Perspective *parent = Perspective::findPerspective(perspective->d->m_parentPerspectiveId)) {
|
||||
qCDebug(perspectivesLog) << "RAMPING UP PARENT PERSPECTIVE" << parent->id();
|
||||
parent->rampUpAsCurrent();
|
||||
} else {
|
||||
qCDebug(perspectivesLog) << "RAMPED DOWN WAS ACTION, BUT NO PARENT AVAILABLE. TAKE FIRST BEST";
|
||||
if (QTC_GUARD(!m_perspectives.isEmpty()))
|
||||
m_perspectives.first()->rampUpAsCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(perspectivesLog) << "DESTROYED PERSPECTIVE" << perspective->id();
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::showStatusMessage(const QString &message, int timeoutMS)
|
||||
@@ -309,36 +386,122 @@ void DebuggerMainWindow::showStatusMessage(const QString &message, int timeoutMS
|
||||
void DebuggerMainWindow::enterDebugMode()
|
||||
{
|
||||
theMainWindow->setDockActionsVisible(true);
|
||||
Perspective *perspective = theMainWindow->d->m_currentPerspective;
|
||||
if (!perspective) {
|
||||
const QSettings *settings = ICore::settings();
|
||||
const QString lastPerspectiveId = settings->value(LAST_PERSPECTIVE_KEY).toString();
|
||||
perspective = Perspective::findPerspective(lastPerspectiveId);
|
||||
// If we don't find a perspective with the stored name, pick any.
|
||||
// This can happen e.g. when a plugin was disabled that provided
|
||||
// the stored perspective, or when the save file was modified externally.
|
||||
if (!perspective && !theMainWindow->d->m_perspectives.isEmpty())
|
||||
perspective = theMainWindow->d->m_perspectives.first();
|
||||
}
|
||||
theMainWindow->restorePersistentSettings();
|
||||
QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
|
||||
|
||||
QSettings *settings = ICore::settings();
|
||||
const QString lastPerspectiveId = settings->value(LAST_PERSPECTIVE_KEY).toString();
|
||||
Perspective *perspective = Perspective::findPerspective(lastPerspectiveId);
|
||||
// If we don't find a perspective with the stored name, pick any.
|
||||
// This can happen e.g. when a plugin was disabled that provided
|
||||
// the stored perspective, or when the save file was modified externally.
|
||||
if (!perspective && !theMainWindow->d->m_perspectives.isEmpty())
|
||||
perspective = theMainWindow->d->m_perspectives.first();
|
||||
|
||||
// There's at least the debugger preset perspective that should be found above.
|
||||
QTC_ASSERT(perspective, return);
|
||||
perspective->select();
|
||||
|
||||
if (auto sub = Perspective::findPerspective(perspective->d->m_lastActiveSubPerspectiveId)) {
|
||||
qCDebug(perspectivesLog) << "SWITCHING TO SUBPERSPECTIVE" << sub->d->m_id;
|
||||
perspective = sub;
|
||||
}
|
||||
|
||||
perspective->rampUpAsCurrent();
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::leaveDebugMode()
|
||||
{
|
||||
if (Perspective *perspective = theMainWindow->d->m_currentPerspective)
|
||||
perspective->d->saveLayout();
|
||||
theMainWindow->savePersistentSettings();
|
||||
|
||||
if (theMainWindow->d->m_currentPerspective)
|
||||
theMainWindow->d->m_currentPerspective->rampDownAsCurrent();
|
||||
QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
|
||||
|
||||
theMainWindow->setDockActionsVisible(false);
|
||||
|
||||
// Hide dock widgets manually in case they are floating.
|
||||
for (QDockWidget *dockWidget : theMainWindow->dockWidgets()) {
|
||||
if (dockWidget->isFloating())
|
||||
dockWidget->hide();
|
||||
dockWidget->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::restorePersistentSettings()
|
||||
{
|
||||
qCDebug(perspectivesLog) << "RESTORE PERSISTENT";
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(MAINWINDOW_KEY);
|
||||
const bool res = theMainWindow->restoreState(settings->value(STATE_KEY).toByteArray(),
|
||||
SettingsVersion);
|
||||
if (!res)
|
||||
qCDebug(perspectivesLog) << "NO READABLE PERSISTENT SETTINGS FOUND, ASSUMING NEW CLEAN SETTINGS";
|
||||
|
||||
theMainWindow->setAutoHideTitleBars(settings->value(AUTOHIDE_TITLEBARS_KEY, true).toBool());
|
||||
theMainWindow->showCentralWidget(settings->value(SHOW_CENTRALWIDGET_KEY, true).toBool());
|
||||
theMainWindow->d->m_persistentChangedDocks
|
||||
= QSet<QString>::fromList(settings->value(CHANGED_DOCK_KEY).toStringList());
|
||||
settings->endGroup();
|
||||
|
||||
qCDebug(perspectivesLog) << "LOADED DOCKS:" << theMainWindow->d->m_persistentChangedDocks;
|
||||
|
||||
for (Perspective *perspective : theMainWindow->d->m_perspectives) {
|
||||
qCDebug(perspectivesLog) << "RESTORING PERSPECTIVE" << perspective->d->m_id;
|
||||
for (DockOperation &op : perspective->d->m_dockOperations) {
|
||||
if (op.operationType != Perspective::Raise) {
|
||||
QTC_ASSERT(op.dock, continue);
|
||||
QTC_ASSERT(op.widget, continue);
|
||||
if (theMainWindow->d->m_persistentChangedDocks.contains(op.name())) {
|
||||
qCDebug(perspectivesLog) << "DOCK " << op.name() << "*** UNUSUAL";
|
||||
op.visibleByUser = !op.visibleByDefault;
|
||||
} else {
|
||||
qCDebug(perspectivesLog) << "DOCK " << op.name() << "NORMAL";
|
||||
QTC_CHECK(op.visibleByUser == op.visibleByDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Perspective *DebuggerMainWindow::currentPerspective()
|
||||
{
|
||||
return theMainWindow->d->m_currentPerspective;
|
||||
}
|
||||
|
||||
void DebuggerMainWindow::savePersistentSettings()
|
||||
{
|
||||
// The current one might have active, non saved changes.
|
||||
if (Perspective *perspective = theMainWindow->d->m_currentPerspective)
|
||||
perspective->d->saveLayout();
|
||||
|
||||
qCDebug(perspectivesLog) << "SAVE PERSISTENT";
|
||||
|
||||
QSet<QString> changedDocks = theMainWindow->d->m_persistentChangedDocks;
|
||||
for (Perspective *perspective : theMainWindow->d->m_perspectives) {
|
||||
qCDebug(perspectivesLog) << "SAVE PERSPECTIVE" << perspective->d->m_id;
|
||||
for (const DockOperation &op : perspective->d->m_dockOperations) {
|
||||
if (op.operationType != Perspective::Raise) {
|
||||
QTC_ASSERT(op.dock, continue);
|
||||
QTC_ASSERT(op.widget, continue);
|
||||
qCDebug(perspectivesLog) << "DOCK " << op.name() << "ACTIVE: " << op.visibleByUser;
|
||||
if (op.visibleByUser != op.visibleByDefault)
|
||||
changedDocks.insert(op.name());
|
||||
else
|
||||
changedDocks.remove(op.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
theMainWindow->d->m_persistentChangedDocks = changedDocks;
|
||||
qCDebug(perspectivesLog) << "CHANGED DOCKS:" << changedDocks;
|
||||
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(MAINWINDOW_KEY);
|
||||
settings->setValue(CHANGED_DOCK_KEY, QStringList(changedDocks.toList()));
|
||||
settings->setValue(STATE_KEY, theMainWindow->saveState(SettingsVersion));
|
||||
settings->setValue(AUTOHIDE_TITLEBARS_KEY, theMainWindow->autoHideTitleBars());
|
||||
settings->setValue(SHOW_CENTRALWIDGET_KEY, theMainWindow->isCentralWidgetShown());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
QWidget *DebuggerMainWindow::centralWidgetStack()
|
||||
{
|
||||
return theMainWindow ? theMainWindow->d->m_centralWidgetStack : nullptr;
|
||||
@@ -358,21 +521,95 @@ DebuggerMainWindow *DebuggerMainWindow::instance()
|
||||
|
||||
Perspective *Perspective::findPerspective(const QString &perspectiveId)
|
||||
{
|
||||
return Utils::findOr(theMainWindow->d->m_perspectives, nullptr, [&](Perspective *perspective) {
|
||||
return perspective->d->m_id == perspectiveId;
|
||||
QTC_ASSERT(theMainWindow, return nullptr);
|
||||
return Utils::findOr(theMainWindow->d->m_perspectives, nullptr,
|
||||
[perspectiveId](Perspective *perspective) {
|
||||
return perspective && perspective->d->m_id == perspectiveId;
|
||||
});
|
||||
}
|
||||
|
||||
bool Perspective::isCurrent() const
|
||||
{
|
||||
return theMainWindow->d->m_currentPerspective == this;
|
||||
}
|
||||
|
||||
QDockWidget *DebuggerMainWindowPrivate::dockForWidget(QWidget *widget) const
|
||||
{
|
||||
QTC_ASSERT(widget, return nullptr);
|
||||
|
||||
for (QDockWidget *dock : q->dockWidgets()) {
|
||||
if (dock->widget() == widget)
|
||||
return dock;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::resetCurrentPerspective()
|
||||
{
|
||||
if (m_currentPerspective) {
|
||||
m_currentPerspective->d->m_nonPersistenSettings.clear();
|
||||
m_currentPerspective->d->hideToolBar();
|
||||
QTC_ASSERT(m_currentPerspective, return);
|
||||
cleanDocks();
|
||||
m_currentPerspective->d->resetPerspective();
|
||||
setCentralWidget(m_currentPerspective->d->m_centralWidget);
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::setCentralWidget(QWidget *widget)
|
||||
{
|
||||
if (widget) {
|
||||
m_centralWidgetStack->addWidget(widget);
|
||||
q->showCentralWidgetAction()->setText(widget->windowTitle());
|
||||
} else {
|
||||
m_centralWidgetStack->addWidget(m_editorPlaceHolder);
|
||||
q->showCentralWidgetAction()->setText(DebuggerMainWindow::tr("Editor"));
|
||||
}
|
||||
}
|
||||
|
||||
void PerspectivePrivate::resetPerspective()
|
||||
{
|
||||
showInnerToolBar();
|
||||
|
||||
for (DockOperation &op : m_dockOperations) {
|
||||
if (op.operationType == Perspective::Raise) {
|
||||
QTC_ASSERT(op.dock, qCDebug(perspectivesLog) << op.name(); continue);
|
||||
op.dock->raise();
|
||||
} else {
|
||||
op.setupLayout();
|
||||
op.dock->setVisible(op.visibleByDefault);
|
||||
qCDebug(perspectivesLog) << "SETTING " << op.name()
|
||||
<< " TO ACTIVE: " << op.visibleByDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DockOperation::setupLayout()
|
||||
{
|
||||
QTC_ASSERT(widget, return);
|
||||
QTC_ASSERT(operationType != Perspective::Raise, return);
|
||||
QTC_ASSERT(dock, return);
|
||||
|
||||
QDockWidget *anchor = nullptr;
|
||||
if (anchorWidget)
|
||||
anchor = theMainWindow->d->dockForWidget(anchorWidget);
|
||||
else if (area == Qt::BottomDockWidgetArea)
|
||||
anchor = theMainWindow->d->m_toolBarDock;
|
||||
|
||||
if (anchor) {
|
||||
switch (operationType) {
|
||||
case Perspective::AddToTab:
|
||||
theMainWindow->tabifyDockWidget(anchor, dock);
|
||||
break;
|
||||
case Perspective::SplitHorizontal:
|
||||
theMainWindow->splitDockWidget(anchor, dock, Qt::Horizontal);
|
||||
break;
|
||||
case Perspective::SplitVertical:
|
||||
theMainWindow->splitDockWidget(anchor, dock, Qt::Vertical);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
theMainWindow->addDockWidget(area, dock);
|
||||
}
|
||||
depopulateCurrentPerspective();
|
||||
populateCurrentPerspective();
|
||||
if (m_currentPerspective)
|
||||
m_currentPerspective->d->saveLayout();
|
||||
}
|
||||
|
||||
int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const
|
||||
@@ -380,47 +617,6 @@ int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const
|
||||
return perspective ? m_perspectiveChooser->findData(perspective->d->m_id) : -1;
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::fixupLayoutIfNeeded()
|
||||
{
|
||||
// Evil workaround for QTCREATORBUG-21455: In some so far unknown situation
|
||||
// the saveLayout/restoreLayout process leads to a situation where some docks
|
||||
// do not end up below the perspective toolbar even though they were there
|
||||
// initially, leading to an awkward dock layout.
|
||||
// This here tries to detect the situation (sonmething else in the bottom
|
||||
// area is at the right of the toolbar) "corrects" that by restoring the
|
||||
// default layout.
|
||||
|
||||
if (m_toolBarDock->width() != q->width()) {
|
||||
qDebug() << "Scrambled dock layout found. Resetting it.";
|
||||
resetCurrentPerspective();
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective)
|
||||
{
|
||||
QTC_ASSERT(perspective, return);
|
||||
|
||||
if (m_currentPerspective) {
|
||||
m_currentPerspective->d->saveLayout();
|
||||
m_currentPerspective->d->hideToolBar();
|
||||
}
|
||||
|
||||
depopulateCurrentPerspective();
|
||||
|
||||
m_currentPerspective = perspective;
|
||||
|
||||
perspective->aboutToActivate();
|
||||
|
||||
populateCurrentPerspective();
|
||||
|
||||
if (m_currentPerspective) {
|
||||
m_currentPerspective->d->restoreLayout();
|
||||
fixupLayoutIfNeeded();
|
||||
}
|
||||
|
||||
updatePerspectiveChooserWidth();
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
|
||||
{
|
||||
Perspective *perspective = m_currentPerspective;
|
||||
@@ -445,111 +641,72 @@ void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::depopulateCurrentPerspective()
|
||||
void DebuggerMainWindowPrivate::cleanDocks()
|
||||
{
|
||||
// Clean up old perspective.
|
||||
for (QDockWidget *dock : q->dockWidgets()) {
|
||||
if (dock->property(OWNED_BY_PERSPECTIVE).toBool()) {
|
||||
// Prevent deletion of plugin-owned widgets.
|
||||
if (dock->widget())
|
||||
dock->widget()->setParent(nullptr);
|
||||
ActionManager::unregisterAction(dock->toggleViewAction(),
|
||||
Id("Dock.").withSuffix(dock->objectName()));
|
||||
delete dock;
|
||||
}
|
||||
}
|
||||
m_statusLabel->clear();
|
||||
|
||||
if (m_currentPerspective) {
|
||||
ICore::removeAdditionalContext(m_currentPerspective->context());
|
||||
QWidget *central = m_currentPerspective->centralWidget();
|
||||
m_centralWidgetStack->removeWidget(central ? central : m_editorPlaceHolder);
|
||||
for (QDockWidget *dock : q->dockWidgets()) {
|
||||
if (dock != m_toolBarDock)
|
||||
dock->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerMainWindowPrivate::populateCurrentPerspective()
|
||||
void PerspectivePrivate::depopulatePerspective()
|
||||
{
|
||||
// Create dock widgets wrapping ther perspective's widgets.
|
||||
QHash<QString, QDockWidget *> dockForDockId;
|
||||
for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) {
|
||||
if (op.operationType == Perspective::Raise)
|
||||
continue;
|
||||
QTC_ASSERT(op.widget, continue);
|
||||
const QString dockId = op.widget->objectName();
|
||||
QTC_CHECK(!dockId.isEmpty());
|
||||
QTC_ASSERT(!dockForDockId.contains(dockId), continue);
|
||||
QDockWidget *dock = q->addDockForWidget(op.widget);
|
||||
dock->setProperty(OWNED_BY_PERSPECTIVE, true);
|
||||
dockForDockId[dockId] = dock;
|
||||
q->addDockWidget(op.area, dock);
|
||||
ICore::removeAdditionalContext(context());
|
||||
theMainWindow->d->m_centralWidgetStack
|
||||
->removeWidget(m_centralWidget ? m_centralWidget : theMainWindow->d->m_editorPlaceHolder);
|
||||
|
||||
QAction *toggleViewAction = dock->toggleViewAction();
|
||||
toggleViewAction->setText(dock->windowTitle());
|
||||
theMainWindow->d->m_statusLabel->clear();
|
||||
|
||||
Command *cmd = ActionManager::registerAction(toggleViewAction,
|
||||
Id("Dock.").withSuffix(dock->objectName()),
|
||||
m_currentPerspective->context());
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd);
|
||||
for (QDockWidget *dock : theMainWindow->dockWidgets()) {
|
||||
if (dock != theMainWindow->d->m_toolBarDock)
|
||||
dock->setVisible(false);
|
||||
}
|
||||
|
||||
m_currentPerspective->d->showToolBar();
|
||||
hideInnerToolBar();
|
||||
}
|
||||
|
||||
// Pre-arrange dock widgets.
|
||||
for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) {
|
||||
QTC_ASSERT(op.widget, continue);
|
||||
const QString dockId = op.widget->objectName();
|
||||
QDockWidget *dock = dockForDockId.value(dockId);
|
||||
QTC_ASSERT(dock, continue);
|
||||
if (op.operationType == Perspective::Raise) {
|
||||
dock->raise();
|
||||
continue;
|
||||
}
|
||||
QDockWidget *anchor = dockForDockId.value(op.anchorDockId);
|
||||
if (!anchor && op.area == Qt::BottomDockWidgetArea) {
|
||||
anchor = m_toolBarDock;
|
||||
}
|
||||
void PerspectivePrivate::saveAsLastUsedPerspective()
|
||||
{
|
||||
if (Perspective *parent = Perspective::findPerspective(m_parentPerspectiveId))
|
||||
parent->d->m_lastActiveSubPerspectiveId = m_id;
|
||||
else
|
||||
m_lastActiveSubPerspectiveId.clear();
|
||||
|
||||
if (anchor) {
|
||||
switch (op.operationType) {
|
||||
case Perspective::AddToTab:
|
||||
q->tabifyDockWidget(anchor, dock);
|
||||
break;
|
||||
case Perspective::SplitHorizontal:
|
||||
q->splitDockWidget(anchor, dock, Qt::Horizontal);
|
||||
break;
|
||||
case Perspective::SplitVertical:
|
||||
q->splitDockWidget(anchor, dock, Qt::Vertical);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
dock->setVisible(op.visibleByDefault);
|
||||
const QString &lastKey = m_parentPerspectiveId.isEmpty() ? m_id : m_parentPerspectiveId;
|
||||
qCDebug(perspectivesLog) << "SAVE LAST USED PERSPECTIVE" << lastKey;
|
||||
ICore::settings()->setValue(LAST_PERSPECTIVE_KEY, lastKey);
|
||||
}
|
||||
|
||||
void PerspectivePrivate::populatePerspective()
|
||||
{
|
||||
showInnerToolBar();
|
||||
|
||||
if (m_centralWidget) {
|
||||
theMainWindow->d->m_centralWidgetStack->addWidget(m_centralWidget);
|
||||
theMainWindow->showCentralWidgetAction()->setText(m_centralWidget->windowTitle());
|
||||
} else {
|
||||
theMainWindow->d->m_centralWidgetStack->addWidget(theMainWindow->d->m_editorPlaceHolder);
|
||||
theMainWindow->showCentralWidgetAction()->setText(DebuggerMainWindow::tr("Editor"));
|
||||
}
|
||||
|
||||
QWidget *central = m_currentPerspective->centralWidget();
|
||||
m_centralWidgetStack->addWidget(central ? central : m_editorPlaceHolder);
|
||||
q->showCentralWidgetAction()->setText(central ? central->windowTitle()
|
||||
: DebuggerMainWindow::tr("Editor"));
|
||||
ICore::addAdditionalContext(context());
|
||||
|
||||
m_statusLabel->clear();
|
||||
|
||||
ICore::addAdditionalContext(m_currentPerspective->context());
|
||||
restoreLayout();
|
||||
}
|
||||
|
||||
// Perspective
|
||||
|
||||
Perspective::Perspective(const QString &id, const QString &name,
|
||||
const QString &parentPerspectiveId,
|
||||
const QString &subPerspectiveType)
|
||||
const QString &settingsId)
|
||||
: d(new PerspectivePrivate)
|
||||
{
|
||||
const bool shouldPersist = parentPerspectiveId.isEmpty();
|
||||
d->m_id = id;
|
||||
d->m_name = name;
|
||||
d->m_parentPerspectiveId = parentPerspectiveId;
|
||||
d->m_subPerspectiveType = subPerspectiveType;
|
||||
d->m_shouldPersistChecker = [shouldPersist] { return shouldPersist; };
|
||||
d->m_settingsId = settingsId;
|
||||
|
||||
DebuggerMainWindow::ensureMainWindowExists();
|
||||
theMainWindow->d->registerPerspective(this);
|
||||
@@ -566,12 +723,8 @@ Perspective::Perspective(const QString &id, const QString &name,
|
||||
Perspective::~Perspective()
|
||||
{
|
||||
if (theMainWindow) {
|
||||
d->saveLayout();
|
||||
|
||||
delete d->m_innerToolBar;
|
||||
d->m_innerToolBar = nullptr;
|
||||
|
||||
theMainWindow->d->destroyPerspective(this);
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
@@ -597,12 +750,6 @@ void Perspective::setAboutToActivateCallback(const Perspective::Callback &cb)
|
||||
d->m_aboutToActivateCallback = cb;
|
||||
}
|
||||
|
||||
void Perspective::aboutToActivate() const
|
||||
{
|
||||
if (d->m_aboutToActivateCallback)
|
||||
d->m_aboutToActivateCallback();
|
||||
}
|
||||
|
||||
void Perspective::setEnabled(bool enabled)
|
||||
{
|
||||
QTC_ASSERT(theMainWindow, return);
|
||||
@@ -655,34 +802,24 @@ void Perspective::addToolbarSeparator()
|
||||
d->m_innerToolBarLayout->addWidget(new StyledSeparator(d->m_innerToolBar));
|
||||
}
|
||||
|
||||
void Perspective::setShouldPersistChecker(const ShouldPersistChecker &checker)
|
||||
{
|
||||
d->m_shouldPersistChecker = checker;
|
||||
}
|
||||
|
||||
QWidget *Perspective::centralWidget() const
|
||||
{
|
||||
return d->m_centralWidget;
|
||||
}
|
||||
|
||||
Perspective *Perspective::currentPerspective()
|
||||
Context PerspectivePrivate::context() const
|
||||
{
|
||||
return theMainWindow ? theMainWindow->d->m_currentPerspective : nullptr;
|
||||
return Context(Id::fromName(m_id.toUtf8()));
|
||||
}
|
||||
|
||||
Context Perspective::context() const
|
||||
{
|
||||
return Context(Id::fromName(d->m_id.toUtf8()));
|
||||
}
|
||||
|
||||
void PerspectivePrivate::showToolBar()
|
||||
void PerspectivePrivate::showInnerToolBar()
|
||||
{
|
||||
m_innerToolBar->setVisible(true);
|
||||
if (m_switcher)
|
||||
m_switcher->setVisible(true);
|
||||
}
|
||||
|
||||
void PerspectivePrivate::hideToolBar()
|
||||
void PerspectivePrivate::hideInnerToolBar()
|
||||
{
|
||||
QTC_ASSERT(m_innerToolBar, return);
|
||||
m_innerToolBar->setVisible(false);
|
||||
@@ -699,63 +836,131 @@ void Perspective::addWindow(QWidget *widget,
|
||||
QTC_ASSERT(widget, return);
|
||||
DockOperation op;
|
||||
op.widget = widget;
|
||||
if (anchorWidget)
|
||||
op.anchorDockId = anchorWidget->objectName();
|
||||
op.operationType = type;
|
||||
op.anchorWidget = anchorWidget;
|
||||
op.visibleByDefault = visibleByDefault;
|
||||
op.area = area;
|
||||
|
||||
if (op.operationType != Perspective::Raise) {
|
||||
qCDebug(perspectivesLog) << "CREATING DOCK " << op.name()
|
||||
<< "DEFAULT: " << op.visibleByDefault;
|
||||
op.dock = theMainWindow->addDockForWidget(op.widget);
|
||||
op.commandId = Id("Dock.").withSuffix(op.name());
|
||||
if (theMainWindow->restoreDockWidget(op.dock)) {
|
||||
qCDebug(perspectivesLog) << "RESTORED SUCCESSFULLY";
|
||||
} else {
|
||||
qCDebug(perspectivesLog) << "COULD NOT RESTORE";
|
||||
op.setupLayout();
|
||||
}
|
||||
op.dock->setVisible(false);
|
||||
op.dock->toggleViewAction()->setText(op.dock->windowTitle());
|
||||
|
||||
QObject::connect(op.dock->toggleViewAction(), &QAction::changed, op.dock, [this, op] {
|
||||
qCDebug(perspectivesLog) << "CHANGED: " << op.name()
|
||||
<< "ACTION CHECKED: " << op.dock->toggleViewAction()->isChecked();
|
||||
});
|
||||
|
||||
Command *cmd = ActionManager::registerAction(op.dock->toggleViewAction(),
|
||||
op.commandId, d->context());
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd);
|
||||
}
|
||||
|
||||
op.visibleByUser = op.visibleByDefault;
|
||||
if (theMainWindow->d->m_persistentChangedDocks.contains(op.name())) {
|
||||
op.visibleByUser = !op.visibleByUser;
|
||||
qCDebug(perspectivesLog) << "*** NON-DEFAULT USER: " << op.visibleByUser;
|
||||
} else {
|
||||
qCDebug(perspectivesLog) << "DEFAULT USER";
|
||||
}
|
||||
|
||||
d->m_dockOperations.append(op);
|
||||
}
|
||||
|
||||
void Perspective::destroy()
|
||||
{
|
||||
theMainWindow->d->destroyPerspective(this);
|
||||
}
|
||||
|
||||
void Perspective::rampDownAsCurrent()
|
||||
{
|
||||
QTC_ASSERT(this == theMainWindow->d->m_currentPerspective, return);
|
||||
d->saveLayout();
|
||||
d->depopulatePerspective();
|
||||
theMainWindow->d->setCurrentPerspective(nullptr);
|
||||
|
||||
Debugger::Internal::EngineManager::updatePerspectives();
|
||||
}
|
||||
|
||||
void Perspective::rampUpAsCurrent()
|
||||
{
|
||||
if (d->m_aboutToActivateCallback)
|
||||
d->m_aboutToActivateCallback();
|
||||
|
||||
QTC_ASSERT(theMainWindow->d->m_currentPerspective == nullptr, return);
|
||||
theMainWindow->d->setCurrentPerspective(this);
|
||||
QTC_ASSERT(theMainWindow->d->m_currentPerspective == this, return);
|
||||
|
||||
d->populatePerspective();
|
||||
|
||||
theMainWindow->d->updatePerspectiveChooserWidth();
|
||||
|
||||
d->saveAsLastUsedPerspective();
|
||||
|
||||
Debugger::Internal::EngineManager::updatePerspectives();
|
||||
}
|
||||
|
||||
void Perspective::select()
|
||||
{
|
||||
Debugger::Internal::EngineManager::activateDebugMode();
|
||||
if (Perspective::currentPerspective() == this)
|
||||
return;
|
||||
theMainWindow->d->selectPerspective(this);
|
||||
if (Perspective *parent = Perspective::findPerspective(d->m_parentPerspectiveId))
|
||||
parent->d->m_lastActiveSubPerspectiveId = d->m_id;
|
||||
else
|
||||
d->m_lastActiveSubPerspectiveId.clear();
|
||||
|
||||
const QString &lastKey = d->m_parentPerspectiveId.isEmpty() ? d->m_id : d->m_parentPerspectiveId;
|
||||
ICore::settings()->setValue(LAST_PERSPECTIVE_KEY, lastKey);
|
||||
if (theMainWindow->d->m_currentPerspective == this)
|
||||
return;
|
||||
|
||||
if (theMainWindow->d->m_currentPerspective)
|
||||
theMainWindow->d->m_currentPerspective->rampDownAsCurrent();
|
||||
QTC_CHECK(theMainWindow->d->m_currentPerspective == nullptr);
|
||||
|
||||
rampUpAsCurrent();
|
||||
}
|
||||
|
||||
void PerspectivePrivate::restoreLayout()
|
||||
{
|
||||
if (m_nonPersistenSettings.isEmpty()) {
|
||||
//qDebug() << "PERSPECTIVE" << m_id << "RESTORE PERSISTENT FROM " << settingsId();
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(settingsId());
|
||||
theMainWindow->restoreSettings(settings);
|
||||
settings->endGroup();
|
||||
m_nonPersistenSettings = theMainWindow->saveSettings();
|
||||
} else {
|
||||
//qDebug() << "PERSPECTIVE" << m_id << "RESTORE FROM LOCAL TEMP";
|
||||
theMainWindow->restoreSettings(m_nonPersistenSettings);
|
||||
qCDebug(perspectivesLog) << "PERSPECTIVE" << m_id << "RESTORING LAYOUT FROM " << settingsId();
|
||||
for (DockOperation &op : m_dockOperations) {
|
||||
if (op.operationType != Perspective::Raise) {
|
||||
QTC_ASSERT(op.dock, continue);
|
||||
const bool active = op.visibleByUser;
|
||||
op.dock->toggleViewAction()->setChecked(active);
|
||||
op.dock->setVisible(active);
|
||||
qCDebug(perspectivesLog) << "RESTORE DOCK " << op.name() << "ACTIVE: " << active
|
||||
<< (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerspectivePrivate::saveLayout()
|
||||
{
|
||||
//qDebug() << "PERSPECTIVE" << m_id << "SAVE LOCAL TEMP";
|
||||
m_nonPersistenSettings = theMainWindow->saveSettings();
|
||||
|
||||
if (m_shouldPersistChecker()) {
|
||||
//qDebug() << "PERSPECTIVE" << m_id << "SAVE PERSISTENT TO " << settingsId();
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->beginGroup(settingsId());
|
||||
theMainWindow->saveSettings(settings);
|
||||
settings->endGroup();
|
||||
} else {
|
||||
//qDebug() << "PERSPECTIVE" << m_id << "NOT PERSISTENT";
|
||||
qCDebug(perspectivesLog) << "PERSPECTIVE" << m_id << "SAVE LAYOUT TO " << settingsId();
|
||||
for (DockOperation &op : m_dockOperations) {
|
||||
if (op.operationType != Perspective::Raise) {
|
||||
QTC_ASSERT(op.dock, continue);
|
||||
QTC_ASSERT(op.widget, continue);
|
||||
const bool active = op.dock->toggleViewAction()->isChecked();
|
||||
op.visibleByUser = active;
|
||||
if (active == op.visibleByDefault)
|
||||
theMainWindow->d->m_persistentChangedDocks.remove(op.name());
|
||||
else
|
||||
theMainWindow->d->m_persistentChangedDocks.insert(op.name());
|
||||
qCDebug(perspectivesLog) << "SAVE DOCK " << op.name() << "ACTIVE: " << active
|
||||
<< (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString PerspectivePrivate::settingsId() const
|
||||
{
|
||||
return m_parentPerspectiveId.isEmpty() ? m_id : (m_parentPerspectiveId + '.' + m_subPerspectiveType);
|
||||
return m_settingsId.isEmpty() ? m_id : m_settingsId;
|
||||
}
|
||||
|
||||
// ToolbarAction
|
||||
|
||||
@@ -59,12 +59,12 @@ public:
|
||||
QPointer<QToolButton> m_toolButton;
|
||||
};
|
||||
|
||||
class DEBUGGER_EXPORT Perspective
|
||||
class DEBUGGER_EXPORT Perspective : public QObject
|
||||
{
|
||||
public:
|
||||
Perspective(const QString &id, const QString &name,
|
||||
const QString &parentPerspectiveId = QString(),
|
||||
const QString &subPerspectiveType = QString());
|
||||
const QString &settingId = QString());
|
||||
~Perspective();
|
||||
|
||||
enum OperationType { SplitVertical, SplitHorizontal, AddToTab, Raise };
|
||||
@@ -92,26 +92,26 @@ public:
|
||||
|
||||
using Callback = std::function<void()>;
|
||||
void setAboutToActivateCallback(const Callback &cb);
|
||||
void aboutToActivate() const;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
void select();
|
||||
void destroy();
|
||||
|
||||
static Perspective *currentPerspective();
|
||||
static Perspective *findPerspective(const QString &perspectiveId);
|
||||
|
||||
Core::Context context() const;
|
||||
|
||||
void showToolBar();
|
||||
void hideToolBar();
|
||||
bool isCurrent() const;
|
||||
|
||||
private:
|
||||
void rampDownAsCurrent();
|
||||
void rampUpAsCurrent();
|
||||
|
||||
Perspective(const Perspective &) = delete;
|
||||
void operator=(const Perspective &) = delete;
|
||||
|
||||
friend class DebuggerMainWindow;
|
||||
friend class DebuggerMainWindowPrivate;
|
||||
friend class PerspectivePrivate;
|
||||
class PerspectivePrivate *d = nullptr;
|
||||
};
|
||||
|
||||
@@ -132,12 +132,20 @@ public:
|
||||
static QWidget *centralWidgetStack();
|
||||
void addSubPerspectiveSwitcher(QWidget *widget);
|
||||
|
||||
static void savePersistentSettings();
|
||||
static void restorePersistentSettings();
|
||||
|
||||
static Perspective *currentPerspective();
|
||||
|
||||
private:
|
||||
DebuggerMainWindow();
|
||||
~DebuggerMainWindow() override;
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent *ev) override;
|
||||
|
||||
friend class Perspective;
|
||||
friend class PerspectivePrivate;
|
||||
friend class DockOperation;
|
||||
class DebuggerMainWindowPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -1052,7 +1052,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
||||
m_breakpointManagerView->setSpanColumn(BreakpointFunctionColumn);
|
||||
m_breakpointManagerWindow = addSearch(m_breakpointManagerView);
|
||||
m_breakpointManagerWindow->setWindowTitle(tr("Breakpoint Preset"));
|
||||
m_breakpointManagerWindow->setObjectName(DOCKWIDGET_BREAKPOINTMANAGER);
|
||||
m_breakpointManagerWindow->setObjectName("Debugger.Docks.BreakpointManager");
|
||||
addLabel(m_breakpointManagerWindow, m_breakpointManagerWindow->windowTitle());
|
||||
|
||||
|
||||
@@ -1064,7 +1064,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
||||
m_engineManagerView->setModel(m_engineManager.model());
|
||||
m_engineManagerWindow = addSearch(m_engineManagerView);
|
||||
m_engineManagerWindow->setWindowTitle(tr("Debugger Perspectives"));
|
||||
m_engineManagerWindow->setObjectName(DOCKWIDGET_ENGINEMANAGER);
|
||||
m_engineManagerWindow->setObjectName("Debugger.Docks.Snapshots");
|
||||
addLabel(m_engineManagerWindow, m_engineManagerWindow->windowTitle());
|
||||
|
||||
// Logging
|
||||
@@ -1366,7 +1366,8 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
||||
DebuggerMainWindow::leaveDebugMode();
|
||||
});
|
||||
|
||||
connect(ModeManager::instance(), &ModeManager::currentModeChanged, this, [](Id mode) {
|
||||
connect(ModeManager::instance(), &ModeManager::currentModeChanged, [](Id mode, Id oldMode) {
|
||||
QTC_ASSERT(mode != oldMode, return);
|
||||
if (mode == MODE_DEBUG) {
|
||||
DebuggerMainWindow::enterDebugMode();
|
||||
if (IEditor *editor = EditorManager::currentEditor())
|
||||
@@ -1531,7 +1532,7 @@ void DebuggerPluginPrivate::updatePresetState()
|
||||
} else {
|
||||
// The startup phase should be over once we are here.
|
||||
// But treat it as 'undisturbable if we are here by accident.
|
||||
QTC_CHECK(state != DebuggerNotReady);
|
||||
//QTC_CHECK(state != DebuggerNotReady);
|
||||
// Everything else is "undisturbable".
|
||||
m_startAction.setEnabled(false);
|
||||
m_debugWithoutDeployAction.setEnabled(false);
|
||||
@@ -1569,7 +1570,7 @@ void DebuggerPluginPrivate::onStartupProjectChanged(Project *project)
|
||||
}
|
||||
for (DebuggerEngine *engine : EngineManager::engines()) {
|
||||
// Run controls might be deleted during exit.
|
||||
engine->updateState(false);
|
||||
engine->updateState();
|
||||
}
|
||||
|
||||
updatePresetState();
|
||||
@@ -2022,11 +2023,9 @@ void DebuggerPluginPrivate::aboutToShutdown()
|
||||
m_shutdownTimer.setInterval(0);
|
||||
m_shutdownTimer.setSingleShot(true);
|
||||
connect(&m_shutdownTimer, &QTimer::timeout, this, &DebuggerPluginPrivate::doShutdown);
|
||||
for (DebuggerEngine *engine : m_engineManager.engines()) {
|
||||
if (engine && engine->state() != Debugger::DebuggerNotReady) {
|
||||
engine->abortDebugger();
|
||||
m_shutdownTimer.setInterval(3000);
|
||||
}
|
||||
if (EngineManager::shutDown()) {
|
||||
// If any engine is aborting we give them extra three seconds.
|
||||
m_shutdownTimer.setInterval(3000);
|
||||
}
|
||||
m_shutdownTimer.start();
|
||||
}
|
||||
|
||||
@@ -730,8 +730,6 @@ void DebuggerRunTool::stop()
|
||||
|
||||
void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine)
|
||||
{
|
||||
EngineManager::activateEngine(engine);
|
||||
|
||||
// Correct:
|
||||
// if (--d->engineStartsNeeded == 0) {
|
||||
// EngineManager::activateDebugMode();
|
||||
|
||||
@@ -155,16 +155,18 @@ public:
|
||||
}
|
||||
|
||||
EngineItem *findEngineItem(DebuggerEngine *engine);
|
||||
void activateEngine(DebuggerEngine *engine);
|
||||
void activateEngineItem(EngineItem *engineItem);
|
||||
void activateEngineByIndex(int index);
|
||||
void selectUiForCurrentEngine();
|
||||
void updateEngineChooserVisibility();
|
||||
void updatePerspectives();
|
||||
|
||||
TreeModel<TypedTreeItem<EngineItem>, EngineItem> m_engineModel;
|
||||
QPointer<EngineItem> m_currentItem;
|
||||
QPointer<EngineItem> m_currentItem; // The primary information is DebuggerMainWindow::d->m_currentPerspective
|
||||
Core::Id m_previousMode;
|
||||
QPointer<QComboBox> m_engineChooser;
|
||||
bool m_shuttingDown = false;
|
||||
Context m_currentAdditionalContext;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -192,6 +194,11 @@ QWidget *EngineManager::engineChooser()
|
||||
return d->m_engineChooser;
|
||||
}
|
||||
|
||||
void EngineManager::updatePerspectives()
|
||||
{
|
||||
d->updatePerspectives();
|
||||
}
|
||||
|
||||
EngineManager::~EngineManager()
|
||||
{
|
||||
theEngineManager = nullptr;
|
||||
@@ -208,11 +215,6 @@ QAbstractItemModel *EngineManager::model()
|
||||
return &d->m_engineModel;
|
||||
}
|
||||
|
||||
void EngineManager::activateEngine(DebuggerEngine *engine)
|
||||
{
|
||||
d->activateEngine(engine);
|
||||
}
|
||||
|
||||
QVariant EngineItem::data(int column, int role) const
|
||||
{
|
||||
if (m_engine) {
|
||||
@@ -273,7 +275,7 @@ bool EngineItem::setData(int row, const QVariant &value, int role)
|
||||
|
||||
if (role == BaseTreeView::ItemActivatedRole) {
|
||||
EngineItem *engineItem = d->findEngineItem(m_engine);
|
||||
d->activateEngineItem(engineItem);
|
||||
d->activateEngineByIndex(engineItem->indexInParent());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -316,21 +318,27 @@ bool EngineItem::setData(int row, const QVariant &value, int role)
|
||||
|
||||
void EngineManagerPrivate::activateEngineByIndex(int index)
|
||||
{
|
||||
activateEngineItem(m_engineModel.rootItem()->childAt(index));
|
||||
// The actual activation is triggered indirectly via the perspective change.
|
||||
Perspective *perspective = nullptr;
|
||||
if (index == 0) {
|
||||
perspective = Perspective::findPerspective(Debugger::Constants::PRESET_PERSPECTIVE_ID);
|
||||
} else {
|
||||
EngineItem *engineItem = m_engineModel.rootItem()->childAt(index);
|
||||
QTC_ASSERT(engineItem, return);
|
||||
QTC_ASSERT(engineItem->m_engine, return);
|
||||
perspective = engineItem->m_engine->perspective();
|
||||
}
|
||||
|
||||
QTC_ASSERT(perspective, return);
|
||||
perspective->select();
|
||||
}
|
||||
|
||||
void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem)
|
||||
{
|
||||
Context previousContext;
|
||||
if (m_currentItem) {
|
||||
if (DebuggerEngine *engine = m_currentItem->m_engine) {
|
||||
previousContext.add(engine->languageContext());
|
||||
previousContext.add(engine->debuggerContext());
|
||||
} else {
|
||||
previousContext.add(Context(Constants::C_DEBUGGER_NOTRUNNING));
|
||||
}
|
||||
}
|
||||
if (m_currentItem == engineItem)
|
||||
return;
|
||||
|
||||
QTC_ASSERT(engineItem, return);
|
||||
m_currentItem = engineItem;
|
||||
|
||||
Context newContext;
|
||||
@@ -343,7 +351,13 @@ void EngineManagerPrivate::activateEngineItem(EngineItem *engineItem)
|
||||
}
|
||||
}
|
||||
|
||||
ICore::updateAdditionalContexts(previousContext, newContext);
|
||||
ICore::updateAdditionalContexts(m_currentAdditionalContext, newContext);
|
||||
m_currentAdditionalContext = newContext;
|
||||
|
||||
// In case this was triggered externally by some Perspective::select() call.
|
||||
const int idx = engineItem->indexInParent();
|
||||
m_engineChooser->setCurrentIndex(idx);
|
||||
|
||||
selectUiForCurrentEngine();
|
||||
}
|
||||
|
||||
@@ -352,12 +366,7 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
|
||||
if (ModeManager::currentModeId() != Constants::MODE_DEBUG)
|
||||
return;
|
||||
|
||||
Perspective *perspective = nullptr;
|
||||
int row = 0;
|
||||
|
||||
if (m_currentItem && m_currentItem->m_engine)
|
||||
perspective = m_currentItem->m_engine->perspective();
|
||||
|
||||
if (m_currentItem)
|
||||
row = m_engineModel.rootItem()->indexOf(m_currentItem);
|
||||
|
||||
@@ -371,12 +380,6 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
|
||||
QStyle::CT_ComboBox, &option, sz).width();
|
||||
m_engineChooser->setFixedWidth(width);
|
||||
|
||||
if (!perspective)
|
||||
perspective = Perspective::findPerspective(Debugger::Constants::PRESET_PERSPECTIVE_ID);
|
||||
|
||||
QTC_ASSERT(perspective, return);
|
||||
perspective->select();
|
||||
|
||||
m_engineModel.rootItem()->forFirstLevelChildren([this](EngineItem *engineItem) {
|
||||
if (engineItem && engineItem->m_engine)
|
||||
engineItem->m_engine->updateUi(engineItem == m_currentItem);
|
||||
@@ -392,12 +395,6 @@ EngineItem *EngineManagerPrivate::findEngineItem(DebuggerEngine *engine)
|
||||
});
|
||||
}
|
||||
|
||||
void EngineManagerPrivate::activateEngine(DebuggerEngine *engine)
|
||||
{
|
||||
EngineItem *engineItem = findEngineItem(engine);
|
||||
activateEngineItem(engineItem);
|
||||
}
|
||||
|
||||
void EngineManagerPrivate::updateEngineChooserVisibility()
|
||||
{
|
||||
// Show it if there's more than one option (i.e. not the preset engine only)
|
||||
@@ -407,12 +404,48 @@ void EngineManagerPrivate::updateEngineChooserVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
void EngineManager::registerEngine(DebuggerEngine *engine)
|
||||
void EngineManagerPrivate::updatePerspectives()
|
||||
{
|
||||
d->updateEngineChooserVisibility();
|
||||
|
||||
Perspective *current = DebuggerMainWindow::currentPerspective();
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_engineModel.rootItem()->forFirstLevelChildren([this, current](EngineItem *engineItem) {
|
||||
if (engineItem == m_currentItem)
|
||||
return;
|
||||
|
||||
bool shouldBeActive = false;
|
||||
if (engineItem->m_engine) {
|
||||
// Normal engine.
|
||||
shouldBeActive = engineItem->m_engine->perspective()->isCurrent();
|
||||
} else {
|
||||
// Preset.
|
||||
shouldBeActive = current->id() == Debugger::Constants::PRESET_PERSPECTIVE_ID;
|
||||
}
|
||||
|
||||
if (shouldBeActive && engineItem != m_currentItem)
|
||||
activateEngineItem(engineItem);
|
||||
});
|
||||
}
|
||||
|
||||
QString EngineManager::registerEngine(DebuggerEngine *engine)
|
||||
{
|
||||
auto engineItem = new EngineItem;
|
||||
engineItem->m_engine = engine;
|
||||
d->m_engineModel.rootItem()->appendChild(engineItem);
|
||||
d->updateEngineChooserVisibility();
|
||||
return QString::number(d->m_engineModel.rootItem()->childCount());
|
||||
}
|
||||
|
||||
void EngineManager::unregisterEngine(DebuggerEngine *engine)
|
||||
{
|
||||
EngineItem *engineItem = d->findEngineItem(engine);
|
||||
QTC_ASSERT(engineItem, return);
|
||||
d->m_engineModel.destroyItem(engineItem);
|
||||
d->updateEngineChooserVisibility();
|
||||
}
|
||||
|
||||
void EngineManager::activateDebugMode()
|
||||
@@ -435,33 +468,6 @@ void EngineManager::deactivateDebugMode()
|
||||
}
|
||||
}
|
||||
|
||||
bool EngineManager::isLastOf(const QString &type)
|
||||
{
|
||||
int count = 0;
|
||||
d->m_engineModel.rootItem()->forFirstLevelChildren([&](EngineItem *engineItem) {
|
||||
if (engineItem && engineItem->m_engine)
|
||||
count += (engineItem->m_engine->debuggerName() == type);
|
||||
});
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
void EngineManager::unregisterEngine(DebuggerEngine *engine)
|
||||
{
|
||||
if (ModeManager::currentModeId() == Constants::MODE_DEBUG) {
|
||||
if (Perspective *parent = Perspective::findPerspective(Constants::PRESET_PERSPECTIVE_ID))
|
||||
parent->select();
|
||||
}
|
||||
|
||||
d->activateEngineItem(d->m_engineModel.rootItem()->childAt(0)); // Preset.
|
||||
|
||||
// Could be that the run controls died before it was appended.
|
||||
if (auto engineItem = d->findEngineItem(engine))
|
||||
d->m_engineModel.destroyItem(engineItem);
|
||||
|
||||
d->updateEngineChooserVisibility();
|
||||
emit theEngineManager->currentEngineChanged();
|
||||
}
|
||||
|
||||
QList<QPointer<DebuggerEngine>> EngineManager::engines()
|
||||
{
|
||||
QList<QPointer<DebuggerEngine>> result;
|
||||
@@ -477,5 +483,18 @@ QPointer<DebuggerEngine> EngineManager::currentEngine()
|
||||
return d->m_currentItem ? d->m_currentItem->m_engine : nullptr;
|
||||
}
|
||||
|
||||
bool EngineManager::shutDown()
|
||||
{
|
||||
d->m_shuttingDown = true;
|
||||
bool anyEngineAborting = false;
|
||||
for (DebuggerEngine *engine : EngineManager::engines()) {
|
||||
if (engine && engine->state() != Debugger::DebuggerNotReady) {
|
||||
engine->abortDebugger();
|
||||
anyEngineAborting = true;
|
||||
}
|
||||
}
|
||||
return anyEngineAborting;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -45,17 +45,19 @@ public:
|
||||
static EngineManager *instance();
|
||||
static QAbstractItemModel *model();
|
||||
|
||||
static void registerEngine(DebuggerEngine *engine);
|
||||
static QString registerEngine(DebuggerEngine *engine);
|
||||
static void unregisterEngine(DebuggerEngine *engine);
|
||||
static void activateEngine(DebuggerEngine *engine);
|
||||
|
||||
static void activateDebugMode();
|
||||
static void deactivateDebugMode();
|
||||
static bool isLastOf(const QString &type);
|
||||
|
||||
static QList<QPointer<DebuggerEngine> > engines();
|
||||
static QPointer<DebuggerEngine> currentEngine();
|
||||
|
||||
static QWidget *engineChooser();
|
||||
static void updatePerspectives();
|
||||
|
||||
static bool shutDown(); // Return true if some engine is being forced to shut down.
|
||||
|
||||
signals:
|
||||
void engineStateChanged(DebuggerEngine *engine);
|
||||
|
||||
@@ -2952,7 +2952,7 @@ void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
|
||||
if (response.resultClass == ResultDone) {
|
||||
ThreadsHandler *handler = threadsHandler();
|
||||
handler->setThreads(response.data);
|
||||
updateState(false); // Adjust Threads combobox.
|
||||
updateState(); // Adjust Threads combobox.
|
||||
if (boolSetting(ShowThreadNames)) {
|
||||
runCommand({"threadnames " + action(MaximalStackDepth)->value().toString(),
|
||||
Discardable, CB(handleThreadNames)});
|
||||
@@ -2992,7 +2992,7 @@ void GdbEngine::handleThreadNames(const DebuggerResponse &response)
|
||||
thread.name = decodeData(name["value"].data(), name["valueencoded"].data());
|
||||
handler->updateThread(thread);
|
||||
}
|
||||
updateState(false);
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ public:
|
||||
|
||||
bool ModulesModel::contextMenuEvent(const ItemViewEvent &ev)
|
||||
{
|
||||
ModuleItem *item = itemForIndexAtLevel<1>(ev.index());
|
||||
ModuleItem *item = itemForIndexAtLevel<1>(ev.sourceModelIndex());
|
||||
|
||||
const bool enabled = engine->debuggerActionsEnabled();
|
||||
const bool canReload = engine->hasCapability(ReloadModuleCapability);
|
||||
|
||||
@@ -679,8 +679,8 @@ bool RegisterHandler::contextMenuEvent(const ItemViewEvent &ev)
|
||||
const DebuggerState state = m_engine->state();
|
||||
const bool actionsEnabled = m_engine->debuggerActionsEnabled();
|
||||
|
||||
RegisterItem *registerItem = itemForIndexAtLevel<1>(ev.index());
|
||||
RegisterSubItem *registerSubItem = itemForIndexAtLevel<2>(ev.index());
|
||||
RegisterItem *registerItem = itemForIndexAtLevel<1>(ev.sourceModelIndex());
|
||||
RegisterSubItem *registerSubItem = itemForIndexAtLevel<2>(ev.sourceModelIndex());
|
||||
|
||||
const quint64 address = registerItem ? registerItem->addressValue() : 0;
|
||||
const QString registerName = registerItem ? registerItem->m_reg.name : QString();
|
||||
|
||||
@@ -367,7 +367,7 @@ bool StackHandler::contextMenuEvent(const ItemViewEvent &ev)
|
||||
{
|
||||
auto menu = new QMenu;
|
||||
|
||||
const int row = ev.index().row();
|
||||
const int row = ev.sourceModelIndex().row();
|
||||
StackFrame frame;
|
||||
if (row >= 0 && row < stackSize())
|
||||
frame = frameAt(row);
|
||||
|
||||
@@ -1638,7 +1638,7 @@ void WatchModel::inputNewExpression()
|
||||
|
||||
bool WatchModel::contextMenuEvent(const ItemViewEvent &ev)
|
||||
{
|
||||
WatchItem *item = itemForIndex(ev.index());
|
||||
WatchItem *item = itemForIndex(ev.sourceModelIndex());
|
||||
|
||||
const QString exp = item ? item->expression() : QString();
|
||||
const QString name = item ? item->name : QString();
|
||||
|
||||
@@ -756,10 +756,16 @@ void QbsProject::updateDocuments(const QSet<QString> &files)
|
||||
}
|
||||
}
|
||||
QSet<IDocument *> toAdd;
|
||||
foreach (const QString &f, filesToAdd)
|
||||
toAdd.insert(new ProjectDocument(Constants::MIME_TYPE, FileName::fromString(f),
|
||||
[this]() { delayParsing(); }));
|
||||
|
||||
const FileName buildDir = FileName::fromString(m_projectData.buildDirectory());
|
||||
for (const QString &f : qAsConst(filesToAdd)) {
|
||||
// A changed qbs file (project, module etc) should trigger a re-parse, but not if
|
||||
// the file was generated by qbs itself, in which case that might cause an infinite loop.
|
||||
const FileName fp = FileName::fromString(f);
|
||||
static const ProjectDocument::ProjectCallback noOpCallback = []{};
|
||||
const ProjectDocument::ProjectCallback reparseCallback = [this]() { delayParsing(); };
|
||||
toAdd.insert(new ProjectDocument(Constants::MIME_TYPE, fp, fp.isChildOf(buildDir)
|
||||
? noOpCallback : reparseCallback));
|
||||
}
|
||||
m_qbsDocuments.unite(toAdd);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ QMakeStepConfig QMakeStep::deducedArguments() const
|
||||
|
||||
bool QMakeStep::init()
|
||||
{
|
||||
m_wasSuccess = true;
|
||||
QmakeBuildConfiguration *qmakeBc = qmakeBuildConfiguration();
|
||||
const BaseQtVersion *qtVersion = QtKitAspect::qtVersion(target()->kit());
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ QPixmap QmlDesignerIconProvider::getPixmap(const QString &id)
|
||||
else if (id == "plus")
|
||||
result = Utils::Icons::PLUS_TOOLBAR.pixmap();
|
||||
else if (id == "expression")
|
||||
result = Icon(iconPath() + "expression.png").pixmap();
|
||||
result = Icon({
|
||||
{ iconPath() + QLatin1String("expression.png"), Theme::QmlDesigner_HighlightColor}}).pixmap();
|
||||
else if (id == "placeholder")
|
||||
result = Icon(iconPath() + "placeholder.png").pixmap();
|
||||
else if (id == "submenu")
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <qmlanchors.h>
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <variantproperty.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
|
||||
#include <QtQml>
|
||||
#include <QDebug>
|
||||
@@ -108,13 +110,18 @@ void QmlAnchorBindingProxy::invalidate(const QmlItemNode &fxItemNode)
|
||||
|
||||
m_ignoreQml = true;
|
||||
|
||||
auto parentModelNode = [](const QmlItemNode &node) {
|
||||
QTC_ASSERT(node.modelNode().hasParentProperty(), return ModelNode());
|
||||
return node.modelNode().parentProperty().parentModelNode();
|
||||
};
|
||||
|
||||
m_verticalTarget =
|
||||
m_horizontalTarget =
|
||||
m_topTarget =
|
||||
m_bottomTarget =
|
||||
m_leftTarget =
|
||||
m_rightTarget =
|
||||
m_qmlItemNode.modelNode().parentProperty().parentModelNode();
|
||||
parentModelNode(m_qmlItemNode);
|
||||
|
||||
setupAnchorTargets();
|
||||
|
||||
|
||||
@@ -172,7 +172,8 @@ void TextEditorView::nodeIdChanged(const ModelNode& /*node*/, const QString &/*n
|
||||
void TextEditorView::selectedNodesChanged(const QList<ModelNode> &/*selectedNodeList*/,
|
||||
const QList<ModelNode> &/*lastSelectedNodeList*/)
|
||||
{
|
||||
m_widget->jumpTextCursorToSelectedModelNode();
|
||||
if (!m_errorState)
|
||||
m_widget->jumpTextCursorToSelectedModelNode();
|
||||
}
|
||||
|
||||
void TextEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList<ModelNode> &/*nodeList*/, const QList<QVariant> &/*data*/)
|
||||
@@ -187,9 +188,11 @@ void TextEditorView::documentMessagesChanged(const QList<DocumentMessage> &error
|
||||
{
|
||||
if (errors.isEmpty()) {
|
||||
m_widget->clearStatusBar();
|
||||
m_errorState = false;
|
||||
} else {
|
||||
const DocumentMessage &error = errors.constFirst();
|
||||
m_widget->setStatusText(QString("%1 (Line: %2)").arg(error.description()).arg(error.line()));
|
||||
m_errorState = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
private:
|
||||
QPointer<TextEditorWidget> m_widget;
|
||||
Internal::TextEditorContext *m_textEditorContext;
|
||||
bool m_errorState = false;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -108,15 +108,20 @@ void TextEditorWidget::updateSelectionByCursorPosition()
|
||||
const int cursorPosition = m_textEditor->editorWidget()->textCursor().position();
|
||||
RewriterView *rewriterView = m_textEditorView->model()->rewriterView();
|
||||
|
||||
m_blockRoundTrip = true;
|
||||
if (rewriterView) {
|
||||
ModelNode modelNode = rewriterView->nodeAtTextCursorPosition(cursorPosition);
|
||||
if (modelNode.isValid() && !m_textEditorView->isSelectedModelNode(modelNode))
|
||||
m_textEditorView->setSelectedModelNode(modelNode);
|
||||
}
|
||||
m_blockRoundTrip = false;
|
||||
}
|
||||
|
||||
void TextEditorWidget::jumpTextCursorToSelectedModelNode()
|
||||
{
|
||||
if (m_blockRoundTrip)
|
||||
return;
|
||||
|
||||
ModelNode selectedNode;
|
||||
|
||||
if (hasFocus())
|
||||
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
QTimer m_updateSelectionTimer;
|
||||
TextEditorStatusBar *m_statusBar;
|
||||
bool m_blockCursorSelectionSynchronisation = false;
|
||||
bool m_blockRoundTrip = false;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 108 B |
@@ -191,7 +191,7 @@ void GenericDirectUploadService::stopDeployment()
|
||||
QList<DeployableFile> GenericDirectUploadService::collectFilesToUpload(
|
||||
const DeployableFile &deployable) const
|
||||
{
|
||||
QList<DeployableFile> collected({deployable});
|
||||
QList<DeployableFile> collected;
|
||||
QFileInfo fileInfo = deployable.localFilePath().toFileInfo();
|
||||
if (fileInfo.isDir()) {
|
||||
const QStringList files = QDir(deployable.localFilePath().toString())
|
||||
@@ -203,6 +203,8 @@ QList<DeployableFile> GenericDirectUploadService::collectFilesToUpload(
|
||||
+ fileInfo.fileName();
|
||||
collected.append(collectFilesToUpload(DeployableFile(localFilePath, remoteDir)));
|
||||
}
|
||||
} else {
|
||||
collected << deployable;
|
||||
}
|
||||
return collected;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: id;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
width: 200
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
property bool pushed
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
|
||||
@@ -125,9 +125,7 @@ def handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms,
|
||||
test.log("Using build system '%s'" % buildSystem)
|
||||
selectFromCombo(combo, buildSystem)
|
||||
clickButton(waitForObject(":Next_QPushButton"))
|
||||
if template == "Qt Quick Application - Scroll":
|
||||
clickButton(waitForObject(":Next_QPushButton"))
|
||||
elif specialHandlingFunc:
|
||||
if specialHandlingFunc:
|
||||
specialHandlingFunc(displayedPlatforms, *args)
|
||||
verifyKitCheckboxes(kits, displayedPlatforms)
|
||||
safeClickButton("Cancel")
|
||||
|
||||
@@ -12646,8 +12646,6 @@
|
||||
"bundledqt.qbs:4" "3"
|
||||
"QPA plugin" "3"
|
||||
"bundledqt.qbs:65" "4"
|
||||
"Qt libraries" "3"
|
||||
"bundledqt.qbs:30" "4"
|
||||
"qt.conf" "3"
|
||||
"bundledqt.qbs:22" "4"
|
||||
"qt.conf" "4"
|
||||
|
||||
|
@@ -404,6 +404,39 @@ TEST_F(ClangFormat, IndentEmptyLineInsideParantheses)
|
||||
" && b)"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentInsideIf)
|
||||
{
|
||||
insertLines({"if (a && b",
|
||||
")"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("if (a && b",
|
||||
" )"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentInsideIf2)
|
||||
{
|
||||
insertLines({"if (a && b &&",
|
||||
")"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("if (a && b &&",
|
||||
" )"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentInsideIf3)
|
||||
{
|
||||
insertLines({"if (a || b",
|
||||
")"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("if (a || b",
|
||||
" )"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, EmptyLineInInitializerList)
|
||||
{
|
||||
insertLines({"Bar foo{a,",
|
||||
@@ -441,6 +474,31 @@ TEST_F(ClangFormat, DoNotIndentClosingBraceAfterSemicolon)
|
||||
"}"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterIf)
|
||||
{
|
||||
insertLines({"if (a)",
|
||||
""});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("if (a)",
|
||||
" "));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterElse)
|
||||
{
|
||||
insertLines({"if (a)",
|
||||
" foo();",
|
||||
"else",
|
||||
""});
|
||||
indenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("if (a)",
|
||||
" foo();",
|
||||
"else",
|
||||
" "));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, SameIndentAfterSecondNewLineAfterIf)
|
||||
{
|
||||
insertLines({"if (a)",
|
||||
@@ -504,6 +562,102 @@ TEST_F(ClangFormat, SameIndentsOnNewLinesAfterComments)
|
||||
""));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterEmptyLineAfterAngledIncludeDirective)
|
||||
{
|
||||
insertLines({"#include <string>",
|
||||
"",
|
||||
"using namespace std;"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("#include <string>",
|
||||
"",
|
||||
"using namespace std;"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterEmptyLineAfterQuotedIncludeDirective)
|
||||
{
|
||||
insertLines({"#include \"foo.h\"",
|
||||
"",
|
||||
"using namespace std;"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("#include \"foo.h\"",
|
||||
"",
|
||||
"using namespace std;"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterLineComment)
|
||||
{
|
||||
insertLines({"int foo()",
|
||||
"{",
|
||||
" // Comment",
|
||||
" ",
|
||||
" if (",
|
||||
"}"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("int foo()",
|
||||
"{",
|
||||
" // Comment",
|
||||
" ",
|
||||
" if (",
|
||||
"}"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterBlockComment)
|
||||
{
|
||||
insertLines({"int foo()",
|
||||
"{",
|
||||
" bar(); /* Comment */",
|
||||
" ",
|
||||
" if (",
|
||||
"}"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("int foo()",
|
||||
"{",
|
||||
" bar(); /* Comment */",
|
||||
" ",
|
||||
" if (",
|
||||
"}"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterIfdef)
|
||||
{
|
||||
insertLines({"int foo()",
|
||||
"{",
|
||||
"#ifdef FOO",
|
||||
"#endif",
|
||||
" ",
|
||||
" if (",
|
||||
"}"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(5), '(', TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("int foo()",
|
||||
"{",
|
||||
"#ifdef FOO",
|
||||
"#endif",
|
||||
" ",
|
||||
" if (",
|
||||
"}"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentAfterEmptyLineInTheFileBeginning)
|
||||
{
|
||||
insertLines({"",
|
||||
"void foo()"});
|
||||
|
||||
indenter.indentBlock(doc.findBlockByNumber(1), ')', TextEditor::TabSettings());
|
||||
|
||||
ASSERT_THAT(documentLines(), ElementsAre("",
|
||||
"void foo()"));
|
||||
}
|
||||
|
||||
TEST_F(ClangFormat, IndentFunctionBodyButNotFormatBeforeIt)
|
||||
{
|
||||
insertLines({"int foo(int a, int b,",
|
||||
|
||||