Added support to debug XSLT using xsldbg by Keith Isdale.
[kdbg.git] / kdbg / winstack.cpp
bloba480660de210d28d6a9537962007673dc67833c8
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "winstack.h"
7 #include "sourcewnd.h"
8 #include <qbrush.h>
9 #include <qfileinfo.h>
10 #include <qlistbox.h>
11 #include <kapp.h>
12 #if QT_VERSION >= 200
13 #include <klocale.h> /* i18n */
14 #else
15 #include <ctype.h>
16 #endif
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 #include "mydebug.h"
24 WinStack::WinStack(QWidget* parent, const char* name) :
25 QWidget(parent, name),
26 m_activeWindow(0),
27 m_windowMenu(0),
28 m_itemMore(0),
29 m_pcLine(-1),
30 m_valueTip(this),
31 m_tipLocation(1,1,10,10),
32 m_tabWidth(0)
34 connect(&m_findDlg.m_buttonForward,
35 SIGNAL(clicked()), SLOT(slotFindForward()));
36 connect(&m_findDlg.m_buttonBackward,
37 SIGNAL(clicked()), SLOT(slotFindBackward()));
39 connect(this, SIGNAL(setTabWidth(int)), this, SLOT(slotSetTabWidth(int)));
42 WinStack::~WinStack()
46 void WinStack::setWindowMenu(QPopupMenu* menu)
48 m_windowMenu = menu;
49 if (menu == 0) {
50 return;
53 // find entry More...
54 m_itemMore = menu->indexOf(WindowMore);
55 // must contain item More...
56 ASSERT(m_itemMore >= 0);
58 m_textMore = menu->text(WindowMore);
59 menu->removeItemAt(m_itemMore);
61 // hook up for menu activations
62 connect(menu, SIGNAL(activated(int)), this, SLOT(selectWindow(int)));
65 void WinStack::mousePressEvent(QMouseEvent* mouseEvent)
67 // Check if right button was clicked.
68 if (mouseEvent->button() == RightButton)
70 emit clickedRight(mouseEvent->pos());
71 } else {
72 QWidget::mousePressEvent(mouseEvent);
77 void WinStack::reloadAllFiles()
79 SourceWindow* fw;
80 for (fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
81 fw->reloadFile();
85 void WinStack::activate(const QString& fileName, int lineNo, const DbgAddr& address)
87 QFileInfo fi(fileName);
89 if (!fi.isFile()) {
91 * We didn't find that file. Now check if it is a relative path and
92 * try m_lastOpenDir as prefix.
94 TRACE(fi.filePath() + (" not found, looking in " + m_lastOpenDir));
95 if (!fi.isRelative() || m_lastOpenDir.isEmpty()) {
96 return;
98 fi.setFile(m_lastOpenDir + "/" + fi.filePath());
99 if (!fi.isFile()) {
100 return;
103 // if this is not an absolute path name, make it one
104 activatePath(fi.absFilePath(), lineNo, address);
107 void WinStack::activateFile(const QString& fileName)
109 activatePath(fileName, 0, DbgAddr());
112 bool WinStack::activatePath(QString pathName, int lineNo, const DbgAddr& address)
114 // check whether the file is already open
115 SourceWindow* fw;
116 for (fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
117 if (fw->fileName() == pathName) {
118 break;
121 if (fw == 0) {
122 // not found, load it
123 fw = new SourceWindow(pathName, this, "fileWindow");
125 // slurp the file in
126 if (!fw->loadFile()) {
127 // read failed
128 delete fw;
129 return false;
132 m_fileList.insert(0, fw);
133 connect(fw, SIGNAL(lineChanged()),SIGNAL(lineChanged()));
134 connect(fw, SIGNAL(clickedLeft(const QString&,int,const DbgAddr&,bool)),
135 SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)));
136 connect(fw, SIGNAL(clickedMid(const QString&,int,const DbgAddr&)),
137 SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)));
139 // Comunication when right button is clicked.
140 connect(fw, SIGNAL(clickedRight(const QPoint &)),
141 SIGNAL(filesRightClick(const QPoint &)));
143 // disassemble code
144 connect(fw, SIGNAL(disassemble(const QString&, int)),
145 SIGNAL(disassemble(const QString&, int)));
146 connect(fw, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
147 connect(fw, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));
149 // tab width
150 connect(this, SIGNAL(setTabWidth(int)), fw, SLOT(setTabWidth(int)));
151 fw->setTabWidth(m_tabWidth);
153 changeWindowMenu();
155 // set PC if there is one
156 emit newFileLoaded();
157 if (m_pcLine >= 0) {
158 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
161 return activateWindow(fw, lineNo, address);
164 bool WinStack::activateWindow(SourceWindow* fw, int lineNo, const DbgAddr& address)
166 int index = m_fileList.findRef(fw);
167 ASSERT(index >= 0);
168 if (index < 0) {
169 return false;
172 * If the file is not in the list of those that would appear in the
173 * window menu, move it to the first position.
175 if (index >= 9) {
176 m_fileList.remove();
177 m_fileList.insert(0, fw);
178 changeWindowMenu();
181 // make the line visible
182 if (lineNo >= 0) {
183 fw->scrollTo(lineNo, address);
186 // first resize the window, then lift it to the top
187 fw->setGeometry(0,0, width(),height());
188 fw->raise();
189 fw->show();
191 // set the focus to the new active window
192 QWidget* oldActive = m_activeWindow;
193 #if QT_VERSION < 200
194 fw->setFocusPolicy(QWidget::StrongFocus);
195 #else
196 fw->setFocusPolicy(QWidget::WheelFocus);
197 #endif
198 m_activeWindow = fw;
199 if (oldActive != 0 && oldActive != fw) {
200 // disable focus on non-active windows
201 oldActive->setFocusPolicy(QWidget::NoFocus);
203 fw->setFocus();
205 emit fileChanged();
207 return true;
210 bool WinStack::activeLine(QString& fileName, int& lineNo)
212 DbgAddr dummy;
213 return activeLine(fileName, lineNo, dummy);
216 bool WinStack::activeLine(QString& fileName, int& lineNo, DbgAddr& address)
218 if (m_activeWindow == 0) {
219 return false;
222 fileName = m_activeWindow->fileName();
223 m_activeWindow->activeLine(lineNo, address);
224 return true;
227 void WinStack::changeWindowMenu()
229 if (m_windowMenu == 0) {
230 return;
233 // delete window entries
234 while ((m_windowMenu->idAt(m_itemMore) & ~WindowMask) == WindowMore) {
235 m_windowMenu->removeItemAt(m_itemMore);
238 // insert current windows
239 QString text;
240 int index = 1;
241 SourceWindow* fw = 0;
242 for (fw = m_fileList.first(); fw != 0 && index < 10; fw = m_fileList.next()) {
243 text.sprintf("&%d ", index);
244 text += fw->fileName();
245 m_windowMenu->insertItem(text, WindowMore+index, m_itemMore+index-1);
246 index++;
248 if (fw != 0) {
249 // there are still windows
250 m_windowMenu->insertItem(m_textMore, WindowMore, m_itemMore+9);
254 void WinStack::updateLineItems(const KDebugger* dbg)
256 SourceWindow* fw = 0;
257 for (fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
258 fw->updateLineItems(dbg);
262 void WinStack::updatePC(const QString& fileName, int lineNo, const DbgAddr& address, int frameNo)
264 if (m_pcLine >= 0) {
265 setPC(false, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
267 m_pcFile = fileName;
268 m_pcLine = lineNo;
269 m_pcAddress = address.asString();
270 m_pcFrame = frameNo;
271 if (lineNo >= 0) {
272 setPC(true, fileName, lineNo, address, frameNo);
276 void WinStack::setPC(bool set, const QString& fileName, int lineNo,
277 const DbgAddr& address, int frameNo)
279 TRACE((set ? "set PC: " : "clear PC: ") + fileName +
280 QString().sprintf(":%d#%d ", lineNo, frameNo) + address.asString());
281 // find file
282 SourceWindow* fw = 0;
283 for (fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
284 if (fw->fileNameMatches(fileName)) {
285 fw->setPC(set, lineNo, address, frameNo);
286 break;
291 void WinStack::resizeEvent(QResizeEvent*)
293 ASSERT(m_activeWindow == 0 || m_fileList.findRef(m_activeWindow) >= 0);
294 if (m_activeWindow != 0) {
295 m_activeWindow->resize(width(), height());
299 void WinStack::slotFindForward()
301 if (m_activeWindow != 0)
302 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
303 SourceWindow::findForward);
306 void WinStack::slotFindBackward()
308 if (m_activeWindow != 0)
309 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
310 SourceWindow::findBackward);
313 void WinStack::maybeTip(const QPoint& p)
315 if (m_activeWindow == 0)
316 return;
318 // get the word at the point
319 QString word;
320 QRect r;
321 if (!m_activeWindow->wordAtPoint(p, word, r))
322 return;
324 // must be valid
325 assert(!word.isEmpty());
326 assert(r.isValid());
328 // remember the location
329 m_tipLocation = r;
331 emit initiateValuePopup(word);
334 void WinStack::slotShowValueTip(const QString& tipText)
336 m_valueTip.tip(m_tipLocation, tipText);
339 void WinStack::slotDisassembled(const QString& fileName, int lineNo,
340 const QList<DisassembledCode>& disass)
342 // lookup the file
343 SourceWindow* fw;
344 for (fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
345 if (fw->fileNameMatches(fileName)) {
346 break;
349 if (fw == 0) {
350 // not found: ignore
351 return;
354 fw->disassembled(lineNo, disass);
357 void WinStack::slotExpandCollapse(int)
359 // update line items after expanding or collapsing disassembled code
361 // HACK: we know that this will result in updateLineItems
362 // should be done more cleanly with a separate signal
363 emit newFileLoaded();
365 if (m_pcLine >= 0) {
366 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
371 void WinStack::slotSetTabWidth(int numChars)
373 m_tabWidth = numChars;
376 void WinStack::slotFileReload()
378 if (m_activeWindow != 0) {
379 TRACE("reloading one file");
380 m_activeWindow->reloadFile();
384 void WinStack::slotViewFind()
386 if (m_findDlg.isVisible()) {
387 m_findDlg.done(0);
388 } else {
389 m_findDlg.show();
393 void WinStack::slotBrkptSet()
395 QString file;
396 int lineNo;
397 DbgAddr address;
398 if (activeLine(file, lineNo, address))
399 emit toggleBreak(file, lineNo, address, false);
402 void WinStack::slotBrkptSetTemp()
404 QString file;
405 int lineNo;
406 DbgAddr address;
407 if (activeLine(file, lineNo, address))
408 emit toggleBreak(file, lineNo, address, true);
411 void WinStack::slotBrkptEnable()
413 QString file;
414 int lineNo;
415 DbgAddr address;
416 if (activeLine(file, lineNo, address))
417 emit enadisBreak(file, lineNo, address);
421 ValueTip::ValueTip(WinStack* parent) :
422 QToolTip(parent)
426 void ValueTip::maybeTip(const QPoint& p)
428 WinStack* w = static_cast<WinStack*>(parentWidget());
429 w->maybeTip(p);
433 class MoreWindowsDialog : public QDialog
435 public:
436 MoreWindowsDialog(QWidget* parent);
437 virtual ~MoreWindowsDialog();
439 void insertString(const char* text) { m_list.insertItem(text); }
440 void setListIndex(int i) { m_list.setCurrentItem(i); }
441 int listIndex() const { return m_list.currentItem(); }
443 protected:
444 QListBox m_list;
445 QPushButton m_buttonOK;
446 QPushButton m_buttonCancel;
447 QVBoxLayout m_layout;
448 QHBoxLayout m_buttons;
451 MoreWindowsDialog::MoreWindowsDialog(QWidget* parent) :
452 QDialog(parent, "morewindows", true),
453 m_list(this, "windows"),
454 m_buttonOK(this, "show"),
455 m_buttonCancel(this, "cancel"),
456 m_layout(this, 8),
457 m_buttons(4)
459 QString title = kapp->getCaption();
460 title += i18n(": Open Windows");
461 setCaption(title);
463 m_list.setMinimumSize(250, 100);
464 connect(&m_list, SIGNAL(selected(int)), SLOT(accept()));
466 m_buttonOK.setMinimumSize(100, 30);
467 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
468 m_buttonOK.setText(i18n("Show"));
469 m_buttonOK.setDefault(true);
471 m_buttonCancel.setMinimumSize(100, 30);
472 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
473 m_buttonCancel.setText(i18n("Cancel"));
475 m_layout.addWidget(&m_list, 10);
476 m_layout.addLayout(&m_buttons);
477 m_buttons.addStretch(10);
478 m_buttons.addWidget(&m_buttonOK);
479 m_buttons.addSpacing(40);
480 m_buttons.addWidget(&m_buttonCancel);
481 m_buttons.addStretch(10);
483 m_layout.activate();
485 m_list.setFocus();
486 resize(320, 320);
489 MoreWindowsDialog::~MoreWindowsDialog()
493 void WinStack::selectWindow(int id)
495 // react only on menu entries concerning windows
496 if ((id & ~WindowMask) != WindowMore) {
497 return;
500 id &= WindowMask;
502 int index = 0;
504 if (id == 0) {
505 // more windows selected: show windows in a list
506 MoreWindowsDialog dlg(this);
507 int i = 0;
508 for (SourceWindow* fw = m_fileList.first(); fw != 0; fw = m_fileList.next()) {
509 dlg.insertString(fw->fileName());
510 if (m_activeWindow == fw) {
511 index = i;
513 i++;
515 dlg.setListIndex(index);
516 if (dlg.exec() == QDialog::Rejected)
517 return;
518 index = dlg.listIndex();
519 } else {
520 index = (id & WindowMask)-1;
523 SourceWindow* fw = m_fileList.first();
524 for (; index > 0; index--) {
525 fw = m_fileList.next();
527 ASSERT(fw != 0);
529 activateWindow(fw, -1, DbgAddr());
533 FindDialog::FindDialog() :
534 QDialog(0, "find", false),
535 m_searchText(this, "text"),
536 m_caseCheck(this, "case"),
537 m_buttonForward(this, "forward"),
538 m_buttonBackward(this, "backward"),
539 m_buttonClose(this, "close"),
540 m_layout(this, 8),
541 m_buttons(4)
543 setCaption(QString(kapp->getCaption()) + i18n(": Search"));
545 m_searchText.setMinimumSize(330, 24);
546 m_searchText.setMaxLength(10000);
547 m_searchText.setFrame(true);
549 m_caseCheck.setText(i18n("&Case sensitive"));
550 m_caseCheck.setChecked(true);
551 m_buttonForward.setText(i18n("&Forward"));
552 m_buttonForward.setDefault(true);
553 m_buttonBackward.setText(i18n("&Backward"));
554 m_buttonClose.setText(i18n("Close"));
556 m_caseCheck.setMinimumSize(330, 24);
558 // get maximum size of buttons
559 QSize maxSize(80,30);
560 #if QT_VERSION >= 140
561 maxSize.expandedTo(m_buttonForward.sizeHint());
562 maxSize.expandedTo(m_buttonBackward.sizeHint());
563 maxSize.expandedTo(m_buttonClose.sizeHint());
564 #endif
566 m_buttonForward.setMinimumSize(maxSize);
567 m_buttonBackward.setMinimumSize(maxSize);
568 m_buttonClose.setMinimumSize(maxSize);
570 connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));
572 m_layout.addWidget(&m_searchText);
573 m_layout.addWidget(&m_caseCheck);
574 m_layout.addLayout(&m_buttons);
575 m_layout.addStretch(10);
576 m_buttons.addWidget(&m_buttonForward);
577 m_buttons.addStretch(10);
578 m_buttons.addWidget(&m_buttonBackward);
579 m_buttons.addStretch(10);
580 m_buttons.addWidget(&m_buttonClose);
582 m_layout.activate();
584 m_searchText.setFocus();
585 resize( 350, 120 );
588 FindDialog::~FindDialog()
592 void FindDialog::closeEvent(QCloseEvent* ev)
594 QDialog::closeEvent(ev);
595 emit closed();
598 void FindDialog::done(int result)
600 QDialog::done(result);
601 emit closed();
604 #include "winstack.moc"