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 <klocalizedstring.h> /* i18n */
8 #include <kiconloader.h>
16 #include <QMouseEvent>
19 #include "dbgdriver.h"
24 #include "ui_brkptcondition.h"
28 class BreakpointItem
: public QTreeWidgetItem
, public Breakpoint
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
) :
43 connect(m_ui
.bpEdit
, SIGNAL(returnPressed()),
44 this, SLOT(on_btAddBP_clicked()));
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
)));
72 for (KDebugger::BrkptROIterator bp
= m_debugger
->breakpointsBegin(); bp
!= m_debugger
->breakpointsEnd(); ++bp
)
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 */
83 // not in the list; add it
84 new BreakpointItem(m_ui
.bpList
,*bp
);
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
),
102 void BreakpointItem::updateFrom(const Breakpoint
& bp
)
104 Breakpoint::operator=(bp
); /* assign new values */
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
;
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
;
132 m_debugger
->setBreakpoint(bp
, false);
136 void BreakpointTable::on_btRemove_clicked()
138 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_ui
.bpList
->currentItem());
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());
150 m_debugger
->enableDisableBreakpoint(bp
->id
);
154 void BreakpointTable::on_btViewCode_clicked()
156 BreakpointItem
* bp
= static_cast<BreakpointItem
*>(m_ui
.bpList
->currentItem());
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);
177 m_ui
.btEnaDis
->setText(i18n("&Disable"));
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
195 static_cast<BreakpointItem
*>(m_ui
.bpList
->itemAt(mev
->pos()));
198 m_debugger
->enableDisableBreakpoint(bp
->id
);
203 return QWidget::eventFilter(ob
, ev
);
206 class ConditionalDlg
: public QDialog
209 Ui::BrkPtCondition m_ui
;
212 ConditionalDlg(QWidget
* parent
);
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());
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
235 ConditionalDlg
dlg(this);
236 dlg
.setCondition(bp
->condition
);
237 dlg
.setIgnoreCount(bp
->ignoreCount
);
239 if (dlg
.exec() != QDialog::Accepted
)
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);
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.
272 QPixmap
canvas(16,16);
274 for (int i
= 0; i
< 32; i
++) {
278 p
.fillRect(0,0, canvas
.width(),canvas
.height(), Qt::cyan
);
281 p
.drawPixmap(1,1, (i
& 8) ? watchena
: brkena
);
283 p
.drawPixmap(1,1, (i
& 8) ? watchdis
: brkdis
);
287 p
.drawPixmap(1,1, brktmp
);
289 // conditional overlay
291 p
.drawPixmap(1,1, brkcond
);
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;
311 if (!condition
.isEmpty() || ignoreCount
> 0)
313 if (Breakpoint::type
== watchpoint
)
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));
330 setText(0, "*" + address
.asString());
334 setText(++c
, address
.asString());
337 setText(++c
, QString());
339 tmp
.setNum(hitCount
);
342 if (ignoreCount
== 0) {
343 setText(++c
, QString());
345 tmp
.setNum(ignoreCount
);
348 if (condition
.isEmpty()) {
349 setText(++c
, QString());
351 setText(++c
, condition
);
356 ConditionalDlg::ConditionalDlg(QWidget
* parent
) :
362 ConditionalDlg::~ConditionalDlg()