summaryrefslogtreecommitdiffstats
path: root/kcachegrind/kcachegrind/partgraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcachegrind/kcachegrind/partgraph.cpp')
-rw-r--r--kcachegrind/kcachegrind/partgraph.cpp534
1 files changed, 534 insertions, 0 deletions
diff --git a/kcachegrind/kcachegrind/partgraph.cpp b/kcachegrind/kcachegrind/partgraph.cpp
new file mode 100644
index 00000000..f4fa72a3
--- /dev/null
+++ b/kcachegrind/kcachegrind/partgraph.cpp
@@ -0,0 +1,534 @@
+/* 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * TracePart as Nested Area
+ */
+
+#include <klocale.h>
+
+#include "partgraph.h"
+#include "configuration.h"
+#include "listutils.h"
+
+
+// PartAreaWidget
+
+PartAreaWidget::PartAreaWidget(QWidget* parent, const char* name)
+ : TreeMapWidget(new BasePartItem(), parent, name)
+{
+ _data = 0;
+ _function = 0;
+
+ _costType = 0;
+ _groupType = TraceCost::NoCostType;
+ _visualisation = NoVisualisation;
+ _zoomFunction = false;
+ _callLevels = 1;
+}
+
+void PartAreaWidget::setData(TraceData* data)
+{
+ if (data == _data) return;
+
+ _data = data;
+ _function = 0;
+ _hiddenParts.clear();
+
+ ((BasePartItem*)base())->setData(data);
+}
+
+void PartAreaWidget::changeHidden(const TracePartList& list)
+{
+ _hiddenParts = list;
+ base()->refresh();
+}
+
+
+void PartAreaWidget::setCostType(TraceCostType* ct)
+{
+ _costType = ct;
+
+ // this resizes items
+ base()->redraw();
+}
+
+void PartAreaWidget::setVisualisation(VisualisationMode m)
+{
+ _visualisation = m;
+ refreshParts();
+}
+
+void PartAreaWidget::setZoomFunction(bool zoomFunction)
+{
+ _zoomFunction = zoomFunction;
+ refreshParts();
+}
+
+void PartAreaWidget::setCallLevels(int callLevels)
+{
+ _callLevels = callLevels;
+ refreshParts();
+}
+
+void PartAreaWidget::refreshParts()
+{
+ // rebuild only subparts to keep part selection state
+ TreeMapItem* i;
+ TreeMapItemList* l = base()->children();
+ if (l)
+ for (i=l->first();i;i=l->next())
+ i->refresh();
+
+ // but resize part areas
+ base()->redraw();
+}
+
+
+void PartAreaWidget::setFunction(TraceFunction* f)
+{
+ _function = f;
+
+ if (_visualisation == PartAreaWidget::Inclusive)
+ refreshParts();
+}
+
+void PartAreaWidget::setGroupType(TraceCost::CostType gt)
+{
+ _groupType = gt;
+
+ // rebuild hierarchy below parts.
+ // thus, selected parts stay selected
+ TreeMapItem* i;
+ TreeMapItemList* l = base()->children();
+ if (l)
+ for (i=l->first();i;i=l->next())
+ i->refresh();
+
+ base()->redraw();
+}
+
+bool PartAreaWidget::isHidden(TracePart* part) const
+{
+ return (_hiddenParts.containsRef(part)>0);
+}
+
+QColor PartAreaWidget::groupColor(TraceFunction* f) const
+{
+ if (!f)
+ return colorGroup().button();
+
+ return Configuration::functionColor(_groupType, f);
+}
+
+QString PartAreaWidget::tipString(TreeMapItem* i) const
+{
+ QString tip, itemTip;
+ int count = 0;
+
+ //qDebug("PartAreaWidget::tipString for '%s'", i->name().ascii());
+
+ // first, SubPartItem's
+ while (i && count<Configuration::maxSymbolCount() && i->rtti() == 3) {
+ 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())
+ itemTip += "\n";
+
+ tip = itemTip + tip;
+ i = i->parent();
+ count++;
+ }
+
+ // skip to part
+ while (i && i->rtti()==3) i = i->parent();
+
+ if (i && i->rtti()==2) {
+ itemTip = i18n("Profile Part %1").arg(i->text(0));
+ if (!i->text(1).isEmpty())
+ itemTip += " (" + i->text(1) + ")";
+
+ if (!tip.isEmpty())
+ itemTip += "\n";
+
+ tip = itemTip + tip;
+ }
+
+// qDebug("PartAreaWidget:: tip %s, itemTip %s",
+// tip.ascii(), itemTip.ascii());
+
+ return tip;
+}
+
+
+
+
+
+// BasePartItem
+
+BasePartItem::BasePartItem()
+ : TreeMapItem()
+{
+ _data = 0;
+ setSorting(-1);
+}
+
+void BasePartItem::setData(TraceData* data)
+{
+ if (data == _data) return;
+
+ _data = data;
+ refresh();
+}
+
+TreeMapItemList* BasePartItem::children()
+{
+ if (!_data) return _children;
+
+ if (!initialized()) {
+// qDebug("Create Parts (%s)", name().ascii());
+
+ PartAreaWidget* w = (PartAreaWidget*) widget();
+ TracePart* part;
+ TracePartList l = _data->parts();
+ for (part=l.first();part;part=l.next())
+ if (!w->isHidden(part))
+ addItem(new PartItem(part));
+ }
+
+ return _children;
+}
+
+QString BasePartItem::text(int textNo) const
+{
+ if (textNo == 0) {
+ if (!_data)
+ return i18n("(no trace)");
+
+ if (_data->parts().count() == 0)
+ return i18n("(no part)");
+ }
+ return QString::null;
+}
+
+
+QColor BasePartItem::backColor() const
+{
+ return widget()->colorGroup().base();
+}
+
+double BasePartItem::value() const
+{
+ if (!_data) return 0;
+
+ PartAreaWidget* w = (PartAreaWidget*) widget();
+ return (double)_data->subCost(w->costType());
+}
+
+
+
+
+
+// PartItem
+
+PartItem::PartItem(TracePart* p)
+{
+ _p = p;
+ _factor=1;
+}
+
+QString PartItem::text(int textNo) const
+{
+ if (textNo == 0)
+ return _p->prettyName();
+
+ if (textNo != 1)
+ return QString::null;
+
+ TraceCostType* ct;
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ SubCost v;
+
+ ct = w->costType();
+ v = _p->subCost(ct);
+
+ if (Configuration::showPercentage()) {
+ TraceCost* t = _p->data()->totals();
+ double p = 100.0 * v / t->subCost(ct);
+ return QString("%1 %")
+ .arg(p, 0, 'f', Configuration::percentPrecision());
+ }
+ return v.pretty();
+}
+
+
+QPixmap PartItem::pixmap(int i) const
+{
+ if (i != 1) return QPixmap();
+
+ // Cost pixmap
+
+ TraceCostType* ct = ((PartAreaWidget*)widget())->costType();
+ return costPixmap( ct, _p, (double) (_p->data()->totals()->subCost(ct)), false );
+}
+
+
+double PartItem::value() const
+{
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ TraceCostType* ct = w->costType();
+ if ((w->visualisation() == PartAreaWidget::Inclusive) &&
+ w->zoomFunction()) {
+
+ // use value of zoomed function
+ TraceFunction* f = w->function();
+ if (f) {
+ TracePartFunction* pf = (TracePartFunction*) f->findDepFromPart(_p);
+ if (pf)
+ return (double) pf->inclusive()->subCost(ct);
+ // when function is not available in part, hide part
+ return 0.0;
+ }
+ }
+ return (double) _p->subCost(ct);
+}
+
+double PartItem::sum() const
+{
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ if (w->visualisation() == PartAreaWidget::Inclusive) {
+ double s = value();
+ //qDebug("PartItem::sum [part %s]: %d", _p->name().ascii(), s);
+ return s;
+ }
+ return 0.0;
+}
+
+TreeMapItemList* PartItem::children()
+{
+ if (initialized()) return _children;
+
+ TraceCost* c;
+// qDebug("Create Part subitems (%s)", name().ascii());
+
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ if (w->visualisation() == PartAreaWidget::Inclusive) {
+ TraceFunction* f = w->function();
+ if (f) {
+ c = f->findDepFromPart(_p);
+ if (c) addItem(new SubPartItem(c));
+ }
+
+ return _children;
+ }
+
+
+ switch( ((PartAreaWidget*)widget())->groupType() ) {
+
+ case TraceCost::Object:
+ {
+ TraceObjectMap::Iterator it;
+ for ( it = _p->data()->objectMap().begin();
+ it != _p->data()->objectMap().end(); ++it ) {
+ c = (*it).findDepFromPart(_p);
+ if (c)
+ addItem(new SubPartItem(c));
+ }
+ }
+ break;
+
+ case TraceCost::Class:
+ {
+ TraceClassMap::Iterator it;
+ for ( it = _p->data()->classMap().begin();
+ it != _p->data()->classMap().end(); ++it ) {
+ c = (*it).findDepFromPart(_p);
+ if (c)
+ addItem(new SubPartItem(c));
+ }
+ }
+ break;
+
+ case TraceCost::File:
+ {
+ TraceFileMap::Iterator it;
+ for ( it = _p->data()->fileMap().begin();
+ it != _p->data()->fileMap().end(); ++it ) {
+ c = (*it).findDepFromPart(_p);
+ if (c)
+ addItem(new SubPartItem(c));
+ }
+ }
+ break;
+
+ case TraceCost::Function:
+ {
+ TraceFunctionMap::Iterator it;
+ for ( it = _p->data()->functionMap().begin();
+ it != _p->data()->functionMap().end(); ++it ) {
+ c = (*it).findDepFromPart(_p);
+ if (c)
+ addItem(new SubPartItem(c));
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return _children;
+}
+
+
+QColor PartItem::backColor() const
+{
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ return w->groupColor(0);
+}
+
+
+// SubPartItem
+
+SubPartItem::SubPartItem(TraceCost* c)
+{
+ _partCostItem = c;
+ _factor=1;
+}
+
+QString SubPartItem::text(int textNo) const
+{
+ if (textNo == 0) {
+ if (!_partCostItem)
+ return i18n("(unknown)");
+
+ return _partCostItem->dependant()->prettyName();
+ }
+
+ if (textNo != 1)
+ return QString::null;
+
+ TraceCostType* ct;
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ SubCost v;
+
+ ct = w->costType();
+ if (w->visualisation() == PartAreaWidget::Inclusive)
+ v = ((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct);
+ else
+ v = _partCostItem->subCost(ct);
+
+ if (Configuration::showPercentage()) {
+ TraceCost* t = Configuration::showExpanded() ?
+ _partCostItem->part() : _partCostItem->part()->data()->totals();
+ double p = 100.0 * v / t->subCost(ct);
+ return QString("%1 %")
+ .arg(p, 0, 'f', Configuration::percentPrecision());
+ }
+ return v.pretty();
+}
+
+QPixmap SubPartItem::pixmap(int i) const
+{
+ if (i != 1) return QPixmap();
+
+ // Cost pixmap
+
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ TraceCostType* ct = w->costType();
+ TraceCost* t = Configuration::showExpanded() ?
+ _partCostItem->part() : _partCostItem->part()->data()->totals();
+ TraceCost* c;
+ if (w->visualisation() == PartAreaWidget::Inclusive)
+ c = ((TracePartFunction*)_partCostItem)->inclusive();
+ else
+ c = _partCostItem;
+
+ return costPixmap( ct, c, (double) (t->subCost(ct)), false );
+}
+
+double SubPartItem::value() const
+{
+ TraceCostType* ct;
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+
+ ct = w->costType();
+ if (w->visualisation() == PartAreaWidget::Inclusive)
+ return (double)
+ ((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct);
+
+ return (double) _partCostItem->subCost(ct);
+}
+
+double SubPartItem::sum() const
+{
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ if (w->visualisation() == PartAreaWidget::Inclusive) {
+ double s = value();
+ //qDebug("SubPartItem::sum [Cost %s]: %d", _cost->name().ascii(), s);
+ return s;
+ }
+ return 0.0;
+}
+
+TreeMapItemList* SubPartItem::children()
+{
+ if (!initialized()) {
+// qDebug("Create Part sub-subitems (%s)", name().ascii());
+
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+
+ if (depth()-2 > w->callLevels())
+ return _children;
+
+ if (w->visualisation() == PartAreaWidget::Inclusive) {
+ TracePartCall* call;
+ TracePartCallList l;
+
+ setSum(value());
+
+ l = ((TracePartFunction*)_partCostItem)->partCallings();
+ for (call=l.first();call;call=l.next()) {
+ TraceFunction* called = call->call()->called();
+ TraceCost* partCalled = called->findDepFromPart(call->part());
+ if (partCalled)
+ addItem(new SubPartItem(partCalled));
+ }
+ }
+ }
+
+ return _children;
+}
+
+
+QColor SubPartItem::backColor() const
+{
+ PartAreaWidget* w = (PartAreaWidget*)widget();
+ if (w->visualisation() == PartAreaWidget::Inclusive)
+ return w->groupColor((TraceFunction*)(_partCostItem->dependant()));
+
+ return Configuration::groupColor(_partCostItem->dependant());
+}
+
+
+#include "partgraph.moc"