3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
13 #include <klocale.h> /* i18n */
24 WinStack::WinStack(QWidget
* parent
, const char* name
) :
25 QWidget(parent
, name
),
31 m_tipLocation(1,1,10,10),
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)));
46 void WinStack::setWindowMenu(QPopupMenu
* menu
)
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());
72 QWidget::mousePressEvent(mouseEvent
);
77 void WinStack::reloadAllFiles()
80 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
85 void WinStack::activate(const QString
& fileName
, int lineNo
, const DbgAddr
& address
)
87 QFileInfo
fi(fileName
);
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()) {
98 fi
.setFile(m_lastOpenDir
+ "/" + fi
.filePath());
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
116 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
117 if (fw
->fileName() == pathName
) {
122 // not found, load it
123 fw
= new SourceWindow(pathName
, this, "fileWindow");
126 if (!fw
->loadFile()) {
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
&)));
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)));
150 connect(this, SIGNAL(setTabWidth(int)), fw
, SLOT(setTabWidth(int)));
151 fw
->setTabWidth(m_tabWidth
);
155 // set PC if there is one
156 emit
newFileLoaded();
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
);
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.
177 m_fileList
.insert(0, fw
);
181 // make the line visible
183 fw
->scrollTo(lineNo
, address
);
186 // first resize the window, then lift it to the top
187 fw
->setGeometry(0,0, width(),height());
191 // set the focus to the new active window
192 QWidget
* oldActive
= m_activeWindow
;
194 fw
->setFocusPolicy(QWidget::StrongFocus
);
196 fw
->setFocusPolicy(QWidget::WheelFocus
);
199 if (oldActive
!= 0 && oldActive
!= fw
) {
200 // disable focus on non-active windows
201 oldActive
->setFocusPolicy(QWidget::NoFocus
);
210 bool WinStack::activeLine(QString
& fileName
, int& lineNo
)
213 return activeLine(fileName
, lineNo
, dummy
);
216 bool WinStack::activeLine(QString
& fileName
, int& lineNo
, DbgAddr
& address
)
218 if (m_activeWindow
== 0) {
222 fileName
= m_activeWindow
->fileName();
223 m_activeWindow
->activeLine(lineNo
, address
);
227 void WinStack::changeWindowMenu()
229 if (m_windowMenu
== 0) {
233 // delete window entries
234 while ((m_windowMenu
->idAt(m_itemMore
) & ~WindowMask
) == WindowMore
) {
235 m_windowMenu
->removeItemAt(m_itemMore
);
238 // insert current windows
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);
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
)
265 setPC(false, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
269 m_pcAddress
= address
.asString();
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());
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
);
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)
318 // get the word at the point
321 if (!m_activeWindow
->wordAtPoint(p
, word
, r
))
325 assert(!word
.isEmpty());
328 // remember the location
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
)
344 for (fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
345 if (fw
->fileNameMatches(fileName
)) {
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();
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()) {
393 void WinStack::slotBrkptSet()
398 if (activeLine(file
, lineNo
, address
))
399 emit
toggleBreak(file
, lineNo
, address
, false);
402 void WinStack::slotBrkptSetTemp()
407 if (activeLine(file
, lineNo
, address
))
408 emit
toggleBreak(file
, lineNo
, address
, true);
411 void WinStack::slotBrkptEnable()
416 if (activeLine(file
, lineNo
, address
))
417 emit
enadisBreak(file
, lineNo
, address
);
421 ValueTip::ValueTip(WinStack
* parent
) :
426 void ValueTip::maybeTip(const QPoint
& p
)
428 WinStack
* w
= static_cast<WinStack
*>(parentWidget());
433 class MoreWindowsDialog
: public QDialog
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(); }
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"),
459 QString title
= kapp
->getCaption();
460 title
+= i18n(": Open Windows");
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);
489 MoreWindowsDialog::~MoreWindowsDialog()
493 void WinStack::selectWindow(int id
)
495 // react only on menu entries concerning windows
496 if ((id
& ~WindowMask
) != WindowMore
) {
505 // more windows selected: show windows in a list
506 MoreWindowsDialog
dlg(this);
508 for (SourceWindow
* fw
= m_fileList
.first(); fw
!= 0; fw
= m_fileList
.next()) {
509 dlg
.insertString(fw
->fileName());
510 if (m_activeWindow
== fw
) {
515 dlg
.setListIndex(index
);
516 if (dlg
.exec() == QDialog::Rejected
)
518 index
= dlg
.listIndex();
520 index
= (id
& WindowMask
)-1;
523 SourceWindow
* fw
= m_fileList
.first();
524 for (; index
> 0; index
--) {
525 fw
= m_fileList
.next();
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"),
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());
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
);
584 m_searchText
.setFocus();
588 FindDialog::~FindDialog()
592 void FindDialog::closeEvent(QCloseEvent
* ev
)
594 QDialog::closeEvent(ev
);
598 void FindDialog::done(int result
)
600 QDialog::done(result
);
604 #include "winstack.moc"