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.