• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

kcachegrind

  • sources
  • kde-4.14
  • kdesdk
  • kcachegrind
  • libviews
sourceview.cpp
Go to the documentation of this file.
1 /* This file is part of KCachegrind.
2  Copyright (C) 2011 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
3 
4  KCachegrind is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public
6  License as published by the Free Software Foundation, version 2.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 /*
20  * Source View
21  */
22 
23 #include "sourceview.h"
24 
25 #include <QDebug>
26 #include <QDir>
27 #include <QFile>
28 #include <QFileInfo>
29 #include <QAction>
30 #include <QMenu>
31 #include <QScrollBar>
32 #include <QHeaderView>
33 #include <QKeyEvent>
34 
35 #include "globalconfig.h"
36 #include "sourceitem.h"
37 
38 
39 
40 //
41 // SourceView
42 //
43 
44 
45 SourceView::SourceView(TraceItemView* parentView,
46  QWidget* parent)
47  : QTreeWidget(parent), TraceItemView(parentView)
48 {
49  _inSelectionUpdate = false;
50 
51  _arrowLevels = 0;
52 
53 
54  setColumnCount(5);
55  setRootIsDecorated(false);
56  setAllColumnsShowFocus(true);
57  setUniformRowHeights(true);
58  // collapsing call/jump lines by double-click is confusing
59  setExpandsOnDoubleClick(false);
60 
61  QStringList headerLabels;
62  headerLabels << tr( "#" )
63  << tr( "Cost" )
64  << tr( "Cost 2" )
65  << ""
66  << tr( "Source (unknown)");
67  setHeaderLabels(headerLabels);
68 
69  // sorting will be enabled after refresh()
70  sortByColumn(0, Qt::AscendingOrder);
71  header()->setSortIndicatorShown(false);
72  this->setItemDelegate(new SourceItemDelegate(this));
73  this->setWhatsThis( whatsThis());
74 
75  connect( this,
76  SIGNAL( currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
77  SLOT( selectedSlot(QTreeWidgetItem*,QTreeWidgetItem*) ) );
78 
79  setContextMenuPolicy(Qt::CustomContextMenu);
80  connect( this,
81  SIGNAL(customContextMenuRequested(const QPoint &) ),
82  SLOT(context(const QPoint &)));
83 
84  connect(this,
85  SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
86  SLOT(activatedSlot(QTreeWidgetItem*,int)));
87 
88  connect(header(), SIGNAL(sectionClicked(int)),
89  this, SLOT(headerClicked(int)));
90 }
91 
92 QString SourceView::whatsThis() const
93 {
94  return tr( "<b>Annotated Source</b>"
95  "<p>The annotated source list shows the "
96  "source lines of the current selected function "
97  "together with (self) cost spent while executing the "
98  "code of this source line. If there was a call "
99  "in a source line, lines with details on the "
100  "call happening are inserted into the source: "
101  "the cost spent inside of the call, the "
102  "number of calls happening, and the call destination.</p>"
103  "<p>Select a inserted call information line to "
104  "make the destination function current.</p>");
105 }
106 
107 void SourceView::context(const QPoint & p)
108 {
109  int c = columnAt(p.x());
110  QTreeWidgetItem* i = itemAt(p);
111  QMenu popup;
112 
113  TraceLineCall* lc = i ? ((SourceItem*) i)->lineCall() : 0;
114  TraceLineJump* lj = i ? ((SourceItem*) i)->lineJump() : 0;
115  TraceFunction* f = lc ? lc->call()->called() : 0;
116  TraceLine* line = lj ? lj->lineTo() : 0;
117 
118  QAction* activateFunctionAction = 0;
119  QAction* activateLineAction = 0;
120  if (f) {
121  QString menuText = tr("Go to '%1'").arg(GlobalConfig::shortenSymbol(f->prettyName()));
122  activateFunctionAction = popup.addAction(menuText);
123  popup.addSeparator();
124  }
125  else if (line) {
126  QString menuText = tr("Go to Line %1").arg(line->name());
127  activateLineAction = popup.addAction(menuText);
128  popup.addSeparator();
129  }
130 
131  if ((c == 1) || (c == 2)) {
132  addEventTypeMenu(&popup);
133  popup.addSeparator();
134  }
135  addGoMenu(&popup);
136 
137  QAction* a = popup.exec(mapToGlobal(p + QPoint(0,header()->height())));
138  if (a == activateFunctionAction)
139  TraceItemView::activated(f);
140  else if (a == activateLineAction)
141  TraceItemView::activated(line);
142 }
143 
144 
145 void SourceView::selectedSlot(QTreeWidgetItem *i, QTreeWidgetItem *)
146 {
147  if (!i) return;
148  // programatically selected items are not signalled
149  if (_inSelectionUpdate) return;
150 
151  TraceLineCall* lc = ((SourceItem*) i)->lineCall();
152  TraceLineJump* lj = ((SourceItem*) i)->lineJump();
153 
154  if (!lc && !lj) {
155  TraceLine* l = ((SourceItem*) i)->line();
156  if (l) {
157  _selectedItem = l;
158  selected(l);
159  }
160  return;
161  }
162 
163  TraceFunction* f = lc ? lc->call()->called() : 0;
164  if (f) {
165  _selectedItem = f;
166  selected(f);
167  }
168  else {
169  TraceLine* line = lj ? lj->lineTo() : 0;
170  if (line) {
171  _selectedItem = line;
172  selected(line);
173  }
174  }
175 }
176 
177 void SourceView::activatedSlot(QTreeWidgetItem* i, int)
178 {
179  if (!i) return;
180 
181  TraceLineCall* lc = ((SourceItem*) i)->lineCall();
182  TraceLineJump* lj = ((SourceItem*) i)->lineJump();
183 
184  if (!lc && !lj) {
185  TraceLine* l = ((SourceItem*) i)->line();
186  if (l) TraceItemView::activated(l);
187  return;
188  }
189 
190  TraceFunction* f = lc ? lc->call()->called() : 0;
191  if (f) TraceItemView::activated(f);
192  else {
193  TraceLine* line = lj ? lj->lineTo() : 0;
194  if (line) TraceItemView::activated(line);
195  }
196 }
197 
198 void SourceView::keyPressEvent(QKeyEvent* event)
199 {
200  QTreeWidgetItem *item = currentItem();
201  if (item && ((event->key() == Qt::Key_Return) ||
202  (event->key() == Qt::Key_Space)))
203  {
204  activatedSlot(item, 0);
205  }
206  QTreeView::keyPressEvent(event);
207 }
208 
209 CostItem* SourceView::canShow(CostItem* i)
210 {
211  ProfileContext::Type t = i ? i->type() : ProfileContext::InvalidType;
212 
213  switch(t) {
214  case ProfileContext::Function:
215  case ProfileContext::Instr:
216  case ProfileContext::Line:
217  return i;
218 
219  default:
220  break;
221  }
222 
223  return 0;
224 }
225 
226 void SourceView::doUpdate(int changeType, bool)
227 {
228  // Special case ?
229  if (changeType == selectedItemChanged) {
230 
231  if (!_selectedItem) {
232  clearSelection();
233  return;
234  }
235 
236  TraceLine* sLine = 0;
237  if (_selectedItem->type() == ProfileContext::Line)
238  sLine = (TraceLine*) _selectedItem;
239  if (_selectedItem->type() == ProfileContext::Instr)
240  sLine = ((TraceInstr*)_selectedItem)->line();
241  if ((_selectedItem->type() != ProfileContext::Function) && (sLine == 0))
242  return;
243 
244  QList<QTreeWidgetItem*> items = selectedItems();
245  SourceItem* si = (items.count() > 0) ? (SourceItem*)items[0] : 0;
246  if (si) {
247  if (sLine && (si->line() == sLine)) return;
248  if (si->lineCall() &&
249  (si->lineCall()->call()->called() == _selectedItem)) return;
250  }
251 
252  QTreeWidgetItem *item, *item2;
253  for (int i=0; i<topLevelItemCount(); i++) {
254  item = topLevelItem(i);
255  si = (SourceItem*)item;
256  if (sLine && (si->line() == sLine)) {
257  scrollToItem(item);
258  _inSelectionUpdate = true;
259  setCurrentItem(item);
260  _inSelectionUpdate = false;
261  break;
262  }
263  bool foundCall = false;
264  for (int j=0; j<item->childCount(); j++) {
265  item2 = item->child(j);
266  si = (SourceItem*)item2;
267  if (!si->lineCall()) continue;
268  if (si->lineCall()->call()->called() == _selectedItem) {
269  scrollToItem(item2);
270  _inSelectionUpdate = true;
271  setCurrentItem(item2);
272  _inSelectionUpdate = false;
273  foundCall = true;
274  break;
275  }
276  }
277  if (foundCall) break;
278  }
279  return;
280  }
281 
282  if (changeType == groupTypeChanged) {
283  // update group colors for call lines
284  QTreeWidgetItem *item, *item2;
285  for (int i=0; i<topLevelItemCount(); i++) {
286  item = topLevelItem(i);
287  for (int j=0; i<item->childCount(); i++) {
288  item2 = item->child(j);
289  ((SourceItem*)item2)->updateGroup();
290  }
291  }
292  return;
293  }
294 
295  // On eventTypeChanged, we can not just change the costs shown in
296  // already existing items, as costs of 0 should make the line to not
297  // be shown at all. So we do a full refresh.
298 
299  refresh();
300 }
301 
302 void SourceView::refresh()
303 {
304  int originalPosition = verticalScrollBar()->value();
305  clear();
306  setColumnWidth(0, 20);
307  setColumnWidth(1, 50);
308  setColumnWidth(2, _eventType2 ? 50:0);
309  setColumnWidth(3, 0); // arrows, defaults to invisible
310  if (_eventType)
311  headerItem()->setText(1, _eventType->name());
312  if (_eventType2)
313  headerItem()->setText(2, _eventType2->name());
314 
315  _arrowLevels = 0;
316  if (!_data || !_activeItem) {
317  headerItem()->setText(4, tr("(No Source)"));
318  return;
319  }
320 
321  ProfileContext::Type t = _activeItem->type();
322  TraceFunction* f = 0;
323  if (t == ProfileContext::Function) f = (TraceFunction*) _activeItem;
324  if (t == ProfileContext::Instr) {
325  f = ((TraceInstr*)_activeItem)->function();
326  if (!_selectedItem)
327  _selectedItem = ((TraceInstr*)_activeItem)->line();
328  }
329  if (t == ProfileContext::Line) {
330  f = ((TraceLine*)_activeItem)->functionSource()->function();
331  if (!_selectedItem) _selectedItem = _activeItem;
332  }
333 
334  if (!f) return;
335 
336  TraceFunctionSource* mainSF = f->sourceFile();
337 
338  // skip first source if there is no debug info and there are more sources
339  // (this is for a bug in GCC 2.95.x giving unknown source for prologs)
340  if (mainSF &&
341  (mainSF->firstLineno() == 0) &&
342  (mainSF->lastLineno() == 0) &&
343  (f->sourceFiles().count()>1) ) {
344  // skip
345  }
346  else
347  fillSourceFile(mainSF, 0);
348 
349  int fileno = 0;
350  foreach(TraceFunctionSource* sf, f->sourceFiles()) {
351  fileno++;
352  if (sf != mainSF)
353  fillSourceFile(sf, fileno);
354  }
355 
356  if (!_eventType2) {
357 #if QT_VERSION >= 0x050000
358  header()->setSectionResizeMode(2, QHeaderView::Interactive);
359 #else
360  header()->setResizeMode(2, QHeaderView::Interactive);
361 #endif
362  setColumnWidth(2, 0);
363  }
364  // reset to the original position - this is useful when the view
365  // is refreshed just because we change between relative/absolute
366  // FIXME: this overrides scrolling to selected item
367  verticalScrollBar()->setValue(originalPosition);
368 }
369 
370 
371 /* Helper for fillSourceList:
372  * search recursive for a file, starting from a base dir
373  * If found, returns true and <dir> is set to the file path.
374  */
375 static bool searchFileRecursive(QString& dir, const QString& name)
376 {
377  // we leave this in...
378  qDebug("Checking %s/%s", qPrintable(dir), qPrintable(name));
379 
380  if (QFile::exists(dir + '/' + name)) return true;
381 
382  // check in subdirectories
383  QDir d(dir);
384  d.setFilter( QDir::Dirs | QDir::NoSymLinks );
385  d.setSorting( QDir::Unsorted );
386  QStringList subdirs = d.entryList();
387  QStringList::const_iterator it =subdirs.constBegin();
388  for(; it != subdirs.constEnd(); ++it ) {
389  if (*it == "." || *it == ".." || *it == "CVS") continue;
390 
391  dir = d.filePath(*it);
392  if (searchFileRecursive(dir, name)) return true;
393  }
394  return false;
395 }
396 
397 /* Search for a source file in different places.
398  * If found, returns true and <dir> is set to the file path.
399  */
400 bool SourceView::searchFile(QString& dir,
401  TraceFunctionSource* sf)
402 {
403  QString name = sf->file()->shortName();
404 
405  if (QDir::isAbsolutePath(dir)) {
406  if (QFile::exists(dir + '/' + name)) return true;
407  }
408  else {
409  /* Directory is relative. Check
410  * - relative to cwd
411  * - relative to path of data file
412  */
413  QString base = QDir::currentPath() + '/' + dir;
414  if (QFile::exists(base + '/' + name)) {
415  dir = base;
416  return true;
417  }
418 
419  TracePart* firstPart = _data->parts().first();
420  if (firstPart) {
421  QFileInfo partFile(firstPart->name());
422  if (QFileInfo(partFile.absolutePath(), name).exists()) {
423  dir = partFile.absolutePath();
424  return true;
425  }
426  }
427  }
428 
429  QStringList list = GlobalConfig::sourceDirs(_data,
430  sf->function()->object());
431  QStringList::const_iterator it;
432  for ( it = list.constBegin(); it != list.constEnd(); ++it ) {
433  dir = *it;
434  if (searchFileRecursive(dir, name)) return true;
435  }
436 
437  return false;
438 }
439 
440 
441 void SourceView::updateJumpArray(uint lineno, SourceItem* si,
442  bool ignoreFrom, bool ignoreTo)
443 {
444  uint lowLineno, highLineno;
445  int iEnd = -1, iStart = -1;
446 
447  if (0) qDebug("updateJumpArray(line %d, jump to %s)",
448  lineno,
449  si->lineJump()
450  ? qPrintable(si->lineJump()->lineTo()->name()) : "?" );
451 
452  while(_lowListIter != _lowList.end()) {
453  TraceLineJump* lj= *_lowListIter;
454  lowLineno = lj->lineFrom()->lineno();
455  if (lj->lineTo()->lineno() < lowLineno)
456  lowLineno = lj->lineTo()->lineno();
457 
458  if (lowLineno > lineno) break;
459 
460  if (ignoreFrom && (lowLineno < lj->lineTo()->lineno())) break;
461  if (ignoreTo && (lowLineno < lj->lineFrom()->lineno())) break;
462 
463  if (si->lineJump() && (lj != si->lineJump())) break;
464 
465  int asize = (int)_jump.size();
466 #if 0
467  for(iStart=0;iStart<asize;iStart++)
468  if (_jump[iStart] &&
469  (_jump[iStart]->lineTo() == lj->lineTo())) break;
470 #else
471  iStart = asize;
472 #endif
473 
474  if (iStart == asize) {
475  for(iStart=0;iStart<asize;iStart++)
476  if (_jump[iStart] == 0) break;
477 
478  if (iStart== asize) {
479  asize++;
480  _jump.resize(asize);
481  if (asize > _arrowLevels) _arrowLevels = asize;
482  }
483 
484  if (0) qDebug(" start %d (%s to %s)",
485  iStart,
486  qPrintable(lj->lineFrom()->name()),
487  qPrintable(lj->lineTo()->name()));
488 
489  _jump[iStart] = lj;
490  }
491  _lowListIter++;
492  }
493 
494  si->setJumpArray(_jump);
495 
496  while(_highListIter != _highList.end()) {
497  TraceLineJump* lj= *_highListIter;
498  highLineno = lj->lineFrom()->lineno();
499  if (lj->lineTo()->lineno() > highLineno) {
500  highLineno = lj->lineTo()->lineno();
501  if (ignoreTo) break;
502  }
503  else if (ignoreFrom) break;
504 
505  if (highLineno > lineno) break;
506 
507  for(iEnd=0;iEnd< (int)_jump.size();iEnd++)
508  if (_jump[iEnd] == lj) break;
509  if (iEnd == (int)_jump.size()) {
510  qDebug("LineView: no jump start for end at %x ?", highLineno);
511  iEnd = -1;
512  }
513 
514  if (0 && (iEnd>=0))
515  qDebug(" end %d (%s to %s)",
516  iEnd,
517  qPrintable(_jump[iEnd]->lineFrom()->name()),
518  qPrintable(_jump[iEnd]->lineTo()->name()));
519 
520  if (0 && lj) qDebug("next end: %s to %s",
521  qPrintable(lj->lineFrom()->name()),
522  qPrintable(lj->lineTo()->name()));
523 
524  _highListIter++;
525 
526  if (highLineno > lineno)
527  break;
528  else {
529  if (iEnd>=0) _jump[iEnd] = 0;
530  iEnd = -1;
531  }
532  }
533  if (iEnd>=0) _jump[iEnd] = 0;
534 }
535 
536 
537 // compare functions for jump arrow drawing
538 
539 void getJumpLines(const TraceLineJump* jump, uint& low, uint& high)
540 {
541  low = jump->lineFrom()->lineno();
542  high = jump->lineTo()->lineno();
543 
544  if (low > high) {
545  uint t = low;
546  low = high;
547  high = t;
548  }
549 }
550 
551 // sort jumps according to lower line number
552 bool lineJumpLowLessThan(const TraceLineJump* jump1,
553  const TraceLineJump* jump2)
554 {
555  uint line1Low, line1High, line2Low, line2High;
556 
557  getJumpLines(jump1, line1Low, line1High);
558  getJumpLines(jump2, line2Low, line2High);
559 
560  if (line1Low != line2Low) return (line1Low < line2Low);
561  // jump ends come before jump starts
562  if (line1Low == jump1->lineTo()->lineno()) return true;
563  if (line2Low == jump2->lineTo()->lineno()) return false;
564  return (line1High < line2High);
565 }
566 
567 // sort jumps according to higher line number
568 bool lineJumpHighLessThan(const TraceLineJump* jump1,
569  const TraceLineJump* jump2)
570 {
571  uint line1Low, line1High, line2Low, line2High;
572 
573  getJumpLines(jump1, line1Low, line1High);
574  getJumpLines(jump2, line2Low, line2High);
575 
576  if (line1High != line2High) return (line1High < line2High);
577  // jump ends come before jump starts
578  if (line1High == jump1->lineTo()->lineno()) return true;
579  if (line2High == jump2->lineTo()->lineno()) return false;
580  return (line1Low < line2Low);
581 }
582 
583 /* If sourceList is empty we set the source file name into the header,
584  * else this code is of a inlined function, and we add "inlined from..."
585  */
586 void SourceView::fillSourceFile(TraceFunctionSource* sf, int fileno)
587 {
588  if (!sf) return;
589 
590  if (0) qDebug("Selected Item %s",
591  _selectedItem ? qPrintable(_selectedItem->name()) : "(none)");
592 
593  TraceLineMap::Iterator lineIt, lineItEnd;
594  int nextCostLineno = 0, lastCostLineno = 0;
595 
596  bool validSourceFile = (!sf->file()->name().isEmpty());
597 
598  TraceLine* sLine = 0;
599  if (_selectedItem) {
600  if (_selectedItem->type() == ProfileContext::Line)
601  sLine = (TraceLine*) _selectedItem;
602  if (_selectedItem->type() == ProfileContext::Instr)
603  sLine = ((TraceInstr*)_selectedItem)->line();
604  }
605 
606  if (validSourceFile) {
607  TraceLineMap* lineMap = sf->lineMap();
608  if (lineMap) {
609  lineIt = lineMap->begin();
610  lineItEnd = lineMap->end();
611  // get first line with cost of selected type
612  while(lineIt != lineItEnd) {
613  if (&(*lineIt) == sLine) break;
614  if ((*lineIt).hasCost(_eventType)) break;
615  if (_eventType2 && (*lineIt).hasCost(_eventType2)) break;
616  ++lineIt;
617  }
618 
619  nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
620  if (nextCostLineno<0) {
621  qDebug() << "SourceView::fillSourceFile: Negative line number "
622  << nextCostLineno;
623  qDebug() << " Function '" << sf->function()->name() << "'";
624  qDebug() << " File '" << sf->file()->name() << "'";
625  nextCostLineno = 0;
626  }
627 
628  }
629 
630  if (nextCostLineno == 0) {
631  new SourceItem(this, this, fileno, 1, false,
632  tr("There is no cost of current selected type associated"));
633  new SourceItem(this, this, fileno, 2, false,
634  tr("with any source line of this function in file"));
635  new SourceItem(this, this, fileno, 3, false,
636  QString(" '%1'").arg(sf->file()->prettyName()));
637  new SourceItem(this, this, fileno, 4, false,
638  tr("Thus, no annotated source can be shown."));
639  return;
640  }
641  }
642 
643  QString filename = sf->file()->shortName();
644  QString dir = sf->file()->directory();
645  if (!dir.isEmpty())
646  filename = dir + '/' + filename;
647 
648  if (nextCostLineno>0) {
649  // we have debug info... search for source file
650  if (searchFile(dir, sf)) {
651  filename = dir + '/' + sf->file()->shortName();
652  // no need to search again
653  sf->file()->setDirectory(dir);
654  }
655  else
656  nextCostLineno = 0;
657  }
658 
659  // do it here, because the source directory could have been set before
660  if (topLevelItemCount()==0) {
661  headerItem()->setText(4, validSourceFile ?
662  tr("Source ('%1')").arg(filename) :
663  tr("Source (unknown)"));
664  }
665  else {
666  new SourceItem(this, this, fileno, 0, true,
667  validSourceFile ?
668  tr("--- Inlined from '%1' ---").arg(filename) :
669  tr("--- Inlined from unknown source ---"));
670  }
671 
672  if (nextCostLineno == 0) {
673  new SourceItem(this, this, fileno, 1, false,
674  tr("There is no source available for the following function:"));
675  new SourceItem(this, this, fileno, 2, false,
676  QString(" '%1'").arg(sf->function()->prettyName()));
677  if (sf->file()->name().isEmpty()) {
678  new SourceItem(this, this, fileno, 3, false,
679  tr("This is because no debug information is present."));
680  new SourceItem(this, this, fileno, 4, false,
681  tr("Recompile source and redo the profile run."));
682  if (sf->function()->object()) {
683  new SourceItem(this, this, fileno, 5, false,
684  tr("The function is located in this ELF object:"));
685  new SourceItem(this, this, fileno, 6, false,
686  QString(" '%1'")
687  .arg(sf->function()->object()->prettyName()));
688  }
689  }
690  else {
691  new SourceItem(this, this, fileno, 3, false,
692  tr("This is because its source file cannot be found:"));
693  new SourceItem(this, this, fileno, 4, false,
694  QString(" '%1'").arg(sf->file()->name()));
695  new SourceItem(this, this, fileno, 5, false,
696  tr("Add the folder of this file to the source folder list."));
697  new SourceItem(this, this, fileno, 6, false,
698  tr("The list can be found in the configuration dialog."));
699  }
700  return;
701  }
702 
703  // initialisation for arrow drawing
704  // create sorted list of jumps (for jump arrows)
705  TraceLineMap::Iterator it = lineIt, nextIt;
706  _lowList.clear();
707  _highList.clear();
708  while(1) {
709 
710  nextIt = it;
711  ++nextIt;
712  while(nextIt != lineItEnd) {
713  if (&(*nextIt) == sLine) break;
714  if ((*nextIt).hasCost(_eventType)) break;
715  if (_eventType2 && (*nextIt).hasCost(_eventType2)) break;
716  ++nextIt;
717  }
718 
719  TraceLineJumpList jlist = (*it).lineJumps();
720  foreach(TraceLineJump* lj, jlist) {
721  if (lj->executedCount()==0) continue;
722  // skip jumps to next source line with cost
723  //if (lj->lineTo() == &(*nextIt)) continue;
724 
725  _lowList.append(lj);
726  _highList.append(lj);
727  }
728  it = nextIt;
729  if (it == lineItEnd) break;
730  }
731  qSort(_lowList.begin(), _lowList.end(), lineJumpLowLessThan);
732  qSort(_highList.begin(), _highList.end(), lineJumpHighLessThan);
733  _lowListIter = _lowList.begin(); // iterators to list start
734  _highListIter = _highList.begin();
735  _jump.resize(0);
736 
737  char buf[160];
738  bool inside = false, skipLineWritten = true;
739  int readBytes;
740  int fileLineno = 0;
741  SubCost most = 0;
742 
743  QList<QTreeWidgetItem*> items;
744  TraceLine* currLine;
745  SourceItem *si, *si2, *item = 0, *first = 0, *selected = 0;
746  QFile file(filename);
747  bool fileEndReached = false;
748  if (!file.open(QIODevice::ReadOnly)) return;
749  while (1) {
750  readBytes=file.readLine(buf, sizeof( buf ));
751  if (readBytes<=0) {
752  // for nice empty 4 lines after function with EOF
753  buf[0] = 0;
754  if (readBytes<0) fileEndReached = true;
755  }
756 
757  if ((readBytes >0) && (buf[readBytes-1] != '\n')) {
758  /* Something was read but not ending in newline. I.e.
759  * - buffer was not big enough: discard rest of line, add "..."
760  * - this is last line of file, not ending in newline
761  * NB: checking for '\n' is enough for all systems.
762  */
763  int r;
764  char buf2[32];
765  bool somethingRead = false;
766  while(1) {
767  r = file.readLine(buf2, sizeof(buf2));
768  if ((r<=0) || (buf2[r-1] == '\n')) break;
769  somethingRead = true;
770  }
771  if (somethingRead) {
772  // add dots as sign that we truncated the line
773  Q_ASSERT(readBytes>3);
774  buf[readBytes-1] = buf[readBytes-2] = buf[readBytes-3] = '.';
775  }
776  }
777  else if ((readBytes>0) && (buf[readBytes-1] == '\n'))
778  buf[readBytes-1] = 0;
779 
780 
781  // keep fileLineno inside [lastCostLineno;nextCostLineno]
782  fileLineno++;
783  if (fileLineno == nextCostLineno) {
784  currLine = &(*lineIt);
785 
786  // get next line with cost of selected type
787  ++lineIt;
788  while(lineIt != lineItEnd) {
789  if (&(*lineIt) == sLine) break;
790  if ((*lineIt).hasCost(_eventType)) break;
791  if (_eventType2 && (*lineIt).hasCost(_eventType2)) break;
792  ++lineIt;
793  }
794 
795  lastCostLineno = nextCostLineno;
796  nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
797  }
798  else
799  currLine = 0;
800 
801  // update inside
802  if (!inside) {
803  if (currLine) inside = true;
804  }
805  else {
806  if ( (fileLineno > lastCostLineno) &&
807  ((nextCostLineno == 0) ||
808  (fileLineno < nextCostLineno - GlobalConfig::noCostInside()) ))
809  inside = false;
810  }
811 
812  int context = GlobalConfig::context();
813 
814  if ( ((lastCostLineno==0) || (fileLineno > lastCostLineno + context)) &&
815  ((nextCostLineno==0) || (fileLineno < nextCostLineno - context))) {
816  if ((lineIt == lineItEnd) || fileEndReached) break;
817 
818  if (!skipLineWritten) {
819  skipLineWritten = true;
820  // a "skipping" line: print "..." instead of a line number
821  strcpy(buf,"...");
822  }
823  else
824  continue;
825  }
826  else
827  skipLineWritten = false;
828 
829  QString s = QString(buf);
830  if(s.size() > 0 && s.at(s.length()-1) == '\r')
831  s = s.left(s.length()-1);
832  si = new SourceItem(this, 0,
833  fileno, fileLineno, inside, s,
834  currLine);
835  items.append(si);
836 
837  if (!currLine) continue;
838 
839  if (!selected && (currLine == sLine)) selected = si;
840  if (!first) first = si;
841 
842  if (currLine->subCost(_eventType) > most) {
843  item = si;
844  most = currLine->subCost(_eventType);
845  }
846 
847  si->setExpanded(true);
848  foreach(TraceLineCall* lc, currLine->lineCalls()) {
849  if ((lc->subCost(_eventType)==0) &&
850  (lc->subCost(_eventType2)==0)) continue;
851 
852  if (lc->subCost(_eventType) > most) {
853  item = si;
854  most = lc->subCost(_eventType);
855  }
856 
857  si2 = new SourceItem(this, si, fileno, fileLineno, currLine, lc);
858 
859  if (!selected && (lc->call()->called() == _selectedItem))
860  selected = si2;
861  }
862 
863  foreach(TraceLineJump* lj, currLine->lineJumps()) {
864  if (lj->executedCount()==0) continue;
865 
866  new SourceItem(this, si, fileno, fileLineno, currLine, lj);
867  }
868  }
869 
870  file.close();
871 
872  // Resize column 0 (line number) and 1/2 (cost) to contents
873 #if QT_VERSION >= 0x050000
874  header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
875  header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
876  header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
877 #else
878  header()->setResizeMode(0, QHeaderView::ResizeToContents);
879  header()->setResizeMode(1, QHeaderView::ResizeToContents);
880  header()->setResizeMode(2, QHeaderView::ResizeToContents);
881 #endif
882 
883  setSortingEnabled(false);
884  addTopLevelItems(items);
885  this->expandAll();
886  setSortingEnabled(true);
887  // always reset to line number sort
888  sortByColumn(0, Qt::AscendingOrder);
889  header()->setSortIndicatorShown(false);
890 
891  // Reallow interactive column size change after resizing to content
892 #if QT_VERSION >= 0x050000
893  header()->setSectionResizeMode(0, QHeaderView::Interactive);
894  header()->setSectionResizeMode(1, QHeaderView::Interactive);
895  header()->setSectionResizeMode(2, QHeaderView::Interactive);
896 #else
897  header()->setResizeMode(0, QHeaderView::Interactive);
898  header()->setResizeMode(1, QHeaderView::Interactive);
899  header()->setResizeMode(2, QHeaderView::Interactive);
900 #endif
901 
902  if (selected) item = selected;
903  if (item) first = item;
904  if (first) {
905  scrollToItem(first);
906  _inSelectionUpdate = true;
907  setCurrentItem(first);
908  _inSelectionUpdate = false;
909  }
910 
911  // for arrows: go down the list according to list sorting
912  QTreeWidgetItem *item1, *item2;
913  for (int i=0; i<topLevelItemCount(); i++) {
914  item1 = topLevelItem(i);
915  si = (SourceItem*)item1;
916  updateJumpArray(si->lineno(), si, true, false);
917 
918  for (int j=0; j<item1->childCount(); j++) {
919  item2 = item1->child(j);
920  si2 = (SourceItem*)item2;
921  if (si2->lineJump())
922  updateJumpArray(si->lineno(), si2, false, true);
923  else
924  si2->setJumpArray(_jump);
925  }
926  }
927 
928  if (arrowLevels())
929  //fix this: setColumnWidth(3, 10 + 6*arrowLevels() + itemMargin() * 2);
930  setColumnWidth(3, 10 + 6*arrowLevels() + 2);
931  else
932  setColumnWidth(3, 0);
933 }
934 
935 
936 void SourceView::headerClicked(int col)
937 {
938  if (col == 0) {
939  sortByColumn(col, Qt::AscendingOrder);
940  }
941  //All others but Source Text column Descending
942  else if (col !=4) {
943  sortByColumn(col, Qt::DescendingOrder);
944  }
945 }
946 
947 #include "sourceview.moc"
QWidget::customContextMenuRequested
void customContextMenuRequested(const QPoint &pos)
TraceItemView::selectedItemChanged
Definition: traceitemview.h:86
QList::clear
void clear()
QWidget
TraceItemView::_selectedItem
CostItem * _selectedItem
Definition: traceitemview.h:211
TracePart::name
QString name() const
Definition: tracedata.h:667
ProfileCostArray::subCost
SubCost subCost(EventType *)
Returns a sub cost.
Definition: costitem.cpp:591
globalconfig.h
ProfileContext::Line
Definition: context.h:39
SourceView::selectedSlot
void selectedSlot(QTreeWidgetItem *, QTreeWidgetItem *)
Definition: sourceview.cpp:145
GlobalConfig::sourceDirs
static QStringList sourceDirs(TraceData *, TraceObject *o=0)
Definition: globalconfig.cpp:305
QTreeWidgetItem::child
QTreeWidgetItem * child(int index) const
QTreeWidget::currentItemChanged
void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
TraceObject::prettyName
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
Definition: tracedata.cpp:2959
QTreeWidget::scrollToItem
void scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
TraceItemView::addEventTypeMenu
void addEventTypeMenu(QMenu *, bool withCost2=true)
Definition: traceitemview.cpp:466
TraceLineJump::lineTo
TraceLine * lineTo() const
Definition: tracedata.h:764
CostItem::type
ProfileContext::Type type() const
Definition: costitem.h:45
QMap
TraceFunction
A traced function.
Definition: tracedata.h:1122
QString::size
int size() const
TraceItemView::_data
TraceData * _data
Definition: traceitemview.h:209
QMenu::addAction
void addAction(QAction *action)
TraceJumpCost::executedCount
SubCost executedCount()
Definition: tracedata.cpp:55
TraceFile::setDirectory
void setDirectory(const QString &dir)
Definition: tracedata.cpp:2826
TraceFunctionSource::function
TraceFunction * function() const
Definition: tracedata.h:1041
TraceItemView::addGoMenu
void addGoMenu(QMenu *)
Definition: traceitemview.cpp:471
QWidget::mapToGlobal
QPoint mapToGlobal(const QPoint &pos) const
TraceFunction::object
TraceObject * object() const
Definition: tracedata.h:1164
QDir::filePath
QString filePath(const QString &fileName) const
SourceView::headerClicked
void headerClicked(int)
Definition: sourceview.cpp:936
QTreeWidget::items
QList< QTreeWidgetItem * > items(const QMimeData *data) const
QTreeView::setUniformRowHeights
void setUniformRowHeights(bool uniform)
CostItem
Base class for cost items.
Definition: costitem.h:37
SourceItem::lineno
uint lineno() const
Definition: sourceitem.h:52
QHeaderView::setSortIndicatorShown
void setSortIndicatorShown(bool show)
TraceLineCall
A call from a line of one function to another function.
Definition: tracedata.h:808
ProfileContext::Instr
Definition: context.h:38
QPoint
TraceFunctionSource::firstLineno
uint firstLineno()
Definition: tracedata.cpp:1532
SourceView::SourceItem
friend class SourceItem
Definition: sourceview.h:33
QTreeView::sortByColumn
void sortByColumn(int column, Qt::SortOrder order)
QFile::exists
bool exists() const
QDir::currentPath
QString currentPath()
TraceLine::lineJumps
const TraceLineJumpList & lineJumps() const
Definition: tracedata.h:957
QDir::setSorting
void setSorting(QFlags< QDir::SortFlag > sort)
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
SourceView::activatedSlot
void activatedSlot(QTreeWidgetItem *, int)
Definition: sourceview.cpp:177
QList::const_iterator
sourceview.h
QFile
QPoint::x
int x() const
SourceView::keyPressEvent
void keyPressEvent(QKeyEvent *event)
Definition: sourceview.cpp:198
TraceItemView::_eventType2
EventType * _eventType2
Definition: traceitemview.h:212
QTreeWidget::clear
void clear()
TraceItemView
Abstract Base Class for KCachegrind Views.
Definition: traceitemview.h:70
SourceItem::setJumpArray
void setJumpArray(const QVector< TraceLineJump * > &a)
Definition: sourceitem.cpp:288
TraceData::parts
TracePartList parts() const
Definition: tracedata.h:1397
QTreeWidget
TraceItemView::_eventType
EventType * _eventType
Definition: traceitemview.h:212
QObject::name
const char * name() const
QDir::setFilter
void setFilter(QFlags< QDir::Filter > filters)
QTreeView::setColumnWidth
void setColumnWidth(int column, int width)
QList::count
int count(const T &value) const
SourceView::context
void context(const QPoint &)
Definition: sourceview.cpp:107
QList::append
void append(const T &value)
QVector::resize
void resize(int size)
TraceInstr
A code instruction address of the program.
Definition: tracedata.h:887
getJumpLines
void getJumpLines(const TraceLineJump *jump, uint &low, uint &high)
Definition: sourceview.cpp:539
QTreeWidget::addTopLevelItems
void addTopLevelItems(const QList< QTreeWidgetItem * > &items)
CostItem::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: costitem.cpp:53
TraceLine::lineCalls
const TraceLineCallList & lineCalls() const
Definition: tracedata.h:956
TraceLineCall::call
TraceCall * call() const
Definition: tracedata.h:817
TraceFile::prettyName
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
Definition: tracedata.cpp:2858
QString::isEmpty
bool isEmpty() const
QAbstractItemView::setItemDelegate
void setItemDelegate(QAbstractItemDelegate *delegate)
SourceView::arrowLevels
int arrowLevels()
Definition: sourceview.h:43
TraceFunctionSource
A container helper class for TraceFunction for source lines where a function is implemented in...
Definition: tracedata.h:1029
lineJumpHighLessThan
bool lineJumpHighLessThan(const TraceLineJump *jump1, const TraceLineJump *jump2)
Definition: sourceview.cpp:568
QTreeWidget::itemAt
QTreeWidgetItem * itemAt(const QPoint &p) const
GlobalConfig::context
static int context()
Definition: globalconfig.cpp:412
TraceCostItem::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.h:986
TraceFunction::prettyName
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
Definition: tracedata.cpp:1889
SourceView::whatsThis
QString whatsThis() const
Definition: sourceview.cpp:92
TraceLine::lineno
uint lineno() const
Definition: tracedata.h:955
QList::first
T & first()
TraceItemView::_activeItem
CostItem * _activeItem
Definition: traceitemview.h:211
searchFileRecursive
static bool searchFileRecursive(QString &dir, const QString &name)
Definition: sourceview.cpp:375
QTreeView::setAllColumnsShowFocus
void setAllColumnsShowFocus(bool enable)
QMenu::addSeparator
QAction * addSeparator()
QTreeWidget::currentItem
QTreeWidgetItem * currentItem() const
QString
QList
QMap::end
iterator end()
TraceLine
A source line of the program.
Definition: tracedata.h:935
QAbstractScrollArea::verticalScrollBar
QScrollBar * verticalScrollBar() const
GlobalConfig::shortenSymbol
static QString shortenSymbol(const QString &)
Definition: globalconfig.cpp:395
QMenu::exec
QAction * exec()
QTreeWidget::setColumnCount
void setColumnCount(int columns)
QMap::begin
iterator begin()
QStringList
TraceLine::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.cpp:1475
QFileInfo
QList::end
iterator end()
TraceItemView::selected
virtual void selected(TraceItemView *sender, CostItem *)
Notification from child views.
Definition: traceitemview.cpp:319
QKeyEvent::key
int key() const
QMenu
TraceFunctionSource::file
TraceFile * file() const
Definition: tracedata.h:1040
TraceItemView::activated
virtual void activated(TraceItemView *sender, CostItem *)
Definition: traceitemview.cpp:347
QWidget::setContextMenuPolicy
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
QAbstractSlider::value
value
QTreeView::expandAll
void expandAll()
lineJumpLowLessThan
bool lineJumpLowLessThan(const TraceLineJump *jump1, const TraceLineJump *jump2)
Definition: sourceview.cpp:552
SourceView::SourceView
SourceView(TraceItemView *parentView, QWidget *parent=0)
Definition: sourceview.cpp:45
TraceFunction::sourceFiles
const TraceFunctionSourceList & sourceFiles() const
Definition: tracedata.h:1168
QTreeWidget::selectedItems
QList< QTreeWidgetItem * > selectedItems() const
QTreeWidget::setCurrentItem
void setCurrentItem(QTreeWidgetItem *item)
QDir
QTreeWidget::setHeaderLabels
void setHeaderLabels(const QStringList &labels)
QKeyEvent
SourceItem::lineCall
TraceLineCall * lineCall() const
Definition: sourceitem.h:56
QTreeView::setExpandsOnDoubleClick
void setExpandsOnDoubleClick(bool enable)
QTreeWidget::headerItem
QTreeWidgetItem * headerItem() const
TraceLineJump::lineFrom
TraceLine * lineFrom() const
Definition: tracedata.h:763
QTreeView::setSortingEnabled
void setSortingEnabled(bool enable)
QTreeWidgetItem::setExpanded
void setExpanded(bool expand)
TracePart
A Trace Part: All data read from a trace file, containing all costs that happened in a specified time...
Definition: tracedata.h:655
QWidget::setWhatsThis
void setWhatsThis(const QString &)
QDir::isAbsolutePath
bool isAbsolutePath(const QString &path)
QTreeWidgetItem
ProfileContext::Type
Type
Definition: context.h:36
QDir::entryList
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
SubCost
Cost event counter, simple wrapper around a 64bit entity.
Definition: subcost.h:32
TraceFunction::sourceFile
TraceFunctionSource * sourceFile(TraceFile *file=0, bool createNew=false)
Definition: tracedata.cpp:2169
QHeaderView::setResizeMode
void setResizeMode(ResizeMode mode)
QString::at
const QChar at(int position) const
QAction
SourceItem::lineJump
TraceLineJump * lineJump() const
Definition: sourceitem.h:57
TraceCall::called
TraceFunction * called(bool skipCycle=false) const
Definition: tracedata.cpp:1235
QTreeWidgetItem::setText
void setText(int column, const QString &text)
sourceitem.h
TraceItemView::groupTypeChanged
Definition: traceitemview.h:83
QString::length
int length() const
QString::left
QString left(int n) const
TraceFunctionSource::lastLineno
uint lastLineno()
Definition: tracedata.cpp:1542
QTreeView::header
QHeaderView * header() const
TraceFile::directory
QString directory()
Definition: tracedata.cpp:2834
QMap::Iterator
typedef Iterator
QTreeWidget::topLevelItem
QTreeWidgetItem * topLevelItem(int index) const
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
QTreeView::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
QTreeView::setRootIsDecorated
void setRootIsDecorated(bool show)
GlobalConfig::noCostInside
static int noCostInside()
Definition: globalconfig.cpp:417
QTreeWidget::topLevelItemCount
int topLevelItemCount() const
QAbstractItemView::clearSelection
void clearSelection()
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QVector::size
int size() const
QTreeWidgetItem::childCount
int childCount() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
TraceFile::shortName
QString shortName() const
Definition: tracedata.cpp:2849
QTreeWidget::itemDoubleClicked
void itemDoubleClicked(QTreeWidgetItem *item, int column)
QList::begin
iterator begin()
TraceLineJump
A jump from one line to another inside of a function.
Definition: tracedata.h:754
SourceItemDelegate
Definition: sourceitem.h:84
QTreeView::columnAt
int columnAt(int x) const
QWidget::height
int height() const
SourceItem
Definition: sourceitem.h:33
EventType::name
const QString & name()
Definition: eventtype.h:65
ProfileContext::Function
Definition: context.h:46
ProfileContext::InvalidType
Definition: context.h:37
TraceFunctionSource::lineMap
TraceLineMap * lineMap()
Definition: tracedata.cpp:1618
SourceItem::line
TraceLine * line() const
Definition: sourceitem.h:55
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:39:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kcachegrind

Skip menu "kcachegrind"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal