Implemented the animated button using a KAnimWidget.
[kdbg.git] / kdbg / winstack.cpp
blob21f18b06a0e24bac15ed7667ff21f48fc26041e6
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 if (m_activeWindow != 0) {
281 m_activeWindow->resize(width(), height());
285 void WinStack::slotFindForward()
287 if (m_activeWindow != 0)
288 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
289 SourceWindow::findForward);
292 void WinStack::slotFindBackward()
294 if (m_activeWindow != 0)
295 m_activeWindow->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
296 SourceWindow::findBackward);
299 void WinStack::maybeTip(const QPoint& p)
301 if (m_activeWindow == 0)
302 return;
304 // get the word at the point
305 QString word;
306 QRect r;
307 if (!m_activeWindow->wordAtPoint(p, word, r))
308 return;
310 // must be valid
311 assert(!word.isEmpty());
312 assert(r.isValid());
314 // remember the location
315 m_tipLocation = r;
317 emit initiateValuePopup(word);
320 void WinStack::slotShowValueTip(const QString& tipText)
322 m_valueTip.tip(m_tipLocation, tipText);
325 void WinStack::slotDisassembled(const QString& fileName, int lineNo,
326 const QList<DisassembledCode>& disass)
328 // lookup the file
329 SourceWindow* fw = 0;
330 for (int i = 0; i < m_fileList.size(); i++) {
331 if (m_fileList[i]->fileNameMatches(fileName)) {
332 fw = m_fileList[i];
333 break;
336 if (fw == 0) {
337 // not found: ignore
338 return;
341 fw->disassembled(lineNo, disass);
344 void WinStack::slotExpandCollapse(int)
346 // update line items after expanding or collapsing disassembled code
348 // HACK: we know that this will result in updateLineItems
349 // should be done more cleanly with a separate signal
350 emit newFileLoaded();
352 if (m_pcLine >= 0) {
353 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
358 void WinStack::slotSetTabWidth(int numChars)
360 m_tabWidth = numChars;
363 void WinStack::slotFileReload()
365 if (m_activeWindow != 0) {
366 TRACE("reloading one file");
367 m_activeWindow->reloadFile();
371 void WinStack::slotViewFind()
373 if (m_findDlg.isVisible()) {
374 m_findDlg.done(0);
375 } else {
376 m_findDlg.show();
380 void WinStack::slotBrkptSet()
382 QString file;
383 int lineNo;
384 DbgAddr address;
385 if (activeLine(file, lineNo, address))
386 emit toggleBreak(file, lineNo, address, false);
389 void WinStack::slotBrkptSetTemp()
391 QString file;
392 int lineNo;
393 DbgAddr address;
394 if (activeLine(file, lineNo, address))
395 emit toggleBreak(file, lineNo, address, true);
398 void WinStack::slotBrkptEnable()
400 QString file;
401 int lineNo;
402 DbgAddr address;
403 if (activeLine(file, lineNo, address))
404 emit enadisBreak(file, lineNo, address);
407 void WinStack::slotMoveProgramCounter()
409 QString file;
410 int lineNo;
411 DbgAddr address;
412 if (activeLine(file, lineNo, address))
413 emit moveProgramCounter(file, lineNo, address);
417 ValueTip::ValueTip(WinStack* parent) :
418 QToolTip(parent)
422 void ValueTip::maybeTip(const QPoint& p)
424 WinStack* w = static_cast<WinStack*>(parentWidget());
425 w->maybeTip(p);
429 class MoreWindowsDialog : public QDialog
431 public:
432 MoreWindowsDialog(QWidget* parent);
433 virtual ~MoreWindowsDialog();
435 void insertString(const char* text) { m_list.insertItem(text); }
436 void setListIndex(int i) { m_list.setCurrentItem(i); }
437 int listIndex() const { return m_list.currentItem(); }
439 protected:
440 QListBox m_list;
441 QPushButton m_buttonOK;
442 QPushButton m_buttonCancel;
443 QVBoxLayout m_layout;
444 QHBoxLayout m_buttons;
447 MoreWindowsDialog::MoreWindowsDialog(QWidget* parent) :
448 QDialog(parent, "morewindows", true),
449 m_list(this, "windows"),
450 m_buttonOK(this, "show"),
451 m_buttonCancel(this, "cancel"),
452 m_layout(this, 8),
453 m_buttons(4)
455 QString title = kapp->caption();
456 title += i18n(": Open Windows");
457 setCaption(title);
459 m_list.setMinimumSize(250, 100);
460 connect(&m_list, SIGNAL(selected(int)), SLOT(accept()));
462 m_buttonOK.setMinimumSize(100, 30);
463 connect(&m_buttonOK, SIGNAL(clicked()), SLOT(accept()));
464 m_buttonOK.setText(i18n("Show"));
465 m_buttonOK.setDefault(true);
467 m_buttonCancel.setMinimumSize(100, 30);
468 connect(&m_buttonCancel, SIGNAL(clicked()), SLOT(reject()));
469 m_buttonCancel.setText(i18n("Cancel"));
471 m_layout.addWidget(&m_list, 10);
472 m_layout.addLayout(&m_buttons);
473 m_buttons.addStretch(10);
474 m_buttons.addWidget(&m_buttonOK);
475 m_buttons.addSpacing(40);
476 m_buttons.addWidget(&m_buttonCancel);
477 m_buttons.addStretch(10);
479 m_layout.activate();
481 m_list.setFocus();
482 resize(320, 320);
485 MoreWindowsDialog::~MoreWindowsDialog()
489 void WinStack::selectWindow(int id)
491 // react only on menu entries concerning windows
492 if ((id & ~WindowMask) != WindowMore) {
493 return;
496 id &= WindowMask;
498 int index = 0;
500 if (id == 0) {
501 // more windows selected: show windows in a list
502 MoreWindowsDialog dlg(this);
503 for (int i = 0; i < m_fileList.size(); i++)
505 dlg.insertString(m_fileList[i]->fileName());
506 if (m_activeWindow == m_fileList[i]) {
507 index = i;
510 dlg.setListIndex(index);
511 if (dlg.exec() == QDialog::Rejected)
512 return;
513 index = dlg.listIndex();
514 } else {
515 index = (id & WindowMask)-1;
518 SourceWindow* fw = m_fileList[index];
519 ASSERT(fw != 0);
521 activateWindow(fw, -1, DbgAddr());
525 FindDialog::FindDialog() :
526 QDialog(0, "find", false),
527 m_searchText(this, "text"),
528 m_caseCheck(this, "case"),
529 m_buttonForward(this, "forward"),
530 m_buttonBackward(this, "backward"),
531 m_buttonClose(this, "close"),
532 m_layout(this, 8),
533 m_buttons(4)
535 setCaption(QString(kapp->caption()) + i18n(": Search"));
537 m_searchText.setMinimumSize(330, 24);
538 m_searchText.setMaxLength(10000);
539 m_searchText.setFrame(true);
541 m_caseCheck.setText(i18n("&Case sensitive"));
542 m_caseCheck.setChecked(true);
543 m_buttonForward.setText(i18n("&Forward"));
544 m_buttonForward.setDefault(true);
545 m_buttonBackward.setText(i18n("&Backward"));
546 m_buttonClose.setText(i18n("Close"));
548 m_caseCheck.setMinimumSize(330, 24);
550 // get maximum size of buttons
551 QSize maxSize(80,30);
552 maxSize.expandedTo(m_buttonForward.sizeHint());
553 maxSize.expandedTo(m_buttonBackward.sizeHint());
554 maxSize.expandedTo(m_buttonClose.sizeHint());
556 m_buttonForward.setMinimumSize(maxSize);
557 m_buttonBackward.setMinimumSize(maxSize);
558 m_buttonClose.setMinimumSize(maxSize);
560 connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));
562 m_layout.addWidget(&m_searchText);
563 m_layout.addWidget(&m_caseCheck);
564 m_layout.addLayout(&m_buttons);
565 m_layout.addStretch(10);
566 m_buttons.addWidget(&m_buttonForward);
567 m_buttons.addStretch(10);
568 m_buttons.addWidget(&m_buttonBackward);
569 m_buttons.addStretch(10);
570 m_buttons.addWidget(&m_buttonClose);
572 m_layout.activate();
574 m_searchText.setFocus();
575 resize( 350, 120 );
578 FindDialog::~FindDialog()
582 void FindDialog::closeEvent(QCloseEvent* ev)
584 QDialog::closeEvent(ev);
585 emit closed();
588 void FindDialog::done(int result)
590 QDialog::done(result);
591 emit closed();
594 #include "winstack.moc"