File indexing completed on 2024-04-28 05:41:32
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 /* 0010 * Items of coverage view. 0011 */ 0012 0013 #include "coverageitem.h" 0014 0015 0016 #include "globalguiconfig.h" 0017 #include "listutils.h" 0018 #include "coverage.h" 0019 0020 0021 // CallerCoverageItem 0022 0023 0024 CallerCoverageItem::CallerCoverageItem(QTreeWidget* parent, Coverage* c, 0025 TraceFunction* base, 0026 EventType* ct, 0027 ProfileContext::Type gt) 0028 : QTreeWidgetItem(parent) 0029 { 0030 _skipped = 0; 0031 _coverage = c; 0032 _function = c->function(); 0033 _base = base; 0034 _groupType = ProfileContext::InvalidType; 0035 0036 setText(3, _function->prettyNameWithLocation()); 0037 setTextAlignment(0, Qt::AlignRight); 0038 setTextAlignment(1, Qt::AlignRight); 0039 setTextAlignment(2, Qt::AlignRight); 0040 setCostType(ct); 0041 setGroupType(gt); 0042 } 0043 0044 CallerCoverageItem::CallerCoverageItem(QTreeWidget* parent, int skipped, Coverage* c, 0045 TraceFunction* base, 0046 EventType* ct, 0047 ProfileContext::Type gt) 0048 : QTreeWidgetItem(parent) 0049 { 0050 _skipped = skipped; 0051 _coverage = c; 0052 _function = c->function(); 0053 _base = base; 0054 _groupType = ProfileContext::InvalidType; 0055 0056 //~ singular (%n function skipped) 0057 //~ plural (%n functions skipped) 0058 setText(3, QObject::tr("(%n function(s) skipped)", "", _skipped)); 0059 setTextAlignment(0, Qt::AlignRight); 0060 setTextAlignment(1, Qt::AlignRight); 0061 setTextAlignment(2, Qt::AlignRight); 0062 setCostType(ct); 0063 setGroupType(gt); 0064 } 0065 0066 void CallerCoverageItem::setGroupType(ProfileContext::Type gt) 0067 { 0068 if (_skipped) return; 0069 if (_groupType == gt) return; 0070 _groupType = gt; 0071 0072 QColor c = GlobalGUIConfig::functionColor(_groupType, _function); 0073 setIcon(3, colorPixmap(10, 10, c)); 0074 } 0075 0076 void CallerCoverageItem::setCostType(EventType* ct) 0077 { 0078 _costType = ct; 0079 update(); 0080 } 0081 0082 void CallerCoverageItem::update() 0083 { 0084 if (!_coverage) { 0085 setText(0, QString()); 0086 setText(1, QString()); 0087 return; 0088 } 0089 0090 _pSum = 100.0 * _coverage->inclusive(); 0091 SubCost realSum = _base->inclusive()->subCost(_costType); 0092 _sum = SubCost(realSum * _coverage->inclusive()); 0093 QString str; 0094 if (GlobalConfig::showPercentage()) 0095 str = QStringLiteral("%1").arg(_pSum, 0, 'f', GlobalConfig::percentPrecision()); 0096 else 0097 str = _sum.pretty(); 0098 0099 if (_skipped) { 0100 setText(0, QStringLiteral("< %1").arg(str)); 0101 return; 0102 } 0103 0104 setText(0, str); 0105 setIcon(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), nullptr, 0106 Coverage::maxHistogramDepth, false)); 0107 0108 // call count 0109 _cc = SubCost(_coverage->callCount()); 0110 setText(2, _cc ? _cc.pretty() : QStringLiteral("(0)")); 0111 0112 // distance (min/max/median) 0113 _distance = _coverage->inclusiveMedian(); 0114 QString distString; 0115 if (_coverage->minDistance() == _coverage->maxDistance()) 0116 distString = QString::number(_distance); 0117 else 0118 distString = QStringLiteral("%1-%2 (%3)") 0119 .arg(_coverage->minDistance()) 0120 .arg(_coverage->maxDistance()) 0121 .arg(_distance); 0122 setText(1, distString); 0123 } 0124 0125 0126 bool CallerCoverageItem::operator<( const QTreeWidgetItem & other ) const 0127 { 0128 const CallerCoverageItem* ci1 = this; 0129 const CallerCoverageItem* ci2 = (CallerCoverageItem*) &other; 0130 int col = treeWidget()->sortColumn(); 0131 0132 // a skip entry is always sorted last 0133 if (ci1->_skipped) return true; 0134 if (ci2->_skipped) return false; 0135 0136 if (col==0) { 0137 if (ci1->_pSum < ci2->_pSum) return true; 0138 if (ci1->_pSum > ci2->_pSum) return false; 0139 0140 // for same percentage (e.g. all 100%), use distance info 0141 return ci1->_distance < ci2->_distance; 0142 } 0143 0144 if (col==1) { 0145 return ci1->_distance < ci2->_distance; 0146 } 0147 0148 if (col==2) { 0149 return ci1->_cc < ci2->_cc; 0150 } 0151 0152 return QTreeWidgetItem::operator <(other); 0153 } 0154 0155 0156 0157 // CalleeCoverageItem 0158 0159 CalleeCoverageItem::CalleeCoverageItem(QTreeWidget* parent, Coverage* c, 0160 TraceFunction* base, 0161 EventType* ct, 0162 ProfileContext::Type gt) 0163 : QTreeWidgetItem(parent) 0164 { 0165 _skipped = 0; 0166 _coverage = c; 0167 _function = c ? c->function() : nullptr; 0168 _base = base; 0169 _groupType = ProfileContext::InvalidType; 0170 0171 if ( _function ) 0172 setText(4, _function->prettyNameWithLocation()); 0173 0174 setTextAlignment(0, Qt::AlignRight); 0175 setTextAlignment(1, Qt::AlignRight); 0176 setTextAlignment(2, Qt::AlignRight); 0177 setTextAlignment(3, Qt::AlignRight); 0178 0179 setCostType(ct); 0180 setGroupType(gt); 0181 } 0182 0183 CalleeCoverageItem::CalleeCoverageItem(QTreeWidget* parent, int skipped, Coverage* c, 0184 TraceFunction* base, 0185 EventType* ct, 0186 ProfileContext::Type gt) 0187 : QTreeWidgetItem(parent) 0188 { 0189 _skipped = skipped; 0190 _coverage = c; 0191 _function = c ? c->function() : nullptr; 0192 _base = base; 0193 _groupType = ProfileContext::InvalidType; 0194 0195 setText(4, QObject::tr("(%n function(s) skipped)", "", _skipped)); 0196 0197 setTextAlignment(0, Qt::AlignRight); 0198 setTextAlignment(1, Qt::AlignRight); 0199 setTextAlignment(2, Qt::AlignRight); 0200 setTextAlignment(3, Qt::AlignRight); 0201 0202 setCostType(ct); 0203 setGroupType(gt); 0204 } 0205 0206 void CalleeCoverageItem::setGroupType(ProfileContext::Type gt) 0207 { 0208 if (_skipped) return; 0209 if (_groupType == gt) return; 0210 _groupType = gt; 0211 0212 QColor c = GlobalGUIConfig::functionColor(_groupType, _function); 0213 setIcon(4, colorPixmap(10, 10, c)); 0214 } 0215 0216 void CalleeCoverageItem::setCostType(EventType* ct) 0217 { 0218 _costType = ct; 0219 update(); 0220 } 0221 0222 void CalleeCoverageItem::update() 0223 { 0224 if (!_coverage) { 0225 setText(0, QString()); 0226 setText(1, QString()); 0227 setText(2, QString()); 0228 return; 0229 } 0230 0231 _pSum = 100.0 * _coverage->inclusive(); 0232 0233 // pSum/pSelf are percentages of inclusive cost of base 0234 SubCost realSum = _base->inclusive()->subCost(_costType); 0235 _sum = SubCost(realSum * _coverage->inclusive()); 0236 0237 0238 QString str; 0239 if (GlobalConfig::showPercentage()) 0240 str = QStringLiteral("%1").arg(_pSum, 0, 'f', GlobalConfig::percentPrecision()); 0241 else 0242 str = _sum.pretty(); 0243 0244 if (_skipped) { 0245 str = QStringLiteral("< %1").arg(str); 0246 setText(0, str); 0247 setText(1, str); 0248 return; 0249 } 0250 setText(0, str); 0251 0252 _pSelf = 100.0 * _coverage->self(); 0253 _self = SubCost(realSum * _coverage->self()); 0254 0255 if (GlobalConfig::showPercentage()) { 0256 setText(1, QStringLiteral("%1") 0257 .arg(_pSelf, 0, 'f', GlobalConfig::percentPrecision())); 0258 } 0259 else { 0260 setText(1, _self.pretty()); 0261 } 0262 0263 setIcon(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), nullptr, 0264 Coverage::maxHistogramDepth, false)); 0265 setIcon(1, partitionPixmap(25, 10, _coverage->selfHistogram(), nullptr, 0266 Coverage::maxHistogramDepth, false)); 0267 0268 0269 _cc = SubCost(_coverage->callCount()); 0270 setText(3, _cc ? _cc.pretty() : QStringLiteral("(0)")); 0271 0272 // for comparisons 0273 _distance = _coverage->inclusiveMedian(); 0274 QString distString; 0275 if (_coverage->minDistance() == _coverage->maxDistance()) 0276 distString = QString::number(_distance); 0277 else { 0278 int sMed = _coverage->selfMedian(); 0279 QString med; 0280 if (_distance == sMed) 0281 med = QString::number(_distance); 0282 else 0283 med = QStringLiteral("%1/%2").arg(_distance).arg(sMed); 0284 0285 distString = QStringLiteral("%1-%2 (%3)") 0286 .arg(_coverage->minDistance()) 0287 .arg(_coverage->maxDistance()) 0288 .arg(med); 0289 } 0290 setText(2, distString); 0291 } 0292 0293 0294 bool CalleeCoverageItem::operator<( const QTreeWidgetItem & other ) const 0295 { 0296 CalleeCoverageItem* ci = (CalleeCoverageItem*) &other; 0297 int col = treeWidget()->sortColumn(); 0298 // a skip entry is always sorted last 0299 if (_skipped) return true; 0300 if (ci->_skipped) return false; 0301 0302 if (col==0) { 0303 if (_pSum < ci->_pSum) return true; 0304 if (_pSum > ci->_pSum) return false; 0305 0306 // for same percentage (e.g. all 100%), use distance info 0307 return _distance < ci->_distance; 0308 0309 } 0310 0311 if (col==1) { 0312 if (_pSelf < ci->_pSelf) return true; 0313 if (_pSelf > ci->_pSelf) return false; 0314 0315 // for same percentage (e.g. all 100%), use distance info 0316 return _distance < ci->_distance; 0317 } 0318 0319 if (col==2) { 0320 // we want to sort the distance in contra direction to costs 0321 return _distance < ci->_distance; 0322 } 0323 0324 if (col==3) { 0325 return _cc < ci->_cc; 0326 } 0327 return QTreeWidgetItem::operator <(other); 0328 } 0329 0330