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

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  * StackSelection for KCachegrind
0011  * For function selection of a most expected stack,
0012  *  to be put into a QDockWindow
0013  */
0014 
0015 #include "stackselection.h"
0016 
0017 #include <QPushButton>
0018 #include <QVBoxLayout>
0019 #include <QTreeWidget>
0020 #include <QHeaderView>
0021 
0022 #include "stackbrowser.h"
0023 #include "stackitem.h"
0024 
0025 
0026 StackSelection::StackSelection(QWidget* parent)
0027     : QWidget(parent)
0028 {
0029     _data = nullptr;
0030     _browser = new StackBrowser();
0031     _function = nullptr;
0032     _eventType = nullptr;
0033     _eventType2 = nullptr;
0034     _groupType = ProfileContext::Function;
0035 
0036     setWindowTitle(tr("Stack Selection"));
0037 
0038     QVBoxLayout* vboxLayout = new QVBoxLayout(this);
0039     vboxLayout->setSpacing(6);
0040     vboxLayout->setContentsMargins(3, 3, 3, 3);
0041 
0042     _stackList = new QTreeWidget(this);
0043     QStringList headerLabels;
0044     headerLabels << tr("Cost")
0045                  << tr("Cost2")
0046                  << tr("Calls")
0047                  << tr("Function");
0048     _stackList->setHeaderLabels(headerLabels);
0049     _stackList->setRootIsDecorated(false);
0050     _stackList->setAllColumnsShowFocus(true);
0051     _stackList->setUniformRowHeights(true);
0052     _stackList->setSortingEnabled(false);
0053     _stackList->setColumnWidth(0, 50);
0054     // 2nd cost column hidden at first (_eventType2 == 0)
0055     _stackList->setColumnWidth(1, 0);
0056     _stackList->setColumnWidth(2, 50);
0057     vboxLayout->addWidget(_stackList);
0058 
0059     connect(_stackList,
0060             &QTreeWidget::currentItemChanged,
0061             this, &StackSelection::stackSelected );
0062 }
0063 
0064 StackSelection::~StackSelection()
0065 {
0066     delete _browser;
0067 }
0068 
0069 void StackSelection::setData(TraceData* data)
0070 {
0071     if (_data == data) return;
0072 
0073     _data = data;
0074 
0075     _stackList->clear();
0076     delete _browser;
0077     _browser = new StackBrowser();
0078     _function = nullptr;
0079 }
0080 
0081 
0082 void StackSelection::setFunction(TraceFunction* f)
0083 {
0084     if (_function == f) return;
0085     _function = f;
0086 
0087     if (!_data || !_function) return;
0088 
0089     //qDebug() << "StackSelection::setFunction " << f->name();
0090 
0091     HistoryItem* item = _browser->current();
0092     if (!item || item->function() != f) {
0093         _browser->select(f);
0094         rebuildStackList();
0095     }
0096 }
0097 
0098 
0099 void StackSelection::rebuildStackList()
0100 {
0101     HistoryItem* item = _browser->current();
0102     _stackList->clear();
0103     _stackList->setColumnWidth(0, 50);
0104     _stackList->setColumnWidth(1, _eventType2 ? 50:0);
0105     _stackList->setColumnWidth(2, 50);
0106     if (!item || !item->stack()) return;
0107 
0108     TraceFunction* top = item->stack()->top();
0109     if (!top) return;
0110 
0111 
0112     QList<QTreeWidgetItem*> items;
0113     QTreeWidgetItem* activeItem = nullptr;
0114     TraceCallList l = item->stack()->calls();
0115     for(int i=l.count()-1; i>=0; i--) {
0116         StackItem* si = new StackItem(this, nullptr, l.at(i));
0117         if (si->function() == item->function())
0118             activeItem = si;
0119         items.prepend(si);
0120     }
0121     StackItem* si = new StackItem(this, nullptr, top);
0122     if (si->function() == item->function())
0123         activeItem = si;
0124     items.prepend(si);
0125 
0126 #if QT_VERSION >= 0x050000
0127     _stackList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0128     _stackList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
0129     _stackList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
0130 #else
0131     _stackList->header()->setResizeMode(0, QHeaderView::ResizeToContents);
0132     _stackList->header()->setResizeMode(1, QHeaderView::ResizeToContents);
0133     _stackList->header()->setResizeMode(2, QHeaderView::ResizeToContents);
0134 #endif
0135 
0136     _stackList->addTopLevelItems(items);
0137     if (activeItem) {
0138         // this calls stackFunctionSelected()
0139         _stackList->setCurrentItem(activeItem);
0140         _stackList->scrollToItem(activeItem);
0141     }
0142 
0143 #if QT_VERSION >= 0x050000
0144     _stackList->header()->setSectionResizeMode(0, QHeaderView::Interactive);
0145     _stackList->header()->setSectionResizeMode(1, QHeaderView::Interactive);
0146     _stackList->header()->setSectionResizeMode(2, QHeaderView::Interactive);
0147 #else
0148     _stackList->header()->setResizeMode(0, QHeaderView::Interactive);
0149     _stackList->header()->setResizeMode(1, QHeaderView::Interactive);
0150     _stackList->header()->setResizeMode(2, QHeaderView::Interactive);
0151 #endif
0152 
0153     if (!_eventType2) {
0154         _stackList->setColumnWidth(1, 0);
0155     }
0156 }
0157 
0158 void StackSelection::stackSelected(QTreeWidgetItem* i, QTreeWidgetItem*)
0159 {
0160     if (!i) return;
0161 
0162     TraceFunction* f = ((StackItem*)i)->function();
0163     emit functionSelected(f);
0164 }
0165 
0166 
0167 void StackSelection::browserBack()
0168 {
0169     if (_browser && _browser->canGoBack()) {
0170         _browser->goBack();
0171         rebuildStackList();
0172     }
0173 }
0174 
0175 void StackSelection::browserForward()
0176 {
0177     if (_browser && _browser->canGoForward()) {
0178         _browser->goForward();
0179         rebuildStackList();
0180     }
0181 }
0182 
0183 void StackSelection::browserUp()
0184 {
0185     if (_browser) {
0186         _browser->goUp();
0187         rebuildStackList();
0188     }
0189 }
0190 
0191 void StackSelection::browserDown()
0192 {
0193     if (_browser) {
0194         _browser->goDown();
0195         rebuildStackList();
0196     }
0197 }
0198 
0199 void StackSelection::refresh()
0200 {
0201 #if QT_VERSION >= 0x050000
0202     _stackList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0203     _stackList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
0204 #else
0205     _stackList->header()->setResizeMode(0, QHeaderView::ResizeToContents);
0206     _stackList->header()->setResizeMode(1, QHeaderView::ResizeToContents);
0207 #endif
0208 
0209     // there is no resorting allowed, so this is save
0210     for(int i = 0; i < _stackList->topLevelItemCount(); i++) {
0211         QTreeWidgetItem* item = _stackList->topLevelItem(i);
0212         ((StackItem*)item)->updateCost();
0213     }
0214 
0215     if (!_eventType2) {
0216 #if QT_VERSION >= 0x050000
0217         _stackList->header()->setSectionResizeMode(1, QHeaderView::Interactive);
0218 #else
0219         _stackList->header()->setResizeMode(1, QHeaderView::Interactive);
0220 #endif
0221         _stackList->setColumnWidth(1, 0);
0222     }
0223 }
0224 
0225 void StackSelection::setEventType(EventType* ct)
0226 {
0227     if (ct == _eventType) return;
0228     _eventType = ct;
0229 
0230     if (_eventType)
0231         _stackList->headerItem()->setText(0, _eventType->name());
0232 
0233     refresh();
0234 }
0235 
0236 void StackSelection::setEventType2(EventType* ct)
0237 {
0238     if (ct == _eventType2) return;
0239     _eventType2 = ct;
0240 
0241     if (_eventType2)
0242         _stackList->headerItem()->setText(1, _eventType2->name());
0243 
0244     refresh();
0245 }
0246 
0247 void StackSelection::setGroupType(ProfileContext::Type gt)
0248 {
0249     if (_groupType == gt) return;
0250     _groupType = gt;
0251 
0252     for(int i = 0; i < _stackList->topLevelItemCount(); i++) {
0253         QTreeWidgetItem* item = _stackList->topLevelItem(i);
0254         ((StackItem*)item)->updateGroup();
0255     }
0256 }
0257 
0258 #include "moc_stackselection.cpp"