1 /*
2     This file is part of KCachegrind.
3 
4     SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5 
6     SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 #include "partlistitem.h"
10 
11 #include <math.h>
12 
13 #include <QPixmap>
14 
15 #include "listutils.h"
16 #include "coverage.h"
17 #include "globalconfig.h"
18 
19 
20 // PartListItem
21 
PartListItem(QTreeWidget * parent,TraceCostItem * costItem,EventType * et,ProfileContext::Type gt,TracePart * part)22 PartListItem::PartListItem(QTreeWidget* parent, TraceCostItem* costItem,
23                            EventType* et, ProfileContext::Type gt,
24                            TracePart* part)
25     :QTreeWidgetItem(parent)
26 {
27     _partCostItem = costItem->findDepFromPart(part);
28     _part = part;
29     _groupType = gt;
30     _eventType = et;
31 
32     setTextAlignment(0, Qt::AlignRight);
33     setTextAlignment(1, Qt::AlignRight);
34     setTextAlignment(2, Qt::AlignRight);
35 
36     setText(0, _part->prettyName());
37 
38     if (_part->trigger().isEmpty())
39         setText(4, QObject::tr("(none)"));
40     else
41         setText(4, _part->trigger());
42 
43     update();
44 }
45 
setEventType(EventType * et)46 void PartListItem::setEventType(EventType* et)
47 {
48     if (_eventType == et) return;
49 
50     _eventType = et;
51     update();
52 }
53 
setGroupType(ProfileContext::Type gt)54 void PartListItem::setGroupType(ProfileContext::Type gt)
55 {
56     if (_groupType == gt) return;
57 
58     _groupType = gt;
59     update();
60 }
61 
update()62 void PartListItem::update()
63 {
64     TracePartFunction* pf;
65     pf = !_partCostItem ? nullptr :
66                           (_partCostItem->type()==ProfileContext::PartFunction) ?
67                               ((TracePartFunction*)_partCostItem) : nullptr;
68 
69     double total = _part->subCost(_eventType);
70 
71     ProfileCostArray* selfTotalCost = _part;
72     if (pf && GlobalConfig::showExpanded()) {
73         switch(_groupType) {
74         case ProfileContext::Object: selfTotalCost = pf->partObject(); break;
75         case ProfileContext::Class:  selfTotalCost = pf->partClass(); break;
76         case ProfileContext::File:   selfTotalCost = pf->partFile(); break;
77         default: break;
78         }
79     }
80     double selfTotal = selfTotalCost->subCost(_eventType);
81 
82     _pure = _partCostItem ? _partCostItem->subCost(_eventType) : SubCost(0);
83     _sum = pf ? pf->inclusive()->subCost(_eventType) : SubCost(0);
84 
85     if (selfTotal == 0 || !_partCostItem) {
86         setText(2, QStringLiteral("-"));
87         setIcon(2, QPixmap());
88     }
89     else {
90         double pure  = 100.0 * _pure / selfTotal;
91         if (GlobalConfig::showPercentage()) {
92             setText(2, QStringLiteral("%1")
93                     .arg(pure, 0, 'f', GlobalConfig::percentPrecision()));
94         }
95         else
96             setText(2, _partCostItem->prettySubCost(_eventType));
97 
98         setIcon(2, costPixmap(_eventType, _partCostItem, selfTotal, false));
99     }
100 
101     if (total == 0 || !pf) {
102         setText(1, QStringLiteral("-"));
103         setIcon(1, QPixmap());
104     }
105     else {
106         double sum  = 100.0 * _sum / total;
107         if (GlobalConfig::showPercentage()) {
108             setText(1, QStringLiteral("%1")
109                     .arg(sum, 0, 'f', GlobalConfig::percentPrecision()));
110         }
111         else
112             setText(1, _sum.pretty());
113 
114         setIcon(1, costPixmap(_eventType, pf->inclusive(), total, false));
115     }
116 
117     if (!pf) {
118         setText(3, QStringLiteral("-"));
119         _callCount = 0;
120         return;
121     }
122 
123     SubCost callCount;
124     QString str;
125 
126     callCount = 0;
127     foreach(TracePartCall* pc, pf->partCallers())
128         callCount += pc->callCount();
129 
130     if ((callCount == 0) && (pf->calledContexts()>0))
131         str = QObject::tr("(active)");
132     else
133         str = callCount.pretty();
134 
135     _callCount = callCount;
136     setText(3, str);
137 }
138 
operator <(const QTreeWidgetItem & other) const139 bool PartListItem::operator<(const QTreeWidgetItem& other) const
140 {
141     const PartListItem* pi1 = this;
142     const PartListItem* pi2 = (PartListItem*) &other;
143     int col = treeWidget()->sortColumn();
144 
145     if (col==0)
146         return (*(pi1->_part) < *(pi2->_part));
147 
148     if (col==1)
149         return (pi1->_sum < pi2->_sum);
150 
151     if (col==2)
152         return (pi1->_pure < pi2->_pure);
153 
154     if (col==3)
155         return (pi1->_callCount < pi2->_callCount);
156 
157     return QTreeWidgetItem::operator <(other);
158 }
159