Extend copyright to 2018.
[kdbg.git] / kdbg / winstack.cpp
blob3b379926764b7689b314b69d42cbdca99745dad5
1 /*
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.
5 */
7 #include "winstack.h"
8 #include "sourcewnd.h"
9 #include "dbgdriver.h"
10 #include <QFileInfo>
11 #include <QMenu>
12 #include <QContextMenuEvent>
13 #include <QToolTip>
14 #include <kxmlguiwindow.h>
15 #include <kxmlguifactory.h>
16 #include <klocalizedstring.h> /* i18n */
17 #include "mydebug.h"
21 WinStack::WinStack(QWidget* parent) :
22 QTabWidget(parent),
23 m_pcLine(-1),
24 m_tabWidth(0)
26 setTabsClosable(true);
27 setMovable(true);
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)));
35 connect(this, SIGNAL(tabCloseRequested(int)),
36 this, SLOT(slotCloseTab(int)));
39 WinStack::~WinStack()
43 void WinStack::contextMenuEvent(QContextMenuEvent* e)
45 // get the context menu from the GUI factory
46 QWidget* top = this;
48 top = top->parentWidget();
49 while (!top->isTopLevel());
50 KXmlGuiWindow* mw = static_cast<KXmlGuiWindow*>(top);
51 QMenu* m =
52 static_cast<QMenu*>(mw->factory()->container("popup_files_empty", mw));
53 m->exec(e->globalPos());
57 void WinStack::reloadAllFiles()
59 for (int i = count()-1; i >= 0; i--) {
60 windowAt(i)->reloadFile();
64 QSize WinStack::sizeHint() const
66 return QSize(640, 480);
69 void WinStack::activate(const QString& fileName, int lineNo, const DbgAddr& address)
71 QFileInfo fi(fileName);
73 if (!fi.isFile()) {
75 * We didn't find that file. Now check if it is a relative path and
76 * try m_lastOpenDir as prefix.
78 TRACE(fi.filePath() + (" not found, looking in " + m_lastOpenDir));
79 if (!fi.isRelative() || m_lastOpenDir.isEmpty()) {
80 return;
82 fi.setFile(m_lastOpenDir + "/" + fi.filePath());
83 if (!fi.isFile()) {
84 return;
87 // if this is not an absolute path name, make it one
88 activatePath(fi.absoluteFilePath(), lineNo, address);
91 void WinStack::activateFile(const QString& fileName)
93 activatePath(fileName, 0, DbgAddr());
96 bool WinStack::activatePath(QString pathName, int lineNo, const DbgAddr& address)
98 // check whether the file is already open
99 SourceWindow* fw = 0;
100 for (int i = count()-1; i >= 0; i--) {
101 if (windowAt(i)->fileName() == pathName) {
102 fw = windowAt(i);
103 break;
106 if (fw == 0) {
107 // not found, load it
108 fw = new SourceWindow(pathName, this);
110 // slurp the file in
111 if (!fw->loadFile()) {
112 // read failed
113 delete fw;
114 return false;
117 int idx = addTab(fw, QFileInfo(pathName).fileName());
118 setTabToolTip(idx, pathName);
120 connect(fw, SIGNAL(clickedLeft(const QString&,int,const DbgAddr&,bool)),
121 SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)));
122 connect(fw, SIGNAL(clickedMid(const QString&,int,const DbgAddr&)),
123 SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)));
125 // disassemble code
126 connect(fw, SIGNAL(disassemble(const QString&, int)),
127 SIGNAL(disassemble(const QString&, int)));
128 connect(fw, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
129 connect(fw, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));
131 // tab width
132 connect(this, SIGNAL(setTabWidth(int)), fw, SLOT(setTabWidth(int)));
133 fw->setTabWidth(m_tabWidth);
134 fw->setFocusPolicy(Qt::WheelFocus);
136 // set PC if there is one
137 emit newFileLoaded();
138 if (m_pcLine >= 0) {
139 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
142 return activateWindow(fw, lineNo, address);
145 bool WinStack::activateWindow(SourceWindow* fw, int lineNo, const DbgAddr& address)
147 // make the line visible
148 if (lineNo >= 0) {
149 fw->scrollTo(lineNo, address);
152 setCurrentWidget(fw);
153 fw->setFocus();
155 return true;
158 bool WinStack::activeLine(QString& fileName, int& lineNo)
160 DbgAddr dummy;
161 return activeLine(fileName, lineNo, dummy);
164 bool WinStack::activeLine(QString& fileName, int& lineNo, DbgAddr& address)
166 if (activeWindow() == 0) {
167 return false;
170 fileName = activeFileName();
171 activeWindow()->activeLine(lineNo, address);
172 return true;
175 void WinStack::updateLineItems(const KDebugger* dbg)
177 for (int i = count()-1; i >= 0; i--) {
178 windowAt(i)->updateLineItems(dbg);
182 void WinStack::updatePC(const QString& fileName, int lineNo, const DbgAddr& address, int frameNo)
184 if (m_pcLine >= 0) {
185 setPC(false, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
187 m_pcFile = fileName;
188 m_pcLine = lineNo;
189 m_pcAddress = address.asString();
190 m_pcFrame = frameNo;
191 if (lineNo >= 0) {
192 setPC(true, fileName, lineNo, address, frameNo);
196 SourceWindow* WinStack::findByFileName(const QString& fileName) const
198 for (int i = count()-1; i >= 0; i--) {
199 if (windowAt(i)->fileNameMatches(fileName)) {
200 return windowAt(i);
203 return 0;
206 void WinStack::setPC(bool set, const QString& fileName, int lineNo,
207 const DbgAddr& address, int frameNo)
209 TRACE((set ? "set PC: " : "clear PC: ") + fileName +
210 QString().sprintf(":%d#%d ", lineNo, frameNo) + address.asString());
211 SourceWindow* fw = findByFileName(fileName);
212 if (fw)
213 fw->setPC(set, lineNo, address, frameNo);
216 SourceWindow* WinStack::windowAt(int i) const
218 return static_cast<SourceWindow*>(widget(i));
221 SourceWindow* WinStack::activeWindow() const
223 return static_cast<SourceWindow*>(currentWidget());
226 QString WinStack::activeFileName() const
228 QString f;
229 if (activeWindow() != 0)
230 f = activeWindow()->fileName();
231 return f;
234 void WinStack::slotFindForward()
236 if (activeWindow() != 0)
237 activeWindow()->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
238 SourceWindow::findForward);
241 void WinStack::slotFindBackward()
243 if (activeWindow() != 0)
244 activeWindow()->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
245 SourceWindow::findBackward);
248 bool WinStack::event(QEvent* evt)
250 if (evt->type() != QEvent::ToolTip)
251 return QTabWidget::event(evt);
253 SourceWindow* w = activeWindow();
254 if (w == 0)
255 return true;
257 QPoint p = static_cast<QHelpEvent*>(evt)->globalPos();
258 // get the word at the point
259 QString word;
260 QRect r;
261 if (!w->wordAtPoint(w->mapFromGlobal(p), word, r)) {
262 QToolTip::hideText();
263 return true;
266 // must be valid
267 assert(!word.isEmpty());
268 assert(r.isValid());
270 // remember the location
271 m_tipLocation = p;
272 m_tipRegion = QRect(w->mapTo(this, r.topLeft()), r.size());
274 emit initiateValuePopup(word);
275 return true;
278 void WinStack::slotShowValueTip(const QString& tipText)
280 QToolTip::showText(m_tipLocation, tipText, this, m_tipRegion);
283 void WinStack::slotDisassembled(const QString& fileName, int lineNo,
284 const std::list<DisassembledCode>& disass)
286 SourceWindow* fw = findByFileName(fileName);
287 if (fw == 0) {
288 // not found: ignore
289 return;
292 fw->disassembled(lineNo, disass);
295 void WinStack::slotExpandCollapse(int)
297 // update line items after expanding or collapsing disassembled code
299 // HACK: we know that this will result in updateLineItems
300 // should be done more cleanly with a separate signal
301 emit newFileLoaded();
303 if (m_pcLine >= 0) {
304 setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
309 void WinStack::slotSetTabWidth(int numChars)
311 m_tabWidth = numChars;
314 void WinStack::slotFileReload()
316 if (activeWindow() != 0) {
317 TRACE("reloading one file");
318 activeWindow()->reloadFile();
322 void WinStack::slotViewFind()
324 if (m_findDlg.isVisible()) {
325 m_findDlg.done(0);
326 } else {
327 m_findDlg.show();
331 void WinStack::slotBrkptSet()
333 QString file;
334 int lineNo;
335 DbgAddr address;
336 if (activeLine(file, lineNo, address))
337 emit toggleBreak(file, lineNo, address, false);
340 void WinStack::slotBrkptSetTemp()
342 QString file;
343 int lineNo;
344 DbgAddr address;
345 if (activeLine(file, lineNo, address))
346 emit toggleBreak(file, lineNo, address, true);
349 void WinStack::slotBrkptEnable()
351 QString file;
352 int lineNo;
353 DbgAddr address;
354 if (activeLine(file, lineNo, address))
355 emit enadisBreak(file, lineNo, address);
358 void WinStack::slotMoveProgramCounter()
360 QString file;
361 int lineNo;
362 DbgAddr address;
363 if (activeLine(file, lineNo, address))
364 emit moveProgramCounter(file, lineNo, address);
367 void WinStack::slotClose()
369 slotCloseTab(currentIndex());
372 void WinStack::slotCloseTab(int tab)
374 QWidget* w = widget(tab);
375 if (!w)
376 return;
378 removeTab(tab);
379 delete w;
383 FindDialog::FindDialog() :
384 QDialog(),
385 m_searchText(this),
386 m_caseCheck(this),
387 m_buttonForward(this),
388 m_buttonBackward(this),
389 m_buttonClose(this)
391 setWindowTitle(i18n("Search"));
393 m_searchText.setMinimumSize(330, 24);
394 m_searchText.setMaxLength(10000);
395 m_searchText.setFrame(true);
396 m_searchText.setFocus();
398 m_caseCheck.setText(i18n("&Case sensitive"));
399 m_caseCheck.setChecked(true);
400 m_buttonForward.setText(i18n("&Forward"));
401 m_buttonForward.setDefault(true);
402 m_buttonBackward.setText(i18n("&Backward"));
403 m_buttonClose.setText(i18n("Close"));
405 connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));
407 m_layout.addWidget(&m_searchText);
408 m_layout.addWidget(&m_caseCheck);
409 m_layout.addLayout(&m_buttons);
411 m_buttons.addWidget(&m_buttonForward);
412 m_buttons.addWidget(&m_buttonBackward);
413 m_buttons.addWidget(&m_buttonClose);
415 setLayout(&m_layout);
418 FindDialog::~FindDialog()
422 void FindDialog::closeEvent(QCloseEvent* ev)
424 QDialog::closeEvent(ev);
425 emit closed();
428 void FindDialog::done(int result)
430 QDialog::done(result);
431 emit closed();
434 #include "winstack.moc"