• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdevelop API Reference
  • KDE Home
  • Contact Us
 

kdevelop/kdevplatform/debugger

  • extragear
  • kdevelop
  • kdevelop
  • kdevplatform
  • debugger
  • breakpoint
breakpointwidget.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KDevelop
3  *
4  * Copyright 2008 Vladimir Prus <[email protected]>
5  * Copyright 2013 Vlas Puhov <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #include "breakpointwidget.h"
24 
25 #include <QIcon>
26 #include <QGroupBox>
27 #include <QVBoxLayout>
28 #include <QTreeView>
29 #include <QHeaderView>
30 #include <QMenu>
31 #include <QContextMenuEvent>
32 
33 #include <KLocalizedString>
34 #include <KPassivePopup>
35 
36 #include "breakpointdetails.h"
37 #include "../breakpoint/breakpoint.h"
38 #include "../breakpoint/breakpointmodel.h"
39 #include <debug.h>
40 #include <interfaces/idebugcontroller.h>
41 #include <util/autoorientedsplitter.h>
42 
43 #define IF_DEBUG(x)
44 #include <interfaces/icore.h>
45 #include <interfaces/idocumentcontroller.h>
46 #include <util/placeholderitemproxymodel.h>
47 
48 using namespace KDevelop;
49 
50 class KDevelop::BreakpointWidgetPrivate
51 {
52 public:
53  explicit BreakpointWidgetPrivate(IDebugController *controller)
54  : debugController(controller)
55  {
56  }
57 
58  QTreeView* breakpointsView = nullptr;
59  BreakpointDetails* details = nullptr;
60  QMenu* popup = nullptr;
61  bool firstShow = true;
62  IDebugController* debugController;
63  QAction* breakpointDisableAllAction = nullptr;
64  QAction* breakpointEnableAllAction = nullptr;
65  QAction* breakpointRemoveAll = nullptr;
66  QAbstractProxyModel* proxyModel = nullptr;
67 };
68 
69 BreakpointWidget::BreakpointWidget(IDebugController *controller, QWidget *parent)
70  : AutoOrientedSplitter(parent)
71  , d_ptr(new BreakpointWidgetPrivate(controller))
72 {
73  Q_D(BreakpointWidget);
74 
75  setWindowTitle(i18nc("@title:window", "Debugger Breakpoints"));
76  setWhatsThis(i18nc("@info:whatsthis", "Displays a list of breakpoints with "
77  "their current status. Clicking on a "
78  "breakpoint item allows you to change "
79  "the breakpoint and will take you "
80  "to the source in the editor window."));
81  setWindowIcon( QIcon::fromTheme( QStringLiteral( "media-playback-pause"), windowIcon() ) );
82 
83  d->breakpointsView = new QTreeView(this);
84  d->breakpointsView->setSelectionBehavior(QAbstractItemView::SelectRows);
85  d->breakpointsView->setSelectionMode(QAbstractItemView::SingleSelection);
86  d->breakpointsView->setRootIsDecorated(false);
87 
88  auto detailsContainer = new QGroupBox(i18n("Breakpoint Details"), this);
89  auto detailsLayout = new QVBoxLayout(detailsContainer);
90  d->details = new BreakpointDetails(detailsContainer);
91  detailsLayout->addWidget(d->details);
92 
93  setStretchFactor(0, 2);
94 
95  auto* proxyModel = new PlaceholderItemProxyModel(this);
96  proxyModel->setSourceModel(d->debugController->breakpointModel());
97  proxyModel->setColumnHint(Breakpoint::LocationColumn, i18n("New code breakpoint ..."));
98  proxyModel->setColumnHint(Breakpoint::ConditionColumn, i18n("Enter condition ..."));
99  d->breakpointsView->setModel(proxyModel);
100  connect(proxyModel, &PlaceholderItemProxyModel::dataInserted, this, &BreakpointWidget::slotDataInserted);
101  d->proxyModel = proxyModel;
102 
103  connect(d->breakpointsView, &QTreeView::activated, this, &BreakpointWidget::slotOpenFile);
104  connect(d->breakpointsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BreakpointWidget::slotUpdateBreakpointDetail);
105  connect(d->debugController->breakpointModel(), &BreakpointModel::rowsInserted, this, &BreakpointWidget::slotUpdateBreakpointDetail);
106  connect(d->debugController->breakpointModel(), &BreakpointModel::rowsRemoved, this, &BreakpointWidget::slotUpdateBreakpointDetail);
107  connect(d->debugController->breakpointModel(), &BreakpointModel::modelReset, this, &BreakpointWidget::slotUpdateBreakpointDetail);
108  connect(d->debugController->breakpointModel(), &BreakpointModel::dataChanged, this, &BreakpointWidget::slotUpdateBreakpointDetail);
109 
110 
111  connect(d->debugController->breakpointModel(),
112  &BreakpointModel::hit,
113  this, &BreakpointWidget::breakpointHit);
114 
115  connect(d->debugController->breakpointModel(),
116  &BreakpointModel::error,
117  this, &BreakpointWidget::breakpointError);
118 
119  setupPopupMenu();
120 }
121 
122 BreakpointWidget::~BreakpointWidget() = default;
123 
124 void BreakpointWidget::setupPopupMenu()
125 {
126  Q_D(BreakpointWidget);
127 
128  d->popup = new QMenu(this);
129 
130  QMenu* newBreakpoint = d->popup->addMenu(i18nc("New breakpoint", "&New"));
131  newBreakpoint->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
132 
133  QAction* action = newBreakpoint->addAction(
134  i18nc("Code breakpoint", "&Code"),
135  this,
136  SLOT(slotAddBlankBreakpoint()) );
137  // Use this action also to provide a local shortcut
138  action->setShortcut(QKeySequence(Qt::Key_B + Qt::CTRL,
139  Qt::Key_C));
140  addAction(action);
141 
142  newBreakpoint->addAction(
143  i18nc("Data breakpoint", "Data &Write"),
144  this, SLOT(slotAddBlankWatchpoint()));
145  newBreakpoint->addAction(
146  i18nc("Data read breakpoint", "Data &Read"),
147  this, SLOT(slotAddBlankReadWatchpoint()));
148  newBreakpoint->addAction(
149  i18nc("Data access breakpoint", "Data &Access"),
150  this, SLOT(slotAddBlankAccessWatchpoint()));
151 
152  QAction* breakpointDelete = d->popup->addAction(
153  QIcon::fromTheme(QStringLiteral("edit-delete")),
154  i18n( "&Delete" ),
155  this,
156  SLOT(slotRemoveBreakpoint()));
157  breakpointDelete->setShortcut(Qt::Key_Delete);
158  breakpointDelete->setShortcutContext(Qt::WidgetWithChildrenShortcut);
159  addAction(breakpointDelete);
160 
161 
162  d->popup->addSeparator();
163  d->breakpointDisableAllAction = d->popup->addAction(i18n("Disable &All"), this, SLOT(slotDisableAllBreakpoints()));
164  d->breakpointEnableAllAction = d->popup->addAction(i18n("&Enable All"), this, SLOT(slotEnableAllBreakpoints()));
165  d->breakpointRemoveAll = d->popup->addAction(i18n("&Remove All"), this, SLOT(slotRemoveAllBreakpoints()));
166 
167  connect(d->popup, &QMenu::aboutToShow, this, &BreakpointWidget::slotPopupMenuAboutToShow);
168 }
169 
170 
171 void BreakpointWidget::contextMenuEvent(QContextMenuEvent* event)
172 {
173  Q_D(BreakpointWidget);
174 
175  d->popup->popup(event->globalPos());
176 }
177 
178 void BreakpointWidget::slotPopupMenuAboutToShow()
179 {
180  Q_D(BreakpointWidget);
181 
182  if (d->debugController->breakpointModel()->rowCount() < 1) {
183  d->breakpointDisableAllAction->setDisabled(true);
184  d->breakpointEnableAllAction->setDisabled(true);
185  d->breakpointRemoveAll->setDisabled(true);
186  } else {
187  d->breakpointRemoveAll->setEnabled(true);
188  bool allDisabled = true;
189  bool allEnabled = true;
190  for (int i = 0; i < d->debugController->breakpointModel()->rowCount(); ++i) {
191  Breakpoint* bp = d->debugController->breakpointModel()->breakpoint(i);
192  if (bp->enabled())
193  allDisabled = false;
194  else
195  allEnabled = false;
196  }
197  d->breakpointDisableAllAction->setDisabled(allDisabled);
198  d->breakpointEnableAllAction->setDisabled(allEnabled);
199  }
200 
201 }
202 
203 void BreakpointWidget::showEvent(QShowEvent *)
204 {
205  Q_D(BreakpointWidget);
206 
207  if (d->firstShow && d->debugController->breakpointModel()->rowCount() > 0) {
208  for (int i = 0; i < d->breakpointsView->model()->columnCount(); ++i) {
209  if(i == Breakpoint::LocationColumn){
210  continue;
211  }
212  d->breakpointsView->resizeColumnToContents(i);
213  }
214  //for some reasons sometimes width can be very small about 200... But it doesn't matter as we use tooltip anyway.
215  int width = d->breakpointsView->size().width();
216 
217  QHeaderView* header = d->breakpointsView->header();
218  header->resizeSection(Breakpoint::LocationColumn, width > 400 ? width/2 : header->sectionSize(Breakpoint::LocationColumn)*2 );
219  d->firstShow = false;
220  }
221 }
222 
223 void BreakpointWidget::edit(KDevelop::Breakpoint *n)
224 {
225  Q_D(BreakpointWidget);
226 
227  QModelIndex index = d->proxyModel->mapFromSource(d->debugController->breakpointModel()->breakpointIndex(n, Breakpoint::LocationColumn));
228  d->breakpointsView->setCurrentIndex(index);
229  d->breakpointsView->edit(index);
230 }
231 
232 void BreakpointWidget::slotDataInserted(int column, const QVariant& value)
233 {
234  Q_D(BreakpointWidget);
235 
236  Breakpoint* breakpoint = d->debugController->breakpointModel()->addCodeBreakpoint();
237  breakpoint->setData(column, value);
238 }
239 
240 void BreakpointWidget::slotAddBlankBreakpoint()
241 {
242  Q_D(BreakpointWidget);
243 
244  edit(d->debugController->breakpointModel()->addCodeBreakpoint());
245 }
246 
247 void BreakpointWidget::slotAddBlankWatchpoint()
248 {
249  Q_D(BreakpointWidget);
250 
251  edit(d->debugController->breakpointModel()->addWatchpoint());
252 }
253 
254 void BreakpointWidget::slotAddBlankReadWatchpoint()
255 {
256  Q_D(BreakpointWidget);
257 
258  edit(d->debugController->breakpointModel()->addReadWatchpoint());
259 }
260 
261 
262 void KDevelop::BreakpointWidget::slotAddBlankAccessWatchpoint()
263 {
264  Q_D(BreakpointWidget);
265 
266  edit(d->debugController->breakpointModel()->addAccessWatchpoint());
267 }
268 
269 
270 void BreakpointWidget::slotRemoveBreakpoint()
271 {
272  Q_D(BreakpointWidget);
273 
274  QItemSelectionModel* sel = d->breakpointsView->selectionModel();
275  QModelIndexList selected = sel->selectedIndexes();
276  IF_DEBUG( qCDebug(DEBUGGER) << selected; )
277  if (!selected.isEmpty()) {
278  d->debugController->breakpointModel()->removeRow(selected.first().row());
279  }
280 }
281 
282 void BreakpointWidget::slotRemoveAllBreakpoints()
283 {
284  Q_D(BreakpointWidget);
285 
286  d->debugController->breakpointModel()->removeRows(0, d->debugController->breakpointModel()->rowCount());
287 }
288 
289 
290 void BreakpointWidget::slotUpdateBreakpointDetail()
291 {
292  Q_D(BreakpointWidget);
293 
294  showEvent(nullptr);
295  QModelIndexList selected = d->breakpointsView->selectionModel()->selectedIndexes();
296  IF_DEBUG( qCDebug(DEBUGGER) << selected; )
297  if (selected.isEmpty()) {
298  d->details->setItem(nullptr);
299  } else {
300  d->details->setItem(d->debugController->breakpointModel()->breakpoint(selected.first().row()));
301  }
302 }
303 
304 void BreakpointWidget::breakpointHit(int row)
305 {
306  Q_D(BreakpointWidget);
307 
308  const QModelIndex index = d->proxyModel->mapFromSource(d->debugController->breakpointModel()->index(row, 0));
309  d->breakpointsView->selectionModel()->select(
310  index,
311  QItemSelectionModel::Rows
312  | QItemSelectionModel::ClearAndSelect);
313 }
314 
315 void BreakpointWidget::breakpointError(int row, const QString& msg)
316 {
317  Q_D(BreakpointWidget);
318 
319  // FIXME: we probably should prevent this error notification during
320  // initial setting of breakpoint, to avoid a cloud of popups.
321  if (!d->breakpointsView->isVisible())
322  return;
323 
324  const QModelIndex index = d->proxyModel->mapFromSource(
325  d->debugController->breakpointModel()->index(row, BreakpointModel::LocationColumn));
326  QPoint p = d->breakpointsView->visualRect(index).topLeft();
327  p = d->breakpointsView->mapToGlobal(p);
328 
329  KPassivePopup *pop = new KPassivePopup(d->breakpointsView);
330  pop->setPopupStyle(KPassivePopup::Boxed);
331  pop->setAutoDelete(true);
332  // FIXME: the icon, too.
333  pop->setView(QString(), msg);
334  pop->setTimeout(-1);
335  pop->show(p);
336 }
337 
338 void BreakpointWidget::slotOpenFile(const QModelIndex& breakpointIdx)
339 {
340  Q_D(BreakpointWidget);
341 
342  if (breakpointIdx.column() != Breakpoint::LocationColumn){
343  return;
344  }
345  Breakpoint* bp = d->debugController->breakpointModel()->breakpoint(breakpointIdx.row());
346  if (!bp || bp->line() == -1 || bp->url().isEmpty() ){
347  return;
348  }
349 
350  ICore::self()->documentController()->openDocument(bp->url(), KTextEditor::Cursor(bp->line(), 0), IDocumentController::DoNotFocus);
351 }
352 
353 void BreakpointWidget::slotDisableAllBreakpoints()
354 {
355  Q_D(BreakpointWidget);
356 
357  for (int i = 0; i < d->debugController->breakpointModel()->rowCount(); ++i) {
358  Breakpoint* bp = d->debugController->breakpointModel()->breakpoint(i);
359  bp->setData(Breakpoint::EnableColumn, Qt::Unchecked);
360  }
361 }
362 
363 void BreakpointWidget::slotEnableAllBreakpoints()
364 {
365  Q_D(BreakpointWidget);
366 
367  for (int i = 0; i < d->debugController->breakpointModel()->rowCount(); ++i) {
368  Breakpoint* bp = d->debugController->breakpointModel()->breakpoint(i);
369  bp->setData(Breakpoint::EnableColumn, Qt::Checked);
370  }
371 }
372 
373 
QModelIndex
QItemSelectionModel::selectionChanged
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
QWidget
QAction::setShortcutContext
void setShortcutContext(Qt::ShortcutContext context)
KDevelop::Breakpoint
Definition: breakpoint.h:38
QAbstractProxyModel
QMenu::addAction
void addAction(QAction *action)
KDevelop::Breakpoint::line
int line() const
Definition: breakpoint.cpp:220
QAbstractItemModel::modelReset
void modelReset()
QPoint
KDevelop::BreakpointModel::error
void error(int row, const QString &errorText)
KDevelop::Breakpoint::LocationColumn
Definition: breakpoint.h:75
KDevelop::BreakpointWidget::showEvent
void showEvent(QShowEvent *event) override
Definition: breakpointwidget.cpp:203
QUrl::isEmpty
bool isEmpty() const
QContextMenuEvent::globalPos
const QPoint & globalPos() const
KDevelop::BreakpointWidget::~BreakpointWidget
~BreakpointWidget() override
KDevelop::BreakpointModel::hit
void hit(int row)
QHeaderView::resizeSection
void resizeSection(int logicalIndex, int size)
KDevelop::BreakpointWidget::BreakpointWidget
BreakpointWidget(IDebugController *controller, QWidget *parent)
Definition: breakpointwidget.cpp:69
QMenu::aboutToShow
void aboutToShow()
QMenu::setIcon
void setIcon(const QIcon &icon)
QMenu::popup
void popup(const QPoint &p, QAction *atAction)
QGroupBox
QAbstractItemModel::dataChanged
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
QShowEvent
QContextMenuEvent
KDevelop::BreakpointWidget
Definition: breakpointwidget.h:37
QItemSelectionModel::selectedIndexes
QModelIndexList selectedIndexes() const
QModelIndex::row
int row() const
QVBoxLayout
IF_DEBUG
#define IF_DEBUG(x)
Definition: breakpointwidget.cpp:43
KDevelop::BreakpointModel::LocationColumn
Location of the breakpoint (modifiable by user); value is a string describing the location; note that...
Definition: breakpointmodel.h:72
QString
KDevelop::BreakpointModel::breakpoint
Breakpoint * breakpoint(int row) const
Definition: breakpointmodel.cpp:617
QAbstractItemModel::rowsRemoved
void rowsRemoved(const QModelIndex &parent, int start, int end)
KDevelop::BreakpointDetails
Definition: breakpointdetails.h:32
KDevelop::Breakpoint::url
QUrl url() const
Definition: breakpoint.cpp:234
QHeaderView::sectionSize
int sectionSize(int logicalIndex) const
QMenu
QAction::setShortcut
void setShortcut(const QKeySequence &shortcut)
breakpointdetails.h
KDevelop::Breakpoint::breakpointModel
BreakpointModel * breakpointModel()
Return the model this breakpoint is attached to.
Definition: breakpoint.cpp:89
QAbstractItemView::activated
void activated(const QModelIndex &index)
KDevelop::Breakpoint::ConditionColumn
Definition: breakpoint.h:76
KDevelop::Breakpoint::enabled
bool enabled() const
Definition: breakpoint.cpp:288
QTreeView
QKeySequence
QAction
KDevelop::Breakpoint::EnableColumn
Definition: breakpoint.h:72
QModelIndex::column
int column() const
breakpointwidget.h
KDevelop::BreakpointModel::addCodeBreakpoint
KDevelop::Breakpoint * addCodeBreakpoint()
Definition: breakpointmodel.cpp:625
QIcon::fromTheme
QIcon fromTheme(const QString &name, const QIcon &fallback)
KDevelop::Breakpoint::setData
bool setData(int index, const QVariant &value)
Definition: breakpoint.cpp:94
QHeaderView
QAbstractItemModel::rowsInserted
void rowsInserted(const QModelIndex &parent, int start, int end)
QItemSelectionModel
AutoOrientedSplitter
KDevelop::BreakpointWidget::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *event) override
Definition: breakpointwidget.cpp:171
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Thu Dec 5 2019 04:59:23 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kdevelop/kdevplatform/debugger

Skip menu "kdevelop/kdevplatform/debugger"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdevelop API Reference

Skip menu "kdevelop API Reference"
  •   kdevplatform
  •     debugger
  •     documentation
  •     interfaces
  •     language
  •       assistant
  •       backgroundparser
  •       checks
  •       classmodel
  •       codecompletion
  •       codegen
  •       duchain
  •       editor
  •       highlighting
  •       interfaces
  •       util
  •     outputview
  •     project
  •     serialization
  •     shell
  •     sublime
  •     tests
  •     util
  •     vcs

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal