Generate and install scalable icons.
[kdbg.git] / kdbg / brkpt.cpp
blob13ea512316e05ea0036d29ef98e45d6047e54221
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 <klocale.h> /* i18n */
8 #include <kiconloader.h>
9 #include <ksimpleconfig.h>
10 #include <QDialog>
11 #include <QFileInfo>
12 #include <QPainter>
13 #include <QLabel>
14 #include <QBitmap>
15 #include <QPixmap>
17 #include <QMouseEvent>
18 #include "debugger.h"
19 #include "brkpt.h"
20 #include "dbgdriver.h"
21 #include <ctype.h>
22 #include <list>
23 #include "mydebug.h"
25 #include "ui_brkptcondition.h"
29 class BreakpointItem : public QTreeWidgetItem, public Breakpoint
31 public:
32 BreakpointItem(QTreeWidget* list, const Breakpoint& bp);
33 void updateFrom(const Breakpoint& bp);
34 void display(); /* sets icon and visible texts */
35 bool enabled() const { return Breakpoint::enabled; }
39 BreakpointTable::BreakpointTable(QWidget* parent) :
40 QWidget(parent),
41 m_debugger(0)
43 m_ui.setupUi(this);
44 connect(m_ui.bpEdit, SIGNAL(returnPressed()),
45 this, SLOT(on_btAddBP_clicked()));
47 initListAndIcons();
49 connect(m_ui.bpList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
50 this, SLOT(updateUI()));
51 // double click on item is same as View code
52 connect(m_ui.bpList,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
53 this, SLOT(on_btViewCode_clicked()));
55 // need mouse button events
56 m_ui.bpList->viewport()->installEventFilter(this);
59 BreakpointTable::~BreakpointTable()
63 void BreakpointTable::updateBreakList()
65 std::list<BreakpointItem*> deletedItems;
67 for (int i = 0 ; i < m_ui.bpList->topLevelItemCount(); i++)
69 deletedItems.push_back(static_cast<BreakpointItem*>(m_ui.bpList->topLevelItem(i)));
72 // get the new list
73 for (KDebugger::BrkptROIterator bp = m_debugger->breakpointsBegin(); bp != m_debugger->breakpointsEnd(); ++bp)
75 // look up this item
76 for (std::list<BreakpointItem*>::iterator o = deletedItems.begin(); o != deletedItems.end(); ++o)
78 if ((*o)->id == bp->id) {
79 (*o)->updateFrom(*bp);
80 deletedItems.erase(o); /* don't delete */
81 goto nextItem;
84 // not in the list; add it
85 new BreakpointItem(m_ui.bpList,*bp);
86 nextItem:;
89 // delete all untouched breakpoints
90 while (!deletedItems.empty()) {
91 delete deletedItems.front();
92 deletedItems.pop_front();
96 BreakpointItem::BreakpointItem(QTreeWidget* list, const Breakpoint& bp) :
97 QTreeWidgetItem(list),
98 Breakpoint(bp)
100 display();
103 void BreakpointItem::updateFrom(const Breakpoint& bp)
105 Breakpoint::operator=(bp); /* assign new values */
106 display();
109 void BreakpointTable::on_btAddBP_clicked()
111 // set a breakpoint at the specified text
112 QString bpText = m_ui.bpEdit->text();
113 bpText = bpText.trimmed();
114 if (m_debugger->isReady())
116 Breakpoint* bp = new Breakpoint;
117 bp->text = bpText;
119 m_debugger->setBreakpoint(bp, false);
123 void BreakpointTable::on_btAddWP_clicked()
125 // set a watchpoint for the specified expression
126 QString wpExpr = m_ui.bpEdit->text();
127 wpExpr = wpExpr.trimmed();
128 if (m_debugger->isReady()) {
129 Breakpoint* bp = new Breakpoint;
130 bp->type = Breakpoint::watchpoint;
131 bp->text = wpExpr;
133 m_debugger->setBreakpoint(bp, false);
137 void BreakpointTable::on_btRemove_clicked()
139 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
140 if (bp != 0) {
141 m_debugger->deleteBreakpoint(bp->id);
142 // note that bp may be deleted by now
143 // (if bp was an orphaned breakpoint)
147 void BreakpointTable::on_btEnaDis_clicked()
149 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
150 if (bp != 0) {
151 m_debugger->enableDisableBreakpoint(bp->id);
155 void BreakpointTable::on_btViewCode_clicked()
157 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
158 if (bp == 0)
159 return;
161 if (!m_debugger->infoLine(bp->fileName, bp->lineNo, bp->address))
162 emit activateFileLine(bp->fileName, bp->lineNo, bp->address);
165 void BreakpointTable::updateUI()
167 bool enableChkpt = m_debugger->canChangeBreakpoints();
168 m_ui.btAddBP->setEnabled(enableChkpt);
169 m_ui.btAddWP->setEnabled(enableChkpt);
171 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
172 m_ui.btViewCode->setEnabled(bp != 0);
174 if (bp == 0) {
175 enableChkpt = false;
176 } else {
177 if (bp->enabled()) {
178 m_ui.btEnaDis->setText(i18n("&Disable"));
179 } else {
180 m_ui.btEnaDis->setText(i18n("&Enable"));
183 m_ui.btRemove->setEnabled(enableChkpt);
184 m_ui.btEnaDis->setEnabled(enableChkpt);
185 m_ui.btConditional->setEnabled(enableChkpt);
188 bool BreakpointTable::eventFilter(QObject* ob, QEvent* ev)
190 if (ev->type() == QEvent::MouseButtonPress)
192 QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
193 if (mev->button() == Qt::MidButton) {
194 // enable or disable the clicked-on item
195 BreakpointItem* bp =
196 static_cast<BreakpointItem*>(m_ui.bpList->itemAt(mev->pos()));
197 if (bp != 0)
199 m_debugger->enableDisableBreakpoint(bp->id);
201 return true;
204 return QWidget::eventFilter(ob, ev);
207 class ConditionalDlg : public QDialog
209 private:
210 Ui::BrkPtCondition m_ui;
212 public:
213 ConditionalDlg(QWidget* parent);
214 ~ConditionalDlg();
216 void setCondition(const QString& text) { m_ui.condition->setText(text); }
217 QString condition() { return m_ui.condition->text(); }
218 void setIgnoreCount(uint count){ m_ui.ignoreCount->setValue(count); };
219 uint ignoreCount(){ return m_ui.ignoreCount->value(); };
222 void BreakpointTable::on_btConditional_clicked()
224 BreakpointItem* bp = static_cast<BreakpointItem*>(m_ui.bpList->currentItem());
225 if (bp == 0)
226 return;
229 * Important: we must not keep a pointer to the Breakpoint around,
230 * since it may vanish while the modal dialog is open through other
231 * user interactions (like clicking at the breakpoint in the source
232 * window)!
234 int id = bp->id;
236 ConditionalDlg dlg(this);
237 dlg.setCondition(bp->condition);
238 dlg.setIgnoreCount(bp->ignoreCount);
240 if (dlg.exec() != QDialog::Accepted)
241 return;
243 QString conditionInput = dlg.condition();
244 int ignoreCount = dlg.ignoreCount();
245 m_debugger->conditionalBreakpoint(id, conditionInput, ignoreCount);
249 void BreakpointTable::initListAndIcons()
251 m_ui.bpList->setColumnWidth(0, 220);
252 m_ui.bpList->setColumnWidth(1, 65);
253 m_ui.bpList->setColumnWidth(2, 30);
254 m_ui.bpList->setColumnWidth(3, 30);
255 m_ui.bpList->setColumnWidth(4, 200);
257 // add pixmaps
258 QPixmap brkena = UserIcon("brkena");
259 QPixmap brkdis = UserIcon("brkdis");
260 QPixmap watchena = UserIcon("watchena");
261 QPixmap watchdis = UserIcon("watchdis");
262 QPixmap brktmp = UserIcon("brktmp");
263 QPixmap brkcond = UserIcon("brkcond");
264 QPixmap brkorph = UserIcon("brkorph");
267 * There are 32 different pixmaps: The basic enabled or disabled
268 * breakpoint, plus an optional overlaid brktmp icon plus an optional
269 * overlaid brkcond icon, plus an optional overlaid brkorph icon. Then
270 * the same sequence for watchpoints.
272 m_icons.resize(32);
273 QPixmap canvas(16,16);
275 for (int i = 0; i < 32; i++) {
277 QPainter p(&canvas);
278 // clear canvas
279 p.fillRect(0,0, canvas.width(),canvas.height(), Qt::cyan);
280 // basic icon
281 if (i & 1) {
282 p.drawPixmap(1,1, (i & 8) ? watchena : brkena);
283 } else {
284 p.drawPixmap(1,1, (i & 8) ? watchdis : brkdis);
286 // temporary overlay
287 if (i & 2) {
288 p.drawPixmap(1,1, brktmp);
290 // conditional overlay
291 if (i & 4) {
292 p.drawPixmap(1,1, brkcond);
294 // orphan overlay
295 if (i & 16) {
296 p.drawPixmap(1,1, brkorph);
299 canvas.setMask(canvas.createHeuristicMask());
300 m_icons[i] = QIcon(canvas);
304 void BreakpointItem::display()
306 BreakpointTable* lb = static_cast<BreakpointTable*>(treeWidget()->parent());
308 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
309 int code = enabled() ? 1 : 0;
310 if (temporary)
311 code += 2;
312 if (!condition.isEmpty() || ignoreCount > 0)
313 code += 4;
314 if (Breakpoint::type == watchpoint)
315 code += 8;
316 if (isOrphaned())
317 code += 16;
318 setIcon(0, lb->m_icons[code]);
320 // more breakpoint info
321 if (!location.isEmpty()) {
322 setText(0, location);
323 } else if (!Breakpoint::text.isEmpty()) {
324 setText(0, Breakpoint::text);
325 } else if (!fileName.isEmpty()) {
326 // use only the file name portion
327 QString file = QFileInfo(fileName).fileName();
328 // correct zero-based line-numbers
329 setText(0, file + ":" + QString::number(lineNo+1));
330 } else {
331 setText(0, "*" + address.asString());
334 int c = 0;
335 setText(++c, address.asString());
336 QString tmp;
337 if (hitCount == 0) {
338 setText(++c, QString());
339 } else {
340 tmp.setNum(hitCount);
341 setText(++c, tmp);
343 if (ignoreCount == 0) {
344 setText(++c, QString());
345 } else {
346 tmp.setNum(ignoreCount);
347 setText(++c, tmp);
349 if (condition.isEmpty()) {
350 setText(++c, QString());
351 } else {
352 setText(++c, condition);
357 ConditionalDlg::ConditionalDlg(QWidget* parent) :
358 QDialog(parent)
360 m_ui.setupUi(this);
363 ConditionalDlg::~ConditionalDlg()
368 #include "brkpt.moc"