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.
7 #include <klocale.h> /* i18n */
8 #include <kiconloader.h>
9 #include <ksimpleconfig.h>
17 #include <QMouseEvent>
20 #include "dbgdriver.h"
25 #include "ui_brkptcondition.h"
29 class BreakpointItem
: public QTreeWidgetItem
, public Breakpoint
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
) :
44 connect(m_ui
.bpEdit
, SIGNAL(returnPressed()),
45 this, SLOT(on_btAddBP_clicked()));
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
)));
73 for (KDebugger::BrkptROIterator bp
= m_debugger
->breakpointsBegin(); bp
!= m_debugger
->breakpointsEnd(); ++bp
)
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 */
84 // not in the list; add it
85 new BreakpointItem(m_ui
.bpList
,*bp
);
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
),
103 void BreakpointItem::updateFrom(const Breakpoint
& bp
)
105 Breakpoint::operator=(bp
); /* assign new values */
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
;
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
;
133 m_debugger
->setBreakpoint(bp
, false);
137 void BreakpointTable::on_btRemove_clicked()
139 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_ui
.bpList
->currentItem());
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());
151 m_debugger
->enableDisableBreakpoint(bp
->id
);
155 void BreakpointTable::on_btViewCode_clicked()
157 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_ui
.bpList
->currentItem());
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);
178 m_ui
.btEnaDis
->setText(i18n("&Disable"));
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
196 static_cast<BreakpointItem
*>(m_ui
.bpList
->itemAt(mev
->pos()));
199 m_debugger
->enableDisableBreakpoint(bp
->id
);
204 return QWidget::eventFilter(ob
, ev
);
207 class ConditionalDlg
: public QDialog
210 Ui::BrkPtCondition m_ui
;
213 ConditionalDlg(QWidget
* parent
);
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());
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
236 ConditionalDlg
dlg(this);
237 dlg
.setCondition(bp
->condition
);
238 dlg
.setIgnoreCount(bp
->ignoreCount
);
240 if (dlg
.exec() != QDialog::Accepted
)
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);
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.
273 QPixmap
canvas(16,16);
275 for (int i
= 0; i
< 32; i
++) {
279 p
.fillRect(0,0, canvas
.width(),canvas
.height(), Qt::cyan
);
282 p
.drawPixmap(1,1, (i
& 8) ? watchena
: brkena
);
284 p
.drawPixmap(1,1, (i
& 8) ? watchdis
: brkdis
);
288 p
.drawPixmap(1,1, brktmp
);
290 // conditional overlay
292 p
.drawPixmap(1,1, brkcond
);
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;
312 if (!condition
.isEmpty() || ignoreCount
> 0)
314 if (Breakpoint::type
== watchpoint
)
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));
331 setText(0, "*" + address
.asString());
335 setText(++c
, address
.asString());
338 setText(++c
, QString());
340 tmp
.setNum(hitCount
);
343 if (ignoreCount
== 0) {
344 setText(++c
, QString());
346 tmp
.setNum(ignoreCount
);
349 if (condition
.isEmpty()) {
350 setText(++c
, QString());
352 setText(++c
, condition
);
357 ConditionalDlg::ConditionalDlg(QWidget
* parent
) :
363 ConditionalDlg::~ConditionalDlg()