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"