3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
7 #include "commandids.h"
10 #include <qfileinfo.h>
14 #include <klocale.h> /* i18n */
25 WinStack::WinStack(QWidget
* parent
, const char* name
) :
26 QWidget(parent
, name
),
32 m_tipLocation(1,1,10,10),
35 // Call menu implementation helper
38 connect(&m_findDlg
.m_buttonForward
,
39 SIGNAL(clicked()), SLOT(slotFindForward()));
40 connect(&m_findDlg
.m_buttonBackward
,
41 SIGNAL(clicked()), SLOT(slotFindBackward()));
43 connect(this, SIGNAL(setTabWidth(int)), this, SLOT(slotSetTabWidth(int)));
45 // Check for right click event.
46 connect(this, SIGNAL(clickedRight(const QPoint
&)),
47 SLOT(slotWidgetRightClick(const QPoint
&)));
54 // All menu initializations.
55 void WinStack::initMenu()
57 // Init float popup menu.
58 m_menuFloat
.insertItem(i18n("&Open Source..."), ID_FILE_OPEN
);
59 m_menuFloat
.insertSeparator();
60 m_menuFloat
.insertItem(i18n("Step &into"), ID_PROGRAM_STEP
);
61 m_menuFloat
.insertItem(i18n("Step &over"), ID_PROGRAM_NEXT
);
62 m_menuFloat
.insertItem(i18n("Step o&ut"), ID_PROGRAM_FINISH
);
63 m_menuFloat
.insertItem(i18n("Run to &cursor"), ID_PROGRAM_UNTIL
);
64 m_menuFloat
.insertSeparator();
65 m_menuFloat
.insertItem(i18n("Set/Clear &breakpoint"), ID_BRKPT_SET
);
67 // Init float file popup.
68 m_menuFileFloat
.insertItem(i18n("&Open Source..."), ID_FILE_OPEN
);
69 m_menuFileFloat
.insertSeparator();
70 m_menuFileFloat
.insertItem(i18n("&Executable..."), ID_FILE_EXECUTABLE
);
71 m_menuFileFloat
.insertItem(i18n("&Core dump..."), ID_FILE_COREFILE
);
74 void WinStack::setWindowMenu(QPopupMenu
* menu
)
82 m_itemMore
= menu
->indexOf(ID_WINDOW_MORE
);
83 // must contain item More...
84 ASSERT(m_itemMore
>= 0);
86 m_textMore
= menu
->text(ID_WINDOW_MORE
);
87 menu
->removeItemAt(m_itemMore
);
90 void WinStack::menuCallback(int item
)
92 TRACE("menu item=" + QString().setNum(item
));
94 if ((item
& ~ID_WINDOW_INDEX_MASK
) == ID_WINDOW_MORE
) {
95 selectWindow(item
& ID_WINDOW_INDEX_MASK
);
101 if (m_activeWindow
!= 0) {
102 TRACE("reloading one file");
103 m_activeWindow
->reloadFile();
106 case ID_VIEW_FINDDLG
:
107 if (m_findDlg
.isVisible()) {
118 if (activeLine(file
, lineNo
, address
))
119 emit
toggleBreak(file
, lineNo
, address
, item
== ID_BRKPT_TEMP
);
122 case ID_BRKPT_ENABLE
:
127 if (activeLine(file
, lineNo
, address
))
128 emit
enadisBreak(file
, lineNo
, address
);
134 void WinStack::mousePressEvent(QMouseEvent
* mouseEvent
)
136 // Check if right button was clicked.
137 if (mouseEvent
->button() == RightButton
)
139 emit
clickedRight(mouseEvent
->pos());
141 QWidget::mousePressEvent(mouseEvent
);
146 void WinStack::reloadAllFiles()
149 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
154 void WinStack::activate(const QString
& fileName
, int lineNo
, const DbgAddr
& address
)
156 QFileInfo
fi(fileName
);
160 * We didn't find that file. Now check if it is a relative path and
161 * try m_lastOpenDir as prefix.
163 TRACE(fi
.filePath() + (" not found, looking in " + m_lastOpenDir
));
164 if (!fi
.isRelative() || m_lastOpenDir
.isEmpty()) {
167 fi
.setFile(m_lastOpenDir
+ "/" + fi
.filePath());
172 // if this is not an absolute path name, make it one
173 activatePath(fi
.absFilePath(), lineNo
, address
);
176 void WinStack::activateFile(const QString
& fileName
)
178 activatePath(fileName
, 0, DbgAddr());
181 bool WinStack::activatePath(QString pathName
, int lineNo
, const DbgAddr
& address
)
183 // check whether the file is already open
185 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
186 if (fw
->fileName() == pathName
) {
191 // not found, load it
192 fw
= new SourceWindow(pathName
, this, "fileWindow");
193 m_fileList
.insert(0, fw
);
194 connect(fw
, SIGNAL(lineChanged()),SIGNAL(lineChanged()));
195 connect(fw
, SIGNAL(clickedLeft(const QString
&,int,const DbgAddr
&,bool)),
196 SIGNAL(toggleBreak(const QString
&,int,const DbgAddr
&,bool)));
197 connect(fw
, SIGNAL(clickedMid(const QString
&,int,const DbgAddr
&)),
198 SIGNAL(enadisBreak(const QString
&,int,const DbgAddr
&)));
200 // Comunication when right button is clicked.
201 connect(fw
, SIGNAL(clickedRight(const QPoint
&)),
202 SLOT(slotFileWindowRightClick(const QPoint
&)));
205 connect(fw
, SIGNAL(disassemble(const QString
&, int)),
206 SIGNAL(disassemble(const QString
&, int)));
207 connect(fw
, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
208 connect(fw
, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));
211 connect(this, SIGNAL(setTabWidth(int)), fw
, SLOT(setTabWidth(int)));
212 fw
->setTabWidth(m_tabWidth
);
219 // set PC if there is one
220 emit
newFileLoaded();
222 setPC(true, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
225 return activateWindow(fw
, lineNo
, address
);
228 bool WinStack::activateWindow(SourceWindow
* fw
, int lineNo
, const DbgAddr
& address
)
230 int index
= m_fileList
.findRef(fw
);
236 * If the file is not in the list of those that would appear in the
237 * window menu, move it to the first position.
241 m_fileList
.insert(0, fw
);
245 // make the line visible
247 fw
->scrollTo(lineNo
, address
);
250 // first resize the window, then lift it to the top
251 fw
->setGeometry(0,0, width(),height());
255 // set the focus to the new active window
256 QWidget
* oldActive
= m_activeWindow
;
258 fw
->setFocusPolicy(QWidget::StrongFocus
);
260 fw
->setFocusPolicy(QWidget::WheelFocus
);
263 if (oldActive
!= 0 && oldActive
!= fw
) {
264 // disable focus on non-active windows
265 oldActive
->setFocusPolicy(QWidget::NoFocus
);
274 bool WinStack::activeLine(QString
& fileName
, int& lineNo
)
277 return activeLine(fileName
, lineNo
, dummy
);
280 bool WinStack::activeLine(QString
& fileName
, int& lineNo
, DbgAddr
& address
)
282 if (m_activeWindow
== 0) {
286 fileName
= m_activeWindow
->fileName();
287 m_activeWindow
->activeLine(lineNo
, address
);
291 void WinStack::changeWindowMenu()
293 if (m_windowMenu
== 0) {
297 // delete window entries
298 while ((m_windowMenu
->idAt(m_itemMore
) & ~ID_WINDOW_INDEX_MASK
) == ID_WINDOW_MORE
) {
299 m_windowMenu
->removeItemAt(m_itemMore
);
302 // insert current windows
305 SourceWindow
* fw
= 0;
306 for (fw
= m_fileList
.first(); fw
!= 0 && index
< 10; fw
= m_fileList
.next()) {
307 text
.sprintf("&%d ", index
);
308 text
+= fw
->fileName();
309 m_windowMenu
->insertItem(text
, ID_WINDOW_MORE
+index
, m_itemMore
+index
-1);
313 // there are still windows
314 m_windowMenu
->insertItem(m_textMore
, ID_WINDOW_MORE
, m_itemMore
+9);
318 void WinStack::updateLineItems(const KDebugger
* dbg
)
320 SourceWindow
* fw
= 0;
321 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
322 fw
->updateLineItems(dbg
);
326 void WinStack::updatePC(const QString
& fileName
, int lineNo
, const DbgAddr
& address
, int frameNo
)
329 setPC(false, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
333 m_pcAddress
= address
.asString();
336 setPC(true, fileName
, lineNo
, address
, frameNo
);
340 void WinStack::setPC(bool set
, const QString
& fileName
, int lineNo
,
341 const DbgAddr
& address
, int frameNo
)
343 TRACE((set
? "set PC: " : "clear PC: ") + fileName
+
344 QString().sprintf(":%d#%d ", lineNo
, frameNo
) + address
.asString());
346 SourceWindow
* fw
= 0;
347 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
348 if (fw
->fileNameMatches(fileName
)) {
349 fw
->setPC(set
, lineNo
, address
, frameNo
);
355 void WinStack::resizeEvent(QResizeEvent
*)
357 ASSERT(m_activeWindow
== 0 || m_fileList
.findRef(m_activeWindow
) >= 0);
358 if (m_activeWindow
!= 0) {
359 m_activeWindow
->resize(width(), height());
363 void WinStack::slotFindForward()
365 if (m_activeWindow
!= 0)
366 m_activeWindow
->find(m_findDlg
.searchText(), m_findDlg
.caseSensitive(),
367 SourceWindow::findForward
);
370 void WinStack::slotFindBackward()
372 if (m_activeWindow
!= 0)
373 m_activeWindow
->find(m_findDlg
.searchText(), m_findDlg
.caseSensitive(),
374 SourceWindow::findBackward
);
377 void WinStack::slotFileWindowRightClick(const QPoint
& pos
)
379 if (m_menuFloat
.isVisible())
385 m_menuFloat
.popup(mapToGlobal(pos
));
389 void WinStack::slotWidgetRightClick(const QPoint
& pos
)
391 if (m_menuFileFloat
.isVisible())
393 m_menuFileFloat
.hide();
397 m_menuFileFloat
.popup(mapToGlobal(pos
));
401 void WinStack::maybeTip(const QPoint
& p
)
403 if (m_activeWindow
== 0)
406 // get the word at the point
409 if (!m_activeWindow
->wordAtPoint(p
, word
, r
))
413 assert(!word
.isEmpty());
416 // remember the location
419 emit
initiateValuePopup(word
);
422 void WinStack::slotShowValueTip(const QString
& tipText
)
424 m_valueTip
.tip(m_tipLocation
, tipText
);
427 void WinStack::slotDisassembled(const QString
& fileName
, int lineNo
,
428 const QList
<DisassembledCode
>& disass
)
432 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
433 if (fw
->fileNameMatches(fileName
)) {
442 fw
->disassembled(lineNo
, disass
);
445 void WinStack::slotExpandCollapse(int)
447 // update line items after expanding or collapsing disassembled code
449 // HACK: we know that this will result in updateLineItems
450 // should be done more cleanly with a separate signal
451 emit
newFileLoaded();
454 setPC(true, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
459 void WinStack::slotSetTabWidth(int numChars
)
461 m_tabWidth
= numChars
;
465 ValueTip::ValueTip(WinStack
* parent
) :
470 void ValueTip::maybeTip(const QPoint
& p
)
472 WinStack
* w
= static_cast<WinStack
*>(parentWidget());
477 class MoreWindowsDialog
: public QDialog
480 MoreWindowsDialog(QWidget
* parent
);
481 virtual ~MoreWindowsDialog();
483 void insertString(const char* text
) { m_list
.insertItem(text
); }
484 void setListIndex(int i
) { m_list
.setCurrentItem(i
); }
485 int listIndex() const { return m_list
.currentItem(); }
489 QPushButton m_buttonOK
;
490 QPushButton m_buttonCancel
;
491 QVBoxLayout m_layout
;
492 QHBoxLayout m_buttons
;
495 MoreWindowsDialog::MoreWindowsDialog(QWidget
* parent
) :
496 QDialog(parent
, "morewindows", true),
497 m_list(this, "windows"),
498 m_buttonOK(this, "show"),
499 m_buttonCancel(this, "cancel"),
503 QString title
= kapp
->getCaption();
504 title
+= i18n(": Open Windows");
507 m_list
.setMinimumSize(250, 100);
508 connect(&m_list
, SIGNAL(selected(int)), SLOT(accept()));
510 m_buttonOK
.setMinimumSize(100, 30);
511 connect(&m_buttonOK
, SIGNAL(clicked()), SLOT(accept()));
512 m_buttonOK
.setText(i18n("Show"));
513 m_buttonOK
.setDefault(true);
515 m_buttonCancel
.setMinimumSize(100, 30);
516 connect(&m_buttonCancel
, SIGNAL(clicked()), SLOT(reject()));
517 m_buttonCancel
.setText(i18n("Cancel"));
519 m_layout
.addWidget(&m_list
, 10);
520 m_layout
.addLayout(&m_buttons
);
521 m_buttons
.addStretch(10);
522 m_buttons
.addWidget(&m_buttonOK
);
523 m_buttons
.addSpacing(40);
524 m_buttons
.addWidget(&m_buttonCancel
);
525 m_buttons
.addStretch(10);
533 MoreWindowsDialog::~MoreWindowsDialog()
537 void WinStack::selectWindow(int id
)
542 // more windows selected: show windows in a list
543 MoreWindowsDialog
dlg(this);
545 for (SourceWindow
* fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
546 dlg
.insertString(fw
->fileName());
547 if (m_activeWindow
== fw
) {
552 dlg
.setListIndex(index
);
553 if (dlg
.exec() == QDialog::Rejected
)
555 index
= dlg
.listIndex();
557 index
= (id
& ID_WINDOW_INDEX_MASK
)-1;
560 SourceWindow
* fw
= m_fileList
.first();
561 for (; index
> 0; index
--) {
562 fw
= m_fileList
.next();
566 activateWindow(fw
, -1, DbgAddr());
570 FindDialog::FindDialog() :
571 QDialog(0, "find", false),
572 m_searchText(this, "text"),
573 m_caseCheck(this, "case"),
574 m_buttonForward(this, "forward"),
575 m_buttonBackward(this, "backward"),
576 m_buttonClose(this, "close"),
580 setCaption(QString(kapp
->getCaption()) + i18n(": Search"));
582 m_searchText
.setMinimumSize(330, 24);
583 m_searchText
.setMaxLength(10000);
584 m_searchText
.setFrame(true);
586 m_caseCheck
.setText(i18n("&Case sensitive"));
587 m_caseCheck
.setChecked(true);
588 m_buttonForward
.setText(i18n("&Forward"));
589 m_buttonForward
.setDefault(true);
590 m_buttonBackward
.setText(i18n("&Backward"));
591 m_buttonClose
.setText(i18n("Close"));
593 m_caseCheck
.setMinimumSize(330, 24);
595 // get maximum size of buttons
596 QSize
maxSize(80,30);
597 #if QT_VERSION >= 140
598 maxSize
.expandedTo(m_buttonForward
.sizeHint());
599 maxSize
.expandedTo(m_buttonBackward
.sizeHint());
600 maxSize
.expandedTo(m_buttonClose
.sizeHint());
603 m_buttonForward
.setMinimumSize(maxSize
);
604 m_buttonBackward
.setMinimumSize(maxSize
);
605 m_buttonClose
.setMinimumSize(maxSize
);
607 connect(&m_buttonClose
, SIGNAL(clicked()), SLOT(reject()));
609 m_layout
.addWidget(&m_searchText
);
610 m_layout
.addWidget(&m_caseCheck
);
611 m_layout
.addLayout(&m_buttons
);
612 m_layout
.addStretch(10);
613 m_buttons
.addWidget(&m_buttonForward
);
614 m_buttons
.addStretch(10);
615 m_buttons
.addWidget(&m_buttonBackward
);
616 m_buttons
.addStretch(10);
617 m_buttons
.addWidget(&m_buttonClose
);
621 m_searchText
.setFocus();
625 FindDialog::~FindDialog()
629 void FindDialog::closeEvent(QCloseEvent
* ev
)
631 QDialog::closeEvent(ev
);
635 void FindDialog::done(int result
)
637 QDialog::done(result
);
641 #include "winstack.moc"