File indexing completed on 2024-04-28 05:41:35
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 * TracePart as Nested Area 0011 */ 0012 0013 #include "partgraph.h" 0014 0015 #include <QPixmap> 0016 0017 #include "globalguiconfig.h" 0018 #include "listutils.h" 0019 0020 0021 // PartAreaWidget 0022 0023 PartAreaWidget::PartAreaWidget(QWidget* parent) 0024 : TreeMapWidget(new BasePartItem(), parent) 0025 { 0026 _data = nullptr; 0027 _function = nullptr; 0028 0029 _eventType = nullptr; 0030 _groupType = ProfileContext::InvalidType; 0031 _visualization = NoVisualization; 0032 _zoomFunction = false; 0033 _callLevels = 1; 0034 } 0035 0036 void PartAreaWidget::setData(TraceData* data) 0037 { 0038 if (data == _data) return; 0039 0040 _data = data; 0041 _function = nullptr; 0042 _hiddenParts.clear(); 0043 0044 ((BasePartItem*)base())->setData(data); 0045 } 0046 0047 void PartAreaWidget::changeHidden(const TracePartList& list) 0048 { 0049 _hiddenParts = list; 0050 base()->refresh(); 0051 } 0052 0053 0054 void PartAreaWidget::setEventType(EventType* ct) 0055 { 0056 _eventType = ct; 0057 0058 // this resizes items 0059 base()->redraw(); 0060 } 0061 0062 void PartAreaWidget::setVisualization(VisualizationMode m) 0063 { 0064 _visualization = m; 0065 refreshParts(); 0066 } 0067 0068 void PartAreaWidget::setZoomFunction(bool zoomFunction) 0069 { 0070 _zoomFunction = zoomFunction; 0071 refreshParts(); 0072 } 0073 0074 void PartAreaWidget::setCallLevels(int callLevels) 0075 { 0076 _callLevels = callLevels; 0077 refreshParts(); 0078 } 0079 0080 void PartAreaWidget::refreshParts() 0081 { 0082 // rebuild only subparts to keep part selection state 0083 TreeMapItemList* l = base()->children(); 0084 if (l) 0085 foreach(TreeMapItem* i, *l) 0086 i->refresh(); 0087 0088 // but resize part areas 0089 base()->redraw(); 0090 } 0091 0092 0093 void PartAreaWidget::setFunction(TraceFunction* f) 0094 { 0095 _function = f; 0096 0097 if (_visualization == PartAreaWidget::Inclusive) 0098 refreshParts(); 0099 } 0100 0101 void PartAreaWidget::setGroupType(ProfileContext::Type gt) 0102 { 0103 _groupType = gt; 0104 0105 // rebuild hierarchy below parts. 0106 // thus, selected parts stay selected 0107 TreeMapItemList* l = base()->children(); 0108 if (l) 0109 foreach(TreeMapItem* i, *l) 0110 i->refresh(); 0111 0112 base()->redraw(); 0113 } 0114 0115 bool PartAreaWidget::isHidden(TracePart* part) const 0116 { 0117 return _hiddenParts.contains(part); 0118 } 0119 0120 QColor PartAreaWidget::groupColor(TraceFunction* f) const 0121 { 0122 if (!f) 0123 return palette().color( QPalette::Button ); 0124 0125 return GlobalGUIConfig::functionColor(_groupType, f); 0126 } 0127 0128 QString PartAreaWidget::tipString(TreeMapItem* i) const 0129 { 0130 QString tip, itemTip; 0131 int count = 0; 0132 0133 //qDebug("PartAreaWidget::tipString for '%s'", i->name().toAscii()); 0134 0135 // first, SubPartItem's 0136 while (i && count<GlobalConfig::maxSymbolCount() && i->rtti() == 3) { 0137 itemTip = GlobalConfig::shortenSymbol(i->text(0)); 0138 0139 if (!i->text(1).isEmpty()) 0140 itemTip += " (" + i->text(1) + ')'; 0141 0142 if (!tip.isEmpty()) 0143 itemTip += '\n'; 0144 0145 tip = itemTip + tip; 0146 i = i->parent(); 0147 count++; 0148 } 0149 0150 // skip to part 0151 while (i && i->rtti()==3) i = i->parent(); 0152 0153 if (i && i->rtti()==2) { 0154 itemTip = QObject::tr("Profile Part %1").arg(i->text(0)); 0155 if (!i->text(1).isEmpty()) 0156 itemTip += " (" + i->text(1) + ')'; 0157 0158 if (!tip.isEmpty()) 0159 itemTip += '\n'; 0160 0161 tip = itemTip + tip; 0162 } 0163 0164 // qDebug("PartAreaWidget:: tip %s, itemTip %s", 0165 // tip.toAscii(), itemTip.toAscii()); 0166 0167 return tip; 0168 } 0169 0170 0171 0172 0173 0174 // BasePartItem 0175 0176 BasePartItem::BasePartItem() 0177 : TreeMapItem() 0178 { 0179 _data = nullptr; 0180 setSorting(-1); 0181 } 0182 0183 void BasePartItem::setData(TraceData* data) 0184 { 0185 if (data == _data) return; 0186 0187 _data = data; 0188 refresh(); 0189 } 0190 0191 TreeMapItemList* BasePartItem::children() 0192 { 0193 if (!_data) return _children; 0194 0195 if (!initialized()) { 0196 // qDebug("Create Parts (%s)", name().toAscii()); 0197 0198 PartAreaWidget* w = (PartAreaWidget*) widget(); 0199 foreach(TracePart* part, _data->parts()) 0200 if (!w->isHidden(part)) 0201 addItem(new PartItem(part)); 0202 } 0203 0204 return _children; 0205 } 0206 0207 QString BasePartItem::text(int textNo) const 0208 { 0209 if (textNo == 0) { 0210 if (!_data) 0211 return QObject::tr("(no trace)"); 0212 0213 if (_data->parts().isEmpty()) 0214 return QObject::tr("(no part)"); 0215 } 0216 return QString(); 0217 } 0218 0219 0220 QColor BasePartItem::backColor() const 0221 { 0222 return widget()->palette().base().color(); 0223 } 0224 0225 double BasePartItem::value() const 0226 { 0227 if (!_data) return 0; 0228 0229 PartAreaWidget* w = (PartAreaWidget*) widget(); 0230 return (double)_data->subCost(w->eventType()); 0231 } 0232 0233 0234 0235 0236 0237 // PartItem 0238 0239 PartItem::PartItem(TracePart* p) 0240 { 0241 _p = p; 0242 _factor=1; 0243 } 0244 0245 QString PartItem::text(int textNo) const 0246 { 0247 if (textNo == 0) 0248 return _p->prettyName(); 0249 0250 if (textNo != 1) 0251 return QString(); 0252 0253 EventType* ct; 0254 PartAreaWidget* w = (PartAreaWidget*)widget(); 0255 SubCost v; 0256 0257 ct = w->eventType(); 0258 v = _p->subCost(ct); 0259 0260 if (GlobalConfig::showPercentage()) { 0261 ProfileCostArray* t = _p->data()->totals(); 0262 double p = 100.0 * v / t->subCost(ct); 0263 return QStringLiteral("%1 %") 0264 .arg(p, 0, 'f', GlobalConfig::percentPrecision()); 0265 } 0266 return v.pretty(); 0267 } 0268 0269 0270 QPixmap PartItem::pixmap(int i) const 0271 { 0272 if (i != 1) return QPixmap(); 0273 0274 // Cost pixmap 0275 0276 EventType* ct = ((PartAreaWidget*)widget())->eventType(); 0277 return costPixmap( ct, _p, (double) (_p->data()->totals()->subCost(ct)), false ); 0278 } 0279 0280 0281 double PartItem::value() const 0282 { 0283 PartAreaWidget* w = (PartAreaWidget*)widget(); 0284 EventType* ct = w->eventType(); 0285 if ((w->visualization() == PartAreaWidget::Inclusive) && 0286 w->zoomFunction()) { 0287 0288 // use value of zoomed function 0289 TraceFunction* f = w->function(); 0290 if (f) { 0291 TracePartFunction* pf = (TracePartFunction*) f->findDepFromPart(_p); 0292 if (pf) 0293 return (double) pf->inclusive()->subCost(ct); 0294 // when function is not available in part, hide part 0295 return 0.0; 0296 } 0297 } 0298 return (double) _p->subCost(ct); 0299 } 0300 0301 double PartItem::sum() const 0302 { 0303 PartAreaWidget* w = (PartAreaWidget*)widget(); 0304 if (w->visualization() == PartAreaWidget::Inclusive) { 0305 double s = value(); 0306 //qDebug("PartItem::sum [part %s]: %d", _p->name().toAscii(), s); 0307 return s; 0308 } 0309 return 0.0; 0310 } 0311 0312 TreeMapItemList* PartItem::children() 0313 { 0314 if (initialized()) return _children; 0315 0316 ProfileCostArray* c; 0317 // qDebug("Create Part subitems (%s)", name().toAscii()); 0318 0319 PartAreaWidget* w = (PartAreaWidget*)widget(); 0320 if (w->visualization() == PartAreaWidget::Inclusive) { 0321 TraceFunction* f = w->function(); 0322 if (f) { 0323 c = f->findDepFromPart(_p); 0324 if (c) addItem(new SubPartItem(c)); 0325 } 0326 0327 return _children; 0328 } 0329 0330 0331 switch( ((PartAreaWidget*)widget())->groupType() ) { 0332 0333 case ProfileContext::Object: 0334 { 0335 TraceObjectMap::Iterator it; 0336 for ( it = _p->data()->objectMap().begin(); 0337 it != _p->data()->objectMap().end(); ++it ) { 0338 c = (*it).findDepFromPart(_p); 0339 if (c) 0340 addItem(new SubPartItem(c)); 0341 } 0342 } 0343 break; 0344 0345 case ProfileContext::Class: 0346 { 0347 TraceClassMap::Iterator it; 0348 for ( it = _p->data()->classMap().begin(); 0349 it != _p->data()->classMap().end(); ++it ) { 0350 c = (*it).findDepFromPart(_p); 0351 if (c) 0352 addItem(new SubPartItem(c)); 0353 } 0354 } 0355 break; 0356 0357 case ProfileContext::File: 0358 { 0359 TraceFileMap::Iterator it; 0360 for ( it = _p->data()->fileMap().begin(); 0361 it != _p->data()->fileMap().end(); ++it ) { 0362 c = (*it).findDepFromPart(_p); 0363 if (c) 0364 addItem(new SubPartItem(c)); 0365 } 0366 } 0367 break; 0368 0369 case ProfileContext::Function: 0370 { 0371 TraceFunctionMap::Iterator it; 0372 for ( it = _p->data()->functionMap().begin(); 0373 it != _p->data()->functionMap().end(); ++it ) { 0374 c = (*it).findDepFromPart(_p); 0375 if (c) 0376 addItem(new SubPartItem(c)); 0377 } 0378 } 0379 break; 0380 0381 default: 0382 break; 0383 } 0384 0385 return _children; 0386 } 0387 0388 0389 QColor PartItem::backColor() const 0390 { 0391 PartAreaWidget* w = (PartAreaWidget*)widget(); 0392 return w->groupColor(nullptr); 0393 } 0394 0395 0396 // SubPartItem 0397 0398 SubPartItem::SubPartItem(ProfileCostArray* c) 0399 { 0400 _partCostItem = c; 0401 _factor=1; 0402 } 0403 0404 QString SubPartItem::text(int textNo) const 0405 { 0406 if (textNo == 0) { 0407 if (!_partCostItem) 0408 return QObject::tr("(unknown)"); 0409 0410 return _partCostItem->dependent()->prettyName(); 0411 } 0412 0413 if (textNo != 1) 0414 return QString(); 0415 0416 EventType* ct; 0417 PartAreaWidget* w = (PartAreaWidget*)widget(); 0418 SubCost v; 0419 0420 ct = w->eventType(); 0421 if (w->visualization() == PartAreaWidget::Inclusive) 0422 v = ((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct); 0423 else 0424 v = _partCostItem->subCost(ct); 0425 0426 if (GlobalConfig::showPercentage()) { 0427 ProfileCostArray* t = GlobalConfig::showExpanded() ? 0428 _partCostItem->part() : _partCostItem->part()->data()->totals(); 0429 double p = 100.0 * v / t->subCost(ct); 0430 return QStringLiteral("%1 %") 0431 .arg(p, 0, 'f', GlobalConfig::percentPrecision()); 0432 } 0433 return v.pretty(); 0434 } 0435 0436 QPixmap SubPartItem::pixmap(int i) const 0437 { 0438 if (i != 1) return QPixmap(); 0439 0440 // Cost pixmap 0441 0442 PartAreaWidget* w = (PartAreaWidget*)widget(); 0443 EventType* ct = w->eventType(); 0444 ProfileCostArray* t = GlobalConfig::showExpanded() ? 0445 _partCostItem->part() : _partCostItem->part()->data()->totals(); 0446 ProfileCostArray* c; 0447 if (w->visualization() == PartAreaWidget::Inclusive) 0448 c = ((TracePartFunction*)_partCostItem)->inclusive(); 0449 else 0450 c = _partCostItem; 0451 0452 return costPixmap( ct, c, (double) (t->subCost(ct)), false ); 0453 } 0454 0455 double SubPartItem::value() const 0456 { 0457 EventType* ct; 0458 PartAreaWidget* w = (PartAreaWidget*)widget(); 0459 0460 ct = w->eventType(); 0461 if (w->visualization() == PartAreaWidget::Inclusive) 0462 return (double) 0463 ((TracePartFunction*)_partCostItem)->inclusive()->subCost(ct); 0464 0465 return (double) _partCostItem->subCost(ct); 0466 } 0467 0468 double SubPartItem::sum() const 0469 { 0470 PartAreaWidget* w = (PartAreaWidget*)widget(); 0471 if (w->visualization() == PartAreaWidget::Inclusive) { 0472 double s = value(); 0473 //qDebug("SubPartItem::sum [Cost %s]: %d", _cost->name().toAscii(), s); 0474 return s; 0475 } 0476 return 0.0; 0477 } 0478 0479 TreeMapItemList* SubPartItem::children() 0480 { 0481 if (!initialized()) { 0482 // qDebug("Create Part sub-subitems (%s)", name().toAscii()); 0483 0484 PartAreaWidget* w = (PartAreaWidget*)widget(); 0485 0486 if (depth()-2 > w->callLevels()) 0487 return _children; 0488 0489 if (w->visualization() == PartAreaWidget::Inclusive) { 0490 setSum(value()); 0491 0492 TracePartCallList l; 0493 l = ((TracePartFunction*)_partCostItem)->partCallings(); 0494 foreach(TracePartCall* call, l) { 0495 TraceFunction* called = call->call()->called(); 0496 ProfileCostArray* partCalled = called->findDepFromPart(call->part()); 0497 if (partCalled) 0498 addItem(new SubPartItem(partCalled)); 0499 } 0500 } 0501 } 0502 0503 return _children; 0504 } 0505 0506 0507 QColor SubPartItem::backColor() const 0508 { 0509 PartAreaWidget* w = (PartAreaWidget*)widget(); 0510 if (w->visualization() == PartAreaWidget::Inclusive) 0511 return w->groupColor((TraceFunction*)(_partCostItem->dependent())); 0512 0513 return GlobalGUIConfig::groupColor(_partCostItem->dependent()); 0514 } 0515 0516 #include "moc_partgraph.cpp"