diff options
author | hjk <qtc-committer@nokia.com> | 2010-06-16 11:08:54 +0200 |
---|---|---|
committer | hjk <qtc-committer@nokia.com> | 2010-06-22 10:59:57 +0200 |
commit | 6a6cba5518fb88345c53a7cd645f6cb6466a84e3 (patch) | |
tree | 88d7875ae5bd6f70a3654b11f80c6ed9b9685369 /src | |
parent | 4cc244469a4c7d9fb2b3e598727c6d8a2e7c1813 (diff) | |
download | qt-creator-6a6cba5518fb88345c53a7cd645f6cb6466a84e3.tar.gz |
debugger: The DebuggerEngine refactoring.
This replaces the (de facto) singleton engines and data handlers by classes
that are instantiated per run. The DebuggerRunControl will now create an
object of (a class derived from) DebuggerEngine that contains all the relevant
"dynamic" data.
DebuggerManager is no more. The "singleton" bits are merged into DebuggerPlugin,
whereas the data bits went to DebuggerEngine.
There is no formal notion of a "current" DebuggerEngine. However, as there's
only one DebuggerEngine at a time that has its data models connected to the
view, there's still some "de facto" notion of a "current" engine. Calling
SomeModel::setData(int role, QVariant data) with custom role is used as the
primary dispatch mechanism from the views to the "current" data models
(and the engine, as all data models know their engine).
Diffstat (limited to 'src')
91 files changed, 5103 insertions, 4691 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index c579a298ff..f4dca3be9d 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 7c9297dcc6..a697474e7e 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 5a9eef7a92..b6044dbc9c 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 b2174bad41..0195ba3c51 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 b3828cae45..3a5d5a18ba 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 38b31d3411..e68ad07d71 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 7c65cada5e..e42c1e513c 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 9a86abe7eb..8b790bdb66 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 455fec4f3b..265e0bb1ba 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 25d22d999d..810a4b1d1d 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 ef0171140b..a0ec96989b 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 3cd8588c6a..54840d7c06 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 be9b10adb1..3c88045bb8 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 4804a242ae..93f068b529 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 0b49e6982d..6323593a82 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 23a5543301..6fc617f532 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 4f5dd73d47..b36a79154c 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 528495e55d..c498f2e932 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 ba95f5f380..b0211a0c32 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); @@ -256,12 +256,6 @@ DebuggerSettings *DebuggerSettings::instance() 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); item = new SavedAction(instance); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index e0040eb09c..86c11ac93e 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 4b0b453c58..cd089d803c 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 fe3cc3a855..febee6c9db 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 841dec77cc..ca15e37150 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 0000000000..5c994407d3 --- /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 0000000000..b6725632c3 --- /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 028e7dad5f..536e608231 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 c46f667c5f..0000000000 --- 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 5c1eec2faf..0000000000 --- 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 df75bc9a4b..8b92763c80 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 01b646c7a3..d4861b3d7b 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,70 +663,559 @@ 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 +// +/////////////////////////////////////////////////////////////////////// + +class DebuggerPluginPrivate : public QObject +{ + Q_OBJECT + +public: + explicit DebuggerPluginPrivate(DebuggerPlugin *plugin); + + bool initialize(const QStringList &arguments, QString *errorMessage); + void notifyCurrentEngine(int role, const QVariant &value = QVariant()); + void connectEngine(DebuggerEngine *engine); + void disconnectEngine() { connectEngine(m_dummySessionEngine); } + +public slots: + void updateWatchersHeader(int section, int, int newSize) + { m_watchersWindow->header()->resizeSection(section, newSize); } + + void reloadSourceFiles() + { notifyCurrentEngine(RequestReloadSourceFilesRole); } + + void sourceFilesDockToggled(bool on) + { if (on) reloadSourceFiles(); } + + void reloadModules() + { notifyCurrentEngine(RequestReloadModulesRole); } + + void modulesDockToggled(bool on) + { if (on) reloadModules(); } + + void onAction(); + void onStatusTimeout(); + void setSimpleDockWidgetArrangement(const QString &activeLanguage); + + 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); + + void activatePreviousMode(); + void activateDebugMode(); + void toggleBreakpoint(); + void toggleBreakpoint(const QString &fileName, int lineNumber); + void breakpointSetRemoveMarginActionTriggered(); + void breakpointEnableDisableMarginActionTriggered(); + void onModeChanged(Core::IMode *mode); + void showSettingsDialog(); + + 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(); + + 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; - DebuggerManager *manager = new DebuggerManager(this); - ExtensionSystem::PluginManager::instance()->addObject(manager); - const QList<Core::IOptionsPage *> engineOptionPages = - manager->initializeEngines(m_cmdLineEnabledEngines); + // 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(manager); - addAutoReleasedObject(m_debuggerRunControlFactory); + m_debuggerRunControlFactory = new DebuggerRunControlFactory + (m_plugin, DebuggerEngineType(cmdLineEnabledEngines)); + m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory); QList<int> context; context.append(uidm->uniqueIdentifier(CC::C_EDITORMANAGER)); @@ -773,16 +1254,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess m_detachAction = new QAction(this); m_detachAction->setText(tr("Detach Debugger")); - connect(m_detachAction, SIGNAL(triggered()), - manager, SLOT(detachDebugger())); + m_detachAction->setData(RequestExecDetachRole); + connect(m_detachAction, SIGNAL(triggered()), SLOT(onAction())); Core::Command *cmd = 0; - const DebuggerManagerActions actions = manager->debuggerManagerActions(); Core::ActionContainer *mstart = am->actionContainer(PE::M_DEBUG_STARTDEBUGGING); - cmd = am->registerAction(actions.continueAction, + cmd = am->registerAction(m_actions.continueAction, PE::DEBUG, QList<int>() << m_gdbRunningContext); mstart->addAction(cmd, CC::G_DEFAULT_ONE); @@ -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,98 +1517,238 @@ 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())); + QAction *act = qobject_cast<QAction *>(sender()); + QTC_ASSERT(act, return); + const int role = act->data().toInt(); + notifyCurrentEngine(role); +} - readSettings(); - m_uiSwitcher->initialize(); +void DebuggerPluginPrivate::languageChanged(const QString &language) +{ + 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); } -void DebuggerPlugin::attachCmdLine() +void DebuggerPluginPrivate::startExternalApplication() { - if (m_manager->state() != DebuggerNotReady) + 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 (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); + + 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 DebuggerPluginPrivate::notifyCurrentEngine(int role, const QVariant &value) +{ + QTC_ASSERT(m_commandWindow && m_commandWindow->model(), return); + m_commandWindow->model()->setData(QModelIndex(), value, role); +} + +void DebuggerPluginPrivate::attachExternalApplication() +{ + AttachExternalDialog dlg(mainWindow()); + if (dlg.exec() == QDialog::Accepted) + attachExternalApplication(dlg.attachPID(), dlg.executable(), QString()); +} + +void DebuggerPluginPrivate::attachExternalApplication + (qint64 pid, const QString &binary, const QString &crashParameter) +{ + if (pid == 0) { + QMessageBox::warning(mainWindow(), tr("Warning"), + tr("Cannot attach to PID 0")); return; } - if (!m_attachRemoteParameters.attachCore.isEmpty()) { - m_manager->showStatusMessage(tr("Attaching to core %1.").arg(m_attachRemoteParameters.attachCore)); - attachCore(m_attachRemoteParameters.attachCore, QString()); - } + DebuggerStartParameters sp; + sp.attachPID = pid; + sp.executable = binary; + sp.crashParameter = crashParameter; + sp.startMode = crashParameter.isEmpty() ? AttachExternal:AttachCrashedExternal; + startDebugger(m_debuggerRunControlFactory->create(sp)); } -/*! Activates the previous mode when the current mode is the debug mode. */ -void DebuggerPlugin::activatePreviousMode() +void DebuggerPluginPrivate::attachCore() { - Core::ModeManager *const modeManager = ICore::instance()->modeManager(); + AttachCoreDialog dlg(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()); +} - if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG) - && !m_previousMode.isEmpty()) { - modeManager->activateMode(m_previousMode); - m_previousMode.clear(); - } +void DebuggerPluginPrivate::attachCore(const QString &core, const QString &exe) +{ + DebuggerStartParameters sp; + sp.executable = exe; + sp.coreFile = core; + sp.displayName = tr("Core file: \"%1\"").arg(core); + sp.startMode = AttachCore; + startDebugger(createDebugger(sp)); } -void DebuggerPlugin::activateDebugMode() +void DebuggerPluginPrivate::startRemoteApplication() { - ModeManager *modeManager = ModeManager::instance(); - m_previousMode = modeManager->currentMode()->id(); - modeManager->activateMode(_(MODE_DEBUG)); + 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)); } -static bool isDebuggable(Core::IEditor *editor) +void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value) { - // 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"); + QTC_ASSERT(m_reverseToolButton, return); + m_reverseToolButton->setVisible(value.toBool()); + m_actions.reverseDirectionAction->setChecked(false); + m_actions.reverseDirectionAction->setEnabled(value.toBool()); } -TextEditor::ITextEditor *DebuggerPlugin::currentTextEditor() +void DebuggerPluginPrivate::attachRemoteTcf() { - EditorManager *editorManager = EditorManager::instance(); - if (!editorManager) - return 0; - Core::IEditor *editor = editorManager->currentEditor(); - return qobject_cast<ITextEditor*>(editor); + 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 DebuggerPlugin::editorOpened(Core::IEditor *editor) +void DebuggerPluginPrivate::editorOpened(Core::IEditor *editor) { if (!isDebuggable(editor)) return; @@ -1137,7 +1763,7 @@ void DebuggerPlugin::editorOpened(Core::IEditor *editor) this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); } -void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor) +void DebuggerPluginPrivate::editorAboutToClose(Core::IEditor *editor) { if (!isDebuggable(editor)) return; @@ -1152,15 +1778,12 @@ void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor) this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); } -void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor, +void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor, int lineNumber, QMenu *menu) { if (!isDebuggable(editor)) return; - BreakHandler *handler = m_manager->breakHandler(); - QTC_ASSERT(handler, return); - BreakpointData *data = 0; QString position; if (editor->property("DisassemblerView").toBool()) { @@ -1171,14 +1794,14 @@ void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor, 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,90 +1855,551 @@ 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); + + QTC_ASSERT(false, /* FIXME ABC */); + // d->m_engine->setToolTipExpression(mousePos, editor, cursorPos); +} + +ProjectExplorer::RunControl * +DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp) +{ + return m_debuggerRunControlFactory->create(sp); +} + +void DebuggerPluginPrivate::startDebugger(ProjectExplorer::RunControl *rc) +{ + 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 DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) +{ + //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(); +} + +static void changeFontSize(QWidget *widget, int size) +{ + QFont font = widget->font(); + font.setPointSize(size); + widget->setFont(font); +} + +void DebuggerPluginPrivate::fontSettingsChanged + (const TextEditor::FontSettings &settings) +{ + 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 DebuggerPluginPrivate::cleanupViews() +{ + 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 DebuggerPluginPrivate::setBusyCursor(bool busy) +{ + //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 DebuggerPluginPrivate::setSimpleDockWidgetArrangement(const QString &activeLanguage) +{ + 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; + + 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 = m_state == InferiorRunning + || m_state == InferiorRunningRequested + || m_state == InferiorStopping + || m_state == InferiorStopped; + + const bool starting = m_state == EngineStarting; + //const bool running = m_state == InferiorRunning; + + m_startExternalAction->setEnabled(!started && !starting); + m_attachExternalAction->setEnabled(!started && !starting); +#ifdef Q_OS_WIN + m_attachCoreAction->setEnabled(false); +#else + 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); + + const bool stoppable = m_state == InferiorRunning + || m_state == InferiorRunningRequested + || m_state == InferiorStopping + || m_state == InferiorStopped + || m_state == InferiorUnrunnable; + + const bool running = m_state == InferiorRunning; +// FIXME ABC +// if (running) +// threadsHandler()->notifyRunning(); + const bool stopped = m_state == InferiorStopped; + + if (stopped) + QApplication::alert(mainWindow(), 3000); + + //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 DebuggerPluginPrivate::resetLocation() +{ + delete m_locationMark; + m_locationMark = 0; +} + +void DebuggerPluginPrivate::gotoLocation(const QString &file, int line, bool setMarker) +{ + 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 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 + // also on shutdown. + + if (mode != m_debugMode) return; - m_manager->setToolTipExpression(point, editor, pos); + EditorManager *editorManager = EditorManager::instance(); + if (editorManager->currentEditor()) { + editorManager->currentEditor()->widget()->setFocus(); + + if (isCurrentProjectCppBased()) + m_uiSwitcher->setActiveLanguage(LANG_CPP); + } +} + +void DebuggerPluginPrivate::showSettingsDialog() +{ + Core::ICore::instance()->showOptionsDialog( + _(DEBUGGER_SETTINGS_CATEGORY), + _(DEBUGGER_COMMON_SETTINGS_ID)); +} + +void DebuggerPluginPrivate::dumpLog() +{ + 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(); +} + +void DebuggerPluginPrivate::clearStatusMessage() +{ + m_statusLabel->setText(m_lastPermanentStatusMessage); +} + +/*! Activates the previous mode when the current mode is the debug mode. */ +void DebuggerPluginPrivate::activatePreviousMode() +{ + Core::ModeManager *modeManager = ICore::instance()->modeManager(); + + if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG) + && !m_previousMode.isEmpty()) { + modeManager->activateMode(m_previousMode); + m_previousMode.clear(); + } +} + +void DebuggerPluginPrivate::activateDebugMode() +{ + //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 DebuggerPluginPrivate::sessionLoaded() +{ + //qDebug() << "SESSION LOADED"; + loadSessionData(); +} + +void DebuggerPluginPrivate::aboutToUnloadSession() +{ + // 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 DebuggerPluginPrivate::aboutToSaveSession() +{ + saveSessionData(); +} + +void DebuggerPluginPrivate::loadSessionData() +{ + // FIXME: Iterate? + //qDebug() << "\nLOADING SESSION DATA..."; + notifyCurrentEngine(RequestLoadSessionDataRole); + //qDebug() << "LOADED SESSION DATA\n"; +} + +void DebuggerPluginPrivate::saveSessionData() +{ + // FIXME: Iterate? + //qDebug() << "\nSAVING SESSION DATA..."; + notifyCurrentEngine(RequestSaveSessionDataRole); + //qDebug() << "SAVED SESSION DATA\n"; +} + +void DebuggerPluginPrivate::interruptDebuggingRequest() +{ + if (state() == InferiorRunning) + notifyCurrentEngine(RequestExecInterruptRole); + else + exitDebugger(); +} + +void DebuggerPluginPrivate::exitDebugger() +{ + // 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(m_debugMode, return); + QTC_ASSERT(d->m_debugMode, return); settings()->setValue(name, value); } QVariant DebuggerPlugin::configValue(const QString &name) const { - QTC_ASSERT(m_debugMode, return QVariant()); + 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 m_locationMark; - m_locationMark = 0; + delete d->m_locationMark; + d->m_locationMark = 0; } void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker) @@ -1331,7 +2413,7 @@ void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker) editor->setProperty("OpenedByDebugger", true); if (setMarker) { resetLocation(); - m_locationMark = new LocationMark(file, line); + d->m_locationMark = new LocationMark(file, line); } } @@ -1347,276 +2429,331 @@ void DebuggerPlugin::openTextEditor(const QString &titlePattern0, editorManager->activateEditor(editor); } -void DebuggerPlugin::handleStateChanged(int state) +void DebuggerPlugin::writeSettings() const { - // Prevent it from beeing triggered on setup. - if (!m_manager) - return; + QSettings *s = settings(); + DebuggerSettings::instance()->writeSettings(s); +} - const bool startIsContinue = (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>()); +void DebuggerPlugin::readSettings() +{ + //qDebug() << "PLUGIN READ SETTINGS"; + QSettings *s = settings(); + DebuggerSettings::instance()->readSettings(s); +} - const bool started = state == InferiorRunning - || state == InferiorRunningRequested - || state == InferiorStopping - || state == InferiorStopped; +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; +} - const bool starting = state == EngineStarting; - //const bool running = state == InferiorRunning; +void DebuggerPlugin::clearCppCodeModelSnapshot() +{ + d->m_codeModelSnapshot = CPlusPlus::Snapshot(); +} - const bool detachable = state == InferiorStopped - && m_manager->runControl()->sp().startMode != AttachCore; +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(); + } +} - m_startExternalAction->setEnabled(!started && !starting); - m_attachExternalAction->setEnabled(!started && !starting); -#ifdef Q_OS_WIN - m_attachCoreAction->setEnabled(false); -#else - m_attachCoreAction->setEnabled(!started && !starting); -#endif - m_startRemoteAction->setEnabled(!started && !starting); - m_detachAction->setEnabled(detachable); +void DebuggerPlugin::aboutToShutdown() +{ + writeSettings(); + if (d->m_uiSwitcher) + d->m_uiSwitcher->aboutToShutdown(); + //if (d->m_engine) + // d->m_engine->shutdown(); } -void DebuggerPlugin::languageChanged(const QString &language) +void DebuggerPlugin::addToWatchWindow() { - if (!m_manager) + 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); + } - const bool debuggerIsCPP = (language == Constants::LANG_CPP); +// FIXME: +// if (!exp.isEmpty()) +// d->m_watchHandler->watchExpression(exp); +} - m_startExternalAction->setVisible(debuggerIsCPP); - m_attachExternalAction->setVisible(debuggerIsCPP); - m_attachCoreAction->setVisible(debuggerIsCPP); - m_startRemoteAction->setVisible(debuggerIsCPP); - m_detachAction->setVisible(debuggerIsCPP); +void DebuggerPlugin::setBusyCursor(bool busy) +{ + d->setBusyCursor(busy); } -void DebuggerPlugin::writeSettings() const +/* +void DebuggerPlugin::gotoLocation(const StackFrame &frame, bool setMarker) { - QSettings *s = settings(); - DebuggerSettings::instance()->writeSettings(s); + 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::readSettings() +void DebuggerPlugin::showMessage(const QString &msg, int channel, int timeout) { - QSettings *s = settings(); - DebuggerSettings::instance()->readSettings(s); + //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; + } } -static bool isCurrentProjectCppBased() + +////////////////////////////////////////////////////////////////////// +// +// Register specific stuff +// +////////////////////////////////////////////////////////////////////// + +bool DebuggerPlugin::isReverseDebugging() const { - 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())); + return d->m_actions.reverseDirectionAction->isChecked(); } -void DebuggerPlugin::onModeChanged(IMode *mode) +QMessageBox *DebuggerPlugin::showMessageBox(int icon, const QString &title, + const QString &text, int buttons) { - // FIXME: This one gets always called, even if switching between modes - // different then the debugger mode. E.g. Welcome and Help mode and - // also on shutdown. + QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon), + title, text, QMessageBox::StandardButtons(buttons), mainWindow()); + mb->setAttribute(Qt::WA_DeleteOnClose); + mb->show(); + return mb; +} - if (mode != m_debugMode) - return; +void DebuggerPlugin::ensureLogVisible() +{ + QAction *action = d->m_outputDock->toggleViewAction(); + if (!action->isChecked()) + action->trigger(); +} - EditorManager *editorManager = EditorManager::instance(); - if (editorManager->currentEditor()) { - editorManager->currentEditor()->widget()->setFocus(); +QIcon DebuggerPlugin::locationMarkIcon() const +{ + return d->m_locationMarkIcon; +} - if (isCurrentProjectCppBased()) - m_uiSwitcher->setActiveLanguage(LANG_CPP); +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::showSettingsDialog() +void DebuggerPlugin::extensionsInitialized() { - Core::ICore::instance()->showOptionsDialog( - _(DEBUGGER_SETTINGS_CATEGORY), - _(DEBUGGER_COMMON_SETTINGS_ID)); + // 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(); } -void DebuggerPlugin::startExternalApplication() +void DebuggerPlugin::updateWatchersWindow(bool showWatchers, bool showReturn) { - 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) - return; + d->m_watchersWindow->setVisible(showWatchers); + d->m_returnWindow->setVisible(showReturn); +} - 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(' ')); +QWidget *DebuggerPlugin::mainWindow() const +{ + return d->m_uiSwitcher->mainWindow(); +} - if (dlg.breakAtMain()) - m_manager->breakByFunctionMain(); +ProjectExplorer::RunControl * +DebuggerPlugin::createDebugger(const DebuggerStartParameters &sp) +{ + return instance()->d->createDebugger(sp); +} - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE); +void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl) +{ + instance()->d->startDebugger(runControl); } -void DebuggerPlugin::attachExternalApplication() +void DebuggerPlugin::updateState(DebuggerEngine *engine) { - AttachExternalDialog dlg(m_uiSwitcher->mainWindow()); - if (dlg.exec() == QDialog::Accepted) - attachExternalApplication(dlg.attachPID(), dlg.executable(), QString()); + d->updateState(engine); } -void DebuggerPlugin::attachExternalApplication(qint64 pid, - const QString &binary, - const QString &crashParameter) +void DebuggerPlugin::activatePreviousMode() { - 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); + d->activatePreviousMode(); } -void DebuggerPlugin::attachCore() +void DebuggerPlugin::activateDebugMode() { - 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()); + d->activateDebugMode(); } -void DebuggerPlugin::attachCore(const QString &core, const QString &exe) +void DebuggerPlugin::exitDebugger() { - 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); + d->exitDebugger(); } -void DebuggerPlugin::startRemoteApplication() +int DebuggerPlugin::state() const { - 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(); + return d->state(); +} - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance() - ->startRunControl(runControl, PE::DEBUGMODE); +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::enableReverseDebuggingTriggered(const QVariant &value) +void DebuggerPlugin::runControlStarted(DebuggerRunControl *runControl) { - QTC_ASSERT(m_reverseToolButton, return); - m_reverseToolButton->setVisible(value.toBool()); - m_manager->debuggerManagerActions().reverseDirectionAction->setChecked(false); - m_manager->debuggerManagerActions().reverseDirectionAction->setEnabled(value.toBool()); + qDebug() << "RUNCONTROL STARTED: " << runControl; + d->connectEngine(runControl->engine()); +} + +void DebuggerPlugin::runControlFinished(DebuggerRunControl *runControl) +{ + Q_UNUSED(runControl); + qDebug() << "RUNCONTROL FINISHED: " << runControl; } -void DebuggerPlugin::attachRemoteTcf() +DebuggerEngine *DebuggerPlugin::sessionTemplate() +{ + return d->m_dummySessionEngine; +} + +////////////////////////////////////////////////////////////////////// +// +// Testing +// +////////////////////////////////////////////////////////////////////// + +/* +void DebuggerPlugin::runTest(const QString &fileName) { 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) - 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(); + sp.executable = fileName; + sp.processArgs = QStringList() << "--run-debuggee"; + sp.workingDirectory.clear(); + startDebugger(m_debuggerRunControlFactory->create(sp)); +} +*/ - if (RunControl *runControl = m_debuggerRunControlFactory->create(sp)) - ProjectExplorerPlugin::instance() - ->startRunControl(runControl, PE::DEBUGMODE); +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 cc895948b6..723784ad78 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 40686d8c1b..73579cad31 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 cc5ab4485b..432765423c 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 a7db1101a7..bfa3b8f6a1 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 9ec60a8a9c..a75e19bd63 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 4d1018cc66..f1d95e18d3 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 d5055633df..a1605e3499 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 642d790d5f..786250b7d9 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 e301d96c31..e8c967ef96 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 d69ee0c9e0..c8f6107762 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 2eca0a4f7d..20a58edf45 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 5e67016de7..ec24089ded 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 7677e1bfc6..225a8c3b03 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 59220c2029..a2d45dd178 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 610baf5798..afbd2362c3 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 09b4176c4c..1cbe7434fb 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 a9bac0ee9d..b417d688a0 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 88a26a3d96..0000000000 --- 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 bd57373f84..0000000000 --- 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 272e71e7df..3b0793af30 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 e1310fa544..ca2dbd95ec 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 5d0fc0cd67..cb821f7bd6 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 978c153769..5cce3eee13 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 ec34f9c42a..e7b2ad9677 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 9c91364372..b36b2d1508 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 6442a64a20..fc3a1c1ba1 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 1667d2383e..eec0e7d310 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 940c6b066e..164342b576 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 ad5502bd32..0818de9c95 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 04146aea6b..62837c4c5c 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 64eb3254d4..f7a81763c1 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 d188f1c3a6..ca73b14a59 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 cea1ae830f..580b023076 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 13e321faa4..2601b4a932 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 e73bb502f3..f77a0a1bfd 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 0000000000..670601f8d1 --- /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 0000000000..3e32ed3cf8 --- /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 e78cf93b36..d68d12a045 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 d9923b1f15..a2b92dd97f 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 2d7076f861..849db5c96f 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 bdfc7b5c11..3cb1787ead 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 28c5cd1029..1cbda98ad2 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 92791ffddf..562d00e1a7 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 29de3c7384..ad6ad41dc7 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 83eb6c38f2..b9ed4c9b20 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 d16502ebf4..41f5bb6cdc 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 3cd67a962c..a049cabe5c 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 10e242a301..882ef1da9b 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 2c2dae34fb..8567ae6d83 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 6f4e2d95c8..2955123d2e 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 7d2f8248a9..bf6b34e02d 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 f8062324ef..cdc9067430 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 3652a31199..63a5a57835 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 daf8507e67..1c37800e18 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 243aaad86a..a39bff63de 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 b08f928203..1970b3f8c6 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 0b98b7e90f..04a782dd1e 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 92dbcf9800..6ea396003d 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 12177e2d71..940520817a 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 e5a6026cd2..b4d377a123 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 cdb4902060..77f8c1a588 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), |