summaryrefslogtreecommitdiffstats
path: root/tdecachegrind/tdecachegrind/sourceview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdecachegrind/tdecachegrind/sourceview.cpp')
-rw-r--r--tdecachegrind/tdecachegrind/sourceview.cpp813
1 files changed, 813 insertions, 0 deletions
diff --git a/tdecachegrind/tdecachegrind/sourceview.cpp b/tdecachegrind/tdecachegrind/sourceview.cpp
new file mode 100644
index 00000000..dde291ea
--- /dev/null
+++ b/tdecachegrind/tdecachegrind/sourceview.cpp
@@ -0,0 +1,813 @@
+/* This file is part of KCachegrind.
+ Copyright (C) 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+ KCachegrind is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * Source View
+ */
+
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqwhatsthis.h>
+#include <tqpopupmenu.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "configuration.h"
+#include "sourceitem.h"
+#include "sourceview.h"
+
+
+//
+// SourceView
+//
+
+
+SourceView::SourceView(TraceItemView* parentView,
+ TQWidget* parent, const char* name)
+ : TQListView(parent, name), TraceItemView(parentView)
+{
+ _inSelectionUpdate = false;
+
+ _arrowLevels = 0;
+ _lowList.setSortLow(true);
+ _highList.setSortLow(false);
+
+ addColumn( i18n( "#" ) );
+ addColumn( i18n( "Cost" ) );
+ addColumn( i18n( "Cost 2" ) );
+ addColumn( "" );
+ addColumn( i18n( "Source (unknown)" ) );
+
+ setAllColumnsShowFocus(true);
+ setColumnAlignment(0, TQt::AlignRight);
+ setColumnAlignment(1, TQt::AlignRight);
+ setColumnAlignment(2, TQt::AlignRight);
+ setResizeMode(TQListView::LastColumn);
+
+ connect(this,
+ TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)),
+ TQT_SLOT(context(TQListViewItem*, const TQPoint &, int)));
+
+ connect(this,
+ TQT_SIGNAL(selectionChanged(TQListViewItem*)),
+ TQT_SLOT(selectedSlot(TQListViewItem*)));
+
+ connect(this,
+ TQT_SIGNAL(doubleClicked(TQListViewItem*)),
+ TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+ connect(this,
+ TQT_SIGNAL(returnPressed(TQListViewItem*)),
+ TQT_SLOT(activatedSlot(TQListViewItem*)));
+
+ TQWhatsThis::add( this, whatsThis());
+}
+
+void SourceView::paintEmptyArea( TQPainter * p, const TQRect & r)
+{
+ TQListView::paintEmptyArea(p, r);
+}
+
+
+TQString SourceView::whatsThis() const
+{
+ return i18n( "<b>Annotated Source</b>"
+ "<p>The annotated source list shows the "
+ "source lines of the current selected function "
+ "together with (self) cost spent while executing the "
+ "code of this source line. If there was a call "
+ "in a source line, lines with details on the "
+ "call happening are inserted into the source: "
+ "the cost spent inside of the call, the "
+ "number of calls happening, and the call destination.</p>"
+ "<p>Select a inserted call information line to "
+ "make the destination function current.</p>");
+}
+
+void SourceView::context(TQListViewItem* i, const TQPoint & p, int c)
+{
+ TQPopupMenu popup;
+
+ // Menu entry:
+ TraceLineCall* lc = i ? ((SourceItem*) i)->lineCall() : 0;
+ TraceLineJump* lj = i ? ((SourceItem*) i)->lineJump() : 0;
+ TraceFunction* f = lc ? lc->call()->called() : 0;
+ TraceLine* line = lj ? lj->lineTo() : 0;
+
+ if (f) {
+ TQString name = f->name();
+ if ((int)name.length()>Configuration::maxSymbolLength())
+ name = name.left(Configuration::maxSymbolLength()) + "...";
+ popup.insertItem(i18n("Go to '%1'").arg(name), 93);
+ popup.insertSeparator();
+ }
+ else if (line) {
+ popup.insertItem(i18n("Go to Line %1").arg(line->name()), 93);
+ popup.insertSeparator();
+ }
+
+ if ((c == 1) || (c == 2)) {
+ addCostMenu(&popup);
+ popup.insertSeparator();
+ }
+ addGoMenu(&popup);
+
+ int r = popup.exec(p);
+ if (r == 93) {
+ if (f) activated(f);
+ if (line) activated(line);
+ }
+}
+
+
+void SourceView::selectedSlot(TQListViewItem * i)
+{
+ if (!i) return;
+ // programatically selected items are not signalled
+ if (_inSelectionUpdate) return;
+
+ TraceLineCall* lc = ((SourceItem*) i)->lineCall();
+ TraceLineJump* lj = ((SourceItem*) i)->lineJump();
+
+ if (!lc && !lj) {
+ TraceLine* l = ((SourceItem*) i)->line();
+ if (l) {
+ _selectedItem = l;
+ selected(l);
+ }
+ return;
+ }
+
+ TraceFunction* f = lc ? lc->call()->called() : 0;
+ if (f) {
+ _selectedItem = f;
+ selected(f);
+ }
+ else {
+ TraceLine* line = lj ? lj->lineTo() : 0;
+ if (line) {
+ _selectedItem = line;
+ selected(line);
+ }
+ }
+}
+
+void SourceView::activatedSlot(TQListViewItem * i)
+{
+ if (!i) return;
+ TraceLineCall* lc = ((SourceItem*) i)->lineCall();
+ TraceLineJump* lj = ((SourceItem*) i)->lineJump();
+
+ if (!lc && !lj) {
+ TraceLine* l = ((SourceItem*) i)->line();
+ if (l) activated(l);
+ return;
+ }
+
+ TraceFunction* f = lc ? lc->call()->called() : 0;
+ if (f) activated(f);
+ else {
+ TraceLine* line = lj ? lj->lineTo() : 0;
+ if (line) activated(line);
+ }
+}
+
+TraceItem* SourceView::canShow(TraceItem* i)
+{
+ TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType;
+ TraceFunction* f = 0;
+
+ switch(t) {
+ case TraceItem::Function:
+ f = (TraceFunction*) i;
+ break;
+
+ case TraceItem::Instr:
+ f = ((TraceInstr*)i)->function();
+ select(i);
+ break;
+
+ case TraceItem::Line:
+ f = ((TraceLine*)i)->functionSource()->function();
+ select(i);
+ break;
+
+ default:
+ break;
+ }
+
+ return f;
+}
+
+void SourceView::doUpdate(int changeType)
+{
+ // Special case ?
+ if (changeType == selectedItemChanged) {
+
+ if (!_selectedItem) {
+ clearSelection();
+ return;
+ }
+
+ TraceLine* sLine = 0;
+ if (_selectedItem->type() == TraceItem::Line)
+ sLine = (TraceLine*) _selectedItem;
+ if (_selectedItem->type() == TraceItem::Instr)
+ sLine = ((TraceInstr*)_selectedItem)->line();
+
+ SourceItem* si = (SourceItem*)TQListView::selectedItem();
+ if (si) {
+ if (si->line() == sLine) return;
+ if (si->lineCall() &&
+ (si->lineCall()->call()->called() == _selectedItem)) return;
+ }
+
+ TQListViewItem *item, *item2;
+ for (item = firstChild();item;item = item->nextSibling()) {
+ si = (SourceItem*)item;
+ if (si->line() == sLine) {
+ ensureItemVisible(item);
+ _inSelectionUpdate = true;
+ setCurrentItem(item);
+ _inSelectionUpdate = false;
+ break;
+ }
+ item2 = item->firstChild();
+ for (;item2;item2 = item2->nextSibling()) {
+ si = (SourceItem*)item2;
+ if (!si->lineCall()) continue;
+ if (si->lineCall()->call()->called() == _selectedItem) {
+ ensureItemVisible(item2);
+ _inSelectionUpdate = true;
+ setCurrentItem(item2);
+ _inSelectionUpdate = false;
+ break;
+ }
+ }
+ if (item2) break;
+ }
+ return;
+ }
+
+ if (changeType == groupTypeChanged) {
+ TQListViewItem *item, *item2;
+ for (item = firstChild();item;item = item->nextSibling())
+ for (item2 = item->firstChild();item2;item2 = item2->nextSibling())
+ ((SourceItem*)item2)->updateGroup();
+ }
+
+ refresh();
+}
+
+void SourceView::refresh()
+{
+ clear();
+ setColumnWidth(0, 20);
+ setColumnWidth(1, 50);
+ setColumnWidth(2, _costType2 ? 50:0);
+ setColumnWidth(3, 0); // arrows, defaults to invisible
+ setSorting(0); // always reset to line number sort
+ if (_costType)
+ setColumnText(1, _costType->name());
+ if (_costType2)
+ setColumnText(2, _costType2->name());
+
+ _arrowLevels = 0;
+
+ if (!_data || !_activeItem) {
+ setColumnText(4, i18n("(No Source)"));
+ return;
+ }
+
+ TraceItem::CostType t = _activeItem->type();
+ TraceFunction* f = 0;
+ if (t == TraceItem::Function) f = (TraceFunction*) _activeItem;
+ if (t == TraceItem::Instr) {
+ f = ((TraceInstr*)_activeItem)->function();
+ if (!_selectedItem) _selectedItem = _activeItem;
+ }
+ if (t == TraceItem::Line) {
+ f = ((TraceLine*)_activeItem)->functionSource()->function();
+ if (!_selectedItem) _selectedItem = _activeItem;
+ }
+
+ if (!f) return;
+
+ // Allow resizing of column 2
+ setColumnWidthMode(2, TQListView::Maximum);
+
+ TraceFunctionSource* mainSF = f->sourceFile();
+
+ // skip first source if there's no debug info and there are more sources
+ // (this is for a bug in GCC 2.95.x giving unknown source for prologs)
+ if (mainSF &&
+ (mainSF->firstLineno() == 0) &&
+ (mainSF->lastLineno() == 0) &&
+ (f->sourceFiles().count()>1) ) {
+ // skip
+ }
+ else
+ fillSourceFile(mainSF, 0);
+
+ TraceFunctionSource* sf;
+ int fileno = 1;
+ TraceFunctionSourceList l = f->sourceFiles();
+ for (sf=l.first();sf;sf=l.next(), fileno++)
+ if (sf != mainSF)
+ fillSourceFile(sf, fileno);
+
+ if (!_costType2) {
+ setColumnWidthMode(2, TQListView::Manual);
+ setColumnWidth(2, 0);
+ }
+}
+
+
+// helper for fillSourceList:
+// search recursive for a file, starting from a base dir
+static bool checkFileExistance(TQString& dir, const TQString& name)
+{
+ // we leave this in...
+ qDebug("Checking %s/%s", dir.ascii(), name.ascii());
+
+ if (TQFile::exists(dir + "/" + name)) return true;
+
+ // check in subdirectories
+ TQDir d(dir);
+ d.setFilter( TQDir::Dirs | TQDir::NoSymLinks );
+ d.setSorting( TQDir::Unsorted );
+ TQStringList subdirs = d.entryList();
+ TQStringList::Iterator it =subdirs.begin();
+ for(; it != subdirs.end(); ++it ) {
+ if (*it == "." || *it == ".." || *it == "CVS") continue;
+
+ dir = d.filePath(*it);
+ if (checkFileExistance(dir, name)) return true;
+ }
+ return false;
+}
+
+
+void SourceView::updateJumpArray(uint lineno, SourceItem* si,
+ bool ignoreFrom, bool ignoreTo)
+{
+ TraceLineJump* lj;
+ uint lowLineno, highLineno;
+ int iEnd = -1, iStart = -1;
+
+ if (0) qDebug("updateJumpArray(line %d, jump to %s)",
+ lineno,
+ si->lineJump()
+ ? si->lineJump()->lineTo()->name().ascii() : "?" );
+
+
+ lj=_lowList.current();
+ while(lj) {
+ lowLineno = lj->lineFrom()->lineno();
+ if (lj->lineTo()->lineno() < lowLineno)
+ lowLineno = lj->lineTo()->lineno();
+
+ if (lowLineno > lineno) break;
+
+ if (ignoreFrom && (lowLineno < lj->lineTo()->lineno())) break;
+ if (ignoreTo && (lowLineno < lj->lineFrom()->lineno())) break;
+
+ if (si->lineJump() && (lj != si->lineJump())) break;
+
+ int asize = (int)_jump.size();
+#if 0
+ for(iStart=0;iStart<asize;iStart++)
+ if (_jump[iStart] &&
+ (_jump[iStart]->lineTo() == lj->lineTo())) break;
+#else
+ iStart = asize;
+#endif
+
+ if (iStart == asize) {
+ for(iStart=0;iStart<asize;iStart++)
+ if (_jump[iStart] == 0) break;
+
+ if (iStart== asize) {
+ asize++;
+ _jump.resize(asize);
+ if (asize > _arrowLevels) _arrowLevels = asize;
+ }
+
+ if (0) qDebug(" start %d (%s to %s)",
+ iStart,
+ lj->lineFrom()->name().ascii(),
+ lj->lineTo()->name().ascii());
+
+ _jump[iStart] = lj;
+ }
+ lj=_lowList.next();
+ }
+
+ si->setJumpArray(_jump);
+
+ lj=_highList.current();
+ while(lj) {
+ highLineno = lj->lineFrom()->lineno();
+ if (lj->lineTo()->lineno() > highLineno) {
+ highLineno = lj->lineTo()->lineno();
+ if (ignoreTo) break;
+ }
+ else if (ignoreFrom) break;
+
+ if (highLineno > lineno) break;
+
+ for(iEnd=0;iEnd< (int)_jump.size();iEnd++)
+ if (_jump[iEnd] == lj) break;
+ if (iEnd == (int)_jump.size()) {
+ qDebug("LineView: no jump start for end at %x ?", highLineno);
+ iEnd = -1;
+ }
+ lj=_highList.next();
+
+ if (0 && (iEnd>=0))
+ qDebug(" end %d (%s to %s)",
+ iEnd,
+ _jump[iEnd]->lineFrom()->name().ascii(),
+ _jump[iEnd]->lineTo()->name().ascii());
+
+ if (0 && lj) qDebug("next end: %s to %s",
+ lj->lineFrom()->name().ascii(),
+ lj->lineTo()->name().ascii());
+
+ if (highLineno > lineno)
+ break;
+ else {
+ if (iEnd>=0) _jump[iEnd] = 0;
+ iEnd = -1;
+ }
+ }
+ if (iEnd>=0) _jump[iEnd] = 0;
+}
+
+
+/* If sourceList is empty we set the source file name into the header,
+ * else this code is of a inlined function, and we add "inlined from..."
+ */
+void SourceView::fillSourceFile(TraceFunctionSource* sf, int fileno)
+{
+ if (!sf) return;
+
+ if (0) qDebug("Selected Item %s",
+ _selectedItem ? _selectedItem->name().ascii() : "(none)");
+
+ TraceLineMap::Iterator lineIt, lineItEnd;
+ int nextCostLineno = 0, lastCostLineno = 0;
+
+ bool validSourceFile = (!sf->file()->name().isEmpty());
+
+ TraceLine* sLine = 0;
+ if (_selectedItem) {
+ if (_selectedItem->type() == TraceItem::Line)
+ sLine = (TraceLine*) _selectedItem;
+ if (_selectedItem->type() == TraceItem::Instr)
+ sLine = ((TraceInstr*)_selectedItem)->line();
+ }
+
+ if (validSourceFile) {
+ TraceLineMap* lineMap = sf->lineMap();
+ if (lineMap) {
+ lineIt = lineMap->begin();
+ lineItEnd = lineMap->end();
+ // get first line with cost of selected type
+ while(lineIt != lineItEnd) {
+ if (&(*lineIt) == sLine) break;
+ if ((*lineIt).hasCost(_costType)) break;
+ if (_costType2 && (*lineIt).hasCost(_costType2)) break;
+ ++lineIt;
+ }
+
+ nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
+ if (nextCostLineno<0) {
+ kdError() << "SourceView::fillSourceFile: Negative line number "
+ << nextCostLineno << endl
+ << " Function '" << sf->function()->name() << "'" << endl
+ << " File '" << sf->file()->name() << "'" << endl;
+ nextCostLineno = 0;
+ }
+
+ }
+
+ if (nextCostLineno == 0) {
+ new SourceItem(this, this, fileno, 0, false,
+ i18n("There is no cost of current selected type associated"));
+ new SourceItem(this, this, fileno, 1, false,
+ i18n("with any source line of this function in file"));
+ new SourceItem(this, this, fileno, 2, false,
+ TQString(" '%1'").arg(sf->function()->prettyName()));
+ new SourceItem(this, this, fileno, 3, false,
+ i18n("Thus, no annotated source can be shown."));
+ return;
+ }
+ }
+
+ TQString filename = sf->file()->shortName();
+ TQString dir = sf->file()->directory();
+ if (!dir.isEmpty())
+ filename = dir + "/" + filename;
+
+ if (nextCostLineno>0) {
+ // we have debug info... search for source file
+ if (!TQFile::exists(filename)) {
+ TQStringList list = Configuration::sourceDirs(_data,
+ sf->function()->object());
+ TQStringList::Iterator it;
+
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ dir = *it;
+ if (checkFileExistance(dir, sf->file()->shortName())) break;
+ }
+
+ if (it == list.end())
+ nextCostLineno = 0;
+ else {
+ filename = dir + "/" + sf->file()->shortName();
+ // no need to search again
+ sf->file()->setDirectory(dir);
+ }
+ }
+ }
+
+ // do it here, because the source directory could have been set before
+ if (childCount()==0) {
+ setColumnText(4, validSourceFile ?
+ i18n("Source ('%1')").arg(filename) :
+ i18n("Source (unknown)"));
+ }
+ else {
+ new SourceItem(this, this, fileno, 0, true,
+ validSourceFile ?
+ i18n("--- Inlined from '%1' ---").arg(filename) :
+ i18n("--- Inlined from unknown source ---"));
+ }
+
+ if (nextCostLineno == 0) {
+ new SourceItem(this, this, fileno, 0, false,
+ i18n("There is no source available for the following function:"));
+ new SourceItem(this, this, fileno, 1, false,
+ TQString(" '%1'").arg(sf->function()->prettyName()));
+ if (sf->file()->name().isEmpty()) {
+ new SourceItem(this, this, fileno, 2, false,
+ i18n("This is because no debug information is present."));
+ new SourceItem(this, this, fileno, 3, false,
+ i18n("Recompile source and redo the profile run."));
+ if (sf->function()->object()) {
+ new SourceItem(this, this, fileno, 4, false,
+ i18n("The function is located in this ELF object:"));
+ new SourceItem(this, this, fileno, 5, false,
+ TQString(" '%1'")
+ .arg(sf->function()->object()->prettyName()));
+ }
+ }
+ else {
+ new SourceItem(this, this, fileno, 2, false,
+ i18n("This is because its source file cannot be found:"));
+ new SourceItem(this, this, fileno, 3, false,
+ TQString(" '%1'").arg(sf->file()->name()));
+ new SourceItem(this, this, fileno, 4, false,
+ i18n("Add the folder of this file to the source folder list."));
+ new SourceItem(this, this, fileno, 5, false,
+ i18n("The list can be found in the configuration dialog."));
+ }
+ return;
+ }
+
+
+ // initialisation for arrow drawing
+ // create sorted list of jumps (for jump arrows)
+ TraceLineMap::Iterator it = lineIt, nextIt;
+ _lowList.clear();
+ _highList.clear();
+ while(1) {
+
+ nextIt = it;
+ ++nextIt;
+ while(nextIt != lineItEnd) {
+ if (&(*nextIt) == sLine) break;
+ if ((*nextIt).hasCost(_costType)) break;
+ if (_costType2 && (*nextIt).hasCost(_costType2)) break;
+ ++nextIt;
+ }
+
+ TraceLineJumpList jlist = (*it).lineJumps();
+ TraceLineJump* lj;
+ for (lj=jlist.first();lj;lj=jlist.next()) {
+ if (lj->executedCount()==0) continue;
+ // skip jumps to next source line with cost
+ //if (lj->lineTo() == &(*nextIt)) continue;
+
+ _lowList.append(lj);
+ _highList.append(lj);
+ }
+ it = nextIt;
+ if (it == lineItEnd) break;
+ }
+ _lowList.sort();
+ _highList.sort();
+ _lowList.first(); // iterators to list start
+ _highList.first();
+ _jump.resize(0);
+
+
+ char buf[256];
+ bool inside = false, skipLineWritten = true;
+ int readBytes;
+ int fileLineno = 0;
+ SubCost most = 0;
+
+ TraceLine* currLine;
+ SourceItem *si, *si2, *item = 0, *first = 0, *selected = 0;
+ TQFile file(filename);
+ if (!file.open(IO_ReadOnly)) return;
+ while (1) {
+ readBytes=file.readLine(buf, sizeof( buf ));
+ if (readBytes<=0) {
+ // for nice empty 4 lines after function with EOF
+ buf[0] = 0;
+ }
+
+ if (readBytes >= (int) sizeof( buf )) {
+ qDebug("%s:%d Line too long\n",
+ sf->file()->name().ascii(), fileLineno);
+ }
+ else if ((readBytes>0) && (buf[readBytes-1] == '\n'))
+ buf[readBytes-1] = 0;
+
+
+ // keep fileLineno inside [lastCostLineno;nextCostLineno]
+ fileLineno++;
+ if (fileLineno == nextCostLineno) {
+ currLine = &(*lineIt);
+
+ // get next line with cost of selected type
+ ++lineIt;
+ while(lineIt != lineItEnd) {
+ if (&(*lineIt) == sLine) break;
+ if ((*lineIt).hasCost(_costType)) break;
+ if (_costType2 && (*lineIt).hasCost(_costType2)) break;
+ ++lineIt;
+ }
+
+ lastCostLineno = nextCostLineno;
+ nextCostLineno = (lineIt == lineItEnd) ? 0 : (*lineIt).lineno();
+ }
+ else
+ currLine = 0;
+
+ // update inside
+ if (!inside) {
+ if (currLine) inside = true;
+ }
+ else {
+ if ( (fileLineno > lastCostLineno) &&
+ ((nextCostLineno == 0) ||
+ (fileLineno < nextCostLineno - Configuration::noCostInside()) ))
+ inside = false;
+ }
+
+ int context = Configuration::context();
+
+ if ( ((lastCostLineno==0) || (fileLineno > lastCostLineno + context)) &&
+ ((nextCostLineno==0) || (fileLineno < nextCostLineno - context))) {
+ if (lineIt == lineItEnd) break;
+
+ if (!skipLineWritten) {
+ skipLineWritten = true;
+ // a "skipping" line: print "..." instead of a line number
+ strcpy(buf,"...");
+ }
+ else
+ continue;
+ }
+ else
+ skipLineWritten = false;
+
+ si = new SourceItem(this, this,
+ fileno, fileLineno, inside, TQString(buf),
+ currLine);
+
+ if (!currLine) continue;
+
+ if (!selected && (currLine == sLine)) selected = si;
+ if (!first) first = si;
+
+ if (currLine->subCost(_costType) > most) {
+ item = si;
+ most = currLine->subCost(_costType);
+ }
+
+ si->setOpen(true);
+ TraceLineCallList list = currLine->lineCalls();
+ TraceLineCall* lc;
+ for (lc=list.first();lc;lc=list.next()) {
+ if ((lc->subCost(_costType)==0) &&
+ (lc->subCost(_costType2)==0)) continue;
+
+ if (lc->subCost(_costType) > most) {
+ item = si;
+ most = lc->subCost(_costType);
+ }
+
+ si2 = new SourceItem(this, si, fileno, fileLineno, currLine, lc);
+
+ if (!selected && (lc->call()->called() == _selectedItem))
+ selected = si2;
+ }
+
+ TraceLineJumpList jlist = currLine->lineJumps();
+ TraceLineJump* lj;
+ for (lj=jlist.first();lj;lj=jlist.next()) {
+ if (lj->executedCount()==0) continue;
+
+ new SourceItem(this, si, fileno, fileLineno, currLine, lj);
+ }
+ }
+
+ if (selected) item = selected;
+ if (item) first = item;
+ if (first) {
+ ensureItemVisible(first);
+ _inSelectionUpdate = true;
+ setCurrentItem(first);
+ _inSelectionUpdate = false;
+ }
+
+ file.close();
+
+ // for arrows: go down the list according to list sorting
+ sort();
+ TQListViewItem *item1, *item2;
+ for (item1=firstChild();item1;item1 = item1->nextSibling()) {
+ si = (SourceItem*)item1;
+ updateJumpArray(si->lineno(), si, true, false);
+
+ for (item2=item1->firstChild();item2;item2 = item2->nextSibling()) {
+ si2 = (SourceItem*)item2;
+ if (si2->lineJump())
+ updateJumpArray(si->lineno(), si2, false, true);
+ else
+ si2->setJumpArray(_jump);
+ }
+ }
+
+ if (arrowLevels())
+ setColumnWidth(3, 10 + 6*arrowLevels() + itemMargin() * 2);
+ else
+ setColumnWidth(3, 0);
+}
+
+
+void SourceView::updateSourceItems()
+{
+ setColumnWidth(1, 50);
+ setColumnWidth(2, _costType2 ? 50:0);
+ // Allow resizing of column 2
+ setColumnWidthMode(2, TQListView::Maximum);
+
+ if (_costType)
+ setColumnText(1, _costType->name());
+ if (_costType2)
+ setColumnText(2, _costType2->name());
+
+ SourceItem* si;
+ TQListViewItem* item = firstChild();
+ for (;item;item = item->nextSibling()) {
+ si = (SourceItem*)item;
+ TraceLine* l = si->line();
+ if (!l) continue;
+
+ si->updateCost();
+
+ TQListViewItem *next, *i = si->firstChild();
+ for (;i;i = next) {
+ next = i->nextSibling();
+ ((SourceItem*)i)->updateCost();
+ }
+ }
+
+ if (!_costType2) {
+ setColumnWidthMode(2, TQListView::Manual);
+ setColumnWidth(2, 0);
+ }
+}
+
+#include "sourceview.moc"