forked from qt-creator/qt-creator
debugger: first shot a implementing data watchpoints
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "debuggeractions.h"
|
#include "debuggeractions.h"
|
||||||
#include "debuggermanager.h"
|
#include "debuggermanager.h"
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
#include "stackframe.h"
|
#include "stackframe.h"
|
||||||
|
|
||||||
#include <texteditor/basetextmark.h>
|
#include <texteditor/basetextmark.h>
|
||||||
@@ -53,13 +54,11 @@ using namespace Debugger::Internal;
|
|||||||
// Compare file names case insensitively on Windows.
|
// Compare file names case insensitively on Windows.
|
||||||
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
||||||
{
|
{
|
||||||
return f1.compare(f2,
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
Qt::CaseInsensitive
|
return f1.compare(f2, Qt::CaseInsensitive) == 0;
|
||||||
#else
|
#else
|
||||||
Qt::CaseSensitive
|
return f1 == f2;
|
||||||
#endif
|
#endif
|
||||||
) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
@@ -87,7 +86,7 @@ public:
|
|||||||
|
|
||||||
QIcon icon() const
|
QIcon icon() const
|
||||||
{
|
{
|
||||||
const BreakHandler *handler = DebuggerManager::instance()->breakHandler();
|
const BreakHandler *handler = m_data->handler();
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return handler->disabledBreakpointIcon();
|
return handler->disabledBreakpointIcon();
|
||||||
return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon();
|
return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon();
|
||||||
@@ -162,28 +161,21 @@ private:
|
|||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
BreakpointData::BreakpointData(BreakHandler *handler)
|
BreakpointData::BreakpointData()
|
||||||
{
|
{
|
||||||
//qDebug() << "CREATE BREAKPOINTDATA" << this;
|
m_handler = 0;
|
||||||
m_handler = handler;
|
|
||||||
enabled = true;
|
enabled = true;
|
||||||
pending = true;
|
pending = true;
|
||||||
|
type = BreakpointType;
|
||||||
marker = 0;
|
marker = 0;
|
||||||
m_markerLineNumber = 0;
|
m_markerLineNumber = 0;
|
||||||
bpMultiple = false;
|
bpMultiple = false;
|
||||||
//#if defined(Q_OS_MAC)
|
|
||||||
// // full names do not work on Mac/MI
|
|
||||||
useFullPath = false;
|
useFullPath = false;
|
||||||
//#else
|
|
||||||
// //where = m_manager->shortName(data->fileName);
|
|
||||||
// useFullPath = true;
|
|
||||||
//#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BreakpointData::~BreakpointData()
|
BreakpointData::~BreakpointData()
|
||||||
{
|
{
|
||||||
removeMarker();
|
removeMarker();
|
||||||
//qDebug() << "DESTROY BREAKPOINTDATA" << this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakpointData::removeMarker()
|
void BreakpointData::removeMarker()
|
||||||
@@ -227,8 +219,6 @@ QString BreakpointData::toToolTip() const
|
|||||||
<< "</td><td>" << m_markerLineNumber << "</td></tr>"
|
<< "</td><td>" << m_markerLineNumber << "</td></tr>"
|
||||||
<< "<tr><td>" << BreakHandler::tr("Breakpoint Number:")
|
<< "<tr><td>" << BreakHandler::tr("Breakpoint Number:")
|
||||||
<< "</td><td>" << bpNumber << "</td></tr>"
|
<< "</td><td>" << bpNumber << "</td></tr>"
|
||||||
<< "<tr><td>" << BreakHandler::tr("Breakpoint Address:")
|
|
||||||
<< "</td><td>" << bpAddress << "</td></tr>"
|
|
||||||
<< "</table><br><hr><table>"
|
<< "</table><br><hr><table>"
|
||||||
<< "<tr><th>" << BreakHandler::tr("Property")
|
<< "<tr><th>" << BreakHandler::tr("Property")
|
||||||
<< "</th><th>" << BreakHandler::tr("Requested")
|
<< "</th><th>" << BreakHandler::tr("Requested")
|
||||||
@@ -241,6 +231,8 @@ QString BreakpointData::toToolTip() const
|
|||||||
<< "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>"
|
<< "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>"
|
||||||
<< "<tr><td>" << BreakHandler::tr("Line Number:")
|
<< "<tr><td>" << BreakHandler::tr("Line Number:")
|
||||||
<< "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>"
|
<< "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>"
|
||||||
|
<< "<tr><td>" << BreakHandler::tr("Breakpoint Address:")
|
||||||
|
<< "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>"
|
||||||
<< "<tr><td>" << BreakHandler::tr("Corrected Line Number:")
|
<< "<tr><td>" << BreakHandler::tr("Corrected Line Number:")
|
||||||
<< "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>"
|
<< "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>"
|
||||||
<< "<tr><td>" << BreakHandler::tr("Condition:")
|
<< "<tr><td>" << BreakHandler::tr("Condition:")
|
||||||
@@ -260,13 +252,14 @@ QString BreakpointData::toString() const
|
|||||||
str << BreakHandler::tr("Marker File:") << m_markerFileName << ' '
|
str << BreakHandler::tr("Marker File:") << m_markerFileName << ' '
|
||||||
<< BreakHandler::tr("Marker Line:") << m_markerLineNumber << ' '
|
<< BreakHandler::tr("Marker Line:") << m_markerLineNumber << ' '
|
||||||
<< BreakHandler::tr("Breakpoint Number:") << bpNumber << ' '
|
<< BreakHandler::tr("Breakpoint Number:") << bpNumber << ' '
|
||||||
<< BreakHandler::tr("Breakpoint Address:") << bpAddress << '\n'
|
|
||||||
<< BreakHandler::tr("File Name:")
|
<< BreakHandler::tr("File Name:")
|
||||||
<< fileName << " -- " << bpFileName << '\n'
|
<< fileName << " -- " << bpFileName << '\n'
|
||||||
<< BreakHandler::tr("Function Name:")
|
<< BreakHandler::tr("Function Name:")
|
||||||
<< funcName << " -- " << bpFuncName << '\n'
|
<< funcName << " -- " << bpFuncName << '\n'
|
||||||
<< BreakHandler::tr("Line Number:")
|
<< BreakHandler::tr("Line Number:")
|
||||||
<< lineNumber << " -- " << bpLineNumber << '\n'
|
<< lineNumber << " -- " << bpLineNumber << '\n'
|
||||||
|
<< BreakHandler::tr("Breakpoint Address:")
|
||||||
|
<< address << " -- " << bpAddress << '\n'
|
||||||
<< BreakHandler::tr("Condition:")
|
<< BreakHandler::tr("Condition:")
|
||||||
<< condition << " -- " << bpCondition << '\n'
|
<< condition << " -- " << bpCondition << '\n'
|
||||||
<< BreakHandler::tr("Ignore Count:")
|
<< BreakHandler::tr("Ignore Count:")
|
||||||
@@ -310,9 +303,10 @@ bool BreakpointData::conditionsMatch() const
|
|||||||
|
|
||||||
BreakHandler::BreakHandler(DebuggerManager *manager, QObject *parent) :
|
BreakHandler::BreakHandler(DebuggerManager *manager, QObject *parent) :
|
||||||
QAbstractTableModel(parent),
|
QAbstractTableModel(parent),
|
||||||
m_breakpointIcon(QLatin1String(":/debugger/images/breakpoint_16.png")),
|
m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")),
|
||||||
m_disabledBreakpointIcon(QLatin1String(":/debugger/images/breakpoint_disabled_16.png")),
|
m_disabledBreakpointIcon(_(":/debugger/images/breakpoint_disabled_16.png")),
|
||||||
m_pendingBreakPointIcon(QLatin1String(":/debugger/images/breakpoint_pending_16.png")),
|
m_pendingBreakPointIcon(_(":/debugger/images/breakpoint_pending_16.png")),
|
||||||
|
m_watchpointIcon(_(":/debugger/images/watchpoint.png")),
|
||||||
m_manager(manager)
|
m_manager(manager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -412,22 +406,29 @@ void BreakHandler::saveBreakpoints()
|
|||||||
for (int index = 0; index != size(); ++index) {
|
for (int index = 0; index != size(); ++index) {
|
||||||
const BreakpointData *data = at(index);
|
const BreakpointData *data = at(index);
|
||||||
QMap<QString, QVariant> map;
|
QMap<QString, QVariant> map;
|
||||||
|
// Do not persist Watchpoints.
|
||||||
|
//if (data->type == BreakpointData::WatchpointType)
|
||||||
|
// continue;
|
||||||
|
if (data->type != BreakpointData::BreakpointType)
|
||||||
|
map.insert(_("type"), data->type);
|
||||||
if (!data->fileName.isEmpty())
|
if (!data->fileName.isEmpty())
|
||||||
map.insert(QLatin1String("filename"), data->fileName);
|
map.insert(_("filename"), data->fileName);
|
||||||
if (!data->lineNumber.isEmpty())
|
if (!data->lineNumber.isEmpty())
|
||||||
map.insert(QLatin1String("linenumber"), data->lineNumber);
|
map.insert(_("linenumber"), data->lineNumber);
|
||||||
if (!data->funcName.isEmpty())
|
if (!data->funcName.isEmpty())
|
||||||
map.insert(QLatin1String("funcname"), data->funcName);
|
map.insert(_("funcname"), data->funcName);
|
||||||
|
if (!data->address.isEmpty())
|
||||||
|
map.insert(_("address"), data->address);
|
||||||
if (!data->condition.isEmpty())
|
if (!data->condition.isEmpty())
|
||||||
map.insert(QLatin1String("condition"), data->condition);
|
map.insert(_("condition"), data->condition);
|
||||||
if (!data->ignoreCount.isEmpty())
|
if (!data->ignoreCount.isEmpty())
|
||||||
map.insert(QLatin1String("ignorecount"), data->ignoreCount);
|
map.insert(_("ignorecount"), data->ignoreCount);
|
||||||
if (!data->threadSpec.isEmpty())
|
if (!data->threadSpec.isEmpty())
|
||||||
map.insert(QLatin1String("threadspec"), data->threadSpec);
|
map.insert(_("threadspec"), data->threadSpec);
|
||||||
if (!data->enabled)
|
if (!data->enabled)
|
||||||
map.insert(QLatin1String("disabled"), QLatin1String("1"));
|
map.insert(_("disabled"), _("1"));
|
||||||
if (data->useFullPath)
|
if (data->useFullPath)
|
||||||
map.insert(QLatin1String("usefullpath"), QLatin1String("1"));
|
map.insert(_("usefullpath"), _("1"));
|
||||||
list.append(map);
|
list.append(map);
|
||||||
}
|
}
|
||||||
m_manager->setSessionValue("Breakpoints", list);
|
m_manager->setSessionValue("Breakpoints", list);
|
||||||
@@ -440,31 +441,37 @@ void BreakHandler::loadBreakpoints()
|
|||||||
clear();
|
clear();
|
||||||
foreach (const QVariant &var, list) {
|
foreach (const QVariant &var, list) {
|
||||||
const QMap<QString, QVariant> map = var.toMap();
|
const QMap<QString, QVariant> map = var.toMap();
|
||||||
BreakpointData *data = new BreakpointData(this);
|
BreakpointData *data = new BreakpointData;
|
||||||
QVariant v = map.value(QLatin1String("filename"));
|
QVariant v = map.value(_("filename"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->fileName = v.toString();
|
data->fileName = v.toString();
|
||||||
v = map.value(QLatin1String("linenumber"));
|
v = map.value(_("linenumber"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->lineNumber = v.toString().toLatin1();
|
data->lineNumber = v.toString().toLatin1();
|
||||||
v = map.value(QLatin1String("condition"));
|
v = map.value(_("condition"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->condition = v.toString().toLatin1();
|
data->condition = v.toString().toLatin1();
|
||||||
v = map.value(QLatin1String("ignorecount"));
|
v = map.value(_("address"));
|
||||||
|
if (v.isValid())
|
||||||
|
data->address = v.toString().toLatin1();
|
||||||
|
v = map.value(_("ignorecount"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->ignoreCount = v.toString().toLatin1();
|
data->ignoreCount = v.toString().toLatin1();
|
||||||
v = map.value(QLatin1String("threadspec"));
|
v = map.value(_("threadspec"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->threadSpec = v.toString().toLatin1();
|
data->threadSpec = v.toString().toLatin1();
|
||||||
v = map.value(QLatin1String("funcname"));
|
v = map.value(_("funcname"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->funcName = v.toString();
|
data->funcName = v.toString();
|
||||||
v = map.value(QLatin1String("disabled"));
|
v = map.value(_("disabled"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->enabled = !v.toInt();
|
data->enabled = !v.toInt();
|
||||||
v = map.value(QLatin1String("usefullpath"));
|
v = map.value(_("usefullpath"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data->useFullPath = bool(v.toInt());
|
data->useFullPath = bool(v.toInt());
|
||||||
|
v = map.value(_("type"));
|
||||||
|
if (v.isValid())
|
||||||
|
data->type = BreakpointData::Type(v.toInt());
|
||||||
data->setMarkerFileName(data->fileName);
|
data->setMarkerFileName(data->fileName);
|
||||||
data->setMarkerLineNumber(data->lineNumber.toInt());
|
data->setMarkerLineNumber(data->lineNumber.toInt());
|
||||||
append(data);
|
append(data);
|
||||||
@@ -538,6 +545,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
|||||||
if (role == Qt::UserRole)
|
if (role == Qt::UserRole)
|
||||||
return data->enabled;
|
return data->enabled;
|
||||||
if (role == Qt::DecorationRole) {
|
if (role == Qt::DecorationRole) {
|
||||||
|
if (data->type == BreakpointData::WatchpointType)
|
||||||
|
return m_watchpointIcon;
|
||||||
if (!data->enabled)
|
if (!data->enabled)
|
||||||
return m_disabledBreakpointIcon;
|
return m_disabledBreakpointIcon;
|
||||||
return data->pending ? m_pendingBreakPointIcon : m_breakpointIcon;
|
return data->pending ? m_pendingBreakPointIcon : m_breakpointIcon;
|
||||||
@@ -606,8 +615,11 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
|||||||
if (role == Qt::UserRole + 1)
|
if (role == Qt::UserRole + 1)
|
||||||
return data->threadSpec;
|
return data->threadSpec;
|
||||||
case 7:
|
case 7:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole) {
|
||||||
|
if (data->type == BreakpointData::WatchpointType)
|
||||||
|
return data->address;
|
||||||
return data->bpAddress;
|
return data->bpAddress;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (role == Qt::ToolTipRole)
|
if (role == Qt::ToolTipRole)
|
||||||
@@ -706,6 +718,7 @@ bool BreakHandler::setData(const QModelIndex &mi, const QVariant &value, int rol
|
|||||||
|
|
||||||
void BreakHandler::append(BreakpointData *data)
|
void BreakHandler::append(BreakpointData *data)
|
||||||
{
|
{
|
||||||
|
data->m_handler = this;
|
||||||
m_bp.append(data);
|
m_bp.append(data);
|
||||||
m_inserted.append(data);
|
m_inserted.append(data);
|
||||||
}
|
}
|
||||||
@@ -823,7 +836,7 @@ void BreakHandler::breakByFunction(const QString &functionName)
|
|||||||
&& data->ignoreCount.isEmpty())
|
&& data->ignoreCount.isEmpty())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BreakpointData *data = new BreakpointData(this);
|
BreakpointData *data = new BreakpointData;
|
||||||
data->funcName = functionName;
|
data->funcName = functionName;
|
||||||
append(data);
|
append(data);
|
||||||
saveBreakpoints();
|
saveBreakpoints();
|
||||||
|
|||||||
@@ -30,90 +30,15 @@
|
|||||||
#ifndef DEBUGGER_BREAKHANDLER_H
|
#ifndef DEBUGGER_BREAKHANDLER_H
|
||||||
#define DEBUGGER_BREAKHANDLER_H
|
#define DEBUGGER_BREAKHANDLER_H
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QAbstractTableModel>
|
#include <QtCore/QAbstractTableModel>
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
class DebuggerManager;
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class BreakpointMarker;
|
|
||||||
class BreakHandler;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// BreakpointData
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class BreakpointData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit BreakpointData(BreakHandler *handler);
|
|
||||||
~BreakpointData();
|
|
||||||
|
|
||||||
void removeMarker();
|
|
||||||
void updateMarker();
|
|
||||||
QString toToolTip() const;
|
|
||||||
QString toString() const;
|
|
||||||
BreakHandler *handler() { return m_handler; }
|
|
||||||
|
|
||||||
bool isLocatedAt(const QString &fileName, int lineNumber) const;
|
|
||||||
bool conditionsMatch() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Intentionally unimplemented.
|
|
||||||
// Making it copyable is tricky because of the markers.
|
|
||||||
void operator=(const BreakpointData &);
|
|
||||||
BreakpointData(const BreakpointData &);
|
|
||||||
|
|
||||||
// Our owner
|
|
||||||
BreakHandler *m_handler; // Not owned.
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool enabled; // Should we talk to the debugger engine?
|
|
||||||
bool pending; // Does the debugger engine know about us already?
|
|
||||||
|
|
||||||
// This "user requested information" will get stored in the session.
|
|
||||||
QString fileName; // Short name of source file.
|
|
||||||
QByteArray condition; // Condition associated with breakpoint.
|
|
||||||
QByteArray ignoreCount; // Ignore count associated with breakpoint.
|
|
||||||
QByteArray lineNumber; // Line in source file.
|
|
||||||
QByteArray threadSpec; // Thread specification.
|
|
||||||
QString funcName; // Name of containing function.
|
|
||||||
bool useFullPath; // Should we use the full path when setting the bp?
|
|
||||||
|
|
||||||
// This is what gdb produced in response.
|
|
||||||
QByteArray bpNumber; // Breakpoint number assigned by the debugger engine.
|
|
||||||
QByteArray bpCondition; // Condition acknowledged by the debugger engine.
|
|
||||||
QByteArray bpIgnoreCount;// Ignore count acknowledged by the debugger engine.
|
|
||||||
QString bpFileName; // File name acknowledged by the debugger engine.
|
|
||||||
QString bpFullName; // Full file name acknowledged by the debugger engine.
|
|
||||||
QByteArray bpLineNumber; // Line number acknowledged by the debugger engine.
|
|
||||||
QByteArray bpCorrectedLineNumber; // Acknowledged by the debugger engine.
|
|
||||||
QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine.
|
|
||||||
QString bpFuncName; // Function name acknowledged by the debugger engine.
|
|
||||||
QByteArray bpAddress; // Address acknowledged by the debugger engine.
|
|
||||||
bool bpMultiple; // Happens in constructors/gdb.
|
|
||||||
bool bpEnabled; // Enable/disable command sent.
|
|
||||||
|
|
||||||
void setMarkerFileName(const QString &fileName);
|
|
||||||
QString markerFileName() const { return m_markerFileName; }
|
|
||||||
|
|
||||||
void setMarkerLineNumber(int lineNumber);
|
|
||||||
int markerLineNumber() const { return m_markerLineNumber; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Taken from either user input or gdb responses.
|
|
||||||
QString m_markerFileName; // Used to locate the marker.
|
|
||||||
int m_markerLineNumber;
|
|
||||||
|
|
||||||
// Our red blob in the editor.
|
|
||||||
BreakpointMarker *marker;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// BreakHandler
|
// BreakHandler
|
||||||
@@ -184,6 +109,7 @@ private:
|
|||||||
const QIcon m_breakpointIcon;
|
const QIcon m_breakpointIcon;
|
||||||
const QIcon m_disabledBreakpointIcon;
|
const QIcon m_disabledBreakpointIcon;
|
||||||
const QIcon m_pendingBreakPointIcon;
|
const QIcon m_pendingBreakPointIcon;
|
||||||
|
const QIcon m_watchpointIcon;
|
||||||
|
|
||||||
DebuggerManager *m_manager; // Not owned.
|
DebuggerManager *m_manager; // Not owned.
|
||||||
QList<BreakpointData *> m_bp;
|
QList<BreakpointData *> m_bp;
|
||||||
|
|||||||
123
src/plugins/debugger/breakpoint.h
Normal file
123
src/plugins/debugger/breakpoint.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** Commercial Usage
|
||||||
|
**
|
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||||
|
** accordance with the Qt Commercial License Agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** If you are unsure which license is appropriate for your use, please
|
||||||
|
** contact the sales department at http://qt.nokia.com/contact.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DEBUGGER_BREAKPOINT_H
|
||||||
|
#define DEBUGGER_BREAKPOINT_H
|
||||||
|
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
class DebuggerManager;
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class BreakpointMarker;
|
||||||
|
class BreakHandler;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// BreakpointData
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class BreakpointData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BreakpointData();
|
||||||
|
~BreakpointData();
|
||||||
|
|
||||||
|
void removeMarker();
|
||||||
|
void updateMarker();
|
||||||
|
QString toToolTip() const;
|
||||||
|
QString toString() const;
|
||||||
|
BreakHandler *handler() { return m_handler; }
|
||||||
|
|
||||||
|
bool isLocatedAt(const QString &fileName, int lineNumber) const;
|
||||||
|
bool conditionsMatch() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Intentionally unimplemented.
|
||||||
|
// Making it copyable is tricky because of the markers.
|
||||||
|
void operator=(const BreakpointData &);
|
||||||
|
BreakpointData(const BreakpointData &);
|
||||||
|
|
||||||
|
// Our owner
|
||||||
|
BreakHandler *m_handler; // Not owned.
|
||||||
|
friend class BreakHandler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Type { BreakpointType, WatchpointType };
|
||||||
|
|
||||||
|
bool enabled; // Should we talk to the debugger engine?
|
||||||
|
bool pending; // Does the debugger engine know about us already?
|
||||||
|
Type type; // Type of breakpoint.
|
||||||
|
|
||||||
|
// This "user requested information" will get stored in the session.
|
||||||
|
QString fileName; // Short name of source file.
|
||||||
|
QByteArray condition; // Condition associated with breakpoint.
|
||||||
|
QByteArray ignoreCount; // Ignore count associated with breakpoint.
|
||||||
|
QByteArray lineNumber; // Line in source file.
|
||||||
|
QByteArray address; // Address for watchpoints.
|
||||||
|
QByteArray threadSpec; // Thread specification.
|
||||||
|
QString funcName; // Name of containing function.
|
||||||
|
bool useFullPath; // Should we use the full path when setting the bp?
|
||||||
|
|
||||||
|
// This is what gdb produced in response.
|
||||||
|
QByteArray bpNumber; // Breakpoint number assigned by the debugger engine.
|
||||||
|
QByteArray bpCondition; // Condition acknowledged by the debugger engine.
|
||||||
|
QByteArray bpIgnoreCount;// Ignore count acknowledged by the debugger engine.
|
||||||
|
QString bpFileName; // File name acknowledged by the debugger engine.
|
||||||
|
QString bpFullName; // Full file name acknowledged by the debugger engine.
|
||||||
|
QByteArray bpLineNumber; // Line number acknowledged by the debugger engine.
|
||||||
|
QByteArray bpCorrectedLineNumber; // Acknowledged by the debugger engine.
|
||||||
|
QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine.
|
||||||
|
QString bpFuncName; // Function name acknowledged by the debugger engine.
|
||||||
|
QByteArray bpAddress; // Address acknowledged by the debugger engine.
|
||||||
|
bool bpMultiple; // Happens in constructors/gdb.
|
||||||
|
bool bpEnabled; // Enable/disable command sent.
|
||||||
|
|
||||||
|
void setMarkerFileName(const QString &fileName);
|
||||||
|
QString markerFileName() const { return m_markerFileName; }
|
||||||
|
|
||||||
|
void setMarkerLineNumber(int lineNumber);
|
||||||
|
int markerLineNumber() const { return m_markerLineNumber; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Taken from either user input or gdb responses.
|
||||||
|
QString m_markerFileName; // Used to locate the marker.
|
||||||
|
int m_markerLineNumber;
|
||||||
|
|
||||||
|
// Our red blob in the editor.
|
||||||
|
BreakpointMarker *marker;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
#endif // DEBUGGER_BREAKPOINT_H
|
||||||
@@ -355,29 +355,30 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list)
|
|||||||
ui.labelFileName->hide();
|
ui.labelFileName->hide();
|
||||||
ui.lineEditLineNumber->hide();
|
ui.lineEditLineNumber->hide();
|
||||||
ui.labelLineNumber->hide();
|
ui.labelLineNumber->hide();
|
||||||
|
QAbstractItemModel *m = model();
|
||||||
//ui.lineEditFunction->setText(
|
//ui.lineEditFunction->setText(
|
||||||
// model()->data(idx.sibling(row, 1), role).toString());
|
// m->data(idx.sibling(row, 1), role).toString());
|
||||||
//ui.lineEditFileName->setText(
|
//ui.lineEditFileName->setText(
|
||||||
// model()->data(idx.sibling(row, 2), role).toString());
|
// m->data(idx.sibling(row, 2), role).toString());
|
||||||
//ui.lineEditLineNumber->setText(
|
//ui.lineEditLineNumber->setText(
|
||||||
// model()->data(idx.sibling(row, 3), role).toString());
|
// m->data(idx.sibling(row, 3), role).toString());
|
||||||
ui.lineEditCondition->setText(
|
ui.lineEditCondition->setText(
|
||||||
model()->data(idx.sibling(row, 4), role).toString());
|
m->data(idx.sibling(row, 4), role).toString());
|
||||||
ui.lineEditIgnoreCount->setText(
|
ui.lineEditIgnoreCount->setText(
|
||||||
model()->data(idx.sibling(row, 5), role).toString());
|
m->data(idx.sibling(row, 5), role).toString());
|
||||||
ui.lineEditThreadSpec->setText(
|
ui.lineEditThreadSpec->setText(
|
||||||
model()->data(idx.sibling(row, 6), role).toString());
|
m->data(idx.sibling(row, 6), role).toString());
|
||||||
|
|
||||||
if (dlg.exec() == QDialog::Rejected)
|
if (dlg.exec() == QDialog::Rejected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (const QModelIndex &idx, list) {
|
foreach (const QModelIndex &idx, list) {
|
||||||
//model()->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text());
|
//m->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text());
|
||||||
//model()->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text());
|
//m->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text());
|
||||||
//model()->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text());
|
//m->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text());
|
||||||
model()->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
|
m->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
|
||||||
model()->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text());
|
m->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text());
|
||||||
model()->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text());
|
m->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text());
|
||||||
}
|
}
|
||||||
emit breakpointSynchronizationRequested();
|
emit breakpointSynchronizationRequested();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ QT += gui \
|
|||||||
script
|
script
|
||||||
HEADERS += breakhandler.h \
|
HEADERS += breakhandler.h \
|
||||||
breakwindow.h \
|
breakwindow.h \
|
||||||
|
breakpoint.h \
|
||||||
debuggeragents.h \
|
debuggeragents.h \
|
||||||
debuggeractions.h \
|
debuggeractions.h \
|
||||||
debuggerconstants.h \
|
debuggerconstants.h \
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<file>images/debugger_stepoverproc_small.png</file>
|
<file>images/debugger_stepoverproc_small.png</file>
|
||||||
<file>images/debugger_stop.png</file>
|
<file>images/debugger_stop.png</file>
|
||||||
<file>images/debugger_stop_small.png</file>
|
<file>images/debugger_stop_small.png</file>
|
||||||
|
<file>images/watchpoint.png</file>
|
||||||
<file>images/breakpoint_16.png</file>
|
<file>images/breakpoint_16.png</file>
|
||||||
<file>images/breakpoint_24.png</file>
|
<file>images/breakpoint_24.png</file>
|
||||||
<file>images/breakpoint_disabled_16.png</file>
|
<file>images/breakpoint_disabled_16.png</file>
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ enum DebuggerCapabilities
|
|||||||
BreakOnThrowAndCatchCapability = 0x200,
|
BreakOnThrowAndCatchCapability = 0x200,
|
||||||
ReturnFromFunctionCapability = 0x400,
|
ReturnFromFunctionCapability = 0x400,
|
||||||
CreateFullBacktraceCapability = 0x800,
|
CreateFullBacktraceCapability = 0x800,
|
||||||
AddWatcherCapability = 0x1000
|
AddWatcherCapability = 0x1000,
|
||||||
|
WatchpointCapability = 0x2000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LogChannel
|
enum LogChannel
|
||||||
|
|||||||
@@ -897,9 +897,9 @@ BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lin
|
|||||||
// FIXME: move further up the plugin where there's more specific context
|
// FIXME: move further up the plugin where there's more specific context
|
||||||
// information available.
|
// information available.
|
||||||
static BreakpointData *createBreakpointByFileAndLine
|
static BreakpointData *createBreakpointByFileAndLine
|
||||||
(const QString &fileName, int lineNumber, BreakHandler *handler)
|
(const QString &fileName, int lineNumber)
|
||||||
{
|
{
|
||||||
BreakpointData *data = new BreakpointData(handler);
|
BreakpointData *data = new BreakpointData;
|
||||||
if (lineNumber > 0) {
|
if (lineNumber > 0) {
|
||||||
data->fileName = fileName;
|
data->fileName = fileName;
|
||||||
data->lineNumber = QByteArray::number(lineNumber);
|
data->lineNumber = QByteArray::number(lineNumber);
|
||||||
@@ -934,7 +934,7 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
|
|||||||
int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
|
int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
d->m_breakHandler->appendBreakpoint(
|
d->m_breakHandler->appendBreakpoint(
|
||||||
createBreakpointByFileAndLine(fileName, lineNumber, d->m_breakHandler));
|
createBreakpointByFileAndLine(fileName, lineNumber));
|
||||||
else
|
else
|
||||||
d->m_breakHandler->removeBreakpoint(index);
|
d->m_breakHandler->removeBreakpoint(index);
|
||||||
|
|
||||||
@@ -1410,6 +1410,13 @@ void DebuggerManager::breakByFunction(const QString &functionName)
|
|||||||
attemptBreakpointSynchronization();
|
attemptBreakpointSynchronization();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebuggerManager::appendBreakpoint(BreakpointData *data)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->m_breakHandler, return);
|
||||||
|
d->m_breakHandler->appendBreakpoint(data);
|
||||||
|
attemptBreakpointSynchronization();
|
||||||
|
}
|
||||||
|
|
||||||
void DebuggerManager::setBusyCursor(bool busy)
|
void DebuggerManager::setBusyCursor(bool busy)
|
||||||
{
|
{
|
||||||
//STATE_DEBUG("BUSY FROM: " << d->m_busy << " TO: " << d->m_busy);
|
//STATE_DEBUG("BUSY FROM: " << d->m_busy << " TO: " << d->m_busy);
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ public slots: // FIXME
|
|||||||
void reloadRegisters();
|
void reloadRegisters();
|
||||||
void registerDockToggled(bool on);
|
void registerDockToggled(bool on);
|
||||||
void clearStatusMessage();
|
void clearStatusMessage();
|
||||||
|
void appendBreakpoint(Internal::BreakpointData *data);
|
||||||
void attemptBreakpointSynchronization();
|
void attemptBreakpointSynchronization();
|
||||||
void reloadFullStack();
|
void reloadFullStack();
|
||||||
void operateByInstructionTriggered();
|
void operateByInstructionTriggered();
|
||||||
|
|||||||
@@ -1394,7 +1394,19 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
|||||||
reloadBreakListInternal();
|
reloadBreakListInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason == "breakpoint-hit") {
|
if (reason == "watchpoint-trigger") {
|
||||||
|
// *stopped,reason="watchpoint-trigger",wpt={number="2",exp="*0xbfffed40"},
|
||||||
|
// value={old="1",new="0"},frame={addr="0x00451e1b",
|
||||||
|
// func="QScopedPointer",args=[{name="this",value="0xbfffed40"},
|
||||||
|
// {name="p",value="0x0"}],file="x.h",fullname="/home/.../x.h",line="95"},
|
||||||
|
// thread-id="1",stopped-threads="all",core="2"
|
||||||
|
GdbMi wpt = data.findChild("wpt");
|
||||||
|
QByteArray bpNumber = wpt.findChild("number").data();
|
||||||
|
QByteArray bpAddress = wpt.findChild("exp").data();
|
||||||
|
//QByteArray threadId = data.findChild("thread-id").data();
|
||||||
|
showStatusMessage(tr("Watchpoint %1 at %2 triggered:")
|
||||||
|
.arg(_(bpNumber), _(bpAddress)));
|
||||||
|
} else if (reason == "breakpoint-hit") {
|
||||||
QByteArray bpNumber = data.findChild("bkptno").data();
|
QByteArray bpNumber = data.findChild("bkptno").data();
|
||||||
QByteArray threadId = data.findChild("thread-id").data();
|
QByteArray threadId = data.findChild("thread-id").data();
|
||||||
showStatusMessage(tr("Stopped at breakpoint %1 in thread %2")
|
showStatusMessage(tr("Stopped at breakpoint %1 in thread %2")
|
||||||
@@ -1825,6 +1837,7 @@ unsigned GdbEngine::debuggerCapabilities() const
|
|||||||
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
|
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
|
||||||
| ReturnFromFunctionCapability
|
| ReturnFromFunctionCapability
|
||||||
| CreateFullBacktraceCapability
|
| CreateFullBacktraceCapability
|
||||||
|
| WatchpointCapability
|
||||||
| AddWatcherCapability;
|
| AddWatcherCapability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2174,6 +2187,13 @@ void GdbEngine::sendInsertBreakpoint(int index)
|
|||||||
const BreakpointData *data = manager()->breakHandler()->at(index);
|
const BreakpointData *data = manager()->breakHandler()->at(index);
|
||||||
// Set up fallback in case of pending breakpoints which aren't handled
|
// Set up fallback in case of pending breakpoints which aren't handled
|
||||||
// by the MI interface.
|
// by the MI interface.
|
||||||
|
if (data->type == BreakpointData::WatchpointType) {
|
||||||
|
postCommand("watch *" + data->address,
|
||||||
|
NeedsStop | RebuildBreakpointModel,
|
||||||
|
CB(handleWatchInsert), index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray cmd;
|
QByteArray cmd;
|
||||||
if (m_isMacGdb) {
|
if (m_isMacGdb) {
|
||||||
cmd = "-break-insert -l -1 -f ";
|
cmd = "-break-insert -l -1 -f ";
|
||||||
@@ -2197,6 +2217,23 @@ void GdbEngine::sendInsertBreakpoint(int index)
|
|||||||
CB(handleBreakInsert1), index);
|
CB(handleBreakInsert1), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleWatchInsert(const GdbResponse &response)
|
||||||
|
{
|
||||||
|
int index = response.cookie.toInt();
|
||||||
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
// "Hardware watchpoint 2: *0xbfffed40\n"
|
||||||
|
QByteArray ba = response.data.findChild("consolestreamoutput").data();
|
||||||
|
if (ba.startsWith("Hardware watchpoint ")) {
|
||||||
|
const int pos = ba.indexOf(':', 20);
|
||||||
|
BreakpointData *data = manager()->breakHandler()->at(index);
|
||||||
|
data->bpNumber = ba.mid(20, pos - 20);
|
||||||
|
manager()->breakHandler()->updateMarkers();
|
||||||
|
} else {
|
||||||
|
debugMessage(_("CANNOT PARSE WATCHPOINT FROM" + ba));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::handleBreakInsert1(const GdbResponse &response)
|
void GdbEngine::handleBreakInsert1(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
int index = response.cookie.toInt();
|
int index = response.cookie.toInt();
|
||||||
@@ -2275,7 +2312,7 @@ void GdbEngine::handleBreakList(const GdbMi &table)
|
|||||||
|
|
||||||
BreakHandler *handler = manager()->breakHandler();
|
BreakHandler *handler = manager()->breakHandler();
|
||||||
for (int index = 0; index != bkpts.size(); ++index) {
|
for (int index = 0; index != bkpts.size(); ++index) {
|
||||||
BreakpointData temp(handler);
|
BreakpointData temp;
|
||||||
breakpointDataFromOutput(&temp, bkpts.at(index));
|
breakpointDataFromOutput(&temp, bkpts.at(index));
|
||||||
int found = handler->findBreakpoint(temp);
|
int found = handler->findBreakpoint(temp);
|
||||||
if (found != -1)
|
if (found != -1)
|
||||||
@@ -2444,7 +2481,7 @@ void GdbEngine::attemptBreakpointSynchronization()
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(!m_sourcesListUpdating,
|
QTC_ASSERT(!m_sourcesListUpdating,
|
||||||
qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
|
qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
|
||||||
debugMessage(tr("ATTEMPT BREAKPOINT SYNC"));
|
debugMessage(_("ATTEMPT BREAKPOINT SYNC"));
|
||||||
|
|
||||||
switch (state()) {
|
switch (state()) {
|
||||||
case InferiorStarting:
|
case InferiorStarting:
|
||||||
@@ -2455,6 +2492,7 @@ void GdbEngine::attemptBreakpointSynchronization()
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//qDebug() << "attempted breakpoint sync in state" << state();
|
//qDebug() << "attempted breakpoint sync in state" << state();
|
||||||
|
debugMessage(_("... NOT POSSIBLE IN CURRENT STATE"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ private: ////////// View & Data Stuff //////////
|
|||||||
void handleBreakInsert2(const GdbResponse &response);
|
void handleBreakInsert2(const GdbResponse &response);
|
||||||
void handleBreakCondition(const GdbResponse &response);
|
void handleBreakCondition(const GdbResponse &response);
|
||||||
void handleBreakInfo(const GdbResponse &response);
|
void handleBreakInfo(const GdbResponse &response);
|
||||||
|
void handleWatchInsert(const GdbResponse &response);
|
||||||
void handleInfoLine(const GdbResponse &response);
|
void handleInfoLine(const GdbResponse &response);
|
||||||
void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
|
void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
|
||||||
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
||||||
|
|||||||
BIN
src/plugins/debugger/images/watchpoint.png
Normal file
BIN
src/plugins/debugger/images/watchpoint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 593 B |
@@ -30,6 +30,7 @@
|
|||||||
#include "watchwindow.h"
|
#include "watchwindow.h"
|
||||||
#include "watchhandler.h"
|
#include "watchhandler.h"
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
#include "debuggeractions.h"
|
#include "debuggeractions.h"
|
||||||
#include "debuggeragents.h"
|
#include "debuggeragents.h"
|
||||||
#include "debuggerdialogs.h"
|
#include "debuggerdialogs.h"
|
||||||
@@ -284,7 +285,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
const QString address = model()->data(mi0, AddressRole).toString();
|
const QString address = model()->data(mi0, AddressRole).toString();
|
||||||
QAction *actWatchKnownMemory = 0;
|
QAction *actWatchKnownMemory = 0;
|
||||||
QAction *actWatchUnknownMemory = new QAction(tr("Open Memory Editor..."), &menu);
|
QAction *actWatchUnknownMemory =
|
||||||
|
new QAction(tr("Open Memory Editor..."), &menu);
|
||||||
const bool canShowMemory = engineCapabilities & ShowMemoryCapability;
|
const bool canShowMemory = engineCapabilities & ShowMemoryCapability;
|
||||||
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
||||||
|
|
||||||
@@ -293,6 +295,17 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
|
QAction *actSetWatchpoint = 0;
|
||||||
|
const bool canSetWatchpoint = engineCapabilities & WatchpointCapability;
|
||||||
|
if (canSetWatchpoint && !address.isEmpty()) {
|
||||||
|
actSetWatchpoint =
|
||||||
|
new QAction(tr("Break on changing %1").arg(address), &menu);
|
||||||
|
} else {
|
||||||
|
actSetWatchpoint =
|
||||||
|
new QAction(tr("Break on changing contents"), &menu);
|
||||||
|
actSetWatchpoint->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
QAction *actWatchOrRemove;
|
QAction *actWatchOrRemove;
|
||||||
if (m_type == LocalsType) {
|
if (m_type == LocalsType) {
|
||||||
actWatchOrRemove = theDebuggerAction(WatchExpression)->updatedAction(exp);
|
actWatchOrRemove = theDebuggerAction(WatchExpression)->updatedAction(exp);
|
||||||
@@ -311,6 +324,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
if (actWatchKnownMemory)
|
if (actWatchKnownMemory)
|
||||||
menu.addAction(actWatchKnownMemory);
|
menu.addAction(actWatchKnownMemory);
|
||||||
menu.addAction(actWatchUnknownMemory);
|
menu.addAction(actWatchUnknownMemory);
|
||||||
|
menu.addAction(actSetWatchpoint);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
||||||
@@ -353,6 +367,11 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
(void) new MemoryViewAgent(m_manager, dialog.address());
|
(void) new MemoryViewAgent(m_manager, dialog.address());
|
||||||
}
|
}
|
||||||
|
} else if (act == actSetWatchpoint) {
|
||||||
|
BreakpointData *data = new BreakpointData;
|
||||||
|
data->type = BreakpointData::WatchpointType;
|
||||||
|
data->address = address.toLatin1();
|
||||||
|
m_manager->appendBreakpoint(data);
|
||||||
} else if (act == actSelectWidgetToWatch) {
|
} else if (act == actSelectWidgetToWatch) {
|
||||||
grabMouse(Qt::CrossCursor);
|
grabMouse(Qt::CrossCursor);
|
||||||
m_grabbing = true;
|
m_grabbing = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user