diff --git a/debugger/breakpoint/breakpoint.cpp b/debugger/breakpoint/breakpoint.cpp index ff5962b75b..12fa815e1b 100644 --- a/debugger/breakpoint/breakpoint.cpp +++ b/debugger/breakpoint/breakpoint.cpp @@ -1,382 +1,382 @@ /* 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 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 "breakpoint.h" #include #include #include #include "breakpointmodel.h" #include "../../interfaces/icore.h" #include "../../interfaces/idebugcontroller.h" #include "../interfaces/idebugsession.h" #include "../interfaces/ibreakpointcontroller.h" using namespace KDevelop; static const char* BREAKPOINT_KINDS[Breakpoint::LastBreakpointKind] = { "Code", "Write", "Read", "Access" }; static Breakpoint::BreakpointKind stringToKind(const QString& kindString) { for (int i = 0; i < Breakpoint::LastBreakpointKind; ++i) { if (BREAKPOINT_KINDS[i] == kindString) { return (Breakpoint::BreakpointKind)i; } } return Breakpoint::CodeBreakpoint; } Breakpoint::Breakpoint(BreakpointModel *model, BreakpointKind kind) : m_model(model), m_enabled(true) , m_deleted(false), m_kind(kind) , m_line(-1) , m_movingCursor(0), m_ignoreHits(0) { if (model) { model->registerBreakpoint(this); } } Breakpoint::Breakpoint(BreakpointModel *model, const KConfigGroup& config) : m_model(model), m_enabled(true) , m_deleted(false) , m_line(-1) , m_movingCursor(0), m_ignoreHits(0) { if (model) { model->registerBreakpoint(this); } m_kind = stringToKind(config.readEntry("kind", "")); m_enabled = config.readEntry("enabled", false); m_url = config.readEntry("url", QUrl()); m_line = config.readEntry("line", -1); m_expression = config.readEntry("expression", QString()); setCondition(config.readEntry("condition", "")); setIgnoreHits(config.readEntry("ignoreHits", 0)); } BreakpointModel *Breakpoint::breakpointModel() { return m_model; } bool Breakpoint::setData(int index, const QVariant& value) { if (index == EnableColumn) { m_enabled = static_cast(value.toInt()) == Qt::Checked; } if (index == LocationColumn || index == ConditionColumn) { QString s = value.toString(); if (index == LocationColumn) { QRegExp rx("^(.+):([0-9]+)$"); int idx = rx.indexIn(s); if (m_kind == CodeBreakpoint && idx != -1) { m_url = QUrl(rx.cap(1)); m_line = rx.cap(2).toInt() - 1; m_expression.clear(); } else { m_expression = s; m_url.clear(); m_line = -1; } } else { m_condition = s; } } reportChange(static_cast(index)); return true; } QVariant Breakpoint::data(int column, int role) const { if (column == EnableColumn) { if (role == Qt::CheckStateRole) return m_enabled ? Qt::Checked : Qt::Unchecked; else if (role == Qt::DisplayRole) return QVariant(); else return QVariant(); } if (column == StateColumn) { if (role == Qt::DecorationRole) { if (!errors().isEmpty()) { return QIcon::fromTheme("dialog-warning"); } switch (state()) { case NotStartedState: return QVariant(); case DirtyState: return QIcon::fromTheme("system-switch-user"); case PendingState: return QIcon::fromTheme("help-contents"); case CleanState: return QIcon::fromTheme("dialog-ok-apply"); } } else if (role == Qt::ToolTipRole) { if (!errors().isEmpty()) { return i18nc("@info:tooltip", "Error"); } switch (state()) { case NotStartedState: return QString(); case DirtyState: return i18nc("@info:tooltip", "Dirty"); case PendingState: return i18nc("@info:tooltip", "Pending"); case CleanState: return i18nc("@info:tooltip", "Clean"); } } else if (role == Qt::DisplayRole) { return QVariant(); } return QVariant(); } if (column == TypeColumn && role == Qt::DisplayRole) { return BREAKPOINT_KINDS[m_kind]; } if (role == Qt::DecorationRole) { if ((column == LocationColumn && errors().contains(LocationColumn)) || (column == ConditionColumn && errors().contains(ConditionColumn))) { /* FIXME: does this leak? Is this efficient? */ return QIcon::fromTheme("dialog-warning"); } return QVariant(); } if (column == ConditionColumn && (role == Qt::DisplayRole || role == Qt::EditRole)) { return m_condition; } if (column == LocationColumn) { if (role == LocationRole || role == Qt::EditRole || role == Qt::ToolTipRole || role == Qt::DisplayRole) { QString ret; if (m_kind == CodeBreakpoint && m_line != -1) { if (role == Qt::DisplayRole) { ret = m_url.fileName(); } else { ret = m_url.toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash); } ret += ':' + QString::number(m_line+1); } else { ret = m_expression; } //FIXME: there should be proper columns for function name and address. if (!m_address.isEmpty() && role == Qt::DisplayRole) { ret = QString("%1 (%2)").arg(ret).arg(m_address); } return ret; } } return QVariant(); } void Breakpoint::setDeleted() { m_deleted = true; BreakpointModel* m = breakpointModel(); if (!m) return; // already removed if (m->breakpointIndex(this, 0).isValid()) { m->removeRow(m->breakpointIndex(this, 0).row()); } m_model = 0; // invalidate } int Breakpoint::line() const { return m_line; } void Breakpoint::setLine(int line) { Q_ASSERT(m_kind == CodeBreakpoint); m_line = line; reportChange(LocationColumn); } -void Breakpoint::setUrl(const KUrl& url) { +void Breakpoint::setUrl(const QUrl& url) { Q_ASSERT(m_kind == CodeBreakpoint); m_url = url; reportChange(LocationColumn); } -KUrl Breakpoint::url() const { +QUrl Breakpoint::url() const { return m_url; } -void Breakpoint::setLocation(const KUrl& url, int line) +void Breakpoint::setLocation(const QUrl& url, int line) { Q_ASSERT(m_kind == CodeBreakpoint); m_url = url; m_line = line; reportChange(LocationColumn); } QString KDevelop::Breakpoint::location() { return data(LocationColumn, LocationRole).toString(); } void Breakpoint::save(KConfigGroup& config) { config.writeEntry("kind", BREAKPOINT_KINDS[m_kind]); config.writeEntry("enabled", m_enabled); config.writeEntry("url", m_url); config.writeEntry("line", m_line); config.writeEntry("expression", m_expression); config.writeEntry("condition", m_condition); config.writeEntry("ignoreHits", m_ignoreHits); } Breakpoint::BreakpointKind Breakpoint::kind() const { return m_kind; } void Breakpoint::setAddress(const QString& address) { m_address = address; //reportChange(); } QString Breakpoint::address() const { return m_address; } int Breakpoint::hitCount() const { IDebugSession* session = ICore::self()->debugController()->currentSession(); if (session) { return session->breakpointController()->breakpointHitCount(this); } else { return -1; } } bool Breakpoint::deleted() const { return m_deleted; } bool Breakpoint::enabled() const { return data(EnableColumn, Qt::CheckStateRole).toBool(); } void KDevelop::Breakpoint::setMovingCursor(KTextEditor::MovingCursor* cursor) { m_movingCursor = cursor; } KTextEditor::MovingCursor* KDevelop::Breakpoint::movingCursor() const { return m_movingCursor; } void Breakpoint::setIgnoreHits(int c) { if (m_ignoreHits != c) { m_ignoreHits = c; reportChange(IgnoreHitsColumn); } } int Breakpoint::ignoreHits() const { return m_ignoreHits; } void Breakpoint::setCondition(const QString& c) { m_condition = c; reportChange(ConditionColumn); } QString Breakpoint::condition() const { return m_condition; } void Breakpoint::setExpression(const QString& e) { m_expression = e; reportChange(LocationColumn); } QString Breakpoint::expression() const { return m_expression; } Breakpoint::BreakpointState Breakpoint::state() const { IDebugSession* session = ICore::self()->debugController()->currentSession(); if (session) { return session->breakpointController()->breakpointState(this); } else { return NotStartedState; } } QSet Breakpoint::errors() const { IDebugSession* session = ICore::self()->debugController()->currentSession(); if (session) { return session->breakpointController()->breakpointErrors(this); } else { return QSet(); } } QString Breakpoint::errorText() const { IDebugSession* session = ICore::self()->debugController()->currentSession(); if (session) { return session->breakpointController()->breakpointErrorText(this); } else { return QString(); } } void KDevelop::Breakpoint::reportChange(Column c) { if (!breakpointModel()) return; breakpointModel()->reportChange(this, c); } diff --git a/debugger/breakpoint/breakpoint.h b/debugger/breakpoint/breakpoint.h index 7be3a8db08..0b6e417a4b 100644 --- a/debugger/breakpoint/breakpoint.h +++ b/debugger/breakpoint/breakpoint.h @@ -1,142 +1,142 @@ /* 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_BREAKPOINT_H #define KDEVPLATFORM_BREAKPOINT_H #include -#include +#include #include "../util/treeitem.h" class KConfigGroup; namespace KTextEditor { class MovingCursor; } namespace KDevelop { class BreakpointModel; class KDEVPLATFORMDEBUGGER_EXPORT Breakpoint { public: enum BreakpointKind { CodeBreakpoint = 0, WriteBreakpoint, ReadBreakpoint, AccessBreakpoint, LastBreakpointKind }; enum BreakpointState { NotStartedState, DirtyState, PendingState, CleanState }; ///Custom roles for retrieving data from breakpoint model. enum BreakpointRole{ LocationRole = Qt::UserRole + 1 ///< Retrieves breakpoint's full path unlike Qt::DisplayRole. Note: it's only appliable to LocationColumn. }; Breakpoint(BreakpointModel *model, BreakpointKind kind); Breakpoint(BreakpointModel *model, const KConfigGroup& config); ///Note: EnableColumn has 3, not 2(true and false) values: Qt::Unchecked, Qt:PartiallyChecked and Qt::Checked bool setData(int index, const QVariant& value); void setDeleted(); ///Note: to retrieve the full path use LocationRole, Qt::DisplayRole return only a file's name QVariant data(int column, int role) const; void save(KConfigGroup& config); enum Column { EnableColumn, StateColumn, TypeColumn, LocationColumn, ConditionColumn, HitCountColumn, IgnoreHitsColumn }; - void setUrl(const KUrl &url); - KUrl url() const; + void setUrl(const QUrl &url); + QUrl url() const; void setLine(int line); int line() const; - void setLocation(const KUrl& url, int line); + void setLocation(const QUrl& url, int line); QString location(); BreakpointKind kind() const; void setAddress(const QString& address); QString address() const; int hitCount() const; bool deleted() const; bool enabled() const; void setMovingCursor(KTextEditor::MovingCursor *cursor); KTextEditor::MovingCursor *movingCursor() const; void setIgnoreHits(int c); int ignoreHits() const; void setCondition(const QString &c); QString condition() const; void setExpression(const QString &c); QString expression() const; BreakpointState state() const; QString errorText() const; QSet errors() const; protected: friend class IBreakpointController; /** * Return the model this breakpoint is attached to * * @note This might be null, e.g. after the breakpoint has been marked as deleted */ BreakpointModel *breakpointModel(); BreakpointModel *m_model; bool m_enabled; bool m_deleted; BreakpointKind m_kind; /* For watchpoints, the address it is set at. */ QString m_address; QUrl m_url; int m_line; QString m_condition; KTextEditor::MovingCursor *m_movingCursor; int m_ignoreHits; QString m_expression; void reportChange(Column c); }; } #endif diff --git a/debugger/breakpoint/breakpointmodel.cpp b/debugger/breakpoint/breakpointmodel.cpp index 16bd156c84..0a5506b2d1 100644 --- a/debugger/breakpoint/breakpointmodel.cpp +++ b/debugger/breakpoint/breakpointmodel.cpp @@ -1,552 +1,551 @@ /* 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 #include "../interfaces/icore.h" #include "../interfaces/idocumentcontroller.h" #include "../interfaces/idocument.h" #include "../interfaces/ipartcontroller.h" #include "breakpoint.h" #include #include #include #include #define IF_DEBUG(x) using namespace KDevelop; using namespace KTextEditor; BreakpointModel::BreakpointModel(QObject* parent) : QAbstractTableModel(parent), m_dontUpdateMarks(false) { connect(this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(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(), SIGNAL(partAdded(KParts::Part*)), this, SLOT(slotPartAdded(KParts::Part*))); } connect (KDevelop::ICore::self()->documentController(), SIGNAL(textDocumentCreated(KDevelop::IDocument*)), this, SLOT(textDocumentCreated(KDevelop::IDocument*))); connect (KDevelop::ICore::self()->documentController(), SIGNAL(documentSaved(KDevelop::IDocument*)), SLOT(documentSaved(KDevelop::IDocument*))); load(); } BreakpointModel::~BreakpointModel() { save(); qDeleteAll(m_breakpoints); } void BreakpointModel::slotPartAdded(KParts::Part* part) { if (KTextEditor::Document* doc = dynamic_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 ) { 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; kDebug() << type; /* Is this a breakpoint mark, to begin with? */ if (!(type & AllBreakpointMarks)) return; Breakpoint *b = breakpoint(document->url(), mark.line); Q_ASSERT(b); if (!b) return; QMenu menu; QAction deleteAction(QIcon::fromTheme("edit-delete"), i18n("&Delete Breakpoint"), 0); QAction disableAction(QIcon::fromTheme("dialog-cancel"), i18n("&Disable Breakpoint"), 0); QAction enableAction(QIcon::fromTheme("dialog-ok-apply"), i18n("&Enable Breakpoint"), 0); menu.addAction(&deleteAction); if (b->enabled()) { menu.addAction(&disableAction); } else { menu.addAction(&enableAction); } QAction *a = menu.exec(pos); if (a == &deleteAction) { b->setDeleted(); } else if (a == &disableAction) { b->setData(Breakpoint::EnableColumn, Qt::Unchecked); } else if (a == &enableAction) { b->setData(Breakpoint::EnableColumn, 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("dialog-ok-apply"); else if (section == 1) return QIcon::fromTheme("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 0; if (index.column() == 0) return static_cast( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsUserCheckable); if (index.column() == Breakpoint::LocationColumn || 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 = m_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; beginRemoveRows(parent, row, row+count-1); for (int i=0; i < count; ++i) { Breakpoint *b = m_breakpoints.at(row); m_breakpoints.removeAt(row); IF_DEBUG ( kDebug() << m_breakpoints; ) b->setDeleted(); emit breakpointDeleted(b); } endRemoveRows(); updateMarks(); return true; } int KDevelop::BreakpointModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return m_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() < m_breakpoints.count()) { return m_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() < m_breakpoints.count() && (role == Qt::EditRole || role == Qt::CheckStateRole)) { return m_breakpoints.at(index.row())->setData(index.column(), value); } return false; } 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)); 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("script-error").pixmap(QSize(22,22), QIcon::Active, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::pendingBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme("script-error").pixmap(QSize(22,22), QIcon::Normal, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::reachedBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme("script-error").pixmap(QSize(22,22), QIcon::Selected, QIcon::Off); return &pixmap; } const QPixmap* BreakpointModel::disabledBreakpointPixmap() { static QPixmap pixmap=QIcon::fromTheme("script-error").pixmap(QSize(22,22), QIcon::Disabled, QIcon::Off); return &pixmap; } -void BreakpointModel::toggleBreakpoint(const KUrl& url, const KTextEditor::Cursor& cursor) +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); } emit breakpointChanged(breakpoint, column); } uint BreakpointModel::breakpointType(Breakpoint *breakpoint) { 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 (m_dontUpdateMarks) return; //add marks foreach (Breakpoint *breakpoint, m_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( kDebug() << type << breakpoint->url() << mark->mark(breakpoint->line()); ) doc->textDocument()->blockSignals(true); 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); } doc->textDocument()->blockSignals(false); } //remove marks foreach (IDocument *doc, ICore::self()->documentController()->openDocuments()) { KTextEditor::MarkInterface *mark = qobject_cast(doc->textDocument()); if (!mark) continue; doc->textDocument()->blockSignals(true); foreach (KTextEditor::Mark *m, mark->marks()) { if (!(m->type & AllBreakpointMarks)) continue; IF_DEBUG( kDebug() << m->line << m->type; ) foreach (Breakpoint *breakpoint, m_breakpoints) { if (breakpoint->kind() != Breakpoint::CodeBreakpoint) continue; if (doc->url() == breakpoint->url() && m->line == breakpoint->line()) { goto continueNextMark; } } mark->removeMark(m->line, AllBreakpointMarks); continueNextMark:; } doc->textDocument()->blockSignals(false); } } void BreakpointModel::documentSaved(KDevelop::IDocument* doc) { IF_DEBUG( kDebug(); ) foreach (Breakpoint *breakpoint, m_breakpoints) { if (breakpoint->movingCursor()) { if (breakpoint->movingCursor()->document() != doc->textDocument()) continue; if (breakpoint->movingCursor()->line() == breakpoint->line()) continue; m_dontUpdateMarks = true; breakpoint->setLine(breakpoint->movingCursor()->line()); m_dontUpdateMarks = false; } } } void BreakpointModel::aboutToDeleteMovingInterfaceContent(KTextEditor::Document* document) { foreach (Breakpoint *breakpoint, m_breakpoints) { if (breakpoint->movingCursor() && breakpoint->movingCursor()->document() == document) { breakpoint->setMovingCursor(0); } } } void BreakpointModel::load() { KConfigGroup breakpoints = KSharedConfig::openConfig()->group("breakpoints"); int count = breakpoints.readEntry("number", 0); if (count == 0) return; beginInsertRows(QModelIndex(), 0, count); 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() { KConfigGroup breakpoints = KSharedConfig::openConfig()->group("breakpoints"); breakpoints.writeEntry("number", m_breakpoints.count()); int i = 0; foreach (Breakpoint *b, m_breakpoints) { KConfigGroup g = breakpoints.group(QString::number(i)); b->save(g); ++i; } breakpoints.sync(); } QList KDevelop::BreakpointModel::breakpoints() const { return m_breakpoints; } Breakpoint* BreakpointModel::breakpoint(int row) { if (row >= m_breakpoints.count()) return 0; return m_breakpoints.at(row); } Breakpoint* BreakpointModel::addCodeBreakpoint() { beginInsertRows(QModelIndex(), m_breakpoints.count(), m_breakpoints.count()); Breakpoint* n = new Breakpoint(this, Breakpoint::CodeBreakpoint); endInsertRows(); return n; } -Breakpoint* BreakpointModel::addCodeBreakpoint(const KUrl& url, int line) +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(), m_breakpoints.count(), m_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(), m_breakpoints.count(), m_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(), m_breakpoints.count(), m_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(!m_breakpoints.contains(breakpoint)); m_breakpoints << breakpoint; } -Breakpoint* BreakpointModel::breakpoint(const KUrl& url, int line) { +Breakpoint* BreakpointModel::breakpoint(const QUrl& url, int line) { foreach (Breakpoint *b, m_breakpoints) { if (b->url() == url && b->line() == line) { return b; } } return 0; } - diff --git a/debugger/breakpoint/breakpointmodel.h b/debugger/breakpoint/breakpointmodel.h index 8b5739ad67..025e78e6d2 100644 --- a/debugger/breakpoint/breakpointmodel.h +++ b/debugger/breakpoint/breakpointmodel.h @@ -1,148 +1,148 @@ /* 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 KUrl; +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: BreakpointModel(QObject* parent); virtual ~BreakpointModel(); QVariant headerData(int section, Qt::Orientation orientation, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const; QModelIndex breakpointIndex(Breakpoint *b, int column); virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; ///Note: to retrieve the full path use Breakpoint::LocationRole, Qt::DisplayRole returns only a file's name virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); - void toggleBreakpoint(const KUrl &url, const KTextEditor::Cursor& cursor); + void toggleBreakpoint(const QUrl &url, const KTextEditor::Cursor& cursor); KDevelop::Breakpoint* addCodeBreakpoint(); - KDevelop::Breakpoint* addCodeBreakpoint(const KUrl& location, int line); + 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); QList breakpoints() const; void errorEmit(Breakpoint *b, const QString& message, int column) { emit error(b, message, column); } void hitEmit(Breakpoint *b) { emit hit(b); } Q_SIGNALS: void error(KDevelop::Breakpoint *b, const QString& message, int column); void hit(KDevelop::Breakpoint *b); 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 }; Q_SIGNALS: /** * A breakpoint has been deleted by the user. The breakpoint object * still exists as is has eventualle be deleted from the debugger engine. */ void breakpointDeleted(KDevelop::Breakpoint *breakpoint); void breakpointChanged(KDevelop::Breakpoint *breakpoint, KDevelop::Breakpoint::Column column); 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; void registerBreakpoint(Breakpoint* breakpoint); void reportChange(Breakpoint *breakpoint, Breakpoint::Column column); uint breakpointType(Breakpoint *breakpoint); - Breakpoint *breakpoint(const KUrl& url, int line); + Breakpoint *breakpoint(const QUrl& url, int line); bool m_dontUpdateMarks; QList m_breakpoints; }; } #endif diff --git a/debugger/breakpoint/breakpointwidget.cpp b/debugger/breakpoint/breakpointwidget.cpp index 9ec0402c17..9dd60df232 100644 --- a/debugger/breakpoint/breakpointwidget.cpp +++ b/debugger/breakpoint/breakpointwidget.cpp @@ -1,323 +1,323 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * Copyright 2013 Vlas Puhov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "breakpointwidget.h" #include #include #include #include #include #include #include #include #include #include #include "breakpointdetails.h" #include "../breakpoint/breakpoint.h" #include "../breakpoint/breakpointmodel.h" #include #include #define IF_DEBUG(x) #include #include #include using namespace KDevelop; BreakpointWidget::BreakpointWidget(IDebugController *controller, QWidget *parent) : QWidget(parent), m_firstShow(true), m_debugController(controller), breakpointDisableAll_(0), breakpointEnableAll_(0), breakpointRemoveAll_(0) { setWindowTitle(i18nc("@title:window", "Debugger Breakpoints")); setWhatsThis(i18nc("@info:whatsthis", "Displays a list of breakpoints with " "their current status. Clicking on a " "breakpoint item allows you to change " "the breakpoint and will take you " "to the source in the editor window.")); setWindowIcon( QIcon::fromTheme("process-stop") ); QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); QSplitter *s = new AutoOrientedSplitter(this); layout->addWidget(s); m_splitter = s; m_breakpointsView = new QTableView(s); m_breakpointsView->setSelectionBehavior(QAbstractItemView::SelectRows); m_breakpointsView->setSelectionMode(QAbstractItemView::SingleSelection); m_breakpointsView->horizontalHeader()->setHighlightSections(false); m_breakpointsView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); details_ = new BreakpointDetails(s); s->setStretchFactor(0, 2); m_breakpointsView->verticalHeader()->hide(); PlaceholderItemProxyModel* proxyModel = new PlaceholderItemProxyModel(this); proxyModel->setSourceModel(m_debugController->breakpointModel()); proxyModel->setColumnHint(Breakpoint::LocationColumn, i18n("New code breakpoint ...")); proxyModel->setColumnHint(Breakpoint::ConditionColumn, i18n("Enter condition ...")); m_breakpointsView->setModel(proxyModel); connect(proxyModel, SIGNAL(dataInserted(int, QVariant)), SLOT(slotDataInserted(int, QVariant))); m_proxyModel = proxyModel; connect(m_breakpointsView, SIGNAL(clicked(QModelIndex)), this, SLOT(slotOpenFile(QModelIndex))); connect(m_breakpointsView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(slotOpenFile(QModelIndex))); connect(m_breakpointsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(slotUpdateBreakpointDetail())); connect(m_debugController->breakpointModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotUpdateBreakpointDetail())); connect(m_debugController->breakpointModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(slotUpdateBreakpointDetail())); connect(m_debugController->breakpointModel(), SIGNAL(modelReset()), SLOT(slotUpdateBreakpointDetail())); connect(m_debugController->breakpointModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(slotUpdateBreakpointDetail())); connect(m_debugController->breakpointModel(), SIGNAL(hit(KDevelop::Breakpoint*)), SLOT(breakpointHit(KDevelop::Breakpoint*))); connect(m_debugController->breakpointModel(), SIGNAL(error(KDevelop::Breakpoint*,QString,int)), SLOT(breakpointError(KDevelop::Breakpoint*,QString,int))); setupPopupMenu(); } void BreakpointWidget::setupPopupMenu() { popup_ = new QMenu(this); QMenu* newBreakpoint = popup_->addMenu( i18nc("New breakpoint", "&New") ); newBreakpoint->setIcon(QIcon::fromTheme("list-add")); QAction* action = newBreakpoint->addAction( i18nc("Code breakpoint", "&Code"), this, SLOT(slotAddBlankBreakpoint()) ); // Use this action also to provide a local shortcut action->setShortcut(QKeySequence(Qt::Key_B + Qt::CTRL, Qt::Key_C)); addAction(action); newBreakpoint->addAction( i18nc("Data breakpoint", "Data &Write"), this, SLOT(slotAddBlankWatchpoint())); newBreakpoint->addAction( i18nc("Data read breakpoint", "Data &Read"), this, SLOT(slotAddBlankReadWatchpoint())); newBreakpoint->addAction( i18nc("Data access breakpoint", "Data &Access"), this, SLOT(slotAddBlankAccessWatchpoint())); QAction* breakpointDelete = popup_->addAction( QIcon::fromTheme("edit-delete"), i18n( "&Delete" ), this, SLOT(slotRemoveBreakpoint())); breakpointDelete->setShortcut(Qt::Key_Delete); breakpointDelete->setShortcutContext(Qt::WidgetWithChildrenShortcut); addAction(breakpointDelete); popup_->addSeparator(); breakpointDisableAll_ = popup_->addAction(i18n("Disable &All"), this, SLOT(slotDisableAllBreakpoints())); breakpointEnableAll_ = popup_->addAction(i18n("&Enable All"), this, SLOT(slotEnableAllBreakpoints())); breakpointRemoveAll_ = popup_->addAction(i18n("&Remove All"), this, SLOT(slotRemoveAllBreakpoints())); connect(popup_,SIGNAL(aboutToShow()), this, SLOT(slotPopupMenuAboutToShow())); } void BreakpointWidget::contextMenuEvent(QContextMenuEvent* event) { popup_->popup(event->globalPos()); } void BreakpointWidget::slotPopupMenuAboutToShow() { if (m_debugController->breakpointModel()->rowCount() < 2) { breakpointDisableAll_->setDisabled(true); breakpointEnableAll_->setDisabled(true); breakpointRemoveAll_->setDisabled(true); } else { breakpointRemoveAll_->setEnabled(true); bool allDisabled = true; bool allEnabled = true; for (int i = 0; i < m_debugController->breakpointModel()->rowCount() - 1 ; i++) { Breakpoint *bp = m_debugController->breakpointModel()->breakpoint(i); if (bp->enabled()) allDisabled = false; else allEnabled = false; } breakpointDisableAll_->setDisabled(allDisabled); breakpointEnableAll_->setDisabled(allEnabled); } } void BreakpointWidget::showEvent(QShowEvent *) { if (m_firstShow) { QHeaderView* header = m_breakpointsView->horizontalHeader(); for (int i = 0; i < m_breakpointsView->model()->columnCount(); ++i) { if(i == Breakpoint::LocationColumn){ continue; } m_breakpointsView->resizeColumnToContents(i); } //for some reasons sometimes width can be very small about 200... But it doesn't matter as we use tooltip anyway. int width = m_breakpointsView->size().width(); header->resizeSection(Breakpoint::LocationColumn, width > 400 ? width/2 : header->sectionSize(Breakpoint::LocationColumn)*2 ); m_firstShow = false; } } void BreakpointWidget::edit(KDevelop::Breakpoint *n) { QModelIndex index = m_proxyModel->mapFromSource(m_debugController->breakpointModel()->breakpointIndex(n, Breakpoint::LocationColumn)); m_breakpointsView->setCurrentIndex(index); m_breakpointsView->edit(index); } void BreakpointWidget::slotDataInserted(int column, const QVariant& value) { Breakpoint* breakpoint = m_debugController->breakpointModel()->addCodeBreakpoint(); breakpoint->setData(column, value); } void BreakpointWidget::slotAddBlankBreakpoint() { edit(m_debugController->breakpointModel()->addCodeBreakpoint()); } void BreakpointWidget::slotAddBlankWatchpoint() { edit(m_debugController->breakpointModel()->addWatchpoint()); } void BreakpointWidget::slotAddBlankReadWatchpoint() { edit(m_debugController->breakpointModel()->addReadWatchpoint()); } void KDevelop::BreakpointWidget::slotAddBlankAccessWatchpoint() { edit(m_debugController->breakpointModel()->addAccessWatchpoint()); } void BreakpointWidget::slotRemoveBreakpoint() { QItemSelectionModel* sel = m_breakpointsView->selectionModel(); QModelIndexList selected = sel->selectedIndexes(); IF_DEBUG( kDebug() << selected; ) if (!selected.isEmpty()) { m_debugController->breakpointModel()->removeRow(selected.first().row()); } } void BreakpointWidget::slotRemoveAllBreakpoints() { m_debugController->breakpointModel()->removeRows(0, m_debugController->breakpointModel()->rowCount()); } void BreakpointWidget::slotUpdateBreakpointDetail() { QModelIndexList selected = m_breakpointsView->selectionModel()->selectedIndexes(); IF_DEBUG( kDebug() << selected; ) if (selected.isEmpty()) { details_->setItem(0); } else { details_->setItem(m_debugController->breakpointModel()->breakpoint(selected.first().row())); } } void BreakpointWidget::breakpointHit(KDevelop::Breakpoint* b) { IF_DEBUG( kDebug() << b; ) const QModelIndex index = m_proxyModel->mapFromSource(m_debugController->breakpointModel()->breakpointIndex(b, 0)); m_breakpointsView->selectionModel()->select( index, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } void BreakpointWidget::breakpointError(KDevelop::Breakpoint* b, const QString& msg, int column) { IF_DEBUG( kDebug() << b << msg << column; ) // FIXME: we probably should prevent this error notification during // initial setting of breakpoint, to avoid a cloud of popups. if (!m_breakpointsView->isVisible()) return; const QModelIndex index = m_proxyModel->mapFromSource(m_debugController->breakpointModel()->breakpointIndex(b, column)); QPoint p = m_breakpointsView->visualRect(index).topLeft(); p = m_breakpointsView->mapToGlobal(p); KPassivePopup *pop = new KPassivePopup(m_breakpointsView); pop->setPopupStyle(KPassivePopup::Boxed); pop->setAutoDelete(true); // FIXME: the icon, too. pop->setView("", msg); pop->setTimeout(-1); pop->show(p); } void BreakpointWidget::slotOpenFile(const QModelIndex& breakpointIdx) { if (breakpointIdx.column() != Breakpoint::LocationColumn){ return; } Breakpoint *bp = m_debugController->breakpointModel()->breakpoint(breakpointIdx.row()); if (!bp || bp->line() == -1 || bp->url().isEmpty() ){ return; } - ICore::self()->documentController()->openDocument(bp->url().pathOrUrl(KUrl::RemoveTrailingSlash), KTextEditor::Cursor(bp->line(), 0), IDocumentController::DoNotFocus); + ICore::self()->documentController()->openDocument(bp->url().url(QUrl::PreferLocalFile | QUrl::StripTrailingSlash), KTextEditor::Cursor(bp->line(), 0), IDocumentController::DoNotFocus); } void BreakpointWidget::slotDisableAllBreakpoints() { for (int i = 0; i < m_debugController->breakpointModel()->rowCount() - 1 ; i++) { Breakpoint *bp = m_debugController->breakpointModel()->breakpoint(i); bp->setData(Breakpoint::EnableColumn, Qt::Unchecked); } } void BreakpointWidget::slotEnableAllBreakpoints() { for (int i = 0; i < m_debugController->breakpointModel()->rowCount() - 1 ; i++) { Breakpoint *bp = m_debugController->breakpointModel()->breakpoint(i); bp->setData(Breakpoint::EnableColumn, Qt::Checked); } } diff --git a/debugger/framestack/framestackmodel.h b/debugger/framestack/framestackmodel.h index dbd3478480..bb170ddfe1 100644 --- a/debugger/framestack/framestackmodel.h +++ b/debugger/framestack/framestackmodel.h @@ -1,114 +1,112 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * This program 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 program 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 General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_FRAMESTACKMODEL_H #define KDEVPLATFORM_FRAMESTACKMODEL_H #include #include -#include - #include #include #include namespace KDevelop { class DebugController; /** FIXME: This class needs rework, since at present it is not true model. Client cannot just obtain frames by grabbing a thread and listing children. It should first setCurrentThread beforehand, and it is the method that will actually fetch threads. Therefore, if this model is submitted to plain QTreeView, it won't work at all. Ideally, this should hold current thread and current frame numbers, and only fetch the list of threads, and list of frames inside thread when asked for by the view. */ class KDEVPLATFORMDEBUGGER_EXPORT FrameStackModel : public IFrameStackModel { Q_OBJECT public: FrameStackModel(IDebugSession* session); virtual ~FrameStackModel(); struct ThreadItem { int nr; QString name; }; void setThreads(const QList &threads); /** * Update frames for thread @p threadNumber * * @note The currentFrame property will be set to the first frame * containing debug information */ void setFrames(int threadNumber, QList frames); void insertFrames(int threadNumber, const QList &frames); void setHasMoreFrames(int threadNumber, bool hasMoreFrames); FrameItem frame(const QModelIndex &index); QList frames(int threadNumber) const; //ItemModel implementation virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& child) const; virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void setCurrentThread(int threadNumber); void setCurrentThread(const QModelIndex &index); int currentThread() const; QModelIndex currentThreadIndex() const; int currentFrame() const; QModelIndex currentFrameIndex() const; void setCurrentFrame(int frame); void fetchMoreFrames(); private Q_SLOTS: void stateChanged(KDevelop::IDebugSession::DebuggerState state); private: virtual void handleEvent(IDebugSession::event_t event); void update(); QModelIndex indexForThreadNumber(int threadNumber); int m_currentThread; int m_currentFrame; // used to count how often a user has scrolled down and more frames needed to be fetched; // this way, the number of frames fetched in each chunk can be increased if the user wants // to scroll far int m_subsequentFrameFetchOperations; bool m_updateCurrentFrameOnNextFetch; QList m_threads; QHash > m_frames; QHash m_hasMoreFrames; }; } #endif diff --git a/debugger/framestack/framestackwidget.cpp b/debugger/framestack/framestackwidget.cpp index f9a89f62cb..2f9c165bb4 100644 --- a/debugger/framestack/framestackwidget.cpp +++ b/debugger/framestack/framestackwidget.cpp @@ -1,248 +1,248 @@ /* * This file is part of KDevelop * * Copyright 1999 John Birch * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * Copyright 2009 Aleix Pol * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "framestackwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "framestackmodel.h" namespace KDevelop { FramestackWidget::FramestackWidget(IDebugController* controller, QWidget* parent) : AutoOrientedSplitter(Qt::Horizontal, parent), m_session(0) { connect(controller, SIGNAL(currentSessionChanged(KDevelop::IDebugSession*)), SLOT(currentSessionChanged(KDevelop::IDebugSession*))); connect(controller, SIGNAL(raiseFramestackViews()), SIGNAL(requestRaise())); setWhatsThis(i18n("Frame stack" "Often referred to as the \"call stack\", " "this is a list showing which function is " "currently active, and what called each " "function to get to this point in your " "program. By clicking on an item you " "can see the values in any of the " "previous calling functions.")); setWindowIcon(QIcon::fromTheme("view-list-text")); m_threadsWidget = new QWidget(this); m_threads = new QListView(m_threadsWidget); m_frames = new QTreeView(this); m_frames->setRootIsDecorated(false); m_frames->setSelectionMode(QAbstractItemView::ContiguousSelection); m_frames->setSelectionBehavior(QAbstractItemView::SelectRows); m_frames->setAllColumnsShowFocus(true); m_frames->setContextMenuPolicy(Qt::CustomContextMenu); m_framesContextMenu = new QMenu(m_frames); QAction* selectAllAction = KStandardAction::selectAll(m_frames); selectAllAction->setShortcut(QKeySequence()); //FIXME: why does CTRL-A conflict with Katepart (while CTRL-Cbelow doesn't) ? selectAllAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(selectAllAction, SIGNAL(triggered()), SLOT(selectAll())); m_framesContextMenu->addAction(selectAllAction); QAction* copyAction = KStandardAction::copy(m_frames); copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(copyAction, SIGNAL(triggered()), SLOT(copySelection())); m_framesContextMenu->addAction(copyAction); addAction(copyAction); connect(m_frames, SIGNAL(customContextMenuRequested(QPoint)), SLOT(frameContextMenuRequested(QPoint))); m_threadsWidget->setLayout(new QVBoxLayout()); m_threadsWidget->layout()->addWidget(new QLabel(i18n("Threads:"))); m_threadsWidget->layout()->addWidget(m_threads); m_threadsWidget->hide(); addWidget(m_threadsWidget); addWidget(m_frames); setStretchFactor(1, 3); connect(m_frames->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(checkFetchMoreFrames())); // Show the selected frame when clicked, even if it has previously been selected connect(m_frames, SIGNAL(clicked(QModelIndex)), SLOT(frameSelectionChanged(QModelIndex))); } FramestackWidget::~FramestackWidget() {} void FramestackWidget::currentSessionChanged(KDevelop::IDebugSession* session) { kDebug() << "Adding session:" << isVisible(); m_session = session; m_threads->setModel(session ? session->frameStackModel() : 0); m_frames->setModel(session ? session->frameStackModel() : 0); if (session) { connect(session->frameStackModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(checkFetchMoreFrames())); connect(session->frameStackModel(), SIGNAL(currentThreadChanged(int)), SLOT(currentThreadChanged(int))); currentThreadChanged(session->frameStackModel()->currentThread()); connect(session->frameStackModel(), SIGNAL(currentFrameChanged(int)), SLOT(currentFrameChanged(int))); currentFrameChanged(session->frameStackModel()->currentFrame()); connect(session, SIGNAL(stateChanged(KDevelop::IDebugSession::DebuggerState)), SLOT(sessionStateChanged(KDevelop::IDebugSession::DebuggerState))); connect(m_threads->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(setThreadShown(QModelIndex))); // Show the selected frame, independent of the means by which it has been selected connect(m_frames->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(frameSelectionChanged(QModelIndex))); } if (isVisible()) { showEvent(0); } } void FramestackWidget::hideEvent(QHideEvent* e) { QWidget::hideEvent(e); } void FramestackWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); } void FramestackWidget::setThreadShown(const QModelIndex& current) { if (!current.isValid()) return; m_session->frameStackModel()->setCurrentThread(current); } void FramestackWidget::checkFetchMoreFrames() { int val = m_frames->verticalScrollBar()->value(); int max = m_frames->verticalScrollBar()->maximum(); const int offset = 20; if (val + offset > max && m_session) { m_session->frameStackModel()->fetchMoreFrames(); } } void FramestackWidget::currentThreadChanged(int thread) { if (thread != -1) { IFrameStackModel* model = m_session->frameStackModel(); QModelIndex idx = model->currentThreadIndex(); m_threads->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); m_threadsWidget->setVisible(model->rowCount() > 1); m_frames->setRootIndex(idx); m_frames->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); } else { m_threadsWidget->hide(); m_threads->selectionModel()->clear(); m_frames->setRootIndex(QModelIndex()); } } void FramestackWidget::currentFrameChanged(int frame) { if (frame != -1) { IFrameStackModel* model = m_session->frameStackModel(); QModelIndex idx = model->currentFrameIndex(); m_frames->selectionModel()->select( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } else { m_frames->selectionModel()->clear(); } } void FramestackWidget::frameSelectionChanged(const QModelIndex& current /* previous */) { if (!current.isValid()) return; IFrameStackModel::FrameItem f = m_session->frameStackModel()->frame(current); /* If line is -1, then it's not a source file at all. */ if (f.line != -1) { - QPair file = m_session->convertToLocalUrl(qMakePair(f.file, f.line)); + QPair file = m_session->convertToLocalUrl(qMakePair(f.file, f.line)); ICore::self()->documentController()->openDocument(file.first, KTextEditor::Cursor(file.second, 0), IDocumentController::DoNotFocus); } m_session->frameStackModel()->setCurrentFrame(f.nr); } void FramestackWidget::frameContextMenuRequested(const QPoint& pos) { m_framesContextMenu->popup( m_frames->mapToGlobal(pos) + QPoint(0, m_frames->header()->height()) ); } void FramestackWidget::copySelection() { QClipboard *cb = QApplication::clipboard(); QModelIndexList indexes = m_frames->selectionModel()->selectedRows(); QString content; Q_FOREACH( QModelIndex index, indexes) { IFrameStackModel::FrameItem frame = m_session->frameStackModel()->frame(index); if (frame.line == -1) { - content += QString("#%1 %2() at %3\n").arg(frame.nr).arg(frame.name).arg(frame.file.pathOrUrl(KUrl::RemoveTrailingSlash)); + content += QString("#%1 %2() at %3\n").arg(frame.nr).arg(frame.name).arg(frame.file.url(QUrl::PreferLocalFile | QUrl::StripTrailingSlash)); } else { - content += QString("#%1 %2() at %3:%4\n").arg(frame.nr).arg(frame.name).arg(frame.file.pathOrUrl(KUrl::RemoveTrailingSlash)).arg(frame.line+1); + content += QString("#%1 %2() at %3:%4\n").arg(frame.nr).arg(frame.name).arg(frame.file.url(QUrl::PreferLocalFile | QUrl::StripTrailingSlash)).arg(frame.line+1); } } cb->setText(content); } void FramestackWidget::selectAll() { m_frames->selectAll(); } void FramestackWidget::sessionStateChanged(KDevelop::IDebugSession::DebuggerState state) { bool enable = state == IDebugSession::PausedState || state == IDebugSession::StoppedState; m_frames->setEnabled(enable); m_threads->setEnabled(enable); } } diff --git a/debugger/interfaces/idebugsession.cpp b/debugger/interfaces/idebugsession.cpp index 9f55f42237..1d68d8dbd3 100644 --- a/debugger/interfaces/idebugsession.cpp +++ b/debugger/interfaces/idebugsession.cpp @@ -1,141 +1,141 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * This program 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 program 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 General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "idebugsession.h" #include "iframestackmodel.h" #include "ivariablecontroller.h" #include #include #include #include namespace KDevelop { IDebugSession::IDebugSession() : m_breakpointController(0), m_variableController(0), m_frameStackModel(0) { connect(this, SIGNAL(stateChanged(KDevelop::IDebugSession::DebuggerState)), SLOT(slotStateChanged(KDevelop::IDebugSession::DebuggerState))); } IDebugSession::~IDebugSession() { } bool IDebugSession::isRunning() const { DebuggerState s = state(); return (s == ActiveState || s == PausedState); } IBreakpointController *IDebugSession::breakpointController() const { return m_breakpointController; } IVariableController *IDebugSession::variableController() const { return m_variableController; } IFrameStackModel* IDebugSession::frameStackModel() const { /* The delayed initialization is used so that derived class can override createFrameStackModel and have it called. If we tried to call virtual function from a constructor, it would not work. */ if (m_frameStackModel == 0) { m_frameStackModel = const_cast(this)->createFrameStackModel(); Q_ASSERT(m_frameStackModel); } return m_frameStackModel; } void IDebugSession::raiseEvent(event_t e) { if (frameStackModel()) frameStackModel()->handleEvent(e); if (m_variableController) m_variableController->handleEvent(e); // FIXME: consider if we actually need signals emit event(e); } -QPair IDebugSession::convertToLocalUrl(const QPair &remoteUrl) const +QPair IDebugSession::convertToLocalUrl(const QPair &remoteUrl) const { return remoteUrl; } -QPair IDebugSession::convertToRemoteUrl(const QPair& localUrl) const +QPair IDebugSession::convertToRemoteUrl(const QPair& localUrl) const { return localUrl; } void IDebugSession::clearCurrentPosition() { kDebug(); m_url.clear(); m_addr = ""; m_line = -1; emit clearExecutionPoint(); } -void IDebugSession::setCurrentPosition(const KUrl& url, int line, const QString& addr) +void IDebugSession::setCurrentPosition(const QUrl& url, int line, const QString& addr) { kDebug() << url << line << addr; if (url.isEmpty() || !QFileInfo(convertToLocalUrl(qMakePair(url,line)).first.path()).exists()) { clearCurrentPosition(); m_addr = addr; emit showStepInDisassemble(addr); } else { m_url = url; m_line = line; m_addr = addr; emit showStepInSource(url, line, addr); } } -KUrl IDebugSession::currentUrl() const +QUrl IDebugSession::currentUrl() const { return m_url; } int IDebugSession::currentLine() const { return m_line; } QString IDebugSession::currentAddr() const { return m_addr; } void IDebugSession::slotStateChanged(IDebugSession::DebuggerState state) { if (state != PausedState) { clearCurrentPosition(); } } } diff --git a/debugger/interfaces/idebugsession.h b/debugger/interfaces/idebugsession.h index d1db6116b1..8dd8b9db48 100644 --- a/debugger/interfaces/idebugsession.h +++ b/debugger/interfaces/idebugsession.h @@ -1,187 +1,185 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * This program 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 program 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 General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_IDEBUGSESSION_H #define KDEVPLATFORM_IDEBUGSESSION_H #include #include #include -#include - -class KUrl; +#include namespace KDevelop { class IVariableController; class IBreakpointController; class IFrameStackModel; class Breakpoint; class StackModel; class KDEVPLATFORMDEBUGGER_EXPORT IDebugSession : public QObject { Q_OBJECT Q_ENUMS(DebuggerState) public: IDebugSession(); virtual ~IDebugSession(); enum DebuggerState { NotStartedState, StartingState, ActiveState, PausedState, StoppingState, StoppedState, EndedState }; enum event_t { program_state_changed = 1, program_exited, debugger_exited, // Emitted when the thread or frame that is selected in UI // changes. thread_or_frame_changed, debugger_busy, debugger_ready, // Raised when debugger believe that program start running. // Can be used to hide current line indicator. // Don't count on this being raise in all cases where // program is running. program_running, // Raise when the debugger is in touch with the program, // and should have access to its debug symbols. The program // is not necessary running yet, or might already exited, // or be otherwise dead. connected_to_program }; public: /** * Current state of the debug session */ virtual DebuggerState state() const = 0; /** * Should return if restart is currently available */ virtual bool restartAvaliable() const = 0; /** * Returns if the debugee is currently running. This includes paused. */ bool isRunning() const; /** * Returns the local Url for a source file used in the current debug session. * * The default implementation just returns the url and is sufficient for * local debuggers. Remote debuggers can implement a path mapping mechanism. */ - virtual QPair convertToLocalUrl(const QPair &remoteUrl) const; + virtual QPair convertToLocalUrl(const QPair &remoteUrl) const; /** * Returns the remote Url for a source file used in the current debug session. * * The default implementation just returns the url and is sufficient for * local debuggers. Remote debuggers can implement a path mapping mechanism. */ - virtual QPair convertToRemoteUrl(const QPair &localUrl) const; + virtual QPair convertToRemoteUrl(const QPair &localUrl) const; IBreakpointController *breakpointController() const; IVariableController *variableController() const; IFrameStackModel *frameStackModel() const; public Q_SLOTS: virtual void restartDebugger() = 0; virtual void stopDebugger() = 0; virtual void interruptDebugger() = 0; virtual void run() = 0; virtual void runToCursor() = 0; virtual void jumpToCursor() = 0; virtual void stepOver() = 0; virtual void stepIntoInstruction() = 0; virtual void stepInto() = 0; virtual void stepOverInstruction() = 0; virtual void stepOut() = 0; Q_SIGNALS: void stateChanged(KDevelop::IDebugSession::DebuggerState state); - void showStepInSource(const KUrl& file, int line, const QString &addr); + void showStepInSource(const QUrl& file, int line, const QString &addr); void showStepInDisassemble(const QString &addr); void clearExecutionPoint(); void finished(); void raiseFramestackViews(); /** This signal is emitted whenever the given event in a program happens. See DESIGN.txt for expected handled of each event. NOTE: this signal should never be emitted directly. Instead, use raiseEvent. */ void event(IDebugSession::event_t e); public: using QObject::event; // prevent hiding of base method. - KUrl currentUrl() const; + QUrl currentUrl() const; int currentLine() const; QString currentAddr() const; protected: // Clear the position before running code void clearCurrentPosition(); /// Sets new position and emits showStepInSource or showStepInDisassemble (if source file is unavailable) signal - void setCurrentPosition(const KUrl& url, int line, const QString& addr); + void setCurrentPosition(const QUrl& url, int line, const QString& addr); /** Raises the specified event. Should be used instead of emitting 'event' directly, since this method can perform additional book-keeping for events. FIXME: it might make sense to automatically route events to all debugger components, as opposed to requiring that they connect to any signal. */ virtual void raiseEvent(event_t e); friend class FrameStackModel; virtual IFrameStackModel* createFrameStackModel() = 0; IBreakpointController *m_breakpointController; IVariableController *m_variableController; mutable IFrameStackModel *m_frameStackModel; private Q_SLOTS: void slotStateChanged(KDevelop::IDebugSession::DebuggerState state); private: //TODO use d-pointer // Current position in debugged program, gets set when the state changes - KUrl m_url; + QUrl m_url; int m_line; QString m_addr; }; } #endif diff --git a/debugger/interfaces/iframestackmodel.h b/debugger/interfaces/iframestackmodel.h index 33deecd0ed..ed0d153474 100644 --- a/debugger/interfaces/iframestackmodel.h +++ b/debugger/interfaces/iframestackmodel.h @@ -1,95 +1,95 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Vladimir Prus * * * * This program 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 program 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 General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_IFRAMESTACKMODEL_H #define KDEVPLATFORM_IFRAMESTACKMODEL_H #include "idebugsession.h" -#include +#include #include #include namespace KDevelop { class KDEVPLATFORMDEBUGGER_EXPORT IFrameStackModel : public QAbstractItemModel { Q_OBJECT public: /** Stack frame */ struct FrameItem { int nr; QString name; - KUrl file; + QUrl file; /* If -1, it means that file is not necessary a source file, but possibly a solib name. */ int line; }; IFrameStackModel(IDebugSession *session) : QAbstractItemModel(session), m_session(session) {} IDebugSession* session() const { return m_session; } /** Sets the current thread to the specified number, and sets the current frame to 0. Note that nothing prevents us from introducing setCurrentThreadAndFrame, but for all the cases when we switch to a different thread we want frame 0. */ virtual void setCurrentThread(int threadNumber) = 0; virtual void setCurrentThread(const QModelIndex &index) = 0; virtual int currentThread() const = 0; virtual QModelIndex currentThreadIndex() const = 0; /* Return the frame we wish to operate on. This is always in context of the current thread. This may be -1 if no frame is selected. This should only the be the case if the thread has no stack as such -- e.g. because it's running, or because it's exited. */ virtual int currentFrame() const = 0; virtual QModelIndex currentFrameIndex() const = 0; virtual void setCurrentFrame(int frame) = 0; virtual FrameItem frame(const QModelIndex &index) = 0; virtual void fetchThreads() = 0; virtual void fetchFrames(int threadNumber, int from, int to) = 0; virtual void fetchMoreFrames() = 0; Q_SIGNALS: /* FIXME: It might make for a more conscise interface if those two were removed, and the clients react to thread_or_frame_changed event and compare the current thread/frame in the framestack model with the one they are displaying. */ void currentThreadChanged(int thread); void currentFrameChanged(int frame); private: virtual void handleEvent(IDebugSession::event_t event) = 0; friend class IDebugSession; IDebugSession *m_session; }; } #endif diff --git a/debugger/util/pathmappings.cpp b/debugger/util/pathmappings.cpp index dd874247f7..0ca7934d05 100644 --- a/debugger/util/pathmappings.cpp +++ b/debugger/util/pathmappings.cpp @@ -1,270 +1,258 @@ /* * This file is part of KDevelop * * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "pathmappings.h" #include #include #include #include #include #include #include #include #include #include #include +namespace { + +static QUrl rebaseMatchingUrl(const QUrl& toRebase, const KConfigGroup& config, const QString& baseEntry, const QString& rebaseEntry) +{ + const QUrl::UrlFormattingOption matchOpts = QUrl::NormalizePathSegments; + foreach (const QString &group, config.groupList()) { + KConfigGroup pathCfg = config.group(group); + const QString baseStr = pathCfg.readEntry(baseEntry, QUrl()).url(matchOpts); + const QString searchStr = toRebase.url(matchOpts); + if (searchStr.contains(baseStr)) { + const QUrl rebase = pathCfg.readEntry(rebaseEntry, QUrl()); + return rebase.resolved(searchStr.mid(baseStr.length())); + } + } + //No mapping found + return toRebase; +} + +} + namespace KDevelop { const QString PathMappings::pathMappingsEntry("Path Mappings"); const QString PathMappings::pathMappingRemoteEntry("Remote"); const QString PathMappings::pathMappingLocalEntry("Local"); -KUrl PathMappings::convertToLocalUrl(const KConfigGroup& config, const KUrl& remoteUrl) +QUrl PathMappings::convertToLocalUrl(const KConfigGroup& config, const QUrl& remoteUrl) { if (remoteUrl.isLocalFile() && QFile::exists(remoteUrl.toLocalFile())) { return remoteUrl; } - kDebug() << remoteUrl; - KConfigGroup cfg = config.group(pathMappingsEntry); - foreach (const QString &group, cfg.groupList()) { - KConfigGroup pCfg = cfg.group(group); - KUrl remote = pCfg.readEntry(pathMappingRemoteEntry, QUrl()); - KUrl local = pCfg.readEntry(pathMappingLocalEntry, QUrl()); - kDebug() << remote << local; - kDebug() << remoteUrl.pathOrUrl() << remote.pathOrUrl(); - if (remoteUrl.pathOrUrl().startsWith(remote.pathOrUrl())) { - QString path = remoteUrl.pathOrUrl().mid(remote.pathOrUrl().length()); - local.addPath(path); - return local; - } - } - - kDebug() << "no mapping found"; - return remoteUrl; + return rebaseMatchingUrl(remoteUrl, cfg, pathMappingRemoteEntry, pathMappingLocalEntry); } -KUrl PathMappings::convertToRemoteUrl(const KConfigGroup& config, const KUrl& localUrl) +QUrl PathMappings::convertToRemoteUrl(const KConfigGroup& config, const QUrl& localUrl) { - kDebug() << localUrl; - KConfigGroup cfg = config.group(pathMappingsEntry); - foreach (const QString &group, cfg.groupList()) { - KConfigGroup pCfg = cfg.group(group); - KUrl remote = pCfg.readEntry(pathMappingRemoteEntry, QUrl()); - KUrl local = pCfg.readEntry(pathMappingLocalEntry, QUrl()); - kDebug() << remote << local; - kDebug() << localUrl.pathOrUrl() << local.pathOrUrl(); - if (localUrl.pathOrUrl().startsWith(local.pathOrUrl())) { - QString path = localUrl.pathOrUrl().mid(local.pathOrUrl().length()); - remote.addPath(path); - return remote; - } - } - - kDebug() << "no mapping found"; - return localUrl; + return rebaseMatchingUrl(localUrl, cfg, pathMappingLocalEntry, pathMappingRemoteEntry); } class PathMappingModel : public QAbstractTableModel { Q_OBJECT public: virtual int columnCount(const QModelIndex& parent = QModelIndex()) const { if (parent.isValid()) return 0; return 2; } virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { if (parent.isValid()) return 0; return m_paths.count() + 1; } virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (section == 0) { return i18n("Remote Path"); } else if (section == 1) { return i18n("Local Path"); } } return QAbstractTableModel::headerData(section, orientation, role); } virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const { if (!index.isValid()) return QVariant(); if (index.parent().isValid()) return QVariant(); if (index.column() > 1) return QVariant(); if (index.row() > m_paths.count()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) { if (index.row() == m_paths.count()) return QString(); if (index.column() == 0) { return m_paths[index.row()].remote.toDisplayString(QUrl::PreferLocalFile); } else if (index.column() == 1) { return m_paths[index.row()].local.toDisplayString(QUrl::PreferLocalFile); } } return QVariant(); } virtual Qt::ItemFlags flags(const QModelIndex& index) const { if (index.parent().isValid()) return Qt::NoItemFlags; if (!index.isValid()) return Qt::NoItemFlags; return ( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ); } virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) { if (!index.isValid()) return false; if (index.parent().isValid()) return false; if (index.column() > 1) return false; if (index.row() > m_paths.count()) return false; if (role == Qt::EditRole) { if (index.row() == m_paths.count()) { beginInsertRows(QModelIndex(), index.row()+1, index.row()+1); m_paths.append(Path()); endInsertRows(); } if (index.column() == 0) { - m_paths[index.row()].remote = KUrl(value.toString()); + m_paths[index.row()].remote = QUrl::fromUserInput(value.toString()); } else if (index.column() == 1) { - m_paths[index.row()].local = KUrl(value.toString()); + m_paths[index.row()].local = QUrl::fromLocalFile(value.toString()); } dataChanged(index, index); return true; } return false; } virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) { if (parent.isValid()) return false; if (row+count > m_paths.count()) return false; beginRemoveRows(parent, row, row+count-1); for (int i=0; i m_paths; }; PathMappingsWidget::PathMappingsWidget(QWidget* parent): QWidget(parent) { QVBoxLayout *verticalLayout = new QVBoxLayout(this); m_pathMappingTable = new QTableView(this); m_pathMappingTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_pathMappingTable->horizontalHeader()->setDefaultSectionSize(150); m_pathMappingTable->horizontalHeader()->setStretchLastSection(true); verticalLayout->addWidget(m_pathMappingTable); m_pathMappingTable->setModel(new PathMappingModel()); connect(m_pathMappingTable->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), SIGNAL(changed())); connect(m_pathMappingTable->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(changed())); connect(m_pathMappingTable->model(), SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(changed())); QAction* deletePath = new QAction( QIcon::fromTheme("edit-delete"), i18n( "Delete" ), this ); connect(deletePath, SIGNAL(triggered(bool)), SLOT(deletePath())); deletePath->setShortcut(Qt::Key_Delete); deletePath->setShortcutContext(Qt::WidgetWithChildrenShortcut); m_pathMappingTable->addAction(deletePath); } void PathMappingsWidget::deletePath() { foreach (const QModelIndex &i, m_pathMappingTable->selectionModel()->selectedRows()) { m_pathMappingTable->model()->removeRow(i.row(), i.parent()); } } void PathMappingsWidget::loadFromConfiguration(const KConfigGroup& cfg) { static_cast(m_pathMappingTable->model())->loadFromConfiguration(cfg); } void PathMappingsWidget::saveToConfiguration(KConfigGroup cfg) const { static_cast(m_pathMappingTable->model())->saveToConfiguration(cfg); } } #include "pathmappings.moc" #include "moc_pathmappings.cpp" diff --git a/debugger/util/pathmappings.h b/debugger/util/pathmappings.h index 20cf9f0db8..b6cb36f521 100644 --- a/debugger/util/pathmappings.h +++ b/debugger/util/pathmappings.h @@ -1,67 +1,67 @@ /* * This file is part of KDevelop * * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PATHMAPPINGSWIDGET_H #define KDEVPLATFORM_PATHMAPPINGSWIDGET_H #include -#include +#include #include #include class QTableView; namespace KDevelop { class KDEVPLATFORMDEBUGGER_EXPORT PathMappings { public: static const QString pathMappingsEntry; static const QString pathMappingRemoteEntry; static const QString pathMappingLocalEntry; - static KUrl convertToLocalUrl(const KConfigGroup &config, const KUrl& remoteUrl); - static KUrl convertToRemoteUrl(const KConfigGroup &config, const KUrl& localUrl); + static QUrl convertToLocalUrl(const KConfigGroup &config, const QUrl& remoteUrl); + static QUrl convertToRemoteUrl(const KConfigGroup &config, const QUrl& localUrl); }; class KDEVPLATFORMDEBUGGER_EXPORT PathMappingsWidget : public QWidget { Q_OBJECT public: PathMappingsWidget(QWidget* parent = 0); void loadFromConfiguration(const KConfigGroup& cfg); void saveToConfiguration(KConfigGroup cfg) const; Q_SIGNALS: void changed(); private Q_SLOTS: void deletePath(); private: QTableView *m_pathMappingTable; }; } #endif diff --git a/shell/debugcontroller.cpp b/shell/debugcontroller.cpp index 6946819e38..d27aee5bbe 100644 --- a/shell/debugcontroller.cpp +++ b/shell/debugcontroller.cpp @@ -1,536 +1,536 @@ /* This file is part of KDevelop * * Copyright 1999-2001 John Birch * Copyright 2001 by Bernd Gehrmann * Copyright 2006 Vladimir Prus * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "debugcontroller.h" #include #include #include #include #include #include #include #include #include #include "../interfaces/idocument.h" #include "../interfaces/icore.h" #include "../interfaces/idocumentcontroller.h" #include "../interfaces/ipartcontroller.h" #include "../interfaces/contextmenuextension.h" #include "../interfaces/context.h" #include "../language/interfaces/editorcontext.h" #include "../sublime/view.h" #include "../sublime/mainwindow.h" #include "../sublime/area.h" #include "core.h" #include "uicontroller.h" #include "../debugger/breakpoint/breakpointmodel.h" #include "../debugger/breakpoint/breakpointwidget.h" #include "../debugger/variable/variablewidget.h" #include "../debugger/framestack/framestackmodel.h" #include "../debugger/framestack/framestackwidget.h" #include namespace KDevelop { template class DebuggerToolFactory : public KDevelop::IToolViewFactory { public: DebuggerToolFactory(DebugController* controller, const QString &id, Qt::DockWidgetArea defaultArea) : m_controller(controller), m_id(id), m_defaultArea(defaultArea) {} virtual QWidget* create(QWidget *parent = 0) { return new T(m_controller, parent); } virtual QString id() const { return m_id; } virtual Qt::DockWidgetArea defaultPosition() { return m_defaultArea; } virtual void viewCreated(Sublime::View* view) { if (view->widget()->metaObject()->indexOfSignal("requestRaise()") != -1) QObject::connect(view->widget(), SIGNAL(requestRaise()), view, SLOT(requestRaise())); } /* At present, some debugger widgets (e.g. breakpoint) contain actions so that shortcuts work, but they don't need any toolbar. So, suppress toolbar action. */ virtual QList toolBarActions( QWidget* viewWidget ) const { Q_UNUSED(viewWidget); return QList(); } private: DebugController* m_controller; QString m_id; Qt::DockWidgetArea m_defaultArea; }; DebugController::DebugController(QObject *parent) : IDebugController(parent), KXMLGUIClient(), m_continueDebugger(0), m_stopDebugger(0), m_interruptDebugger(0), m_runToCursor(0), m_jumpToCursor(0), m_stepOver(0), m_stepIntoInstruction(0), m_stepInto(0), m_stepOverInstruction(0), m_stepOut(0), m_toggleBreakpoint(0), m_breakpointModel(new BreakpointModel(this)), m_variableCollection(new VariableCollection(this)), m_uiInitialized(false) { setComponentName("kdevdebugger", "kdevdebugger"); setXMLFile("kdevdebuggershellui.rc"); } void DebugController::initialize() { } void DebugController::initializeUi() { if (m_uiInitialized) return; m_uiInitialized = true; if((Core::self()->setupFlags() & Core::NoUi)) return; setupActions(); ICore::self()->uiController()->addToolView( i18n("Frame Stack"), new DebuggerToolFactory( this, "org.kdevelop.debugger.StackView", Qt::BottomDockWidgetArea)); ICore::self()->uiController()->addToolView( i18n("Breakpoints"), new DebuggerToolFactory( this, "org.kdevelop.debugger.BreakpointsView", Qt::BottomDockWidgetArea)); ICore::self()->uiController()->addToolView( i18n("Variables"), new DebuggerToolFactory( this, "org.kdevelop.debugger.VariablesView", Qt::LeftDockWidgetArea)); foreach(KParts::Part* p, KDevelop::ICore::self()->partController()->parts()) partAdded(p); connect(KDevelop::ICore::self()->partController(), SIGNAL(partAdded(KParts::Part*)), this, SLOT(partAdded(KParts::Part*))); ICore::self()->uiController()->activeMainWindow()->guiFactory()->addClient(this); stateChanged("ended"); } void DebugController::cleanup() { if (m_currentSession) m_currentSession.data()->stopDebugger(); } DebugController::~DebugController() { } BreakpointModel* DebugController::breakpointModel() { return m_breakpointModel; } VariableCollection* DebugController::variableCollection() { return m_variableCollection; } void DebugController::partAdded(KParts::Part* part) { if (KTextEditor::Document* doc = dynamic_cast(part)) { KTextEditor::MarkInterface *iface = dynamic_cast(doc); if( !iface ) return; iface->setMarkPixmap(KTextEditor::MarkInterface::Execution, *executionPointPixmap()); } } IDebugSession* DebugController::currentSession() { return m_currentSession.data(); } void DebugController::setupActions() { KActionCollection* ac = actionCollection(); QAction* action = m_continueDebugger = new QAction(QIcon::fromTheme("media-playback-start"), i18n("&Continue"), this); action->setToolTip( i18n("Continue application execution") ); action->setWhatsThis( i18n("Continues the execution of your application in the " "debugger. This only takes effect when the application " "has been halted by the debugger (i.e. a breakpoint has " "been activated or the interrupt was pressed).") ); ac->addAction("debug_continue", action); connect(action, SIGNAL(triggered(bool)), this, SLOT(run())); #if 0 m_restartDebugger = action = new QAction(QIcon::fromTheme("media-seek-backward"), i18n("&Restart"), this); action->setToolTip( i18n("Restart program") ); action->setWhatsThis( i18n("Restarts applications from the beginning.") ); action->setEnabled(false); connect(action, SIGNAL(triggered(bool)), this, SLOT(restartDebugger())); ac->addAction("debug_restart", action); #endif m_interruptDebugger = action = new QAction(QIcon::fromTheme("media-playback-pause"), i18n("Interrupt"), this); action->setToolTip( i18n("Interrupt application") ); action->setWhatsThis(i18n("Interrupts the debugged process or current debugger command.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(interruptDebugger())); ac->addAction("debug_pause", action); m_runToCursor = action = new QAction(QIcon::fromTheme("debug-run-cursor"), i18n("Run to &Cursor"), this); action->setToolTip( i18n("Run to cursor") ); action->setWhatsThis(i18n("Continues execution until the cursor position is reached.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(runToCursor())); ac->addAction("debug_runtocursor", action); m_jumpToCursor = action = new QAction(QIcon::fromTheme("debug-execute-to-cursor"), i18n("Set E&xecution Position to Cursor"), this); action->setToolTip( i18n("Jump to cursor") ); action->setWhatsThis(i18n("Continue execution from the current cursor position.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(jumpToCursor())); ac->addAction("debug_jumptocursor", action); m_stepOver = action = new QAction(QIcon::fromTheme("debug-step-over"), i18n("Step &Over"), this); action->setShortcut(Qt::Key_F10); action->setToolTip( i18n("Step over the next line") ); action->setWhatsThis( i18n("Executes one line of source in the current source file. " "If the source line is a call to a function the whole " "function is executed and the app will stop at the line " "following the function call.") ); connect(action, SIGNAL(triggered(bool)), this, SLOT(stepOver())); ac->addAction("debug_stepover", action); m_stepOverInstruction = action = new QAction(QIcon::fromTheme("debug-step-instruction"), i18n("Step over Ins&truction"), this); action->setToolTip( i18n("Step over instruction") ); action->setWhatsThis(i18n("Steps over the next assembly instruction.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(stepOverInstruction())); ac->addAction("debug_stepoverinst", action); m_stepInto = action = new QAction(QIcon::fromTheme("debug-step-into"), i18n("Step &Into"), this); action->setShortcut(Qt::Key_F11); action->setToolTip( i18n("Step into the next statement") ); action->setWhatsThis( i18n("Executes exactly one line of source. If the source line " "is a call to a function then execution will stop after " "the function has been entered.") ); connect(action, SIGNAL(triggered(bool)), this, SLOT(stepInto())); ac->addAction("debug_stepinto", action); m_stepIntoInstruction = action = new QAction(QIcon::fromTheme("debug-step-into-instruction"), i18n("Step into I&nstruction"), this); action->setToolTip( i18n("Step into instruction") ); action->setWhatsThis(i18n("Steps into the next assembly instruction.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(stepIntoInstruction())); ac->addAction("debug_stepintoinst", action); m_stepOut = action = new QAction(QIcon::fromTheme("debug-step-out"), i18n("Step O&ut"), this); action->setShortcut(Qt::Key_F12); action->setToolTip( i18n("Step out of the current function") ); action->setWhatsThis( i18n("Executes the application until the currently executing " "function is completed. The debugger will then display " "the line after the original call to that function. If " "program execution is in the outermost frame (i.e. in " "main()) then this operation has no effect.") ); connect(action, SIGNAL(triggered(bool)), this, SLOT(stepOut())); ac->addAction("debug_stepout", action); m_toggleBreakpoint = action = new QAction(QIcon::fromTheme("script-error"), i18n("Toggle Breakpoint"), this); action->setShortcut( i18n("Ctrl+Alt+B") ); action->setToolTip(i18n("Toggle breakpoint")); action->setWhatsThis(i18n("Toggles the breakpoint at the current line in editor.")); connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleBreakpoint())); ac->addAction("debug_toggle_breakpoint", action); } void DebugController::addSession(IDebugSession* session) { kDebug() << session; Q_ASSERT(session->variableController()); Q_ASSERT(session->breakpointController()); Q_ASSERT(session->frameStackModel()); //TODO support multiple sessions if (m_currentSession) { m_currentSession.data()->stopDebugger(); } m_currentSession = session; connect(session, SIGNAL(stateChanged(KDevelop::IDebugSession::DebuggerState)), SLOT(debuggerStateChanged(KDevelop::IDebugSession::DebuggerState))); connect(session, SIGNAL(showStepInSource(KUrl,int,QString)), SLOT(showStepInSource(KUrl,int))); connect(session, SIGNAL(clearExecutionPoint()), SLOT(clearExecutionPoint())); connect(session, SIGNAL(raiseFramestackViews()), SIGNAL(raiseFramestackViews())); updateDebuggerState(session->state(), session); emit currentSessionChanged(session); if((Core::self()->setupFlags() & Core::NoUi)) return; Sublime::MainWindow* mainWindow = Core::self()->uiControllerInternal()->activeSublimeWindow(); if (mainWindow->area()->objectName() != "debug") { QString workingSet = mainWindow->area()->workingSet(); ICore::self()->uiController()->switchToArea("debug", IUiController::ThisWindow); mainWindow->area()->setWorkingSet(workingSet); connect(mainWindow, SIGNAL(areaChanged(Sublime::Area*)), SLOT(areaChanged(Sublime::Area*))); } } void DebugController::clearExecutionPoint() { kDebug(); foreach (KDevelop::IDocument* document, KDevelop::ICore::self()->documentController()->openDocuments()) { KTextEditor::MarkInterface *iface = dynamic_cast(document->textDocument()); if (!iface) continue; QHashIterator it = iface->marks(); while (it.hasNext()) { KTextEditor::Mark* mark = it.next().value(); if( mark->type & KTextEditor::MarkInterface::Execution ) iface->removeMark( mark->line, KTextEditor::MarkInterface::Execution ); } } } -void DebugController::showStepInSource(const KUrl &url, int lineNum) +void DebugController::showStepInSource(const QUrl &url, int lineNum) { if((Core::self()->setupFlags() & Core::NoUi)) return; clearExecutionPoint(); kDebug() << url << lineNum; Q_ASSERT(dynamic_cast(sender())); - QPair openUrl = static_cast(sender())->convertToLocalUrl(qMakePair( url, lineNum )); + QPair openUrl = static_cast(sender())->convertToLocalUrl(qMakePair( url, lineNum )); KDevelop::IDocument* document = KDevelop::ICore::self() ->documentController() ->openDocument(openUrl.first, KTextEditor::Cursor(openUrl.second, 0), IDocumentController::DoNotFocus); if( !document ) return; KTextEditor::MarkInterface *iface = dynamic_cast(document->textDocument()); if( !iface ) return; document->textDocument()->blockSignals(true); iface->addMark( lineNum, KTextEditor::MarkInterface::Execution ); document->textDocument()->blockSignals(false); } void DebugController::debuggerStateChanged(KDevelop::IDebugSession::DebuggerState state) { Q_ASSERT(dynamic_cast(sender())); IDebugSession* session = static_cast(sender()); kDebug() << session << state << "current" << m_currentSession.data(); if (session == m_currentSession.data()) { updateDebuggerState(state, session); } if (state == IDebugSession::EndedState) { if (session == m_currentSession.data()) { m_currentSession.clear(); emit currentSessionChanged(0); if (!Core::self()->shuttingDown()) { Sublime::MainWindow* mainWindow = Core::self()->uiControllerInternal()->activeSublimeWindow(); if (mainWindow && mainWindow->area()->objectName() != "code") { QString workingSet = mainWindow->area()->workingSet(); ICore::self()->uiController()->switchToArea("code", IUiController::ThisWindow); mainWindow->area()->setWorkingSet(workingSet); } ICore::self()->uiController()->findToolView(i18n("Debug"), 0, IUiController::Raise); } } session->deleteLater(); } } void DebugController::updateDebuggerState(IDebugSession::DebuggerState state, IDebugSession *session) { Q_UNUSED(session); if((Core::self()->setupFlags() & Core::NoUi)) return; kDebug() << state; switch (state) { case IDebugSession::StoppedState: case IDebugSession::NotStartedState: case IDebugSession::StoppingState: kDebug() << "new state: stopped"; stateChanged("stopped"); //m_restartDebugger->setEnabled(session->restartAvailable()); break; case IDebugSession::StartingState: case IDebugSession::PausedState: kDebug() << "new state: paused"; stateChanged("paused"); //m_restartDebugger->setEnabled(session->restartAvailable()); break; case IDebugSession::ActiveState: kDebug() << "new state: active"; stateChanged("active"); //m_restartDebugger->setEnabled(false); break; case IDebugSession::EndedState: kDebug() << "new state: ended"; stateChanged("ended"); //m_restartDebugger->setEnabled(false); break; } if (state == IDebugSession::PausedState && ICore::self()->uiController()->activeMainWindow()) { ICore::self()->uiController()->activeMainWindow()->activateWindow(); } } ContextMenuExtension DebugController::contextMenuExtension( Context* context ) { ContextMenuExtension menuExt; if( context->type() != Context::EditorContext ) return menuExt; KDevelop::EditorContext *econtext = dynamic_cast(context); if (!econtext) return menuExt; if (m_currentSession && m_currentSession.data()->isRunning()) { menuExt.addAction( KDevelop::ContextMenuExtension::DebugGroup, m_runToCursor); } if (econtext->url().isLocalFile()) { menuExt.addAction( KDevelop::ContextMenuExtension::DebugGroup, m_toggleBreakpoint); } return menuExt; } #if 0 void DebugController::restartDebugger() { if (m_currentSession) { m_currentSession.data()->restartDebugger(); } } #endif void DebugController::stopDebugger() { if (m_currentSession) { m_currentSession.data()->stopDebugger(); } } void DebugController::interruptDebugger() { if (m_currentSession) { m_currentSession.data()->interruptDebugger(); } } void DebugController::run() { if (m_currentSession) { m_currentSession.data()->run(); } } void DebugController::runToCursor() { if (m_currentSession) { m_currentSession.data()->runToCursor(); } } void DebugController::jumpToCursor() { if (m_currentSession) { m_currentSession.data()->jumpToCursor(); } } void DebugController::stepOver() { if (m_currentSession) { m_currentSession.data()->stepOver(); } } void DebugController::stepIntoInstruction() { if (m_currentSession) { m_currentSession.data()->stepIntoInstruction(); } } void DebugController::stepInto() { if (m_currentSession) { m_currentSession.data()->stepInto(); } } void DebugController::stepOverInstruction() { if (m_currentSession) { m_currentSession.data()->stepOverInstruction(); } } void DebugController::stepOut() { if (m_currentSession) { m_currentSession.data()->stepOut(); } } void DebugController::areaChanged(Sublime::Area* newArea) { if (newArea->objectName()!="debug") { stopDebugger(); } } void DebugController::toggleBreakpoint() { if (KDevelop::IDocument* document = KDevelop::ICore::self()->documentController()->activeDocument()) { KTextEditor::Cursor cursor = document->cursorPosition(); if (!cursor.isValid()) return; breakpointModel()->toggleBreakpoint(document->url(), cursor); } } const QPixmap* DebugController::executionPointPixmap() { static QPixmap pixmap=QIcon::fromTheme("go-next").pixmap(QSize(22,22), QIcon::Normal, QIcon::Off); return &pixmap; } } diff --git a/shell/debugcontroller.h b/shell/debugcontroller.h index 0c525b53dc..c7163d3455 100644 --- a/shell/debugcontroller.h +++ b/shell/debugcontroller.h @@ -1,123 +1,123 @@ /* This file is part of KDevelop * * Copyright 1999-2001 John Birch * Copyright 2001 by Bernd Gehrmann * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_DEBUGCONTROLLER_H #define KDEVPLATFORM_DEBUGCONTROLLER_H #include #include #include #include #include "../interfaces/idebugcontroller.h" #include "../debugger/interfaces/idebugsession.h" class QAction; namespace Sublime { class Area; } namespace KParts { class Part; } namespace KDevelop { class Context; class ContextMenuExtension; class DebugController : public IDebugController, public KXMLGUIClient { Q_OBJECT public: DebugController(QObject *parent = 0); ~DebugController(); void initialize(); void cleanup(); /// Must be called by debugger plugin that needs debugger actions and toolviews. virtual void initializeUi(); virtual void addSession(IDebugSession* session); virtual IDebugSession* currentSession(); ContextMenuExtension contextMenuExtension( Context* context ); virtual BreakpointModel* breakpointModel(); virtual VariableCollection* variableCollection(); private Q_SLOTS: //void restartDebugger(); void stopDebugger(); void interruptDebugger(); void run(); void runToCursor(); void jumpToCursor(); void stepOver(); void stepIntoInstruction(); void stepInto(); void stepOverInstruction(); void stepOut(); void toggleBreakpoint(); void debuggerStateChanged(KDevelop::IDebugSession::DebuggerState state); - void showStepInSource(const KUrl &file, int line); + void showStepInSource(const QUrl &file, int line); void clearExecutionPoint(); void partAdded(KParts::Part* part); void areaChanged(Sublime::Area* newArea); Q_SIGNALS: void raiseFramestackViews(); private: void setupActions(); void updateDebuggerState(KDevelop::IDebugSession::DebuggerState state, KDevelop::IDebugSession* session); static const QPixmap* executionPointPixmap(); QAction* m_continueDebugger; //QAction* m_restartDebugger; QAction* m_stopDebugger; QAction* m_interruptDebugger; QAction* m_runToCursor; QAction* m_jumpToCursor; QAction* m_stepOver; QAction* m_stepIntoInstruction; QAction* m_stepInto; QAction* m_stepOverInstruction; QAction* m_stepOut; QAction* m_toggleBreakpoint; QPointer m_currentSession; BreakpointModel *m_breakpointModel; VariableCollection *m_variableCollection; bool m_uiInitialized; }; } #endif