File indexing completed on 2024-03-24 04:38:32
0001 /* This file is part of KDevelop 0002 * Copyright 2011 Sebastien Rannou <mxs@sbrk.org> 0003 * Copyright 2008 Hamish Rodda <rodda@kde.org> 0004 * Copyright 2011 Lucas Sarie <lucas.sarie@gmail.com> 0005 * Copyright 2017 Anton Anikin <anton@anikin.xyz> 0006 0007 This program is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This program is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with this program; see the file COPYING. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 0022 */ 0023 0024 #include "callgrind_view.h" 0025 #include "ui_callgrind_view.h" 0026 0027 #include "callgrind_config.h" 0028 #include "callgrind_model.h" 0029 #include "debug.h" 0030 #include "utils.h" 0031 0032 #include <QSortFilterProxyModel> 0033 #include <QProcess> 0034 #include <QTemporaryFile> 0035 0036 namespace Valgrind 0037 { 0038 0039 CallgrindView::CallgrindView(KConfigGroup configGroup, QTemporaryFile* outputFile, CallgrindFunctionsModel* model, QWidget* parent) 0040 : QWidget(parent) 0041 , ui(new Ui::CallgrindView) 0042 , m_kcachegrindProcess(new QProcess) 0043 { 0044 ui->setupUi(this); 0045 0046 Q_ASSERT(model); 0047 model->setParent(this); 0048 0049 Q_ASSERT(outputFile); 0050 outputFile->setParent(this); 0051 0052 for (const QString& eventType : model->eventTypes()) { 0053 ui->eventTypes->addItem(eventFullName(eventType)); 0054 } 0055 connect(ui->eventTypes, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), 0056 model, &CallgrindFunctionsModel::setCurrentEventType); 0057 model->setCurrentEventType(ui->eventTypes->currentIndex()); 0058 0059 connect(ui->percenageValues, &QCheckBox::stateChanged, 0060 model, &CallgrindFunctionsModel::setPercentageValues); 0061 model->setPercentageValues(ui->percenageValues->checkState()); 0062 0063 auto functionsProxyModel = new QSortFilterProxyModel(this); 0064 functionsProxyModel->setSourceModel(model); 0065 functionsProxyModel->setSortRole(SortRole); 0066 functionsProxyModel->setFilterKeyColumn(-1); 0067 ui->functionsView->setModel(functionsProxyModel); 0068 ui->functionsView->setSortingEnabled(true); 0069 0070 connect(ui->searchEdit, &QLineEdit::textChanged, 0071 functionsProxyModel, &QSortFilterProxyModel::setFilterWildcard); 0072 0073 auto eventsModel = new CallgrindFunctionEventsModel(model); 0074 ui->eventsView->setModel(eventsModel); 0075 ui->eventsView->header()->resizeSections(QHeaderView::ResizeToContents); 0076 0077 auto callersModel = new CallgrindFunctionCallersCalleesModel(model, true); 0078 auto callersProxyModel = new QSortFilterProxyModel(this); 0079 callersProxyModel->setSourceModel(callersModel); 0080 callersProxyModel->setSortRole(SortRole); 0081 ui->callersView->setModel(callersProxyModel); 0082 ui->callersView->setSortingEnabled(true); 0083 0084 connect(callersModel, &CallgrindFunctionCallersCalleesModel::headerDataChanged, 0085 this, [this](Qt::Orientation, int, int) { 0086 ui->callersView->header()->resizeSections(QHeaderView::ResizeToContents); 0087 }); 0088 0089 auto calleesModel = new CallgrindFunctionCallersCalleesModel(model, false); 0090 auto calleesProxyModel = new QSortFilterProxyModel(this); 0091 calleesProxyModel->setSourceModel(calleesModel); 0092 calleesProxyModel->setSortRole(SortRole); 0093 ui->calleesView->setModel(calleesProxyModel); 0094 ui->calleesView->setSortingEnabled(true); 0095 0096 connect(calleesModel, &CallgrindFunctionCallersCalleesModel::headerDataChanged, 0097 this, [this](Qt::Orientation, int, int) { 0098 ui->calleesView->header()->resizeSections(QHeaderView::ResizeToContents); 0099 }); 0100 0101 connect(ui->functionsView->selectionModel(), &QItemSelectionModel::currentChanged, 0102 this, [=](const QModelIndex& currentProxyIndex, const QModelIndex&) { 0103 0104 auto sourceIndex = functionsProxyModel->mapToSource(currentProxyIndex); 0105 auto function = static_cast<CallgrindFunction*>(sourceIndex.internalPointer()); 0106 0107 eventsModel->setFunction(function); 0108 callersModel->setFunction(function); 0109 calleesModel->setFunction(function); 0110 0111 if (function) { 0112 ui->binaryLabel->setText(function->binaryFile); 0113 ui->sourceLabel->setText(function->sourceFiles.join('\n')); 0114 } else { 0115 ui->binaryLabel->clear(); 0116 ui->sourceLabel->clear(); 0117 } 0118 }); 0119 ui->binaryLabel->clear(); 0120 ui->sourceLabel->clear(); 0121 0122 if (functionsProxyModel->rowCount()) { 0123 ui->functionsView->setCurrentIndex(functionsProxyModel->index(0,0)); 0124 } 0125 0126 auto startVisualizer = [this, outputFile]() { 0127 m_kcachegrindProcess->start(CallgrindConfig::kcachegrindExecutablePath(), 0128 { outputFile->fileName() }); 0129 }; 0130 0131 CallgrindConfig config; 0132 config.setConfigGroup(configGroup); 0133 config.load(); 0134 0135 setupVisualizerProcess(m_kcachegrindProcess.data(), 0136 ui->launchKCachegrindButton, 0137 startVisualizer, config.launchKCachegrind()); 0138 } 0139 0140 CallgrindView::~CallgrindView() 0141 { 0142 m_kcachegrindProcess->disconnect(); // FIXME is this really needed ? 0143 } 0144 0145 }