diff --git a/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp b/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp index 37d52b4ea6f..cf23a94c063 100644 --- a/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcallmodel.cpp @@ -36,31 +36,17 @@ namespace Valgrind { namespace Callgrind { -//BEGIN CallModel::Private - class CallModel::Private { public: - Private(); - - const ParseData *m_data; + const ParseData *m_data = 0; QVector m_calls; - int m_event; - const Function *m_function; + int m_event = 0; + const Function *m_function = 0; }; -CallModel::Private::Private() - : m_data(0) - , m_event(0) - , m_function(0) -{ -} - -//END CallModel::Private - -//BEGIN CallModel -CallModel::CallModel(QObject *parent) - : QAbstractItemModel(parent), d(new Private) +CallModel::CallModel() + : d(new Private) { } diff --git a/src/plugins/valgrind/callgrind/callgrindcallmodel.h b/src/plugins/valgrind/callgrind/callgrindcallmodel.h index 8096e66ee3b..a297f7f9de5 100644 --- a/src/plugins/valgrind/callgrind/callgrindcallmodel.h +++ b/src/plugins/valgrind/callgrind/callgrindcallmodel.h @@ -43,7 +43,7 @@ class CallModel : public QAbstractItemModel { Q_OBJECT public: - explicit CallModel(QObject *parent); + CallModel(); virtual ~CallModel(); void clear(); diff --git a/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp b/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp index e821e977b5e..d282822666b 100644 --- a/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrinddatamodel.cpp @@ -41,27 +41,16 @@ namespace Valgrind { namespace Callgrind { -//BEGIN DataModel::Private - class DataModel::Private { public: - Private() - : m_data(0) - , m_event(0) - , m_verboseToolTips(true) - , m_cycleDetection(false) - , m_shortenTemplates(false) - { - } - void updateFunctions(); - const ParseData *m_data; - int m_event; - bool m_verboseToolTips; - bool m_cycleDetection; - bool m_shortenTemplates; + const ParseData *m_data = 0; + int m_event = 0; + bool m_verboseToolTips = true; + bool m_cycleDetection = false; + bool m_shortenTemplates = false; QVector m_functions; }; @@ -77,10 +66,8 @@ void DataModel::Private::updateFunctions() } } -//BEGIN DataModel - -DataModel::DataModel(QObject *parent) - : QAbstractItemModel(parent), d(new Private) +DataModel::DataModel() + : d(new Private) { } diff --git a/src/plugins/valgrind/callgrind/callgrinddatamodel.h b/src/plugins/valgrind/callgrind/callgrinddatamodel.h index 602f65af19a..43b8dbef232 100644 --- a/src/plugins/valgrind/callgrind/callgrinddatamodel.h +++ b/src/plugins/valgrind/callgrind/callgrinddatamodel.h @@ -41,7 +41,7 @@ class DataModel : public QAbstractItemModel Q_OBJECT public: - explicit DataModel(QObject *parent); + DataModel(); virtual ~DataModel(); virtual void setParseData(const ParseData *data); diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index de22d4e502c..26065fee713 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -43,25 +43,31 @@ #include #include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include +#include #include #include #include -#include +#include #include #include -#include #include +#include #include #include @@ -70,24 +76,19 @@ #include #include -#include -#include -#include - #include #include -#include #include -#include +#include #include -#include +#include #include #include #include #include +#include #include #include -#include using namespace Analyzer; using namespace Core; @@ -98,33 +99,29 @@ using namespace ProjectExplorer; namespace Valgrind { namespace Internal { -class CallgrindToolPrivate : public QObject +class CallgrindTool : public QObject { Q_OBJECT public: - friend class CallgrindTool; + CallgrindTool(QObject *parent); + ~CallgrindTool(); - explicit CallgrindToolPrivate(CallgrindTool *parent); - virtual ~CallgrindToolPrivate(); + ValgrindRunControl *createRunControl(RunConfiguration *runConfiguration); + void createWidgets(); void setParseData(ParseData *data); - CostDelegate::CostFormat costFormat() const; - QWidget *createWidgets(); void doClear(bool clearParseData); void updateEventCombo(); - ValgrindRunControl *createRunControl(RunConfiguration *runConfiguration = 0); - signals: - void cycleDetectionEnabled(bool enabled); void dumpRequested(); void resetRequested(); void pauseToggled(bool checked); -public slots: +public: void slotClear(); void slotRequestDump(); void loadExternalLogFile(); @@ -169,104 +166,143 @@ public slots: void requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu); public: - CallgrindTool *q; + DataModel m_dataModel; + DataProxyModel m_proxyModel; + StackBrowser m_stackBrowser; - DataModel *m_dataModel; - DataProxyModel *m_proxyModel; - StackBrowser *m_stackBrowser; + CallModel m_callersModel; + CallModel m_calleesModel; - CallModel *m_callersModel; - CallModel *m_calleesModel; + QSortFilterProxyModel m_callersProxy; + QSortFilterProxyModel m_calleesProxy; - // callgrind widgets - CostView *m_flatView; - CostView *m_callersView; - CostView *m_calleesView; - Visualisation *m_visualisation; + // Callgrind widgets + CostView *m_flatView = 0; + CostView *m_callersView = 0; + CostView *m_calleesView = 0; + Visualisation *m_visualization = 0; - // navigation - QAction *m_goBack; - QAction *m_goNext; - QLineEdit *m_searchFilter; + // Navigation + QAction *m_goBack = 0; + QAction *m_goNext = 0; + QLineEdit *m_searchFilter = 0; - // cost formatting - QAction *m_filterProjectCosts; - QAction *m_costAbsolute; - QAction *m_costRelative; - QAction *m_costRelativeToParent; + // Cost formatting + QAction *m_filterProjectCosts = 0; + QAction *m_costAbsolute = 0; + QAction *m_costRelative = 0; + QAction *m_costRelativeToParent = 0; QAction *m_cycleDetection; QAction *m_shortenTemplates; - QComboBox *m_eventCombo; + QComboBox *m_eventCombo = 0; - QTimer *m_updateTimer; + QTimer m_updateTimer; QVector m_textMarks; QAction *m_loadExternalLogFile; - QAction *m_dumpAction; - QAction *m_resetAction; - QAction *m_pauseAction; + QAction *m_dumpAction = 0; + QAction *m_resetAction = 0; + QAction *m_pauseAction = 0; QString m_toggleCollectFunction; }; -CallgrindToolPrivate::CallgrindToolPrivate(CallgrindTool *parent) - : q(parent) - , m_dataModel(new DataModel(this)) - , m_proxyModel(new DataProxyModel(this)) - , m_stackBrowser(new StackBrowser(this)) - , m_callersModel(new CallModel(this)) - , m_calleesModel(new CallModel(this)) - , m_flatView(0) - , m_callersView(0) - , m_calleesView(0) - , m_visualisation(0) - , m_goBack(0) - , m_goNext(0) - , m_searchFilter(0) - , m_filterProjectCosts(0) - , m_costAbsolute(0) - , m_costRelative(0) - , m_costRelativeToParent(0) - , m_eventCombo(0) - , m_updateTimer(new QTimer(this)) - , m_dumpAction(0) - , m_resetAction(0) - , m_pauseAction(0) +CallgrindTool::CallgrindTool(QObject *parent) + : QObject(parent) { - m_updateTimer->setInterval(200); - m_updateTimer->setSingleShot(true); + setObjectName(QLatin1String("CallgrindTool")); - m_proxyModel->setSourceModel(m_dataModel); - m_proxyModel->setDynamicSortFilter(true); - m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - m_proxyModel->setFilterKeyColumn(DataModel::NameColumn); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_updateTimer.setInterval(200); + m_updateTimer.setSingleShot(true); - connect(m_stackBrowser, &StackBrowser::currentChanged, - this, &CallgrindToolPrivate::stackBrowserChanged); - connect(m_updateTimer, &QTimer::timeout, - this, &CallgrindToolPrivate::updateFilterString); + m_proxyModel.setSourceModel(&m_dataModel); + m_proxyModel.setDynamicSortFilter(true); + m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive); + m_proxyModel.setFilterKeyColumn(DataModel::NameColumn); + m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive); + + connect(&m_stackBrowser, &StackBrowser::currentChanged, + this, &CallgrindTool::stackBrowserChanged); + connect(&m_updateTimer, &QTimer::timeout, + this, &CallgrindTool::updateFilterString); + + connect(EditorManager::instance(), &EditorManager::editorOpened, + this, &CallgrindTool::editorOpened); + + ActionDescription desc; + desc.setToolTip(tr("Valgrind Function Profile uses the " + "Callgrind tool to record function calls when a program runs.")); + + if (!Utils::HostOsInfo::isWindowsHost()) { + desc.setText(tr("Valgrind Function Profiler")); + desc.setPerspectiveId(CallgrindPerspectiveId); + desc.setRunControlCreator([this](RunConfiguration *runConfiguration, Id) { + return createRunControl(runConfiguration); + }); + desc.setToolMode(OptimizedMode); + desc.setRunMode(CALLGRIND_RUN_MODE); + desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); + AnalyzerManager::registerAction(CallgrindLocalActionId, desc); + } + + desc.setText(tr("Valgrind Function Profiler (External Remote Application)")); + desc.setPerspectiveId(CallgrindPerspectiveId); + desc.setCustomToolStarter([this](ProjectExplorer::RunConfiguration *runConfig) { + StartRemoteDialog dlg; + if (dlg.exec() != QDialog::Accepted) + return; + ValgrindRunControl *rc = createRunControl(runConfig); + QTC_ASSERT(rc, return); + const auto runnable = dlg.runnable(); + rc->setRunnable(runnable); + AnalyzerConnection connection; + connection.connParams = dlg.sshParams(); + rc->setConnection(connection); + rc->setDisplayName(runnable.executable); + ProjectExplorerPlugin::startRunControl(rc, CALLGRIND_RUN_MODE); + }); + desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS); + AnalyzerManager::registerAction(CallgrindRemoteActionId, desc); + + // If there is a CppEditor context menu add our own context menu actions. + if (ActionContainer *editorContextMenu = + ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT)) { + Context analyzerContext = Context(Analyzer::Constants::C_ANALYZEMODE); + editorContextMenu->addSeparator(analyzerContext); + + auto action = new QAction(tr("Profile Costs of This Function and Its Callees"), this); + action->setIcon(Analyzer::Icons::ANALYZER_CONTROL_START.icon()); + connect(action, &QAction::triggered, this, + &CallgrindTool::handleShowCostsOfFunction); + Command *cmd = ActionManager::registerAction(action, "Analyzer.Callgrind.ShowCostsOfFunction", + analyzerContext); + editorContextMenu->addAction(cmd); + cmd->setAttribute(Command::CA_Hide); + cmd->setAttribute(Command::CA_NonConfigurable); + } + + createWidgets(); } -CallgrindToolPrivate::~CallgrindToolPrivate() +CallgrindTool::~CallgrindTool() { qDeleteAll(m_textMarks); doClear(false); } -void CallgrindToolPrivate::slotGoToOverview() +void CallgrindTool::slotGoToOverview() { selectFunction(0); } -void CallgrindToolPrivate::slotClear() +void CallgrindTool::slotClear() { doClear(true); } -void CallgrindToolPrivate::doClear(bool clearParseData) +void CallgrindTool::doClear(bool clearParseData) { if (clearParseData) // Crashed when done from destructor. setParseData(0); @@ -274,46 +310,46 @@ void CallgrindToolPrivate::doClear(bool clearParseData) // clear filters if (m_filterProjectCosts) m_filterProjectCosts->setChecked(false); - m_proxyModel->setFilterBaseDir(QString()); + m_proxyModel.setFilterBaseDir(QString()); if (m_searchFilter) m_searchFilter->clear(); - m_proxyModel->setFilterFixedString(QString()); + m_proxyModel.setFilterFixedString(QString()); } -void CallgrindToolPrivate::setBusyCursor(bool busy) +void CallgrindTool::setBusyCursor(bool busy) { QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor); m_flatView->setCursor(cursor); m_calleesView->setCursor(cursor); m_callersView->setCursor(cursor); - m_visualisation->setCursor(cursor); + m_visualization->setCursor(cursor); } -void CallgrindToolPrivate::selectFunction(const Function *func) +void CallgrindTool::selectFunction(const Function *func) { if (!func) { m_flatView->clearSelection(); - m_visualisation->setFunction(0); - m_callersModel->clear(); - m_calleesModel->clear(); + m_visualization->setFunction(0); + m_callersModel.clear(); + m_calleesModel.clear(); return; } - const QModelIndex index = m_dataModel->indexForObject(func); - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(index); + const QModelIndex index = m_dataModel.indexForObject(func); + const QModelIndex proxyIndex = m_proxyModel.mapFromSource(index); m_flatView->selectionModel()->clearSelection(); m_flatView->selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); m_flatView->scrollTo(proxyIndex); - m_callersModel->setCalls(func->incomingCalls(), func); - m_calleesModel->setCalls(func->outgoingCalls(), func); - m_visualisation->setFunction(func); + m_callersModel.setCalls(func->incomingCalls(), func); + m_calleesModel.setCalls(func->outgoingCalls(), func); + m_visualization->setFunction(func); - const Function *item = m_stackBrowser->current(); + const Function *item = m_stackBrowser.current(); if (!item || item != func) - m_stackBrowser->select(func); + m_stackBrowser.select(func); if (QFile::exists(func->file())) { ///TODO: custom position support? @@ -322,20 +358,20 @@ void CallgrindToolPrivate::selectFunction(const Function *func) } } -void CallgrindToolPrivate::stackBrowserChanged() +void CallgrindTool::stackBrowserChanged() { - m_goBack->setEnabled(m_stackBrowser->hasPrevious()); - m_goNext->setEnabled(m_stackBrowser->hasNext()); - const Function *item = m_stackBrowser->current(); + m_goBack->setEnabled(m_stackBrowser.hasPrevious()); + m_goNext->setEnabled(m_stackBrowser.hasNext()); + const Function *item = m_stackBrowser.current(); selectFunction(item); } -void CallgrindToolPrivate::updateFilterString() +void CallgrindTool::updateFilterString() { - m_proxyModel->setFilterFixedString(m_searchFilter->text()); + m_proxyModel.setFilterFixedString(m_searchFilter->text()); } -void CallgrindToolPrivate::setCostFormat(CostDelegate::CostFormat format) +void CallgrindTool::setCostFormat(CostDelegate::CostFormat format) { switch (format) { case CostDelegate::FormatAbsolute: @@ -350,31 +386,31 @@ void CallgrindToolPrivate::setCostFormat(CostDelegate::CostFormat format) } } -void CallgrindToolPrivate::setCostEvent(int index) +void CallgrindTool::setCostEvent(int index) { // prevent assert in model, don't try to set event to -1 // happens when we clear the eventcombo if (index == -1) index = 0; - m_dataModel->setCostEvent(index); - m_calleesModel->setCostEvent(index); - m_callersModel->setCostEvent(index); + m_dataModel.setCostEvent(index); + m_calleesModel.setCostEvent(index); + m_callersModel.setCostEvent(index); } -void CallgrindToolPrivate::enableCycleDetection(bool enabled) +void CallgrindTool::enableCycleDetection(bool enabled) { m_cycleDetection->setChecked(enabled); } -void CallgrindToolPrivate::shortenTemplates(bool enabled) +void CallgrindTool::shortenTemplates(bool enabled) { m_shortenTemplates->setChecked(enabled); } // Following functions can be called with actions=0 or widgets=0 // depending on initialization sequence (whether callgrind was current). -CostDelegate::CostFormat CallgrindToolPrivate::costFormat() const +CostDelegate::CostFormat CallgrindTool::costFormat() const { if (m_costRelativeToParent && m_costRelativeToParent->isChecked()) return CostDelegate::FormatRelativeToParent; @@ -383,7 +419,7 @@ CostDelegate::CostFormat CallgrindToolPrivate::costFormat() const return CostDelegate::FormatAbsolute; } -void CallgrindToolPrivate::updateCostFormat() +void CallgrindTool::updateCostFormat() { const CostDelegate::CostFormat format = costFormat(); if (m_flatView) @@ -396,19 +432,19 @@ void CallgrindToolPrivate::updateCostFormat() settings->setCostFormat(format); } -void CallgrindToolPrivate::handleFilterProjectCosts() +void CallgrindTool::handleFilterProjectCosts() { Project *pro = ProjectTree::currentProject(); if (pro && m_filterProjectCosts->isChecked()) { const QString projectDir = pro->projectDirectory().toString(); - m_proxyModel->setFilterBaseDir(projectDir); + m_proxyModel.setFilterBaseDir(projectDir); } else { - m_proxyModel->setFilterBaseDir(QString()); + m_proxyModel.setFilterBaseDir(QString()); } } -void CallgrindToolPrivate::dataFunctionSelected(const QModelIndex &index) +void CallgrindTool::dataFunctionSelected(const QModelIndex &index) { const Function *func = index.data(DataModel::FunctionRole).value(); QTC_ASSERT(func, return); @@ -416,7 +452,7 @@ void CallgrindToolPrivate::dataFunctionSelected(const QModelIndex &index) selectFunction(func); } -void CallgrindToolPrivate::calleeFunctionSelected(const QModelIndex &index) +void CallgrindTool::calleeFunctionSelected(const QModelIndex &index) { const FunctionCall *call = index.data(CallModel::FunctionCallRole).value(); QTC_ASSERT(call, return); @@ -424,7 +460,7 @@ void CallgrindToolPrivate::calleeFunctionSelected(const QModelIndex &index) selectFunction(call->callee()); } -void CallgrindToolPrivate::callerFunctionSelected(const QModelIndex &index) +void CallgrindTool::callerFunctionSelected(const QModelIndex &index) { const FunctionCall *call = index.data(CallModel::FunctionCallRole).value(); QTC_ASSERT(call, return); @@ -432,22 +468,22 @@ void CallgrindToolPrivate::callerFunctionSelected(const QModelIndex &index) selectFunction(call->caller()); } -void CallgrindToolPrivate::visualisationFunctionSelected(const Function *function) +void CallgrindTool::visualisationFunctionSelected(const Function *function) { - if (function && function == m_visualisation->function()) + if (function && function == m_visualization->function()) // up-navigation when the initial function was activated - m_stackBrowser->goBack(); + m_stackBrowser.goBack(); else selectFunction(function); } -void CallgrindToolPrivate::setParseData(ParseData *data) +void CallgrindTool::setParseData(ParseData *data) { // we have new parse data, invalidate filters in the proxy model - m_visualisation->setFunction(0); + m_visualization->setFunction(0); // invalidate parse data in the data model - delete m_dataModel->parseData(); + delete m_dataModel.parseData(); if (data && data->events().isEmpty()) { // might happen if the user cancelled the profile run @@ -455,26 +491,26 @@ void CallgrindToolPrivate::setParseData(ParseData *data) delete data; data = 0; } - m_dataModel->setParseData(data); - m_calleesModel->setParseData(data); - m_callersModel->setParseData(data); + m_dataModel.setParseData(data); + m_calleesModel.setParseData(data); + m_callersModel.setParseData(data); updateEventCombo(); // clear history for new data - m_stackBrowser->clear(); + m_stackBrowser.clear(); // unset busy state //setBusy(false); } -void CallgrindToolPrivate::updateEventCombo() +void CallgrindTool::updateEventCombo() { QTC_ASSERT(m_eventCombo, return); m_eventCombo->clear(); - const ParseData *data = m_dataModel->parseData(); + const ParseData *data = m_dataModel.parseData(); if (!data || data->events().isEmpty()) { m_eventCombo->hide(); return; @@ -493,40 +529,17 @@ static QToolButton *createToolButton(QAction *action) return button; } -CallgrindTool::CallgrindTool(QObject *parent) - : QObject(parent) -{ - d = new CallgrindToolPrivate(this); - setObjectName(QLatin1String("CallgrindTool")); - - connect(EditorManager::instance(), &EditorManager::editorOpened, - d, &CallgrindToolPrivate::editorOpened); -} - -CallgrindTool::~CallgrindTool() -{ - delete d; -} - ValgrindRunControl *CallgrindTool::createRunControl(RunConfiguration *runConfiguration) -{ - return d->createRunControl(runConfiguration); -} - -ValgrindRunControl *CallgrindToolPrivate::createRunControl(RunConfiguration *runConfiguration) { auto rc = new CallgrindRunControl(runConfiguration); - connect(rc, &CallgrindRunControl::parserDataReady, - this, &CallgrindToolPrivate::takeParserDataFromRunControl); - connect(rc, &AnalyzerRunControl::starting, - this, &CallgrindToolPrivate::engineStarting); - connect(rc, &RunControl::finished, - this, &CallgrindToolPrivate::engineFinished); + connect(rc, &CallgrindRunControl::parserDataReady, this, &CallgrindTool::takeParserDataFromRunControl); + connect(rc, &AnalyzerRunControl::starting, this, &CallgrindTool::engineStarting); + connect(rc, &RunControl::finished, this, &CallgrindTool::engineFinished); - connect(this, &CallgrindToolPrivate::dumpRequested, rc, &CallgrindRunControl::dump); - connect(this, &CallgrindToolPrivate::resetRequested, rc, &CallgrindRunControl::reset); - connect(this, &CallgrindToolPrivate::pauseToggled, rc, &CallgrindRunControl::setPaused); + connect(this, &CallgrindTool::dumpRequested, rc, &CallgrindRunControl::dump); + connect(this, &CallgrindTool::resetRequested, rc, &CallgrindRunControl::reset); + connect(this, &CallgrindTool::pauseToggled, rc, &CallgrindRunControl::setPaused); // initialize run control rc->setPaused(m_pauseAction->isChecked()); @@ -535,47 +548,37 @@ ValgrindRunControl *CallgrindToolPrivate::createRunControl(RunConfiguration *run rc->setToggleCollectFunction(m_toggleCollectFunction); m_toggleCollectFunction.clear(); - QTC_ASSERT(m_visualisation, return rc); + QTC_ASSERT(m_visualization, return rc); // apply project settings if (runConfiguration) { if (IRunConfigurationAspect *analyzerAspect = runConfiguration->extraAspect(ANALYZER_VALGRIND_SETTINGS)) { if (const ValgrindBaseSettings *settings = qobject_cast(analyzerAspect->currentSettings())) { - m_visualisation->setMinimumInclusiveCostRatio(settings->visualisationMinimumInclusiveCostRatio() / 100.0); - m_proxyModel->setMinimumInclusiveCostRatio(settings->minimumInclusiveCostRatio() / 100.0); - m_dataModel->setVerboseToolTipsEnabled(settings->enableEventToolTips()); + m_visualization->setMinimumInclusiveCostRatio(settings->visualisationMinimumInclusiveCostRatio() / 100.0); + m_proxyModel.setMinimumInclusiveCostRatio(settings->minimumInclusiveCostRatio() / 100.0); + m_dataModel.setVerboseToolTipsEnabled(settings->enableEventToolTips()); } } } return rc; } -void CallgrindTool::handleShowCostsOfFunction() +void CallgrindTool::createWidgets() { - d->handleShowCostsOfFunction(); -} - -QWidget *CallgrindTool::createWidgets() -{ - return d->createWidgets(); -} - -QWidget *CallgrindToolPrivate::createWidgets() -{ - QTC_ASSERT(!m_visualisation, return 0); + QTC_ASSERT(!m_visualization, return); QSettings *coreSettings = ICore::settings(); // // DockWidgets // - m_visualisation = new Visualisation; - m_visualisation->setFrameStyle(QFrame::NoFrame); - m_visualisation->setObjectName(QLatin1String("Valgrind.CallgrindTool.Visualisation")); - m_visualisation->setWindowTitle(tr("Visualization")); - m_visualisation->setModel(m_dataModel); - connect(m_visualisation, &Visualisation::functionActivated, - this, &CallgrindToolPrivate::visualisationFunctionSelected); + m_visualization = new Visualisation; + m_visualization->setFrameStyle(QFrame::NoFrame); + m_visualization->setObjectName(QLatin1String("Valgrind.CallgrindTool.Visualisation")); + m_visualization->setWindowTitle(tr("Visualization")); + m_visualization->setModel(&m_dataModel); + connect(m_visualization, &Visualisation::functionActivated, + this, &CallgrindTool::visualisationFunctionSelected); m_callersView = new CostView; m_callersView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CallersView")); @@ -584,12 +587,11 @@ QWidget *CallgrindToolPrivate::createWidgets() m_callersView->sortByColumn(CallModel::CostColumn); m_callersView->setFrameStyle(QFrame::NoFrame); // enable sorting - QSortFilterProxyModel *callerProxy = new QSortFilterProxyModel(m_callersModel); - callerProxy->setSourceModel(m_callersModel); - m_callersView->setModel(callerProxy); + m_callersProxy.setSourceModel(&m_callersModel); + m_callersView->setModel(&m_callersProxy); m_callersView->hideColumn(CallModel::CalleeColumn); connect(m_callersView, &QAbstractItemView::activated, - this, &CallgrindToolPrivate::callerFunctionSelected); + this, &CallgrindTool::callerFunctionSelected); m_calleesView = new CostView; m_calleesView->setObjectName(QLatin1String("Valgrind.CallgrindTool.CalleesView")); @@ -598,12 +600,11 @@ QWidget *CallgrindToolPrivate::createWidgets() m_calleesView->sortByColumn(CallModel::CostColumn); m_calleesView->setFrameStyle(QFrame::NoFrame); // enable sorting - QSortFilterProxyModel *calleeProxy = new QSortFilterProxyModel(m_calleesModel); - calleeProxy->setSourceModel(m_calleesModel); - m_calleesView->setModel(calleeProxy); + m_calleesProxy.setSourceModel(&m_calleesModel); + m_calleesView->setModel(&m_calleesProxy); m_calleesView->hideColumn(CallModel::CallerColumn); connect(m_calleesView, &QAbstractItemView::activated, - this, &CallgrindToolPrivate::calleeFunctionSelected); + this, &CallgrindTool::calleeFunctionSelected); m_flatView = new CostView; m_flatView->setObjectName(QLatin1String("Valgrind.CallgrindTool.FlatView")); @@ -612,41 +613,27 @@ QWidget *CallgrindToolPrivate::createWidgets() m_flatView->sortByColumn(DataModel::SelfCostColumn); m_flatView->setFrameStyle(QFrame::NoFrame); m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false); - m_flatView->setModel(m_proxyModel); + m_flatView->setModel(&m_proxyModel); connect(m_flatView, &QAbstractItemView::activated, - this, &CallgrindToolPrivate::dataFunctionSelected); + this, &CallgrindTool::dataFunctionSelected); updateCostFormat(); - AnalyzerManager::registerDockWidget(CallgrindCallersDockId, m_callersView); - AnalyzerManager::registerDockWidget(CallgrindFlatDockId, m_flatView); - AnalyzerManager::registerDockWidget(CallgrindCalleesDockId, m_calleesView); - AnalyzerManager::registerDockWidget(CallgrindVisualizationDockId, m_visualisation); - - AnalyzerManager::registerPerspective(CallgrindPerspectiveId, { - { CallgrindFlatDockId, Id(), Perspective::SplitVertical }, - { CallgrindCalleesDockId, Id(), Perspective::SplitVertical }, - { CallgrindCallersDockId, CallgrindCalleesDockId, Perspective::SplitHorizontal }, - { CallgrindVisualizationDockId, Id(), Perspective::SplitVertical, - false, Qt::RightDockWidgetArea } - }); - // // Control Widget // - QAction *action = 0; - QWidget *widget = new QWidget; - QHBoxLayout *layout = new QHBoxLayout; - + auto layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(0); + + auto widget = new QWidget; widget->setLayout(layout); // load external log file - action = new QAction(this); + auto action = new QAction(this); action->setIcon(Core::Icons::OPENFILE.icon()); action->setToolTip(tr("Load External Log File")); - connect(action, &QAction::triggered, this, &CallgrindToolPrivate::loadExternalLogFile); + connect(action, &QAction::triggered, this, &CallgrindTool::loadExternalLogFile); layout->addWidget(createToolButton(action)); m_loadExternalLogFile = action; @@ -656,7 +643,7 @@ QWidget *CallgrindToolPrivate::createWidgets() action->setIcon(Core::Icons::REDO.icon()); //action->setText(tr("Dump")); action->setToolTip(tr("Request the dumping of profile information. This will update the Callgrind visualization.")); - connect(action, &QAction::triggered, this, &CallgrindToolPrivate::slotRequestDump); + connect(action, &QAction::triggered, this, &CallgrindTool::slotRequestDump); layout->addWidget(createToolButton(action)); m_dumpAction = action; @@ -666,7 +653,7 @@ QWidget *CallgrindToolPrivate::createWidgets() action->setIcon(Core::Icons::RELOAD.icon()); //action->setText(tr("Reset")); action->setToolTip(tr("Reset all event counters.")); - connect(action, &QAction::triggered, this, &CallgrindToolPrivate::resetRequested); + connect(action, &QAction::triggered, this, &CallgrindTool::resetRequested); layout->addWidget(createToolButton(action)); m_resetAction = action; @@ -676,7 +663,7 @@ QWidget *CallgrindToolPrivate::createWidgets() action->setIcon(ProjectExplorer::Icons::INTERRUPT_SMALL.icon()); //action->setText(tr("Ignore")); action->setToolTip(tr("Pause event logging. No events are counted which will speed up program execution during profiling.")); - connect(action, &QAction::toggled, this, &CallgrindToolPrivate::pauseToggled); + connect(action, &QAction::toggled, this, &CallgrindTool::pauseToggled); layout->addWidget(createToolButton(action)); m_pauseAction = action; @@ -686,7 +673,7 @@ QWidget *CallgrindToolPrivate::createWidgets() action->setDisabled(true); action->setIcon(Core::Icons::PREV.icon()); action->setToolTip(tr("Go back one step in history. This will select the previously selected item.")); - connect(action, &QAction::triggered, m_stackBrowser, &StackBrowser::goBack); + connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goBack); layout->addWidget(createToolButton(action)); m_goBack = action; @@ -695,7 +682,7 @@ QWidget *CallgrindToolPrivate::createWidgets() action->setDisabled(true); action->setIcon(Core::Icons::NEXT.icon()); action->setToolTip(tr("Go forward one step in history.")); - connect(action, &QAction::triggered, m_stackBrowser, &StackBrowser::goNext); + connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goNext); layout->addWidget(createToolButton(action)); m_goNext = action; @@ -705,41 +692,41 @@ QWidget *CallgrindToolPrivate::createWidgets() m_eventCombo = new QComboBox; m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized.")); connect(m_eventCombo, static_cast(&QComboBox::currentIndexChanged), - this, &CallgrindToolPrivate::setCostEvent); + this, &CallgrindTool::setCostEvent); updateEventCombo(); layout->addWidget(m_eventCombo); - // cost formatting + // Cost formatting { - QMenu *menu = new QMenu(layout->parentWidget()); - QActionGroup *group = new QActionGroup(this); + auto menu = new QMenu(layout->parentWidget()); + auto group = new QActionGroup(this); - // show costs as absolute numbers + // Show costs as absolute numbers m_costAbsolute = new QAction(tr("Absolute Costs"), this); m_costAbsolute->setToolTip(tr("Show costs as absolute numbers.")); m_costAbsolute->setCheckable(true); m_costAbsolute->setChecked(true); - connect(m_costAbsolute, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat); + connect(m_costAbsolute, &QAction::toggled, this, &CallgrindTool::updateCostFormat); group->addAction(m_costAbsolute); menu->addAction(m_costAbsolute); - // show costs in percentages + // Show costs in percentages m_costRelative = new QAction(tr("Relative Costs"), this); m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost.")); m_costRelative->setCheckable(true); - connect(m_costRelative, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat); + connect(m_costRelative, &QAction::toggled, this, &CallgrindTool::updateCostFormat); group->addAction(m_costRelative); menu->addAction(m_costRelative); - // show costs relative to parent + // Show costs relative to parent m_costRelativeToParent = new QAction(tr("Relative Costs to Parent"), this); m_costRelativeToParent->setToolTip(tr("Show costs relative to parent functions inclusive cost.")); m_costRelativeToParent->setCheckable(true); - connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat); + connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindTool::updateCostFormat); group->addAction(m_costRelativeToParent); menu->addAction(m_costRelativeToParent); - QToolButton *button = new QToolButton; + auto button = new QToolButton; button->setMenu(menu); button->setPopupMode(QToolButton::InstantPopup); button->setText(QLatin1String("$")); @@ -747,43 +734,42 @@ QWidget *CallgrindToolPrivate::createWidgets() layout->addWidget(button); } - ValgrindGlobalSettings *settings = ValgrindPlugin::globalSettings(); - // cycle detection + // Cycle detection //action = new QAction(QLatin1String("Cycle Detection"), this); ///FIXME: icon action = new QAction(QLatin1String("O"), this); ///FIXME: icon action->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls.")); action->setCheckable(true); - connect(action, &QAction::toggled, m_dataModel, &DataModel::enableCycleDetection); + connect(action, &QAction::toggled, &m_dataModel, &DataModel::enableCycleDetection); connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setDetectCycles); layout->addWidget(createToolButton(action)); m_cycleDetection = action; - // shorter template signature + // Shorter template signature action = new QAction(QLatin1String("<>"), this); action->setToolTip(tr("This removes template parameter lists when displaying function names.")); action->setCheckable(true); - connect(action, &QAction::toggled, m_dataModel, &DataModel::setShortenTemplates); + connect(action, &QAction::toggled, &m_dataModel, &DataModel::setShortenTemplates); connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setShortenTemplates); layout->addWidget(createToolButton(action)); m_shortenTemplates = action; - // filtering + // Filtering action = new QAction(tr("Show Project Costs Only"), this); action->setIcon(Core::Icons::FILTER.icon()); action->setToolTip(tr("Show only profiling info that originated from this project source.")); action->setCheckable(true); - connect(action, &QAction::toggled, this, &CallgrindToolPrivate::handleFilterProjectCosts); + connect(action, &QAction::toggled, this, &CallgrindTool::handleFilterProjectCosts); layout->addWidget(createToolButton(action)); m_filterProjectCosts = action; - // filter + // Filter ///FIXME: find workaround for https://bugreports.qt.io/browse/QTCREATORBUG-3247 - QLineEdit *filter = new QLineEdit; + auto filter = new QLineEdit; filter->setPlaceholderText(tr("Filter...")); connect(filter, &QLineEdit::textChanged, - m_updateTimer, static_cast(&QTimer::start)); + &m_updateTimer, static_cast(&QTimer::start)); layout->addWidget(filter); m_searchFilter = filter; @@ -793,16 +779,29 @@ QWidget *CallgrindToolPrivate::createWidgets() layout->addWidget(new Utils::StyledSeparator); layout->addStretch(); - return widget; + AnalyzerManager::registerDockWidget(CallgrindCallersDockId, m_callersView); + AnalyzerManager::registerDockWidget(CallgrindFlatDockId, m_flatView); + AnalyzerManager::registerDockWidget(CallgrindCalleesDockId, m_calleesView); + AnalyzerManager::registerDockWidget(CallgrindVisualizationDockId, m_visualization); + + AnalyzerManager::registerPerspective(CallgrindPerspectiveId, { + { CallgrindFlatDockId, Id(), Perspective::SplitVertical }, + { CallgrindCalleesDockId, Id(), Perspective::SplitVertical }, + { CallgrindCallersDockId, CallgrindCalleesDockId, Perspective::SplitHorizontal }, + { CallgrindVisualizationDockId, Id(), Perspective::SplitVertical, + false, Qt::RightDockWidgetArea } + }); + + AnalyzerManager::registerToolbar(CallgrindPerspectiveId, widget); } -void CallgrindToolPrivate::clearTextMarks() +void CallgrindTool::clearTextMarks() { qDeleteAll(m_textMarks); m_textMarks.clear(); } -void CallgrindToolPrivate::engineStarting() +void CallgrindTool::engineStarting() { // enable/disable actions m_resetAction->setEnabled(true); @@ -812,14 +811,14 @@ void CallgrindToolPrivate::engineStarting() slotClear(); } -void CallgrindToolPrivate::engineFinished() +void CallgrindTool::engineFinished() { - // enable/disable actions + // Enable/disable actions m_resetAction->setEnabled(false); m_dumpAction->setEnabled(false); m_loadExternalLogFile->setEnabled(true); - const ParseData *data = m_dataModel->parseData(); + const ParseData *data = m_dataModel.parseData(); if (data) showParserResults(data); else @@ -828,7 +827,7 @@ void CallgrindToolPrivate::engineFinished() setBusyCursor(false); } -void CallgrindToolPrivate::showParserResults(const ParseData *data) +void CallgrindTool::showParserResults(const ParseData *data) { QString msg; if (data) { @@ -845,15 +844,15 @@ void CallgrindToolPrivate::showParserResults(const ParseData *data) AnalyzerManager::showPermanentStatusMessage(CallgrindPerspectiveId, msg); } -void CallgrindToolPrivate::editorOpened(IEditor *editor) +void CallgrindTool::editorOpened(IEditor *editor) { if (auto widget = qobject_cast(editor->widget())) { connect(widget, &TextEditorWidget::markContextMenuRequested, - this, &CallgrindToolPrivate::requestContextMenu); + this, &CallgrindTool::requestContextMenu); } } -void CallgrindToolPrivate::requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu) +void CallgrindTool::requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu) { // Find callgrind text mark that corresponds to this editor's file and line number foreach (CallgrindTextMark *textMark, m_textMarks) { @@ -866,7 +865,7 @@ void CallgrindToolPrivate::requestContextMenu(TextEditorWidget *widget, int line } } -void CallgrindToolPrivate::handleShowCostsOfFunction() +void CallgrindTool::handleShowCostsOfFunction() { CPlusPlus::Symbol *symbol = AnalyzerUtils::findSymbolUnderCursor(); if (!symbol) @@ -883,14 +882,14 @@ void CallgrindToolPrivate::handleShowCostsOfFunction() AnalyzerManager::selectAction(CallgrindLocalActionId, /* alsoRunIt = */ true); } -void CallgrindToolPrivate::slotRequestDump() +void CallgrindTool::slotRequestDump() { //setBusy(true); - m_visualisation->setText(tr("Populating...")); + m_visualization->setText(tr("Populating...")); dumpRequested(); } -void CallgrindToolPrivate::loadExternalLogFile() +void CallgrindTool::loadExternalLogFile() { const QString filePath = QFileDialog::getOpenFileName( ICore::mainWindow(), @@ -915,12 +914,12 @@ void CallgrindToolPrivate::loadExternalLogFile() takeParserData(parser.takeData()); } -void CallgrindToolPrivate::takeParserDataFromRunControl(CallgrindRunControl *rc) +void CallgrindTool::takeParserDataFromRunControl(CallgrindRunControl *rc) { takeParserData(rc->takeParserData()); } -void CallgrindToolPrivate::takeParserData(ParseData *data) +void CallgrindTool::takeParserData(ParseData *data) { showParserResults(data); @@ -935,14 +934,11 @@ void CallgrindToolPrivate::takeParserData(ParseData *data) createTextMarks(); } -void CallgrindToolPrivate::createTextMarks() +void CallgrindTool::createTextMarks() { - DataModel *model = m_dataModel; - QTC_ASSERT(model, return); - QList locations; - for (int row = 0; row < model->rowCount(); ++row) { - const QModelIndex index = model->index(row, DataModel::InclusiveCostColumn); + for (int row = 0; row < m_dataModel.rowCount(); ++row) { + const QModelIndex index = m_dataModel.index(row, DataModel::InclusiveCostColumn); QString fileName = index.data(DataModel::FileNameRole).toString(); if (fileName.isEmpty() || fileName == QLatin1String("???")) @@ -969,6 +965,19 @@ void CallgrindToolPrivate::createTextMarks() } } +static CallgrindTool *theCallgrindTool; + +void initCallgrindTool(QObject *parent) +{ + theCallgrindTool = new CallgrindTool(parent); +} + +void destroyCallgrindTool() +{ + delete theCallgrindTool; + theCallgrindTool = 0; +} + } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/callgrindtool.h b/src/plugins/valgrind/callgrindtool.h index 271b92fe4b7..e7df17db865 100644 --- a/src/plugins/valgrind/callgrindtool.h +++ b/src/plugins/valgrind/callgrindtool.h @@ -28,8 +28,6 @@ #include -namespace ProjectExplorer { class RunConfiguration; } - namespace Valgrind { namespace Internal { @@ -41,27 +39,10 @@ const char CallgrindCalleesDockId[] = "Callgrind.Callees.Dock"; const char CallgrindFlatDockId[] = "Callgrind.Flat.Dock"; const char CallgrindVisualizationDockId[] = "Callgrind.Visualization.Dock"; -class ValgrindRunControl; const char CALLGRIND_RUN_MODE[] = "CallgrindTool.CallgrindRunMode"; -class CallgrindToolPrivate; - -class CallgrindTool : public QObject -{ - Q_OBJECT - -public: - CallgrindTool(QObject *parent); - ~CallgrindTool(); - - ValgrindRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration); - QWidget *createWidgets(); - - void handleShowCostsOfFunction(); - -private: - CallgrindToolPrivate *d; -}; +void initCallgrindTool(QObject *parent); +void destroyCallgrindTool(); } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 758c02225e9..7ac4de1ffa2 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -30,9 +30,11 @@ #include "valgrindsettings.h" #include "valgrindplugin.h" -#include -#include #include +#include +#include +#include +#include #include #include @@ -62,26 +64,26 @@ #include #include -#include #include +#include +#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include - -#include #include -#include #include -#include -#include +#include #include +#include +#include +#include #include -#include -#include using namespace Analyzer; using namespace ProjectExplorer; @@ -90,7 +92,23 @@ using namespace Valgrind::XmlProtocol; namespace Valgrind { namespace Internal { -// ---------------------------- MemcheckErrorFilterProxyModel +class FrameFinder; + +class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel +{ +public: + MemcheckErrorFilterProxyModel(QObject *parent = 0); + +public: + void setAcceptedKinds(const QList &acceptedKinds); + void setFilterExternalIssues(bool filter); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + +private: + QList m_acceptedKinds; + bool m_filterExternalIssues; +}; + MemcheckErrorFilterProxyModel::MemcheckErrorFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_filterExternalIssues(false) @@ -178,6 +196,56 @@ static void initKindFilterAction(QAction *action, const QVariantList &kinds) action->setData(kinds); } +class MemcheckTool : public QObject +{ + Q_DECLARE_TR_FUNCTIONS(Valgrind::Internal::MemcheckTool) + +public: + MemcheckTool(QObject *parent); + + QWidget *createWidgets(); + + MemcheckRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration, + Core::Id runMode); + +private: + void settingsDestroyed(QObject *settings); + void maybeActiveRunConfigurationChanged(); + + void engineStarting(const MemcheckRunControl *engine); + void engineFinished(); + void loadingExternalXmlLogFileFinished(); + + void parserError(const Valgrind::XmlProtocol::Error &error); + void internalParserError(const QString &errorString); + void updateErrorFilter(); + + void loadExternalXmlLogFile(); + + void setBusyCursor(bool busy); + + void clearErrorView(); + void updateFromSettings(); + int updateUiAfterFinishedHelper(); + +private: + ValgrindBaseSettings *m_settings; + QMenu *m_filterMenu; + + FrameFinder *m_frameFinder; + Valgrind::XmlProtocol::ErrorListModel *m_errorModel; + MemcheckErrorFilterProxyModel *m_errorProxyModel; + MemcheckErrorView *m_errorView; + + QList m_errorFilterActions; + QAction *m_filterProjectAction; + QList m_suppressionActions; + QAction *m_suppressionSeparator; + QAction *m_loadExternalLogFile; + QAction *m_goBack; + QAction *m_goNext; +}; + MemcheckTool::MemcheckTool(QObject *parent) : QObject(parent) { @@ -216,6 +284,55 @@ MemcheckTool::MemcheckTool(QObject *parent) a = new QAction(tr("Invalid Calls to \"free()\""), this); initKindFilterAction(a, { InvalidFree, MismatchedFree }); m_errorFilterActions.append(a); + + + using namespace std::placeholders; + + AnalyzerManager::registerToolbar(MemcheckPerspectiveId, createWidgets()); + + ActionDescription desc; + desc.setToolTip(tr("Valgrind Analyze Memory uses the " + "Memcheck tool to find memory leaks.")); + + if (!Utils::HostOsInfo::isWindowsHost()) { + desc.setText(tr("Valgrind Memory Analyzer")); + desc.setPerspectiveId(MemcheckPerspectiveId); + desc.setRunControlCreator(std::bind(&MemcheckTool::createRunControl, this, _1, _2)); + desc.setToolMode(DebugMode); + desc.setRunMode(MEMCHECK_RUN_MODE); + desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); + AnalyzerManager::registerAction("Memcheck.Local", desc); + + desc.setText(tr("Valgrind Memory Analyzer with GDB")); + desc.setToolTip(tr("Valgrind Analyze Memory with GDB uses the " + "Memcheck tool to find memory leaks.\nWhen a problem is detected, " + "the application is interrupted and can be debugged.")); + desc.setPerspectiveId(MemcheckPerspectiveId); + desc.setRunControlCreator(std::bind(&MemcheckTool::createRunControl, this, _1, _2)); + desc.setToolMode(DebugMode); + desc.setRunMode(MEMCHECK_WITH_GDB_RUN_MODE); + desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); + AnalyzerManager::registerAction("MemcheckWithGdb.Local", desc); + } + + desc.setText(tr("Valgrind Memory Analyzer (External Remote Application)")); + desc.setPerspectiveId(MemcheckPerspectiveId); + desc.setCustomToolStarter([this](ProjectExplorer::RunConfiguration *runConfig) { + StartRemoteDialog dlg; + if (dlg.exec() != QDialog::Accepted) + return; + ValgrindRunControl *rc = createRunControl(runConfig, MEMCHECK_RUN_MODE); + QTC_ASSERT(rc, return); + const auto runnable = dlg.runnable(); + rc->setRunnable(runnable); + AnalyzerConnection connection; + connection.connParams = dlg.sshParams(); + rc->setConnection(connection); + rc->setDisplayName(runnable.executable); + ProjectExplorerPlugin::startRunControl(rc, MEMCHECK_RUN_MODE); + }); + desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS); + AnalyzerManager::registerAction("Memcheck.Remote", desc); } void MemcheckTool::settingsDestroyed(QObject *settings) @@ -576,5 +693,18 @@ void MemcheckTool::setBusyCursor(bool busy) m_errorView->setCursor(cursor); } +static MemcheckTool *theMemcheckTool; + +void initMemcheckTool(QObject *parent) +{ + theMemcheckTool = new MemcheckTool(parent); +} + +void destroyMemcheckTool() +{ + delete theMemcheckTool; + theMemcheckTool = 0; +} + } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/memchecktool.h b/src/plugins/valgrind/memchecktool.h index 230dd74e8b2..1ea57b97780 100644 --- a/src/plugins/valgrind/memchecktool.h +++ b/src/plugins/valgrind/memchecktool.h @@ -27,24 +27,7 @@ #ifndef MEMCHECKTOOL_H #define MEMCHECKTOOL_H -#include - -#include - -QT_BEGIN_NAMESPACE -class QModelIndex; -class QAction; -class QMenu; -QT_END_NAMESPACE - -namespace Valgrind { -namespace XmlProtocol { -class ErrorListModel; -class Error; -} -} - -namespace ProjectExplorer { class RunConfiguration; } +#include namespace Valgrind { @@ -56,80 +39,8 @@ const char MemcheckErrorDockId[] = "Memcheck.Dock.Error"; namespace Internal { -class FrameFinder; -class MemcheckErrorView; -class MemcheckRunControl; -class ValgrindBaseSettings; - - -class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - MemcheckErrorFilterProxyModel(QObject *parent = 0); - -public slots: - void setAcceptedKinds(const QList &acceptedKinds); - void setFilterExternalIssues(bool filter); - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - -private: - QList m_acceptedKinds; - bool m_filterExternalIssues; -}; - -class MemcheckTool : public QObject -{ - Q_OBJECT - -public: - MemcheckTool(QObject *parent); - - QWidget *createWidgets(); - - MemcheckRunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id runMode); - -private: - void settingsDestroyed(QObject *settings); - void maybeActiveRunConfigurationChanged(); - - void engineStarting(const MemcheckRunControl *engine); - void engineFinished(); - void loadingExternalXmlLogFileFinished(); - - void parserError(const Valgrind::XmlProtocol::Error &error); - void internalParserError(const QString &errorString); - void updateErrorFilter(); - - void loadExternalXmlLogFile(); - - void setBusyCursor(bool busy); - - void clearErrorView(); - void updateFromSettings(); - int updateUiAfterFinishedHelper(); - -private: - ValgrindBaseSettings *m_settings; - QMenu *m_filterMenu; - - FrameFinder *m_frameFinder; - Valgrind::XmlProtocol::ErrorListModel *m_errorModel; - MemcheckErrorFilterProxyModel *m_errorProxyModel; - MemcheckErrorView *m_errorView; - - QList m_errorFilterActions; - QAction *m_filterProjectAction; - QList m_suppressionActions; - QAction *m_suppressionSeparator; - QAction *m_loadExternalLogFile; - QAction *m_goBack; - QAction *m_goNext; -}; +void initMemcheckTool(QObject *parent); +void destroyMemcheckTool(); } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindplugin.cpp b/src/plugins/valgrind/valgrindplugin.cpp index c31d7bf1b07..cec95ee127f 100644 --- a/src/plugins/valgrind/valgrindplugin.cpp +++ b/src/plugins/valgrind/valgrindplugin.cpp @@ -28,37 +28,20 @@ #include "callgrindtool.h" #include "memchecktool.h" -#include "memcheckengine.h" #include "valgrindruncontrolfactory.h" #include "valgrindsettings.h" #include "valgrindconfigwidget.h" -#include -#include -#include -#include -#include - #include -#include -#include -#include -#include #include #include -#include - #include -#include - #include -#include #include #include -using namespace Analyzer; using namespace Core; using namespace ProjectExplorer; @@ -108,132 +91,31 @@ ValgrindPlugin::~ValgrindPlugin() bool ValgrindPlugin::initialize(const QStringList &, QString *) { - theGlobalSettings = new ValgrindGlobalSettings(); + theGlobalSettings = new ValgrindGlobalSettings; theGlobalSettings->readSettings(); - addAutoReleasedObject(new ValgrindOptionsPage()); - addAutoReleasedObject(new ValgrindRunControlFactory()); + addAutoReleasedObject(new ValgrindOptionsPage); + addAutoReleasedObject(new ValgrindRunControlFactory); return true; } void ValgrindPlugin::extensionsInitialized() { - using namespace std::placeholders; + initMemcheckTool(this); + initCallgrindTool(this); +} - QString callgrindToolTip = tr("Valgrind Function Profile uses the " - "Callgrind tool to record function calls when a program runs."); - - QString memcheckToolTip = tr("Valgrind Analyze Memory uses the " - "Memcheck tool to find memory leaks."); - - auto mcTool = new MemcheckTool(this); - auto cgTool = new CallgrindTool(this); - auto cgRunControlCreator = [cgTool](RunConfiguration *runConfiguration, Id) { - return cgTool->createRunControl(runConfiguration); - }; - - AnalyzerManager::registerToolbar(MemcheckPerspectiveId, mcTool->createWidgets()); - AnalyzerManager::registerToolbar(CallgrindPerspectiveId, cgTool->createWidgets()); - - ActionDescription desc; - - if (!Utils::HostOsInfo::isWindowsHost()) { - desc.setText(tr("Valgrind Memory Analyzer")); - desc.setToolTip(memcheckToolTip); - desc.setPerspectiveId(MemcheckPerspectiveId); - desc.setRunControlCreator([mcTool](RunConfiguration *runConfig, Id runMode) { - return mcTool->createRunControl(runConfig, runMode); - }); - desc.setToolMode(DebugMode); - desc.setRunMode(MEMCHECK_RUN_MODE); - desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); - AnalyzerManager::registerAction("Memcheck.Local", desc); - - desc.setText(tr("Valgrind Memory Analyzer with GDB")); - desc.setToolTip(tr("Valgrind Analyze Memory with GDB uses the " - "Memcheck tool to find memory leaks.\nWhen a problem is detected, " - "the application is interrupted and can be debugged.")); - desc.setPerspectiveId(MemcheckPerspectiveId); - desc.setRunControlCreator([mcTool](RunConfiguration *runConfig, Id runMode) { - return mcTool->createRunControl(runConfig, runMode); - }); - desc.setToolMode(DebugMode); - desc.setRunMode(MEMCHECK_WITH_GDB_RUN_MODE); - desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); - AnalyzerManager::registerAction("MemcheckWithGdb.Local", desc); - - desc.setText(tr("Valgrind Function Profiler")); - desc.setToolTip(callgrindToolTip); - desc.setPerspectiveId(CallgrindPerspectiveId); - desc.setRunControlCreator(cgRunControlCreator); - desc.setToolMode(OptimizedMode); - desc.setRunMode(CALLGRIND_RUN_MODE); - desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_TOOLS); - AnalyzerManager::registerAction(CallgrindLocalActionId, desc); - } - - desc.setText(tr("Valgrind Memory Analyzer (External Remote Application)")); - desc.setToolTip(memcheckToolTip); - desc.setPerspectiveId(MemcheckPerspectiveId); - desc.setCustomToolStarter([mcTool](ProjectExplorer::RunConfiguration *runConfig) { - StartRemoteDialog dlg; - if (dlg.exec() != QDialog::Accepted) - return; - ValgrindRunControl *rc = mcTool->createRunControl(runConfig, MEMCHECK_RUN_MODE); - QTC_ASSERT(rc, return); - const auto runnable = dlg.runnable(); - rc->setRunnable(runnable); - AnalyzerConnection connection; - connection.connParams = dlg.sshParams(); - rc->setConnection(connection); - rc->setDisplayName(runnable.executable); - ProjectExplorerPlugin::startRunControl(rc, MEMCHECK_RUN_MODE); - }); - desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS); - AnalyzerManager::registerAction("Memcheck.Remote", desc); - - desc.setText(tr("Valgrind Function Profiler (External Remote Application)")); - desc.setToolTip(callgrindToolTip); - desc.setPerspectiveId(CallgrindPerspectiveId); - desc.setCustomToolStarter([cgTool](ProjectExplorer::RunConfiguration *runConfig) { - StartRemoteDialog dlg; - if (dlg.exec() != QDialog::Accepted) - return; - ValgrindRunControl *rc = cgTool->createRunControl(runConfig); - QTC_ASSERT(rc, return); - const auto runnable = dlg.runnable(); - rc->setRunnable(runnable); - AnalyzerConnection connection; - connection.connParams = dlg.sshParams(); - rc->setConnection(connection); - rc->setDisplayName(runnable.executable); - ProjectExplorerPlugin::startRunControl(rc, CALLGRIND_RUN_MODE); - }); - desc.setMenuGroup(Analyzer::Constants::G_ANALYZER_REMOTE_TOOLS); - AnalyzerManager::registerAction(CallgrindRemoteActionId, desc); - - // If there is a CppEditor context menu add our own context menu actions. - if (ActionContainer *editorContextMenu = - ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT)) { - Context analyzerContext = Context(Analyzer::Constants::C_ANALYZEMODE); - editorContextMenu->addSeparator(analyzerContext); - - QAction *action = new QAction(tr("Profile Costs of This Function and Its Callees"), this); - action->setIcon(Analyzer::Icons::ANALYZER_CONTROL_START.icon()); - connect(action, &QAction::triggered, cgTool, - &CallgrindTool::handleShowCostsOfFunction); - Command *cmd = ActionManager::registerAction(action, "Analyzer.Callgrind.ShowCostsOfFunction", - analyzerContext); - editorContextMenu->addAction(cmd); - cmd->setAttribute(Command::CA_Hide); - cmd->setAttribute(Command::CA_NonConfigurable); - } +ExtensionSystem::IPlugin::ShutdownFlag ValgrindPlugin::aboutToShutdown() +{ + destroyCallgrindTool(); + destroyMemcheckTool(); + return SynchronousShutdown; } ValgrindGlobalSettings *ValgrindPlugin::globalSettings() { - return theGlobalSettings; + return theGlobalSettings; } } // namespace Internal diff --git a/src/plugins/valgrind/valgrindplugin.h b/src/plugins/valgrind/valgrindplugin.h index dd72f555615..f402e4c2ba0 100644 --- a/src/plugins/valgrind/valgrindplugin.h +++ b/src/plugins/valgrind/valgrindplugin.h @@ -44,8 +44,9 @@ public: ValgrindPlugin() {} ~ValgrindPlugin(); - bool initialize(const QStringList &arguments, QString *errorString); - void extensionsInitialized(); + bool initialize(const QStringList &arguments, QString *errorString) override; + void extensionsInitialized() override; + ShutdownFlag aboutToShutdown() override; static ValgrindGlobalSettings *globalSettings(); };