You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/tdecachegrind/tdecachegrind/callmapview.cpp

1000 lines
27 KiB

/* 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 Map View
*/
#include <tqwhatsthis.h>
#include <tqpopupmenu.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kapplication.h>
#include <tdeconfig.h>
#include "callmapview.h"
#include "configuration.h"
#include "listutils.h"
#include "toplevel.h"
//
// CallMapView
//
// defaults
#define DEFAULT_SPLITMODE "Rows"
#define DEFAULT_DRAWNAME true
#define DEFAULT_DRAWCOST true
#define DEFAULT_DRAWLOCATION false
#define DEFAULT_DRAWCALLS false
#define DEFAULT_FORCESTRINGS false
#define DEFAULT_ROTATION true
#define DEFAULT_SHADING true
#define DEFAULT_MAXAREA 100
CallMapView::CallMapView(bool showCallers, TraceItemView* parentView,
TQWidget* parent, const char* name)
: TreeMapWidget(new CallMapBaseItem(), parent, name), TraceItemView(parentView)
{
_showCallers = showCallers;
setFieldType(0, i18n( "Name" ));
setFieldType(1, i18n( "Cost" ));
setFieldType(2, i18n( "Location" ));
setFieldPosition(2, TreeMapItem::TopLeft);
setFieldType(3, i18n( "Calls" ));
setFieldPosition(3, TreeMapItem::TopRight);
setSplitMode(DEFAULT_SPLITMODE);
setFieldVisible(0, DEFAULT_DRAWNAME);
setFieldVisible(1, DEFAULT_DRAWCOST);
setFieldVisible(2, DEFAULT_DRAWLOCATION);
setFieldVisible(3, DEFAULT_DRAWCALLS);
setFieldForced(0, DEFAULT_FORCESTRINGS);
setFieldForced(1, DEFAULT_FORCESTRINGS);
setFieldForced(2, DEFAULT_FORCESTRINGS);
setFieldForced(3, DEFAULT_FORCESTRINGS);
setAllowRotation(DEFAULT_ROTATION);
setShadingEnabled(DEFAULT_SHADING);
setMinimalArea(DEFAULT_MAXAREA);
connect(this,
TQT_SIGNAL(doubleClicked(TreeMapItem*)),
TQT_SLOT(activatedSlot(TreeMapItem*)));
connect(this,
TQT_SIGNAL(returnPressed(TreeMapItem*)),
TQT_SLOT(activatedSlot(TreeMapItem*)));
connect(this,
TQT_SIGNAL(currentChanged(TreeMapItem*, bool)),
TQT_SLOT(selectedSlot(TreeMapItem*, bool)));
connect(this,
TQT_SIGNAL(contextMenuRequested(TreeMapItem*,const TQPoint &)),
TQT_SLOT(context(TreeMapItem*,const TQPoint &)));
TQWhatsThis::add( this, whatsThis());
}
TQString CallMapView::whatsThis() const
{
TQString s = _showCallers ?
i18n( "<b>Caller Map</b>"
"<p>This graph shows the nested hierarchy of "
"all callers of the current activated function. "
"Each colored rectangle represents a function; "
"its size tries to be proportional to the cost spent "
"therein while the active function is running "
"(however, there are drawing constrains).</p>") :
i18n("<b>Call Map</b>"
"<p>This graph shows the nested hierarchy of "
"all callees of the current activated function. "
"Each colored rectangle represents a function; "
"its size tries to be proportional to the cost spent "
"therein while the active function is running "
"(however, there are drawing constrains).</p>");
s += i18n( "<p>Appearance options can be found in the "
"in the context menu. To get exact size proportions, "
"choose 'Hide incorrect borders'. As this mode can be "
"<em>very</em> time consuming, you may want to limit "
"the maximum drawn nesting level before. "
"'Best' determinates the split direction for children "
"from the aspect ratio of the parent. "
"'Always Best' decides on remaining space for each "
"sibling. "
"'Ignore Proportions' takes space for function name "
"drawing <em>before</em> drawing children. Note that "
"size proportions can get <em>heavily</em> wrong.</p>"
"<p>This is a <em>TreeMap</em> widget. "
"Keyboard navigation is available with the left/right arrow "
"keys for traversing siblings, and up/down arrow keys "
"to go a nesting level up/down. "
"<em>Return</em> activates the current item.</p>");
return s;
}
void CallMapView::setData(TraceData* d)
{
TraceItemView::setData(d);
((CallMapBaseItem*)base())->setFunction(0);
}
void CallMapView::context(TreeMapItem* i,const TQPoint & p)
{
if (!i) return;
TQPopupMenu popup;
TQPopupMenu fpopup; // select function subpopup
TQPopupMenu vpopup; // visualisation subpopup
TQPopupMenu dpopup; // split direction
TQPopupMenu bpopup; // border subpopup
TQPopupMenu l1popup; // depth limit subpopup
TQPopupMenu l2popup; // function limit subpopup
TQPopupMenu l3popup; // area limit subpopup
TreeMapItem* item = i;
int count;
TQString shortCurrentName;
if (i) {
shortCurrentName = i->text(0);
if ((int)shortCurrentName.length() > Configuration::maxSymbolLength())
shortCurrentName =
shortCurrentName.left(Configuration::maxSymbolLength()) + "...";
}
if (item) {
popup.insertItem(i18n("Go To"), &fpopup, 100);
count = 0;
while (count<Configuration::maxSymbolCount() && item) {
TQString name = item->text(0);
if ((int)name.length()>Configuration::maxSymbolLength())
name = name.left(Configuration::maxSymbolLength()) + "...";
fpopup.insertItem(name, 101+count);
item = item->parent();
count++;
}
popup.insertSeparator();
}
addGoMenu(&popup);
popup.insertSeparator();
l1popup.setCheckable(true);
popup.insertItem(i18n("Stop at Depth"), &l1popup, 12);
int maxDepth = maxDrawingDepth();
l1popup.insertItem(i18n("No Depth Limit"), 50);
l1popup.setItemChecked(50, maxDepth==-1);
l1popup.insertSeparator();
l1popup.insertItem(i18n("Depth 10"), 51);
l1popup.setItemChecked(51, maxDepth==10);
l1popup.insertItem(i18n("Depth 15"), 52);
l1popup.setItemChecked(52, maxDepth==15);
l1popup.insertItem(i18n("Depth 20"), 53);
l1popup.setItemChecked(53, maxDepth==20);
if (i) {
l1popup.insertSeparator();
l1popup.insertItem(i18n("Depth of '%1' (%2)")
.arg(shortCurrentName).arg(i->depth()), 55);
l1popup.setItemChecked(55, maxDepth == i->depth());
}
if (maxDepth>0) {
l1popup.insertSeparator();
l1popup.insertItem(i18n("Decrement Depth (to %1)").arg(maxDepth-1), 56);
l1popup.insertItem(i18n("Increment Depth (to %1)").arg(maxDepth+1), 57);
}
l2popup.setCheckable(true);
popup.insertItem(i18n("Stop at Function"), &l2popup, 13);
l2popup.insertItem(i18n("No Function Limit"), 200);
l2popup.setItemChecked(200, fieldStop(0).isEmpty());
bool foundStopName = false;
item = i;
if (i) {
l2popup.insertSeparator();
count = 0;
while (count<Configuration::maxSymbolCount() && item) {
TQString name = item->text(0);
if ((int)name.length()>Configuration::maxSymbolLength())
name = name.left(Configuration::maxSymbolLength()) + "...";
l2popup.insertItem(name, 201+count);
if (item->text(0) == fieldStop(0)) {
l2popup.setItemChecked(201+count, true);
foundStopName = true;
}
item = item->parent();
count++;
}
}
if (!foundStopName && !fieldStop(0).isEmpty()) {
l2popup.insertSeparator();
TQString name = fieldStop(0);
if ((int)name.length()>Configuration::maxSymbolLength())
name = name.left(Configuration::maxSymbolLength()) + "...";
l2popup.insertItem(name, 199);
l2popup.setItemChecked(199, true);
}
l3popup.setCheckable(true);
popup.insertItem(i18n("Stop at Area"), &l3popup, 14);
int mArea = minimalArea();
l3popup.insertItem(i18n("No Area Limit"), 60);
l3popup.setItemChecked(60, mArea ==-1);
l3popup.insertSeparator();
l3popup.insertItem(i18n("50 Pixels"), 63);
l3popup.setItemChecked(63, mArea==50);
l3popup.insertItem(i18n("100 Pixels"), 64);
l3popup.setItemChecked(64, mArea==100);
l3popup.insertItem(i18n("200 Pixels"), 65);
l3popup.setItemChecked(65, mArea==200);
l3popup.insertItem(i18n("500 Pixels"), 66);
l3popup.setItemChecked(66, mArea==500);
int currentArea = 0;
if (i) {
currentArea = i->width() * i->height();
l3popup.insertSeparator();
l3popup.insertItem(i18n("Area of '%1' (%2)")
.arg(shortCurrentName).arg(currentArea), 67);
l3popup.setItemChecked(67, mArea == currentArea);
}
if (mArea>0) {
l3popup.insertSeparator();
l3popup.insertItem(i18n("Double Area Limit (to %1)")
.arg(mArea*2), 68);
l3popup.insertItem(i18n("Half Area Limit (to %1)")
.arg(mArea/2), 69);
}
popup.insertSeparator();
vpopup.setCheckable(true);
popup.insertItem(i18n("Visualisation"), &vpopup, 10);
TQPopupMenu splitpopup;
addSplitDirectionItems(&splitpopup, 1001);
vpopup.insertItem(i18n("Split Direction"), &splitpopup, 1000);
vpopup.insertItem(i18n("Skip Incorrect Borders"), 40);
vpopup.setItemEnabled(40, !_showCallers);
vpopup.setItemChecked(40, skipIncorrectBorder());
bpopup.setCheckable(true);
vpopup.insertItem(i18n("Border Width"), &bpopup, 41);
bpopup.insertItem(i18n("Border 0"), 42);
bpopup.setItemEnabled(42, !_showCallers);
bpopup.setItemChecked(42, borderWidth()==0);
bpopup.insertItem(i18n("Border 1"), 43);
bpopup.setItemChecked(43, borderWidth()==1);
bpopup.insertItem(i18n("Border 2"), 44);
bpopup.setItemChecked(44, borderWidth()==2);
bpopup.insertItem(i18n("Border 3"), 45);
bpopup.setItemChecked(45, borderWidth()==3);
vpopup.insertSeparator();
vpopup.insertItem(i18n("Draw Symbol Names"), 20);
vpopup.insertItem(i18n("Draw Cost"), 21);
vpopup.insertItem(i18n("Draw Location"), 22);
vpopup.insertItem(i18n("Draw Calls"), 23);
vpopup.insertSeparator();
vpopup.insertItem(i18n("Ignore Proportions"), 24);
vpopup.insertItem(i18n("Allow Rotation"), 25);
if (!fieldVisible(0) &&
!fieldVisible(1) &&
!fieldVisible(2) &&
!fieldVisible(3)) {
vpopup.setItemEnabled(24, false);
vpopup.setItemEnabled(25, false);
}
else {
vpopup.setItemChecked(20,fieldVisible(0));
vpopup.setItemChecked(21,fieldVisible(1));
vpopup.setItemChecked(22,fieldVisible(2));
vpopup.setItemChecked(23,fieldVisible(3));
vpopup.setItemChecked(24,fieldForced(0));
vpopup.setItemChecked(25,allowRotation());
}
vpopup.insertItem(i18n("Shading"), 26);
vpopup.setItemChecked(26,isShadingEnabled());
int r = popup.exec(mapToGlobal(p));
if (r>100 && r<150) {
r -= 100;
while (i && (r>1)) {
i=i->parent();
r--;
}
activatedSlot(i);
return;
}
if (r>200 && r<250) {
r -= 200;
while (i && (r>1)) {
i=i->parent();
r--;
}
if (i)
setFieldStop(0, i->text(0));
return;
}
switch(r) {
case 20:
setFieldVisible(0, !vpopup.isItemChecked(20));
break;
case 21:
setFieldVisible(1, !vpopup.isItemChecked(21));
break;
case 22:
setFieldVisible(2, !vpopup.isItemChecked(22));
break;
case 23:
setFieldVisible(3, !vpopup.isItemChecked(23));
break;
case 24:
setFieldForced(0, !vpopup.isItemChecked(24));
setFieldForced(1, !vpopup.isItemChecked(24));
setFieldForced(2, !vpopup.isItemChecked(24));
setFieldForced(3, !vpopup.isItemChecked(24));
break;
case 25: setAllowRotation(!vpopup.isItemChecked(25)); break;
case 26: setShadingEnabled(!vpopup.isItemChecked(26)); break;
case 40:
setSkipIncorrectBorder(!vpopup.isItemChecked(40));
break;
case 42: setBorderWidth(0); break;
case 43: setBorderWidth(1); break;
case 44: setBorderWidth(2); break;
case 45: setBorderWidth(3); break;
case 50: setMaxDrawingDepth(-1); break;
case 51: setMaxDrawingDepth(10); break;
case 52: setMaxDrawingDepth(15); break;
case 53: setMaxDrawingDepth(20); break;
case 55: setMaxDrawingDepth(i->depth()); break;
case 56: setMaxDrawingDepth(maxDepth-1); break;
case 57: setMaxDrawingDepth(maxDepth+1); break;
case 200: setFieldStop(0, TQString()); break;
case 60: setMinimalArea(-1); break;
case 61: setMinimalArea(10); break;
case 62: setMinimalArea(20); break;
case 63: setMinimalArea(50); break;
case 64: setMinimalArea(100); break;
case 65: setMinimalArea(200); break;
case 66: setMinimalArea(500); break;
case 67: setMinimalArea(currentArea); break;
case 68: setMinimalArea(mArea*2); break;
case 69: setMinimalArea(mArea/2); break;
}
}
void CallMapView::activatedSlot(TreeMapItem* item)
{
if (!item) return;
if (item->rtti() == 1) {
CallMapBaseItem* bi = (CallMapBaseItem*)item;
activated(bi->function());
}
else if (item->rtti() == 2) {
CallMapCallingItem* ci = (CallMapCallingItem*)item;
activated(ci->function());
}
else if (item->rtti() == 3) {
CallMapCallerItem* ci = (CallMapCallerItem*)item;
activated(ci->function());
}
}
void CallMapView::selectedSlot(TreeMapItem* item, bool kbd)
{
if (!item) return;
if (item->text(0).isEmpty()) return;
if (kbd) {
TQString msg = i18n("Call Map: Current is '%1'").arg(item->text(0));
if (_topLevel)
_topLevel->showMessage(msg, 5000);
}
TraceFunction* f = 0;
if (item->rtti() == 1) {
CallMapBaseItem* bi = (CallMapBaseItem*)item;
f = bi->function();
}
else if (item->rtti() == 2) {
CallMapCallingItem* ci = (CallMapCallingItem*)item;
f = ci->function();
}
else if (item->rtti() == 3) {
CallMapCallerItem* ci = (CallMapCallerItem*)item;
f = ci->function();
}
if (f) {
// this avoids marking
_selectedItem = f;
selected(f);
}
}
TraceItem* CallMapView::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 CallMapView::doUpdate(int changeType)
{
if (changeType == costType2Changed) return;
// if there is a selected item, always draw marking...
if (changeType & selectedItemChanged) {
TraceFunction* f = 0;
if (_selectedItem) {
switch(_selectedItem->type()) {
case TraceItem::Function:
case TraceItem::FunctionCycle:
f = (TraceFunction*)_selectedItem;
break;
default:
break;
}
}
// if this is the only change...
if (changeType == selectedItemChanged) {
setMarked(f ? 1:0, true);
return;
}
setMarked(f ? 1:0, false);
}
if (changeType & activeItemChanged) {
TraceFunction* f = 0;
if (_activeItem) {
switch(_activeItem->type()) {
case TraceItem::Function:
case TraceItem::FunctionCycle:
f = (TraceFunction*)_activeItem;
break;
default:
break;
}
}
((CallMapBaseItem*)base())->setFunction(f);
}
else if ( ((changeType & partsChanged) && Configuration::showCycles()) ||
(changeType & dataChanged) ||
(changeType & configChanged)) {
/* regenerates the treemap because traceitems were added/removed */
base()->refresh();
}
else if ((changeType & partsChanged) ||
(changeType & costTypeChanged)) {
/* we need to do the draw order sorting again as the values change */
resort();
redraw();
}
else
redraw();
}
TQColor CallMapView::groupColor(TraceFunction* f) const
{
if (!f)
return colorGroup().button();
return Configuration::functionColor(_groupType, f);
}
TQString CallMapView::tipString(TreeMapItem* i) const
{
TQString tip, itemTip;
int count = 0;
//tqDebug("CallMapView::tipString for '%s'", i->text(0).ascii());
// first, SubPartItem's
while (i && count<Configuration::maxSymbolCount()) {
itemTip = i->text(0);
if ((int)itemTip.length()>Configuration::maxSymbolLength())
itemTip = itemTip.left(Configuration::maxSymbolLength()) + "...";
if (!i->text(1).isEmpty())
itemTip += " (" + i->text(1) + ")";
if (!tip.isEmpty()) tip += "\n";
tip += itemTip;
i = i->parent();
count++;
}
if (count == Configuration::maxSymbolCount()) tip += "\n...";
return tip;
}
TraceCost* CallMapView::totalCost()
{
TraceFunction* f = ((CallMapBaseItem*)base())->function();
if (!f) return 0;
return Configuration::showExpanded() ? f->inclusive() : f->data();
}
// CallMapBaseItem
CallMapBaseItem::CallMapBaseItem()
{
_f = 0;
}
void CallMapBaseItem::setFunction(TraceFunction* f)
{
if (f == _f) return;
_f = f;
refresh();
}
TQString CallMapBaseItem::text(int textNo) const
{
if (textNo == 0) {
if (!_f)
return i18n("(no function)");
return _f->prettyName();
}
if (!_f) return TQString();
if (textNo == 2) return _f->prettyLocation();
if (textNo == 3) return _f->calledCount().pretty();
if (textNo != 1) return TQString();
TraceCostType* ct = ((CallMapView*)widget())->costType();
TraceCost* t = ((CallMapView*)widget())->totalCost();
if (Configuration::showPercentage()) {
double sum, total = t->subCost(ct);
if (total == 0.0)
sum = 100.0;
else
sum = 100.0 * _f->inclusive()->subCost(ct) / total;
return TQString("%1 %")
.arg(sum, 0, 'f', Configuration::percentPrecision());
}
return _f->inclusive()->prettySubCost(ct);
}
TQPixmap CallMapBaseItem::pixmap(int i) const
{
if ((i != 1) || !_f) return TQPixmap();
TraceCostType* ct = ((CallMapView*)widget())->costType();
TraceCost* t = ((CallMapView*)widget())->totalCost();
// colored level meter with frame
return costPixmap( ct, _f->inclusive(), (double) (t->subCost(ct)), true);
}
double CallMapBaseItem::value() const
{
if (!_f) return 0.0;
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
return (double) _f->inclusive()->subCost(ct);
}
double CallMapBaseItem::sum() const
{
if (!_f) return 0.0;
CallMapView* w = (CallMapView*)widget();
if (w->showCallers())
return 0.0;
else
return (double) _f->inclusive()->subCost(w->costType());
}
bool CallMapBaseItem::isMarked(int) const
{
return ((CallMapView*)widget())->selectedItem() == _f;
}
TreeMapItemList* CallMapBaseItem::children()
{
if (_f && !initialized()) {
CallMapView* w = (CallMapView*)widget();
if (0) tqDebug("Create Function %s (%s)",
w->showCallers() ? "Callers":"Callees",
text(0).ascii());
TraceCall* call;
setSorting(-1);
if (w->showCallers()) {
TraceCallList l = _f->callers();
for (call=l.first();call;call=l.next()) {
// don't show calls inside of a cycle
if (call->inCycle()>0) continue;
if (call->isRecursion()) continue;
addItem(new CallMapCallerItem(1.0, call));
}
setSum(0);
}
else {
TraceCallList l = _f->callings();
for (call=l.first();call;call=l.next()) {
// don't show calls inside of a cycle
if (call->inCycle()>0) continue;
if (call->isRecursion()) continue;
CallMapCallingItem* i = new CallMapCallingItem(1.0, call);
i->init();
addItem(i);
}
setSum(_f->inclusive()->subCost(w->costType()));
}
setSorting(-2, false);
}
return _children;
}
TQColor CallMapBaseItem::backColor() const
{
return ((CallMapView*)widget())->groupColor(_f);
}
// CallMapCallingItems
CallMapCallingItem::CallMapCallingItem(double factor, TraceCall* c)
{
_factor = factor;
_c = c;
}
void CallMapCallingItem::init()
{
#if 0
// create assoziation: if not possible, i.e. an ass. already exists
// for the function, we need to draw the recursive version
_recursive = !setFunction(_c->called());
_valid = true;
#endif
}
TQString CallMapCallingItem::text(int textNo) const
{
if (textNo == 0) {
if (!_c)
return i18n("(no call)");
return _c->calledName();
}
if (textNo == 2) return _c->called()->prettyLocation();
if (textNo == 3) return SubCost(_factor * _c->callCount()).pretty();
if (textNo != 1) return TQString();
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
SubCost val = SubCost(_factor * _c->subCost(ct));
if (Configuration::showPercentage()) {
// percentage relative to function cost
TraceCost* t = ((CallMapView*)widget())->totalCost();
double p = 100.0 * _factor * _c->subCost(ct) / t->subCost(ct);
return TQString("%1 %")
.arg(p, 0, 'f', Configuration::percentPrecision());
}
return val.pretty();
}
TQPixmap CallMapCallingItem::pixmap(int i) const
{
if (i != 1) return TQPixmap();
// Cost pixmap
TraceCostType* ct = ((CallMapView*)widget())->costType();
TraceCost* t = ((CallMapView*)widget())->totalCost();
// colored level meter with frame
return costPixmap( ct, _c, t->subCost(ct) / _factor, true);
}
double CallMapCallingItem::value() const
{
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
return _factor * _c->subCost(ct);
}
double CallMapCallingItem::sum() const
{
return value();
}
bool CallMapCallingItem::isMarked(int) const
{
return ((CallMapView*)widget())->selectedItem() == _c->called();
}
TreeMapItemList* CallMapCallingItem::children()
{
if (!initialized()) {
if (0) tqDebug("Create Calling subitems (%s)", path(0).join("/").ascii());
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
// same as sum()
SubCost s = _c->called()->inclusive()->subCost(ct);
SubCost v = _c->subCost(ct);
if (v>s) {
tqDebug("Warning: CallingItem subVal %u > Sum %u (%s)",
(unsigned)v, (unsigned)s, _c->called()->prettyName().ascii());
v = s;
}
double newFactor = _factor * v / s;
#if 0
tqDebug("CallingItem: Subitems of %s => %s, factor %f * %d/%d => %f",
_c->caller()->prettyName().ascii(),
_c->called()->prettyName().ascii(),
_factor, v, s, newFactor);
#endif
setSorting(-1);
TraceCall* call;
TraceCallList l = _c->called()->callings();
for (call=l.first();call;call=l.next()) {
// don't show calls inside of a cycle
if (call->inCycle()>0) continue;
if (call->isRecursion()) continue;
CallMapCallingItem* i = new CallMapCallingItem(newFactor, call);
i->init();
addItem(i);
}
setSorting(-2, false);
}
return _children;
}
TQColor CallMapCallingItem::backColor() const
{
CallMapView* w = (CallMapView*)widget();
return w->groupColor(_c->called());
}
// CallMapCallerItem
CallMapCallerItem::CallMapCallerItem(double factor, TraceCall* c)
{
_factor = factor;
_c = c;
}
TQString CallMapCallerItem::text(int textNo) const
{
if (textNo == 0) {
if (!_c)
return i18n("(no call)");
return _c->callerName();
}
if (textNo == 2) return _c->caller()->prettyLocation();
if (textNo == 3) return SubCost(_factor * _c->callCount()).pretty();
if (textNo != 1) return TQString();
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
SubCost val = SubCost(_factor * _c->subCost(ct));
if (Configuration::showPercentage()) {
TraceCost* t = ((CallMapView*)widget())->totalCost();
double p = 100.0 * _factor * _c->subCost(ct) / t->subCost(ct);
return TQString("%1 %")
.arg(p, 0, 'f', Configuration::percentPrecision());
}
return val.pretty();
}
TQPixmap CallMapCallerItem::pixmap(int i) const
{
if (i != 1) return TQPixmap();
// Cost pixmap
TraceCostType* ct = ((CallMapView*)widget())->costType();
TraceCost* t = ((CallMapView*)widget())->totalCost();
// colored level meter with frame
return costPixmap( ct, _c, t->subCost(ct) / _factor, true );
}
double CallMapCallerItem::value() const
{
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
return (double) _c->subCost(ct);
}
bool CallMapCallerItem::isMarked(int) const
{
return ((CallMapView*)widget())->selectedItem() == _c->caller();
}
TreeMapItemList* CallMapCallerItem::children()
{
if (!initialized()) {
//tqDebug("Create Caller subitems (%s)", name().ascii());
TraceCostType* ct;
ct = ((CallMapView*)widget())->costType();
SubCost s = _c->caller()->inclusive()->subCost(ct);
SubCost v = _c->subCost(ct);
double newFactor = _factor * v / s;
#if 0
tqDebug("CallerItem: Subitems of %s => %s, factor %f * %d/%d => %f",
_c->caller()->prettyName().ascii(),
_c->called()->prettyName().ascii(),
_factor, v, s, newFactor);
#endif
setSorting(-1);
TraceCall* call;
TraceCallList l = _c->caller()->callers();
for (call=l.first();call;call=l.next()) {
// don't show calls inside of a cycle
if (call->inCycle()>0) continue;
if (call->isRecursion()) continue;
TreeMapItem* i = new CallMapCallerItem(newFactor, call);
addItem(i);
}
setSorting(-2, false);
}
return _children;
}
TQColor CallMapCallerItem::backColor() const
{
CallMapView* w = (CallMapView*)widget();
return w->groupColor(_c->caller());
}
void CallMapView::readViewConfig(TDEConfig* c,
TQString prefix, TQString postfix, bool)
{
TDEConfigGroup* g = configGroup(c, prefix, postfix);
setSplitMode(g->readEntry("SplitMode", DEFAULT_SPLITMODE));
setFieldVisible(0, g->readBoolEntry("DrawName", DEFAULT_DRAWNAME));
setFieldVisible(1, g->readBoolEntry("DrawCost", DEFAULT_DRAWCOST));
setFieldVisible(2, g->readBoolEntry("DrawLocation", DEFAULT_DRAWLOCATION));
setFieldVisible(3, g->readBoolEntry("DrawCalls", DEFAULT_DRAWCALLS));
bool enable = g->readBoolEntry("ForceStrings", DEFAULT_FORCESTRINGS);
setFieldForced(0, enable);
setFieldForced(1, enable);
setFieldForced(2, enable);
setFieldForced(3, enable);
setAllowRotation(g->readBoolEntry("AllowRotation", DEFAULT_ROTATION));
setShadingEnabled(g->readBoolEntry("Shading", DEFAULT_SHADING));
setFieldStop(0, g->readEntry("StopName"));
setMaxDrawingDepth(g->readNumEntry("MaxDepth", -1));
setMinimalArea(g->readNumEntry("MaxArea", DEFAULT_MAXAREA));
delete g;
}
void CallMapView::saveViewConfig(TDEConfig* c,
TQString prefix, TQString postfix, bool)
{
TDEConfigGroup g(c, (prefix+postfix).ascii());
writeConfigEntry(&g, "SplitMode", splitModeString(), DEFAULT_SPLITMODE);
writeConfigEntry(&g, "DrawName", fieldVisible(0), DEFAULT_DRAWNAME);
writeConfigEntry(&g, "DrawCost", fieldVisible(1), DEFAULT_DRAWCOST);
writeConfigEntry(&g, "DrawLocation", fieldVisible(2), DEFAULT_DRAWLOCATION);
writeConfigEntry(&g, "DrawCalls", fieldVisible(3), DEFAULT_DRAWCALLS);
// when option for all text (0-3)
writeConfigEntry(&g, "ForceStrings", fieldForced(0), DEFAULT_FORCESTRINGS);
writeConfigEntry(&g, "AllowRotation", allowRotation(), DEFAULT_ROTATION);
writeConfigEntry(&g, "Shading", isShadingEnabled(), DEFAULT_SHADING);
writeConfigEntry(&g, "StopName", fieldStop(0), "");
writeConfigEntry(&g, "MaxDepth", maxDrawingDepth(), -1);
writeConfigEntry(&g, "MaxArea", minimalArea(), DEFAULT_MAXAREA);
}
#include "callmapview.moc"