diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index 492925541dde24c50dce485a4cf8e278a1334b1e..4f352da9cdf9ed58e154f16f927b22872dc89ae5 100644 --- a/share/qtcreator/gdbmacros/dumper.py +++ b/share/qtcreator/gdbmacros/dumper.py @@ -942,7 +942,7 @@ class Dumper: pass except: # Locals with failing memory access. - with SubItem(d): + with SubItem(self): self.put('iname="%s",' % item.iname) self.put('name="%s",' % item.name) self.put('addr="<not accessible>",') @@ -963,7 +963,7 @@ class Dumper: p += 1 n += 1 - with SubItem(d): + with SubItem(self): self.put('iname="%s",' % item.iname) self.putName(item.name) self.putItemCount(select(n <= 100, n, "> 100")) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index c579a298ff65e07c50232167045a53bd578784cd..f4dca3be9ddec098036304531da7c95330893e5d 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -30,8 +30,11 @@ #include "breakhandler.h" #include "debuggeractions.h" -#include "debuggermanager.h" +#include "debuggerengine.h" +#include "debuggerplugin.h" #include "debuggerstringutils.h" +#include "threadshandler.h" +#include "stackhandler.h" #include "stackframe.h" #include <texteditor/basetextmark.h> @@ -42,9 +45,6 @@ #include <QtCore/QTextStream> #include <QtCore/QFileInfo> -using namespace Debugger; -using namespace Debugger::Internal; - ////////////////////////////////////////////////////////////////// // @@ -65,6 +65,8 @@ static inline bool fileNameMatch(const QString &f1, const QString &f2) 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 { @@ -137,7 +139,7 @@ public: } // 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. + // 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); @@ -151,10 +153,6 @@ private: bool m_enabled; }; -} // namespace Internal -} // namespace Debugger - - ////////////////////////////////////////////////////////////////// // @@ -175,6 +173,27 @@ BreakpointData::BreakpointData() useFullPath = false; } +BreakpointData::BreakpointData(const BreakpointData &other) +{ + //qDebug() << "COPYING BREAKPOINT " << other.toString(); + pending = true; + marker = 0; + + m_handler = other.m_handler; + m_markerFileName = other.m_markerFileName; + m_markerLineNumber = other.m_markerLineNumber; + enabled = other.enabled; + type = other.type; + fileName = other.fileName; + condition = other.condition; + ignoreCount = other.ignoreCount; + lineNumber = other.lineNumber; + address = other.address; + threadSpec = other.threadSpec; + funcName = other.funcName; + useFullPath = other.useFullPath; +} + BreakpointData::~BreakpointData() { removeMarker(); @@ -223,7 +242,7 @@ QString BreakpointData::toToolTip() const << "</td><td>" << bpNumber << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Breakpoint Type:") << "</td><td>" - << (type == BreakpointType ? BreakHandler::tr("Breakpoint") + << (type == BreakpointType ? BreakHandler::tr("Breakpoint") : type == WatchpointType ? BreakHandler::tr("Watchpoint") : BreakHandler::tr("Unknown breakpoint type")) << "</td></tr>" @@ -261,7 +280,7 @@ QString BreakpointData::toString() const << BreakHandler::tr("Marker Line:") << ' ' << m_markerLineNumber << '\n' << BreakHandler::tr("Breakpoint Number:") << ' ' << bpNumber << '\n' << BreakHandler::tr("Breakpoint Type:") << ' ' - << (type == BreakpointType ? BreakHandler::tr("Breakpoint") + << (type == BreakpointType ? BreakHandler::tr("Breakpoint") : type == WatchpointType ? BreakHandler::tr("Watchpoint") : BreakHandler::tr("Unknown breakpoint type")) << '\n' << BreakHandler::tr("File Name:") << ' ' @@ -296,6 +315,43 @@ bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_) cons && 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. @@ -313,15 +369,15 @@ bool BreakpointData::conditionsMatch() const // ////////////////////////////////////////////////////////////////// -BreakHandler::BreakHandler(DebuggerManager *manager, QObject *parent) : - QAbstractTableModel(parent), - m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")), +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_watchpointIcon(_(":/debugger/images/watchpoint.png")), - m_manager(manager) -{ -} + m_engine(engine), // Possibly 0 for the dummy engine "handling" session data. + m_lastFound(0), + m_lastFoundQueried(false) +{} BreakHandler::~BreakHandler() { @@ -369,29 +425,12 @@ void BreakHandler::clear() m_inserted.clear(); } -BreakpointData *BreakHandler::findSimilarBreakpoint(const BreakpointData &needle) const +BreakpointData *BreakHandler::findSimilarBreakpoint(const BreakpointData *needle) const { // Search a breakpoint we might refer to. for (int index = 0; index != size(); ++index) { BreakpointData *data = m_bp[index]; - // Clear hit. - if (data->bpNumber == needle.bpNumber - && !data->bpNumber.isEmpty() - && data->bpNumber.toInt() != 0) - return data; - // Clear miss. - if (data->type != needle.type) - continue; - // We have numbers, but they are different. - if (!data->bpNumber.isEmpty() && !needle.bpNumber.isEmpty() - && !data->bpNumber.startsWith(needle.bpNumber) - && !needle.bpNumber.startsWith(data->bpNumber)) - continue; - // 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) + if (data->isSimilarTo(needle)) return data; } return 0; @@ -426,6 +465,8 @@ bool BreakHandler::watchPointAt(quint64 address) const void BreakHandler::saveBreakpoints() { + //qDebug() << "SAVING BREAKPOINTS..."; + QTC_ASSERT(plugin(), return); QList<QVariant> list; for (int index = 0; index != size(); ++index) { const BreakpointData *data = at(index); @@ -455,12 +496,15 @@ void BreakHandler::saveBreakpoints() map.insert(_("usefullpath"), _("1")); list.append(map); } - m_manager->setSessionValue("Breakpoints", list); + plugin()->setSessionValue("Breakpoints", list); + //qDebug() << "SAVED BREAKPOINTS" << this << list.size(); } void BreakHandler::loadBreakpoints() { - QVariant value = m_manager->sessionValue("Breakpoints"); + QTC_ASSERT(plugin(), return); + //qDebug() << "LOADING BREAKPOINTS..."; + QVariant value = plugin()->sessionValue("Breakpoints"); QList<QVariant> list = value.toList(); clear(); foreach (const QVariant &var, list) { @@ -500,6 +544,7 @@ void BreakHandler::loadBreakpoints() data->setMarkerLineNumber(data->lineNumber.toInt()); append(data); } + //qDebug() << "LOADED BREAKPOINTS" << this << list.size(); } void BreakHandler::resetBreakpoints() @@ -554,20 +599,56 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const { static const QString empty = QString(QLatin1Char('-')); - QTC_ASSERT(mi.isValid(), return QVariant()); + switch (role) { + case RequestFindSimilarBreakpointRole: { + // Complain if data/setData are not used alternately. + QTC_ASSERT(m_lastFoundQueried, return false); + QVariant value = QVariant::fromValue(m_lastFound); + m_lastFoundQueried = false; + m_lastFound = 0; // Reset for "safety". + return value; + } + + case CurrentThreadIdRole: + QTC_ASSERT(m_engine, return QVariant()); + return m_engine->threadsHandler()->currentThreadId(); + + case EngineActionsEnabledRole: + QTC_ASSERT(m_engine, return QVariant()); + return m_engine->debuggerActionsEnabled(); + case EngineCapabilitiesRole: + QTC_ASSERT(m_engine, return QVariant()); + return m_engine->debuggerCapabilities(); + + default: + break; + } + + QTC_ASSERT(mi.isValid(), return QVariant()); if (mi.row() >= size()) return QVariant(); const BreakpointData *data = at(mi.row()); + + if (role == BreakpointUseFullPathRole) + return data->useFullPath; + + if (role == BreakpointFileNameRole) + return data->fileName; + + if (role == BreakpointEnabledRole) + return data->enabled; + + if (role == BreakpointFunctionNameRole) + return data->funcName; + switch (mi.column()) { case 0: if (role == Qt::DisplayRole) { const QString str = data->bpNumber; return str.isEmpty() ? empty : str; } - if (role == Qt::UserRole) - return data->enabled; if (role == Qt::DecorationRole) { if (data->type == BreakpointData::WatchpointType) return m_watchpointIcon; @@ -581,8 +662,6 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const const QString str = data->pending ? data->funcName : data->bpFuncName; return str.isEmpty() ? empty : str; } - if (role == Qt::UserRole + 1) - return data->funcName; break; case 2: if (role == Qt::DisplayRole) { @@ -596,10 +675,6 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const str = "/.../" + str; return str; } - if (role == Qt::UserRole) - return data->useFullPath; - if (role == Qt::UserRole + 1) - return data->fileName; break; case 3: if (role == Qt::DisplayRole) { @@ -645,7 +720,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const if (data->type == BreakpointData::WatchpointType) return data->address; return data->bpAddress; - } + } break; } if (role == Qt::ToolTipRole) @@ -654,92 +729,151 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const return QVariant(); } -Qt::ItemFlags BreakHandler::flags(const QModelIndex &mi) const +Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const { - switch (mi.column()) { + switch (index.column()) { //case 0: // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; default: - return QAbstractTableModel::flags(mi); + return QAbstractTableModel::flags(index); } } -bool BreakHandler::setData(const QModelIndex &mi, const QVariant &value, int role) +bool BreakHandler::setData(const QModelIndex &index, const QVariant &value, int role) { - BreakpointData *data = at(mi.row()); + switch (role) { + case RequestFindSimilarBreakpointRole: { + // Complain if data/setData are not used alternately. + QTC_ASSERT(!m_lastFoundQueried, return false); + BreakpointData *needle = value.value<BreakpointData *>(); + QTC_ASSERT(needle, return false); + m_lastFound = findSimilarBreakpoint(needle); + m_lastFoundQueried = true; + return true; + } - if (role == Qt::UserRole + 1) { - if (data->enabled != value.toBool()) { - toggleBreakpointEnabled(data); - layoutChanged(); + case RequestActivateBreakpointRole: { + const BreakpointData *data = at(value.toInt()); + QTC_ASSERT(data, return false); + m_engine->gotoLocation(data->markerFileName(), + data->markerLineNumber(), false); + return true; } - return true; - } - if (role == Qt::UserRole + 2) { - if (data->useFullPath != value.toBool()) { - data->useFullPath = value.toBool(); - layoutChanged(); + case RequestRemoveBreakpointByIndexRole: { + BreakpointData *data = at(value.toInt()); + QTC_ASSERT(data, return false); + removeBreakpoint(data); + return true; } - return true; + + case RequestRemoveBreakpointRole: { + BreakpointData *data = value.value<BreakpointData *>(); + QTC_ASSERT(data, return false); + removeBreakpoint(data); + return true; + } + + case RequestAppendBreakpointRole: { + BreakpointData *data = value.value<BreakpointData *>(); + QTC_ASSERT(data, return false); + appendBreakpoint(data); + if (m_engine) + m_engine->attemptBreakpointSynchronization(); + return true; + } + + case RequestUpdateBreakpointRole: { + BreakpointData *data = value.value<BreakpointData *>(); + QTC_ASSERT(data, return false); + if (m_engine) + m_engine->attemptBreakpointSynchronization(); + return true; + } + + case RequestSynchronizeBreakpointsRole: + QTC_ASSERT(m_engine, return false); + m_engine->attemptBreakpointSynchronization(); + return true; + + case RequestBreakByFunctionRole: + QTC_ASSERT(m_engine, return false); + m_engine->breakByFunction(value.toString()); + return true; + + case RequestBreakByFunctionMainRole: + QTC_ASSERT(m_engine, return false); + m_engine->breakByFunctionMain(); + return true; } - //if (role != Qt::EditRole) - // return false; + BreakpointData *data = at(index.row()); - switch (mi.column()) { - case 1: { + switch (role) { + case BreakpointEnabledRole: + if (data->enabled != value.toBool()) { + toggleBreakpointEnabled(data); + layoutChanged(); + } + return true; + + case BreakpointUseFullPathRole: + if (data->useFullPath != value.toBool()) { + data->useFullPath = value.toBool(); + layoutChanged(); + } + return true; + + /* QString val = value.toString(); if (data->funcName != val) { data->funcName = val; layoutChanged(); } return true; - } - case 2: { + QString val = value.toString(); if (data->fileName != val) { data->fileName = val; layoutChanged(); } return true; - } - case 3: { + QByteArray val = value.toString().toLatin1(); if (data->lineNumber != val) { data->lineNumber = val; layoutChanged(); } return true; - } - case 4: { - QByteArray val = value.toString().toLatin1(); - if (val != data->condition) { - data->condition = val; - layoutChanged(); + */ + case BreakpointConditionRole: { + QByteArray val = value.toString().toLatin1(); + if (val != data->condition) { + data->condition = val; + layoutChanged(); + } } return true; - } - case 5: { - QByteArray val = value.toString().toLatin1(); - if (val != data->ignoreCount) { - data->ignoreCount = val; - layoutChanged(); + + case BreakpointIgnoreCountRole: { + QByteArray val = value.toString().toLatin1(); + if (val != data->ignoreCount) { + data->ignoreCount = val; + layoutChanged(); + } } return true; - } - case 6: { - QByteArray val = value.toString().toLatin1(); - if (val != data->threadSpec) { - data->threadSpec = val; - layoutChanged(); + + case BreakpointThreadSpecRole: { + QByteArray val = value.toString().toLatin1(); + if (val != data->threadSpec) { + data->threadSpec = val; + layoutChanged(); + } } return true; - } - default: { - return false; - } } + return false; } void BreakHandler::append(BreakpointData *data) @@ -749,7 +883,7 @@ void BreakHandler::append(BreakpointData *data) m_inserted.append(data); } -QList<BreakpointData *> BreakHandler::insertedBreakpoints() const +Breakpoints BreakHandler::insertedBreakpoints() const { return m_inserted; } @@ -759,23 +893,23 @@ void BreakHandler::takeInsertedBreakPoint(BreakpointData *d) m_inserted.removeAll(d); } -QList<BreakpointData *> BreakHandler::takeRemovedBreakpoints() +Breakpoints BreakHandler::takeRemovedBreakpoints() { - QList<BreakpointData *> result = m_removed; + Breakpoints result = m_removed; m_removed.clear(); return result; } -QList<BreakpointData *> BreakHandler::takeEnabledBreakpoints() +Breakpoints BreakHandler::takeEnabledBreakpoints() { - QList<BreakpointData *> result = m_enabled; + Breakpoints result = m_enabled; m_enabled.clear(); return result; } -QList<BreakpointData *> BreakHandler::takeDisabledBreakpoints() +Breakpoints BreakHandler::takeDisabledBreakpoints() { - QList<BreakpointData *> result = m_disabled; + Breakpoints result = m_disabled; m_disabled.clear(); return result; } @@ -838,11 +972,14 @@ void BreakHandler::removeAllBreakpoints() void BreakHandler::setAllPending() { + QTC_ASSERT(false, /*ABC*/ return); +/* loadBreakpoints(); for (int index = size(); --index >= 0;) at(index)->pending = true; saveBreakpoints(); updateMarkers(); +*/ } void BreakHandler::saveSessionData() @@ -876,4 +1013,14 @@ void BreakHandler::breakByFunction(const QString &functionName) updateMarkers(); } +void BreakHandler::initializeFromTemplate(BreakHandler *other) +{ + //qDebug() << "COPYING BREAKPOINTS INTO NEW SESSION"; + m_bp = other->m_bp; + updateMarkers(); +} + +} // namespace Internal +} // namespace Debugger + #include "breakhandler.moc" diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 7c9297dcc60372826403f1834901eb122e34bd66..a697474e7e4a818eb04931989c34fa90ccb9c56b 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -39,6 +39,8 @@ namespace Debugger { namespace Internal { +class DebuggerEngine; + ////////////////////////////////////////////////////////////////// // // BreakHandler @@ -50,7 +52,7 @@ class BreakHandler : public QAbstractTableModel Q_OBJECT public: - explicit BreakHandler(DebuggerManager *manager, QObject *parent = 0); + explicit BreakHandler(DebuggerEngine *engine); ~BreakHandler(); void removeAllBreakpoints(); @@ -67,23 +69,25 @@ public: void removeAt(int index); // This also deletes the marker. void clear(); // This also deletes all the marker. int indexOf(BreakpointData *data) { return m_bp.indexOf(data); } - // Find a breakpoint matching approximately the data in needle.bp*, - BreakpointData *findSimilarBreakpoint(const BreakpointData &needle) const; + // Find a breakpoint matching approximately the data in needle. + BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const; BreakpointData *findBreakpointByNumber(int bpNumber) const; int findWatchPointIndexByAddress(const QByteArray &a) const; bool watchPointAt(quint64 address) const; void updateMarkers(); - QList<BreakpointData *> insertedBreakpoints() const; + Breakpoints insertedBreakpoints() const; void takeInsertedBreakPoint(BreakpointData *); - QList<BreakpointData *> takeRemovedBreakpoints(); // Owned. - QList<BreakpointData *> takeEnabledBreakpoints(); // Not owned. - QList<BreakpointData *> takeDisabledBreakpoints(); // Not owned. + Breakpoints takeRemovedBreakpoints(); // Owned. + Breakpoints takeEnabledBreakpoints(); // Not owned. + Breakpoints takeDisabledBreakpoints(); // Not owned. QIcon breakpointIcon() const { return m_breakpointIcon; } QIcon disabledBreakpointIcon() const { return m_disabledBreakpointIcon; } QIcon pendingBreakPointIcon() const { return m_pendingBreakPointIcon; } + void initializeFromTemplate(BreakHandler *other); + public slots: void appendBreakpoint(BreakpointData *data); void toggleBreakpointEnabled(BreakpointData *data); @@ -98,7 +102,7 @@ private: int columnCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; - bool setData(const QModelIndex &index, const QVariant &, int role); + bool setData(const QModelIndex &index, const QVariant &value, int role); QVariant headerData(int section, Qt::Orientation orientation, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const; @@ -113,12 +117,16 @@ private: const QIcon m_pendingBreakPointIcon; const QIcon m_watchpointIcon; - DebuggerManager *m_manager; // Not owned. - QList<BreakpointData *> m_bp; - QList<BreakpointData *> m_inserted; // Lately inserted breakpoints. - QList<BreakpointData *> m_removed; // Lately removed breakpoints. - QList<BreakpointData *> m_enabled; // Lately enabled breakpoints. - QList<BreakpointData *> m_disabled; // Lately disabled breakpoints. + DebuggerEngine *m_engine; // Not owned. + Breakpoints m_bp; + 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; }; } // namespace Internal diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index 5a9eef7a92322d8062e90e09252e848fe82e38c5..b6044dbc9c876fa1a070e73a599688bee837829e 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -30,6 +30,8 @@ #ifndef DEBUGGER_BREAKPOINT_H #define DEBUGGER_BREAKPOINT_H +#include <QtCore/QMetaType> +#include <QtCore/QList> #include <QtCore/QString> namespace Debugger { @@ -58,13 +60,17 @@ public: BreakHandler *handler() { return m_handler; } bool isLocatedAt(const QString &fileName, int lineNumber) const; + bool isSimilarTo(const BreakpointData *needle) const; bool conditionsMatch() const; +protected: + // This copies only the static data. + BreakpointData(const BreakpointData &); + private: // Intentionally unimplemented. // Making it copyable is tricky because of the markers. void operator=(const BreakpointData &); - BreakpointData(const BreakpointData &); // Our owner BreakHandler *m_handler; // Not owned. @@ -116,8 +122,11 @@ private: BreakpointMarker *marker; }; +typedef QList<BreakpointData *> Breakpoints; } // namespace Internal } // namespace Debugger +Q_DECLARE_METATYPE(Debugger::Internal::BreakpointData *); + #endif // DEBUGGER_BREAKPOINT_H diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index b2174bad41b0b95bdc7d6b2ebbd53e052b872073..0195ba3c51661e3ca31f7316293a327b7bafb185 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -29,11 +29,8 @@ #include "breakwindow.h" -#include "breakhandler.h" -#include "threadshandler.h" #include "debuggeractions.h" -#include "debuggermanager.h" -#include "stackhandler.h" +#include "debuggerconstants.h" #include "ui_breakcondition.h" #include "ui_breakbyfunction.h" @@ -41,9 +38,6 @@ #include <utils/savedaction.h> #include <QtCore/QDebug> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtCore/QFileInfoList> #include <QtGui/QAction> #include <QtGui/QHeaderView> @@ -54,8 +48,9 @@ #include <QtGui/QToolButton> #include <QtGui/QTreeView> -using Debugger::Internal::BreakWindow; +namespace Debugger { +namespace Internal { /////////////////////////////////////////////////////////////////////// // @@ -83,9 +78,11 @@ public: // /////////////////////////////////////////////////////////////////////// -BreakWindow::BreakWindow(Debugger::DebuggerManager *manager) - : m_manager(manager), m_alwaysResizeColumnsToContents(false) +BreakWindow::BreakWindow(QWidget *parent) + : QTreeView(parent) { + m_alwaysResizeColumnsToContents = false; + QAction *act = theDebuggerAction(UseAlternatingRowColors); setFrameStyle(QFrame::NoFrame); setAttribute(Qt::WA_MacShowFocusRect, false); @@ -104,6 +101,10 @@ BreakWindow::BreakWindow(Debugger::DebuggerManager *manager) this, SLOT(showAddressColumn(bool))); } +BreakWindow::~BreakWindow() +{ +} + void BreakWindow::showAddressColumn(bool on) { setColumnHidden(7, !on); @@ -112,9 +113,9 @@ void BreakWindow::showAddressColumn(bool on) static QModelIndexList normalizeIndexes(const QModelIndexList &list) { QModelIndexList res; - foreach (const QModelIndex &idx, list) - if (idx.column() == 0) - res.append(idx); + foreach (const QModelIndex &index, list) + if (index.column() == 0) + res.append(index); return res; } @@ -147,7 +148,6 @@ void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; - const QAbstractItemModel *itemModel = model(); QItemSelectionModel *sm = selectionModel(); QTC_ASSERT(sm, return); QModelIndexList si = sm->selectedIndexes(); @@ -156,8 +156,9 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0)); si = normalizeIndexes(si); - const int rowCount = itemModel->rowCount(); - const unsigned engineCapabilities = m_manager->debuggerCapabilities(); + const int rowCount = model()->rowCount(); + const unsigned engineCapabilities = + model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt(); QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu); deleteAction->setEnabled(si.size() > 0); @@ -170,10 +171,10 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) QList<int> breakPointsOfFile; if (indexUnderMouse.isValid()) { const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2); - const QString file = itemModel->data(index).toString(); + const QString file = model()->data(index).toString(); if (!file.isEmpty()) { for (int i = 0; i < rowCount; i++) - if (itemModel->data(itemModel->index(i, 2)).toString() == file) + if (model()->data(model()->index(i, 2)).toString() == file) breakPointsOfFile.push_back(i); if (breakPointsOfFile.size() > 1) { deleteByFileAction = @@ -200,7 +201,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) new QAction(tr("Edit Breakpoint..."), &menu); editBreakpointAction->setEnabled(si.size() > 0); - int threadId = m_manager->threadsHandler()->currentThreadId(); + int threadId = model()->data(QModelIndex(), CurrentThreadIdRole).toInt(); QString associateTitle = threadId == -1 ? tr("Associate Breakpoint With All Threads") : tr("Associate Breakpoint With Thread %1").arg(threadId); @@ -210,11 +211,12 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *synchronizeAction = new QAction(tr("Synchronize Breakpoints"), &menu); synchronizeAction->setEnabled( - Debugger::DebuggerManager::instance()->debuggerActionsEnabled()); + model()->data(QModelIndex(), EngineActionsEnabledRole).toBool()); QModelIndex idx0 = (si.size() ? si.front() : QModelIndex()); QModelIndex idx2 = idx0.sibling(idx0.row(), 2); - bool enabled = si.isEmpty() || itemModel->data(idx0, Qt::UserRole).toBool(); + bool enabled = si.isEmpty() + || idx0.data(BreakpointEnabledRole).toBool(); const QString str5 = si.size() > 1 ? enabled @@ -226,7 +228,8 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *toggleEnabledAction = new QAction(str5, &menu); toggleEnabledAction->setEnabled(si.size() > 0); - const bool fullpath = si.isEmpty() || itemModel->data(idx2, Qt::UserRole).toBool(); + const bool fullpath = si.isEmpty() + || idx2.data(BreakpointEnabledRole).toBool(); const QString str6 = fullpath ? tr("Use Short Path") : tr("Use Full Path"); QAction *pathAction = new QAction(str6, &menu); pathAction->setEnabled(si.size() > 0); @@ -285,7 +288,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) else if (act == associateBreakpointAction) associateBreakpoint(si, threadId); else if (act == synchronizeAction) - emit breakpointSynchronizationRequested(); + setModelData(RequestSynchronizeBreakpointsRole); else if (act == toggleEnabledAction) setBreakpointsEnabled(si, !enabled); else if (act == pathAction) @@ -293,37 +296,35 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) else if (act == breakAtFunctionAction) { BreakByFunctionDialog dlg(this); if (dlg.exec()) - emit breakByFunctionRequested(dlg.functionName()); + setModelData(RequestBreakByFunctionRole, dlg.functionName()); } else if (act == breakAtMainAction) - emit breakByFunctionMainRequested(); + setModelData(RequestBreakByFunctionMainRole); else if (act == breakAtThrowAction) - emit breakByFunctionRequested("__cxa_throw"); + setModelData(RequestBreakByFunctionRole, "__cxa_throw"); else if (act == breakAtCatchAction) - emit breakByFunctionRequested("__cxa_begin_catch"); + setModelData(RequestBreakByFunctionRole, "__cxa_begin_catch"); } void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled) { - foreach (const QModelIndex &idx, list) - model()->setData(idx, enabled, Qt::UserRole + 1); - emit breakpointSynchronizationRequested(); + foreach (const QModelIndex &index, list) + setModelData(BreakpointEnabledRole, enabled, index); + setModelData(RequestSynchronizeBreakpointsRole); } void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath) { - foreach (const QModelIndex &idx, list) { - QModelIndex idx2 = idx.sibling(idx.row(), 2); - model()->setData(idx2, fullpath, Qt::UserRole + 2); - } - emit breakpointSynchronizationRequested(); + foreach (const QModelIndex &index, list) + setModelData(BreakpointUseFullPathRole, fullpath, index); + setModelData(RequestSynchronizeBreakpointsRole); } void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes) { QTC_ASSERT(!indexes.isEmpty(), return); QList<int> list; - foreach (const QModelIndex &idx, indexes) - list.append(idx.row()); + foreach (const QModelIndex &index, indexes) + list.append(index.row()); deleteBreakpoints(list); } @@ -334,12 +335,12 @@ void BreakWindow::deleteBreakpoints(QList<int> list) const int firstRow = list.front(); qSort(list.begin(), list.end()); for (int i = list.size(); --i >= 0; ) - emit breakpointDeleted(list.at(i)); + setModelData(RequestRemoveBreakpointByIndexRole, list.at(i)); const int row = qMin(firstRow, model()->rowCount() - 1); if (row >= 0) setCurrentIndex(model()->index(row, 0)); - emit breakpointSynchronizationRequested(); + setModelData(RequestSynchronizeBreakpointsRole); } void BreakWindow::editBreakpoint(const QModelIndexList &list) @@ -350,9 +351,8 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list) QTC_ASSERT(!list.isEmpty(), return); QModelIndex idx = list.front(); - int row = idx.row(); + const int row = idx.row(); dlg.setWindowTitle(tr("Conditions on Breakpoint %1").arg(row)); - int role = Qt::UserRole + 1; ui.lineEditFunction->hide(); ui.labelFunction->hide(); ui.lineEditFileName->hide(); @@ -360,18 +360,12 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list) ui.lineEditLineNumber->hide(); ui.labelLineNumber->hide(); QAbstractItemModel *m = model(); - //ui.lineEditFunction->setText( - // m->data(idx.sibling(row, 1), role).toString()); - //ui.lineEditFileName->setText( - // m->data(idx.sibling(row, 2), role).toString()); - //ui.lineEditLineNumber->setText( - // m->data(idx.sibling(row, 3), role).toString()); ui.lineEditCondition->setText( - m->data(idx.sibling(row, 4), role).toString()); + m->data(idx, BreakpointConditionRole).toString()); ui.lineEditIgnoreCount->setText( - m->data(idx.sibling(row, 5), role).toString()); + m->data(idx, BreakpointIgnoreCountRole).toString()); ui.lineEditThreadSpec->setText( - m->data(idx.sibling(row, 6), role).toString()); + m->data(idx, BreakpointThreadSpecRole).toString()); if (dlg.exec() == QDialog::Rejected) return; @@ -380,11 +374,11 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list) //m->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text()); //m->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text()); //m->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text()); - m->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text()); - m->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text()); - m->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text()); + m->setData(idx, ui.lineEditCondition->text(), BreakpointConditionRole); + m->setData(idx, ui.lineEditIgnoreCount->text(), BreakpointIgnoreCountRole); + m->setData(idx, ui.lineEditThreadSpec->text(), BreakpointThreadSpecRole); } - emit breakpointSynchronizationRequested(); + setModelData(RequestSynchronizeBreakpointsRole); } void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId) @@ -392,9 +386,9 @@ void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId) QString str; if (threadId != -1) str = QString::number(threadId); - foreach (const QModelIndex &idx, list) - model()->setData(idx.sibling(idx.row(), 6), str); - emit breakpointSynchronizationRequested(); + foreach (const QModelIndex &index, list) + setModelData(BreakpointThreadSpecRole, str, index); + setModelData(RequestSynchronizeBreakpointsRole); } void BreakWindow::resizeColumnsToContents() @@ -412,8 +406,46 @@ void BreakWindow::setAlwaysResizeColumnsToContents(bool on) header()->setResizeMode(i, mode); } -void BreakWindow::rowActivated(const QModelIndex &idx) +void BreakWindow::rowActivated(const QModelIndex &index) +{ + setModelData(RequestActivateBreakpointRole, index.row()); +} + +BreakpointData *BreakWindow::findSimilarBreakpoint(const BreakpointData *needle0) +{ + BreakpointData *needle = const_cast<BreakpointData *>(needle0); + QVariant v = QVariant::fromValue<BreakpointData *>(needle); + setModelData(RequestFindSimilarBreakpointRole, v); + QTC_ASSERT(model(), return false); + v = model()->data(QModelIndex(), RequestFindSimilarBreakpointRole); + return v.value<BreakpointData *>(); +} + +void BreakWindow::appendBreakpoint(BreakpointData *data) +{ + QVariant v = QVariant::fromValue<BreakpointData *>(data); + setModelData(RequestAppendBreakpointRole, v); +} + +void BreakWindow::removeBreakpoint(BreakpointData *data) { - emit breakpointActivated(idx.row()); + QVariant v = QVariant::fromValue<BreakpointData *>(data); + setModelData(RequestRemoveBreakpointRole, v); } +void BreakWindow::updateBreakpoint(BreakpointData *data) +{ + QVariant v = QVariant::fromValue<BreakpointData *>(data); + setModelData(RequestUpdateBreakpointRole, v); +} + +void BreakWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) +{ + QTC_ASSERT(model(), return); + model()->setData(index, value, role); +} + + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index b3828cae455d56e6045d56b826068aada9dbe03d..3a5d5a18ba9904c17213e3b5907fd9004d49c478 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -1,5 +1,4 @@ /************************************************************************** -QT_END_NAMESPACE ** ** This file is part of Qt Creator ** @@ -31,12 +30,11 @@ QT_END_NAMESPACE #ifndef DEBUGGER_BREAKWINDOW_H #define DEBUGGER_BREAKWINDOW_H +#include "breakpoint.h" + #include <QtGui/QTreeView> namespace Debugger { - -class DebuggerManager; - namespace Internal { class BreakWindow : public QTreeView @@ -44,31 +42,30 @@ class BreakWindow : public QTreeView Q_OBJECT public: - explicit BreakWindow(DebuggerManager *manager); + explicit BreakWindow(QWidget *parent = 0); + ~BreakWindow(); + + BreakpointData *findSimilarBreakpoint(const BreakpointData *needle); + void updateBreakpoint(BreakpointData *data); + void appendBreakpoint(BreakpointData *data); + void removeBreakpoint(BreakpointData *data); + QVariant modelData(int role, int index); public slots: void resizeColumnsToContents(); void setAlwaysResizeColumnsToContents(bool on); -signals: - void breakpointDeleted(int index); - void breakpointActivated(int index); - void breakpointSynchronizationRequested(); - void breakByFunctionRequested(const QString &functionName); - void breakByFunctionMainRequested(); - private slots: void rowActivated(const QModelIndex &index); void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } void showAddressColumn(bool on); -protected: +private: void resizeEvent(QResizeEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void keyPressEvent(QKeyEvent *ev); void mouseDoubleClickEvent(QMouseEvent *ev); -private: void deleteBreakpoints(const QModelIndexList &list); void deleteBreakpoints(QList<int> rows); void editBreakpoint(const QModelIndexList &list); @@ -76,11 +73,12 @@ private: void setBreakpointsEnabled(const QModelIndexList &list, bool enabled); void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath); - DebuggerManager *m_manager; + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); + bool m_alwaysResizeColumnsToContents; }; - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/breakpoint.h b/src/plugins/debugger/cdb/breakpoint.h index 38b31d3411eb9966323a77d1c378fe9a25ffb9fb..e68ad07d712fe300b1ae5580d5c04644aea3c40c 100644 --- a/src/plugins/debugger/cdb/breakpoint.h +++ b/src/plugins/debugger/cdb/breakpoint.h @@ -47,6 +47,8 @@ namespace CdbCore { * When/How many times it triggers can be influenced by * condition/ignorecount and 'oneshot'-flag. */ +// FIXME: Merge with/derive from Debugger::Internal::Breakpoint + struct BreakPoint { enum Type { Code, // Stop in code. diff --git a/src/plugins/debugger/cdb/cdbcore.pri b/src/plugins/debugger/cdb/cdbcore.pri index 7c65cada5ecaddb37186711a168b1afb75ac5d46..e42c1e513cc17d42e09f67075b2354813bdec70e 100644 --- a/src/plugins/debugger/cdb/cdbcore.pri +++ b/src/plugins/debugger/cdb/cdbcore.pri @@ -1,6 +1,10 @@ # Detect presence of "Debugging Tools For Windows" # in case VS compilers are used. +# FIXME +CDB_PATH="" +false { + win32 { contains(QMAKE_CXX, cl) { @@ -50,3 +54,5 @@ LIBS+=-lpsapi } # exists($$CDB_PATH) } # (QMAKE_CXX, cl) } # win32 + +} # false diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 9a86abe7eb6be6d93e456b6977364e92b0516a57..8b790bdb66088311ea4e0e65dd3c91622ade7d35 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -45,7 +45,6 @@ #include "debuggermainwindow.h" #include "debuggeractions.h" -#include "debuggermanager.h" #include "breakhandler.h" #include "stackhandler.h" #include "watchhandler.h" @@ -83,6 +82,7 @@ static const char *localSymbolRootC = "local"; namespace Debugger { namespace Internal { +CdbOptionsPage *theOptionsPage = 0; typedef QList<WatchData> WatchList; // ----- Message helpers @@ -119,9 +119,8 @@ static QString msgFunctionFailed(const char *func, const QString &why) // --- CdbDebugEnginePrivate -CdbDebugEnginePrivate::CdbDebugEnginePrivate(const QSharedPointer<CdbOptions> &options, - CdbDebugEngine *engine) : - m_options(options), +CdbDebugEnginePrivate::CdbDebugEnginePrivate(CdbDebugEngine *engine) : + m_options(theOptionsPage->options()), m_hDebuggeeProcess(0), m_hDebuggeeThread(0), m_breakEventMode(BreakEventHandle), @@ -159,11 +158,10 @@ bool CdbDebugEnginePrivate::init(QString *errorMessage) return true; } -IDebuggerEngine *CdbDebugEngine::create(Debugger::DebuggerManager *manager, - const QSharedPointer<CdbOptions> &options, - QString *errorMessage) +DebuggerEngine *CdbDebugEngine::create(const DebuggerStartParameters &sp, + QString *errorMessage) { - CdbDebugEngine *rc = new CdbDebugEngine(manager, options); + CdbDebugEngine *rc = new CdbDebugEngine(sp); if (rc->m_d->init(errorMessage)) { rc->syncDebuggerPaths(); return rc; @@ -184,11 +182,6 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate() cleanStackTrace(); } -DebuggerManager *CdbDebugEnginePrivate::manager() const -{ - return m_engine->manager(); -} - void CdbDebugEnginePrivate::clearForRun() { if (debugCDB) @@ -212,9 +205,9 @@ void CdbDebugEnginePrivate::cleanStackTrace() m_editorToolTipCache.clear(); } -CdbDebugEngine::CdbDebugEngine(DebuggerManager *manager, const QSharedPointer<CdbOptions> &options) : - IDebuggerEngine(manager), - m_d(new CdbDebugEnginePrivate(options, this)) +CdbDebugEngine::CdbDebugEngine(const DebuggerStartParameters &startParameters) : + DebuggerEngine(startParamters), + m_d(new CdbDebugEnginePrivate(this)) { m_d->m_consoleStubProc.setMode(Utils::ConsoleProcess::Suspend); connect(&m_d->m_consoleStubProc, SIGNAL(processMessage(QString,bool)), @@ -234,7 +227,7 @@ void CdbDebugEngine::setState(DebuggerState state, const char *func, int line) { if (debugCDB) qDebug() << "setState(" << state << ") at " << func << ':' << line; - IDebuggerEngine::setState(state); + DebuggerEngine::setState(state); } void CdbDebugEngine::shutdown() @@ -392,6 +385,7 @@ void CdbDebugEngine::startDebugger() if (m_d->m_hDebuggeeProcess) { warning(QLatin1String("Internal error: Attempt to start debugger while another process is being debugged.")); setState(AdapterStartFailed, Q_FUNC_INFO, __LINE__); + setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); emit startFailed(); return; } @@ -400,6 +394,7 @@ void CdbDebugEngine::startDebugger() case AttachToRemote: warning(QLatin1String("Internal error: Mode not supported.")); setState(AdapterStartFailed, Q_FUNC_INFO, __LINE__); + setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); emit startFailed(); break; default: @@ -415,24 +410,24 @@ void CdbDebugEngine::startDebugger() showMessage(errorMessage, LogWarning); m_d->setVerboseSymbolLoading(m_d->m_options->verboseSymbolLoading); // Figure out dumper. @TODO: same in gdb... - const QString dumperLibName = QDir::toNativeSeparators(manager()->qtDumperLibraryName()); + const QString dumperLibName = QDir::toNativeSeparators(qtDumperLibraryName()); bool dumperEnabled = m_d->m_mode != AttachCore && m_d->m_mode != AttachCrashedExternal - && manager()->qtDumperLibraryEnabled(); + && qtDumperLibraryEnabled(); if (dumperEnabled) { const QFileInfo fi(dumperLibName); if (!fi.isFile()) { - const QStringList &locations = manager()->qtDumperLibraryLocations(); + const QStringList &locations = qtDumperLibraryLocations(); const QString loc = locations.join(QLatin1String(", ")); const QString msg = tr("The dumper library was not found at %1.").arg(loc); - manager()->showQtDumperLibraryWarning(msg); + showQtDumperLibraryWarning(msg); dumperEnabled = false; } } m_d->m_dumper->reset(dumperLibName, dumperEnabled); setState(InferiorStarting, Q_FUNC_INFO, __LINE__); - manager()->showStatusMessage("Starting Debugger", messageTimeOut); + showStatusMessage("Starting Debugger", messageTimeOut); bool rc = false; bool needWatchTimer = false; @@ -474,11 +469,11 @@ void CdbDebugEngine::startDebugger() if (rc) { if (needWatchTimer) m_d->startWatchTimer(); - emit startSuccessful(); + startSuccessful(); } else { warning(errorMessage); setState(InferiorStartFailed, Q_FUNC_INFO, __LINE__); - emit startFailed(); + startFailed(); } } @@ -543,7 +538,7 @@ void CdbDebugEngine::processTerminated(unsigned long exitCode) m_d->clearForRun(); setState(InferiorShutDown, Q_FUNC_INFO, __LINE__); // Avoid calls from event handler. - QTimer::singleShot(0, manager(), SLOT(exitDebugger())); + QTimer::singleShot(0, this, SLOT(quitDebugger())); } bool CdbDebugEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessage) @@ -680,15 +675,14 @@ void CdbDebugEngine::updateWatchData(const WatchData &incomplete) if (debugCDBWatchHandling) qDebug() << Q_FUNC_INFO << "\n " << incomplete.toString(); - WatchHandler *watchHandler = manager()->watchHandler(); if (incomplete.iname.startsWith("watch.")) { WatchData watchData = incomplete; evaluateWatcher(&watchData); - watchHandler->insertData(watchData); + watchHandler()->insertData(watchData); return; } - const int frameIndex = manager()->stackHandler()->currentIndex(); + const int frameIndex = stackHandler()->currentIndex(); bool success = false; QString errorMessage; @@ -696,14 +690,14 @@ void CdbDebugEngine::updateWatchData(const WatchData &incomplete) CdbSymbolGroupContext *sg = m_d->m_currentStackTrace->cdbSymbolGroupContextAt(frameIndex, &errorMessage); if (!sg) break; - if (!sg->completeData(incomplete, watchHandler, &errorMessage)) + if (!sg->completeData(incomplete, watchHandler(), &errorMessage)) break; success = true; } while (false); if (!success) warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); if (debugCDBWatchHandling > 1) - qDebug() << *manager()->watchHandler()->model(LocalsWatch); + qDebug() << *watchHandler()->model(LocalsWatch); } // Continue inferior with a debugger command, such as "p", "pt" @@ -771,7 +765,7 @@ bool CdbDebugEngine::step(unsigned long executionStatus) const int triggeringEventThread = m_d->m_eventThreadId; const bool sameThread = triggeringEventThread == -1 || m_d->m_currentThreadId == triggeringEventThread - || manager()->threadsHandler()->threads().size() == 1; + || threadsHandler()->threads().size() == 1; m_d->clearForRun(); // clears thread ids m_d->updateCodeLevel(); // Step by instruction or source line setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); @@ -819,12 +813,12 @@ bool CdbDebugEngine::step(unsigned long executionStatus) void CdbDebugEngine::executeStep() { - step(manager()->isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_INTO : DEBUG_STATUS_STEP_INTO); + step(isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_INTO : DEBUG_STATUS_STEP_INTO); } void CdbDebugEngine::executeNext() { - step(manager()->isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_OVER : DEBUG_STATUS_STEP_OVER); + step(isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_OVER : DEBUG_STATUS_STEP_OVER); } void CdbDebugEngine::executeStepI() @@ -839,7 +833,7 @@ void CdbDebugEngine::executeNextI() void CdbDebugEngine::executeStepOut() { - if (!manager()->isReverseDebugging()) + if (!isReverseDebugging()) step(CdbExtendedExecutionStatusStepOut); } @@ -887,8 +881,8 @@ bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage) clearForRun(); updateCodeLevel(); killWatchTimer(); - manager()->resetLocation(); - manager()->showStatusMessage(CdbDebugEngine::tr("Running requested..."), messageTimeOut); + m_engine->resetLocation(); + m_engine->showStatusMessage(CdbDebugEngine::tr("Running requested..."), messageTimeOut); if (!continueInferiorProcess(errorMessage)) break; @@ -988,7 +982,7 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v { if (debugCDB) qDebug() << Q_FUNC_INFO << expr << value; - const int frameIndex = manager()->stackHandler()->currentIndex(); + const int frameIndex = stackHandler()->currentIndex(); QString errorMessage; bool success = false; do { @@ -999,11 +993,10 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v if (!sg->assignValue(expr, value, &newValue, &errorMessage)) break; // Update view - WatchHandler *watchHandler = manager()->watchHandler(); - if (WatchData *fwd = watchHandler->findItem(expr.toLatin1())) { + if (WatchData *fwd = watchHandler()->findItem(expr.toLatin1())) { fwd->setValue(newValue); - watchHandler->insertData(*fwd); - watchHandler->updateWatchers(); + watchHandler()->insertData(*fwd); + watchHandler()->updateWatchers(); } success = true; } while (false); @@ -1032,24 +1025,22 @@ void CdbDebugEngine::activateFrame(int frameIndex) QString errorMessage; bool success = false; - StackHandler *stackHandler = manager()->stackHandler(); do { - WatchHandler *watchHandler = manager()->watchHandler(); - const int oldIndex = stackHandler->currentIndex(); - if (frameIndex >= stackHandler->stackSize()) { - errorMessage = msgStackIndexOutOfRange(frameIndex, stackHandler->stackSize()); + const int oldIndex = stackHandler()->currentIndex(); + if (frameIndex >= stackHandler()->stackSize()) { + errorMessage = msgStackIndexOutOfRange(frameIndex, stackHandler()->stackSize()); break; } if (oldIndex != frameIndex) - stackHandler->setCurrentIndex(frameIndex); + stackHandler()->setCurrentIndex(frameIndex); - const StackFrame &frame = stackHandler->currentFrame(); + const StackFrame &frame = stackHandler()->currentFrame(); const bool showAssembler = !frame.isUsable(); if (showAssembler) { // Assembly code: Clean out model and force instruction mode. - watchHandler->beginCycle(); - watchHandler->endCycle(); + watchHandler()->beginCycle(); + watchHandler()->endCycle(); QAction *assemblerAction = theDebuggerAction(OperateByInstruction); if (!assemblerAction->isChecked()) assemblerAction->trigger(); @@ -1057,20 +1048,22 @@ void CdbDebugEngine::activateFrame(int frameIndex) break; } - manager()->gotoLocation(frame, true); + gotoLocation(frame, true); if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) { - watchHandler->beginCycle(); + watchHandler()->beginCycle(); if (CdbSymbolGroupContext *sgc = m_d->getSymbolGroupContext(frameIndex, &errorMessage)) - success = sgc->populateModelInitially(watchHandler, &errorMessage); - watchHandler->endCycle(); + success = sgc->populateModelInitially(watchHandler(), &errorMessage); + watchHandler()->endCycle(); } else { success = true; } } while (false); + if (!success) { const QString msg = QString::fromLatin1("Internal error: activateFrame() failed for frame #%1 of %2, thread %3: %4"). - arg(frameIndex).arg(stackHandler->stackSize()).arg(m_d->m_currentThreadId).arg(errorMessage); + arg(frameIndex).arg(stackHandler()->stackSize()). + arg(m_d->m_currentThreadId).arg(errorMessage); warning(msg); } m_d->m_firstActivatedFrame = false; @@ -1081,14 +1074,13 @@ void CdbDebugEngine::selectThread(int index) if (debugCDB) qDebug() << Q_FUNC_INFO << index; - //reset location arrow - manager()->resetLocation(); + // Reset location arrow. + resetLocation(); - ThreadsHandler *threadsHandler = manager()->threadsHandler(); - threadsHandler->setCurrentThread(index); - const int newThreadId = threadsHandler->threads().at(index).id; + threadsHandler()->setCurrentThread(index); + const int newThreadId = threadsHandler()->threads().at(index).id; if (newThreadId != m_d->m_currentThreadId) { - m_d->m_currentThreadId = threadsHandler->threads().at(index).id; + m_d->m_currentThreadId = threadsHandler()->threads().at(index).id; m_d->updateStackTrace(); } } @@ -1133,7 +1125,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa QStringList warnings; const bool ok = synchronizeBreakPoints(interfaces().debugControl, interfaces().debugSymbols, - manager()->breakHandler(), + breakHandler(), errorMessage, &warnings); if (const int warningsCount = warnings.size()) for (int w = 0; w < warningsCount; w++) @@ -1313,7 +1305,7 @@ void CdbDebugEnginePrivate::notifyException(long code, bool fatal, const QString static int threadIndexById(const ThreadsHandler *threadsHandler, int id) { - const QList<ThreadData> threads = threadsHandler->threads(); + const Threads threads = threadsHandler->threads(); const int count = threads.count(); for (int i = 0; i < count; i++) if (threads.at(i).id == id) @@ -1343,7 +1335,7 @@ void CdbDebugEnginePrivate::handleDebugEvent() // Get thread to stop and its index. If avoidable, do not use // the artifical thread that is created when interrupting, // use the oldest thread 0 instead. - ThreadsHandler *threadsHandler = manager()->threadsHandler(); + ThreadsHandler *threadsHandler = m_engine->threadsHandler(); m_currentThreadId = m_interrupted ? 0 : m_eventThreadId; int currentThreadIndex = -1; m_currentThreadId = -1; @@ -1418,13 +1410,13 @@ ULONG CdbDebugEnginePrivate::updateThreadList() if (debugCDB) qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; - QList<ThreadData> threads; + Threads threads; ULONG currentThreadId; QString errorMessage; // When interrupting, an artifical thread with a breakpoint is created. if (!CdbStackTraceContext::getThreads(interfaces(), &threads, ¤tThreadId, &errorMessage)) m_engine->warning(errorMessage); - manager()->threadsHandler()->setThreads(threads); + m_engine->threadsHandler()->setThreads(threads); return currentThreadId; } @@ -1527,19 +1519,19 @@ void CdbDebugEnginePrivate::updateStackTrace() qDebug() << "updateStackTrace() current: " << m_currentThreadId << " dumper=" << dumperThread; m_dumper->setDumperCallThread(dumperThread); // Display frames - manager()->stackHandler()->setFrames(stackFrames); + m_engine->stackHandler()->setFrames(stackFrames); m_firstActivatedFrame = true; if (current >= 0) { - manager()->stackHandler()->setCurrentIndex(current); + m_engine->stackHandler()->setCurrentIndex(current); m_engine->activateFrame(current); } else { // Clean out variables - manager()->watchHandler()->beginCycle(); - manager()->watchHandler()->endCycle(); + m_engine->watchHandler()->beginCycle(); + m_engine->watchHandler()->endCycle(); } - manager()->watchHandler()->updateWatchers(); + m_engine->watchHandler()->updateWatchers(); // Show message after a lengthy dumper initialization - manager()->showStatusMessage(stopMessage, 15000); + m_engine->showMessage(stopMessage, StatusBar, 15000); } void CdbDebugEnginePrivate::updateModules() @@ -1618,30 +1610,28 @@ unsigned CdbDebugEngine::debuggerCapabilities() const |BreakOnThrowAndCatchCapability; // Sort-of: Can break on throw(). } -// Accessed by DebuggerManager -IDebuggerEngine *createCdbEngine(DebuggerManager *parent, - bool cmdLineEnabled, - QList<Core::IOptionsPage*> *opts) +// Accessed by RunControlFactory +DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp) { - // Create options page - QSharedPointer<CdbOptions> options(new CdbOptions); - options->fromSettings(Core::ICore::instance()->settings()); - CdbOptionsPage *optionsPage = new CdbOptionsPage(options); - opts->push_back(optionsPage); - if (!cmdLineEnabled || !options->enabled) - return 0; // Create engine QString errorMessage; - IDebuggerEngine *engine = CdbDebugEngine::create(parent, options, &errorMessage); + DebuggerEngine *engine = CdbDebugEngine::create(sp, &errorMessage); if (engine) { - QObject::connect(optionsPage, SIGNAL(debuggerPathsChanged()), engine, SLOT(syncDebuggerPaths())); + QObject::connect(theOptionsPage, SIGNAL(debuggerPathsChanged()), engine, SLOT(syncDebuggerPaths())); } else { - optionsPage->setFailureMessage(errorMessage); + theOptionsPage->setFailureMessage(errorMessage); qWarning("%s\n" ,qPrintable(errorMessage)); } return engine; } +void addCdbOptionPages(QList<Core::IOptionsPage *> *opts) +{ + // FIXME: HACK (global variable) + theOptionsPage = new CdbOptionsPage; + opts->push_back(theOptionsPage); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h index 455fec4f3b67f64e263eaa8593708b2bfbb2a412..265e0bb1bafb1335fb59097790c9d679a467db5a 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.h +++ b/src/plugins/debugger/cdb/cdbdebugengine.h @@ -30,14 +30,11 @@ #ifndef DEBUGGER_CDBENGINE_H #define DEBUGGER_CDBENGINE_H -#include "idebuggerengine.h" -#include "debuggermanager.h" +#include "debuggerengine.h" #include <QtCore/QSharedPointer> namespace Debugger { -class DebuggerManager; - namespace Internal { class DisassemblerViewAgent; @@ -46,19 +43,17 @@ class CdbDebugOutput; class CdbDebugEnginePrivate; struct CdbOptions; -class CdbDebugEngine : public IDebuggerEngine +class CdbDebugEngine : public DebuggerEngine { Q_DISABLE_COPY(CdbDebugEngine) Q_OBJECT - explicit CdbDebugEngine(DebuggerManager *parent, - const QSharedPointer<CdbOptions> &options); + explicit CdbDebugEngine(const DebuggerStartParameters &sp); public: ~CdbDebugEngine(); // Factory function that returns 0 if the debug engine library cannot be found. - static IDebuggerEngine *create(DebuggerManager *parent, - const QSharedPointer<CdbOptions> &options, + static DebuggerEngine *create(const DebuggerStartParameters &sp, QString *errorMessage); virtual void shutdown(); diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index 25d22d999dd349d3a244b8ded6698cebffa845a8..810a4b1d1dbf56575c5e6664697d1f8ef7a6233c 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -31,18 +31,17 @@ #define DEBUGGER_CDBENGINEPRIVATE_H #include "coreengine.h" +#include "debuggerconstants.h" #include "cdboptions.h" #include "cdbdumperhelper.h" #include "stackhandler.h" -#include "debuggermanager.h" #include <utils/consoleprocess.h> + #include <QtCore/QSharedPointer> #include <QtCore/QMap> namespace Debugger { -class DebuggerManager; - namespace Internal { class WatchHandler; @@ -68,8 +67,7 @@ public: StoppedOther }; - explicit CdbDebugEnginePrivate(const QSharedPointer<CdbOptions> &options, - CdbDebugEngine* engine); + explicit CdbDebugEnginePrivate(CdbDebugEngine* engine); ~CdbDebugEnginePrivate(); bool init(QString *errorMessage); @@ -128,7 +126,6 @@ public: QSharedPointer<CdbDumperHelper> m_dumper; CdbDebugEngine *m_engine; - inline DebuggerManager *manager() const; CdbStackTraceContext *m_currentStackTrace; EditorToolTipCache m_editorToolTipCache; diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index ef0171140b0e78f3533c0afe313a31264a5a5478..a0ec96989ba51d220fd93b120e5893a5d9883ce8 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -31,7 +31,6 @@ #include "cdbdebugengine.h" #include "cdbexceptionutils.h" #include "cdbdebugengine_p.h" -#include "debuggermanager.h" #include <QtCore/QDebug> #include <QtCore/QTextStream> @@ -42,7 +41,7 @@ namespace Internal { // ---------- CdbDebugEventCallback -CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) : +CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine *dbg) : m_pEngine(dbg) { } diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp index 3cd8588c6a1fb60251409ecbd598e2f99b203c8d..54840d7c06875b813c27c92e62be1b5b98a7ff34 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp +++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp @@ -100,7 +100,7 @@ namespace Internal { // the QtCored4.pdb file to be present as we need "qstrdup" // as dummy symbol. This is ok ATM since dumpers only // make sense for Qt apps. -static bool debuggeeLoadLibrary(CdbDebugEngine *manager, +static bool debuggeeLoadLibrary(CdbDebugEngine *cdbEngine, CdbCore::CoreEngine *engine, unsigned long threadId, const QString &moduleName, @@ -109,7 +109,8 @@ static bool debuggeeLoadLibrary(CdbDebugEngine *manager, if (loadDebug > 1) qDebug() << Q_FUNC_INFO << moduleName; // Try to ignore the breakpoints, skip stray startup-complete trap exceptions - QSharedPointer<CdbExceptionLoggerEventCallback> exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, manager)); + QSharedPointer<CdbExceptionLoggerEventCallback> + exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, cdbEngine)); CdbCore::EventCallbackRedirector eventRedir(engine, exLogger); Q_UNUSED(eventRedir) // Make a call to LoadLibraryA. First, reserve memory in debugger @@ -251,7 +252,7 @@ bool CdbDumperInitThread::ensureDumperInitialized(CdbDumperHelper &h, QString *e h.m_state = CdbDumperHelper::Disabled; // No message here *errorMessage = QCoreApplication::translate("Debugger::Internal::CdbDumperHelper", "The custom dumper library could not be initialized: %1").arg(*errorMessage); h.m_engine->showStatusMessage(*errorMessage, messageTimeOut); - h.m_engine->manager()->showQtDumperLibraryWarning(*errorMessage); + h.m_engine->showQtDumperLibraryWarning(*errorMessage); } if (loadDebug) qDebug() << Q_FUNC_INFO << '\n' << thread.m_ok; diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.h b/src/plugins/debugger/cdb/cdbdumperhelper.h index be9b10adb1639b25d677b96b2b80dc70b6aa6b79..3c88045bb892554de3d8671b502db03c13d14469 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.h +++ b/src/plugins/debugger/cdb/cdbdumperhelper.h @@ -42,9 +42,8 @@ namespace CdbCore { } namespace Debugger { -class DebuggerManager; - namespace Internal { + class CdbDumperInitThread; class CdbDebugEngine; diff --git a/src/plugins/debugger/cdb/cdboptionspage.cpp b/src/plugins/debugger/cdb/cdboptionspage.cpp index 4804a242aed6b259f0c5e4ca492ba5662331451d..93f068b52908149c7cfb6662e2742ab41131a1c5 100644 --- a/src/plugins/debugger/cdb/cdboptionspage.cpp +++ b/src/plugins/debugger/cdb/cdboptionspage.cpp @@ -138,9 +138,10 @@ QString CdbOptionsPageWidget::searchKeywords() const } // ---------- CdbOptionsPage -CdbOptionsPage::CdbOptionsPage(const QSharedPointer<CdbOptions> &options) : - m_options(options) +CdbOptionsPage::CdbOptionsPage() : + m_options(new CdbOptions) { + m_options->fromSettings(Core::ICore::instance()->settings()); } CdbOptionsPage::~CdbOptionsPage() diff --git a/src/plugins/debugger/cdb/cdboptionspage.h b/src/plugins/debugger/cdb/cdboptionspage.h index 0b49e6982d6d40bd3fc0c3714b84081640bfd3df..6323593a8208095c6fec414ac6eaeec572a7831b 100644 --- a/src/plugins/debugger/cdb/cdboptionspage.h +++ b/src/plugins/debugger/cdb/cdboptionspage.h @@ -68,7 +68,7 @@ class CdbOptionsPage : public Core::IOptionsPage Q_DISABLE_COPY(CdbOptionsPage) Q_OBJECT public: - explicit CdbOptionsPage(const QSharedPointer<CdbOptions> &options); + explicit CdbOptionsPage(); virtual ~CdbOptionsPage(); // IOptionsPage @@ -87,6 +87,7 @@ public: // Load failure messages can be displayed here void setFailureMessage(const QString &msg) { m_failureMessage = msg; } + QSharedPointer<CdbOptions> options() const { return m_options; } signals: void debuggerPathsChanged(); diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp index 23a55433017f795f9c77f7b143af72c95c7dc0e3..6fc617f532969e1b475158abe01251010a13bbbd 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -28,10 +28,12 @@ **************************************************************************/ #include "cdbstacktracecontext.h" + #include "cdbsymbolgroupcontext.h" #include "cdbdumperhelper.h" #include "cdbdebugengine_p.h" #include "debuggeractions.h" +#include "debuggerplugin.h" #include "watchutils.h" #include "threadshandler.h" @@ -61,18 +63,18 @@ CdbStackTraceContext *CdbStackTraceContext::create(const QSharedPointer<CdbDumpe return ctx; } -CdbCore::SymbolGroupContext - *CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */, - int index, - const QString &prefix, - CIDebugSymbolGroup *comSymbolGroup, - QString *errorMessage) +CdbCore::SymbolGroupContext * +CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */, + int index, + const QString &prefix, + CIDebugSymbolGroup *comSymbolGroup, + QString *errorMessage) { // Exclude uninitialized variables if desired QStringList uninitializedVariables; const CdbCore::StackFrame &frame = stackFrameAt(index); if (theDebuggerAction(UseCodeModel)->isChecked()) - getUninitializedVariables(DebuggerManager::instance()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables); + getUninitializedVariables(DebuggerPlugin::instance()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables); if (debug) qDebug() << frame << uninitializedVariables; CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(prefix, @@ -113,7 +115,7 @@ QList<StackFrame> CdbStackTraceContext::stackFrames() const } bool CdbStackTraceContext::getThreads(const CdbCore::ComInterfaces &cif, - QList<ThreadData> *threads, + Threads *threads, ULONG *currentThreadId, QString *errorMessage) { diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h index 4f5dd73d473b89d8f1c6e3cf30a76d62f2b2d853..b36a79154c2f98e22e7404206f386f41193c2091 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.h +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h @@ -32,6 +32,7 @@ #include "stackhandler.h" #include "stacktracecontext.h" +#include "threadshandler.h" #include "cdbcom.h" @@ -74,7 +75,7 @@ public: // get threads in stopped state static bool getThreads(const CdbCore::ComInterfaces &cif, - QList<ThreadData> *threads, + Threads *threads, ULONG *currentThreadId, QString *errorMessage); diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 528495e55d94125fb288a398967608c3d89d4ffd..c498f2e9328326793efa4c0739b97a4934d51517 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -21,14 +21,13 @@ HEADERS += breakhandler.h \ debuggeractions.h \ debuggerconstants.h \ debuggerdialogs.h \ - debuggermanager.h \ + debuggerengine.h \ debugger_global.h \ debuggeroutputwindow.h \ debuggerplugin.h \ debuggerrunner.h \ debuggertooltip.h \ debuggerstringutils.h \ - idebuggerengine.h \ moduleshandler.h \ moduleswindow.h \ outputcollector.h \ @@ -40,6 +39,7 @@ HEADERS += breakhandler.h \ stackwindow.h \ snapshothandler.h \ snapshotwindow.h \ + sourcefileshandler.h \ sourcefileswindow.h \ threadswindow.h \ watchhandler.h \ @@ -55,12 +55,11 @@ SOURCES += breakhandler.cpp \ debuggeragents.cpp \ debuggeractions.cpp \ debuggerdialogs.cpp \ - debuggermanager.cpp \ + debuggerengine.cpp \ debuggeroutputwindow.cpp \ debuggerplugin.cpp \ debuggerrunner.cpp \ debuggertooltip.cpp \ - idebuggerengine.cpp \ moduleshandler.cpp \ moduleswindow.cpp \ outputcollector.cpp \ @@ -71,6 +70,7 @@ SOURCES += breakhandler.cpp \ snapshotwindow.cpp \ stackhandler.cpp \ stackwindow.cpp \ + sourcefileshandler.cpp \ sourcefileswindow.cpp \ threadswindow.cpp \ watchdata.cpp \ diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index ba95f5f380e0840664e846af2491d3faac1c7332..b0211a0c328af89466d364a0328e0b8e3eef7cc9 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -64,7 +64,7 @@ namespace Internal { ////////////////////////////////////////////////////////////////////////// DebuggerSettings::DebuggerSettings(QObject *parent) - : QObject(parent), m_gdbBinaryToolChainMap(new GdbBinaryToolChainMap) + : QObject(parent) {} DebuggerSettings::~DebuggerSettings() @@ -87,7 +87,7 @@ void DebuggerSettings::readSettings(QSettings *settings) item->readSettings(settings); // Convert gdb binaries from flat settings list (see writeSettings) // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). - m_gdbBinaryToolChainMap->clear(); + m_gdbBinaryToolChainMap.clear(); const QChar separator = QLatin1Char(','); const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') + QLatin1String(debugModeGdbBinaryKeyC); @@ -102,15 +102,15 @@ void DebuggerSettings::readSettings(QSettings *settings) const QString binary = tokens.front(); tokens.pop_front(); foreach(const QString &t, tokens) - m_gdbBinaryToolChainMap->insert(binary, t.toInt()); + m_gdbBinaryToolChainMap.insert(binary, t.toInt()); } // Linux defaults #ifdef Q_OS_UNIX - if (m_gdbBinaryToolChainMap->isEmpty()) { + if (m_gdbBinaryToolChainMap.isEmpty()) { const QString gdb = QLatin1String("gdb"); - m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::GCC); - m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::OTHER); - m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::UNKNOWN); + m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::GCC); + m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::OTHER); + m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::UNKNOWN); } #endif } @@ -124,8 +124,8 @@ void DebuggerSettings::writeSettings(QSettings *settings) const 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) { + 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); @@ -255,12 +255,6 @@ DebuggerSettings *DebuggerSettings::instance() item->setTextPattern(tr("Watch Expression \"%1\" in Separate Window")); instance->insertItem(WatchExpressionInWindow, item); - item = new SavedAction(instance); - instance->insertItem(AssignValue, item); - - item = new SavedAction(instance); - instance->insertItem(AssignType, item); - item = new SavedAction(instance); instance->insertItem(WatchPoint, item); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index e0040eb09c0dfbc9d23a9c5dd5372ced8a97f430..86c11ac93e65c5d95076e5d621310f546c4168db 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -32,7 +32,6 @@ #include <QtCore/QHash> #include <QtCore/QMap> -#include <QtCore/QSharedPointer> QT_BEGIN_NAMESPACE class QAction; @@ -41,7 +40,7 @@ class QSettings; QT_END_NAMESPACE namespace Utils { - class SavedAction; +class SavedAction; } namespace Debugger { @@ -52,12 +51,14 @@ class DebuggerSettings : public QObject Q_OBJECT public: typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - typedef QSharedPointer<GdbBinaryToolChainMap> GdbBinaryToolChainMapPtr; explicit DebuggerSettings(QObject *parent = 0); ~DebuggerSettings(); - GdbBinaryToolChainMapPtr gdbBinaryToolChainMap() const { return m_gdbBinaryToolChainMap; } + GdbBinaryToolChainMap gdbBinaryToolChainMap() const + { return m_gdbBinaryToolChainMap; } + void setGdbBinaryToolChainMap(const GdbBinaryToolChainMap &map) + { m_gdbBinaryToolChainMap = map; } void insertItem(int code, Utils::SavedAction *item); Utils::SavedAction *item(int code) const; @@ -72,8 +73,7 @@ public slots: private: QHash<int, Utils::SavedAction *> m_items; - - const GdbBinaryToolChainMapPtr m_gdbBinaryToolChainMap; + GdbBinaryToolChainMap m_gdbBinaryToolChainMap; }; @@ -127,8 +127,6 @@ enum DebuggerActionCode WatchExpressionInWindow, RemoveWatchExpression, WatchPoint, - AssignValue, - AssignType, ShowStdNamespace, ShowQtNamespace, @@ -160,30 +158,6 @@ Utils::SavedAction *theDebuggerAction(int code); bool theDebuggerBoolSetting(int code); QString theDebuggerStringSetting(int code); -struct DebuggerManagerActions -{ - QAction *continueAction; - QAction *stopAction; - QAction *resetAction; // FIXME: Should not be needed in a stable release - QAction *stepAction; - QAction *stepOutAction; - QAction *runToLineAction1; // in the Debug menu - QAction *runToLineAction2; // in the text editor context menu - QAction *runToFunctionAction; - QAction *jumpToLineAction1; // in the Debug menu - QAction *jumpToLineAction2; // in the text editor context menu - QAction *returnFromFunctionAction; - QAction *nextAction; - QAction *snapshotAction; - QAction *watchAction1; // in the Debug menu - QAction *watchAction2; // in the text editor context menu - QAction *breakAction; - QAction *sepAction; - QAction *reverseDirectionAction; - QAction *frameUpAction; - QAction *frameDownAction; -}; - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index 4b0b453c58121996b989e4c316f9f07216bc62ad..cd089d803c9eb4b3451058bf12eec917633a42f8 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -28,10 +28,11 @@ **************************************************************************/ #include "debuggeragents.h" -#include "debuggermanager.h" -#include "stackframe.h" + +#include "debuggerengine.h" +#include "debuggerplugin.h" #include "debuggerstringutils.h" -#include "idebuggerengine.h" +#include "stackframe.h" #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> @@ -71,15 +72,17 @@ namespace Internal { it handles communication between the engine and the bineditor. */ -MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, quint64 addr) - : QObject(manager), m_engine(manager->currentEngine()), m_manager(manager) +MemoryViewAgent::MemoryViewAgent(DebuggerEngine *engine, quint64 addr) + : QObject(engine), m_engine(engine) { + QTC_ASSERT(engine, /**/); createBinEditor(addr); } -MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, const QString &addr) - : QObject(manager), m_engine(manager->currentEngine()), m_manager(manager) +MemoryViewAgent::MemoryViewAgent(DebuggerEngine *engine, const QString &addr) + : QObject(engine), m_engine(engine) { + QTC_ASSERT(engine, /**/); bool ok = true; createBinEditor(addr.toULongLong(&ok, 0)); //qDebug() << " ADDRESS: " << addr << addr.toUInt(&ok, 0); @@ -111,7 +114,7 @@ void MemoryViewAgent::createBinEditor(quint64 addr) QMetaObject::invokeMethod(editor->widget(), "setLazyData", Q_ARG(quint64, addr), Q_ARG(int, 1024 * 1024), Q_ARG(int, BinBlockSize)); } else { - m_manager->showMessageBox(QMessageBox::Warning, + DebuggerPlugin::instance()->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.")); @@ -122,8 +125,7 @@ void MemoryViewAgent::createBinEditor(quint64 addr) void MemoryViewAgent::fetchLazyData(Core::IEditor *editor, quint64 block, bool sync) { Q_UNUSED(sync); // FIXME: needed support for incremental searching - if (m_engine) - m_engine->fetchMemory(this, editor, BinBlockSize * block, BinBlockSize); + m_engine->fetchMemory(this, editor, BinBlockSize * block, BinBlockSize); } void MemoryViewAgent::addLazyData(QObject *editorToken, quint64 addr, @@ -150,7 +152,7 @@ class LocationMark2 : public TextEditor::ITextMark public: LocationMark2() {} - QIcon icon() const { return DebuggerManager::instance()->locationMarkIcon(); } + QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); } void updateLineNumber(int /*lineNumber*/) {} void updateBlock(const QTextBlock & /*block*/) {} void removedFromEditor() {} @@ -164,7 +166,7 @@ struct DisassemblerViewAgentPrivate QPointer<TextEditor::ITextEditor> editor; StackFrame frame; bool tryMixed; - QPointer<DebuggerManager> manager; + QPointer<DebuggerEngine> engine; LocationMark2 *locationMark; QHash<QString, QString> cache; }; @@ -201,12 +203,12 @@ private: it handles communication between the engine and the editor. */ -DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager) +DisassemblerViewAgent::DisassemblerViewAgent(DebuggerEngine *engine) : QObject(0), d(new DisassemblerViewAgentPrivate) { d->editor = 0; d->locationMark = new LocationMark2(); - d->manager = manager; + d->engine = engine; } DisassemblerViewAgent::~DisassemblerViewAgent() @@ -261,16 +263,12 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed) if (it != d->cache.end()) { QString msg = _("Use cache disassembler for '%1' in '%2'") .arg(frame.function).arg(frame.file); - QTC_ASSERT(d->manager->runControl(), /**/); - if (d->manager->runControl()) - d->manager->runControl()->showMessage(msg); + d->engine->showMessage(msg); setContents(*it); return; } } - IDebuggerEngine *engine = d->manager->currentEngine(); - QTC_ASSERT(engine, return); - engine->fetchDisassembler(this); + d->engine->fetchDisassembler(this); } void DisassemblerViewAgent::setContents(const QString &contents) diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h index fe3cc3a8552e0842190a4749e3b18ab260e3e2bb..febee6c9db1b3b337594934bfc83be358172f391 100644 --- a/src/plugins/debugger/debuggeragents.h +++ b/src/plugins/debugger/debuggeragents.h @@ -34,15 +34,14 @@ #include <QtCore/QPointer> namespace Core { - class IEditor; +class IEditor; } -namespace Debugger { -class DebuggerManager; +namespace Debugger { namespace Internal { -struct StackFrame; -class IDebuggerEngine; -struct DisassemblerViewAgentPrivate; + +class DebuggerEngine; +class StackFrame; class MemoryViewAgent : public QObject { @@ -50,8 +49,8 @@ class MemoryViewAgent : public QObject public: // Called from Gui - explicit MemoryViewAgent(DebuggerManager *manager, quint64 startaddr); - explicit MemoryViewAgent(DebuggerManager *manager, const QString &startaddr); + explicit MemoryViewAgent(DebuggerEngine *engine, quint64 startaddr); + explicit MemoryViewAgent(DebuggerEngine *engine, const QString &startaddr); ~MemoryViewAgent(); enum { BinBlockSize = 1024 }; @@ -65,19 +64,20 @@ public slots: private: Q_SLOT void createBinEditor(quint64 startAddr); - QPointer<IDebuggerEngine> m_engine; QList<QPointer<Core::IEditor> > m_editors; - QPointer<DebuggerManager> m_manager; + QPointer<DebuggerEngine> m_engine; }; +class DisassemblerViewAgentPrivate; + class DisassemblerViewAgent : public QObject { Q_OBJECT public: // Called from Gui - explicit DisassemblerViewAgent(DebuggerManager *manager); + explicit DisassemblerViewAgent(DebuggerEngine *engine); ~DisassemblerViewAgent(); void setFrame(const StackFrame &frame, bool tryMixed = true); diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 841dec77ccd92a9c3e108f1c86e9fa1f333ea262..ca15e371505d1fd7a1729273588447f1d849cd57 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -138,36 +138,132 @@ enum DebuggerCapabilities enum LogChannel { - LogInput, // Used for user input - LogMiscInput, // Used for misc stuff in the input pane - LogOutput, - LogWarning, - LogError, - LogStatus, // Used for status changed messages - LogTime, // Used for time stamp messages - LogDebug, - LogMisc, - AppOutput, - AppError, - StatusBar // LogStatus and also put to the status bar -}; - -enum ModelRoles -{ - DisplaySourceRole = 32, // Qt::UserRole, + LogInput, // Used for user input + LogMiscInput, // Used for misc stuff in the input pane + LogOutput, + LogWarning, + LogError, + LogStatus, // Used for status changed messages + LogTime, // Used for time stamp messages + LogDebug, + LogMisc, + AppOutput, + AppError, + AppStuff, + StatusBar // LogStatus and also put to the status bar +}; + +enum ModelRoles +{ + DisplaySourceRole = 32, // Qt::UserRole - EngineCapabilityRole, + EngineStateRole, + EngineCapabilitiesRole, EngineActionsEnabledRole, + // Running + RequestExecContinueRole, + RequestExecInterruptRole, + RequestExecResetRole, + RequestExecStepRole, + RequestExecStepOutRole, + RequestExecNextRole, + RequestExecRunToLineRole, + RequestExecRunToFunctionRole, + RequestExecReturnFromFunctionRole, + RequestExecJumpToLineRole, + RequestExecWatchRole, + RequestExecSnapshotRole, + RequestExecFrameDownRole, + RequestExecFrameUpRole, + RequestExecDetachRole, + RequestExecExitRole, + RequestLoadSessionDataRole, + RequestSaveSessionDataRole, + + // Breakpoints + BreakpointEnabledRole, + BreakpointUseFullPathRole, + BreakpointFunctionNameRole, + BreakpointFileNameRole, + BreakpointConditionRole, + BreakpointIgnoreCountRole, + BreakpointThreadSpecRole, + RequestActivateBreakpointRole, + RequestRemoveBreakpointRole, + RequestRemoveBreakpointByIndexRole, + RequestSynchronizeBreakpointsRole, + RequestBreakByFunctionRole, + RequestBreakByFunctionMainRole, + RequestFindSimilarBreakpointRole, + RequestAppendBreakpointRole, + RequestUpdateBreakpointRole, + + // Locals and Watchers + LocalsINameRole, + LocalsExpressionRole, + LocalsExpandedRole, // The preferred expanded state to the view + LocalsTypeFormatListRole, + LocalsTypeFormatRole, // Used to communicate alternative formats to the view + LocalsIndividualFormatRole, + LocalsAddressRole, // Memory address of variable as quint64 + LocalsRawValueRole, // Unformatted value as string + LocalsPointerValueRole, // Pointer value (address) as quint64 + LocalsIsWatchpointAtAddressRole, + LocalsIsWatchpointAtPointerValueRole, + RequestToggleWatchRole, + RequestClearCppCodeModelSnapshotRole, + RequestAssignValueRole, + RequestAssignTypeRole, + + // Stack + StackFrameAddressRole, + RequestActivateFrameRole, + RequestReloadFullStackRole, + RequestShowMemoryRole, + RequestShowDisassemblerRole, + + // Threads + CurrentThreadIdRole, + RequestSelectThreadRole, + // Modules RequestReloadModulesRole, RequestModuleSymbolsRole, RequestAllSymbolsRole, + RequestOpenFileRole, + + // Registers + RegisterNumberBaseRole, // Currently used number base + RegisterAddressRole, // Start value for opening memory view + RegisterChangedRole, // Used for painting changed values + RequestSetRegisterRole, + RequestReloadRegistersRole, // Snapshots RequestMakeSnapshotRole, RequestActivateSnapshotRole, RequestRemoveSnapshotRole, + + // Sources + RequestReloadSourceFilesRole, +}; + +enum DebuggerEngineType +{ + NoEngineType = 0, + GdbEngineType = 0x01, + ScriptEngineType = 0x02, + CdbEngineType = 0x04, + PdbEngineType = 0x08, + TcfEngineType = 0x10, + QmlEngineType = 0x20, + AllEngineTypes = GdbEngineType + | ScriptEngineType + | CdbEngineType + | PdbEngineType + | TcfEngineType + | QmlEngineType }; } // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c994407d33d408158a2c7d1ad62aafa2942227c --- /dev/null +++ b/src/plugins/debugger/debuggerengine.cpp @@ -0,0 +1,943 @@ +/************************************************************************** +** +** 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 "debuggerengine.h" + +#include "debuggeractions.h" +#include "debuggeragents.h" +#include "debuggerrunner.h" +#include "debuggeroutputwindow.h" +#include "debuggerplugin.h" +#include "debuggerstringutils.h" + +#include "breakhandler.h" +#include "moduleshandler.h" +#include "registerhandler.h" +#include "snapshothandler.h" +#include "sourcefileshandler.h" +#include "stackhandler.h" +#include "threadshandler.h" +#include "watchhandler.h" + +#include <projectexplorer/debugginghelper.h> +#include <projectexplorer/environment.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/target.h> +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication* + +#include <qt4projectmanager/qt4projectmanagerconstants.h> + +#include <utils/savedaction.h> +#include <utils/qtcassert.h> + +#include <coreplugin/icore.h> + +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QTimer> + +#include <QtGui/QAbstractItemView> +#include <QtGui/QStandardItemModel> +#include <QtGui/QAction> +#include <QtGui/QMessageBox> +#include <QtGui/QPushButton> +#include <QtGui/QTextDocument> +#include <QtGui/QTreeWidget> + + +using namespace ProjectExplorer; +using namespace Debugger; +using namespace Debugger::Internal; + + +/////////////////////////////////////////////////////////////////////// +// +// DebuggerStartParameters +// +/////////////////////////////////////////////////////////////////////// + +DebuggerStartParameters::DebuggerStartParameters() + : attachPID(-1), + useTerminal(false), + breakAtMain(false), + toolChainType(ToolChain::UNKNOWN), + startMode(NoStartMode) +{} + +void DebuggerStartParameters::clear() +{ + *this = DebuggerStartParameters(); +} + + +namespace Debugger { + +QDebug operator<<(QDebug d, DebuggerState state) +{ + return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')'; +} + +QDebug operator<<(QDebug str, const DebuggerStartParameters &sp) +{ + QDebug nospace = str.nospace(); + const QString sep = QString(QLatin1Char(',')); + nospace << "executable=" << sp.executable + << " coreFile=" << sp.coreFile + << " processArgs=" << sp.processArgs.join(sep) + << " environment=<" << sp.environment.size() << " variables>" + << " workingDir=" << sp.workingDirectory + << " attachPID=" << sp.attachPID + << " useTerminal=" << sp.useTerminal + << " remoteChannel=" << sp.remoteChannel + << " remoteArchitecture=" << sp.remoteArchitecture + << " symbolFileName=" << sp.symbolFileName + << " serverStartScript=" << sp.serverStartScript + << " toolchain=" << sp.toolChainType << '\n'; + return str; +} + + +namespace Internal { + +const char *DebuggerEngine::stateName(int s) +{ +# define SN(x) case x: return #x; + switch (s) { + SN(DebuggerNotReady) + SN(EngineStarting) + SN(AdapterStarting) + SN(AdapterStarted) + SN(AdapterStartFailed) + SN(InferiorStarting) + SN(InferiorStartFailed) + SN(InferiorRunningRequested) + SN(InferiorRunningRequested_Kill) + SN(InferiorRunning) + SN(InferiorUnrunnable) + SN(InferiorStopping) + SN(InferiorStopping_Kill) + SN(InferiorStopped) + SN(InferiorStopFailed) + SN(InferiorShuttingDown) + SN(InferiorShutDown) + SN(InferiorShutdownFailed) + SN(EngineShuttingDown) + } + return "<unknown>"; +# undef SN +} + +////////////////////////////////////////////////////////////////////// +// +// CommandHandler +// +////////////////////////////////////////////////////////////////////// + +class CommandHandler : public QStandardItemModel +{ +public: + CommandHandler(DebuggerEngine *engine) : m_engine(engine) {} + bool setData(const QModelIndex &index, const QVariant &value, int role); + QAbstractItemModel *model() { return this; } + +private: + DebuggerEngine *m_engine; +}; + +bool CommandHandler::setData + (const QModelIndex &index, const QVariant &value, int role) +{ + //qDebug() << "COMMAND: " << role << value; + Q_UNUSED(index); + Q_UNUSED(value); + + switch (role) { + case RequestLoadSessionDataRole: + m_engine->loadSessionData(); + return true; + + case RequestSaveSessionDataRole: + m_engine->saveSessionData(); + return true; + + case RequestReloadSourceFilesRole: + m_engine->reloadSourceFiles(); + return true; + + case RequestReloadModulesRole: + m_engine->reloadModules(); + return true; + + case RequestExecContinueRole: + m_engine->continueInferior(); + return true; + + case RequestExecInterruptRole: + m_engine->interruptInferior(); + return true; + + case RequestExecResetRole: + //m_engine->exec(); + return true; + + case RequestExecStepRole: + m_engine->executeStepX(); + return true; + + case RequestExecStepOutRole: + m_engine->executeStepOutX(); + return true; + + case RequestExecNextRole: + m_engine->executeStepNextX(); + return true; + + case RequestExecRunToLineRole: + //m_engine->executeRunToLine(); + QTC_ASSERT(false, /* FIXME ABC */); + return true; + + case RequestExecRunToFunctionRole: + //m_engine->executeRunToFunction(); + QTC_ASSERT(false, /* FIXME ABC */); + return true; + + case RequestExecReturnFromFunctionRole: + m_engine->executeReturnX(); + return true; + + case RequestExecJumpToLineRole: + //m_engine->executeJumpToLine(); + QTC_ASSERT(false, /* FIXME ABC */); + return true; + + case RequestExecWatchRole: + //m_engine->exec(); + QTC_ASSERT(false, /* FIXME ABC */); + return true; + + case RequestExecExitRole: + m_engine->exitDebugger(); + return true; + + case RequestExecSnapshotRole: + m_engine->makeSnapshot(); + return true; + + case RequestExecFrameDownRole: + m_engine->frameDown(); + return true; + + case RequestExecFrameUpRole: + m_engine->frameUp(); + return true; + } + + return false; +} + + +////////////////////////////////////////////////////////////////////// +// +// DebuggerEnginePrivate +// +////////////////////////////////////////////////////////////////////// + +class DebuggerEnginePrivate +{ +public: + DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp) + : m_engine(engine), + m_runControl(0), + m_startParameters(sp), + m_state(DebuggerNotReady), + m_breakHandler(engine), + m_commandHandler(engine), + m_modulesHandler(engine), + m_registerHandler(engine), + m_snapshotHandler(engine), + m_sourceFilesHandler(engine), + m_stackHandler(engine), + m_threadsHandler(engine), + m_watchHandler(engine), + m_disassemblerViewAgent(engine) + {} + +public: + DebuggerEngine *m_engine; // Not owned. + DebuggerRunControl *m_runControl; // Not owned. + + DebuggerStartParameters m_startParameters; + DebuggerState m_state; + + qint64 m_inferiorPid; + + BreakHandler m_breakHandler; + CommandHandler m_commandHandler; + ModulesHandler m_modulesHandler; + RegisterHandler m_registerHandler; + SnapshotHandler m_snapshotHandler; + SourceFilesHandler m_sourceFilesHandler; + StackHandler m_stackHandler; + ThreadsHandler m_threadsHandler; + WatchHandler m_watchHandler; + DisassemblerViewAgent m_disassemblerViewAgent; +}; + + +////////////////////////////////////////////////////////////////////// +// +// DebuggerEngine +// +////////////////////////////////////////////////////////////////////// + +DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters) + : d(new DebuggerEnginePrivate(this, startParameters)) +{ + //loadSessionData(); +} + +DebuggerEngine::~DebuggerEngine() +{ + //saveSessionData(); +} + +/* +void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) +{ + plugin()->showStatusMessage(msg, timeout); +} +*/ + +void DebuggerEngine::showModuleSymbols + (const QString &moduleName, const Symbols &symbols) +{ + QTreeWidget *w = new QTreeWidget; + w->setColumnCount(3); + w->setRootIsDecorated(false); + w->setAlternatingRowColors(true); + w->setSortingEnabled(true); + w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code")); + w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName)); + foreach (const Symbol &s, symbols) { + QTreeWidgetItem *it = new QTreeWidgetItem; + it->setData(0, Qt::DisplayRole, s.name); + it->setData(1, Qt::DisplayRole, s.address); + it->setData(2, Qt::DisplayRole, s.state); + w->addTopLevelItem(it); + } + plugin()->createNewDock(w); +} + +void DebuggerEngine::frameUp() +{ + int currentIndex = stackHandler()->currentIndex(); + activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1)); +} + +void DebuggerEngine::frameDown() +{ + int currentIndex = stackHandler()->currentIndex(); + activateFrame(qMax(currentIndex - 1, 0)); +} + +ModulesHandler *DebuggerEngine::modulesHandler() const +{ + return &d->m_modulesHandler; +} + +BreakHandler *DebuggerEngine::breakHandler() const +{ + return &d->m_breakHandler; +} + +RegisterHandler *DebuggerEngine::registerHandler() const +{ + return &d->m_registerHandler; +} + +StackHandler *DebuggerEngine::stackHandler() const +{ + return &d->m_stackHandler; +} + +ThreadsHandler *DebuggerEngine::threadsHandler() const +{ + return &d->m_threadsHandler; +} + +WatchHandler *DebuggerEngine::watchHandler() const +{ + return &d->m_watchHandler; +} + +SnapshotHandler *DebuggerEngine::snapshotHandler() const +{ + return &d->m_snapshotHandler; +} + +SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const +{ + return &d->m_sourceFilesHandler; +} + +QAbstractItemModel *DebuggerEngine::modulesModel() const +{ + return d->m_modulesHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::breakModel() const +{ + return d->m_breakHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::registerModel() const +{ + return d->m_registerHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::stackModel() const +{ + return d->m_stackHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::threadsModel() const +{ + return d->m_threadsHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::localsModel() const +{ + return d->m_watchHandler.model(LocalsWatch); +} + +QAbstractItemModel *DebuggerEngine::watchersModel() const +{ + return d->m_watchHandler.model(WatchersWatch); +} + +QAbstractItemModel *DebuggerEngine::returnModel() const +{ + return d->m_watchHandler.model(ReturnWatch); +} + +QAbstractItemModel *DebuggerEngine::snapshotModel() const +{ + return d->m_snapshotHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::sourceFilesModel() const +{ + return d->m_sourceFilesHandler.model(); +} + +QAbstractItemModel *DebuggerEngine::commandModel() const +{ + return d->m_commandHandler.model(); +} + +void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *, + quint64 addr, quint64 length) +{ + Q_UNUSED(addr); + Q_UNUSED(length); +} + +void DebuggerEngine::setRegisterValue(int regnr, const QString &value) +{ + Q_UNUSED(regnr); + Q_UNUSED(value); +} + +void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const +{ + //qDebug() << channel << msg; + d->m_runControl->showMessage(msg, channel); + plugin()->showMessage(msg, channel, timeout); +} + +void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) +{ + QTC_ASSERT(runControl, startFailed(); return); + QTC_ASSERT(!d->m_runControl, startFailed(); return); + + DebuggerEngine *sessionTemplate = plugin()->sessionTemplate(); + QTC_ASSERT(sessionTemplate, startFailed(); return); + QTC_ASSERT(sessionTemplate != this, startFailed(); return); + + breakHandler()->initializeFromTemplate(sessionTemplate->breakHandler()); + + d->m_runControl = runControl; + + QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady)); + + d->m_inferiorPid = d->m_startParameters.attachPID > 0 + ? d->m_startParameters.attachPID : 0; + + if (d->m_startParameters.environment.empty()) + d->m_startParameters.environment = Environment().toStringList(); + + if (d->m_startParameters.breakAtMain) + breakByFunctionMain(); + + const unsigned engineCapabilities = debuggerCapabilities(); + theDebuggerAction(OperateByInstruction) + ->setEnabled(engineCapabilities & DisassemblerCapability); + + //loadSessionData(); + startDebugger(); +} + +void DebuggerEngine::breakByFunctionMain() +{ +#ifdef Q_OS_WIN + // FIXME: wrong on non-Qt based binaries + emit breakByFunction("qMain"); +#else + emit breakByFunction("main"); +#endif +} + +void DebuggerEngine::breakByFunction(const QString &functionName) +{ + d->m_breakHandler.breakByFunction(functionName); + attemptBreakpointSynchronization(); +} + +void DebuggerEngine::loadSessionData() +{ + d->m_breakHandler.loadSessionData(); + d->m_watchHandler.loadSessionData(); +} + +void DebuggerEngine::saveSessionData() +{ + d->m_breakHandler.saveSessionData(); + d->m_watchHandler.saveSessionData(); +} + +void DebuggerEngine::resetLocation() +{ + d->m_disassemblerViewAgent.resetLocation(); + d->m_stackHandler.setCurrentIndex(-1); + plugin()->resetLocation(); +} + +void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker) +{ + StackFrame frame; + frame.file = fileName; + frame.line = lineNumber; + gotoLocation(frame, setMarker); +} + +void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker) +{ + if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) { + if (setMarker) + plugin()->resetLocation(); + d->m_disassemblerViewAgent.setFrame(frame); + } else { + plugin()->gotoLocation(frame.file, frame.line, setMarker); + } +} + +void DebuggerEngine::executeStepX() +{ + resetLocation(); + if (theDebuggerBoolSetting(OperateByInstruction)) + executeStepI(); + else + executeStep(); +} + +void DebuggerEngine::executeStepOutX() +{ + resetLocation(); + executeStepOut(); +} + +void DebuggerEngine::executeStepNextX() +{ + resetLocation(); + if (theDebuggerBoolSetting(OperateByInstruction)) + executeNextI(); + else + executeNext(); +} + +void DebuggerEngine::executeReturnX() +{ + resetLocation(); + executeReturn(); +} + +void DebuggerEngine::executeWatchPointX() +{ + if (QAction *action = qobject_cast<QAction *>(sender())) + watchPoint(action->data().toPoint()); +} + +/* +void DebuggerEngine::executeDebuggerCommand() +{ + if (QAction *action = qobject_cast<QAction *>(sender())) + executeDebuggerCommand(action->data().toString()); +} +void DebuggerManager::executeRunToLine() +{ + ITextEditor *textEditor = d->m_plugin->currentTextEditor(); + QTC_ASSERT(textEditor, return); + QString fileName = textEditor->file()->fileName(); + int lineNumber = textEditor->currentLine(); + if (d->m_engine && !fileName.isEmpty()) { + STATE_DEBUG(fileName << lineNumber); + resetLocation(); + d->m_engine->executeRunToLine(fileName, lineNumber); + } +} + +void DebuggerManager::executeRunToFunction() +{ + ITextEditor *textEditor = d->m_plugin->currentTextEditor(); + QTC_ASSERT(textEditor, return); + QString fileName = textEditor->file()->fileName(); + QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget()); + if (!ed) + return; + QTextCursor cursor = ed->textCursor(); + QString functionName = cursor.selectedText(); + if (functionName.isEmpty()) { + const QTextBlock block = cursor.block(); + const QString line = block.text(); + foreach (const QString &str, line.trimmed().split('(')) { + QString a; + for (int i = str.size(); --i >= 0; ) { + if (!str.at(i).isLetterOrNumber()) + break; + a = str.at(i) + a; + } + if (!a.isEmpty()) { + functionName = a; + break; + } + } + } + STATE_DEBUG(functionName); + + if (d->m_engine && !functionName.isEmpty()) { + resetLocation(); + d->m_engine->executeRunToFunction(functionName); + } +} + +void DebuggerManager::executeJumpToLine() +{ + ITextEditor *textEditor = d->m_plugin->currentTextEditor(); + QTC_ASSERT(textEditor, return); + QString fileName = textEditor->file()->fileName(); + int lineNumber = textEditor->currentLine(); + if (d->m_engine && !fileName.isEmpty()) { + STATE_DEBUG(fileName << lineNumber); + d->m_engine->executeJumpToLine(fileName, lineNumber); + } +} +*/ + +void DebuggerEngine::operateByInstructionTriggered() +{ + StackFrame frame = d->m_stackHandler.currentFrame(); + gotoLocation(frame, true); +} + +void DebuggerEngine::cleanup() +{ +/* + FIXME ABS: Still needed? + modulesHandler()->removeAll(); + breakHandler()->setAllPending(); + stackHandler()->removeAll(); + threadsHandler()->removeAll(); + watchHandler()->cleanup(); +*/ +} + +const DebuggerStartParameters &DebuggerEngine::startParameters() const +{ + return d->m_startParameters; +} + +DebuggerStartParameters &DebuggerEngine::startParameters() +{ + return d->m_startParameters; +} + + +////////////////////////////////////////////////////////////////////// +// +// Dumpers. "Custom dumpers" are a library compiled against the current +// Qt containing functions to evaluate values of Qt classes +// (such as QString, taking pointers to their addresses). +// The library must be loaded into the debuggee. +// +////////////////////////////////////////////////////////////////////// + +bool DebuggerEngine::qtDumperLibraryEnabled() const +{ + return theDebuggerBoolSetting(UseDebuggingHelpers); +} + +QStringList DebuggerEngine::qtDumperLibraryLocations() const +{ + if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) { + const QString customLocation = + theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); + const QString location = + tr("%1 (explicitly set in the Debugger Options)").arg(customLocation); + return QStringList(location); + } + return d->m_startParameters.dumperLibraryLocations; +} + +void DebuggerEngine::showQtDumperLibraryWarning(const QString &details) +{ + //QMessageBox dialog(d->m_mainWindow); // FIXME + QMessageBox dialog; + QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"), + QMessageBox::ActionRole); + QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"), + QMessageBox::ActionRole); + QPushButton *justContinue = dialog.addButton(tr("Continue anyway"), + QMessageBox::AcceptRole); + dialog.setDefaultButton(justContinue); + dialog.setWindowTitle(tr("Debugging helper missing")); + dialog.setText(tr("The debugger could not load the debugging helper library.")); + dialog.setInformativeText(tr( + "The debugging helper is used to nicely format the values of some Qt " + "and Standard Library data types. " + "It must be compiled for each used Qt version separately. " + "This can be done in the Qt preferences page by selecting a Qt installation " + "and clicking on 'Rebuild' in the 'Debugging Helper' row.")); + if (!details.isEmpty()) + dialog.setDetailedText(details); + dialog.exec(); + if (dialog.clickedButton() == qtPref) { + Core::ICore::instance()->showOptionsDialog( + _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY), + _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID)); + } else if (dialog.clickedButton() == helperOff) { + theDebuggerAction(UseDebuggingHelpers) + ->setValue(qVariantFromValue(false), false); + } +} + +QString DebuggerEngine::qtDumperLibraryName() const +{ + if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) + return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); + return startParameters().dumperLibrary; +} + +DebuggerState DebuggerEngine::state() const +{ + return d->m_state; +} + +static bool isAllowedTransition(int from, int to) +{ + switch (from) { + case -1: + return to == DebuggerNotReady; + + case DebuggerNotReady: + return to == EngineStarting || to == DebuggerNotReady; + + case EngineStarting: + return to == AdapterStarting || to == DebuggerNotReady; + + case AdapterStarting: + return to == AdapterStarted || to == AdapterStartFailed; + case AdapterStarted: + return to == InferiorStarting || to == EngineShuttingDown; + case AdapterStartFailed: + return to == DebuggerNotReady; + + case InferiorStarting: + return to == InferiorRunningRequested || to == InferiorStopped + || to == InferiorStartFailed || to == InferiorUnrunnable; + case InferiorStartFailed: + return to == EngineShuttingDown; + + case InferiorRunningRequested: + return to == InferiorRunning || to == InferiorStopped + || to == InferiorRunningRequested_Kill; + case InferiorRunningRequested_Kill: + return to == InferiorRunning || to == InferiorStopped; + case InferiorRunning: + return to == InferiorStopping; + + case InferiorStopping: + return to == InferiorStopped || to == InferiorStopFailed + || to == InferiorStopping_Kill; + case InferiorStopping_Kill: + return to == InferiorStopped || to == InferiorStopFailed; + case InferiorStopped: + return to == InferiorRunningRequested || to == InferiorShuttingDown; + case InferiorStopFailed: + return to == EngineShuttingDown; + + case InferiorUnrunnable: + return to == EngineShuttingDown; + case InferiorShuttingDown: + return to == InferiorShutDown || to == InferiorShutdownFailed; + case InferiorShutDown: + return to == EngineShuttingDown; + case InferiorShutdownFailed: + return to == EngineShuttingDown; + + case EngineShuttingDown: + return to == DebuggerNotReady; + } + + qDebug() << "UNKNOWN STATE:" << from; + return false; +} + +void DebuggerEngine::setState(DebuggerState state, bool forced) +{ + //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) + // << " TO " << stateName(state); + + QString msg = _("State changed from %1(%2) to %3(%4).") + .arg(stateName(d->m_state)).arg(d->m_state).arg(stateName(state)).arg(state); + //if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0))) + // qDebug() << msg; + if (!forced && !isAllowedTransition(d->m_state, state)) + qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; + + showMessage(msg, LogDebug); + + //resetLocation(); + if (state == d->m_state) + return; + + d->m_state = state; + + plugin()->updateState(this); + + if (d->m_state == DebuggerNotReady) { + saveSessionData(); + d->m_runControl->debuggingFinished(); + } +} + +bool DebuggerEngine::debuggerActionsEnabled() const +{ + return debuggerActionsEnabled(d->m_state); +} + +bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state) +{ + switch (state) { + case InferiorStarting: + case InferiorRunningRequested: + case InferiorRunning: + case InferiorUnrunnable: + case InferiorStopping: + case InferiorStopped: + return true; + case DebuggerNotReady: + case EngineStarting: + case AdapterStarting: + case AdapterStarted: + case AdapterStartFailed: + case InferiorStartFailed: + case InferiorRunningRequested_Kill: + case InferiorStopping_Kill: + case InferiorStopFailed: + case InferiorShuttingDown: + case InferiorShutDown: + case InferiorShutdownFailed: + case EngineShuttingDown: + break; + } + return false; +} + +void DebuggerEngine::startFailed() +{ + // The concrete engines themselves are responsible for changing state. + QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady)); + d->m_runControl->startFailed(); +} + +void DebuggerEngine::startSuccessful() +{ + d->m_runControl->startSuccessful(); +} + +void DebuggerEngine::notifyInferiorPid(qint64 pid) +{ + //STATE_DEBUG(d->m_inferiorPid << pid); + if (d->m_inferiorPid == pid) + return; + d->m_inferiorPid = pid; + QTimer::singleShot(0, this, SLOT(raiseApplication())); +} + +qint64 DebuggerEngine::inferiorPid() const +{ + return d->m_inferiorPid; +} + +DebuggerPlugin *DebuggerEngine::plugin() const +{ + return DebuggerPlugin::instance(); +} + +void DebuggerEngine::raiseApplication() +{ + d->m_runControl->bringApplicationToForeground(d->m_inferiorPid); +} + +void DebuggerEngine::openFile(const QString &fileName, int lineNumber) +{ + plugin()->gotoLocation(fileName, lineNumber, false); +} + +bool DebuggerEngine::isReverseDebugging() const +{ + return plugin()->isReverseDebugging(); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h new file mode 100644 index 0000000000000000000000000000000000000000..b6725632c3c07baf88488cc098465c197d3a5b1d --- /dev/null +++ b/src/plugins/debugger/debuggerengine.h @@ -0,0 +1,273 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEBUGGER_DEBUGGERENGINE_H +#define DEBUGGER_DEBUGGERENGINE_H + +#include "debugger_global.h" +#include "debuggerconstants.h" +#include "moduleshandler.h" // For 'Symbols' + +#include <coreplugin/ssh/sshconnection.h> + +#include <QtCore/QObject> +#include <QtCore/QSharedPointer> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE +class QDebug; +class QPoint; +QT_END_NAMESPACE + +namespace TextEditor { +class ITextEditor; +} + +namespace Core { +class IOptionsPage; +} + +namespace Debugger { + +class DebuggerRunControl; +class DebuggerPlugin; + +class DEBUGGER_EXPORT DebuggerStartParameters +{ +public: + DebuggerStartParameters(); + void clear(); + + QString executable; + QString displayName; + QString coreFile; + QStringList processArgs; + QStringList environment; + QString workingDirectory; + qint64 attachPID; + bool useTerminal; + bool breakAtMain; + QString crashParameter; // for AttachCrashedExternal + // for remote debugging + QString remoteChannel; + QString remoteArchitecture; + QString symbolFileName; + QString serverStartScript; + QString sysRoot; + QString debuggerCommand; + int toolChainType; + QByteArray remoteDumperLib; + QString qtInstallPath; + + QString dumperLibrary; + QStringList dumperLibraryLocations; + Core::SshServerInfo sshserver; + DebuggerStartMode startMode; +}; + +DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &); +DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state); + +namespace Internal { + +class DisassemblerViewAgent; +class MemoryViewAgent; +class Symbol; +class WatchData; +class BreakHandler; +class ModulesHandler; +class RegisterHandler; +class StackHandler; +class StackFrame; +class SnapshotHandler; +class SourceFilesHandler; +class ThreadsHandler; +class WatchHandler; + +class DebuggerEnginePrivate; + + +class DebuggerEngine : public QObject +{ + Q_OBJECT + +public: + DebuggerEngine(const DebuggerStartParameters &sp); + virtual ~DebuggerEngine(); + + virtual void shutdown() {} + virtual void setToolTipExpression(const QPoint &mousePos, + TextEditor::ITextEditor *editor, int cursorPos) + { Q_UNUSED(mousePos); Q_UNUSED(editor); Q_UNUSED(cursorPos); } + void initializeFromTemplate(DebuggerEngine *other); + void startDebugger(DebuggerRunControl *runControl); + virtual void startDebugger() {} + virtual void exitDebugger() {} + virtual void abortDebugger() { exitDebugger(); } + virtual void detachDebugger() {} + virtual void updateWatchData(const WatchData &data) + { Q_UNUSED(data); } + + virtual void executeStep() {} + virtual void executeStepOut() {} + virtual void executeNext() {} + virtual void executeStepI() {} + virtual void executeNextI() {} + virtual void executeReturn() {} + + virtual void continueInferior() {} + virtual void interruptInferior() {} + + virtual void executeRunToLine(const QString &fileName, int lineNumber) + { Q_UNUSED(fileName); Q_UNUSED(lineNumber); } + virtual void executeRunToFunction(const QString &functionName) + { Q_UNUSED(functionName); } + virtual void executeJumpToLine(const QString &fileName, int lineNumber) + { Q_UNUSED(fileName); Q_UNUSED(lineNumber); } + virtual void assignValueInDebugger(const QString &expr, const QString &value) + { Q_UNUSED(expr); Q_UNUSED(value); } + virtual void executeDebuggerCommand(const QString &command) + { Q_UNUSED(command); } + + virtual void activateFrame(int index) { Q_UNUSED(index); } + virtual void frameUp(); + virtual void frameDown(); + virtual void selectThread(int index) { Q_UNUSED(index); } + + virtual void makeSnapshot() {} + virtual void activateSnapshot(int index) { Q_UNUSED(index); } + + virtual void attemptBreakpointSynchronization() {} + + virtual void reloadModules() {} + virtual void loadSymbols(const QString &moduleName) + { Q_UNUSED(moduleName); } + virtual void loadAllSymbols() {} + virtual void requestModuleSymbols(const QString &moduleName) + { Q_UNUSED(moduleName); } + + virtual void reloadRegisters() {} + virtual void reloadSourceFiles() {} + virtual void reloadFullStack() {} + + virtual void watchPoint(const QPoint &) {} + virtual void fetchMemory(MemoryViewAgent *, QObject *, + quint64 addr, quint64 length); + virtual void fetchDisassembler(DisassemblerViewAgent *) {} + virtual void setRegisterValue(int regnr, const QString &value); + virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {} + virtual unsigned debuggerCapabilities() const { return 0; } + + virtual bool isSynchroneous() const { return false; } + virtual QString qtNamespace() const { return QString(); } + +public slots: + // Convenience + void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const; + void showStatusMessage(const QString &msg, int timeout = -1) const + { showMessage(msg, StatusBar, timeout); } + +public: + DebuggerPlugin *plugin() const; + const DebuggerStartParameters &startParameters() const; + DebuggerStartParameters &startParameters(); + + ModulesHandler *modulesHandler() const; + BreakHandler *breakHandler() const; + RegisterHandler *registerHandler() const; + StackHandler *stackHandler() const; + ThreadsHandler *threadsHandler() const; + WatchHandler *watchHandler() const; + SnapshotHandler *snapshotHandler() const; + SourceFilesHandler *sourceFilesHandler() const; + + QAbstractItemModel *commandModel() const; + QAbstractItemModel *modulesModel() const; + QAbstractItemModel *breakModel() const; + QAbstractItemModel *registerModel() const; + QAbstractItemModel *stackModel() const; + QAbstractItemModel *threadsModel() const; + QAbstractItemModel *localsModel() const; + QAbstractItemModel *watchersModel() const; + QAbstractItemModel *returnModel() const; + QAbstractItemModel *snapshotModel() const; + QAbstractItemModel *sourceFilesModel() const; + + void cleanup(); + bool debuggerActionsEnabled() const; + static bool debuggerActionsEnabled(DebuggerState state); + void showModuleSymbols(const QString &moduleName, const Symbols &symbols); + + void breakByFunction(const QString &functionName); + void breakByFunctionMain(); + + void loadSessionData(); + void saveSessionData(); + + void executeStepX(); + void executeStepOutX(); + void executeStepNextX(); + void executeReturnX(); + void executeWatchPointX(); + + void operateByInstructionTriggered(); + DebuggerState state() const; + + // Dumper stuff (common to cdb and gdb). + bool qtDumperLibraryEnabled() const; + QString qtDumperLibraryName() const; + QStringList qtDumperLibraryLocations() const; + void showQtDumperLibraryWarning(const QString &details = QString()); + + static const char *stateName(int s); + + void notifyInferiorPid(qint64 pid); + qint64 inferiorPid() const; + bool isReverseDebugging() const; + +public slots: + void resetLocation(); + void openFile(const QString &fileName, int lineNumber = -1); + void gotoLocation(const QString &fileName, int lineNumber, bool setMarker); + void gotoLocation(const StackFrame &frame, bool setMarker); + void startSuccessful(); + void startFailed(); + void raiseApplication(); + void quitDebugger() { exitDebugger(); } + +protected: + void setState(DebuggerState state, bool forced = false); + + DebuggerEnginePrivate *d; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_DEBUGGERENGINE_H diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h index 028e7dad5f7481e5c8025d8eda1e12eecaa7ef12..536e6082313a2f85dbb1291f665d3110eb536dc6 100644 --- a/src/plugins/debugger/debuggermainwindow.h +++ b/src/plugins/debugger/debuggermainwindow.h @@ -39,11 +39,12 @@ class DebuggerUISwitcher; namespace Internal { -class DebugToolWindow { +class DebugToolWindow +{ public: - DebugToolWindow() : m_visible(false) {} - QDockWidget* m_dockWidget; + DebugToolWindow() : m_dockWidget(0), m_languageId(-1), m_visible(false) {} + QDockWidget *m_dockWidget; int m_languageId; bool m_visible; }; diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp deleted file mode 100644 index c46f667c5f7778dc9cbeb69e7687d18b45003605..0000000000000000000000000000000000000000 --- a/src/plugins/debugger/debuggermanager.cpp +++ /dev/null @@ -1,1942 +0,0 @@ -/************************************************************************** -** -** 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 "debuggermanager.h" - -#include "debuggeractions.h" -#include "debuggeragents.h" -#include "debuggerconstants.h" -#include "debuggermainwindow.h" -#include "debuggerplugin.h" -#include "debuggerrunner.h" -#include "debuggerstringutils.h" -#include "debuggertooltip.h" -#include "debuggeruiswitcher.h" -#include "idebuggerengine.h" -#include "watchutils.h" - -#include "breakwindow.h" -#include "debuggeroutputwindow.h" -#include "moduleswindow.h" -#include "registerwindow.h" -#include "snapshotwindow.h" -#include "stackwindow.h" -#include "sourcefileswindow.h" -#include "threadswindow.h" -#include "watchwindow.h" - -#include "breakhandler.h" -#include "snapshothandler.h" -#include "stackhandler.h" -#include "threadshandler.h" -#include "watchhandler.h" - -#include "debuggerdialogs.h" -#ifdef Q_OS_WIN -# include "shared/peutils.h" -#endif - -#include <coreplugin/icore.h> -#include <coreplugin/minisplitter.h> -#include <coreplugin/editormanager/editormanager.h> -#include <utils/qtcassert.h> -#include <utils/savedaction.h> -#include <projectexplorer/toolchain.h> -#include <cplusplus/CppDocument.h> -#include <cpptools/cppmodelmanagerinterface.h> -#include <qt4projectmanager/qt4projectmanagerconstants.h> -#include <texteditor/fontsettings.h> -#include <texteditor/itexteditor.h> - -#include <QtCore/QDebug> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtCore/QTextStream> -#include <QtCore/QTime> -#include <QtCore/QTimer> - -#include <QtGui/QApplication> -#include <QtGui/QAbstractItemView> -#include <QtGui/QAction> -#include <QtGui/QComboBox> -#include <QtGui/QDockWidget> -#include <QtGui/QErrorMessage> -#include <QtGui/QFileDialog> -#include <QtGui/QHeaderView> -#include <QtGui/QLabel> -#include <QtGui/QMessageBox> -#include <QtGui/QPlainTextEdit> -#include <QtGui/QPushButton> -#include <QtGui/QStatusBar> -#include <QtGui/QTextBlock> -#include <QtGui/QTextCursor> -#include <QtGui/QToolButton> -#include <QtGui/QToolTip> -#include <QtGui/QTreeWidget> - -#define DEBUG_STATE 1 -#ifdef DEBUG_STATE -// use Q_FUNC_INFO? -# define STATE_DEBUG(s) \ - do { QString msg; QTextStream ts(&msg); ts << s; \ - showMessage(msg, LogDebug); } while (0) -#else -# define STATE_DEBUG(s) -#endif - -// Note: the Debugger process itself and any helper processes like -// gdbserver, the trk client etc are referred to as 'Adapter', -// whereas the debugged process is referred to as 'Inferior'. -// -// 0 == DebuggerNotReady -// | -// EngineStarting -// | -// AdapterStarting --> AdapterStartFailed --> 0 -// | -// AdapterStarted ------------------------------------. -// | v -// InferiorStarting ----> InferiorStartFailed -------->| -// | | -// (core) | (attach) (term) (remote) | -// .-----------------<-|->------------------. | -// | v | | -// InferiorUnrunnable | (plain) | | -// | | (trk) | | -// | | | | -// | .--> InferiorRunningRequested | | -// | | | | | -// | | InferiorRunning | | -// | | | | | -// | | InferiorStopping | | -// | | | | | -// | '------ InferiorStopped <-----------' | -// | | v -// | InferiorShuttingDown -> InferiorShutdownFailed ---->| -// | | | -// | InferiorShutDown | -// | | | -// '--------> EngineShuttingDown <--------------------------------' -// | -// 0 -// -// Allowed actions: -// [R] : Run -// [C] : Continue -// [N] : Step, Next - -namespace Debugger { -namespace Internal { - -IDebuggerEngine *createGdbEngine(DebuggerManager *parent); -IDebuggerEngine *createScriptEngine(DebuggerManager *parent); -IDebuggerEngine *createPdbEngine(DebuggerManager *parent); -IDebuggerEngine *createTcfEngine(DebuggerManager *parent); -IDebuggerEngine *createQmlEngine(DebuggerManager *parent); - -// The createCdbEngine function takes a list of options pages it can add to. -// This allows for having a "enabled" toggle on the page independently -// of the engine. That's good for not enabling the related ActiveX control -// unnecessarily. - -IDebuggerEngine *createCdbEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *) -#ifdef CDB_ENABLED -; -#else -{ return 0; } -#endif - -} // namespace Internal - -DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &p) -{ - QDebug nospace = str.nospace(); - const QString sep = QString(QLatin1Char(',')); - nospace << "executable=" << p.executable << " coreFile=" << p.coreFile - << " processArgs=" << p.processArgs.join(sep) - << " environment=<" << p.environment.size() << " variables>" - << " workingDir=" << p.workingDirectory - << " attachPID=" << p.attachPID << " useTerminal=" << p.useTerminal - << " remoteChannel=" << p.remoteChannel - << " remoteArchitecture=" << p.remoteArchitecture - << " symbolFileName=" << p.symbolFileName - << " serverStartScript=" << p.serverStartScript - << " toolchain=" << p.toolChainType << '\n'; - return str; -} - -using namespace Constants; -using namespace Debugger::Internal; -using namespace TextEditor; - -const char *DebuggerManager::stateName(int s) -{ -# define SN(x) case x: return #x; - switch (s) { - SN(DebuggerNotReady) - SN(EngineStarting) - SN(AdapterStarting) - SN(AdapterStarted) - SN(AdapterStartFailed) - SN(InferiorStarting) - SN(InferiorStartFailed) - SN(InferiorRunningRequested) - SN(InferiorRunningRequested_Kill) - SN(InferiorRunning) - SN(InferiorUnrunnable) - SN(InferiorStopping) - SN(InferiorStopping_Kill) - SN(InferiorStopped) - SN(InferiorStopFailed) - SN(InferiorShuttingDown) - SN(InferiorShutDown) - SN(InferiorShutdownFailed) - SN(EngineShuttingDown) - } - return "<unknown>"; -# undef SN -} - - -/////////////////////////////////////////////////////////////////////// -// -// DebuggerStartParameters -// -/////////////////////////////////////////////////////////////////////// - -DebuggerStartParameters::DebuggerStartParameters() - : attachPID(-1), - useTerminal(false), - toolChainType(ProjectExplorer::ToolChain::UNKNOWN), - startMode(NoStartMode) -{} - -void DebuggerStartParameters::clear() -{ - *this = DebuggerStartParameters(); -} - - -/////////////////////////////////////////////////////////////////////// -// -// DebuggerManager -// -/////////////////////////////////////////////////////////////////////// - -static Debugger::Internal::IDebuggerEngine *gdbEngine = 0; -static Debugger::Internal::IDebuggerEngine *scriptEngine = 0; -static Debugger::Internal::IDebuggerEngine *cdbEngine = 0; -static Debugger::Internal::IDebuggerEngine *pdbEngine = 0; -static Debugger::Internal::IDebuggerEngine *qmlEngine = 0; -static Debugger::Internal::IDebuggerEngine *tcfEngine = 0; - -struct DebuggerManagerPrivate -{ - explicit DebuggerManagerPrivate(DebuggerManager *manager); - - static DebuggerManager *instance; - - QIcon m_stopIcon; - QIcon m_interruptIcon; - const QIcon m_locationMarkIcon; - - // FIXME: Remove engine-specific state - DebuggerRunControl *m_runControl; - - /// Views - DebuggerMainWindow *m_mainWindow; - - QLabel *m_statusLabel; - - // FIXME: Move to DebuggerRunControl - BreakHandler *m_breakHandler; - StackHandler *m_stackHandler; - ThreadsHandler *m_threadsHandler; - WatchHandler *m_watchHandler; - - QDockWidget *m_breakDock; - QDockWidget *m_modulesDock; - QDockWidget *m_outputDock; - QDockWidget *m_registerDock; - QDockWidget *m_snapshotDock; - QDockWidget *m_sourceFilesDock; - QDockWidget *m_stackDock; - QDockWidget *m_threadsDock; - QDockWidget *m_watchDock; - QList<QDockWidget *> m_dockWidgets; - - DebuggerManagerActions m_actions; - - QWidget *m_breakWindow; - QWidget *m_returnWindow; - QWidget *m_localsWindow; - QWidget *m_watchersWindow; - QAbstractItemView *m_registerWindow; - QAbstractItemView *m_modulesWindow; - QAbstractItemView *m_snapshotWindow; - SourceFilesWindow *m_sourceFilesWindow; - QWidget *m_stackWindow; - QWidget *m_threadsWindow; - DebuggerOutputWindow *m_outputWindow; - - bool m_busy; - QTimer *m_statusTimer; - QString m_lastPermanentStatusMessage; - DisassemblerViewAgent m_disassemblerViewAgent; - - IDebuggerEngine *m_engine; - DebuggerState m_state; - - CPlusPlus::Snapshot m_codeModelSnapshot; - DebuggerPlugin *m_plugin; -}; - -DebuggerManager *DebuggerManagerPrivate::instance = 0; - -DebuggerManagerPrivate::DebuggerManagerPrivate(DebuggerManager *manager) : - m_stopIcon(QLatin1String(":/debugger/images/debugger_stop_small.png")), - m_interruptIcon(QLatin1String(":/debugger/images/debugger_interrupt_small.png")), - m_locationMarkIcon(QLatin1String(":/debugger/images/location_16.png")), - m_disassemblerViewAgent(manager), - m_engine(0) -{ - m_runControl = 0; - m_interruptIcon.addFile(":/debugger/images/debugger_interrupt.png"); - m_stopIcon.addFile(":/debugger/images/debugger_stop.png"); -} - -DebuggerManager::DebuggerManager(DebuggerPlugin *plugin) - : d(new DebuggerManagerPrivate(this)) -{ - DebuggerManagerPrivate::instance = this; - d->m_plugin = plugin; - init(); -} - -DebuggerManager::~DebuggerManager() -{ -# define doDelete(ptr) delete ptr; ptr = 0 - doDelete(scriptEngine); - doDelete(pdbEngine); - doDelete(gdbEngine); - doDelete(cdbEngine); - doDelete(tcfEngine); - doDelete(qmlEngine); - - doDelete(d->m_breakHandler); - doDelete(d->m_threadsHandler); - doDelete(d->m_stackHandler); - doDelete(d->m_watchHandler); -# undef doDelete - DebuggerManagerPrivate::instance = 0; - delete d; -} - -DebuggerManager *DebuggerManager::instance() -{ - return DebuggerManagerPrivate::instance; -} - -void DebuggerManager::init() -{ - d->m_state = DebuggerState(-1); - d->m_busy = false; - - d->m_statusLabel = new QLabel; - d->m_statusLabel->setMinimumSize(QSize(30, 10)); - - d->m_breakWindow = new BreakWindow(this); - d->m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints")); - d->m_modulesWindow = new ModulesWindow(); - d->m_modulesWindow->setObjectName(QLatin1String("CppDebugModules")); - d->m_outputWindow = new DebuggerOutputWindow; - d->m_outputWindow->setObjectName(QLatin1String("CppDebugOutput")); - - d->m_registerWindow = new RegisterWindow(this); - d->m_registerWindow->setObjectName(QLatin1String("CppDebugRegisters")); - d->m_snapshotWindow = new SnapshotWindow(); - d->m_snapshotWindow->setObjectName(QLatin1String("CppDebugSnapshots")); - d->m_stackWindow = new StackWindow(this); - d->m_stackWindow->setObjectName(QLatin1String("CppDebugStack")); - d->m_sourceFilesWindow = new SourceFilesWindow; - d->m_sourceFilesWindow->setObjectName(QLatin1String("CppDebugSources")); - d->m_threadsWindow = new ThreadsWindow; - d->m_threadsWindow->setObjectName(QLatin1String("CppDebugThreads")); - d->m_returnWindow = new WatchWindow(WatchWindow::ReturnType, this); - d->m_returnWindow->setObjectName(QLatin1String("CppDebugReturn")); - d->m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this); - d->m_localsWindow->setObjectName(QLatin1String("CppDebugLocals")); - d->m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this); - d->m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers")); - d->m_statusTimer = new QTimer(this); - - d->m_mainWindow = - qobject_cast<DebuggerMainWindow*>(DebuggerUISwitcher::instance()->mainWindow()); - QTC_ASSERT(d->m_mainWindow, return) - - // Stack - d->m_stackHandler = new StackHandler; - StackWindow *stackView = - qobject_cast<StackWindow *>(d->m_stackWindow); - stackView->setModel(d->m_stackHandler->stackModel()); - stackView->header()->resizeSection(0, 60); - stackView->header()->resizeSection(3, 60); - - connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()), - this, SLOT(reloadFullStack())); - connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()), - this, SLOT(reloadFullStack())); - - // Threads - d->m_threadsHandler = new ThreadsHandler; - QAbstractItemView *threadsView = - qobject_cast<QAbstractItemView *>(d->m_threadsWindow); - threadsView->setModel(d->m_threadsHandler->threadsModel()); - connect(threadsView, SIGNAL(threadSelected(int)), - this, SLOT(selectThread(int))); - - // Breakpoints - d->m_breakHandler = new BreakHandler(this); - QAbstractItemView *breakView = - qobject_cast<QAbstractItemView *>(d->m_breakWindow); - breakView->setModel(d->m_breakHandler->model()); - connect(breakView, SIGNAL(breakpointActivated(int)), - this, SLOT(activateBreakpoint(int))); - connect(breakView, SIGNAL(breakpointDeleted(int)), - d->m_breakHandler, SLOT(removeBreakpoint(int))); - connect(breakView, SIGNAL(breakpointSynchronizationRequested()), - this, SLOT(attemptBreakpointSynchronization())); - connect(breakView, SIGNAL(breakByFunctionRequested(QString)), - this, SLOT(breakByFunction(QString)), Qt::QueuedConnection); - connect(breakView, SIGNAL(breakByFunctionMainRequested()), - this, SLOT(breakByFunctionMain()), Qt::QueuedConnection); - - // Modules - connect(d->m_modulesWindow, SIGNAL(fileOpenRequested(QString)), - this, SLOT(fileOpen(QString))); - - // Source Files - //d->m_sourceFilesHandler = new SourceFilesHandler; - QAbstractItemView *sourceFilesView = - qobject_cast<QAbstractItemView *>(d->m_sourceFilesWindow); - //sourceFileView->setModel(d->m_stackHandler->stackModel()); - connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()), - this, SLOT(reloadSourceFiles())); - connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)), - this, SLOT(fileOpen(QString))); - - // Return Value - d->m_watchHandler = new WatchHandler(this); - QTreeView *returnView = qobject_cast<QTreeView *>(d->m_returnWindow); - returnView->setModel(d->m_watchHandler->model(ReturnWatch)); - - // Locals - QTreeView *localsView = qobject_cast<QTreeView *>(d->m_localsWindow); - localsView->setModel(d->m_watchHandler->model(LocalsWatch)); - - // Watchers - QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow); - watchersView->setModel(d->m_watchHandler->model(WatchersWatch)); - connect(theDebuggerAction(AssignValue), SIGNAL(triggered()), - this, SLOT(assignValueInDebugger()), Qt::QueuedConnection); - connect(theDebuggerAction(RemoveWatchExpression), SIGNAL(triggered()), - this, SLOT(updateWatchersWindow()), Qt::QueuedConnection); - connect(localsView->header(), SIGNAL(sectionResized(int,int,int)), - this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection); - - // Tooltip - qRegisterMetaType<WatchData>("WatchData"); - qRegisterMetaType<StackCookie>("StackCookie"); - - d->m_actions.continueAction = new QAction(tr("Continue"), this); - QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png"); - continueIcon.addFile(":/debugger/images/debugger_continue.png"); - d->m_actions.continueAction->setIcon(continueIcon); - - d->m_actions.stopAction = new QAction(tr("Interrupt"), this); - d->m_actions.stopAction->setIcon(d->m_interruptIcon); - - d->m_actions.resetAction = new QAction(tr("Abort Debugging"), this); - d->m_actions.resetAction->setToolTip(tr("Aborts debugging and " - "resets the debugger to the initial state.")); - - d->m_actions.nextAction = new QAction(tr("Step Over"), this); - d->m_actions.nextAction->setIcon( - QIcon(":/debugger/images/debugger_stepover_small.png")); - - d->m_actions.stepAction = new QAction(tr("Step Into"), this); - d->m_actions.stepAction->setIcon( - QIcon(":/debugger/images/debugger_stepinto_small.png")); - - d->m_actions.stepOutAction = new QAction(tr("Step Out"), this); - d->m_actions.stepOutAction->setIcon( - QIcon(":/debugger/images/debugger_stepout_small.png")); - - d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this); - d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this); - - d->m_actions.runToFunctionAction = - new QAction(tr("Run to Outermost Function"), this); - - d->m_actions.returnFromFunctionAction = - new QAction(tr("Immediately Return From Inner Function"), this); - - d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this); - d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this); - - d->m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this); - - d->m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this); - d->m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this); - - d->m_actions.snapshotAction = new QAction(tr("Snapshot"), this); - d->m_actions.snapshotAction->setIcon( - QIcon(":/debugger/images/debugger_snapshot_small.png")); - - d->m_actions.reverseDirectionAction = - new QAction(tr("Reverse Direction"), this); - d->m_actions.reverseDirectionAction->setCheckable(true); - d->m_actions.reverseDirectionAction->setChecked(false); - d->m_actions.reverseDirectionAction->setIcon( - QIcon(":/debugger/images/debugger_reversemode_16.png")); - d->m_actions.reverseDirectionAction->setIconVisibleInMenu(false); - - d->m_actions.frameDownAction = - new QAction(tr("Move to Called Frame"), this); - d->m_actions.frameUpAction = - new QAction(tr("Move to Calling Frame"), this); - - d->m_actions.reverseDirectionAction->setCheckable(false); - connect(d->m_actions.continueAction, SIGNAL(triggered()), - this, SLOT(executeContinue())); - connect(d->m_actions.stopAction, SIGNAL(triggered()), - this, SLOT(interruptDebuggingRequest())); - connect(d->m_actions.resetAction, SIGNAL(triggered()), - this, SLOT(abortDebugger())); - connect(d->m_actions.nextAction, SIGNAL(triggered()), - this, SLOT(executeStepNext())); - connect(d->m_actions.stepAction, SIGNAL(triggered()), - this, SLOT(executeStep())); - connect(d->m_actions.stepOutAction, SIGNAL(triggered()), - this, SLOT(executeStepOut())); - connect(d->m_actions.runToLineAction1, SIGNAL(triggered()), - this, SLOT(executeRunToLine())); - connect(d->m_actions.runToLineAction2, SIGNAL(triggered()), - this, SLOT(executeRunToLine())); - connect(d->m_actions.runToFunctionAction, SIGNAL(triggered()), - this, SLOT(executeRunToFunction())); - connect(d->m_actions.jumpToLineAction1, SIGNAL(triggered()), - this, SLOT(executeJumpToLine())); - connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()), - this, SLOT(executeJumpToLine())); - connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()), - this, SLOT(executeReturn())); - connect(d->m_actions.watchAction1, SIGNAL(triggered()), - this, SLOT(addToWatchWindow())); - connect(d->m_actions.watchAction2, SIGNAL(triggered()), - this, SLOT(addToWatchWindow())); - connect(d->m_actions.snapshotAction, SIGNAL(triggered()), - this, SLOT(makeSnapshot())); - connect(d->m_actions.frameDownAction, SIGNAL(triggered()), - this, SLOT(frameDown())); - connect(d->m_actions.frameUpAction, SIGNAL(triggered()), - this, SLOT(frameUp())); - - connect(d->m_statusTimer, SIGNAL(timeout()), - this, SLOT(clearStatusMessage())); - - connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()), - this, SLOT(executeDebuggerCommand())); - - connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()), - this, SLOT(watchPoint())); - - connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()), - this, SLOT(operateByInstructionTriggered())); - - DebuggerUISwitcher *uiSwitcher = DebuggerUISwitcher::instance(); - d->m_breakDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_breakWindow); - d->m_modulesDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_modulesWindow, - Qt::TopDockWidgetArea, false); - - connect(d->m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)), - this, SLOT(reloadModules()), Qt::QueuedConnection); - - d->m_registerDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_registerWindow, - Qt::TopDockWidgetArea, false); - connect(d->m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)), - this, SLOT(reloadRegisters()), Qt::QueuedConnection); - - d->m_outputDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_outputWindow, - Qt::TopDockWidgetArea, false); - - d->m_snapshotDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_snapshotWindow); - d->m_stackDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_stackWindow); - d->m_sourceFilesDock = uiSwitcher->createDockWidget(LANG_CPP, - d->m_sourceFilesWindow, Qt::TopDockWidgetArea, false); - connect(d->m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)), - this, SLOT(reloadSourceFiles()), Qt::QueuedConnection); - - d->m_threadsDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_threadsWindow); - - QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical); - localsAndWatchers->setObjectName(QLatin1String("CppDebugLocalsAndWatchers")); - localsAndWatchers->setWindowTitle(d->m_localsWindow->windowTitle()); - localsAndWatchers->addWidget(d->m_localsWindow); - localsAndWatchers->addWidget(d->m_returnWindow); - localsAndWatchers->addWidget(d->m_watchersWindow); - //localsAndWatchers->addWidget(d->m_tooltipWindow); - localsAndWatchers->setStretchFactor(0, 3); - localsAndWatchers->setStretchFactor(1, 1); - localsAndWatchers->setStretchFactor(2, 1); - d->m_watchDock = DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, - localsAndWatchers); - d->m_dockWidgets << d->m_breakDock << d->m_modulesDock << d->m_registerDock - << d->m_outputDock << d->m_stackDock << d->m_sourceFilesDock - << d->m_threadsDock << d->m_watchDock; - - setState(DebuggerNotReady); -} - -QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags) -{ - QList<Core::IOptionsPage*> rc; - - if (enabledTypeFlags & GdbEngineType) { - gdbEngine = createGdbEngine(this); - gdbEngine->addOptionPages(&rc); - } - - cdbEngine = createCdbEngine(this, (enabledTypeFlags & CdbEngineType), &rc); - - if (enabledTypeFlags & ScriptEngineType) { - scriptEngine = createScriptEngine(this); - scriptEngine->addOptionPages(&rc); - } - - if (enabledTypeFlags & PdbEngineType) { - pdbEngine = createPdbEngine(this); - //pdbEngine->addOptionPages(&rc); - } - - if (enabledTypeFlags & TcfEngineType) { - tcfEngine = createTcfEngine(this); - tcfEngine->addOptionPages(&rc); - } - - if (enabledTypeFlags & QmlEngineType) { - qmlEngine = createQmlEngine(this); - //qmlEngine->addOptionPages(&rc); - } - - d->m_engine = 0; - STATE_DEBUG(gdbEngine << cdbEngine << scriptEngine - << pdbEngine << rc.size()); - return rc; -} - -DebuggerManagerActions DebuggerManager::debuggerManagerActions() const -{ - return d->m_actions; -} - -QLabel *DebuggerManager::statusLabel() const -{ - return d->m_statusLabel; -} - -IDebuggerEngine *DebuggerManager::currentEngine() const -{ - return d->m_engine; -} - -const CPlusPlus::Snapshot &DebuggerManager::cppCodeModelSnapshot() const -{ - if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked()) - d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); - return d->m_codeModelSnapshot; -} - -void DebuggerManager::clearCppCodeModelSnapshot() -{ - d->m_codeModelSnapshot = CPlusPlus::Snapshot(); -} - -QAbstractItemView *DebuggerManager::modulesWindow() const -{ - return d->m_modulesWindow; -} - -QAbstractItemView *DebuggerManager::registerWindow() const -{ - return d->m_registerWindow; -} - -QAbstractItemView *DebuggerManager::snapshotWindow() const -{ - return d->m_snapshotWindow; -} - -SourceFilesWindow *DebuggerManager::sourceFileWindow() const -{ - return d->m_sourceFilesWindow; -} - -QWidget *DebuggerManager::threadsWindow() const -{ - return d->m_threadsWindow; -} - -void DebuggerManager::createNewDock(QWidget *widget) -{ - QDockWidget *dockWidget = - DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, widget); - dockWidget->setWindowTitle(widget->windowTitle()); - dockWidget->setObjectName(widget->windowTitle()); - dockWidget->setFeatures(QDockWidget::DockWidgetClosable); - //dockWidget->setWidget(widget); - //d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget); - dockWidget->show(); -} - -void DebuggerManager::setSimpleDockWidgetArrangement(const QString &activeLanguage) -{ - if (activeLanguage == LANG_CPP || activeLanguage.isEmpty()) { - d->m_mainWindow->setTrackingEnabled(false); - QList<QDockWidget *> dockWidgets = d->m_mainWindow->dockWidgets(); - foreach (QDockWidget *dockWidget, dockWidgets) { - if (d->m_dockWidgets.contains(dockWidget)) { - dockWidget->setFloating(false); - d->m_mainWindow->removeDockWidget(dockWidget); - } - } - - foreach (QDockWidget *dockWidget, dockWidgets) { - if (d->m_dockWidgets.contains(dockWidget)) { - if (dockWidget == d->m_outputDock) - d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget); - else - d->m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget); - dockWidget->show(); - } - } - - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_breakDock); - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_modulesDock); - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_registerDock); - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_threadsDock); - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_sourceFilesDock); - d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_snapshotDock); - // They following views are rarely used in ordinary debugging. Hiding them - // saves cycles since the corresponding information won't be retrieved. - d->m_sourceFilesDock->hide(); - d->m_registerDock->hide(); - d->m_modulesDock->hide(); - d->m_outputDock->hide(); - d->m_mainWindow->setTrackingEnabled(true); - } -} - -QAbstractItemModel *DebuggerManager::threadsModel() -{ - return qobject_cast<ThreadsWindow*>(d->m_threadsWindow)->model(); -} - -void DebuggerManager::clearStatusMessage() -{ - d->m_statusLabel->setText(d->m_lastPermanentStatusMessage); -} - -void DebuggerManager::showStatusMessage(const QString &msg0, int timeout) -{ - Q_UNUSED(timeout) - showMessage(msg0, LogStatus); - QString msg = msg0; - msg.replace(QLatin1Char('\n'), QString()); - d->m_statusLabel->setText(msg); - if (timeout > 0) { - d->m_statusTimer->setSingleShot(true); - d->m_statusTimer->start(timeout); - } else { - d->m_lastPermanentStatusMessage = msg; - d->m_statusTimer->stop(); - } -} - -void DebuggerManager::notifyInferiorStopped() -{ - setState(InferiorStopped); - showStatusMessage(tr("Stopped"), 5000); -} - -void DebuggerManager::notifyInferiorRunning() -{ - setState(InferiorRunning); - showStatusMessage(tr("Running..."), 5000); -} - -void DebuggerManager::notifyInferiorExited() -{ - setState(DebuggerNotReady); - showStatusMessage(tr("Exited"), 5000); -} - -void DebuggerManager::aboutToShutdown() -{ - STATE_DEBUG(d->m_engine); - if (d->m_engine) - d->m_engine->shutdown(); - d->m_engine = 0; -} - -void DebuggerManager::frameUp() -{ - QTC_ASSERT(d->m_engine, return); - int currentIndex = stackHandler()->currentIndex(); - activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1)); -} - -void DebuggerManager::frameDown() -{ - QTC_ASSERT(d->m_engine, return); - int currentIndex = stackHandler()->currentIndex(); - activateFrame(qMax(currentIndex - 1, 0)); -} - -void DebuggerManager::attemptBreakpointSynchronization() -{ - if (d->m_engine) - d->m_engine->attemptBreakpointSynchronization(); -} - -void DebuggerManager::setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, int cursorPos) -{ - if (d->m_engine) - d->m_engine->setToolTipExpression(mousePos, editor, cursorPos); -} - -void DebuggerManager::updateWatchData(const Debugger::Internal::WatchData &data) -{ - if (d->m_engine) - d->m_engine->updateWatchData(data); -} - -static QString msgEngineNotAvailable(const char *engine) -{ - return DebuggerManager::tr("The application requires the debugger engine '%1', " - "which is disabled.").arg(QLatin1String(engine)); -} - -static IDebuggerEngine *debuggerEngineForToolChain(int toolChainType) -{ - switch (toolChainType) { - case ProjectExplorer::ToolChain::LINUX_ICC: - case ProjectExplorer::ToolChain::MinGW: - case ProjectExplorer::ToolChain::GCC: - return gdbEngine; - case ProjectExplorer::ToolChain::MSVC: - case ProjectExplorer::ToolChain::WINCE: - return cdbEngine; - case ProjectExplorer::ToolChain::WINSCW: // S60 - case ProjectExplorer::ToolChain::GCCE: - case ProjectExplorer::ToolChain::RVCT_ARMV5: - case ProjectExplorer::ToolChain::RVCT_ARMV6: - case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain::GCCE_GNUPOC: - return gdbEngine; - case ProjectExplorer::ToolChain::OTHER: - case ProjectExplorer::ToolChain::UNKNOWN: - case ProjectExplorer::ToolChain::INVALID: - default: - break; - } - return 0; -} - -// Figure out the debugger type of an executable. Analyze executable -// unless the toolchain provides a hint. -static IDebuggerEngine *debuggerEngineForExecutable(const QString &executable, - QString *errorMessage, - QString *settingsIdHint) -{ - if (executable.endsWith(_("qmlviewer"))) { - qDebug() << "HERE"; - if (!qmlEngine) { - *errorMessage = msgEngineNotAvailable("Qml Engine"); - return 0; - } - return qmlEngine; - } - - if (executable.endsWith(_(".js"))) { - if (!scriptEngine) { - *errorMessage = msgEngineNotAvailable("Script Engine"); - return 0; - } - return scriptEngine; - } - - if (executable.endsWith(_(".py"))) { - if (!pdbEngine) { - *errorMessage = msgEngineNotAvailable("Pdb Engine"); - return 0; - } - return pdbEngine; - } - -#ifndef Q_OS_WIN - Q_UNUSED(settingsIdHint) - if (!gdbEngine) { - *errorMessage = msgEngineNotAvailable("Gdb Engine"); - return 0; - } - - return gdbEngine; -#else - // A remote executable? - if (!executable.endsWith(_(".exe"))) - return gdbEngine; - // If a file has PDB files, it has been compiled by VS. - QStringList pdbFiles; - if (!getPDBFiles(executable, &pdbFiles, errorMessage)) { - qWarning("Cannot determine type of executable %s: %s", - qPrintable(executable), qPrintable(*errorMessage)); - return 0; - } - if (pdbFiles.empty()) - return gdbEngine; - - // We need the CDB debugger in order to be able to debug VS - // executables - if (!DebuggerManager::instance()->checkDebugConfiguration( - ProjectExplorer::ToolChain::MSVC, errorMessage, 0, settingsIdHint)) - return 0; - return cdbEngine; -#endif -} - -// Debugger type for mode -static IDebuggerEngine *debuggerEngineForMode(DebuggerStartMode startMode, QString *errorMessage) -{ - if (startMode == AttachTcf) - return tcfEngine; - -#ifdef Q_OS_WIN - // Preferably Windows debugger for attaching locally. - if (startMode != AttachToRemote && cdbEngine) - return cdbEngine; - if (gdbEngine) - return gdbEngine; - *errorMessage = msgEngineNotAvailable("Gdb Engine"); - return 0; -#else - Q_UNUSED(startMode) - if (!gdbEngine) { - *errorMessage = msgEngineNotAvailable("Gdb Engine"); - return 0; - } - - return gdbEngine; -#endif -} - -void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl) -{ - if (d->m_state != DebuggerNotReady) - return; - d->m_runControl = runControl; - const DebuggerStartParameters *sp = &runControl->sp(); - const QString toolChainName = ProjectExplorer::ToolChain::toolChainName( - ProjectExplorer::ToolChain::ToolChainType(sp->toolChainType)); - - d->m_plugin->activateDebugMode(); - showMessage(tr("Starting debugger for tool chain '%1'...").arg(toolChainName), - LogStatus); - showMessage(DebuggerSettings::instance()->dump(), LogDebug); - - QString errorMessage; - QString settingsIdHint; - - // Figure out engine: toolchain, executable, attach or default - const DebuggerStartMode startMode = sp->startMode; - - if (sp->executable.endsWith(_("qmlviewer"))) - d->m_engine = qmlEngine; - else if (sp->executable.endsWith(_(".js"))) - d->m_engine = scriptEngine; - else if (sp->executable.endsWith(_(".py"))) - d->m_engine = pdbEngine; - else - d->m_engine = debuggerEngineForToolChain(sp->toolChainType); - - if (d->m_engine == 0 - && startMode != AttachToRemote - && !sp->executable.isEmpty()) - d->m_engine = debuggerEngineForExecutable( - sp->executable, &errorMessage, &settingsIdHint); - - if (d->m_engine == 0) - d->m_engine = debuggerEngineForMode(startMode, &errorMessage); - - if (!d->m_engine) { - emit debuggingFinished(); - // Create Message box with possibility to go to settings - const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3") - .arg(sp->executable, toolChainName, errorMessage); - Core::ICore::instance()->showWarningWithOptions(tr("Warning"), msg, QString(), - QLatin1String(DEBUGGER_SETTINGS_CATEGORY), settingsIdHint); - return; - } - - STATE_DEBUG(sp->executable << d->m_engine); - setBusyCursor(false); - setState(EngineStarting); - connect(d->m_engine, SIGNAL(startFailed()), this, SLOT(startFailed())); - runControl->startDebugger(d->m_engine); - - const unsigned engineCapabilities = d->m_engine->debuggerCapabilities(); - theDebuggerAction(OperateByInstruction) - ->setEnabled(engineCapabilities & DisassemblerCapability); - - const bool canReverse = (engineCapabilities & ReverseSteppingCapability) - && theDebuggerBoolSetting(EnableReverseDebugging); - d->m_actions.reverseDirectionAction->setChecked(false); - d->m_actions.reverseDirectionAction->setEnabled(canReverse); -} - -void DebuggerManager::startFailed() -{ - disconnect(d->m_engine, SIGNAL(startFailed()), this, SLOT(startFailed())); - setState(DebuggerNotReady); - emit debuggingFinished(); -} - -void DebuggerManager::cleanupViews() -{ - resetLocation(); - breakHandler()->setAllPending(); - stackHandler()->removeAll(); - threadsHandler()->removeAll(); - watchHandler()->cleanup(); - d->m_sourceFilesWindow->removeAll(); - d->m_disassemblerViewAgent.cleanup(); - d->m_actions.reverseDirectionAction->setChecked(false); - d->m_actions.reverseDirectionAction->setEnabled(false); - hideDebuggerToolTip(); - - // FIXME: Delete run control? - if (d->m_runControl) - d->m_runControl->cleanup(); - - // FIXME: Move to plugin? - using namespace Core; - if (EditorManager *editorManager = EditorManager::instance()) { - QList<IEditor *> toClose; - foreach (IEditor *editor, editorManager->openedEditors()) - if (editor->property("OpenedByDebugger").toBool()) - toClose.append(editor); - editorManager->closeEditors(toClose); - } -} - -void DebuggerManager::exitDebugger() -{ - // The engine will finally call setState(DebuggerNotReady) which - // in turn will handle the cleanup. - if (d->m_engine && state() != DebuggerNotReady) - d->m_engine->exitDebugger(); - d->m_codeModelSnapshot = CPlusPlus::Snapshot(); -} - -void DebuggerManager::abortDebugger() -{ - if (d->m_engine && state() != DebuggerNotReady) - d->m_engine->abortDebugger(); - d->m_codeModelSnapshot = CPlusPlus::Snapshot(); -} - -void DebuggerManager::assignValueInDebugger() -{ - if (QAction *action = qobject_cast<QAction *>(sender())) { - QString str = action->data().toString(); - int i = str.indexOf('='); - if (i != -1) - assignValueInDebugger(str.left(i), str.mid(i + 1)); - } -} - -void DebuggerManager::assignValueInDebugger(const QString &expr, const QString &value) -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->assignValueInDebugger(expr, value); -} - -void DebuggerManager::activateFrame(int index) -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->activateFrame(index); -} - -void DebuggerManager::selectThread(int index) -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->selectThread(index); -} - -void DebuggerManager::loadAllSymbols() -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->loadAllSymbols(); -} - -void DebuggerManager::loadSymbols(const QString &module) -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->loadSymbols(module); -} - -void DebuggerManager::executeStep() -{ - QTC_ASSERT(d->m_engine, return); - resetLocation(); - if (theDebuggerBoolSetting(OperateByInstruction)) - d->m_engine->executeStepI(); - else - d->m_engine->executeStep(); -} - -void DebuggerManager::executeStepOut() -{ - QTC_ASSERT(d->m_engine, return); - resetLocation(); - d->m_engine->executeStepOut(); -} - -void DebuggerManager::executeStepNext() -{ - QTC_ASSERT(d->m_engine, return); - resetLocation(); - if (theDebuggerBoolSetting(OperateByInstruction)) - d->m_engine->executeNextI(); - else - d->m_engine->executeNext(); -} - -void DebuggerManager::executeReturn() -{ - QTC_ASSERT(d->m_engine, return); - resetLocation(); - d->m_engine->executeReturn(); -} - -void DebuggerManager::watchPoint() -{ - if (QAction *action = qobject_cast<QAction *>(sender())) - if (d->m_engine) - d->m_engine->watchPoint(action->data().toPoint()); -} - -void DebuggerManager::executeDebuggerCommand() -{ - if (QAction *action = qobject_cast<QAction *>(sender())) - executeDebuggerCommand(action->data().toString()); -} - -void DebuggerManager::executeDebuggerCommand(const QString &command) -{ - STATE_DEBUG(command); - QTC_ASSERT(d->m_engine, return); - d->m_engine->executeDebuggerCommand(command); -} - -void DebuggerManager::sessionLoaded() -{ - loadSessionData(); -} - -void DebuggerManager::aboutToUnloadSession() -{ - // Stop debugging the active project when switching sessions. - // Note that at startup, session switches may occur, which interfer - // with command-line debugging startup. - if (d->m_engine && state() != DebuggerNotReady - && runControl()->sp().startMode == StartInternal) - d->m_engine->shutdown(); -} - -void DebuggerManager::aboutToSaveSession() -{ - saveSessionData(); -} - -void DebuggerManager::loadSessionData() -{ - d->m_breakHandler->loadSessionData(); - d->m_watchHandler->loadSessionData(); -} - -void DebuggerManager::saveSessionData() -{ - d->m_breakHandler->saveSessionData(); - d->m_watchHandler->saveSessionData(); -} - -void DebuggerManager::dumpLog() -{ - QString fileName = QFileDialog::getSaveFileName(d->m_mainWindow, - tr("Save Debugger Log"), QDir::tempPath()); - if (fileName.isEmpty()) - return; - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly)) - return; - QTextStream ts(&file); - ts << d->m_outputWindow->inputContents(); - ts << "\n\n=======================================\n\n"; - ts << d->m_outputWindow->combinedContents(); -} - -void DebuggerManager::addToWatchWindow() -{ - using namespace Core; - using namespace TextEditor; - // Requires a selection, but that's the only case we want anyway. - EditorManager *editorManager = EditorManager::instance(); - if (!editorManager) - return; - IEditor *editor = editorManager->currentEditor(); - if (!editor) - return; - ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor); - if (!textEditor) - return; - QTextCursor tc; - QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget()); - if (ptEdit) - tc = ptEdit->textCursor(); - QString exp; - if (tc.hasSelection()) { - exp = tc.selectedText(); - } else { - int line, column; - exp = cppExpressionAt(textEditor, tc.position(), &line, &column); - } - if (!exp.isEmpty()) - d->m_watchHandler->watchExpression(exp); -} - -void DebuggerManager::activateBreakpoint(int index) -{ - const BreakpointData *data = breakHandler()->at(index); - if (!data->markerFileName().isEmpty()) { - StackFrame frame; - frame.file = data->markerFileName(); - frame.line = data->markerLineNumber(); - gotoLocation(frame, false); - } -} - -void DebuggerManager::breakByFunctionMain() -{ -#ifdef Q_OS_WIN - // FIXME: wrong on non-Qt based binaries - emit breakByFunction("qMain"); -#else - emit breakByFunction("main"); -#endif -} - -void DebuggerManager::breakByFunction(const QString &functionName) -{ - QTC_ASSERT(d->m_breakHandler, return); - d->m_breakHandler->breakByFunction(functionName); - attemptBreakpointSynchronization(); -} - -void DebuggerManager::setBusyCursor(bool busy) -{ - //STATE_DEBUG("BUSY FROM: " << d->m_busy << " TO: " << d->m_busy); - if (busy == d->m_busy) - return; - d->m_busy = busy; - - QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor); - d->m_breakWindow->setCursor(cursor); - d->m_returnWindow->setCursor(cursor); - d->m_localsWindow->setCursor(cursor); - d->m_modulesWindow->setCursor(cursor); - d->m_outputWindow->setCursor(cursor); - d->m_registerWindow->setCursor(cursor); - d->m_stackWindow->setCursor(cursor); - d->m_sourceFilesWindow->setCursor(cursor); - d->m_threadsWindow->setCursor(cursor); - //d->m_tooltipWindow->setCursor(cursor); - d->m_watchersWindow->setCursor(cursor); -} - -void DebuggerManager::executeContinue() -{ - if (d->m_engine) - d->m_engine->continueInferior(); -} - -void DebuggerManager::detachDebugger() -{ - if (d->m_engine) - d->m_engine->detachDebugger(); -} - -void DebuggerManager::interruptDebuggingRequest() -{ - STATE_DEBUG(state()); - if (!d->m_engine) - return; - bool interruptIsExit = (state() != InferiorRunning); - if (interruptIsExit) { - exitDebugger(); - } else { - d->m_engine->interruptInferior(); - } -} - -void DebuggerManager::executeRunToLine() -{ - ITextEditor *textEditor = d->m_plugin->currentTextEditor(); - QTC_ASSERT(textEditor, return); - QString fileName = textEditor->file()->fileName(); - int lineNumber = textEditor->currentLine(); - if (d->m_engine && !fileName.isEmpty()) { - STATE_DEBUG(fileName << lineNumber); - resetLocation(); - d->m_engine->executeRunToLine(fileName, lineNumber); - } -} - -void DebuggerManager::executeRunToFunction() -{ - ITextEditor *textEditor = d->m_plugin->currentTextEditor(); - QTC_ASSERT(textEditor, return); - QString fileName = textEditor->file()->fileName(); - QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget()); - if (!ed) - return; - QTextCursor cursor = ed->textCursor(); - QString functionName = cursor.selectedText(); - if (functionName.isEmpty()) { - const QTextBlock block = cursor.block(); - const QString line = block.text(); - foreach (const QString &str, line.trimmed().split('(')) { - QString a; - for (int i = str.size(); --i >= 0; ) { - if (!str.at(i).isLetterOrNumber()) - break; - a = str.at(i) + a; - } - if (!a.isEmpty()) { - functionName = a; - break; - } - } - } - STATE_DEBUG(functionName); - - if (d->m_engine && !functionName.isEmpty()) { - resetLocation(); - d->m_engine->executeRunToFunction(functionName); - } -} - -void DebuggerManager::executeJumpToLine() -{ - ITextEditor *textEditor = d->m_plugin->currentTextEditor(); - QTC_ASSERT(textEditor, return); - QString fileName = textEditor->file()->fileName(); - int lineNumber = textEditor->currentLine(); - if (d->m_engine && !fileName.isEmpty()) { - STATE_DEBUG(fileName << lineNumber); - d->m_engine->executeJumpToLine(fileName, lineNumber); - } -} - -void DebuggerManager::resetLocation() -{ - d->m_disassemblerViewAgent.resetLocation(); - d->m_stackHandler->setCurrentIndex(-1); - d->m_plugin->resetLocation(); -} - -void DebuggerManager::gotoLocation(const StackFrame &frame, bool setMarker) -{ - if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) { - if (setMarker) - d->m_plugin->resetLocation(); - d->m_disassemblerViewAgent.setFrame(frame); - } else { - d->m_plugin->gotoLocation(frame.file, frame.line, setMarker); - } -} - -void DebuggerManager::fileOpen(const QString &fileName) -{ - StackFrame frame; - frame.file = fileName; - frame.line = -1; - gotoLocation(frame, false); -} - -void DebuggerManager::operateByInstructionTriggered() -{ - if (!d->m_engine) - return; - QTC_ASSERT(d->m_stackHandler, return); - StackFrame frame = d->m_stackHandler->currentFrame(); - gotoLocation(frame, true); -} - - -////////////////////////////////////////////////////////////////////// -// -// Source files specific stuff -// -////////////////////////////////////////////////////////////////////// - -void DebuggerManager::reloadSourceFiles() -{ - if (d->m_engine && d->m_sourceFilesDock && d->m_sourceFilesDock->isVisible()) - d->m_engine->reloadSourceFiles(); -} - -void DebuggerManager::sourceFilesDockToggled(bool on) -{ - if (on) - reloadSourceFiles(); -} - - -////////////////////////////////////////////////////////////////////// -// -// Modules specific stuff -// -////////////////////////////////////////////////////////////////////// - -void DebuggerManager::reloadModules() -{ - if (d->m_engine && d->m_modulesDock && d->m_modulesDock->isVisible()) - d->m_engine->reloadModules(); -} - -void DebuggerManager::modulesDockToggled(bool on) -{ - if (on) - reloadModules(); -} - -void DebuggerManager::showMessage(const QString &msg, int channel) -{ - if (runControl()) - runControl()->showMessage(msg, channel); - //else - // qDebug() << "OUTPUT: " << channel << msg; -} - - -////////////////////////////////////////////////////////////////////// -// -// Register specific stuff -// -////////////////////////////////////////////////////////////////////// - -void DebuggerManager::registerDockToggled(bool on) -{ - if (on) - reloadRegisters(); -} - -void DebuggerManager::reloadRegisters() -{ - if (d->m_engine && d->m_registerDock && d->m_registerDock->isVisible()) - d->m_engine->reloadRegisters(); -} - -////////////////////////////////////////////////////////////////////// -// -// Dumpers. "Custom dumpers" are a library compiled against the current -// Qt containing functions to evaluate values of Qt classes -// (such as QString, taking pointers to their addresses). -// The library must be loaded into the debuggee. -// -////////////////////////////////////////////////////////////////////// - -bool DebuggerManager::qtDumperLibraryEnabled() const -{ - return theDebuggerBoolSetting(UseDebuggingHelpers); -} - -QString DebuggerManager::qtDumperLibraryName() const -{ - if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) - return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); - return runControl()->sp().dumperLibrary; -} - -QStringList DebuggerManager::qtDumperLibraryLocations() const -{ - if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) { - const QString customLocation = - theDebuggerAction(CustomDebuggingHelperLocation)->value().toString(); - const QString location = - tr("%1 (explicitly set in the Debugger Options)").arg(customLocation); - return QStringList(location); - } - return runControl()->sp().dumperLibraryLocations; -} - -void DebuggerManager::showQtDumperLibraryWarning(const QString &details) -{ - QMessageBox dialog(d->m_mainWindow); - QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"), - QMessageBox::ActionRole); - QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"), - QMessageBox::ActionRole); - QPushButton *justContinue = dialog.addButton(tr("Continue anyway"), - QMessageBox::AcceptRole); - dialog.setDefaultButton(justContinue); - dialog.setWindowTitle(tr("Debugging helper missing")); - dialog.setText(tr("The debugger could not load the debugging helper library.")); - dialog.setInformativeText(tr( - "The debugging helper is used to nicely format the values of some Qt " - "and Standard Library data types. " - "It must be compiled for each used Qt version separately. " - "This can be done in the Qt preferences page by selecting a Qt installation " - "and clicking on 'Rebuild' in the 'Debugging Helper' row.")); - if (!details.isEmpty()) - dialog.setDetailedText(details); - dialog.exec(); - if (dialog.clickedButton() == qtPref) { - Core::ICore::instance()->showOptionsDialog( - _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY), - _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID)); - } else if (dialog.clickedButton() == helperOff) { - theDebuggerAction(UseDebuggingHelpers) - ->setValue(qVariantFromValue(false), false); - } -} - -void DebuggerManager::reloadFullStack() -{ - if (d->m_engine) - d->m_engine->reloadFullStack(); -} - -void DebuggerManager::setRegisterValue(int nr, const QString &value) -{ - if (d->m_engine) - d->m_engine->setRegisterValue(nr, value); -} - -bool DebuggerManager::isReverseDebugging() const -{ - return d->m_actions.reverseDirectionAction->isChecked(); -} - -QVariant DebuggerManager::sessionValue(const QString &name) -{ - return d->m_plugin->sessionValue(name); -} - -void DebuggerManager::setSessionValue(const QString &name, const QVariant &value) -{ - d->m_plugin->setSessionValue(name, value); -} - -QMessageBox *DebuggerManager::showMessageBox(int icon, const QString &title, - const QString &text, int buttons) -{ - QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon), - title, text, QMessageBox::StandardButtons(buttons), d->m_mainWindow); - mb->setAttribute(Qt::WA_DeleteOnClose); - mb->show(); - return mb; -} - -DebuggerState DebuggerManager::state() const -{ - return d->m_state; -} - -static bool isAllowedTransition(int from, int to) -{ - switch (from) { - case -1: - return to == DebuggerNotReady; - - case DebuggerNotReady: - return to == EngineStarting || to == DebuggerNotReady; - - case EngineStarting: - return to == AdapterStarting || to == DebuggerNotReady; - - case AdapterStarting: - return to == AdapterStarted || to == AdapterStartFailed; - case AdapterStarted: - return to == InferiorStarting || to == EngineShuttingDown; - case AdapterStartFailed: - return to == DebuggerNotReady; - - case InferiorStarting: - return to == InferiorRunningRequested || to == InferiorStopped - || to == InferiorStartFailed || to == InferiorUnrunnable; - case InferiorStartFailed: - return to == EngineShuttingDown; - - case InferiorRunningRequested: - return to == InferiorRunning || to == InferiorStopped - || to == InferiorRunningRequested_Kill; - case InferiorRunningRequested_Kill: - return to == InferiorRunning || to == InferiorStopped; - case InferiorRunning: - return to == InferiorStopping; - - case InferiorStopping: - return to == InferiorStopped || to == InferiorStopFailed - || to == InferiorStopping_Kill; - case InferiorStopping_Kill: - return to == InferiorStopped || to == InferiorStopFailed; - case InferiorStopped: - return to == InferiorRunningRequested || to == InferiorShuttingDown; - case InferiorStopFailed: - return to == EngineShuttingDown; - - case InferiorUnrunnable: - return to == EngineShuttingDown; - case InferiorShuttingDown: - return to == InferiorShutDown || to == InferiorShutdownFailed; - case InferiorShutDown: - return to == EngineShuttingDown; - case InferiorShutdownFailed: - return to == EngineShuttingDown; - - case EngineShuttingDown: - return to == DebuggerNotReady; - } - - qDebug() << "UNKNOWN STATE:" << from; - return false; -} - -void DebuggerManager::setState(DebuggerState state, bool forced) -{ - //STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state) - // << " TO " << stateName(state)); - - QString msg = _("State changed from %1(%2) to %3(%4).") - .arg(stateName(d->m_state)).arg(d->m_state).arg(stateName(state)).arg(state); - //if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0))) - // qDebug() << msg; - if (!forced && !isAllowedTransition(d->m_state, state)) - qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; - - showMessage(msg, LogDebug); - - //resetLocation(); - if (state == d->m_state) - return; - - d->m_state = state; - - emit stateChanged(state); - - //if (d->m_state == InferiorStopped) - // resetLocation(); - - if (d->m_state == DebuggerNotReady) { - setBusyCursor(false); - cleanupViews(); - emit debuggingFinished(); - } - - const bool stoppable = state == InferiorRunning - || state == InferiorRunningRequested - || state == InferiorStopping - || state == InferiorStopped - || state == InferiorUnrunnable; - - const bool running = state == InferiorRunning; - if (running) - threadsHandler()->notifyRunning(); - const bool stopped = state == InferiorStopped; - - if (stopped) - QApplication::alert(d->m_mainWindow, 3000); - - const bool actionsEnabled = debuggerActionsEnabled(); - const unsigned engineCapabilities = debuggerCapabilities(); - d->m_actions.watchAction1->setEnabled(true); - d->m_actions.watchAction2->setEnabled(true); - d->m_actions.breakAction->setEnabled(true); - d->m_actions.snapshotAction-> - setEnabled(stopped && (engineCapabilities & SnapshotCapability)); - - theDebuggerAction(OperateByInstruction)->setEnabled(!running); - - const bool interruptIsExit = !running; - if (interruptIsExit) { - d->m_actions.stopAction->setIcon(d->m_stopIcon); - d->m_actions.stopAction->setText(tr("Stop Debugger")); - } else { - d->m_actions.stopAction->setIcon(d->m_interruptIcon); - d->m_actions.stopAction->setText(tr("Interrupt")); - } - - d->m_actions.stopAction->setEnabled(stoppable); - d->m_actions.resetAction->setEnabled(state != DebuggerNotReady); - - d->m_actions.stepAction->setEnabled(stopped); - d->m_actions.stepOutAction->setEnabled(stopped); - d->m_actions.runToLineAction1->setEnabled(stopped); - d->m_actions.runToLineAction2->setEnabled(stopped); - d->m_actions.runToFunctionAction->setEnabled(stopped); - d->m_actions.returnFromFunctionAction-> - setEnabled(stopped && (engineCapabilities & ReturnFromFunctionCapability)); - - const bool canJump = stopped && (engineCapabilities & JumpToLineCapability); - d->m_actions.jumpToLineAction1->setEnabled(canJump); - d->m_actions.jumpToLineAction2->setEnabled(canJump); - - d->m_actions.nextAction->setEnabled(stopped); - - theDebuggerAction(RecheckDebuggingHelpers)->setEnabled(actionsEnabled); - const bool canDeref = actionsEnabled - && (engineCapabilities & AutoDerefPointersCapability); - theDebuggerAction(AutoDerefPointers)->setEnabled(canDeref); - theDebuggerAction(ExpandStack)->setEnabled(actionsEnabled); - theDebuggerAction(ExecuteCommand)->setEnabled(d->m_state != DebuggerNotReady); - - updateWatchersWindow(); - - d->m_plugin->handleStateChanged(d->m_state); - const bool notbusy = state == InferiorStopped - || state == DebuggerNotReady - || state == InferiorUnrunnable; - setBusyCursor(!notbusy); -} - -bool DebuggerManager::debuggerActionsEnabled() const -{ - if (!d->m_engine) - return false; - switch (state()) { - case InferiorStarting: - case InferiorRunningRequested: - case InferiorRunning: - case InferiorUnrunnable: - case InferiorStopping: - case InferiorStopped: - return true; - case DebuggerNotReady: - case EngineStarting: - case AdapterStarting: - case AdapterStarted: - case AdapterStartFailed: - case InferiorStartFailed: - case InferiorRunningRequested_Kill: - case InferiorStopping_Kill: - case InferiorStopFailed: - case InferiorShuttingDown: - case InferiorShutDown: - case InferiorShutdownFailed: - case EngineShuttingDown: - break; - } - return false; -} - -unsigned DebuggerManager::debuggerCapabilities() const -{ - return d->m_engine ? d->m_engine->debuggerCapabilities() : 0; -} - -bool DebuggerManager::checkDebugConfiguration(int toolChain, - QString *errorMessage, - QString *settingsCategory /* = 0 */, - QString *settingsPage /* = 0 */) const -{ - errorMessage->clear(); - if (settingsCategory) - settingsCategory->clear(); - if (settingsPage) - settingsPage->clear(); - bool success = true; - switch(toolChain) { - case ProjectExplorer::ToolChain::GCC: - case ProjectExplorer::ToolChain::LINUX_ICC: - case ProjectExplorer::ToolChain::MinGW: - case ProjectExplorer::ToolChain::WINCE: // S60 - case ProjectExplorer::ToolChain::WINSCW: - case ProjectExplorer::ToolChain::GCCE: - case ProjectExplorer::ToolChain::RVCT_ARMV5: - case ProjectExplorer::ToolChain::RVCT_ARMV6: - if (gdbEngine) { - success = gdbEngine->checkConfiguration(toolChain, errorMessage, settingsPage); - } else { - success = false; - *errorMessage = msgEngineNotAvailable("Gdb"); - } - break; - case ProjectExplorer::ToolChain::MSVC: - if (cdbEngine) { - success = cdbEngine->checkConfiguration(toolChain, errorMessage, settingsPage); - } else { - success = false; - *errorMessage = msgEngineNotAvailable("Cdb"); - if (settingsPage) - *settingsPage = QLatin1String("Cdb"); - } - break; - } - if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty()) - *settingsCategory = QLatin1String(DEBUGGER_SETTINGS_CATEGORY); - return success; -} - -void DebuggerManager::ensureLogVisible() -{ - QAction *action = d->m_outputDock->toggleViewAction(); - if (!action->isChecked()) - action->trigger(); -} - -QIcon DebuggerManager::locationMarkIcon() const -{ - return d->m_locationMarkIcon; -} - -QDebug operator<<(QDebug d, DebuggerState state) -{ - return d << DebuggerManager::stateName(state) << '(' << int(state) << ')'; -} - -static void changeFontSize(QWidget *widget, int size) -{ - QFont font = widget->font(); - font.setPointSize(size); - widget->setFont(font); -} - -void DebuggerManager::fontSettingsChanged(const TextEditor::FontSettings &settings) -{ - int size = settings.fontZoom() * settings.fontSize() / 100; - changeFontSize(d->m_returnWindow, size); - changeFontSize(d->m_localsWindow, size); - changeFontSize(d->m_watchersWindow, size); - changeFontSize(d->m_breakWindow, size); - changeFontSize(d->m_modulesWindow, size); - changeFontSize(d->m_outputWindow, size); - changeFontSize(d->m_registerWindow, size); - changeFontSize(d->m_stackWindow, size); - changeFontSize(d->m_sourceFilesWindow, size); - changeFontSize(d->m_threadsWindow, size); -} - -void DebuggerManager::updateWatchersHeader(int section, int, int newSize) -{ - QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow); - watchersView->header()->resizeSection(section, newSize); -} - -void DebuggerManager::updateWatchersWindow() -{ - d->m_watchersWindow->setVisible( - d->m_watchHandler->model(WatchersWatch)->rowCount(QModelIndex()) > 0); - d->m_returnWindow->setVisible( - d->m_watchHandler->model(ReturnWatch)->rowCount(QModelIndex()) > 0); -} - -void DebuggerManager::openTextEditor(const QString &titlePattern, - const QString &contents) -{ - d->m_plugin->openTextEditor(titlePattern, contents); -} - -DebuggerRunControl *DebuggerManager::runControl() const -{ - return d->m_runControl; -} - -DebuggerOutputWindow *DebuggerManager::debuggerOutputWindow() const -{ - return d->m_outputWindow; -} - -BreakHandler *DebuggerManager::breakHandler() const -{ - return d->m_breakHandler; -} - -StackHandler *DebuggerManager::stackHandler() const -{ - return d->m_stackHandler; -} - -ThreadsHandler *DebuggerManager::threadsHandler() const -{ - return d->m_threadsHandler; -} - -WatchHandler *DebuggerManager::watchHandler() const -{ - return d->m_watchHandler; -} - -void DebuggerManager::makeSnapshot() -{ - QTC_ASSERT(d->m_engine, return); - d->m_engine->makeSnapshot(); -} - - -////////////////////////////////////////////////////////////////////// -// -// Testing -// -////////////////////////////////////////////////////////////////////// - -/* -void DebuggerManager::runTest(const QString &fileName) -{ - d->m_startParameters->executable = fileName; - d->m_startParameters->processArgs = QStringList() << "--run-debuggee"; - d->m_startParameters->workingDirectory.clear(); - //startNewDebugger(StartInternal); -} -*/ - -} // namespace Debugger - diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h deleted file mode 100644 index 5c1eec2faf29430766e452e48eaca747a8a60cce..0000000000000000000000000000000000000000 --- a/src/plugins/debugger/debuggermanager.h +++ /dev/null @@ -1,321 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** -**************************************************************************/ - -#ifndef DEBUGGER_DEBUGGERMANAGER_H -#define DEBUGGER_DEBUGGERMANAGER_H - -#include "debugger_global.h" -#include "debuggerconstants.h" -#include "debuggerrunner.h" - -#include <QtCore/QObject> -#include <QtCore/QSharedPointer> -#include <QtCore/QStringList> -#include <QtCore/QVariant> - -QT_BEGIN_NAMESPACE -class QAbstractItemModel; -class QAbstractItemView; -class QAction; -class QDebug; -class QDockWidget; -class QLabel; -class QMessageBox; -class QPoint; -class QIcon; -QT_END_NAMESPACE - -namespace Core { -class IOptionsPage; -} - -namespace TextEditor { -class ITextEditor; -class FontSettings; -} - -namespace CPlusPlus { - class Snapshot; -} - -namespace Debugger { -namespace Internal { - -class DebuggerOutputWindow; -class DebuggerPlugin; - -class BreakpointData; -class SourceFilesWindow; -struct StackFrame; -class Symbol; -class WatchData; -class WatchHandler; -class IDebuggerEngine; -class GdbEngine; -class ScriptEngine; -class PdbEngine; -class CdbDebugEngine; -class CdbDebugEnginePrivate; -struct DebuggerManagerActions; -class CdbDebugEventCallback; -class CdbDumperHelper; -class CdbDumperInitThread; -class CdbExceptionLoggerEventCallback; -class GdbEngine; -class TcfEngine; -class QmlEngine; -class CdbDebugEngine; -class CdbDebugEnginePrivate; -class TrkGdbAdapter; -class BreakpointMarker; -} // namespace Internal - -// Flags for initialization -enum DebuggerEngineTypeFlags -{ - GdbEngineType = 0x01, - ScriptEngineType = 0x02, - CdbEngineType = 0x04, - PdbEngineType = 0x08, - TcfEngineType = 0x10, - QmlEngineType = 0x20, - AllEngineTypes = GdbEngineType - | ScriptEngineType - | CdbEngineType - | PdbEngineType - | TcfEngineType - | QmlEngineType -}; - -QDebug operator<<(QDebug d, DebuggerState state); - -// -// DebuggerManager -// - -struct DebuggerManagerPrivate; - -class DEBUGGER_EXPORT DebuggerManager : public QObject -{ - Q_OBJECT - -public: - explicit DebuggerManager(Internal::DebuggerPlugin *plugin); - ~DebuggerManager(); - - friend class Internal::IDebuggerEngine; - friend class Internal::DebuggerPlugin; - friend class Internal::CdbDebugEventCallback; - friend class Internal::CdbDumperHelper; - friend class Internal::CdbDumperInitThread; - friend class Internal::CdbExceptionLoggerEventCallback; - friend class Internal::GdbEngine; - friend class Internal::ScriptEngine; - friend class Internal::PdbEngine; - friend class Internal::TcfEngine; - friend class Internal::QmlEngine; - friend class Internal::CdbDebugEngine; - friend class Internal::CdbDebugEnginePrivate; - friend class Internal::TrkGdbAdapter; - friend class Internal::BreakpointMarker; - - DebuggerState state() const; - QList<Core::IOptionsPage*> initializeEngines(unsigned enabledTypeFlags); - - QLabel *statusLabel() const; - Internal::IDebuggerEngine *currentEngine() const; - - DebuggerRunControl *runControl() const; - - QMessageBox *showMessageBox(int icon, const QString &title, const QString &text, - int buttons = 0); - - bool debuggerActionsEnabled() const; - unsigned debuggerCapabilities() const; - - bool checkDebugConfiguration(int toolChain, - QString *errorMessage, - QString *settingsCategory = 0, - QString *settingsPage = 0) const; - - const CPlusPlus::Snapshot &cppCodeModelSnapshot() const; - - QIcon locationMarkIcon() const; - - static DebuggerManager *instance(); - - void startNewDebugger(DebuggerRunControl *runControl); -public slots: - void exitDebugger(); - void abortDebugger(); - - void setSimpleDockWidgetArrangement(const QString &activeLanguage); - - void setBusyCursor(bool on); - - void gotoLocation(const Debugger::Internal::StackFrame &frame, bool setLocationMarker); - void fileOpen(const QString &file); - void resetLocation(); - - void interruptDebuggingRequest(); - - void executeJumpToLine(); - void executeRunToLine(); - void executeRunToFunction(); - void breakByFunction(const QString &functionName); - void breakByFunctionMain(); - void activateFrame(int index); - void selectThread(int index); - - void executeStep(); - void executeStepOut(); - void executeStepNext(); - void executeContinue(); - void executeReturn(); - void detachDebugger(); - void frameUp(); - void frameDown(); - - void addToWatchWindow(); - void updateWatchData(const Debugger::Internal::WatchData &data); - - void sessionLoaded(); - void aboutToUnloadSession(); - void aboutToSaveSession(); - QVariant sessionValue(const QString &name); - void setSessionValue(const QString &name, const QVariant &value); - - void assignValueInDebugger(); - void assignValueInDebugger(const QString &expr, const QString &value); - - void executeDebuggerCommand(); - void executeDebuggerCommand(const QString &command); - - void watchPoint(); - void setRegisterValue(int nr, const QString &value); - - void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever - void clearCppCodeModelSnapshot(); - - static const char *stateName(int s); - -public slots: // FIXME - void ensureLogVisible(); - void updateWatchersWindow(); - void updateWatchersHeader(int section, int oldSize, int newSize); - void activateBreakpoint(int index); - -//private slots: // FIXME - void reloadSourceFiles(); - void sourceFilesDockToggled(bool on); - - void reloadModules(); - void modulesDockToggled(bool on); - void loadSymbols(const QString &moduleName); - void loadAllSymbols(); - - void reloadRegisters(); - void registerDockToggled(bool on); - void clearStatusMessage(); - void attemptBreakpointSynchronization(); - void reloadFullStack(); - void operateByInstructionTriggered(); - void startFailed(); - - // Called from global action. - void makeSnapshot(); - - friend class DebuggerRunControl; -public: - Internal::BreakHandler *breakHandler() const; - Internal::StackHandler *stackHandler() const; - Internal::ThreadsHandler *threadsHandler() const; - Internal::WatchHandler *watchHandler() const; - - Internal::DebuggerOutputWindow *debuggerOutputWindow() const; - -private: - Internal::SourceFilesWindow *sourceFileWindow() const; - QAbstractItemView *modulesWindow() const; - QAbstractItemView *registerWindow() const; - QAbstractItemView *snapshotWindow() const; - QWidget *threadsWindow() const; - - Internal::DebuggerManagerActions debuggerManagerActions() const; - - void notifyInferiorStopped(); - void notifyInferiorRunning(); - void notifyInferiorExited(); - - void cleanupViews(); - - void setState(DebuggerState state, bool forced = false); - - // - // internal implementation - // - bool qtDumperLibraryEnabled() const; - QString qtDumperLibraryName() const; - QStringList qtDumperLibraryLocations() const; - void showQtDumperLibraryWarning(const QString &details = QString()); - bool isReverseDebugging() const; - QAbstractItemModel *threadsModel(); - - Q_SLOT void loadSessionData(); - Q_SLOT void saveSessionData(); - Q_SLOT void dumpLog(); - Q_SLOT void fontSettingsChanged(const TextEditor::FontSettings &settings); - -signals: - void debuggingFinished(); - void stateChanged(int newstatus); - void statusMessageRequested(const QString &msg, int timeout); // -1 for 'forever' - void applicationOutputAvailable(const QString &output, bool onStdErr); - void messageAvailable(const QString &output, bool isError); - -private: - void init(); - // void runTest(const QString &fileName); - void showMessage(const QString &msg, int channel); - Q_SLOT void createNewDock(QWidget *widget); - - void aboutToShutdown(); - - //void toggleBreakpoint(const QString &fileName, int lineNumber); - void setToolTipExpression(const QPoint &mousePos, - TextEditor::ITextEditor *editor, int cursorPos); - void openTextEditor(const QString &titlePattern, - const QString &contents); - - DebuggerManagerPrivate *d; -}; - -} // namespace Debugger - -#endif // DEBUGGER_DEBUGGERMANAGER_H diff --git a/src/plugins/debugger/debuggeroutputwindow.cpp b/src/plugins/debugger/debuggeroutputwindow.cpp index df75bc9a4b82786f17dc04c65280746de02abbbb..8b92763c8028988e56e04188a84dabaefa74dfec 100644 --- a/src/plugins/debugger/debuggeroutputwindow.cpp +++ b/src/plugins/debugger/debuggeroutputwindow.cpp @@ -28,8 +28,9 @@ **************************************************************************/ #include "debuggeroutputwindow.h" + #include "debuggeractions.h" -#include "debuggermanager.h" +#include "debuggerconstants.h" #include <QtCore/QDebug> #include <QtCore/QFile> diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 01b646c7a3768cf11a09968a7cd87ceb9b43f039..d4861b3d7bd3fb4fddd37eb11ac36a9a9b0a1bfa 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -29,15 +29,37 @@ #include "debuggerplugin.h" -#include "breakhandler.h" #include "debuggeractions.h" -#include "debuggerdialogs.h" +#include "debuggeragents.h" #include "debuggerconstants.h" -#include "debuggermanager.h" +#include "debuggerdialogs.h" +#include "debuggerengine.h" +#include "debuggermainwindow.h" +#include "debuggeroutputwindow.h" +#include "debuggerplugin.h" #include "debuggerrunner.h" #include "debuggerstringutils.h" +#include "debuggertooltip.h" #include "debuggeruiswitcher.h" -#include "debuggermainwindow.h" + +#include "breakwindow.h" +#include "moduleswindow.h" +#include "registerwindow.h" +#include "snapshotwindow.h" +#include "stackwindow.h" +#include "sourcefileswindow.h" +#include "threadswindow.h" +#include "watchwindow.h" + +//#include "sessiondata.h" +#include "watchutils.h" +#include "stackhandler.h" // FIXME +#include "watchhandler.h" // FIXME + +#ifdef Q_OS_WIN +# include "shared/peutils.h" +#endif + #include "ui_commonoptionspage.h" #include "ui_dumperoptionpage.h" @@ -62,8 +84,10 @@ #include <coreplugin/uniqueidmanager.h> #include <cplusplus/ExpressionUnderCursor.h> +#include <cplusplus/CppDocument.h> #include <cppeditor/cppeditorconstants.h> +#include <cpptools/cppmodelmanagerinterface.h> #include <extensionsystem/pluginmanager.h> @@ -75,35 +99,104 @@ #include <texteditor/basetexteditor.h> #include <texteditor/basetextmark.h> +#include <texteditor/fontsettings.h> #include <texteditor/itexteditor.h> #include <texteditor/texteditorconstants.h> #include <texteditor/texteditorsettings.h> +//#include <qt4projectmanager/qt4projectmanagerconstants.h> + #include <utils/qtcassert.h> -#include <utils/styledbar.h> #include <utils/savedaction.h> +#include <utils/styledbar.h> +#include <QtCore/QCoreApplication> #include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QFileInfo> #include <QtCore/QObject> #include <QtCore/QPoint> #include <QtCore/QSettings> -#include <QtCore/QtPlugin> -#include <QtCore/QCoreApplication> +#include <QtCore/QTextStream> +#include <QtCore/QTime> #include <QtCore/QTimer> #include <QtCore/QVariant> +#include <QtCore/QtPlugin> -#include <QtGui/QLineEdit> +#include <QtGui/QAbstractItemView> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QComboBox> #include <QtGui/QDockWidget> +#include <QtGui/QErrorMessage> +#include <QtGui/QFileDialog> +#include <QtGui/QHeaderView> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QMenu> +#include <QtGui/QMessageBox> #include <QtGui/QPlainTextEdit> +#include <QtGui/QPushButton> +#include <QtGui/QStatusBar> #include <QtGui/QTextBlock> #include <QtGui/QTextCursor> #include <QtGui/QToolButton> -#include <QtGui/QMessageBox> -#include <QtGui/QAction> -#include <QtGui/QMenu> +#include <QtGui/QToolTip> +#include <QtGui/QTreeWidget> #include <climits> +#define DEBUG_STATE 1 +#ifdef DEBUG_STATE +//# define STATE_DEBUG(s) +// do { QString msg; QTextStream ts(&msg); ts << s; +// showMessage(msg, LogDebug); } while (0) +# define STATE_DEBUG(s) do { qDebug() << s; } while(0) +#else +# define STATE_DEBUG(s) +#endif + +// Note: the Debugger process itself and any helper processes like +// gdbserver, the trk client etc are referred to as 'Adapter', +// whereas the debugged process is referred to as 'Inferior'. +// +// 0 == DebuggerNotReady +// | +// EngineStarting +// | +// AdapterStarting --> AdapterStartFailed --> 0 +// | +// AdapterStarted ------------------------------------. +// | v +// InferiorStarting ----> InferiorStartFailed -------->| +// | | +// (core) | (attach) (term) (remote) | +// .-----------------<-|->------------------. | +// | v | | +// InferiorUnrunnable | (plain) | | +// | | (trk) | | +// | | | | +// | .--> InferiorRunningRequested | | +// | | | | | +// | | InferiorRunning | | +// | | | | | +// | | InferiorStopping | | +// | | | | | +// | '------ InferiorStopped <-----------' | +// | | v +// | InferiorShuttingDown -> InferiorShutdownFailed ---->| +// | | | +// | InferiorShutDown | +// | | | +// '--------> EngineShuttingDown <--------------------------------' +// | +// 0 +// +// Allowed actions: +// [R] : Run +// [C] : Continue +// [N] : Step, Next + using namespace Core; using namespace Debugger; using namespace Debugger::Constants; @@ -179,6 +272,7 @@ const char * const SNAPSHOT_KEY = "Alt+D,Alt+S"; } // namespace Debugger + static ProjectExplorer::SessionManager *sessionManager() { return ProjectExplorer::ProjectExplorerPlugin::instance()->session(); @@ -196,38 +290,58 @@ static QToolButton *toolButton(QAction *action) return button; } +namespace Debugger { +namespace Internal { + +// FIXME: Outdated? +// The createCdbEngine function takes a list of options pages it can add to. +// This allows for having a "enabled" toggle on the page independently +// of the engine. That's good for not enabling the related ActiveX control +// unnecessarily. + +void addGdbOptionPages(QList<Core::IOptionsPage*> *opts); +void addScriptOptionPages(QList<Core::IOptionsPage*> *opts); +void addTcfOptionPages(QList<Core::IOptionsPage*> *opts); +#ifdef CDB_ENABLED +void addCdbOptionPages(QList<Core::IOptionsPage*> *opts); +#endif + + +struct AttachRemoteParameters +{ + AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {} + + quint64 attachPid; + QString attachCore; + // Event handle for attaching to crashed Windows processes. + quint64 winCrashEvent; +}; + + /////////////////////////////////////////////////////////////////////// // // DebugMode // /////////////////////////////////////////////////////////////////////// -namespace Debugger { -namespace Internal { - class DebugMode : public Core::BaseMode { - Q_OBJECT - public: - DebugMode(QObject *parent = 0); - ~DebugMode(); -}; + DebugMode(QObject *parent = 0) : BaseMode(parent) + { + setDisplayName(tr("Debug")); + setId(MODE_DEBUG); + setIcon(QIcon(":/fancyactionbar/images/mode_Debug.png")); + setPriority(P_MODE_DEBUG); + } -DebugMode::DebugMode(QObject *parent) - : BaseMode(parent) -{ - setDisplayName(tr("Debug")); - setId(MODE_DEBUG); - setIcon(QIcon(":/fancyactionbar/images/mode_Debug.png")); - setPriority(P_MODE_DEBUG); -} + ~DebugMode() + { + // Make sure the editor manager does not get deleted. + EditorManager::instance()->setParent(0); + } +}; -DebugMode::~DebugMode() -{ - // Make sure the editor manager does not get deleted - EditorManager::instance()->setParent(0); -} /////////////////////////////////////////////////////////////////////// // @@ -237,59 +351,11 @@ DebugMode::~DebugMode() class DebuggerListener : public Core::ICoreListener { - Q_OBJECT public: DebuggerListener() {} virtual bool coreAboutToClose(); }; -bool DebuggerListener::coreAboutToClose() -{ - DebuggerManager *mgr = DebuggerManager::instance(); - if (!mgr) - return true; - // Ask to terminate the session. - bool cleanTermination = false; - switch (mgr->state()) { - case DebuggerNotReady: - return true; - case AdapterStarted: // Most importantly, terminating a running - case AdapterStartFailed: // debuggee can cause problems. - case InferiorUnrunnable: - case InferiorStartFailed: - case InferiorStopped: - case InferiorShutDown: - cleanTermination = true; - break; - default: - break; - } - - const QString question = cleanTermination ? - tr("A debugging session is still in progress.\n" - "Would you like to terminate it?") : - tr("A debugging session is still in progress. " - "Terminating the session in the current" - " state (%1) can leave the target in an inconsistent state." - " Would you still like to terminate it?") - .arg(_(DebuggerManager::stateName(mgr->state()))); - - QMessageBox::StandardButton answer = - QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(), - tr("Close Debugging Session"), question, - QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); - - if (answer != QMessageBox::Yes) - return false; - - mgr->exitDebugger(); - QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); - return true; -} - -} // namespace Internal -} // namespace Debugger - /////////////////////////////////////////////////////////////////////// // @@ -297,28 +363,20 @@ bool DebuggerListener::coreAboutToClose() // /////////////////////////////////////////////////////////////////////// -namespace Debugger { -namespace Internal { - // Used in "real" editors class LocationMark : public TextEditor::BaseTextMark { - Q_OBJECT - public: LocationMark(const QString &fileName, int linenumber) : BaseTextMark(fileName, linenumber) {} - QIcon icon() const { return DebuggerManager::instance()->locationMarkIcon(); } + QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); } void updateLineNumber(int /*lineNumber*/) {} void updateBlock(const QTextBlock & /*block*/) {} void removedFromEditor() {} }; -} // namespace Internal -} // namespace Debugger - /////////////////////////////////////////////////////////////////////// // @@ -326,13 +384,8 @@ public: // /////////////////////////////////////////////////////////////////////// -namespace Debugger { -namespace Internal { - class CommonOptionsPage : public Core::IOptionsPage { - Q_OBJECT - public: CommonOptionsPage() {} @@ -419,10 +472,6 @@ bool CommonOptionsPage::matches(const QString &s) const return m_searchKeywords.contains(s, Qt::CaseInsensitive); } -} // namespace Internal -} // namespace Debugger - - /////////////////////////////////////////////////////////////////////// // // DebuggingHelperOptionPage @@ -436,13 +485,8 @@ static inline bool oxygenStyle() return false; } -namespace Debugger { -namespace Internal { - class DebuggingHelperOptionPage : public Core::IOptionsPage { - Q_OBJECT - public: DebuggingHelperOptionPage() {} @@ -523,64 +567,13 @@ bool DebuggingHelperOptionPage::matches(const QString &s) const return m_searchKeywords.contains(s, Qt::CaseInsensitive); } -} // namespace Internal -} // namespace Debugger - /////////////////////////////////////////////////////////////////////// // -// DebuggerPlugin +// Argument parsing // /////////////////////////////////////////////////////////////////////// - -DebuggerPlugin::AttachRemoteParameters::AttachRemoteParameters() : - attachPid(0), - winCrashEvent(0) -{ -} - -DebuggerPlugin::DebuggerPlugin() - : m_manager(0), - m_debugMode(0), - m_locationMark(0), - m_gdbRunningContext(0), - m_cmdLineEnabledEngines(AllEngineTypes) -{} - -DebuggerPlugin::~DebuggerPlugin() -{ - delete DebuggerSettings::instance(); - - removeObject(m_debugMode); - - delete m_debugMode; - m_debugMode = 0; - - delete m_locationMark; - m_locationMark = 0; - - removeObject(m_manager); - delete m_manager; - m_manager = 0; - - removeObject(m_uiSwitcher); - delete m_uiSwitcher; - m_uiSwitcher = 0; -} - -void DebuggerPlugin::aboutToShutdown() -{ - QTC_ASSERT(m_manager, /**/); - if (m_manager) - m_manager->aboutToShutdown(); - - writeSettings(); - - if (m_uiSwitcher) - m_uiSwitcher->aboutToShutdown(); -} - static QString msgParameterMissing(const QString &a) { return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a); @@ -591,11 +584,10 @@ static QString msgInvalidNumericParameter(const QString &a, const QString &numbe return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a); } -// Parse arguments static bool parseArgument(QStringList::const_iterator &it, - const QStringList::const_iterator &cend, - DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters, - unsigned *enabledEngines, QString *errorMessage) + const QStringList::const_iterator &cend, + AttachRemoteParameters *attachRemoteParameters, + unsigned *enabledEngines, QString *errorMessage) { const QString &option = *it; // '-debug <pid>' @@ -656,7 +648,7 @@ static bool parseArgument(QStringList::const_iterator &it, } static bool parseArguments(const QStringList &args, - DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters, + AttachRemoteParameters *attachRemoteParameters, unsigned *enabledEngines, QString *errorMessage) { const QStringList::const_iterator cend = args.constEnd(); @@ -671,119 +663,607 @@ static bool parseArguments(const QStringList &args, return true; } -void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &) + +/////////////////////////////////////////////////////////////////////// +// +// Misc +// +/////////////////////////////////////////////////////////////////////// + +static bool isDebuggable(Core::IEditor *editor) { - QString errorMessage; - AttachRemoteParameters parameters; - unsigned dummy = 0; - // Did we receive a request for debugging (unless it is ourselves)? - if (parseArguments(options, ¶meters, &dummy, &errorMessage) - && parameters.attachPid != quint64(QCoreApplication::applicationPid())) { - m_attachRemoteParameters = parameters; - attachCmdLine(); - } + // Only blacklist Qml. Whitelisting would fail on C++ code in files + // with strange names, more harm would be done this way. + //Core::IFile *file = editor->file(); + //return !(file && file->mimeType() == "application/x-qml"); + + // Nowadays, even Qml is debuggable. + Q_UNUSED(editor); + return true; } -bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage) +static TextEditor::ITextEditor *currentTextEditor() { - // Do not fail the whole plugin if something goes wrong here. - if (!parseArguments(arguments, &m_attachRemoteParameters, &m_cmdLineEnabledEngines, errorMessage)) { - *errorMessage = tr("Error evaluating command line arguments: %1") - .arg(*errorMessage); - qWarning("%s\n", qPrintable(*errorMessage)); - errorMessage->clear(); - } + EditorManager *editorManager = EditorManager::instance(); + if (!editorManager) + return 0; + Core::IEditor *editor = editorManager->currentEditor(); + return qobject_cast<ITextEditor*>(editor); +} - // Debug mode setup. - m_debugMode = new DebugMode(this); - m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this); - ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher); +static bool isCurrentProjectCppBased() +{ + Project *startupProject = ProjectExplorerPlugin::instance()->startupProject(); + if (!startupProject) + return false; + const QString id = startupProject->id(); + return id == _("GenericProjectManager.GenericProject") + || id == _("CMakeProjectManager.CMakeProject") + || id == _("Qt4ProjectManager.Qt4Project"); +} - ICore *core = ICore::instance(); - QTC_ASSERT(core, return false); - Core::ActionManager *am = core->actionManager(); - QTC_ASSERT(am, return false); +/////////////////////////////////////////////////////////////////////// +// +// DummyEngine +// +/////////////////////////////////////////////////////////////////////// - Core::UniqueIDManager *uidm = core->uniqueIDManager(); - QTC_ASSERT(uidm, return false); +class DummyEngine : public DebuggerEngine +{ +public: + DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {} +}; - QList<int> globalcontext; - globalcontext << CC::C_GLOBAL_ID; - QList<int> cppcontext; - cppcontext << uidm->uniqueIdentifier(PE::LANG_CXX); +/////////////////////////////////////////////////////////////////////// +// +// DebuggerPluginPrivate +// +/////////////////////////////////////////////////////////////////////// - QList<int> cppDebuggercontext; - cppDebuggercontext << uidm->uniqueIdentifier(C_CPPDEBUGGER); +struct DebuggerActions +{ + QAction *continueAction; + QAction *stopAction; + QAction *resetAction; // FIXME: Should not be needed in a stable release + QAction *stepAction; + QAction *stepOutAction; + QAction *runToLineAction1; // in the Debug menu + QAction *runToLineAction2; // in the text editor context menu + QAction *runToFunctionAction; + QAction *jumpToLineAction1; // in the Debug menu + QAction *jumpToLineAction2; // in the text editor context menu + QAction *returnFromFunctionAction; + QAction *nextAction; + QAction *snapshotAction; + QAction *watchAction1; // in the Debug menu + QAction *watchAction2; // in the text editor context menu + QAction *breakAction; + QAction *sepAction; + QAction *reverseDirectionAction; + QAction *frameUpAction; + QAction *frameDownAction; +}; - QList<int> cppeditorcontext; - cppeditorcontext << uidm->uniqueIdentifier(CppEditor::Constants::C_CPPEDITOR); +} // namespace Internal - QList<int> texteditorcontext; - texteditorcontext << uidm->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR); +using namespace Debugger::Internal; - m_gdbRunningContext = uidm->uniqueIdentifier(Constants::GDBRUNNING); +/////////////////////////////////////////////////////////////////////// +// +// DebuggerPluginPrivate +// +/////////////////////////////////////////////////////////////////////// - m_uiSwitcher->addLanguage(LANG_CPP, cppDebuggercontext); +class DebuggerPluginPrivate : public QObject +{ + Q_OBJECT - DebuggerManager *manager = new DebuggerManager(this); - ExtensionSystem::PluginManager::instance()->addObject(manager); - const QList<Core::IOptionsPage *> engineOptionPages = - manager->initializeEngines(m_cmdLineEnabledEngines); +public: + explicit DebuggerPluginPrivate(DebuggerPlugin *plugin); - // Register factory of DebuggerRunControl. - m_debuggerRunControlFactory = new DebuggerRunControlFactory(manager); - addAutoReleasedObject(m_debuggerRunControlFactory); + bool initialize(const QStringList &arguments, QString *errorMessage); + void notifyCurrentEngine(int role, const QVariant &value = QVariant()); + void connectEngine(DebuggerEngine *engine); + void disconnectEngine() { connectEngine(m_dummySessionEngine); } - QList<int> context; - context.append(uidm->uniqueIdentifier(CC::C_EDITORMANAGER)); - context.append(uidm->uniqueIdentifier(C_DEBUGMODE)); - context.append(uidm->uniqueIdentifier(CC::C_NAVIGATION_PANE)); - m_debugMode->setContext(context); +public slots: + void updateWatchersHeader(int section, int, int newSize) + { m_watchersWindow->header()->resizeSection(section, newSize); } - m_reverseToolButton = 0; + void reloadSourceFiles() + { notifyCurrentEngine(RequestReloadSourceFilesRole); } - // Handling of external applications. - m_startExternalAction = new QAction(this); - m_startExternalAction->setText(tr("Start and Debug External Application...")); - connect(m_startExternalAction, SIGNAL(triggered()), - this, SLOT(startExternalApplication())); + void sourceFilesDockToggled(bool on) + { if (on) reloadSourceFiles(); } - m_attachExternalAction = new QAction(this); - m_attachExternalAction->setText(tr("Attach to Running External Application...")); - connect(m_attachExternalAction, SIGNAL(triggered()), - this, SLOT(attachExternalApplication())); + void reloadModules() + { notifyCurrentEngine(RequestReloadModulesRole); } - m_attachCoreAction = new QAction(this); - m_attachCoreAction->setText(tr("Attach to Core...")); - connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore())); + void modulesDockToggled(bool on) + { if (on) reloadModules(); } - m_attachTcfAction = new QAction(this); - m_attachTcfAction->setText(tr("Attach to Running Tcf Agent...")); - m_attachTcfAction->setToolTip(tr("This attaches to a running " - "'Target Communication Framework' agent.")); - connect(m_attachTcfAction, SIGNAL(triggered()), - this, SLOT(attachRemoteTcf())); + void onAction(); + void onStatusTimeout(); - m_startRemoteAction = new QAction(this); - m_startRemoteAction->setText(tr("Start and Attach to Remote Application...")); - connect(m_startRemoteAction, SIGNAL(triggered()), - this, SLOT(startRemoteApplication())); + void setSimpleDockWidgetArrangement(const QString &activeLanguage); - m_detachAction = new QAction(this); - m_detachAction->setText(tr("Detach Debugger")); - connect(m_detachAction, SIGNAL(triggered()), - manager, SLOT(detachDebugger())); + void editorOpened(Core::IEditor *editor); + void editorAboutToClose(Core::IEditor *editor); + void setBusyCursor(bool busy); + void requestMark(TextEditor::ITextEditor *editor, int lineNumber); + void showToolTip(TextEditor::ITextEditor *editor, const QPoint &pnt, int pos); + void requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu); - Core::Command *cmd = 0; - const DebuggerManagerActions actions = manager->debuggerManagerActions(); + void activatePreviousMode(); + void activateDebugMode(); + void toggleBreakpoint(); + void toggleBreakpoint(const QString &fileName, int lineNumber); + void breakpointSetRemoveMarginActionTriggered(); + void breakpointEnableDisableMarginActionTriggered(); + void onModeChanged(Core::IMode *mode); + void showSettingsDialog(); - Core::ActionContainer *mstart = - am->actionContainer(PE::M_DEBUG_STARTDEBUGGING); + void startExternalApplication(); + void startRemoteApplication(); + void attachExternalApplication(); + void attachExternalApplication + (qint64 pid, const QString &binary, const QString &crashParameter); + void attachCore(); + void attachCore(const QString &core, const QString &exeFileName); + void attachCmdLine(); + void attachRemoteTcf(); - cmd = am->registerAction(actions.continueAction, - PE::DEBUG, QList<int>() << m_gdbRunningContext); + void loadSessionData(); + void saveSessionData(); + void interruptDebuggingRequest(); + void exitDebugger(); + + void enableReverseDebuggingTriggered(const QVariant &value); + void languageChanged(const QString &debuggerLanguage); + + DebuggerMainWindow *mainWindow() + { return qobject_cast<DebuggerMainWindow*> + (DebuggerUISwitcher::instance()->mainWindow()); } + + void setConfigValue(const QString &name, const QVariant &value) + { settings()->setValue(name, value); } + QVariant configValue(const QString &name) const + { return settings()->value(name); } + + ProjectExplorer::RunControl *createDebugger(const DebuggerStartParameters &sp); + void startDebugger(ProjectExplorer::RunControl *runControl); + + void setToolTipExpression(const QPoint &mousePos, + TextEditor::ITextEditor *editor, int cursorPos); + + void dumpLog(); + void cleanupViews(); + + void fontSettingsChanged(const TextEditor::FontSettings &settings); + DebuggerState state() const { return m_state; } + + void updateState(DebuggerEngine *engine); + + void resetLocation(); + void gotoLocation(const QString &file, int line, bool setMarker); + + void registerDockToggled(bool on); + void clearStatusMessage(); + void operateByInstructionTriggered(); + + void sessionLoaded(); + void aboutToUnloadSession(); + void aboutToSaveSession(); + +public: + DebuggerState m_state; + uint m_capabilities; + DebuggerUISwitcher *m_uiSwitcher; + DebuggerPlugin *m_manager; + DebugMode *m_debugMode; + DebuggerRunControlFactory *m_debuggerRunControlFactory; + + QString m_previousMode; + TextEditor::BaseTextMark *m_locationMark; + int m_gdbRunningContext; + AttachRemoteParameters m_attachRemoteParameters; + + QAction *m_startExternalAction; + QAction *m_startRemoteAction; + QAction *m_attachExternalAction; + QAction *m_attachCoreAction; + QAction *m_attachTcfAction; + QAction *m_detachAction; + QComboBox *m_langBox; + QToolButton *m_reverseToolButton; + + QIcon m_stopIcon; + QIcon m_interruptIcon; + QIcon m_locationMarkIcon; + + QLabel *m_statusLabel; + QComboBox *m_threadBox; + + QDockWidget *m_breakDock; + QDockWidget *m_modulesDock; + QDockWidget *m_outputDock; + QDockWidget *m_registerDock; + QDockWidget *m_snapshotDock; + QDockWidget *m_sourceFilesDock; + QDockWidget *m_stackDock; + QDockWidget *m_threadsDock; + QDockWidget *m_watchDock; + QList<QDockWidget *> m_dockWidgets; + + DebuggerActions m_actions; + + BreakWindow *m_breakWindow; + QTreeView *m_returnWindow; + QTreeView *m_localsWindow; + QTreeView *m_watchersWindow; + QTreeView *m_commandWindow; + QAbstractItemView *m_registerWindow; + QAbstractItemView *m_modulesWindow; + QAbstractItemView *m_snapshotWindow; + SourceFilesWindow *m_sourceFilesWindow; + QAbstractItemView *m_stackWindow; + QAbstractItemView *m_threadsWindow; + DebuggerOutputWindow *m_outputWindow; + + DebuggerEngine *m_dummySessionEngine; + + bool m_busy; + QTimer m_statusTimer; + QString m_lastPermanentStatusMessage; + + //SessionData m_sessionData; + + CPlusPlus::Snapshot m_codeModelSnapshot; + DebuggerPlugin *m_plugin; + + QList<QPointer<DebuggerRunControl> > m_allRunControls; +}; + +DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) +{ + m_plugin = plugin; + + m_statusLabel = 0; + m_threadBox = 0; + + m_breakDock = 0; + m_modulesDock = 0; + m_outputDock = 0; + m_registerDock = 0; + m_snapshotDock = 0; + m_sourceFilesDock = 0; + m_stackDock = 0; + m_threadsDock = 0; + m_watchDock = 0; + + m_breakWindow = 0; + m_returnWindow = 0; + m_localsWindow = 0; + m_watchersWindow = 0; + m_registerWindow = 0; + m_modulesWindow = 0; + m_snapshotWindow = 0; + m_sourceFilesWindow = 0; + m_stackWindow = 0; + m_threadsWindow = 0; + m_outputWindow = 0; + + m_dummySessionEngine = 0; + m_debugMode = 0; + m_locationMark = 0; + m_gdbRunningContext = 0; + + m_debugMode = 0; + m_uiSwitcher = 0; +} + +bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *errorMessage) +{ + // FIXME: Move part of this to extensionsInitialized()? + ICore *core = ICore::instance(); + QTC_ASSERT(core, return false); + + Core::UniqueIDManager *uidm = core->uniqueIDManager(); + QTC_ASSERT(uidm, return false); + + Core::ActionManager *am = core->actionManager(); + QTC_ASSERT(am, return false); + + const QList<int> globalcontext = QList<int>() + << CC::C_GLOBAL_ID; + + const QList<int> cppcontext = QList<int>() + << uidm->uniqueIdentifier(PE::LANG_CXX); + + const QList<int> cppDebuggercontext = QList<int>() + << uidm->uniqueIdentifier(C_CPPDEBUGGER); + + const QList<int> cppeditorcontext = QList<int>() + << uidm->uniqueIdentifier(CppEditor::Constants::C_CPPEDITOR); + + const QList<int> texteditorcontext = QList<int>() + << uidm->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR); + + m_stopIcon = QIcon(_(":/debugger/images/debugger_stop_small.png")); + m_stopIcon.addFile(":/debugger/images/debugger_stop.png"); + m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png")); + m_interruptIcon.addFile(":/debugger/images/debugger_interrupt.png"); + m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png")); + + m_busy = false; + + m_statusLabel = new QLabel; + m_statusLabel->setMinimumSize(QSize(30, 10)); + + m_breakWindow = new BreakWindow; + m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints")); + m_modulesWindow = new ModulesWindow; + m_modulesWindow->setObjectName(QLatin1String("CppDebugModules")); + m_outputWindow = new DebuggerOutputWindow; + m_outputWindow->setObjectName(QLatin1String("CppDebugOutput")); + + m_registerWindow = new RegisterWindow; + m_registerWindow->setObjectName(QLatin1String("CppDebugRegisters")); + m_snapshotWindow = new SnapshotWindow; + m_snapshotWindow->setObjectName(QLatin1String("CppDebugSnapshots")); + m_stackWindow = new StackWindow; + m_stackWindow->setObjectName(QLatin1String("CppDebugStack")); + m_sourceFilesWindow = new SourceFilesWindow; + m_sourceFilesWindow->setObjectName(QLatin1String("CppDebugSources")); + m_threadsWindow = new ThreadsWindow; + m_threadsWindow->setObjectName(QLatin1String("CppDebugThreads")); + m_returnWindow = new WatchWindow(WatchWindow::ReturnType); + m_returnWindow->setObjectName(QLatin1String("CppDebugReturn")); + m_localsWindow = new WatchWindow(WatchWindow::LocalsType); + m_localsWindow->setObjectName(QLatin1String("CppDebugLocals")); + m_watchersWindow = new WatchWindow(WatchWindow::WatchersType); + m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers")); + m_commandWindow = new QTreeView; + + // Session related data + m_dummySessionEngine = new DummyEngine; + + // Debug mode setup + m_debugMode = new DebugMode(this); + + // Watchers + connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)), + this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection); + + // Tooltip + qRegisterMetaType<WatchData>("WatchData"); + qRegisterMetaType<StackCookie>("StackCookie"); + + m_actions.continueAction = new QAction(tr("Continue"), this); + QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png"); + continueIcon.addFile(":/debugger/images/debugger_continue.png"); + m_actions.continueAction->setIcon(continueIcon); + m_actions.continueAction->setData(RequestExecContinueRole); + + m_actions.stopAction = new QAction(tr("Interrupt"), this); + m_actions.stopAction->setIcon(m_interruptIcon); + m_actions.stopAction->setData(RequestExecInterruptRole); + + m_actions.resetAction = new QAction(tr("Abort Debugging"), this); + m_actions.resetAction->setData(RequestExecResetRole); + m_actions.resetAction->setToolTip(tr("Aborts debugging and " + "resets the debugger to the initial state.")); + + m_actions.nextAction = new QAction(tr("Step Over"), this); + m_actions.nextAction->setData(RequestExecNextRole); + m_actions.nextAction->setIcon( + QIcon(":/debugger/images/debugger_stepover_small.png")); + + m_actions.stepAction = new QAction(tr("Step Into"), this); + m_actions.stepAction->setData(RequestExecStepRole); + m_actions.stepAction->setIcon( + QIcon(":/debugger/images/debugger_stepinto_small.png")); + + m_actions.stepOutAction = new QAction(tr("Step Out"), this); + m_actions.stepOutAction->setData(RequestExecStepOutRole); + m_actions.stepOutAction->setIcon( + QIcon(":/debugger/images/debugger_stepout_small.png")); + + m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this); + m_actions.runToLineAction1->setData(RequestExecRunToLineRole); + m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this); + m_actions.runToLineAction2->setData(RequestExecRunToLineRole); + + m_actions.runToFunctionAction = + new QAction(tr("Run to Outermost Function"), this); + m_actions.runToFunctionAction->setData(RequestExecRunToFunctionRole); + + m_actions.returnFromFunctionAction = + new QAction(tr("Immediately Return From Inner Function"), this); + m_actions.returnFromFunctionAction->setData(RequestExecReturnFromFunctionRole); + + m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this); + m_actions.jumpToLineAction1->setData(RequestExecJumpToLineRole); + m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this); + m_actions.jumpToLineAction1->setData(RequestExecJumpToLineRole); + + m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this); + + m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this); + m_actions.watchAction1->setData(RequestExecWatchRole); + m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this); + m_actions.watchAction2->setData(RequestExecWatchRole); + + m_actions.snapshotAction = new QAction(tr("Snapshot"), this); + m_actions.snapshotAction->setData(RequestExecSnapshotRole); + m_actions.snapshotAction->setIcon( + QIcon(":/debugger/images/debugger_snapshot_small.png")); + + m_actions.reverseDirectionAction = + new QAction(tr("Reverse Direction"), this); + m_actions.reverseDirectionAction->setCheckable(true); + m_actions.reverseDirectionAction->setChecked(false); + m_actions.reverseDirectionAction->setIcon( + QIcon(":/debugger/images/debugger_reversemode_16.png")); + m_actions.reverseDirectionAction->setIconVisibleInMenu(false); + + m_actions.frameDownAction = + new QAction(tr("Move to Called Frame"), this); + m_actions.frameDownAction->setData(RequestExecFrameDownRole); + m_actions.frameUpAction = + new QAction(tr("Move to Calling Frame"), this); + m_actions.frameUpAction->setData(RequestExecFrameUpRole); + + m_actions.reverseDirectionAction->setCheckable(false); + connect(m_actions.continueAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.nextAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.stepAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.stepOutAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.runToLineAction1, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.runToLineAction2, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.runToFunctionAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.jumpToLineAction1, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.jumpToLineAction2, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.returnFromFunctionAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.watchAction1, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.watchAction2, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.snapshotAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.frameDownAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.frameUpAction, SIGNAL(triggered()), SLOT(onAction())); + connect(m_actions.stopAction, SIGNAL(triggered()), SLOT(interruptDebuggingRequest())); + connect(m_actions.resetAction, SIGNAL(triggered()), SLOT(onAction())); + connect(&m_statusTimer, SIGNAL(timeout()), SLOT(clearStatusMessage())); + +/* + connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()), +SLOT(onAction())); + this, SLOT(executeDebuggerCommand())); + + connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()), +SLOT(onAction())); + this, SLOT(watchPoint())); + + connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()), + this, SLOT(operateByInstructionTriggered())); +*/ + + m_plugin->readSettings(); + + // Cpp/Qml ui setup + m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this); + ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher); + theDebuggerAction(SwitchLanguageAutomatically)->setChecked(true); + m_uiSwitcher->addLanguage(LANG_CPP, cppDebuggercontext); + m_uiSwitcher->setActiveLanguage(LANG_CPP); + + + // Dock widgets + m_breakDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_breakWindow); + m_modulesDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_modulesWindow, + Qt::TopDockWidgetArea, false); + + connect(m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)), + this, SLOT(reloadModules()), Qt::QueuedConnection); + + m_registerDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_registerWindow, + Qt::TopDockWidgetArea, false); + connect(m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)), + m_registerWindow, SLOT(reloadRegisters()), Qt::QueuedConnection); + + m_outputDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_outputWindow, + Qt::TopDockWidgetArea, false); + + m_snapshotDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_snapshotWindow); + m_stackDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_stackWindow); + m_sourceFilesDock = m_uiSwitcher->createDockWidget(LANG_CPP, + m_sourceFilesWindow, Qt::TopDockWidgetArea, false); + connect(m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)), + this, SLOT(reloadSourceFiles()), Qt::QueuedConnection); + + m_threadsDock = m_uiSwitcher->createDockWidget(LANG_CPP, m_threadsWindow); + + QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical); + localsAndWatchers->setObjectName(QLatin1String("CppDebugLocalsAndWatchers")); + localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle()); + localsAndWatchers->addWidget(m_localsWindow); + localsAndWatchers->addWidget(m_returnWindow); + localsAndWatchers->addWidget(m_watchersWindow); + //localsAndWatchers->addWidget(m_tooltipWindow); + localsAndWatchers->setStretchFactor(0, 3); + localsAndWatchers->setStretchFactor(1, 1); + localsAndWatchers->setStretchFactor(2, 1); + + m_watchDock = m_uiSwitcher->createDockWidget(LANG_CPP, localsAndWatchers); + m_dockWidgets << m_breakDock << m_modulesDock << m_registerDock + << m_outputDock << m_stackDock << m_sourceFilesDock + << m_threadsDock << m_watchDock; + + // Do not fail the whole plugin if something goes wrong here. + uint cmdLineEnabledEngines = AllEngineTypes; + if (!parseArguments(arguments, &m_attachRemoteParameters, &cmdLineEnabledEngines, errorMessage)) { + *errorMessage = tr("Error evaluating command line arguments: %1") + .arg(*errorMessage); + qWarning("%s\n", qPrintable(*errorMessage)); + errorMessage->clear(); + } + + m_gdbRunningContext = uidm->uniqueIdentifier(Constants::GDBRUNNING); + + // Register factory of DebuggerRunControl. + m_debuggerRunControlFactory = new DebuggerRunControlFactory + (m_plugin, DebuggerEngineType(cmdLineEnabledEngines)); + m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory); + + QList<int> context; + context.append(uidm->uniqueIdentifier(CC::C_EDITORMANAGER)); + context.append(uidm->uniqueIdentifier(C_DEBUGMODE)); + context.append(uidm->uniqueIdentifier(CC::C_NAVIGATION_PANE)); + m_debugMode->setContext(context); + + m_reverseToolButton = 0; + + // Handling of external applications. + m_startExternalAction = new QAction(this); + m_startExternalAction->setText(tr("Start and Debug External Application...")); + connect(m_startExternalAction, SIGNAL(triggered()), + this, SLOT(startExternalApplication())); + + m_attachExternalAction = new QAction(this); + m_attachExternalAction->setText(tr("Attach to Running External Application...")); + connect(m_attachExternalAction, SIGNAL(triggered()), + this, SLOT(attachExternalApplication())); + + m_attachCoreAction = new QAction(this); + m_attachCoreAction->setText(tr("Attach to Core...")); + connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore())); + + m_attachTcfAction = new QAction(this); + m_attachTcfAction->setText(tr("Attach to Running Tcf Agent...")); + m_attachTcfAction->setToolTip(tr("This attaches to a running " + "'Target Communication Framework' agent.")); + connect(m_attachTcfAction, SIGNAL(triggered()), + this, SLOT(attachRemoteTcf())); + + m_startRemoteAction = new QAction(this); + m_startRemoteAction->setText(tr("Start and Attach to Remote Application...")); + connect(m_startRemoteAction, SIGNAL(triggered()), + this, SLOT(startRemoteApplication())); + + m_detachAction = new QAction(this); + m_detachAction->setText(tr("Detach Debugger")); + m_detachAction->setData(RequestExecDetachRole); + connect(m_detachAction, SIGNAL(triggered()), SLOT(onAction())); + + Core::Command *cmd = 0; + + Core::ActionContainer *mstart = + am->actionContainer(PE::M_DEBUG_STARTDEBUGGING); + + cmd = am->registerAction(m_actions.continueAction, + PE::DEBUG, QList<int>() << m_gdbRunningContext); mstart->addAction(cmd, CC::G_DEFAULT_ONE); cmd = am->registerAction(m_startExternalAction, @@ -816,7 +1296,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, CC::G_DEFAULT_ONE); - cmd = am->registerAction(actions.stopAction, + cmd = am->registerAction(m_actions.stopAction, Constants::INTERRUPT, globalcontext); cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateIcon); @@ -824,7 +1304,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess cmd->setDefaultText(tr("Stop Debugger/Interrupt Debugger")); m_uiSwitcher->addMenuAction(cmd, CC::G_DEFAULT_ONE); - cmd = am->registerAction(actions.resetAction, + cmd = am->registerAction(m_actions.resetAction, Constants::RESET, globalcontext); cmd->setAttribute(Core::Command::CA_UpdateText); //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY)); @@ -836,53 +1316,53 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess cmd = am->registerAction(sep, _("Debugger.Sep.Step"), globalcontext); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.nextAction, + cmd = am->registerAction(m_actions.nextAction, Constants::NEXT, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.stepAction, + cmd = am->registerAction(m_actions.stepAction, Constants::STEP, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.stepOutAction, + cmd = am->registerAction(m_actions.stepOutAction, Constants::STEPOUT, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.runToLineAction1, + cmd = am->registerAction(m_actions.runToLineAction1, Constants::RUN_TO_LINE1, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.runToFunctionAction, + cmd = am->registerAction(m_actions.runToFunctionAction, Constants::RUN_TO_FUNCTION, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.jumpToLineAction1, + cmd = am->registerAction(m_actions.jumpToLineAction1, Constants::JUMP_TO_LINE1, cppDebuggercontext); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.returnFromFunctionAction, + cmd = am->registerAction(m_actions.returnFromFunctionAction, Constants::RETURN_FROM_FUNCTION, cppDebuggercontext); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.reverseDirectionAction, + cmd = am->registerAction(m_actions.reverseDirectionAction, Constants::REVERSE, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY)); cmd->setAttribute(Command::CA_Hide); @@ -895,15 +1375,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.snapshotAction, + cmd = am->registerAction(m_actions.snapshotAction, Constants::SNAPSHOT, cppDebuggercontext); cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY)); cmd->setAttribute(Command::CA_Hide); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.frameDownAction, + cmd = am->registerAction(m_actions.frameDownAction, Constants::FRAME_DOWN, cppDebuggercontext); - cmd = am->registerAction(actions.frameUpAction, + cmd = am->registerAction(m_actions.frameUpAction, Constants::FRAME_UP, cppDebuggercontext); @@ -913,11 +1393,11 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.breakAction, + cmd = am->registerAction(m_actions.breakAction, Constants::TOGGLE_BREAK, cppeditorcontext); cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY)); m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - connect(actions.breakAction, SIGNAL(triggered()), + connect(m_actions.breakAction, SIGNAL(triggered()), this, SLOT(toggleBreakpoint())); //mcppcontext->addAction(cmd); @@ -928,7 +1408,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP); - cmd = am->registerAction(actions.watchAction1, + cmd = am->registerAction(m_actions.watchAction1, Constants::ADD_TO_WATCH1, cppeditorcontext); cmd->action()->setEnabled(true); //cmd->setDefaultKeySequence(QKeySequence(tr("ALT+D,ALT+W"))); @@ -943,41 +1423,49 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess editorContextMenu->addAction(cmd); cmd->setAttribute(Command::CA_Hide); - cmd = am->registerAction(actions.watchAction2, + cmd = am->registerAction(m_actions.watchAction2, Constants::ADD_TO_WATCH2, cppDebuggercontext); cmd->action()->setEnabled(true); editorContextMenu->addAction(cmd); cmd->setAttribute(Command::CA_Hide); - cmd = am->registerAction(actions.runToLineAction2, + cmd = am->registerAction(m_actions.runToLineAction2, Constants::RUN_TO_LINE2, cppDebuggercontext); cmd->action()->setEnabled(true); editorContextMenu->addAction(cmd); cmd->setAttribute(Command::CA_Hide); - cmd = am->registerAction(actions.jumpToLineAction2, + cmd = am->registerAction(m_actions.jumpToLineAction2, Constants::JUMP_TO_LINE2, cppDebuggercontext); cmd->action()->setEnabled(true); editorContextMenu->addAction(cmd); cmd->setAttribute(Command::CA_Hide); - addAutoReleasedObject(new CommonOptionsPage); + m_plugin->addAutoReleasedObject(new CommonOptionsPage); + QList<Core::IOptionsPage *> engineOptionPages; + if (cmdLineEnabledEngines & GdbEngineType) + addGdbOptionPages(&engineOptionPages); +#ifdef CDB_ENABLED + if (cmdLineEnabledEngines & CdbEngineType) + addCdbOptionPages(&engineOptionPages); +#endif + //if (cmdLineEnabledEngines & ScriptEngineType) + // addScriptOptionPages(&engineOptionPages); + //if (cmdLineEnabledEngines & TcfEngineType) + // addTcfOptionPages(&engineOptionPages); foreach (Core::IOptionsPage *op, engineOptionPages) - addAutoReleasedObject(op); - addAutoReleasedObject(new DebuggingHelperOptionPage); + m_plugin->addAutoReleasedObject(op); + m_plugin->addAutoReleasedObject(new DebuggingHelperOptionPage); - addAutoReleasedObject(new DebuggerListener); + m_plugin->addAutoReleasedObject(new DebuggerListener); m_locationMark = 0; - manager->setSimpleDockWidgetArrangement(LANG_CPP); - readSettings(); + //setSimpleDockWidgetArrangement(LANG_CPP); connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), this, SLOT(onModeChanged(Core::IMode*))); m_debugMode->widget()->setFocusProxy(EditorManager::instance()); - addObject(m_debugMode); - - m_manager = manager; + m_plugin->addObject(m_debugMode); // @@ -987,15 +1475,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess // TextEditor connect(TextEditorSettings::instance(), SIGNAL(fontSettingsChanged(TextEditor::FontSettings)), - manager, SLOT(fontSettingsChanged(TextEditor::FontSettings))); + this, SLOT(fontSettingsChanged(TextEditor::FontSettings))); // ProjectExplorer connect(sessionManager(), SIGNAL(sessionLoaded()), - manager, SLOT(sessionLoaded())); + this, SLOT(sessionLoaded())); connect(sessionManager(), SIGNAL(aboutToSaveSession()), - manager, SLOT(aboutToSaveSession())); + this, SLOT(aboutToSaveSession())); connect(sessionManager(), SIGNAL(aboutToUnloadSession()), - manager, SLOT(aboutToUnloadSession())); + this, SLOT(aboutToUnloadSession())); // EditorManager QObject *editorManager = core->editorManager(); @@ -1008,8 +1496,6 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()), this, SLOT(showSettingsDialog())); - handleStateChanged(DebuggerNotReady); - // Toolbar QWidget *toolbarContainer = new QWidget; @@ -1031,154 +1517,291 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess hbox->addWidget(new Utils::StyledSeparator); hbox->addWidget(new QLabel(tr("Threads:"))); - QComboBox *threadBox = new QComboBox; - threadBox->setModel(m_manager->threadsModel()); - connect(threadBox, SIGNAL(activated(int)), - m_manager->threadsWindow(), SIGNAL(threadSelected(int))); + m_threadBox = new QComboBox; + connect(m_threadBox, SIGNAL(activated(int)), + m_threadsWindow, SLOT(selectThread(int))); - hbox->addWidget(threadBox); + hbox->addWidget(m_threadBox); hbox->addSpacerItem(new QSpacerItem(4, 0)); - hbox->addWidget(m_manager->statusLabel(), 10); - + hbox->addWidget(m_statusLabel, 10); m_uiSwitcher->setToolbar(LANG_CPP, toolbarContainer); - connect(m_uiSwitcher, SIGNAL(dockArranged(QString)), manager, - SLOT(setSimpleDockWidgetArrangement(QString))); + connect(m_uiSwitcher, SIGNAL(dockArranged(QString)), + this, SLOT(setSimpleDockWidgetArrangement(QString))); connect(theDebuggerAction(EnableReverseDebugging), SIGNAL(valueChanged(QVariant)), this, SLOT(enableReverseDebuggingTriggered(QVariant))); // UI Switcher - connect(DebuggerUISwitcher::instance(), SIGNAL(languageChanged(QString)), - this, SLOT(languageChanged(QString))); + connect(m_uiSwitcher, SIGNAL(languageChanged(QString)), + this, SLOT(languageChanged(QString))); + m_uiSwitcher->initialize(); + m_watchersWindow->setVisible(false); + m_returnWindow->setVisible(false); + disconnectEngine(); return true; } -void DebuggerPlugin::extensionsInitialized() +void DebuggerPluginPrivate::onAction() { - // time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin - const QByteArray env = qgetenv("QTC_DEBUGGER_TEST"); - //qDebug() << "EXTENSIONS INITIALIZED:" << env; - // if (!env.isEmpty()) - // m_manager->runTest(QString::fromLocal8Bit(env)); - if (m_attachRemoteParameters.attachPid || !m_attachRemoteParameters.attachCore.isEmpty()) - QTimer::singleShot(0, this, SLOT(attachCmdLine())); - - readSettings(); - m_uiSwitcher->initialize(); + QAction *act = qobject_cast<QAction *>(sender()); + QTC_ASSERT(act, return); + const int role = act->data().toInt(); + notifyCurrentEngine(role); } -void DebuggerPlugin::attachCmdLine() +void DebuggerPluginPrivate::languageChanged(const QString &language) { - if (m_manager->state() != DebuggerNotReady) - return; - if (m_attachRemoteParameters.attachPid) { - m_manager->showStatusMessage(tr("Attaching to PID %1.").arg(m_attachRemoteParameters.attachPid)); - const QString crashParameter = - m_attachRemoteParameters.winCrashEvent ? QString::number(m_attachRemoteParameters.winCrashEvent) : QString(); - attachExternalApplication(m_attachRemoteParameters.attachPid, QString(), crashParameter); - return; - } - if (!m_attachRemoteParameters.attachCore.isEmpty()) { - m_manager->showStatusMessage(tr("Attaching to core %1.").arg(m_attachRemoteParameters.attachCore)); - attachCore(m_attachRemoteParameters.attachCore, QString()); - } + const bool debuggerIsCPP = (language == Constants::LANG_CPP); + //qDebug() << "DEBUGGER IS CPP: " << debuggerIsCPP; + + m_startExternalAction->setVisible(debuggerIsCPP); + m_attachExternalAction->setVisible(debuggerIsCPP); + m_attachCoreAction->setVisible(debuggerIsCPP); + m_startRemoteAction->setVisible(debuggerIsCPP); + m_detachAction->setVisible(debuggerIsCPP); } -/*! Activates the previous mode when the current mode is the debug mode. */ -void DebuggerPlugin::activatePreviousMode() +void DebuggerPluginPrivate::startExternalApplication() { - Core::ModeManager *const modeManager = ICore::instance()->modeManager(); + DebuggerStartParameters sp; + StartExternalDialog dlg(mainWindow()); + dlg.setExecutableFile( + configValue(_("LastExternalExecutableFile")).toString()); + dlg.setExecutableArguments( + configValue(_("LastExternalExecutableArguments")).toString()); + dlg.setWorkingDirectory( + configValue(_("LastExternalWorkingDirectory")).toString()); + if (dlg.exec() != QDialog::Accepted) + return; - if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG) - && !m_previousMode.isEmpty()) { - modeManager->activateMode(m_previousMode); - m_previousMode.clear(); - } + setConfigValue(_("LastExternalExecutableFile"), + dlg.executableFile()); + setConfigValue(_("LastExternalExecutableArguments"), + dlg.executableArguments()); + setConfigValue(_("LastExternalWorkingDirectory"), + dlg.workingDirectory()); + sp.executable = dlg.executableFile(); + sp.startMode = StartExternal; + sp.workingDirectory = dlg.workingDirectory(); + sp.breakAtMain = dlg.breakAtMain(); + if (!dlg.executableArguments().isEmpty()) + sp.processArgs = dlg.executableArguments().split(QLatin1Char(' ')); + + startDebugger(m_debuggerRunControlFactory->create(sp)); } -void DebuggerPlugin::activateDebugMode() +void DebuggerPluginPrivate::notifyCurrentEngine(int role, const QVariant &value) { - ModeManager *modeManager = ModeManager::instance(); - m_previousMode = modeManager->currentMode()->id(); - modeManager->activateMode(_(MODE_DEBUG)); + QTC_ASSERT(m_commandWindow && m_commandWindow->model(), return); + m_commandWindow->model()->setData(QModelIndex(), value, role); } -static bool isDebuggable(Core::IEditor *editor) +void DebuggerPluginPrivate::attachExternalApplication() { - // Only blacklist QML. Whitelisting would fail on C++ code in files - // with strange names, more harm would be done this way. - Core::IFile *file = editor->file(); - return !(file && file->mimeType() == "application/x-qml"); + AttachExternalDialog dlg(mainWindow()); + if (dlg.exec() == QDialog::Accepted) + attachExternalApplication(dlg.attachPID(), dlg.executable(), QString()); } -TextEditor::ITextEditor *DebuggerPlugin::currentTextEditor() +void DebuggerPluginPrivate::attachExternalApplication + (qint64 pid, const QString &binary, const QString &crashParameter) { - EditorManager *editorManager = EditorManager::instance(); - if (!editorManager) - return 0; - Core::IEditor *editor = editorManager->currentEditor(); - return qobject_cast<ITextEditor*>(editor); + if (pid == 0) { + QMessageBox::warning(mainWindow(), tr("Warning"), + tr("Cannot attach to PID 0")); + return; + } + DebuggerStartParameters sp; + sp.attachPID = pid; + sp.executable = binary; + sp.crashParameter = crashParameter; + sp.startMode = crashParameter.isEmpty() ? AttachExternal:AttachCrashedExternal; + startDebugger(m_debuggerRunControlFactory->create(sp)); } -void DebuggerPlugin::editorOpened(Core::IEditor *editor) +void DebuggerPluginPrivate::attachCore() { - if (!isDebuggable(editor)) - return; - ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor); - if (!textEditor) + AttachCoreDialog dlg(mainWindow()); + dlg.setExecutableFile( + configValue(_("LastExternalExecutableFile")).toString()); + dlg.setCoreFile( + configValue(_("LastExternalCoreFile")).toString()); + if (dlg.exec() != QDialog::Accepted) return; - connect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)), - this, SLOT(requestMark(TextEditor::ITextEditor*,int))); - connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), - this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); - connect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), - this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); + setConfigValue(_("LastExternalExecutableFile"), + dlg.executableFile()); + setConfigValue(_("LastExternalCoreFile"), + dlg.coreFile()); + attachCore(dlg.coreFile(), dlg.executableFile()); } -void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor) +void DebuggerPluginPrivate::attachCore(const QString &core, const QString &exe) { - if (!isDebuggable(editor)) - return; - ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor); - if (!textEditor) - return; - disconnect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)), - this, SLOT(requestMark(TextEditor::ITextEditor*,int))); - disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), - this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); - disconnect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), - this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); + DebuggerStartParameters sp; + sp.executable = exe; + sp.coreFile = core; + sp.displayName = tr("Core file: \"%1\"").arg(core); + sp.startMode = AttachCore; + startDebugger(createDebugger(sp)); } -void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor, - int lineNumber, QMenu *menu) +void DebuggerPluginPrivate::startRemoteApplication() { - if (!isDebuggable(editor)) + DebuggerStartParameters sp; + StartRemoteDialog dlg(mainWindow()); + QStringList arches; + arches.append(_("i386:x86-64:intel")); + arches.append(_("i386")); + QString lastUsed = configValue(_("LastRemoteArchitecture")).toString(); + if (!arches.contains(lastUsed)) + arches.prepend(lastUsed); + dlg.setRemoteArchitectures(arches); + dlg.setRemoteChannel( + configValue(_("LastRemoteChannel")).toString()); + dlg.setLocalExecutable( + configValue(_("LastLocalExecutable")).toString()); + dlg.setDebugger(configValue(_("LastDebugger")).toString()); + dlg.setRemoteArchitecture(lastUsed); + dlg.setServerStartScript( + configValue(_("LastServerStartScript")).toString()); + dlg.setUseServerStartScript( + configValue(_("LastUseServerStartScript")).toBool()); + dlg.setSysRoot(configValue(_("LastSysroot")).toString()); + if (dlg.exec() != QDialog::Accepted) return; + setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel()); + setConfigValue(_("LastLocalExecutable"), dlg.localExecutable()); + setConfigValue(_("LastDebugger"), dlg.debugger()); + setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture()); + setConfigValue(_("LastServerStartScript"), dlg.serverStartScript()); + setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript()); + setConfigValue(_("LastSysroot"), dlg.sysRoot()); + sp.remoteChannel = dlg.remoteChannel(); + sp.remoteArchitecture = dlg.remoteArchitecture(); + sp.executable = dlg.localExecutable(); + sp.displayName = dlg.localExecutable(); + sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection. + if (!sp.debuggerCommand.isEmpty()) + sp.toolChainType = ProjectExplorer::ToolChain::INVALID; + sp.startMode = AttachToRemote; + if (dlg.useServerStartScript()) + sp.serverStartScript = dlg.serverStartScript(); + sp.sysRoot = dlg.sysRoot(); + startDebugger(createDebugger(sp)); +} - BreakHandler *handler = m_manager->breakHandler(); - QTC_ASSERT(handler, return); +void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value) +{ + QTC_ASSERT(m_reverseToolButton, return); + m_reverseToolButton->setVisible(value.toBool()); + m_actions.reverseDirectionAction->setChecked(false); + m_actions.reverseDirectionAction->setEnabled(value.toBool()); +} - BreakpointData *data = 0; - QString position; - if (editor->property("DisassemblerView").toBool()) { - QString fileName = editor->file()->fileName(); +void DebuggerPluginPrivate::attachRemoteTcf() +{ + DebuggerStartParameters sp; + AttachTcfDialog dlg(mainWindow()); + QStringList arches; + arches.append(_("i386:x86-64:intel")); + dlg.setRemoteArchitectures(arches); + dlg.setRemoteChannel( + configValue(_("LastTcfRemoteChannel")).toString()); + dlg.setRemoteArchitecture( + configValue(_("LastTcfRemoteArchitecture")).toString()); + dlg.setServerStartScript( + configValue(_("LastTcfServerStartScript")).toString()); + dlg.setUseServerStartScript( + configValue(_("LastTcfUseServerStartScript")).toBool()); + if (dlg.exec() != QDialog::Accepted) + return; + setConfigValue(_("LastTcfRemoteChannel"), dlg.remoteChannel()); + setConfigValue(_("LastTcfRemoteArchitecture"), dlg.remoteArchitecture()); + setConfigValue(_("LastTcfServerStartScript"), dlg.serverStartScript()); + setConfigValue(_("LastTcfUseServerStartScript"), dlg.useServerStartScript()); + sp.remoteChannel = dlg.remoteChannel(); + sp.remoteArchitecture = dlg.remoteArchitecture(); + sp.serverStartScript = dlg.serverStartScript(); + sp.startMode = AttachTcf; + if (dlg.useServerStartScript()) + sp.serverStartScript = dlg.serverStartScript(); + startDebugger(createDebugger(sp)); +} + +void DebuggerPluginPrivate::attachCmdLine() +{ + if (m_attachRemoteParameters.attachPid) { + m_plugin->showStatusMessage(tr("Attaching to PID %1.") + .arg(m_attachRemoteParameters.attachPid)); + const QString crashParameter = m_attachRemoteParameters.winCrashEvent + ? QString::number(m_attachRemoteParameters.winCrashEvent) : QString(); + attachExternalApplication(m_attachRemoteParameters.attachPid, + QString(), crashParameter); + return; + } + if (!m_attachRemoteParameters.attachCore.isEmpty()) { + m_plugin->showStatusMessage(tr("Attaching to core %1.") + .arg(m_attachRemoteParameters.attachCore)); + attachCore(m_attachRemoteParameters.attachCore, QString()); + } +} + +void DebuggerPluginPrivate::editorOpened(Core::IEditor *editor) +{ + if (!isDebuggable(editor)) + return; + ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor); + if (!textEditor) + return; + connect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)), + this, SLOT(requestMark(TextEditor::ITextEditor*,int))); + connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), + this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); + connect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); +} + +void DebuggerPluginPrivate::editorAboutToClose(Core::IEditor *editor) +{ + if (!isDebuggable(editor)) + return; + ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor); + if (!textEditor) + return; + disconnect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)), + this, SLOT(requestMark(TextEditor::ITextEditor*,int))); + disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), + this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); + disconnect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); +} + +void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu) +{ + if (!isDebuggable(editor)) + return; + + BreakpointData *data = 0; + QString position; + if (editor->property("DisassemblerView").toBool()) { + QString fileName = editor->file()->fileName(); QString line = editor->contents() .section('\n', lineNumber - 1, lineNumber - 1); position = _("*") + fileName; BreakpointData needle; needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1(); needle.bpLineNumber = "-1"; - data = handler->findSimilarBreakpoint(needle); + data = m_breakWindow->findSimilarBreakpoint(&needle); } else { QString fileName = editor->file()->fileName(); position = fileName + QString(":%1").arg(lineNumber); BreakpointData needle; needle.bpFileName = fileName; needle.bpLineNumber = QByteArray::number(lineNumber); - data = handler->findSimilarBreakpoint(needle); + data = m_breakWindow->findSimilarBreakpoint(&needle); } if (data) { @@ -1208,7 +1831,7 @@ void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor, } } -void DebuggerPlugin::toggleBreakpoint() +void DebuggerPluginPrivate::toggleBreakpoint() { ITextEditor *textEditor = currentTextEditor(); QTC_ASSERT(textEditor, return); @@ -1217,16 +1840,14 @@ void DebuggerPlugin::toggleBreakpoint() toggleBreakpoint(textEditor->file()->fileName(), lineNumber); } -void DebuggerPlugin::toggleBreakpoint(const QString &fileName, int lineNumber) +void DebuggerPluginPrivate::toggleBreakpoint(const QString &fileName, int lineNumber) { - BreakHandler *handler = m_manager->breakHandler(); - QTC_ASSERT(handler, return); BreakpointData needle; needle.bpFileName = fileName; needle.bpLineNumber.setNum(lineNumber); - BreakpointData *data = handler->findSimilarBreakpoint(needle); + BreakpointData *data = m_breakWindow->findSimilarBreakpoint(&needle); if (data) { - handler->removeBreakpoint(data); + m_breakWindow->removeBreakpoint(data); } else { data = new BreakpointData; data->fileName = fileName; @@ -1234,142 +1855,240 @@ void DebuggerPlugin::toggleBreakpoint(const QString &fileName, int lineNumber) data->pending = true; data->setMarkerFileName(fileName); data->setMarkerLineNumber(lineNumber); - handler->appendBreakpoint(data); + m_breakWindow->appendBreakpoint(data); } - m_manager->attemptBreakpointSynchronization(); } -void DebuggerPlugin::breakpointSetRemoveMarginActionTriggered() +void DebuggerPluginPrivate::breakpointSetRemoveMarginActionTriggered() { QAction *act = qobject_cast<QAction *>(sender()); QTC_ASSERT(act, return); - BreakHandler *handler = m_manager->breakHandler(); - QTC_ASSERT(handler, return); QString str = act->data().toString(); int pos = str.lastIndexOf(':'); toggleBreakpoint(str.left(pos), str.mid(pos + 1).toInt()); } -void DebuggerPlugin::breakpointEnableDisableMarginActionTriggered() +void DebuggerPluginPrivate::breakpointEnableDisableMarginActionTriggered() { QAction *act = qobject_cast<QAction *>(sender()); QTC_ASSERT(act, return); - BreakHandler *handler = m_manager->breakHandler(); - QTC_ASSERT(handler, return); QString str = act->data().toString(); int pos = str.lastIndexOf(':'); BreakpointData needle; needle.bpFileName = str.left(pos); needle.bpLineNumber = str.mid(pos + 1).toLatin1(); - BreakpointData *data = handler->findSimilarBreakpoint(needle); + BreakpointData *data = m_breakWindow->findSimilarBreakpoint(&needle); QTC_ASSERT(data, return); - handler->toggleBreakpointEnabled(data); - m_manager->attemptBreakpointSynchronization(); + data->enabled = !data->enabled; + m_breakWindow->updateBreakpoint(data); } -void DebuggerPlugin::requestMark(ITextEditor *editor, int lineNumber) +void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber) { - if (!isDebuggable(editor)) - return; - toggleBreakpoint(editor->file()->fileName(), lineNumber); + if (isDebuggable(editor)) + toggleBreakpoint(editor->file()->fileName(), lineNumber); } -void DebuggerPlugin::showToolTip(ITextEditor *editor, const QPoint &point, int pos) +void DebuggerPluginPrivate::showToolTip(ITextEditor *editor, const QPoint &point, int pos) { if (!isDebuggable(editor)) return; if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)) return; - if (m_manager->state() == DebuggerNotReady) + if (state() == DebuggerNotReady) return; + setToolTipExpression(point, editor, pos); - m_manager->setToolTipExpression(point, editor, pos); + QTC_ASSERT(false, /* FIXME ABC */); + // d->m_engine->setToolTipExpression(mousePos, editor, cursorPos); } -void DebuggerPlugin::setSessionValue(const QString &name, const QVariant &value) +ProjectExplorer::RunControl * +DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp) { - QTC_ASSERT(sessionManager(), return); - sessionManager()->setValue(name, value); + return m_debuggerRunControlFactory->create(sp); } -QVariant DebuggerPlugin::sessionValue(const QString &name) +void DebuggerPluginPrivate::startDebugger(ProjectExplorer::RunControl *rc) { - QTC_ASSERT(sessionManager(), return QVariant()); - return sessionManager()->value(name); + DebuggerRunControl *runControl = qobject_cast<DebuggerRunControl *>(rc); + qDebug() << "START DEBUGGER: " << runControl << rc; + QTC_ASSERT(runControl, return); + activateDebugMode(); + connectEngine(runControl->engine()); + ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE); } -void DebuggerPlugin::setConfigValue(const QString &name, const QVariant &value) +void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) { - QTC_ASSERT(m_debugMode, return); - settings()->setValue(name, value); + //if (engine == m_dummySessionEngine) + // qDebug() << "CONNECTING DUMMY ENGINE" << engine; + //else + // qDebug() << "CONNECTING ENGINE " << engine; + m_breakWindow->setModel(engine->breakModel()); + m_commandWindow->setModel(engine->commandModel()); + m_localsWindow->setModel(engine->localsModel()); + m_modulesWindow->setModel(engine->modulesModel()); + m_registerWindow->setModel(engine->registerModel()); + m_returnWindow->setModel(engine->returnModel()); + m_snapshotWindow->setModel(engine->snapshotModel()); + m_sourceFilesWindow->setModel(engine->sourceFilesModel()); + m_stackWindow->setModel(engine->stackModel()); + m_threadsWindow->setModel(engine->threadsModel()); + m_threadBox->setModel(engine->threadsModel()); + m_watchersWindow->setModel(engine->watchersModel()); + m_capabilities = engine->debuggerCapabilities(); } -QVariant DebuggerPlugin::configValue(const QString &name) const +static void changeFontSize(QWidget *widget, int size) { - QTC_ASSERT(m_debugMode, return QVariant()); - return settings()->value(name); + QFont font = widget->font(); + font.setPointSize(size); + widget->setFont(font); } -void DebuggerPlugin::resetLocation() +void DebuggerPluginPrivate::fontSettingsChanged + (const TextEditor::FontSettings &settings) { - //qDebug() << "RESET_LOCATION: current:" << currentTextEditor(); - //qDebug() << "RESET_LOCATION: locations:" << m_locationMark; - //qDebug() << "RESET_LOCATION: stored:" << m_locationMark->editor(); - delete m_locationMark; - m_locationMark = 0; + int size = settings.fontZoom() * settings.fontSize() / 100; + changeFontSize(m_breakWindow, size); + changeFontSize(m_localsWindow, size); + changeFontSize(m_modulesWindow, size); + changeFontSize(m_outputWindow, size); + changeFontSize(m_registerWindow, size); + changeFontSize(m_returnWindow, size); + changeFontSize(m_sourceFilesWindow, size); + changeFontSize(m_stackWindow, size); + changeFontSize(m_threadsWindow, size); + changeFontSize(m_watchersWindow, size); } -void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker) +void DebuggerPluginPrivate::cleanupViews() { - bool newEditor = false; - ITextEditor *editor = - BaseTextEditor::openEditorAt(file, line, 0, QString(), &newEditor); - if (!editor) - return; - if (newEditor) - editor->setProperty("OpenedByDebugger", true); - if (setMarker) { - resetLocation(); - m_locationMark = new LocationMark(file, line); + resetLocation(); + m_actions.reverseDirectionAction->setChecked(false); + m_actions.reverseDirectionAction->setEnabled(false); + hideDebuggerToolTip(); + + // FIXME ABC: Delete run control / engine? + //if (d->m_engine) + // d->m_engine->cleanup(); + + if (EditorManager *editorManager = EditorManager::instance()) { + QList<IEditor *> toClose; + foreach (IEditor *editor, editorManager->openedEditors()) + if (editor->property("OpenedByDebugger").toBool()) + toClose.append(editor); + editorManager->closeEditors(toClose); } } -void DebuggerPlugin::openTextEditor(const QString &titlePattern0, - const QString &contents) +void DebuggerPluginPrivate::setBusyCursor(bool busy) { - QString titlePattern = titlePattern0; - EditorManager *editorManager = EditorManager::instance(); - QTC_ASSERT(editorManager, return); - Core::IEditor *editor = editorManager->openEditorWithContents( - Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents); - QTC_ASSERT(editor, return); - editorManager->activateEditor(editor); + //STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << busy); + if (busy == m_busy) + return; + + m_busy = busy; + + QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor); + m_breakWindow->setCursor(cursor); + m_returnWindow->setCursor(cursor); + m_localsWindow->setCursor(cursor); + m_modulesWindow->setCursor(cursor); + m_outputWindow->setCursor(cursor); + m_registerWindow->setCursor(cursor); + m_stackWindow->setCursor(cursor); + m_sourceFilesWindow->setCursor(cursor); + m_threadsWindow->setCursor(cursor); + //m_tooltipWindow->setCursor(cursor); + m_watchersWindow->setCursor(cursor); + + m_breakWindow->setCursor(cursor); + m_returnWindow->setCursor(cursor); + m_localsWindow->setCursor(cursor); + m_modulesWindow->setCursor(cursor); + m_outputWindow->setCursor(cursor); + m_registerWindow->setCursor(cursor); + m_stackWindow->setCursor(cursor); + m_sourceFilesWindow->setCursor(cursor); + m_threadsWindow->setCursor(cursor); + //m_tooltipWindow->setCursor(cursor); + m_watchersWindow->setCursor(cursor); } -void DebuggerPlugin::handleStateChanged(int state) +void DebuggerPluginPrivate::setSimpleDockWidgetArrangement(const QString &activeLanguage) { - // Prevent it from beeing triggered on setup. - if (!m_manager) - return; + DebuggerMainWindow *mw = mainWindow(); + if (activeLanguage == LANG_CPP || activeLanguage.isEmpty()) { + //qDebug() << "SETTING SIMPLE CPP ARRANGEMENT" << activeLanguage; + mw->setTrackingEnabled(false); + QList<QDockWidget *> dockWidgets = mw->dockWidgets(); + foreach (QDockWidget *dockWidget, dockWidgets) { + if (m_dockWidgets.contains(dockWidget)) { + dockWidget->setFloating(false); + mw->removeDockWidget(dockWidget); + } + } + + foreach (QDockWidget *dockWidget, dockWidgets) { + if (m_dockWidgets.contains(dockWidget)) { + if (dockWidget == m_outputDock) + mw->addDockWidget(Qt::TopDockWidgetArea, dockWidget); + else + mw->addDockWidget(Qt::BottomDockWidgetArea, dockWidget); + dockWidget->show(); + } + } + + mw->tabifyDockWidget(m_watchDock, m_breakDock); + mw->tabifyDockWidget(m_watchDock, m_modulesDock); + mw->tabifyDockWidget(m_watchDock, m_registerDock); + mw->tabifyDockWidget(m_watchDock, m_threadsDock); + mw->tabifyDockWidget(m_watchDock, m_sourceFilesDock); + mw->tabifyDockWidget(m_watchDock, m_snapshotDock); + // They following views are rarely used in ordinary debugging. Hiding them + // saves cycles since the corresponding information won't be retrieved. + m_sourceFilesDock->hide(); + m_registerDock->hide(); + m_modulesDock->hide(); + m_outputDock->hide(); + mw->setTrackingEnabled(true); + } else { + //qDebug() << "SETTING SIMPLE QML ARRANGEMENT" << activeLanguage; + } +} + +void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) +{ + QTC_ASSERT(engine, return); + m_state = engine->state(); + bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(m_state); + + //if (m_state == InferiorStopped) + // resetLocation(); + //qDebug() << "PLUGIN SET STATE: " << m_state; - const bool startIsContinue = (state == InferiorStopped); + if (m_state == DebuggerNotReady) { + setBusyCursor(false); + cleanupViews(); + } + + const bool startIsContinue = (m_state == InferiorStopped); ICore *core = ICore::instance(); if (startIsContinue) core->updateAdditionalContexts(QList<int>(), QList<int>() << m_gdbRunningContext); else core->updateAdditionalContexts(QList<int>() << m_gdbRunningContext, QList<int>()); - const bool started = state == InferiorRunning - || state == InferiorRunningRequested - || state == InferiorStopping - || state == InferiorStopped; + const bool started = m_state == InferiorRunning + || m_state == InferiorRunningRequested + || m_state == InferiorStopping + || m_state == InferiorStopped; - const bool starting = state == EngineStarting; - //const bool running = state == InferiorRunning; - - const bool detachable = state == InferiorStopped - && m_manager->runControl()->sp().startMode != AttachCore; + const bool starting = m_state == EngineStarting; + //const bool running = m_state == InferiorRunning; m_startExternalAction->setEnabled(!started && !starting); m_attachExternalAction->setEnabled(!started && !starting); @@ -1379,46 +2098,103 @@ void DebuggerPlugin::handleStateChanged(int state) m_attachCoreAction->setEnabled(!started && !starting); #endif m_startRemoteAction->setEnabled(!started && !starting); + + const bool detachable = m_state == InferiorStopped + && engine->startParameters().startMode != AttachCore; m_detachAction->setEnabled(detachable); -} -void DebuggerPlugin::languageChanged(const QString &language) -{ - if (!m_manager) - return; + const bool stoppable = m_state == InferiorRunning + || m_state == InferiorRunningRequested + || m_state == InferiorStopping + || m_state == InferiorStopped + || m_state == InferiorUnrunnable; - const bool debuggerIsCPP = (language == Constants::LANG_CPP); + const bool running = m_state == InferiorRunning; +// FIXME ABC +// if (running) +// threadsHandler()->notifyRunning(); + const bool stopped = m_state == InferiorStopped; - m_startExternalAction->setVisible(debuggerIsCPP); - m_attachExternalAction->setVisible(debuggerIsCPP); - m_attachCoreAction->setVisible(debuggerIsCPP); - m_startRemoteAction->setVisible(debuggerIsCPP); - m_detachAction->setVisible(debuggerIsCPP); -} + if (stopped) + QApplication::alert(mainWindow(), 3000); -void DebuggerPlugin::writeSettings() const -{ - QSettings *s = settings(); - DebuggerSettings::instance()->writeSettings(s); + //qDebug() << "FLAGS: " << stoppable << running << stopped; + + m_actions.watchAction1->setEnabled(true); + m_actions.watchAction2->setEnabled(true); + m_actions.breakAction->setEnabled(true); + m_actions.snapshotAction-> + setEnabled(stopped && (m_capabilities & SnapshotCapability)); + + theDebuggerAction(OperateByInstruction)->setEnabled(!running); + + const bool interruptIsExit = !running; + if (interruptIsExit) { + m_actions.stopAction->setIcon(m_stopIcon); + m_actions.stopAction->setText(tr("Stop Debugger")); + } else { + m_actions.stopAction->setIcon(m_interruptIcon); + m_actions.stopAction->setText(tr("Interrupt")); + } + + m_actions.stopAction->setEnabled(stoppable); + m_actions.resetAction->setEnabled(m_state != DebuggerNotReady); + + m_actions.stepAction->setEnabled(stopped); + m_actions.stepOutAction->setEnabled(stopped); + m_actions.runToLineAction1->setEnabled(stopped); + m_actions.runToLineAction2->setEnabled(stopped); + m_actions.runToFunctionAction->setEnabled(stopped); + m_actions.returnFromFunctionAction-> + setEnabled(stopped && (m_capabilities & ReturnFromFunctionCapability)); + + const bool canJump = stopped && (m_capabilities & JumpToLineCapability); + m_actions.jumpToLineAction1->setEnabled(canJump); + m_actions.jumpToLineAction2->setEnabled(canJump); + + m_actions.nextAction->setEnabled(stopped); + + theDebuggerAction(RecheckDebuggingHelpers)->setEnabled(actionsEnabled); + const bool canDeref = actionsEnabled + && (m_capabilities & AutoDerefPointersCapability); + theDebuggerAction(AutoDerefPointers)->setEnabled(canDeref); + theDebuggerAction(ExpandStack)->setEnabled(actionsEnabled); + theDebuggerAction(ExecuteCommand)->setEnabled(m_state == InferiorStopped); + + m_watchersWindow->setVisible(false); + m_returnWindow->setVisible(false); + + const bool notbusy = m_state == InferiorStopped + || m_state == DebuggerNotReady + || m_state == InferiorUnrunnable; + setBusyCursor(!notbusy); + + // FIXME: for QML + //emit m_plugin->stateChanged(m_state); } -void DebuggerPlugin::readSettings() +void DebuggerPluginPrivate::resetLocation() { - QSettings *s = settings(); - DebuggerSettings::instance()->readSettings(s); + delete m_locationMark; + m_locationMark = 0; } -static bool isCurrentProjectCppBased() +void DebuggerPluginPrivate::gotoLocation(const QString &file, int line, bool setMarker) { - ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); - Project *startupProject = projectExplorer->startupProject(); - const QStringList cppProjectIds = QStringList() << QLatin1String("GenericProjectManager.GenericProject") - << QLatin1String("CMakeProjectManager.CMakeProject") - << QLatin1String("Qt4ProjectManager.Qt4Project"); - return (startupProject && cppProjectIds.contains(startupProject->id())); + bool newEditor = false; + ITextEditor *editor = + BaseTextEditor::openEditorAt(file, line, 0, QString(), &newEditor); + if (!editor) + return; + if (newEditor) + editor->setProperty("OpenedByDebugger", true); + if (setMarker) { + resetLocation(); + m_locationMark = new LocationMark(file, line); + } } -void DebuggerPlugin::onModeChanged(IMode *mode) +void DebuggerPluginPrivate::onModeChanged(IMode *mode) { // FIXME: This one gets always called, even if switching between modes // different then the debugger mode. E.g. Welcome and Help mode and @@ -1436,187 +2212,548 @@ void DebuggerPlugin::onModeChanged(IMode *mode) } } -void DebuggerPlugin::showSettingsDialog() +void DebuggerPluginPrivate::showSettingsDialog() { Core::ICore::instance()->showOptionsDialog( _(DEBUGGER_SETTINGS_CATEGORY), _(DEBUGGER_COMMON_SETTINGS_ID)); } -void DebuggerPlugin::startExternalApplication() +void DebuggerPluginPrivate::dumpLog() { - DebuggerStartParameters sp; - StartExternalDialog dlg(m_uiSwitcher->mainWindow()); - dlg.setExecutableFile( - configValue(_("LastExternalExecutableFile")).toString()); - dlg.setExecutableArguments( - configValue(_("LastExternalExecutableArguments")).toString()); - dlg.setWorkingDirectory( - configValue(_("LastExternalWorkingDirectory")).toString()); - if (dlg.exec() != QDialog::Accepted) + QString fileName = QFileDialog::getSaveFileName(mainWindow(), + tr("Save Debugger Log"), QDir::tempPath()); + if (fileName.isEmpty()) return; + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) + return; + QTextStream ts(&file); + ts << m_outputWindow->inputContents(); + ts << "\n\n=======================================\n\n"; + ts << m_outputWindow->combinedContents(); +} - setConfigValue(_("LastExternalExecutableFile"), - dlg.executableFile()); - setConfigValue(_("LastExternalExecutableArguments"), - dlg.executableArguments()); - setConfigValue(_("LastExternalWorkingDirectory"), - dlg.workingDirectory()); - sp.executable = dlg.executableFile(); - sp.startMode = StartExternal; - sp.workingDirectory = dlg.workingDirectory(); - if (!dlg.executableArguments().isEmpty()) - sp.processArgs = dlg.executableArguments().split(QLatin1Char(' ')); +void DebuggerPluginPrivate::clearStatusMessage() +{ + m_statusLabel->setText(m_lastPermanentStatusMessage); +} - if (dlg.breakAtMain()) - m_manager->breakByFunctionMain(); +/*! Activates the previous mode when the current mode is the debug mode. */ +void DebuggerPluginPrivate::activatePreviousMode() +{ + Core::ModeManager *modeManager = ICore::instance()->modeManager(); - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE); + if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG) + && !m_previousMode.isEmpty()) { + modeManager->activateMode(m_previousMode); + m_previousMode.clear(); + } } -void DebuggerPlugin::attachExternalApplication() +void DebuggerPluginPrivate::activateDebugMode() { - AttachExternalDialog dlg(m_uiSwitcher->mainWindow()); - if (dlg.exec() == QDialog::Accepted) - attachExternalApplication(dlg.attachPID(), dlg.executable(), QString()); + //qDebug() << "ACTIVATING DEBUG MODE"; + const bool canReverse = (m_capabilities & ReverseSteppingCapability) + && theDebuggerBoolSetting(EnableReverseDebugging); + m_actions.reverseDirectionAction->setChecked(false); + m_actions.reverseDirectionAction->setEnabled(canReverse); + m_actions.reverseDirectionAction->setEnabled(false); + ModeManager *modeManager = ModeManager::instance(); + m_previousMode = modeManager->currentMode()->id(); + modeManager->activateMode(_(MODE_DEBUG)); } -void DebuggerPlugin::attachExternalApplication(qint64 pid, - const QString &binary, - const QString &crashParameter) +void DebuggerPluginPrivate::sessionLoaded() { - if (pid == 0) { - QMessageBox::warning(m_uiSwitcher->mainWindow(), tr("Warning"), - tr("Cannot attach to PID 0")); - return; - } - DebuggerStartParameters sp; - sp.attachPID = pid; - sp.executable = binary; - sp.crashParameter = crashParameter; - sp.startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal; - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE); + //qDebug() << "SESSION LOADED"; + loadSessionData(); } -void DebuggerPlugin::attachCore() +void DebuggerPluginPrivate::aboutToUnloadSession() { - AttachCoreDialog dlg(m_uiSwitcher->mainWindow()); - dlg.setExecutableFile( - configValue(_("LastExternalExecutableFile")).toString()); - dlg.setCoreFile( - configValue(_("LastExternalCoreFile")).toString()); - if (dlg.exec() != QDialog::Accepted) - return; - setConfigValue(_("LastExternalExecutableFile"), - dlg.executableFile()); - setConfigValue(_("LastExternalCoreFile"), - dlg.coreFile()); - attachCore(dlg.coreFile(), dlg.executableFile()); + // Stop debugging the active project when switching sessions. + // Note that at startup, session switches may occur, which interfer + // with command-line debugging startup. + // FIXME ABC: Still wanted? + //if (d->m_engine && state() != DebuggerNotReady + // && runControl()->sp().startMode == StartInternal) + // d->m_engine->shutdown(); } -void DebuggerPlugin::attachCore(const QString &core, const QString &exe) +void DebuggerPluginPrivate::aboutToSaveSession() { - DebuggerStartParameters sp; - sp.executable = exe; - sp.coreFile = core; - sp.displayName = tr("Core file: \"%1\"").arg(core); - sp.startMode = AttachCore; - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance()-> - startRunControl(runControl, PE::DEBUGMODE); + saveSessionData(); } -void DebuggerPlugin::startRemoteApplication() +void DebuggerPluginPrivate::loadSessionData() { - DebuggerStartParameters sp; - StartRemoteDialog dlg(m_uiSwitcher->mainWindow()); - QStringList arches; - arches.append(_("i386:x86-64:intel")); - arches.append(_("i386")); - QString lastUsed = configValue(_("LastRemoteArchitecture")).toString(); - if (!arches.contains(lastUsed)) - arches.prepend(lastUsed); - dlg.setRemoteArchitectures(arches); - dlg.setRemoteChannel( - configValue(_("LastRemoteChannel")).toString()); - dlg.setLocalExecutable( - configValue(_("LastLocalExecutable")).toString()); - dlg.setDebugger(configValue(_("LastDebugger")).toString()); - dlg.setRemoteArchitecture(lastUsed); - dlg.setServerStartScript( - configValue(_("LastServerStartScript")).toString()); - dlg.setUseServerStartScript( - configValue(_("LastUseServerStartScript")).toBool()); - dlg.setSysRoot(configValue(_("LastSysroot")).toString()); - if (dlg.exec() != QDialog::Accepted) - return; - setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel()); - setConfigValue(_("LastLocalExecutable"), dlg.localExecutable()); - setConfigValue(_("LastDebugger"), dlg.debugger()); - setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture()); - setConfigValue(_("LastServerStartScript"), dlg.serverStartScript()); - setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript()); - setConfigValue(_("LastSysroot"), dlg.sysRoot()); - sp.remoteChannel = dlg.remoteChannel(); - sp.remoteArchitecture = dlg.remoteArchitecture(); - sp.executable = dlg.localExecutable(); - sp.displayName = dlg.localExecutable(); - sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection. - if (!sp.debuggerCommand.isEmpty()) - sp.toolChainType = ProjectExplorer::ToolChain::INVALID; - sp.startMode = AttachToRemote; - if (dlg.useServerStartScript()) - sp.serverStartScript = dlg.serverStartScript(); - sp.sysRoot = dlg.sysRoot(); + // FIXME: Iterate? + //qDebug() << "\nLOADING SESSION DATA..."; + notifyCurrentEngine(RequestLoadSessionDataRole); + //qDebug() << "LOADED SESSION DATA\n"; +} - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance() - ->startRunControl(runControl, PE::DEBUGMODE); +void DebuggerPluginPrivate::saveSessionData() +{ + // FIXME: Iterate? + //qDebug() << "\nSAVING SESSION DATA..."; + notifyCurrentEngine(RequestSaveSessionDataRole); + //qDebug() << "SAVED SESSION DATA\n"; } -void DebuggerPlugin::enableReverseDebuggingTriggered(const QVariant &value) +void DebuggerPluginPrivate::interruptDebuggingRequest() { - QTC_ASSERT(m_reverseToolButton, return); - m_reverseToolButton->setVisible(value.toBool()); - m_manager->debuggerManagerActions().reverseDirectionAction->setChecked(false); - m_manager->debuggerManagerActions().reverseDirectionAction->setEnabled(value.toBool()); + if (state() == InferiorRunning) + notifyCurrentEngine(RequestExecInterruptRole); + else + exitDebugger(); } -void DebuggerPlugin::attachRemoteTcf() +void DebuggerPluginPrivate::exitDebugger() { - DebuggerStartParameters sp; - AttachTcfDialog dlg(m_uiSwitcher->mainWindow()); - QStringList arches; - arches.append(_("i386:x86-64:intel")); - dlg.setRemoteArchitectures(arches); - dlg.setRemoteChannel( - configValue(_("LastTcfRemoteChannel")).toString()); - dlg.setRemoteArchitecture( - configValue(_("LastTcfRemoteArchitecture")).toString()); - dlg.setServerStartScript( - configValue(_("LastTcfServerStartScript")).toString()); - dlg.setUseServerStartScript( - configValue(_("LastTcfUseServerStartScript")).toBool()); - if (dlg.exec() != QDialog::Accepted) + // The engine will finally call setState(DebuggerNotReady) which + // in turn will handle the cleanup. + notifyCurrentEngine(RequestExecExitRole); + m_codeModelSnapshot = CPlusPlus::Snapshot(); +} + + +/////////////////////////////////////////////////////////////////////// +// +// DebuggerPlugin +// +/////////////////////////////////////////////////////////////////////// + +DebuggerPlugin *theInstance = 0; + +DebuggerPlugin *DebuggerPlugin::instance() +{ + return theInstance; +} + +DebuggerPlugin::DebuggerPlugin() +{ + d = new DebuggerPluginPrivate(this); + theInstance = this; +} + +DebuggerPlugin::~DebuggerPlugin() +{ + delete d->m_dummySessionEngine; + d->m_dummySessionEngine = 0; + + theInstance = 0; + delete DebuggerSettings::instance(); + + removeObject(d->m_debugMode); + + delete d->m_debugMode; + d->m_debugMode = 0; + + delete d->m_locationMark; + d->m_locationMark = 0; + + removeObject(d->m_uiSwitcher); + delete d->m_uiSwitcher; + d->m_uiSwitcher = 0; + + delete d; +} + +bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage) +{ + return d->initialize(arguments, errorMessage); +} + +void DebuggerPlugin::setSessionValue(const QString &name, const QVariant &value) +{ + QTC_ASSERT(sessionManager(), return); + sessionManager()->setValue(name, value); + //qDebug() << "SET SESSION VALUE: " << name; +} + +QVariant DebuggerPlugin::sessionValue(const QString &name) +{ + QTC_ASSERT(sessionManager(), return QVariant()); + //qDebug() << "GET SESSION VALUE: " << name; + return sessionManager()->value(name); +} + +void DebuggerPlugin::setConfigValue(const QString &name, const QVariant &value) +{ + QTC_ASSERT(d->m_debugMode, return); + settings()->setValue(name, value); +} + +QVariant DebuggerPlugin::configValue(const QString &name) const +{ + QTC_ASSERT(d->m_debugMode, return QVariant()); + return settings()->value(name); +} + +void DebuggerPlugin::resetLocation() +{ + d->resetLocation(); + //qDebug() << "RESET_LOCATION: current:" << currentTextEditor(); + //qDebug() << "RESET_LOCATION: locations:" << m_locationMark; + //qDebug() << "RESET_LOCATION: stored:" << m_locationMark->editor(); + delete d->m_locationMark; + d->m_locationMark = 0; +} + +void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker) +{ + bool newEditor = false; + ITextEditor *editor = + BaseTextEditor::openEditorAt(file, line, 0, QString(), &newEditor); + if (!editor) return; - setConfigValue(_("LastTcfRemoteChannel"), dlg.remoteChannel()); - setConfigValue(_("LastTcfRemoteArchitecture"), dlg.remoteArchitecture()); - setConfigValue(_("LastTcfServerStartScript"), dlg.serverStartScript()); - setConfigValue(_("LastTcfUseServerStartScript"), dlg.useServerStartScript()); - sp.remoteChannel = dlg.remoteChannel(); - sp.remoteArchitecture = dlg.remoteArchitecture(); - sp.serverStartScript = dlg.serverStartScript(); - sp.startMode = AttachTcf; - if (dlg.useServerStartScript()) - sp.serverStartScript = dlg.serverStartScript(); + if (newEditor) + editor->setProperty("OpenedByDebugger", true); + if (setMarker) { + resetLocation(); + d->m_locationMark = new LocationMark(file, line); + } +} + +void DebuggerPlugin::openTextEditor(const QString &titlePattern0, + const QString &contents) +{ + QString titlePattern = titlePattern0; + EditorManager *editorManager = EditorManager::instance(); + QTC_ASSERT(editorManager, return); + Core::IEditor *editor = editorManager->openEditorWithContents( + Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents); + QTC_ASSERT(editor, return); + editorManager->activateEditor(editor); +} + +void DebuggerPlugin::writeSettings() const +{ + QSettings *s = settings(); + DebuggerSettings::instance()->writeSettings(s); +} + +void DebuggerPlugin::readSettings() +{ + //qDebug() << "PLUGIN READ SETTINGS"; + QSettings *s = settings(); + DebuggerSettings::instance()->readSettings(s); +} + +const CPlusPlus::Snapshot &DebuggerPlugin::cppCodeModelSnapshot() const +{ + if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked()) + d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); + return d->m_codeModelSnapshot; +} + +void DebuggerPlugin::clearCppCodeModelSnapshot() +{ + d->m_codeModelSnapshot = CPlusPlus::Snapshot(); +} + +void DebuggerPlugin::showStatusMessage(const QString &msg0, int timeout) +{ + showMessage(msg0, LogStatus); + QString msg = msg0; + msg.replace(QLatin1Char('\n'), QString()); + d->m_statusLabel->setText(msg); + if (timeout > 0) { + d->m_statusTimer.setSingleShot(true); + d->m_statusTimer.start(timeout); + } else { + d->m_lastPermanentStatusMessage = msg; + d->m_statusTimer.stop(); + } +} + +void DebuggerPlugin::aboutToShutdown() +{ + writeSettings(); + if (d->m_uiSwitcher) + d->m_uiSwitcher->aboutToShutdown(); + //if (d->m_engine) + // d->m_engine->shutdown(); +} + +void DebuggerPlugin::addToWatchWindow() +{ + using namespace Core; + using namespace TextEditor; + // Requires a selection, but that's the only case we want anyway. + EditorManager *editorManager = EditorManager::instance(); + if (!editorManager) + return; + IEditor *editor = editorManager->currentEditor(); + if (!editor) + return; + ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor); + if (!textEditor) + return; + QTextCursor tc; + QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget()); + if (ptEdit) + tc = ptEdit->textCursor(); + QString exp; + if (tc.hasSelection()) { + exp = tc.selectedText(); + } else { + int line, column; + exp = cppExpressionAt(textEditor, tc.position(), &line, &column); + } + +// FIXME: +// if (!exp.isEmpty()) +// d->m_watchHandler->watchExpression(exp); +} + +void DebuggerPlugin::setBusyCursor(bool busy) +{ + d->setBusyCursor(busy); +} + +/* +void DebuggerPlugin::gotoLocation(const StackFrame &frame, bool setMarker) +{ + if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) { + if (setMarker) + d->m_plugin->resetLocation(); + d->m_disassemblerViewAgent->setFrame(frame); + } else { + d->m_plugin->gotoLocation(frame.file, frame.line, setMarker); + } +} +*/ + +void DebuggerPlugin::showMessage(const QString &msg, int channel, int timeout) +{ + //qDebug() << "PLUGIN OUTPUT: " << channel << msg; + DebuggerOutputWindow *ow = d->m_outputWindow; + QTC_ASSERT(ow, return); + switch (channel) { + case StatusBar: + showStatusMessage(msg, timeout); + ow->showOutput(LogStatus, msg); + break; + case LogMiscInput: + ow->showInput(LogMisc, msg); + ow->showOutput(LogMisc, msg); + break; + case LogInput: + ow->showInput(channel, msg); + ow->showOutput(channel, msg); + break; + default: + ow->showOutput(channel, msg); + break; + } +} + + +////////////////////////////////////////////////////////////////////// +// +// Register specific stuff +// +////////////////////////////////////////////////////////////////////// + +bool DebuggerPlugin::isReverseDebugging() const +{ + return d->m_actions.reverseDirectionAction->isChecked(); +} + +QMessageBox *DebuggerPlugin::showMessageBox(int icon, const QString &title, + const QString &text, int buttons) +{ + QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon), + title, text, QMessageBox::StandardButtons(buttons), mainWindow()); + mb->setAttribute(Qt::WA_DeleteOnClose); + mb->show(); + return mb; +} + +void DebuggerPlugin::ensureLogVisible() +{ + QAction *action = d->m_outputDock->toggleViewAction(); + if (!action->isChecked()) + action->trigger(); +} + +QIcon DebuggerPlugin::locationMarkIcon() const +{ + return d->m_locationMarkIcon; +} + +void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &) +{ + QString errorMessage; + AttachRemoteParameters parameters; + unsigned dummy = 0; + // Did we receive a request for debugging (unless it is ourselves)? + if (parseArguments(options, ¶meters, &dummy, &errorMessage) + && parameters.attachPid != quint64(QCoreApplication::applicationPid())) { + d->m_attachRemoteParameters = parameters; + d->attachCmdLine(); + } +} + +void DebuggerPlugin::extensionsInitialized() +{ + // time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin + const QByteArray env = qgetenv("QTC_DEBUGGER_TEST"); + //qDebug() << "EXTENSIONS INITIALIZED:" << env; + // if (!env.isEmpty()) + // m_plugin->runTest(QString::fromLocal8Bit(env)); + if (d->m_attachRemoteParameters.attachPid + || !d->m_attachRemoteParameters.attachCore.isEmpty()) + QTimer::singleShot(0, d, SLOT(attachCmdLine())); + + //qDebug() << "EXTENSIONS INITIALIZED"; + // Already done in initialize(). FIXME: Move stuff to here? + //readSettings(); + //d->m_uiSwitcher->initialize(); +} - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance() - ->startRunControl(runControl, PE::DEBUGMODE); +void DebuggerPlugin::updateWatchersWindow(bool showWatchers, bool showReturn) +{ + d->m_watchersWindow->setVisible(showWatchers); + d->m_returnWindow->setVisible(showReturn); } +QWidget *DebuggerPlugin::mainWindow() const +{ + return d->m_uiSwitcher->mainWindow(); +} + +ProjectExplorer::RunControl * +DebuggerPlugin::createDebugger(const DebuggerStartParameters &sp) +{ + return instance()->d->createDebugger(sp); +} + +void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl) +{ + instance()->d->startDebugger(runControl); +} + +void DebuggerPlugin::updateState(DebuggerEngine *engine) +{ + d->updateState(engine); +} + +void DebuggerPlugin::activatePreviousMode() +{ + d->activatePreviousMode(); +} + +void DebuggerPlugin::activateDebugMode() +{ + d->activateDebugMode(); +} + +void DebuggerPlugin::exitDebugger() +{ + d->exitDebugger(); +} + +int DebuggerPlugin::state() const +{ + return d->state(); +} + +void DebuggerPlugin::createNewDock(QWidget *widget) +{ + QDockWidget *dockWidget = + DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, widget); + dockWidget->setWindowTitle(widget->windowTitle()); + dockWidget->setObjectName(widget->windowTitle()); + dockWidget->setFeatures(QDockWidget::DockWidgetClosable); + //dockWidget->setWidget(widget); + //mainWindow()->addDockWidget(Qt::TopDockWidgetArea, dockWidget); + dockWidget->show(); +} + +void DebuggerPlugin::runControlStarted(DebuggerRunControl *runControl) +{ + qDebug() << "RUNCONTROL STARTED: " << runControl; + d->connectEngine(runControl->engine()); +} + +void DebuggerPlugin::runControlFinished(DebuggerRunControl *runControl) +{ + Q_UNUSED(runControl); + qDebug() << "RUNCONTROL FINISHED: " << runControl; +} + +DebuggerEngine *DebuggerPlugin::sessionTemplate() +{ + return d->m_dummySessionEngine; +} + +////////////////////////////////////////////////////////////////////// +// +// Testing +// +////////////////////////////////////////////////////////////////////// + +/* +void DebuggerPlugin::runTest(const QString &fileName) +{ + DebuggerStartParameters sp; + sp.executable = fileName; + sp.processArgs = QStringList() << "--run-debuggee"; + sp.workingDirectory.clear(); + startDebugger(m_debuggerRunControlFactory->create(sp)); +} +*/ + +bool DebuggerListener::coreAboutToClose() +{ + DebuggerPlugin *plugin = DebuggerPlugin::instance(); + if (!plugin) + return true; + // Ask to terminate the session. + bool cleanTermination = false; + switch (plugin->state()) { + case DebuggerNotReady: + return true; + case AdapterStarted: // Most importantly, terminating a running + case AdapterStartFailed: // debuggee can cause problems. + case InferiorUnrunnable: + case InferiorStartFailed: + case InferiorStopped: + case InferiorShutDown: + cleanTermination = true; + break; + default: + break; + } + + const QString question = cleanTermination ? + tr("A debugging session is still in progress.\n" + "Would you like to terminate it?") : + tr("A debugging session is still in progress. " + "Terminating the session in the current" + " state (%1) can leave the target in an inconsistent state." + " Would you still like to terminate it?") + .arg(_(DebuggerEngine::stateName(plugin->state()))); + + QMessageBox::StandardButton answer = + QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(), + tr("Close Debugging Session"), question, + QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); + + if (answer != QMessageBox::Yes) + return false; + + plugin->d->exitDebugger(); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + return true; +} + +} // namespace Debugger + #include "debuggerplugin.moc" Q_EXPORT_PLUGIN(DebuggerPlugin) diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index cc895948b6cba53a00da734c69895cf3c5284d01..723784ad78767c3acf42be2167b98ebd5587dc10 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -30,138 +30,121 @@ #ifndef DEBUGGERPLUGIN_H #define DEBUGGERPLUGIN_H -#include <extensionsystem/iplugin.h> +#include "debugger_global.h" -#include <QtCore/QObject> +#include <extensionsystem/iplugin.h> QT_BEGIN_NAMESPACE -class QAction; -class QComboBox; -class QMenu; -class QPoint; -class QToolButton; +class QAbstractItemView; +class QIcon; +class QMessageBox; QT_END_NAMESPACE -namespace Core { -class IEditor; -class IMode; +namespace CPlusPlus { +class Snapshot; } -namespace TextEditor { -class ITextEditor; -class ITextMark; -class BaseTextMark; +namespace ProjectExplorer { +class RunControl; } namespace Debugger { -class DebuggerManager; -class DebuggerUISwitcher; -class DebuggerRunControlFactory; +class DebuggerPluginPrivate; +class DebuggerRunControl; +class DebuggerStartParameters; namespace Internal { +class DebuggerEngine; +class DebuggerListener; +} -class BreakpointData; -class DebugMode; - -class DebuggerPlugin : public ExtensionSystem::IPlugin +class DEBUGGER_EXPORT DebuggerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT public: - struct AttachRemoteParameters { - AttachRemoteParameters(); - - quint64 attachPid; - QString attachCore; - // Event handle for attaching to crashed Windows processes. - quint64 winCrashEvent; - }; - DebuggerPlugin(); ~DebuggerPlugin(); -private: - bool initialize(const QStringList &arguments, QString *error_message); - void aboutToShutdown(); - void extensionsInitialized(); - void remoteCommand(const QStringList &options, const QStringList &arguments); + static DebuggerPlugin *instance(); QVariant configValue(const QString &name) const; - TextEditor::ITextEditor *currentTextEditor(); QVariant sessionValue(const QString &name); void setSessionValue(const QString &name, const QVariant &value); void setConfigValue(const QString &name, const QVariant &value); -private slots: + void resetLocation(); + void gotoLocation(const QString &fileName, int lineNumber, bool setMarker); void activatePreviousMode(); void activateDebugMode(); - void editorOpened(Core::IEditor *editor); - void editorAboutToClose(Core::IEditor *editor); - void handleStateChanged(int state); - void requestMark(TextEditor::ITextEditor *editor, int lineNumber); - void showToolTip(TextEditor::ITextEditor *editor, const QPoint &pnt, int pos); - void requestContextMenu(TextEditor::ITextEditor *editor, - int lineNumber, QMenu *menu); + void openTextEditor(const QString &titlePattern, const QString &contents); - void resetLocation(); - void gotoLocation(const QString &fileName, int lineNumber, bool setMarker); + void readSettings(); + void writeSettings() const; - void openTextEditor(const QString &titlePattern, const QString &contents); + static ProjectExplorer::RunControl *createDebugger + (const DebuggerStartParameters &sp); + static void startDebugger(ProjectExplorer::RunControl *runControl); - void toggleBreakpoint(); - void toggleBreakpoint(const QString &fileName, int lineNumber); - void breakpointSetRemoveMarginActionTriggered(); - void breakpointEnableDisableMarginActionTriggered(); - void onModeChanged(Core::IMode *mode); - void showSettingsDialog(); + QMessageBox *showMessageBox(int icon, const QString &title, + const QString &text, int buttons = 0); - void startExternalApplication(); - void startRemoteApplication(); - void attachExternalApplication(); - void attachCore(); - void attachCmdLine(); - void attachRemoteTcf(); + const CPlusPlus::Snapshot &cppCodeModelSnapshot() const; - void enableReverseDebuggingTriggered(const QVariant &value); - void languageChanged(const QString &debuggerLanguage); + QIcon locationMarkIcon() const; + int state() const; // Last reported state of last active engine. + bool isReverseDebugging() const; + void createNewDock(QWidget *widget); + void runControlStarted(DebuggerRunControl *runControl); + void runControlFinished(DebuggerRunControl *runControl); + + // This contains per-session data like breakpoints and watched + // expression. It serves as a template for new engine instantiations. + Internal::DebuggerEngine *sessionTemplate(); + +public slots: + void exitDebugger(); // FIXME: remove + void setBusyCursor(bool on); + void interruptDebuggingRequest(); + void detachDebugger(); + void addToWatchWindow(); + + void executeDebuggerCommand(); + void executeDebuggerCommand(const QString &command); + + void watchPoint(); + + void clearCppCodeModelSnapshot(); + + void ensureLogVisible(); + void updateWatchersWindow(bool showWatchers, bool showReturn); + + // void runTest(const QString &fileName); + void showMessage(const QString &msg, int channel, int timeout = -1); + +signals: + void stateChanged(int); private: - void readSettings(); - void writeSettings() const; - void attachExternalApplication(qint64 pid, - const QString &binary, - const QString &crashParameter); - void attachCore(const QString &core, const QString &exeFileName); - - friend class Debugger::DebuggerManager; - friend class GdbOptionPage; - friend class DebuggingHelperOptionPage; - // FIXME: Just a hack now so that it can access the views. - friend class Debugger::Internal::DebugMode; - - DebuggerUISwitcher *m_uiSwitcher; - DebuggerManager *m_manager; - DebugMode *m_debugMode; - DebuggerRunControlFactory *m_debuggerRunControlFactory; - - QString m_previousMode; - TextEditor::BaseTextMark *m_locationMark; - int m_gdbRunningContext; - AttachRemoteParameters m_attachRemoteParameters; - unsigned m_cmdLineEnabledEngines; - - QAction *m_startExternalAction; - QAction *m_startRemoteAction; - QAction *m_attachExternalAction; - QAction *m_attachCoreAction; - QAction *m_attachTcfAction; - QAction *m_detachAction; - QComboBox *m_langBox; - QToolButton *m_reverseToolButton; + friend class Internal::DebuggerEngine; + friend class Internal::DebuggerListener +; + bool initialize(const QStringList &arguments, QString *errorMessage); + void aboutToShutdown(); + void extensionsInitialized(); + void remoteCommand(const QStringList &options, const QStringList &arguments); + + void updateState(Internal::DebuggerEngine *engine); + void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever + + QWidget *mainWindow() const; + +private: + friend class DebuggerPluginPrivate; + DebuggerPluginPrivate *d; }; -} // namespace Internal } // namespace Debugger #endif // DEBUGGERPLUGIN_H diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 40686d8c1bc9e85979e680f3b3f7deca6da314a8..73579cad318fe2c353b5a747fec8b31e7ea1fcc9 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -28,19 +28,12 @@ **************************************************************************/ #include "debuggerrunner.h" -#include "debuggermanager.h" -#include "debuggeroutputwindow.h" -#include "idebuggerengine.h" - -#include "breakhandler.h" -#include "moduleshandler.h" -#include "registerhandler.h" -#include "snapshothandler.h" -#include "stackhandler.h" -#include "stackframe.h" -#include "threadshandler.h" -#include "watchhandler.h" +#include "debuggeractions.h" +#include "debuggerconstants.h" +#include "debuggerengine.h" +#include "debuggerplugin.h" +#include "debuggerstringutils.h" #include <projectexplorer/debugginghelper.h> #include <projectexplorer/environment.h> @@ -65,6 +58,38 @@ using namespace ProjectExplorer; using namespace Debugger::Internal; +namespace Debugger { +namespace Internal { + +DebuggerEngine *createGdbEngine(const DebuggerStartParameters &); +DebuggerEngine *createScriptEngine(const DebuggerStartParameters &); +DebuggerEngine *createPdbEngine(const DebuggerStartParameters &); +DebuggerEngine *createTcfEngine(const DebuggerStartParameters &); +DebuggerEngine *createQmlEngine(const DebuggerStartParameters &); + +#ifdef CDB_ENABLED +DebuggerEngine *createCdbEngine(const DebuggerStartParameters &); +#else +DebuggerEngine *createCdbEngine(const DebuggerStartParameters &) { return 0; } +#endif + +// FIXME: Outdated? +// The createCdbEngine function takes a list of options pages it can add to. +// This allows for having a "enabled" toggle on the page independently +// of the engine. That's good for not enabling the related ActiveX control +// unnecessarily. + +bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage); +bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage); + +} + + +static QString toolChainName(int toolChainType) +{ + return ToolChain::toolChainName(ToolChain::ToolChainType(toolChainType)); +} + //////////////////////////////////////////////////////////////////////// // @@ -72,11 +97,18 @@ using namespace Debugger::Internal; // //////////////////////////////////////////////////////////////////////// -namespace Debugger { +static QString msgEngineNotAvailable(const char *engine) +{ + return DebuggerPlugin::tr("The application requires the debugger engine '%1', " + "which is disabled.").arg(QLatin1String(engine)); +} + +static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); } // A factory to create DebuggerRunControls -DebuggerRunControlFactory::DebuggerRunControlFactory(DebuggerManager *manager) - : m_manager(manager) +DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent, + DebuggerEngineType enabledEngines) + : IRunControlFactory(parent), m_enabledEngines(enabledEngines) {} bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const @@ -131,12 +163,22 @@ RunControl *DebuggerRunControlFactory::create { QTC_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE, return 0); DebuggerStartParameters sp = localStartParameters(runConfiguration); - return new DebuggerRunControl(m_manager, sp); + return create(sp); } RunControl *DebuggerRunControlFactory::create(const DebuggerStartParameters &sp) { - return new DebuggerRunControl(m_manager, sp); + DebuggerRunControl *runControl = new DebuggerRunControl; + runControl->setEnabledEngines(m_enabledEngines); + runControl->createEngine(sp); + if (!runControl->engine()) { + qDebug() << "FAILED TO CREATE ENGINE"; + delete runControl; + return 0; + } + connect(runControl, SIGNAL(started()), runControl, SLOT(handleStarted())); + connect(runControl, SIGNAL(finished()), runControl, SLOT(handleFinished())); + return runControl; } QWidget *DebuggerRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration) @@ -149,340 +191,333 @@ QWidget *DebuggerRunControlFactory::createConfigurationWidget(RunConfiguration * //////////////////////////////////////////////////////////////////////// // -// DebuggerRunControl::Private +// DebuggerRunControl // //////////////////////////////////////////////////////////////////////// -class DebuggerRunControl::Private -{ -public: - Private(DebuggerRunControl *parent, DebuggerManager *manager, - const DebuggerStartParameters &startParameters); - ~Private(); - -public: - DebuggerRunControl *q; - - DebuggerStartParameters m_startParameters; - DebuggerManager *m_manager; - Internal::IDebuggerEngine *m_engine; - bool m_running; - qint64 m_inferiorPid; - - ModulesHandler *m_modulesHandler; - RegisterHandler *m_registerHandler; - SnapshotHandler *m_snapshotHandler; -/* - // FIXME: Move from DebuggerManager - BreakHandler *m_breakHandler; - StackHandler *m_stackHandler; - ThreadsHandler *m_threadsHandler; - WatchHandler *m_watchHandler; -*/ -}; - -DebuggerRunControl::Private::Private(DebuggerRunControl *parent, - DebuggerManager *manager, - const DebuggerStartParameters &startParameters) - : q(parent), - m_startParameters(startParameters), - m_manager(manager), - m_engine(0) +DebuggerRunControl::DebuggerRunControl(QObject *parent) + : RunControl(0, ProjectExplorer::Constants::DEBUGMODE) { + Q_UNUSED(parent); m_running = false; - m_inferiorPid = m_startParameters.attachPID > 0 ? m_startParameters.attachPID : 0; - m_modulesHandler = new ModulesHandler(q); - m_registerHandler = new RegisterHandler(); - m_snapshotHandler = new SnapshotHandler(q); + m_engine = 0; + m_enabledEngines = AllEngineTypes; +} + +static DebuggerEngineType engineForToolChain(int toolChainType) +{ + switch (toolChainType) { + case ProjectExplorer::ToolChain::LINUX_ICC: + case ProjectExplorer::ToolChain::MinGW: + case ProjectExplorer::ToolChain::GCC: + case ProjectExplorer::ToolChain::WINSCW: // S60 + case ProjectExplorer::ToolChain::GCCE: + case ProjectExplorer::ToolChain::RVCT_ARMV5: + case ProjectExplorer::ToolChain::RVCT_ARMV6: + case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: + case ProjectExplorer::ToolChain::GCCE_GNUPOC: + return GdbEngineType; + + case ProjectExplorer::ToolChain::MSVC: + case ProjectExplorer::ToolChain::WINCE: + return CdbEngineType; + + case ProjectExplorer::ToolChain::OTHER: + case ProjectExplorer::ToolChain::UNKNOWN: + case ProjectExplorer::ToolChain::INVALID: + default: + break; + } + return NoEngineType; } -DebuggerRunControl::Private::~Private() + +// Figure out the debugger type of an executable. Analyze executable +// unless the toolchain provides a hint. +DebuggerEngineType DebuggerRunControl::engineForExecutable(const QString &executable) { -#define doDelete(ptr) delete ptr; ptr = 0 - doDelete(m_modulesHandler); - doDelete(m_registerHandler); - doDelete(m_snapshotHandler); -#undef doDelete -} + if (executable.endsWith(_("qmlviewer"))) { + if (m_enabledEngines & QmlEngineType) + return QmlEngineType; + m_errorMessage = msgEngineNotAvailable("Qml Engine"); + } + if (executable.endsWith(_(".js"))) { + if (m_enabledEngines & ScriptEngineType) + return ScriptEngineType; + m_errorMessage = msgEngineNotAvailable("Script Engine"); + } -//////////////////////////////////////////////////////////////////////// -// -// DebuggerRunControl -// -//////////////////////////////////////////////////////////////////////// + if (executable.endsWith(_(".py"))) { + if (m_enabledEngines & PdbEngineType) + return PdbEngineType; + m_errorMessage = msgEngineNotAvailable("Pdb Engine"); + } -DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, - const DebuggerStartParameters &startParameters) - : RunControl(0, ProjectExplorer::Constants::DEBUGMODE), - d(new Private(this, manager, startParameters)) -{ - connect(d->m_manager, SIGNAL(debuggingFinished()), - this, SLOT(debuggingFinished()), - Qt::QueuedConnection); - connect(d->m_manager, SIGNAL(messageAvailable(QString, bool)), - this, SLOT(slotMessageAvailable(QString, bool))); - connect(this, SIGNAL(stopRequested()), - d->m_manager, SLOT(exitDebugger())); - - if (d->m_startParameters.environment.empty()) - d->m_startParameters.environment = ProjectExplorer::Environment().toStringList(); - d->m_startParameters.useTerminal = false; +#ifdef Q_OS_WIN + // A remote executable? + if (!executable.endsWith(_(".exe"))) + return GdbEngineType + + // If a file has PDB files, it has been compiled by VS. + QStringList pdbFiles; + if (!getPDBFiles(executable, &pdbFiles, errorMessage)) { + qWarning("Cannot determine type of executable %s: %s", + qPrintable(executable), qPrintable(m_errorMessage)); + return 0; + } + if (pdbFiles.empty()) + return GdbEngineType; -} + // We need the CDB debugger in order to be able to debug VS + // executables + if (checkDebugConfiguration(ToolChain::MSVC, errorMessage, 0, &m_settingsIdHint)) + return CdbEngineType; +#else + if (m_enabledEngines & GdbEngineType) + return GdbEngineType; + m_errorMessage = msgEngineNotAvailable("Gdb Engine"); +#endif -DebuggerRunControl::~DebuggerRunControl() -{ - delete d; + return NoEngineType; } -QString DebuggerRunControl::displayName() const +// Debugger type for mode. +DebuggerEngineType DebuggerRunControl::engineForMode(DebuggerStartMode startMode) { - return d->m_startParameters.displayName; -} + if (startMode == AttachTcf) + return TcfEngineType; -void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env) -{ - d->m_startParameters.environment = env.toStringList(); +#ifdef Q_OS_WIN + // Preferably Windows debugger for attaching locally. + if (startMode != AttachToRemote && cdbEngine) + return CdbEngineType; + if (gdbEngine) + return GdbEngineType; + m_errorMessage = msgEngineNotAvailable("Gdb Engine"); + return NoEngineType; +#else + Q_UNUSED(startMode) + // m_errorMessage = msgEngineNotAvailable("Gdb Engine"); + return GdbEngineType; +#endif } -void DebuggerRunControl::init() +void DebuggerRunControl::setEnabledEngines(DebuggerEngineType enabledEngines) { + m_enabledEngines = enabledEngines; } -void DebuggerRunControl::start() +void DebuggerRunControl::createEngine(const DebuggerStartParameters &sp) { - d->m_running = true; - QString errorMessage; - QString settingsCategory; - QString settingsPage; - if (d->m_manager->checkDebugConfiguration(d->m_startParameters.toolChainType, - &errorMessage, &settingsCategory, &settingsPage)) { - d->m_manager->startNewDebugger(this); - emit started(); - } else { - appendMessage(this, errorMessage, true); - emit finished(); - Core::ICore::instance()->showWarningWithOptions(tr("Debugger"), - errorMessage, QString(), settingsCategory, settingsPage); - } -} + // Figure out engine according to toolchain, executable, attach or default. -void DebuggerRunControl::showMessage(const QString &msg, int channel, - int timeout) -{ - if (!d->m_manager) - return; - DebuggerOutputWindow *ow = d->m_manager->debuggerOutputWindow(); - QTC_ASSERT(ow, return); - switch (channel) { - case StatusBar: - d->m_manager->showStatusMessage(msg, timeout); - ow->showOutput(LogStatus, msg); + DebuggerEngineType engineType = NoEngineType; + QString errorMessage; + QString settingsIdHint; + + if (sp.executable.endsWith(_("qmlviewer"))) + engineType = QmlEngineType; + else if (sp.executable.endsWith(_(".js"))) + engineType = ScriptEngineType; + else if (sp.executable.endsWith(_(".py"))) + engineType = PdbEngineType; + else + engineType = engineForToolChain(sp.toolChainType); + + if (engineType == NoEngineType + && sp.startMode != AttachToRemote + && !sp.executable.isEmpty()) + engineType = engineForExecutable(sp.executable); + + if (!engineType) + engineType = engineForMode(sp.startMode); + + //qDebug() << "USING ENGINE : " << engineType; + + switch (engineType) { + case GdbEngineType: + m_engine = createGdbEngine(sp); break; - case AppOutput: - emit addToOutputWindowInline(this, msg, false); + case ScriptEngineType: + m_engine = createScriptEngine(sp); break; - case AppError: - emit addToOutputWindowInline(this, msg, true); + case CdbEngineType: + m_engine = createCdbEngine(sp); break; - case LogMiscInput: - ow->showInput(LogMisc, msg); - ow->showOutput(LogMisc, msg); + case PdbEngineType: + m_engine = createPdbEngine(sp); break; - case LogInput: - ow->showInput(channel, msg); - ow->showOutput(channel, msg); + case TcfEngineType: + m_engine = createTcfEngine(sp); break; - default: - ow->showOutput(channel, msg); + case QmlEngineType: + m_engine = createQmlEngine(sp); + break; + default: { + // Could not find anything suitable. + emit debuggingFinished(); + // Create Message box with possibility to go to settings + const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3") + .arg(sp.executable, toolChainName(sp.toolChainType), m_errorMessage); + Core::ICore::instance()->showWarningWithOptions(tr("Warning"), + msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY), + m_settingsIdHint); break; + } } } -void DebuggerRunControl::slotMessageAvailable(const QString &data, bool isError) -{ - emit appendMessage(this, data, isError); -} - -void DebuggerRunControl::stop() -{ - d->m_running = false; - emit stopRequested(); -} - -void DebuggerRunControl::debuggingFinished() -{ - d->m_running = false; - emit finished(); -} - -bool DebuggerRunControl::isRunning() const -{ - return d->m_running; -} - -const DebuggerStartParameters &DebuggerRunControl::sp() const -{ - return d->m_startParameters; -} - -ModulesHandler *DebuggerRunControl::modulesHandler() const -{ - return d->m_modulesHandler; -} - -BreakHandler *DebuggerRunControl::breakHandler() const -{ - return d->m_manager->breakHandler(); -} - -RegisterHandler *DebuggerRunControl::registerHandler() const +DebuggerRunControl::~DebuggerRunControl() { - return d->m_registerHandler; + delete m_engine; } -StackHandler *DebuggerRunControl::stackHandler() const +QString DebuggerRunControl::displayName() const { - return d->m_manager->stackHandler(); + QTC_ASSERT(m_engine, return QString()); + return m_engine->startParameters().displayName; } -ThreadsHandler *DebuggerRunControl::threadsHandler() const +void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env) { - return d->m_manager->threadsHandler(); + m_engine->startParameters().environment = env.toStringList(); } -WatchHandler *DebuggerRunControl::watchHandler() const +void DebuggerRunControl::init() { - return d->m_manager->watchHandler(); } -SnapshotHandler *DebuggerRunControl::snapshotHandler() const -{ - return d->m_snapshotHandler; -} +bool DebuggerRunControl::checkDebugConfiguration(int toolChain, + QString *errorMessage, + QString *settingsCategory /* = 0 */, + QString *settingsPage /* = 0 */) +{ + errorMessage->clear(); + if (settingsCategory) + settingsCategory->clear(); + if (settingsPage) + settingsPage->clear(); + + bool success = true; + + switch(toolChain) { + case ProjectExplorer::ToolChain::GCC: + case ProjectExplorer::ToolChain::LINUX_ICC: + case ProjectExplorer::ToolChain::MinGW: + case ProjectExplorer::ToolChain::WINCE: // S60 + case ProjectExplorer::ToolChain::WINSCW: + case ProjectExplorer::ToolChain::GCCE: + case ProjectExplorer::ToolChain::RVCT_ARMV5: + case ProjectExplorer::ToolChain::RVCT_ARMV6: + success = checkGdbConfiguration(toolChain, errorMessage, settingsPage); + if (!success) + *errorMessage = msgEngineNotAvailable("Gdb"); + break; + case ProjectExplorer::ToolChain::MSVC: + success = checkCdbConfiguration(toolChain, errorMessage, settingsPage); + if (!success) { + *errorMessage = msgEngineNotAvailable("Cdb"); + if (settingsPage) + *settingsPage = QLatin1String("Cdb"); + } + break; + } + if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty()) + *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY); -void DebuggerRunControl::cleanup() -{ - modulesHandler()->removeAll(); + return success; } -Internal::IDebuggerEngine *DebuggerRunControl::engine() +void DebuggerRunControl::start() { - QTC_ASSERT(d->m_engine, /**/); - return d->m_engine; -} + QTC_ASSERT(m_engine, return); + const DebuggerStartParameters &sp = m_engine->startParameters(); -void DebuggerRunControl::startDebugger(IDebuggerEngine *engine) -{ - d->m_engine = engine; - d->m_engine->setRunControl(this); - d->m_manager->modulesWindow()->setModel(d->m_modulesHandler->model()); - d->m_manager->registerWindow()->setModel(d->m_registerHandler->model()); - d->m_manager->snapshotWindow()->setModel(d->m_snapshotHandler->model()); - d->m_engine->startDebugger(); -} + QString errorMessage; + QString settingsCategory; + QString settingsPage; + QString settingsIdHint; -void DebuggerRunControl::notifyInferiorPid(qint64 pid) -{ - //STATE_DEBUG(d->m_inferiorPid << pid); - if (d->m_inferiorPid == pid) + if (!checkDebugConfiguration(sp.toolChainType, + &errorMessage, &settingsCategory, &settingsPage)) { + emit appendMessage(this, errorMessage, true); + emit finished(); + Core::ICore::instance()->showWarningWithOptions(tr("Debugger"), + errorMessage, QString(), settingsCategory, settingsPage); return; - d->m_inferiorPid = pid; - QTimer::singleShot(0, this, SLOT(raiseApplication())); -} - -qint64 DebuggerRunControl::inferiorPid() const -{ - return d->m_inferiorPid; -} - -void DebuggerRunControl::raiseApplication() -{ - bringApplicationToForeground(d->m_inferiorPid); -} + } -////////////////////////////////////////////////////////////////////// -// -// AbstractDebuggerEngine -// -////////////////////////////////////////////////////////////////////// + plugin()->activateDebugMode(); -/* -void IDebuggerEngine::showStatusMessage(const QString &msg, int timeout) -{ - m_manager->showStatusMessage(msg, timeout); -} -*/ + showMessage(tr("Starting debugger for tool chain '%1'...") + .arg(toolChainName(sp.toolChainType)), LogStatus); + showMessage(DebuggerSettings::instance()->dump(), LogDebug); -DebuggerState IDebuggerEngine::state() const -{ - return m_manager->state(); + plugin()->setBusyCursor(false); + engine()->startDebugger(this); } -void IDebuggerEngine::setState(DebuggerState state, bool forced) +void DebuggerRunControl::startSuccessful() { - m_manager->setState(state, forced); + m_running = true; + emit started(); } -bool IDebuggerEngine::debuggerActionsEnabled() const +void DebuggerRunControl::startFailed() { - return m_manager->debuggerActionsEnabled(); + m_running = false; + emit finished(); } -void IDebuggerEngine::showModuleSymbols - (const QString &moduleName, const Symbols &symbols) +void DebuggerRunControl::handleStarted() { - QTreeWidget *w = new QTreeWidget; - w->setColumnCount(3); - w->setRootIsDecorated(false); - w->setAlternatingRowColors(true); - w->setSortingEnabled(true); - w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code")); - w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName)); - foreach (const Symbol &s, symbols) { - QTreeWidgetItem *it = new QTreeWidgetItem; - it->setData(0, Qt::DisplayRole, s.name); - it->setData(1, Qt::DisplayRole, s.address); - it->setData(2, Qt::DisplayRole, s.state); - w->addTopLevelItem(it); - } - manager()->createNewDock(w); + plugin()->runControlStarted(this); } -ModulesHandler *IDebuggerEngine::modulesHandler() const +void DebuggerRunControl::handleFinished() { - return runControl()->modulesHandler(); + plugin()->runControlFinished(this); } -BreakHandler *IDebuggerEngine::breakHandler() const +void DebuggerRunControl::showMessage(const QString &msg, int channel) { - return runControl()->breakHandler(); + switch (channel) { + case AppOutput: + emit addToOutputWindowInline(this, msg, false); + break; + case AppError: + emit addToOutputWindowInline(this, msg, true); + break; + case AppStuff: + emit appendMessage(this, msg, true); + break; + } } -RegisterHandler *IDebuggerEngine::registerHandler() const +void DebuggerRunControl::stop() { - return runControl()->registerHandler(); + m_running = false; + QTC_ASSERT(m_engine, return); + m_engine->exitDebugger(); } -StackHandler *IDebuggerEngine::stackHandler() const +void DebuggerRunControl::debuggingFinished() { - return runControl()->stackHandler(); + m_running = false; + emit finished(); } -ThreadsHandler *IDebuggerEngine::threadsHandler() const +bool DebuggerRunControl::isRunning() const { - return runControl()->threadsHandler(); + return m_running; } -WatchHandler *IDebuggerEngine::watchHandler() const +Internal::DebuggerEngine *DebuggerRunControl::engine() { - return runControl()->watchHandler(); + QTC_ASSERT(m_engine, /**/); + return m_engine; } -SnapshotHandler *IDebuggerEngine::snapshotHandler() const -{ - return runControl()->snapshotHandler(); -} } // namespace Debugger diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index cc5ab4485b5ab71c407f4c330ab767abfd05da89..432765423cfdf0491759a133e322571f2cf7ab19 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -33,11 +33,8 @@ #include "debugger_global.h" #include "debuggerconstants.h" -#include <coreplugin/ssh/sshconnection.h> #include <projectexplorer/runconfiguration.h> -#include <QtCore/QStringList> - namespace ProjectExplorer { class Environment; } @@ -45,51 +42,12 @@ class Environment; namespace Debugger { -class DebuggerManager; +class DebuggerStartParameters; namespace Internal { -class IDebuggerEngine; -class BreakHandler; -class ModulesHandler; -class RegisterHandler; -class StackHandler; -class SnapshotHandler; -class ThreadsHandler; -class WatchHandler; +class DebuggerEngine; } -class DEBUGGER_EXPORT DebuggerStartParameters -{ -public: - DebuggerStartParameters(); - void clear(); - - QString executable; - QString displayName; - QString coreFile; - QStringList processArgs; - QStringList environment; - QString workingDirectory; - qint64 attachPID; - bool useTerminal; - QString crashParameter; // for AttachCrashedExternal - // for remote debugging - QString remoteChannel; - QString remoteArchitecture; - QString symbolFileName; - QString serverStartScript; - QString sysRoot; - QString debuggerCommand; - int toolChainType; - QByteArray remoteDumperLib; - QString qtInstallPath; - - QString dumperLibrary; - QStringList dumperLibraryLocations; - Core::SshServerInfo sshserver; - DebuggerStartMode startMode; -}; - //DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &); class DEBUGGER_EXPORT DebuggerRunControlFactory @@ -98,24 +56,25 @@ class DEBUGGER_EXPORT DebuggerRunControlFactory Q_OBJECT public: - explicit DebuggerRunControlFactory(DebuggerManager *manager); + DebuggerRunControlFactory(QObject *parent, DebuggerEngineType enabledEngines); // ProjectExplorer::IRunControlFactory - bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const; - virtual ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, - const QString &mode); - virtual QString displayName() const; - - virtual QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *runConfiguration); - + bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, + const QString &mode) const; + ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration + *runConfiguration, const QString &mode); + QString displayName() const; + QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration + *runConfiguration); // This is used by the "Non-Standard" scenarios, e.g. Attach to Core. ProjectExplorer::RunControl *create(const DebuggerStartParameters &sp); private: - DebuggerManager *m_manager; + DebuggerEngineType m_enabledEngines; }; + // This is a job description containing all data "local" to the jobs, including // the models of the individual debugger views. class DEBUGGER_EXPORT DebuggerRunControl @@ -124,51 +83,48 @@ class DEBUGGER_EXPORT DebuggerRunControl Q_OBJECT public: - DebuggerRunControl(DebuggerManager *manager, - const DebuggerStartParameters &startParameters); + DebuggerRunControl(QObject *parent = 0); ~DebuggerRunControl(); - void setCustomEnvironment(ProjectExplorer::Environment env); - // ProjectExplorer::RunControl virtual void start(); virtual void stop(); virtual bool isRunning() const; QString displayName() const; - Q_SLOT void debuggingFinished(); - - const DebuggerStartParameters &sp() const; + void createEngine(const DebuggerStartParameters &startParameters); - Internal::ModulesHandler *modulesHandler() const; - Internal::BreakHandler *breakHandler() const; - Internal::RegisterHandler *registerHandler() const; - Internal::StackHandler *stackHandler() const; - Internal::ThreadsHandler *threadsHandler() const; - Internal::WatchHandler *watchHandler() const; - Internal::SnapshotHandler *snapshotHandler() const; + void setCustomEnvironment(ProjectExplorer::Environment env); + void setEnabledEngines(DebuggerEngineType enabledEngines); - void cleanup(); - void startDebugger(Internal::IDebuggerEngine *engine); - void notifyInferiorPid(qint64 pid); - qint64 inferiorPid() const; + void startFailed(); + void startSuccessful(); + void debuggingFinished(); - Internal::IDebuggerEngine *engine(); + Internal::DebuggerEngine *engine(); -signals: - void stopRequested(); + void showMessage(const QString &msg, int channel); -public slots: - void showMessage(const QString &output, int channel = LogDebug, int timeout = -1); + static bool checkDebugConfiguration(int toolChain, + QString *errorMessage, + QString *settingsCategory = 0, + QString *settingsPage = 0); private slots: - void slotMessageAvailable(const QString &data, bool isError); - void raiseApplication(); + void handleStarted(); + void handleFinished(); private: void init(); - class Private; - Private *d; + + DebuggerEngineType engineForExecutable(const QString &executable); + DebuggerEngineType engineForMode(DebuggerStartMode mode); + + Internal::DebuggerEngine *m_engine; + bool m_running; + DebuggerEngineType m_enabledEngines; + QString m_errorMessage; + QString m_settingsIdHint; }; } // namespace Debugger diff --git a/src/plugins/debugger/debuggeruiswitcher.cpp b/src/plugins/debugger/debuggeruiswitcher.cpp index a7db1101a7ac0215d623d899ee6527340d21e160..bfa3b8f6a1d012de28d98bb67e3fd28a05d3c739 100644 --- a/src/plugins/debugger/debuggeruiswitcher.cpp +++ b/src/plugins/debugger/debuggeruiswitcher.cpp @@ -153,8 +153,8 @@ DebuggerUISwitcher::~DebuggerUISwitcher() delete d; } -void DebuggerUISwitcher::addMenuAction(Core::Command *command, const QString &langName, - const QString &group) +void DebuggerUISwitcher::addMenuAction(Core::Command *command, + const QString &langName, const QString &group) { d->m_debugMenu->addAction(command, group); d->m_menuCommands.insert(d->m_languages.indexOf(langName), command); @@ -162,6 +162,9 @@ void DebuggerUISwitcher::addMenuAction(Core::Command *command, const QString &la void DebuggerUISwitcher::setActiveLanguage(const QString &langName) { + //qDebug() << "SET ACTIVE LANGUAGE: " << langName + // << theDebuggerAction(SwitchLanguageAutomatically)->isChecked() + // << d->m_languages; if (theDebuggerAction(SwitchLanguageAutomatically)->isChecked() && d->m_languages.contains(langName)) { @@ -173,6 +176,7 @@ int DebuggerUISwitcher::activeLanguageId() const { return d->m_activeLanguage; } + void DebuggerUISwitcher::modeChanged(Core::IMode *mode) { d->m_isActiveMode = (mode->id() == Debugger::Constants::MODE_DEBUG); @@ -235,6 +239,7 @@ DebuggerUISwitcher *DebuggerUISwitcher::instance() void DebuggerUISwitcher::addLanguage(const QString &langName, const QList<int> &context) { + //qDebug() << "ADD UI LANGUAGE: " << langName; d->m_toolBars.insert(langName, 0); d->m_contextsForLanguage.insert(d->m_languages.count(), context); d->m_languages.append(langName); @@ -250,7 +255,8 @@ void DebuggerUISwitcher::addLanguage(const QString &langName, const QList<int> & connect(langChange, SIGNAL(triggered()), SLOT(langChangeTriggered())); Core::Command *cmd = am->registerAction(langChange, "Debugger.Language." + langName, d->m_globalContext); - cmd->setDefaultKeySequence(QKeySequence(QString("%1,%2").arg(prefix, QString::number(d->m_languages.count())))); + cmd->setDefaultKeySequence(QKeySequence( + QString("%1,%2").arg(prefix).arg(d->m_languages.count()))); d->m_languageMenu->addAction(cmd); } @@ -264,6 +270,7 @@ void DebuggerUISwitcher::langChangeTriggered() void DebuggerUISwitcher::changeDebuggerUI(const QString &langName) { + //qDebug() << "CHANGE DEBUGGER UI: " << langName << d->m_changingUI; if (d->m_changingUI) return; d->m_changingUI = true; @@ -271,9 +278,13 @@ void DebuggerUISwitcher::changeDebuggerUI(const QString &langName) int langId = d->m_languages.indexOf(langName); if (langId != d->m_activeLanguage) { d->m_languageActionGroup->actions()[langId]->setChecked(true); - d->m_toolbarStack->setCurrentWidget(d->m_toolBars.value(langName)); + if ((d->m_toolBars.value(langName))) + d->m_toolbarStack->setCurrentWidget(d->m_toolBars.value(langName)); foreach (DebugToolWindow *window, d->m_dockWidgets) { + //qDebug() << " WINDOW " << window->m_dockWidget->objectName() + // << window->m_visible; + if (window->m_languageId != langId) { // visibleTo must be used because during init, debugger is not visible, // although visibility is explicitly set through both default layout and @@ -373,9 +384,11 @@ QWidget *DebuggerUISwitcher::createMainWindow(Core::BaseMode *mode) /*! Keep track of dock widgets so they can be shown/hidden for different languages */ -QDockWidget *DebuggerUISwitcher::createDockWidget(const QString &langName, QWidget *widget, - Qt::DockWidgetArea area, bool visibleByDefault) +QDockWidget *DebuggerUISwitcher::createDockWidget(const QString &langName, + QWidget *widget, Qt::DockWidgetArea area, bool visibleByDefault) { + //qDebug() << "CREATE DOCK" << widget->objectName() << langName + // << d->m_activeLanguage << "VISIBLE BY DEFAULT: " << visibleByDefault; QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget); d->m_mainWindow->addDockWidget(area, dockWidget); DebugToolWindow *window = new DebugToolWindow; @@ -446,20 +459,23 @@ void DebuggerUISwitcher::writeSettings() const void DebuggerUISwitcher::readSettings() { + //qDebug() << "\n SWITCHER READ SETTINGS \n"; QSettings *s = Core::ICore::instance()->settings(); s->beginGroup(QLatin1String("DebugMode")); d->m_mainWindow->restoreSettings(s); s->endGroup(); - +/* foreach(Internal::DebugToolWindow *toolWindow, d->m_dockWidgets) { toolWindow->m_visible = toolWindow->m_dockWidget->isVisibleTo(d->m_mainWindow); } +*/ } void DebuggerUISwitcher::initialize() { createViewsMenuItems(); + //qDebug() << "UI SWITCHER INITIALIZE"; emit dockArranged(QString()); readSettings(); @@ -472,6 +488,7 @@ void DebuggerUISwitcher::initialize() void DebuggerUISwitcher::resetDebuggerLayout() { + //qDebug() << "RESET DEBUGGER LAYOUT" << d->m_languages.at(d->m_activeLanguage); emit dockArranged(d->m_languages.at(d->m_activeLanguage)); } diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp index 9ec60a8a9c235c22036f24873860afccc29d00ee..a75e19bd632a22596fb7115cac38e8bc3abfb451 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp @@ -54,6 +54,7 @@ void AbstractGdbAdapter::shutdown() void AbstractGdbAdapter::startInferiorPhase2() { + qDebug() << "START INFERIOR PHASE 2"; } const char *AbstractGdbAdapter::inferiorShutdownCommand() const diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h index 4d1018cc6641eab4ac300f40eeedb8552da2e505..f1d95e18d384f08e24124d4fb353997f64631932 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.h +++ b/src/plugins/debugger/gdb/abstractgdbadapter.h @@ -50,10 +50,13 @@ class AbstractGdbAdapter : public QObject Q_OBJECT public: - enum DumperHandling { DumperNotAvailable, - DumperLoadedByAdapter, - DumperLoadedByGdbPreload, - DumperLoadedByGdb }; + enum DumperHandling + { + DumperNotAvailable, + DumperLoadedByAdapter, + DumperLoadedByGdbPreload, + DumperLoadedByGdb + }; AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0); virtual ~AbstractGdbAdapter(); @@ -107,10 +110,8 @@ protected: { m_engine->setState(state); } const DebuggerStartParameters &startParameters() const { return m_engine->startParameters(); } - DebuggerRunControl *runControl() const - { return m_engine->runControl(); } void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1) - { runControl()->showMessage(msg, channel, timeout); } + { m_engine->showMessage(msg, channel, timeout); } void showMessageBox(int icon, const QString &title, const QString &text) const { m_engine->showMessageBox(icon, title, text); } diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp index d5055633dfa74bca20e5a454276068e2b1f67fe6..a1605e3499d56ec907788ad217df141c7c26a2a1 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp @@ -47,7 +47,6 @@ AbstractPlainGdbAdapter::AbstractPlainGdbAdapter(GdbEngine *engine, { } - void AbstractPlainGdbAdapter::startInferior() { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp index 642d790d5f6d8f75de5847907d78d5ada51a7dd9..786250b7d954905dde79c6134185a228eb929cbf 100644 --- a/src/plugins/debugger/gdb/classicgdbengine.cpp +++ b/src/plugins/debugger/gdb/classicgdbengine.cpp @@ -32,6 +32,7 @@ #include "abstractgdbadapter.h" #include "debuggeractions.h" #include "debuggerstringutils.h" +#include "debuggerplugin.h" #include "stackhandler.h" #include "watchhandler.h" @@ -113,7 +114,7 @@ void GdbEngine::updateLocalsClassic(const QVariant &cookie) //PENDING_DEBUG("\nRESET PENDING"); //m_toolTipCache.clear(); m_toolTipExpression.clear(); - manager()->watchHandler()->beginCycle(); + watchHandler()->beginCycle(); QByteArray level = QByteArray::number(currentFrame()); // '2' is 'list with type and value' @@ -290,7 +291,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) qDebug() << "UPDATE SUBITEM: CUSTOMVALUE"; # endif runDebuggingHelperClassic(data, - manager()->watchHandler()->isExpandedIName(data.iname)); + watchHandler()->isExpandedIName(data.iname)); return; } @@ -356,8 +357,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) # if DEBUG_SUBITEM qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN"; # endif - runDebuggingHelperClassic(data, - manager()->watchHandler()->isExpandedIName(data.iname)); + runDebuggingHelperClassic(data, watchHandler()->isExpandedIName(data.iname)); return; } @@ -419,11 +419,11 @@ void GdbEngine::handleDebuggingHelperValue2Classic(const GdbResponse &response) setWatchDataType(data, response.data.findChild("type")); setWatchDataDisplayedType(data, response.data.findChild("displaytype")); QList<WatchData> list; - parseWatchData(manager()->watchHandler()->expandedINames(), + parseWatchData(watchHandler()->expandedINames(), data, contents, &list); //for (int i = 0; i != list.size(); ++i) // qDebug() << "READ: " << list.at(i).toString(); - manager()->watchHandler()->insertBulkData(list); + watchHandler()->insertBulkData(list); } void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response) @@ -514,11 +514,11 @@ void GdbEngine::tryLoadDebuggingHelpersClassic() m_debuggingHelperState = DebuggingHelperLoadTried; QByteArray dlopenLib; - if (runControl()->sp().startMode == AttachToRemote - || runControl()->sp().startMode == StartRemoteGdb) - dlopenLib = runControl()->sp().remoteDumperLib; + const DebuggerStartMode startMode = startParameters().startMode; + if (startMode == AttachToRemote || startMode == StartRemoteGdb) + dlopenLib = startParameters().remoteDumperLib; else - dlopenLib = manager()->qtDumperLibraryName().toLocal8Bit(); + dlopenLib = qtDumperLibraryName().toLocal8Bit(); // Do not use STRINGIFY for RTLD_NOW as we really want to expand that to a number. #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) @@ -580,10 +580,10 @@ void GdbEngine::updateAllClassic() postCommand("-stack-list-frames", WatchUpdate, CB(handleStackListFrames), QVariant::fromValue<StackCookie>(StackCookie(false, true))); - manager()->stackHandler()->setCurrentIndex(0); + stackHandler()->setCurrentIndex(0); if (supportsThreads()) postCommand("-thread-list-ids", WatchUpdate, CB(handleThreadListIds), 0); - manager()->reloadRegisters(); + reloadRegisters(); updateLocals(); } @@ -593,7 +593,7 @@ void GdbEngine::setDebugDebuggingHelpersClassic(const QVariant &on) if (on.toBool()) { showMessage(_("SWITCHING ON DUMPER DEBUGGING")); postCommand("set unwindonsignal off"); - m_manager->breakByFunction(_("qDumpObjectData440")); + breakByFunction(_("qDumpObjectData440")); //updateLocals(); } else { showMessage(_("SWITCHING OFF DUMPER DEBUGGING")); @@ -660,11 +660,12 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response) // is not known at this point. QStringList uninitializedVariables; if (theDebuggerAction(UseCodeModel)->isChecked()) { - const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ? - qVariantValue<Debugger::Internal::StackFrame>(response.cookie) : - m_manager->stackHandler()->currentFrame(); + const StackFrame frame = + qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) + ? qVariantValue<Debugger::Internal::StackFrame>(response.cookie) + : stackHandler()->currentFrame(); if (frame.isUsable()) - getUninitializedVariables(m_manager->cppCodeModelSnapshot(), + getUninitializedVariables(plugin()->cppCodeModelSnapshot(), frame.function, frame.file, frame.line, &uninitializedVariables); } @@ -683,23 +684,23 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response) list.append(rd); } - manager()->watchHandler()->insertBulkData(list); - manager()->watchHandler()->updateWatchers(); + watchHandler()->insertBulkData(list); + watchHandler()->updateWatchers(); } bool GdbEngine::checkDebuggingHelpersClassic() { PRECONDITION; - if (!manager()->qtDumperLibraryEnabled()) + if (!qtDumperLibraryEnabled()) return false; const QString lib = qtDumperLibraryName(); const QFileInfo fi(lib); if (!fi.exists()) { - const QStringList &locations = manager()->qtDumperLibraryLocations(); + const QStringList &locations = qtDumperLibraryLocations(); const QString loc = locations.join(QLatin1String(", ")); const QString msg = tr("The debugging helper library was not found at %1.").arg(loc); showMessage(msg); - manager()->showQtDumperLibraryWarning(msg); + showQtDumperLibraryWarning(msg); return false; } return true; @@ -719,7 +720,7 @@ void GdbEngine::handleQueryDebuggingHelperClassic(const GdbResponse &response) // currently causes errors. const double dumperVersion = getDumperVersion(contents); if (dumperVersion < dumperVersionRequired) { - manager()->showQtDumperLibraryWarning( + showQtDumperLibraryWarning( QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion)); m_debuggingHelperState = DebuggingHelperUnavailable; return; @@ -750,7 +751,7 @@ void GdbEngine::handleDebuggingHelperVersionCheckClassic(const GdbResponse &resp QString debuggeeQtVersion = value.section(QLatin1Char('"'), 1, 1); QString dumperQtVersion = m_dumperHelper.qtVersionString(); if (dumperQtVersion != debuggeeQtVersion) { - manager()->showMessageBox(QMessageBox::Warning, + showMessageBox(QMessageBox::Warning, tr("Debugging helpers: Qt version mismatch"), tr("The Qt version used to build the debugging helpers (%1) " "does not match the Qt version used to build the debugged " @@ -821,7 +822,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item, setWatchDataValue(data, item); setWatchDataAddress(data, item.findChild("addr")); setWatchDataChildCount(data, item.findChild("numchild")); - if (!manager()->watchHandler()->isExpandedIName(data.iname)) + if (!watchHandler()->isExpandedIName(data.iname)) data.setChildrenUnneeded(); data.name = _(exp); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index e301d96c31339f32450a94d57ca42f752f6ad6b5..e8c967ef969a7e899175eb077533473aa2e62ed7 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -30,9 +30,11 @@ #define QT_NO_CAST_FROM_ASCII #include "gdbengine.h" + #include "gdboptionspage.h" #include "debuggeruiswitcher.h" #include "debuggermainwindow.h" +#include "debuggerplugin.h" #include "attachgdbadapter.h" #include "coregdbadapter.h" @@ -46,7 +48,6 @@ #include "debuggeractions.h" #include "debuggeragents.h" #include "debuggerconstants.h" -#include "debuggermanager.h" #include "debuggertooltip.h" #include "debuggerstringutils.h" #include "gdbmi.h" @@ -55,6 +56,7 @@ #include "moduleshandler.h" #include "registerhandler.h" #include "snapshothandler.h" +#include "sourcefileshandler.h" #include "stackhandler.h" #include "threadshandler.h" #include "watchhandler.h" @@ -172,9 +174,8 @@ static QByteArray parsePlainConsoleStream(const GdbResponse &response) // /////////////////////////////////////////////////////////////////////// -GdbEngine::GdbEngine(DebuggerManager *manager) : - IDebuggerEngine(manager), - m_gdbBinaryToolChainMap(DebuggerSettings::instance()->gdbBinaryToolChainMap()) +GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters) + : DebuggerEngine(startParameters) { m_gdbAdapter = 0; m_progress = 0; @@ -185,6 +186,7 @@ GdbEngine::GdbEngine(DebuggerManager *manager) : // Needs no resetting in initializeVariables() m_busy = false; + initializeVariables(); connect(theDebuggerAction(AutoDerefPointers), SIGNAL(valueChanged(QVariant)), this, SLOT(setAutoDerefPointers(QVariant))); @@ -211,7 +213,6 @@ void GdbEngine::disconnectDebuggingHelperActions() DebuggerStartMode GdbEngine::startMode() const { - QTC_ASSERT(m_runControl, return NoStartMode); return startParameters().startMode; } @@ -337,8 +338,9 @@ static void dump(const char *first, const char *middle, const QString & to) void GdbEngine::readDebugeeOutput(const QByteArray &data) { - m_manager->messageAvailable(m_outputCodec->toUnicode( - data.constData(), data.length(), &m_outputCodecState), true); + QString msg = m_outputCodec->toUnicode(data.constData(), data.length(), + &m_outputCodecState); + showMessage(msg, AppStuff); } void GdbEngine::handleResponse(const QByteArray &buff) @@ -449,7 +451,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) QByteArray id = result.findChild("id").data(); showStatusMessage(tr("Thread group %1 created").arg(_(id)), 1000); const int pid = id.toInt(); - runControl()->notifyInferiorPid(pid); + notifyInferiorPid(pid); } else if (asyncClass == "thread-created") { //"{id="1",group-id="28902"}" QByteArray id = result.findChild("id").data(); @@ -502,7 +504,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) m_pendingConsoleStreamOutput += data; // Parse pid from noise. - if (!runControl()->inferiorPid()) { + if (!inferiorPid()) { // Linux/Mac gdb: [New [Tt]hread 0x545 (LWP 4554)] static QRegExp re1(_("New .hread 0x[0-9a-f]+ \\(LWP ([0-9]*)\\)")); // MinGW 6.8: [New thread 2437.0x435345] @@ -542,7 +544,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) // On Windows, the contents seem to depend on the debugger // version and/or OS version used. if (data.startsWith("warning:")) - manager()->messageAvailable(_(data.mid(9)), true); // cut "warning: " + showMessage(_(data.mid(9)), AppStuff); // cut "warning: " break; } @@ -564,7 +566,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) m_progress->reportFinished(); } if (state() == InferiorStopped) { // Result of manual command. - m_manager->resetLocation(); + resetLocation(); setTokenBarrier(); setState(InferiorRunningRequested); } @@ -678,11 +680,12 @@ void GdbEngine::interruptInferior() void GdbEngine::interruptInferiorTemporarily() { interruptInferior(); - foreach (const GdbCommand &cmd, m_commandsToRunOnTemporaryBreak) + foreach (const GdbCommand &cmd, m_commandsToRunOnTemporaryBreak) { if (cmd.flags & LosesChild) { setState(InferiorStopping_Kill); break; } + } } void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) @@ -692,11 +695,11 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) showMessage(_("Cannot parse PID from %1").arg(pid0)); return; } - if (pid == runControl()->inferiorPid()) + if (pid == inferiorPid()) return; - showMessage(_("FOUND PID %1").arg(pid)); - runControl()->notifyInferiorPid(pid); + showMessage(_("FOUND PID %1").arg(pid)); + notifyInferiorPid(pid); } void GdbEngine::postCommand(const QByteArray &command, AdapterCallback callback, @@ -970,7 +973,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response) GdbResultDone)) { #ifdef Q_OS_WIN // Ignore spurious 'running' responses to 'attach' - const bool warning = !(runControl()->sp().startMode == AttachExternal + const bool warning = !(startParameters().startMode == AttachExternal && cmd.command.startsWith("attach")); #else const bool warning = true; @@ -1079,7 +1082,7 @@ void GdbEngine::handleQuerySources(const GdbResponse &response) } } if (m_shortToFullName != oldShortToFull) - manager()->sourceFileWindow()->setSourceFiles(m_shortToFullName); + sourceFilesHandler()->setSourceFiles(m_shortToFullName); } } @@ -1275,7 +1278,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) // Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports everything. // The case of the user really setting a breakpoint at _start is simply // unsupported. - if (!runControl()->inferiorPid()) // For programs without -pthread under gdb <= 6.8. + if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8. postCommand("info proc", CB(handleInfoProc)); continueInferiorInternal(); return; @@ -1313,13 +1316,13 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (isLeavableFunction(funcName, fileName)) { //showMessage(_("LEAVING ") + funcName); ++stepCounter; - m_manager->executeStepOut(); + executeStepOutX(); return; } if (isSkippableFunction(funcName, fileName)) { //showMessage(_("SKIPPING ") + funcName); ++stepCounter; - m_manager->executeStep(); + executeStepX(); return; } //if (stepCounter) @@ -1349,7 +1352,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) && reason == "signal-received") { QByteArray name = data.findChild("signal-name").data(); if (name != STOP_SIGNAL - && (runControl()->sp().startMode != AttachToRemote + && (startParameters().startMode != AttachToRemote || name != CROSS_STOP_SIGNAL)) initHelpers = false; } @@ -1427,7 +1430,7 @@ void GdbEngine::handleStop1(const GdbMi &data) // Ignore these as they are showing up regularly when // stopping debugging. if (name != STOP_SIGNAL - && (runControl()->sp().startMode != AttachToRemote + && (startParameters().startMode != AttachToRemote || name != CROSS_STOP_SIGNAL)) { QString msg = tr("<p>The inferior stopped because it received a " "signal from the Operating System.<p>" @@ -1484,7 +1487,7 @@ void GdbEngine::handleStop1(const GdbMi &data) // // Registers // - manager()->reloadRegisters(); + reloadRegisters(); } void GdbEngine::handleInfoProc(const GdbResponse &response) @@ -1529,9 +1532,9 @@ void GdbEngine::handleHasPython(const GdbResponse &response) QByteArray cmd = "set environment "; cmd += Debugger::Constants::Internal::LD_PRELOAD_ENV_VAR; cmd += ' '; - cmd += runControl()->sp().startMode == StartRemoteGdb - ? runControl()->sp().remoteDumperLib - : cmd += manager()->qtDumperLibraryName().toLocal8Bit(); + cmd += startParameters().startMode == StartRemoteGdb + ? startParameters().remoteDumperLib + : cmd += qtDumperLibraryName().toLocal8Bit(); postCommand(cmd); m_debuggingHelperState = DebuggingHelperLoadTried; } @@ -1695,13 +1698,13 @@ void GdbEngine::detachDebugger() shutdown(); } -void GdbEngine::exitDebugger() // called from the manager +void GdbEngine::exitDebugger() { disconnectDebuggingHelperActions(); shutdown(); } -void GdbEngine::abortDebugger() // called from the manager +void GdbEngine::abortDebugger() { disconnectDebuggingHelperActions(); shutdown(); @@ -1720,61 +1723,54 @@ static inline QString msgNoBinaryForToolChain(int tc) return GdbEngine::tr("There is no gdb binary available for '%1'").arg(toolChainName); } -bool GdbEngine::checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage) const +static QString gdbBinaryForToolChain(int toolChain) { - if (m_gdbBinaryToolChainMap->key(toolChain).isEmpty()) { - *errorMessage = msgNoBinaryForToolChain(toolChain); - *settingsPage = GdbOptionsPage::settingsId(); - return false; - } - return true; + return DebuggerSettings::instance()->gdbBinaryToolChainMap().key(toolChain); } AbstractGdbAdapter *GdbEngine::createAdapter() { - QTC_ASSERT(runControl(), return 0); - const DebuggerStartParameters &sp = runControl()->sp(); + const DebuggerStartParameters &sp = startParameters(); + //qDebug() << "CREATE ADAPTER: " << sp.toolChainType; switch (sp.toolChainType) { - case ProjectExplorer::ToolChain::WINSCW: // S60 - case ProjectExplorer::ToolChain::GCCE: - case ProjectExplorer::ToolChain::RVCT_ARMV5: - case ProjectExplorer::ToolChain::RVCT_ARMV6: - case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain::GCCE_GNUPOC: - return new TrkGdbAdapter(this); - default: - break; + case ProjectExplorer::ToolChain::WINSCW: // S60 + case ProjectExplorer::ToolChain::GCCE: + case ProjectExplorer::ToolChain::RVCT_ARMV5: + case ProjectExplorer::ToolChain::RVCT_ARMV6: + case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: + case ProjectExplorer::ToolChain::GCCE_GNUPOC: + return new TrkGdbAdapter(this); + default: + break; } + // @todo: remove testing hack if (sp.processArgs.size() == 3 && sp.processArgs.at(0) == _("@sym@")) return new TrkGdbAdapter(this); + switch (sp.startMode) { - case AttachCore: - return new CoreGdbAdapter(this); - case AttachToRemote: - return new RemoteGdbServerAdapter(this, sp.toolChainType); - case StartRemoteGdb: - return new RemotePlainGdbAdapter(this); - case AttachExternal: - return new AttachGdbAdapter(this); - default: - if (sp.useTerminal) - return new TermGdbAdapter(this); - return new LocalPlainGdbAdapter(this); + case AttachCore: + return new CoreGdbAdapter(this); + case AttachToRemote: + return new RemoteGdbServerAdapter(this, sp.toolChainType); + case StartRemoteGdb: + return new RemotePlainGdbAdapter(this); + case AttachExternal: + return new AttachGdbAdapter(this); + default: + if (sp.useTerminal) + return new TermGdbAdapter(this); + return new LocalPlainGdbAdapter(this); } } void GdbEngine::startDebugger() { - QTC_ASSERT(runControl(), return); - QTC_ASSERT(state() == EngineStarting, qDebug() << state()); - // This should be set by the constructor or in exitDebugger() - // via initializeVariables() - //QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, - // initializeVariables()); - //QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0); - - initializeVariables(); + //qDebug() << "GDB START DEBUGGER"; + QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady)); + setState(EngineStarting); + QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/); + QTC_ASSERT(m_gdbAdapter == 0, /**/); m_progress = new QFutureInterface<void>(); m_progress->setProgressRange(0, 100); @@ -1783,14 +1779,15 @@ void GdbEngine::startDebugger() fp->setKeepOnFinish(false); m_progress->reportStarted(); - delete m_gdbAdapter; m_gdbAdapter = createAdapter(); + //qDebug() << "CREATED ADAPTER: " << m_gdbAdapter; connectAdapter(); if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) connectDebuggingHelperActions(); m_progress->setProgressValue(20); + QTC_ASSERT(state() == EngineStarting, /**/); m_gdbAdapter->startAdapter(); } @@ -1823,7 +1820,7 @@ void GdbEngine::autoContinueInferior() void GdbEngine::continueInferior() { - m_manager->resetLocation(); + resetLocation(); setTokenBarrier(); continueInferiorInternal(); showStatusMessage(tr("Running requested..."), 5000); @@ -1837,7 +1834,7 @@ void GdbEngine::executeStep() showStatusMessage(tr("Step requested..."), 5000); if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0) postCommand("sal step," + stackHandler()->topAddress().toLatin1()); - if (manager()->isReverseDebugging()) + if (isReverseDebugging()) postCommand("reverse-step", RunRequest, CB(handleExecuteStep)); else postCommand("-exec-step", RunRequest, CB(handleExecuteStep)); @@ -1876,7 +1873,7 @@ void GdbEngine::executeStepI() setTokenBarrier(); setState(InferiorRunningRequested); showStatusMessage(tr("Step by instruction requested..."), 5000); - if (manager()->isReverseDebugging()) + if (isReverseDebugging()) postCommand("reverse-stepi", RunRequest, CB(handleExecuteContinue)); else postCommand("-exec-step-instruction", RunRequest, CB(handleExecuteContinue)); @@ -1900,7 +1897,7 @@ void GdbEngine::executeNext() showStatusMessage(tr("Step next requested..."), 5000); if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0) postCommand("sal next," + stackHandler()->topAddress().toLatin1()); - if (manager()->isReverseDebugging()) + if (isReverseDebugging()) postCommand("reverse-next", RunRequest, CB(handleExecuteNext)); else postCommand("-exec-next", RunRequest, CB(handleExecuteNext)); @@ -1938,7 +1935,7 @@ void GdbEngine::executeNextI() setTokenBarrier(); setState(InferiorRunningRequested); showStatusMessage(tr("Step next instruction requested..."), 5000); - if (manager()->isReverseDebugging()) + if (isReverseDebugging()) postCommand("reverse-nexti", RunRequest, CB(handleExecuteContinue)); else postCommand("-exec-next-instruction", RunRequest, CB(handleExecuteContinue)); @@ -2283,7 +2280,7 @@ void GdbEngine::handleBreakList(const GdbMi &table) foreach (const GdbMi &bkpt, bkpts) { BreakpointData temp; setBreakpointDataFromOutput(&temp, bkpt); - BreakpointData *data = breakHandler()->findSimilarBreakpoint(temp); + BreakpointData *data = breakHandler()->findSimilarBreakpoint(&temp); //qDebug() << "\n\nGOT: " << bkpt.toString() << '\n' << temp.toString(); if (data) { //qDebug() << " FROM: " << data->toString(); @@ -2698,7 +2695,7 @@ void GdbEngine::handleModulesList(const GdbResponse &response) } } } - runControl()->modulesHandler()->setModules(modules); + modulesHandler()->setModules(modules); } @@ -2743,7 +2740,7 @@ void GdbEngine::reloadSourceFilesInternal() void GdbEngine::selectThread(int index) { threadsHandler()->setCurrentThread(index); - QList<ThreadData> threads = threadsHandler()->threads(); + Threads threads = threadsHandler()->threads(); QTC_ASSERT(index < threads.size(), return); int id = threads.at(index).id; showStatusMessage(tr("Retrieving data for stack view..."), 10000); @@ -2755,7 +2752,7 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &) QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/); //qDebug("FIXME: StackHandler::handleOutput: SelectThread"); showStatusMessage(tr("Retrieving data for stack view..."), 3000); - manager()->reloadRegisters(); + reloadRegisters(); reloadStack(true); updateLocals(); } @@ -2889,7 +2886,7 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response) void GdbEngine::activateFrame(int frameIndex) { - m_manager->resetLocation(); + resetLocation(); if (state() != InferiorStopped && state() != InferiorUnrunnable) return; @@ -2930,7 +2927,7 @@ void GdbEngine::handleThreadInfo(const GdbResponse &response) // file="/.../app.cpp",fullname="/../app.cpp",line="1175"}, // state="stopped",core="0"}],current-thread-id="1" const QList<GdbMi> items = response.data.findChild("threads").children(); - QList<ThreadData> threads; + Threads threads; for (int index = 0, n = items.size(); index != n; ++index) { bool ok = false; const GdbMi item = items.at(index); @@ -2962,7 +2959,7 @@ void GdbEngine::handleThreadListIds(const GdbResponse &response) // "72^done,{thread-ids={thread-id="2",thread-id="1"},number-of-threads="2"} // In gdb 7.1+ additionally: current-thread-id="1" const QList<GdbMi> items = response.data.findChild("thread-ids").children(); - QList<ThreadData> threads; + Threads threads; int currentIndex = -1; for (int index = 0, n = items.size(); index != n; ++index) { ThreadData thread; @@ -3017,10 +3014,10 @@ void GdbEngine::handleMakeSnapshot(const GdbResponse &response) void GdbEngine::activateSnapshot(int index) { - QTC_ASSERT(runControl(), return); SnapshotData snapshot = snapshotHandler()->setCurrentIndex(index); - DebuggerStartParameters &sp = const_cast<DebuggerStartParameters &>(runControl()->sp()); + DebuggerStartParameters &sp = + const_cast<DebuggerStartParameters &>(startParameters()); sp.startMode = AttachCore; sp.coreFile = snapshot.location(); @@ -3096,7 +3093,7 @@ void GdbEngine::reloadRegisters() void GdbEngine::setRegisterValue(int nr, const QString &value) { - Register reg = runControl()->registerHandler()->registers().at(nr); + Register reg = registerHandler()->registers().at(nr); //qDebug() << "NOT IMPLEMENTED: CHANGE REGISTER " << nr << reg.name << ":" // << value; postCommand("-var-delete \"R@\""); @@ -3119,7 +3116,7 @@ void GdbEngine::handleRegisterListNames(const GdbResponse &response) foreach (const GdbMi &item, response.data.findChild("register-names").children()) registers.append(Register(item.data())); - runControl()->registerHandler()->setRegisters(registers); + registerHandler()->setRegisters(registers); if (m_gdbAdapter->isTrkAdapter()) m_gdbAdapter->trkReloadRegisters(); @@ -3130,7 +3127,7 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response) if (response.resultClass != GdbResultDone) return; - Registers registers = runControl()->registerHandler()->registers(); + Registers registers = registerHandler()->registers(); // 24^done,register-values=[{number="0",value="0xf423f"},...] const GdbMi values = response.data.findChild("register-values"); @@ -3167,7 +3164,7 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response) reg.value = value; } } - runControl()->registerHandler()->setRegisters(registers); + registerHandler()->setRegisters(registers); } @@ -3463,7 +3460,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response) if (response.resultClass == GdbResultDone) { data.variable = data.iname; setWatchDataType(data, response.data.findChild("type")); - if (runControl()->watchHandler()->isExpandedIName(data.iname) + if (watchHandler()->isExpandedIName(data.iname) && !response.data.findChild("children").isValid()) data.setChildrenNeeded(); else @@ -3592,7 +3589,7 @@ void GdbEngine::insertData(const WatchData &data0) qDebug() << "BOGUS VALUE:" << data.toString(); return; } - runControl()->watchHandler()->insertData(data); + watchHandler()->insertData(data); } void GdbEngine::assignValueInDebugger(const QString &expression, const QString &value) @@ -3603,11 +3600,6 @@ void GdbEngine::assignValueInDebugger(const QString &expression, const QString & Discardable, CB(handleVarAssign)); } -QString GdbEngine::qtDumperLibraryName() const -{ - return m_manager->qtDumperLibraryName(); -} - void GdbEngine::watchPoint(const QPoint &pnt) { //qDebug() << "WATCH " << pnt; @@ -3970,12 +3962,6 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response) } } -void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker) -{ - // qDebug() << "GOTO " << frame << setMarker; - m_manager->gotoLocation(frame, setMarker); -} - // // Starting up & shutting down // @@ -3984,14 +3970,15 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr { gdbProc()->disconnect(); // From any previous runs - m_gdb = QString::fromLatin1(qgetenv("QTC_DEBUGGER_PATH")); + m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); if (m_gdb.isEmpty()) - m_gdb = m_gdbBinaryToolChainMap->key(m_runControl->sp().toolChainType); + m_gdb = gdbBinaryForToolChain(startParameters().toolChainType); if (m_gdb.isEmpty()) m_gdb = gdb; if (m_gdb.isEmpty()) { - handleAdapterStartFailed(msgNoBinaryForToolChain(m_runControl->sp().toolChainType), - GdbOptionsPage::settingsId()); + handleAdapterStartFailed( + msgNoBinaryForToolChain(startParameters().toolChainType), + GdbOptionsPage::settingsId()); return false; } showMessage(_("STARTING GDB ") + m_gdb); @@ -4224,7 +4211,8 @@ void GdbEngine::handleAdapterStarted() void GdbEngine::handleInferiorPrepared() { - const QByteArray qtInstallPath = m_runControl->sp().qtInstallPath.toLocal8Bit(); + startSuccessful(); + const QByteArray qtInstallPath = startParameters().qtInstallPath.toLocal8Bit(); if (!qtInstallPath.isEmpty()) { QByteArray qtBuildPath; #if defined(Q_OS_WIN) @@ -4288,15 +4276,10 @@ void GdbEngine::handleAdapterCrashed(const QString &msg) showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); } -void GdbEngine::addOptionPages(QList<Core::IOptionsPage *> *opts) const -{ - opts->push_back(new GdbOptionsPage(m_gdbBinaryToolChainMap)); -} - QMessageBox *GdbEngine::showMessageBox(int icon, const QString &title, const QString &text, int buttons) { - return m_manager->showMessageBox(icon, title, text, buttons); + return plugin()->showMessageBox(icon, title, text, buttons); } void GdbEngine::setUseDebuggingHelpers(const QVariant &on) @@ -4320,7 +4303,7 @@ void GdbEngine::createFullBacktrace() void GdbEngine::handleCreateFullBacktrace(const GdbResponse &response) { if (response.resultClass == GdbResultDone) { - m_manager->openTextEditor(_("Backtrace $"), + plugin()->openTextEditor(_("Backtrace $"), _(response.data.findChild("consolestreamoutput").data())); } } @@ -4330,9 +4313,24 @@ void GdbEngine::handleCreateFullBacktrace(const GdbResponse &response) // Factory // -IDebuggerEngine *createGdbEngine(DebuggerManager *manager) +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); +} + +void addGdbOptionPages(QList<Core::IOptionsPage *> *opts) { - return new GdbEngine(manager); + opts->push_back(new GdbOptionsPage()); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index d69ee0c9e0d346c71e9f8b1e20cc39bfc09f3a48..c8f610776291517f2411adeebac1232e7fbe101b 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -30,8 +30,7 @@ #ifndef DEBUGGER_GDBENGINE_H #define DEBUGGER_GDBENGINE_H -#include "idebuggerengine.h" -#include "debuggermanager.h" // only for StartParameters +#include "debuggerengine.h" #include "gdbmi.h" #include "localgdbprocess.h" #include "watchutils.h" @@ -56,7 +55,6 @@ class QTimer; QT_END_NAMESPACE namespace Debugger { -class DebuggerManager; namespace Internal { class AbstractGdbAdapter; @@ -83,15 +81,12 @@ enum DebuggingHelperState }; -class GdbEngine : public IDebuggerEngine +class GdbEngine : public DebuggerEngine { Q_OBJECT public: - typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - typedef QSharedPointer<GdbBinaryToolChainMap> GdbBinaryToolChainMapPtr; - - explicit GdbEngine(DebuggerManager *manager); + explicit GdbEngine(const DebuggerStartParameters &startParameters); ~GdbEngine(); private: @@ -107,10 +102,6 @@ private: private: ////////// General Interface ////////// - virtual void addOptionPages(QList<Core::IOptionsPage*> *opts) const; - - virtual bool checkConfiguration(int toolChain, QString *errorMessage, - QString *settingsPage = 0) const; virtual void startDebugger(); virtual unsigned debuggerCapabilities() const; virtual void exitDebugger(); @@ -125,8 +116,6 @@ private: ////////// General State ////////// void initializeVariables(); DebuggerStartMode startMode() const; - const DebuggerStartParameters &startParameters() const - { return m_runControl->sp(); } Q_SLOT void setAutoDerefPointers(const QVariant &on); bool m_registerNamesListed; @@ -332,8 +321,6 @@ private: ////////// View & Data Stuff ////////// virtual void selectThread(int index); virtual void activateFrame(int index); - void gotoLocation(const StackFrame &frame, bool setLocationMarker); - // // Breakpoint specific stuff // @@ -502,8 +489,9 @@ private: ////////// View & Data Stuff ////////// QSet<QByteArray> m_processedNames; -private: ////////// Dumper Management ////////// - QString qtDumperLibraryName() const; + // + // Dumper Management + // bool checkDebuggingHelpers(); bool checkDebuggingHelpersClassic(); void setDebuggingHelperStateClassic(DebuggingHelperState); @@ -515,13 +503,13 @@ private: ////////// Dumper Management ////////// Q_SLOT void setDebugDebuggingHelpersClassic(const QVariant &on); Q_SLOT void setUseDebuggingHelpers(const QVariant &on); - const GdbBinaryToolChainMapPtr m_gdbBinaryToolChainMap; DebuggingHelperState m_debuggingHelperState; QtDumperHelper m_dumperHelper; QString m_gdb; -private: ////////// Convenience Functions ////////// - + // + // Convenience Functions + // QString errorMessage(QProcess::ProcessError error); QMessageBox *showMessageBox(int icon, const QString &title, const QString &text, int buttons = 0); diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 2eca0a4f7d3cce3cf55b8d157a581cbd882bc3e5..20a58edf45c83948560924a799a9bcd1760ab0b3 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -38,8 +38,7 @@ namespace Debugger { namespace Internal { -GdbOptionsPage::GdbOptionsPage(const GdbBinaryToolChainMapPtr &binaryToolChainMap) : - m_binaryToolChainMap(binaryToolChainMap) +GdbOptionsPage::GdbOptionsPage() { } @@ -72,7 +71,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) { QWidget *w = new QWidget(parent); m_ui.setupUi(w); - m_ui.gdbChooserWidget->setGdbBinaries(*m_binaryToolChainMap); + m_ui.gdbChooserWidget + ->setGdbBinaries(DebuggerSettings::instance()->gdbBinaryToolChainMap()); m_ui.scriptFileChooser->setExpectedKind(Utils::PathChooser::File); m_ui.scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File")); @@ -131,7 +131,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) void GdbOptionsPage::apply() { m_group.apply(Core::ICore::instance()->settings()); - *m_binaryToolChainMap = m_ui.gdbChooserWidget->gdbBinaries(); + DebuggerSettings::instance() + ->setGdbBinaryToolChainMap(m_ui.gdbChooserWidget->gdbBinaries()); } void GdbOptionsPage::finish() diff --git a/src/plugins/debugger/gdb/gdboptionspage.h b/src/plugins/debugger/gdb/gdboptionspage.h index 5e67016de7d516b0d7c08e03116e475ea13ba396..ec24089ded0f98d6d93d9ef54ea5982712b4e43a 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.h +++ b/src/plugins/debugger/gdb/gdboptionspage.h @@ -35,8 +35,6 @@ #include <coreplugin/dialogs/ioptionspage.h> #include <utils/savedaction.h> -#include <QtCore/QSharedPointer> -#include <QtCore/QMultiMap> namespace Debugger { namespace Internal { @@ -45,10 +43,7 @@ class GdbOptionsPage : public Core::IOptionsPage { Q_OBJECT public: - typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - typedef QSharedPointer<GdbBinaryToolChainMap> GdbBinaryToolChainMapPtr; - - explicit GdbOptionsPage(const GdbBinaryToolChainMapPtr &binaryToolChainMap); + explicit GdbOptionsPage(); virtual QString id() const { return settingsId(); } virtual QString displayName() const; @@ -64,8 +59,6 @@ public: static QString settingsId(); private: - const GdbBinaryToolChainMapPtr m_binaryToolChainMap; - Ui::GdbOptionsPage m_ui; Utils::SavedActionSet m_group; QString m_searchKeywords; diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp index 7677e1bfc6bb128d1c8b15aa2ffdcde81b6c3379..225a8c3b03c2c4906bdd3a2fb588dcebd21d0f4d 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp @@ -123,7 +123,7 @@ void LocalPlainGdbAdapter::checkForReleaseBuild() void LocalPlainGdbAdapter::interruptInferior() { - const qint64 attachedPID = runControl()->inferiorPid(); + const qint64 attachedPID = m_engine->inferiorPid(); if (attachedPID <= 0) { showMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED")); return; diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 59220c20293dff5ee33147c7adb91a28018e852c..a2d45dd178e30cb90bb3b684fd78708a8443adbc 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -51,9 +51,9 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList) PRECONDITION; m_processedNames.clear(); - manager()->watchHandler()->beginCycle(); + watchHandler()->beginCycle(); //m_toolTipExpression.clear(); - WatchHandler *handler = m_manager->watchHandler(); + WatchHandler *handler = watchHandler(); QByteArray expanded = "expanded:" + handler->expansionRequests() + ' '; expanded += "typeformats:" + handler->typeFormatRequests() + ' '; @@ -130,22 +130,21 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) GdbMi data = all.findChild("data"); QList<WatchData> list; - WatchHandler *watchHandler = manager()->watchHandler(); foreach (const GdbMi &child, data.children()) { WatchData dummy; dummy.iname = child.findChild("iname").data(); dummy.name = _(child.findChild("name").data()); //qDebug() << "CHILD: " << child.toString(); - parseWatchData(watchHandler->expandedINames(), dummy, child, &list); + parseWatchData(watchHandler()->expandedINames(), dummy, child, &list); } - watchHandler->insertBulkData(list); + watchHandler()->insertBulkData(list); //for (int i = 0; i != list.size(); ++i) // qDebug() << "LOCAL: " << list.at(i).toString(); #if 0 data = all.findChild("bkpts"); if (data.isValid()) { - BreakHandler *handler = manager()->breakHandler(); + BreakHandler *handler = breakHandler(); foreach (const GdbMi &child, data.children()) { int bpNumber = child.findChild("number").data().toInt(); int found = handler->findBreakpoint(bpNumber); @@ -199,12 +198,12 @@ void GdbEngine::updateAllPython() reloadModulesInternal(); postCommand("-stack-list-frames", CB(handleStackListFrames), QVariant::fromValue<StackCookie>(StackCookie(false, true))); - manager()->stackHandler()->setCurrentIndex(0); + stackHandler()->setCurrentIndex(0); if (m_gdbAdapter->isTrkAdapter()) m_gdbAdapter->trkReloadThreads(); else postCommand("-thread-list-ids", CB(handleThreadListIds), 0); - manager()->reloadRegisters(); + reloadRegisters(); updateLocals(); } diff --git a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp index 610baf579853374226e4c14ffc20410d8789bc28..afbd2362c39ab42963025f020e3a72f5549cb360 100644 --- a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp +++ b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp @@ -28,25 +28,27 @@ **************************************************************************/ #include "s60debuggerbluetoothstarter.h" + #include "bluetoothlistener.h" -#include "debuggermanager.h" +#include "debuggerengine.h" #include "trkdevice.h" namespace Debugger { namespace Internal { -S60DebuggerBluetoothStarter::S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent) : - trk::AbstractBluetoothStarter(trkDevice, parent) +S60DebuggerBluetoothStarter::S60DebuggerBluetoothStarter + (const TrkDevicePtr& trkDevice, QObject *parent) + : trk::AbstractBluetoothStarter(trkDevice, parent) { } trk::BluetoothListener *S60DebuggerBluetoothStarter::createListener() { - DebuggerManager *dm = DebuggerManager::instance(); - trk::BluetoothListener *rc = new trk::BluetoothListener(dm); + DebuggerEngine *engine = 0; // FIXME: ABC + trk::BluetoothListener *rc = new trk::BluetoothListener(engine); rc->setMode(trk::BluetoothListener::Listen); - connect(rc, SIGNAL(message(QString)), dm, SLOT(showDebuggerOutput(QString))); - connect(rc, SIGNAL(terminated()), dm, SLOT(startFailed())); + connect(rc, SIGNAL(message(QString)), engine, SLOT(showDebuggerOutput(QString))); + connect(rc, SIGNAL(terminated()), engine, SLOT(startFailed())); return rc; } diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp index 09b4176c4cc1f2580a8dc97235e2eaa8bb15b3b6..1cbe7434fb29fa92254f7af393b0a555286a847a 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.cpp +++ b/src/plugins/debugger/gdb/termgdbadapter.cpp @@ -120,7 +120,7 @@ void TermGdbAdapter::startInferior() { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); const qint64 attachedPID = m_stubProc.applicationPID(); - runControl()->notifyInferiorPid(attachedPID); + m_engine->notifyInferiorPid(attachedPID); m_engine->postCommand("attach " + QByteArray::number(attachedPID), CB(handleStubAttached)); } @@ -159,7 +159,7 @@ void TermGdbAdapter::handleEntryPoint(const GdbResponse &response) void TermGdbAdapter::interruptInferior() { - const qint64 attachedPID = runControl()->inferiorPid(); + const qint64 attachedPID = m_engine->inferiorPid(); QTC_ASSERT(attachedPID > 0, return); if (!interruptProcess(attachedPID)) showMessage(_("CANNOT INTERRUPT %1").arg(attachedPID)); diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp index a9bac0ee9df13c040b20db3addc174cec5621c82..b417d688a08fd3b0b57f1bfaa225a7e3d40dd79b 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp @@ -1724,7 +1724,8 @@ bool TrkGdbAdapter::initializeDevice(const QString &remoteChannel, QString *erro return false; } // Run config: Acquire from device manager. - m_trkDevice = SymbianUtils::SymbianDeviceManager::instance()->acquireDevice(remoteChannel); + m_trkDevice = SymbianUtils::SymbianDeviceManager::instance() + ->acquireDevice(remoteChannel); if (m_trkDevice.isNull()) { *errorMessage = tr("Unable to acquire a device on '%1'. It appears to be in use.").arg(remoteChannel); return false; @@ -2140,7 +2141,7 @@ void TrkGdbAdapter::trkReloadRegisters() { // Take advantage of direct access to cached register values. QTC_ASSERT(m_snapshot.registerValid, /**/); - RegisterHandler *handler = m_engine->runControl()->registerHandler(); + RegisterHandler *handler = m_engine->registerHandler(); Registers registers = handler->registers(); QTC_ASSERT(registers.size() >= 26, @@ -2164,12 +2165,10 @@ void TrkGdbAdapter::trkReloadThreads() { // Take advantage of direct access to cached register values. QTC_ASSERT(m_snapshot.registerValid, /**/); - QList<ThreadData> threads; - foreach (const Session::Thread &thread, m_session.threads) { + Threads threads; + foreach (const Session::Thread &thread, m_session.threads) threads.append(thread); - } - ThreadsHandler *handler = m_engine->manager()->threadsHandler(); - handler->setThreads(threads); + m_engine->threadsHandler()->setThreads(threads); } } // namespace Internal diff --git a/src/plugins/debugger/idebuggerengine.cpp b/src/plugins/debugger/idebuggerengine.cpp deleted file mode 100644 index 88a26a3d96df2c6350da8e2e3f985f110638d323..0000000000000000000000000000000000000000 --- a/src/plugins/debugger/idebuggerengine.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** -** -** 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 "idebuggerengine.h" -#include "debuggermanager.h" - -#include <utils/qtcassert.h> - - -namespace Debugger { -namespace Internal { - -void IDebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *, - quint64 addr, quint64 length) -{ - Q_UNUSED(addr); - Q_UNUSED(length); -} - -void IDebuggerEngine::setRegisterValue(int regnr, const QString &value) -{ - Q_UNUSED(regnr); - Q_UNUSED(value); -} - -bool IDebuggerEngine::checkConfiguration(int toolChain, - QString *errorMessage, QString *settingsPage) const -{ - Q_UNUSED(toolChain); - Q_UNUSED(errorMessage); - Q_UNUSED(settingsPage); - return true; -} - -void IDebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const -{ - QTC_ASSERT(runControl(), return); - runControl()->showMessage(msg, channel, timeout); -} - -} // namespace Internal -} // namespace Debugger - diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h deleted file mode 100644 index bd57373f8419dda21b1b0e6501979819ea42579f..0000000000000000000000000000000000000000 --- a/src/plugins/debugger/idebuggerengine.h +++ /dev/null @@ -1,176 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** -**************************************************************************/ - -#ifndef DEBUGGER_IDEBUGGERENGINE_H -#define DEBUGGER_IDEBUGGERENGINE_H - -#include "debuggerconstants.h" -#include "moduleshandler.h" // For 'Symbols'. - -#include <QtCore/QObject> -#include <QtCore/QList> -#include <QtCore/QSharedPointer> - -QT_BEGIN_NAMESPACE -class QPoint; -class QString; -QT_END_NAMESPACE - -namespace TextEditor { -class ITextEditor; -} - -namespace Core { -class IOptionsPage; -} - -namespace Debugger { - -class DebuggerManager; -class DebuggerRunControl; - -namespace Internal { - -class DisassemblerViewAgent; -class MemoryViewAgent; -class Symbol; -class WatchData; -class BreakHandler; -class ModulesHandler; -class RegisterHandler; -class StackHandler; -class SnapshotHandler; -class ThreadsHandler; -class WatchHandler; - - -class IDebuggerEngine : public QObject -{ - Q_OBJECT - -public: - IDebuggerEngine(DebuggerManager *manager, QObject *parent = 0) - : QObject(parent), m_manager(manager), m_runControl() - {} - - // FIXME: Move this to DebuggerEngineFactory::create(); ? - void setRunControl(DebuggerRunControl *runControl) - { m_runControl = runControl; } - DebuggerRunControl *runControl() const - { return m_runControl; } - - virtual void shutdown() = 0; - virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos) = 0; - virtual void startDebugger() = 0; - virtual void exitDebugger() = 0; - virtual void abortDebugger() { exitDebugger(); } - virtual void detachDebugger() {} - virtual void updateWatchData(const WatchData &data) = 0; - - virtual void executeStep() = 0; - virtual void executeStepOut() = 0; - virtual void executeNext() = 0; - virtual void executeStepI() = 0; - virtual void executeNextI() = 0; - virtual void executeReturn() {} - - virtual void continueInferior() = 0; - virtual void interruptInferior() = 0; - - virtual void executeRunToLine(const QString &fileName, int lineNumber) = 0; - virtual void executeRunToFunction(const QString &functionName) = 0; - virtual void executeJumpToLine(const QString &fileName, int lineNumber) = 0; - virtual void assignValueInDebugger(const QString &expr, const QString &value) = 0; - virtual void executeDebuggerCommand(const QString &command) = 0; - - virtual void activateFrame(int index) = 0; - virtual void selectThread(int index) = 0; - - virtual void makeSnapshot() {} - virtual void activateSnapshot(int index) { Q_UNUSED(index); } - - virtual void attemptBreakpointSynchronization() = 0; - - virtual void reloadModules() = 0; - virtual void loadSymbols(const QString &moduleName) = 0; - virtual void loadAllSymbols() = 0; - virtual void requestModuleSymbols(const QString &moduleName) = 0; - - virtual void reloadRegisters() = 0; - - virtual void reloadSourceFiles() = 0; - virtual void reloadFullStack() = 0; - - virtual void watchPoint(const QPoint &) {} - virtual void fetchMemory(MemoryViewAgent *, QObject *, - quint64 addr, quint64 length); - virtual void fetchDisassembler(DisassemblerViewAgent *) {} - virtual void setRegisterValue(int regnr, const QString &value); - virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {} - virtual unsigned debuggerCapabilities() const { return 0; } - - virtual bool checkConfiguration(int toolChain, - QString *errorMessage, QString *settingsPage = 0) const; - - virtual bool isSynchroneous() const { return false; } - virtual QString qtNamespace() const { return QString(); } - -public slots: - // Convenience - void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const; - void showStatusMessage(const QString &msg, int timeout = -1) const - { showMessage(msg, StatusBar, timeout); } - -public: - DebuggerManager *manager() const { return m_manager; } - bool debuggerActionsEnabled() const; - void showModuleSymbols(const QString &moduleName, const Symbols &symbols); - ModulesHandler *modulesHandler() const; - BreakHandler *breakHandler() const; - RegisterHandler *registerHandler() const; - StackHandler *stackHandler() const; - ThreadsHandler *threadsHandler() const; - WatchHandler *watchHandler() const; - SnapshotHandler *snapshotHandler() const; - -protected: - DebuggerState state() const; - void setState(DebuggerState state, bool forced = false); - DebuggerManager *m_manager; - DebuggerRunControl *m_runControl; - -signals: - void startSuccessful(); - void startFailed(); -}; - -} // namespace Internal -} // namespace Debugger - -#endif // DEBUGGER_IDEBUGGERENGINE_H diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index 272e71e7df24a02af554f9497d1f8f0cf2b4004a..3b0793af301f83573a1fa04800fb54f93cec4f07 100644 --- a/src/plugins/debugger/moduleshandler.cpp +++ b/src/plugins/debugger/moduleshandler.cpp @@ -28,8 +28,7 @@ **************************************************************************/ #include "moduleshandler.h" -#include "idebuggerengine.h" -#include "debuggerrunner.h" +#include "debuggerengine.h" #include <utils/qtcassert.h> @@ -55,7 +54,7 @@ namespace Internal { class ModulesModel : public QAbstractItemModel { public: - explicit ModulesModel(ModulesHandler *parent, DebuggerRunControl *runControl); + explicit ModulesModel(ModulesHandler *parent, DebuggerEngine *engine); // QAbstractItemModel int columnCount(const QModelIndex &parent) const @@ -75,21 +74,19 @@ public: void setModules(const Modules &m); const Modules &modules() const { return m_modules; } - IDebuggerEngine *engine() { return m_runControl->engine(); } - const IDebuggerEngine *engine() const { return m_runControl->engine(); } private: int indexOfModule(const QString &name) const; - DebuggerRunControl *m_runControl; + DebuggerEngine *m_engine; const QVariant m_yes; const QVariant m_no; Modules m_modules; }; -ModulesModel::ModulesModel(ModulesHandler *parent, DebuggerRunControl *runControl) +ModulesModel::ModulesModel(ModulesHandler *parent, DebuggerEngine *engine) : QAbstractItemModel(parent), - m_runControl(runControl), m_yes(tr("yes")), m_no(tr("no")) + m_engine(engine), m_yes(tr("yes")), m_no(tr("no")) {} QVariant ModulesModel::headerData(int section, @@ -110,11 +107,11 @@ QVariant ModulesModel::headerData(int section, QVariant ModulesModel::data(const QModelIndex &index, int role) const { - if (role == EngineCapabilityRole) - return engine()->debuggerCapabilities(); + if (role == EngineCapabilitiesRole) + return m_engine->debuggerCapabilities(); if (role == EngineActionsEnabledRole) - return engine()->debuggerActionsEnabled(); + return m_engine->debuggerActionsEnabled(); int row = index.row(); if (row < 0 || row >= m_modules.size()) @@ -152,19 +149,26 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (role == RequestReloadModulesRole) { - engine()->reloadModules(); - return true; - } - if (role == RequestModuleSymbolsRole) { - engine()->loadSymbols(value.toString()); - return true; - } - if (role == RequestAllSymbolsRole) { - engine()->loadAllSymbols(); - return true; + Q_UNUSED(index); + + switch (role) { + case RequestReloadModulesRole: + m_engine->reloadModules(); + return true; + + case RequestModuleSymbolsRole: + m_engine->loadSymbols(value.toString()); + return true; + + case RequestAllSymbolsRole: + m_engine->loadAllSymbols(); + return true; + + case RequestOpenFileRole: + m_engine->openFile(value.toString()); + return true; } - return QAbstractItemModel::setData(index, value, role); + return false; } void ModulesModel::addModule(const Module &m) @@ -213,9 +217,9 @@ void ModulesModel::removeModule(const QString &moduleName) // ////////////////////////////////////////////////////////////////// -ModulesHandler::ModulesHandler(DebuggerRunControl *runControl) +ModulesHandler::ModulesHandler(DebuggerEngine *engine) { - m_model = new ModulesModel(this, runControl); + m_model = new ModulesModel(this, engine); m_proxyModel = new QSortFilterProxyModel(this); m_proxyModel->setSourceModel(m_model); } diff --git a/src/plugins/debugger/moduleshandler.h b/src/plugins/debugger/moduleshandler.h index e1310fa5441bb47bb8cddd2bf5e26e4e24bfb528..ca2dbd95ecdccd2b02cb709a736541bac7ef1e46 100644 --- a/src/plugins/debugger/moduleshandler.h +++ b/src/plugins/debugger/moduleshandler.h @@ -40,11 +40,9 @@ QT_END_NAMESPACE namespace Debugger { - -class DebuggerRunControl; - namespace Internal { +class DebuggerEngine; class ModulesModel; ////////////////////////////////////////////////////////////////// @@ -94,7 +92,7 @@ typedef QList<Module> Modules; class ModulesHandler : public QObject { public: - explicit ModulesHandler(DebuggerRunControl *runControl); + explicit ModulesHandler(DebuggerEngine *engine); QAbstractItemModel *model() const; diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp index 5d0fc0cd67615b85dcf4c71651d9a1ac277f1bf0..cb821f7bd6dd041fb81ae934133bf29fdb9b08e6 100644 --- a/src/plugins/debugger/moduleswindow.cpp +++ b/src/plugins/debugger/moduleswindow.cpp @@ -72,8 +72,8 @@ ModulesWindow::ModulesWindow(QWidget *parent) void ModulesWindow::moduleActivated(const QModelIndex &index) { qDebug() << "ACTIVATED: " << index.row() << index.column() - << model()->data(index); - emit fileOpenRequested(model()->data(index).toString()); + << index.data().toString(); + setModelData(RequestOpenFileRole, index.data().toString()); } void ModulesWindow::resizeEvent(QResizeEvent *event) @@ -104,7 +104,7 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) const bool enabled = model() && model()->data(index, EngineActionsEnabledRole).toBool(); const unsigned capabilities = - model()->data(index, EngineCapabilityRole).toInt(); + model()->data(index, EngineCapabilitiesRole).toInt(); QMenu menu; QAction *act0 = new QAction(tr("Update Module List"), &menu); @@ -149,8 +149,7 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *act = menu.exec(ev->globalPos()); if (act == act0) { - QTC_ASSERT(model(), return); - model()->setData(QModelIndex(), QVariant(), RequestReloadModulesRole); + setModelData(RequestReloadModulesRole); } else if (act == actAdjustColumnWidths) { resizeColumnsToContents(); } else if (act == actAlwaysAdjustColumnWidth) { @@ -158,16 +157,13 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) //} else if (act == act3) { // emit displaySourceRequested(name); } else if (act == act4) { - QTC_ASSERT(model(), return); - model()->setData(QModelIndex(), QVariant(), RequestAllSymbolsRole); + setModelData(RequestAllSymbolsRole); } else if (act == act5) { - QTC_ASSERT(model(), return); - model()->setData(QModelIndex(), name, RequestModuleSymbolsRole); + setModelData(RequestModuleSymbolsRole, name); } else if (act == act6) { - emit fileOpenRequested(name); + setModelData(RequestOpenFileRole, name); } else if (act == act7) { - QTC_ASSERT(model(), return); - model()->setData(QModelIndex(), name, RequestModuleSymbolsRole); + setModelData(RequestModuleSymbolsRole, name); } } @@ -198,5 +194,12 @@ void ModulesWindow::setModel(QAbstractItemModel *model) setAlwaysResizeColumnsToContents(true); } +void ModulesWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) +{ + QTC_ASSERT(model(), return); + model()->setData(index, value, role); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/moduleswindow.h b/src/plugins/debugger/moduleswindow.h index 978c153769826506c93b6274978d99392c9f728f..5cce3eee13ab8392246d9e477aeea5746cece475 100644 --- a/src/plugins/debugger/moduleswindow.h +++ b/src/plugins/debugger/moduleswindow.h @@ -42,9 +42,6 @@ class ModulesWindow : public QTreeView public: explicit ModulesWindow(QWidget *parent = 0); -signals: - void fileOpenRequested(QString); - private slots: void resizeColumnsToContents(); void setAlwaysResizeColumnsToContents(bool on); @@ -55,6 +52,8 @@ private: void resizeEvent(QResizeEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void setModel(QAbstractItemModel *model); + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); bool m_alwaysResizeColumnsToContents; }; diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index ec34f9c42a40dc7c7e85527f081800c542db9ad3..e7b2ad967764362884b1320ad58eec04708b28b0 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -32,16 +32,18 @@ #include "pdbengine.h" #include "debuggeractions.h" +#include "debuggerconstants.h" #include "debuggerdialogs.h" +#include "debuggerplugin.h" +#include "debuggerstringutils.h" + #include "breakhandler.h" -#include "debuggerconstants.h" -#include "debuggermanager.h" #include "moduleshandler.h" #include "registerhandler.h" #include "stackhandler.h" #include "watchhandler.h" #include "watchutils.h" -#include "debuggerstringutils.h" + #include "../gdb/gdbmi.h" #include <utils/qtcassert.h> @@ -83,8 +85,8 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -PdbEngine::PdbEngine(DebuggerManager *manager) - : IDebuggerEngine(manager) +PdbEngine::PdbEngine(const DebuggerStartParameters &startParameters) + : DebuggerEngine(startParameters) {} PdbEngine::~PdbEngine() @@ -138,16 +140,15 @@ void PdbEngine::exitDebugger() void PdbEngine::startDebugger() { - QTC_ASSERT(runControl(), return); setState(AdapterStarting); - m_scriptFileName = QFileInfo(runControl()->sp().executable).absoluteFilePath(); + m_scriptFileName = QFileInfo(startParameters().executable).absoluteFilePath(); QFile scriptFile(m_scriptFileName); if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) { //showMessage("STARTING " +m_scriptFileName + "FAILED"); showMessage(QString::fromLatin1("Cannot open %1: %2"). arg(m_scriptFileName, scriptFile.errorString()), LogError); - emit startFailed(); + startFailed(); return; } setState(AdapterStarted); @@ -192,7 +193,7 @@ void PdbEngine::startDebugger() Core::ICore::instance()->showWarningWithOptions(title, msg); } shutdown(); - emit startFailed(); + startFailed(); return; } @@ -220,7 +221,7 @@ void PdbEngine::interruptInferior() void PdbEngine::executeStep() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); postCommand("step", CB(handleUpdateAll)); @@ -228,7 +229,7 @@ void PdbEngine::executeStep() void PdbEngine::executeStepI() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); postCommand("step", CB(handleUpdateAll)); @@ -236,7 +237,7 @@ void PdbEngine::executeStepI() void PdbEngine::executeStepOut() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); postCommand("finish", CB(handleUpdateAll)); @@ -244,7 +245,7 @@ void PdbEngine::executeStepOut() void PdbEngine::executeNext() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); postCommand("next", CB(handleUpdateAll)); @@ -252,7 +253,7 @@ void PdbEngine::executeNext() void PdbEngine::executeNextI() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); postCommand("next", CB(handleUpdateAll)); @@ -260,7 +261,7 @@ void PdbEngine::executeNextI() void PdbEngine::continueInferior() { - m_manager->resetLocation(); + resetLocation(); setState(InferiorRunningRequested); setState(InferiorRunning); // Callback will be triggered e.g. when breakpoint is hit. @@ -289,29 +290,29 @@ void PdbEngine::executeJumpToLine(const QString &fileName, int lineNumber) void PdbEngine::activateFrame(int frameIndex) { - manager()->resetLocation(); + resetLocation(); if (state() != InferiorStopped && state() != InferiorUnrunnable) return; - StackHandler *stackHandler = manager()->stackHandler(); - int oldIndex = stackHandler->currentIndex(); + StackHandler *handler = stackHandler(); + int oldIndex = handler->currentIndex(); - //if (frameIndex == stackHandler->stackSize()) { + //if (frameIndex == handler->stackSize()) { // reloadFullStack(); // return; //} - QTC_ASSERT(frameIndex < stackHandler->stackSize(), return); + QTC_ASSERT(frameIndex < handler->stackSize(), return); if (oldIndex != frameIndex) { // Assuming the command always succeeds this saves a roundtrip. // Otherwise the lines below would need to get triggered // after a response to this -stack-select-frame here. - stackHandler->setCurrentIndex(frameIndex); + handler->setCurrentIndex(frameIndex); //postCommand("-stack-select-frame " + QByteArray::number(frameIndex), // CB(handleStackSelectFrame)); } - manager()->gotoLocation(stackHandler->currentFrame(), true); + gotoLocation(handler->currentFrame(), true); } void PdbEngine::selectThread(int index) @@ -336,7 +337,7 @@ static QByteArray breakpointLocation(const BreakpointData *data) void PdbEngine::attemptBreakpointSynchronization() { - BreakHandler *handler = manager()->breakHandler(); + BreakHandler *handler = breakHandler(); //qDebug() << "ATTEMPT BP SYNC"; bool updateNeeded = false; for (int index = 0; index != handler->size(); ++index) { @@ -368,7 +369,7 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response) //qDebug() << "BP RESPONSE: " << response.data; // "Breakpoint 1 at /pdb/math.py:10" int index = response.cookie.toInt(); - BreakHandler *handler = manager()->breakHandler(); + BreakHandler *handler = breakHandler(); BreakpointData *data = handler->at(index); QTC_ASSERT(data, return); QTC_ASSERT(response.data.startsWith("Breakpoint "), return); @@ -419,7 +420,7 @@ void PdbEngine::handleListModules(const PdbResponse &response) module.modulePath = path; modules.append(module); } - runControl()->modulesHandler()->setModules(modules); + modulesHandler()->setModules(modules); } void PdbEngine::requestModuleSymbols(const QString &moduleName) @@ -516,7 +517,7 @@ void PdbEngine::setToolTipExpression(const QPoint &mousePos, } #if 0 - //if (m_manager->status() != InferiorStopped) + //if (status() != InferiorStopped) // return; // FIXME: 'exp' can contain illegal characters @@ -567,7 +568,7 @@ void PdbEngine::handlePdbError(QProcess::ProcessError error) default: m_pdbProc.kill(); setState(EngineShuttingDown, true); - m_manager->showMessageBox(QMessageBox::Critical, tr("Pdb I/O Error"), + plugin()->showMessageBox(QMessageBox::Critical, tr("Pdb I/O Error"), errorMessage(error)); break; } @@ -664,7 +665,7 @@ void PdbEngine::handleResponse(const QByteArray &response0) frame.file = _(fileName); frame.line = lineNumber; if (frame.line > 0 && QFileInfo(frame.file).exists()) { - manager()->gotoLocation(frame, true); + gotoLocation(frame, true); setState(InferiorStopping); setState(InferiorStopped); return; @@ -685,7 +686,7 @@ void PdbEngine::updateAll() setState(InferiorStopping); setState(InferiorStopped); - WatchHandler *handler = m_manager->watchHandler(); + WatchHandler *handler = watchHandler(); QByteArray watchers; //if (!m_toolTipExpression.isEmpty()) @@ -767,13 +768,13 @@ void PdbEngine::handleBacktrace(const PdbResponse &response) const int frameCount = stackFrames.size(); for (int i = 0; i != frameCount; ++i) stackFrames[i].level = frameCount - stackFrames[i].level - 1; - manager()->stackHandler()->setFrames(stackFrames); + stackHandler()->setFrames(stackFrames); // Select current frame. if (currentIndex != -1) { currentIndex = frameCount - currentIndex - 1; - manager()->stackHandler()->setCurrentIndex(currentIndex); - manager()->gotoLocation(stackFrames.at(currentIndex), true); + stackHandler()->setCurrentIndex(currentIndex); + gotoLocation(stackFrames.at(currentIndex), true); } } @@ -788,15 +789,15 @@ void PdbEngine::handleListLocals(const PdbResponse &response) //GdbMi data = all.findChild("data"); QList<WatchData> list; - WatchHandler *watchHandler = manager()->watchHandler(); + WatchHandler *handler = watchHandler(); foreach (const GdbMi &child, all.children()) { WatchData dummy; dummy.iname = child.findChild("iname").data(); dummy.name = _(child.findChild("name").data()); //qDebug() << "CHILD: " << child.toString(); - parseWatchData(watchHandler->expandedINames(), dummy, child, &list); + parseWatchData(handler->expandedINames(), dummy, child, &list); } - watchHandler->insertBulkData(list); + handler->insertBulkData(list); } void PdbEngine::handleLoadDumper(const PdbResponse &response) @@ -811,9 +812,9 @@ unsigned PdbEngine::debuggerCapabilities() const return ReloadModuleCapability; } -IDebuggerEngine *createPdbEngine(DebuggerManager *manager) +DebuggerEngine *createPdbEngine(const DebuggerStartParameters &startParameters) { - return new PdbEngine(manager); + return new PdbEngine(startParameters); } diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h index 9c91364372119b72795d44a77aeb9395a25344c9..b36b2d1508cecb837664ce25897bbd35cf46b8a7 100644 --- a/src/plugins/debugger/pdb/pdbengine.h +++ b/src/plugins/debugger/pdb/pdbengine.h @@ -30,7 +30,7 @@ #ifndef DEBUGGER_PDBENGINE_H #define DEBUGGER_PDBENGINE_H -#include "idebuggerengine.h" +#include "debuggerengine.h" #include <QtCore/QProcess> #include <QtCore/QQueue> @@ -53,16 +53,16 @@ public: QVariant cookie; }; -class PdbEngine : public IDebuggerEngine +class PdbEngine : public DebuggerEngine { Q_OBJECT public: - PdbEngine(DebuggerManager *manager); + explicit PdbEngine(const DebuggerStartParameters &startParameters); ~PdbEngine(); private: - // IDebuggerEngine implementation + // DebuggerEngine implementation void executeStep(); void executeStepOut(); void executeNext(); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 6442a64a200829b831f74ed6f517d96100c42880..fc3a1c1ba1b15f8c220827f93104adf3d97bfae4 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -29,17 +29,16 @@ #include "qmlengine.h" -#include "debuggerstringutils.h" +#include "debuggerconstants.h" #include "debuggerdialogs.h" +#include "debuggerstringutils.h" + #include "breakhandler.h" -#include "debuggerconstants.h" -#include "debuggermanager.h" #include "moduleshandler.h" #include "registerhandler.h" #include "stackhandler.h" #include "watchhandler.h" #include "watchutils.h" -#include "moduleshandler.h" #include <utils/qtcassert.h> @@ -104,8 +103,8 @@ QString QmlEngine::QmlCommand::toString() const // /////////////////////////////////////////////////////////////////////// -QmlEngine::QmlEngine(DebuggerManager *manager) - : IDebuggerEngine(manager) +QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters) + : DebuggerEngine(startParameters) { m_congestion = 0; m_inAir = 0; @@ -169,7 +168,7 @@ void QmlEngine::socketError(QAbstractSocket::SocketError) QString msg = tr("%1.").arg(m_socket->errorString()); //QMessageBox::critical(q->mainWindow(), tr("Error"), msg); showStatusMessage(msg); - manager()->notifyInferiorExited(); + exitDebugger(); } void QmlEngine::executeDebuggerCommand(const QString &command) @@ -198,22 +197,20 @@ void QmlEngine::shutdown() void QmlEngine::exitDebugger() { SDEBUG("QmlEngine::exitDebugger()"); - manager()->notifyInferiorExited(); } void QmlEngine::startDebugger() { - QTC_ASSERT(runControl(), return); qDebug() << "STARTING QML ENGINE"; setState(InferiorRunningRequested); showStatusMessage(tr("Running requested..."), 5000); - const DebuggerStartParameters &sp = runControl()->sp(); + const DebuggerStartParameters &sp = startParameters(); const int pos = sp.remoteChannel.indexOf(QLatin1Char(':')); const QString host = sp.remoteChannel.left(pos); const quint16 port = sp.remoteChannel.mid(pos + 1).toInt(); //QTimer::singleShot(0, this, SLOT(runInferior())); m_socket->connectToHost(host, port); - emit startSuccessful(); + startSuccessful(); } void QmlEngine::continueInferior() @@ -526,7 +523,7 @@ void QmlEngine::updateLocals() void QmlEngine::updateWatchData(const WatchData &) { - //qq->watchHandler()->rebuildModel(); + //watchHandler()->rebuildModel(); showStatusMessage(tr("Stopped."), 5000); } @@ -536,9 +533,9 @@ void QmlEngine::updateSubItem(const WatchData &data0) QTC_ASSERT(false, return); } -IDebuggerEngine *createQmlEngine(DebuggerManager *manager) +DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp) { - return new QmlEngine(manager); + return new QmlEngine(sp); } } // namespace Internal diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 1667d2383e6f1ee1fb0e46b9fdeee4105418de9f..eec0e7d310b1bc3f7e0ddd4b6c827b3a948faf3b 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE class QTcpSocket; QT_END_NAMESPACE -#include "idebuggerengine.h" -#include "debuggermanager.h" +#include "debuggerengine.h" + namespace Debugger { namespace Internal { @@ -57,16 +57,16 @@ class ScriptAgent; class WatchData; class QmlResponse; -class QmlEngine : public IDebuggerEngine +class QmlEngine : public DebuggerEngine { Q_OBJECT public: - explicit QmlEngine(DebuggerManager *parent); + explicit QmlEngine(const DebuggerStartParameters &startParameters); ~QmlEngine(); private: - // IDebuggerEngine implementation + // DebuggerEngine implementation void executeStep(); void executeStepOut(); void executeNext(); diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp index 940c6b066eb23fc39a82ce4dc6885e73ecbf3787..164342b57631911f79baadc4d36c7c78b9ccbba9 100644 --- a/src/plugins/debugger/registerhandler.cpp +++ b/src/plugins/debugger/registerhandler.cpp @@ -29,7 +29,10 @@ #include "registerhandler.h" +#include "debuggeractions.h" +#include "debuggeragents.h" #include "debuggerconstants.h" +#include "debuggerengine.h" #include <utils/qtcassert.h> @@ -49,8 +52,8 @@ using namespace Debugger::Constants; // ////////////////////////////////////////////////////////////////// -RegisterHandler::RegisterHandler(QObject *parent) - : QAbstractTableModel(parent) +RegisterHandler::RegisterHandler(DebuggerEngine *engine) + : m_engine(engine) { setNumberBase(16); } @@ -67,8 +70,19 @@ int RegisterHandler::columnCount(const QModelIndex &parent) const QVariant RegisterHandler::data(const QModelIndex &index, int role) const { - if (role == RegisterNumberBaseRole) - return m_base; + switch (role) { + case EngineStateRole: + return m_engine->state(); + + case EngineCapabilitiesRole: + return m_engine->debuggerCapabilities(); + + case EngineActionsEnabledRole: + return m_engine->debuggerActionsEnabled(); + + case RegisterNumberBaseRole: + return m_base; + } if (!index.isValid() || index.row() >= m_registers.size()) return QVariant(); @@ -136,6 +150,26 @@ Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const return notEditable; } +bool RegisterHandler::setData(const QModelIndex &index, const QVariant &value, int role) +{ + switch (role) { + case RequestSetRegisterRole: + m_engine->setRegisterValue(index.row(), value.toString()); + return true; + + case RequestReloadRegistersRole: + m_engine->reloadRegisters(); + return true; + + case RequestShowMemoryRole: + (void) new MemoryViewAgent(m_engine, value.toString()); + return true; + + default: + return QAbstractTableModel::setData(index, value, role); + } +} + void RegisterHandler::removeAll() { m_registers.clear(); diff --git a/src/plugins/debugger/registerhandler.h b/src/plugins/debugger/registerhandler.h index ad5502bd32ffb264845b2995e07e39a4c5953e71..0818de9c95dad89bec2af8aa8c4300b19c28061c 100644 --- a/src/plugins/debugger/registerhandler.h +++ b/src/plugins/debugger/registerhandler.h @@ -36,12 +36,7 @@ namespace Debugger { namespace Internal { -enum RegisterRole -{ - RegisterNumberBaseRole = Qt::UserRole, // Currently used number base - RegisterAddressRole, // Start value for opening memory view - RegisterChangedRole // Used for painting changed values -}; +class DebuggerEngine; class Register { @@ -62,7 +57,7 @@ class RegisterHandler : public QAbstractTableModel Q_OBJECT public: - RegisterHandler(QObject *parent = 0); + explicit RegisterHandler(DebuggerEngine *engine); QAbstractItemModel *model() { return this; } @@ -76,13 +71,15 @@ private: int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &, int role); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &idx) const; + DebuggerEngine *m_engine; // Not owned. Registers m_registers; int m_base; - int m_strlen; // approximate width of an value in chars + int m_strlen; // approximate width of a value in chars. }; } // namespace Internal diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index 04146aea6b024d2d62118fd8b688337bbf4a6fec..62837c4c5cbfb65e67e9edd331ed82007f5d533e 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -28,11 +28,8 @@ **************************************************************************/ #include "registerwindow.h" -#include "registerhandler.h" #include "debuggeractions.h" -#include "debuggeragents.h" -#include "debuggermanager.h" #include "debuggerconstants.h" #include <utils/qtcassert.h> @@ -64,8 +61,8 @@ namespace Internal { class RegisterDelegate : public QItemDelegate { public: - RegisterDelegate(DebuggerManager *manager, QObject *parent) - : QItemDelegate(parent), m_manager(manager) + RegisterDelegate(RegisterWindow *owner, QObject *parent) + : QItemDelegate(parent), m_owner(owner) {} QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, @@ -80,7 +77,7 @@ public: { QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor); QTC_ASSERT(lineEdit, return); - lineEdit->setText(index.model()->data(index, Qt::DisplayRole).toString()); + lineEdit->setText(index.data(Qt::DisplayRole).toString()); } void setModelData(QWidget *editor, QAbstractItemModel *model, @@ -93,7 +90,7 @@ public: QString value = lineEdit->text(); //model->setData(index, value, Qt::EditRole); if (index.column() == 1) - m_manager->setRegisterValue(index.row(), value); + m_owner->model()->setData(index, value, RequestSetRegisterRole); } void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, @@ -134,7 +131,7 @@ public: } private: - DebuggerManager *m_manager; + RegisterWindow *m_owner; }; @@ -144,15 +141,15 @@ private: // /////////////////////////////////////////////////////////////////////// -RegisterWindow::RegisterWindow(DebuggerManager *manager) - : m_manager(manager), m_alwaysResizeColumnsToContents(true) +RegisterWindow::RegisterWindow(QWidget *parent) + : QTreeView(parent), m_alwaysResizeColumnsToContents(true) { QAction *act = theDebuggerAction(UseAlternatingRowColors); setWindowTitle(tr("Registers")); setAttribute(Qt::WA_MacShowFocusRect, false); setAlternatingRowColors(act->isChecked()); setRootIsDecorated(false); - setItemDelegate(new RegisterDelegate(m_manager, this)); + setItemDelegate(new RegisterDelegate(this, this)); connect(act, SIGNAL(toggled(bool)), this, SLOT(setAlternatingRowColorsHelper(bool))); @@ -167,18 +164,18 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; - const unsigned engineCapabilities = m_manager->debuggerCapabilities(); - const bool actionsEnabled = m_manager->debuggerActionsEnabled(); + const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt(); + const bool actionsEnabled = modelData(EngineActionsEnabledRole).toInt(); + const int state = modelData(EngineStateRole).toInt(); QAction *actReload = menu.addAction(tr("Reload Register Listing")); actReload->setEnabled((engineCapabilities & RegisterCapability) - && (m_manager->state() == InferiorStopped - || m_manager->state() == InferiorUnrunnable)); + && (state == InferiorStopped || state == InferiorUnrunnable)); menu.addSeparator(); QModelIndex idx = indexAt(ev->pos()); - QString address = model()->data(idx, RegisterAddressRole).toString(); + QString address = modelData(RegisterAddressRole, idx).toString(); QAction *actShowMemory = menu.addAction(QString()); if (address.isEmpty()) { actShowMemory->setText(tr("Open Memory Editor")); @@ -190,7 +187,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) } menu.addSeparator(); - int base = model()->data(QModelIndex(), RegisterNumberBaseRole).toInt(); + int base = modelData(RegisterNumberBaseRole).toInt(); QAction *act16 = menu.addAction(tr("Hexadecimal")); act16->setCheckable(true); act16->setChecked(base == 16); @@ -221,9 +218,9 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) else if (act == actAlwaysAdjust) setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents); else if (act == actReload) - m_manager->reloadRegisters(); + setModelData(RequestReloadRegistersRole); else if (act == actShowMemory) - (void) new MemoryViewAgent(m_manager, address); + setModelData(RequestShowMemoryRole, address); else if (act) { base = (act == act10 ? 10 : act == act8 ? 8 : act == act2 ? 2 : 16); QMetaObject::invokeMethod(model(), "setNumberBase", Q_ARG(int, base)); @@ -245,12 +242,30 @@ void RegisterWindow::setAlwaysResizeColumnsToContents(bool on) header()->setResizeMode(1, mode); } - void RegisterWindow::setModel(QAbstractItemModel *model) { QTreeView::setModel(model); setAlwaysResizeColumnsToContents(true); } +void RegisterWindow::reloadRegisters() +{ + // FIXME: Only trigger when becoming visible? + setModelData(RequestReloadRegistersRole); +} + +void RegisterWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) +{ + QTC_ASSERT(model(), return); + model()->setData(index, value, role); +} + +QVariant RegisterWindow::modelData(int role, const QModelIndex &index) +{ + QTC_ASSERT(model(), return QVariant()); + return model()->data(index, role); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h index 64eb3254d40d6857100ef53119b479569c3f2bc2..f7a81763c146ed3cabc72318097cddb42f38dd27 100644 --- a/src/plugins/debugger/registerwindow.h +++ b/src/plugins/debugger/registerwindow.h @@ -33,9 +33,6 @@ #include <QtGui/QTreeView> namespace Debugger { - -class DebuggerManager; - namespace Internal { class RegisterWindow : public QTreeView @@ -43,19 +40,22 @@ class RegisterWindow : public QTreeView Q_OBJECT public: - explicit RegisterWindow(DebuggerManager *manager); + explicit RegisterWindow(QWidget *parent = 0); void setModel(QAbstractItemModel *model); public slots: void resizeColumnsToContents(); void setAlwaysResizeColumnsToContents(bool on); void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } + void reloadRegisters(); private: void resizeEvent(QResizeEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); - DebuggerManager *m_manager; + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); + QVariant modelData(int role, const QModelIndex &index = QModelIndex()); bool m_alwaysResizeColumnsToContents; }; diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index d188f1c3a63597cc599c3c82c2b024265afcb3a2..ca73b14a59146025c328197e7589a50d88560da1 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -31,10 +31,9 @@ #include "scriptengine.h" -#include "debuggerdialogs.h" #include "breakhandler.h" #include "debuggerconstants.h" -#include "debuggermanager.h" +#include "debuggerdialogs.h" #include "moduleshandler.h" #include "registerhandler.h" #include "stackhandler.h" @@ -192,8 +191,8 @@ void ScriptAgent::scriptUnload(qint64 scriptId) // /////////////////////////////////////////////////////////////////////// -ScriptEngine::ScriptEngine(DebuggerManager *manager) - : IDebuggerEngine(manager) +ScriptEngine::ScriptEngine(const DebuggerStartParameters &startParameters) + : DebuggerEngine(startParameters) { } @@ -231,6 +230,9 @@ void ScriptEngine::exitDebugger() void ScriptEngine::startDebugger() { + qDebug() << "STARTING SCRIPT DEBUGGER"; + QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady)); + setState(EngineStarting); setState(AdapterStarting); if (m_scriptEngine.isNull()) m_scriptEngine = Core::ICore::instance()->scriptManager()->scriptEngine(); @@ -248,13 +250,13 @@ void ScriptEngine::startDebugger() setState(AdapterStarted); setState(InferiorStarting); - QTC_ASSERT(runControl(), return); - m_scriptFileName = QFileInfo(runControl()->sp().executable).absoluteFilePath(); + m_scriptFileName = QFileInfo(startParameters().executable).absoluteFilePath(); + qDebug() << "SCRIPT FILE: " << m_scriptFileName; QFile scriptFile(m_scriptFileName); if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) { showMessage(QString::fromLatin1("Cannot open %1: %2"). arg(m_scriptFileName, scriptFile.errorString()), LogError); - emit startFailed(); + startFailed(); return; } QTextStream stream(&scriptFile); @@ -265,7 +267,7 @@ void ScriptEngine::startDebugger() showStatusMessage(tr("Running requested..."), 5000); showMessage(QLatin1String("Running: ") + m_scriptFileName, LogMisc); QTimer::singleShot(0, this, SLOT(runInferior())); - emit startSuccessful(); + startSuccessful(); } void ScriptEngine::continueInferior() @@ -419,7 +421,7 @@ void ScriptEngine::selectThread(int index) void ScriptEngine::attemptBreakpointSynchronization() { - BreakHandler *handler = manager()->breakHandler(); + BreakHandler *handler = breakHandler(); bool updateNeeded = false; for (int index = 0; index != handler->size(); ++index) { BreakpointData *data = handler->at(index); @@ -602,8 +604,8 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) if (byFunction && functionName.isEmpty()) return false; BreakpointData *data = byFunction ? - findBreakPointByFunction(manager()->breakHandler(), functionName) : - findBreakPointByFileName(manager()->breakHandler(), lineNumber, fileName); + findBreakPointByFunction(breakHandler(), functionName) : + findBreakPointByFileName(breakHandler(), lineNumber, fileName); if (!data) return false; @@ -625,7 +627,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) StackFrame frame; frame.file = fileName; frame.line = lineNumber; - manager()->gotoLocation(frame, true); + gotoLocation(frame, true); updateLocals(); return true; } @@ -633,7 +635,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) void ScriptEngine::updateLocals() { QScriptContext *context = m_scriptEngine->currentContext(); - manager()->watchHandler()->beginCycle(); + watchHandler()->beginCycle(); //SDEBUG("UPDATE LOCALS"); // @@ -655,7 +657,7 @@ void ScriptEngine::updateLocals() //frame.address = ...; stackFrames.append(frame); } - manager()->stackHandler()->setFrames(stackFrames); + stackHandler()->setFrames(stackFrames); // // Build locals, deactivate agent meanwhile. @@ -666,9 +668,9 @@ void ScriptEngine::updateLocals() data.iname = "local"; data.name = QString::fromLatin1(data.iname); data.scriptValue = context->activationObject(); - manager()->watchHandler()->beginCycle(); + watchHandler()->beginCycle(); updateSubItem(data); - manager()->watchHandler()->endCycle(); + watchHandler()->endCycle(); // FIXME: Use an extra thread. This here is evil m_stopped = true; showStatusMessage(tr("Stopped."), 5000); @@ -772,7 +774,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0) data1.exp = it.name().toLatin1(); data1.name = it.name(); data1.scriptValue = it.value(); - if (manager()->watchHandler()->isExpandedIName(data1.iname)) { + if (watchHandler()->isExpandedIName(data1.iname)) { data1.setChildrenNeeded(); } else { data1.setChildrenUnneeded(); @@ -789,14 +791,14 @@ void ScriptEngine::updateSubItem(const WatchData &data0) } SDEBUG(msgDebugInsert(data, children)); - manager()->watchHandler()->insertData(data); + watchHandler()->insertData(data); if (!children.isEmpty()) - manager()->watchHandler()->insertBulkData(children); + watchHandler()->insertBulkData(children); } -IDebuggerEngine *createScriptEngine(DebuggerManager *manager) +DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp) { - return new ScriptEngine(manager); + return new ScriptEngine(sp); } } // namespace Internal diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h index cea1ae830f3cc9d3e10aebff4bc5fbf4d35cfacb..580b02307681f672588694d21baff138ccf75f6a 100644 --- a/src/plugins/debugger/script/scriptengine.h +++ b/src/plugins/debugger/script/scriptengine.h @@ -30,7 +30,7 @@ #ifndef DEBUGGER_SCRIPTENGINE_H #define DEBUGGER_SCRIPTENGINE_H -#include "idebuggerengine.h" +#include "debuggerengine.h" #include <QtCore/QSharedPointer> #include <QtCore/QScopedPointer> @@ -52,16 +52,16 @@ class WatchData; * processEvents() triggered by QScriptEngine::setProcessEventsInterval(). * Stopping is emulated by manually calling processEvents() from the debugger engine. */ -class ScriptEngine : public IDebuggerEngine +class ScriptEngine : public DebuggerEngine { Q_OBJECT public: - ScriptEngine(DebuggerManager *manager); + ScriptEngine(const DebuggerStartParameters &startParameters); ~ScriptEngine(); private: - // IDebuggerEngine implementation + // DebuggerEngine implementation void executeStep(); void executeStepOut(); void executeNext(); diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp index 13e321faa46144b405f70863c449796a76a31343..2601b4a932c1755dd00d94f72fa3050c5f294159 100644 --- a/src/plugins/debugger/snapshothandler.cpp +++ b/src/plugins/debugger/snapshothandler.cpp @@ -31,8 +31,7 @@ #include "debuggeractions.h" #include "debuggerconstants.h" -#include "debuggerrunner.h" -#include "idebuggerengine.h" +#include "debuggerengine.h" #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -112,9 +111,8 @@ QDebug operator<<(QDebug d, const SnapshotData &f) // //////////////////////////////////////////////////////////////////////// -SnapshotHandler::SnapshotHandler(DebuggerRunControl *runControl, QObject *parent) - : QAbstractTableModel(parent), - m_runControl(runControl), +SnapshotHandler::SnapshotHandler(DebuggerEngine *engine) + : m_engine(engine), m_positionIcon(QIcon(":/debugger/images/location_16.png")), m_emptyIcon(QIcon(":/debugger/images/debugger_empty_14.png")) { @@ -211,11 +209,11 @@ bool SnapshotHandler::setData (const QModelIndex &index, const QVariant &value, int role) { if (role == RequestMakeSnapshotRole) { - m_runControl->engine()->makeSnapshot(); + m_engine->makeSnapshot(); return true; } if (role == RequestActivateSnapshotRole) { - m_runControl->engine()->activateSnapshot(value.toInt()); + m_engine->activateSnapshot(value.toInt()); return true; } if (role == RequestRemoveSnapshotRole) { diff --git a/src/plugins/debugger/snapshothandler.h b/src/plugins/debugger/snapshothandler.h index e73bb502f3b26ff7780e11396bfcf55599b39eb4..f77a0a1bfde632281f3cb8a1cc9ca7cf6a16fffa 100644 --- a/src/plugins/debugger/snapshothandler.h +++ b/src/plugins/debugger/snapshothandler.h @@ -36,11 +36,10 @@ #include <QtCore/QDateTime> namespace Debugger { - -class DebuggerRunControl; - namespace Internal { +class DebuggerEngine; + //////////////////////////////////////////////////////////////////////// // // SnapshotData @@ -64,8 +63,8 @@ public: void setLocation(const QString &location) { m_location = location; } QString location() const { return m_location; } - void setFrames(const QList<StackFrame> &frames) { m_frames = frames; } - QList<StackFrame> frames() const { return m_frames; } + void setFrames(const StackFrames &frames) { m_frames = frames; } + StackFrames frames() const { return m_frames; } QString function() const; // Topmost entry. @@ -90,7 +89,7 @@ class SnapshotHandler : public QAbstractTableModel Q_OBJECT public: - SnapshotHandler(DebuggerRunControl *runControl, QObject *parent = 0); + explicit SnapshotHandler(DebuggerEngine *engine); ~SnapshotHandler(); void setFrames(const Snapshots &snapshots, bool canExpand = false); @@ -114,7 +113,7 @@ private: Qt::ItemFlags flags(const QModelIndex &index) const; Q_SLOT void resetModel() { reset(); } - DebuggerRunControl *m_runControl; + DebuggerEngine *m_engine; int m_currentIndex; Snapshots m_snapshots; const QVariant m_positionIcon; diff --git a/src/plugins/debugger/sourcefileshandler.cpp b/src/plugins/debugger/sourcefileshandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..670601f8d1d9492c26d9088dd8b3917c7d217ac1 --- /dev/null +++ b/src/plugins/debugger/sourcefileshandler.cpp @@ -0,0 +1,146 @@ +/************************************************************************** +** +** 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 "sourcefileshandler.h" + +#include "debuggerconstants.h" +#include "debuggerengine.h" + +#include <QtCore/QDebug> +#include <QtCore/QFileInfo> + +#include <QtGui/QSortFilterProxyModel> + +namespace Debugger { +namespace Internal { + +SourceFilesHandler::SourceFilesHandler(DebuggerEngine *engine) + : m_engine(engine) +{ + QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); + proxy->setSourceModel(this); + m_proxyModel = proxy; +} + +void SourceFilesHandler::clearModel() +{ + if (m_shortNames.isEmpty()) + return; + m_shortNames.clear(); + m_fullNames.clear(); + reset(); +} + +QVariant SourceFilesHandler::headerData(int section, + Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + static QString headers[] = { + tr("Internal name") + " ", + tr("Full name") + " ", + }; + return headers[section]; + } + return QVariant(); +} + +Qt::ItemFlags SourceFilesHandler::flags(const QModelIndex &index) const +{ + if (index.row() >= m_fullNames.size()) + return 0; + QFileInfo fi(m_fullNames.at(index.row())); + return fi.isReadable() ? QAbstractItemModel::flags(index) : Qt::ItemFlags(0); +} + +QVariant SourceFilesHandler::data(const QModelIndex &index, int role) const +{ + switch (role) { + case EngineActionsEnabledRole: + return m_engine->debuggerActionsEnabled(); + } + + int row = index.row(); + if (row < 0 || row >= m_shortNames.size()) + return QVariant(); + + switch (index.column()) { + case 0: + if (role == Qt::DisplayRole) + return m_shortNames.at(row); + // FIXME: add icons + //if (role == Qt::DecorationRole) + // return module.symbolsRead ? icon2 : icon; + break; + case 1: + if (role == Qt::DisplayRole) + return m_fullNames.at(row); + //if (role == Qt::DecorationRole) + // return module.symbolsRead ? icon2 : icon; + break; + } + return QVariant(); +} + +bool SourceFilesHandler::setData + (const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(index); + switch (role) { + case RequestReloadSourceFilesRole: + m_engine->reloadSourceFiles(); + return true; + + case RequestOpenFileRole: + m_engine->openFile(value.toString()); + return true; + } + return false; +} + +void SourceFilesHandler::setSourceFiles(const QMap<QString, QString> &sourceFiles) +{ + m_shortNames.clear(); + m_fullNames.clear(); + QMap<QString, QString>::ConstIterator it = sourceFiles.begin(); + QMap<QString, QString>::ConstIterator et = sourceFiles.end(); + for (; it != et; ++it) { + m_shortNames.append(it.key()); + m_fullNames.append(it.value()); + } + reset(); +} + +void SourceFilesHandler::removeAll() +{ + setSourceFiles(QMap<QString, QString>()); + //header()->setResizeMode(0, QHeaderView::ResizeToContents); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/sourcefileshandler.h b/src/plugins/debugger/sourcefileshandler.h new file mode 100644 index 0000000000000000000000000000000000000000..3e32ed3cf8bbfe842b778124e772067a33668f5a --- /dev/null +++ b/src/plugins/debugger/sourcefileshandler.h @@ -0,0 +1,80 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEBUGGER_SOURCEFILESHANDLER_H +#define DEBUGGER_SOURCEFILESHANDLER_H + +#include <QtCore/QAbstractItemModel> +#include <QtCore/QMap> +#include <QtCore/QStringList> + + +namespace Debugger { +namespace Internal { + +class DebuggerEngine; + +class SourceFilesHandler : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit SourceFilesHandler(DebuggerEngine *engine); + + int columnCount(const QModelIndex &parent) const + { return parent.isValid() ? 0 : 2; } + int rowCount(const QModelIndex &parent) const + { return parent.isValid() ? 0 : m_shortNames.size(); } + QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } + QModelIndex index(int row, int column, const QModelIndex &) const + { return createIndex(row, column); } + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + Qt::ItemFlags flags(const QModelIndex &index) const; + + void clearModel(); + void update() { reset(); } + + void setSourceFiles(const QMap<QString, QString> &sourceFiles); + void removeAll(); + + QAbstractItemModel *model() { return m_proxyModel; } + +private: + DebuggerEngine *m_engine; + QStringList m_shortNames; + QStringList m_fullNames; + QAbstractItemModel *m_proxyModel; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_SOURCEFILESHANDLER_H diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp index e78cf93b363b1d33cfcdd30e51b73d35a5f4cbd1..d68d12a045343ac273d93dec227f8eb7efe3e9af 100644 --- a/src/plugins/debugger/sourcefileswindow.cpp +++ b/src/plugins/debugger/sourcefileswindow.cpp @@ -28,132 +28,22 @@ **************************************************************************/ #include "sourcefileswindow.h" + #include "debuggeractions.h" -#include "debuggermanager.h" +#include "debuggerconstants.h" + +#include <utils/qtcassert.h> +#include <utils/savedaction.h> #include <QtCore/QDebug> #include <QtCore/QFileInfo> -#include <utils/savedaction.h> - #include <QtGui/QAction> -#include <QtGui/QComboBox> #include <QtGui/QHeaderView> #include <QtGui/QMenu> #include <QtGui/QResizeEvent> -#include <QtGui/QSortFilterProxyModel> #include <QtGui/QTreeView> -#include <QtGui/QVBoxLayout> -using Debugger::Internal::SourceFilesWindow; -using Debugger::Internal::SourceFilesModel; - -////////////////////////////////////////////////////////////////// -// -// SourceFilesModel -// -////////////////////////////////////////////////////////////////// - -class Debugger::Internal::SourceFilesModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - SourceFilesModel(QObject *parent = 0) : QAbstractItemModel(parent) {} - - // QAbstractItemModel - int columnCount(const QModelIndex &parent) const - { return parent.isValid() ? 0 : 2; } - int rowCount(const QModelIndex &parent) const - { return parent.isValid() ? 0 : m_shortNames.size(); } - QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } - QModelIndex index(int row, int column, const QModelIndex &) const - { return createIndex(row, column); } - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QVariant data(const QModelIndex &index, int role) const; - bool setData(const QModelIndex &index, const QVariant &value, int role); - Qt::ItemFlags flags(const QModelIndex &index) const; - - void clearModel(); - void update() { reset(); } - void setSourceFiles(const QMap<QString, QString> &sourceFiles); - -public: - QStringList m_shortNames; - QStringList m_fullNames; -}; - -void SourceFilesModel::clearModel() -{ - if (m_shortNames.isEmpty()) - return; - m_shortNames.clear(); - m_fullNames.clear(); - reset(); -} - -QVariant SourceFilesModel::headerData(int section, - Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { - static QString headers[] = { - tr("Internal name") + " ", - tr("Full name") + " ", - }; - return headers[section]; - } - return QVariant(); -} - -Qt::ItemFlags SourceFilesModel::flags(const QModelIndex &index) const -{ - if (index.row() >= m_fullNames.size()) - return 0; - QFileInfo fi(m_fullNames.at(index.row())); - return fi.isReadable() ? QAbstractItemModel::flags(index) : Qt::ItemFlags(0); -} - -QVariant SourceFilesModel::data(const QModelIndex &index, int role) const -{ - int row = index.row(); - if (row < 0 || row >= m_shortNames.size()) - return QVariant(); - - switch (index.column()) { - case 0: - if (role == Qt::DisplayRole) - return m_shortNames.at(row); - // FIXME: add icons - //if (role == Qt::DecorationRole) - // return module.symbolsRead ? icon2 : icon; - break; - case 1: - if (role == Qt::DisplayRole) - return m_fullNames.at(row); - //if (role == Qt::DecorationRole) - // return module.symbolsRead ? icon2 : icon; - break; - } - return QVariant(); -} - -bool SourceFilesModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - return QAbstractItemModel::setData(index, value, role); -} - -void SourceFilesModel::setSourceFiles(const QMap<QString, QString> &sourceFiles) -{ - m_shortNames.clear(); - m_fullNames.clear(); - QMap<QString, QString>::ConstIterator it = sourceFiles.begin(); - QMap<QString, QString>::ConstIterator et = sourceFiles.end(); - for (; it != et; ++it) { - m_shortNames.append(it.key()); - m_fullNames.append(it.value()); - } - reset(); -} ////////////////////////////////////////////////////////////////// // @@ -161,16 +51,14 @@ void SourceFilesModel::setSourceFiles(const QMap<QString, QString> &sourceFiles) // ////////////////////////////////////////////////////////////////// +namespace Debugger { +namespace Internal { + SourceFilesWindow::SourceFilesWindow(QWidget *parent) : QTreeView(parent) { - m_model = new SourceFilesModel(this); QAction *act = theDebuggerAction(UseAlternatingRowColors); - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); - proxyModel->setSourceModel(m_model); - setModel(proxyModel); - setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); setWindowTitle(tr("Source Files")); @@ -188,20 +76,20 @@ SourceFilesWindow::SourceFilesWindow(QWidget *parent) void SourceFilesWindow::sourceFileActivated(const QModelIndex &index) { - qDebug() << "ACTIVATED: " << index.row() << index.column() - << model()->data(index); - emit fileOpenRequested(model()->data(index).toString()); + setModelData(RequestOpenFileRole, index.data()); } void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) { QModelIndex index = indexAt(ev->pos()); index = index.sibling(index.row(), 0); - QString name = model()->data(index).toString(); + QString name = index.data().toString(); + bool engineActionsEnabled = index.data(EngineActionsEnabledRole).toBool(); QMenu menu; QAction *act1 = new QAction(tr("Reload Data"), &menu); - act1->setEnabled(Debugger::DebuggerManager::instance()->debuggerActionsEnabled()); + + act1->setEnabled(engineActionsEnabled); //act1->setCheckable(true); QAction *act2 = 0; if (name.isEmpty()) { @@ -220,21 +108,18 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *act = menu.exec(ev->globalPos()); if (act == act1) - emit reloadSourceFilesRequested(); + setModelData(RequestReloadSourceFilesRole); else if (act == act2) - emit fileOpenRequested(name); + setModelData(RequestOpenFileRole, name); } -void SourceFilesWindow::setSourceFiles(const QMap<QString, QString> &sourceFiles) +void SourceFilesWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) { - m_model->setSourceFiles(sourceFiles); - header()->setResizeMode(0, QHeaderView::ResizeToContents); + QTC_ASSERT(model(), return); + model()->setData(index, value, role); } -void SourceFilesWindow::removeAll() -{ - m_model->setSourceFiles(QMap<QString, QString>()); - header()->setResizeMode(0, QHeaderView::ResizeToContents); -} +} // namespace Internal +} // namespace Debugger -#include "sourcefileswindow.moc" diff --git a/src/plugins/debugger/sourcefileswindow.h b/src/plugins/debugger/sourcefileswindow.h index d9923b1f152db73071cad3f34da4a01159256641..a2b92dd97f6de4041e2a3b9c7273a7477a92fa66 100644 --- a/src/plugins/debugger/sourcefileswindow.h +++ b/src/plugins/debugger/sourcefileswindow.h @@ -30,13 +30,13 @@ #ifndef DEBUGGER_SOURCEFILEWINDOW_H #define DEBUGGER_SOURCEFILEWINDOW_H +#include <QtCore/QMap> #include <QtGui/QTreeView> + namespace Debugger { namespace Internal { -class SourceFilesModel; - class SourceFilesWindow : public QTreeView { Q_OBJECT @@ -44,20 +44,14 @@ class SourceFilesWindow : public QTreeView public: SourceFilesWindow(QWidget *parent = 0); - void setSourceFiles(const QMap<QString, QString> &sourceFiles); - void removeAll(); - -signals: - void reloadSourceFilesRequested(); - void fileOpenRequested(QString file); - private slots: void sourceFileActivated(const QModelIndex &index); void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } private: void contextMenuEvent(QContextMenuEvent *ev); - SourceFilesModel *m_model; + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); }; } // namespace Internal diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h index 2d7076f8614b1c9d622edcec121078e514bf980f..849db5c96f408a20bb50c109fd0fda4758d82a89 100644 --- a/src/plugins/debugger/stackframe.h +++ b/src/plugins/debugger/stackframe.h @@ -30,9 +30,9 @@ #ifndef DEBUGGER_STACKFRAME_H #define DEBUGGER_STACKFRAME_H -#include <QtCore/QString> #include <QtCore/QList> #include <QtCore/QMetaType> +#include <QtCore/QString> QT_BEGIN_NAMESPACE class QDebug; @@ -41,14 +41,16 @@ QT_END_NAMESPACE namespace Debugger { namespace Internal { -struct StackFrame +class StackFrame { +public: StackFrame(); void clear(); bool isUsable() const; QString toToolTip() const; QString toString() const; +public: int level; QString function; QString file; // We try to put an absolute file name in there. diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index bdfc7b5c11650a41ca4e2923ccf2c5cf293d67ec..3cb1787eadf532c52b1c737f167db464bee3d5bc 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -30,6 +30,8 @@ #include "stackhandler.h" #include "debuggeractions.h" +#include "debuggeragents.h" +#include "debuggerengine.h" #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -37,29 +39,34 @@ #include <QtCore/QAbstractTableModel> #include <QtCore/QDebug> #include <QtCore/QFileInfo> -#include <QtCore/QDir> + namespace Debugger { namespace Internal { - //////////////////////////////////////////////////////////////////////// // // StackHandler // //////////////////////////////////////////////////////////////////////// -StackHandler::StackHandler(QObject *parent) - : QAbstractTableModel(parent), - m_positionIcon(QIcon(":/debugger/images/location_16.png")), +StackHandler::StackHandler(DebuggerEngine *engine) + : m_positionIcon(QIcon(":/debugger/images/location_16.png")), m_emptyIcon(QIcon(":/debugger/images/debugger_empty_14.png")) { + m_engine = engine; + m_disassemblerViewAgent = new DisassemblerViewAgent(engine); m_currentIndex = 0; m_canExpand = false; connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()), this, SLOT(resetModel())); } +StackHandler::~StackHandler() +{ + //delete m_disassemblerViewAgent; +} + int StackHandler::rowCount(const QModelIndex &parent) const { // Since the stack is not a tree, row count is 0 for any valid parent @@ -73,6 +80,17 @@ int StackHandler::columnCount(const QModelIndex &parent) const QVariant StackHandler::data(const QModelIndex &index, int role) const { + switch (role) { + case EngineStateRole: + return m_engine->state(); + + case EngineCapabilitiesRole: + return m_engine->debuggerCapabilities(); + + case EngineActionsEnabledRole: + return m_engine->debuggerActionsEnabled(); + } + if (!index.isValid() || index.row() >= m_stackFrames.size() + m_canExpand) return QVariant(); @@ -104,25 +122,51 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const return QVariant(); } - if (role == Qt::ToolTipRole) { - //: Tooltip for variable - return frame.toToolTip(); - } - if (role == Qt::DecorationRole && index.column() == 0) { // Return icon that indicates whether this is the active stack frame return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon; } - if (role == Qt::UserRole) - return QVariant::fromValue(frame); + if (role == StackFrameAddressRole) + return frame.address; + + //: Tooltip for variable + if (role == Qt::ToolTipRole) + return frame.toToolTip(); return QVariant(); } -QVariant StackHandler::headerData(int section, Qt::Orientation orientation, int role) const + +bool StackHandler::setData(const QModelIndex &index, const QVariant &value, int role) { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (role) { + case RequestActivateFrameRole: + m_engine->activateFrame(value.toInt()); + return true; + + case RequestShowMemoryRole: + (void) new MemoryViewAgent(m_engine, value.toString()); + return true; + + case RequestShowDisassemblerRole: { + const StackFrame &frame = m_stackFrames.at(value.toInt()); + m_disassemblerViewAgent->setFrame(frame); + return true; + } + + case RequestReloadFullStackRole: + m_engine->reloadFullStack(); + return true; + + default: + return QAbstractTableModel::setData(index, value, role); + } +} + +QVariant StackHandler::headerData(int section, Qt::Orientation orient, int role) const +{ + if (orient == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { case 0: return tr("Level"); case 1: return tr("Function"); @@ -176,7 +220,7 @@ void StackHandler::removeAll() reset(); } -void StackHandler::setFrames(const QList<StackFrame> &frames, bool canExpand) +void StackHandler::setFrames(const StackFrames &frames, bool canExpand) { m_canExpand = canExpand; m_stackFrames = frames; @@ -185,7 +229,7 @@ void StackHandler::setFrames(const QList<StackFrame> &frames, bool canExpand) reset(); } -QList<StackFrame> StackHandler::frames() const +StackFrames StackHandler::frames() const { return m_stackFrames; } @@ -198,6 +242,5 @@ bool StackHandler::isDebuggingDebuggingHelpers() const return false; } - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h index 28c5cd1029f04a4bf1387e79cab5946c33060c31..1cbda98ad216478be85919e91cfa4ad6e36e7c83 100644 --- a/src/plugins/debugger/stackhandler.h +++ b/src/plugins/debugger/stackhandler.h @@ -37,9 +37,13 @@ #include <QtGui/QIcon> + namespace Debugger { namespace Internal { +class DebuggerEngine; +class DisassemblerViewAgent; + //////////////////////////////////////////////////////////////////////// // // StackModel @@ -54,6 +58,7 @@ struct StackCookie bool gotoLocation; }; + //////////////////////////////////////////////////////////////////////// // // StackModel @@ -66,10 +71,11 @@ class StackHandler : public QAbstractTableModel Q_OBJECT public: - StackHandler(QObject *parent = 0); + explicit StackHandler(DebuggerEngine *engine); + ~StackHandler(); - void setFrames(const QList<StackFrame> &frames, bool canExpand = false); - QList<StackFrame> frames() const; + void setFrames(const StackFrames &frames, bool canExpand = false); + StackFrames frames() const; void setCurrentIndex(int index); int currentIndex() const { return m_currentIndex; } StackFrame currentFrame() const; @@ -78,7 +84,7 @@ public: // Called from StackHandler after a new stack list has been received void removeAll(); - QAbstractItemModel *stackModel() { return this; } + QAbstractItemModel *model() { return this; } bool isDebuggingDebuggingHelpers() const; private: @@ -86,19 +92,20 @@ private: int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &, int role); QVariant headerData(int section, Qt::Orientation orientation, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const; Q_SLOT void resetModel() { reset(); } - QList<StackFrame> m_stackFrames; + DebuggerEngine *m_engine; + DisassemblerViewAgent *m_disassemblerViewAgent; + StackFrames m_stackFrames; int m_currentIndex; const QVariant m_positionIcon; const QVariant m_emptyIcon; bool m_canExpand; }; - - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp index 92791ffddf23b574613aabd959939913c3497520..562d00e1a72635689bfc05c58ed99da55e33050c 100644 --- a/src/plugins/debugger/stackwindow.cpp +++ b/src/plugins/debugger/stackwindow.cpp @@ -31,8 +31,7 @@ #include "stackframe.h" #include "debuggeractions.h" -#include "debuggeragents.h" -#include "debuggermanager.h" +#include "debuggerconstants.h" #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -53,12 +52,11 @@ namespace Debugger { namespace Internal { -StackWindow::StackWindow(DebuggerManager *manager, QWidget *parent) - : QTreeView(parent), m_manager(manager), m_alwaysResizeColumnsToContents(false) +StackWindow::StackWindow(QWidget *parent) + : QTreeView(parent), m_alwaysResizeColumnsToContents(false) { setAttribute(Qt::WA_MacShowFocusRect, false); setFrameStyle(QFrame::NoFrame); - m_disassemblerAgent = new DisassemblerViewAgent(manager); QAction *act = theDebuggerAction(UseAlternatingRowColors); setWindowTitle(tr("Stack")); @@ -68,6 +66,8 @@ StackWindow::StackWindow(DebuggerManager *manager, QWidget *parent) setIconSize(QSize(10, 10)); header()->setDefaultAlignment(Qt::AlignLeft); + header()->resizeSection(0, 60); + header()->resizeSection(3, 60); connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(rowActivated(QModelIndex))); @@ -75,11 +75,14 @@ StackWindow::StackWindow(DebuggerManager *manager, QWidget *parent) this, SLOT(setAlternatingRowColorsHelper(bool))); connect(theDebuggerAction(UseAddressInStackView), SIGNAL(toggled(bool)), this, SLOT(showAddressColumn(bool))); + connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()), + this, SLOT(reloadFullStack())); + connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()), + this, SLOT(reloadFullStack())); } StackWindow::~StackWindow() { - delete m_disassemblerAgent; } void StackWindow::showAddressColumn(bool on) @@ -89,18 +92,16 @@ void StackWindow::showAddressColumn(bool on) void StackWindow::rowActivated(const QModelIndex &index) { - m_manager->activateFrame(index.row()); + setModelData(RequestActivateFrameRole, index.row()); } void StackWindow::contextMenuEvent(QContextMenuEvent *ev) { - QModelIndex idx = indexAt(ev->pos()); - StackFrame frame = model()->data(idx, Qt::UserRole).value<StackFrame>(); - QString address = frame.address; + const QModelIndex index = indexAt(ev->pos()); + const QString address = modelData(StackFrameAddressRole, index).toString(); + const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt(); QMenu menu; - - const unsigned engineCapabilities = m_manager->debuggerCapabilities(); menu.addAction(theDebuggerAction(ExpandStack)); QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard")); @@ -153,9 +154,9 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) else if (act == actAlwaysAdjust) setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents); else if (act == actShowMemory) - (void) new MemoryViewAgent(m_manager, address); + setModelData(RequestShowMemoryRole, address); else if (act == actShowDisassembler) - m_disassemblerAgent->setFrame(frame); + setModelData(RequestShowDisassemblerRole, index.row()); } void StackWindow::copyContentsToClipboard() @@ -178,6 +179,11 @@ void StackWindow::copyContentsToClipboard() clipboard->setText(str, QClipboard::Clipboard); } +void StackWindow::reloadFullStack() +{ + setModelData(RequestReloadFullStackRole); +} + void StackWindow::resizeColumnsToContents() { for (int i = model()->columnCount(); --i >= 0; ) @@ -193,5 +199,19 @@ void StackWindow::setAlwaysResizeColumnsToContents(bool on) header()->setResizeMode(i, mode); } +void StackWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) +{ + QTC_ASSERT(model(), return); + model()->setData(index, value, role); +} + +QVariant StackWindow::modelData(int role, const QModelIndex &index) +{ + QTC_ASSERT(model(), return QVariant()); + return model()->data(index, role); +} + + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h index 29de3c73848ad55f407bb75364d548e3483585c6..ad6ad41dc77ad78107b2ef380053faf542b638c3 100644 --- a/src/plugins/debugger/stackwindow.h +++ b/src/plugins/debugger/stackwindow.h @@ -33,17 +33,14 @@ #include <QtGui/QTreeView> namespace Debugger { -class DebuggerManager; - namespace Internal { -class DisassemblerViewAgent; class StackWindow : public QTreeView { Q_OBJECT public: - StackWindow(DebuggerManager *manager, QWidget *parent = 0); + explicit StackWindow(QWidget *parent = 0); ~StackWindow(); public slots: @@ -54,13 +51,16 @@ private slots: void rowActivated(const QModelIndex &index); void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } void showAddressColumn(bool on); + void reloadFullStack(); private: void contextMenuEvent(QContextMenuEvent *ev); void copyContentsToClipboard(); - DebuggerManager *m_manager; - DisassemblerViewAgent *m_disassemblerAgent; + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); + QVariant modelData(int role, const QModelIndex &index = QModelIndex()); + bool m_alwaysResizeColumnsToContents; }; diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp index 83eb6c38f2c6c69f8208ebada7eb062e0c96f9fa..b9ed4c9b207e69d575d6ddfc1795217b2ffe63aa 100644 --- a/src/plugins/debugger/tcf/tcfengine.cpp +++ b/src/plugins/debugger/tcf/tcfengine.cpp @@ -29,19 +29,17 @@ #include "tcfengine.h" -#include "debuggerstringutils.h" +#include "debuggerconstants.h" #include "debuggerdialogs.h" +#include "debuggerstringutils.h" +#include "json.h" + #include "breakhandler.h" -#include "debuggerconstants.h" -#include "debuggermanager.h" #include "moduleshandler.h" #include "registerhandler.h" #include "stackhandler.h" #include "watchhandler.h" #include "watchutils.h" -#include "moduleshandler.h" -#include "json.h" - #include <utils/qtcassert.h> #include <QtCore/QDateTime> @@ -106,8 +104,8 @@ QString TcfEngine::TcfCommand::toString() const // /////////////////////////////////////////////////////////////////////// -TcfEngine::TcfEngine(DebuggerManager *manager) - : IDebuggerEngine(manager) +TcfEngine::TcfEngine(const DebuggerStartParameters &startParameters) + : DebuggerEngine(startParameters) { m_congestion = 0; m_inAir = 0; @@ -171,7 +169,7 @@ void TcfEngine::socketError(QAbstractSocket::SocketError) QString msg = tr("%1.").arg(m_socket->errorString()); //QMessageBox::critical(q->mainWindow(), tr("Error"), msg); showStatusMessage(msg); - manager()->notifyInferiorExited(); + exitDebugger(); } void TcfEngine::executeDebuggerCommand(const QString &command) @@ -200,15 +198,13 @@ void TcfEngine::shutdown() void TcfEngine::exitDebugger() { SDEBUG("TcfEngine::exitDebugger()"); - manager()->notifyInferiorExited(); } void TcfEngine::startDebugger() { - QTC_ASSERT(runControl(), return); setState(InferiorRunningRequested); showStatusMessage(tr("Running requested..."), 5000); - const DebuggerStartParameters &sp = runControl()->sp(); + const DebuggerStartParameters &sp = startParameters(); const int pos = sp.remoteChannel.indexOf(QLatin1Char(':')); const QString host = sp.remoteChannel.left(pos); const quint16 port = sp.remoteChannel.mid(pos + 1).toInt(); @@ -558,9 +554,9 @@ void TcfEngine::updateSubItem(const WatchData &data0) QTC_ASSERT(false, return); } -IDebuggerEngine *createTcfEngine(DebuggerManager *manager) +DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp) { - return new TcfEngine(manager); + return new TcfEngine(sp); } } // namespace Internal diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h index d16502ebf48fe410e729a019da8de1f174002646..41f5bb6cdc39a4ee2f5baca749b943c7c04654d4 100644 --- a/src/plugins/debugger/tcf/tcfengine.h +++ b/src/plugins/debugger/tcf/tcfengine.h @@ -47,8 +47,7 @@ QT_BEGIN_NAMESPACE class QTcpSocket; QT_END_NAMESPACE -#include "idebuggerengine.h" -#include "debuggermanager.h" +#include "debuggerengine.h" #include "json.h" namespace Debugger { @@ -57,16 +56,16 @@ namespace Internal { class ScriptAgent; class WatchData; -class TcfEngine : public IDebuggerEngine +class TcfEngine : public DebuggerEngine { Q_OBJECT public: - explicit TcfEngine(DebuggerManager *parent); + explicit TcfEngine(const DebuggerStartParameters &startParameters); ~TcfEngine(); private: - // IDebuggerEngine implementation + // DebuggerEngine implementation void executeStep(); void executeStepOut(); void executeNext(); diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp index 3cd67a962c354406fab45ce3cb6159c4fe1f56aa..a049cabe5c4ba40ad1a25d488424b4cb3b53b5d7 100644 --- a/src/plugins/debugger/threadshandler.cpp +++ b/src/plugins/debugger/threadshandler.cpp @@ -29,6 +29,10 @@ #include "threadshandler.h" +#include "debuggerconstants.h" +#include "debuggerengine.h" + + namespace Debugger { namespace Internal { @@ -60,8 +64,8 @@ void ThreadData::notifyRunning() // /////////////////////////////////////////////////////////////////////// -ThreadsHandler::ThreadsHandler(QObject *parent) : - QAbstractTableModel(parent), +ThreadsHandler::ThreadsHandler(DebuggerEngine *engine) + : m_engine(engine), m_currentIndex(0), m_positionIcon(QLatin1String(":/debugger/images/location_16.png")), m_emptyIcon(QLatin1String(":/debugger/images/debugger_empty_14.png")) @@ -97,9 +101,12 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const case ThreadData::FileColumn: return thread.fileName; case ThreadData::LineColumn: - return thread.lineNumber >= 0 ? QString::number(thread.lineNumber) : QString(); + return thread.lineNumber >= 0 + ? QString::number(thread.lineNumber) : QString(); case ThreadData::AddressColumn: - return thread.address > 0 ? QLatin1String("0x") + QString::number(thread.address, 16) : QString(); + return thread.address > 0 + ? QLatin1String("0x") + QString::number(thread.address, 16) + : QString(); case ThreadData::CoreColumn: return thread.core; case ThreadData::StateColumn: @@ -110,9 +117,11 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const return tr("Thread: %1").arg(thread.id); // Stopped if (thread.fileName.isEmpty()) - return tr("Thread: %1 at %2 (0x%3)").arg(thread.id).arg(thread.function).arg(thread.address, 0, 16); + return tr("Thread: %1 at %2 (0x%3)").arg(thread.id) + .arg(thread.function).arg(thread.address, 0, 16); return tr("Thread: %1 at %2, %3:%4 (0x%5)"). - arg(thread.id).arg(thread.function, thread.fileName).arg(thread.lineNumber).arg(thread.address, 0, 16); + arg(thread.id).arg(thread.function, thread.fileName) + .arg(thread.lineNumber).arg(thread.address, 0, 16); } else if (role == Qt::DecorationRole && index.column() == 0) { // Return icon that indicates whether this is the active stack frame return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon; @@ -121,7 +130,8 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const return QVariant(); } -QVariant ThreadsHandler::headerData(int section, Qt::Orientation orientation, int role) const +QVariant ThreadsHandler::headerData + (int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); @@ -144,6 +154,16 @@ QVariant ThreadsHandler::headerData(int section, Qt::Orientation orientation, in return QVariant(); } +bool ThreadsHandler::setData + (const QModelIndex &index, const QVariant &value, int role) +{ + if (role == RequestSelectThreadRole) { + m_engine->selectThread(value.toInt()); + return true; + } + return QAbstractTableModel::setData(index, value, role); +} + int ThreadsHandler::currentThreadId() const { if (m_currentIndex < 0 || m_currentIndex >= m_threads.size()) @@ -167,7 +187,7 @@ void ThreadsHandler::setCurrentThread(int index) emit dataChanged(i, i); } -void ThreadsHandler::setThreads(const QList<ThreadData> &threads) +void ThreadsHandler::setThreads(const Threads &threads) { m_threads = threads; if (m_currentIndex >= m_threads.size()) @@ -175,7 +195,7 @@ void ThreadsHandler::setThreads(const QList<ThreadData> &threads) reset(); } -QList<ThreadData> ThreadsHandler::threads() const +Threads ThreadsHandler::threads() const { return m_threads; } @@ -194,8 +214,8 @@ void ThreadsHandler::notifyRunning() return; if (m_threads.front().address == 0) return; - const QList<ThreadData>::iterator end = m_threads.end(); - for (QList<ThreadData>::iterator it = m_threads.begin(); it != end; ++it) + const Threads::iterator end = m_threads.end(); + for (Threads::iterator it = m_threads.begin(); it != end; ++it) it->notifyRunning(); emit dataChanged(index(0, 1), index(m_threads.size() - 1, ThreadData::ColumnCount - 1)); diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h index 10e242a301a5d5e5d5a52faca119e4b9e3dfba78..882ef1da9b9ae550eebf06c5ece01f683abaa95d 100644 --- a/src/plugins/debugger/threadshandler.h +++ b/src/plugins/debugger/threadshandler.h @@ -39,6 +39,8 @@ namespace Debugger { namespace Internal { +class DebuggerEngine; + //////////////////////////////////////////////////////////////////////// // // ThreadData @@ -77,6 +79,8 @@ struct ThreadData int lineNumber; }; +typedef QVector<ThreadData> Threads; + //////////////////////////////////////////////////////////////////////// // @@ -90,15 +94,15 @@ class ThreadsHandler : public QAbstractTableModel Q_OBJECT public: - ThreadsHandler(QObject *parent = 0); + explicit ThreadsHandler(DebuggerEngine *engine); int currentThreadId() const; void setCurrentThread(int index); void selectThread(int index); - void setThreads(const QList<ThreadData> &threads); + void setThreads(const Threads &threads); void removeAll(); - QList<ThreadData> threads() const; - QAbstractItemModel *threadsModel() { return this; } + Threads threads() const; + QAbstractItemModel *model() { return this; } // Clear out all frame information void notifyRunning(); @@ -107,10 +111,13 @@ private: int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; private: - QList<ThreadData> m_threads; + DebuggerEngine *m_engine; + Threads m_threads; int m_currentIndex; const QIcon m_positionIcon; const QIcon m_emptyIcon; diff --git a/src/plugins/debugger/threadswindow.cpp b/src/plugins/debugger/threadswindow.cpp index 2c2dae34fb8ad22fbe6d0fdf87aed7db7d3e4aae..8567ae6d831b78e3061af4c3a134fb3946878e27 100644 --- a/src/plugins/debugger/threadswindow.cpp +++ b/src/plugins/debugger/threadswindow.cpp @@ -30,6 +30,7 @@ #include "threadswindow.h" #include "debuggeractions.h" +#include "debuggerconstants.h" #include <utils/savedaction.h> @@ -38,7 +39,9 @@ #include <QtGui/QHeaderView> #include <QtGui/QMenu> -using Debugger::Internal::ThreadsWindow; + +namespace Debugger { +namespace Internal { ThreadsWindow::ThreadsWindow(QWidget *parent) : QTreeView(parent), m_alwaysResizeColumnsToContents(false) @@ -62,7 +65,7 @@ ThreadsWindow::ThreadsWindow(QWidget *parent) void ThreadsWindow::rowActivated(const QModelIndex &index) { - emit threadSelected(index.row()); + selectThread(index.row()); } void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) @@ -79,7 +82,7 @@ void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(theDebuggerAction(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); - if(!act) + if (!act) return; if (act == adjustColumnAction) { @@ -103,3 +106,11 @@ void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on) ? QHeaderView::ResizeToContents : QHeaderView::Interactive; header()->setResizeMode(0, mode); } + +void ThreadsWindow::selectThread(int index) +{ + model()->setData(QModelIndex(), index, RequestSelectThreadRole); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/threadswindow.h b/src/plugins/debugger/threadswindow.h index 6f4e2d95c86c47c7f66614cd4ec57b453b2a9334..2955123d2e6b01091250a42ed62e1a39e7be5d1a 100644 --- a/src/plugins/debugger/threadswindow.h +++ b/src/plugins/debugger/threadswindow.h @@ -42,12 +42,10 @@ class ThreadsWindow : public QTreeView public: ThreadsWindow(QWidget *parent = 0); -signals: - void threadSelected(int); - public slots: void resizeColumnsToContents(); void setAlwaysResizeColumnsToContents(bool on); + void selectThread(int index); private slots: void rowActivated(const QModelIndex &index); diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index 7d2f8248a977f6b15010fcf0536d15cf51f45073..bf6b34e02daf0968c79802c9e3c2794bcaa862f4 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -260,6 +260,17 @@ QString WatchData::shadowedName(const QString &name, int seen) return shadowedNameFormat().arg(name, seen); } +quint64 WatchData::coreAddress() const +{ + if (!addr.isEmpty()) { + bool ok; + const quint64 address = addr.toULongLong(&ok, 16); + if (ok) + return address; + } + return quint64(0); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h index f8062324ef25eaf4ae2385582dedadcf069b9bac..cdc9067430f91a8125426d0d20f1c473186c6c60 100644 --- a/src/plugins/debugger/watchdata.h +++ b/src/plugins/debugger/watchdata.h @@ -101,6 +101,7 @@ public: bool isValid() const { return !iname.isEmpty(); } bool isEqual(const WatchData &other) const; + quint64 coreAddress() const; static QString msgNotInScope(); static QString shadowedName(const QString &name, int seen); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 3652a31199af0c8347695a6db569f159aababe2b..63a5a5783532e6b4d5a243492c6db2e6cd703b77 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -28,10 +28,14 @@ **************************************************************************/ #include "watchhandler.h" -#include "watchutils.h" + +#include "breakhandler.h" +#include "breakpoint.h" #include "debuggeractions.h" -#include "debuggermanager.h" -#include "idebuggerengine.h" +#include "debuggeragents.h" +#include "debuggerengine.h" +#include "debuggerplugin.h" +#include "watchutils.h" #if USE_MODEL_TEST #include "modeltest.h" @@ -76,6 +80,8 @@ static const QString strNotInScope = static int watcherCounter = 0; static int generationCounter = 0; +static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); } + //////////////////////////////////////////////////////////////////// // // WatchItem @@ -178,6 +184,11 @@ void WatchModel::endCycle() m_fetchTriggered.clear(); emit enableUpdates(true); } + +DebuggerEngine *WatchModel::engine() const +{ + return m_handler->m_engine; +} void WatchModel::dump() { @@ -375,9 +386,8 @@ QString WatchModel::niceType(const QString &typeIn) const QString type = niceTypeHelper(typeIn); if (!theDebuggerBoolSetting(ShowStdNamespace)) type = type.remove("std::"); - IDebuggerEngine *engine = m_handler->m_manager->currentEngine(); - if (engine && !theDebuggerBoolSetting(ShowQtNamespace)) - type = type.remove(engine->qtNamespace()); + if (!theDebuggerBoolSetting(ShowQtNamespace)) + type = type.remove(engine()->qtNamespace()); return type; } @@ -459,7 +469,7 @@ void WatchModel::fetchMore(const QModelIndex &index) if (item->children.isEmpty()) { WatchData data = *item; data.setChildrenNeeded(); - m_handler->m_manager->updateWatchData(data); + engine()->updateWatchData(data); } } @@ -583,6 +593,14 @@ static inline quint64 pointerValue(QString data) QVariant WatchModel::data(const QModelIndex &idx, int role) const { + switch (role) { + case EngineCapabilitiesRole: + return engine()->debuggerCapabilities(); + + case EngineActionsEnabledRole: + return engine()->debuggerActionsEnabled(); + } + const WatchItem *item = watchItem(idx); const WatchItem &data = *item; @@ -623,16 +641,16 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const break; } - case ExpressionRole: + case LocalsExpressionRole: return data.exp; - case INameRole: + case LocalsINameRole: return data.iname; - case ExpandedRole: + case LocalsExpandedRole: return m_handler->m_expandedINames.contains(data.iname); - case TypeFormatListRole: + case LocalsTypeFormatListRole: if (!data.typeFormats.isEmpty()) return data.typeFormats.split(','); if (isIntType(data.type)) @@ -647,28 +665,33 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const << tr("UCS4 string"); break; - case TypeFormatRole: + case LocalsTypeFormatRole: return m_handler->m_typeFormats.value(data.type, -1); - case IndividualFormatRole: + case LocalsIndividualFormatRole: return m_handler->m_individualFormats.value(data.addr, -1); - case AddressRole: - if (!data.addr.isEmpty()) { - bool ok; - const quint64 address = data.addr.toULongLong(&ok, 16); - if (ok) - return QVariant(address); - } - return QVariant(quint64(0)); - - case RawValueRole: + case LocalsRawValueRole: return data.value; - case PointerValue: + case LocalsPointerValueRole: if (isPointerType(data.type)) return pointerValue(data.value); return QVariant(quint64(0)); + + case LocalsIsWatchpointAtAddressRole: + return engine()->breakHandler() + ->watchPointAt(data.coreAddress()); + + case LocalsAddressRole: + return data.coreAddress(); + + case LocalsIsWatchpointAtPointerValueRole: + if (isPointerType(data.type)) + return engine()->breakHandler() + ->watchPointAt(pointerValue(data.addr)); + return false; + default: break; } @@ -677,8 +700,54 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role) { + switch (role) { + case RequestAssignValueRole: { + QString str = value.toString(); + int i = str.indexOf('='); + if (i != -1) + engine()->assignValueInDebugger(str.left(i), str.mid(i + 1)); + return true; + } + + case RequestAssignTypeRole: { + QString str = value.toString(); + int i = str.indexOf('='); + if (i != -1) + engine()->assignValueInDebugger(str.left(i), str.mid(i + 1)); + return true; + } + + case RequestToggleWatchRole: { + BreakHandler *handler = engine()->breakHandler(); + const quint64 address = value.toULongLong(); + const QByteArray addressBA = + QByteArray("0x") + QByteArray::number(address, 16); + const int index = handler->findWatchPointIndexByAddress(addressBA); + if (index == -1) { + BreakpointData *data = new BreakpointData; + data->type = BreakpointData::WatchpointType; + data->address = addressBA; + handler->appendBreakpoint(data); + } else { + handler->removeBreakpoint(index); + } + engine()->attemptBreakpointSynchronization(); + return true; + } + + case RequestShowMemoryRole: { + (void) new MemoryViewAgent(engine(), value.toULongLong()); + return true; + } + + case RequestClearCppCodeModelSnapshotRole: { + plugin()->clearCppCodeModelSnapshot(); + return true; + } + } + WatchItem &data = *watchItem(index); - if (role == ExpandedRole) { + if (role == LocalsExpandedRole) { if (value.toBool()) { // Should already have been triggered by fetchMore() //QTC_ASSERT(m_handler->m_expandedINames.contains(data.iname), /**/); @@ -686,17 +755,17 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro } else { m_handler->m_expandedINames.remove(data.iname); } - } else if (role == TypeFormatRole) { + } else if (role == LocalsTypeFormatRole) { m_handler->setFormat(data.type, value.toInt()); - m_handler->m_manager->updateWatchData(data); - } else if (role == IndividualFormatRole) { + engine()->updateWatchData(data); + } else if (role == LocalsIndividualFormatRole) { const int format = value.toInt(); if (format == -1) { m_handler->m_individualFormats.remove(data.addr); } else { m_handler->m_individualFormats[data.addr] = format; } - m_handler->m_manager->updateWatchData(data); + engine()->updateWatchData(data); } emit dataChanged(index, index); return true; @@ -985,9 +1054,9 @@ void WatchModel::formatRequests(QByteArray *out, const WatchItem *item) const // /////////////////////////////////////////////////////////////////////// -WatchHandler::WatchHandler(DebuggerManager *manager) +WatchHandler::WatchHandler(DebuggerEngine *engine) { - m_manager = manager; + m_engine = engine; m_expandPointers = true; m_inChange = false; @@ -1021,7 +1090,7 @@ void WatchHandler::endCycle() m_locals->endCycle(); m_watchers->endCycle(); m_tooltips->endCycle(); - m_manager->updateWatchersWindow(); + updateWatchersWindow(); } void WatchHandler::cleanup() @@ -1063,9 +1132,8 @@ void WatchHandler::insertData(const WatchData &data) if (data.isSomethingNeeded() && data.iname.contains('.')) { MODEL_DEBUG("SOMETHING NEEDED: " << data.toString()); - IDebuggerEngine *engine = m_manager->currentEngine(); - if (engine && !engine->isSynchroneous()) { - m_manager->updateWatchData(data); + if (!m_engine->isSynchroneous()) { + m_engine->updateWatchData(data); } else { qDebug() << "ENDLESS LOOP: SOMETHING NEEDED: " << data.toString(); WatchData data1 = data; @@ -1116,7 +1184,7 @@ void WatchHandler::insertBulkData(const QList<WatchData> &list) foreach (const WatchData &data, list) { if (data.isSomethingNeeded()) - m_manager->updateWatchData(data); + m_engine->updateWatchData(data); } } @@ -1151,13 +1219,12 @@ void WatchHandler::watchExpression(const QString &exp) if (exp.isEmpty() || exp == watcherEditPlaceHolder()) data.setAllUnneeded(); data.iname = watcherName(data.exp); - IDebuggerEngine *engine = m_manager->currentEngine(); - if (engine && engine->isSynchroneous()) - m_manager->updateWatchData(data); + if (m_engine && m_engine->isSynchroneous()) + m_engine->updateWatchData(data); else insertData(data); - m_manager->updateWatchData(data); - m_manager->updateWatchersWindow(); + m_engine->updateWatchData(data); + updateWatchersWindow(); saveWatchers(); } @@ -1275,6 +1342,13 @@ void WatchHandler::removeWatchExpression(const QString &exp0) } } +void WatchHandler::updateWatchersWindow() +{ + const bool showWatchers = m_watchers->rowCount(QModelIndex()) > 0; + const bool showReturn = m_return->rowCount(QModelIndex()) > 0; + plugin()->updateWatchersWindow(showWatchers, showReturn); +} + void WatchHandler::updateWatchers() { //qDebug() << "UPDATE WATCHERS"; @@ -1291,7 +1365,7 @@ void WatchHandler::updateWatchers() void WatchHandler::loadWatchers() { - QVariant value = m_manager->sessionValue("Watchers"); + QVariant value = plugin()->sessionValue("Watchers"); foreach (const QString &exp, value.toStringList()) m_watcherNames[exp.toLatin1()] = watcherCounter++; @@ -1316,12 +1390,12 @@ QStringList WatchHandler::watchedExpressions() const void WatchHandler::saveWatchers() { //qDebug() << "SAVE WATCHERS: " << m_watchers; - m_manager->setSessionValue("Watchers", QVariant(watchedExpressions())); + plugin()->setSessionValue("Watchers", QVariant(watchedExpressions())); } void WatchHandler::loadTypeFormats() { - QVariant value = m_manager->sessionValue("DefaultFormats"); + QVariant value = plugin()->sessionValue("DefaultFormats"); QMap<QString, QVariant> typeFormats = value.toMap(); QMapIterator<QString, QVariant> it(typeFormats); while (it.hasNext()) { @@ -1344,7 +1418,7 @@ void WatchHandler::saveTypeFormats() typeFormats.insert(key, format); } } - m_manager->setSessionValue("DefaultFormats", QVariant(typeFormats)); + plugin()->setSessionValue("DefaultFormats", QVariant(typeFormats)); } void WatchHandler::saveSessionData() diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index daf8507e67e20d5a12ed522a83d5be74500252f3..1c37800e1891620b879d63fc7d5e2edb1798a96f 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -44,26 +44,18 @@ class QDebug; QT_END_NAMESPACE namespace Debugger { - -class DebuggerManager; - namespace Internal { +class DebuggerEngine; class WatchItem; class WatchHandler; -enum WatchType { ReturnWatch, LocalsWatch, WatchersWatch, TooltipsWatch }; -enum WatchRoles +enum WatchType { - INameRole = Qt::UserRole, - ExpressionRole, - ExpandedRole, // Used to communicate preferred expanded state to the view. - TypeFormatListRole, - TypeFormatRole, // Used to communicate alternative formats to the view. - IndividualFormatRole, - AddressRole, // Memory address of variable as quint64. - RawValueRole, // Unformatted value as string. - PointerValue // Pointer value (address) as quint64. + ReturnWatch, + LocalsWatch, + WatchersWatch, + TooltipsWatch }; enum IntegerFormat @@ -132,6 +124,7 @@ signals: private: QString niceType(const QString &typeIn) const; void formatRequests(QByteArray *out, const WatchItem *item) const; + DebuggerEngine *engine() const; WatchHandler *m_handler; WatchType m_type; @@ -144,7 +137,7 @@ class WatchHandler : public QObject Q_OBJECT public: - explicit WatchHandler(DebuggerManager *manager); + explicit WatchHandler(DebuggerEngine *engine); WatchModel *model(WatchType type) const; WatchModel *modelForIName(const QByteArray &iname) const; @@ -192,6 +185,7 @@ private: void loadTypeFormats(); void saveTypeFormats(); void setFormat(const QString &type, int format); + void updateWatchersWindow(); bool m_expandPointers; bool m_inChange; @@ -212,7 +206,7 @@ private: WatchModel *m_locals; WatchModel *m_watchers; WatchModel *m_tooltips; - DebuggerManager *m_manager; + DebuggerEngine *m_engine; }; } // namespace Internal diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 243aaad86af367bb2bc866e64a2bf513cdb53da2..a39bff63dea4d5c98338993cc193df603ea1b54b 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -28,15 +28,12 @@ **************************************************************************/ #include "watchwindow.h" -#include "watchhandler.h" -#include "breakpoint.h" -#include "breakhandler.h" #include "debuggeractions.h" -#include "debuggeragents.h" +#include "debuggerconstants.h" +#include "debuggerengine.h" #include "debuggerdialogs.h" -#include "debuggermanager.h" -#include "idebuggerengine.h" +#include "watchhandler.h" #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -80,9 +77,9 @@ public: QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor); QTC_ASSERT(lineEdit, return); if (index.column() == 1) - lineEdit->setText(index.model()->data(index, Qt::DisplayRole).toString()); + lineEdit->setText(index.data(Qt::DisplayRole).toString()); else - lineEdit->setText(index.model()->data(index, ExpressionRole).toString()); + lineEdit->setText(index.data(LocalsExpressionRole).toString()); } void setModelData(QWidget *editor, QAbstractItemModel *model, @@ -91,15 +88,15 @@ public: //qDebug() << "SET MODEL DATA"; QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor); QTC_ASSERT(lineEdit, return); - QString value = lineEdit->text(); - QString exp = model->data(index, ExpressionRole).toString(); + const QString value = lineEdit->text(); + const QString exp = index.data(LocalsExpressionRole).toString(); model->setData(index, value, Qt::EditRole); if (index.column() == 1) { // The value column. - theDebuggerAction(AssignValue)->trigger(QString(exp + '=' + value)); + model->setData(index, QString(exp + '=' + value), RequestAssignValueRole); } else if (index.column() == 2) { // The type column. - theDebuggerAction(AssignType)->trigger(QString(exp + '=' + value)); + model->setData(index, QString(exp + '=' + value), RequestAssignTypeRole); } else if (index.column() == 0) { // The watcher name column. theDebuggerAction(RemoveWatchExpression)->trigger(exp); @@ -121,9 +118,10 @@ public: // ///////////////////////////////////////////////////////////////////// -WatchWindow::WatchWindow(Type type, DebuggerManager *manager, QWidget *parent) - : QTreeView(parent), m_alwaysResizeColumnsToContents(true), m_type(type), - m_manager(manager) +WatchWindow::WatchWindow(Type type, QWidget *parent) + : QTreeView(parent), + m_alwaysResizeColumnsToContents(true), + m_type(type) { m_grabbing = false; @@ -149,12 +147,12 @@ WatchWindow::WatchWindow(Type type, DebuggerManager *manager, QWidget *parent) void WatchWindow::expandNode(const QModelIndex &idx) { - model()->setData(idx, true, ExpandedRole); + setModelData(LocalsExpandedRole, true, idx); } void WatchWindow::collapseNode(const QModelIndex &idx) { - model()->setData(idx, false, ExpandedRole); + setModelData(LocalsExpandedRole, false, idx); } void WatchWindow::keyPressEvent(QKeyEvent *ev) @@ -162,7 +160,7 @@ void WatchWindow::keyPressEvent(QKeyEvent *ev) if (ev->key() == Qt::Key_Delete && m_type == WatchersType) { QModelIndex idx = currentIndex(); QModelIndex idx1 = idx.sibling(idx.row(), 0); - QString exp = model()->data(idx1).toString(); + QString exp = idx1.data().toString(); theDebuggerAction(RemoveWatchExpression)->trigger(exp); } else if (ev->key() == Qt::Key_Return && ev->modifiers() == Qt::ControlModifier @@ -204,38 +202,23 @@ void WatchWindow::dropEvent(QDropEvent *ev) //QTreeView::dropEvent(ev); } -static inline void toggleWatchPoint(DebuggerManager *manager, quint64 address) -{ - const QByteArray addressBA = QByteArray("0x") + QByteArray::number(address, 16); - const int index = manager->breakHandler()->findWatchPointIndexByAddress(addressBA); - if (index == -1) { - BreakpointData *data = new BreakpointData; - data->type = BreakpointData::WatchpointType; - data->address = addressBA; - manager->breakHandler()->appendBreakpoint(data); - } else { - manager->breakHandler()->removeBreakpoint(index); - } - manager->attemptBreakpointSynchronization(); -} - void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) { const QModelIndex idx = indexAt(ev->pos()); const QModelIndex mi0 = idx.sibling(idx.row(), 0); const QModelIndex mi1 = idx.sibling(idx.row(), 1); const QModelIndex mi2 = idx.sibling(idx.row(), 2); - const quint64 address = model()->data(mi0, AddressRole).toULongLong(); - const quint64 pointerValue = model()->data(mi0, PointerValue).toULongLong(); - const QString exp = model()->data(mi0, ExpressionRole).toString(); - const QString type = model()->data(mi2).toString(); + const quint64 address = mi0.data(LocalsAddressRole).toULongLong(); + const quint64 pointerValue = mi0.data(LocalsPointerValueRole).toULongLong(); + const QString exp = mi0.data(LocalsExpressionRole).toString(); + const QString type = mi2.data().toString(); const QStringList alternativeFormats = - model()->data(mi0, TypeFormatListRole).toStringList(); + mi0.data(LocalsTypeFormatListRole).toStringList(); const int typeFormat = - model()->data(mi0, TypeFormatRole).toInt(); + mi0.data(LocalsTypeFormatRole).toInt(); const int individualFormat = - model()->data(mi0, IndividualFormatRole).toInt(); + mi0.data(LocalsIndividualFormatRole).toInt(); const int effectiveIndividualFormat = individualFormat == -1 ? typeFormat : individualFormat; @@ -297,12 +280,11 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) individualFormatMenu.setEnabled(false); } - QMenu menu; - - const bool actionsEnabled = m_manager->debuggerActionsEnabled(); - const unsigned engineCapabilities = m_manager->debuggerCapabilities(); + const bool actionsEnabled = modelData(EngineActionsEnabledRole).toBool(); + const unsigned engineCapabilities = modelData(EngineCapabilitiesRole).toUInt(); const bool canHandleWatches = actionsEnabled && (engineCapabilities & AddWatcherCapability); + QMenu menu; QAction *actInsertNewWatchItem = menu.addAction(tr("Insert New Watch Item")); actInsertNewWatchItem->setEnabled(canHandleWatches); QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch")); @@ -316,29 +298,31 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) actOpenMemoryEditor->setEnabled(actionsEnabled && canShowMemory); // Offer to open address pointed to or variable address. - const bool createPointerActions = pointerValue && pointerValue != address; + const bool createPointerActions = pointerValue && pointerValue != address; if (canShowMemory && address) actOpenMemoryEditAtVariableAddress = new QAction(tr("Open Memory Editor at Object's Address (0x%1)").arg(address, 0, 16), &menu); if (createPointerActions) actOpenMemoryEditAtPointerValue = - new QAction(tr("Open Memory Editor at Referenced Address (0x%1)").arg(pointerValue, 0, 16), &menu); + new QAction(tr("Open Memory Editor at Referenced Address (0x%1)").arg(pointerValue, 0, 16), &menu); menu.addSeparator(); QAction *actSetWatchPointAtVariableAddress = 0; - QAction *actSetWatchPointAtPointerValue= 0; + QAction *actSetWatchPointAtPointerValue = 0; const bool canSetWatchpoint = engineCapabilities & WatchpointCapability; if (canSetWatchpoint && address) { actSetWatchPointAtVariableAddress = new QAction(tr("Break on Changes at Object's Address (0x%1)").arg(address, 0, 16), &menu); actSetWatchPointAtVariableAddress->setCheckable(true); - actSetWatchPointAtVariableAddress->setChecked(m_manager->breakHandler()->watchPointAt(address)); + actSetWatchPointAtVariableAddress-> + setChecked(mi0.data(LocalsIsWatchpointAtAddressRole).toBool()); if (createPointerActions) { actSetWatchPointAtPointerValue = - new QAction(tr("Break on Changes at Referenced Address (0x%1)").arg(pointerValue, 0, 16), &menu); + new QAction(tr("Break on Changes at Referenced Address (0x%1)").arg(pointerValue, 0, 16), &menu); actSetWatchPointAtPointerValue->setCheckable(true); - actSetWatchPointAtPointerValue->setChecked(m_manager->breakHandler()->watchPointAt(pointerValue)); + actSetWatchPointAtPointerValue-> + setChecked(mi0.data(LocalsIsWatchpointAtPointerValueRole).toBool()); } } else { actSetWatchPointAtVariableAddress = @@ -407,35 +391,34 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) theDebuggerAction(WatchExpression) ->trigger(WatchHandler::watcherEditPlaceHolder()); } else if (act == actOpenMemoryEditAtVariableAddress) { - (void) new MemoryViewAgent(m_manager, address); + setModelData(RequestShowMemoryRole, address); } else if (act == actOpenMemoryEditAtPointerValue) { - (void) new MemoryViewAgent(m_manager, pointerValue); + setModelData(RequestShowMemoryRole, pointerValue); } else if (act == actOpenMemoryEditor) { AddressDialog dialog; - if (dialog.exec() == QDialog::Accepted) { - (void) new MemoryViewAgent(m_manager, dialog.address()); - } + if (dialog.exec() == QDialog::Accepted) + setModelData(RequestShowMemoryRole, dialog.address()); } else if (act == actSetWatchPointAtVariableAddress) { - toggleWatchPoint(m_manager, address); + setModelData(RequestToggleWatchRole, address); } else if (act == actSetWatchPointAtPointerValue) { - toggleWatchPoint(m_manager, pointerValue); + setModelData(RequestToggleWatchRole, pointerValue); } else if (act == actSelectWidgetToWatch) { grabMouse(Qt::CrossCursor); m_grabbing = true; } else if (act == actClearCodeModelSnapshot) { - m_manager->clearCppCodeModelSnapshot(); + setModelData(RequestClearCppCodeModelSnapshotRole); } else if (act == clearTypeFormatAction) { - model()->setData(mi1, -1, TypeFormatRole); + setModelData(LocalsTypeFormatRole, -1, mi1); } else if (act == clearIndividualFormatAction) { - model()->setData(mi1, -1, IndividualFormatRole); + setModelData(LocalsIndividualFormatRole, -1, mi1); } else { for (int i = 0; i != typeFormatActions.size(); ++i) { if (act == typeFormatActions.at(i)) - model()->setData(mi1, i, TypeFormatRole); + setModelData(LocalsTypeFormatRole, 1, mi1); } for (int i = 0; i != individualFormatActions.size(); ++i) { if (act == individualFormatActions.at(i)) - model()->setData(mi1, i, IndividualFormatRole); + setModelData(LocalsIndividualFormatRole, 1, mi1); } } } @@ -502,7 +485,7 @@ void WatchWindow::resetHelper() void WatchWindow::resetHelper(const QModelIndex &idx) { - if (model()->data(idx, ExpandedRole).toBool()) { + if (idx.data(LocalsExpandedRole).toBool()) { //qDebug() << "EXPANDING " << model()->data(idx, INameRole); expand(idx); for (int i = 0, n = model()->rowCount(idx); i != n; ++i) { @@ -514,3 +497,17 @@ void WatchWindow::resetHelper(const QModelIndex &idx) collapse(idx); } } + +void WatchWindow::setModelData + (int role, const QVariant &value, const QModelIndex &index) +{ + QTC_ASSERT(model(), return); + model()->setData(index, value, role); +} + +QVariant WatchWindow::modelData(int role, const QModelIndex &index) +{ + QTC_ASSERT(model(), return QVariant()); + return model()->data(index, role); +} + diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index b08f928203902a177bea7e491f84b00e6e00cc6e..1970b3f8c6392b4477bd04f164715c6227159eef 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -32,9 +32,8 @@ #include <QtGui/QTreeView> -namespace Debugger { -class DebuggerManager; +namespace Debugger { namespace Internal { ///////////////////////////////////////////////////////////////////// @@ -50,8 +49,7 @@ class WatchWindow : public QTreeView public: enum Type { ReturnType, LocalsType, TooltipType, WatchersType }; - WatchWindow(Type type, DebuggerManager *manager, QWidget *parent = 0); - void setType(Type type) { m_type = type; } + WatchWindow(Type type, QWidget *parent = 0); Type type() const { return m_type; } public slots: @@ -76,9 +74,12 @@ private: void editItem(const QModelIndex &idx); void resetHelper(const QModelIndex &idx); + void setModelData(int role, const QVariant &value = QVariant(), + const QModelIndex &index = QModelIndex()); + QVariant modelData(int role, const QModelIndex &index = QModelIndex()); + bool m_alwaysResizeColumnsToContents; Type m_type; - DebuggerManager *m_manager; bool m_grabbing; }; diff --git a/src/plugins/qmlinspector/qmlinspector.cpp b/src/plugins/qmlinspector/qmlinspector.cpp index 0b98b7e90fa41d084bdd2457015e4edf075d4abe..04a782dd1efd6cd7611ea4fc8a126cd04fb7d5d6 100644 --- a/src/plugins/qmlinspector/qmlinspector.cpp +++ b/src/plugins/qmlinspector/qmlinspector.cpp @@ -38,11 +38,12 @@ #include "components/expressionquerywidget.h" #include "components/objectpropertiesview.h" -#include <debugger/debuggermanager.h> +#include <debugger/debuggerconstants.h> +#include <debugger/debuggerengine.h> #include <debugger/debuggermainwindow.h> +#include <debugger/debuggerplugin.h> #include <debugger/debuggerrunner.h> #include <debugger/debuggeruiswitcher.h> -#include <debugger/debuggerconstants.h> #include <utils/styledbar.h> #include <utils/fancymainwindow.h> @@ -176,8 +177,8 @@ QmlInspector::QmlInspector(QObject *parent) // m_frameRateWidget = new Internal::CanvasFrameRate; // m_frameRateWidget->setObjectName(QLatin1String("QmlDebugFrameRate")); - Debugger::DebuggerManager *debugManager = Debugger::DebuggerManager::instance(); - connect(debugManager, SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int))); + connect(Debugger::DebuggerPlugin::instance(), + SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int))); m_editablePropertyTypes = QStringList() << "qreal" << "bool" << "QString" << "int" << "QVariant" << "QUrl" << "QColor"; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp index 92dbcf9800be4e8a49dc288be0977e46f8b52a96..6ea396003d8723c0023c101b06d3d14965e6270d 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp @@ -41,7 +41,8 @@ #include <coreplugin/icore.h> #include <coreplugin/progressmanager/progressmanager.h> -#include <debugger/debuggermanager.h> +#include <debugger/debuggerengine.h> +#include <debugger/debuggerplugin.h> #include <debugger/debuggerrunner.h> #include <extensionsystem/pluginmanager.h> #include <projectexplorer/toolchain.h> @@ -381,11 +382,9 @@ void MaemoRunControl::handleRemoteOutput(const QString &output) MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration) : AbstractMaemoRunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE) - , m_debuggerManager(ExtensionSystem::PluginManager::instance() - ->getObject<Debugger::DebuggerManager>()) + , m_debuggerRunControl(0) , m_startParams(new Debugger::DebuggerStartParameters) { - QTC_ASSERT(m_debuggerManager != 0, return); #ifdef USE_GDBSERVER m_startParams->startMode = Debugger::AttachToRemote; m_startParams->executable = executableOnHost(); @@ -406,8 +405,14 @@ MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration) m_startParams->remoteDumperLib = remoteDir().toUtf8() + '/' + QFileInfo(m_runConfig->dumperLib()).fileName().toUtf8(); - connect(m_debuggerManager, SIGNAL(debuggingFinished()), this, + m_debuggerRunControl = qobject_cast<Debugger::DebuggerRunControl *> + (Debugger::DebuggerPlugin::createDebugger(*m_startParams.data())); + connect(m_debuggerRunControl, SIGNAL(debuggingFinished()), this, SLOT(debuggingFinished()), Qt::QueuedConnection); + +/* + FIXME: + connect(m_debuggerManager, SIGNAL(applicationOutputAvailable(QString, bool)), this, #ifdef USE_GDBSERVER @@ -416,6 +421,7 @@ MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration) SLOT(handleRemoteOutput(QString)) #endif , Qt::QueuedConnection); +*/ } MaemoDebugRunControl::~MaemoDebugRunControl() @@ -460,20 +466,18 @@ void MaemoDebugRunControl::handleRemoteOutput(const QString &output) void MaemoDebugRunControl::startDebugging() { - Debugger::DebuggerRunControl *runControl = - new Debugger::DebuggerRunControl(m_debuggerManager, *m_startParams.data()); - m_debuggerManager->startNewDebugger(runControl); + Debugger::DebuggerPlugin::startDebugger(m_debuggerRunControl); } void MaemoDebugRunControl::stopInternal() { - m_debuggerManager->exitDebugger(); + m_debuggerRunControl->engine()->quitDebugger(); } bool MaemoDebugRunControl::isRunning() const { return AbstractMaemoRunControl::isRunning() - || m_debuggerManager->state() != Debugger::DebuggerNotReady; + || m_debuggerRunControl->engine()->state() != Debugger::DebuggerNotReady; } void MaemoDebugRunControl::debuggingFinished() @@ -499,5 +503,5 @@ QString MaemoDebugRunControl::gdbServerPort() const // but we will make sure we use the right port from the information file. } - } // namespace Internal +} // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h index 12177e2d7117f7da625b2f0a6a0ce8baa163544e..940520817a4ea73764ec9d4f28d2f2caf4b26a18 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.h @@ -48,7 +48,7 @@ class QProcess; QT_END_NAMESPACE namespace Debugger { - class DebuggerManager; + class DebuggerRunControl; class DebuggerStartParameters; } // namespace Debugger @@ -168,7 +168,7 @@ private: QString gdbServerPort() const; void startDebugging(); - Debugger::DebuggerManager *m_debuggerManager; + Debugger::DebuggerRunControl *m_debuggerRunControl; QSharedPointer<Debugger::DebuggerStartParameters> m_startParams; bool m_debuggingStarted; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index e5a6026cd20a195f67dd8717967f1ef1a7661e6a..b4d377a123f35bbdf19699eee60066697075501d 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -51,7 +51,8 @@ #include <projectexplorer/project.h> #include <projectexplorer/buildconfiguration.h> -#include <debugger/debuggermanager.h> +#include <debugger/debuggerengine.h> +#include <debugger/debuggerplugin.h> #include <debugger/debuggerrunner.h> #include <QtGui/QMessageBox> @@ -890,7 +891,7 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *ru m_startParams(new Debugger::DebuggerStartParameters) { setReleaseDeviceAfterLauncherFinish(true); // Debugger controls device after install - Debugger::DebuggerManager *dm = Debugger::DebuggerManager::instance(); + Debugger::DebuggerPlugin *dm = Debugger::DebuggerPlugin::instance(); S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration); QTC_ASSERT(dm && rc, return); @@ -915,8 +916,10 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *ru void S60DeviceDebugRunControl::stop() { S60DeviceRunControlBase::stop(); - Debugger::DebuggerManager *dm = Debugger::DebuggerManager::instance(); + Debugger::DebuggerPlugin *dm = Debugger::DebuggerPlugin::instance(); QTC_ASSERT(dm, return) + // FIXME: ABC: that should use the RunControl present in + // handleLauncherFinished if (dm->state() == Debugger::DebuggerNotReady) dm->exitDebugger(); } @@ -944,11 +947,11 @@ void S60DeviceDebugRunControl::initLauncher(const QString &executable, trk::Laun void S60DeviceDebugRunControl::handleLauncherFinished() { + using namespace Debugger; emit appendMessage(this, tr("Launching debugger..."), false); - Debugger::DebuggerManager *dm = Debugger::DebuggerManager::instance(); - Debugger::DebuggerRunControl *runControl = - new Debugger::DebuggerRunControl(dm, *m_startParams.data()); - dm->startNewDebugger(runControl); + ProjectExplorer::RunControl *rc + = DebuggerPlugin::createDebugger(*m_startParams.data()); + DebuggerPlugin::startDebugger(rc); } void S60DeviceDebugRunControl::debuggingFinished() @@ -961,8 +964,9 @@ bool S60DeviceDebugRunControl::checkConfiguration(QString *errorMessage, QString *settingsCategory, QString *settingsPage) const { - return Debugger::DebuggerManager::instance()->checkDebugConfiguration(m_startParams->toolChainType, - errorMessage, - settingsCategory, - settingsPage); + return Debugger::DebuggerRunControl::checkDebugConfiguration( + m_startParams->toolChainType, + errorMessage, + settingsCategory, + settingsPage); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp index cdb490206016e6a497e9a0f08bd57cbcc063ca48..77f8c1a5884cc753fc5bae3910dc6917a1ea8f13 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp @@ -43,7 +43,7 @@ #include <extensionsystem/pluginmanager.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/toolchain.h> -#include <debugger/debuggermanager.h> +#include <debugger/debuggerplugin.h> #include <utils/qtcassert.h> #include <QtGui/QMainWindow> @@ -121,7 +121,7 @@ S60Manager::S60Manager(QObject *parent) tr("Run on Device"), parent)); addAutoReleasedObject(new S60CreatePackageStepFactory); - if (Debugger::DebuggerManager::instance()) + if (Debugger::DebuggerPlugin::instance()) addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl, S60DeviceRunConfiguration> (QLatin1String(ProjectExplorer::Constants::DEBUGMODE), diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 3acb3a1405570ae7d3a195b07af60ace8eea48d7..a9cef8c01795b29d0ddf6ee063798fca7eb19153 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -749,7 +749,7 @@ void testQObject(int &argc, char *argv[]) ob1.setObjectName("A Subobject"); #endif -#if 0 +#if 1 QString str = QString::fromUtf8("XXXXXXXXXXXXXXyyXXX ö"); QLabel l(str); l.setObjectName("Some Label");