Fixed printing of QString values for some at least gdb 5.2.1.
[kdbg.git] / kdbg / brkpt.cpp
blobd873d16902d37707f5348d3ebe6d2a1bde8c1f4e
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <kapp.h> /* i18n */
7 #include <klocale.h> /* i18n */
8 #include <kiconloader.h>
9 #include <ksimpleconfig.h>
10 #include <qdialog.h>
11 #include <qkeycode.h>
12 #include <qpainter.h>
13 #include <qlabel.h>
14 #include <qbitmap.h>
15 #include "debugger.h"
16 #include "brkpt.h"
17 #include "dbgdriver.h"
18 #include "brkpt.moc"
19 #include <ctype.h>
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include "mydebug.h"
26 class BreakpointItem : public QListViewItem, public Breakpoint
28 public:
29 BreakpointItem(QListView* list, const Breakpoint& bp);
30 void updateFrom(const Breakpoint& bp);
31 void display(); /* sets icon and visible texts */
32 bool enabled() const { return Breakpoint::enabled; }
36 BreakpointTable::BreakpointTable(QWidget* parent, const char* name) :
37 QWidget(parent, name),
38 m_debugger(0),
39 m_bpEdit(this, "bpedit"),
40 m_list(this, "bptable"),
41 m_btAddBP(this, "addbp"),
42 m_btAddWP(this, "addwp"),
43 m_btRemove(this, "remove"),
44 m_btEnaDis(this, "enadis"),
45 m_btViewCode(this, "view"),
46 m_btConditional(this, "conditional"),
47 m_layout(this, 8),
48 m_listandedit(8),
49 m_buttons(8)
51 m_bpEdit.setMinimumSize(m_bpEdit.sizeHint());
52 connect(&m_bpEdit, SIGNAL(returnPressed()), this, SLOT(addBP()));
54 initListAndIcons();
55 connect(&m_list, SIGNAL(currentChanged(QListViewItem*)), SLOT(updateUI()));
56 // double click on item is same as View code
57 connect(&m_list, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(viewBP()));
59 // need mouse button events
60 m_list.viewport()->installEventFilter(this);
62 m_btAddBP.setText(i18n("Add &Breakpoint"));
63 m_btAddBP.setMinimumSize(m_btAddBP.sizeHint());
64 connect(&m_btAddBP, SIGNAL(clicked()), this, SLOT(addBP()));
66 m_btAddWP.setText(i18n("Add &Watchpoint"));
67 m_btAddWP.setMinimumSize(m_btAddWP.sizeHint());
68 connect(&m_btAddWP, SIGNAL(clicked()), this, SLOT(addWP()));
70 m_btRemove.setText(i18n("&Remove"));
71 m_btRemove.setMinimumSize(m_btRemove.sizeHint());
72 connect(&m_btRemove, SIGNAL(clicked()), this, SLOT(removeBP()));
74 // the Enable/Disable button changes its label
75 m_btEnaDis.setText(i18n("&Disable"));
76 // make a dummy button to get the size of the alternate label
78 QSize size = m_btEnaDis.sizeHint();
79 QPushButton dummy(this);
80 dummy.setText(i18n("&Enable"));
81 QSize sizeAlt = dummy.sizeHint();
82 if (sizeAlt.width() > size.width())
83 size.setWidth(sizeAlt.width());
84 if (sizeAlt.height() > size.height())
85 size.setHeight(sizeAlt.height());
86 m_btEnaDis.setMinimumSize(size);
88 connect(&m_btEnaDis, SIGNAL(clicked()), this, SLOT(enadisBP()));
90 m_btViewCode.setText(i18n("&View Code"));
91 m_btViewCode.setMinimumSize(m_btViewCode.sizeHint());
92 connect(&m_btViewCode, SIGNAL(clicked()), this, SLOT(viewBP()));
94 m_btConditional.setText(i18n("&Conditional..."));
95 m_btConditional.setMinimumSize(m_btConditional.sizeHint());
96 connect(&m_btConditional, SIGNAL(clicked()), this, SLOT(conditionalBP()));
98 m_layout.addLayout(&m_listandedit, 10);
99 m_layout.addLayout(&m_buttons);
100 m_listandedit.addWidget(&m_bpEdit);
101 m_listandedit.addWidget(&m_list, 10);
102 m_buttons.addWidget(&m_btAddBP);
103 m_buttons.addWidget(&m_btAddWP);
104 m_buttons.addWidget(&m_btRemove);
105 m_buttons.addWidget(&m_btEnaDis);
106 m_buttons.addWidget(&m_btViewCode);
107 m_buttons.addWidget(&m_btConditional);
108 m_buttons.addStretch(10);
110 m_layout.activate();
112 resize(350, 300);
114 m_bpEdit.setFocus();
117 BreakpointTable::~BreakpointTable()
121 void BreakpointTable::updateBreakList()
123 QList<BreakpointItem> deletedItems;
125 for (QListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
126 deletedItems.append(static_cast<BreakpointItem*>(it));
129 // get the new list
130 for (int i = m_debugger->numBreakpoints()-1; i >= 0; i--) {
131 const Breakpoint* bp = m_debugger->breakpoint(i);
132 // look up this item
133 for (BreakpointItem* oldbp = deletedItems.first(); oldbp != 0;
134 oldbp = deletedItems.next())
136 if (oldbp->id == bp->id) {
137 oldbp->updateFrom(*bp);
138 deletedItems.take(); /* 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 deletedItems.setAutoDelete(true);
151 BreakpointItem::BreakpointItem(QListView* list, const Breakpoint& bp) :
152 QListViewItem(list),
153 Breakpoint(bp)
155 display();
158 void BreakpointItem::updateFrom(const Breakpoint& bp)
160 Breakpoint::operator=(bp); /* assign new values */
161 display();
164 void BreakpointTable::addBP()
166 // set a breakpoint at the specified text
167 QString bpText = m_bpEdit.text();
168 bpText = bpText.stripWhiteSpace();
169 if (m_debugger->isReady()) {
170 m_debugger->driver()->executeCmd(DCbreaktext, bpText);
171 // clear text if successfully set
172 m_bpEdit.setText("");
176 void BreakpointTable::addWP()
178 // set a watchpoint for the specified expression
179 QString wpExpr = m_bpEdit.text();
180 wpExpr = wpExpr.stripWhiteSpace();
181 if (m_debugger->isReady()) {
182 m_debugger->driver()->executeCmd(DCwatchpoint, wpExpr);
186 void BreakpointTable::removeBP()
188 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
189 if (bp == 0)
190 return;
192 m_debugger->driver()->executeCmd(DCdelete, bp->id);
195 void BreakpointTable::enadisBP()
197 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
198 if (bp == 0)
199 return;
201 DbgCommand cmd = bp->enabled() ? DCdisable : DCenable;
202 m_debugger->driver()->executeCmd(cmd, bp->id);
205 void BreakpointTable::viewBP()
207 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
208 if (bp == 0)
209 return;
211 emit activateFileLine(bp->fileName, bp->lineNo, bp->address);
214 void BreakpointTable::updateUI()
216 bool enableChkpt = m_debugger->canChangeBreakpoints();
217 m_btAddBP.setEnabled(enableChkpt);
218 m_btAddWP.setEnabled(enableChkpt);
220 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
221 m_btViewCode.setEnabled(bp != 0);
223 if (bp == 0) {
224 enableChkpt = false;
225 } else {
226 if (bp->enabled()) {
227 m_btEnaDis.setText(i18n("&Disable"));
228 } else {
229 m_btEnaDis.setText(i18n("&Enable"));
232 m_btRemove.setEnabled(enableChkpt);
233 m_btEnaDis.setEnabled(enableChkpt);
234 m_btConditional.setEnabled(enableChkpt);
237 bool BreakpointTable::eventFilter(QObject* ob, QEvent* ev)
239 if (ev->type() == QEvent::MouseButtonPress)
241 QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
242 if (mev->button() == MidButton) {
243 // enable or disable the clicked-on item
244 BreakpointItem* bp =
245 static_cast<BreakpointItem*>(m_list.itemAt(mev->pos()));
246 if (bp != 0 && m_debugger->canChangeBreakpoints())
248 DbgCommand cmd = bp->enabled() ? DCdisable : DCenable;
249 m_debugger->driver()->executeCmd(cmd, bp->id);
251 return true;
254 return QWidget::eventFilter(ob, ev);
257 class ConditionalDlg : public QDialog
259 public:
260 ConditionalDlg(QWidget* parent);
261 ~ConditionalDlg();
263 void setCondition(const char* text) { m_condition.setText(text); }
264 const char* condition() { return m_condition.text(); }
265 void setIgnoreCount(uint count);
266 uint ignoreCount();
268 protected:
269 QLabel m_conditionLabel;
270 QLineEdit m_condition;
271 QLabel m_ignoreLabel;
272 QLineEdit m_ignoreCount;
273 QPushButton m_buttonOK;
274 QPushButton m_buttonCancel;
275 QVBoxLayout m_layout;
276 QGridLayout m_inputs;
277 QHBoxLayout m_buttons;
280 void BreakpointTable::conditionalBP()
282 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
283 if (bp == 0)
284 return;
287 * Important: we must not keep a pointer to the Breakpoint around,
288 * since it may vanish while the modal dialog is open through other
289 * user interactions (like clicking at the breakpoint in the source
290 * window)!
292 int id = bp->id;
294 ConditionalDlg dlg(this);
295 dlg.setCondition(bp->condition);
296 dlg.setIgnoreCount(bp->ignoreCount);
298 if (dlg.exec() != QDialog::Accepted)
299 return;
301 QString conditionInput = dlg.condition();
302 int ignoreCount = dlg.ignoreCount();
303 updateBreakpointCondition(id, conditionInput, ignoreCount);
306 void BreakpointTable::updateBreakpointCondition(int id,
307 const QString& condition,
308 int ignoreCount)
310 BreakpointItem* bp = itemByBreakId(id);
311 if (bp == 0)
312 return; /* breakpoint no longer exists */
314 bool changed = false;
316 if (bp->condition != condition) {
317 // change condition
318 m_debugger->driver()->executeCmd(DCcondition, condition, bp->id);
319 bp->condition = condition;
320 changed = true;
322 if (bp->ignoreCount != ignoreCount) {
323 // change ignore count
324 m_debugger->driver()->executeCmd(DCignore, bp->id, ignoreCount);
325 changed = true;
327 if (changed) {
328 // get the changes
329 m_debugger->driver()->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
334 BreakpointItem* BreakpointTable::itemByBreakId(int id)
336 for (QListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
337 BreakpointItem* bp = static_cast<BreakpointItem*>(it);
338 if (bp->id == id) {
339 return bp;
342 return 0;
346 void BreakpointTable::initListAndIcons()
348 m_list.addColumn(i18n("Location"), 220);
349 m_list.addColumn(i18n("Address"), 65);
350 m_list.addColumn(i18n("Hits"), 30);
351 m_list.addColumn(i18n("Ignore"), 30);
352 m_list.addColumn(i18n("Condition"), 200);
354 m_list.setMinimumSize(200, 100);
356 m_list.setSorting(-1);
358 // add pixmaps
359 QPixmap brkena = BarIcon("brkena.xpm");
360 QPixmap brkdis = BarIcon("brkdis.xpm");
361 QPixmap watchena = BarIcon("watchena.xpm");
362 QPixmap watchdis = BarIcon("watchdis.xpm");
363 QPixmap brktmp = BarIcon("brktmp.xpm");
364 QPixmap brkcond = BarIcon("brkcond.xpm");
367 * There are 16 different pixmaps: The basic enabled or disabled
368 * breakpoint, plus an optional overlaid brktmp icon plus an optional
369 * overlaid brkcond icon. Then the same sequence for watchpoints.
371 m_icons.setSize(16);
372 QPixmap canvas(16,16);
374 for (int i = 0; i < 16; i++) {
376 QPainter p(&canvas);
377 // clear canvas
378 p.fillRect(0,0, canvas.width(),canvas.height(), cyan);
379 // basic icon
380 if (i & 1) {
381 p.drawPixmap(1,1, (i & 8) ? watchena : brkena);
382 } else {
383 p.drawPixmap(1,1, (i & 8) ? watchdis : brkdis);
385 // temporary overlay
386 if (i & 2) {
387 p.drawPixmap(1,1, brktmp);
389 // conditional overlay
390 if (i & 4) {
391 p.drawPixmap(1,1, brkcond);
394 canvas.setMask(canvas.createHeuristicMask());
395 m_icons[i] = canvas;
399 void BreakpointItem::display()
401 BreakpointTable* lb = static_cast<BreakpointTable*>(listView()->parent());
403 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
404 int code = enabled() ? 1 : 0;
405 if (temporary)
406 code += 2;
407 if (!condition.isEmpty() || ignoreCount > 0)
408 code += 4;
409 if (type == watchpoint)
410 code += 8;
411 setPixmap(0, lb->m_icons[code]);
413 // more breakpoint info
414 setText(0, location);
415 int c = 0;
416 setText(++c, address.asString());
417 QString tmp;
418 if (hitCount == 0) {
419 setText(++c, QString());
420 } else {
421 tmp.setNum(hitCount);
422 setText(++c, tmp);
424 if (ignoreCount == 0) {
425 setText(++c, QString());
426 } else {
427 tmp.setNum(ignoreCount);
428 setText(++c, tmp);
430 if (condition.isEmpty()) {
431 setText(++c, QString());
432 } else {
433 setText(++c, condition);
438 ConditionalDlg::ConditionalDlg(QWidget* parent) :
439 QDialog(parent, "conditional", true),
440 m_conditionLabel(this, "condLabel"),
441 m_condition(this, "condition"),
442 m_ignoreLabel(this, "ignoreLabel"),
443 m_ignoreCount(this, "ignoreCount"),
444 m_buttonOK(this, "ok"),
445 m_buttonCancel(this, "cancel"),
446 m_layout(this, 10),
447 m_inputs(2, 2, 10),
448 m_buttons(4)
450 QString title = kapp->caption();
451 title += i18n(": Conditional breakpoint");
452 setCaption(title);
454 m_conditionLabel.setText(i18n("&Condition:"));
455 m_conditionLabel.setMinimumSize(m_conditionLabel.sizeHint());
456 m_ignoreLabel.setText(i18n("Ignore &next hits:"));
457 m_ignoreLabel.setMinimumSize(m_ignoreLabel.sizeHint());
459 m_condition.setMinimumSize(150, 24);
460 m_condition.setMaxLength(10000);
461 m_condition.setFrame(true);
462 m_ignoreCount.setMinimumSize(150, 24);
463 m_ignoreCount.setMaxLength(10000);
464 m_ignoreCount.setFrame(true);
466 m_conditionLabel.setBuddy(&m_condition);
467 m_ignoreLabel.setBuddy(&m_ignoreCount);
469 m_buttonOK.setMinimumSize(100, 30);
470 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
471 m_buttonOK.setText(i18n("OK"));
472 m_buttonOK.setDefault(true);
474 m_buttonCancel.setMinimumSize(100, 30);
475 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
476 m_buttonCancel.setText(i18n("Cancel"));
478 m_layout.addLayout(&m_inputs);
479 m_inputs.addWidget(&m_conditionLabel, 0, 0);
480 m_inputs.addWidget(&m_condition, 0, 1);
481 m_inputs.addWidget(&m_ignoreLabel, 1, 0);
482 m_inputs.addWidget(&m_ignoreCount, 1, 1);
483 m_inputs.setColStretch(1, 10);
484 m_layout.addLayout(&m_buttons);
485 m_layout.addStretch(10);
486 m_buttons.addStretch(10);
487 m_buttons.addWidget(&m_buttonOK);
488 m_buttons.addSpacing(40);
489 m_buttons.addWidget(&m_buttonCancel);
490 m_buttons.addStretch(10);
492 m_layout.activate();
494 m_condition.setFocus();
495 resize(400, 100);
498 ConditionalDlg::~ConditionalDlg()
502 uint ConditionalDlg::ignoreCount()
504 bool ok;
505 QString input = m_ignoreCount.text();
506 uint result = input.toUInt(&ok);
507 return ok ? result : 0;
510 void ConditionalDlg::setIgnoreCount(uint count)
512 QString text;
513 // set empty if ignore count is zero
514 if (count > 0) {
515 text.setNum(count);
517 m_ignoreCount.setText(text);