Remove Help button from the program arguments dialog.
[kdbg.git] / kdbg / brkpt.cpp
blob65e99be870535dee323047f00b2956727c9e7598
1 /*
2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
5 */
7 #include <kapplication.h>
8 #include <klocale.h> /* i18n */
9 #include <kiconloader.h>
10 #include <ksimpleconfig.h>
11 #include <qdialog.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 <ctype.h>
20 #include <list>
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 */
33 bool enabled() const { return Breakpoint::enabled; }
37 BreakpointTable::BreakpointTable(QWidget* parent, const char* name) :
38 QWidget(parent, name),
39 m_debugger(0),
40 m_bpEdit(this, "bpedit"),
41 m_list(this, "bptable"),
42 m_btAddBP(this, "addbp"),
43 m_btAddWP(this, "addwp"),
44 m_btRemove(this, "remove"),
45 m_btEnaDis(this, "enadis"),
46 m_btViewCode(this, "view"),
47 m_btConditional(this, "conditional"),
48 m_layout(this, 8),
49 m_listandedit(8),
50 m_buttons(8)
52 m_bpEdit.setMinimumSize(m_bpEdit.sizeHint());
53 connect(&m_bpEdit, SIGNAL(returnPressed()), this, SLOT(addBP()));
55 initListAndIcons();
56 connect(&m_list, SIGNAL(currentChanged(QListViewItem*)), SLOT(updateUI()));
57 // double click on item is same as View code
58 connect(&m_list, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(viewBP()));
60 // need mouse button events
61 m_list.viewport()->installEventFilter(this);
63 m_btAddBP.setText(i18n("Add &Breakpoint"));
64 m_btAddBP.setMinimumSize(m_btAddBP.sizeHint());
65 connect(&m_btAddBP, SIGNAL(clicked()), this, SLOT(addBP()));
67 m_btAddWP.setText(i18n("Add &Watchpoint"));
68 m_btAddWP.setMinimumSize(m_btAddWP.sizeHint());
69 connect(&m_btAddWP, SIGNAL(clicked()), this, SLOT(addWP()));
71 m_btRemove.setText(i18n("&Remove"));
72 m_btRemove.setMinimumSize(m_btRemove.sizeHint());
73 connect(&m_btRemove, SIGNAL(clicked()), this, SLOT(removeBP()));
75 // the Enable/Disable button changes its label
76 m_btEnaDis.setText(i18n("&Disable"));
77 // make a dummy button to get the size of the alternate label
79 QSize size = m_btEnaDis.sizeHint();
80 QPushButton dummy(this);
81 dummy.setText(i18n("&Enable"));
82 QSize sizeAlt = dummy.sizeHint();
83 if (sizeAlt.width() > size.width())
84 size.setWidth(sizeAlt.width());
85 if (sizeAlt.height() > size.height())
86 size.setHeight(sizeAlt.height());
87 m_btEnaDis.setMinimumSize(size);
89 connect(&m_btEnaDis, SIGNAL(clicked()), this, SLOT(enadisBP()));
91 m_btViewCode.setText(i18n("&View Code"));
92 m_btViewCode.setMinimumSize(m_btViewCode.sizeHint());
93 connect(&m_btViewCode, SIGNAL(clicked()), this, SLOT(viewBP()));
95 m_btConditional.setText(i18n("&Conditional..."));
96 m_btConditional.setMinimumSize(m_btConditional.sizeHint());
97 connect(&m_btConditional, SIGNAL(clicked()), this, SLOT(conditionalBP()));
99 m_layout.addLayout(&m_listandedit, 10);
100 m_layout.addLayout(&m_buttons);
101 m_listandedit.addWidget(&m_bpEdit);
102 m_listandedit.addWidget(&m_list, 10);
103 m_buttons.addWidget(&m_btAddBP);
104 m_buttons.addWidget(&m_btAddWP);
105 m_buttons.addWidget(&m_btRemove);
106 m_buttons.addWidget(&m_btEnaDis);
107 m_buttons.addWidget(&m_btViewCode);
108 m_buttons.addWidget(&m_btConditional);
109 m_buttons.addStretch(10);
111 m_layout.activate();
113 resize(350, 300);
115 m_bpEdit.setFocus();
118 BreakpointTable::~BreakpointTable()
122 void BreakpointTable::updateBreakList()
124 std::list<BreakpointItem*> deletedItems;
126 for (QListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
127 deletedItems.push_back(static_cast<BreakpointItem*>(it));
130 // get the new list
131 for (KDebugger::BrkptROIterator bp = m_debugger->breakpointsBegin(); bp != m_debugger->breakpointsEnd(); ++bp)
133 // look up this item
134 for (std::list<BreakpointItem*>::iterator o = deletedItems.begin(); o != deletedItems.end(); ++o)
136 if ((*o)->id == bp->id) {
137 (*o)->updateFrom(*bp);
138 deletedItems.erase(o); /* don't delete */
139 goto nextItem;
142 // not in the list; add it
143 new BreakpointItem(&m_list, *bp);
144 nextItem:;
147 // delete all untouched breakpoints
148 while (!deletedItems.empty()) {
149 delete deletedItems.front();
150 deletedItems.pop_front();
154 BreakpointItem::BreakpointItem(QListView* list, const Breakpoint& bp) :
155 QListViewItem(list),
156 Breakpoint(bp)
158 display();
161 void BreakpointItem::updateFrom(const Breakpoint& bp)
163 Breakpoint::operator=(bp); /* assign new values */
164 display();
167 void BreakpointTable::addBP()
169 // set a breakpoint at the specified text
170 QString bpText = m_bpEdit.text();
171 bpText = bpText.stripWhiteSpace();
172 if (m_debugger->isReady())
174 Breakpoint* bp = new Breakpoint;
175 bp->text = bpText;
177 m_debugger->setBreakpoint(bp, false);
181 void BreakpointTable::addWP()
183 // set a watchpoint for the specified expression
184 QString wpExpr = m_bpEdit.text();
185 wpExpr = wpExpr.stripWhiteSpace();
186 if (m_debugger->isReady()) {
187 Breakpoint* bp = new Breakpoint;
188 bp->type = Breakpoint::watchpoint;
189 bp->text = wpExpr;
191 m_debugger->setBreakpoint(bp, false);
195 void BreakpointTable::removeBP()
197 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
198 if (bp != 0) {
199 m_debugger->deleteBreakpoint(bp->id);
200 // note that bp may be deleted by now
201 // (if bp was an orphaned breakpoint)
205 void BreakpointTable::enadisBP()
207 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
208 if (bp != 0) {
209 m_debugger->enableDisableBreakpoint(bp->id);
213 void BreakpointTable::viewBP()
215 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
216 if (bp == 0)
217 return;
219 emit activateFileLine(bp->fileName, bp->lineNo, bp->address);
222 void BreakpointTable::updateUI()
224 bool enableChkpt = m_debugger->canChangeBreakpoints();
225 m_btAddBP.setEnabled(enableChkpt);
226 m_btAddWP.setEnabled(enableChkpt);
228 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
229 m_btViewCode.setEnabled(bp != 0);
231 if (bp == 0) {
232 enableChkpt = false;
233 } else {
234 if (bp->enabled()) {
235 m_btEnaDis.setText(i18n("&Disable"));
236 } else {
237 m_btEnaDis.setText(i18n("&Enable"));
240 m_btRemove.setEnabled(enableChkpt);
241 m_btEnaDis.setEnabled(enableChkpt);
242 m_btConditional.setEnabled(enableChkpt);
245 bool BreakpointTable::eventFilter(QObject* ob, QEvent* ev)
247 if (ev->type() == QEvent::MouseButtonPress)
249 QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
250 if (mev->button() == Qt::MidButton) {
251 // enable or disable the clicked-on item
252 BreakpointItem* bp =
253 static_cast<BreakpointItem*>(m_list.itemAt(mev->pos()));
254 if (bp != 0)
256 m_debugger->enableDisableBreakpoint(bp->id);
258 return true;
261 return QWidget::eventFilter(ob, ev);
264 class ConditionalDlg : public QDialog
266 public:
267 ConditionalDlg(QWidget* parent);
268 ~ConditionalDlg();
270 void setCondition(const QString& text) { m_condition.setText(text); }
271 QString condition() { return m_condition.text(); }
272 void setIgnoreCount(uint count);
273 uint ignoreCount();
275 protected:
276 QLabel m_conditionLabel;
277 QLineEdit m_condition;
278 QLabel m_ignoreLabel;
279 QLineEdit m_ignoreCount;
280 QPushButton m_buttonOK;
281 QPushButton m_buttonCancel;
282 QVBoxLayout m_layout;
283 QGridLayout m_inputs;
284 QHBoxLayout m_buttons;
287 void BreakpointTable::conditionalBP()
289 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
290 if (bp == 0)
291 return;
294 * Important: we must not keep a pointer to the Breakpoint around,
295 * since it may vanish while the modal dialog is open through other
296 * user interactions (like clicking at the breakpoint in the source
297 * window)!
299 int id = bp->id;
301 ConditionalDlg dlg(this);
302 dlg.setCondition(bp->condition);
303 dlg.setIgnoreCount(bp->ignoreCount);
305 if (dlg.exec() != QDialog::Accepted)
306 return;
308 QString conditionInput = dlg.condition();
309 int ignoreCount = dlg.ignoreCount();
310 m_debugger->conditionalBreakpoint(id, conditionInput, ignoreCount);
314 void BreakpointTable::initListAndIcons()
316 m_list.addColumn(i18n("Location"), 220);
317 m_list.addColumn(i18n("Address"), 65);
318 m_list.addColumn(i18n("Hits"), 30);
319 m_list.addColumn(i18n("Ignore"), 30);
320 m_list.addColumn(i18n("Condition"), 200);
322 m_list.setMinimumSize(200, 100);
324 m_list.setSorting(-1);
326 // add pixmaps
327 QPixmap brkena = UserIcon("brkena.xpm");
328 QPixmap brkdis = UserIcon("brkdis.xpm");
329 QPixmap watchena = UserIcon("watchena.xpm");
330 QPixmap watchdis = UserIcon("watchdis.xpm");
331 QPixmap brktmp = UserIcon("brktmp.xpm");
332 QPixmap brkcond = UserIcon("brkcond.xpm");
333 QPixmap brkorph = UserIcon("brkorph.xpm");
336 * There are 32 different pixmaps: The basic enabled or disabled
337 * breakpoint, plus an optional overlaid brktmp icon plus an optional
338 * overlaid brkcond icon, plus an optional overlaid brkorph icon. Then
339 * the same sequence for watchpoints.
341 m_icons.resize(32);
342 QPixmap canvas(16,16);
344 for (int i = 0; i < 32; i++) {
346 QPainter p(&canvas);
347 // clear canvas
348 p.fillRect(0,0, canvas.width(),canvas.height(), Qt::cyan);
349 // basic icon
350 if (i & 1) {
351 p.drawPixmap(1,1, (i & 8) ? watchena : brkena);
352 } else {
353 p.drawPixmap(1,1, (i & 8) ? watchdis : brkdis);
355 // temporary overlay
356 if (i & 2) {
357 p.drawPixmap(1,1, brktmp);
359 // conditional overlay
360 if (i & 4) {
361 p.drawPixmap(1,1, brkcond);
363 // orphan overlay
364 if (i & 16) {
365 p.drawPixmap(1,1, brkorph);
368 canvas.setMask(canvas.createHeuristicMask());
369 m_icons[i] = canvas;
373 void BreakpointItem::display()
375 BreakpointTable* lb = static_cast<BreakpointTable*>(listView()->parent());
377 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
378 int code = enabled() ? 1 : 0;
379 if (temporary)
380 code += 2;
381 if (!condition.isEmpty() || ignoreCount > 0)
382 code += 4;
383 if (type == watchpoint)
384 code += 8;
385 if (isOrphaned())
386 code += 16;
387 setPixmap(0, lb->m_icons[code]);
389 // more breakpoint info
390 if (!location.isEmpty()) {
391 setText(0, location);
392 } else if (!Breakpoint::text.isEmpty()) {
393 setText(0, Breakpoint::text);
394 } else if (!fileName.isEmpty()) {
395 // use only the file name portion
396 QString file = fileName;
397 int slash = file.findRev('/');
398 if (slash >= 0) {
399 file = file.mid(slash+1);
401 // correct zero-based line-numbers
402 setText(0, file + ":" + QString::number(lineNo+1));
403 } else {
404 setText(0, "*" + address.asString());
407 int c = 0;
408 setText(++c, address.asString());
409 QString tmp;
410 if (hitCount == 0) {
411 setText(++c, QString());
412 } else {
413 tmp.setNum(hitCount);
414 setText(++c, tmp);
416 if (ignoreCount == 0) {
417 setText(++c, QString());
418 } else {
419 tmp.setNum(ignoreCount);
420 setText(++c, tmp);
422 if (condition.isEmpty()) {
423 setText(++c, QString());
424 } else {
425 setText(++c, condition);
430 ConditionalDlg::ConditionalDlg(QWidget* parent) :
431 QDialog(parent, "conditional", true),
432 m_conditionLabel(this, "condLabel"),
433 m_condition(this, "condition"),
434 m_ignoreLabel(this, "ignoreLabel"),
435 m_ignoreCount(this, "ignoreCount"),
436 m_buttonOK(this, "ok"),
437 m_buttonCancel(this, "cancel"),
438 m_layout(this, 10),
439 m_inputs(2, 2, 10),
440 m_buttons(4)
442 QString title = kapp->caption();
443 title += i18n(": Conditional breakpoint");
444 setCaption(title);
446 m_conditionLabel.setText(i18n("&Condition:"));
447 m_conditionLabel.setMinimumSize(m_conditionLabel.sizeHint());
448 m_ignoreLabel.setText(i18n("Ignore &next hits:"));
449 m_ignoreLabel.setMinimumSize(m_ignoreLabel.sizeHint());
451 m_condition.setMinimumSize(150, 24);
452 m_condition.setMaxLength(10000);
453 m_condition.setFrame(true);
454 m_ignoreCount.setMinimumSize(150, 24);
455 m_ignoreCount.setMaxLength(10000);
456 m_ignoreCount.setFrame(true);
458 m_conditionLabel.setBuddy(&m_condition);
459 m_ignoreLabel.setBuddy(&m_ignoreCount);
461 m_buttonOK.setMinimumSize(100, 30);
462 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
463 m_buttonOK.setText(i18n("OK"));
464 m_buttonOK.setDefault(true);
466 m_buttonCancel.setMinimumSize(100, 30);
467 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
468 m_buttonCancel.setText(i18n("Cancel"));
470 m_layout.addLayout(&m_inputs);
471 m_inputs.addWidget(&m_conditionLabel, 0, 0);
472 m_inputs.addWidget(&m_condition, 0, 1);
473 m_inputs.addWidget(&m_ignoreLabel, 1, 0);
474 m_inputs.addWidget(&m_ignoreCount, 1, 1);
475 m_inputs.setColStretch(1, 10);
476 m_layout.addLayout(&m_buttons);
477 m_layout.addStretch(10);
478 m_buttons.addStretch(10);
479 m_buttons.addWidget(&m_buttonOK);
480 m_buttons.addSpacing(40);
481 m_buttons.addWidget(&m_buttonCancel);
482 m_buttons.addStretch(10);
484 m_layout.activate();
486 m_condition.setFocus();
487 resize(400, 100);
490 ConditionalDlg::~ConditionalDlg()
494 uint ConditionalDlg::ignoreCount()
496 bool ok;
497 QString input = m_ignoreCount.text();
498 uint result = input.toUInt(&ok);
499 return ok ? result : 0;
502 void ConditionalDlg::setIgnoreCount(uint count)
504 QString text;
505 // set empty if ignore count is zero
506 if (count > 0) {
507 text.setNum(count);
509 m_ignoreCount.setText(text);
513 #include "brkpt.moc"