32 #include <QHeaderView>
49 _inSelectionUpdate =
false;
55 setRootIsDecorated(
false);
56 setAllColumnsShowFocus(
true);
57 setUniformRowHeights(
true);
59 setExpandsOnDoubleClick(
false);
61 QStringList headerLabels;
62 headerLabels << tr(
"#" )
66 << tr(
"Source (unknown)");
67 setHeaderLabels(headerLabels);
70 sortByColumn(0, Qt::AscendingOrder);
71 header()->setSortIndicatorShown(
false);
79 setContextMenuPolicy(Qt::CustomContextMenu);
81 SIGNAL(customContextMenuRequested(
const QPoint &) ),
88 connect(header(), SIGNAL(sectionClicked(
int)),
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>");
109 int c = columnAt(p.x());
118 QAction* activateFunctionAction = 0;
119 QAction* activateLineAction = 0;
122 activateFunctionAction = popup.addAction(menuText);
123 popup.addSeparator();
126 QString menuText = tr(
"Go to Line %1").arg(line->
name());
127 activateLineAction = popup.addAction(menuText);
128 popup.addSeparator();
131 if ((c == 1) || (c == 2)) {
133 popup.addSeparator();
137 QAction* a = popup.exec(mapToGlobal(p + QPoint(0,header()->height())));
138 if (a == activateFunctionAction)
140 else if (a == activateLineAction)
149 if (_inSelectionUpdate)
return;
201 if (item && ((event->key() == Qt::Key_Return) ||
202 (event->key() == Qt::Key_Space)))
206 QTreeView::keyPressEvent(event);
225 f = ((
TraceLine*)i)->functionSource()->function();
236 void SourceView::doUpdate(
int changeType,
bool)
257 if (si->
line() == sLine)
return;
263 for (
int i=0; i<topLevelItemCount(); i++) {
264 item = topLevelItem(i);
266 if (si->
line() == sLine) {
268 _inSelectionUpdate =
true;
269 setCurrentItem(item);
270 _inSelectionUpdate =
false;
274 for (
int j=0; i<item->childCount(); j++) {
275 item2 = item->child(j);
280 _inSelectionUpdate =
true;
281 setCurrentItem(item2);
282 _inSelectionUpdate =
false;
294 for (
int i=0; i<topLevelItemCount(); i++) {
295 item = topLevelItem(i);
296 for (
int j=0; i<item->childCount(); i++) {
297 item2 = item->child(j);
311 void SourceView::refresh()
313 int originalPosition = verticalScrollBar()->value();
315 setColumnWidth(0, 20);
316 setColumnWidth(1, 50);
318 setColumnWidth(3, 0);
326 headerItem()->setText(4, tr(
"(No Source)"));
355 fillSourceFile(mainSF, 0);
361 fillSourceFile(sf, fileno);
365 #if QT_VERSION >= 0x050000
366 header()->setSectionResizeMode(2, QHeaderView::Interactive);
368 header()->setResizeMode(2, QHeaderView::Interactive);
370 setColumnWidth(2, 0);
374 verticalScrollBar()->setValue(originalPosition);
385 qDebug(
"Checking %s/%s", qPrintable(dir), qPrintable(name));
387 if (QFile::exists(dir +
'/' + name))
return true;
391 d.setFilter( QDir::Dirs | QDir::NoSymLinks );
392 d.setSorting( QDir::Unsorted );
393 QStringList subdirs = d.entryList();
394 QStringList::const_iterator it =subdirs.constBegin();
395 for(; it != subdirs.constEnd(); ++it ) {
396 if (*it ==
"." || *it ==
".." || *it ==
"CVS")
continue;
398 dir = d.filePath(*it);
407 bool SourceView::searchFile(QString& dir,
412 if (QDir::isAbsolutePath(dir)) {
413 if (QFile::exists(dir +
'/' + name))
return true;
420 QString base = QDir::currentPath() +
'/' + dir;
421 if (QFile::exists(base +
'/' + name)) {
428 QFileInfo partFile(firstPart->
name());
429 if (QFileInfo(partFile.absolutePath(), name).exists()) {
430 dir = partFile.absolutePath();
438 QStringList::const_iterator it;
439 for ( it = list.constBegin(); it != list.constEnd(); ++it ) {
448 void SourceView::updateJumpArray(uint lineno,
SourceItem* si,
449 bool ignoreFrom,
bool ignoreTo)
451 uint lowLineno, highLineno;
452 int iEnd = -1, iStart = -1;
454 if (0) qDebug(
"updateJumpArray(line %d, jump to %s)",
459 while(_lowListIter != _lowList.end()) {
465 if (lowLineno > lineno)
break;
467 if (ignoreFrom && (lowLineno < lj->lineTo()->lineno()))
break;
468 if (ignoreTo && (lowLineno < lj->lineFrom()->lineno()))
break;
472 int asize = (int)_jump.size();
474 for(iStart=0;iStart<asize;iStart++)
476 (_jump[iStart]->lineTo() == lj->
lineTo()))
break;
481 if (iStart == asize) {
482 for(iStart=0;iStart<asize;iStart++)
483 if (_jump[iStart] == 0)
break;
485 if (iStart== asize) {
488 if (asize > _arrowLevels) _arrowLevels = asize;
491 if (0) qDebug(
" start %d (%s to %s)",
503 while(_highListIter != _highList.end()) {
510 else if (ignoreFrom)
break;
512 if (highLineno > lineno)
break;
514 for(iEnd=0;iEnd< (int)_jump.size();iEnd++)
515 if (_jump[iEnd] == lj)
break;
516 if (iEnd == (
int)_jump.size()) {
517 qDebug(
"LineView: no jump start for end at %x ?", highLineno);
522 qDebug(
" end %d (%s to %s)",
524 qPrintable(_jump[iEnd]->lineFrom()->name()),
525 qPrintable(_jump[iEnd]->lineTo()->name()));
527 if (0 && lj) qDebug(
"next end: %s to %s",
533 if (highLineno > lineno)
536 if (iEnd>=0) _jump[iEnd] = 0;
540 if (iEnd>=0) _jump[iEnd] = 0;
562 uint line1Low, line1High, line2Low, line2High;
567 if (line1Low != line2Low)
return (line1Low < line2Low);
570 if (line2Low == jump2->
lineTo()->
lineno())
return false;
571 return (line1High < line2High);
578 uint line1Low, line1High, line2Low, line2High;
583 if (line1High != line2High)
return (line1High < line2High);
585 if (line1High == jump1->
lineTo()->
lineno())
return true;
586 if (line2High == jump2->
lineTo()->
lineno())
return false;
587 return (line1Low < line2Low);
597 if (0) qDebug(
"Selected Item %s",
600 TraceLineMap::Iterator lineIt, lineItEnd;
601 int nextCostLineno = 0, lastCostLineno = 0;
603 bool validSourceFile = (!sf->
file()->
name().isEmpty());
613 if (validSourceFile) {
616 lineIt = lineMap->begin();
617 lineItEnd = lineMap->end();
619 while(lineIt != lineItEnd) {
620 if (&(*lineIt) == sLine)
break;
626 nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
627 if (nextCostLineno<0) {
628 qDebug() <<
"SourceView::fillSourceFile: Negative line number "
630 qDebug() <<
" Function '" << sf->
function()->
name() <<
"'";
631 qDebug() <<
" File '" << sf->
file()->
name() <<
"'";
637 if (nextCostLineno == 0) {
639 tr(
"There is no cost of current selected type associated"));
641 tr(
"with any source line of this function in file"));
645 tr(
"Thus, no annotated source can be shown."));
653 filename = dir +
'/' + filename;
655 if (nextCostLineno>0) {
657 if (searchFile(dir, sf)) {
667 if (topLevelItemCount()==0) {
668 headerItem()->setText(4, validSourceFile ?
669 tr(
"Source ('%1')").arg(filename) :
670 tr(
"Source (unknown)"));
675 tr(
"--- Inlined from '%1' ---").arg(filename) :
676 tr(
"--- Inlined from unknown source ---"));
679 if (nextCostLineno == 0) {
681 tr(
"There is no source available for the following function:"));
686 tr(
"This is because no debug information is present."));
688 tr(
"Recompile source and redo the profile run."));
691 tr(
"The function is located in this ELF object:"));
699 tr(
"This is because its source file cannot be found:"));
701 QString(
" '%1'").arg(sf->
file()->
name()));
703 tr(
"Add the folder of this file to the source folder list."));
705 tr(
"The list can be found in the configuration dialog."));
712 TraceLineMap::Iterator it = lineIt, nextIt;
719 while(nextIt != lineItEnd) {
720 if (&(*nextIt) == sLine)
break;
733 _highList.append(lj);
736 if (it == lineItEnd)
break;
740 _lowListIter = _lowList.begin();
741 _highListIter = _highList.begin();
745 bool inside =
false, skipLineWritten =
true;
753 QFile file(filename);
754 bool fileEndReached =
false;
755 if (!file.open(QIODevice::ReadOnly))
return;
757 readBytes=file.readLine(buf,
sizeof( buf ));
761 if (readBytes<0) fileEndReached =
true;
764 if ((readBytes >0) && (buf[readBytes-1] !=
'\n')) {
772 bool somethingRead =
false;
774 r = file.readLine(buf2,
sizeof(buf2));
775 if ((r<=0) || (buf2[r-1] ==
'\n'))
break;
776 somethingRead =
true;
780 Q_ASSERT(readBytes>3);
781 buf[readBytes-1] = buf[readBytes-2] = buf[readBytes-3] =
'.';
784 else if ((readBytes>0) && (buf[readBytes-1] ==
'\n'))
785 buf[readBytes-1] = 0;
790 if (fileLineno == nextCostLineno) {
791 currLine = &(*lineIt);
795 while(lineIt != lineItEnd) {
796 if (&(*lineIt) == sLine)
break;
802 lastCostLineno = nextCostLineno;
803 nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).
lineno();
810 if (currLine) inside =
true;
813 if ( (fileLineno > lastCostLineno) &&
814 ((nextCostLineno == 0) ||
821 if ( ((lastCostLineno==0) || (fileLineno > lastCostLineno + context)) &&
822 ((nextCostLineno==0) || (fileLineno < nextCostLineno - context))) {
823 if ((lineIt == lineItEnd) || fileEndReached)
break;
825 if (!skipLineWritten) {
826 skipLineWritten =
true;
834 skipLineWritten =
false;
836 QString s = QString(buf);
837 if(s.size() > 0 && s.at(s.length()-1) ==
'\r')
838 s = s.left(s.length()-1);
840 fileno, fileLineno, inside, s,
844 if (!currLine)
continue;
847 if (!first) first = si;
854 si->setExpanded(
true);
864 si2 =
new SourceItem(
this, si, fileno, fileLineno, currLine, lc);
873 new SourceItem(
this, si, fileno, fileLineno, currLine, lj);
880 #if QT_VERSION >= 0x050000
881 header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
882 header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
883 header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
885 header()->setResizeMode(0, QHeaderView::ResizeToContents);
886 header()->setResizeMode(1, QHeaderView::ResizeToContents);
887 header()->setResizeMode(2, QHeaderView::ResizeToContents);
890 setSortingEnabled(
false);
891 addTopLevelItems(items);
893 setSortingEnabled(
true);
895 sortByColumn(0, Qt::AscendingOrder);
896 header()->setSortIndicatorShown(
false);
899 #if QT_VERSION >= 0x050000
900 header()->setSectionResizeMode(0, QHeaderView::Interactive);
901 header()->setSectionResizeMode(1, QHeaderView::Interactive);
902 header()->setSectionResizeMode(2, QHeaderView::Interactive);
904 header()->setResizeMode(0, QHeaderView::Interactive);
905 header()->setResizeMode(1, QHeaderView::Interactive);
906 header()->setResizeMode(2, QHeaderView::Interactive);
910 if (item) first = item;
913 _inSelectionUpdate =
true;
914 setCurrentItem(first);
915 _inSelectionUpdate =
false;
920 for (
int i=0; i<topLevelItemCount(); i++) {
921 item1 = topLevelItem(i);
923 updateJumpArray(si->
lineno(), si,
true,
false);
925 for (
int j=0; j<item1->childCount(); j++) {
926 item2 = item1->child(j);
929 updateJumpArray(si->
lineno(), si2,
false,
true);
939 setColumnWidth(3, 0);
946 sortByColumn(col, Qt::AscendingOrder);
950 sortByColumn(col, Qt::DescendingOrder);
954 #include "sourceview.moc"
QList< TraceLineJump * > TraceLineJumpList
SubCost subCost(EventType *)
Returns a sub cost.
void selectedSlot(QTreeWidgetItem *, QTreeWidgetItem *)
static QStringList sourceDirs(TraceData *, TraceObject *o=0)
QMap< uint, TraceLine > TraceLineMap
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
void addEventTypeMenu(QMenu *, bool withCost2=true)
TraceLine * lineTo() const
ProfileContext::Type type() const
void setDirectory(const QString &dir)
TraceFunction * function() const
TraceObject * object() const
Base class for cost items.
A call from a line of one function to another function.
const TraceLineJumpList & lineJumps() const
void activatedSlot(QTreeWidgetItem *, int)
void keyPressEvent(QKeyEvent *event)
Abstract Base Class for KCachegrind Views.
void setJumpArray(const QVector< TraceLineJump * > &a)
TracePartList parts() const
void context(const QPoint &)
A code instruction address of the program.
void getJumpLines(const TraceLineJump *jump, uint &low, uint &high)
virtual QString name() const
Returns dynamic name info (without type)
const TraceLineCallList & lineCalls() const
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
A container helper class for TraceFunction for source lines where a function is implemented in...
bool lineJumpHighLessThan(const TraceLineJump *jump1, const TraceLineJump *jump2)
virtual QString name() const
Returns dynamic name info (without type)
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
QString whatsThis() const
static bool searchFileRecursive(QString &dir, const QString &name)
A source line of the program.
static QString shortenSymbol(const QString &)
virtual QString name() const
Returns dynamic name info (without type)
virtual void selected(TraceItemView *sender, CostItem *)
Notification from child views.
virtual void activated(TraceItemView *sender, CostItem *)
bool lineJumpLowLessThan(const TraceLineJump *jump1, const TraceLineJump *jump2)
SourceView(TraceItemView *parentView, QWidget *parent=0)
const TraceFunctionSourceList & sourceFiles() const
TraceLineCall * lineCall() const
TraceLine * lineFrom() const
A Trace Part: All data read from a trace file, containing all costs that happened in a specified time...
Cost event counter, simple wrapper around a 64bit entity.
TraceFunctionSource * sourceFile(TraceFile *file=0, bool createNew=false)
TraceLineJump * lineJump() const
TraceFunction * called(bool skipCycle=false) const
static int noCostInside()
QString shortName() const
A jump from one line to another inside of a function.