Fix path determination for NetBSD.
[kdbg.git] / kdbg / brkpt.cpp
blob9b3e331caf3e4cd62ef38266ff96ec2a472c9dc4
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <kapp.h> /* i18n */
7 #if QT_VERSION >= 200
8 #include <klocale.h> /* i18n */
9 #endif
10 #include <kiconloader.h>
11 #include <ksimpleconfig.h>
12 #include <qkeycode.h>
13 #include <qpainter.h>
14 #include <qlabel.h>
15 #include <qbitmap.h>
16 #include "debugger.h"
17 #include "brkpt.h"
18 #include "dbgdriver.h"
19 #include "brkpt.moc"
20 #include <ctype.h>
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include "mydebug.h"
27 class BreakpointItem : public QListViewItem, public Breakpoint
29 public:
30 BreakpointItem(QListView* list, const Breakpoint& bp);
31 void updateFrom(const Breakpoint& bp);
32 void display(); /* sets icon and visible texts */
36 BreakpointTable::BreakpointTable() :
37 QDialog(0, "breakpoints"),
38 m_debugger(0),
39 m_bpEdit(this, "bpedit"),
40 m_list(this, "bptable"),
41 m_btAdd(this, "add"),
42 m_btRemove(this, "remove"),
43 m_btViewCode(this, "view"),
44 m_btConditional(this, "conditional"),
45 m_btClose(this, "close"),
46 m_layout(this, 8),
47 m_listandedit(8),
48 m_buttons(8)
50 m_bpEdit.setMinimumSize(m_bpEdit.sizeHint());
51 connect(&m_bpEdit, SIGNAL(returnPressed()), this, SLOT(addBP()));
53 initListAndIcons();
54 // double click on item is same as View code
55 connect(&m_list, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(viewBP()));
57 m_btAdd.setText(i18n("&Add"));
58 m_btAdd.setMinimumSize(m_btAdd.sizeHint());
59 connect(&m_btAdd, SIGNAL(clicked()), this, SLOT(addBP()));
61 m_btRemove.setText(i18n("&Remove"));
62 m_btRemove.setMinimumSize(m_btRemove.sizeHint());
63 connect(&m_btRemove, SIGNAL(clicked()), this, SLOT(removeBP()));
65 m_btViewCode.setText(i18n("&View Code"));
66 m_btViewCode.setMinimumSize(m_btViewCode.sizeHint());
67 connect(&m_btViewCode, SIGNAL(clicked()), this, SLOT(viewBP()));
69 m_btConditional.setText(i18n("&Conditional..."));
70 m_btConditional.setMinimumSize(m_btConditional.sizeHint());
71 connect(&m_btConditional, SIGNAL(clicked()), this, SLOT(conditionalBP()));
73 m_btClose.setText(i18n("Close"));
74 m_btClose.setMinimumSize(m_btClose.sizeHint());
75 connect(&m_btClose, SIGNAL(clicked()), this, SLOT(hide()));
77 m_layout.addLayout(&m_listandedit, 10);
78 m_layout.addLayout(&m_buttons);
79 m_listandedit.addWidget(&m_bpEdit);
80 m_listandedit.addWidget(&m_list, 10);
81 m_buttons.addWidget(&m_btAdd);
82 m_buttons.addWidget(&m_btRemove);
83 m_buttons.addWidget(&m_btViewCode);
84 m_buttons.addWidget(&m_btConditional);
85 m_buttons.addWidget(&m_btClose);
86 m_buttons.addStretch(10);
88 m_layout.activate();
90 resize(350, 300);
92 m_bpEdit.setFocus();
95 BreakpointTable::~BreakpointTable()
99 void BreakpointTable::updateBreakList()
101 QList<BreakpointItem> deletedItems;
103 for (QListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
104 deletedItems.append(static_cast<BreakpointItem*>(it));
107 // get the new list
108 for (int i = m_debugger->numBreakpoints()-1; i >= 0; i--) {
109 const Breakpoint* bp = m_debugger->breakpoint(i);
110 // look up this item
111 for (BreakpointItem* oldbp = deletedItems.first(); oldbp != 0;
112 oldbp = deletedItems.next())
114 if (oldbp->id == bp->id) {
115 oldbp->updateFrom(*bp);
116 deletedItems.take(); /* don't delete */
117 goto nextItem;
120 // not in the list; add it
121 new BreakpointItem(&m_list, *bp);
122 nextItem:;
125 // delete all untouched breakpoints
126 deletedItems.setAutoDelete(true);
129 BreakpointItem::BreakpointItem(QListView* list, const Breakpoint& bp) :
130 QListViewItem(list),
131 Breakpoint(bp)
133 display();
136 void BreakpointItem::updateFrom(const Breakpoint& bp)
138 Breakpoint::operator=(bp); /* assign new values */
139 display();
142 void BreakpointTable::closeEvent(QCloseEvent* ev)
144 QDialog::closeEvent(ev);
145 emit closed();
148 void BreakpointTable::hide()
150 QDialog::hide();
151 emit closed();
154 void BreakpointTable::addBP()
156 // set a breakpoint at the specified text
157 QString bpText = m_bpEdit.text();
158 bpText = bpText.stripWhiteSpace();
159 if (m_debugger->isReady()) {
160 m_debugger->driver()->executeCmd(DCbreaktext, bpText);
161 // clear text if successfully set
162 m_bpEdit.setText("");
166 void BreakpointTable::removeBP()
168 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
169 if (bp == 0)
170 return;
172 m_debugger->driver()->executeCmd(DCdelete, bp->id);
175 void BreakpointTable::viewBP()
177 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
178 if (bp == 0)
179 return;
181 emit activateFileLine(bp->fileName, bp->lineNo);
184 void BreakpointTable::updateUI()
186 bool enableChkpt = m_debugger->canChangeBreakpoints();
187 m_btAdd.setEnabled(enableChkpt);
188 m_btRemove.setEnabled(enableChkpt);
189 m_btConditional.setEnabled(enableChkpt);
192 class ConditionalDlg : public QDialog
194 public:
195 ConditionalDlg(QWidget* parent);
196 ~ConditionalDlg();
198 void setCondition(const char* text) { m_condition.setText(text); }
199 const char* condition() { return m_condition.text(); }
200 void setIgnoreCount(uint count);
201 uint ignoreCount();
203 protected:
204 QLabel m_conditionLabel;
205 QLineEdit m_condition;
206 QLabel m_ignoreLabel;
207 QLineEdit m_ignoreCount;
208 QPushButton m_buttonOK;
209 QPushButton m_buttonCancel;
210 QVBoxLayout m_layout;
211 QGridLayout m_inputs;
212 QHBoxLayout m_buttons;
215 void BreakpointTable::conditionalBP()
217 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
218 if (bp == 0)
219 return;
222 * Important: we must not keep a pointer to the Breakpoint around,
223 * since it may vanish while the modal dialog is open through other
224 * user interactions (like clicking at the breakpoint in the source
225 * window)!
227 int id = bp->id;
229 ConditionalDlg dlg(this);
230 dlg.setCondition(bp->condition);
231 dlg.setIgnoreCount(bp->ignoreCount);
233 if (dlg.exec() != QDialog::Accepted)
234 return;
236 QString conditionInput = dlg.condition();
237 int ignoreCount = dlg.ignoreCount();
238 updateBreakpointCondition(id, conditionInput, ignoreCount);
241 void BreakpointTable::updateBreakpointCondition(int id,
242 const QString& condition,
243 int ignoreCount)
245 BreakpointItem* bp = itemByBreakId(id);
246 if (bp == 0)
247 return; /* breakpoint no longer exists */
249 bool changed = false;
251 if (bp->condition != condition) {
252 // change condition
253 m_debugger->driver()->executeCmd(DCcondition, condition, bp->id);
254 bp->condition = condition;
255 changed = true;
257 if (bp->ignoreCount != ignoreCount) {
258 // change ignore count
259 m_debugger->driver()->executeCmd(DCignore, bp->id, ignoreCount);
260 changed = true;
262 if (changed) {
263 // get the changes
264 m_debugger->driver()->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
269 BreakpointItem* BreakpointTable::itemByBreakId(int id)
271 for (QListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
272 BreakpointItem* bp = static_cast<BreakpointItem*>(it);
273 if (bp->id == id) {
274 return bp;
277 return 0;
281 void BreakpointTable::initListAndIcons()
283 m_list.addColumn(i18n("Location"), 300);
284 m_list.addColumn(i18n("Hits"), 30);
285 m_list.addColumn(i18n("Ignore"), 30);
286 m_list.addColumn(i18n("Condition"), 200);
288 m_list.setMinimumSize(200, 100);
289 setFocusPolicy(QWidget::StrongFocus);
291 m_list.setSorting(-1);
293 // add pixmaps
294 #if QT_VERSION < 200
295 KIconLoader* loader = kapp->getIconLoader();
296 QPixmap brkena = loader->loadIcon("brkena.xpm");
297 QPixmap brkdis = loader->loadIcon("brkdis.xpm");
298 QPixmap brktmp = loader->loadIcon("brktmp.xpm");
299 QPixmap brkcond = loader->loadIcon("brkcond.xpm");
300 #else
301 QPixmap brkena = BarIcon("brkena.xpm");
302 QPixmap brkdis = BarIcon("brkdis.xpm");
303 QPixmap brktmp = BarIcon("brktmp.xpm");
304 QPixmap brkcond = BarIcon("brkcond.xpm");
305 #endif
307 * There are 8 different pixmaps: The basic enabled or disabled
308 * breakpoint, plus an optional overlaid brktmp icon plus an optional
309 * overlaid brkcond icon.
311 m_icons.setSize(8);
312 QPixmap canvas(16,16);
314 for (int i = 0; i < 8; i++) {
316 QPainter p(&canvas);
317 // clear canvas
318 p.fillRect(0,0, canvas.width(),canvas.height(), cyan);
319 // basic icon
320 if (i & 1) {
321 p.drawPixmap(1,1, brkena);
322 } else {
323 p.drawPixmap(1,1, brkdis);
325 // temporary overlay
326 if (i & 2) {
327 p.drawPixmap(1,1, brktmp);
329 // conditional overlay
330 if (i & 4) {
331 p.drawPixmap(1,1, brkcond);
334 canvas.setMask(canvas.createHeuristicMask());
335 m_icons[i] = canvas;
339 void BreakpointItem::display()
341 BreakpointTable* lb = static_cast<BreakpointTable*>(listView()->parent());
343 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
344 int code = enabled ? 1 : 0;
345 if (temporary)
346 code += 2;
347 if (!condition.isEmpty() || ignoreCount > 0)
348 code += 4;
349 setPixmap(0, lb->m_icons[code]);
351 // more breakpoint info
352 setText(0, location);
353 QString tmp;
354 if (hitCount == 0) {
355 setText(1, QString());
356 } else {
357 tmp.setNum(hitCount);
358 setText(1, tmp);
360 if (ignoreCount == 0) {
361 setText(2, QString());
362 } else {
363 tmp.setNum(ignoreCount);
364 setText(2, tmp);
366 if (condition.isEmpty()) {
367 setText(3, QString());
368 } else {
369 setText(3, condition);
374 ConditionalDlg::ConditionalDlg(QWidget* parent) :
375 QDialog(parent, "conditional", true),
376 m_conditionLabel(this, "condLabel"),
377 m_condition(this, "condition"),
378 m_ignoreLabel(this, "ignoreLabel"),
379 m_ignoreCount(this, "ignoreCount"),
380 m_buttonOK(this, "ok"),
381 m_buttonCancel(this, "cancel"),
382 m_layout(this, 10),
383 m_inputs(2, 2, 10),
384 m_buttons(4)
386 QString title = kapp->getCaption();
387 title += i18n(": Conditional breakpoint");
388 setCaption(title);
390 m_conditionLabel.setText(i18n("&Condition:"));
391 m_conditionLabel.setMinimumSize(m_conditionLabel.sizeHint());
392 m_ignoreLabel.setText(i18n("Ignore &next hits:"));
393 m_ignoreLabel.setMinimumSize(m_ignoreLabel.sizeHint());
395 m_condition.setMinimumSize(150, 24);
396 m_condition.setMaxLength(10000);
397 m_condition.setFrame(true);
398 m_ignoreCount.setMinimumSize(150, 24);
399 m_ignoreCount.setMaxLength(10000);
400 m_ignoreCount.setFrame(true);
402 m_conditionLabel.setBuddy(&m_condition);
403 m_ignoreLabel.setBuddy(&m_ignoreCount);
405 m_buttonOK.setMinimumSize(100, 30);
406 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
407 m_buttonOK.setText(i18n("OK"));
408 m_buttonOK.setDefault(true);
410 m_buttonCancel.setMinimumSize(100, 30);
411 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
412 m_buttonCancel.setText(i18n("Cancel"));
414 m_layout.addLayout(&m_inputs);
415 m_inputs.addWidget(&m_conditionLabel, 0, 0);
416 m_inputs.addWidget(&m_condition, 0, 1);
417 m_inputs.addWidget(&m_ignoreLabel, 1, 0);
418 m_inputs.addWidget(&m_ignoreCount, 1, 1);
419 m_inputs.setColStretch(1, 10);
420 m_layout.addLayout(&m_buttons);
421 m_layout.addStretch(10);
422 m_buttons.addStretch(10);
423 m_buttons.addWidget(&m_buttonOK);
424 m_buttons.addSpacing(40);
425 m_buttons.addWidget(&m_buttonCancel);
426 m_buttons.addStretch(10);
428 m_layout.activate();
430 m_condition.setFocus();
431 resize(400, 100);
434 ConditionalDlg::~ConditionalDlg()
438 uint ConditionalDlg::ignoreCount()
440 bool ok;
441 QString input = m_ignoreCount.text();
442 uint result = input.toUInt(&ok);
443 return ok ? result : 0;
446 void ConditionalDlg::setIgnoreCount(uint count)
448 QString text;
449 // set empty if ignore count is zero
450 if (count > 0) {
451 text.setNum(count);
453 m_ignoreCount.setText(text);