/* This file is part of KCachegrind. Copyright (C) 2003 Josef Weidendorfer 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 #include #include #include #include #include #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( "Caller Map" "

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).

") : i18n("Call Map" "

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).

"); s += i18n( "

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 " "very 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 before drawing children. Note that " "size proportions can get heavily wrong.

" "

This is a TreeMap 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. " "Return activates the current item.

"); 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 (counttext(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 (counttext(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 && counttext(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(KConfig* c, TQString prefix, TQString postfix, bool) { KConfigGroup* 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(KConfig* c, TQString prefix, TQString postfix, bool) { KConfigGroup 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"