1 /*
2     This file is part of KCachegrind.
3 
4     SPDX-FileCopyrightText: 2002-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5 
6     SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 /*
10  * Items for caller/callee view.
11  */
12 
13 #include "callitem.h"
14 
15 #include <QFontMetrics>
16 
17 #include "globalguiconfig.h"
18 #include "listutils.h"
19 #include "callview.h"
20 
21 
22 // CallItem
23 
24 
CallItem(CallView * view,QTreeWidget * parent,TraceCall * c)25 CallItem::CallItem(CallView* view, QTreeWidget* parent, TraceCall* c)
26     : QTreeWidgetItem(parent)
27 {
28     for (int i = 0 ; i < 5; ++i)
29         setTextAlignment(i, Qt::AlignRight);
30 
31     _call = c;
32     _view = view;
33 
34     _active = _view->activeFunction();
35     bool baseIsCycle = (_active && (_active == _active->cycle()));
36 
37     QString fName;
38     if (_view->showCallers()) {
39         _shown = _call->caller(true);
40         fName  = c->callerName(!baseIsCycle);
41     }
42     else {
43         _shown = _call->called(true);
44         fName = c->calledName(!baseIsCycle);
45     }
46 
47     _shown->addPrettyLocation(fName);
48 
49     setText(5, fName);
50     updateGroup();
51     updateCost();
52 }
53 
updateGroup()54 void  CallItem::updateGroup()
55 {
56     QColor c = GlobalGUIConfig::functionColor(_view->groupType(), _shown);
57     setIcon(5, colorPixmap(10, 10, c));
58 }
59 
updateCost()60 void CallItem::updateCost()
61 {
62     bool sameCycle = _shown->cycle() && (_active->cycle() == _shown->cycle());
63     bool shownIsCycle = (_shown == _shown->cycle());
64     bool selectedIsCycle = (_active == _active->cycle());
65     if (_call->isRecursion()) sameCycle=true;
66 
67     QString cStr;
68     if ((selectedIsCycle || shownIsCycle) && sameCycle)
69         cStr = QStringLiteral("-");
70     else {
71         _cc  = _call->callCount();
72         if (_cc == 0)
73             cStr = QObject::tr("(active)");
74         else
75             cStr = _call->prettyCallCount();
76     }
77     setText(4, cStr);
78 
79     ProfileCostArray* totalCost;
80     if (GlobalConfig::showExpanded()) {
81         if (_active->cycle())
82             totalCost = _active->cycle()->inclusive();
83         else
84             totalCost = _active->inclusive();
85     }
86     else
87         totalCost = _active->data();
88 
89     EventType* ct = _view->eventType();
90     _sum = _call->subCost(ct);
91     double total = totalCost->subCost(ct);
92 
93     if (total == 0.0) {
94         QString str = QStringLiteral("-");
95 
96         setText(0, str);
97         setIcon(0, QIcon());
98     }
99     else {
100         double sum  = 100.0 * _sum / total;
101 
102         if (GlobalConfig::showPercentage())
103             setText(0, QStringLiteral("%1")
104                     .arg(sum, 0, 'f', GlobalConfig::percentPrecision()));
105         else {
106             setText(0, _call->prettySubCost(ct));
107         }
108         setIcon(0, costPixmap(ct, _call, total, false));
109         setText(1, _call->prettySubCostPerCall(ct, _cc));
110     }
111 
112     // Cost Type 2
113     EventType* ct2 = _view->eventType2();
114     if (ct2) {
115         _sum2 = _call->subCost(ct2);
116         double total = totalCost->subCost(ct2);
117 
118         if (total == 0.0) {
119             QString str = QStringLiteral("-");
120 
121             setText(2, str);
122             setIcon(2, QIcon());
123         }
124         else {
125             double sum  = 100.0 * _sum2 / total;
126 
127             if (GlobalConfig::showPercentage())
128                 setText(2, QStringLiteral("%1")
129                         .arg(sum, 0, 'f', GlobalConfig::percentPrecision()));
130             else {
131                 setText(2, _call->prettySubCost(ct2));
132             }
133             setIcon(2, costPixmap(ct2, _call, total, false));
134             setText(3, _call->prettySubCostPerCall(ct2, _cc));
135         }
136     }
137 
138     QIcon p;
139     if (sameCycle && !selectedIsCycle && !shownIsCycle) {
140         QFontMetrics fm(font(4));
141         p = QIcon::fromTheme(QStringLiteral("edit-undo")).pixmap(fm.height());
142     }
143     setIcon(4, p);
144 }
145 
146 
operator <(const QTreeWidgetItem & other) const147 bool CallItem::operator<(const QTreeWidgetItem& other) const
148 {
149     int col = treeWidget()->sortColumn();
150     const CallItem* ci1 = this;
151     const CallItem* ci2 = (CallItem*) &other;
152 
153     if (col==0)
154         return ci1->_sum < ci2->_sum;
155 
156     if (col==1) {
157         uint64 cc1 = ci1->_cc;
158         uint64 cc2 = ci2->_cc;
159         if (cc1 == 0) cc1 = 1;
160         if (cc2 == 0) cc2 = 1;
161         return (ci1->_sum / cc1) < (ci2->_sum / cc2);
162     }
163 
164     if (col==2)
165         return ci1->_sum2 < ci2->_sum2;
166 
167     if (col==3) {
168         uint64 cc1 = ci1->_cc;
169         uint64 cc2 = ci2->_cc;
170         if (cc1 == 0) cc1 = 1;
171         if (cc2 == 0) cc2 = 1;
172         return (ci1->_sum2 / cc1) < (ci2->_sum2 / cc2);
173     }
174 
175     if (col==4)
176         return ci1->_cc < ci2->_cc;
177 
178     return QTreeWidgetItem::operator <(other);
179 }
180 
181