diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index a8841260b60d6057642e2159e9ecd9f39aa0a8ee..1673d7fce8c7cc730125a8c2a22e2cb7d73bccd4 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -41,325 +41,14 @@ #include <utils/qtcassert.h> #include <QtCore/QByteArray> -#include <QtCore/QDebug> -#include <QtCore/QTextStream> #include <QtCore/QFileInfo> -////////////////////////////////////////////////////////////////// -// -// BreakpointMarker -// -////////////////////////////////////////////////////////////////// - -// Compare file names case insensitively on Windows. -static inline bool fileNameMatch(const QString &f1, const QString &f2) -{ -#ifdef Q_OS_WIN - return f1.compare(f2, Qt::CaseInsensitive) == 0; -#else - return f1 == f2; -#endif -} - namespace Debugger { namespace Internal { static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); } -// The red blob on the left side in the cpp editor. -class BreakpointMarker : public TextEditor::BaseTextMark -{ - Q_OBJECT -public: - BreakpointMarker(BreakpointData *data, const QString &fileName, int lineNumber) - : BaseTextMark(fileName, lineNumber) - { - m_data = data; - m_pending = true; - m_enabled = true; - //qDebug() << "CREATE MARKER " << fileName << lineNumber; - } - - ~BreakpointMarker() - { - //qDebug() << "REMOVE MARKER "; - m_data = 0; - } - - QIcon icon() const - { - const BreakHandler *handler = m_data->handler(); - if (!m_enabled) - return handler->disabledBreakpointIcon(); - return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon(); - } - - void setPending(bool pending, bool enabled) - { - if (pending == m_pending && enabled == m_enabled) - return; - m_pending = pending; - m_enabled = enabled; - updateMarker(); - } - - void updateBlock(const QTextBlock &) - { - //qDebug() << "BREAKPOINT MARKER UPDATE BLOCK"; - } - - void removedFromEditor() - { - if (!m_data) - return; - - BreakHandler *handler = m_data->handler(); - handler->removeBreakpoint(m_data); - //handler->saveBreakpoints(); - handler->updateMarkers(); - } - - void 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.isEmpty()) { - 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 = QByteArray::number(lineNumber); - m_data->handler()->updateMarkers(); - } - } - -private: - BreakpointData *m_data; - bool m_pending; - bool m_enabled; -}; - - -////////////////////////////////////////////////////////////////// -// -// BreakpointData -// -////////////////////////////////////////////////////////////////// - -BreakpointData::BreakpointData() -{ - m_handler = 0; - enabled = true; - pending = true; - type = BreakpointType; - marker = 0; - m_markerLineNumber = 0; - bpMultiple = false; - bpEnabled = true; - useFullPath = false; -} - -BreakpointData *BreakpointData::clone() const -{ - BreakpointData *data = new BreakpointData(); - data->m_handler = m_handler; - data->m_markerFileName = m_markerFileName; - data->m_markerLineNumber = m_markerLineNumber; - 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; - return data; -} - -BreakpointData::~BreakpointData() -{ - removeMarker(); -} - -void BreakpointData::removeMarker() -{ - BreakpointMarker *m = marker; - marker = 0; - delete m; -} - -void BreakpointData::updateMarker() -{ - if (marker && (m_markerFileName != marker->fileName() - || m_markerLineNumber != marker->lineNumber())) - removeMarker(); - - if (!marker && !m_markerFileName.isEmpty() && m_markerLineNumber > 0) - marker = new BreakpointMarker(this, m_markerFileName, m_markerLineNumber); - - if (marker) - marker->setPending(pending, enabled); -} - -void BreakpointData::setMarkerFileName(const QString &fileName) -{ - m_markerFileName = fileName; -} - -void BreakpointData::setMarkerLineNumber(int lineNumber) -{ - m_markerLineNumber = lineNumber; -} - -QString BreakpointData::toToolTip() const -{ - QString rc; - QTextStream str(&rc); - str << "<html><body><table>" - << "<tr><td>" << BreakHandler::tr("Marker File:") - << "</td><td>" << m_markerFileName << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Marker Line:") - << "</td><td>" << m_markerLineNumber << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Breakpoint Number:") - << "</td><td>" << bpNumber << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Breakpoint Type:") - << "</td><td>" - << (type == BreakpointType ? BreakHandler::tr("Breakpoint") - : type == WatchpointType ? BreakHandler::tr("Watchpoint") - : BreakHandler::tr("Unknown breakpoint type")) - << "</td></tr>" - << "</table><br><hr><table>" - << "<tr><th>" << BreakHandler::tr("Property") - << "</th><th>" << BreakHandler::tr("Requested") - << "</th><th>" << BreakHandler::tr("Obtained") << "</th></tr>" - << "<tr><td>" << BreakHandler::tr("Internal Number:") - << "</td><td>—</td><td>" << bpNumber << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("File Name:") - << "</td><td>" << fileName << "</td><td>" << bpFileName << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Function Name:") - << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Line Number:") - << "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Breakpoint Address:") - << "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Corrected Line Number:") - << "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Condition:") - << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Ignore Count:") - << "</td><td>" << ignoreCount << "</td><td>" << bpIgnoreCount << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Thread Specification:") - << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" - << "</table></body></html>"; - return rc; -} - -QString BreakpointData::toString() const -{ - QString rc; - QTextStream str(&rc); - str << BreakHandler::tr("Marker File:") << ' ' << m_markerFileName << '\n' - << BreakHandler::tr("Marker Line:") << ' ' << m_markerLineNumber << '\n' - << BreakHandler::tr("Breakpoint Number:") << ' ' << bpNumber << '\n' - << BreakHandler::tr("Breakpoint Type:") << ' ' - << (type == BreakpointType ? BreakHandler::tr("Breakpoint") - : type == WatchpointType ? BreakHandler::tr("Watchpoint") - : BreakHandler::tr("Unknown breakpoint type")) << '\n' - << BreakHandler::tr("File Name:") << ' ' - << fileName << " -- " << bpFileName << '\n' - << BreakHandler::tr("Function Name:") << ' ' - << funcName << " -- " << bpFuncName << '\n' - << BreakHandler::tr("Line Number:") << ' ' - << lineNumber << " -- " << bpLineNumber << '\n' - << BreakHandler::tr("Breakpoint Address:") << ' ' - << address << " -- " << bpAddress << '\n' - << BreakHandler::tr("Condition:") << ' ' - << condition << " -- " << bpCondition << '\n' - << BreakHandler::tr("Ignore Count:") << ' ' - << ignoreCount << " -- " << bpIgnoreCount << '\n' - << BreakHandler::tr("Thread Specification:") << ' ' - << threadSpec << " -- " << bpThreadSpec << '\n'; - return rc; -} - -bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_) const -{ - /* - if (lineNumber != QString::number(lineNumber_)) - return false; - if (fileName == fileName_) - return true; - if (fileName_.endsWith(fileName)) - return true; - return false; - */ - return lineNumber_ == m_markerLineNumber - && fileNameMatch(fileName_, m_markerFileName); -} - -bool BreakpointData::isSimilarTo(const BreakpointData *needle) const -{ - //qDebug() << "COMPARING " << toString() << " WITH " << needle->toString(); - - // 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; - - // 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 -{ - // Some versions of gdb "beautify" the passed condition. - QString s1 = condition; - s1.remove(QChar(' ')); - QString s2 = bpCondition; - s2.remove(QChar(' ')); - return s1 == s2; -} - ////////////////////////////////////////////////////////////////// // @@ -371,6 +60,8 @@ BreakHandler::BreakHandler(DebuggerEngine *engine) : m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")), m_disabledBreakpointIcon(_(":/debugger/images/breakpoint_disabled_16.png")), m_pendingBreakPointIcon(_(":/debugger/images/breakpoint_pending_16.png")), + m_emptyIcon(_(":/debugger/images/watchpoint.png")), + //m_emptyIcon(_(":/debugger/images/debugger_empty_14.png")), m_watchpointIcon(_(":/debugger/images/watchpoint.png")), m_engine(engine), m_lastFound(0), @@ -960,6 +651,11 @@ void BreakHandler::breakByFunction(const QString &functionName) updateMarkers(); } +bool BreakHandler::isActive() const +{ + return m_engine->isActive(); +} + void BreakHandler::initializeFromTemplate(BreakHandler *other) { //qDebug() << "COPYING BREAKPOINTS INTO NEW SESSION"; @@ -983,5 +679,3 @@ void BreakHandler::storeToTemplate(BreakHandler *other) } // namespace Internal } // namespace Debugger - -#include "breakhandler.moc" diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 16a477eb7854f5835789b2849d213a3450c3b217..270310e60f3c00191eedb501aba5267fdcab52fa 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -34,8 +34,10 @@ #include <QtCore/QObject> #include <QtCore/QAbstractTableModel> + #include <QtGui/QIcon> + namespace Debugger { namespace Internal { @@ -74,6 +76,7 @@ public: int findWatchPointIndexByAddress(const QByteArray &a) const; bool watchPointAt(quint64 address) const; void updateMarkers(); + bool isActive() const; Breakpoints insertedBreakpoints() const; void takeInsertedBreakPoint(BreakpointData *); @@ -81,9 +84,10 @@ public: Breakpoints takeEnabledBreakpoints(); // Not owned. Breakpoints takeDisabledBreakpoints(); // Not owned. - QIcon breakpointIcon() const { return m_breakpointIcon; } + QIcon breakpointIcon() const { return m_breakpointIcon; } QIcon disabledBreakpointIcon() const { return m_disabledBreakpointIcon; } - QIcon pendingBreakPointIcon() const { return m_pendingBreakPointIcon; } + QIcon pendingBreakPointIcon() const { return m_pendingBreakPointIcon; } + QIcon emptyIcon() const { return m_emptyIcon; } void initializeFromTemplate(BreakHandler *other); void storeToTemplate(BreakHandler *other); @@ -117,6 +121,7 @@ private: const QIcon m_breakpointIcon; const QIcon m_disabledBreakpointIcon; const QIcon m_pendingBreakPointIcon; + const QIcon m_emptyIcon; const QIcon m_watchpointIcon; DebuggerEngine *m_engine; // Not owned. diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..166bebd398ec2fc04524e9e2a6c91111dcda848b --- /dev/null +++ b/src/plugins/debugger/breakpoint.cpp @@ -0,0 +1,365 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "breakhandler.h" + +#include "debuggeractions.h" +#include "debuggerengine.h" +#include "debuggerstringutils.h" +#include "threadshandler.h" +#include "stackhandler.h" +#include "stackframe.h" + +#include <texteditor/basetextmark.h> +#include <utils/qtcassert.h> + +#include <QtCore/QByteArray> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> +#include <QtCore/QFileInfo> + + +////////////////////////////////////////////////////////////////// +// +// BreakpointMarker +// +////////////////////////////////////////////////////////////////// + +// Compare file names case insensitively on Windows. +static inline bool fileNameMatch(const QString &f1, const QString &f2) +{ +#ifdef Q_OS_WIN + return f1.compare(f2, Qt::CaseInsensitive) == 0; +#else + return f1 == f2; +#endif +} + +namespace Debugger { +namespace Internal { + +// The red blob on the left side in the cpp editor. +class BreakpointMarker : public TextEditor::BaseTextMark +{ + Q_OBJECT +public: + BreakpointMarker(BreakpointData *data, const QString &fileName, int lineNumber) + : BaseTextMark(fileName, lineNumber) + { + m_data = data; + m_pending = true; + m_enabled = true; + //qDebug() << "CREATE MARKER " << fileName << lineNumber; + } + + ~BreakpointMarker() + { + //qDebug() << "REMOVE MARKER "; + m_data = 0; + } + + QIcon icon() const + { + const BreakHandler *handler = m_data->handler(); + if (!handler->isActive()) + return handler->emptyIcon(); + if (!m_enabled) + return handler->disabledBreakpointIcon(); + return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon(); + } + + void setPending(bool pending, bool enabled) + { + if (pending == m_pending && enabled == m_enabled) + return; + m_pending = pending; + m_enabled = enabled; + updateMarker(); + } + + void updateBlock(const QTextBlock &) + { + //qDebug() << "BREAKPOINT MARKER UPDATE BLOCK"; + } + + void removedFromEditor() + { + if (!m_data) + return; + + BreakHandler *handler = m_data->handler(); + handler->removeBreakpoint(m_data); + //handler->saveBreakpoints(); + handler->updateMarkers(); + } + + void 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.isEmpty()) { + 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 = QByteArray::number(lineNumber); + m_data->handler()->updateMarkers(); + } + } + +private: + BreakpointData *m_data; + bool m_pending; + bool m_enabled; +}; + + +////////////////////////////////////////////////////////////////// +// +// BreakpointData +// +////////////////////////////////////////////////////////////////// + +BreakpointData::BreakpointData() +{ + m_handler = 0; + enabled = true; + pending = true; + type = BreakpointType; + marker = 0; + m_markerLineNumber = 0; + bpMultiple = false; + bpEnabled = true; + useFullPath = false; +} + +BreakpointData *BreakpointData::clone() const +{ + BreakpointData *data = new BreakpointData(); + data->m_handler = m_handler; + data->m_markerFileName = m_markerFileName; + data->m_markerLineNumber = m_markerLineNumber; + 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; + return data; +} + +BreakpointData::~BreakpointData() +{ + removeMarker(); +} + +void BreakpointData::removeMarker() +{ + BreakpointMarker *m = marker; + marker = 0; + delete m; +} + +void BreakpointData::updateMarker() +{ + if (marker && (m_markerFileName != marker->fileName() + || m_markerLineNumber != marker->lineNumber())) + removeMarker(); + + if (!marker && !m_markerFileName.isEmpty() && m_markerLineNumber > 0) + marker = new BreakpointMarker(this, m_markerFileName, m_markerLineNumber); + + if (marker) + marker->setPending(pending, enabled); +} + +void BreakpointData::setMarkerFileName(const QString &fileName) +{ + m_markerFileName = fileName; +} + +void BreakpointData::setMarkerLineNumber(int lineNumber) +{ + m_markerLineNumber = lineNumber; +} + +QString BreakpointData::toToolTip() const +{ + QString rc; + QTextStream str(&rc); + str << "<html><body><table>" + << "<tr><td>" << BreakHandler::tr("Marker File:") + << "</td><td>" << m_markerFileName << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Marker Line:") + << "</td><td>" << m_markerLineNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Breakpoint Number:") + << "</td><td>" << bpNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Breakpoint Type:") + << "</td><td>" + << (type == BreakpointType ? BreakHandler::tr("Breakpoint") + : type == WatchpointType ? BreakHandler::tr("Watchpoint") + : BreakHandler::tr("Unknown breakpoint type")) + << "</td></tr>" + << "</table><br><hr><table>" + << "<tr><th>" << BreakHandler::tr("Property") + << "</th><th>" << BreakHandler::tr("Requested") + << "</th><th>" << BreakHandler::tr("Obtained") << "</th></tr>" + << "<tr><td>" << BreakHandler::tr("Internal Number:") + << "</td><td>—</td><td>" << bpNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("File Name:") + << "</td><td>" << fileName << "</td><td>" << bpFileName << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Function Name:") + << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Line Number:") + << "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Breakpoint Address:") + << "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Corrected Line Number:") + << "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Condition:") + << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Ignore Count:") + << "</td><td>" << ignoreCount << "</td><td>" << bpIgnoreCount << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Thread Specification:") + << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" + << "</table></body></html>"; + return rc; +} + +QString BreakpointData::toString() const +{ + QString rc; + QTextStream str(&rc); + str << BreakHandler::tr("Marker File:") << ' ' << m_markerFileName << '\n' + << BreakHandler::tr("Marker Line:") << ' ' << m_markerLineNumber << '\n' + << BreakHandler::tr("Breakpoint Number:") << ' ' << bpNumber << '\n' + << BreakHandler::tr("Breakpoint Type:") << ' ' + << (type == BreakpointType ? BreakHandler::tr("Breakpoint") + : type == WatchpointType ? BreakHandler::tr("Watchpoint") + : BreakHandler::tr("Unknown breakpoint type")) << '\n' + << BreakHandler::tr("File Name:") << ' ' + << fileName << " -- " << bpFileName << '\n' + << BreakHandler::tr("Function Name:") << ' ' + << funcName << " -- " << bpFuncName << '\n' + << BreakHandler::tr("Line Number:") << ' ' + << lineNumber << " -- " << bpLineNumber << '\n' + << BreakHandler::tr("Breakpoint Address:") << ' ' + << address << " -- " << bpAddress << '\n' + << BreakHandler::tr("Condition:") << ' ' + << condition << " -- " << bpCondition << '\n' + << BreakHandler::tr("Ignore Count:") << ' ' + << ignoreCount << " -- " << bpIgnoreCount << '\n' + << BreakHandler::tr("Thread Specification:") << ' ' + << threadSpec << " -- " << bpThreadSpec << '\n'; + return rc; +} + +bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_) const +{ + /* + if (lineNumber != QString::number(lineNumber_)) + return false; + if (fileName == fileName_) + return true; + if (fileName_.endsWith(fileName)) + return true; + return false; + */ + return lineNumber_ == m_markerLineNumber + && fileNameMatch(fileName_, m_markerFileName); +} + +bool BreakpointData::isSimilarTo(const BreakpointData *needle) const +{ + //qDebug() << "COMPARING " << toString() << " WITH " << needle->toString(); + + // 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; + + // 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 +{ + // Some versions of gdb "beautify" the passed condition. + QString s1 = condition; + s1.remove(QChar(' ')); + QString s2 = bpCondition; + s2.remove(QChar(' ')); + return s1 == s2; +} + +} // namespace Internal +} // namespace Debugger + +#include "breakpoint.moc" diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index e12367c3ebdfb57351e04814bf0f1e80e94eea92..98c569cdf6551c279fa4b7984450edbe94ac5fa8 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -35,7 +35,6 @@ #include <QtCore/QString> namespace Debugger { -class DebuggerManager; namespace Internal { class BreakpointMarker; @@ -63,8 +62,8 @@ public: bool isSimilarTo(const BreakpointData *needle) const; bool conditionsMatch() const; - BreakpointData *clone() const; // This copies only the static data. + BreakpointData *clone() const; private: // Intentionally unimplemented. diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index e7f6e0446d0c5e1f9871fe4eeb0ec90dd4f034d2..336306ea9ae382f5509993a6fe922522b3e4758e 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -54,7 +54,7 @@ HEADERS += breakhandler.h \ SOURCES += breakhandler.cpp \ breakwindow.cpp \ - breakwindow.h \ + breakpoint.cpp \ debuggeragents.cpp \ debuggeractions.cpp \ debuggerdialogs.cpp \ diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 00f1aad5131503be93ebc010eaac2aefe674e6f5..5b823e5243ea6dd6370d4a75e2150c6216dc769e 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -164,6 +164,7 @@ enum ModelRoles EngineStateRole, EngineCapabilitiesRole, EngineActionsEnabledRole, + RequestActivationRole, // Running RequestExecContinueRole, diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index cf88ea2f081ef925a32615ea72e8c7bbd39a9c72..10042e7f6547b72fab33364f8148e3dbfac4b320 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -217,6 +217,7 @@ public: DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp) : m_engine(engine), m_runControl(0), + m_isActive(false), m_startParameters(sp), m_state(DebuggerNotReady), m_lastGoodState(DebuggerNotReady), @@ -272,6 +273,7 @@ public: DebuggerEngine *m_engine; // Not owned. DebuggerRunControl *m_runControl; // Not owned. + bool m_isActive; DebuggerStartParameters m_startParameters; @@ -466,6 +468,10 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value) makeSnapshot(); break; + case RequestActivationRole: + setActive(value.toBool()); + break; + case RequestExecFrameDownRole: frameDown(); break; @@ -648,8 +654,8 @@ void DebuggerEngine::setRegisterValue(int regnr, const QString &value) void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const { - if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper()) - qDebug() << qPrintable(msg) << "IN STATE" << state(); + //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper()) + // qDebug() << qPrintable(msg) << "IN STATE" << state(); d->m_runControl->showMessage(msg, channel); plugin()->showMessage(msg, channel, timeout); } @@ -1294,8 +1300,8 @@ void DebuggerEngine::notifyInferiorExited() void DebuggerEngine::setState(DebuggerState state, bool forced) { SDEBUG(Q_FUNC_INFO); - qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) - << " TO " << stateName(state); + //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) + // << " TO " << stateName(state); DebuggerState oldState = d->m_state; d->m_state = state; @@ -1379,6 +1385,18 @@ bool DebuggerEngine::isReverseDebugging() const return plugin()->isReverseDebugging(); } +bool DebuggerEngine::isActive() const +{ + return d->m_isActive && !isSessionEngine(); +} + +void DebuggerEngine::setActive(bool on) +{ + qDebug() << "SETTING ACTIVE" << this << on; + d->m_isActive = on; + //breakHandler()->updateMarkers(); +} + // called by DebuggerRunControl void DebuggerEngine::quitDebugger() { diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index fcd54a242f3171eb8d99e83c8cff1eb4c27146e2..f21db60de7df80c3c7a414e2fa20c7be54996776 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -239,6 +239,8 @@ public: void notifyInferiorPid(qint64 pid); qint64 inferiorPid() const; bool isReverseDebugging() const; + bool isActive() const; // True if this is the currently active engine; + void setActive(bool on); // FIXME: private? void handleCommand(int role, const QVariant &value); // Convenience diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 3fa094c092871963324d0654e45de89a18471a37..44dbe9fa21269d938b9b5e0cb92c708d9222d209 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -869,7 +869,7 @@ public: bool initialize(const QStringList &arguments, QString *errorMessage); void notifyCurrentEngine(int role, const QVariant &value = QVariant()); - void connectEngine(DebuggerEngine *engine); + void connectEngine(DebuggerEngine *engine, bool notify = true); void disconnectEngine() { connectEngine(m_sessionEngine); } public slots: @@ -1608,8 +1608,8 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er connect(m_uiSwitcher, SIGNAL(languageChanged(QString)), this, SLOT(languageChanged(QString))); - disconnectEngine(); setInitialState(); + connectEngine(m_sessionEngine, false); return true; } @@ -1934,8 +1934,10 @@ void DebuggerPluginPrivate::startDebugger(ProjectExplorer::RunControl *rc) qDebug() << "START DEBUGGER 2"; } -void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) +void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify) { + if (notify) + notifyCurrentEngine(RequestActivationRole, false); if (engine == m_sessionEngine) qDebug() << "CONNECTING DUMMY ENGINE" << engine; else @@ -1952,6 +1954,8 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) m_threadBox->setModel(engine->threadsModel()); m_watchersWindow->setModel(engine->watchersModel()); m_capabilities = engine->debuggerCapabilities(); + if (notify) + notifyCurrentEngine(RequestActivationRole, true); } static void changeFontSize(QWidget *widget, int size) diff --git a/src/plugins/debugger/sessionengine.h b/src/plugins/debugger/sessionengine.h index c426c097c8f64428dacfd77033f05d147b621106..f6486e3c4fc6828fd093edb957d1125fe33f157b 100644 --- a/src/plugins/debugger/sessionengine.h +++ b/src/plugins/debugger/sessionengine.h @@ -42,6 +42,8 @@ class SnapshotHandler; class SessionEngine : public DebuggerEngine { + Q_OBJECT + public: SessionEngine();