diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 4e89fbf40bd30faec7be086529202c088f2959e3..6e91f1c3966e421f105a6b7c191ea9c794e38e17 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -57,14 +57,11 @@ BreakHandler::BreakHandler() m_emptyIcon(_(":/debugger/images/breakpoint_pending_16.png")), //m_emptyIcon(_(":/debugger/images/debugger_empty_14.png")), m_watchpointIcon(_(":/debugger/images/watchpoint.png")), - m_lastFound(0), - m_lastFoundQueried(false) + m_syncTimerId(-1) {} BreakHandler::~BreakHandler() -{ - clear(); -} +{} int BreakHandler::columnCount(const QModelIndex &parent) const { @@ -73,74 +70,149 @@ int BreakHandler::columnCount(const QModelIndex &parent) const int BreakHandler::rowCount(const QModelIndex &parent) const { - return parent.isValid() ? 0 : size(); + return parent.isValid() ? 0 : m_bp.size(); } +// FIXME: Only used by cdb. Move there? bool BreakHandler::hasPendingBreakpoints() const { - for (int i = size() - 1; i >= 0; i--) - if (at(i)->pending) + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->isPending()) return true; return false; } -BreakpointData *BreakHandler::at(int index) const +static inline bool fileNameMatch(const QString &f1, const QString &f2) { - QTC_ASSERT(index < size(), return 0); - return m_bp.at(index); +#ifdef Q_OS_WIN + return f1.compare(f2, Qt::CaseInsensitive) == 0; +#else + return f1 == f2; +#endif } -void BreakHandler::removeAt(int index) +static bool isSimilarTo(const BreakpointData *data, const BreakpointResponse &needle) { - BreakpointData *data = at(index); - QTC_ASSERT(data, return); - m_bp.removeAt(index); - delete m_markers.take(data->id); - delete data; -} + // Clear hit. + // Clear miss. + if (needle.bpType != UnknownType && data->type() != UnknownType + && data->type() != needle.bpType) + return false; -void BreakHandler::clear() -{ - m_enabled.clear(); - m_disabled.clear(); - m_removed.clear(); + // Clear hit. + if (data->address() && data->address() == needle.bpAddress) + 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.bpFileName) + && data->lineNumber() == needle.bpLineNumber) + 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.bpFileName) + && data->lineNumber() == needle.bpLineNumber) + return true; + + return false; } -BreakpointData *BreakHandler::findSimilarBreakpoint(const BreakpointData *needle) const +BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const { // Search a breakpoint we might refer to. - for (int index = 0; index != size(); ++index) { - BreakpointData *data = m_bp[index]; - if (data->isSimilarTo(needle)) - return data; + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) { + const BreakpointId id = it.key(); + const BreakpointData *data = it.value(); + QTC_ASSERT(data, continue); + const BreakpointResponse *response = m_responses.value(id); + QTC_ASSERT(response, continue); + + qDebug() << "COMPARING " << data->toString() << " WITH " << needle.toString(); + if (response->bpNumber && response->bpNumber == needle.bpNumber) + return id; + + if (isSimilarTo(data, needle)) + return id; } - return 0; + return BreakpointId(-1); } -BreakpointData *BreakHandler::findBreakpointByNumber(int bpNumber) const +BreakpointId BreakHandler::findBreakpointByNumber(int bpNumber) const { - if (!size()) - return 0; - QString numStr = QString::number(bpNumber); - for (int index = 0; index != size(); ++index) - if (at(index)->bpNumber == numStr) - return at(index); - return 0; + Responses::ConstIterator it = m_responses.constBegin(); + Responses::ConstIterator et = m_responses.constEnd(); + for ( ; it != et; ++it) + if (it.value()->bpNumber == bpNumber) + return it.key(); + return BreakpointId(-1); } -int BreakHandler::findWatchPointIndexByAddress(quint64 address) const +BreakpointId BreakHandler::findBreakpointByFunction(const QString &functionName) const { - for (int index = size() - 1; index >= 0; --index) { - BreakpointData *bd = at(index); - if (bd->isWatchpoint() && bd->address == address) - return index; + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->functionName() == functionName) + return it.key(); + return BreakpointId(-1); +} + +BreakpointId BreakHandler::findBreakpointByAddress(quint64 address) const +{ + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->address() == address) + return it.key(); + return BreakpointId(-1); +} + +BreakpointId BreakHandler::findBreakpointByFileAndLine(const QString &fileName, + int lineNumber, bool useMarkerPosition) +{ + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->isLocatedAt(fileName, lineNumber, useMarkerPosition)) + return it.key(); + return BreakpointId(-1); +} + +BreakpointData *BreakHandler::breakpointById(BreakpointId id) const +{ + return m_bp.value(id, 0); +} + +BreakpointId BreakHandler::findWatchpointByAddress(quint64 address) const +{ + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->isWatchpoint() && it.value()->address() == address) + return it.key(); + return BreakpointId(-1); +} + + +void BreakHandler::setWatchpointByAddress(quint64 address) +{ + const int id = findWatchpointByAddress(address); + if (id == -1) { + BreakpointData *data = new BreakpointData; + data->setType(Watchpoint); + data->setAddress(address); + appendBreakpoint(data); + scheduleSynchronization(); + } else { + qDebug() << "WATCHPOINT EXISTS"; + // removeBreakpoint(index); } - return -1; } -bool BreakHandler::watchPointAt(quint64 address) const +bool BreakHandler::hasWatchpointAt(quint64 address) const { - return findWatchPointIndexByAddress(address) != -1; + return findWatchpointByAddress(address) != BreakpointId(-1); } void BreakHandler::saveBreakpoints() @@ -148,31 +220,32 @@ void BreakHandler::saveBreakpoints() //qDebug() << "SAVING BREAKPOINTS..."; QTC_ASSERT(debuggerCore(), return); QList<QVariant> list; - for (int index = 0; index != size(); ++index) { - const BreakpointData *data = at(index); + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) { + const BreakpointData *data = it.value(); QMap<QString, QVariant> map; // 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"), QVariant(data->lineNumber)); - if (!data->funcName.isEmpty()) - map.insert(_("funcname"), data->funcName); - if (data->address) - map.insert(_("address"), data->address); - if (!data->condition.isEmpty()) - map.insert(_("condition"), data->condition); - if (data->ignoreCount) - map.insert(_("ignorecount"), QVariant(data->ignoreCount)); - if (!data->threadSpec.isEmpty()) - map.insert(_("threadspec"), data->threadSpec); - if (!data->enabled) + 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->isEnabled()) map.insert(_("disabled"), _("1")); - if (data->useFullPath) + if (data->useFullPath()) map.insert(_("usefullpath"), _("1")); list.append(map); } @@ -186,75 +259,76 @@ void BreakHandler::loadBreakpoints() //qDebug() << "LOADING BREAKPOINTS..."; QVariant value = debuggerCore()->sessionValue("Breakpoints"); QList<QVariant> list = value.toList(); - clear(); + //clear(); foreach (const QVariant &var, list) { const QMap<QString, QVariant> map = var.toMap(); BreakpointData *data = new BreakpointData; QVariant v = map.value(_("filename")); if (v.isValid()) - data->fileName = v.toString(); + data->setFileName(v.toString()); v = map.value(_("linenumber")); if (v.isValid()) - data->lineNumber = v.toString().toInt(); + data->setLineNumber(v.toString().toInt()); v = map.value(_("condition")); if (v.isValid()) - data->condition = v.toString().toLatin1(); + data->setCondition(v.toString().toLatin1()); v = map.value(_("address")); if (v.isValid()) - data->address = v.toString().toULongLong(); + data->setAddress(v.toString().toULongLong()); v = map.value(_("ignorecount")); if (v.isValid()) - data->ignoreCount = v.toString().toInt(); + data->setIgnoreCount(v.toString().toInt()); v = map.value(_("threadspec")); if (v.isValid()) - data->threadSpec = v.toString().toLatin1(); + data->setThreadSpec(v.toString().toLatin1()); v = map.value(_("funcname")); if (v.isValid()) - data->funcName = v.toString(); + data->setFunctionName(v.toString()); v = map.value(_("disabled")); if (v.isValid()) - data->enabled = !v.toInt(); + data->setEnabled(!v.toInt()); v = map.value(_("usefullpath")); if (v.isValid()) - data->useFullPath = bool(v.toInt()); + data->setUseFullPath(bool(v.toInt())); v = map.value(_("type")); if (v.isValid()) - data->type = BreakpointType(v.toInt()); - data->setMarkerFileName(data->fileName); - data->setMarkerLineNumber(data->lineNumber); - append(data); + data->setType(BreakpointType(v.toInt())); + data->setMarkerFileName(data->fileName()); + data->setMarkerLineNumber(data->lineNumber()); + appendBreakpoint(data); } //qDebug() << "LOADED BREAKPOINTS" << this << list.size(); } void BreakHandler::updateMarkers() { - for (int index = 0; index != size(); ++index) - updateMarker(at(index)); - emit layoutChanged(); + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + updateMarker(it.key()); } -void BreakHandler::updateMarker(BreakpointData * bp) +void BreakHandler::updateMarker(BreakpointId id) { - BreakpointMarker *marker = m_markers.value(bp->id); + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return); - if (marker && (bp->m_markerFileName != marker->fileName() - || bp->m_markerLineNumber != marker->lineNumber())) { - removeMarker(bp); + BreakpointMarker *marker = m_markers.value(id); + + if (marker && (data->m_markerFileName != marker->fileName() + || data->m_markerLineNumber != marker->lineNumber())) { + removeMarker(id); marker = 0; } - if (!marker && !bp->m_markerFileName.isEmpty() && bp->m_markerLineNumber > 0) { - marker = new BreakpointMarker(this, bp, bp->m_markerFileName, bp->m_markerLineNumber); - m_markers.insert(bp->id, marker); + if (!marker && !data->m_markerFileName.isEmpty() && data->m_markerLineNumber > 0) { + marker = new BreakpointMarker(id, data->m_markerFileName, data->m_markerLineNumber); + m_markers.insert(id, marker); } - - if (marker) - marker->setPending(bp->pending); } -void BreakHandler::removeMarker(BreakpointData * bp) + +void BreakHandler::removeMarker(BreakpointId id) { - delete m_markers.take(bp->id); + delete m_markers.take(id); } QVariant BreakHandler::headerData(int section, @@ -270,45 +344,57 @@ QVariant BreakHandler::headerData(int section, return QVariant(); } +BreakpointId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const +{ + int r = index.row(); + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for (int i = 0; it != et; ++it, ++i) + if (i == r) + return it.key(); + return BreakpointId(-1); +} + QVariant BreakHandler::data(const QModelIndex &mi, int role) const { static const QString empty = QString(QLatin1Char('-')); QTC_ASSERT(mi.isValid(), return QVariant()); - if (mi.row() >= size()) - return QVariant(); - - BreakpointData *data = at(mi.row()); + BreakpointId id = findBreakpointByIndex(mi); + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return QVariant()); + BreakpointResponse *response = m_responses.value(id, 0); + QTC_ASSERT(response, return QVariant()); switch (mi.column()) { case 0: if (role == Qt::DisplayRole) { - const QString str = data->bpNumber; - return str.isEmpty() ? empty : str; + return QString("%1 - %2").arg(id).arg(response->bpNumber); } if (role == Qt::DecorationRole) { if (data->isWatchpoint()) return m_watchpointIcon; - if (!data->enabled) + if (!data->isEnabled()) return m_disabledBreakpointIcon; - return data->pending ? m_pendingBreakPointIcon : m_breakpointIcon; + return data->isPending() ? m_pendingBreakPointIcon : m_breakpointIcon; } break; case 1: if (role == Qt::DisplayRole) { - const QString str = data->pending ? data->funcName : data->bpFuncName; + const QString str = data->isPending() + ? data->functionName() : response->bpFuncName; return str.isEmpty() ? empty : str; } break; case 2: if (role == Qt::DisplayRole) { - QString str = data->pending ? data->fileName : data->bpFileName; + QString str = data->isPending() + ? data->fileName() : response->bpFileName; str = QFileInfo(str).fileName(); // FIXME: better? //if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty()) // str = data->markerFileName; str = str.isEmpty() ? empty : str; - if (data->useFullPath) + if (data->useFullPath()) str = QDir::toNativeSeparators(QLatin1String("/.../") + str); return str; } @@ -318,277 +404,426 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const // FIXME: better? //if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty()) // str = data->markerLineNumber; - const int nr = data->pending ? data->lineNumber : data->bpLineNumber; + const int nr = data->isPending() + ? data->lineNumber() : response->bpLineNumber; return nr ? QString::number(nr) : empty; } if (role == Qt::UserRole + 1) - return data->lineNumber; + return data->lineNumber(); break; case 4: if (role == Qt::DisplayRole) - return data->pending ? data->condition : data->bpCondition; + return data->isPending() ? data->condition() : response->bpCondition; if (role == Qt::ToolTipRole) return tr("Breakpoint will only be hit if this condition is met."); if (role == Qt::UserRole + 1) - return data->condition; + return data->condition(); break; case 5: if (role == Qt::DisplayRole) { - const int ignoreCount = data->pending ? data->ignoreCount : data->bpIgnoreCount; + const int ignoreCount = + data->isPending() ? data->ignoreCount() : response->bpIgnoreCount; return ignoreCount ? QVariant(ignoreCount) : QVariant(QString()); } if (role == Qt::ToolTipRole) return tr("Breakpoint will only be hit after being ignored so many times."); if (role == Qt::UserRole + 1) - return data->ignoreCount; + return data->ignoreCount(); break; case 6: if (role == Qt::DisplayRole) { - if (data->pending) - return !data->threadSpec.isEmpty() ? data->threadSpec : tr("(all)"); + if (data->isPending()) + return !data->threadSpec().isEmpty() ? data->threadSpec() : tr("(all)"); else - return !data->bpThreadSpec.isEmpty() ? data->bpThreadSpec : tr("(all)"); + return !response->bpThreadSpec.isEmpty() ? response->bpThreadSpec : 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; + return data->threadSpec(); break; case 7: if (role == Qt::DisplayRole) { QString displayValue; - const quint64 effectiveAddress - = data->isWatchpoint() ? data->address : data->bpAddress; - if (effectiveAddress) - displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16); - if (!data->bpState.isEmpty()) { + const quint64 address = + data->isWatchpoint() ? data->address() : response->bpAddress; + if (address) + displayValue += QString::fromAscii("0x%1").arg(address, 0, 16); + if (!response->bpState.isEmpty()) { if (!displayValue.isEmpty()) displayValue += QLatin1Char(' '); - displayValue += QString::fromAscii(data->bpState); + displayValue += QString::fromAscii(response->bpState); } return displayValue; } break; } if (role == Qt::ToolTipRole) - return theDebuggerBoolSetting(UseToolTipsInBreakpointsView) + return debuggerCore()->boolSetting(UseToolTipsInBreakpointsView) ? data->toToolTip() : QVariant(); + return QVariant(); } -Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const -{ -// switch (index.column()) { -// //case 0: -// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; -// default: - return QAbstractTableModel::flags(index); -// } +#define GETTER(type, getter) \ +type BreakHandler::getter(BreakpointId id) const \ +{ \ + BreakpointData *data = m_bp.value(id); \ + QTC_ASSERT(data, return type()); \ + return data->getter(); \ } -void BreakHandler::reinsertBreakpoint(BreakpointData *data) -{ - // FIXME: Use some more direct method? - appendBreakpoint(data->clone()); - removeBreakpoint(data); - synchronizeBreakpoints(); - emit layoutChanged(); +#define SETTER(type, setter) \ +void BreakHandler::setter(BreakpointId id, const type &value) \ +{ \ + BreakpointData *data = m_bp.value(id); \ + QTC_ASSERT(data, return); \ + if (data->setter(value)) \ + scheduleSynchronization(); \ } -void BreakHandler::append(BreakpointData *data) -{ - m_bp.append(data); -} +#define PROPERTY(type, getter, setter) \ + GETTER(type, getter) \ + SETTER(type, setter) -Breakpoints BreakHandler::takeRemovedBreakpoints() -{ - foreach(BreakpointData *bp, m_removed) { - removeMarker(bp); - } - Breakpoints result = m_removed; - m_removed.clear(); - return result; -} -Breakpoints BreakHandler::takeEnabledBreakpoints() +PROPERTY(bool, useFullPath, setUseFullPath) +PROPERTY(QString, markerFileName, setMarkerFileName) +PROPERTY(QString, fileName, setFileName) +PROPERTY(QString, functionName, setFunctionName) +PROPERTY(int, markerLineNumber, setMarkerLineNumber) +PROPERTY(bool, isEnabled, setEnabled) +PROPERTY(BreakpointType, type, setType) +PROPERTY(BreakpointState, state, setState) +PROPERTY(QByteArray, threadSpec, setThreadSpec) +PROPERTY(QByteArray, condition, setCondition) +PROPERTY(int, lineNumber, setLineNumber) +PROPERTY(quint64, address, setAddress) + +DebuggerEngine *BreakHandler::engine(BreakpointId id) const { - Breakpoints result = m_enabled; - m_enabled.clear(); - return result; + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return 0); + return data->engine(); } -Breakpoints BreakHandler::takeDisabledBreakpoints() +void BreakHandler::setEngine(BreakpointId id, DebuggerEngine *value) { - Breakpoints result = m_disabled; - m_disabled.clear(); - return result; + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return); + QTC_ASSERT(data->state() == BreakpointNew, /**/); + QTC_ASSERT(!data->engine(), return); + data->setEngine(value); + data->setState(BreakpointInsertRequested); + updateMarker(id); + scheduleSynchronization(); } -void BreakHandler::removeBreakpointHelper(int index) +void BreakHandler::ackCondition(BreakpointId id) { - BreakpointData *data = at(index); + BreakpointData *data = m_bp.value(id); + BreakpointResponse *response = m_responses[id]; QTC_ASSERT(data, return); - m_bp.removeAt(index); - removeMarker(data); - m_removed.append(data); + QTC_ASSERT(response, return); + response->bpCondition = data->condition(); + updateMarker(id); } -void BreakHandler::removeBreakpoint(int index) +void BreakHandler::ackIgnoreCount(BreakpointId id) { - if (index < 0 || index >= size()) - return; - removeBreakpointHelper(index); - emit layoutChanged(); + BreakpointData *data = m_bp.value(id); + BreakpointResponse *response = m_responses[id]; + QTC_ASSERT(data, return); + QTC_ASSERT(response, return); + response->bpIgnoreCount = data->ignoreCount(); + updateMarker(id); } -void BreakHandler::removeBreakpoint(BreakpointData *data) +Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const { - removeBreakpointHelper(indexOf(data)); - emit layoutChanged(); +// switch (index.column()) { +// //case 0: +// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; +// default: + return QAbstractTableModel::flags(index); +// } } -void BreakHandler::toggleBreakpointEnabled(BreakpointData *data) +void BreakHandler::removeBreakpoint(BreakpointId id) { - QTC_ASSERT(data, return); - data->enabled = !data->enabled; - if (data->enabled) { - m_enabled.append(data); - m_disabled.removeAll(data); + BreakpointData *data = m_bp.value(id); + if (data->state() == BreakpointInserted) { + qDebug() << "MARK AS CHANGED: " << id; + data->m_state = BreakpointRemoveRequested; + QTC_ASSERT(data->engine(), return); + debuggerCore()->synchronizeBreakpoints(); + } else if (data->state() == BreakpointNew) { + data->m_state = BreakpointDead; + cleanupBreakpoint(id); } else { - m_enabled.removeAll(data); - m_disabled.append(data); + qDebug() << "CANNOT REMOVE IN STATE " << data->state(); } - removeMarker(data); // Force icon update. - updateMarker(data); - emit layoutChanged(); - synchronizeBreakpoints(); -} - -void BreakHandler::toggleBreakpointEnabled(const QString &fileName, int lineNumber) -{ - BreakpointData *data = findBreakpoint(fileName, lineNumber); - toggleBreakpointEnabled(data); } void BreakHandler::appendBreakpoint(BreakpointData *data) { - append(data); - emit layoutChanged(); - saveBreakpoints(); // FIXME: remove? - updateMarkers(); -} - -void BreakHandler::removeAllBreakpoints() -{ - for (int index = size(); --index >= 0;) - removeBreakpointHelper(index); - emit layoutChanged(); - updateMarkers(); -} + // Ok to be not thread-safe. The order does not matter and only the gui + // produces authoritative ids. + static quint64 currentId = 0; -BreakpointData *BreakHandler::findBreakpoint(quint64 address) const -{ - foreach (BreakpointData *data, m_bp) - if (data->address == address) - return data; - return 0; -} - -BreakpointData *BreakHandler::findBreakpoint(const QString &fileName, - int lineNumber, bool useMarkerPosition) -{ - foreach (BreakpointData *data, m_bp) - if (data->isLocatedAt(fileName, lineNumber, useMarkerPosition)) - return data; - return 0; + BreakpointId id(++currentId); + m_bp.insert(id, data); + m_responses.insert(id, new BreakpointResponse); + scheduleSynchronization(); } void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber, quint64 address /* = 0 */) { - BreakpointData *data = 0; + BreakpointId id(-1); if (address) { - data = findBreakpoint(address); + id = findBreakpointByAddress(address); } else { - data = findBreakpoint(fileName, lineNumber, true); - if (!data) - data = findBreakpoint(fileName, lineNumber, false); + id = findBreakpointByFileAndLine(fileName, lineNumber, true); + if (id == BreakpointId(-1)) + id = findBreakpointByFileAndLine(fileName, lineNumber, false); } - if (data) { - removeBreakpoint(data); + if (id != BreakpointId(-1)) { + removeBreakpoint(id); } else { - data = new BreakpointData; + BreakpointData *data = new BreakpointData; if (address) { - data->address = address; + data->setAddress(address); } else { - data->fileName = fileName; - data->lineNumber = lineNumber; + data->setFileName(fileName); + data->setLineNumber(lineNumber); } - data->pending = true; data->setMarkerFileName(fileName); data->setMarkerLineNumber(lineNumber); appendBreakpoint(data); } - synchronizeBreakpoints(); + debuggerCore()->synchronizeBreakpoints(); } void BreakHandler::saveSessionData() { - // FIXME QTC_ASSERT(m_engine->isSessionEngine(), return); saveBreakpoints(); } void BreakHandler::loadSessionData() { - // FIXME QTC_ASSERT(m_engine->isSessionEngine(), return); - foreach (BreakpointData *bp, m_bp) { - delete m_markers.take(bp->id); - } + qDeleteAll(m_responses); + m_responses.clear(); qDeleteAll(m_bp); m_bp.clear(); + qDeleteAll(m_markers); + m_markers.clear(); loadBreakpoints(); - updateMarkers(); } 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. - for (int index = size(); --index >= 0;) { - const BreakpointData *data = at(index); + ConstIterator it = m_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) { + const BreakpointData *data = it.value(); QTC_ASSERT(data, break); - if (data->funcName == functionName && data->condition.isEmpty() - && data->ignoreCount == 0) + if (data->functionName() == functionName + && data->condition().isEmpty() + && data->ignoreCount() == 0) return; } BreakpointData *data = new BreakpointData; - data->funcName = functionName; - append(data); - //saveBreakpoints(); + data->setType(BreakpointByFunction); + data->setFunctionName(functionName); + appendBreakpoint(data); +} + +QIcon BreakHandler::icon(BreakpointId id) const +{ + //if (!m_handler->isActive()) + // return m_handler->emptyIcon(); + const BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return pendingBreakPointIcon()); + //if (!isActive()) + // return emptyIcon(); + switch (data->state()) { + case BreakpointInserted: + return breakpointIcon(); + default: + return pendingBreakPointIcon(); + } +} + +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(); updateMarkers(); + emit layoutChanged(); + saveBreakpoints(); // FIXME: remove? +} + +void BreakHandler::gotoLocation(BreakpointId id) const +{ + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return); + debuggerCore()->gotoLocation( + data->fileName(), data->lineNumber(), false); +} + +void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber) +{ + BreakpointData *data = m_bp.value(id); + QTC_ASSERT(data, return); + //if (data->markerLineNumber == lineNumber) + // return; + if (data->markerLineNumber() != lineNumber) { + data->setMarkerLineNumber(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? + BreakpointResponse *response = m_responses[id]; + QTC_ASSERT(response, return); + if (response->bpNumber == 0) { + data->setLineNumber(lineNumber); + updateMarker(id); + } +} + +BreakpointIds BreakHandler::allBreakpointIds() const +{ + BreakpointIds ids; + ConstIterator it = m_bp.constBegin(), et = m_bp.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_bp.constBegin(), et = m_bp.constEnd(); + for ( ; it != et; ++it) + if (it.value()->engine() == engine) + ids.append(it.key()); + return ids; +} + +void BreakHandler::notifyBreakpointInsertOk(BreakpointId id) +{ + QTC_ASSERT(breakHandler()->state(id)== BreakpointInsertProceeding, /**/); + breakHandler()->setState(id, BreakpointInserted); } -bool BreakHandler::isActive() const +void BreakHandler::notifyBreakpointInsertFailed(BreakpointId id) { - return true; // FIXME m_engine->isActive(); + QTC_ASSERT(breakHandler()->state(id)== BreakpointInsertProceeding, /**/); + breakHandler()->setState(id, BreakpointDead); } -int BreakHandler::size() const +void BreakHandler::notifyBreakpointRemoveOk(BreakpointId id) { - return m_bp.size(); + QTC_ASSERT(state(id) == BreakpointRemoveProceeding, /**/); + setState(id, BreakpointDead); + cleanupBreakpoint(id); } -int BreakHandler::indexOf(BreakpointData *data) +void BreakHandler::notifyBreakpointRemoveFailed(BreakpointId id) { - return m_bp.indexOf(data); + QTC_ASSERT(state(id) == BreakpointRemoveProceeding, /**/); + setState(id, BreakpointDead); + cleanupBreakpoint(id); } -void BreakHandler::synchronizeBreakpoints() +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, /**/); + setState(id, BreakpointNew); + m_bp.value(id)->setEngine(0); + delete m_markers.take(id); + *m_responses[id] = BreakpointResponse(); + updateMarker(id); +} + +void BreakHandler::cleanupBreakpoint(BreakpointId id) +{ + QTC_ASSERT(state(id) == BreakpointDead, /**/); + delete m_markers.take(id); + delete m_bp.take(id); + delete m_responses.take(id); +} + +BreakpointResponse BreakHandler::response(BreakpointId id) const +{ + BreakpointResponse *response = m_responses[id]; + return response ? *response : BreakpointResponse(); +} + +void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &data) +{ + delete m_responses.take(id); + m_responses[id] = new BreakpointResponse(data); + updateMarker(id); +} +#if 0 +void BreakHandler::notifyBreakpointAdjusted(BreakpointId id) { - emit breakpointSynchronizationRequested(); + QTC_ASSERT(state(id)== BreakpointChangeProceeding, /**/); + bp->bpNumber = rbp.bpNumber; + bp->bpCondition = rbp.bpCondition; + bp->bpIgnoreCount = rbp.bpIgnoreCount; + bp->bpFileName = rbp.bpFileName; + bp->bpFullName = rbp.bpFullName; + bp->bpLineNumber = rbp.bpLineNumber; + bp->bpCorrectedLineNumber = rbp.bpCorrectedLineNumber; + bp->bpThreadSpec = rbp.bpThreadSpec; + bp->bpFuncName = rbp.bpFuncName; + bp->bpAddress = rbp.bpAddress; + bp->bpMultiple = rbp.bpMultiple; + bp->bpEnabled = rbp.bpEnabled; + setState(id, BreakpointOk); } +#endif } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 0099c7c1d3eec6a34a89f14dd398286925b7da12..877b19a541f07e12fcbd6ea76035a1ad5405fc9a 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -37,18 +37,15 @@ #include <QtGui/QIcon> -namespace Debugger { - -class DebuggerEngine; - -namespace Internal { - ////////////////////////////////////////////////////////////////// // // BreakHandler // ////////////////////////////////////////////////////////////////// +namespace Debugger { +namespace Internal { + class BreakHandler : public QAbstractTableModel { Q_OBJECT @@ -57,31 +54,28 @@ public: BreakHandler(); ~BreakHandler(); - void removeAllBreakpoints(); void loadSessionData(); void saveSessionData(); QAbstractItemModel *model() { return this; } - BreakpointData *at(int index) const; - int size() const; + BreakpointIds allBreakpointIds() const; + BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const; + BreakpointIds unclaimedBreakpointIds() const; + BreakpointData *breakpointById(BreakpointId id) const; + int size() const { return m_bp.size(); } bool hasPendingBreakpoints() const; - void removeAt(int index); // This also deletes the marker. - void clear(); // This also deletes all the marker. - int indexOf(BreakpointData *data); + // Find a breakpoint matching approximately the data in needle. - BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const; - BreakpointData *findBreakpointByNumber(int bpNumber) const; - int findWatchPointIndexByAddress(quint64 address) const; - bool watchPointAt(quint64 address) const; + BreakpointId findSimilarBreakpoint(const BreakpointResponse &needle) const; + BreakpointId findBreakpointByNumber(int bpNumber) const; + BreakpointId findWatchpointByAddress(quint64 address) const; + BreakpointId findBreakpointByFunction(const QString &functionName) const; + BreakpointId findBreakpointByIndex(const QModelIndex &index) const; + void setWatchpointByAddress(quint64 address); + bool hasWatchpointAt(quint64 address) const; void updateMarkers(); - void updateMarker(BreakpointData *); - void removeMarker(BreakpointData *); - bool isActive() const; - - Breakpoints takeRemovedBreakpoints(); // Owned. - Breakpoints takeEnabledBreakpoints(); // Not owned. - Breakpoints takeDisabledBreakpoints(); // Not owned. + void removeMarker(BreakpointId id); QIcon breakpointIcon() const { return m_breakpointIcon; } QIcon disabledBreakpointIcon() const { return m_disabledBreakpointIcon; } @@ -89,21 +83,60 @@ public: QIcon emptyIcon() const { return m_emptyIcon; } void toggleBreakpoint(const QString &fileName, int lineNumber, quint64 address = 0); - void toggleBreakpointEnabled(const QString &fileName, int lineNumber); - BreakpointData *findBreakpoint(const QString &fileName, int lineNumber, - bool useMarkerPosition = true); - BreakpointData *findBreakpoint(quint64 address) const; + BreakpointId findBreakpointByFileAndLine(const QString &fileName, + int lineNumber, bool useMarkerPosition = true); + BreakpointId findBreakpointByAddress(quint64 address) const; - void appendBreakpoint(BreakpointData *data); - void reinsertBreakpoint(BreakpointData *data); - void toggleBreakpointEnabled(BreakpointData *data); void breakByFunction(const QString &functionName); - void removeBreakpoint(int index); - void removeBreakpoint(BreakpointData *data); - void synchronizeBreakpoints(); - -signals: - void breakpointSynchronizationRequested(); + void removeBreakpoint(BreakpointId id); + QIcon icon(BreakpointId id) const; + + void gotoLocation(BreakpointId id) const; + + // Getter retrieves property value. + // Setter sets property value and triggers update if changed. + #define PROPERTY(type, getter, setter) \ + type getter(BreakpointId id) const; \ + void setter(BreakpointId id, const type &value); + + PROPERTY(bool, useFullPath, setUseFullPath) + PROPERTY(QString, markerFileName, setMarkerFileName) + PROPERTY(int, markerLineNumber, setMarkerLineNumber) + PROPERTY(QByteArray, condition, setCondition) + PROPERTY(int, ignoreCount, setIgnoreCount) + PROPERTY(QByteArray, threadSpec, setThreadSpec) + PROPERTY(BreakpointState, state, setState) + PROPERTY(QString, fileName, setFileName) + PROPERTY(QString, functionName, setFunctionName) + PROPERTY(BreakpointType, type, setType); + PROPERTY(quint64, address, setAddress); + PROPERTY(int, lineNumber, setLineNumber); + #undef PROPERTY + bool isEnabled(BreakpointId id) const; + void setEnabled(BreakpointId id, const bool &on); + void updateEnabled(BreakpointId id, const bool &on); + void updateLineNumberFromMarker(BreakpointId id, int lineNumber); + + DebuggerEngine *engine(BreakpointId id) const; + void setEngine(BreakpointId id, DebuggerEngine *engine); + BreakpointResponse response(BreakpointId id) const; + void setResponse(BreakpointId id, const BreakpointResponse &data); + + // Incorporate debugger feedback. No synchronization request needed. + // Return true if something changed. + void ackCondition(BreakpointId id); + void ackIgnoreCount(BreakpointId id); + + void notifyBreakpointInsertOk(BreakpointId id); + void notifyBreakpointInsertFailed(BreakpointId id); + void notifyBreakpointChangeOk(BreakpointId id); + void notifyBreakpointChangeFailed(BreakpointId id); + void notifyBreakpointRemoveOk(BreakpointId id); + void notifyBreakpointRemoveFailed(BreakpointId id); + void notifyBreakpointReleased(BreakpointId id); + + // This takes ownership. + void appendBreakpoint(BreakpointData *data); private: friend class BreakpointMarker; @@ -118,8 +151,8 @@ private: void markerUpdated(BreakpointMarker *marker, int lineNumber); void loadBreakpoints(); void saveBreakpoints(); - void removeBreakpointHelper(int index); - void append(BreakpointData *data); + void updateMarker(BreakpointId id); + void cleanupBreakpoint(BreakpointId id); const QIcon m_breakpointIcon; const QIcon m_disabledBreakpointIcon; @@ -127,17 +160,17 @@ private: const QIcon m_emptyIcon; const QIcon m_watchpointIcon; - Breakpoints m_inserted; // Lately inserted breakpoints. - Breakpoints m_removed; // Lately removed breakpoints. - Breakpoints m_enabled; // Lately enabled breakpoints. - Breakpoints m_disabled; // Lately disabled breakpoints. - - // Hack for BreakWindow::findSimilarBreakpoint - mutable BreakpointData *m_lastFound; - mutable bool m_lastFoundQueried; - + typedef QMap<BreakpointId, BreakpointData *> Breakpoints; + typedef QMap<BreakpointId, BreakpointMarker *> Markers; + typedef QMap<BreakpointId, BreakpointResponse *> Responses; + typedef Breakpoints::ConstIterator ConstIterator; Breakpoints m_bp; - QHash<quint64, BreakpointMarker *> m_markers; + Markers m_markers; + Responses m_responses; + + void scheduleSynchronization(); + void timerEvent(QTimerEvent *event); + int m_syncTimerId; }; } // namespace Internal diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 269e37d7c0ad21d9885dd49e2633ae7e80f2924e..8ee94e6604d6b81d7f34cdf4c308c445924f72a1 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -50,88 +50,86 @@ namespace Internal { const char *BreakpointData::throwFunction = "throw"; const char *BreakpointData::catchFunction = "catch"; -static quint64 nextBPId() { - /* ok to be not thread-safe - the order does not matter and only the gui - produces authoritative ids. well, for now... - */ - static quint64 i=1; - return ++i; -} - -BreakpointData::BreakpointData() : - id(nextBPId()), uiDirty(false), enabled(true), - pending(true), type(BreakpointByFileAndLine), - ignoreCount(0), lineNumber(0), address(0), - useFullPath(false), - bpIgnoreCount(0), bpLineNumber(0), - bpCorrectedLineNumber(0), bpAddress(0), - bpMultiple(false), bpEnabled(true), - m_markerLineNumber(0) -{ -} - -BreakpointData *BreakpointData::clone() const +static quint64 nextBPId() { - BreakpointData *data = new BreakpointData(); - data->enabled = enabled; - data->type = type; - data->fileName = fileName; - data->condition = condition; - data->ignoreCount = ignoreCount; - data->lineNumber = lineNumber; - data->address = address; - data->threadSpec = threadSpec; - data->funcName = funcName; - data->useFullPath = useFullPath; - if (data->type == BreakpointByFunction) { - // FIXME: Would removing it be better then leaving this - // "history" around? - data->m_markerFileName = m_markerFileName; - data->m_markerLineNumber = m_markerLineNumber; - } else { - data->m_markerFileName = fileName; - data->m_markerLineNumber = lineNumber; - } - return data; + // Ok to be not thread-safe. The order does not matter and only the gui + // produces authoritative ids. + static quint64 i = 0; + return ++i; } -BreakpointData::~BreakpointData() +BreakpointData::BreakpointData() { + m_state = BreakpointNew; + m_engine = 0; + m_enabled = true; + m_type = BreakpointByFileAndLine; + m_ignoreCount = 0; + m_lineNumber = 0; + m_address = 0; + m_useFullPath = false; + m_markerLineNumber = 0; } -void BreakpointData::clear() +BreakpointResponse::BreakpointResponse() { - uiDirty = false; - pending = true; - bpNumber.clear(); - bpCondition.clear(); + bpNumber = 0; bpIgnoreCount = 0; - bpFileName.clear(); - bpFullName.clear(); bpLineNumber = 0; - bpCorrectedLineNumber = 0; - bpThreadSpec.clear(); - bpFuncName.clear(); + //bpCorrectedLineNumber = 0; bpAddress = 0; bpMultiple = false; bpEnabled = true; - bpState.clear(); - m_markerFileName = fileName; - m_markerLineNumber = lineNumber; } -void BreakpointData::setMarkerFileName(const QString &fileName) -{ - m_markerFileName = fileName; -} +#define SETIT(var, value) return (var != value) && (var = value, true) -void BreakpointData::setMarkerLineNumber(int lineNumber) -{ - m_markerLineNumber = lineNumber; -} +bool BreakpointData::setUseFullPath(bool on) +{ SETIT(m_useFullPath, on); } + +bool BreakpointData::setMarkerFileName(const QString &file) +{ SETIT(m_markerFileName, file); } + +bool BreakpointData::setMarkerLineNumber(int line) +{ SETIT(m_markerLineNumber, line); } + +bool BreakpointData::setFileName(const QString &file) +{ SETIT(m_fileName, file); } + +bool BreakpointData::setEnabled(bool on) +{ SETIT(m_enabled, on); } + +bool BreakpointData::setIgnoreCount(bool count) +{ SETIT(m_ignoreCount, count); } + +bool BreakpointData::setFunctionName(const QString &name) +{ SETIT(m_functionName, name); } + +bool BreakpointData::setLineNumber(int line) +{ SETIT(m_lineNumber, line); } + +bool BreakpointData::setAddress(quint64 address) +{ SETIT(m_address, address); } -static inline void formatAddress(QTextStream &str, quint64 address) +bool BreakpointData::setThreadSpec(const QByteArray &spec) +{ SETIT(m_threadSpec, spec); } + +bool BreakpointData::setType(BreakpointType type) +{ SETIT(m_type, type); } + +bool BreakpointData::setCondition(const QByteArray &cond) +{ SETIT(m_condition, cond); } + +bool BreakpointData::setState(BreakpointState state) +{ SETIT(m_state, state); } + +bool BreakpointData::setEngine(DebuggerEngine *engine) +{ SETIT(m_engine, engine); } + +#undef SETIT + + +static void formatAddress(QTextStream &str, quint64 address) { if (address) { str << "0x"; @@ -143,8 +141,8 @@ static inline void formatAddress(QTextStream &str, quint64 address) QString BreakpointData::toToolTip() const { - QString t = tr("Unknown Breakpoint Type"); - switch (type) { + QString t; + switch (m_type) { case BreakpointByFileAndLine: t = tr("Breakpoint by File and Line"); break; @@ -157,64 +155,72 @@ QString BreakpointData::toToolTip() const case Watchpoint: t = tr("Watchpoint"); break; + case UnknownType: + t = tr("Unknown Breakpoint Type"); } QString rc; QTextStream str(&rc); str << "<html><body><table>" + //<< "<tr><td>" << tr("Id:") + //<< "</td><td>" << m_id << "</td></tr>" + << "<tr><td>" << tr("State:") + << "</td><td>" << m_state << "</td></tr>" + << "<tr><td>" << tr("Engine:") + << "</td><td>" << m_engine << "</td></tr>" << "<tr><td>" << tr("Marker File:") << "</td><td>" << QDir::toNativeSeparators(m_markerFileName) << "</td></tr>" << "<tr><td>" << tr("Marker Line:") << "</td><td>" << m_markerLineNumber << "</td></tr>" - << "<tr><td>" << tr("Breakpoint Number:") - << "</td><td>" << bpNumber << "</td></tr>" + //<< "<tr><td>" << tr("Breakpoint Number:") + //<< "</td><td>" << bpNumber << "</td></tr>" << "<tr><td>" << tr("Breakpoint Type:") << "</td><td>" << t << "</td></tr>" << "<tr><td>" << tr("State:") - << "</td><td>" << bpState << "</td></tr>" + //<< "</td><td>" << bpState << "</td></tr>" << "</table><br><hr><table>" << "<tr><th>" << tr("Property") << "</th><th>" << tr("Requested") << "</th><th>" << tr("Obtained") << "</th></tr>" << "<tr><td>" << tr("Internal Number:") - << "</td><td>—</td><td>" << bpNumber << "</td></tr>" + //<< "</td><td>—</td><td>" << bpNumber << "</td></tr>" << "<tr><td>" << tr("File Name:") - << "</td><td>" << QDir::toNativeSeparators(fileName) - << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>" + << "</td><td>" << QDir::toNativeSeparators(m_fileName) + //<< "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>" << "<tr><td>" << tr("Function Name:") - << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>" + << "</td><td>" << m_functionName // << "</td><td>" << bpFuncName << "</td></tr>" << "<tr><td>" << tr("Line Number:") << "</td><td>"; - if (lineNumber) - str << lineNumber; - str << "</td><td>"; - if (bpLineNumber) - str << bpLineNumber; + if (m_lineNumber) + str << m_lineNumber; + //str << "</td><td>"; + //if (bpLineNumber) + // str << bpLineNumber; str << "</td></tr>" << "<tr><td>" << tr("Breakpoint Address:") << "</td><td>"; - formatAddress(str, address); + formatAddress(str, m_address); str << "</td><td>"; - formatAddress(str, bpAddress); - str << "</td></tr>" - << "<tr><td>" << tr("Corrected Line Number:") - << "</td><td>-</td><td>"; - if (bpCorrectedLineNumber > 0) { - str << bpCorrectedLineNumber; - } else { - str << '-'; - } + //formatAddress(str, bpAddress); + //str << "</td></tr>" + // << "<tr><td>" << tr("Corrected Line Number:") + // << "</td><td>-</td><td>"; + //if (bpCorrectedLineNumber > 0) { + // str << bpCorrectedLineNumber; + // } else { + // str << '-'; + // } str << "</td></tr>" << "<tr><td>" << tr("Condition:") - << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>" + // << "</td><td>" << m_condition << "</td><td>" << bpCondition << "</td></tr>" << "<tr><td>" << tr("Ignore Count:") << "</td><td>"; - if (ignoreCount) - str << ignoreCount; + if (m_ignoreCount) + str << m_ignoreCount; str << "</td><td>"; - if (bpIgnoreCount) - str << bpIgnoreCount; + //if (bpIgnoreCount) + // str << bpIgnoreCount; str << "</td></tr>" << "<tr><td>" << tr("Thread Specification:") - << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" + // << "</td><td>" << m_threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" << "</table></body></html>"; return rc; } @@ -229,66 +235,52 @@ static inline bool fileNameMatch(const QString &f1, const QString &f2) #endif } -bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_, +bool BreakpointData::isLocatedAt(const QString &fileName, int lineNumber, bool useMarkerPosition) const { - int line = useMarkerPosition ? m_markerLineNumber : lineNumber; - return lineNumber_ == line && fileNameMatch(fileName_, m_markerFileName); + int line = useMarkerPosition ? m_markerLineNumber : m_lineNumber; + return lineNumber == line && fileNameMatch(fileName, m_markerFileName); } -bool BreakpointData::isSimilarTo(const BreakpointData *needle) const -{ - //qDebug() << "COMPARING " << toString() << " WITH " << needle->toString(); - - if (id == needle->id && id != 0) - return true; - - // Clear hit. - if (bpNumber == needle->bpNumber - && !bpNumber.isEmpty() - && bpNumber.toInt() != 0) - return true; - - // Clear miss. - if (type != needle->type) - return false; - - // We have numbers, but they are different. - if (!bpNumber.isEmpty() && !needle->bpNumber.isEmpty() - && !bpNumber.startsWith(needle->bpNumber) - && !needle->bpNumber.startsWith(bpNumber)) - return false; - - if (address && needle->address && address == needle->address) - return true; - - // At least at a position we were looking for. - // FIXME: breaks multiple breakpoints at the same location - if (!fileName.isEmpty() - && fileNameMatch(fileName, needle->fileName) - && lineNumber == needle->lineNumber) - return true; - - // At least at a position we were looking for. - // FIXME: breaks multiple breakpoints at the same location - if (!fileName.isEmpty() - && fileNameMatch(fileName, needle->bpFileName) - && lineNumber == needle->bpLineNumber) - return true; - - return false; -} - -bool BreakpointData::conditionsMatch() const +bool BreakpointData::conditionsMatch(const QString &other) const { // Some versions of gdb "beautify" the passed condition. - QString s1 = condition; + QString s1 = m_condition; s1.remove(QChar(' ')); - QString s2 = bpCondition; + QString s2 = other; s2.remove(QChar(' ')); return s1 == s2; } +QString BreakpointData::toString() const +{ + QString result; + QTextStream ts(&result); + ts << fileName(); + ts << condition(); + ts << ignoreCount(); + ts << lineNumber(); + ts << address(); + ts << functionName(); + ts << useFullPath(); + return result; +} + +QString BreakpointResponse::toString() const +{ + QString result; + QTextStream ts(&result); + ts << bpNumber; + ts << bpCondition; + ts << bpIgnoreCount; + ts << bpFileName; + ts << bpFullName; + ts << bpLineNumber; + ts << bpThreadSpec; + ts << bpFuncName; + ts << bpAddress; + return result; +} + } // namespace Internal } // namespace Debugger - diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index e155457ffd2ba18fee3f67f57f38d7dfd9f84e21..c013df2ef0239f8136ad5d62ace978a0232aed76 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -36,6 +36,11 @@ #include <QtCore/QCoreApplication> namespace Debugger { + +class DebuggerEngine; + +typedef quint64 BreakpointId; // FIXME: make Internal. + namespace Internal { class BreakpointMarker; @@ -49,6 +54,7 @@ class BreakHandler; enum BreakpointType { + UnknownType, BreakpointByFileAndLine, BreakpointByFunction, BreakpointByAddress, @@ -58,36 +64,21 @@ enum BreakpointType enum BreakpointState { BreakpointNew, - BreakpointInsertionRequested, // Inferior was told about bp, not ack'ed. + BreakpointInsertRequested, // Inferior was told about bp, not ack'ed. + BreakpointInsertProceeding, BreakpointChangeRequested, - BreakpointOk, - BreakpointRemovalRequested, - BreakpointRemoved, + BreakpointChangeProceeding, + BreakpointPending, + BreakpointInserted, + BreakpointRemoveRequested, + BreakpointRemoveProceeding, BreakpointDead, }; class BreakpointData { -public: - BreakpointData(); - ~BreakpointData(); - - QString toToolTip() const; - void clear(); // Delete all generated data. - - bool isLocatedAt(const QString &fileName, int lineNumber, - bool useMarkerPosition) const; - bool isSimilarTo(const BreakpointData *needle) const; - bool conditionsMatch() const; - - // This copies only the static data. - BreakpointData *clone() const; - - // Generic name for function to break on 'throw' - static const char *throwFunction; - static const char *catchFunction; - private: + // Intentionally unimplemented. // Making it copyable is tricky because of the markers. BreakpointData(const BreakpointData &); @@ -96,64 +87,106 @@ private: friend class BreakHandler; public: - quint64 id; - BreakpointState state; - bool uiDirty; // ui has changed stuff + BreakpointData(); - bool enabled; // Should we talk to the debugger engine? - bool pending; // Does the debugger engine know about us already? - BreakpointType type; // Type of breakpoint. + bool isPending() const { return m_state == BreakpointPending + || m_state == BreakpointNew; } + BreakpointType type() const { return m_type; } + quint64 address() const { return m_address; } + bool useFullPath() const { return m_useFullPath; } + QString toToolTip() const; + QString toString() const; - // This "user requested information" will get stored in the session. - QString fileName; // Short name of source file. - QByteArray condition; // Condition associated with breakpoint. - int ignoreCount; // Ignore count associated with breakpoint. - int lineNumber; // Line in source file. - quint64 address; // Address for watchpoints. - QByteArray threadSpec; // Thread specification. - // Name of containing function, special values: - // BreakpointData::throwFunction, BreakpointData::catchFunction - QString funcName; - 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. - int 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. - int bpLineNumber; // Line number acknowledged by the debugger engine. - int bpCorrectedLineNumber; // Acknowledged by the debugger engine. - QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine. - QString bpFuncName; // Function name acknowledged by the debugger engine. - quint64 bpAddress; // Address acknowledged by the debugger engine. - bool bpMultiple; // Happens in constructors/gdb. - bool bpEnabled; // Enable/disable command sent. - QByteArray bpState; // gdb: <PENDING>, <MULTIPLE> - - void setMarkerFileName(const QString &fileName); + bool isLocatedAt(const QString &fileName, int lineNumber, + bool useMarkerPosition) const; + bool conditionsMatch(const QString &other) const; + BreakpointState state() const { return m_state; } + QString functionName() const { return m_functionName; } QString markerFileName() const { return m_markerFileName; } - - void setMarkerLineNumber(int lineNumber); + QString fileName() const { return m_fileName; } int markerLineNumber() const { return m_markerLineNumber; } + int lineNumber() const { return m_lineNumber; } + int ignoreCount() const { return m_ignoreCount; } + bool isEnabled() const { return m_enabled; } + QByteArray threadSpec() const { return m_threadSpec; } + QByteArray condition() const { return m_condition; } + DebuggerEngine *engine() const { return m_engine; } + + bool isWatchpoint() const { return m_type == Watchpoint; } + bool isBreakpoint() const { return m_type != Watchpoint; } // Enough for now. + // Generic name for function to break on 'throw' + static const char *throwFunction; + static const char *catchFunction; - bool isWatchpoint() const { return type == Watchpoint; } - bool isBreakpoint() const { return type != Watchpoint; } // Enough for now. - - Q_DECLARE_TR_FUNCTIONS(BreakHandler) +//private: + // All setters return true on change. + bool setUseFullPath(bool on); + bool setMarkerFileName(const QString &file); + bool setMarkerLineNumber(int line); + bool setFileName(const QString &file); + bool setEnabled(bool on); + bool setIgnoreCount(bool count); + bool setFunctionName(const QString &name); + bool setLineNumber(int line); + bool setAddress(quint64 address); + bool setThreadSpec(const QByteArray &spec); + bool setType(BreakpointType type); + bool setCondition(const QByteArray &cond); + bool setState(BreakpointState state); + bool setEngine(DebuggerEngine *engine); - // TODO: move those to breakhandler private: - // Taken from either user input or gdb responses. + DebuggerEngine *m_engine; + BreakpointType m_type; // Type of breakpoint. + BreakpointState m_state; // Current state of breakpoint. + bool m_enabled; // Should we talk to the debugger engine? + bool m_pending; // Does the debugger engine know about us already? + bool m_useFullPath; // Should we use the full path when setting the bp? + // This "user requested information" will get stored in the session. + QString m_fileName; // Short name of source file. + QByteArray m_condition; // Condition associated with breakpoint. + int m_ignoreCount; // Ignore count associated with breakpoint. + int m_lineNumber; // Line in source file. + quint64 m_address; // Address for watchpoints. + QByteArray m_threadSpec; // Thread specification. + // Name of containing function, special values: + // BreakpointData::throwFunction, BreakpointData::catchFunction + QString m_functionName; QString m_markerFileName; // Used to locate the marker. int m_markerLineNumber; + +public: + Q_DECLARE_TR_FUNCTIONS(BreakHandler) +}; + +// This is what debuggers produced in response to the attempt to +// insert a breakpoint. The data might differ from the requested bits. +class BreakpointResponse +{ +public: + BreakpointResponse(); + QString toString() const; + +public: + int bpNumber; // Breakpoint number assigned by the debugger engine. + BreakpointType bpType; // Breakpoint type used by debugger engine. + QByteArray bpCondition; // Condition acknowledged by the debugger engine. + int 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. + int bpLineNumber; // Line number acknowledged by the debugger engine. + //int bpCorrectedLineNumber; // Acknowledged by the debugger engine. + QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine. + QString bpFuncName; // Function name acknowledged by the debugger engine. + quint64 bpAddress; // Address acknowledged by the debugger engine. + bool bpMultiple; // Happens in constructors/gdb. + bool bpEnabled; // Enable/disable command sent. + QByteArray bpState; // gdb: <PENDING>, <MULTIPLE> }; -typedef QList<BreakpointData *> Breakpoints; +typedef QList<BreakpointId> BreakpointIds; } // namespace Internal } // namespace Debugger -Q_DECLARE_METATYPE(Debugger::Internal::BreakpointData *); - #endif // DEBUGGER_BREAKPOINT_H diff --git a/src/plugins/debugger/breakpointmarker.cpp b/src/plugins/debugger/breakpointmarker.cpp index f0ffa4d67e41769dd4e2ad00ce9849629132f264..c77751b478a17e9cdf342e92328d41f9f43e9a69 100644 --- a/src/plugins/debugger/breakpointmarker.cpp +++ b/src/plugins/debugger/breakpointmarker.cpp @@ -29,17 +29,14 @@ #include "breakpointmarker.h" #include "breakhandler.h" - -#include "stackframe.h" +#include "debuggercore.h" #include <texteditor/basetextmark.h> #include <utils/qtcassert.h> #include <QtCore/QByteArray> #include <QtCore/QDebug> -#include <QtCore/QTextStream> -#include <QtCore/QFileInfo> -#include <QtCore/QDir> + ////////////////////////////////////////////////////////////////// // @@ -51,12 +48,9 @@ namespace Debugger { namespace Internal { -BreakpointMarker::BreakpointMarker(BreakHandler *handler, BreakpointData *data, +BreakpointMarker::BreakpointMarker(BreakpointId id, const QString &fileName, int lineNumber) - : BaseTextMark(fileName, lineNumber) - , m_handler(handler) - , m_data(data) - , m_pending(true) + : BaseTextMark(fileName, lineNumber), m_id(id) { //qDebug() << "CREATE MARKER " << fileName << lineNumber; } @@ -64,24 +58,11 @@ BreakpointMarker::BreakpointMarker(BreakHandler *handler, BreakpointData *data, BreakpointMarker::~BreakpointMarker() { //qDebug() << "REMOVE MARKER "; - m_data = 0; } QIcon BreakpointMarker::icon() const { - if (!m_data->enabled) - return m_handler->disabledBreakpointIcon(); - if (!m_handler->isActive()) - return m_handler->emptyIcon(); - return m_pending ? m_handler->pendingBreakPointIcon() : m_handler->breakpointIcon(); -} - -void BreakpointMarker::setPending(bool pending) -{ - if (pending == m_pending) - return; - m_pending = pending; - updateMarker(); + return breakHandler()->icon(m_id); } void BreakpointMarker::updateBlock(const QTextBlock &) @@ -91,38 +72,12 @@ void BreakpointMarker::updateBlock(const QTextBlock &) void BreakpointMarker::removedFromEditor() { - if (!m_data) - return; - m_handler->removeBreakpoint(m_data); - //handler->saveBreakpoints(); - m_handler->updateMarkers(); + breakHandler()->removeBreakpoint(m_id); } void BreakpointMarker::updateLineNumber(int lineNumber) { - if (!m_data) - return; - //if (m_data->markerLineNumber == lineNumber) - // return; - if (m_data->markerLineNumber() != lineNumber) { - m_data->setMarkerLineNumber(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 && m_data->bpLineNumber) { - if (!m_data->bpNumber.trimmed().isEmpty()) { - m_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 (m_data->bpNumber.trimmed().isEmpty()) { - m_data->lineNumber = lineNumber; - m_handler->updateMarkers(); - } + breakHandler()->updateLineNumberFromMarker(m_id, lineNumber); } } // namespace Internal diff --git a/src/plugins/debugger/breakpointmarker.h b/src/plugins/debugger/breakpointmarker.h index f643a96d46df5d3d5f7f17e70f8c846b68bc5163..2e8bd325aaa7c3b7e7cac12a199b44547d79ae43 100644 --- a/src/plugins/debugger/breakpointmarker.h +++ b/src/plugins/debugger/breakpointmarker.h @@ -45,18 +45,14 @@ class BreakpointMarker : public TextEditor::BaseTextMark { Q_OBJECT public: - BreakpointMarker(BreakHandler *handler, BreakpointData *data, - const QString &fileName, int lineNumber); + BreakpointMarker(BreakpointId id, const QString &fileName, int lineNumber); ~BreakpointMarker(); QIcon icon() const; - void setPending(bool pending); void updateBlock(const QTextBlock &); void removedFromEditor(); void updateLineNumber(int lineNumber); private: - BreakHandler *m_handler; - BreakpointData *m_data; - bool m_pending; + BreakpointId m_id; friend class BreakHandler; }; diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index ba3ecddddeba81d866e903c659562e96cfe1c3e3..6b328eba7311f15ba18e30f962ba46c94e25f6f8 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -55,32 +55,6 @@ namespace Debugger { namespace Internal { -static BreakHandler *breakHandler() -{ - return debuggerCore()->breakHandler(); -} - -static BreakpointData *breakpointAt(int index) -{ - BreakHandler *handler = breakHandler(); - QTC_ASSERT(handler, return 0); - return handler->at(index); -} - -static void synchronizeBreakpoints() -{ - BreakHandler *handler = breakHandler(); - QTC_ASSERT(handler, return); - handler->synchronizeBreakpoints(); -} - -static void appendBreakpoint(BreakpointData *data) -{ - BreakHandler *handler = breakHandler(); - QTC_ASSERT(handler, return); - handler->appendBreakpoint(data); -} - /////////////////////////////////////////////////////////////////////// // @@ -114,19 +88,20 @@ BreakpointDialog::BreakpointDialog(QWidget *parent) : QDialog(parent) bool BreakpointDialog::showDialog(BreakpointData *data) { - pathChooserFileName->setPath(data->fileName); - lineEditLineNumber->setText(QString::number(data->lineNumber)); - lineEditFunction->setText(data->funcName); - lineEditCondition->setText(QString::fromUtf8(data->condition)); - lineEditIgnoreCount->setText(QString::number(data->ignoreCount)); - checkBoxUseFullPath->setChecked(data->useFullPath); - lineEditThreadSpec->setText(QString::fromUtf8(data->threadSpec)); - if (data->address) - lineEditAddress->setText(QString::fromAscii("0x%1").arg(data->address, 0, 16)); + pathChooserFileName->setPath(data->fileName()); + lineEditLineNumber->setText(QString::number(data->lineNumber())); + lineEditFunction->setText(data->functionName()); + lineEditCondition->setText(QString::fromUtf8(data->condition())); + lineEditIgnoreCount->setText(QString::number(data->ignoreCount())); + checkBoxUseFullPath->setChecked(data->useFullPath()); + lineEditThreadSpec->setText(QString::fromUtf8(data->threadSpec())); + const quint64 address = data->address(); + if (address) + lineEditAddress->setText(QString::fromAscii("0x%1").arg(address, 0, 16)); int initialType = 0; - if (!data->funcName.isEmpty()) - initialType = data->funcName == QLatin1String("main") ? 2 : 1; - if (data->address) + if (!data->functionName().isEmpty()) + initialType = data->functionName() == QLatin1String("main") ? 2 : 1; + if (address) initialType = 3; typeChanged(initialType); @@ -137,26 +112,22 @@ bool BreakpointDialog::showDialog(BreakpointData *data) const int newLineNumber = lineEditLineNumber->text().toInt(); const bool newUseFullPath = checkBoxUseFullPath->isChecked(); const quint64 newAddress = lineEditAddress->text().toULongLong(0, 0); - const QString newFunc = lineEditFunction->text(); + const QString newFunction = lineEditFunction->text(); const QString newFileName = pathChooserFileName->path(); const QByteArray newCondition = lineEditCondition->text().toUtf8(); const int newIgnoreCount = lineEditIgnoreCount->text().toInt(); const QByteArray newThreadSpec = lineEditThreadSpec->text().toUtf8(); - if (newLineNumber == data->lineNumber && newUseFullPath == data->useFullPath - && newAddress == data->address && newFunc == data->funcName - && newFileName == data->fileName && newCondition == data->condition - && newIgnoreCount == data->ignoreCount && newThreadSpec == data->threadSpec) - return false; // Unchanged -> Cancel. - - data->address = newAddress; - data->funcName = newFunc; - data->useFullPath = newUseFullPath; - data->fileName = newFileName; - data->lineNumber = newLineNumber; - data->condition = newCondition; - data->ignoreCount = newIgnoreCount; - data->threadSpec = newThreadSpec; - return true; + + bool result = false; + result |= data->setAddress(newAddress); + result |= data->setFunctionName(newFunction); + result |= data->setUseFullPath(newUseFullPath); + result |= data->setFileName(newFileName); + result |= data->setLineNumber(newLineNumber); + result |= data->setCondition(newCondition); + result |= data->setIgnoreCount(newIgnoreCount); + result |= data->setThreadSpec(newThreadSpec); + return result; } void BreakpointDialog::typeChanged(int index) @@ -189,7 +160,7 @@ BreakWindow::BreakWindow(QWidget *parent) { m_alwaysResizeColumnsToContents = false; - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setFrameStyle(QFrame::NoFrame); setAttribute(Qt::WA_MacShowFocusRect, false); setWindowTitle(tr("Breakpoints")); @@ -200,11 +171,11 @@ BreakWindow::BreakWindow(QWidget *parent) setSelectionMode(QAbstractItemView::ExtendedSelection); connect(this, SIGNAL(activated(QModelIndex)), - this, SLOT(rowActivated(QModelIndex))); + SLOT(rowActivated(QModelIndex))); connect(act, SIGNAL(toggled(bool)), - this, SLOT(setAlternatingRowColorsHelper(bool))); - connect(theDebuggerAction(UseAddressInBreakpointsView), SIGNAL(toggled(bool)), - this, SLOT(showAddressColumn(bool))); + SLOT(setAlternatingRowColorsHelper(bool))); + connect(debuggerCore()->action(UseAddressInBreakpointsView), SIGNAL(toggled(bool)), + SLOT(showAddressColumn(bool))); } BreakWindow::~BreakWindow() @@ -264,6 +235,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) const int rowCount = model()->rowCount(); const unsigned engineCapabilities = BreakOnThrowAndCatchCapability; + BreakHandler *handler = breakHandler(); // FIXME BP: model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt(); QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu); @@ -274,14 +246,14 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) // Delete by file: Find indices of breakpoints of the same file. QAction *deleteByFileAction = 0; - QList<int> breakPointsOfFile; + QList<QModelIndex> breakPointsOfFile; if (indexUnderMouse.isValid()) { const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2); const QString file = model()->data(index).toString(); if (!file.isEmpty()) { for (int i = 0; i < rowCount; i++) if (model()->data(model()->index(i, 2)).toString() == file) - breakPointsOfFile.push_back(i); + breakPointsOfFile.push_back(model()->index(i, 2)); if (breakPointsOfFile.size() > 1) { deleteByFileAction = new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu); @@ -321,8 +293,9 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) QModelIndex idx0 = (si.size() ? si.front() : QModelIndex()); QModelIndex idx2 = idx0.sibling(idx0.row(), 2); - BreakpointData *data = breakpointAt(idx0.row()); - bool enabled = si.isEmpty() || (data && data->enabled); + const BreakpointId id = handler->findBreakpointByIndex(idx0); + + bool enabled = si.isEmpty() || handler->isEnabled(id); const QString str5 = si.size() > 1 ? enabled @@ -348,7 +321,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(toggleEnabledAction); menu.addSeparator(); menu.addAction(deleteAllAction); - menu.addAction(deleteByFileAction); + //menu.addAction(deleteByFileAction); menu.addSeparator(); menu.addAction(synchronizeAction); if (engineCapabilities & BreakOnThrowAndCatchCapability) { @@ -357,21 +330,21 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(breakAtCatchAction); } menu.addSeparator(); - menu.addAction(theDebuggerAction(UseToolTipsInBreakpointsView)); - menu.addAction(theDebuggerAction(UseAddressInBreakpointsView)); + menu.addAction(debuggerCore()->action(UseToolTipsInBreakpointsView)); + menu.addAction(debuggerCore()->action(UseAddressInBreakpointsView)); menu.addAction(adjustColumnAction); menu.addAction(alwaysAdjustAction); menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); if (act == deleteAction) { deleteBreakpoints(si); } else if (act == deleteAllAction) { - QList<int> allRows; + QList<QModelIndex> allRows; for (int i = 0; i < rowCount; i++) - allRows.push_back(i); + allRows.push_back(model()->index(i, 0)); deleteBreakpoints(allRows); } else if (act == deleteByFileAction) deleteBreakpoints(breakPointsOfFile); @@ -384,81 +357,62 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) else if (act == associateBreakpointAction) associateBreakpoint(si, threadId); else if (act == synchronizeAction) - synchronizeBreakpoints(); + ; //synchronizeBreakpoints(); else if (act == toggleEnabledAction) setBreakpointsEnabled(si, !enabled); else if (act == addBreakpointAction) addBreakpoint(); else if (act == breakAtThrowAction) { + // FIXME: Use the proper breakpoint type instead. BreakpointData *data = new BreakpointData; - data->funcName = BreakpointData::throwFunction; - appendBreakpoint(data); + data->setFunctionName(BreakpointData::throwFunction); + handler->appendBreakpoint(data); } else if (act == breakAtCatchAction) { + // FIXME: Use the proper breakpoint type instead. BreakpointData *data = new BreakpointData; - data->funcName = BreakpointData::catchFunction; - appendBreakpoint(data); + data->setFunctionName(BreakpointData::catchFunction); + handler->appendBreakpoint(data); } } void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled) { - foreach (const QModelIndex &index, list) { - BreakpointData *data = breakpointAt(index.row()); - QTC_ASSERT(data, continue); - data->enabled = enabled; - } - synchronizeBreakpoints(); + BreakHandler *handler = breakHandler(); + foreach (const QModelIndex &index, list) + handler->setEnabled(handler->findBreakpointByIndex(index), enabled); } void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath) { - foreach (const QModelIndex &index, list) { - BreakpointData *data = breakpointAt(index.row()); - QTC_ASSERT(data, continue); - data->useFullPath = fullpath; - } - synchronizeBreakpoints(); + BreakHandler *handler = breakHandler(); + foreach (const QModelIndex &index, list) + handler->setUseFullPath(handler->findBreakpointByIndex(index), fullpath); } -void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes) +void BreakWindow::deleteBreakpoints(const QModelIndexList &list) { - QTC_ASSERT(!indexes.isEmpty(), return); - QList<int> list; - foreach (const QModelIndex &index, indexes) - list.append(index.row()); - deleteBreakpoints(list); + BreakHandler *handler = breakHandler(); + foreach (const QModelIndex &index, list) + handler->removeBreakpoint(handler->findBreakpointByIndex(index)); } -void BreakWindow::deleteBreakpoints(QList<int> list) +static bool editBreakpointInternal(BreakpointData *data, QWidget *parent) { - if (list.empty()) - return; - BreakHandler *handler = breakHandler(); - const int firstRow = list.front(); - qSort(list.begin(), list.end()); - for (int i = list.size(); --i >= 0; ) { - BreakpointData *data = breakpointAt(i); - QTC_ASSERT(data, continue); - handler->removeBreakpoint(data); - } - - const int row = qMin(firstRow, model()->rowCount() - 1); - if (row >= 0) - setCurrentIndex(model()->index(row, 0)); - synchronizeBreakpoints(); + BreakpointDialog dialog(parent); + return dialog.showDialog(data); } -bool BreakWindow::editBreakpoint(BreakpointData *data, QWidget *parent) +bool BreakWindow::editBreakpoint(BreakpointId id, QWidget *parent) { BreakpointDialog dialog(parent); - return dialog.showDialog(data); + return dialog.showDialog(breakHandler()->breakpointById(id)); } void BreakWindow::addBreakpoint() { BreakpointData *data = new BreakpointData(); - if (editBreakpoint(data, this)) - appendBreakpoint(data); + if (editBreakpointInternal(data, this)) + breakHandler()->appendBreakpoint(data); else delete data; } @@ -467,11 +421,11 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list) { QTC_ASSERT(!list.isEmpty(), return); + BreakHandler *handler = breakHandler(); + const BreakpointId id = handler->findBreakpointByIndex(list.at(0)); + if (list.size() == 1) { - BreakpointData *data = breakpointAt(0); - QTC_ASSERT(data, return); - if (editBreakpoint(data, this)) - breakHandler()->reinsertBreakpoint(data); + editBreakpoint(id, this); return; } @@ -483,13 +437,9 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list) ui.lineEditIgnoreCount->setValidator( new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount)); - const QModelIndex idx = list.front(); - BreakpointData *data = breakpointAt(idx.row()); - QTC_ASSERT(data, return); - - const QString oldCondition = QString::fromLatin1(data->condition); - const QString oldIgnoreCount = QString::number(data->ignoreCount); - const QString oldThreadSpec = QString::fromLatin1(data->threadSpec); + const QString oldCondition = QString::fromLatin1(handler->condition(id)); + const QString oldIgnoreCount = QString::number(handler->ignoreCount(id)); + const QString oldThreadSpec = QString::fromLatin1(handler->threadSpec(id)); ui.lineEditCondition->setText(oldCondition); ui.lineEditIgnoreCount->setText(oldIgnoreCount); @@ -508,27 +458,19 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list) return; foreach (const QModelIndex &idx, list) { - BreakpointData *data = breakpointAt(idx.row()); - QTC_ASSERT(data, continue); - data->condition = newCondition.toLatin1(); - data->ignoreCount = newIgnoreCount.toInt(); - data->threadSpec = newThreadSpec.toLatin1(); - data->uiDirty = true; + BreakpointId id = handler->findBreakpointByIndex(idx); + handler->setCondition(id, newCondition.toLatin1()); + handler->setIgnoreCount(id, newIgnoreCount.toInt()); + handler->setThreadSpec(id, newThreadSpec.toLatin1()); } - synchronizeBreakpoints(); } void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId) { - QByteArray condition; - if (threadId != -1) - condition = QByteArray::number(threadId); - foreach (const QModelIndex &index, list) { - BreakpointData *data = breakpointAt(index.row()); - QTC_ASSERT(data, continue); - data->condition = condition; - } - synchronizeBreakpoints(); + BreakHandler *handler = breakHandler(); + QByteArray spec = QByteArray::number(threadId); + foreach (const QModelIndex &index, list) + handler->setThreadSpec(handler->findBreakpointByIndex(index), spec); } void BreakWindow::resizeColumnsToContents() @@ -548,10 +490,7 @@ void BreakWindow::setAlwaysResizeColumnsToContents(bool on) void BreakWindow::rowActivated(const QModelIndex &index) { - BreakpointData *data = breakpointAt(index.row()); - QTC_ASSERT(data, return); - debuggerCore()->gotoLocation(data->markerFileName(), - data->markerLineNumber(), false); + breakHandler()->gotoLocation(breakHandler()->findBreakpointByIndex(index)); } } // namespace Internal diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index bfa3b06fd7cdfa49a8f33e09621171eb1dd8e5e9..e843e8ade66e77f512364379fb9649417a2a14d5 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -30,13 +30,13 @@ #ifndef DEBUGGER_BREAKWINDOW_H #define DEBUGGER_BREAKWINDOW_H +#include "breakhandler.h" + #include <QtGui/QTreeView> namespace Debugger { namespace Internal { -class BreakpointData; - class BreakWindow : public QTreeView { Q_OBJECT @@ -45,7 +45,7 @@ public: explicit BreakWindow(QWidget *parent = 0); ~BreakWindow(); - static bool editBreakpoint(BreakpointData *data, QWidget *parent = 0); + static bool editBreakpoint(BreakpointId id, QWidget *parent = 0); private slots: void resizeColumnsToContents(); @@ -62,7 +62,6 @@ private: void mouseDoubleClickEvent(QMouseEvent *ev); void deleteBreakpoints(const QModelIndexList &list); - void deleteBreakpoints(QList<int> rows); void addBreakpoint(); void editBreakpoints(const QModelIndexList &list); void associateBreakpoint(const QModelIndexList &list, int thread); diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index a25143062878648dfca5391ed456e7fefbf35db4..e70b0b2a6ba76149bf2edd30684a08a27455a43d 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -183,7 +183,7 @@ DebuggerEngine *CdbEngine::create(const DebuggerStartParameters &sp, void CdbEnginePrivate::updateCodeLevel() { - const CdbCore::CoreEngine::CodeLevel cl = theDebuggerBoolSetting(OperateByInstruction) ? + const CdbCore::CoreEngine::CodeLevel cl = debuggerCore()->boolSetting(OperateByInstruction) ? CdbCore::CoreEngine::CodeLevelAssembly : CdbCore::CoreEngine::CodeLevelSource; setCodeLevel(cl); } @@ -1174,7 +1174,7 @@ void CdbEngine::activateFrame(int frameIndex) if (showAssembler) { // Assembly code: Clean out model and force instruction mode. watchHandler()->beginCycle(); watchHandler()->endCycle(); - QAction *assemblerAction = theDebuggerAction(OperateByInstruction); + QAction *assemblerAction = debuggerCore()->action(OperateByInstruction); if (!assemblerAction->isChecked()) assemblerAction->trigger(); success = true; diff --git a/src/plugins/debugger/cdb/cdbstackframecontext.cpp b/src/plugins/debugger/cdb/cdbstackframecontext.cpp index 963aba5623fa775dca3d13fdeee20d66321c3c77..c55eddf4ff0ded2c90cb4878b684cdd8a721ab1a 100644 --- a/src/plugins/debugger/cdb/cdbstackframecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstackframecontext.cpp @@ -294,7 +294,7 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd) // -----------CdbStackFrameContext CdbStackFrameContext::CdbStackFrameContext(const QSharedPointer<CdbDumperHelper> &dumper, CdbSymbolGroupContext *symbolContext) : - m_useDumpers(dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers)), + m_useDumpers(dumper->isEnabled() && debuggerCore()->boolSetting(UseDebuggingHelpers)), m_dumper(dumper), m_symbolContext(symbolContext) { diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp index fb826f8897423d10b6c04244cf21de1f3410d63f..bb130141cbfd25019337c098fb39d4644746fb09 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -73,7 +73,7 @@ CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */ // Exclude uninitialized variables if desired QStringList uninitializedVariables; const CdbCore::StackFrame &frame = stackFrameAt(index); - if (theDebuggerAction(UseCodeModel)->isChecked()) + if (debuggerCore()->action(UseCodeModel)->isChecked()) getUninitializedVariables(debuggerCore()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables); if (debug) diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp index 9cd8f6903cf4aacb25b77cfb8d88c77d92117f38..0d6923555ed5beef91d43dec52e22dd6450dd4be 100644 --- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp @@ -319,7 +319,7 @@ CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix, CdbCore::SymbolGroupContext(prefix, symbolGroup, dumper->comInterfaces()->debugDataSpaces, uninitializedVariables), - m_useDumpers(dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers)), + m_useDumpers(dumper->isEnabled() && debuggerCore()->boolSetting(UseDebuggingHelpers)), m_dumper(dumper) { setShadowedNameFormat(WatchData::shadowedNameFormat()); diff --git a/src/plugins/debugger/consolewindow.cpp b/src/plugins/debugger/consolewindow.cpp index bb904ea58d797aa39c523ce35cfd71071ffb679c..eecb3aa7696c4f97f26d11f9da3c50058cc9e519 100644 --- a/src/plugins/debugger/consolewindow.cpp +++ b/src/plugins/debugger/consolewindow.cpp @@ -31,7 +31,7 @@ #include "logwindow.h" #include "debuggeractions.h" -#include "debuggerconstants.h" +#include "debuggercore.h" #include <QtCore/QDebug> @@ -188,15 +188,15 @@ public: void contextMenuEvent(QContextMenuEvent *ev) { - theDebuggerAction(ExecuteCommand)->setData(textCursor().block().text()); + debuggerCore()->action(ExecuteCommand)->setData(textCursor().block().text()); QMenu *menu = createStandardContextMenu(); menu->addAction(m_clearContentsAction); menu->addAction(m_saveContentsAction); // X11 clipboard is unreliable for long texts - menu->addAction(theDebuggerAction(ExecuteCommand)); - menu->addAction(theDebuggerAction(LogTimeStamps)); - menu->addAction(theDebuggerAction(VerboseLog)); + menu->addAction(debuggerCore()->action(ExecuteCommand)); + menu->addAction(debuggerCore()->action(LogTimeStamps)); + menu->addAction(debuggerCore()->action(VerboseLog)); menu->addSeparator(); - menu->addAction(theDebuggerAction(SettingsDialog)); + menu->addAction(debuggerCore()->action(SettingsDialog)); menu->exec(ev->globalPos()); delete menu; } @@ -213,7 +213,7 @@ public: if (c.unicode() >= 32 && c.unicode() < 128) cleanCmd.append(c); if (!cleanCmd.isEmpty()) { - theDebuggerAction(ExecuteCommand)->trigger(cleanCmd); + debuggerCore()->action(ExecuteCommand)->trigger(cleanCmd); m_history.append(cleanCmd); } } diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 741ff24389c8f6b5e6a454f9d4e3cbdec63f2490..e0bf9870546990b80f20864aa33801d28c324b0e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -52,8 +52,6 @@ using namespace Utils; static const char debugModeSettingsGroupC[] = "DebugMode"; -static const char gdbBinariesSettingsGroupC[] = "GdbBinaries"; -static const char debugModeGdbBinaryKeyC[] = "GdbBinary"; namespace Debugger { namespace Internal { @@ -64,217 +62,59 @@ namespace Internal { // ////////////////////////////////////////////////////////////////////////// -DebuggerSettings::DebuggerSettings(QObject *parent) - : QObject(parent), m_gdbBinariesChanged(false) -{} - -DebuggerSettings::~DebuggerSettings() -{ - qDeleteAll(m_items); -} - -DebuggerSettings::GdbBinaryToolChainMap DebuggerSettings::gdbBinaryToolChainMap() const -{ - return m_gdbBinaryToolChainMap; -} - -void DebuggerSettings::setGdbBinaryToolChainMap(const GdbBinaryToolChainMap &map) -{ - m_gdbBinaryToolChainMap = map; - m_gdbBinariesChanged = true; -} - -void DebuggerSettings::insertItem(int code, SavedAction *item) -{ - QTC_ASSERT(!m_items.contains(code), - qDebug() << code << item->toString(); return); - QTC_ASSERT(item->settingsKey().isEmpty() || item->defaultValue().isValid(), - qDebug() << "NO DEFAULT VALUE FOR " << item->settingsKey()); - m_items[code] = item; -} - -void DebuggerSettings::readSettings(const QSettings *settings) -{ - foreach (SavedAction *item, m_items) - item->readSettings(settings); - readGdbBinarySettings(settings); -} - -void DebuggerSettings::writeSettings(QSettings *settings) const -{ - foreach (SavedAction *item, m_items) - item->writeSettings(settings); - if (m_gdbBinariesChanged) - writeGdbBinarySettings(settings); -} - -void DebuggerSettings::readGdbBinarySettings(const QSettings *settings) -{ - // Convert gdb binaries from flat settings list (see writeSettings) - // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). - m_gdbBinaryToolChainMap.clear(); - const QChar separator = QLatin1Char(','); - const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') + - QLatin1String(debugModeGdbBinaryKeyC); - for (int i = 1; ; i++) { - const QString value = settings->value(keyRoot + QString::number(i)).toString(); - if (value.isEmpty()) - break; - // Split apart comma-separated binary and its numerical toolchains. - QStringList tokens = value.split(separator); - if (tokens.size() < 2) - break; - const QString binary = tokens.front(); - // Skip non-existent absolute binaries allowing for upgrades by the installer. - // Force a rewrite of the settings file. - const QFileInfo binaryInfo(binary); - if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) { - m_gdbBinariesChanged = true; - const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary); - qWarning("%s", qPrintable(msg)); - continue; - } - // Create entries for all toolchains. - tokens.pop_front(); - foreach(const QString &t, tokens) { - // Paranoia: Check if the there is already a binary configured for the toolchain. - const int toolChain = t.toInt(); - const QString predefinedGdb = m_gdbBinaryToolChainMap.key(toolChain); - if (predefinedGdb.isEmpty()) { - m_gdbBinaryToolChainMap.insert(binary, toolChain); - } else { - const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChainType>(toolChain)); - const QString msg = - QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n" - "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it."). - arg(settings->fileName(), binary, toolChainName, predefinedGdb); - qWarning("%s", qPrintable(msg)); - } - } - } - // Linux defaults -#ifdef Q_OS_UNIX - if (m_gdbBinaryToolChainMap.isEmpty()) { - const QString gdb = QLatin1String("gdb"); - m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain_GCC); - m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain_LINUX_ICC); - m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain_OTHER); - m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain_UNKNOWN); - } -#endif -} - -void DebuggerSettings::writeGdbBinarySettings(QSettings *settings) const +DebuggerSettings::DebuggerSettings(QSettings *settings) { - // Convert gdb binaries map into a flat settings list of - // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers - QString lastBinary; - QStringList settingsList; - const QChar separator = QLatin1Char(','); - const GdbBinaryToolChainMap::const_iterator cend = m_gdbBinaryToolChainMap.constEnd(); - for (GdbBinaryToolChainMap::const_iterator it = m_gdbBinaryToolChainMap.constBegin(); it != cend; ++it) { - if (it.key() != lastBinary) { - lastBinary = it.key(); // Start new entry with first toolchain - settingsList.push_back(lastBinary); - } - settingsList.back().append(separator); // Append toolchain to last binary - settingsList.back().append(QString::number(it.value())); - } - // Terminate settings list by an empty element such that consecutive keys resulting - // from ini-file merging are suppressed while reading. - settingsList.push_back(QString()); - // Write out list - settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC)); - settings->remove(QString()); // remove all keys in group. - const int count = settingsList.size(); - const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC); - for (int i = 0; i < count; i++) - settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i)); - settings->endGroup(); -} - -SavedAction *DebuggerSettings::item(int code) const -{ - QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0); - return m_items.value(code, 0); -} - -QString DebuggerSettings::dump() const -{ - QString out; - QTextStream ts(&out); - ts << "Debugger settings: "; - foreach (SavedAction *item, m_items) { - QString key = item->settingsKey(); - if (!key.isEmpty()) { - const QString current = item->value().toString(); - const QString default_ = item->defaultValue().toString(); - ts << '\n' << key << ": " << current - << " (default: " << default_ << ")"; - if (current != default_) - ts << " ***"; - } - } - return out; -} - -DebuggerSettings *DebuggerSettings::instance() -{ - static DebuggerSettings *instance = 0; - if (instance) - return instance; - + m_settings = settings; const QString debugModeGroup = QLatin1String(debugModeSettingsGroupC); - instance = new DebuggerSettings; SavedAction *item = 0; - item = new SavedAction(instance); - instance->insertItem(SettingsDialog, item); + item = new SavedAction(this); + insertItem(SettingsDialog, item); item->setText(tr("Debugger Properties...")); // // View // - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Adjust Column Widths to Contents")); - instance->insertItem(AdjustColumnWidths, item); + insertItem(AdjustColumnWidths, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Always Adjust Column Widths to Contents")); item->setCheckable(true); - instance->insertItem(AlwaysAdjustColumnWidths, item); + insertItem(AlwaysAdjustColumnWidths, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Use Alternating Row Colors")); item->setSettingsKey(debugModeGroup, QLatin1String("UseAlternatingRowColours")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseAlternatingRowColors, item); + insertItem(UseAlternatingRowColors, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Show a Message Box When Receiving a Signal")); item->setSettingsKey(debugModeGroup, QLatin1String("UseMessageBoxForSignals")); item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(UseMessageBoxForSignals, item); + insertItem(UseMessageBoxForSignals, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Log Time Stamps")); item->setSettingsKey(debugModeGroup, QLatin1String("LogTimeStamps")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(LogTimeStamps, item); + insertItem(LogTimeStamps, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Verbose Log")); item->setSettingsKey(debugModeGroup, QLatin1String("VerboseLog")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(VerboseLog, item); + insertItem(VerboseLog, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Operate by Instruction")); item->setCheckable(true); item->setDefaultValue(false); @@ -284,9 +124,9 @@ DebuggerSettings *DebuggerSettings::instance() "instructions and the source location view also shows the " "disassembled instructions.")); item->setIconVisibleInMenu(false); - instance->insertItem(OperateByInstruction, item); + insertItem(OperateByInstruction, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Dereference Pointers Automatically")); item->setCheckable(true); item->setDefaultValue(true); @@ -295,69 +135,69 @@ DebuggerSettings *DebuggerSettings::instance() "automatically dereference pointers. This saves a level in the " "tree view, but also loses data for the now-missing intermediate " "level.")); - instance->insertItem(AutoDerefPointers, item); + insertItem(AutoDerefPointers, item); // // Locals & Watchers // - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("ShowStandardNamespace")); item->setText(tr("Show \"std::\" Namespace in Types")); item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(ShowStdNamespace, item); + insertItem(ShowStdNamespace, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("ShowQtNamespace")); item->setText(tr("Show Qt's Namespace in Types")); item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(ShowQtNamespace, item); + insertItem(ShowQtNamespace, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("SortStructMembers")); item->setText(tr("Sort Members of Classes and Structs Alphabetically")); item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(SortStructMembers, item); + insertItem(SortStructMembers, item); // // DebuggingHelper // - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper")); item->setText(tr("Use Debugging Helpers")); item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(UseDebuggingHelpers, item); + insertItem(UseDebuggingHelpers, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseCustomDebuggingHelperLocation")); item->setCheckable(true); item->setDefaultValue(false); item->setValue(false); - instance->insertItem(UseCustomDebuggingHelperLocation, item); + insertItem(UseCustomDebuggingHelperLocation, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("CustomDebuggingHelperLocation")); item->setCheckable(true); item->setDefaultValue(QString()); item->setValue(QString()); - instance->insertItem(CustomDebuggingHelperLocation, item); + insertItem(CustomDebuggingHelperLocation, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("DebugDebuggingHelpers")); item->setText(tr("Debug Debugging Helpers")); item->setCheckable(true); item->setDefaultValue(false); item->setValue(false); - instance->insertItem(DebugDebuggingHelpers, item); + insertItem(DebugDebuggingHelpers, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel")); item->setText(tr("Use Code Model")); item->setToolTip(tr("Selecting this causes the C++ Code Model being asked " @@ -366,17 +206,17 @@ DebuggerSettings *DebuggerSettings::instance() item->setCheckable(true); item->setDefaultValue(true); item->setValue(true); - instance->insertItem(UseCodeModel, item); + insertItem(UseCodeModel, item); // // Breakpoints // - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Synchronize Breakpoints")); - instance->insertItem(SynchronizeBreakpoints, item); + insertItem(SynchronizeBreakpoints, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Adjust Breakpoint Locations")); item->setToolTip(tr("Not all source code lines generate " "executable code. Putting a breakpoint on such a line acts as " @@ -388,58 +228,58 @@ DebuggerSettings *DebuggerSettings::instance() item->setDefaultValue(true); item->setValue(true); item->setSettingsKey(debugModeGroup, QLatin1String("AdjustBreakpointLocations")); - instance->insertItem(AdjustBreakpointLocations, item); + insertItem(AdjustBreakpointLocations, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Break on \"throw\"")); item->setCheckable(true); item->setDefaultValue(false); item->setValue(false); item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnThrow")); - instance->insertItem(BreakOnThrow, item); + insertItem(BreakOnThrow, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Break on \"catch\"")); item->setCheckable(true); item->setDefaultValue(false); item->setValue(false); item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnCatch")); - instance->insertItem(BreakOnCatch, item); + insertItem(BreakOnCatch, item); // // Settings // - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("Environment")); item->setDefaultValue(QString()); - instance->insertItem(GdbEnvironment, item); + insertItem(GdbEnvironment, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("ScriptFile")); item->setDefaultValue(QString()); - instance->insertItem(GdbScriptFile, item); + insertItem(GdbScriptFile, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("CloseBuffersOnExit")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(CloseBuffersOnExit, item); + insertItem(CloseBuffersOnExit, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("SwitchModeOnExit")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(SwitchModeOnExit, item); + insertItem(SwitchModeOnExit, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("AutoQuit")); item->setText(tr("Automatically Quit Debugger")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(AutoQuit, item); + insertItem(AutoQuit, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTips")); item->setText(tr("Use tooltips in main editor when debugging")); item->setToolTip(tr("Checking this will enable tooltips for variable " @@ -448,52 +288,52 @@ DebuggerSettings *DebuggerSettings::instance() "information, it is switched off by default.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseToolTipsInMainEditor, item); + insertItem(UseToolTipsInMainEditor, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInLocalsView")); item->setText(tr("Use Tooltips in Locals View When Debugging")); item->setToolTip(tr("Checking this will enable tooltips in the locals " "view during debugging.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseToolTipsInLocalsView, item); + insertItem(UseToolTipsInLocalsView, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInBreakpointsView")); item->setText(tr("Use Tooltips in Breakpoints View When Debugging")); item->setToolTip(tr("Checking this will enable tooltips in the breakpoints " "view during debugging.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseToolTipsInBreakpointsView, item); + insertItem(UseToolTipsInBreakpointsView, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseAddressInBreakpointsView")); item->setText(tr("Show Address Data in Breakpoints View When Debugging")); item->setToolTip(tr("Checking this will show a column with address " "information in the breakpoint view during debugging.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseAddressInBreakpointsView, item); + insertItem(UseAddressInBreakpointsView, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseAddressInStackView")); item->setText(tr("Show Address Data in Stack View When Debugging")); item->setToolTip(tr("Checking this will show a column with address " "information in the stack view during debugging.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(UseAddressInStackView, item); - item = new SavedAction(instance); + insertItem(UseAddressInStackView, item); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("ListSourceFiles")); item->setText(tr("List Source Files")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(ListSourceFiles, item); + insertItem(ListSourceFiles, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("SkipKnownFrames")); item->setText(tr("Skip Known Frames")); item->setToolTip(tr("Selecting this results in well-known but usually " @@ -501,89 +341,117 @@ DebuggerSettings *DebuggerSettings::instance() "signal emission being skipped while single-stepping.")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(SkipKnownFrames, item); + insertItem(SkipKnownFrames, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("EnableReverseDebugging")); item->setText(tr("Enable Reverse Debugging")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(EnableReverseDebugging, item); + insertItem(EnableReverseDebugging, item); #ifdef Q_OS_WIN - item = new RegisterPostMortemAction(instance); + item = new RegisterPostMortemAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("RegisterForPostMortem")); item->setText(tr("Register For Post-Mortem Debugging")); item->setCheckable(true); item->setDefaultValue(false); - instance->insertItem(RegisterForPostMortem, item); + insertItem(RegisterForPostMortem, item); #endif - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("AllPluginBreakpoints")); item->setDefaultValue(true); - instance->insertItem(AllPluginBreakpoints, item); + insertItem(AllPluginBreakpoints, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("SelectedPluginBreakpoints")); item->setDefaultValue(false); - instance->insertItem(SelectedPluginBreakpoints, item); + insertItem(SelectedPluginBreakpoints, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("NoPluginBreakpoints")); item->setDefaultValue(false); - instance->insertItem(NoPluginBreakpoints, item); + insertItem(NoPluginBreakpoints, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("SelectedPluginBreakpointsPattern")); item->setDefaultValue(QLatin1String(".*")); - instance->insertItem(SelectedPluginBreakpointsPattern, item); + insertItem(SelectedPluginBreakpointsPattern, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("MaximalStackDepth")); item->setDefaultValue(20); - instance->insertItem(MaximalStackDepth, item); + insertItem(MaximalStackDepth, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Reload Full Stack")); - instance->insertItem(ExpandStack, item); + insertItem(ExpandStack, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Create Full Backtrace")); - instance->insertItem(CreateFullBacktrace, item); + insertItem(CreateFullBacktrace, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setText(tr("Execute Line")); - instance->insertItem(ExecuteCommand, item); + insertItem(ExecuteCommand, item); - item = new SavedAction(instance); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("WatchdogTimeout")); item->setDefaultValue(20); - instance->insertItem(GdbWatchdogTimeout, item); + insertItem(GdbWatchdogTimeout, item); +} - return instance; + +DebuggerSettings::~DebuggerSettings() +{ + qDeleteAll(m_items); } +void DebuggerSettings::insertItem(int code, SavedAction *item) +{ + QTC_ASSERT(!m_items.contains(code), + qDebug() << code << item->toString(); return); + QTC_ASSERT(item->settingsKey().isEmpty() || item->defaultValue().isValid(), + qDebug() << "NO DEFAULT VALUE FOR " << item->settingsKey()); + m_items[code] = item; +} -////////////////////////////////////////////////////////////////////////// -// -// DebuggerActions -// -////////////////////////////////////////////////////////////////////////// +void DebuggerSettings::readSettings() +{ + foreach (SavedAction *item, m_items) + item->readSettings(m_settings); +} -SavedAction *theDebuggerAction(int code) +void DebuggerSettings::writeSettings() const { - return DebuggerSettings::instance()->item(code); + foreach (SavedAction *item, m_items) + item->writeSettings(m_settings); } -bool theDebuggerBoolSetting(int code) +SavedAction *DebuggerSettings::item(int code) const { - return DebuggerSettings::instance()->item(code)->value().toBool(); + QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0); + return m_items.value(code, 0); } -QString theDebuggerStringSetting(int code) +QString DebuggerSettings::dump() const { - return DebuggerSettings::instance()->item(code)->value().toString(); + QString out; + QTextStream ts(&out); + ts << "Debugger settings: "; + foreach (SavedAction *item, m_items) { + QString key = item->settingsKey(); + if (!key.isEmpty()) { + const QString current = item->value().toString(); + const QString default_ = item->defaultValue().toString(); + ts << '\n' << key << ": " << current + << " (default: " << default_ << ")"; + if (current != default_) + ts << " ***"; + } + } + return out; } } // namespace Internal diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 1b8a99fb50b7bb8e9ef3324368f5558ad0e1daeb..22ea568845d4d5d083364c0ed39759cec88bb5ec 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -34,8 +34,6 @@ #include <QtCore/QMap> QT_BEGIN_NAMESPACE -class QAction; -class QActionGroup; class QSettings; QT_END_NAMESPACE @@ -48,34 +46,22 @@ namespace Internal { class DebuggerSettings : public QObject { - Q_OBJECT + Q_OBJECT // For tr(). public: - typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - - explicit DebuggerSettings(QObject *parent = 0); + explicit DebuggerSettings(QSettings *setting); ~DebuggerSettings(); - GdbBinaryToolChainMap gdbBinaryToolChainMap() const; - void setGdbBinaryToolChainMap(const GdbBinaryToolChainMap &map); - void insertItem(int code, Utils::SavedAction *item); Utils::SavedAction *item(int code) const; QString dump() const; - static DebuggerSettings *instance(); - -public slots: - void readSettings(const QSettings *settings); - void writeSettings(QSettings *settings) const; + void readSettings(); + void writeSettings() const; private: - void readGdbBinarySettings(const QSettings *settings); - void writeGdbBinarySettings(QSettings *settings) const; - QHash<int, Utils::SavedAction *> m_items; - GdbBinaryToolChainMap m_gdbBinaryToolChainMap; - bool m_gdbBinariesChanged; + QSettings *m_settings; }; /////////////////////////////////////////////////////////// @@ -147,13 +133,6 @@ enum DebuggerActionCode BreakOnCatch }; -// singleton access -Utils::SavedAction *theDebuggerAction(int code); - -// convenience -bool theDebuggerBoolSetting(int code); -QString theDebuggerStringSetting(int code); - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index bd5161afa614f105ca0e57ee47e5ed0d91d04a80..6a9be5d98ba155a2edc77d5167904d77ef575b70 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -134,7 +134,7 @@ void MemoryViewAgent::createBinEditor(quint64 addr) QMetaObject::invokeMethod(editor->widget(), "setLazyData", Q_ARG(quint64, addr), Q_ARG(int, DataRange), Q_ARG(int, BinBlockSize)); } else { - DebuggerEngine::showMessageBox(QMessageBox::Warning, + showMessageBox(QMessageBox::Warning, tr("No memory viewer available"), tr("The memory contents cannot be shown as no viewer plugin " "for binary data has been loaded.")); diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h index a8acfe0f0dd0cc2ee332bae5bfdf455d894c13cb..3b8bc2eeb951e4baff19e6de24e26d1caeb4b0a0 100644 --- a/src/plugins/debugger/debuggercore.h +++ b/src/plugins/debugger/debuggercore.h @@ -34,6 +34,7 @@ #include "debuggerconstants.h" #include <QtCore/QObject> +#include <QtCore/QMultiMap> QT_BEGIN_NAMESPACE class QIcon; @@ -45,6 +46,10 @@ namespace CPlusPlus { class Snapshot; } +namespace Utils { +class SavedAction; +} + namespace Debugger { class DebuggerEngine; @@ -78,8 +83,8 @@ public: virtual bool isRegisterViewVisible() const = 0; virtual bool hasSnapshots() const = 0; virtual void openTextEditor(const QString &titlePattern, const QString &contents) = 0; - virtual Internal::BreakHandler *breakHandler() const = 0; - virtual Internal::SnapshotHandler *snapshotHandler() const = 0; + virtual BreakHandler *breakHandler() const = 0; + virtual SnapshotHandler *snapshotHandler() const = 0; virtual DebuggerEngine *currentEngine() const = 0; virtual bool isActiveDebugLanguage(int language) const = 0; @@ -103,16 +108,22 @@ public: virtual void runControlFinished(DebuggerRunControl *runControl) = 0; virtual void displayDebugger(DebuggerEngine *engine, bool updateEngine) = 0; virtual DebuggerLanguages activeLanguages() const = 0; - - virtual QMessageBox *showMessageBox(int icon, const QString &title, - const QString &text, int buttons = 0) = 0; + virtual void synchronizeBreakpoints() = 0; virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0; virtual QWidget *mainWindow() const = 0; + virtual QString gdbBinaryForToolChain(int toolChain) const = 0; + + virtual Utils::SavedAction *action(int code) const = 0; + virtual bool boolSetting(int code) const = 0; + virtual QString stringSetting(int code) const = 0; }; // This is the only way to access the global object. DebuggerCore *debuggerCore(); +inline BreakHandler *breakHandler() { return debuggerCore()->breakHandler(); } +QMessageBox *showMessageBox(int icon, const QString &title, + const QString &text, int buttons = 0); } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index bb614ab1b962d5cc06c327135c63c47ee897218f..f706146117be363e53ac0c71547f2833ee5ac71d 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -271,7 +271,6 @@ public: DisassemblerViewAgent m_disassemblerViewAgent; QFutureInterface<void> m_progress; - QHash<quint64, Internal::BreakpointData *> m_breakpoints; bool m_isSlaveEngine; }; @@ -485,7 +484,7 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) breakByFunctionMain(); const unsigned engineCapabilities = debuggerCapabilities(); - theDebuggerAction(OperateByInstruction) + debuggerCore()->action(OperateByInstruction) ->setEnabled(engineCapabilities & DisassemblerCapability); QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished, @@ -509,7 +508,6 @@ void DebuggerEngine::breakByFunctionMain() void DebuggerEngine::breakByFunction(const QString &functionName) { breakHandler()->breakByFunction(functionName); - breakHandler()->synchronizeBreakpoints(); } void DebuggerEngine::resetLocation() @@ -529,7 +527,7 @@ void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker) { - if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) { + if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable()) { if (setMarker) resetLocation(); d->m_disassemblerViewAgent.setFrame(frame); @@ -583,14 +581,14 @@ DebuggerStartParameters &DebuggerEngine::startParameters() bool DebuggerEngine::qtDumperLibraryEnabled() const { - return theDebuggerBoolSetting(UseDebuggingHelpers); + return debuggerCore()->boolSetting(UseDebuggingHelpers); } QStringList DebuggerEngine::qtDumperLibraryLocations() const { - if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) { + if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) { const QString customLocation = - theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); + debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString(); const QString location = tr("%1 (explicitly set in the Debugger Options)").arg(customLocation); return QStringList(location); @@ -605,8 +603,8 @@ void DebuggerEngine::showQtDumperLibraryWarning(const QString &details) QString DebuggerEngine::qtDumperLibraryName() const { - if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) - return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); + if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) + return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString(); return startParameters().dumperLibrary; } @@ -994,6 +992,13 @@ void DebuggerEngine::setState(DebuggerState state, bool forced) if (!forced && !isAllowedTransition(oldState, state)) qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; + if (state == DebuggerFinished) { + // Give up ownership on claimed breakpoints. + BreakHandler *handler = breakHandler(); + foreach (BreakpointId id, handler->engineBreakpointIds(this)) + handler->notifyBreakpointReleased(id); + } + const bool running = d->m_state == InferiorRunOk; if (running) threadsHandler()->notifyRunning(); @@ -1121,12 +1126,6 @@ void DebuggerEngine::progressPing() d->m_progress.setProgressValue(progress); } -QMessageBox *DebuggerEngine::showMessageBox(int icon, const QString &title, - const QString &text, int buttons) -{ - return debuggerCore()->showMessageBox(icon, title, text, buttons); -} - DebuggerRunControl *DebuggerEngine::runControl() const { return d->m_runControl; @@ -1213,111 +1212,123 @@ void DebuggerEngine::updateAll() { } +#if 0 + // FIXME: Remove explicit use of BreakpointData + if (!bp->engine && acceptsBreakpoint(id)) { + QTC_ASSERT(state == BreakpointNew, /**/); + // Take ownership of the breakpoint. + bp->engine = this; + } +#endif + void DebuggerEngine::attemptBreakpointSynchronization() { - for (int i = 0; i < breakHandler()->size(); i++) { - BreakpointData *bp = breakHandler()->at(i); - if (!d->m_breakpoints.contains(bp->id)) { - d->m_breakpoints.insert(bp->id, bp); - bp->state = BreakpointInsertionRequested; - addBreakpoint(*bp); - } - QTC_ASSERT(d->m_breakpoints[bp->id] == bp, qDebug() << "corrupted breakpoint map"); - if (bp->uiDirty) { - bp->uiDirty = false; - bp->state = BreakpointChangeRequested; - changeBreakpoint(*bp); - } + if (!stateAcceptsBreakpointChanges()) { + showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE")); + return; } - Breakpoints bps = breakHandler()->takeRemovedBreakpoints(); - foreach (BreakpointData *bp, bps) { - if (d->m_breakpoints.contains(bp->id)) { - bp->state = BreakpointRemovalRequested; - removeBreakpoint(bp->id); - } else { - delete bp; + BreakHandler *handler = breakHandler(); + + foreach (BreakpointId id, handler->unclaimedBreakpointIds()) { + // Take ownership of the breakpoint. Requests insertion. + if (acceptsBreakpoint(id)) + handler->setEngine(id, this); + } + + foreach (BreakpointId id, handler->engineBreakpointIds(this)) { + switch (handler->state(id)) { + case BreakpointNew: + // Should not happen once claimed. + QTC_ASSERT(false, /**/); + continue; + case BreakpointInsertRequested: + insertBreakpoint(id); + continue; + case BreakpointChangeRequested: + changeBreakpoint(id); + continue; + case BreakpointRemoveRequested: + removeBreakpoint(id); + continue; + case BreakpointChangeProceeding: + case BreakpointInsertProceeding: + case BreakpointRemoveProceeding: + //qDebug() << "BREAKPOINT " << id << " STILL IN PROGRESS, STATE" + // << handler->state(id); + continue; + case BreakpointPending: + //qDebug() << "BREAKPOINT " << id << " IS GOOD: PENDING"; + continue; + case BreakpointInserted: + //qDebug() << "BREAKPOINT " << id << " IS GOOD: INSERTED"; + continue; + case BreakpointDead: + // Should not only be visible inside BreakpointHandler. + QTC_ASSERT(false, /**/); + continue; } + QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); } + } -bool DebuggerEngine::acceptsBreakpoint(const BreakpointData *) +bool DebuggerEngine::acceptsBreakpoint(BreakpointId) const { return true; } -void DebuggerEngine::addBreakpoint(const BreakpointData &) +void DebuggerEngine::insertBreakpoint(BreakpointId) { + QTC_ASSERT(false, /**/); } -void DebuggerEngine::notifyAddBreakpointOk(quint64 id) +void DebuggerEngine::notifyBreakpointInsertOk(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[id]; - QTC_ASSERT(bp, return); - bp->state = BreakpointOk; + breakHandler()->notifyBreakpointInsertOk(id); } -void DebuggerEngine::notifyAddBreakpointFailed(quint64 id) +void DebuggerEngine::notifyBreakpointInsertFailed(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[id]; - QTC_ASSERT(bp, return); - bp->state = BreakpointDead; + breakHandler()->notifyBreakpointInsertFailed(id); } -void DebuggerEngine::removeBreakpoint(quint64) +void DebuggerEngine::removeBreakpoint(BreakpointId) { + QTC_ASSERT(false, /**/); } -void DebuggerEngine::notifyRemoveBreakpointOk(quint64 id) +void DebuggerEngine::notifyBreakpointRemoveOk(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints.take(id); - QTC_ASSERT(bp, return); - bp->state = BreakpointDead; - delete bp; + breakHandler()->notifyBreakpointRemoveOk(id); } -void DebuggerEngine::notifyRemoveBreakpointFailed(quint64 id) +void DebuggerEngine::notifyBreakpointRemoveFailed(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[id]; - QTC_ASSERT(bp, return); - bp->state = BreakpointOk; + breakHandler()->notifyBreakpointRemoveFailed(id); } -void DebuggerEngine::changeBreakpoint(const BreakpointData &) +void DebuggerEngine::changeBreakpoint(BreakpointId) { + QTC_ASSERT(false, /**/); } -void DebuggerEngine::notifyChangeBreakpointOk(quint64 id) +void DebuggerEngine::notifyBreakpointChangeOk(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[id]; - QTC_ASSERT(bp, return); - bp->state = BreakpointOk; + breakHandler()->notifyBreakpointChangeOk(id); } -void DebuggerEngine::notifyChangeBreakpointFailed(quint64 id) +void DebuggerEngine::notifyBreakpointChangeFailed(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[id]; - QTC_ASSERT(bp, return); - bp->state = BreakpointDead; + breakHandler()->notifyBreakpointChangeFailed(id); } -void DebuggerEngine::notifyBreakpointAdjusted(const BreakpointData & rbp) +/* +void DebuggerEngine::notifyBreakpointAdjusted(BreakpointId id) { - BreakpointData *bp = d->m_breakpoints[rbp.id]; - QTC_ASSERT(bp, return); - bp->bpNumber = rbp.bpNumber; - bp->bpCondition = rbp.bpCondition; - bp->bpIgnoreCount = rbp.bpIgnoreCount; - bp->bpFileName = rbp.bpFileName; - bp->bpFullName = rbp.bpFullName; - bp->bpLineNumber = rbp.bpLineNumber; - bp->bpCorrectedLineNumber = rbp.bpCorrectedLineNumber; - bp->bpThreadSpec = rbp.bpThreadSpec; - bp->bpFuncName = rbp.bpFuncName; - bp->bpAddress = rbp.bpAddress; - bp->bpMultiple = rbp.bpMultiple; - bp->bpEnabled = rbp.bpEnabled; + breakHandler()->notifyChangeBreakpointAdjusted(id); } +*/ void DebuggerEngine::selectThread(int) { diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index f3f5f162ad9c0f00f73426fc26df15e2e8e71756..49f78f78bd67a5bd36d4b470971e8b55046b6bce 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -33,6 +33,7 @@ #include "debugger_global.h" #include "debuggerconstants.h" #include "moduleshandler.h" // For 'Symbols' +#include "breakpoint.h" // For 'BreakpointId' #include <coreplugin/ssh/sshconnection.h> @@ -116,11 +117,9 @@ DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state); namespace Internal { -class DebuggerCore; class DebuggerPluginPrivate; class DisassemblerViewAgent; class MemoryViewAgent; -class Symbol; class WatchData; class BreakHandler; class ModulesHandler; @@ -183,29 +182,24 @@ public: virtual void createSnapshot(); virtual void updateAll(); - virtual void attemptBreakpointSynchronization(); - virtual bool acceptsBreakpoint(const Internal::BreakpointData *); - - virtual void addBreakpoint(const Internal::BreakpointData &bp); - virtual void notifyAddBreakpointOk(quint64 id); - virtual void notifyAddBreakpointFailed(quint64 id); - virtual void removeBreakpoint(quint64 id); - virtual void notifyRemoveBreakpointOk(quint64 id); - virtual void notifyRemoveBreakpointFailed(quint64 id); - virtual void changeBreakpoint(const Internal::BreakpointData &bp); - virtual void notifyChangeBreakpointOk(quint64 id); - virtual void notifyChangeBreakpointFailed(quint64 id); - virtual void notifyBreakpointAdjusted(const Internal::BreakpointData &bp); - virtual void selectThread(int index); + virtual bool stateAcceptsBreakpointChanges() const { return true; } + virtual void attemptBreakpointSynchronization(); + virtual bool acceptsBreakpoint(BreakpointId id) const; // FIXME: make pure + virtual void insertBreakpoint(BreakpointId id); // FIXME: make pure + virtual void notifyBreakpointInsertOk(BreakpointId id); + virtual void notifyBreakpointInsertFailed(BreakpointId id); + virtual void removeBreakpoint(BreakpointId id); // FIXME: make pure + virtual void notifyBreakpointRemoveOk(BreakpointId id); + virtual void notifyBreakpointRemoveFailed(BreakpointId id); + virtual void changeBreakpoint(BreakpointId id); // FIXME: make pure + virtual void notifyBreakpointChangeOk(BreakpointId id); + virtual void notifyBreakpointChangeFailed(BreakpointId id); virtual void assignValueInDebugger(const Internal::WatchData *data, const QString &expr, const QVariant &value); virtual void removeTooltip(); - - // Convenience - static QMessageBox *showMessageBox - (int icon, const QString &title, const QString &text, int buttons = 0); + virtual void selectThread(int index); protected: friend class Internal::DebuggerPluginPrivate; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 2bc8bec20277ec7d4a8388f5b23f68c744623240..7efe4608783394bdae096e8a50f79d6d541a0162 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -59,6 +59,7 @@ #include "snapshothandler.h" #include "threadshandler.h" +#include "gdb/gdboptionspage.h" #include "ui_commonoptionspage.h" #include "ui_dumperoptionpage.h" @@ -402,11 +403,6 @@ static SessionManager *sessionManager() return ProjectExplorerPlugin::instance()->session(); } -static QSettings *settings() -{ - return ICore::instance()->settings(); -} - static QToolButton *toolButton(QAction *action) { QToolButton *button = new QToolButton; @@ -450,7 +446,6 @@ void addTcfOptionPages(QList<IOptionsPage*> *opts); void addCdbOptionPages(QList<IOptionsPage*> *opts); #endif - struct AttachRemoteParameters { AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {} @@ -539,7 +534,7 @@ public: { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); } QWidget *createPage(QWidget *parent); - void apply() { m_group.apply(settings()); } + void apply() { m_group.apply(ICore::instance()->settings()); } void finish() { m_group.finish(); } virtual bool matches(const QString &s) const; @@ -555,32 +550,32 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent) m_ui.setupUi(w); m_group.clear(); - m_group.insert(theDebuggerAction(ListSourceFiles), + m_group.insert(debuggerCore()->action(ListSourceFiles), m_ui.checkBoxListSourceFiles); - m_group.insert(theDebuggerAction(UseAlternatingRowColors), + m_group.insert(debuggerCore()->action(UseAlternatingRowColors), m_ui.checkBoxUseAlternatingRowColors); - m_group.insert(theDebuggerAction(UseToolTipsInMainEditor), + m_group.insert(debuggerCore()->action(UseToolTipsInMainEditor), m_ui.checkBoxUseToolTipsInMainEditor); - m_group.insert(theDebuggerAction(CloseBuffersOnExit), + m_group.insert(debuggerCore()->action(CloseBuffersOnExit), m_ui.checkBoxCloseBuffersOnExit); - m_group.insert(theDebuggerAction(SwitchModeOnExit), + m_group.insert(debuggerCore()->action(SwitchModeOnExit), m_ui.checkBoxSwitchModeOnExit); - m_group.insert(theDebuggerAction(AutoDerefPointers), 0); - m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0); - m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0); - m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0); - m_group.insert(theDebuggerAction(UseAddressInStackView), 0); - m_group.insert(theDebuggerAction(MaximalStackDepth), + m_group.insert(debuggerCore()->action(AutoDerefPointers), 0); + m_group.insert(debuggerCore()->action(UseToolTipsInLocalsView), 0); + m_group.insert(debuggerCore()->action(UseToolTipsInBreakpointsView), 0); + m_group.insert(debuggerCore()->action(UseAddressInBreakpointsView), 0); + m_group.insert(debuggerCore()->action(UseAddressInStackView), 0); + m_group.insert(debuggerCore()->action(MaximalStackDepth), m_ui.spinBoxMaximalStackDepth); - m_group.insert(theDebuggerAction(ShowStdNamespace), 0); - m_group.insert(theDebuggerAction(ShowQtNamespace), 0); - m_group.insert(theDebuggerAction(SortStructMembers), 0); - m_group.insert(theDebuggerAction(LogTimeStamps), 0); - m_group.insert(theDebuggerAction(VerboseLog), 0); - m_group.insert(theDebuggerAction(BreakOnThrow), 0); - m_group.insert(theDebuggerAction(BreakOnCatch), 0); + m_group.insert(debuggerCore()->action(ShowStdNamespace), 0); + m_group.insert(debuggerCore()->action(ShowQtNamespace), 0); + m_group.insert(debuggerCore()->action(SortStructMembers), 0); + m_group.insert(debuggerCore()->action(LogTimeStamps), 0); + m_group.insert(debuggerCore()->action(VerboseLog), 0); + m_group.insert(debuggerCore()->action(BreakOnThrow), 0); + m_group.insert(debuggerCore()->action(BreakOnCatch), 0); #ifdef Q_OS_WIN - Utils::SavedAction *registerAction = theDebuggerAction(RegisterForPostMortem); + Utils::SavedAction *registerAction = debuggerCore()->action(RegisterForPostMortem); m_group.insert(registerAction, m_ui.checkBoxRegisterForPostMortem); connect(registerAction, SIGNAL(toggled(bool)), @@ -623,8 +618,8 @@ static inline bool oxygenStyle() } class DebuggingHelperOptionPage : public Core::IOptionsPage -{ // Needs tr - context - Q_OBJECT +{ + Q_OBJECT // Needs tr-context. public: DebuggingHelperOptionPage() {} @@ -638,7 +633,7 @@ public: { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); } QWidget *createPage(QWidget *parent); - void apply() { m_group.apply(settings()); } + void apply() { m_group.apply(ICore::instance()->settings()); } void finish() { m_group.finish(); } virtual bool matches(const QString &s) const; @@ -659,22 +654,22 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent) ICore::instance()->resourcePath() + "../../lib"); m_group.clear(); - m_group.insert(theDebuggerAction(UseDebuggingHelpers), + m_group.insert(debuggerCore()->action(UseDebuggingHelpers), m_ui.debuggingHelperGroupBox); - m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation), + m_group.insert(debuggerCore()->action(UseCustomDebuggingHelperLocation), m_ui.customLocationGroupBox); // Suppress Oxygen style's giving flat group boxes bold titles. if (oxygenStyle()) m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }")); - m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation), + m_group.insert(debuggerCore()->action(CustomDebuggingHelperLocation), m_ui.dumperLocationChooser); - m_group.insert(theDebuggerAction(UseCodeModel), + m_group.insert(debuggerCore()->action(UseCodeModel), m_ui.checkBoxUseCodeModel); #ifdef QT_DEBUG - m_group.insert(theDebuggerAction(DebugDebuggingHelpers), + m_group.insert(debuggerCore()->action(DebugDebuggingHelpers), m_ui.checkBoxDebugDebuggingHelpers); #else m_ui.checkBoxDebugDebuggingHelpers->hide(); @@ -818,8 +813,7 @@ static bool isDebuggable(IEditor *editor) // IFile *file = editor->file(); // return !(file && file->mimeType() == "application/x-qml"); // Nowadays, even Qml is debuggable. - Q_UNUSED(editor); - return true; + return editor; } @@ -881,7 +875,7 @@ public slots: currentEngine()->selectThread(index); } - void breakpointSetRemoveMarginActionTriggered() + void breakpointSetMarginActionTriggered() { QString fileName; int lineNumber; @@ -890,12 +884,32 @@ public slots: m_breakHandler->toggleBreakpoint(fileName, lineNumber, address); } - void breakpointEnableDisableMarginActionTriggered() + void breakpointRemoveMarginActionTriggered() { + const QAction *act = qobject_cast<QAction *>(sender()); + QTC_ASSERT(act, return); + const BreakpointId id = act->data().toInt(); + QTC_ASSERT(id > 0, return); + QString fileName; int lineNumber; - if (positionFromContextActionData(sender(), &fileName, &lineNumber)) - m_breakHandler->toggleBreakpointEnabled(fileName, lineNumber); + quint64 address; + if (positionFromContextActionData(sender(), &fileName, &lineNumber, &address)) + m_breakHandler->toggleBreakpoint(fileName, lineNumber, address); + } + + void breakpointEnableMarginActionTriggered() + { + const QAction *act = qobject_cast<QAction *>(sender()); + QTC_ASSERT(act, return); + breakHandler()->setEnabled(act->data().toInt(), true); + } + + void breakpointDisableMarginActionTriggered() + { + const QAction *act = qobject_cast<QAction *>(sender()); + QTC_ASSERT(act, return); + breakHandler()->setEnabled(act->data().toInt(), false); } void updateWatchersHeader(int section, int, int newSize) @@ -991,11 +1005,10 @@ public slots: void runControlStarted(DebuggerRunControl *runControl); void runControlFinished(DebuggerRunControl *runControl); DebuggerLanguages activeLanguages() const; + QString gdbBinaryForToolChain(int toolChain) const; void remoteCommand(const QStringList &options, const QStringList &); bool isReverseDebugging() const; - QMessageBox *showMessageBox(int icon, const QString &title, - const QString &text, int buttons); void ensureLogVisible(); void extensionsInitialized(); @@ -1042,7 +1055,7 @@ public slots: void handleExecStep() { resetLocation(); - if (theDebuggerBoolSetting(OperateByInstruction)) + if (debuggerCore()->boolSetting(OperateByInstruction)) currentEngine()->executeStepI(); else currentEngine()->executeStep(); @@ -1051,7 +1064,7 @@ public slots: void handleExecNext() { resetLocation(); - if (theDebuggerBoolSetting(OperateByInstruction)) + if (debuggerCore()->boolSetting(OperateByInstruction)) currentEngine()->executeNextI(); else currentEngine()->executeNext(); @@ -1124,10 +1137,9 @@ public slots: { const QAction *act = qobject_cast<QAction *>(sender()); QTC_ASSERT(act, return); - const QVariant data = act->data(); - QTC_ASSERT(qVariantCanConvert<BreakpointData *>(data), return); - BreakpointData *breakPointData = qvariant_cast<BreakpointData *>(data); - BreakWindow::editBreakpoint(breakPointData, mainWindow()); + const BreakpointId id = act->data().toInt(); + QTC_ASSERT(id > 0, return); + BreakWindow::editBreakpoint(id, mainWindow()); } void slotRunToLine() @@ -1211,6 +1223,10 @@ public slots: void clearCppCodeModelSnapshot(); void showMessage(const QString &msg, int channel, int timeout = -1); + Utils::SavedAction *action(int code) const; + bool boolSetting(int code) const; + QString stringSetting(int code) const; + public: DebuggerState m_state; DebuggerUISwitcher *m_uiSwitcher; @@ -1285,6 +1301,9 @@ public: SnapshotHandler *m_snapshotHandler; bool m_shuttingDown; DebuggerEngine *m_currentEngine; + DebuggerSettings *m_debuggerSettings; + QSettings *m_coreSettings; + bool m_gdbBinariesChanged; }; @@ -1337,10 +1356,16 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) m_state = DebuggerNotReady; m_snapshotHandler = 0; m_currentEngine = 0; + m_debuggerSettings = 0; + + m_gdbBinariesChanged = true; } DebuggerPluginPrivate::~DebuggerPluginPrivate() { + delete m_debuggerSettings; + m_debuggerSettings = 0; + m_plugin->removeObject(theDebuggerCore->m_debugMode); delete m_debugMode; m_debugMode = 0; @@ -1361,6 +1386,9 @@ DebuggerCore *debuggerCore() bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *errorMessage) { + m_coreSettings = ICore::instance()->settings(); + m_debuggerSettings = new DebuggerSettings(m_coreSettings); + m_continuableContext = Context("Gdb.Continuable"); m_interruptibleContext = Context("Gdb.Interruptible"); m_undisturbableContext = Context("Gdb.Undisturbable"); @@ -1399,8 +1427,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, m_statusLabel->setMinimumSize(QSize(30, 10)); m_breakHandler = new BreakHandler; - connect(m_breakHandler, SIGNAL(breakpointSynchronizationRequested()), - SLOT(synchronizeBreakpoints())); m_breakWindow = new BreakWindow; m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints")); m_breakWindow->setModel(m_breakHandler->model()); @@ -1522,21 +1548,22 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, act = m_actions.frameUpAction = new QAction(tr("Move to Calling Frame"), this); connect(act, SIGNAL(triggered()), SLOT(handleFrameUp())); - connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()), + connect(debuggerCore()->action(OperateByInstruction), SIGNAL(triggered()), SLOT(handleOperateByInstructionTriggered())); connect(&m_statusTimer, SIGNAL(timeout()), SLOT(clearStatusMessage())); - connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()), + connect(debuggerCore()->action(ExecuteCommand), SIGNAL(triggered()), SLOT(executeDebuggerCommand())); - readSettings(); - // Cpp/Qml ui setup m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this); ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher); m_uiSwitcher->addLanguage(CppLanguage, cppDebuggercontext); m_uiSwitcher->addLanguage(QmlLanguage, qmlDebuggerContext); + m_uiSwitcher->initialize(m_coreSettings); + + readSettings(); // Dock widgets m_breakDock = m_uiSwitcher->createDockWidget(CppLanguage, m_breakWindow); @@ -1793,7 +1820,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, Constants::FRAME_UP, cppDebuggercontext); - cmd = am->registerAction(theDebuggerAction(OperateByInstruction), + cmd = am->registerAction(debuggerCore()->action(OperateByInstruction), Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, CppLanguage); @@ -1886,7 +1913,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, SLOT(editorOpened(Core::IEditor*))); // Application interaction - connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()), + connect(debuggerCore()->action(SettingsDialog), SIGNAL(triggered()), SLOT(showSettingsDialog())); // Toolbar @@ -1922,7 +1949,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, SIGNAL(dockResetRequested(Debugger::DebuggerLanguages)), SLOT(setSimpleDockWidgetArrangement(Debugger::DebuggerLanguages))); - connect(theDebuggerAction(EnableReverseDebugging), + connect(debuggerCore()->action(EnableReverseDebugging), SIGNAL(valueChanged(QVariant)), SLOT(enableReverseDebuggingTriggered(QVariant))); @@ -1943,16 +1970,16 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, void DebuggerPluginPrivate::setConfigValue(const QString &name, const QVariant &value) { - settings()->setValue(_("DebugMode/") + name, value); + m_coreSettings->setValue(_("DebugMode/") + name, value); } QVariant DebuggerPluginPrivate::configValue(const QString &name) const { - const QVariant value = settings()->value(_("DebugMode/") + name); + const QVariant value = m_coreSettings->value(_("DebugMode/") + name); if (value.isValid()) return value; // Legacy (pre-2.1): Check old un-namespaced-settings. - return settings()->value(name); + return m_coreSettings->value(name); } void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project) @@ -2259,7 +2286,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor, if (!isDebuggable(editor)) return; - BreakpointData *data = 0; + BreakpointId id = -1; QString fileName; quint64 address = 0; @@ -2267,14 +2294,13 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor, fileName = editor->file()->fileName(); QString line = editor->contents() .section('\n', lineNumber - 1, lineNumber - 1); - BreakpointData needle; - address = DisassemblerViewAgent::addressFromDisassemblyLine(line); - needle.address = address; + BreakpointResponse needle; + needle.bpAddress = DisassemblerViewAgent::addressFromDisassemblyLine(line); needle.bpLineNumber = -1; - data = m_breakHandler->findSimilarBreakpoint(&needle); + id = breakHandler()->findSimilarBreakpoint(needle); } else { fileName = editor->file()->fileName(); - data = m_breakHandler->findBreakpoint(fileName, lineNumber); + id = breakHandler()->findBreakpointByFileAndLine(fileName, lineNumber); } QList<QVariant> args; @@ -2282,51 +2308,43 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor, args.append(lineNumber); args.append(address); - if (data) { - // existing breakpoint - const QString number = QString::fromAscii(data->bpNumber); - QAction *act; - if (number.isEmpty()) - act = new QAction(tr("Remove Breakpoint"), menu); - else - act = new QAction(tr("Remove Breakpoint %1").arg(number), menu); - act->setData(args); + if (id != BreakpointId(-1)) { + // Remove existing breakpoint. + QAction *act = new QAction(menu); + act->setData(int(id)); + act->setText(tr("Remove Breakpoint %1").arg(id)); connect(act, SIGNAL(triggered()), - SLOT(breakpointSetRemoveMarginActionTriggered())); + SLOT(breakpointRemoveMarginActionTriggered())); menu->addAction(act); - QAction *act2; - if (data->enabled) - if (number.isEmpty()) - act2 = new QAction(tr("Disable Breakpoint"), menu); - else - act2 = new QAction(tr("Disable Breakpoint %1").arg(number), menu); - else - if (number.isEmpty()) - act2 = new QAction(tr("Enable Breakpoint"), menu); - else - act2 = new QAction(tr("Enable Breakpoint %1").arg(number), menu); - act2->setData(args); - connect(act2, SIGNAL(triggered()), - this, SLOT(breakpointEnableDisableMarginActionTriggered())); - menu->addAction(act2); - QAction *editAction; - if (number.isEmpty()) - editAction = new QAction(tr("Edit Breakpoint..."), menu); - else - editAction = new QAction(tr("Edit Breakpoint %1...").arg(number), menu); - connect(editAction, SIGNAL(triggered()), SLOT(slotEditBreakpoint())); - editAction->setData(qVariantFromValue(data)); - menu->addAction(editAction); + // Enable/disable existing breakpoint. + act = new QAction(menu); + if (breakHandler()->isEnabled(id)) { + act->setText(tr("Disable Breakpoint %1").arg(id)); + connect(act, SIGNAL(triggered()), + SLOT(breakpointDisableMarginActionTriggered())); + } else { + act->setText(tr("Enable Breakpoint %1").arg(id)); + connect(act, SIGNAL(triggered()), + SLOT(breakpointEnableMarginActionTriggered())); + } + menu->addAction(act); + + // Edit existing breakpoint. + act = new QAction(menu); + act->setText(tr("Edit Breakpoint %1...").arg(id)); + connect(act, SIGNAL(triggered()), SLOT(slotEditBreakpoint())); + act->setData(int(id)); + menu->addAction(act); } else { - // non-existing + // Handle non-existing breakpoint. const QString text = address ? tr("Set Breakpoint at 0x%1").arg(address, 0, 16) : tr("Set Breakpoint at line %1").arg(lineNumber); QAction *act = new QAction(text, menu); act->setData(args); connect(act, SIGNAL(triggered()), - SLOT(breakpointSetRemoveMarginActionTriggered())); + SLOT(breakpointSetMarginActionTriggered())); menu->addAction(act); } // Run to, jump to line below in stopped state. @@ -2362,12 +2380,11 @@ void DebuggerPluginPrivate::toggleBreakpoint() void DebuggerPluginPrivate::toggleBreakpoint(const QString &fileName, int lineNumber) { m_breakHandler->toggleBreakpoint(fileName, lineNumber); - m_breakHandler->synchronizeBreakpoints(); } void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber) { - if (isDebuggable(editor) && editor && editor->file()) + if (isDebuggable(editor) && editor->file()) toggleBreakpoint(editor->file()->fileName(), lineNumber); } @@ -2376,7 +2393,7 @@ void DebuggerPluginPrivate::showToolTip(ITextEditor *editor, { if (!isDebuggable(editor)) return; - if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)) + if (!boolSetting(UseToolTipsInMainEditor)) return; if (state() != InferiorStopOk) return; @@ -2485,27 +2502,26 @@ void DebuggerPluginPrivate::cleanupViews() m_actions.reverseDirectionAction->setEnabled(false); hideDebuggerToolTip(); - // FIXME ABC: Delete run control / engine? - //if (d->m_engine) - // d->m_engine->cleanup(); - - if (theDebuggerBoolSetting(CloseBuffersOnExit)) { - if (EditorManager *editorManager = EditorManager::instance()) { - QList<IEditor *> toClose; - foreach (IEditor *editor, editorManager->openedEditors()) { - if (editor->property(Debugger::Constants::OPENED_BY_DEBUGGER).toBool()) { - // close disassembly views. close other opened files if they are not modified and not current editor - if (editor->property(Debugger::Constants::OPENED_WITH_DISASSEMBLY).toBool() - || (!editor->file()->isModified() && editor != editorManager->currentEditor())) { - toClose.append(editor); - } else { - editor->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, false); - } - } + if (!boolSetting(CloseBuffersOnExit)) + return; + + EditorManager *editorManager = EditorManager::instance(); + QTC_ASSERT(editorManager, return); + QList<IEditor *> toClose; + foreach (IEditor *editor, editorManager->openedEditors()) { + if (editor->property(Constants::OPENED_BY_DEBUGGER).toBool()) { + // Close disassembly views. Close other opened files + // if they are not modified and not current editor. + if (editor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool() + || (!editor->file()->isModified() + && editor != editorManager->currentEditor())) { + toClose.append(editor); + } else { + editor->setProperty(Constants::OPENED_BY_DEBUGGER, false); } - editorManager->closeEditors(toClose); } } + editorManager->closeEditors(toClose); } void DebuggerPluginPrivate::setBusyCursor(bool busy) @@ -2606,7 +2622,7 @@ void DebuggerPluginPrivate::setInitialState() m_actions.watchAction2->setEnabled(true); m_actions.breakAction->setEnabled(true); //m_actions.snapshotAction->setEnabled(false); - theDebuggerAction(OperateByInstruction)->setEnabled(false); + debuggerCore()->action(OperateByInstruction)->setEnabled(false); m_actions.exitAction->setEnabled(false); m_actions.resetAction->setEnabled(false); @@ -2619,9 +2635,9 @@ void DebuggerPluginPrivate::setInitialState() m_actions.jumpToLineAction->setEnabled(false); m_actions.nextAction->setEnabled(false); - theDebuggerAction(AutoDerefPointers)->setEnabled(true); - theDebuggerAction(ExpandStack)->setEnabled(false); - theDebuggerAction(ExecuteCommand)->setEnabled(m_state == InferiorStopOk); + debuggerCore()->action(AutoDerefPointers)->setEnabled(true); + debuggerCore()->action(ExpandStack)->setEnabled(false); + debuggerCore()->action(ExecuteCommand)->setEnabled(m_state == InferiorStopOk); m_scriptConsoleWindow->setEnabled(false); @@ -2728,7 +2744,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) const uint caps = engine->debuggerCapabilities(); const bool canReverse = (caps & ReverseSteppingCapability) - && theDebuggerBoolSetting(EnableReverseDebugging); + && debuggerCore()->boolSetting(EnableReverseDebugging); m_actions.reverseDirectionAction->setEnabled(canReverse); m_actions.watchAction1->setEnabled(true); @@ -2736,7 +2752,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_actions.breakAction->setEnabled(true); //m_actions.snapshotAction->setEnabled(stopped && (caps & SnapshotCapability)); - theDebuggerAction(OperateByInstruction)->setEnabled(stopped); + debuggerCore()->action(OperateByInstruction)->setEnabled(stopped); m_actions.resetAction->setEnabled(m_state != DebuggerNotReady && m_state != DebuggerFinished); @@ -2754,10 +2770,10 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_actions.nextAction->setEnabled(stopped); const bool canDeref = actionsEnabled && (caps & AutoDerefPointersCapability); - theDebuggerAction(AutoDerefPointers)->setEnabled(canDeref); - theDebuggerAction(AutoDerefPointers)->setEnabled(true); - theDebuggerAction(ExpandStack)->setEnabled(actionsEnabled); - theDebuggerAction(ExecuteCommand)->setEnabled(m_state == InferiorStopOk); + debuggerCore()->action(AutoDerefPointers)->setEnabled(canDeref); + debuggerCore()->action(AutoDerefPointers)->setEnabled(true); + debuggerCore()->action(ExpandStack)->setEnabled(actionsEnabled); + debuggerCore()->action(ExecuteCommand)->setEnabled(m_state == InferiorStopOk); const bool notbusy = m_state == InferiorStopOk || m_state == DebuggerNotReady @@ -2921,25 +2937,24 @@ void DebuggerPluginPrivate::coreShutdown() void DebuggerPluginPrivate::writeSettings() const { - QSettings *s = settings(); - DebuggerSettings::instance()->writeSettings(s); - if (m_uiSwitcher) - m_uiSwitcher->writeSettings(s); + m_debuggerSettings->writeSettings(); + m_uiSwitcher->writeSettings(); + if (GdbOptionsPage::gdbBinariesChanged) + GdbOptionsPage::writeGdbBinarySettings(); } void DebuggerPluginPrivate::readSettings() { //qDebug() << "PLUGIN READ SETTINGS"; - QSettings *s = settings(); - DebuggerSettings::instance()->readSettings(s); - if (m_uiSwitcher) - m_uiSwitcher->writeSettings(s); + m_debuggerSettings->readSettings(); + m_uiSwitcher->readSettings(); + GdbOptionsPage::readGdbBinarySettings(); } const CPlusPlus::Snapshot &DebuggerPluginPrivate::cppCodeModelSnapshot() const { if (m_codeModelSnapshot.isEmpty() - && theDebuggerAction(UseCodeModel)->isChecked()) + && debuggerCore()->action(UseCodeModel)->isChecked()) m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); return m_codeModelSnapshot; } @@ -3050,7 +3065,7 @@ void DebuggerPluginPrivate::showQtDumperLibraryWarning(const QString &details) _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY), _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID)); } else if (dialog.clickedButton() == helperOff) { - theDebuggerAction(UseDebuggingHelpers) + debuggerCore()->action(UseDebuggingHelpers) ->setValue(qVariantFromValue(false), false); } } @@ -3080,7 +3095,7 @@ void DebuggerPluginPrivate::runControlStarted(DebuggerRunControl *runControl) const QString message = runControl->idString(); showMessage(message, StatusBar); - showMessage(DebuggerSettings::instance()->dump(), LogDebug); + showMessage(m_debuggerSettings->dump(), LogDebug); m_snapshotHandler->appendSnapshot(runControl); connectEngine(runControl->engine()); } @@ -3089,7 +3104,7 @@ void DebuggerPluginPrivate::runControlFinished(DebuggerRunControl *runControl) { m_snapshotHandler->removeSnapshot(runControl); disconnectEngine(); - if (theDebuggerBoolSetting(SwitchModeOnExit)) + if (debuggerCore()->boolSetting(SwitchModeOnExit)) if (m_snapshotHandler->size() == 0) activatePreviousMode(); } @@ -3115,6 +3130,11 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options, arg(options.join(QString(QLatin1Char(' ')))))); } +QString DebuggerPluginPrivate::gdbBinaryForToolChain(int toolChain) const +{ + return GdbOptionsPage::gdbBinaryToolChainMap.key(toolChain); +} + DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const { return m_uiSwitcher->activeDebugLanguages(); @@ -3125,11 +3145,12 @@ bool DebuggerPluginPrivate::isReverseDebugging() const return m_actions.reverseDirectionAction->isChecked(); } -QMessageBox *DebuggerPluginPrivate::showMessageBox(int icon, const QString &title, +QMessageBox *showMessageBox(int icon, const QString &title, const QString &text, int buttons) { QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon), - title, text, QMessageBox::StandardButtons(buttons), mainWindow()); + title, text, QMessageBox::StandardButtons(buttons), + debuggerCore()->mainWindow()); mb->setAttribute(Qt::WA_DeleteOnClose); mb->show(); return mb; @@ -3144,7 +3165,7 @@ void DebuggerPluginPrivate::ensureLogVisible() void DebuggerPluginPrivate::extensionsInitialized() { - m_uiSwitcher->initialize(settings()); + QTC_ASSERT(m_coreSettings, /**/); m_watchersWindow->setVisible(false); m_returnWindow->setVisible(false); connect(m_uiSwitcher, SIGNAL(memoryEditorRequested()), @@ -3160,6 +3181,21 @@ void DebuggerPluginPrivate::extensionsInitialized() QTimer::singleShot(0, this, SLOT(attachCmdLine())); } +Utils::SavedAction *DebuggerPluginPrivate::action(int code) const +{ + return m_debuggerSettings->item(code); +} + +bool DebuggerPluginPrivate::boolSetting(int code) const +{ + return m_debuggerSettings->item(code)->value().toBool(); +} + +QString DebuggerPluginPrivate::stringSetting(int code) const +{ + return m_debuggerSettings->item(code)->value().toString(); +} + } // namespace Internal using namespace Debugger::Internal; @@ -3177,7 +3213,6 @@ DebuggerPlugin::DebuggerPlugin() DebuggerPlugin::~DebuggerPlugin() { - delete DebuggerSettings::instance(); delete theDebuggerCore; theDebuggerCore = 0; } @@ -3256,6 +3291,7 @@ DebuggerUISwitcher *DebuggerPlugin::uiSwitcher() return theDebuggerCore->m_uiSwitcher; } + ////////////////////////////////////////////////////////////////////// // // Testing diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index ee9fde62793a5c6a893c745800fd61992b876ed2..5362ecc261d403eddd3e897e0d9e99728dc5d5bc 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -38,6 +38,7 @@ #include "gdb/gdbengine.h" #include "gdb/remotegdbserveradapter.h" #include "gdb/remoteplaingdbadapter.h" +#include "gdb/gdboptionspage.h" #include "qml/qmlengine.h" #include "qml/qmlcppengine.h" #include "lldb/lldbenginehost.h" @@ -76,7 +77,7 @@ DebuggerEngine *createQmlEngine(const DebuggerStartParameters &); DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &); DebuggerEngine *createLLDBEngine(const DebuggerStartParameters &); -bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage); +extern QString msgNoBinaryForToolChain(int tc); // FIXME: Outdated? // The createCdbEngine function takes a list of options pages it can add to. @@ -552,9 +553,14 @@ bool DebuggerRunControl::checkDebugConfiguration(int toolChain, case ProjectExplorer::ToolChain_GCCE: case ProjectExplorer::ToolChain_RVCT_ARMV5: case ProjectExplorer::ToolChain_RVCT_ARMV6: - success = checkGdbConfiguration(toolChain, errorMessage, settingsPage); - if (!success) + if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) { + *errorMessage = msgNoBinaryForToolChain(toolChain); + *settingsPage = GdbOptionsPage::settingsId(); *errorMessage += msgEngineNotAvailable("Gdb"); + success = false; + } else { + success = true; + } break; case ProjectExplorer::ToolChain_MSVC: success = checkCdbConfiguration(toolChain, errorMessage, settingsPage); diff --git a/src/plugins/debugger/debuggerstreamops.cpp b/src/plugins/debugger/debuggerstreamops.cpp index aea66f5a6b0a4b9f6ca0c4d27fce2c0b0b16ce3a..024560d5d134edf414fff82613d455782379451c 100644 --- a/src/plugins/debugger/debuggerstreamops.cpp +++ b/src/plugins/debugger/debuggerstreamops.cpp @@ -134,56 +134,64 @@ QDataStream &operator>>(QDataStream &stream, StackFrames &frames) return stream; } -QDataStream &operator<<(QDataStream &stream, const BreakpointData &s) +QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s) { - stream << s.fileName; - stream << s.condition; - stream << (quint64)s.ignoreCount; - stream << (quint64)s.lineNumber; - stream << s.address; - stream << s.funcName; - stream << s.useFullPath; - stream << s.bpNumber; stream << s.bpCondition; stream << s.bpIgnoreCount; stream << s.bpFileName; stream << s.bpFullName; stream << s.bpLineNumber; - stream << s.bpCorrectedLineNumber; + //stream << s.bpCorrectedLineNumber; stream << s.bpThreadSpec; stream << s.bpFuncName; stream << s.bpAddress; - return stream; } -QDataStream &operator>>(QDataStream &stream, BreakpointData &s) +QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s) { - quint64 t; - stream >> s.fileName; - stream >> s.condition; - stream >> t; - s.ignoreCount = t; - stream >> t; - s.lineNumber = t; - stream >> s.address; - stream >> s.funcName; - stream >> s.useFullPath; - stream >> s.bpNumber; stream >> s.bpCondition; stream >> s.bpIgnoreCount; stream >> s.bpFileName; stream >> s.bpFullName; stream >> s.bpLineNumber; - stream >> s.bpCorrectedLineNumber; + //stream >> s.bpCorrectedLineNumber; stream >> s.bpThreadSpec; stream >> s.bpFuncName; stream >> s.bpAddress; return stream; } +QDataStream &operator<<(QDataStream &stream, const BreakpointData &s) +{ + stream << s.fileName(); + stream << s.condition(); + stream << quint64(s.ignoreCount()); + stream << quint64(s.lineNumber()); + stream << quint64(s.address()); + stream << s.functionName(); + stream << s.useFullPath(); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, BreakpointData &s) +{ + quint64 t; + QString str; + QByteArray ba; + bool b; + stream >> str; s.setFileName(str); + stream >> ba; s.setCondition(ba); + stream >> t; s.setIgnoreCount(t); + stream >> t; s.setLineNumber(t); + stream >> t; s.setAddress(t); + stream >> str; s.setFunctionName(str); + stream >> b; s.setUseFullPath(b); + return stream; +} + QDataStream &operator<<(QDataStream &stream, const WatchData &wd) { stream << wd.id; diff --git a/src/plugins/debugger/debuggerstreamops.h b/src/plugins/debugger/debuggerstreamops.h index 8bb38a45d7d9ab318ff9c33092c52101acc7c316..af93b59e60c62e7be67d49de7bf8675b02884c89 100644 --- a/src/plugins/debugger/debuggerstreamops.h +++ b/src/plugins/debugger/debuggerstreamops.h @@ -47,12 +47,12 @@ QDataStream &operator<<(QDataStream& stream, const StackFrame& frame); QDataStream &operator>>(QDataStream& stream, StackFrame &frame); QDataStream &operator<<(QDataStream& stream, const StackFrames& frames); QDataStream &operator>>(QDataStream& stream, StackFrames &frames); -QDataStream &operator<<(QDataStream& stream, const BreakpointData &bps); -QDataStream &operator>>(QDataStream& stream, BreakpointData &bps); -QDataStream &operator<<(QDataStream& stream, const WatchData &bps); -QDataStream &operator>>(QDataStream& stream, WatchData &bps); -QDataStream &operator<<(QDataStream& stream, const WatchData &bps); -QDataStream &operator>>(QDataStream& stream, WatchData &bps); +QDataStream &operator<<(QDataStream& stream, const BreakpointData &data); +QDataStream &operator>>(QDataStream& stream, BreakpointData &data); +QDataStream &operator<<(QDataStream& stream, const BreakpointResponse &data); +QDataStream &operator>>(QDataStream& stream, BreakpointResponse &data); +QDataStream &operator<<(QDataStream& stream, const WatchData &data); +QDataStream &operator>>(QDataStream& stream, WatchData &data); } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggeruiswitcher.cpp b/src/plugins/debugger/debuggeruiswitcher.cpp index 80aa00fb91880cb13db3fda6ed86ccf85c0d745e..635bfb60e43ba530be216adb4781bf3782a32999 100644 --- a/src/plugins/debugger/debuggeruiswitcher.cpp +++ b/src/plugins/debugger/debuggeruiswitcher.cpp @@ -140,6 +140,7 @@ struct DebuggerUISwitcherPrivate QWeakPointer<ProjectExplorer::RunConfiguration> m_previousRunConfiguration; bool m_initialized; + QSettings *m_settings; }; DebuggerUISwitcherPrivate::DebuggerUISwitcherPrivate(DebuggerUISwitcher *q) @@ -155,6 +156,7 @@ DebuggerUISwitcherPrivate::DebuggerUISwitcherPrivate(DebuggerUISwitcher *q) , m_viewsMenu(0) , m_debugMenu(0) , m_initialized(false) + , m_settings(0) { } @@ -583,44 +585,39 @@ QWidget *DebuggerUISwitcher::createContents(BaseMode *mode) return splitter; } -void DebuggerUISwitcher::writeSettings(QSettings *settings) const +void DebuggerUISwitcher::writeSettings() const { - { - settings->beginGroup(QLatin1String("DebugMode.CppMode")); - QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateCpp); - while (it.hasNext()) { - it.next(); - settings->setValue(it.key(), it.value()); - } - settings->endGroup(); + d->m_settings->beginGroup(QLatin1String("DebugMode.CppMode")); + QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateCpp); + while (it.hasNext()) { + it.next(); + d->m_settings->setValue(it.key(), it.value()); } - { - settings->beginGroup(QLatin1String("DebugMode.CppQmlMode")); - QHashIterator<QString, QVariant> it(d->m_dockWidgetActiveStateQmlCpp); - while (it.hasNext()) { - it.next(); - settings->setValue(it.key(), it.value()); - } - settings->endGroup(); + d->m_settings->endGroup(); + + d->m_settings->beginGroup(QLatin1String("DebugMode.CppQmlMode")); + it = QHashIterator<QString, QVariant>(d->m_dockWidgetActiveStateQmlCpp); + while (it.hasNext()) { + it.next(); + d->m_settings->setValue(it.key(), it.value()); } + d->m_settings->endGroup(); } -void DebuggerUISwitcher::readSettings(QSettings *settings) +void DebuggerUISwitcher::readSettings() { d->m_dockWidgetActiveStateCpp.clear(); d->m_dockWidgetActiveStateQmlCpp.clear(); - settings->beginGroup(QLatin1String("DebugMode.CppMode")); - foreach (const QString &key, settings->childKeys()) { - d->m_dockWidgetActiveStateCpp.insert(key, settings->value(key)); - } - settings->endGroup(); + d->m_settings->beginGroup(QLatin1String("DebugMode.CppMode")); + foreach (const QString &key, d->m_settings->childKeys()) + d->m_dockWidgetActiveStateCpp.insert(key, d->m_settings->value(key)); + d->m_settings->endGroup(); - settings->beginGroup(QLatin1String("DebugMode.CppQmlMode")); - foreach (const QString &key, settings->childKeys()) { - d->m_dockWidgetActiveStateQmlCpp.insert(key, settings->value(key)); - } - settings->endGroup(); + d->m_settings->beginGroup(QLatin1String("DebugMode.CppQmlMode")); + foreach (const QString &key, d->m_settings->childKeys()) + d->m_dockWidgetActiveStateQmlCpp.insert(key, d->m_settings->value(key)); + d->m_settings->endGroup(); // reset initial settings when there are none yet DebuggerLanguages langs = d->m_activeDebugLanguages; @@ -637,10 +634,11 @@ void DebuggerUISwitcher::readSettings(QSettings *settings) void DebuggerUISwitcher::initialize(QSettings *settings) { + d->m_settings = settings; createViewsMenuItems(); emit dockResetRequested(AnyLanguage); - readSettings(settings); + readSettings(); updateUi(); diff --git a/src/plugins/debugger/debuggeruiswitcher.h b/src/plugins/debugger/debuggeruiswitcher.h index 4b243db8432b4d35859ba06488afe9f0c7e99c43..1700e12439fcd3fb1eee8f2bd4625bf9abe9405d 100644 --- a/src/plugins/debugger/debuggeruiswitcher.h +++ b/src/plugins/debugger/debuggeruiswitcher.h @@ -130,8 +130,8 @@ private slots: public slots: void updateActiveLanguages(); void updateDockWidgetSettings(); - void readSettings(QSettings *settings); - void writeSettings(QSettings *settings) const; + void readSettings(); + void writeSettings() const; private: // Used by MainWindow diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp index 241776dc480198490334b2e910e613d219e97146..e4e7ea16a93aafc468eb5929c658fcf5d3d481dd 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp @@ -31,6 +31,7 @@ #include "gdbmi.h" #include "gdbengine.h" #include "debuggeractions.h" +#include "debuggercore.h" #include "debuggerstringutils.h" #include <utils/qtcassert.h> @@ -96,7 +97,7 @@ void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response) showMessage(_("INFERIOR STARTED")); showMessage(msgInferiorSetupOk(), StatusBar); // FIXME: That's the wrong place for it. - if (theDebuggerBoolSetting(EnableReverseDebugging)) + if (debuggerCore()->boolSetting(EnableReverseDebugging)) m_engine->postCommand("target record"); } else { QString msg = fromLocalEncoding(response.data.findChild("msg").data()); diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp index 8f227d2f53e0582cec479d3ea504e44445e3eb15..732122f3e2fad18486b026ed13f471032365c2df 100644 --- a/src/plugins/debugger/gdb/classicgdbengine.cpp +++ b/src/plugins/debugger/gdb/classicgdbengine.cpp @@ -273,7 +273,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) qDebug() << "IT'S A POINTER"; # endif - if (theDebuggerBoolSetting(AutoDerefPointers)) { + if (debuggerCore()->boolSetting(AutoDerefPointers)) { // Try automatic dereferentiation data.exp = "(*(" + data.exp + "))"; data.type = data.type + "."; // FIXME: fragile HACK to avoid recursion @@ -658,7 +658,7 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response) // handleStop1, which passes on the frame as cookie. The whole stack // is not known at this point. QStringList uninitializedVariables; - if (theDebuggerAction(UseCodeModel)->isChecked()) { + if (debuggerCore()->action(UseCodeModel)->isChecked()) { const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ? qVariantValue<Debugger::Internal::StackFrame>(response.cookie) diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp index 552d84cae2411a4c20cfc2e5a102104ebcdfd34f..77afb67a6546894e3aec9656d13c1880af5055ad 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.cpp +++ b/src/plugins/debugger/gdb/coregdbadapter.cpp @@ -28,10 +28,12 @@ **************************************************************************/ #include "coregdbadapter.h" -#include "gdbmi.h" + +#include "debuggercore.h" #include "debuggeractions.h" -#include "gdbengine.h" #include "debuggerstringutils.h" +#include "gdbmi.h" +#include "gdbengine.h" #include <utils/qtcassert.h> @@ -73,7 +75,7 @@ void CoreGdbAdapter::startAdapter() return; //if (m_executable.isEmpty()) { - // DebuggerEngine::showMessageBox(QMessageBox::Warning, + // showMessageBox(QMessageBox::Warning, // tr("Error Loading Symbols"), // tr("No executable to load symbols from specified.")); //} @@ -100,7 +102,7 @@ void CoreGdbAdapter::startAdapter() msg += _(" "); msg += tr("Try to specify the binary using the " "<i>Debug->Start Debugging->Attach to Core</i> dialog."); - DebuggerEngine::showMessageBox(QMessageBox::Warning, + showMessageBox(QMessageBox::Warning, tr("Loading core file failed"), msg); m_engine->notifyEngineSetupFailed(); } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 089322f01987b40b3eb0c775da65eab0efabe6ae..fdae9ffc626d3bcadb739de2fff275c1a4fc33c5 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -191,11 +191,11 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters) initializeVariables(); m_gdbAdapter = createAdapter(); - connect(theDebuggerAction(AutoDerefPointers), SIGNAL(valueChanged(QVariant)), + connect(debuggerCore()->action(AutoDerefPointers), SIGNAL(valueChanged(QVariant)), SLOT(reloadLocals())); - connect(theDebuggerAction(SortStructMembers), SIGNAL(valueChanged(QVariant)), + connect(debuggerCore()->action(SortStructMembers), SIGNAL(valueChanged(QVariant)), SLOT(reloadLocals())); - connect(theDebuggerAction(CreateFullBacktrace), SIGNAL(triggered()), + connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()), SLOT(createFullBacktrace())); } @@ -456,9 +456,8 @@ void GdbEngine::handleResponse(const QByteArray &buff) // line="1584",shlib="/../libFoo_debug.dylib",times="0"} const GdbMi bkpt = result.findChild("bkpt"); const int number = bkpt.findChild("number").data().toInt(); - BreakpointData *data = breakHandler()->findBreakpointByNumber(number); - setBreakpointDataFromOutput(data, bkpt); - breakHandler()->updateMarkers(); + BreakpointId id = breakHandler()->findBreakpointByNumber(number); + setBreakpointDataFromOutput(id, bkpt); } else { qDebug() << "IGNORED ASYNC OUTPUT" << asyncClass << result.toString(); @@ -809,7 +808,7 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0) int GdbEngine::commandTimeoutTime() const { - int time = theDebuggerAction(GdbWatchdogTimeout)->value().toInt(); + int time = debuggerCore()->action(GdbWatchdogTimeout)->value().toInt(); return 1000 * qMax(20, time); } @@ -917,7 +916,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response) } GdbCommand cmd = m_cookieForToken.take(token); - if (theDebuggerBoolSetting(LogTimeStamps)) { + if (debuggerCore()->boolSetting(LogTimeStamps)) { showMessage(_("Response time: %1: %2 s") .arg(_(cmd.command)) .arg(cmd.postTime.msecsTo(QTime::currentTime()) / 1000.), @@ -1124,7 +1123,7 @@ static bool isExitedReason(const QByteArray &reason) void GdbEngine::handleAqcuiredInferior() { // Reverse debugging. FIXME: Should only be used when available. - //if (theDebuggerBoolSetting(EnableReverseDebugging)) + //if (debuggerCore()->boolSetting(EnableReverseDebugging)) // postCommand("target response"); tryLoadDebuggingHelpers(); @@ -1132,16 +1131,16 @@ void GdbEngine::handleAqcuiredInferior() # ifndef Q_OS_MAC // intentionally after tryLoadDebuggingHelpers(), // otherwise we'd interrupt solib loading. - if (theDebuggerBoolSetting(AllPluginBreakpoints)) { + if (debuggerCore()->boolSetting(AllPluginBreakpoints)) { postCommand("set auto-solib-add on"); postCommand("set stop-on-solib-events 0"); postCommand("sharedlibrary .*"); - } else if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) { + } else if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) { postCommand("set auto-solib-add on"); postCommand("set stop-on-solib-events 1"); postCommand("sharedlibrary " + theDebuggerStringSetting(SelectedPluginBreakpointsPattern)); - } else if (theDebuggerBoolSetting(NoPluginBreakpoints)) { + } else if (debuggerCore()->boolSetting(NoPluginBreakpoints)) { // should be like that already postCommand("set auto-solib-add off"); postCommand("set stop-on-solib-events 0"); @@ -1240,7 +1239,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) postCommand("set stop-on-solib-events 0"); #if 0 // The related code (handleAqcuiredInferior()) is disabled as well. - if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) { + if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) { QString dataStr = _(data.toString()); showMessage(_("SHARED LIBRARY EVENT: ") + dataStr); QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); @@ -1297,7 +1296,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) // Jump over well-known frames. static int stepCounter = 0; - if (theDebuggerBoolSetting(SkipKnownFrames)) { + if (debuggerCore()->boolSetting(SkipKnownFrames)) { if (reason == "end-stepping-range" || reason == "function-finished") { GdbMi frame = data.findChild("frame"); //showMessage(frame.toString()); @@ -1417,7 +1416,7 @@ void GdbEngine::handleStop1(const GdbMi &data) } else { QString reasontr = tr("Stopped: \"%1\"").arg(_(reason)); if (reason == "signal-received" - && theDebuggerBoolSetting(UseMessageBoxForSignals)) { + && debuggerCore()->boolSetting(UseMessageBoxForSignals)) { QByteArray name = data.findChild("signal-name").data(); QByteArray meaning = data.findChild("signal-meaning").data(); // Ignore these as they are showing up regularly when @@ -1721,16 +1720,11 @@ int GdbEngine::currentFrame() const return stackHandler()->currentIndex(); } -static inline QString msgNoBinaryForToolChain(int tc) +QString msgNoBinaryForToolChain(int tc) { - const ProjectExplorer::ToolChainType toolChain = static_cast<ProjectExplorer::ToolChainType>(tc); - const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(toolChain); - return GdbEngine::tr("There is no gdb binary available for '%1'").arg(toolChainName); -} - -static QString gdbBinaryForToolChain(int toolChain) -{ - return DebuggerSettings::instance()->gdbBinaryToolChainMap().key(toolChain); + using namespace ProjectExplorer; + return GdbEngine::tr("There is no gdb binary available for '%1'") + .arg(ToolChain::toolChainName(ToolChainType(tc))); } AbstractGdbAdapter *GdbEngine::createAdapter() @@ -1770,17 +1764,16 @@ AbstractGdbAdapter *GdbEngine::createAdapter() void GdbEngine::setupEngine() { - //qDebug() << "GDB START DEBUGGER"; QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/); - //qDebug() << "CREATED ADAPTER: " << m_gdbAdapter; - if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) { - connect(theDebuggerAction(UseDebuggingHelpers), SIGNAL(valueChanged(QVariant)), - this, SLOT(setUseDebuggingHelpers(QVariant))); - connect(theDebuggerAction(DebugDebuggingHelpers), SIGNAL(valueChanged(QVariant)), - this, SLOT(setDebugDebuggingHelpersClassic(QVariant))); + connect(debuggerCore()->action(UseDebuggingHelpers), + SIGNAL(valueChanged(QVariant)), + SLOT(setUseDebuggingHelpers(QVariant))); + connect(debuggerCore()->action(DebugDebuggingHelpers), + SIGNAL(valueChanged(QVariant)), + SLOT(setDebugDebuggingHelpersClassic(QVariant))); } QTC_ASSERT(state() == EngineSetupRequested, /**/); @@ -2047,7 +2040,7 @@ void GdbEngine::setTokenBarrier() } PENDING_DEBUG("\n--- token barrier ---\n"); showMessage(_("--- token barrier ---"), LogMiscInput); - if (theDebuggerBoolSetting(LogTimeStamps)) + if (debuggerCore()->boolSetting(LogTimeStamps)) showMessage(LogWindow::logTimeStamp(), LogMiscInput); m_oldestAcceptableToken = currentToken(); } @@ -2059,31 +2052,31 @@ void GdbEngine::setTokenBarrier() // ////////////////////////////////////////////////////////////////////// -void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt) +void GdbEngine::setBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt) { if (!bkpt.isValid()) return; - if (!data) - return; - data->pending = false; - data->bpMultiple = false; - data->bpEnabled = true; - data->bpCondition.clear(); + + BreakpointResponse response; + //data->pending = false; + response.bpMultiple = false; + response.bpEnabled = true; + response.bpCondition.clear(); QByteArray file, fullName; foreach (const GdbMi &child, bkpt.children()) { if (child.hasName("number")) { - data->bpNumber = child.data(); + response.bpNumber = child.data().toInt(); } else if (child.hasName("func")) { - data->bpFuncName = _(child.data()); + response.bpFuncName = _(child.data()); } else if (child.hasName("addr")) { // <MULTIPLE> happens in constructors. In this case there are // _two_ fields named "addr" in the response. On Linux that is... if (child.data().startsWith("0x")) { - data->bpAddress = child.data().mid(2).toULongLong(0, 16); + response.bpAddress = child.data().mid(2).toULongLong(0, 16); } else { - data->bpState = child.data(); + response.bpState = child.data(); if (child.data() == "<MULTIPLE>") - data->bpMultiple = true; + response.bpMultiple = true; } } else if (child.hasName("file")) { file = child.data(); @@ -2092,18 +2085,20 @@ void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &b } else if (child.hasName("line")) { bool ok; const int lineNumber = child.data().toInt(&ok); - data->bpLineNumber = lineNumber; - if (ok && data->bpCorrectedLineNumber <= 0) - data->setMarkerLineNumber(lineNumber); + response.bpLineNumber = lineNumber; + //if (ok && response.bpCorrectedLineNumber <= 0) + // data->setMarkerLineNumber(lineNumber); } else if (child.hasName("cond")) { - data->bpCondition = child.data(); + response.bpCondition = child.data(); // gdb 6.3 likes to "rewrite" conditions. Just accept that fact. - if (data->bpCondition != data->condition && data->conditionsMatch()) - data->condition = data->bpCondition; + //if (response.bpCondition != data->condition() + // && data->conditionsMatch(response.bpCondition)) + // data->setCondition(response.bpCondition); } else if (child.hasName("enabled")) { - data->bpEnabled = (child.data() == "y"); + response.bpEnabled = (child.data() == "y"); } else if (child.hasName("pending")) { - data->pending = true; + //data->setState(BreakpointPending); + breakHandler()->setState(id, BreakpointPending); // Any content here would be interesting only if we did accept // spontaneously appearing breakpoints (user using gdb commands). } else if (child.hasName("at")) { @@ -2111,9 +2106,9 @@ void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &b QByteArray ba = child.data(); if (ba.startsWith('<') && ba.endsWith('>')) ba = ba.mid(1, ba.size() - 2); - data->bpFuncName = _(ba); + response.bpFuncName = _(ba); } else if (child.hasName("thread")) { - data->bpThreadSpec = child.data(); + response.bpThreadSpec = child.data(); } else if (child.hasName("type")) { // FIXME: This should not change the type. //if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint" @@ -2130,15 +2125,18 @@ void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &b QString name; if (!fullName.isEmpty()) { name = cleanupFullName(QFile::decodeName(fullName)); - if (data->markerFileName().isEmpty()) - data->setMarkerFileName(name); + response.bpFileName = name; + //if (data->markerFileName().isEmpty()) + // data->setMarkerFileName(name); } else { name = QFile::decodeName(file); // Use fullName() once we have a mapping which is more complete than // gdb's own. No point in assigning markerFileName for now. } if (!name.isEmpty()) - data->bpFileName = name; + response.bpFileName = name; + + breakHandler()->setResponse(id, response); } QString GdbEngine::breakLocation(const QString &file) const @@ -2150,78 +2148,50 @@ QString GdbEngine::breakLocation(const QString &file) const return where; } -static inline QByteArray bpAddressSpec(quint64 address) +static QByteArray addressSpec(quint64 address) { return "*0x" + QByteArray::number(address, 16); } -QByteArray GdbEngine::breakpointLocation(const BreakpointData *data) +QByteArray GdbEngine::breakpointLocation(BreakpointId id) { - if (!data->funcName.isEmpty()) { - if (data->funcName == QLatin1String(BreakpointData::throwFunction)) - return QByteArray("__cxa_throw"); - if (data->funcName == QLatin1String(BreakpointData::catchFunction)) - return QByteArray("__cxa_begin_catch"); - return data->funcName.toLatin1(); - } - if (data->address) - return bpAddressSpec(data->address); + BreakHandler *handler = breakHandler(); + QByteArray functionName = handler->functionName(id).toUtf8(); + if (!functionName.isEmpty()) { + // FIXME: Use the types. + if (functionName == BreakpointData::throwFunction) + return "__cxa_throw"; + if (functionName == BreakpointData::catchFunction) + return "__cxa_begin_catch"; + return functionName; + } + quint64 address = handler->address(id); + if (address) + return addressSpec(address); // In this case, data->funcName is something like '*0xdeadbeef' - if (data->lineNumber == 0) - return data->funcName.toLatin1(); - QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName); + int lineNumber = handler->lineNumber(id); + if (lineNumber == 0) + return functionName; + QString fileName = handler->fileName(id); + if (handler->useFullPath(id)) + fileName = breakLocation(fileName); // The argument is simply a C-quoted version of the argument to the // non-MI "break" command, including the "original" quoting it wants. - return "\"\\\"" + GdbMi::escapeCString(loc).toLocal8Bit() + "\\\":" - + QByteArray::number(data->lineNumber) + '"'; -} - -void GdbEngine::sendInsertBreakpoint(int index) -{ - const BreakpointData *data = breakHandler()->at(index); - // Set up fallback in case of pending breakpoints which aren't handled - // by the MI interface. - if (data->type == Watchpoint) { - postCommand("watch " + bpAddressSpec(data->address), - NeedsStop | RebuildBreakpointModel, - CB(handleWatchInsert), index); - return; - } - - QByteArray cmd; - if (m_isMacGdb) { - cmd = "-break-insert -l -1 -f "; - } else if (m_gdbAdapter->isTrkAdapter()) { - cmd = "-break-insert -h -f "; - } else if (m_gdbVersion >= 70000) { - cmd = "-break-insert "; - if (!data->threadSpec.isEmpty()) - cmd += "-p " + data->threadSpec; - cmd += " -f "; - } else if (m_gdbVersion >= 60800) { - // Probably some earlier version would work as well. - cmd = "-break-insert -f "; - } else { - cmd = "-break-insert "; - } - //if (!data->condition.isEmpty()) - // cmd += "-c " + data->condition + ' '; - cmd += breakpointLocation(data); - postCommand(cmd, NeedsStop | RebuildBreakpointModel, - CB(handleBreakInsert1), index); + return "\"\\\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\\\":" + + QByteArray::number(lineNumber) + '"'; } void GdbEngine::handleWatchInsert(const GdbResponse &response) { - int index = response.cookie.toInt(); + const int id = 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 = breakHandler()->at(index); - data->bpNumber = ba.mid(20, pos - 20); - breakHandler()->updateMarkers(); + BreakpointResponse response = breakHandler()->response(id); + response.bpNumber = ba.mid(20, pos - 20).toInt(); + breakHandler()->setResponse(id, response); } else { showMessage(_("CANNOT PARSE WATCHPOINT FROM" + ba)); } @@ -2230,19 +2200,19 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response) void GdbEngine::handleBreakInsert1(const GdbResponse &response) { - int index = response.cookie.toInt(); - BreakpointData *data = breakHandler()->at(index); + const int id = response.cookie.toInt(); if (response.resultClass == GdbResultDone) { // Interesting only on Mac? GdbMi bkpt = response.data.findChild("bkpt"); - setBreakpointDataFromOutput(data, bkpt); + setBreakpointDataFromOutput(id, bkpt); + notifyBreakpointInsertOk(id); } else { // Some versions of gdb like "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)" // know how to do pending breakpoints using CLI but not MI. So try // again with MI. - QByteArray cmd = "break " + breakpointLocation(data); + QByteArray cmd = "break " + breakpointLocation(id); postCommand(cmd, NeedsStop | RebuildBreakpointModel, - CB(handleBreakInsert2), index); + CB(handleBreakInsert2), id); } } @@ -2262,9 +2232,11 @@ void GdbEngine::handleBreakInsert2(const GdbResponse &response) void GdbEngine::reloadBreakListInternal() { +/* postCommand("-break-list", NeedsStop | RebuildBreakpointModel, CB(handleBreakList)); +*/ } void GdbEngine::handleBreakList(const GdbResponse &response) @@ -2305,16 +2277,17 @@ void GdbEngine::handleBreakList(const GdbMi &table) } foreach (const GdbMi &bkpt, bkpts) { - BreakpointData temp; - setBreakpointDataFromOutput(&temp, bkpt); - BreakpointData *data = breakHandler()->findSimilarBreakpoint(&temp); + BreakpointResponse needle; + needle.bpFileName = _("xx"); + BreakpointId id = breakHandler()->findSimilarBreakpoint(needle); //qDebug() << "\n\nGOT: " << bkpt.toString() << '\n' << temp.toString(); - if (data) { + // FIXME: use setBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt) + if (id != BreakpointId(-1)) { //qDebug() << " FROM: " << data->toString(); - setBreakpointDataFromOutput(data, bkpt); + setBreakpointDataFromOutput(id, bkpt); //qDebug() << " TO: " << data->toString(); } else { - //qDebug() << " NOTHING SUITABLE FOUND"; + qDebug() << " NOTHING SUITABLE FOUND"; showMessage(_("CANNOT FIND BP: " + bkpt.toString())); } } @@ -2331,7 +2304,6 @@ void GdbEngine::handleBreakDisable(const GdbResponse &response) void GdbEngine::handleBreakIgnore(const GdbResponse &response) { - int bpNumber = response.cookie.toInt(); // gdb 6.8: // ignore 2 0: // ~"Will stop next time breakpoint 2 is reached.\n" @@ -2342,8 +2314,7 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response) // 29^done // // gdb 6.3 does not produce any console output - BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber); - if (response.resultClass == GdbResultDone && data) { + if (response.resultClass == GdbResultDone) { QString msg = _(response.data.findChild("consolestreamoutput").data()); //if (msg.contains(__("Will stop next time breakpoint"))) { // data->bpIgnoreCount = _("0"); @@ -2351,36 +2322,31 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response) // data->bpIgnoreCount = data->ignoreCount; //} // FIXME: this assumes it is doing the right thing... - data->bpIgnoreCount = data->ignoreCount; - breakHandler()->updateMarkers(); + breakHandler()->ackIgnoreCount(BreakpointId(response.cookie.toInt())); } } void GdbEngine::handleBreakCondition(const GdbResponse &response) { - int bpNumber = response.cookie.toInt(); - BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber); + const int id = response.cookie.toInt(); if (response.resultClass == GdbResultDone) { // We just assume it was successful. Otherwise we had to parse // the output stream data. //qDebug() << "HANDLE BREAK CONDITION" << bpNumber << data->condition; - data->bpCondition = data->condition; + breakHandler()->ackCondition(id); } else { QByteArray msg = response.data.findChild("msg").data(); // happens on Mac if (1 || msg.startsWith("Error parsing breakpoint condition. " " Will try again when we hit the breakpoint.")) { //qDebug() << "ERROR BREAK CONDITION" << bpNumber << data->condition; - data->bpCondition = data->condition; + breakHandler()->ackCondition(id); } } - breakHandler()->updateMarkers(); } -void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *data) +void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id) { - data->bpFileName = _("<MULTIPLE>"); - //qDebug() << output; if (output.isEmpty()) return; @@ -2401,10 +2367,15 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData * QRegExp re(_("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)")); re.setMinimal(true); + BreakpointResponse response; + response.bpFileName = _("<MULTIPLE>"); + + QString requestedFileName = breakHandler()->fileName(id); + if (re.indexIn(output) != -1) { - data->bpAddress = re.cap(1).toULongLong(0, 16); - data->bpFuncName = re.cap(2).trimmed(); - data->bpLineNumber = re.cap(4).toInt(); + response.bpAddress = re.cap(1).toULongLong(0, 16); + response.bpFuncName = re.cap(2).trimmed(); + response.bpLineNumber = re.cap(4).toInt(); QString full = fullName(re.cap(3)); if (full.isEmpty()) { // FIXME: This happens without UsePreciseBreakpoints regularly. @@ -2421,18 +2392,19 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData * // for "/full/path/to/foo.cpp". In this case, using the requested // instead of the acknowledged name makes sense as it will allow setting // the marker in more cases. - if (data->fileName.endsWith(full)) - full = data->fileName; - data->setMarkerLineNumber(data->bpLineNumber); - if (data->markerFileName().isEmpty()) { - qDebug() << "111"; - data->setMarkerFileName(full); - } - data->bpFileName = full; + if (requestedFileName.endsWith(full)) + full = requestedFileName; + //response.bpCorrectedLineNumber = breakHandler()->lineNumber(); + //if (data->markerFileName().isEmpty()) { + // qDebug() << "111"; + // data->setMarkerFileName(full); + //} + response.bpFileName = full; } else { qDebug() << "COULD NOT MATCH " << re.pattern() << " AND " << output; - data->bpNumber = "<unavailable>"; + response.bpNumber = -1; // <unavailable> } + breakHandler()->setResponse(id, response); } void GdbEngine::handleBreakInfo(const GdbResponse &response) @@ -2440,13 +2412,10 @@ void GdbEngine::handleBreakInfo(const GdbResponse &response) if (response.resultClass == GdbResultDone) { // Old-style output for multiple breakpoints, presumably in a // constructor. - const int bpNumber = response.cookie.toInt(); - BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber); - if (data) { - QString str = QString::fromLocal8Bit( - response.data.findChild("consolestreamoutput").data()); - extractDataFromInfoBreak(str, data); - } + const BreakpointId id(response.cookie.toInt()); + const QString str = QString::fromLocal8Bit( + response.data.findChild("consolestreamoutput").data()); + extractDataFromInfoBreak(str, id); } } @@ -2456,20 +2425,34 @@ void GdbEngine::handleInfoLine(const GdbResponse &response) // Old-style output: "Line 1102 of \"simple/app.cpp\" starts // at address 0x80526aa <_Z10...+131> and ends at 0x80526b5 // <_Z10testQStackv+142>.\n" - const int bpNumber = response.cookie.toInt(); - BreakpointData *data = breakHandler()->findBreakpointByNumber(bpNumber); - if (!data) - return; QByteArray ba = response.data.findChild("consolestreamoutput").data(); const int pos = ba.indexOf(' ', 5); if (ba.startsWith("Line ") && pos != -1) { const int line = ba.mid(5, pos - 5).toInt(); - data->bpCorrectedLineNumber = line; - data->setMarkerLineNumber(line); + const BreakpointId id = response.cookie.toInt(); + BreakpointResponse br = breakHandler()->response(id); + br.bpLineNumber = line; + breakHandler()->setResponse(id, br); } } } + +bool GdbEngine::stateAcceptsBreakpointChanges() const +{ + switch (state()) { + case InferiorSetupRequested: + case InferiorRunRequested: + case InferiorRunOk: + case InferiorStopRequested: + case InferiorStopOk: + return true; + default: + return false; + } +} + +/* void GdbEngine::attemptBreakpointSynchronization() { QTC_ASSERT(!m_sourcesListUpdating, @@ -2518,19 +2501,6 @@ void GdbEngine::attemptBreakpointSynchronization() } } - foreach (BreakpointData *data, handler->takeRemovedBreakpoints()) { - QByteArray bpNumber = data->bpNumber; - if (!bpNumber.trimmed().isEmpty()) { - showMessage(_("DELETING BP " + bpNumber + " IN " - + data->markerFileName().toLocal8Bit())); - postCommand("-break-delete " + bpNumber, - NeedsStop | RebuildBreakpointModel); - } else { - showMessage(_("QUIETLY REMOVING UNNUMBERED BREAKPOINT")); - } - delete data; - } - for (int index = 0; index != handler->size(); ++index) { BreakpointData *data = handler->at(index); if (data->bpNumber.isEmpty()) { // Unset breakpoint? @@ -2540,14 +2510,14 @@ void GdbEngine::attemptBreakpointSynchronization() if (data->bpMultiple && data->bpFileName.isEmpty()) { postCommand("info break " + data->bpNumber, NeedsStop | RebuildBreakpointModel, - CB(handleBreakInfo), data->bpNumber.toInt()); + CB(handleBreakInfo), id); continue; } if (data->condition != data->bpCondition && !data->conditionsMatch()) { // Update conditions if needed. postCommand("condition " + data->bpNumber + ' ' + data->condition, NeedsStop | RebuildBreakpointModel, - CB(handleBreakCondition), data->bpNumber.toInt()); + CB(handleBreakCondition), id); } else // Because gdb won't do both changes at a time anyway. if (data->ignoreCount != data->bpIgnoreCount) { @@ -2555,13 +2525,13 @@ void GdbEngine::attemptBreakpointSynchronization() QByteArray ic = QByteArray::number(data->ignoreCount); postCommand("ignore " + data->bpNumber + ' ' + ic, NeedsStop | RebuildBreakpointModel, - CB(handleBreakIgnore), data->bpNumber.toInt()); + CB(handleBreakIgnore), id); continue; } if (!data->enabled && data->bpEnabled) { postCommand("-break-disable " + data->bpNumber, NeedsStop | RebuildBreakpointModel, - CB(handleBreakDisable), data->bpNumber.toInt()); + CB(handleBreakDisable), id); data->bpEnabled = false; continue; } @@ -2577,11 +2547,11 @@ void GdbEngine::attemptBreakpointSynchronization() if (data->bpAddress && data->bpCorrectedLineNumber == 0) { // Prevent endless loop. data->bpCorrectedLineNumber = -1; - if (theDebuggerBoolSetting(AdjustBreakpointLocations)) { + if (debuggerCore()->boolSetting(AdjustBreakpointLocations)) { postCommand( "info line *0x" + QByteArray::number(data->bpAddress, 16), NeedsStop | RebuildBreakpointModel, - CB(handleInfoLine), data->bpNumber.toInt()); + CB(handleInfoLine), id) } } } @@ -2589,10 +2559,71 @@ void GdbEngine::attemptBreakpointSynchronization() handler->updateMarkers(); } +*/ + -bool GdbEngine::acceptsBreakpoint(const Internal::BreakpointData *br) +bool GdbEngine::acceptsBreakpoint(BreakpointId id) const { - return !( br->fileName.endsWith(QLatin1String("js")) || br->fileName.endsWith(QLatin1String("qml")) ); + const QString fileName = breakHandler()->fileName(id); + return !fileName.endsWith(QLatin1String("js")) + && !fileName.endsWith(QLatin1String("qml")); +} + +void GdbEngine::insertBreakpoint(BreakpointId id) +{ + // Set up fallback in case of pending breakpoints which aren't handled + // by the MI interface. + BreakHandler *handler = breakHandler(); + QTC_ASSERT(handler->state(id) == BreakpointInsertRequested, /**/); + handler->setState(id, BreakpointInsertProceeding); + if (handler->type(id) == Watchpoint) { + postCommand("watch " + addressSpec(handler->address(id)), + NeedsStop | RebuildBreakpointModel, + CB(handleWatchInsert), id); + return; + } + + QByteArray cmd; + if (m_isMacGdb) { + cmd = "-break-insert -l -1 -f "; + } else if (m_gdbAdapter->isTrkAdapter()) { + cmd = "-break-insert -h -f "; + } else if (m_gdbVersion >= 70000) { + QByteArray spec = handler->threadSpec(id); + cmd = "-break-insert "; + if (!spec.isEmpty()) + cmd += "-p " + spec; + cmd += " -f "; + } else if (m_gdbVersion >= 60800) { + // Probably some earlier version would work as well. + cmd = "-break-insert -f "; + } else { + cmd = "-break-insert "; + } + //if (!data->condition.isEmpty()) + // cmd += "-c " + data->condition + ' '; + cmd += breakpointLocation(id); + postCommand(cmd, NeedsStop | RebuildBreakpointModel, + CB(handleBreakInsert1), id); +} + +void GdbEngine::changeBreakpoint(BreakpointId) +{ + QTC_ASSERT(false, return); +} + +void GdbEngine::removeBreakpoint(BreakpointId id) +{ + BreakHandler *handler = breakHandler(); + QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/); + handler->setState(id, BreakpointRemoveProceeding); + BreakpointResponse br = handler->response(id); + showMessage(_("DELETING BP %1 IN ").arg(br.bpNumber) + + handler->markerFileName(id)); + postCommand("-break-delete " + QByteArray::number(br.bpNumber), + NeedsStop | RebuildBreakpointModel); + // Pretend it succeeds without waiting for response. Feels better. + handler->notifyBreakpointRemoveOk(id); } @@ -2806,7 +2837,7 @@ void GdbEngine::reloadStack(bool forceGotoLocation) { PENDING_DEBUG("RELOAD STACK"); QByteArray cmd = "-stack-list-frames"; - int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt(); + int stackDepth = debuggerCore()->action(MaximalStackDepth)->value().toInt(); if (stackDepth && !m_gdbAdapter->isTrkAdapter()) cmd += " 0 " + QByteArray::number(stackDepth); // FIXME: gdb 6.4 symbianelf likes to be asked twice. The first time it @@ -2891,8 +2922,8 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response) } bool canExpand = !cookie.isFull - && (n >= theDebuggerAction(MaximalStackDepth)->value().toInt()); - theDebuggerAction(ExpandStack)->setEnabled(canExpand); + && (n >= debuggerCore()->action(MaximalStackDepth)->value().toInt()); + debuggerCore()->action(ExpandStack)->setEnabled(canExpand); stackHandler()->setFrames(stackFrames, canExpand); // We can't jump to any file if we don't have any frames. @@ -2904,7 +2935,7 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response) // a few exceptions: // Always jump to frame #0 when stepping by instruction. - if (theDebuggerBoolSetting(OperateByInstruction)) + if (debuggerCore()->boolSetting(OperateByInstruction)) targetFrame = 0; // If there is no frame with source, jump to frame #0. @@ -2967,7 +2998,7 @@ void GdbEngine::handleThreadInfo(const GdbResponse &response) updateViews(); // Adjust Threads combobox. if (m_hasInferiorThreadList) { postCommand("threadnames " + - theDebuggerAction(MaximalStackDepth)->value().toByteArray(), + debuggerCore()->action(MaximalStackDepth)->value().toByteArray(), CB(handleThreadNames), id); } } else { @@ -3192,7 +3223,7 @@ bool GdbEngine::showToolTip() { QByteArray iname = tooltipIName(m_toolTipExpression); - if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)) { + if (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)) { watchHandler()->removeData(iname); return true; } @@ -3217,7 +3248,7 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos, return; } - if (theDebuggerBoolSetting(DebugDebuggingHelpers)) { + if (debuggerCore()->boolSetting(DebugDebuggingHelpers)) { // minimize interference return; } @@ -3335,7 +3366,7 @@ void GdbEngine::reloadLocals() bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const { - if (!theDebuggerBoolSetting(UseDebuggingHelpers)) + if (!debuggerCore()->boolSetting(UseDebuggingHelpers)) return false; if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) { @@ -3344,7 +3375,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const || type == "QStringList" || type.endsWith("::QStringList"); } - if (theDebuggerBoolSetting(DebugDebuggingHelpers) + if (debuggerCore()->boolSetting(DebugDebuggingHelpers) && stackHandler()->isDebuggingDebuggingHelpers()) return false; @@ -3442,7 +3473,7 @@ void GdbEngine::rebuildWatchModel() if (!isSynchronous()) m_processedNames.clear(); PENDING_DEBUG("REBUILDING MODEL" << count); - if (theDebuggerBoolSetting(LogTimeStamps)) + if (debuggerCore()->boolSetting(LogTimeStamps)) showMessage(LogWindow::logTimeStamp(), LogMiscInput); showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput); showStatusMessage(tr("Finished retrieving data"), 400); @@ -3629,7 +3660,8 @@ void GdbEngine::insertData(const WatchData &data0) watchHandler()->insertData(data); } -void GdbEngine::assignValueInDebugger(const Internal::WatchData *, const QString &expression, const QVariant &value) +void GdbEngine::assignValueInDebugger(const WatchData *, + const QString &expression, const QVariant &value) { postCommand("-var-delete assign"); postCommand("-var-create assign * " + expression.toLatin1()); @@ -4008,7 +4040,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); if (m_gdb.isEmpty() && startParameters().startMode != StartRemoteGdb) - m_gdb = gdbBinaryForToolChain(startParameters().toolChainType); + m_gdb = debuggerCore()->gdbBinaryForToolChain(startParameters().toolChainType); if (m_gdb.isEmpty()) m_gdb = gdb; if (m_gdb.isEmpty()) { @@ -4149,7 +4181,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr loadPythonDumpers(); } - QString scriptFileName = theDebuggerStringSetting(GdbScriptFile); + QString scriptFileName = debuggerCore()->stringSetting(GdbScriptFile); if (!scriptFileName.isEmpty()) { if (QFileInfo(scriptFileName).isReadable()) { postCommand("source " + scriptFileName.toLocal8Bit()); @@ -4397,16 +4429,6 @@ void GdbEngine::removeTooltip() // Factory // -bool checkGdbConfiguration(int toolChain, QString *errorMessage, QString *settingsPage) -{ - if (gdbBinaryForToolChain(toolChain).isEmpty()) { - *errorMessage = msgNoBinaryForToolChain(toolChain); - *settingsPage = GdbOptionsPage::settingsId(); - return false; - } - return true; -} - DebuggerEngine *createGdbEngine(const DebuggerStartParameters &startParameters) { return new GdbEngine(startParameters); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 396693ee8bcb832a0a167bb81135d89e924efc94..ce932356a2f766daab184ad011cad15a8c8df1d1 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -305,25 +305,29 @@ private: ////////// Gdb Output, State & Capability Handling ////////// private: ////////// Inferior Management ////////// // This should be always the last call in a function. - Q_SLOT virtual void attemptBreakpointSynchronization(); - bool acceptsBreakpoint(const Internal::BreakpointData *br); - - virtual void executeStep(); - virtual void executeStepOut(); - virtual void executeNext(); - virtual void executeStepI(); - virtual void executeNextI(); + //Q_SLOT virtual void attemptBreakpointSynchronization(); + bool stateAcceptsBreakpointChanges() const; + bool acceptsBreakpoint(BreakpointId id) const; + void insertBreakpoint(BreakpointId id); + void removeBreakpoint(BreakpointId id); + void changeBreakpoint(BreakpointId id); + + void executeStep(); + void executeStepOut(); + void executeNext(); + void executeStepI(); + void executeNextI(); void continueInferiorInternal(); void autoContinueInferior(); - virtual void continueInferior(); - virtual void interruptInferior(); + void continueInferior(); + void interruptInferior(); void interruptInferiorTemporarily(); - virtual void executeRunToLine(const QString &fileName, int lineNumber); - virtual void executeRunToFunction(const QString &functionName); - virtual void executeJumpToLine(const QString &fileName, int lineNumber); - virtual void executeReturn(); + void executeRunToLine(const QString &fileName, int lineNumber); + void executeRunToFunction(const QString &functionName); + void executeJumpToLine(const QString &fileName, int lineNumber); + void executeReturn(); void handleExecuteContinue(const GdbResponse &response); void handleExecuteStep(const GdbResponse &response); @@ -340,8 +344,8 @@ private: ////////// Inferior Management ////////// private: ////////// View & Data Stuff ////////// - virtual void selectThread(int index); - virtual void activateFrame(int index); + void selectThread(int index); + void activateFrame(int index); // // Breakpoint specific stuff @@ -356,21 +360,20 @@ private: ////////// View & Data Stuff ////////// void handleBreakInfo(const GdbResponse &response); void handleWatchInsert(const GdbResponse &response); void handleInfoLine(const GdbResponse &response); - void extractDataFromInfoBreak(const QString &output, BreakpointData *data); - void setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt); - QByteArray breakpointLocation(const BreakpointData *data); - void sendInsertBreakpoint(int index); + void extractDataFromInfoBreak(const QString &output, BreakpointId); + void setBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt); + QByteArray breakpointLocation(BreakpointId id); QString breakLocation(const QString &file) const; void reloadBreakListInternal(); // // Modules specific stuff // - virtual void loadSymbols(const QString &moduleName); - virtual void loadAllSymbols(); - virtual void requestModuleSymbols(const QString &moduleName); - virtual void reloadModules(); - virtual void examineModules(); + void loadSymbols(const QString &moduleName); + void loadAllSymbols(); + void requestModuleSymbols(const QString &moduleName); + void reloadModules(); + void examineModules(); void reloadModulesInternal(); void handleModulesList(const GdbResponse &response); @@ -385,15 +388,15 @@ private: ////////// View & Data Stuff ////////// // // Register specific stuff // - Q_SLOT virtual void reloadRegisters(); - virtual void setRegisterValue(int nr, const QString &value); + Q_SLOT void reloadRegisters(); + void setRegisterValue(int nr, const QString &value); void handleRegisterListNames(const GdbResponse &response); void handleRegisterListValues(const GdbResponse &response); // // Disassembler specific stuff // - virtual void fetchDisassembler(DisassemblerViewAgent *agent); + void fetchDisassembler(DisassemblerViewAgent *agent); void fetchDisassemblerByAddress(const DisassemblerAgentCookie &ac, bool useMixedMode); void fetchDisassemblerByCli(const DisassemblerAgentCookie &ac, @@ -408,7 +411,7 @@ private: ////////// View & Data Stuff ////////// // // Source file specific stuff // - virtual void reloadSourceFiles(); + void reloadSourceFiles(); void reloadSourceFilesInternal(); void handleQuerySources(const GdbResponse &response); diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 62b1db19c43af1679d1b32b559ca43c22f9596d6..5e831edb9797cd6951649f9440c6d7a345c75105 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -29,15 +29,115 @@ #include "gdboptionspage.h" #include "debuggeractions.h" -#include "debuggerconstants.h" +#include "debuggercore.h" #include <coreplugin/icore.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchaintype.h> + #include <QtCore/QCoreApplication> #include <QtCore/QTextStream> +#include <QtCore/QFileInfo> namespace Debugger { namespace Internal { +const char gdbBinariesSettingsGroupC[] = "GdbBinaries"; +const char debugModeGdbBinaryKeyC[] = "GdbBinary"; + +GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::gdbBinaryToolChainMap; +bool GdbOptionsPage::gdbBinariesChanged = true; + +void GdbOptionsPage::readGdbBinarySettings() /* static */ +{ + using namespace ProjectExplorer; + QSettings *settings = Core::ICore::instance()->settings(); + // Convert gdb binaries from flat settings list (see writeSettings) + // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). + gdbBinaryToolChainMap.clear(); + const QChar separator = QLatin1Char(','); + const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') + + QLatin1String(debugModeGdbBinaryKeyC); + for (int i = 1; ; i++) { + const QString value = settings->value(keyRoot + QString::number(i)).toString(); + if (value.isEmpty()) + break; + // Split apart comma-separated binary and its numerical toolchains. + QStringList tokens = value.split(separator); + if (tokens.size() < 2) + break; + const QString binary = tokens.front(); + // Skip non-existent absolute binaries allowing for upgrades by the installer. + // Force a rewrite of the settings file. + const QFileInfo binaryInfo(binary); + if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) { + gdbBinariesChanged = true; + const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary); + qWarning("%s", qPrintable(msg)); + continue; + } + // Create entries for all toolchains. + tokens.pop_front(); + foreach (const QString &t, tokens) { + // Paranoia: Check if the there is already a binary configured for the toolchain. + const int toolChain = t.toInt(); + const QString predefinedGdb = gdbBinaryToolChainMap.key(toolChain); + if (predefinedGdb.isEmpty()) { + gdbBinaryToolChainMap.insert(binary, toolChain); + } else { + const QString toolChainName = + ProjectExplorer::ToolChain::toolChainName(ToolChainType(toolChain)); + const QString msg = + QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n" + "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it."). + arg(settings->fileName(), binary, toolChainName, predefinedGdb); + qWarning("%s", qPrintable(msg)); + } + } + } + // Linux defaults +#ifdef Q_OS_UNIX + if (gdbBinaryToolChainMap.isEmpty()) { + const QString gdb = QLatin1String("gdb"); + gdbBinaryToolChainMap.insert(gdb, ToolChain_GCC); + gdbBinaryToolChainMap.insert(gdb, ToolChain_LINUX_ICC); + gdbBinaryToolChainMap.insert(gdb, ToolChain_OTHER); + gdbBinaryToolChainMap.insert(gdb, ToolChain_UNKNOWN); + } +#endif +} + +void GdbOptionsPage::writeGdbBinarySettings() /* static */ +{ + QSettings *settings = Core::ICore::instance()->settings(); + // Convert gdb binaries map into a flat settings list of + // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers + QString lastBinary; + QStringList settingsList; + const QChar separator = QLatin1Char(','); + const GdbBinaryToolChainMap::const_iterator cend = gdbBinaryToolChainMap.constEnd(); + for (GdbBinaryToolChainMap::const_iterator it = gdbBinaryToolChainMap.constBegin(); it != cend; ++it) { + if (it.key() != lastBinary) { + lastBinary = it.key(); // Start new entry with first toolchain + settingsList.push_back(lastBinary); + } + settingsList.back().append(separator); // Append toolchain to last binary + settingsList.back().append(QString::number(it.value())); + } + // Terminate settings list by an empty element such that consecutive keys resulting + // from ini-file merging are suppressed while reading. + settingsList.push_back(QString()); + // Write out list + settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC)); + settings->remove(QString()); // remove all keys in group. + const int count = settingsList.size(); + const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC); + for (int i = 0; i < count; i++) + settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i)); + settings->endGroup(); +} + GdbOptionsPage::GdbOptionsPage() { } @@ -71,44 +171,43 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) { QWidget *w = new QWidget(parent); m_ui.setupUi(w); - m_ui.gdbChooserWidget - ->setGdbBinaries(DebuggerSettings::instance()->gdbBinaryToolChainMap()); + m_ui.gdbChooserWidget->setGdbBinaries(gdbBinaryToolChainMap); m_ui.scriptFileChooser->setExpectedKind(Utils::PathChooser::File); m_ui.scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File")); m_group.clear(); - m_group.insert(theDebuggerAction(GdbScriptFile), + m_group.insert(debuggerCore()->action(GdbScriptFile), m_ui.scriptFileChooser); - m_group.insert(theDebuggerAction(GdbEnvironment), + m_group.insert(debuggerCore()->action(GdbEnvironment), m_ui.environmentEdit); - m_group.insert(theDebuggerAction(AdjustBreakpointLocations), + m_group.insert(debuggerCore()->action(AdjustBreakpointLocations), m_ui.checkBoxAdjustBreakpointLocations); - m_group.insert(theDebuggerAction(GdbWatchdogTimeout), + m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), m_ui.spinBoxGdbWatchdogTimeout); - m_group.insert(theDebuggerAction(UseMessageBoxForSignals), + m_group.insert(debuggerCore()->action(UseMessageBoxForSignals), m_ui.checkBoxUseMessageBoxForSignals); - m_group.insert(theDebuggerAction(SkipKnownFrames), + m_group.insert(debuggerCore()->action(SkipKnownFrames), m_ui.checkBoxSkipKnownFrames); - m_group.insert(theDebuggerAction(EnableReverseDebugging), + m_group.insert(debuggerCore()->action(EnableReverseDebugging), m_ui.checkBoxEnableReverseDebugging); - m_group.insert(theDebuggerAction(GdbWatchdogTimeout), 0); + m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), 0); #if 1 m_ui.groupBoxPluginDebugging->hide(); #else // The related code (handleAqcuiredInferior()) is disabled as well. - m_group.insert(theDebuggerAction(AllPluginBreakpoints), + m_group.insert(debuggerCore()->action(AllPluginBreakpoints), m_ui.radioButtonAllPluginBreakpoints); - m_group.insert(theDebuggerAction(SelectedPluginBreakpoints), + m_group.insert(debuggerCore()->action(SelectedPluginBreakpoints), m_ui.radioButtonSelectedPluginBreakpoints); - m_group.insert(theDebuggerAction(NoPluginBreakpoints), + m_group.insert(debuggerCore()->action(NoPluginBreakpoints), m_ui.radioButtonNoPluginBreakpoints); - m_group.insert(theDebuggerAction(SelectedPluginBreakpointsPattern), + m_group.insert(debuggerCore()->action(SelectedPluginBreakpointsPattern), m_ui.lineEditSelectedPluginBreakpointsPattern); #endif m_ui.lineEditSelectedPluginBreakpointsPattern-> - setEnabled(theDebuggerAction(SelectedPluginBreakpoints)->value().toBool()); + setEnabled(debuggerCore()->action(SelectedPluginBreakpoints)->value().toBool()); connect(m_ui.radioButtonSelectedPluginBreakpoints, SIGNAL(toggled(bool)), m_ui.lineEditSelectedPluginBreakpointsPattern, SLOT(setEnabled(bool))); @@ -128,13 +227,14 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) } return w; } + void GdbOptionsPage::apply() { m_group.apply(Core::ICore::instance()->settings()); if (m_ui.gdbChooserWidget->isDirty()) { - DebuggerSettings::instance() - ->setGdbBinaryToolChainMap(m_ui.gdbChooserWidget->gdbBinaries()); + gdbBinariesChanged = true; + gdbBinaryToolChainMap = m_ui.gdbChooserWidget->gdbBinaries(); m_ui.gdbChooserWidget->clearDirty(); } } diff --git a/src/plugins/debugger/gdb/gdboptionspage.h b/src/plugins/debugger/gdb/gdboptionspage.h index 7cd7ad8b2ec52efe0977a021d7cd1837d2bf3055..445dac36e58c8da6c7da2fa3a01695d3c1bda379 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.h +++ b/src/plugins/debugger/gdb/gdboptionspage.h @@ -57,6 +57,12 @@ public: static QString settingsId(); + typedef QMultiMap<QString, int> GdbBinaryToolChainMap; + static GdbBinaryToolChainMap gdbBinaryToolChainMap; + static bool gdbBinariesChanged; + static void readGdbBinarySettings(); + static void writeGdbBinarySettings(); + private: Ui::GdbOptionsPage m_ui; Utils::SavedActionSet m_group; diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp index f0483c6c6b8baa01fbe5d5458754bf4de3809f9d..89a8d549abf08a87ed89c84917c093cf8fc33521 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp @@ -31,6 +31,7 @@ #include "gdbengine.h" #include "procinterrupt.h" +#include "debuggercore.h" #include "debuggerstringutils.h" #include <utils/qtcassert.h> @@ -140,7 +141,7 @@ void LocalPlainGdbAdapter::checkForReleaseBuild() // "30 .debug_info 00087d36 00000000 00000000 0006bbd5 2**0\n" // " CONTENTS, READONLY, DEBUGGING" if (ba.contains("Sections:") && !ba.contains(".debug_info")) { - m_engine->showMessageBox(QMessageBox::Information, "Warning", + showMessageBox(QMessageBox::Information, "Warning", tr("This does not seem to be a \"Debug\" build.\n" "Setting breakpoints by file name and line number may fail.")); } diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 7a3ece861724307fb0b4ecbe1d8b6c18f753ab75..aa21cd979a17d66a96aae26108727945a02875de 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -31,6 +31,7 @@ #include "gdbmi.h" #include "abstractgdbadapter.h" #include "debuggeractions.h" +#include "debuggercore.h" #include "debuggerstringutils.h" #include "breakhandler.h" @@ -75,9 +76,9 @@ void GdbEngine::updateLocalsPython(bool tryPartial, const QByteArray &varList) } QByteArray options; - if (theDebuggerBoolSetting(UseDebuggingHelpers)) + if (debuggerCore()->boolSetting(UseDebuggingHelpers)) options += "fancy,"; - if (theDebuggerBoolSetting(AutoDerefPointers)) + if (debuggerCore()->boolSetting(AutoDerefPointers)) options += "autoderef,"; if (!qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty()) options += "pe,"; diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index dfa9e356e50a7b8416f82515587aa5cfaf20a7eb..006dbb2ab72187f2644184d64e5e03da998d198c 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -28,9 +28,11 @@ **************************************************************************/ #include "remotegdbserveradapter.h" -#include "gdbmi.h" + +#include "debuggercore.h" #include "debuggerstringutils.h" #include "gdbengine.h" +#include "gdbmi.h" #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> @@ -132,7 +134,7 @@ void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error) } showMessage(msg, StatusBar); - DebuggerEngine::showMessageBox(QMessageBox::Critical, tr("Error"), msg); + showMessageBox(QMessageBox::Critical, tr("Error"), msg); } void RemoteGdbServerAdapter::readUploadStandardOutput() diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp index a6e6899fa4e2dabe18330e4db282aa063e608f58..cf2b8c30074c0ed82ca339787617ae8a9f7d6bec 100644 --- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp @@ -34,6 +34,7 @@ #include "registerhandler.h" #include "threadshandler.h" +#include "debuggercore.h" #include "debuggeractions.h" #include "debuggerstringutils.h" #include "watchutils.h" @@ -135,9 +136,9 @@ TcfTrkGdbAdapter::TcfTrkGdbAdapter(GdbEngine *engine) : #endif m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset); - setVerbose(theDebuggerBoolSetting(VerboseLog) ? 1 : 0); + setVerbose(debuggerCore()->boolSetting(VerboseLog) ? 1 : 0); - connect(theDebuggerAction(VerboseLog), SIGNAL(valueChanged(QVariant)), + connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)), this, SLOT(setVerbose(QVariant))); connect(m_trkDevice, SIGNAL(error(QString)), this, SLOT(tcftrkDeviceError(QString))); diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp index f38fae20aa22c0c7d0bcd4c40739e4e9c176b1e9..1f9826d20dcdf7069cbf0ea9cdf364f7e6fe641f 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.cpp +++ b/src/plugins/debugger/gdb/termgdbadapter.cpp @@ -32,6 +32,7 @@ #include "gdbengine.h" #include "procinterrupt.h" #include "debuggerstringutils.h" +#include "debuggercore.h" #include <utils/qtcassert.h> #include <coreplugin/icore.h> @@ -199,7 +200,7 @@ void TermGdbAdapter::interruptInferior() void TermGdbAdapter::stubMessage(const QString &msg, bool) { - DebuggerEngine::showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg); + showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg); } void TermGdbAdapter::stubExited() diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp index 32f6f16fb9962370d4b3341b031ea594c454aef8..c5790f26f6de8efb8ff45bb66f660d8e43872bd6 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp @@ -38,6 +38,7 @@ #include "registerhandler.h" #include "threadshandler.h" #include "debuggeractions.h" +#include "debuggercore.h" #include "debuggerstringutils.h" #include "watchutils.h" #ifndef STANDALONE_RUNNER @@ -107,9 +108,9 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine) : #endif m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset); - setVerbose(theDebuggerBoolSetting(VerboseLog)); + setVerbose(debuggerCore()->boolSetting(VerboseLog)); - connect(theDebuggerAction(VerboseLog), SIGNAL(valueChanged(QVariant)), + connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)), this, SLOT(setVerbose(QVariant))); } diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp index 277fd26607cd133117a76d8805eb4e73673de885..f1bc78fa2e63be8333a846ed4b34c8c6371948c9 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ b/src/plugins/debugger/lldb/ipcenginehost.cpp @@ -475,7 +475,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyAddBreakpointOk(id); + notifyBreakpointInsertOk(id); } case IPCEngineGuest::NotifyAddBreakpointFailed: { @@ -483,7 +483,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyAddBreakpointFailed(id); + notifyBreakpointInsertFailed(id); } case IPCEngineGuest::NotifyRemoveBreakpointOk: { @@ -491,7 +491,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyRemoveBreakpointOk(id); + notifyBreakpointRemoveOk(id); } case IPCEngineGuest::NotifyRemoveBreakpointFailed: { @@ -499,7 +499,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyRemoveBreakpointFailed(id); + notifyBreakpointRemoveFailed(id); } case IPCEngineGuest::NotifyChangeBreakpointOk: { @@ -507,7 +507,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyChangeBreakpointOk(id); + notifyBreakpointChangeOk(id); } case IPCEngineGuest::NotifyChangeBreakpointFailed: { @@ -515,7 +515,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); quint64 id; s >> id; - notifyChangeBreakpointFailed(id); + notifyBreakpointChangeFailed(id); } case IPCEngineGuest::NotifyBreakpointAdjusted: { @@ -523,7 +523,8 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) SET_NATIVE_BYTE_ORDER(s); BreakpointData d; s >> d; - notifyBreakpointAdjusted(d); + qDebug() << "FIXME"; + //notifyBreakpointAdjusted(d); } } } diff --git a/src/plugins/debugger/logwindow.cpp b/src/plugins/debugger/logwindow.cpp index d11fad9eb71c16a58e64c0b260f1781a38f6eb3d..bdd731541a7f23ac0d9825fed04eaab9312f9ac7 100644 --- a/src/plugins/debugger/logwindow.cpp +++ b/src/plugins/debugger/logwindow.cpp @@ -30,7 +30,7 @@ #include "logwindow.h" #include "debuggeractions.h" -#include "debuggerconstants.h" +#include "debuggercore.h" #include <QtCore/QDebug> #include <QtCore/QFile> @@ -198,12 +198,12 @@ public: menu->addAction(m_clearContentsAction); menu->addAction(m_saveContentsAction); // X11 clipboard is unreliable for long texts addContextActions(menu); - theDebuggerAction(ExecuteCommand)->setData(textCursor().block().text()); - menu->addAction(theDebuggerAction(ExecuteCommand)); - menu->addAction(theDebuggerAction(LogTimeStamps)); - menu->addAction(theDebuggerAction(VerboseLog)); + debuggerCore()->action(ExecuteCommand)->setData(textCursor().block().text()); + menu->addAction(debuggerCore()->action(ExecuteCommand)); + menu->addAction(debuggerCore()->action(LogTimeStamps)); + menu->addAction(debuggerCore()->action(VerboseLog)); menu->addSeparator(); - menu->addAction(theDebuggerAction(SettingsDialog)); + menu->addAction(debuggerCore()->action(SettingsDialog)); menu->exec(ev->globalPos()); delete menu; } @@ -248,7 +248,7 @@ private: void keyPressEvent(QKeyEvent *ev) { if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return) - theDebuggerAction(ExecuteCommand)->trigger(textCursor().block().text()); + debuggerCore()->action(ExecuteCommand)->trigger(textCursor().block().text()); else if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_R) emit clearContentsRequested(); else @@ -276,7 +276,7 @@ private: void addContextActions(QMenu *menu) { - menu->addAction(theDebuggerAction(ExecuteCommand)); + menu->addAction(debuggerCore()->action(ExecuteCommand)); } void focusInEvent(QFocusEvent *ev) @@ -393,7 +393,7 @@ void LogWindow::showOutput(int channel, const QString &output) cursor.movePosition(QTextCursor::End); bool atEnd = oldCursor.position() == cursor.position(); - if (theDebuggerBoolSetting(LogTimeStamps)) + if (debuggerCore()->boolSetting(LogTimeStamps)) m_combinedText->appendPlainText(charForChannel(LogTime) + logTimeStamp()); foreach (QString line, output.split('\n')) { // FIXME: QTextEdit asserts on really long lines... @@ -415,7 +415,7 @@ void LogWindow::showOutput(int channel, const QString &output) void LogWindow::showInput(int channel, const QString &input) { Q_UNUSED(channel) - if (theDebuggerBoolSetting(LogTimeStamps)) + if (debuggerCore()->boolSetting(LogTimeStamps)) m_inputText->appendPlainText(logTimeStamp()); m_inputText->appendPlainText(input); QTextCursor cursor = m_inputText->textCursor(); diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp index e73cab44a63e0d8c58b3e3e00b645d80a283f9fc..4de85fa91ef6c2245169193227b260a813428a60 100644 --- a/src/plugins/debugger/moduleswindow.cpp +++ b/src/plugins/debugger/moduleswindow.cpp @@ -56,7 +56,7 @@ namespace Internal { ModulesWindow::ModulesWindow(QWidget *parent) : QTreeView(parent), m_alwaysResizeColumnsToContents(false) { - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setWindowTitle(tr("Modules")); setAttribute(Qt::WA_MacShowFocusRect, false); setSortingEnabled(true); @@ -146,7 +146,7 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) actAlwaysAdjustColumnWidth->setCheckable(true); actAlwaysAdjustColumnWidth->setChecked(m_alwaysResizeColumnsToContents); menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 2afdbdb429eaa152c641eae2d86ce23240d7a33e..9533c8da7ec27ae9ff53043533c9891fab316bd8 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -32,7 +32,7 @@ #include "pdbengine.h" #include "debuggeractions.h" -#include "debuggerconstants.h" +#include "debuggercore.h" #include "debuggerdialogs.h" #include "debuggerplugin.h" #include "debuggerstringutils.h" @@ -50,7 +50,6 @@ #include <texteditor/itexteditor.h> #include <coreplugin/ifile.h> -//#include <coreplugin/scriptmanager/scriptmanager.h> #include <coreplugin/icore.h> #include <QtCore/QDateTime> @@ -327,33 +326,28 @@ void PdbEngine::selectThread(int index) Q_UNUSED(index) } -static QByteArray breakpointLocation(const BreakpointData *data) -{ - if (!data->funcName.isEmpty()) - return data->funcName.toLatin1(); - // In this case, data->funcName is something like '*0xdeadbeef' - if (data->lineNumber == 0) - return data->funcName.toLatin1(); - //QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName); - // The argument is simply a C-quoted version of the argument to the - // non-MI "break" command, including the "original" quoting it wants. - //return "\"\\\"" + GdbMi::escapeCString(data->fileName).toLocal8Bit() + "\\\":" - // + data->lineNumber + '"'; - return data->fileName.toLocal8Bit() + ':' + QByteArray::number(data->lineNumber); -} - void PdbEngine::attemptBreakpointSynchronization() { BreakHandler *handler = breakHandler(); //qDebug() << "ATTEMPT BP SYNC"; bool updateNeeded = false; - for (int index = 0; index != handler->size(); ++index) { - BreakpointData *data = handler->at(index); - if (data->pending) { - data->pending = false; // FIXME + foreach (BreakpointId id, handler->engineBreakpointIds(this)) { + if (handler->state(id) == BreakpointInsertRequested) { + handler->setState(id, BreakpointInserted); // FIXME updateNeeded = true; - QByteArray loc = breakpointLocation(data); - postCommand("break " + loc, CB(handleBreakInsert), QVariant(index)); + + QByteArray loc; + if (!handler->functionName(id).isEmpty()) + loc = handler->functionName(id).toLatin1(); + // The argument is simply a C-quoted version of the argument to the + // non-MI "break" command, including the "original" quoting it wants. + //return "\"\\\"" + GdbMi::escapeCString(data->fileName).toLocal8Bit() + // + "\\\":" + data->lineNumber + '"'; + else + loc = handler->fileName(id).toLocal8Bit() + ':' + + QByteArray::number(handler->lineNumber(id)); + + postCommand("break " + loc, CB(handleBreakInsert), QVariant(id)); } /* if (data->bpNumber.isEmpty()) { @@ -375,10 +369,8 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response) { //qDebug() << "BP RESPONSE: " << response.data; // "Breakpoint 1 at /pdb/math.py:10" - int index = response.cookie.toInt(); + BreakpointId id(response.cookie.toInt()); BreakHandler *handler = breakHandler(); - BreakpointData *data = handler->at(index); - QTC_ASSERT(data, return); QTC_ASSERT(response.data.startsWith("Breakpoint "), return); int pos1 = response.data.indexOf(" at "); QTC_ASSERT(pos1 != -1, return); @@ -386,10 +378,11 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response) int pos2 = response.data.lastIndexOf(":"); QByteArray file = response.data.mid(pos1 + 4, pos2 - pos1 - 4); QByteArray line = response.data.mid(pos2 + 1); - data->bpNumber = bpnr; - data->bpFileName = _(file); - data->bpLineNumber = line.toInt(); - handler->updateMarkers(); + BreakpointResponse br; + br.bpNumber = bpnr.toInt(); + br.bpFileName = _(file); + br.bpLineNumber = line.toInt(); + handler->setResponse(id, br); } void PdbEngine::loadSymbols(const QString &moduleName) @@ -741,9 +734,9 @@ void PdbEngine::updateLocals() } QByteArray options; - if (theDebuggerBoolSetting(UseDebuggingHelpers)) + if (debuggerCore()->boolSetting(UseDebuggingHelpers)) options += "fancy,"; - if (theDebuggerBoolSetting(AutoDerefPointers)) + if (debuggerCore()->boolSetting(AutoDerefPointers)) options += "autoderef,"; if (options.isEmpty()) options += "defaults,"; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 8cd04b7557451c44c082d2e3d9d6e272c1e95a49..74c788a4c41e848aa2681b721f89c7af24731569 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -238,10 +238,10 @@ void QmlCppEngine::attemptBreakpointSynchronization() static_cast<DebuggerEngine*>(d->m_qmlEngine)->attemptBreakpointSynchronization(); } -bool QmlCppEngine::acceptsBreakpoint(const Internal::BreakpointData *br) +bool QmlCppEngine::acceptsBreakpoint(BreakpointId id) { - return d->m_cppEngine->acceptsBreakpoint(br) - || d->m_qmlEngine->acceptsBreakpoint(br); + return d->m_cppEngine->acceptsBreakpoint(id) + || d->m_qmlEngine->acceptsBreakpoint(id); } void QmlCppEngine::selectThread(int index) diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index a79593b119e647a6368447a8974788d70404f5df..9bb063adde8157f614cf1f9d5f0f7421b3457157 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -53,7 +53,7 @@ public: virtual void updateAll(); virtual void attemptBreakpointSynchronization(); - virtual bool acceptsBreakpoint(const Internal::BreakpointData *br); + virtual bool acceptsBreakpoint(BreakpointId id); virtual void selectThread(int index); virtual void assignValueInDebugger(const Internal::WatchData *w, diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index b41b0a5f040d1b564e0e4ce906e5a4c3f7a0a280..2082ca77845e3850135f8ee37134281a22d3821e 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -31,12 +31,13 @@ #include "qmladapter.h" #include "debuggeractions.h" -#include "debuggertooltip.h" #include "debuggerconstants.h" +#include "debuggercore.h" #include "debuggerdialogs.h" +#include "debuggerrunner.h" #include "debuggerstringutils.h" +#include "debuggertooltip.h" #include "debuggeruiswitcher.h" -#include "debuggerrunner.h" #include "breakhandler.h" #include "moduleshandler.h" @@ -142,6 +143,8 @@ static QDataStream &operator>>(QDataStream &s, StackFrame &frame) } // namespace Internal +using namespace Internal; + struct QmlEnginePrivate { explicit QmlEnginePrivate(QmlEngine *q); @@ -199,9 +202,9 @@ void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMa DebuggerEngine::gotoLocation(processedFilename, lineNumber, setMarker); } -void QmlEngine::gotoLocation(const Internal::StackFrame &frame, bool setMarker) +void QmlEngine::gotoLocation(const StackFrame &frame, bool setMarker) { - Internal::StackFrame adjustedFrame = frame; + StackFrame adjustedFrame = frame; if (isShadowBuildProject()) adjustedFrame.file = fromShadowBuildFilename(frame.file); @@ -478,14 +481,11 @@ void QmlEngine::executeJumpToLine(const QString &fileName, int lineNumber) void QmlEngine::activateFrame(int index) { - Q_UNUSED(index) - QByteArray reply; QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("ACTIVATE_FRAME"); rs << index; sendMessage(reply); - gotoLocation(stackHandler()->frames().value(index), true); } @@ -496,18 +496,17 @@ void QmlEngine::selectThread(int index) void QmlEngine::attemptBreakpointSynchronization() { - Internal::BreakHandler *handler = breakHandler(); + BreakHandler *handler = breakHandler(); //bool updateNeeded = false; - Internal::JSAgentBreakpoints breakpoints; - for (int index = 0; index != handler->size(); ++index) { - Internal::BreakpointData *data = handler->at(index); - QString processedFilename = data->fileName; + JSAgentBreakpoints breakpoints; + foreach (BreakpointId id, handler->engineBreakpointIds(this)) { + QString processedFilename = handler->fileName(id); if (isShadowBuildProject()) - processedFilename = toShadowBuildFilename(data->fileName); - Internal::JSAgentBreakpointData bp; + processedFilename = toShadowBuildFilename(handler->fileName(id)); + JSAgentBreakpointData bp; bp.fileName = processedFilename.toUtf8(); - bp.lineNumber = data->lineNumber; - bp.functionName = data->funcName.toUtf8(); + bp.lineNumber = handler->lineNumber(id); + bp.functionName = handler->functionName(id).toUtf8(); breakpoints.insert(bp); } @@ -519,10 +518,11 @@ void QmlEngine::attemptBreakpointSynchronization() sendMessage(reply); } -bool QmlEngine::acceptsBreakpoint(const Internal::BreakpointData *br) +bool QmlEngine::acceptsBreakpoint(BreakpointId id) { - return br->fileName.endsWith(QLatin1String(".qml")) - || br->fileName.endsWith(QLatin1String(".js")); + const QString fileName = breakHandler()->fileName(id); + return fileName.endsWith(QLatin1String(".qml")) + || fileName.endsWith(QLatin1String(".js")); } void QmlEngine::loadSymbols(const QString &moduleName) @@ -563,7 +563,7 @@ void QmlEngine::setToolTipExpression(const QPoint &mousePos, // ////////////////////////////////////////////////////////////////////// -void QmlEngine::assignValueInDebugger(const Internal::WatchData *, +void QmlEngine::assignValueInDebugger(const WatchData *, const QString &expression, const QVariant &valueV) { QRegExp inObject("@([0-9a-fA-F]+)->(.+)"); @@ -581,8 +581,8 @@ void QmlEngine::assignValueInDebugger(const Internal::WatchData *, } } -void QmlEngine::updateWatchData(const Internal::WatchData &data, - const Internal::WatchUpdateFlags &) +void QmlEngine::updateWatchData(const WatchData &data, + const WatchUpdateFlags &) { // qDebug() << "UPDATE WATCH DATA" << data.toString(); //watchHandler()->rebuildModel(); @@ -661,15 +661,15 @@ void QmlEngine::messageReceived(const QByteArray &message) stream >> command; showMessage(QLatin1String("RECEIVED RESPONSE: ") - + Internal::quoteUnprintableLatin1(message)); + + quoteUnprintableLatin1(message)); if (command == "STOPPED") { if (state() == InferiorRunOk) notifyInferiorSpontaneousStop(); - Internal::StackFrames stackFrames; - QList<Internal::WatchData> watches; - QList<Internal::WatchData> locals; + StackFrames stackFrames; + QList<WatchData> watches; + QList<WatchData> locals; stream >> stackFrames >> watches >> locals; for (int i = 0; i != stackFrames.size(); ++i) @@ -681,7 +681,7 @@ void QmlEngine::messageReceived(const QByteArray &message) watchHandler()->beginCycle(); bool needPing = false; - foreach (Internal::WatchData data, watches) { + foreach (WatchData data, watches) { data.iname = watchHandler()->watcherName(data.exp); watchHandler()->insertData(data); @@ -691,7 +691,7 @@ void QmlEngine::messageReceived(const QByteArray &message) } } - foreach (Internal::WatchData data, locals) { + foreach (WatchData data, locals) { data.iname = "local." + data.exp; watchHandler()->insertData(data); @@ -734,22 +734,21 @@ void QmlEngine::messageReceived(const QByteArray &message) } } - Internal::BreakHandler *handler = breakHandler(); - for (int index = 0; index != handler->size(); ++index) { - Internal::BreakpointData *data = handler->at(index); - QString processedFilename = data->fileName; - - if (processedFilename == file && data->lineNumber == line) { - data->pending = false; - data->bpFileName = file; - data->bpLineNumber = line; - data->bpFuncName = function; - handler->updateMarker(data); + BreakHandler *handler = breakHandler(); + foreach (BreakpointId id, handler->engineBreakpointIds(this)) { + QString processedFilename = handler->fileName(id); + if (processedFilename == file && handler->lineNumber(id) == line) { + handler->setState(id, BreakpointInserted); + BreakpointResponse br = handler->response(id); + br.bpFileName = file; + br.bpLineNumber = line; + br.bpFuncName = function; + handler->setResponse(id, br); } } } } else if (command == "RESULT") { - Internal::WatchData data; + WatchData data; QByteArray iname; stream >> iname >> data; data.iname = iname; @@ -761,11 +760,11 @@ void QmlEngine::messageReceived(const QByteArray &message) qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value; } } else if (command == "EXPANDED") { - QList<Internal::WatchData> result; + QList<WatchData> result; QByteArray iname; stream >> iname >> result; bool needPing = false; - foreach (Internal::WatchData data, result) { + foreach (WatchData data, result) { data.iname = iname + '.' + data.exp; watchHandler()->insertData(data); @@ -777,12 +776,12 @@ void QmlEngine::messageReceived(const QByteArray &message) if (needPing) sendPing(); } else if (command == "LOCALS") { - QList<Internal::WatchData> locals; + QList<WatchData> locals; int frameId; stream >> frameId >> locals; watchHandler()->beginCycle(); bool needPing = false; - foreach (Internal::WatchData data, locals) { + foreach (WatchData data, locals) { data.iname = "local." + data.exp; watchHandler()->insertData(data); if (watchHandler()->expandedINames().contains(data.iname)) { diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 9df910b0b9055a99ca89a99d2a2be9fc5e4194b2..3cc949d7d3225d3eeedd25b856a5e8adec6540b4 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -94,9 +94,10 @@ private: void selectThread(int index); void attemptBreakpointSynchronization(); - bool acceptsBreakpoint(const Internal::BreakpointData *br); + bool acceptsBreakpoint(BreakpointId id); - void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value); + void assignValueInDebugger(const Internal::WatchData *data, + const QString &expr, const QVariant &value); void loadSymbols(const QString &moduleName); void loadAllSymbols(); void requestModuleSymbols(const QString &moduleName); diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index 053b23719fe92aa6ec9ceadaf8239b028cff8ad3..6893dcc3433ac2318900a17bfd62f0e02e3d6c42 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -157,7 +157,7 @@ public: RegisterWindow::RegisterWindow(QWidget *parent) : QTreeView(parent), m_alwaysResizeColumnsToContents(true) { - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setFrameStyle(QFrame::NoFrame); setWindowTitle(tr("Registers")); setAttribute(Qt::WA_MacShowFocusRect, false); @@ -226,7 +226,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) actAlwaysAdjust->setChecked(m_alwaysResizeColumnsToContents); menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index b6f3ff35547501e972bc10c5fe499fbdea000310..dd70b92d4dc60df1a6a474f014ca071a5f7f4b02 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -33,6 +33,7 @@ #include "breakhandler.h" #include "debuggerconstants.h" +#include "debuggercore.h" #include "debuggerdialogs.h" #include "debuggerstringutils.h" #include "moduleshandler.h" @@ -448,6 +449,8 @@ void ScriptEngine::selectThread(int index) void ScriptEngine::attemptBreakpointSynchronization() { + QTC_ASSERT(false, /* FIXME */); +/* BreakHandler *handler = breakHandler(); bool updateNeeded = false; for (int index = 0; index != handler->size(); ++index) { @@ -468,6 +471,7 @@ void ScriptEngine::attemptBreakpointSynchronization() } if (updateNeeded) handler->updateMarkers(); +*/ } void ScriptEngine::loadSymbols(const QString &moduleName) @@ -589,31 +593,6 @@ void ScriptEngine::assignValueInDebugger(const Internal::WatchData *, updateLocals(); } -static BreakpointData *findBreakPointByFunction(BreakHandler *handler, - const QString &functionName) -{ - const int count = handler->size(); - for (int b = 0; b < count; b++) { - BreakpointData *data = handler->at(b); - if (data->funcName == functionName) - return data; - } - return 0; -} - -static BreakpointData *findBreakPointByFileName(BreakHandler *handler, - int lineNumber, - const QString &fileName) -{ - const int count = handler->size(); - for (int b = 0; b < count; b++) { - BreakpointData *data = handler->at(b); - if (lineNumber == data->lineNumber && fileName == data->fileName) - return data; - } - return 0; -} - bool ScriptEngine::checkForBreakCondition(bool byFunction) { // FIXME: Should that ever happen after setAgent(0) in shutdownInferior()? @@ -629,33 +608,30 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) const QString fileName = info.fileName(); const int lineNumber = byFunction ? info.functionStartLineNumber() : info.lineNumber(); - SDEBUG(Q_FUNC_INFO << byFunction << functionName - << lineNumber << fileName); + SDEBUG(Q_FUNC_INFO << byFunction << functionName << lineNumber << fileName); if (m_stopOnNextLine) { // Interrupt inferior m_stopOnNextLine = false; } else { if (byFunction && functionName.isEmpty()) return false; - BreakpointData *data = byFunction ? - findBreakPointByFunction(breakHandler(), functionName) : - findBreakPointByFileName(breakHandler(), lineNumber, fileName); - if (!data) - return false; + BreakHandler *handler = breakHandler(); + BreakpointId id = byFunction ? + handler->findBreakpointByFunction(functionName) : + handler->findBreakpointByFileAndLine(fileName, lineNumber, false); // Skip disabled breakpoint. - if (!data->enabled) + if (!handler->isEnabled(id)) return false; + BreakpointResponse br; // We just run into a breakpoint. //SDEBUG("RESOLVING BREAKPOINT AT " << fileName << lineNumber); - data->bpLineNumber = lineNumber; - data->bpFileName = fileName; - data->bpFuncName = functionName; - data->setMarkerLineNumber(lineNumber); - data->setMarkerFileName(fileName); - data->pending = false; - breakHandler()->updateMarker(data); + br.bpLineNumber = lineNumber; + br.bpFileName = fileName; + br.bpFuncName = functionName; + handler->setState(id, BreakpointInserted); + handler->setResponse(id, br); } notifyInferiorSpontaneousStop(); SDEBUG("Stopped at " << lineNumber << fileName); diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h index 82b6894fa78e1e0219f50ce6fa138ecf6dba2c73..d73a2e034f0277cce14b8e718d4b02cc892c3eb9 100644 --- a/src/plugins/debugger/script/scriptengine.h +++ b/src/plugins/debugger/script/scriptengine.h @@ -89,7 +89,8 @@ private: void attemptBreakpointSynchronization(); - void assignValueInDebugger(const Internal::WatchData *w, const QString &expr, const QVariant &value); + void assignValueInDebugger(const WatchData *w, + const QString &expr, const QVariant &value); void executeDebuggerCommand(const QString &command); void loadSymbols(const QString &moduleName); diff --git a/src/plugins/debugger/snapshotwindow.cpp b/src/plugins/debugger/snapshotwindow.cpp index 74b534e4e50461f63cbb4c18a853cdf279e2d2e7..97519b68e8a97dd84a5aa27ea6a6af11de8d06bf 100644 --- a/src/plugins/debugger/snapshotwindow.cpp +++ b/src/plugins/debugger/snapshotwindow.cpp @@ -31,7 +31,7 @@ #include "snapshothandler.h" #include "debuggeractions.h" -#include "debuggerconstants.h" +#include "debuggercore.h" #include "debuggerrunner.h" #include <utils/qtcassert.h> @@ -43,15 +43,6 @@ #include <QtGui/QMenu> #include <QtGui/QKeyEvent> -static QModelIndexList normalizeIndexes(const QModelIndexList &list) -{ - QModelIndexList res; - foreach (const QModelIndex &idx, list) - if (idx.column() == 0) - res.append(idx); - return res; -} - namespace Debugger { namespace Internal { @@ -67,7 +58,7 @@ SnapshotWindow::SnapshotWindow(SnapshotHandler *handler) { m_snapshotHandler = handler; - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setWindowTitle(tr("Snapshots")); setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); @@ -96,8 +87,10 @@ void SnapshotWindow::keyPressEvent(QKeyEvent *ev) QModelIndexList si = sm->selectedIndexes(); if (si.isEmpty()) si.append(currentIndex().sibling(currentIndex().row(), 0)); - foreach (const QModelIndex &idx, normalizeIndexes(si)) - removeSnapshot(idx.row()); + + foreach (const QModelIndex &idx, si) + if (idx.column() == 0) + removeSnapshot(idx.row()); } QTreeView::keyPressEvent(ev); } @@ -127,7 +120,7 @@ void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp index f7bcadf213b588af4d93ab635fa205539fbef4ac..55e075c317f96dec45b06251a7be60c0721cee04 100644 --- a/src/plugins/debugger/sourcefileswindow.cpp +++ b/src/plugins/debugger/sourcefileswindow.cpp @@ -62,7 +62,7 @@ static DebuggerEngine *currentEngine() SourceFilesWindow::SourceFilesWindow(QWidget *parent) : QTreeView(parent) { - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); @@ -108,7 +108,7 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(act1); menu.addAction(act2); menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 731523f333a81e0d74dc2111150f9e9267d136ab..a2c5df6bf182c080777f4c85f1950ebd1cfc2d86 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -31,6 +31,7 @@ #include "debuggeractions.h" #include "debuggeragents.h" +#include "debuggercore.h" #include "debuggerengine.h" #include <utils/qtcassert.h> @@ -54,7 +55,7 @@ StackHandler::StackHandler() { m_currentIndex = 0; m_canExpand = false; - connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()), + connect(debuggerCore()->action(OperateByInstruction), SIGNAL(triggered()), this, SLOT(resetModel())); } @@ -142,7 +143,7 @@ Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const return QAbstractTableModel::flags(index); const StackFrame &frame = m_stackFrames.at(index.row()); const bool isValid = (frame.isUsable() && !frame.function.isEmpty()) - || theDebuggerBoolSetting(OperateByInstruction); + || debuggerCore()->boolSetting(OperateByInstruction); return isValid ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0); } diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp index 007fe9758b240c0ddd42240f1c4170bab76fd9d9..25f5cae841e6d9ebe58690ce849f8d6f9446f45e 100644 --- a/src/plugins/debugger/stackwindow.cpp +++ b/src/plugins/debugger/stackwindow.cpp @@ -61,7 +61,7 @@ StackWindow::StackWindow(QWidget *parent) setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setWindowTitle(tr("Stack")); setAlternatingRowColors(act->isChecked()); @@ -76,11 +76,11 @@ StackWindow::StackWindow(QWidget *parent) SLOT(rowActivated(QModelIndex))); connect(act, SIGNAL(toggled(bool)), SLOT(setAlternatingRowColorsHelper(bool))); - connect(theDebuggerAction(UseAddressInStackView), SIGNAL(toggled(bool)), + connect(debuggerCore()->action(UseAddressInStackView), SIGNAL(toggled(bool)), SLOT(showAddressColumn(bool))); - connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()), + connect(debuggerCore()->action(ExpandStack), SIGNAL(triggered()), SLOT(reloadFullStack())); - connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()), + connect(debuggerCore()->action(MaximalStackDepth), SIGNAL(triggered()), SLOT(reloadFullStack())); } @@ -107,13 +107,13 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) const quint64 address = frame.address; QMenu menu; - menu.addAction(theDebuggerAction(ExpandStack)); + menu.addAction(debuggerCore()->action(ExpandStack)); QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard")); actCopyContents->setEnabled(model() != 0); if (engineCapabilities & CreateFullBacktraceCapability) - menu.addAction(theDebuggerAction(CreateFullBacktrace)); + menu.addAction(debuggerCore()->action(CreateFullBacktrace)); QAction *actShowMemory = menu.addAction(QString()); if (address == 0) { @@ -135,9 +135,9 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addSeparator(); #if 0 // @TODO: not implemented - menu.addAction(theDebuggerAction(UseToolTipsInStackView)); + menu.addAction(debuggerCore()->action(UseToolTipsInStackView)); #endif - menu.addAction(theDebuggerAction(UseAddressInStackView)); + menu.addAction(debuggerCore()->action(UseAddressInStackView)); QAction *actAdjust = menu.addAction(tr("Adjust Column Widths to Contents")); @@ -148,7 +148,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/threadswindow.cpp b/src/plugins/debugger/threadswindow.cpp index e63ba6656e2dd38bca00459f931459f7ddd20c61..5349204fbd5e815623e977d97f2a99971724abe1 100644 --- a/src/plugins/debugger/threadswindow.cpp +++ b/src/plugins/debugger/threadswindow.cpp @@ -47,7 +47,7 @@ namespace Internal { ThreadsWindow::ThreadsWindow(QWidget *parent) : QTreeView(parent), m_alwaysResizeColumnsToContents(false) { - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); @@ -80,7 +80,7 @@ void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) alwaysAdjustColumnAction->setChecked(m_alwaysResizeColumnsToContents); menu.addSeparator(); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); if (!act) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 65cf5d59c3576b3f2f7c674332027f1289813f6e..488de4223dc5865eb7848311fd5e05db413e8e5b 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -383,9 +383,9 @@ QString WatchModel::displayType(const WatchData &data) const if (!data.displayedType.isEmpty()) return data.displayedType; QString type = niceTypeHelper(data.type); - if (!theDebuggerBoolSetting(ShowStdNamespace)) + if (!debuggerCore()->boolSetting(ShowStdNamespace)) type.remove(QLatin1String("std::")); - if (!theDebuggerBoolSetting(ShowQtNamespace)) { + if (!debuggerCore()->boolSetting(ShowQtNamespace)) { const QString qtNamespace = QString::fromLatin1(engine()->qtNamespace()); if (!qtNamespace.isEmpty()) type.remove(qtNamespace); @@ -742,7 +742,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const default: break; } // switch editrole column case Qt::ToolTipRole: - return theDebuggerBoolSetting(UseToolTipsInLocalsView) + return debuggerCore()->boolSetting(UseToolTipsInLocalsView) ? data.toToolTip() : QVariant(); case Qt::ForegroundRole: { @@ -800,7 +800,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case LocalsIsWatchpointAtAddressRole: return engine()->breakHandler() - ->watchPointAt(data.coreAddress()); + ->hasWatchpointAt(data.coreAddress()); case LocalsAddressRole: return data.coreAddress(); @@ -808,7 +808,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case LocalsIsWatchpointAtPointerValueRole: if (isPointerType(data.type)) return engine()->breakHandler() - ->watchPointAt(pointerValue(data.value)); + ->hasWatchpointAt(pointerValue(data.value)); return false; default: @@ -966,7 +966,7 @@ bool watchItemSorter(const WatchItem *item1, const WatchItem *item2) static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *item) { - sortWatchDataAlphabetically = theDebuggerBoolSetting(SortStructMembers); + sortWatchDataAlphabetically = debuggerCore()->boolSetting(SortStructMembers); const QList<WatchItem *>::const_iterator it = qLowerBound(list.begin(), list.end(), item, watchItemSorter); return it - list.begin(); @@ -1053,7 +1053,7 @@ void WatchModel::insertBulkData(const QList<WatchData> &list) } QModelIndex index = watchIndex(parent); - sortWatchDataAlphabetically = theDebuggerBoolSetting(SortStructMembers); + sortWatchDataAlphabetically = debuggerCore()->boolSetting(SortStructMembers); QMap<WatchDataSortKey, WatchData> newList; typedef QMap<WatchDataSortKey, WatchData>::iterator Iterator; foreach (const WatchItem &data, list) @@ -1185,11 +1185,11 @@ WatchHandler::WatchHandler(DebuggerEngine *engine) m_watchers = new WatchModel(this, WatchersWatch); m_tooltips = new WatchModel(this, TooltipsWatch); - connect(theDebuggerAction(ShowStdNamespace), + connect(debuggerCore()->action(ShowStdNamespace), SIGNAL(triggered()), this, SLOT(emitAllChanged())); - connect(theDebuggerAction(ShowQtNamespace), + connect(debuggerCore()->action(ShowQtNamespace), SIGNAL(triggered()), this, SLOT(emitAllChanged())); - connect(theDebuggerAction(SortStructMembers), + connect(debuggerCore()->action(SortStructMembers), SIGNAL(triggered()), this, SLOT(emitAllChanged())); } diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index bcab265b8f5006a86b478bf5a775147c93b469c7..fdb016f161b78e2e9f70f702b1fa65322f6daf66 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -140,7 +140,7 @@ WatchWindow::WatchWindow(Type type, QWidget *parent) { m_grabbing = false; - QAction *act = theDebuggerAction(UseAlternatingRowColors); + QAction *act = debuggerCore()->action(UseAlternatingRowColors); setFrameStyle(QFrame::NoFrame); setAttribute(Qt::WA_MacShowFocusRect, false); setWindowTitle(tr("Locals and Watchers")); @@ -343,29 +343,29 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) .arg(pointerValue, 0, 16), &menu); menu.addSeparator(); - QAction *actSetWatchPointAtVariableAddress = 0; - QAction *actSetWatchPointAtPointerValue = 0; + QAction *actSetWatchpointAtVariableAddress = 0; + QAction *actSetWatchpointAtPointerValue = 0; const bool canSetWatchpoint = engineCapabilities & WatchpointCapability; if (canSetWatchpoint && address) { - actSetWatchPointAtVariableAddress = + actSetWatchpointAtVariableAddress = new QAction(tr("Add Watchpoint at Object's Address (0x%1)") .arg(address, 0, 16), &menu); - actSetWatchPointAtVariableAddress-> + actSetWatchpointAtVariableAddress-> setChecked(mi0.data(LocalsIsWatchpointAtAddressRole).toBool()); if (createPointerActions) { - actSetWatchPointAtPointerValue = + actSetWatchpointAtPointerValue = new QAction(tr("Add Watchpoint at Referenced Address (0x%1)") .arg(pointerValue, 0, 16), &menu); - actSetWatchPointAtPointerValue->setCheckable(true); - actSetWatchPointAtPointerValue-> + actSetWatchpointAtPointerValue->setCheckable(true); + actSetWatchpointAtPointerValue-> setChecked(mi0.data(LocalsIsWatchpointAtPointerValueRole).toBool()); } } else { - actSetWatchPointAtVariableAddress = + actSetWatchpointAtVariableAddress = new QAction(tr("At Watchpoint"), &menu); - actSetWatchPointAtVariableAddress->setEnabled(false); + actSetWatchpointAtVariableAddress->setEnabled(false); } - actSetWatchPointAtVariableAddress->setToolTip( + actSetWatchpointAtVariableAddress->setToolTip( tr("Setting a watchpoint on an address will cause the program " "to stop when the data at the address it modified.")); @@ -395,17 +395,17 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) if (actOpenMemoryEditAtPointerValue) menu.addAction(actOpenMemoryEditAtPointerValue); menu.addAction(actOpenMemoryEditor); - menu.addAction(actSetWatchPointAtVariableAddress); - if (actSetWatchPointAtPointerValue) - menu.addAction(actSetWatchPointAtPointerValue); + menu.addAction(actSetWatchpointAtVariableAddress); + if (actSetWatchpointAtPointerValue) + menu.addAction(actSetWatchpointAtPointerValue); menu.addSeparator(); - menu.addAction(theDebuggerAction(UseDebuggingHelpers)); - menu.addAction(theDebuggerAction(UseToolTipsInLocalsView)); - menu.addAction(theDebuggerAction(AutoDerefPointers)); - menu.addAction(theDebuggerAction(ShowStdNamespace)); - menu.addAction(theDebuggerAction(ShowQtNamespace)); - menu.addAction(theDebuggerAction(SortStructMembers)); + menu.addAction(debuggerCore()->action(UseDebuggingHelpers)); + menu.addAction(debuggerCore()->action(UseToolTipsInLocalsView)); + menu.addAction(debuggerCore()->action(AutoDerefPointers)); + menu.addAction(debuggerCore()->action(ShowStdNamespace)); + menu.addAction(debuggerCore()->action(ShowQtNamespace)); + menu.addAction(debuggerCore()->action(SortStructMembers)); QAction *actAdjustColumnWidths = menu.addAction(tr("Adjust Column Widths to Contents")); @@ -418,13 +418,13 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *actClearCodeModelSnapshot = new QAction(tr("Refresh Code Model Snapshot"), &menu); actClearCodeModelSnapshot->setEnabled(actionsEnabled - && theDebuggerAction(UseCodeModel)->isChecked()); + && debuggerCore()->action(UseCodeModel)->isChecked()); menu.addAction(actClearCodeModelSnapshot); QAction *actShowInEditor = new QAction(tr("Show View Contents in Editor"), &menu); actShowInEditor->setEnabled(actionsEnabled); menu.addAction(actShowInEditor); - menu.addAction(theDebuggerAction(SettingsDialog)); + menu.addAction(debuggerCore()->action(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); if (act == 0) @@ -444,9 +444,9 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) AddressDialog dialog; if (dialog.exec() == QDialog::Accepted) (void) new MemoryViewAgent(currentEngine(), dialog.address()); - } else if (act == actSetWatchPointAtVariableAddress) { + } else if (act == actSetWatchpointAtVariableAddress) { setWatchpoint(address); - } else if (act == actSetWatchPointAtPointerValue) { + } else if (act == actSetWatchpointAtPointerValue) { setWatchpoint(pointerValue); } else if (act == actSelectWidgetToWatch) { grabMouse(Qt::CrossCursor); @@ -574,18 +574,7 @@ QVariant WatchWindow::modelData(int role, const QModelIndex &index) void WatchWindow::setWatchpoint(quint64 address) { - DebuggerEngine *engine = currentEngine(); - BreakHandler *handler = engine->breakHandler(); - const int index = handler->findWatchPointIndexByAddress(address); - if (index == -1) { - BreakpointData *data = new BreakpointData; - data->type = Watchpoint; - data->address = address; - handler->appendBreakpoint(data); - } else { - handler->removeBreakpoint(index); - } - engine->attemptBreakpointSynchronization(); + breakHandler()->setWatchpointByAddress(address); } } // namespace Internal