Merge remote-tracking branch 'origin/4.9'

Change-Id: I7d1912cd5c4d824fd40d3454c5f1bb796f2c21d8
This commit is contained in:
Orgad Shaneh
2019-04-07 20:40:29 +03:00
92 changed files with 1153 additions and 490 deletions
+1 -1
View File
@@ -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
+5
View File
@@ -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 -1
View File
@@ -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.
+2 -1
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

+17 -6
View File
@@ -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.
+1 -1
View File
@@ -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}.
*/
+5 -1
View File
@@ -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
*/
+73
View File
@@ -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]
*/
+9 -5
View File
@@ -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.
+10 -3
View File
@@ -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",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

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
+2 -2
View File
@@ -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>
+2 -3
View File
@@ -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")) {
+15 -1
View File
@@ -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
+2
View File
@@ -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;
};
+15
View File
@@ -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;
+4
View File
@@ -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);
+1 -1
View File
@@ -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 &currentBlock)
{
@@ -150,10 +155,42 @@ QChar findFirstNonWhitespaceCharacter(const QTextBlock &currentBlock)
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 &currentBlock,
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 &currentBlock,
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 &currentBlock)
@@ -181,20 +221,18 @@ bool nextBlockExistsAndEmpty(const QTextBlock &currentBlock)
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();
+5 -2
View File
@@ -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",
+10 -6
View 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)) {
+1
View File
@@ -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);
+3 -3
View File
@@ -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)
+54 -42
View 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();
}
+1 -1
View File
@@ -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 {
+425 -220
View File
@@ -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
+16 -8
View File
@@ -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;
};
+9 -10
View File
@@ -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();
+83 -64
View File
@@ -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
+5 -3
View File
@@ -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);
+2 -2
View File
@@ -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();
}
}
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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();
+10 -4
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

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;
+1 -1
View File
@@ -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"
1 text nestinglevel
12646 bundledqt.qbs:4 3
12647 QPA plugin 3
12648 bundledqt.qbs:65 4
Qt libraries 3
bundledqt.qbs:30 4
12649 qt.conf 3
12650 bundledqt.qbs:22 4
12651 qt.conf 4
+154
View File
@@ -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,",