diff --git a/debugger/breakpoint/breakpointmodel.cpp b/debugger/breakpoint/breakpointmodel.cpp index b7968bff7..a9da4853a 100644 --- a/debugger/breakpoint/breakpointmodel.cpp +++ b/debugger/breakpoint/breakpointmodel.cpp @@ -1,665 +1,666 @@ /* This file is part of the KDE project Copyright (C) 2002 Matthias Hoelzer-Kluepfel Copyright (C) 2002 John Firebaugh Copyright (C) 2006, 2008 Vladimir Prus Copyright (C) 2007 Hamish Rodda Copyright (C) 2009 Niko Sams This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, see . */ #include "breakpointmodel.h" #include #include #include #include #include #include #include "../interfaces/icore.h" #include "../interfaces/idebugcontroller.h" #include "../interfaces/idocumentcontroller.h" #include "../interfaces/idocument.h" #include "../interfaces/ipartcontroller.h" #include #include #include #include #include "breakpoint.h" #include #include #include #include #define IF_DEBUG(x) using namespace KDevelop; using namespace KTextEditor; namespace { IBreakpointController* breakpointController() { KDevelop::ICore* core = KDevelop::ICore::self(); if (!core) { return nullptr; } IDebugController* controller = core->debugController(); if (!controller) { return nullptr; } IDebugSession* session = controller->currentSession(); return session ? session->breakpointController() : nullptr; } } // anonymous namespace class KDevelop::BreakpointModelPrivate { public: bool dirty = false; bool dontUpdateMarks = false; QList breakpoints; }; BreakpointModel::BreakpointModel(QObject* parent) : QAbstractTableModel(parent), d(new BreakpointModelPrivate) { connect(this, &BreakpointModel::dataChanged, this, &BreakpointModel::updateMarks); if (KDevelop::ICore::self()->partController()) { //TODO remove if foreach(KParts::Part* p, KDevelop::ICore::self()->partController()->parts()) slotPartAdded(p); connect(KDevelop::ICore::self()->partController(), &IPartController::partAdded, this, &BreakpointModel::slotPartAdded); } connect (KDevelop::ICore::self()->documentController(), &IDocumentController::textDocumentCreated, this, &BreakpointModel::textDocumentCreated); connect (KDevelop::ICore::self()->documentController(), &IDocumentController::documentSaved, this, &BreakpointModel::documentSaved); } BreakpointModel::~BreakpointModel() { qDeleteAll(d->breakpoints); } void BreakpointModel::slotPartAdded(KParts::Part* part) { if (auto doc = qobject_cast(part)) { MarkInterface *iface = dynamic_cast(doc); if( !iface ) return; iface->setMarkDescription((MarkInterface::MarkTypes)BreakpointMark, i18n("Breakpoint")); iface->setMarkPixmap((MarkInterface::MarkTypes)BreakpointMark, *breakpointPixmap()); iface->setMarkPixmap((MarkInterface::MarkTypes)PendingBreakpointMark, *pendingBreakpointPixmap()); iface->setMarkPixmap((MarkInterface::MarkTypes)ReachedBreakpointMark, *reachedBreakpointPixmap()); iface->setMarkPixmap((MarkInterface::MarkTypes)DisabledBreakpointMark, *disabledBreakpointPixmap()); iface->setEditableMarks( MarkInterface::Bookmark | BreakpointMark ); updateMarks(); } } void BreakpointModel::textDocumentCreated(KDevelop::IDocument* doc) { KTextEditor::MarkInterface *iface = qobject_cast(doc->textDocument()); if (iface) { // can't use new signal slot syntax here, MarkInterface is not a QObject connect(doc->textDocument(), SIGNAL(markChanged(KTextEditor::Document*,KTextEditor::Mark,KTextEditor::MarkInterface::MarkChangeAction)), this, SLOT(markChanged(KTextEditor::Document*,KTextEditor::Mark,KTextEditor::MarkInterface::MarkChangeAction))); connect(doc->textDocument(), SIGNAL(markContextMenuRequested(KTextEditor::Document*,KTextEditor::Mark,QPoint,bool&)), SLOT(markContextMenuRequested(KTextEditor::Document*,KTextEditor::Mark,QPoint,bool&))); } } void BreakpointModel::markContextMenuRequested(Document* document, Mark mark, const QPoint &pos, bool& handled) { int type = mark.type; qCDebug(DEBUGGER) << type; Breakpoint *b = nullptr; if ((type & AllBreakpointMarks)) { b = breakpoint(document->url(), mark.line); if (!b) { QMessageBox::critical(nullptr, i18n("Breakpoint not found"), i18n("Couldn't find breakpoint at %1:%2", document->url().toString(), mark.line)); } } else if (!(type & MarkInterface::Bookmark)) // neither breakpoint nor bookmark return; QMenu menu; // TODO: needs qwidget QAction* breakpointAction = menu.addAction(QIcon::fromTheme(QStringLiteral("breakpoint")), i18n("&Breakpoint")); breakpointAction->setCheckable(true); breakpointAction->setChecked(b); QAction* enableAction = nullptr; if (b) { enableAction = b->enabled() ? menu.addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("&Disable Breakpoint")) : menu.addAction(QIcon::fromTheme(QStringLiteral("dialog-ok-apply")), i18n("&Enable Breakpoint")); } menu.addSeparator(); QAction* bookmarkAction = menu.addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), i18n("&Bookmark")); bookmarkAction->setCheckable(true); bookmarkAction->setChecked((type & MarkInterface::Bookmark)); QAction* triggeredAction = menu.exec(pos); if (triggeredAction) { if (triggeredAction == bookmarkAction) { KTextEditor::MarkInterface *iface = qobject_cast(document); if ((type & MarkInterface::Bookmark)) iface->removeMark(mark.line, MarkInterface::Bookmark); else iface->addMark(mark.line, MarkInterface::Bookmark); } else if (triggeredAction == breakpointAction) { if (b) { b->setDeleted(); } else { Breakpoint *breakpoint = addCodeBreakpoint(document->url(), mark.line); MovingInterface *moving = qobject_cast(document); if (moving) { MovingCursor* cursor = moving->newMovingCursor(Cursor(mark.line, 0)); // can't use new signal/slot syntax here, MovingInterface is not a QObject connect(document, SIGNAL(aboutToDeleteMovingInterfaceContent(Document*)), this, SLOT(aboutToDeleteMovingInterfaceContent(Document*)), Qt::UniqueConnection); breakpoint->setMovingCursor(cursor); } } } else if (triggeredAction == enableAction) { b->setData(Breakpoint::EnableColumn, b->enabled() ? Qt::Unchecked : Qt::Checked); } } handled = true; } QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Vertical) return QVariant(); if (role == Qt::DecorationRole ) { if (section == 0) return QIcon::fromTheme(QStringLiteral("dialog-ok-apply")); else if (section == 1) return QIcon::fromTheme(QStringLiteral("system-switch-user")); } if (role == Qt::DisplayRole) { if (section == 0 || section == 1) return ""; if (section == 2) return i18n("Type"); if (section == 3) return i18n("Location"); if (section == 4) return i18n("Condition"); } if (role == Qt::ToolTipRole) { if (section == 0) return i18n("Active status"); if (section == 1) return i18n("State"); return headerData(section, orientation, Qt::DisplayRole); } return QVariant(); } Qt::ItemFlags BreakpointModel::flags(const QModelIndex &index) const { /* FIXME: all this logic must be in item */ if (!index.isValid()) return Qt::NoItemFlags; if (index.column() == 0) return static_cast( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsUserCheckable); if (index.column() == Breakpoint::ConditionColumn) return static_cast( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); return static_cast(Qt::ItemIsEnabled | Qt::ItemIsSelectable); } QModelIndex BreakpointModel::breakpointIndex(KDevelop::Breakpoint* b, int column) { int row = d->breakpoints.indexOf(b); if (row == -1) return QModelIndex(); return index(row, column); } bool KDevelop::BreakpointModel::removeRows(int row, int count, const QModelIndex& parent) { if (count < 1 || (row < 0) || (row + count) > rowCount(parent)) return false; IBreakpointController* controller = breakpointController(); beginRemoveRows(parent, row, row+count-1); for (int i=0; i < count; ++i) { Breakpoint* b = d->breakpoints.at(row); b->m_deleted = true; if (controller) controller->breakpointAboutToBeDeleted(row); d->breakpoints.removeAt(row); b->m_model = nullptr; // To be changed: the controller is currently still responsible for deleting the breakpoint // object } endRemoveRows(); updateMarks(); scheduleSave(); return true; } int KDevelop::BreakpointModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return d->breakpoints.count(); } return 0; } int KDevelop::BreakpointModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return 5; } QVariant BreakpointModel::data(const QModelIndex& index, int role) const { if (!index.parent().isValid() && index.row() < d->breakpoints.count()) { return d->breakpoints.at(index.row())->data(index.column(), role); } return QVariant(); } bool KDevelop::BreakpointModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (!index.parent().isValid() && index.row() < d->breakpoints.count() && (role == Qt::EditRole || role == Qt::CheckStateRole)) { return d->breakpoints.at(index.row())->setData(index.column(), value); } return false; } void BreakpointModel::updateState(int row, Breakpoint::BreakpointState state) { Breakpoint* breakpoint = d->breakpoints.at(row); if (state != breakpoint->m_state) { breakpoint->m_state = state; reportChange(breakpoint, Breakpoint::StateColumn); } } void BreakpointModel::updateHitCount(int row, int hitCount) { Breakpoint* breakpoint = d->breakpoints.at(row); if (hitCount != breakpoint->m_hitCount) { breakpoint->m_hitCount = hitCount; reportChange(breakpoint, Breakpoint::HitCountColumn); } } void BreakpointModel::updateErrorText(int row, const QString& errorText) { Breakpoint* breakpoint = d->breakpoints.at(row); if (breakpoint->m_errorText != errorText) { breakpoint->m_errorText = errorText; reportChange(breakpoint, Breakpoint::StateColumn); } if (!errorText.isEmpty()) { emit error(row, errorText); } } void BreakpointModel::notifyHit(int row) { emit hit(row); } void BreakpointModel::markChanged( KTextEditor::Document *document, KTextEditor::Mark mark, KTextEditor::MarkInterface::MarkChangeAction action) { int type = mark.type; /* Is this a breakpoint mark, to begin with? */ if (!(type & AllBreakpointMarks)) return; if (action == KTextEditor::MarkInterface::MarkAdded) { Breakpoint *b = breakpoint(document->url(), mark.line); if (b) { //there was already a breakpoint, so delete instead of adding b->setDeleted(); return; } Breakpoint *breakpoint = addCodeBreakpoint(document->url(), mark.line); KTextEditor::MovingInterface *moving = qobject_cast(document); if (moving) { KTextEditor::MovingCursor* cursor = moving->newMovingCursor(KTextEditor::Cursor(mark.line, 0)); // can't use new signal/slot syntax here, MovingInterface is not a QObject connect(document, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document*)), this, SLOT(aboutToDeleteMovingInterfaceContent(KTextEditor::Document*)), Qt::UniqueConnection); breakpoint->setMovingCursor(cursor); } } else { // Find this breakpoint and delete it Breakpoint *b = breakpoint(document->url(), mark.line); if (b) { b->setDeleted(); } } #if 0 if ( KDevelop::ICore::self()->documentController()->activeDocument() && KDevelop::ICore::self()->documentController()->activeDocument()->textDocument() == document ) { //bring focus back to the editor // TODO probably want a different command here KDevelop::ICore::self()->documentController()->activateDocument(KDevelop::ICore::self()->documentController()->activeDocument()); } #endif } const QPixmap* BreakpointModel::breakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme(QStringLiteral("breakpoint")).pixmap(QSize(16,16), QIcon::Active, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::pendingBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme(QStringLiteral("breakpoint")).pixmap(QSize(16,16), QIcon::Normal, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::reachedBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme(QStringLiteral("breakpoint")).pixmap(QSize(16,16), QIcon::Selected, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::disabledBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme(QStringLiteral("breakpoint")).pixmap(QSize(16,16), QIcon::Disabled, QIcon::Off); return &pixmap; } void BreakpointModel::toggleBreakpoint(const QUrl& url, const KTextEditor::Cursor& cursor) { Breakpoint *b = breakpoint(url, cursor.line()); if (b) { b->setDeleted(); } else { addCodeBreakpoint(url, cursor.line()); } } void BreakpointModel::reportChange(Breakpoint* breakpoint, Breakpoint::Column column) { // note: just a portion of Breakpoint::Column is displayed in this model! if (column >= 0 && column < columnCount()) { QModelIndex idx = breakpointIndex(breakpoint, column); Q_ASSERT(idx.isValid()); // make sure we don't pass invalid indices to dataChanged() emit dataChanged(idx, idx); } if (IBreakpointController* controller = breakpointController()) { int row = d->breakpoints.indexOf(breakpoint); Q_ASSERT(row != -1); controller->breakpointModelChanged(row, ColumnFlags(1 << column)); } scheduleSave(); } -uint BreakpointModel::breakpointType(Breakpoint *breakpoint) +uint BreakpointModel::breakpointType(Breakpoint *breakpoint) const { uint type = BreakpointMark; if (!breakpoint->enabled()) { type = DisabledBreakpointMark; } else if (breakpoint->hitCount() > 0) { type = ReachedBreakpointMark; } else if (breakpoint->state() == Breakpoint::PendingState) { type = PendingBreakpointMark; } return type; } void KDevelop::BreakpointModel::updateMarks() { if (d->dontUpdateMarks) return; //add marks foreach (Breakpoint* breakpoint, d->breakpoints) { if (breakpoint->kind() != Breakpoint::CodeBreakpoint) continue; if (breakpoint->line() == -1) continue; IDocument *doc = ICore::self()->documentController()->documentForUrl(breakpoint->url()); if (!doc) continue; KTextEditor::MarkInterface *mark = qobject_cast(doc->textDocument()); if (!mark) continue; uint type = breakpointType(breakpoint); IF_DEBUG( qCDebug(DEBUGGER) << type << breakpoint->url() << mark->mark(breakpoint->line()); ) { QSignalBlocker blocker(doc->textDocument()); if (mark->mark(breakpoint->line()) & AllBreakpointMarks) { if (!(mark->mark(breakpoint->line()) & type)) { mark->removeMark(breakpoint->line(), AllBreakpointMarks); mark->addMark(breakpoint->line(), type); } } else { mark->addMark(breakpoint->line(), type); } } } //remove marks foreach (IDocument *doc, ICore::self()->documentController()->openDocuments()) { KTextEditor::MarkInterface *mark = qobject_cast(doc->textDocument()); if (!mark) continue; { QSignalBlocker blocker(doc->textDocument()); foreach (KTextEditor::Mark *m, mark->marks()) { if (!(m->type & AllBreakpointMarks)) continue; IF_DEBUG( qCDebug(DEBUGGER) << m->line << m->type; ) foreach (Breakpoint* breakpoint, d->breakpoints) { if (breakpoint->kind() != Breakpoint::CodeBreakpoint) continue; if (doc->url() == breakpoint->url() && m->line == breakpoint->line()) { goto continueNextMark; } } mark->removeMark(m->line, AllBreakpointMarks); continueNextMark:; } } } } void BreakpointModel::documentSaved(KDevelop::IDocument* doc) { IF_DEBUG( qCDebug(DEBUGGER); ) foreach (Breakpoint* breakpoint, d->breakpoints) { if (breakpoint->movingCursor()) { if (breakpoint->movingCursor()->document() != doc->textDocument()) continue; if (breakpoint->movingCursor()->line() == breakpoint->line()) continue; d->dontUpdateMarks = true; breakpoint->setLine(breakpoint->movingCursor()->line()); d->dontUpdateMarks = false; } } } void BreakpointModel::aboutToDeleteMovingInterfaceContent(KTextEditor::Document* document) { foreach (Breakpoint* breakpoint, d->breakpoints) { if (breakpoint->movingCursor() && breakpoint->movingCursor()->document() == document) { breakpoint->setMovingCursor(nullptr); } } } void BreakpointModel::load() { KConfigGroup breakpoints = ICore::self()->activeSession()->config()->group("Breakpoints"); int count = breakpoints.readEntry("number", 0); if (count == 0) return; beginInsertRows(QModelIndex(), 0, count - 1); for (int i = 0; i < count; ++i) { if (!breakpoints.group(QString::number(i)).readEntry("kind", "").isEmpty()) { new Breakpoint(this, breakpoints.group(QString::number(i))); } } endInsertRows(); } void BreakpointModel::save() { d->dirty = false; KConfigGroup breakpoints = ICore::self()->activeSession()->config()->group("Breakpoints"); breakpoints.writeEntry("number", d->breakpoints.count()); int i = 0; foreach (Breakpoint* b, d->breakpoints) { KConfigGroup g = breakpoints.group(QString::number(i)); b->save(g); ++i; } breakpoints.sync(); } void BreakpointModel::scheduleSave() { if (d->dirty) return; d->dirty = true; QTimer::singleShot(0, this, &BreakpointModel::save); } QList KDevelop::BreakpointModel::breakpoints() const { return d->breakpoints; } -Breakpoint* BreakpointModel::breakpoint(int row) +Breakpoint* BreakpointModel::breakpoint(int row) const { if (row >= d->breakpoints.count()) return nullptr; return d->breakpoints.at(row); } Breakpoint* BreakpointModel::addCodeBreakpoint() { beginInsertRows(QModelIndex(), d->breakpoints.count(), d->breakpoints.count()); Breakpoint* n = new Breakpoint(this, Breakpoint::CodeBreakpoint); endInsertRows(); return n; } Breakpoint* BreakpointModel::addCodeBreakpoint(const QUrl& url, int line) { Breakpoint* n = addCodeBreakpoint(); n->setLocation(url, line); return n; } Breakpoint* BreakpointModel::addCodeBreakpoint(const QString& expression) { Breakpoint* n = addCodeBreakpoint(); n->setExpression(expression); return n; } Breakpoint* BreakpointModel::addWatchpoint() { beginInsertRows(QModelIndex(), d->breakpoints.count(), d->breakpoints.count()); Breakpoint* n = new Breakpoint(this, Breakpoint::WriteBreakpoint); endInsertRows(); return n; } Breakpoint* BreakpointModel::addWatchpoint(const QString& expression) { Breakpoint* n = addWatchpoint(); n->setExpression(expression); return n; } Breakpoint* BreakpointModel::addReadWatchpoint() { beginInsertRows(QModelIndex(), d->breakpoints.count(), d->breakpoints.count()); Breakpoint* n = new Breakpoint(this, Breakpoint::ReadBreakpoint); endInsertRows(); return n; } Breakpoint* BreakpointModel::addReadWatchpoint(const QString& expression) { Breakpoint* n = addReadWatchpoint(); n->setExpression(expression); return n; } Breakpoint* BreakpointModel::addAccessWatchpoint() { beginInsertRows(QModelIndex(), d->breakpoints.count(), d->breakpoints.count()); Breakpoint* n = new Breakpoint(this, Breakpoint::AccessBreakpoint); endInsertRows(); return n; } Breakpoint* BreakpointModel::addAccessWatchpoint(const QString& expression) { Breakpoint* n = addAccessWatchpoint(); n->setExpression(expression); return n; } void BreakpointModel::registerBreakpoint(Breakpoint* breakpoint) { Q_ASSERT(!d->breakpoints.contains(breakpoint)); int row = d->breakpoints.size(); d->breakpoints << breakpoint; if (IBreakpointController* controller = breakpointController()) { controller->breakpointAdded(row); } scheduleSave(); } -Breakpoint* BreakpointModel::breakpoint(const QUrl& url, int line) { +Breakpoint* BreakpointModel::breakpoint(const QUrl& url, int line) const +{ foreach (Breakpoint* b, d->breakpoints) { if (b->url() == url && b->line() == line) { return b; } } return nullptr; } diff --git a/debugger/breakpoint/breakpointmodel.h b/debugger/breakpoint/breakpointmodel.h index aeb59747e..61d71a0c2 100644 --- a/debugger/breakpoint/breakpointmodel.h +++ b/debugger/breakpoint/breakpointmodel.h @@ -1,201 +1,201 @@ /* This file is part of the KDE project Copyright (C) 2002 Matthias Hoelzer-Kluepfel Copyright (C) 2002 John Firebaugh Copyright (C) 2007 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, see . */ #ifndef KDEVPLATFORM_BREAKPOINTMODEL_H #define KDEVPLATFORM_BREAKPOINTMODEL_H #include #include #include "breakpoint.h" class QUrl; namespace KParts { class Part; } namespace KTextEditor { class Cursor; } namespace KDevelop { class IDocument; class Breakpoint; class KDEVPLATFORMDEBUGGER_EXPORT BreakpointModel : public QAbstractTableModel { Q_OBJECT public: enum Column { /** * Whether the breakpoint is active or not (settable by user): value is Qt::Checked * or Qt::Unchecked. */ EnableColumn, /** * Synchronization state of the breakpoint (not settable by user): value is one of the * BreakpointState enum values. */ StateColumn, /** * Kind/type of breakpoint (never changes): value is one of the BreakpointKind * enum values. */ KindColumn, /** * Location of the breakpoint (modifiable by user); value is a string describing the * location; note that the formatting of retrieved data can be affected by a custom * BreakpointRole. */ LocationColumn, /** * Condition for conditional breakpoints (modifiable by user). */ ConditionColumn, /** * The number of times this breakpoint has been hit (cannot be modified by the user). */ HitCountColumn, /** * How many hits of the breakpoint will be ignored before the breakpoint actually stops * the program (can be modified by the user and is updated by the debugger backend). */ IgnoreHitsColumn, NumColumns }; enum ColumnFlag { EnableColumnFlag = 1 << EnableColumn, StateColumnFlag = 1 << StateColumn, KindColumnFlag = 1 << KindColumn, LocationColumnFlag = 1 << LocationColumn, ConditionColumnFlag = 1 << ConditionColumn, HitCountColumnFlag = 1 << HitCountColumn, IgnoreHitsColumnFlag = 1 << IgnoreHitsColumn }; Q_DECLARE_FLAGS(ColumnFlags, ColumnFlag) explicit BreakpointModel(QObject* parent); virtual ~BreakpointModel(); QVariant headerData(int section, Qt::Orientation orientation, int role) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; QModelIndex breakpointIndex(Breakpoint *b, int column); bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; ///Note: to retrieve the full path use Breakpoint::LocationRole, Qt::DisplayRole returns only a file's name QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; void toggleBreakpoint(const QUrl &url, const KTextEditor::Cursor& cursor); KDevelop::Breakpoint* addCodeBreakpoint(); KDevelop::Breakpoint* addCodeBreakpoint(const QUrl& location, int line); KDevelop::Breakpoint* addCodeBreakpoint(const QString& expression); KDevelop::Breakpoint* addWatchpoint(); KDevelop::Breakpoint* addWatchpoint(const QString& expression); KDevelop::Breakpoint* addReadWatchpoint(); KDevelop::Breakpoint* addReadWatchpoint(const QString& expression); KDevelop::Breakpoint* addAccessWatchpoint(); KDevelop::Breakpoint* addAccessWatchpoint(const QString& expression); - Breakpoint *breakpoint(int row); + Breakpoint* breakpoint(int row) const; QList breakpoints() const; Q_SIGNALS: void error(int row, const QString& errorText); void hit(int row); public Q_SLOTS: void save(); void load(); private: enum MarkType { BreakpointMark = KTextEditor::MarkInterface::BreakpointActive, ReachedBreakpointMark = KTextEditor::MarkInterface::BreakpointReached, DisabledBreakpointMark = KTextEditor::MarkInterface::BreakpointDisabled, PendingBreakpointMark = KTextEditor::MarkInterface::markType08, AllBreakpointMarks = BreakpointMark | ReachedBreakpointMark | DisabledBreakpointMark | PendingBreakpointMark }; private Q_SLOTS: void updateMarks(); void slotPartAdded(KParts::Part* part); /** * Called by the TextEditor interface when the marks have changed position * because the user has added or removed source. * In here we figure out if we need to reset the breakpoints due to * these source changes. */ void markChanged(KTextEditor::Document *document, KTextEditor::Mark mark, KTextEditor::MarkInterface::MarkChangeAction action); void textDocumentCreated(KDevelop::IDocument*); void documentSaved(KDevelop::IDocument*); void aboutToDeleteMovingInterfaceContent(KTextEditor::Document *document); void markContextMenuRequested( KTextEditor::Document* document, KTextEditor::Mark mark, const QPoint &pos, bool& handled ); private: static const QPixmap* breakpointPixmap(); static const QPixmap* pendingBreakpointPixmap(); static const QPixmap* reachedBreakpointPixmap(); static const QPixmap* disabledBreakpointPixmap(); private: friend class Breakpoint; friend class IBreakpointController; void updateState(int row, Breakpoint::BreakpointState state); void updateHitCount(int row, int hitCount); void updateErrorText(int row, const QString& errorText); void notifyHit(int row); void registerBreakpoint(Breakpoint* breakpoint); void scheduleSave(); void reportChange(Breakpoint *breakpoint, Breakpoint::Column column); - uint breakpointType(Breakpoint *breakpoint); - Breakpoint *breakpoint(const QUrl& url, int line); + uint breakpointType(Breakpoint *breakpoint) const; + Breakpoint *breakpoint(const QUrl& url, int line) const; private: const QScopedPointer d; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::BreakpointModel::ColumnFlags) #endif