2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
10 #include <qfileinfo.h>
13 #include <kmainwindow.h>
14 #include <klocale.h> /* i18n */
22 WinStack::WinStack(QWidget
* parent
, const char* name
) :
23 QWidget(parent
, name
),
28 m_tipLocation(1,1,10,10),
31 connect(&m_findDlg
.m_buttonForward
,
32 SIGNAL(clicked()), SLOT(slotFindForward()));
33 connect(&m_findDlg
.m_buttonBackward
,
34 SIGNAL(clicked()), SLOT(slotFindBackward()));
36 connect(this, SIGNAL(setTabWidth(int)), this, SLOT(slotSetTabWidth(int)));
43 void WinStack::setWindowMenu(QPopupMenu
* menu
)
50 // hook up for menu activations
51 connect(menu
, SIGNAL(activated(int)), this, SLOT(selectWindow(int)));
54 void WinStack::contextMenuEvent(QContextMenuEvent
* e
)
56 // get the context menu from the GUI factory
59 top
= top
->parentWidget();
60 while (!top
->isTopLevel());
61 KMainWindow
* mw
= static_cast<KMainWindow
*>(top
);
63 static_cast<QPopupMenu
*>(mw
->factory()->container("popup_files_empty", mw
));
64 m
->exec(e
->globalPos());
68 void WinStack::reloadAllFiles()
70 for (int i
= 0; i
< m_fileList
.size(); i
++) {
71 m_fileList
[i
]->reloadFile();
75 QSize
WinStack::sizeHint() const
77 return QSize(640, 480);
80 void WinStack::activate(const QString
& fileName
, int lineNo
, const DbgAddr
& address
)
82 QFileInfo
fi(fileName
);
86 * We didn't find that file. Now check if it is a relative path and
87 * try m_lastOpenDir as prefix.
89 TRACE(fi
.filePath() + (" not found, looking in " + m_lastOpenDir
));
90 if (!fi
.isRelative() || m_lastOpenDir
.isEmpty()) {
93 fi
.setFile(m_lastOpenDir
+ "/" + fi
.filePath());
98 // if this is not an absolute path name, make it one
99 activatePath(fi
.absFilePath(), lineNo
, address
);
102 void WinStack::activateFile(const QString
& fileName
)
104 activatePath(fileName
, 0, DbgAddr());
107 bool WinStack::activatePath(QString pathName
, int lineNo
, const DbgAddr
& address
)
109 // check whether the file is already open
110 SourceWindow
* fw
= 0;
111 for (int i
= 0; i
< m_fileList
.size(); i
++) {
112 if (m_fileList
[i
]->fileName() == pathName
) {
118 // not found, load it
119 fw
= new SourceWindow(pathName
, this, "fileWindow");
122 if (!fw
->loadFile()) {
128 m_fileList
.insertAt(0, fw
);
129 connect(fw
, SIGNAL(clickedLeft(const QString
&,int,const DbgAddr
&,bool)),
130 SIGNAL(toggleBreak(const QString
&,int,const DbgAddr
&,bool)));
131 connect(fw
, SIGNAL(clickedMid(const QString
&,int,const DbgAddr
&)),
132 SIGNAL(enadisBreak(const QString
&,int,const DbgAddr
&)));
135 connect(fw
, SIGNAL(disassemble(const QString
&, int)),
136 SIGNAL(disassemble(const QString
&, int)));
137 connect(fw
, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
138 connect(fw
, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));
141 connect(this, SIGNAL(setTabWidth(int)), fw
, SLOT(setTabWidth(int)));
142 fw
->setTabWidth(m_tabWidth
);
146 // set PC if there is one
147 emit
newFileLoaded();
149 setPC(true, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
152 return activateWindow(fw
, lineNo
, address
);
155 bool WinStack::activateWindow(SourceWindow
* fw
, int lineNo
, const DbgAddr
& address
)
158 int index
= m_fileList
.size()-1;
159 while (index
>= 0 && m_fileList
[index
] != fw
)
166 * If the file is not in the list of those that would appear in the
167 * window menu, move it to the first position.
170 m_fileList
.removeAt(index
);
171 m_fileList
.insertAt(0, fw
);
175 // make the line visible
177 fw
->scrollTo(lineNo
, address
);
180 // first resize the window, then lift it to the top
181 fw
->setGeometry(0,0, width(),height());
185 // set the focus to the new active window
186 QWidget
* oldActive
= m_activeWindow
;
187 fw
->setFocusPolicy(QWidget::WheelFocus
);
189 if (oldActive
!= 0 && oldActive
!= fw
) {
190 // disable focus on non-active windows
191 oldActive
->setFocusPolicy(QWidget::NoFocus
);
200 bool WinStack::activeLine(QString
& fileName
, int& lineNo
)
203 return activeLine(fileName
, lineNo
, dummy
);
206 bool WinStack::activeLine(QString
& fileName
, int& lineNo
, DbgAddr
& address
)
208 if (m_activeWindow
== 0) {
212 fileName
= m_activeWindow
->fileName();
213 m_activeWindow
->activeLine(lineNo
, address
);
217 void WinStack::changeWindowMenu()
219 if (m_windowMenu
== 0) {
224 // Delete entries at most the N window entries that we insert below.
225 // When we get here if the More entry was selected, we must make sure
226 // that we don't delete it (or we crash).
227 bool haveMore
= m_windowMenu
->count() > uint(N
);
228 int k
= haveMore
? N
: m_windowMenu
->count();
230 for (int i
= 0; i
< k
; i
++) {
231 m_windowMenu
->removeItemAt(0);
234 // insert current windows
236 for (int i
= 0; i
< m_fileList
.size() && i
< N
; i
++) {
237 text
.sprintf("&%d ", i
+1);
238 text
+= m_fileList
[i
]->fileName();
239 m_windowMenu
->insertItem(text
, WindowMore
+i
+1, i
);
241 // add More entry if we have none yet
242 if (!haveMore
&& m_fileList
.size() > N
) {
243 m_windowMenu
->insertItem(i18n("&More..."), WindowMore
, N
);
247 void WinStack::updateLineItems(const KDebugger
* dbg
)
249 for (int i
= 0; i
< m_fileList
.size(); i
++) {
250 m_fileList
[i
]->updateLineItems(dbg
);
254 void WinStack::updatePC(const QString
& fileName
, int lineNo
, const DbgAddr
& address
, int frameNo
)
257 setPC(false, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
261 m_pcAddress
= address
.asString();
264 setPC(true, fileName
, lineNo
, address
, frameNo
);
268 void WinStack::setPC(bool set
, const QString
& fileName
, int lineNo
,
269 const DbgAddr
& address
, int frameNo
)
271 TRACE((set
? "set PC: " : "clear PC: ") + fileName
+
272 QString().sprintf(":%d#%d ", lineNo
, frameNo
) + address
.asString());
274 for (int i
= 0; i
< m_fileList
.size(); i
++) {
275 if (m_fileList
[i
]->fileNameMatches(fileName
)) {
276 m_fileList
[i
]->setPC(set
, lineNo
, address
, frameNo
);
282 void WinStack::resizeEvent(QResizeEvent
*)
284 if (m_activeWindow
!= 0) {
285 m_activeWindow
->resize(width(), height());
289 QString
WinStack::activeFileName() const
292 if (m_activeWindow
!= 0)
293 f
= m_activeWindow
->fileName();
297 void WinStack::slotFindForward()
299 if (m_activeWindow
!= 0)
300 m_activeWindow
->find(m_findDlg
.searchText(), m_findDlg
.caseSensitive(),
301 SourceWindow::findForward
);
304 void WinStack::slotFindBackward()
306 if (m_activeWindow
!= 0)
307 m_activeWindow
->find(m_findDlg
.searchText(), m_findDlg
.caseSensitive(),
308 SourceWindow::findBackward
);
311 void WinStack::maybeTip(const QPoint
& p
)
313 if (m_activeWindow
== 0)
316 // get the word at the point
319 if (!m_activeWindow
->wordAtPoint(p
, word
, r
))
323 assert(!word
.isEmpty());
326 // remember the location
329 emit
initiateValuePopup(word
);
332 void WinStack::slotShowValueTip(const QString
& tipText
)
334 m_valueTip
.tip(m_tipLocation
, tipText
);
337 void WinStack::slotDisassembled(const QString
& fileName
, int lineNo
,
338 const QList
<DisassembledCode
>& disass
)
341 SourceWindow
* fw
= 0;
342 for (int i
= 0; i
< m_fileList
.size(); i
++) {
343 if (m_fileList
[i
]->fileNameMatches(fileName
)) {
353 fw
->disassembled(lineNo
, disass
);
356 void WinStack::slotExpandCollapse(int)
358 // update line items after expanding or collapsing disassembled code
360 // HACK: we know that this will result in updateLineItems
361 // should be done more cleanly with a separate signal
362 emit
newFileLoaded();
365 setPC(true, m_pcFile
, m_pcLine
, DbgAddr(m_pcAddress
), m_pcFrame
);
370 void WinStack::slotSetTabWidth(int numChars
)
372 m_tabWidth
= numChars
;
375 void WinStack::slotFileReload()
377 if (m_activeWindow
!= 0) {
378 TRACE("reloading one file");
379 m_activeWindow
->reloadFile();
383 void WinStack::slotViewFind()
385 if (m_findDlg
.isVisible()) {
392 void WinStack::slotBrkptSet()
397 if (activeLine(file
, lineNo
, address
))
398 emit
toggleBreak(file
, lineNo
, address
, false);
401 void WinStack::slotBrkptSetTemp()
406 if (activeLine(file
, lineNo
, address
))
407 emit
toggleBreak(file
, lineNo
, address
, true);
410 void WinStack::slotBrkptEnable()
415 if (activeLine(file
, lineNo
, address
))
416 emit
enadisBreak(file
, lineNo
, address
);
419 void WinStack::slotMoveProgramCounter()
424 if (activeLine(file
, lineNo
, address
))
425 emit
moveProgramCounter(file
, lineNo
, address
);
429 ValueTip::ValueTip(WinStack
* parent
) :
434 void ValueTip::maybeTip(const QPoint
& p
)
436 WinStack
* w
= static_cast<WinStack
*>(parentWidget());
441 class MoreWindowsDialog
: public QDialog
444 MoreWindowsDialog(QWidget
* parent
);
445 virtual ~MoreWindowsDialog();
447 void insertString(const char* text
) { m_list
.insertItem(text
); }
448 void setListIndex(int i
) { m_list
.setCurrentItem(i
); }
449 int listIndex() const { return m_list
.currentItem(); }
453 QPushButton m_buttonOK
;
454 QPushButton m_buttonCancel
;
455 QVBoxLayout m_layout
;
456 QHBoxLayout m_buttons
;
459 MoreWindowsDialog::MoreWindowsDialog(QWidget
* parent
) :
460 QDialog(parent
, "morewindows", true),
461 m_list(this, "windows"),
462 m_buttonOK(this, "show"),
463 m_buttonCancel(this, "cancel"),
467 QString title
= kapp
->caption();
468 title
+= i18n(": Open Windows");
471 m_list
.setMinimumSize(250, 100);
472 connect(&m_list
, SIGNAL(selected(int)), SLOT(accept()));
474 m_buttonOK
.setMinimumSize(100, 30);
475 connect(&m_buttonOK
, SIGNAL(clicked()), SLOT(accept()));
476 m_buttonOK
.setText(i18n("Show"));
477 m_buttonOK
.setDefault(true);
479 m_buttonCancel
.setMinimumSize(100, 30);
480 connect(&m_buttonCancel
, SIGNAL(clicked()), SLOT(reject()));
481 m_buttonCancel
.setText(i18n("Cancel"));
483 m_layout
.addWidget(&m_list
, 10);
484 m_layout
.addLayout(&m_buttons
);
485 m_buttons
.addStretch(10);
486 m_buttons
.addWidget(&m_buttonOK
);
487 m_buttons
.addSpacing(40);
488 m_buttons
.addWidget(&m_buttonCancel
);
489 m_buttons
.addStretch(10);
497 MoreWindowsDialog::~MoreWindowsDialog()
501 void WinStack::selectWindow(int id
)
503 // react only on menu entries concerning windows
504 if ((id
& ~WindowMask
) != WindowMore
) {
513 // more windows selected: show windows in a list
514 MoreWindowsDialog
dlg(this);
515 for (int i
= 0; i
< m_fileList
.size(); i
++)
517 dlg
.insertString(m_fileList
[i
]->fileName());
518 if (m_activeWindow
== m_fileList
[i
]) {
522 dlg
.setListIndex(index
);
523 if (dlg
.exec() == QDialog::Rejected
)
525 index
= dlg
.listIndex();
527 index
= (id
& WindowMask
)-1;
530 SourceWindow
* fw
= m_fileList
[index
];
533 activateWindow(fw
, -1, DbgAddr());
537 FindDialog::FindDialog() :
538 QDialog(0, "find", false),
539 m_searchText(this, "text"),
540 m_caseCheck(this, "case"),
541 m_buttonForward(this, "forward"),
542 m_buttonBackward(this, "backward"),
543 m_buttonClose(this, "close"),
547 setCaption(QString(kapp
->caption()) + i18n(": Search"));
549 m_searchText
.setMinimumSize(330, 24);
550 m_searchText
.setMaxLength(10000);
551 m_searchText
.setFrame(true);
553 m_caseCheck
.setText(i18n("&Case sensitive"));
554 m_caseCheck
.setChecked(true);
555 m_buttonForward
.setText(i18n("&Forward"));
556 m_buttonForward
.setDefault(true);
557 m_buttonBackward
.setText(i18n("&Backward"));
558 m_buttonClose
.setText(i18n("Close"));
560 m_caseCheck
.setMinimumSize(330, 24);
562 // get maximum size of buttons
563 QSize
maxSize(80,30);
564 maxSize
.expandedTo(m_buttonForward
.sizeHint());
565 maxSize
.expandedTo(m_buttonBackward
.sizeHint());
566 maxSize
.expandedTo(m_buttonClose
.sizeHint());
568 m_buttonForward
.setMinimumSize(maxSize
);
569 m_buttonBackward
.setMinimumSize(maxSize
);
570 m_buttonClose
.setMinimumSize(maxSize
);
572 connect(&m_buttonClose
, SIGNAL(clicked()), SLOT(reject()));
574 m_layout
.addWidget(&m_searchText
);
575 m_layout
.addWidget(&m_caseCheck
);
576 m_layout
.addLayout(&m_buttons
);
577 m_layout
.addStretch(10);
578 m_buttons
.addWidget(&m_buttonForward
);
579 m_buttons
.addStretch(10);
580 m_buttons
.addWidget(&m_buttonBackward
);
581 m_buttons
.addStretch(10);
582 m_buttons
.addWidget(&m_buttonClose
);
586 m_searchText
.setFocus();
590 FindDialog::~FindDialog()
594 void FindDialog::closeEvent(QCloseEvent
* ev
)
596 QDialog::closeEvent(ev
);
600 void FindDialog::done(int result
)
602 QDialog::done(result
);
606 #include "winstack.moc"