diff --git a/debugger/breakpoint/breakpointdetails.cpp b/debugger/breakpoint/breakpointdetails.cpp index 250c179001..d58ef551b0 100644 --- a/debugger/breakpoint/breakpointdetails.cpp +++ b/debugger/breakpoint/breakpointdetails.cpp @@ -1,165 +1,160 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * * 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 "breakpointdetails.h" #include #include #include #include #include #include #include "../breakpoint/breakpoint.h" #include "../interfaces/idebugsession.h" #include "../../interfaces/icore.h" #include "../interfaces/ibreakpointcontroller.h" #include "../../interfaces/idebugcontroller.h" using namespace KDevelop; BreakpointDetails::BreakpointDetails(QWidget *parent) : QWidget(parent), m_currentBreakpoint(0) { QVBoxLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(11, 0, 0, 11); m_status = new QLabel(this); connect(m_status, &QLabel::linkActivated, this, &BreakpointDetails::showExplanation); layout->addWidget(m_status); QGridLayout* hitsLayout = new QGridLayout(); layout->addLayout(hitsLayout); hitsLayout->setContentsMargins(0, 0, 0, 0); m_hits = new QLabel(i18n("Not hit yet"), this); m_hits->setWordWrap(true); hitsLayout->addWidget(m_hits, 0, 0, 1, 3); - QFrame* frame = new QFrame(this); - frame->setFrameShape(QFrame::HLine); - hitsLayout->addWidget(frame, 1, 0, 1, 3); - QLabel *l2 = new QLabel(i18n("Ignore"), this); hitsLayout->addWidget(l2, 2, 0); m_ignore = new QSpinBox(this); hitsLayout->addWidget(m_ignore, 2, 1); m_ignore->setRange(0, 99999); connect(m_ignore, static_cast(&QSpinBox::valueChanged), this, &BreakpointDetails::setIgnoreHits); QLabel *l3 = new QLabel(i18n("next hits"), this); hitsLayout->addWidget(l3, 2, 2); layout->addStretch(); setItem(0); //initialize with no breakpoint active } void KDevelop::BreakpointDetails::setIgnoreHits(int ignoreHits) { if (!m_currentBreakpoint) return; m_currentBreakpoint->setIgnoreHits(ignoreHits); } void BreakpointDetails::setItem(Breakpoint *breakpoint) { m_currentBreakpoint = breakpoint; if (!breakpoint) { m_status->hide(); m_hits->hide(); m_ignore->setEnabled(false); return; } m_ignore->setValue(breakpoint->ignoreHits()); if (breakpoint->state() == Breakpoint::NotStartedState) { m_status->hide(); m_hits->hide(); m_ignore->setEnabled(true); return; } m_status->show(); m_hits->show(); m_ignore->setEnabled(true); if (breakpoint->errorText().isEmpty()) { switch (breakpoint->state()) { case Breakpoint::NotStartedState: Q_ASSERT(0); break; case Breakpoint::PendingState: m_status->setText(i18n("Breakpoint is pending")); break; case Breakpoint::DirtyState: m_status->setText(i18n("Breakpoint is dirty")); break; case Breakpoint::CleanState: m_status->setText(i18n("Breakpoint is active")); break; } if (breakpoint->hitCount() == -1) m_hits->clear(); else if (breakpoint->hitCount()) m_hits->setText(i18np("Hit %1 time", "Hit %1 times", breakpoint->hitCount())); else m_hits->setText(i18n("Not hit yet")); } else { m_status->setText(i18n("Breakpoint has errors")); m_hits->setText(breakpoint->errorText()); } } void BreakpointDetails::showExplanation(const QString& link) { QPoint pos = m_status->mapToGlobal(m_status->geometry().topLeft()); if (link == QLatin1String("pending")) { QWhatsThis::showText(pos, i18n("Breakpoint is pending" "

Pending breakpoints are those that have " "been passed to GDB, but which are not yet " "installed in the target, because GDB cannot " "find the function or file to which the breakpoint " "refers. The most common case is a breakpoint " "in a shared library: GDB will insert this " "breakpoint only when the library is loaded.

"), m_status); } else if (link == QLatin1String("dirty")) { QWhatsThis::showText(pos, i18n("Breakpoint is dirty" "

The breakpoint has not yet been passed " "to the debugger.

"), m_status); } } diff --git a/debugger/breakpoint/breakpointdetails.h b/debugger/breakpoint/breakpointdetails.h index 59afa303a9..20c2897971 100644 --- a/debugger/breakpoint/breakpointdetails.h +++ b/debugger/breakpoint/breakpointdetails.h @@ -1,57 +1,57 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * * 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_BREAKPOINTDETAILS_H #define KDEVPLATFORM_BREAKPOINTDETAILS_H #include #include "debuggerexport.h" class QSpinBox; class QLabel; namespace KDevelop { class Breakpoint; class KDEVPLATFORMDEBUGGER_EXPORT BreakpointDetails : public QWidget { Q_OBJECT public: - explicit BreakpointDetails(QWidget *parent); + explicit BreakpointDetails(QWidget *parent = nullptr); void setItem(Breakpoint *breakpoint); private Q_SLOTS: void showExplanation(const QString& link); void setIgnoreHits(int ignoreHits); private: QLabel* m_status; QLabel* m_hits; QSpinBox* m_ignore; Breakpoint* m_currentBreakpoint; }; } #endif // KDEVPLATFORM_BREAKPOINTDETAILS_H diff --git a/debugger/breakpoint/breakpointwidget.cpp b/debugger/breakpoint/breakpointwidget.cpp index 81d8464b4d..fe539b1a2b 100644 --- a/debugger/breakpoint/breakpointwidget.cpp +++ b/debugger/breakpoint/breakpointwidget.cpp @@ -1,309 +1,314 @@ /* * 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 "util/debug.h" #include #include #define IF_DEBUG(x) #include #include #include using namespace KDevelop; BreakpointWidget::BreakpointWidget(IDebugController *controller, QWidget *parent) : AutoOrientedSplitter(parent), m_firstShow(true), m_debugController(controller), m_breakpointDisableAllAction(0), m_breakpointEnableAllAction(0), m_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( QStringLiteral( "media-playback-pause"), windowIcon() ) ); m_breakpointsView = new QTreeView(this); m_breakpointsView->setSelectionBehavior(QAbstractItemView::SelectRows); m_breakpointsView->setSelectionMode(QAbstractItemView::SingleSelection); m_breakpointsView->setRootIsDecorated(false); - m_details = new BreakpointDetails(this); + + auto detailsContainer = new QGroupBox(i18n("Breakpoint Details"), this); + auto detailsLayout = new QVBoxLayout(detailsContainer); + m_details = new BreakpointDetails(detailsContainer); + detailsLayout->addWidget(m_details); setStretchFactor(0, 2); 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, &PlaceholderItemProxyModel::dataInserted, this, &BreakpointWidget::slotDataInserted); m_proxyModel = proxyModel; connect(m_breakpointsView, &QTreeView::activated, this, &BreakpointWidget::slotOpenFile); connect(m_breakpointsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BreakpointWidget::slotUpdateBreakpointDetail); connect(m_debugController->breakpointModel(), &BreakpointModel::rowsInserted, this, &BreakpointWidget::slotUpdateBreakpointDetail); connect(m_debugController->breakpointModel(), &BreakpointModel::rowsRemoved, this, &BreakpointWidget::slotUpdateBreakpointDetail); connect(m_debugController->breakpointModel(), &BreakpointModel::modelReset, this, &BreakpointWidget::slotUpdateBreakpointDetail); connect(m_debugController->breakpointModel(), &BreakpointModel::dataChanged, this, &BreakpointWidget::slotUpdateBreakpointDetail); connect(m_debugController->breakpointModel(), &BreakpointModel::hit, this, &BreakpointWidget::breakpointHit); connect(m_debugController->breakpointModel(), &BreakpointModel::error, this, &BreakpointWidget::breakpointError); setupPopupMenu(); } void BreakpointWidget::setupPopupMenu() { m_popup = new QMenu(this); QMenu* newBreakpoint = m_popup->addMenu( i18nc("New breakpoint", "&New") ); newBreakpoint->setIcon(QIcon::fromTheme(QStringLiteral("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 = m_popup->addAction( QIcon::fromTheme(QStringLiteral("edit-delete")), i18n( "&Delete" ), this, SLOT(slotRemoveBreakpoint())); breakpointDelete->setShortcut(Qt::Key_Delete); breakpointDelete->setShortcutContext(Qt::WidgetWithChildrenShortcut); addAction(breakpointDelete); m_popup->addSeparator(); m_breakpointDisableAllAction = m_popup->addAction(i18n("Disable &All"), this, SLOT(slotDisableAllBreakpoints())); m_breakpointEnableAllAction = m_popup->addAction(i18n("&Enable All"), this, SLOT(slotEnableAllBreakpoints())); m_breakpointRemoveAll = m_popup->addAction(i18n("&Remove All"), this, SLOT(slotRemoveAllBreakpoints())); connect(m_popup,&QMenu::aboutToShow, this, &BreakpointWidget::slotPopupMenuAboutToShow); } void BreakpointWidget::contextMenuEvent(QContextMenuEvent* event) { m_popup->popup(event->globalPos()); } void BreakpointWidget::slotPopupMenuAboutToShow() { if (m_debugController->breakpointModel()->rowCount() < 2) { m_breakpointDisableAllAction->setDisabled(true); m_breakpointEnableAllAction->setDisabled(true); m_breakpointRemoveAll->setDisabled(true); } else { m_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; } m_breakpointDisableAllAction->setDisabled(allDisabled); m_breakpointEnableAllAction->setDisabled(allEnabled); } } void BreakpointWidget::showEvent(QShowEvent *) { if (m_firstShow) { 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(); QHeaderView* header = m_breakpointsView->header(); 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( qCDebug(DEBUGGER) << 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( qCDebug(DEBUGGER) << selected; ) if (selected.isEmpty()) { m_details->setItem(0); } else { m_details->setItem(m_debugController->breakpointModel()->breakpoint(selected.first().row())); } } void BreakpointWidget::breakpointHit(int row) { const QModelIndex index = m_proxyModel->mapFromSource(m_debugController->breakpointModel()->index(row, 0)); m_breakpointsView->selectionModel()->select( index, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } void BreakpointWidget::breakpointError(int row, const QString& msg) { // 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()->index(row, BreakpointModel::LocationColumn)); 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(QString(), 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(), 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); } }