Commit 1afea78c authored by hjk's avatar hjk

debugger: convert register handler/window architecture

parent 702e9f3f
...@@ -31,26 +31,20 @@ ...@@ -31,26 +31,20 @@
#include "breakpointmarker.h" #include "breakpointmarker.h"
#include "debuggeractions.h" #include "debuggeractions.h"
#include "debuggerengine.h"
#include "debuggerplugin.h" #include "debuggerplugin.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include "threadshandler.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); } static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
static Breakpoints m_bp;
// FIXME this is only static because it might map to bps in the above list
static QHash<quint64,BreakpointMarker*> m_markers;
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// //
// BreakHandler // BreakHandler
......
...@@ -117,7 +117,7 @@ private: ...@@ -117,7 +117,7 @@ private:
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
void markerUpdated(BreakpointMarker *, int lineNumber); void markerUpdated(BreakpointMarker *marker, int lineNumber);
void loadBreakpoints(); void loadBreakpoints();
void saveBreakpoints(); void saveBreakpoints();
void removeBreakpointHelper(int index); void removeBreakpointHelper(int index);
...@@ -138,7 +138,8 @@ private: ...@@ -138,7 +138,8 @@ private:
mutable BreakpointData *m_lastFound; mutable BreakpointData *m_lastFound;
mutable bool m_lastFoundQueried; mutable bool m_lastFoundQueried;
QList<BreakpointData *> m_bp; Breakpoints m_bp;
QHash<quint64, BreakpointMarker *> m_markers;
}; };
} // namespace Internal } // namespace Internal
......
...@@ -239,14 +239,6 @@ enum ModelRoles ...@@ -239,14 +239,6 @@ enum ModelRoles
RequestAllSymbolsRole, RequestAllSymbolsRole,
RequestOpenFileRole, RequestOpenFileRole,
// Registers
RegisterNumberBaseRole, // Currently used number base
RegisterAddressRole, // Start value for opening memory view
RegisterChangedRole, // Used for painting changed values
RegisterBigNumberRole, // Register is a big integer that cannot be handled as quint64.
RequestSetRegisterRole,
RequestReloadRegistersRole,
// Snapshots // Snapshots
SnapshotCapabilityRole, SnapshotCapabilityRole,
RequestCreateSnapshotRole, RequestCreateSnapshotRole,
......
...@@ -225,7 +225,7 @@ public: ...@@ -225,7 +225,7 @@ public:
m_targetState(DebuggerNotReady), m_targetState(DebuggerNotReady),
m_commandHandler(engine), m_commandHandler(engine),
m_modulesHandler(engine), m_modulesHandler(engine),
m_registerHandler(engine), m_registerHandler(),
m_sourceFilesHandler(engine), m_sourceFilesHandler(engine),
m_stackHandler(engine), m_stackHandler(engine),
m_threadsHandler(engine), m_threadsHandler(engine),
...@@ -534,9 +534,9 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value) ...@@ -534,9 +534,9 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
reloadModules(); reloadModules();
break; break;
case RequestReloadRegistersRole: //case RequestReloadRegistersRole:
reloadRegisters(); // reloadRegisters();
break; // break;
case RequestExecDetachRole: case RequestExecDetachRole:
detachDebugger(); detachDebugger();
......
...@@ -226,7 +226,7 @@ ...@@ -226,7 +226,7 @@
// * * + // * * +
// EngineShutdownRequested + // EngineShutdownRequested +
// + + // + +
// (calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+' // (calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
// | | // | |
// | | // | |
// {notify- {notify- // {notify- {notify-
...@@ -296,7 +296,7 @@ sg1: } ...@@ -296,7 +296,7 @@ sg1: }
// //
// //
// GdbEngine::setupInferior() // GdbEngine::setupInferior()
// + // +
// (calls *Adapter->prepareInferior()) // (calls *Adapter->prepareInferior())
// | | // | |
// | `---> handlePrepareInferiorFailed() // | `---> handlePrepareInferiorFailed()
...@@ -305,7 +305,7 @@ sg1: } ...@@ -305,7 +305,7 @@ sg1: }
// | // |
// handleInferiorPrepared() // handleInferiorPrepared()
// + // +
// {notifyInferiorSetupOk} // {notifyInferiorSetupOk}
...@@ -429,7 +429,7 @@ struct AttachRemoteParameters ...@@ -429,7 +429,7 @@ struct AttachRemoteParameters
quint64 attachPid; quint64 attachPid;
QString attachTarget; // core file name or server:port QString attachTarget; // core file name or server:port
// Event handle for attaching to crashed Windows processes. // Event handle for attaching to crashed Windows processes.
quint64 winCrashEvent; quint64 winCrashEvent;
}; };
...@@ -863,8 +863,12 @@ public slots: ...@@ -863,8 +863,12 @@ public slots:
{ if (on) notifyCurrentEngine(RequestReloadSourceFilesRole); } { if (on) notifyCurrentEngine(RequestReloadSourceFilesRole); }
void modulesDockToggled(bool on) void modulesDockToggled(bool on)
{ if (on) notifyCurrentEngine(RequestReloadModulesRole); } { if (on) notifyCurrentEngine(RequestReloadModulesRole); }
void registerDockToggled(bool on) void registerDockToggled(bool on)
{ if (on) notifyCurrentEngine(RequestReloadRegistersRole); } {
if (on && m_currentEngine)
m_currentEngine->reloadRegisters();
}
void synchronizeBreakpoints() void synchronizeBreakpoints()
{ {
...@@ -1767,7 +1771,7 @@ void DebuggerPluginPrivate::startExternalApplication() ...@@ -1767,7 +1771,7 @@ void DebuggerPluginPrivate::startExternalApplication()
void DebuggerPluginPrivate::notifyCurrentEngine(int role, const QVariant &value) void DebuggerPluginPrivate::notifyCurrentEngine(int role, const QVariant &value)
{ {
QTC_ASSERT(m_commandWindow, return); QTC_ASSERT(m_commandWindow, return);
if (m_commandWindow->model()) if (m_commandWindow->model())
m_commandWindow->model()->setData(QModelIndex(), value, role); m_commandWindow->model()->setData(QModelIndex(), value, role);
} }
...@@ -2059,40 +2063,54 @@ void DebuggerPluginPrivate::startDebugger(RunControl *rc) ...@@ -2059,40 +2063,54 @@ void DebuggerPluginPrivate::startDebugger(RunControl *rc)
ProjectExplorerPlugin::instance()->startRunControl(rc, PE::DEBUGMODE); ProjectExplorerPlugin::instance()->startRunControl(rc, PE::DEBUGMODE);
} }
class DummyEngine : public DebuggerEngine
{
Q_OBJECT
public:
DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
virtual ~DummyEngine() {}
virtual void setupEngine() {}
virtual void setupInferior() {}
virtual void runEngine() {}
virtual void shutdownEngine() {}
virtual void shutdownInferior() {}
virtual void executeDebuggerCommand(const QString &) {}
virtual unsigned debuggerCapabilities() const { return 0; }
};
void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify) void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify)
{ {
static Debugger::DummyEngine dummyEngine;
if (!engine)
engine = &dummyEngine;
if (m_currentEngine == engine) if (m_currentEngine == engine)
return; return;
if (engine) { m_currentEngine = engine;
if (notify)
notifyCurrentEngine(RequestActivationRole, false); if (notify)
m_commandWindow->setModel(engine->commandModel()); notifyCurrentEngine(RequestActivationRole, false);
m_localsWindow->setModel(engine->localsModel());
m_modulesWindow->setModel(engine->modulesModel()); m_commandWindow->setModel(engine->commandModel());
m_registerWindow->setModel(engine->registerModel()); m_localsWindow->setModel(engine->localsModel());
m_returnWindow->setModel(engine->returnModel()); m_modulesWindow->setModel(engine->modulesModel());
m_sourceFilesWindow->setModel(engine->sourceFilesModel()); m_registerWindow->setModel(engine->registerModel());
m_stackWindow->setModel(engine->stackModel()); m_returnWindow->setModel(engine->returnModel());
m_threadsWindow->setModel(engine->threadsModel()); m_sourceFilesWindow->setModel(engine->sourceFilesModel());
m_threadBox->setModel(engine->threadsModel()); m_stackWindow->setModel(engine->stackModel());
m_threadBox->setModelColumn(ThreadData::NameColumn); m_threadsWindow->setModel(engine->threadsModel());
m_watchersWindow->setModel(engine->watchersModel()); m_threadBox->setModel(engine->threadsModel());
if (notify) m_threadBox->setModelColumn(ThreadData::NameColumn);
notifyCurrentEngine(RequestActivationRole, true); m_watchersWindow->setModel(engine->watchersModel());
} else {
m_commandWindow->setModel(0); if (notify)
m_localsWindow->setModel(0); notifyCurrentEngine(RequestActivationRole, true);
m_modulesWindow->setModel(0);
m_registerWindow->setModel(0);
m_returnWindow->setModel(0);
m_sourceFilesWindow->setModel(0);
m_stackWindow->setModel(0);
m_threadsWindow->setModel(0);
m_threadBox->setModel(0);
m_threadBox->setModelColumn(ThreadData::NameColumn);
m_watchersWindow->setModel(0);
}
} }
static void changeFontSize(QWidget *widget, qreal size) static void changeFontSize(QWidget *widget, qreal size)
...@@ -2542,7 +2560,7 @@ void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression) ...@@ -2542,7 +2560,7 @@ void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression)
} }
void DebuggerPluginPrivate::openMemoryEditor() void DebuggerPluginPrivate::openMemoryEditor()
{ {
AddressDialog dialog; AddressDialog dialog;
if (dialog.exec() != QDialog::Accepted) if (dialog.exec() != QDialog::Accepted)
return; return;
...@@ -2856,6 +2874,11 @@ Internal::BreakHandler *DebuggerPlugin::breakHandler() const ...@@ -2856,6 +2874,11 @@ Internal::BreakHandler *DebuggerPlugin::breakHandler() const
return d->m_breakHandler; return d->m_breakHandler;
} }
DebuggerEngine *DebuggerPlugin::currentEngine() const
{
return d->m_currentEngine;
}
void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &) void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &)
{ {
if (options.isEmpty()) if (options.isEmpty())
......
...@@ -91,6 +91,7 @@ public: ...@@ -91,6 +91,7 @@ public:
void openTextEditor(const QString &titlePattern, const QString &contents); void openTextEditor(const QString &titlePattern, const QString &contents);
Internal::BreakHandler *breakHandler() const; Internal::BreakHandler *breakHandler() const;
DebuggerEngine *currentEngine() const;
public slots: public slots:
void clearCppCodeModelSnapshot(); void clearCppCodeModelSnapshot();
......
...@@ -28,24 +28,8 @@ ...@@ -28,24 +28,8 @@
**************************************************************************/ **************************************************************************/
#include "registerhandler.h" #include "registerhandler.h"
#include "debuggeractions.h"
#include "debuggeragents.h"
#include "debuggerconstants.h"
#include "debuggerengine.h"
#include "watchdelegatewidgets.h" #include "watchdelegatewidgets.h"
#include <utils/qtcassert.h>
#include <QtCore/QAbstractTableModel>
#include <QtCore/QDebug>
#include <QtGui/QColor>
using namespace Debugger;
using namespace Debugger::Internal;
using namespace Debugger::Constants;
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
// //
...@@ -53,8 +37,11 @@ using namespace Debugger::Constants; ...@@ -53,8 +37,11 @@ using namespace Debugger::Constants;
// //
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
RegisterHandler::RegisterHandler(DebuggerEngine *engine) namespace Debugger {
: m_engine(engine), m_base(15) namespace Internal {
RegisterHandler::RegisterHandler()
: m_base(-1)
{ {
setNumberBase(16); setNumberBase(16);
} }
...@@ -70,53 +57,36 @@ int RegisterHandler::columnCount(const QModelIndex &parent) const ...@@ -70,53 +57,36 @@ int RegisterHandler::columnCount(const QModelIndex &parent) const
} }
// Editor value: Preferably number, else string. // Editor value: Preferably number, else string.
QVariant RegisterHandler::editValue(const Register &reg) QVariant Register::editValue() const
{ {
bool ok = true; bool ok = true;
// Try to convert to number? // Try to convert to number?
const qulonglong value = reg.value.toULongLong(&ok, 0); // Autodetect format const qulonglong v = value.toULongLong(&ok, 0); // Autodetect format
if (ok) if (ok)
return QVariant(value); return QVariant(v);
return QVariant(reg.value); return QVariant(value);
} }
// Editor value: Preferably padded number, else padded string. // Editor value: Preferably padded number, else padded string.
inline QString RegisterHandler::displayValue(const Register &reg) const QString Register::displayValue(int base, int strlen) const
{ {
const QVariant editV = RegisterHandler::editValue(reg); const QVariant editV = editValue();
if (editV.type() == QVariant::ULongLong) if (editV.type() == QVariant::ULongLong)
return QString::fromAscii("%1").arg(editV.toULongLong(), m_strlen, m_base); return QString::fromAscii("%1").arg(editV.toULongLong(), strlen, base);
const QString stringValue = editV.toString(); const QString stringValue = editV.toString();
if (stringValue.size() < m_strlen) if (stringValue.size() < strlen)
return QString(m_strlen - stringValue.size(), QLatin1Char(' ')) + reg.value; return QString(strlen - stringValue.size(), QLatin1Char(' ')) + value;
return stringValue; return stringValue;
} }
QVariant RegisterHandler::data(const QModelIndex &index, int role) const QVariant RegisterHandler::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_registers.size()) if (!index.isValid() || index.row() >= m_registers.size())
return QVariant(); return QVariant();
const Register &reg = m_registers.at(index.row()); const Register &reg = m_registers.at(index.row());
switch (role) { switch (role) {
case RegisterAddressRole: {
// Return some address associated with the register. Autodetect format
const QVariant editV = RegisterHandler::editValue(reg);
return editV.type() == QVariant::ULongLong ? editV : QVariant();
}
case Qt::DisplayRole: case Qt::DisplayRole:
switch (index.column()) { switch (index.column()) {
case 0: { case 0: {
...@@ -124,18 +94,12 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const ...@@ -124,18 +94,12 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
return QVariant(padding + reg.name + padding); return QVariant(padding + reg.name + padding);
} }
case 1: // Display: Pad value for alignment case 1: // Display: Pad value for alignment
return displayValue(reg); return reg.displayValue(m_base, m_strlen);
} // switch column } // switch column
case Qt::EditRole: // Edit: Unpadded for editing case Qt::EditRole: // Edit: Unpadded for editing
return RegisterHandler::editValue(reg); return reg.editValue();
case Qt::TextAlignmentRole: case Qt::TextAlignmentRole:
return index.column() == 1 ? QVariant(Qt::AlignRight) : QVariant(); return index.column() == 1 ? QVariant(Qt::AlignRight) : QVariant();
case RegisterChangedRole:
return QVariant(reg.changed);
case RegisterBigNumberRole: // Editor: Can it be handled as quint64?
return editValue(reg).type() != QVariant::ULongLong;
case RegisterNumberBaseRole: // Big integers are assumed to be hexadecimal
return editValue(reg).type() == QVariant::ULongLong ? m_base : 16;
default: default:
break; break;
} }
...@@ -161,31 +125,12 @@ Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const ...@@ -161,31 +125,12 @@ Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const
const Qt::ItemFlags notEditable = Qt::ItemIsSelectable|Qt::ItemIsEnabled; const Qt::ItemFlags notEditable = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
// Can edit registers if they are hex numbers and not arrays. // Can edit registers if they are hex numbers and not arrays.
if (idx.column() == 1 && IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value)) if (idx.column() == 1
&& IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value))
return notEditable | Qt::ItemIsEditable; return notEditable | Qt::ItemIsEditable;
return notEditable; 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() void RegisterHandler::removeAll()
{ {
m_registers.clear(); m_registers.clear();
...@@ -232,3 +177,6 @@ void RegisterHandler::setNumberBase(int base) ...@@ -232,3 +177,6 @@ void RegisterHandler::setNumberBase(int base)
emit reset(); emit reset();
} }
} }
} // namespace Internal
} // namespace Debugger
...@@ -34,14 +34,16 @@ ...@@ -34,14 +34,16 @@
#include <QtCore/QVector> #include <QtCore/QVector>
namespace Debugger { namespace Debugger {
class DebuggerEngine;
namespace Internal { namespace Internal {
class Register class Register
{ {
public: public:
Register() : changed(true) {} Register() : changed(true) {}
Register(QByteArray const &name_) : name(name_), changed(true) {} Register(const QByteArray &name_) : name(name_), changed(true) {}
QVariant editValue() const;
QString displayValue(int base, int strlen) const;
public: public:
QByteArray name; QByteArray name;
...@@ -60,7 +62,7 @@ class RegisterHandler : public QAbstractTableModel ...@@ -60,7 +62,7 @@ class RegisterHandler : public QAbstractTableModel
Q_OBJECT Q_OBJECT
public: public:
explicit RegisterHandler(DebuggerEngine *engine); RegisterHandler();
QAbstractItemModel *model() { return this; } QAbstractItemModel *model() { return this; }
...@@ -68,22 +70,20 @@ public: ...@@ -68,22 +70,20 @@ public:
void setRegisters(const Registers &registers); void setRegisters(const Registers &registers);
void setAndMarkRegisters(const Registers &registers); void setAndMarkRegisters(const Registers &registers);
Registers registers() const; Registers registers() const;
Register registerAt(int i) const { return m_registers.at(i); }
void removeAll(); void removeAll();
Q_SLOT void setNumberBase(int base); Q_SLOT void setNumberBase(int base);
int numberBase() const { return m_base; }
private: private:
void calculateWidth(); void calculateWidth();
inline QString displayValue(const Register &reg) const;
static QVariant editValue(const Register &reg);
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) 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, QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const; int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &idx) const; Qt::ItemFlags flags(const QModelIndex &idx) const;
DebuggerEngine *m_engine; // Not owned.
Registers m_registers; Registers m_registers;
int m_base;