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 * Event Type View 0011 */ 0012 0013 0014 #include "eventtypeview.h" 0015 0016 #include <QAction> 0017 #include <QMenu> 0018 #include <QHeaderView> 0019 0020 #include "eventtypeitem.h" 0021 #include "toplevelbase.h" 0022 0023 0024 // 0025 // EventTypeView 0026 // 0027 0028 EventTypeView::EventTypeView(TraceItemView* parentView, 0029 QWidget* parent, const QString& name) 0030 : QTreeWidget(parent), TraceItemView(parentView) 0031 { 0032 setObjectName(name); 0033 // forbid scaling icon pixmaps to smaller size 0034 setIconSize(QSize(99,99)); 0035 setColumnCount(6); 0036 QStringList labels; 0037 labels << tr( "Event Type" ) 0038 << tr( "Incl." ) 0039 << tr( "Self" ) 0040 << tr( "Short" ) 0041 << QString() 0042 << tr( "Formula" ); 0043 setHeaderLabels(labels); 0044 // reduce minimum width for '=' column 0045 header()->setMinimumSectionSize(10); 0046 0047 setRootIsDecorated(false); 0048 setSortingEnabled(false); 0049 setAllColumnsShowFocus(true); 0050 setMinimumHeight(50); 0051 0052 0053 setContextMenuPolicy(Qt::CustomContextMenu); 0054 connect( this, 0055 &QWidget::customContextMenuRequested, 0056 this, &EventTypeView::context); 0057 0058 // FIXME: Endless jumping among 2 types possible! 0059 connect( this, 0060 SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), 0061 SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)) ); 0062 0063 connect(this, 0064 SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), 0065 SLOT(itemDoubleClicked(QTreeWidgetItem*,int))); 0066 0067 connect(this, 0068 SIGNAL(itemChanged(QTreeWidgetItem*,int)), 0069 SLOT(itemChanged(QTreeWidgetItem*,int))); 0070 0071 setWhatsThis( whatsThis() ); 0072 } 0073 0074 QString EventTypeView::whatsThis() const 0075 { 0076 return tr( "<b>Cost Types List</b>" 0077 "<p>This list shows all cost types available " 0078 "and what the self/inclusive cost of the " 0079 "current selected function is for that cost type.</p>" 0080 "<p>By choosing a cost type from the list, " 0081 "you change the cost type of costs shown " 0082 "all over KCachegrind to be the selected one.</p>"); 0083 } 0084 0085 0086 void EventTypeView::context(const QPoint & p) 0087 { 0088 QMenu popup; 0089 0090 QTreeWidgetItem* i = itemAt(p); 0091 EventType* ct = i ? ((EventTypeItem*) i)->eventType() : nullptr; 0092 0093 QAction* selectType2Action = nullptr; 0094 QAction* hideType2Action = nullptr; 0095 if (ct) 0096 selectType2Action = popup.addAction(tr("Set as Secondary Event Type")); 0097 if (_eventType2) 0098 hideType2Action = popup.addAction(tr("Hide Secondary Event Type")); 0099 if (!popup.isEmpty()) 0100 popup.addSeparator(); 0101 0102 QAction* editLongNameAction = nullptr; 0103 QAction* editShortNameAction = nullptr; 0104 QAction* editFormulaAction = nullptr; 0105 QAction* removeTypeAction = nullptr; 0106 if (ct && !ct->isReal()) { 0107 editLongNameAction = popup.addAction(tr("Edit Long Name")); 0108 editShortNameAction = popup.addAction(tr("Edit Short Name")); 0109 editFormulaAction = popup.addAction(tr("Edit Formula")); 0110 removeTypeAction = popup.addAction(tr("Remove")); 0111 popup.addSeparator(); 0112 } 0113 0114 addGoMenu(&popup); 0115 0116 QAction* newTypeAction = nullptr; 0117 if( _data) { 0118 popup.addSeparator(); 0119 newTypeAction = popup.addAction(tr("New Event Type...")); 0120 } 0121 0122 QAction* a = popup.exec(viewport()->mapToGlobal(p)); 0123 if (a == hideType2Action) selectedEventType2(nullptr); 0124 else if (a == selectType2Action) selectedEventType2(ct); 0125 else if (a == editLongNameAction) editItem(i, 0); 0126 else if (a == editShortNameAction) editItem(i, 3); 0127 else if (a == editFormulaAction) editItem(i, 5); 0128 else if (a == removeTypeAction) { 0129 0130 // search for a previous type 0131 EventType* prev = nullptr, *ct = nullptr; 0132 EventTypeSet* m = _data->eventTypes(); 0133 for (int i=0;i<m->realCount();i++) { 0134 ct = m->realType(i); 0135 if (ct) prev = ct; 0136 } 0137 for (int i=0;i<m->derivedCount();i++) { 0138 ct = m->derivedType(i); 0139 if (ct == _eventType) break; 0140 if (ct) prev = ct; 0141 } 0142 0143 if (_data->eventTypes()->remove(ct)) { 0144 // select previous cost type 0145 selectedEventType(prev); 0146 if (_eventType2 == ct) 0147 selectedEventType2(prev); 0148 refresh(); 0149 } 0150 } 0151 else if (a == newTypeAction) { 0152 int i = 1; 0153 while(1) { 0154 if (!EventType::hasKnownDerivedType(tr("New%1").arg(i))) 0155 break; 0156 i++; 0157 } 0158 // add same new cost type to this set and to known types 0159 QString shortName = tr("New%1").arg(i); 0160 QString longName = tr("New Event Type %1").arg(i); 0161 EventType* et; 0162 et = new EventType(shortName, longName); 0163 et->setFormula(QString()); // event is derived 0164 EventType::add(et); 0165 // EventType::add() took ownership, need new object 0166 et = new EventType(shortName, longName); 0167 et->setFormula(QString()); // event is derived 0168 _data->eventTypes()->add(et); 0169 refresh(); 0170 } 0171 } 0172 0173 0174 void EventTypeView::currentItemChanged(QTreeWidgetItem* i, QTreeWidgetItem*) 0175 { 0176 EventType* ct = i ? ((EventTypeItem*) i)->eventType() : nullptr; 0177 if (ct) 0178 selectedEventType(ct); 0179 } 0180 0181 void EventTypeView::itemDoubleClicked(QTreeWidgetItem* i, int) 0182 { 0183 EventType* ct = i ? ((EventTypeItem*) i)->eventType() : nullptr; 0184 if (ct) 0185 selectedEventType2(ct); 0186 } 0187 0188 CostItem* EventTypeView::canShow(CostItem* i) 0189 { 0190 if (!i) return nullptr; 0191 0192 switch(i->type()) { 0193 case ProfileContext::Object: 0194 case ProfileContext::Class: 0195 case ProfileContext::File: 0196 case ProfileContext::Call: 0197 case ProfileContext::FunctionCycle: 0198 case ProfileContext::Function: 0199 break; 0200 default: 0201 return nullptr; 0202 } 0203 return i; 0204 } 0205 0206 void EventTypeView::doUpdate(int changeType, bool) 0207 { 0208 // Special case ? 0209 if (changeType == selectedItemChanged) return; 0210 0211 if (changeType == eventType2Changed) return; 0212 0213 if (changeType == groupTypeChanged) { 0214 for(int i = 0; i < topLevelItemCount(); i++) 0215 ((EventTypeItem*)topLevelItem(i))->setGroupType(_groupType); 0216 0217 return; 0218 } 0219 0220 if (changeType == eventTypeChanged) { 0221 for(int i = 0; i < topLevelItemCount(); i++) { 0222 EventTypeItem* item = (EventTypeItem*)topLevelItem(i); 0223 if ( item->eventType() == _eventType) { 0224 setCurrentItem(item); 0225 scrollToItem(item); 0226 break; 0227 } 0228 } 0229 0230 return; 0231 } 0232 0233 if (changeType == partsChanged) { 0234 for(int i = 0; i < topLevelItemCount(); i++) 0235 ((EventTypeItem*)topLevelItem(i))->update(); 0236 0237 resizeColumnToContents(1); 0238 resizeColumnToContents(2); 0239 return; 0240 } 0241 0242 0243 refresh(); 0244 } 0245 0246 void EventTypeView::refresh() 0247 { 0248 clear(); 0249 setColumnWidth(1, 50); 0250 setColumnWidth(2, 50); 0251 0252 if (!_data || !_activeItem) return; 0253 switch(_activeItem->type()) { 0254 case ProfileContext::Object: 0255 case ProfileContext::Class: 0256 case ProfileContext::File: 0257 case ProfileContext::FunctionCycle: 0258 case ProfileContext::Function: 0259 break; 0260 default: 0261 return; 0262 } 0263 TraceCostItem* c = (TraceCostItem*) _activeItem; 0264 0265 EventType* ct =nullptr; 0266 QTreeWidgetItem* item = nullptr; 0267 QTreeWidgetItem* selected = nullptr; 0268 QList<QTreeWidgetItem*> items; 0269 0270 EventTypeSet* m = _data->eventTypes(); 0271 for (int i=0; i<m->realCount();i++) { 0272 ct = m->realType(i); 0273 item = new EventTypeItem(c, ct, _groupType); 0274 if (ct == _eventType) selected = item; 0275 items.append(item); 0276 } 0277 for (int i=0; i<m->derivedCount();i++) { 0278 ct = m->derivedType(i); 0279 if (!ct) continue; 0280 item = new EventTypeItem(c, ct, _groupType); 0281 if (ct == _eventType) selected = item; 0282 items.append(item); 0283 } 0284 insertTopLevelItems(0,items); 0285 0286 if (selected) { 0287 setCurrentItem(selected); 0288 scrollToItem(selected); 0289 } 0290 0291 for(int c = 0; c<6; c++) 0292 resizeColumnToContents(c); 0293 } 0294 0295 void EventTypeView::itemChanged(QTreeWidgetItem* item, int c) 0296 { 0297 EventType* ct = item ? ((EventTypeItem*) item)->eventType() : nullptr; 0298 if (!ct || ct->isReal()) return; 0299 0300 // search for matching known Type 0301 int knownCount = EventType::knownTypeCount(); 0302 EventType* known = nullptr; 0303 for (int i=0; i<knownCount; i++) { 0304 known = EventType::knownType(i); 0305 if (known->name() == ct->name()) break; 0306 } 0307 0308 QString t = item->text(c); 0309 if (c == 0) { 0310 ct->setLongName(t); 0311 if (known) known->setLongName(t); 0312 } 0313 else if (c == 3) { 0314 // not allowed to use already existing short name 0315 if (EventType::hasKnownRealType(t) || EventType::hasKnownDerivedType(t)) { 0316 if (_topLevel) 0317 _topLevel->showMessage("Error: Event type name already used", 0318 5000); 0319 } 0320 else { 0321 ct->setName(t); 0322 if (known) known->setName(t); 0323 } 0324 } 0325 else if (c == 5) { 0326 ct->setFormula(t); 0327 if (known) known->setFormula(t); 0328 } 0329 else return; 0330 0331 if (_topLevel) _topLevel->configChanged(); 0332 refresh(); 0333 } 0334 0335 #include "moc_eventtypeview.cpp"