3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <kapp.h> /* i18n */
8 #include <klocale.h> /* i18n */
10 #include <kiconloader.h>
11 #include <ksimpleconfig.h>
18 #include "dbgdriver.h"
27 class BreakpointItem
: public QListViewItem
, public Breakpoint
30 BreakpointItem(QListView
* list
, const Breakpoint
& bp
);
31 void updateFrom(const Breakpoint
& bp
);
32 void display(); /* sets icon and visible texts */
36 BreakpointTable::BreakpointTable() :
37 QDialog(0, "breakpoints"),
39 m_bpEdit(this, "bpedit"),
40 m_list(this, "bptable"),
42 m_btRemove(this, "remove"),
43 m_btViewCode(this, "view"),
44 m_btConditional(this, "conditional"),
45 m_btClose(this, "close"),
50 m_bpEdit
.setMinimumSize(m_bpEdit
.sizeHint());
51 connect(&m_bpEdit
, SIGNAL(returnPressed()), this, SLOT(addBP()));
54 // double click on item is same as View code
55 connect(&m_list
, SIGNAL(doubleClicked(QListViewItem
*)), this, SLOT(viewBP()));
57 m_btAdd
.setText(i18n("&Add"));
58 m_btAdd
.setMinimumSize(m_btAdd
.sizeHint());
59 connect(&m_btAdd
, SIGNAL(clicked()), this, SLOT(addBP()));
61 m_btRemove
.setText(i18n("&Remove"));
62 m_btRemove
.setMinimumSize(m_btRemove
.sizeHint());
63 connect(&m_btRemove
, SIGNAL(clicked()), this, SLOT(removeBP()));
65 m_btViewCode
.setText(i18n("&View Code"));
66 m_btViewCode
.setMinimumSize(m_btViewCode
.sizeHint());
67 connect(&m_btViewCode
, SIGNAL(clicked()), this, SLOT(viewBP()));
69 m_btConditional
.setText(i18n("&Conditional..."));
70 m_btConditional
.setMinimumSize(m_btConditional
.sizeHint());
71 connect(&m_btConditional
, SIGNAL(clicked()), this, SLOT(conditionalBP()));
73 m_btClose
.setText(i18n("Close"));
74 m_btClose
.setMinimumSize(m_btClose
.sizeHint());
75 connect(&m_btClose
, SIGNAL(clicked()), this, SLOT(hide()));
77 m_layout
.addLayout(&m_listandedit
, 10);
78 m_layout
.addLayout(&m_buttons
);
79 m_listandedit
.addWidget(&m_bpEdit
);
80 m_listandedit
.addWidget(&m_list
, 10);
81 m_buttons
.addWidget(&m_btAdd
);
82 m_buttons
.addWidget(&m_btRemove
);
83 m_buttons
.addWidget(&m_btViewCode
);
84 m_buttons
.addWidget(&m_btConditional
);
85 m_buttons
.addWidget(&m_btClose
);
86 m_buttons
.addStretch(10);
95 BreakpointTable::~BreakpointTable()
99 void BreakpointTable::updateBreakList()
101 QList
<BreakpointItem
> deletedItems
;
103 for (QListViewItem
* it
= m_list
.firstChild(); it
!= 0; it
= it
->nextSibling()) {
104 deletedItems
.append(static_cast<BreakpointItem
*>(it
));
108 for (int i
= m_debugger
->numBreakpoints()-1; i
>= 0; i
--) {
109 const Breakpoint
* bp
= m_debugger
->breakpoint(i
);
111 for (BreakpointItem
* oldbp
= deletedItems
.first(); oldbp
!= 0;
112 oldbp
= deletedItems
.next())
114 if (oldbp
->id
== bp
->id
) {
115 oldbp
->updateFrom(*bp
);
116 deletedItems
.take(); /* don't delete */
120 // not in the list; add it
121 new BreakpointItem(&m_list
, *bp
);
125 // delete all untouched breakpoints
126 deletedItems
.setAutoDelete(true);
129 BreakpointItem::BreakpointItem(QListView
* list
, const Breakpoint
& bp
) :
136 void BreakpointItem::updateFrom(const Breakpoint
& bp
)
138 Breakpoint::operator=(bp
); /* assign new values */
142 void BreakpointTable::closeEvent(QCloseEvent
* ev
)
144 QDialog::closeEvent(ev
);
148 void BreakpointTable::hide()
154 void BreakpointTable::addBP()
156 // set a breakpoint at the specified text
157 QString bpText
= m_bpEdit
.text();
158 bpText
= bpText
.stripWhiteSpace();
159 if (m_debugger
->isReady()) {
160 m_debugger
->driver()->executeCmd(DCbreaktext
, bpText
);
161 // clear text if successfully set
162 m_bpEdit
.setText("");
166 void BreakpointTable::removeBP()
168 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_list
.currentItem());
172 m_debugger
->driver()->executeCmd(DCdelete
, bp
->id
);
175 void BreakpointTable::viewBP()
177 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_list
.currentItem());
181 emit
activateFileLine(bp
->fileName
, bp
->lineNo
);
184 void BreakpointTable::updateUI()
186 bool enableChkpt
= m_debugger
->canChangeBreakpoints();
187 m_btAdd
.setEnabled(enableChkpt
);
188 m_btRemove
.setEnabled(enableChkpt
);
189 m_btConditional
.setEnabled(enableChkpt
);
192 class ConditionalDlg
: public QDialog
195 ConditionalDlg(QWidget
* parent
);
198 void setCondition(const char* text
) { m_condition
.setText(text
); }
199 const char* condition() { return m_condition
.text(); }
200 void setIgnoreCount(uint count
);
204 QLabel m_conditionLabel
;
205 QLineEdit m_condition
;
206 QLabel m_ignoreLabel
;
207 QLineEdit m_ignoreCount
;
208 QPushButton m_buttonOK
;
209 QPushButton m_buttonCancel
;
210 QVBoxLayout m_layout
;
211 QGridLayout m_inputs
;
212 QHBoxLayout m_buttons
;
215 void BreakpointTable::conditionalBP()
217 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_list
.currentItem());
222 * Important: we must not keep a pointer to the Breakpoint around,
223 * since it may vanish while the modal dialog is open through other
224 * user interactions (like clicking at the breakpoint in the source
229 ConditionalDlg
dlg(this);
230 dlg
.setCondition(bp
->condition
);
231 dlg
.setIgnoreCount(bp
->ignoreCount
);
233 if (dlg
.exec() != QDialog::Accepted
)
236 QString conditionInput
= dlg
.condition();
237 int ignoreCount
= dlg
.ignoreCount();
238 updateBreakpointCondition(id
, conditionInput
, ignoreCount
);
241 void BreakpointTable::updateBreakpointCondition(int id
,
242 const QString
& condition
,
245 BreakpointItem
* bp
= itemByBreakId(id
);
247 return; /* breakpoint no longer exists */
249 bool changed
= false;
251 if (bp
->condition
!= condition
) {
253 m_debugger
->driver()->executeCmd(DCcondition
, condition
, bp
->id
);
254 bp
->condition
= condition
;
257 if (bp
->ignoreCount
!= ignoreCount
) {
258 // change ignore count
259 m_debugger
->driver()->executeCmd(DCignore
, bp
->id
, ignoreCount
);
264 m_debugger
->driver()->queueCmd(DCinfobreak
, DebuggerDriver::QMoverride
);
269 BreakpointItem
* BreakpointTable::itemByBreakId(int id
)
271 for (QListViewItem
* it
= m_list
.firstChild(); it
!= 0; it
= it
->nextSibling()) {
272 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(it
);
281 void BreakpointTable::initListAndIcons()
283 m_list
.addColumn(i18n("Location"), 300);
284 m_list
.addColumn(i18n("Hits"), 30);
285 m_list
.addColumn(i18n("Ignore"), 30);
286 m_list
.addColumn(i18n("Condition"), 200);
288 m_list
.setMinimumSize(200, 100);
289 setFocusPolicy(QWidget::StrongFocus
);
291 m_list
.setSorting(-1);
295 KIconLoader
* loader
= kapp
->getIconLoader();
296 QPixmap brkena
= loader
->loadIcon("brkena.xpm");
297 QPixmap brkdis
= loader
->loadIcon("brkdis.xpm");
298 QPixmap brktmp
= loader
->loadIcon("brktmp.xpm");
299 QPixmap brkcond
= loader
->loadIcon("brkcond.xpm");
301 QPixmap brkena
= BarIcon("brkena.xpm");
302 QPixmap brkdis
= BarIcon("brkdis.xpm");
303 QPixmap brktmp
= BarIcon("brktmp.xpm");
304 QPixmap brkcond
= BarIcon("brkcond.xpm");
307 * There are 8 different pixmaps: The basic enabled or disabled
308 * breakpoint, plus an optional overlaid brktmp icon plus an optional
309 * overlaid brkcond icon.
312 QPixmap
canvas(16,16);
314 for (int i
= 0; i
< 8; i
++) {
318 p
.fillRect(0,0, canvas
.width(),canvas
.height(), cyan
);
321 p
.drawPixmap(1,1, brkena
);
323 p
.drawPixmap(1,1, brkdis
);
327 p
.drawPixmap(1,1, brktmp
);
329 // conditional overlay
331 p
.drawPixmap(1,1, brkcond
);
334 canvas
.setMask(canvas
.createHeuristicMask());
339 void BreakpointItem::display()
341 BreakpointTable
* lb
= static_cast<BreakpointTable
*>(listView()->parent());
343 /* breakpoint icon code; keep order the same as in BreakpointTable::initListAndIcons */
344 int code
= enabled
? 1 : 0;
347 if (!condition
.isEmpty() || ignoreCount
> 0)
349 setPixmap(0, lb
->m_icons
[code
]);
351 // more breakpoint info
352 setText(0, location
);
355 setText(1, QString());
357 tmp
.setNum(hitCount
);
360 if (ignoreCount
== 0) {
361 setText(2, QString());
363 tmp
.setNum(ignoreCount
);
366 if (condition
.isEmpty()) {
367 setText(3, QString());
369 setText(3, condition
);
374 ConditionalDlg::ConditionalDlg(QWidget
* parent
) :
375 QDialog(parent
, "conditional", true),
376 m_conditionLabel(this, "condLabel"),
377 m_condition(this, "condition"),
378 m_ignoreLabel(this, "ignoreLabel"),
379 m_ignoreCount(this, "ignoreCount"),
380 m_buttonOK(this, "ok"),
381 m_buttonCancel(this, "cancel"),
386 QString title
= kapp
->getCaption();
387 title
+= i18n(": Conditional breakpoint");
390 m_conditionLabel
.setText(i18n("&Condition:"));
391 m_conditionLabel
.setMinimumSize(m_conditionLabel
.sizeHint());
392 m_ignoreLabel
.setText(i18n("Ignore &next hits:"));
393 m_ignoreLabel
.setMinimumSize(m_ignoreLabel
.sizeHint());
395 m_condition
.setMinimumSize(150, 24);
396 m_condition
.setMaxLength(10000);
397 m_condition
.setFrame(true);
398 m_ignoreCount
.setMinimumSize(150, 24);
399 m_ignoreCount
.setMaxLength(10000);
400 m_ignoreCount
.setFrame(true);
402 m_conditionLabel
.setBuddy(&m_condition
);
403 m_ignoreLabel
.setBuddy(&m_ignoreCount
);
405 m_buttonOK
.setMinimumSize(100, 30);
406 connect(&m_buttonOK
, SIGNAL(clicked()), SLOT(accept()));
407 m_buttonOK
.setText(i18n("OK"));
408 m_buttonOK
.setDefault(true);
410 m_buttonCancel
.setMinimumSize(100, 30);
411 connect(&m_buttonCancel
, SIGNAL(clicked()), SLOT(reject()));
412 m_buttonCancel
.setText(i18n("Cancel"));
414 m_layout
.addLayout(&m_inputs
);
415 m_inputs
.addWidget(&m_conditionLabel
, 0, 0);
416 m_inputs
.addWidget(&m_condition
, 0, 1);
417 m_inputs
.addWidget(&m_ignoreLabel
, 1, 0);
418 m_inputs
.addWidget(&m_ignoreCount
, 1, 1);
419 m_inputs
.setColStretch(1, 10);
420 m_layout
.addLayout(&m_buttons
);
421 m_layout
.addStretch(10);
422 m_buttons
.addStretch(10);
423 m_buttons
.addWidget(&m_buttonOK
);
424 m_buttons
.addSpacing(40);
425 m_buttons
.addWidget(&m_buttonCancel
);
426 m_buttons
.addStretch(10);
430 m_condition
.setFocus();
434 ConditionalDlg::~ConditionalDlg()
438 uint
ConditionalDlg::ignoreCount()
441 QString input
= m_ignoreCount
.text();
442 uint result
= input
.toUInt(&ok
);
443 return ok
? result
: 0;
446 void ConditionalDlg::setIgnoreCount(uint count
)
449 // set empty if ignore count is zero
453 m_ignoreCount
.setText(text
);