File indexing completed on 2024-04-28 05:41:36

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  * Part View
0011  */
0012 
0013 
0014 #include "partview.h"
0015 
0016 #include <QAction>
0017 #include <QMenu>
0018 #include <QTreeWidget>
0019 #include <QHeaderView>
0020 #include <QKeyEvent>
0021 
0022 #include "partlistitem.h"
0023 #include "toplevelbase.h"
0024 
0025 
0026 //
0027 // PartView
0028 //
0029 
0030 
0031 PartView::PartView(TraceItemView* parentView, QWidget* parent)
0032     : QTreeWidget(parent), TraceItemView(parentView)
0033 {
0034     _inSelectionUpdate = false;
0035 
0036     QStringList headerLabels;
0037     headerLabels << tr( "Profile Part" )
0038                  << tr( "Incl." )
0039                  << tr( "Self" )
0040                  << tr( "Called" )
0041                  << tr( "Comment" );
0042     setHeaderLabels(headerLabels);
0043 
0044     setAllColumnsShowFocus(true);
0045     setRootIsDecorated(false);
0046     setUniformRowHeights(true);
0047     // sorting will be enabled after refresh()
0048     sortByColumn(0, Qt::DescendingOrder);
0049     setMinimumHeight(50);
0050     setSelectionMode(QAbstractItemView::ExtendedSelection);
0051 
0052     connect( this, &QTreeWidget::itemSelectionChanged,
0053              this, &PartView::selectionChangedSlot );
0054 
0055     setContextMenuPolicy(Qt::CustomContextMenu);
0056     connect( this,
0057              &QWidget::customContextMenuRequested,
0058              this, &PartView::context);
0059 
0060     connect(header(), &QHeaderView::sectionClicked,
0061             this, &PartView::headerClicked);
0062 
0063     setWhatsThis( whatsThis() );
0064 }
0065 
0066 QString PartView::whatsThis() const
0067 {
0068     return tr( "<b>Trace Part List</b>"
0069                "<p>This list shows all trace parts of the loaded "
0070                "trace. For each part, the "
0071                "self/inclusive cost of the current selected "
0072                "function, spent in the part, is shown; "
0073                "percentage costs are always relative to the "
0074                "total cost <em>of the part</em> (not to the whole "
0075                "trace as in the Trace Part Overview). "
0076                "Also shown are the calls happening to/from the "
0077                "current function inside of the trace part.</p>"
0078                "<p>By choosing one or more trace parts from the "
0079                "list, the costs shown all over KCachegrind will "
0080                "only be the ones spent in the selected part(s). "
0081                "If no list selection is shown, in fact all trace "
0082                "parts are selected implicitly.</p>"
0083                "<p>This is a multi-selection list. You can select "
0084                "ranges by dragging the mouse or use SHIFT/CTRL "
0085                "modifiers. "
0086                "Selection/Deselection of trace parts can also be "
0087                "done by using the Trace Part Overview Dockable. "
0088                "This one also supports multiple selection.</p>"
0089                "<p>Note that the list is hidden if only one trace "
0090                "part is loaded.</p>");
0091 }
0092 
0093 
0094 void PartView::context(const QPoint & p)
0095 {
0096     QMenu popup;
0097     addGoMenu(&popup);
0098 
0099     // p is in local coordinates
0100     popup.exec(mapToGlobal(p + QPoint(0,header()->height())));
0101 }
0102 
0103 
0104 void PartView::selectionChangedSlot()
0105 {
0106     if (_inSelectionUpdate) return;
0107 
0108     TracePartList l;
0109     QList<QTreeWidgetItem*> sItems = selectedItems();
0110     foreach(QTreeWidgetItem* item, sItems)
0111         l.append( ((PartListItem*)item)->part() );
0112 
0113     // nothing selected means all
0114     if (l.isEmpty()) l = _data->parts();
0115 
0116     partsSelected(l);
0117 }
0118 
0119 void PartView::headerClicked(int col)
0120 {
0121     // name columns should be sortable in both ways
0122     if ((col == 0) || (col == 4)) return;
0123 
0124     // all others only descending
0125     sortByColumn(col, Qt::DescendingOrder);
0126 }
0127 
0128 CostItem* PartView::canShow(CostItem* i)
0129 {
0130     if (!TraceItemView::data()) return nullptr;
0131     if (TraceItemView::data()->parts().count()>1) return i;
0132     return nullptr;
0133 }
0134 
0135 void PartView::doUpdate(int changeType, bool)
0136 {
0137     // Special case ?
0138     if (changeType == eventType2Changed) return;
0139     if (changeType == selectedItemChanged) return;
0140 
0141     if (changeType == groupTypeChanged) {
0142         QTreeWidgetItem *item;
0143         for (int i=0; i<topLevelItemCount(); i++){
0144             item = topLevelItem(i);
0145             ((PartListItem*)item)->setGroupType(_groupType);
0146         }
0147         return;
0148     }
0149 
0150     if (changeType == eventTypeChanged) {
0151 #if QT_VERSION >= 0x050000
0152         header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
0153         header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
0154 #else
0155         header()->setResizeMode(1, QHeaderView::ResizeToContents);
0156         header()->setResizeMode(2, QHeaderView::ResizeToContents);
0157 #endif
0158         // need to disable sorting! Otherwise each change of shown cost
0159         // can reorders list and change order returned by topLevelItem()
0160         setSortingEnabled(false);
0161         for (int i=0; i< topLevelItemCount(); i++) {
0162             PartListItem* item = (PartListItem*) topLevelItem(i);
0163             item->setEventType(_eventType);
0164         }
0165 #if QT_VERSION >= 0x050000
0166         header()->setSectionResizeMode(1, QHeaderView::Interactive);
0167         header()->setSectionResizeMode(2, QHeaderView::Interactive);
0168 #else
0169         header()->setResizeMode(1, QHeaderView::Interactive);
0170         header()->setResizeMode(2, QHeaderView::Interactive);
0171 #endif
0172         setSortingEnabled(true);
0173         header()->setSortIndicatorShown(false);
0174 
0175         return;
0176     }
0177 
0178     if (changeType == partsChanged) {
0179 
0180         TracePart* part;
0181 
0182         _inSelectionUpdate = true;
0183         for (int i=0; i< topLevelItemCount(); i++) {
0184             PartListItem* item = (PartListItem*) topLevelItem(i);
0185             part = ((PartListItem*)item)->part();
0186 
0187             if (_partList.contains(part)) {
0188                 item->setSelected(true);
0189                 scrollToItem(item);
0190             }
0191             else
0192                 item->setSelected(false);
0193         }
0194         _inSelectionUpdate = false;
0195 
0196         return;
0197     }
0198 
0199     refresh();
0200 }
0201 
0202 void PartView::refresh()
0203 {
0204     setColumnWidth(1, 50);
0205     setColumnWidth(2, 50);
0206 
0207     if (!_data || !_activeItem) {
0208         clear();
0209         return;
0210     }
0211 
0212     ProfileContext::Type t = _activeItem->type();
0213     TraceFunction* f = nullptr;
0214     if (t == ProfileContext::Function) f = (TraceFunction*) _activeItem;
0215     if (!f) return;
0216 
0217     TracePartList hidden;
0218     if (_topLevel)
0219         hidden = _topLevel->hiddenParts();
0220 
0221     _inSelectionUpdate = true;
0222     clear();
0223 
0224     QList<QTreeWidgetItem*> items;
0225     QTreeWidgetItem* item;
0226     foreach(TracePart* part, _data->parts()) {
0227         if (hidden.contains(part)) continue;
0228         item = new PartListItem(nullptr, f, _eventType, _groupType, part);
0229         items.append(item);
0230     }
0231     setSortingEnabled(false);
0232     addTopLevelItems(items);
0233     setSortingEnabled(true);
0234     header()->setSortIndicatorShown(false);
0235     header()->resizeSections(QHeaderView::ResizeToContents);
0236 
0237     foreach(item, items) {
0238         TracePart* part = ((PartListItem*)item)->part();
0239         if (hidden.contains(part)) continue;
0240         if (part->isActive()) {
0241             item->setSelected(true);
0242             scrollToItem(item);
0243         }
0244     }
0245 
0246     _inSelectionUpdate = false;
0247 }
0248 
0249 #include "moc_partview.cpp"