Convert from Qt 3 to Qt 4 using qt3to4.
[kdbg.git] / kdbg / brkpt.cpp
blobff9d2c48e363a0ab9c84f33d872a184ec5712a8f
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 <qnamespace.h>
13 #include <qpainter.h>
14 #include <qlabel.h>
15 #include <qbitmap.h>
16 #include <Q3HBoxLayout>
17 #include <Q3GridLayout>
18 #include <QPixmap>
19 #include <QMouseEvent>
20 #include <QEvent>
21 #include <Q3VBoxLayout>
22 #include "debugger.h"
23 #include "brkpt.h"
24 #include "dbgdriver.h"
25 #include <ctype.h>
26 #include <list>
27 #include "mydebug.h"
30 class BreakpointItem : public Q3ListViewItem, public Breakpoint
32 public:
33 BreakpointItem(Q3ListView* list, const Breakpoint& bp);
34 void updateFrom(const Breakpoint& bp);
35 void display(); /* sets icon and visible texts */
36 bool enabled() const { return Breakpoint::enabled; }
40 BreakpointTable::BreakpointTable(QWidget* parent) :
41 QWidget(parent),
42 m_debugger(0),
43 m_bpEdit(this, "bpedit"),
44 m_list(this, "bptable"),
45 m_btAddBP(this, "addbp"),
46 m_btAddWP(this, "addwp"),
47 m_btRemove(this, "remove"),
48 m_btEnaDis(this, "enadis"),
49 m_btViewCode(this, "view"),
50 m_btConditional(this, "conditional"),
51 m_layout(this, 8),
52 m_listandedit(8),
53 m_buttons(8)
55 m_bpEdit.setMinimumSize(m_bpEdit.sizeHint());
56 connect(&m_bpEdit, SIGNAL(returnPressed()), this, SLOT(addBP()));
58 initListAndIcons();
59 connect(&m_list, SIGNAL(currentChanged(Q3ListViewItem*)), SLOT(updateUI()));
60 // double click on item is same as View code
61 connect(&m_list, SIGNAL(doubleClicked(Q3ListViewItem*)), this, SLOT(viewBP()));
63 // need mouse button events
64 m_list.viewport()->installEventFilter(this);
66 m_btAddBP.setText(i18n("Add &Breakpoint"));
67 m_btAddBP.setMinimumSize(m_btAddBP.sizeHint());
68 connect(&m_btAddBP, SIGNAL(clicked()), this, SLOT(addBP()));
70 m_btAddWP.setText(i18n("Add &Watchpoint"));
71 m_btAddWP.setMinimumSize(m_btAddWP.sizeHint());
72 connect(&m_btAddWP, SIGNAL(clicked()), this, SLOT(addWP()));
74 m_btRemove.setText(i18n("&Remove"));
75 m_btRemove.setMinimumSize(m_btRemove.sizeHint());
76 connect(&m_btRemove, SIGNAL(clicked()), this, SLOT(removeBP()));
78 // the Enable/Disable button changes its label
79 m_btEnaDis.setText(i18n("&Disable"));
80 // make a dummy button to get the size of the alternate label
82 QSize size = m_btEnaDis.sizeHint();
83 QPushButton dummy(this);
84 dummy.setText(i18n("&Enable"));
85 QSize sizeAlt = dummy.sizeHint();
86 if (sizeAlt.width() > size.width())
87 size.setWidth(sizeAlt.width());
88 if (sizeAlt.height() > size.height())
89 size.setHeight(sizeAlt.height());
90 m_btEnaDis.setMinimumSize(size);
92 connect(&m_btEnaDis, SIGNAL(clicked()), this, SLOT(enadisBP()));
94 m_btViewCode.setText(i18n("&View Code"));
95 m_btViewCode.setMinimumSize(m_btViewCode.sizeHint());
96 connect(&m_btViewCode, SIGNAL(clicked()), this, SLOT(viewBP()));
98 m_btConditional.setText(i18n("&Conditional..."));
99 m_btConditional.setMinimumSize(m_btConditional.sizeHint());
100 connect(&m_btConditional, SIGNAL(clicked()), this, SLOT(conditionalBP()));
102 m_layout.addLayout(&m_listandedit, 10);
103 m_layout.addLayout(&m_buttons);
104 m_listandedit.addWidget(&m_bpEdit);
105 m_listandedit.addWidget(&m_list, 10);
106 m_buttons.addWidget(&m_btAddBP);
107 m_buttons.addWidget(&m_btAddWP);
108 m_buttons.addWidget(&m_btRemove);
109 m_buttons.addWidget(&m_btEnaDis);
110 m_buttons.addWidget(&m_btViewCode);
111 m_buttons.addWidget(&m_btConditional);
112 m_buttons.addStretch(10);
114 m_layout.activate();
116 resize(350, 300);
118 m_bpEdit.setFocus();
121 BreakpointTable::~BreakpointTable()
125 void BreakpointTable::updateBreakList()
127 std::list<BreakpointItem*> deletedItems;
129 for (Q3ListViewItem* it = m_list.firstChild(); it != 0; it = it->nextSibling()) {
130 deletedItems.push_back(static_cast<BreakpointItem*>(it));
133 // get the new list
134 for (KDebugger::BrkptROIterator bp = m_debugger->breakpointsBegin(); bp != m_debugger->breakpointsEnd(); ++bp)
136 // look up this item
137 for (std::list<BreakpointItem*>::iterator o = deletedItems.begin(); o != deletedItems.end(); ++o)
139 if ((*o)->id == bp->id) {
140 (*o)->updateFrom(*bp);
141 deletedItems.erase(o); /* don't delete */
142 goto nextItem;
145 // not in the list; add it
146 new BreakpointItem(&m_list, *bp);
147 nextItem:;
150 // delete all untouched breakpoints
151 while (!deletedItems.empty()) {
152 delete deletedItems.front();
153 deletedItems.pop_front();
157 BreakpointItem::BreakpointItem(Q3ListView* list, const Breakpoint& bp) :
158 Q3ListViewItem(list),
159 Breakpoint(bp)
161 display();
164 void BreakpointItem::updateFrom(const Breakpoint& bp)
166 Breakpoint::operator=(bp); /* assign new values */
167 display();
170 void BreakpointTable::addBP()
172 // set a breakpoint at the specified text
173 QString bpText = m_bpEdit.text();
174 bpText = bpText.stripWhiteSpace();
175 if (m_debugger->isReady())
177 Breakpoint* bp = new Breakpoint;
178 bp->text = bpText;
180 m_debugger->setBreakpoint(bp, false);
184 void BreakpointTable::addWP()
186 // set a watchpoint for the specified expression
187 QString wpExpr = m_bpEdit.text();
188 wpExpr = wpExpr.stripWhiteSpace();
189 if (m_debugger->isReady()) {
190 Breakpoint* bp = new Breakpoint;
191 bp->type = Breakpoint::watchpoint;
192 bp->text = wpExpr;
194 m_debugger->setBreakpoint(bp, false);
198 void BreakpointTable::removeBP()
200 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
201 if (bp != 0) {
202 m_debugger->deleteBreakpoint(bp->id);
203 // note that bp may be deleted by now
204 // (if bp was an orphaned breakpoint)
208 void BreakpointTable::enadisBP()
210 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
211 if (bp != 0) {
212 m_debugger->enableDisableBreakpoint(bp->id);
216 void BreakpointTable::viewBP()
218 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
219 if (bp == 0)
220 return;
222 if (!m_debugger->infoLine(bp->fileName, bp->lineNo, bp->address))
223 emit activateFileLine(bp->fileName, bp->lineNo, bp->address);
226 void BreakpointTable::updateUI()
228 bool enableChkpt = m_debugger->canChangeBreakpoints();
229 m_btAddBP.setEnabled(enableChkpt);
230 m_btAddWP.setEnabled(enableChkpt);
232 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
233 m_btViewCode.setEnabled(bp != 0);
235 if (bp == 0) {
236 enableChkpt = false;
237 } else {
238 if (bp->enabled()) {
239 m_btEnaDis.setText(i18n("&Disable"));
240 } else {
241 m_btEnaDis.setText(i18n("&Enable"));
244 m_btRemove.setEnabled(enableChkpt);
245 m_btEnaDis.setEnabled(enableChkpt);
246 m_btConditional.setEnabled(enableChkpt);
249 bool BreakpointTable::eventFilter(QObject* ob, QEvent* ev)
251 if (ev->type() == QEvent::MouseButtonPress)
253 QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
254 if (mev->button() == Qt::MidButton) {
255 // enable or disable the clicked-on item
256 BreakpointItem* bp =
257 static_cast<BreakpointItem*>(m_list.itemAt(mev->pos()));
258 if (bp != 0)
260 m_debugger->enableDisableBreakpoint(bp->id);
262 return true;
265 return QWidget::eventFilter(ob, ev);
268 class ConditionalDlg : public QDialog
270 public:
271 ConditionalDlg(QWidget* parent);
272 ~ConditionalDlg();
274 void setCondition(const QString& text) { m_condition.setText(text); }
275 QString condition() { return m_condition.text(); }
276 void setIgnoreCount(uint count);
277 uint ignoreCount();
279 protected:
280 QLabel m_conditionLabel;
281 QLineEdit m_condition;
282 QLabel m_ignoreLabel;
283 QLineEdit m_ignoreCount;
284 QPushButton m_buttonOK;
285 QPushButton m_buttonCancel;
286 Q3VBoxLayout m_layout;
287 Q3GridLayout m_inputs;
288 Q3HBoxLayout m_buttons;
291 void BreakpointTable::conditionalBP()
293 BreakpointItem* bp = static_cast<BreakpointItem*>(m_list.currentItem());
294 if (bp == 0)
295 return;
298 * Important: we must not keep a pointer to the Breakpoint around,
299 * since it may vanish while the modal dialog is open through other
300 * user interactions (like clicking at the breakpoint in the source
301 * window)!
303 int id = bp->id;
305 ConditionalDlg dlg(this);
306 dlg.setCondition(bp->condition);
307 dlg.setIgnoreCount(bp->ignoreCount);
309 if (dlg.exec() != QDialog::Accepted)
310 return;
312 QString conditionInput = dlg.condition();
313 int ignoreCount = dlg.ignoreCount();
314 m_debugger->conditionalBreakpoint(id, conditionInput, ignoreCount);
318 void BreakpointTable::initListAndIcons()
320 m_list.addColumn(i18n("Location"), 220);
321 m_list.addColumn(i18n("Address"), 65);
322 m_list.addColumn(i18n("Hits"), 30);
323 m_list.addColumn(i18n("Ignore"), 30);
324 m_list.addColumn(i18n("Condition"), 200);
326 m_list.setMinimumSize(200, 100);
328 m_list.setSorting(-1);
330 // add pixmaps
331 QPixmap brkena = UserIcon("brkena.xpm");
332 QPixmap brkdis = UserIcon("brkdis.xpm");
333 QPixmap watchena = UserIcon("watchena.xpm");
334 QPixmap watchdis = UserIcon("watchdis.xpm");
335 QPixmap brktmp = UserIcon("brktmp.xpm");
336 QPixmap brkcond = UserIcon("brkcond.xpm");
337 QPixmap brkorph = UserIcon("brkorph.xpm");
340 * There are 32 different pixmaps: The basic enabled or disabled
341 * breakpoint, plus an optional overlaid brktmp icon plus an optional
342 * overlaid brkcond icon, plus an optional overlaid brkorph icon. Then
343 * the same sequence for watchpoints.
345 m_icons.resize(32);
346 QPixmap canvas(16,16);
348 for (int i = 0; i < 32; i++) {
350 QPainter p(&canvas);
351 // clear canvas
352 p.fillRect(0,0, canvas.width(),canvas.height(), Qt::cyan);
353 // basic icon
354 if (i & 1) {
355 p.drawPixmap(1,1, (i & 8) ? watchena : brkena);
356 } else {
357 p.drawPixmap(1,1, (i & 8) ? watchdis : brkdis);
359 // temporary overlay
360 if (i & 2) {
361 p.drawPixmap(1,1, brktmp);
363 // conditional overlay
364 if (i & 4) {
365 p.drawPixmap(1,1, brkcond);
367 // orphan overlay
368 if (i & 16) {
369 p.drawPixmap(1,1, brkorph);
372 canvas.setMask(canvas.createHeuristicMask());
373 m_icons[i] = canvas;
377 void BreakpointItem::display()
379 BreakpointTable* lb = static_cast<BreakpointTable*>(listView()->parent());
381 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
382 int code = enabled() ? 1 : 0;
383 if (temporary)
384 code += 2;
385 if (!condition.isEmpty() || ignoreCount > 0)
386 code += 4;
387 if (type == watchpoint)
388 code += 8;
389 if (isOrphaned())
390 code += 16;
391 setPixmap(0, lb->m_icons[code]);
393 // more breakpoint info
394 if (!location.isEmpty()) {
395 setText(0, location);
396 } else if (!Breakpoint::text.isEmpty()) {
397 setText(0, Breakpoint::text);
398 } else if (!fileName.isEmpty()) {
399 // use only the file name portion
400 QString file = fileName;
401 int slash = file.findRev('/');
402 if (slash >= 0) {
403 file = file.mid(slash+1);
405 // correct zero-based line-numbers
406 setText(0, file + ":" + QString::number(lineNo+1));
407 } else {
408 setText(0, "*" + address.asString());
411 int c = 0;
412 setText(++c, address.asString());
413 QString tmp;
414 if (hitCount == 0) {
415 setText(++c, QString());
416 } else {
417 tmp.setNum(hitCount);
418 setText(++c, tmp);
420 if (ignoreCount == 0) {
421 setText(++c, QString());
422 } else {
423 tmp.setNum(ignoreCount);
424 setText(++c, tmp);
426 if (condition.isEmpty()) {
427 setText(++c, QString());
428 } else {
429 setText(++c, condition);
434 ConditionalDlg::ConditionalDlg(QWidget* parent) :
435 QDialog(parent, "conditional", true),
436 m_conditionLabel(this, "condLabel"),
437 m_condition(this, "condition"),
438 m_ignoreLabel(this, "ignoreLabel"),
439 m_ignoreCount(this, "ignoreCount"),
440 m_buttonOK(this, "ok"),
441 m_buttonCancel(this, "cancel"),
442 m_layout(this, 10),
443 m_inputs(2, 2, 10),
444 m_buttons(4)
446 QString title = kapp->caption();
447 title += i18n(": Conditional breakpoint");
448 setCaption(title);
450 m_conditionLabel.setText(i18n("&Condition:"));
451 m_conditionLabel.setMinimumSize(m_conditionLabel.sizeHint());
452 m_ignoreLabel.setText(i18n("Ignore &next hits:"));
453 m_ignoreLabel.setMinimumSize(m_ignoreLabel.sizeHint());
455 m_condition.setMinimumSize(150, 24);
456 m_condition.setMaxLength(10000);
457 m_condition.setFrame(true);
458 m_ignoreCount.setMinimumSize(150, 24);
459 m_ignoreCount.setMaxLength(10000);
460 m_ignoreCount.setFrame(true);
462 m_conditionLabel.setBuddy(&m_condition);
463 m_ignoreLabel.setBuddy(&m_ignoreCount);
465 m_buttonOK.setMinimumSize(100, 30);
466 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
467 m_buttonOK.setText(i18n("OK"));
468 m_buttonOK.setDefault(true);
470 m_buttonCancel.setMinimumSize(100, 30);
471 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
472 m_buttonCancel.setText(i18n("Cancel"));
474 m_layout.addLayout(&m_inputs);
475 m_inputs.addWidget(&m_conditionLabel, 0, 0);
476 m_inputs.addWidget(&m_condition, 0, 1);
477 m_inputs.addWidget(&m_ignoreLabel, 1, 0);
478 m_inputs.addWidget(&m_ignoreCount, 1, 1);
479 m_inputs.setColStretch(1, 10);
480 m_layout.addLayout(&m_buttons);
481 m_layout.addStretch(10);
482 m_buttons.addStretch(10);
483 m_buttons.addWidget(&m_buttonOK);
484 m_buttons.addSpacing(40);
485 m_buttons.addWidget(&m_buttonCancel);
486 m_buttons.addStretch(10);
488 m_layout.activate();
490 m_condition.setFocus();
491 resize(400, 100);
494 ConditionalDlg::~ConditionalDlg()
498 uint ConditionalDlg::ignoreCount()
500 bool ok;
501 QString input = m_ignoreCount.text();
502 uint result = input.toUInt(&ok);
503 return ok ? result : 0;
506 void ConditionalDlg::setIgnoreCount(uint count)
508 QString text;
509 // set empty if ignore count is zero
510 if (count > 0) {
511 text.setNum(count);
513 m_ignoreCount.setText(text);
517 #include "brkpt.moc"