Extend copyright to 2018.
[kdbg.git] / kdbg / brkpt.cpp
blob8c46e468eef23467ec6d75161e2a16e7f8a8de0b
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 <klocalizedstring.h> /* i18n */
8 #include <kiconloader.h>
9 #include <QDialog>
10 #include <QFileInfo>
11 #include <QPainter>
12 #include <QLabel>
13 #include <QBitmap>
14 #include <QPixmap>
16 #include <QMouseEvent>
17 #include "debugger.h"
18 #include "brkpt.h"
19 #include "dbgdriver.h"
20 #include <ctype.h>
21 #include <list>
22 #include "mydebug.h"
24 #include "ui_brkptcondition.h"
28 class BreakpointItem : public QTreeWidgetItem, public Breakpoint
30 public:
31 BreakpointItem(QTreeWidget* list, const Breakpoint& bp);
32 void updateFrom(const Breakpoint& bp);
33 void display(); /* sets icon and visible texts */
34 bool enabled() const { return Breakpoint::enabled; }
38 BreakpointTable::BreakpointTable(QWidget* parent) :
39 QWidget(parent),
40 m_debugger(0)
42 m_ui.setupUi(this);
43 connect(m_ui.bpEdit, SIGNAL(returnPressed()),
44 this, SLOT(on_btAddBP_clicked()));
46 initListAndIcons();
48 connect(m_ui.bpList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
49 this, SLOT(updateUI()));
50 // double click on item is same as View code
51 connect(m_ui.bpList,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
52 this, SLOT(on_btViewCode_clicked()));
54 // need mouse button events
55 m_ui.bpList->viewport()->installEventFilter(this);
58 BreakpointTable::~BreakpointTable()
62 void BreakpointTable::updateBreakList()
64 std::list<BreakpointItem*> deletedItems;
66 for (int i = 0 ; i < m_ui.bpList->topLevelItemCount(); i++)
68 deletedItems.push_back(static_cast<BreakpointItem*>(m_ui.bpList->topLevelItem(i)));
71 // get the new list
72 for (KDebugger::BrkptROIterator bp = m_debugger->breakpointsBegin(); bp != m_debugger->breakpointsEnd(); ++bp)
74 // look up this item
75 for (std::list<BreakpointItem*>::iterator o = deletedItems.begin(); o != deletedItems.end(); ++o)
77 if ((*o)->id == bp->id) {
78 (*o)->updateFrom(*bp);
79 deletedItems.erase(o); /* don't delete */
80 goto nextItem;
83 // not in the list; add it
84 new BreakpointItem(m_ui.bpList,*bp);
85 nextItem:;
88 // delete all untouched breakpoints
89 while (!deletedItems.empty()) {
90 delete deletedItems.front();
91 deletedItems.pop_front();
95 BreakpointItem::BreakpointItem(QTreeWidget* list, const Breakpoint& bp) :
96 QTreeWidgetItem(list),
97 Breakpoint(bp)
99 display();
102 void BreakpointItem::updateFrom(const Breakpoint& bp)
104 Breakpoint::operator=(bp); /* assign new values */
105 display();
108 void BreakpointTable::on_btAddBP_clicked()
110 // set a breakpoint at the specified text
111 QString bpText = m_ui.bpEdit->text();
112 bpText = bpText.trimmed();
113 if (m_debugger->isReady())
115 Breakpoint* bp = new Breakpoint;
116 bp->text = bpText;
118 m_debugger->setBreakpoint(bp, false);
122 void BreakpointTable::on_btAddWP_clicked()
124 // set a watchpoint for the specified expression
125 QString wpExpr = m_ui.bpEdit->text();
126 wpExpr = wpExpr.trimmed();
127 if (m_debugger->isReady()) {
128 Breakpoint* bp = new Breakpoint;
129 bp->type = Breakpoint::watchpoint;
130 bp->text = wpExpr;
132 m_debugger->setBreakpoint(bp, false);
136 void BreakpointTable::on_btRemove_clicked()
138 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
139 if (bp != 0) {
140 m_debugger->deleteBreakpoint(bp->id);
141 // note that bp may be deleted by now
142 // (if bp was an orphaned breakpoint)
146 void BreakpointTable::on_btEnaDis_clicked()
148 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
149 if (bp != 0) {
150 m_debugger->enableDisableBreakpoint(bp->id);
154 void BreakpointTable::on_btViewCode_clicked()
156 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
157 if (bp == 0)
158 return;
160 if (!m_debugger->infoLine(bp->fileName, bp->lineNo, bp->address))
161 emit activateFileLine(bp->fileName, bp->lineNo, bp->address);
164 void BreakpointTable::updateUI()
166 bool enableChkpt = m_debugger->canChangeBreakpoints();
167 m_ui.btAddBP->setEnabled(enableChkpt);
168 m_ui.btAddWP->setEnabled(enableChkpt);
170 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
171 m_ui.btViewCode->setEnabled(bp != 0);
173 if (bp == 0) {
174 enableChkpt = false;
175 } else {
176 if (bp->enabled()) {
177 m_ui.btEnaDis->setText(i18n("&Disable"));
178 } else {
179 m_ui.btEnaDis->setText(i18n("&Enable"));
182 m_ui.btRemove->setEnabled(enableChkpt);
183 m_ui.btEnaDis->setEnabled(enableChkpt);
184 m_ui.btConditional->setEnabled(enableChkpt);
187 bool BreakpointTable::eventFilter(QObject* ob, QEvent* ev)
189 if (ev->type() == QEvent::MouseButtonPress)
191 QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
192 if (mev->button() == Qt::MidButton) {
193 // enable or disable the clicked-on item
194 BreakpointItem* bp =
195 static_cast<BreakpointItem*>(m_ui.bpList->itemAt(mev->pos()));
196 if (bp != 0)
198 m_debugger->enableDisableBreakpoint(bp->id);
200 return true;
203 return QWidget::eventFilter(ob, ev);
206 class ConditionalDlg : public QDialog
208 private:
209 Ui::BrkPtCondition m_ui;
211 public:
212 ConditionalDlg(QWidget* parent);
213 ~ConditionalDlg();
215 void setCondition(const QString& text) { m_ui.condition->setText(text); }
216 QString condition() { return m_ui.condition->text(); }
217 void setIgnoreCount(uint count){ m_ui.ignoreCount->setValue(count); };
218 uint ignoreCount(){ return m_ui.ignoreCount->value(); };
221 void BreakpointTable::on_btConditional_clicked()
223 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
224 if (bp == 0)
225 return;
228 * Important: we must not keep a pointer to the Breakpoint around,
229 * since it may vanish while the modal dialog is open through other
230 * user interactions (like clicking at the breakpoint in the source
231 * window)!
233 int id = bp->id;
235 ConditionalDlg dlg(this);
236 dlg.setCondition(bp->condition);
237 dlg.setIgnoreCount(bp->ignoreCount);
239 if (dlg.exec() != QDialog::Accepted)
240 return;
242 QString conditionInput = dlg.condition();
243 int ignoreCount = dlg.ignoreCount();
244 m_debugger->conditionalBreakpoint(id, conditionInput, ignoreCount);
248 void BreakpointTable::initListAndIcons()
250 m_ui.bpList->setColumnWidth(0, 220);
251 m_ui.bpList->setColumnWidth(1, 65);
252 m_ui.bpList->setColumnWidth(2, 30);
253 m_ui.bpList->setColumnWidth(3, 30);
254 m_ui.bpList->setColumnWidth(4, 200);
256 // add pixmaps
257 QPixmap brkena = UserIcon("brkena");
258 QPixmap brkdis = UserIcon("brkdis");
259 QPixmap watchena = UserIcon("watchena");
260 QPixmap watchdis = UserIcon("watchdis");
261 QPixmap brktmp = UserIcon("brktmp");
262 QPixmap brkcond = UserIcon("brkcond");
263 QPixmap brkorph = UserIcon("brkorph");
266 * There are 32 different pixmaps: The basic enabled or disabled
267 * breakpoint, plus an optional overlaid brktmp icon plus an optional
268 * overlaid brkcond icon, plus an optional overlaid brkorph icon. Then
269 * the same sequence for watchpoints.
271 m_icons.resize(32);
272 QPixmap canvas(16,16);
274 for (int i = 0; i < 32; i++) {
276 QPainter p(&canvas);
277 // clear canvas
278 p.fillRect(0,0, canvas.width(),canvas.height(), Qt::cyan);
279 // basic icon
280 if (i & 1) {
281 p.drawPixmap(1,1, (i & 8) ? watchena : brkena);
282 } else {
283 p.drawPixmap(1,1, (i & 8) ? watchdis : brkdis);
285 // temporary overlay
286 if (i & 2) {
287 p.drawPixmap(1,1, brktmp);
289 // conditional overlay
290 if (i & 4) {
291 p.drawPixmap(1,1, brkcond);
293 // orphan overlay
294 if (i & 16) {
295 p.drawPixmap(1,1, brkorph);
298 canvas.setMask(canvas.createHeuristicMask());
299 m_icons[i] = QIcon(canvas);
303 void BreakpointItem::display()
305 BreakpointTable* lb = static_cast<BreakpointTable*>(treeWidget()->parent());
307 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
308 int code = enabled() ? 1 : 0;
309 if (temporary)
310 code += 2;
311 if (!condition.isEmpty() || ignoreCount > 0)
312 code += 4;
313 if (Breakpoint::type == watchpoint)
314 code += 8;
315 if (isOrphaned())
316 code += 16;
317 setIcon(0, lb->m_icons[code]);
319 // more breakpoint info
320 if (!location.isEmpty()) {
321 setText(0, location);
322 } else if (!Breakpoint::text.isEmpty()) {
323 setText(0, Breakpoint::text);
324 } else if (!fileName.isEmpty()) {
325 // use only the file name portion
326 QString file = QFileInfo(fileName).fileName();
327 // correct zero-based line-numbers
328 setText(0, file + ":" + QString::number(lineNo+1));
329 } else {
330 setText(0, "*" + address.asString());
333 int c = 0;
334 setText(++c, address.asString());
335 QString tmp;
336 if (hitCount == 0) {
337 setText(++c, QString());
338 } else {
339 tmp.setNum(hitCount);
340 setText(++c, tmp);
342 if (ignoreCount == 0) {
343 setText(++c, QString());
344 } else {
345 tmp.setNum(ignoreCount);
346 setText(++c, tmp);
348 if (condition.isEmpty()) {
349 setText(++c, QString());
350 } else {
351 setText(++c, condition);
356 ConditionalDlg::ConditionalDlg(QWidget* parent) :
357 QDialog(parent)
359 m_ui.setupUi(this);
362 ConditionalDlg::~ConditionalDlg()
367 #include "brkpt.moc"