Latest updates from Keith for xsldbg 3.0.5.
[kdbg.git] / kdbg / winstack.cpp
blob97eada6e8844762460bd6b49ab7a37ee7fdba213
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 #include <klocale.h> /* i18n */
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16 #include "mydebug.h"
20 WinStack::WinStack(QWidget* parent, const char* name) :
21 QWidget(parent, name),
22 m_activeWindow(0),
23 m_windowMenu(0),
24 m_pcLine(-1),
25 m_valueTip(this),
26 m_tipLocation(1,1,10,10),
27 m_tabWidth(0)
29 connect(&m_findDlg.m_buttonForward,
30 SIGNAL(clicked()), SLOT(slotFindForward()));
31 connect(&m_findDlg.m_buttonBackward,
32 SIGNAL(clicked()), SLOT(slotFindBackward()));
34 connect(this, SIGNAL(setTabWidth(int)), this, SLOT(slotSetTabWidth(int)));
37 WinStack::~WinStack()
41 void WinStack::setWindowMenu(QPopupMenu* menu)
43 m_windowMenu = menu;
44 if (menu == 0) {
45 return;
48 // hook up for menu activations
49 connect(menu, SIGNAL(activated(int)), this, SLOT(selectWindow(int)));
52 void WinStack::mousePressEvent(QMouseEvent* mouseEvent)
54 // Check if right button was clicked.
55 if (mouseEvent->button() == RightButton)
57 emit clickedRight(mouseEvent->pos());
58 } else {
59 QWidget::mousePressEvent(mouseEvent);
64 void WinStack::reloadAllFiles()
66 for (int i = 0; i < m_fileList.size(); i++) {
67 m_fileList[i]->reloadFile();
71 void WinStack::activate(const QString& fileName, int lineNo, const DbgAddr& address)
73 QFileInfo fi(fileName);
75 if (!fi.isFile()) {
77 * We didn't find that file. Now check if it is a relative path and
78 * try m_lastOpenDir as prefix.
80 TRACE(fi.filePath() + (" not found, looking in " + m_lastOpenDir));
81 if (!fi.isRelative() || m_lastOpenDir.isEmpty()) {
82 return;
84 fi.setFile(m_lastOpenDir + "/" + fi.filePath());
85 if (!fi.isFile()) {
86 return;
89 // if this is not an absolute path name, make it one
90 activatePath(fi.absFilePath(), lineNo, address);
93 void WinStack::activateFile(const QString& fileName)
95 activatePath(fileName, 0, DbgAddr());
98 bool WinStack::activatePath(QString pathName, int lineNo, const DbgAddr& address)
100 // check whether the file is already open
101 SourceWindow* fw = 0;
102 for (int i = 0; i < m_fileList.size(); i++) {
103 if (m_fileList[i]->fileName() == pathName) {
104 fw = m_fileList[i];
105 break;
108 if (fw == 0) {
109 // not found, load it
110 fw = new SourceWindow(pathName, this, "fileWindow");
112 // slurp the file in
113 if (!fw->loadFile()) {
114 // read failed
115 delete fw;
116 return false;
119 m_fileList.insertAt(0, fw);
120 connect(fw, SIGNAL(lineChanged()),SIGNAL(lineChanged()));
121 connect(fw, SIGNAL(clickedLeft(const QString&,int,const DbgAddr&,bool)),
122 SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)));
123 connect(fw, SIGNAL(clickedMid(const QString&,int,const DbgAddr&)),
124 SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)));
126 // Comunication when right button is clicked.
127 connect(fw, SIGNAL(clickedRight(const QPoint &)),
128 SIGNAL(filesRightClick(const QPoint &)));
130 // disassemble code
131 connect(fw, SIGNAL(disassemble(const QString&, int)),
132 SIGNAL(disassemble(const QString&, int)));
133 connect(fw, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
134 connect(fw, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));
136 // tab width
137 connect(this, SIGNAL(setTabWidth(int)), fw, SLOT(setTabWidth(int)));
138 fw->setTabWidth(m_tabWidth);
140 changeWindowMenu();
142 // set PC if there is one
143 emit newFileLoaded();
144 if (m_pcLine >= 0) {
145 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
148 return activateWindow(fw, lineNo, address);
151 bool WinStack::activateWindow(SourceWindow* fw, int lineNo, const DbgAddr& address)
153 // lookup fw
154 int index = m_fileList.size()-1;
155 while (index >= 0 && m_fileList[index] != fw)
156 --index;
157 ASSERT(index >= 0);
158 if (index < 0) {
159 return false;
162 * If the file is not in the list of those that would appear in the
163 * window menu, move it to the first position.
165 if (index >= 9) {
166 m_fileList.removeAt(index);
167 m_fileList.insertAt(0, fw);
168 changeWindowMenu();
171 // make the line visible
172 if (lineNo >= 0) {
173 fw->scrollTo(lineNo, address);
176 // first resize the window, then lift it to the top
177 fw->setGeometry(0,0, width(),height());
178 fw->raise();
179 fw->show();
181 // set the focus to the new active window
182 QWidget* oldActive = m_activeWindow;
183 fw->setFocusPolicy(QWidget::WheelFocus);
184 m_activeWindow = fw;
185 if (oldActive != 0 && oldActive != fw) {
186 // disable focus on non-active windows
187 oldActive->setFocusPolicy(QWidget::NoFocus);
189 fw->setFocus();
191 emit fileChanged();
193 return true;
196 bool WinStack::activeLine(QString& fileName, int& lineNo)
198 DbgAddr dummy;
199 return activeLine(fileName, lineNo, dummy);
202 bool WinStack::activeLine(QString& fileName, int& lineNo, DbgAddr& address)
204 if (m_activeWindow == 0) {
205 return false;
208 fileName = m_activeWindow->fileName();
209 m_activeWindow->activeLine(lineNo, address);
210 return true;
213 void WinStack::changeWindowMenu()
215 if (m_windowMenu == 0) {
216 return;
219 const int N = 9;
220 // Delete entries at most the N window entries that we insert below.
221 // When we get here if the More entry was selected, we must make sure
222 // that we don't delete it (or we crash).
223 bool haveMore = m_windowMenu->count() > uint(N);
224 int k = haveMore ? N : m_windowMenu->count();
226 for (int i = 0; i < k; i++) {
227 m_windowMenu->removeItemAt(0);
230 // insert current windows
231 QString text;
232 for (int i = 0; i < m_fileList.size() && i < N; i++) {
233 text.sprintf("&%d ", i+1);
234 text += m_fileList[i]->fileName();
235 m_windowMenu->insertItem(text, WindowMore+i+1, i);
237 // add More entry if we have none yet
238 if (!haveMore && m_fileList.size() > N) {
239 m_windowMenu->insertItem(i18n("&More..."), WindowMore, N);
243 void WinStack::updateLineItems(const KDebugger* dbg)
245 for (int i = 0; i < m_fileList.size(); i++) {
246 m_fileList[i]->updateLineItems(dbg);
250 void WinStack::updatePC(const QString& fileName, int lineNo, const DbgAddr& address, int frameNo)
252 if (m_pcLine >= 0) {
253 setPC(false, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
255 m_pcFile = fileName;
256 m_pcLine = lineNo;
257 m_pcAddress = address.asString();
258 m_pcFrame = frameNo;
259 if (lineNo >= 0) {
260 setPC(true, fileName, lineNo, address, frameNo);
264 void WinStack::setPC(bool set, const QString& fileName, int lineNo,
265 const DbgAddr& address, int frameNo)
267 TRACE((set ? "set PC: " : "clear PC: ") + fileName +
268 QString().sprintf(":%d#%d ", lineNo, frameNo) + address.asString());
269 // find file
270 for (int i = 0; i < m_fileList.size(); i++) {
271 if (m_fileList[i]->fileNameMatches(fileName)) {
272 m_fileList[i]->setPC(set, lineNo, address, frameNo);
273 break;
278 void WinStack::resizeEvent(QResizeEvent*)
280 ASSERT(m_activeWindow == 0);
281 if (m_activeWindow != 0) {
282 m_activeWindow->resize(width(), height());
286 void WinStack::slotFindForward()
288 if (m_activeWindow != 0)
289 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
290 SourceWindow::findForward);
293 void WinStack::slotFindBackward()
295 if (m_activeWindow != 0)
296 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
297 SourceWindow::findBackward);
300 void WinStack::maybeTip(const QPoint& p)
302 if (m_activeWindow == 0)
303 return;
305 // get the word at the point
306 QString word;
307 QRect r;
308 if (!m_activeWindow->wordAtPoint(p, word, r))
309 return;
311 // must be valid
312 assert(!word.isEmpty());
313 assert(r.isValid());
315 // remember the location
316 m_tipLocation = r;
318 emit initiateValuePopup(word);
321 void WinStack::slotShowValueTip(const QString& tipText)
323 m_valueTip.tip(m_tipLocation, tipText);
326 void WinStack::slotDisassembled(const QString& fileName, int lineNo,
327 const QList<DisassembledCode>& disass)
329 // lookup the file
330 SourceWindow* fw = 0;
331 for (int i = 0; i < m_fileList.size(); i++) {
332 if (m_fileList[i]->fileNameMatches(fileName)) {
333 fw = m_fileList[i];
334 break;
337 if (fw == 0) {
338 // not found: ignore
339 return;
342 fw->disassembled(lineNo, disass);
345 void WinStack::slotExpandCollapse(int)
347 // update line items after expanding or collapsing disassembled code
349 // HACK: we know that this will result in updateLineItems
350 // should be done more cleanly with a separate signal
351 emit newFileLoaded();
353 if (m_pcLine >= 0) {
354 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
359 void WinStack::slotSetTabWidth(int numChars)
361 m_tabWidth = numChars;
364 void WinStack::slotFileReload()
366 if (m_activeWindow != 0) {
367 TRACE("reloading one file");
368 m_activeWindow->reloadFile();
372 void WinStack::slotViewFind()
374 if (m_findDlg.isVisible()) {
375 m_findDlg.done(0);
376 } else {
377 m_findDlg.show();
381 void WinStack::slotBrkptSet()
383 QString file;
384 int lineNo;
385 DbgAddr address;
386 if (activeLine(file, lineNo, address))
387 emit toggleBreak(file, lineNo, address, false);
390 void WinStack::slotBrkptSetTemp()
392 QString file;
393 int lineNo;
394 DbgAddr address;
395 if (activeLine(file, lineNo, address))
396 emit toggleBreak(file, lineNo, address, true);
399 void WinStack::slotBrkptEnable()
401 QString file;
402 int lineNo;
403 DbgAddr address;
404 if (activeLine(file, lineNo, address))
405 emit enadisBreak(file, lineNo, address);
409 ValueTip::ValueTip(WinStack* parent) :
410 QToolTip(parent)
414 void ValueTip::maybeTip(const QPoint& p)
416 WinStack* w = static_cast<WinStack*>(parentWidget());
417 w->maybeTip(p);
421 class MoreWindowsDialog : public QDialog
423 public:
424 MoreWindowsDialog(QWidget* parent);
425 virtual ~MoreWindowsDialog();
427 void insertString(const char* text) { m_list.insertItem(text); }
428 void setListIndex(int i) { m_list.setCurrentItem(i); }
429 int listIndex() const { return m_list.currentItem(); }
431 protected:
432 QListBox m_list;
433 QPushButton m_buttonOK;
434 QPushButton m_buttonCancel;
435 QVBoxLayout m_layout;
436 QHBoxLayout m_buttons;
439 MoreWindowsDialog::MoreWindowsDialog(QWidget* parent) :
440 QDialog(parent, "morewindows", true),
441 m_list(this, "windows"),
442 m_buttonOK(this, "show"),
443 m_buttonCancel(this, "cancel"),
444 m_layout(this, 8),
445 m_buttons(4)
447 QString title = kapp->caption();
448 title += i18n(": Open Windows");
449 setCaption(title);
451 m_list.setMinimumSize(250, 100);
452 connect(&m_list, SIGNAL(selected(int)), SLOT(accept()));
454 m_buttonOK.setMinimumSize(100, 30);
455 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
456 m_buttonOK.setText(i18n("Show"));
457 m_buttonOK.setDefault(true);
459 m_buttonCancel.setMinimumSize(100, 30);
460 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
461 m_buttonCancel.setText(i18n("Cancel"));
463 m_layout.addWidget(&m_list, 10);
464 m_layout.addLayout(&m_buttons);
465 m_buttons.addStretch(10);
466 m_buttons.addWidget(&m_buttonOK);
467 m_buttons.addSpacing(40);
468 m_buttons.addWidget(&m_buttonCancel);
469 m_buttons.addStretch(10);
471 m_layout.activate();
473 m_list.setFocus();
474 resize(320, 320);
477 MoreWindowsDialog::~MoreWindowsDialog()
481 void WinStack::selectWindow(int id)
483 // react only on menu entries concerning windows
484 if ((id & ~WindowMask) != WindowMore) {
485 return;
488 id &= WindowMask;
490 int index = 0;
492 if (id == 0) {
493 // more windows selected: show windows in a list
494 MoreWindowsDialog dlg(this);
495 for (int i = 0; i < m_fileList.size(); i++)
497 dlg.insertString(m_fileList[i]->fileName());
498 if (m_activeWindow == m_fileList[i]) {
499 index = i;
502 dlg.setListIndex(index);
503 if (dlg.exec() == QDialog::Rejected)
504 return;
505 index = dlg.listIndex();
506 } else {
507 index = (id & WindowMask)-1;
510 SourceWindow* fw = m_fileList[index];
511 ASSERT(fw != 0);
513 activateWindow(fw, -1, DbgAddr());
517 FindDialog::FindDialog() :
518 QDialog(0, "find", false),
519 m_searchText(this, "text"),
520 m_caseCheck(this, "case"),
521 m_buttonForward(this, "forward"),
522 m_buttonBackward(this, "backward"),
523 m_buttonClose(this, "close"),
524 m_layout(this, 8),
525 m_buttons(4)
527 setCaption(QString(kapp->caption()) + i18n(": Search"));
529 m_searchText.setMinimumSize(330, 24);
530 m_searchText.setMaxLength(10000);
531 m_searchText.setFrame(true);
533 m_caseCheck.setText(i18n("&Case sensitive"));
534 m_caseCheck.setChecked(true);
535 m_buttonForward.setText(i18n("&Forward"));
536 m_buttonForward.setDefault(true);
537 m_buttonBackward.setText(i18n("&Backward"));
538 m_buttonClose.setText(i18n("Close"));
540 m_caseCheck.setMinimumSize(330, 24);
542 // get maximum size of buttons
543 QSize maxSize(80,30);
544 maxSize.expandedTo(m_buttonForward.sizeHint());
545 maxSize.expandedTo(m_buttonBackward.sizeHint());
546 maxSize.expandedTo(m_buttonClose.sizeHint());
548 m_buttonForward.setMinimumSize(maxSize);
549 m_buttonBackward.setMinimumSize(maxSize);
550 m_buttonClose.setMinimumSize(maxSize);
552 connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));
554 m_layout.addWidget(&m_searchText);
555 m_layout.addWidget(&m_caseCheck);
556 m_layout.addLayout(&m_buttons);
557 m_layout.addStretch(10);
558 m_buttons.addWidget(&m_buttonForward);
559 m_buttons.addStretch(10);
560 m_buttons.addWidget(&m_buttonBackward);
561 m_buttons.addStretch(10);
562 m_buttons.addWidget(&m_buttonClose);
564 m_layout.activate();
566 m_searchText.setFocus();
567 resize( 350, 120 );
570 FindDialog::~FindDialog()
574 void FindDialog::closeEvent(QCloseEvent* ev)
576 QDialog::closeEvent(ev);
577 emit closed();
580 void FindDialog::done(int result)
582 QDialog::done(result);
583 emit closed();
586 #include "winstack.moc"