Newer
Older
/**************************************************************************
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
** 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
**************************************************************************/
#include "debuggeractions.h"
#include "debuggerengine.h"
#include "debuggerstringutils.h"
//////////////////////////////////////////////////////////////////
//
// BreakHandler
//
//////////////////////////////////////////////////////////////////
namespace Debugger {
namespace Internal {
BreakHandler::BreakHandler()
: m_syncTimerId(-1)
QIcon BreakHandler::breakpointIcon()
{
static QIcon icon(_(":/debugger/images/breakpoint_16.png"));
return icon;
}
QIcon BreakHandler::disabledBreakpointIcon()
{
static QIcon icon(_(":/debugger/images/breakpoint_disabled_16.png"));
return icon;
}
QIcon BreakHandler::pendingBreakPointIcon()
{
static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
return icon;
}
QIcon BreakHandler::emptyIcon()
{
static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
//static QIcon icon(_(":/debugger/images/watchpoint.png"));
//static QIcon icon(_(":/debugger/images/debugger_empty_14.png"));
return icon;
}
}
int BreakHandler::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_storage.size();
static inline bool fileNameMatch(const QString &f1, const QString &f2)
#ifdef Q_OS_WIN
return f1.compare(f2, Qt::CaseInsensitive) == 0;
#else
return f1 == f2;
#endif
static bool isSimilarTo(const BreakpointParameters &data, const BreakpointResponse &needle)
if (needle.type != UnknownType && data.type != UnknownType
&& data.type != needle.type)
if (data.address && data.address == needle.address)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!data.fileName.isEmpty()
&& fileNameMatch(data.fileName, needle.fileName)
&& data.lineNumber == needle.lineNumber)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!data.fileName.isEmpty()
&& fileNameMatch(data.fileName, needle.fileName)
&& data.lineNumber == needle.lineNumber)
BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const
// Search a breakpoint we might refer to.
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for ( ; it != et; ++it) {
const BreakpointId id = it.key();
const BreakpointParameters &data = it->data;
const BreakpointResponse &response = it->response;
qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
if (response.number && response.number == needle.number)
return id;
if (isSimilarTo(data, needle))
return id;
BreakpointId BreakHandler::findBreakpointByNumber(int bpNumber) const
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->response.number == bpNumber)
return it.key();
return BreakpointId(-1);
BreakpointId BreakHandler::findBreakpointByFunction(const QString &functionName) const
{
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->data.functionName == functionName)
return it.key();
return BreakpointId(-1);
}
BreakpointId BreakHandler::findBreakpointByAddress(quint64 address) const
{
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->data.address == address)
return it.key();
return BreakpointId(-1);
}
BreakpointId BreakHandler::findBreakpointByFileAndLine(const QString &fileName,
int lineNumber, bool useMarkerPosition)
{
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->isLocatedAt(fileName, lineNumber, useMarkerPosition))
return it.key();
return BreakpointId(-1);
}
const BreakpointParameters &BreakHandler::breakpointData(BreakpointId id) const
static BreakpointParameters dummy;
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return dummy);
}
BreakpointId BreakHandler::findWatchpointByAddress(quint64 address) const
{
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->data.isWatchpoint() && it->data.address == address)
return it.key();
return BreakpointId(-1);
}
void BreakHandler::setWatchpointByAddress(quint64 address)
{
const int id = findWatchpointByAddress(address);
if (id == -1) {
BreakpointParameters data(Watchpoint);
data.address = address;
appendBreakpoint(data);
scheduleSynchronization();
} else {
qDebug() << "WATCHPOINT EXISTS";
// removeBreakpoint(index);
}
}
bool BreakHandler::hasWatchpointAt(quint64 address) const
return findWatchpointByAddress(address) != BreakpointId(-1);
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
const BreakpointParameters &data = it->data;
// Do not persist Watchpoints.
if (data.isWatchpoint())
continue;
if (data.type != BreakpointByFileAndLine)
map.insert(_("type"), data.type);
if (!data.fileName.isEmpty())
map.insert(_("filename"), data.fileName);
if (data.lineNumber)
map.insert(_("linenumber"), data.lineNumber);
if (!data.functionName.isEmpty())
map.insert(_("funcname"), data.functionName);
if (data.address)
map.insert(_("address"), data.address);
if (!data.condition.isEmpty())
map.insert(_("condition"), data.condition);
if (data.ignoreCount)
map.insert(_("ignorecount"), data.ignoreCount);
if (!data.threadSpec.isEmpty())
map.insert(_("threadspec"), data.threadSpec);
if (!data.enabled)
map.insert(_("disabled"), _("1"));
map.insert(_("usefullpath"), _("1"));
debuggerCore()->setSessionValue("Breakpoints", list);
//qDebug() << "SAVED BREAKPOINTS" << this << list.size();
QVariant value = debuggerCore()->sessionValue("Breakpoints");
foreach (const QVariant &var, list) {
const QMap<QString, QVariant> map = var.toMap();
BreakpointParameters data(BreakpointByFileAndLine);
QVariant v = map.value(_("filename"));
v = map.value(_("linenumber"));
v = map.value(_("condition"));
v = map.value(_("address"));
if (v.isValid())
v = map.value(_("ignorecount"));
v = map.value(_("threadspec"));
v = map.value(_("funcname"));
v = map.value(_("disabled"));
v = map.value(_("usefullpath"));
if (v.isValid() && v.toInt() != UnknownType)
//qDebug() << "LOADED BREAKPOINTS" << this << list.size();
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for ( ; it != et; ++it)
updateMarker(it.key());
void BreakHandler::updateMarker(BreakpointId id)
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
QString markerFileName = it->markerFileName();
int markerLineNumber = it->markerLineNumber();
if (it->marker && (markerFileName != it->marker->fileName()
|| markerLineNumber != it->marker->lineNumber()))
it->destroyMarker();
if (!it->marker && !markerFileName.isEmpty() && markerLineNumber > 0)
it->marker = new BreakpointMarker(id, markerFileName, markerLineNumber);
QVariant BreakHandler::headerData(int section,
Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
static QString headers[] = {
tr("Number"), tr("Function"), tr("File"), tr("Line"),
tr("Condition"), tr("Ignore"), tr("Threads"), tr("Address")
};
return headers[section];
}
return QVariant();
}
BreakpointId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
{
int r = index.row();
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for (int i = 0; it != et; ++it, ++i)
if (i == r)
return it.key();
return BreakpointId(-1);
}
BreakpointIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
{
BreakpointIds ids;
foreach (const QModelIndex &index, list)
ids.append(findBreakpointByIndex(index));
return ids;
}
Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
{
// switch (index.column()) {
// //case 0:
// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
// default:
return QAbstractTableModel::flags(index);
// }
}
QVariant BreakHandler::data(const QModelIndex &mi, int role) const
{
static const QString empty = QString(QLatin1Char('-'));
if (!mi.isValid())
return QVariant();
BreakpointId id = findBreakpointByIndex(mi);
//qDebug() << "DATA: " << id << role << mi.column();
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return QVariant());
const BreakpointParameters &data = it->data;
const BreakpointResponse &response = it->response;
switch (mi.column()) {
case 0:
if (role == Qt::DisplayRole) {
//return QString("%1 - %2").arg(id).arg(response.number);
if (role == Qt::DecorationRole)
return it->icon();
if (!response.functionName.isEmpty())
return response.functionName;
if (!data.functionName.isEmpty())
return data.functionName;
return empty;
QString str;
if (!response.fileName.isEmpty())
str = response.fileName;
if (str.isEmpty() && !data.fileName.isEmpty())
if (str.isEmpty()) {
QString s = QFileInfo(str).fileName();
if (!s.isEmpty())
str = s;
}
//if (data.multiple && str.isEmpty() && !response.fileName.isEmpty())
// str = response.fileName;
if (!str.isEmpty())
return str;
return empty;
if (response.lineNumber > 0)
return response.lineNumber;
if (data.lineNumber > 0)
return data.lineNumber;
return empty;
return data.lineNumber;
return it->isPending() ? data.condition : response.condition;
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit if this condition is met.");
return data.condition;
if (role == Qt::DisplayRole) {
it->isPending() ? data.ignoreCount : response.ignoreCount;
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
}
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit after being ignored so many times.");
return data.ignoreCount;
if (it->isPending())
return !data.threadSpec.isEmpty() ? data.threadSpec : tr("(all)");
return !response.threadSpec.isEmpty() ? response.threadSpec : tr("(all)");
}
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit in the specified thread(s).");
if (role == Qt::UserRole + 1)
return data.threadSpec;
if (role == Qt::DisplayRole) {
QString displayValue;
data.isWatchpoint() ? data.address : response.address;
if (address)
displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
if (!displayValue.isEmpty())
displayValue += QLatin1Char(' ');
displayValue += QString::fromAscii(response.extra);
}
return displayValue;
return debuggerCore()->boolSetting(UseToolTipsInBreakpointsView)
? QVariant(it->toToolTip()) : QVariant();
#define GETTER(type, getter) \
type BreakHandler::getter(BreakpointId id) const \
{ \
ConstIterator it = m_storage.find(id); \
QTC_ASSERT(it != m_storage.end(), \
qDebug() << "ID" << id << "NOT KNOWN"; \
return type()); \
return it->data.getter; \
#define SETTER(type, getter, setter) \
void BreakHandler::setter(BreakpointId id, const type &value) \
{ \
Iterator it = m_storage.find(id); \
QTC_ASSERT(it != m_storage.end(), \
qDebug() << "ID" << id << "NOT KNOWN"; return); \
if (it->data.getter == value) \
it->data.getter = value; \
it->state = BreakpointChangeRequested; \
scheduleSynchronization(); \

hjk
committed
}
#define PROPERTY(type, getter, setter) \
GETTER(type, getter) \
SETTER(type, getter, setter)
PROPERTY(bool, useFullPath, setUseFullPath)
PROPERTY(QString, fileName, setFileName)
PROPERTY(QString, functionName, setFunctionName)
PROPERTY(BreakpointType, type, setType)
PROPERTY(QByteArray, threadSpec, setThreadSpec)
PROPERTY(QByteArray, condition, setCondition)
PROPERTY(int, lineNumber, setLineNumber)
PROPERTY(quint64, address, setAddress)
PROPERTY(int, ignoreCount, setIgnoreCount)
bool BreakHandler::isEnabled(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return false);
return it->data.enabled;
}
void BreakHandler::setEnabled(BreakpointId id, bool on)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
//qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on;
if (it->data.enabled == on)
return;
it->data.enabled = on;
it->destroyMarker();
it->state = BreakpointChangeRequested;
updateMarker(id);
scheduleSynchronization();
void BreakHandler::setMarkerFileAndLine(BreakpointId id,
const QString &fileName, int lineNumber)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
if (it->response.fileName == fileName && it->response.lineNumber == lineNumber)
return;
it->response.fileName = fileName;
it->response.lineNumber = lineNumber;
it->destroyMarker();
emit layoutChanged();
BreakpointState BreakHandler::state(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return BreakpointDead);
return it->state;
}
DebuggerEngine *BreakHandler::engine(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return 0);
return it->engine;
}
void BreakHandler::setEngine(BreakpointId id, DebuggerEngine *value)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
QTC_ASSERT(it->state == BreakpointNew, /**/);
QTC_ASSERT(!it->engine, return);
it->engine = value;
it->state = BreakpointInsertRequested;
it->response = BreakpointResponse();
it->response.fileName = it->data.fileName;
updateMarker(id);
scheduleSynchronization();
}
static bool isAllowedTransition(BreakpointState from, BreakpointState to)
{
switch (from) {
case BreakpointNew:
return to == BreakpointInsertRequested;
case BreakpointInsertRequested:
return to == BreakpointInsertProceeding;
case BreakpointInsertProceeding:
return to == BreakpointInserted
|| to == BreakpointDead
|| to == BreakpointChangeRequested;
case BreakpointChangeRequested:
return to == BreakpointChangeProceeding;
case BreakpointChangeProceeding:
return to == BreakpointInserted
|| to == BreakpointDead;
case BreakpointInserted:
return to == BreakpointChangeRequested
|| to == BreakpointRemoveRequested;
case BreakpointRemoveRequested:
return to == BreakpointRemoveProceeding;
case BreakpointRemoveProceeding:
return to == BreakpointDead;
case BreakpointDead:
return false;
}
qDebug() << "UNKNOWN BREAKPOINT STATE:" << from;
return false;
}
void BreakHandler::setState(BreakpointId id, BreakpointState state)
{
Iterator it = m_storage.find(id);
//qDebug() << "BREAKPOINT STATE TRANSITION" << id << it->state << state;
QTC_ASSERT(it != m_storage.end(), return);
QTC_ASSERT(isAllowedTransition(it->state, state),
qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION"
<< it->state << state);
if (it->state == state) {
qDebug() << "STATE UNCHANGED: " << id << state;
return;
}
it->state = state;
}
void BreakHandler::notifyBreakpointInsertProceeding(BreakpointId id)
QTC_ASSERT(state(id) == BreakpointInsertRequested, /**/);
setState(id, BreakpointInsertProceeding);
void BreakHandler::notifyBreakpointInsertOk(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointInsertProceeding, /**/);
setState(id, BreakpointInserted);
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
//if (it0->needsChange(it->data, it->response)) {
// setState(id, BreakpointChangeRequested);
// scheduleSynchronization();
//}
}
void BreakHandler::notifyBreakpointInsertFailed(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointInsertProceeding, /**/);
setState(id, BreakpointDead);
}
void BreakHandler::notifyBreakpointRemoveProceeding(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointRemoveRequested, /**/);
setState(id, BreakpointRemoveProceeding);
}
void BreakHandler::notifyBreakpointRemoveOk(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointRemoveProceeding, /**/);
setState(id, BreakpointDead);
cleanupBreakpoint(id);
}
void BreakHandler::notifyBreakpointRemoveFailed(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointRemoveProceeding, /**/);
setState(id, BreakpointDead);
cleanupBreakpoint(id);
}
void BreakHandler::notifyBreakpointChangeOk(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointChangeProceeding, /**/);
setState(id, BreakpointInserted);
}
void BreakHandler::notifyBreakpointChangeFailed(BreakpointId id)
QTC_ASSERT(state(id) == BreakpointChangeProceeding, /**/);
setState(id, BreakpointDead);
}
void BreakHandler::notifyBreakpointReleased(BreakpointId id)
{
//QTC_ASSERT(state(id) == BreakpointChangeProceeding, /**/);
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->state = BreakpointNew;
it->engine = 0;
it->response = BreakpointResponse();
delete it->marker;
it->marker = 0;
void BreakHandler::notifyBreakpointAdjusted(BreakpointId id,
const BreakpointParameters &data)
{
QTC_ASSERT(state(id) == BreakpointInserted, /**/);
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->data = data;
if (it->needsChange())
setState(id, BreakpointChangeRequested);
}
void BreakHandler::ackCondition(BreakpointId id)
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.condition = it->data.condition;
void BreakHandler::ackIgnoreCount(BreakpointId id)
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.ignoreCount = it->data.ignoreCount;
void BreakHandler::ackEnabled(BreakpointId id)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.enabled = it->data.enabled;
updateMarker(id);
}
void BreakHandler::removeBreakpoint(BreakpointId id)
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
if (it->state == BreakpointInserted) {
scheduleSynchronization();
} else if (it->state == BreakpointNew) {
it->state = BreakpointDead;
qDebug() << "CANNOT REMOVE IN STATE " << it->state;
void BreakHandler::appendBreakpoint(const BreakpointParameters &data)
QTC_ASSERT(data.type != UnknownType, return);
// Ok to be not thread-safe. The order does not matter and only the gui
// produces authoritative ids.
static quint64 currentId = 0;
item.response.fileName = data.fileName;
item.response.lineNumber = data.lineNumber;
m_storage.insert(id, item);
void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber,
quint64 address /* = 0 */)
if (address) {
id = findBreakpointByFileAndLine(fileName, lineNumber, true);
if (id == BreakpointId(-1))
id = findBreakpointByFileAndLine(fileName, lineNumber, false);
if (id != BreakpointId(-1)) {
removeBreakpoint(id);
data.type = BreakpointByAddress;
data.address = address;
data.type = BreakpointByFileAndLine;
data.fileName = fileName;
data.lineNumber = lineNumber;
appendBreakpoint(data);
void BreakHandler::saveSessionData()
{
saveBreakpoints();
}
void BreakHandler::loadSessionData()
{
loadBreakpoints();
}
void BreakHandler::breakByFunction(const QString &functionName)
{
// One breakpoint per function is enough for now. This does not handle
// combinations of multiple conditions and ignore counts, though.
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
const BreakpointParameters &data = it->data;
if (data.functionName == functionName
&& data.condition.isEmpty()
&& data.ignoreCount == 0)
BreakpointParameters data(BreakpointByFunction);
data.functionName = functionName;
appendBreakpoint(data);
}
QIcon BreakHandler::icon(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return pendingBreakPointIcon());
return it->icon();
}
void BreakHandler::scheduleSynchronization()
{
if (m_syncTimerId == -1)
m_syncTimerId = startTimer(10);
}
void BreakHandler::timerEvent(QTimerEvent *event)
{
QTC_ASSERT(event->timerId() == m_syncTimerId, return);
killTimer(m_syncTimerId);
m_syncTimerId = -1;
//qDebug() << "BREAKPOINT SYNCRONIZATION STARTED";
debuggerCore()->synchronizeBreakpoints();
emit layoutChanged();
saveBreakpoints(); // FIXME: remove?
}
void BreakHandler::gotoLocation(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->data.fileName, it->data.lineNumber, false);
}
void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
{
Iterator it = m_storage.find(id);
it->response.pending = false;
QTC_ASSERT(it != m_storage.end(), return);
//if (data.markerLineNumber == lineNumber)
if (it->response.lineNumber != lineNumber) {
it->response.lineNumber = lineNumber;
// FIXME: Should we tell gdb about the change?
// Ignore it for now, as we would require re-compilation
// and debugger re-start anyway.
//if (0 && data.bpLineNumber) {
// if (!data.bpNumber.trimmed().isEmpty()) {
// data.pending = true;
// }
//}
}
// Ignore updates to the "real" line number while the debugger is
// running, as this can be triggered by moving the breakpoint to
// the next line that generated code.
// FIXME: Do we need yet another data member?
if (it->response.number == 0) {
it->data.lineNumber = lineNumber;
updateMarker(id);
emit layoutChanged();
}
BreakpointIds BreakHandler::allBreakpointIds() const
{
BreakpointIds ids;
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for ( ; it != et; ++it)
ids.append(it.key());
return ids;
}
BreakpointIds BreakHandler::unclaimedBreakpointIds() const
{
return engineBreakpointIds(0);
}
BreakpointIds BreakHandler::engineBreakpointIds(DebuggerEngine *engine) const
{
BreakpointIds ids;
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
if (it->engine == engine)
ids.append(it.key());
return ids;
}
void BreakHandler::cleanupBreakpoint(BreakpointId id)
{
QTC_ASSERT(state(id) == BreakpointDead, /**/);
BreakpointItem item = m_storage.take(id);
item.destroyMarker();
layoutChanged();
const BreakpointResponse &BreakHandler::response(BreakpointId id) const
static BreakpointResponse dummy;
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return dummy);
return it->response;
}
void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &data)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response = data;
//qDebug() << "SET RESPONSE: " << id << it->state << it->needsChange();
if (it->state == BreakpointChangeProceeding
|| it->state == BreakpointInsertProceeding) {
if (it->needsChange())
setState(id, BreakpointChangeRequested);
else
setState(id, BreakpointInserted);
}
it->destroyMarker();
updateMarker(id);
void BreakHandler::setBreakpointData(BreakpointId id, const BreakpointParameters &data)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->destroyMarker();
updateMarker(id);
layoutChanged();
}
//////////////////////////////////////////////////////////////////
//
// Storage
//
//////////////////////////////////////////////////////////////////
BreakHandler::BreakpointItem::BreakpointItem()
: state(BreakpointNew), engine(0), marker(0)
void BreakHandler::BreakpointItem::destroyMarker()
BreakpointMarker *m = marker;
delete m;
}
QString BreakHandler::BreakpointItem::markerFileName() const
{
// Some heuristics to find a "good" file name.
if (!data.fileName.isEmpty()) {
QFileInfo fi(data.fileName);
if (fi.exists())
return fi.absoluteFilePath();
}
if (!response.fileName.isEmpty()) {
QFileInfo fi(response.fileName);
if (fi.exists())
return fi.absoluteFilePath();
}
if (response.fileName.endsWith(data.fileName))
return response.fileName;
if (data.fileName.endsWith(response.fileName))
return data.fileName;
return response.fileName.size() > data.fileName.size()
? response.fileName : data.fileName;