Commit 78513ecd authored by hjk's avatar hjk

Debugger: Split Expressions view into dock of its own

Change-Id: Ie86a5bd72c3140219f925835a065d9f6a3ae0ea4
Task-number: QTCREATORBUG-19167
Reviewed-by: Riitta-Leena Miettinen's avatarLeena Miettinen <>
Reviewed-by: Christian Stenger's avatarChristian Stenger <>
parent 0e1953a0
......@@ -639,8 +639,9 @@
If the address is displayed in the \uicontrol {Locals and Expressions} view,
you can select \uicontrol {Add Data Breakpoint at Object's Address} in the
If the address is displayed in the \uicontrol {Locals} or
\uicontrol {Expressions} view, you can select
\uicontrol {Add Data Breakpoint at Object's Address} in the
context menu to set the data breakpoint.
Data breakpoints will be disabled when the debugged program exits, as it
......@@ -665,8 +666,8 @@
corresponding source locations are grayed out in the \uicontrol Stack view.
If you click a frame with a known source location, the text editor jumps to
the corresponding location and updates the
\uicontrol {Locals and Expressions} view, making it seem like the program
the corresponding location and updates the \uicontrol {Locals} and
\uicontrol {Expressions} views, making it seem like the program
was interrupted before entering the function.
To find out which QML file is causing a Qt Quick 2 application to crash,
......@@ -676,28 +677,29 @@
should it find any. You can click a frame in the QML stack to open the QML
file in the editor.
\section1 Locals and Expressions
\section1 Local Variables and Function Parameters
The Locals and Expressions view consists of three parts: the
\uicontrol Locals pane at the top, the \uicontrol {Return Value} pane in
the middle, and the \uicontrol Expressions pane at the bottom. The
\uicontrol {Return Value} and \uicontrol Expression panes are only visible
if they are not empty.
The Locals view consists of two parts: the \uicontrol Locals pane at the top
and the \uicontrol {Return Value} pane at the bottom. The
\uicontrol {Return Value} is only visible if it is not empty.
\image qtcreator-locals-expressions.png "Locals and Expressions view"
\image qtcreator-locals-expressions.png "Locals view"
Whenever a program stops under the control of the debugger, it retrieves
information about the topmost stack frame and displays it in the
\uicontrol {Locals and Expressions} view. The \uicontrol Locals pane shows
\uicontrol {Locals} view. The \uicontrol Locals pane shows
information about parameters of the function in that frame as well as the
local variables. If the last operation in the debugger was returning from a
function after pressing \key {Shift+F11}, the \uicontrol {Return Value}
pane displays the value returned by the function.
\section1 Evaluating Expresssion
To compute values of arithmetic expressions or function calls, use
expression evaluators in the \uicontrol Expressions pane. To insert a new
expression evaluators in the \uicontrol Expressions view. To insert a new
expression evaluator, either double-click on an empty part of the
\uicontrol {Locals and Expressions} view, or select
\uicontrol {Expressions} or \uicontrol {Locals} view, or select
\uicontrol {Add New Expression Evaluator} from the context menu, or drag and
drop an expression from the code editor.
......@@ -734,8 +736,8 @@
\li GDB and LLDB, and therefore \QC's debugger, also work for optimized
builds on Linux and \macos. Optimization can lead to re-ordering
of instructions or removal of some local variables, causing the
\uicontrol {Locals and Expressions} view to show unexpected
\uicontrol {Locals} and \uicontrol {Expressions} view to show
unexpected data.
\li The debug information provided by GCC does not include enough
information about the time when a variable is initialized.
......@@ -747,8 +749,8 @@
The \uicontrol {Locals and Expressions} view also provides access to the
most powerful feature of the debugger: comprehensive display of data
The \uicontrol {Locals} and \uicontrol {Expressions} views also provide access
to the most powerful feature of the debugger: comprehensive display of data
belonging to Qt's basic objects. For example, in case of QObject, instead of
displaying a pointer to some private data structure, you see a list of
children, signals and slots.
......@@ -758,8 +760,8 @@
debugger displays access data for QFileInfo and provides access to the
"real" contents of QVariant.
Right-click in the \uicontrol {Locals and Expressions} view to open a
context menu that provides additional options for viewing data. The
Right-click in the \uicontrol {Locals} or the \uicontrol {Expressions} view
to open a context menu that provides additional options for viewing data. The
available options depend on the type of the current items, and are provided
by the \l{Using Debugging Helpers}{Debugging Helpers}. Typically,
string-like data, such as \c{QByteArray} and \c{std::string}, offer a
......@@ -770,8 +772,8 @@
example, to expand all the values of QMap, select
\uicontrol {Change Value Display Format} > \uicontrol Compact.
You can use the \uicontrol {Locals and Expressions} view to change the
contents of variables of simple data types, for example, \c int, \c float,
You can use the \uicontrol {Locals} and \uicontrol {Expressions} view to change
the contents of variables of simple data types, for example, \c int, \c float,
\c QString and \c std::string when the program is interrupted. To do so,
click the \uicontrol Value column, modify the value with the inplace editor,
and press \key Enter (or \key Return).
......@@ -798,7 +800,7 @@
\note Usually, you do not need this feature, because \QC provides you
with better ways to handle the task. For example, instead of using the GDB
\c print command from the command line, you can evaluate an expression in
the \uicontrol {Locals and Expressions} view.
the \uicontrol {Expressions} view.
\section1 Debugging C++ Based Applications
......@@ -932,8 +934,8 @@
\title Using Debugging Helpers
Structured data, such as objects of \c class, \c struct, or \c union
types, is displayed in the \uicontrol {Locals and Expressions} view as part
Structured data, such as objects of \c class, \c struct, or \c union types,
is displayed in the \uicontrol {Locals} and \uicontrol {Expressions} views as part
of a tree. To access sub-structures of the objects, expand the tree nodes.
The sub-structures are presented in their in-memory order, unless the
\uicontrol {Sort Members of Classes and Structs Alphabetically} option
......@@ -970,8 +972,8 @@
\QC uses Python scripts to translate raw memory contents and type information
data from native debugger backends (GDB, LLDB, and CDB are currently supported)
into the form presented to the user in the \uicontrol {Locals and Expressions}
into the form presented to the user in the \uicontrol {Locals} and
\uicontrol {Expressions} views.
Unlike GDB's
......@@ -149,7 +149,10 @@
\li \l{Viewing Call Stack Trace}{Viewing call stack trace}
\li \l{Locals and Expressions}{Viewing locals and expressions}
\li \l{Local Variables and Function Parameters}
{Viewing local variables and function parameters}
\li \l{Evaluating Expressions}{Evaluating expressions at run time}
......@@ -167,21 +170,21 @@
\section1 Applying QML Changes at Runtime
When you change property values in the \uicontrol {Debugger Console} or in the
\uicontrol {Locals and Expressions} view, they are immediately updated in the running
application, but not in the source code.
\uicontrol {Locals} or \uicontrol {Expression} view, they are immediately updated
in the running application, but not in the source code.
\section1 Inspecting Items
While the application is running, you can use the
\uicontrol {Locals and Expressions} view to explore the QML item structure.
While the application is running, you can use the \uicontrol {Locals}
and \uicontrol{Expressions} views to explore the QML item structure.
\image qml-observer-view.png "QML item tree"
To keep the application visible while you interact with the debugger, select
\uicontrol Debug > \uicontrol {Show Application on Top}.
You can view a QML item in \uicontrol {Locals and Expressions} in the following
You can view a QML item in \uicontrol {Locals} and \uicontrol {Expressions}
in the following ways:
......@@ -205,7 +208,7 @@
In the selection mode, you can click items in the running
application to jump to their definitions in the code. The properties of the
selected item are displayed in the \uicontrol {Locals and Expressions} view.
selected item are displayed in the \uicontrol {Locals} view.
The \uicontrol Select tool will be enabled either if your application is
using Qt 5.7 or later, or if your application is using an earlier version
......@@ -168,15 +168,14 @@
If an instance of a class is derived from QObject, and you would like to
find all other objects connected to one of your object's slots using
Qt's signals and slots mechanism, select \uicontrol Tools > \uicontrol Options
> \uicontrol{Debugger} > \uicontrol{Locals and Expressions} >
\uicontrol{Use Debugging Helper}.
> \uicontrol{Debugger} > \uicontrol{Locals} > \uicontrol{Use Debugging Helper}.
In the \uicontrol{Locals and Expressions} view, expand the object's entry and open
In the \uicontrol{Locals} view, expand the object's entry and open
the slot in the \e slots subitem. The objects connected to this slot are
shown as children of the slot. This method works with signals too.
For more information about the \uicontrol{Locals and Expressions} view, see
\l{Locals and Expressions}.
For more information about the \uicontrol{Locals} view, see
\l{Local Variables and Function Parameters}.
\section1 Displaying Low Level Data
......@@ -188,7 +187,7 @@
\list 1
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
\uicontrol{Locals and Expressions}.
\li Uncheck the \uicontrol{Use Debugging Helper} checkbox.
......@@ -216,8 +215,8 @@
\image qtcreator-pin-tooltip.png
Pinned tooltips are stored in the session. To close all pinned tooltips,
select \uicontrol {Close Editor Tooltips} in the context menu in the \uicontrol {Locals
and Expressions} view.
select \uicontrol {Close Editor Tooltips} in the context menu in the
\uicontrol {Locals} view.
\section1 Locating Files
......@@ -35,7 +35,6 @@
#include <functional>
class QIcon;
class QMessageBox;
class QWidget;
class QMenu;
......@@ -67,7 +66,7 @@ enum TestCases
// Some convenience.
void updateState(DebuggerRunTool *runTool);
void updateWatchersWindow(bool showWatch, bool showReturn);
void updateLocalsWindow(bool showReturn);
const CPlusPlus::Snapshot &cppCodeModelSnapshot();
bool hasSnapshots();
void openTextEditor(const QString &titlePattern, const QString &contents);
......@@ -83,6 +82,7 @@ void synchronizeBreakpoints();
void saveModeToRestore();
QWidget *mainWindow();
void raiseWatchersWindow();
bool isRegistersWindowVisible();
bool isModulesWindowVisible();
void showModuleSymbols(const QString &moduleName, const QVector<Internal::Symbol> &symbols);
......@@ -39,7 +39,8 @@ const char DOCKWIDGET_SNAPSHOTS[] = "Debugger.Docks.Snapshots";
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_WATCHERS[] = "Debugger.Docks.LocalsAndWatchers";
const char DOCKWIDGET_LOCALS_AND_INSPECTOR[] = "Debugger.Docks.LocalsAndInspector";
const char DOCKWIDGET_WATCHERS[] = "Debugger.Docks.Watchers";
} // namespace Internal
......@@ -51,6 +51,7 @@
#include <QMenu>
#include <QStackedWidget>
#include <QStandardItemModel>
#include <QTimer>
#include <QToolButton>
using namespace Debugger;
......@@ -127,6 +128,16 @@ QDockWidget *DebuggerMainWindow::dockWidget(const QByteArray &dockId) const
return m_dockForDockId.value(dockId);
void DebuggerMainWindow::raiseDock(const QByteArray &dockId)
QDockWidget *dock = m_dockForDockId.value(dockId);
QTC_ASSERT(dock, return);
QAction *act = dock->toggleViewAction();
if (!act->isChecked())
QTimer::singleShot(1, act, [act, dock] { act->trigger(); });
void DebuggerMainWindow::onModeChanged(Core::Id mode)
if (mode == Debugger::Constants::MODE_DEBUG) {
......@@ -131,6 +131,7 @@ public:
void showStatusMessage(const QString &message, int timeoutMS);
QDockWidget *dockWidget(const QByteArray &dockId) const;
void raiseDock(const QByteArray &dockId);
QByteArray currentPerspective() const { return m_currentPerspectiveId; }
QStackedWidget *centralWidgetStack() const { return m_centralWidgetStack; }
......@@ -695,12 +695,10 @@ public:
toggleBreakpoint(data, message);
void updateWatchersHeader(int section, int, int newSize)
void updateReturnViewHeader(int section, int, int newSize)
if (m_shuttingDown)
m_watchersView->header()->resizeSection(section, newSize);
m_returnView->header()->resizeSection(section, newSize);
......@@ -1036,7 +1034,7 @@ public:
QWidget *m_stackWindow = 0;
QWidget *m_threadsWindow = 0;
LogWindow *m_logWindow = 0;
LocalsAndExpressionsWindow *m_localsAndExpressionsWindow = 0;
LocalsAndInspectorWindow *m_localsAndInspectorWindow = 0;
bool m_busy;
QString m_lastPermanentStatusMessage;
......@@ -1369,18 +1367,19 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_threadsWindow = addSearch(m_threadsView, tr("&Threads"), DOCKWIDGET_THREADS);
m_returnView = new WatchTreeView(ReturnType); // No settings.
m_returnWindow = addSearch(m_returnView, tr("Locals and &Expressions"), "CppDebugReturn");
m_returnWindow = addSearch(m_returnView, tr("Locals"), "CppDebugReturn");
m_localsView = new WatchTreeView(LocalsType);
m_localsView->setSettings(settings, "Debugger.LocalsView");
m_localsWindow = addSearch(m_localsView, tr("Locals and &Expressions"), "CppDebugLocals");
m_watchersView = new WatchTreeView(WatchersType); // No settings.
m_watchersWindow = addSearch(m_watchersView, tr("Locals and &Expressions"), "CppDebugWatchers");
m_localsWindow = addSearch(m_localsView, tr("Locals"), "CppDebugLocals");
m_inspectorView = new WatchTreeView(InspectType);
m_inspectorView = new WatchTreeView(InspectType); // No settings.
m_inspectorView->setSettings(settings, "Debugger.LocalsView"); // sic! same as locals view.
m_inspectorWindow = addSearch(m_inspectorView, tr("Locals and &Expressions"), "Inspector");
m_inspectorWindow = addSearch(m_inspectorView, tr("Locals"), "Inspector");
m_watchersView = new WatchTreeView(WatchersType);
m_watchersView->setSettings(settings, "Debugger.WatchersView");
m_watchersWindow = addSearch(m_watchersView, tr("&Expressions"), "CppDebugWatchers");
// Snapshot
m_snapshotHandler = new SnapshotHandler;
......@@ -1390,9 +1389,9 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_snapshotWindow = addSearch(m_snapshotView, tr("Snapshots"), DOCKWIDGET_SNAPSHOTS);
// Watchers
// Locals
connect(m_localsView->header(), &QHeaderView::sectionResized,
this, &DebuggerPluginPrivate::updateWatchersHeader, Qt::QueuedConnection);
this, &DebuggerPluginPrivate::updateReturnViewHeader, Qt::QueuedConnection);
auto act = m_continueAction = new QAction(tr("Continue"), this);
act->setIcon(visibleStartIcon(Id(Constants::CONTINUE), false));
......@@ -1474,10 +1473,10 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
ActionContainer *debugMenu = ActionManager::actionContainer(PE::M_DEBUG);
m_localsAndExpressionsWindow = new LocalsAndExpressionsWindow(
m_localsWindow, m_inspectorWindow, m_returnWindow, m_watchersWindow);
m_localsAndInspectorWindow = new LocalsAndInspectorWindow(
m_localsWindow, m_inspectorWindow, m_returnWindow);
......@@ -1830,7 +1829,9 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
{DOCKWIDGET_MODULES, m_modulesWindow, DOCKWIDGET_THREADS, Perspective::AddToTab, false},
{DOCKWIDGET_SOURCE_FILES, m_sourceFilesWindow, DOCKWIDGET_MODULES, Perspective::AddToTab, false},
{DOCKWIDGET_SNAPSHOTS, m_snapshotWindow, DOCKWIDGET_SOURCE_FILES, Perspective::AddToTab, false},
{DOCKWIDGET_WATCHERS, m_localsAndExpressionsWindow, {}, Perspective::AddToTab, true,
{DOCKWIDGET_LOCALS_AND_INSPECTOR, m_localsAndInspectorWindow, {}, Perspective::AddToTab, true,
{DOCKWIDGET_OUTPUT, m_logWindow, {}, Perspective::AddToTab, false, Qt::TopDockWidgetArea},
{DOCKWIDGET_BREAK, 0, {}, Perspective::Raise}
......@@ -1865,7 +1866,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
return true;
......@@ -2491,7 +2491,6 @@ void DebuggerPluginPrivate::setBusyCursor(bool busy)
void DebuggerPluginPrivate::setInitialState()
......@@ -2575,7 +2574,7 @@ void DebuggerPluginPrivate::updateState(DebuggerRunTool *runTool)
setProxyAction(m_visibleStartAction, Id(Constants::CONTINUE));
} else if (state == InferiorRunOk) {
// Shift-F5 interrupts. It is also "interruptible".
......@@ -2585,7 +2584,7 @@ void DebuggerPluginPrivate::updateState(DebuggerRunTool *runTool)
setProxyAction(m_visibleStartAction, Id(Constants::INTERRUPT));
} else if (state == DebuggerFinished) {
const bool canRun = ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE);
// We don't want to do anything anymore.
......@@ -2609,7 +2608,7 @@ void DebuggerPluginPrivate::updateState(DebuggerRunTool *runTool)
// show locals in core dumps
} else {
// Everything else is "undisturbable".
......@@ -3143,9 +3142,8 @@ void updateState(DebuggerRunTool *runTool)
void updateWatchersWindow(bool showWatch, bool showReturn)
void updateLocalsWindow(bool showReturn)
......@@ -3203,6 +3201,11 @@ QWidget *mainWindow()
return dd->m_mainWindow;
void raiseWatchersWindow()
return dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS);
bool isRegistersWindowVisible()
return dd->m_registerWindow->isVisible();
......@@ -35,8 +35,8 @@ namespace Internal {
enum { LocalsIndex = 0, InspectorIndex = 1 };
LocalsAndExpressionsWindow::LocalsAndExpressionsWindow(QWidget *locals,
QWidget *inspector, QWidget *returnWidget, QWidget *watchers)
LocalsAndInspectorWindow::LocalsAndInspectorWindow(QWidget *locals,
QWidget *inspector, QWidget *returnWidget)
: m_showLocals(false)
auto layout = new QVBoxLayout(this);
......@@ -53,7 +53,6 @@ LocalsAndExpressionsWindow::LocalsAndExpressionsWindow(QWidget *locals,
splitter->setStretchFactor(0, 3);
splitter->setStretchFactor(2, 1);
......@@ -68,7 +67,7 @@ LocalsAndExpressionsWindow::LocalsAndExpressionsWindow(QWidget *locals,
void LocalsAndExpressionsWindow::setShowLocals(bool showLocals)
void LocalsAndInspectorWindow::setShowLocals(bool showLocals)
m_showLocals = showLocals;
......@@ -31,11 +31,11 @@
namespace Debugger {
namespace Internal {
class LocalsAndExpressionsWindow : public QWidget
class LocalsAndInspectorWindow : public QWidget
LocalsAndExpressionsWindow(QWidget *locals, QWidget *inspector,
QWidget *returnWidget, QWidget *watchers);
LocalsAndInspectorWindow(QWidget *locals, QWidget *inspector,
QWidget *returnWidget);
void setShowLocals(bool showLocals);
......@@ -1326,7 +1326,7 @@ void QmlEnginePrivate::handleEvaluateExpression(const QVariantMap &response,
void QmlEnginePrivate::lookup(const LookupItems &items)
......@@ -537,7 +537,7 @@ void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
m_objectToSelect = WatchItem::InvalidId;
......@@ -1127,7 +1127,7 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
if (item->iname.contains('.'))
return true;
case LocalsTypeFormatRole:
......@@ -2086,7 +2086,7 @@ void WatchHandler::notifyUpdateStarted(const UpdateParameters &updateParameters)
m_model->m_contentsValid = false;
void WatchHandler::notifyUpdateFinished()
......@@ -2111,7 +2111,7 @@ void WatchHandler::notifyUpdateFinished()
m_model->m_contentsValid = true;
emit m_model->updateFinished();
......@@ -2130,7 +2130,7 @@ void WatchModel::removeWatchItem(WatchItem *item)
QString WatchHandler::watcherName(const QString &exp)
......@@ -2162,7 +2162,8 @@ void WatchHandler::watchExpression(const QString &exp, const QString &name, bool
} else {
void WatchHandler::updateWatchExpression(WatchItem *item, const QString &newExp)
......@@ -2184,7 +2185,7 @@ void WatchHandler::updateWatchExpression(WatchItem *item, const QString &newExp)
} else {
// Watch something obtained from the editor.
......@@ -2340,16 +2341,14 @@ void WatchModel::clearWatches()
theWatcherCount = 0;
void WatchHandler::updateWatchersWindow()
void WatchHandler::updateLocalsWindow()
// Force show/hide of watchers and return view.
int showWatch = !theWatcherNames.isEmpty();
int showReturn = m_model->m_returnRoot->childCount() != 0;
Internal::updateWatchersWindow(showWatch, showReturn);
// Force show/hide of return view.
bool showReturn = m_model->m_returnRoot->childCount() != 0;
QStringList WatchHandler::watchedExpressions()
......@@ -103,7 +103,7 @@ public:
void resetLocation();
void setCurrentItem(const QString &iname);
void updateWatchersWindow();
void updateLocalsWindow();
bool insertItem(WatchItem *item); // Takes ownership, returns whether item was added, not overwritten.
void insertItems(const GdbMi &data);
......@@ -78,7 +78,7 @@ void WatchTreeView::setModel(QAbstractItemModel *model)
if (header()) {
if (m_type != LocalsType && m_type != InspectType)
if (m_type == ReturnType && m_type == TooltipType)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment