Commit 8e627151 authored by hjk's avatar hjk

debugger: move logical ownership of breakhandler from engines to plugin

parent 05c9ea02
......@@ -57,7 +57,7 @@ static QHash<quint64,BreakpointMarker*> m_markers;
//
//////////////////////////////////////////////////////////////////
BreakHandler::BreakHandler(Debugger::DebuggerEngine *engine)
BreakHandler::BreakHandler()
: m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")),
m_disabledBreakpointIcon(_(":/debugger/images/breakpoint_disabled_16.png")),
m_pendingBreakPointIcon(_(":/debugger/images/breakpoint_pending_16.png")),
......@@ -65,12 +65,9 @@ BreakHandler::BreakHandler(Debugger::DebuggerEngine *engine)
m_emptyIcon(_(":/debugger/images/breakpoint_pending_16.png")),
//m_emptyIcon(_(":/debugger/images/debugger_empty_14.png")),
m_watchpointIcon(_(":/debugger/images/watchpoint.png")),
m_engine(engine),
m_lastFound(0),
m_lastFoundQueried(false)
{
QTC_ASSERT(m_engine, /**/);
}
{}
BreakHandler::~BreakHandler()
{
......@@ -285,53 +282,12 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
{
static const QString empty = QString(QLatin1Char('-'));
switch (role) {
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();
BreakpointData *data = at(mi.row());
if (role == BreakpointRole)
return qVariantFromValue(data);
if (role == BreakpointUseFullPathRole)
return data->useFullPath;
if (role == BreakpointFileNameRole)
return data->fileName;
if (role == BreakpointEnabledRole)
return data->enabled;
if (role == BreakpointFunctionNameRole)
return data->funcName;
if (role == BreakpointConditionRole)
return data->condition;
if (role == BreakpointIgnoreCountRole)
return data->ignoreCount ? QVariant(data->ignoreCount) : QVariant(QString());
if (role == BreakpointThreadSpecRole)
return data->threadSpec;
switch (mi.column()) {
case 0:
if (role == Qt::DisplayRole) {
......@@ -438,102 +394,12 @@ Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
// }
}
bool BreakHandler::setData(const QModelIndex &index, const QVariant &value, int role)
{
switch (role) {
case RequestActivateBreakpointRole: {
const BreakpointData *data = at(value.toInt());
QTC_ASSERT(data, return false);
m_engine->gotoLocation(data->markerFileName(),
data->markerLineNumber(), false);
return true;
}
case RequestRemoveBreakpointByIndexRole: {
BreakpointData *data = at(value.toInt());
QTC_ASSERT(data, return false);
removeBreakpoint(data);
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;
case RequestBreakpointRole:
QTC_ASSERT(m_engine, return false);
BreakpointData *data = value.value<BreakpointData *>();
if (data->funcName == "main") {
m_engine->breakByFunctionMain();
} else {
appendBreakpoint(data);
m_engine->attemptBreakpointSynchronization();
}
return true;
}
BreakpointData *data = at(index.row());
switch (role) {
case BreakpointEnabledRole:
if (data->enabled != value.toBool())
toggleBreakpointEnabled(data);
return true;
case BreakpointUseFullPathRole:
if (data->useFullPath != value.toBool()) {
data->useFullPath = value.toBool();
emit layoutChanged();
}
return true;
case BreakpointConditionRole: {
QByteArray val = value.toString().toLatin1();
if (val != data->condition) {
data->condition = val;
emit layoutChanged();
}
}
return true;
case BreakpointIgnoreCountRole: {
const int ignoreCount = value.toInt();
if (ignoreCount != data->ignoreCount) {
data->ignoreCount = ignoreCount;
emit layoutChanged();
}
}
return true;
case BreakpointThreadSpecRole: {
QByteArray val = value.toString().toLatin1();
if (val != data->threadSpec) {
data->threadSpec = val;
emit layoutChanged();
}
}
return true;
}
return false;
}
void BreakHandler::reinsertBreakpoint(BreakpointData *data)
{
// FIXME: Use some more direct method?
appendBreakpoint(data->clone());
removeBreakpoint(data);
m_engine->attemptBreakpointSynchronization();
synchronizeBreakpoints();
emit layoutChanged();
}
......@@ -603,7 +469,7 @@ void BreakHandler::toggleBreakpointEnabled(BreakpointData *data)
removeMarker(data); // Force icon update.
updateMarker(data);
emit layoutChanged();
m_engine->attemptBreakpointSynchronization();
synchronizeBreakpoints();
}
void BreakHandler::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
......@@ -673,19 +539,19 @@ void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber,
data->setMarkerLineNumber(lineNumber);
appendBreakpoint(data);
}
m_engine->attemptBreakpointSynchronization();
synchronizeBreakpoints();
}
void BreakHandler::saveSessionData()
{
QTC_ASSERT(m_engine->isSessionEngine(), return);
// FIXME QTC_ASSERT(m_engine->isSessionEngine(), return);
saveBreakpoints();
}
void BreakHandler::loadSessionData()
{
QTC_ASSERT(m_engine->isSessionEngine(), return);
foreach(BreakpointData *bp, m_bp) {
// FIXME QTC_ASSERT(m_engine->isSessionEngine(), return);
foreach (BreakpointData *bp, m_bp) {
delete m_markers.take(bp->id);
}
qDeleteAll(m_bp);
......@@ -714,15 +580,15 @@ void BreakHandler::breakByFunction(const QString &functionName)
bool BreakHandler::isActive() const
{
return m_engine->isActive();
return true; // FIXME m_engine->isActive();
}
void BreakHandler::initializeFromTemplate(BreakHandler *other)
{
Q_UNUSED(other)
m_inserted.clear();
foreach(BreakpointData *data, m_bp) {
if (m_engine->acceptsBreakpoint(data)) {
foreach (BreakpointData *data, m_bp) {
if (true /* FIXME m_engine->acceptsBreakpoint(data) */) {
BreakpointMarker *marker = m_markers.value(data->id);
if (marker)
marker->m_handler = this;
......@@ -752,5 +618,10 @@ int BreakHandler::indexOf(BreakpointData *data)
return m_bp.indexOf(data);
}
void BreakHandler::synchronizeBreakpoints()
{
emit breakpointSynchronizationRequested();
}
} // namespace Internal
} // namespace Debugger
......@@ -54,7 +54,7 @@ class BreakHandler : public QAbstractTableModel
Q_OBJECT
public:
explicit BreakHandler(DebuggerEngine *engine);
BreakHandler();
~BreakHandler();
void removeAllBreakpoints();
......@@ -96,13 +96,16 @@ public:
bool useMarkerPosition = true);
BreakpointData *findBreakpoint(quint64 address) const;
public slots:
void appendBreakpoint(BreakpointData *data);
void reinsertBreakpoint(BreakpointData *data);
void toggleBreakpointEnabled(BreakpointData *data);
void breakByFunction(const QString &functionName);
void removeBreakpoint(int index);
void removeBreakpoint(BreakpointData *data);
void synchronizeBreakpoints();
signals:
void breakpointSynchronizationRequested();
private:
friend class BreakpointMarker;
......@@ -111,7 +114,6 @@ 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 &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
......@@ -127,7 +129,6 @@ private:
const QIcon m_emptyIcon;
const QIcon m_watchpointIcon;
Debugger::DebuggerEngine *m_engine; // Not owned.
Breakpoints m_inserted; // Lately inserted breakpoints.
Breakpoints m_removed; // Lately removed breakpoints.
Breakpoints m_enabled; // Lately enabled breakpoints.
......@@ -136,6 +137,8 @@ private:
// Hack for BreakWindow::findSimilarBreakpoint
mutable BreakpointData *m_lastFound;
mutable bool m_lastFoundQueried;
QList<BreakpointData *> m_bp;
};
} // namespace Internal
......
......@@ -31,6 +31,7 @@
#include "breakhandler.h"
#include "debuggeractions.h"
#include "debuggerplugin.h"
#include "debuggerconstants.h"
#include "ui_breakpoint.h"
#include "ui_breakcondition.h"
......@@ -55,6 +56,38 @@
namespace Debugger {
namespace Internal {
static DebuggerPlugin *plugin()
{
return DebuggerPlugin::instance();
}
static BreakHandler *breakHandler()
{
return plugin()->breakHandler();
}
static BreakpointData *breakpointAt(int index)
{
BreakHandler *handler = breakHandler();
QTC_ASSERT(handler, return 0);
return handler->at(index);
}
static void synchronizeBreakpoints()
{
BreakHandler *handler = breakHandler();
QTC_ASSERT(handler, return);
handler->synchronizeBreakpoints();
}
static void appendBreakpoint(BreakpointData *data)
{
BreakHandler *handler = breakHandler();
QTC_ASSERT(handler, return);
handler->appendBreakpoint(data);
}
///////////////////////////////////////////////////////////////////////
//
// BreakpointDialog
......@@ -236,8 +269,8 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
si = normalizeIndexes(si);
const int rowCount = model()->rowCount();
const unsigned engineCapabilities =
model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
const unsigned engineCapabilities = BreakOnThrowAndCatchCapability;
// FIXME BP: model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
deleteAction->setEnabled(si.size() > 0);
......@@ -280,7 +313,8 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
new QAction(tr("Edit Breakpoint..."), &menu);
editBreakpointAction->setEnabled(si.size() > 0);
int threadId = model()->data(QModelIndex(), CurrentThreadIdRole).toInt();
int threadId = 0;
// FIXME BP: m_engine->threadsHandler()->currentThreadId();
QString associateTitle = threadId == -1
? tr("Associate Breakpoint With All Threads")
: tr("Associate Breakpoint With Thread %1").arg(threadId);
......@@ -289,13 +323,12 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *synchronizeAction =
new QAction(tr("Synchronize Breakpoints"), &menu);
synchronizeAction->setEnabled(
model()->data(QModelIndex(), EngineActionsEnabledRole).toBool());
synchronizeAction->setEnabled(plugin()->hasSnapshots());
QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
QModelIndex idx2 = idx0.sibling(idx0.row(), 2);
bool enabled = si.isEmpty()
|| idx0.data(BreakpointEnabledRole).toBool();
BreakpointData *data = breakpointAt(idx0.row());
bool enabled = si.isEmpty() || (data && data->enabled);
const QString str5 = si.size() > 1
? enabled
......@@ -357,29 +390,40 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
else if (act == associateBreakpointAction)
associateBreakpoint(si, threadId);
else if (act == synchronizeAction)
setModelData(RequestSynchronizeBreakpointsRole);
synchronizeBreakpoints();
else if (act == toggleEnabledAction)
setBreakpointsEnabled(si, !enabled);
else if (act == addBreakpointAction)
addBreakpoint();
else if (act == breakAtThrowAction)
setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::throwFunction));
else if (act == breakAtCatchAction)
setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::catchFunction));
else if (act == breakAtThrowAction) {
BreakpointData *data = new BreakpointData;
data->funcName = BreakpointData::throwFunction;
appendBreakpoint(data);
} else if (act == breakAtCatchAction) {
BreakpointData *data = new BreakpointData;
data->funcName = BreakpointData::catchFunction;
appendBreakpoint(data);
}
}
void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
{
foreach (const QModelIndex &index, list)
setModelData(BreakpointEnabledRole, enabled, index);
setModelData(RequestSynchronizeBreakpointsRole);
foreach (const QModelIndex &index, list) {
BreakpointData *data = breakpointAt(index.row());
QTC_ASSERT(data, continue);
data->enabled = enabled;
}
synchronizeBreakpoints();
}
void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
{
foreach (const QModelIndex &index, list)
setModelData(BreakpointUseFullPathRole, fullpath, index);
setModelData(RequestSynchronizeBreakpointsRole);
foreach (const QModelIndex &index, list) {
BreakpointData *data = breakpointAt(index.row());
QTC_ASSERT(data, continue);
data->useFullPath = fullpath;
}
synchronizeBreakpoints();
}
void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes)
......@@ -395,15 +439,19 @@ void BreakWindow::deleteBreakpoints(QList<int> list)
{
if (list.empty())
return;
BreakHandler *handler = breakHandler();
const int firstRow = list.front();
qSort(list.begin(), list.end());
for (int i = list.size(); --i >= 0; )
setModelData(RequestRemoveBreakpointByIndexRole, list.at(i));
for (int i = list.size(); --i >= 0; ) {
BreakpointData *data = breakpointAt(i);
QTC_ASSERT(data, continue);
handler->removeBreakpoint(data);
}
const int row = qMin(firstRow, model()->rowCount() - 1);
if (row >= 0)
setCurrentIndex(model()->index(row, 0));
setModelData(RequestSynchronizeBreakpointsRole);
synchronizeBreakpoints();
}
bool BreakWindow::editBreakpoint(BreakpointData *data, QWidget *parent)
......@@ -416,7 +464,7 @@ void BreakWindow::addBreakpoint()
{
BreakpointData *data = new BreakpointData();
if (editBreakpoint(data, this))
setModelData(RequestBreakpointRole, QVariant::fromValue(data));
appendBreakpoint(data);
else
delete data;
}
......@@ -424,16 +472,12 @@ void BreakWindow::addBreakpoint()
void BreakWindow::editBreakpoints(const QModelIndexList &list)
{
QTC_ASSERT(!list.isEmpty(), return);
if (list.size() == 1) {
const QVariant dataV = model()->data(list.at(0), BreakpointRole);
QTC_ASSERT(qVariantCanConvert<BreakpointData *>(dataV), return );
BreakpointData *data = qvariant_cast<BreakpointData *>(dataV);
if (editBreakpoint(data, this)) {
// FIXME: nasty MVC violation
BreakHandler * handler = qobject_cast<BreakHandler *>(model());
if (handler)
handler->reinsertBreakpoint(data);
}
BreakpointData *data = breakpointAt(0);
QTC_ASSERT(data, return);
if (editBreakpoint(data, this))
breakHandler()->reinsertBreakpoint(data);
return;
}
......@@ -442,14 +486,16 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
Ui::BreakCondition ui;
ui.setupUi(&dlg);
dlg.setWindowTitle(tr("Edit Breakpoint Properties"));
ui.lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
ui.lineEditIgnoreCount->setValidator(
new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
const QModelIndex idx = list.front();
QAbstractItemModel *m = model();
BreakpointData *data = breakpointAt(idx.row());
QTC_ASSERT(data, return);
const QString oldCondition = m->data(idx, BreakpointConditionRole).toString();
const QString oldIgnoreCount = m->data(idx, BreakpointIgnoreCountRole).toString();
const QString oldThreadSpec = m->data(idx, BreakpointThreadSpecRole).toString();
const QString oldCondition = QString::fromLatin1(data->condition);
const QString oldIgnoreCount = QString::number(data->ignoreCount);
const QString oldThreadSpec = QString::fromLatin1(data->threadSpec);
ui.lineEditCondition->setText(oldCondition);
ui.lineEditIgnoreCount->setText(oldIgnoreCount);
......@@ -468,21 +514,26 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
return;
foreach (const QModelIndex &idx, list) {
m->setData(idx, newCondition, BreakpointConditionRole);
m->setData(idx, newIgnoreCount, BreakpointIgnoreCountRole);
m->setData(idx, newThreadSpec, BreakpointThreadSpecRole);
BreakpointData *data = breakpointAt(idx.row());
QTC_ASSERT(data, continue);
data->condition = newCondition.toLatin1();
data->ignoreCount = newIgnoreCount.toInt();
data->threadSpec = newThreadSpec.toLatin1();
}
setModelData(RequestSynchronizeBreakpointsRole);
synchronizeBreakpoints();
}
void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId)
{
QString str;
QByteArray condition;
if (threadId != -1)
str = QString::number(threadId);
foreach (const QModelIndex &index, list)
setModelData(BreakpointThreadSpecRole, str, index);
setModelData(RequestSynchronizeBreakpointsRole);
condition = QByteArray::number(threadId);
foreach (const QModelIndex &index, list) {
BreakpointData *data = breakpointAt(index.row());
QTC_ASSERT(data, continue);
data->condition = condition;
}
synchronizeBreakpoints();
}
void BreakWindow::resizeColumnsToContents()
......@@ -502,17 +553,12 @@ void BreakWindow::setAlwaysResizeColumnsToContents(bool on)
void BreakWindow::rowActivated(const QModelIndex &index)
{
setModelData(RequestActivateBreakpointRole, index.row());
BreakpointData *data = breakpointAt(index.row());
QTC_ASSERT(data, return);
plugin()->gotoLocation(data->markerFileName(),
data->markerLineNumber(), false);
}
void BreakWindow::setModelData
(int role, const QVariant &value, const QModelIndex &index)
{
QTC_ASSERT(model(), return);
model()->setData(index, value, role);
}
} // namespace Internal
} // namespace Debugger
......
......@@ -36,6 +36,7 @@ namespace Debugger {
namespace Internal {
class BreakpointData;
class BreakWindow : public QTreeView
{
Q_OBJECT
......@@ -68,9 +69,6 @@ private:
void setBreakpointsEnabled(const QModelIndexList &list, bool enabled);
void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath);
void setModelData(int role, const QVariant &value = QVariant(),
const QModelIndex &index = QModelIndex());
bool m_alwaysResizeColumnsToContents;
};
......
......@@ -184,6 +184,7 @@ enum ModelRoles
EngineCapabilitiesRole,
EngineActionsEnabledRole,
RequestActivationRole,
RequestContextMenuRole,
// Running
RequestExecContinueRole,
......@@ -205,25 +206,6 @@ enum ModelRoles
RequestOperatedByInstructionTriggeredRole,
RequestExecuteCommandRole,
// Breakpoints
BreakpointRole,
BreakpointEnabledRole,
BreakpointUseFullPathRole,
BreakpointFunctionNameRole,
BreakpointFileNameRole,
BreakpointConditionRole,
BreakpointIgnoreCountRole,
BreakpointThreadSpecRole,
RequestActivateBreakpointRole,
RequestRemoveBreakpointByIndexRole,
RequestSynchronizeBreakpointsRole,
RequestBreakByFunctionRole,
RequestBreakByFunctionMainRole,
RequestBreakpointRole,
RequestToggleBreakpointRole,
RequestToggleBreakpointEnabledRole,
RequestContextMenuRole,
// Locals and Watchers
LocalsINameRole,
LocalsEditTypeRole, // A QVariant::type describing the item
......@@ -254,7 +236,6 @@ enum ModelRoles
RequestShowDisassemblerRole,
// Threads
CurrentThreadIdRole,
RequestSelectThreadRole,
// Modules
......
......@@ -224,7 +224,6 @@ public:
m_state(DebuggerNotReady),
m_lastGoodState(DebuggerNotReady),
m_targetState(DebuggerNotReady),
m_breakHandler(engine),
m_commandHandler(engine),
m_modulesHandler(engine),
m_registerHandler(engine),
......@@ -304,7 +303,6 @@ public:
qint64 m_inferiorPid;
BreakHandler m_breakHandler;
CommandHandler m_commandHandler;
ModulesHandler m_modulesHandler;
RegisterHandler m_registerHandler;
......@@ -327,7 +325,7 @@ void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()