Don't check for -Wbad-function-cast, because g++ 3.3 doesn't like it.
[kdbg.git] / kdbg / winstack.cpp
blob386c784baf79799058d60dcd5a374a9161f6fe9b
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);
408 void WinStack::slotMoveProgramCounter()
410 QString file;
411 int lineNo;
412 DbgAddr address;
413 if (activeLine(file, lineNo, address))
414 emit moveProgramCounter(file, lineNo, address);
418 ValueTip::ValueTip(WinStack* parent) :
419 QToolTip(parent)
423 void ValueTip::maybeTip(const QPoint& p)
425 WinStack* w = static_cast<WinStack*>(parentWidget());
426 w->maybeTip(p);
430 class MoreWindowsDialog : public QDialog
432 public:
433 MoreWindowsDialog(QWidget* parent);
434 virtual ~MoreWindowsDialog();
436 void insertString(const char* text) { m_list.insertItem(text); }
437 void setListIndex(int i) { m_list.setCurrentItem(i); }
438 int listIndex() const { return m_list.currentItem(); }
440 protected:
441 QListBox m_list;
442 QPushButton m_buttonOK;
443 QPushButton m_buttonCancel;
444 QVBoxLayout m_layout;
445 QHBoxLayout m_buttons;
448 MoreWindowsDialog::MoreWindowsDialog(QWidget* parent) :
449 QDialog(parent, "morewindows", true),
450 m_list(this, "windows"),
451 m_buttonOK(this, "show"),
452 m_buttonCancel(this, "cancel"),
453 m_layout(this, 8),
454 m_buttons(4)
456 QString title = kapp->caption();
457 title += i18n(": Open Windows");
458 setCaption(title);
460 m_list.setMinimumSize(250, 100);
461 connect(&m_list, SIGNAL(selected(int)), SLOT(accept()));
463 m_buttonOK.setMinimumSize(100, 30);
464 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
465 m_buttonOK.setText(i18n("Show"));
466 m_buttonOK.setDefault(true);
468 m_buttonCancel.setMinimumSize(100, 30);
469 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
470 m_buttonCancel.setText(i18n("Cancel"));
472 m_layout.addWidget(&m_list, 10);
473 m_layout.addLayout(&m_buttons);
474 m_buttons.addStretch(10);
475 m_buttons.addWidget(&m_buttonOK);
476 m_buttons.addSpacing(40);
477 m_buttons.addWidget(&m_buttonCancel);
478 m_buttons.addStretch(10);
480 m_layout.activate();
482 m_list.setFocus();
483 resize(320, 320);
486 MoreWindowsDialog::~MoreWindowsDialog()
490 void WinStack::selectWindow(int id)
492 // react only on menu entries concerning windows
493 if ((id & ~WindowMask) != WindowMore) {
494 return;
497 id &= WindowMask;
499 int index = 0;
501 if (id == 0) {
502 // more windows selected: show windows in a list
503 MoreWindowsDialog dlg(this);
504 for (int i = 0; i < m_fileList.size(); i++)
506 dlg.insertString(m_fileList[i]->fileName());
507 if (m_activeWindow == m_fileList[i]) {
508 index = i;
511 dlg.setListIndex(index);
512 if (dlg.exec() == QDialog::Rejected)
513 return;
514 index = dlg.listIndex();
515 } else {
516 index = (id & WindowMask)-1;
519 SourceWindow* fw = m_fileList[index];
520 ASSERT(fw != 0);
522 activateWindow(fw, -1, DbgAddr());
526 FindDialog::FindDialog() :
527 QDialog(0, "find", false),
528 m_searchText(this, "text"),
529 m_caseCheck(this, "case"),
530 m_buttonForward(this, "forward"),
531 m_buttonBackward(this, "backward"),
532 m_buttonClose(this, "close"),
533 m_layout(this, 8),
534 m_buttons(4)
536 setCaption(QString(kapp->caption()) + i18n(": Search"));
538 m_searchText.setMinimumSize(330, 24);
539 m_searchText.setMaxLength(10000);
540 m_searchText.setFrame(true);
542 m_caseCheck.setText(i18n("&Case sensitive"));
543 m_caseCheck.setChecked(true);
544 m_buttonForward.setText(i18n("&Forward"));
545 m_buttonForward.setDefault(true);
546 m_buttonBackward.setText(i18n("&Backward"));
547 m_buttonClose.setText(i18n("Close"));
549 m_caseCheck.setMinimumSize(330, 24);
551 // get maximum size of buttons
552 QSize maxSize(80,30);
553 maxSize.expandedTo(m_buttonForward.sizeHint());
554 maxSize.expandedTo(m_buttonBackward.sizeHint());
555 maxSize.expandedTo(m_buttonClose.sizeHint());
557 m_buttonForward.setMinimumSize(maxSize);
558 m_buttonBackward.setMinimumSize(maxSize);
559 m_buttonClose.setMinimumSize(maxSize);
561 connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));
563 m_layout.addWidget(&m_searchText);
564 m_layout.addWidget(&m_caseCheck);
565 m_layout.addLayout(&m_buttons);
566 m_layout.addStretch(10);
567 m_buttons.addWidget(&m_buttonForward);
568 m_buttons.addStretch(10);
569 m_buttons.addWidget(&m_buttonBackward);
570 m_buttons.addStretch(10);
571 m_buttons.addWidget(&m_buttonClose);
573 m_layout.activate();
575 m_searchText.setFocus();
576 resize( 350, 120 );
579 FindDialog::~FindDialog()
583 void FindDialog::closeEvent(QCloseEvent* ev)
585 QDialog::closeEvent(ev);
586 emit closed();
589 void FindDialog::done(int result)
591 QDialog::done(result);
592 emit closed();
595 #include "winstack.moc"