diff options
Diffstat (limited to 'tdecachegrind/tdecachegrind/callview.cpp')
-rw-r--r-- | tdecachegrind/tdecachegrind/callview.cpp | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/tdecachegrind/tdecachegrind/callview.cpp b/tdecachegrind/tdecachegrind/callview.cpp new file mode 100644 index 00000000..317d137b --- /dev/null +++ b/tdecachegrind/tdecachegrind/callview.cpp @@ -0,0 +1,256 @@ +/* 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. +*/ + +/* + * Call Views + */ + +#include <tqwhatsthis.h> +#include <tqpopupmenu.h> +#include <klocale.h> + +#include "configuration.h" +#include "callitem.h" +#include "callview.h" + + + +// +// CallView +// + + +CallView::CallView(bool showCallers, TraceItemView* parentView, + TQWidget* parent, const char* name) + : TQListView(parent, name), TraceItemView(parentView) +{ + _showCallers = showCallers; + + addColumn( i18n( "Cost" ) ); + addColumn( i18n( "Cost 2" ) ); + if (_showCallers) { + addColumn( i18n( "Count" ) ); + addColumn( i18n( "Caller" ) ); + } + else { + addColumn( i18n( "Count" ) ); + addColumn( i18n( "Callee" ) ); + } + + setSorting(0,false); + setColumnAlignment(0, TQt::AlignRight); + setColumnAlignment(1, TQt::AlignRight); + setColumnAlignment(2, TQt::AlignRight); + setAllColumnsShowFocus(true); + setResizeMode(TQListView::LastColumn); + setMinimumHeight(50); + + connect( this, + TQT_SIGNAL( selectionChanged(TQListViewItem*) ), + TQT_SLOT( selectedSlot(TQListViewItem*) ) ); + + connect( this, + TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint &, int)), + TQT_SLOT(context(TQListViewItem*, const TQPoint &, int))); + + connect(this, + TQT_SIGNAL(doubleClicked(TQListViewItem*)), + TQT_SLOT(activatedSlot(TQListViewItem*))); + + connect(this, + TQT_SIGNAL(returnPressed(TQListViewItem*)), + TQT_SLOT(activatedSlot(TQListViewItem*))); + + TQWhatsThis::add( this, whatsThis() ); +} + +TQString CallView::whatsThis() const +{ + return _showCallers ? + i18n( "<b>List of direct Callers</b>" + "<p>This list shows all functions calling the " + "current selected one directly, together with " + "a call count and the cost spent in the current " + "selected function while being called from the " + "function from the list.</p>" + "<p>An icon instead of an inclusive cost specifies " + "that this is a call inside of a recursive cycle. " + "An inclusive cost makes no sense here.</p>" + "<p>Selecting a function makes it the current selected " + "one of this information panel. " + "If there are two panels (Split mode), the " + "function of the other panel is changed instead.</p>") : + i18n( "<b>List of direct Callees</b>" + "<p>This list shows all functions called by the " + "current selected one directly, together with " + "a call count and the cost spent in this function " + "while being called from the selected function.</p>" + "<p>Selecting a function makes it the current selected " + "one of this information panel. " + "If there are two panels (Split mode), the " + "function of the other panel is changed instead.</p>"); +} + + +void CallView::context(TQListViewItem* i, const TQPoint & p, int col) +{ + TQPopupMenu popup; + + // Menu entry: + TraceCall* c = i ? ((CallItem*) i)->call() : 0; + TraceFunction *f = 0, *cycle = 0; + + if (c) { + TQString name = _showCallers ? c->callerName(true) : c->calledName(true); + f = _showCallers ? c->caller(true) : c->called(true); + cycle = f->cycle(); + + popup.insertItem(i18n("Go to '%1'") + .arg(Configuration::shortenSymbol(name)), 93); + + if (cycle) { + name = Configuration::shortenSymbol(cycle->prettyName()); + popup.insertItem(i18n("Go to '%1'").arg(name), 94); + } + + popup.insertSeparator(); + } + + if ((col == 0) || (col == 1)) { + addCostMenu(&popup); + popup.insertSeparator(); + } + addGoMenu(&popup); + + int r = popup.exec(p); + if (r == 93) activated(f); + else if (r == 94) activated(cycle); +} + +void CallView::selectedSlot(TQListViewItem * i) +{ + if (!i) return; + TraceCall* c = ((CallItem*) i)->call(); + // Should we skip cycles here? + TraceItem* f = _showCallers ? c->caller(false) : c->called(false); + + _selectedItem = f; + selected(f); +} + +void CallView::activatedSlot(TQListViewItem * i) +{ + if (!i) return; + TraceCall* c = ((CallItem*) i)->call(); + // skip cycles: use the context menu to get to the cycle... + TraceItem* f = _showCallers ? c->caller(true) : c->called(true); + + activated(f); +} + +TraceItem* CallView::canShow(TraceItem* i) +{ + TraceItem::CostType t = i ? i->type() : TraceItem::NoCostType; + + switch(t) { + case TraceItem::Function: + case TraceItem::FunctionCycle: + return i; + default: + break; + } + return 0; +} + +void CallView::doUpdate(int changeType) +{ + // Special case ? + if (changeType == selectedItemChanged) { + + if (!_selectedItem) { + clearSelection(); + return; + } + + CallItem* ci = (CallItem*) TQListView::selectedItem(); + TraceCall* c; + TraceItem* ti; + if (ci) { + c = ci->call(); + ti = _showCallers ? c->caller() : c->called(); + if (ti == _selectedItem) return; + } + + TQListViewItem *item; + for (item = firstChild();item;item = item->nextSibling()) { + c = ((CallItem*) item)->call(); + ti = _showCallers ? c->caller() : c->called(); + if (ti == _selectedItem) { + ensureItemVisible(item); + setSelected(item, true); + break; + } + } + if (!item && ci) clearSelection(); + return; + } + + if (changeType == groupTypeChanged) { + TQListViewItem *item; + for (item = firstChild();item;item = item->nextSibling()) + ((CallItem*)item)->updateGroup(); + return; + } + + refresh(); +} + +void CallView::refresh() +{ + clear(); + setColumnWidth(0, 50); + setColumnWidth(1, _costType2 ? 50:0); + setColumnWidth(2, 50); + if (_costType) + setColumnText(0, _costType->name()); + if (_costType2) + setColumnText(1, _costType2->name()); + + if (!_data || !_activeItem) return; + + TraceFunction* f = activeFunction(); + if (!f) return; + + TraceCall* call; + // In the call lists, we skip cycles to show the real call relations + TraceCallList l = _showCallers ? f->callers(true) : f->callings(true); + + // Allow resizing of column 1 + setColumnWidthMode(1, TQListView::Maximum); + + for (call=l.first();call;call=l.next()) + if (call->subCost(_costType)>0) + new CallItem(this, this, call); + + if (!_costType2) { + setColumnWidthMode(1, TQListView::Manual); + setColumnWidth(1, 0); + } +} + +#include "callview.moc" |