From a8d7e15a5dd88f2c7f34e03ca8594d584ac15bc0 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar <nikolai.kosjar@digia.com> Date: Mon, 9 Sep 2013 14:34:19 +0200 Subject: [PATCH] Valgrind: Add action to load external log file ...for the memcheck and callgrind tool. Task-number: QTCREATORBUG-10057 Change-Id: I23dd3ad47f0498af37787bf54e76b09852cb327c Reviewed-by: hjk <hjk121@nokiamail.com> --- src/plugins/valgrind/callgrindtool.cpp | 49 ++++++++++- src/plugins/valgrind/callgrindtool.h | 1 + src/plugins/valgrind/memchecktool.cpp | 115 +++++++++++++++++++------ src/plugins/valgrind/memchecktool.h | 8 +- 4 files changed, 147 insertions(+), 26 deletions(-) diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index a55688c7a42..904b7f196fb 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -41,6 +41,7 @@ #include <valgrind/callgrind/callgrindfunction.h> #include <valgrind/callgrind/callgrindfunctioncall.h> #include <valgrind/callgrind/callgrindparsedata.h> +#include <valgrind/callgrind/callgrindparser.h> #include <valgrind/callgrind/callgrindproxymodel.h> #include <valgrind/callgrind/callgrindstackbrowser.h> #include <valgrind/valgrindplugin.h> @@ -74,10 +75,12 @@ #include <QCheckBox> #include <QComboBox> #include <QDockWidget> +#include <QFileDialog> #include <QGraphicsItem> #include <QHBoxLayout> #include <QLineEdit> #include <QMenu> +#include <QMessageBox> #include <QSortFilterProxyModel> #include <QToolBar> #include <QToolButton> @@ -124,6 +127,7 @@ signals: public slots: void slotClear(); void slotRequestDump(); + void loadExternalXmlLogFile(); void selectFunction(const Valgrind::Callgrind::Function *); void setCostFormat(Valgrind::Internal::CostDelegate::CostFormat format); @@ -158,6 +162,7 @@ public slots: void showParserResults(const Valgrind::Callgrind::ParseData *data); void takeParserData(CallgrindRunControl *rc); + void takeParserData(ParseData *data); void engineStarting(const Analyzer::AnalyzerRunControl *); void engineFinished(); @@ -198,6 +203,7 @@ public: QVector<CallgrindTextMark *> m_textMarks; + QAction *m_loadExternalLogFile; QAction *m_dumpAction; QAction *m_resetAction; QAction *m_pauseAction; @@ -562,6 +568,11 @@ void CallgrindTool::startTool(StartMode mode) d->setBusyCursor(true); } +void CallgrindTool::loadExternalXmlLogFile() +{ + d->loadExternalXmlLogFile(); +} + void CallgrindTool::handleShowCostsOfFunction() { d->handleShowCostsOfFunction(); @@ -654,6 +665,14 @@ QWidget *CallgrindToolPrivate::createWidgets() layout->setSpacing(0); widget->setLayout(layout); + // load external XML log file + action = new QAction(this); + action->setIcon(QIcon(QLatin1String(Core::Constants::ICON_OPENFILE))); + action->setToolTip(tr("Load External XML Log File.")); + connect(action, SIGNAL(triggered(bool)), this, SLOT(loadExternalXmlLogFile())); + layout->addWidget(createToolButton(action)); + m_loadExternalLogFile = action; + // dump action action = new QAction(this); action->setDisabled(true); @@ -810,6 +829,7 @@ void CallgrindToolPrivate::engineStarting(const Analyzer::AnalyzerRunControl *) // enable/disable actions m_resetAction->setEnabled(true); m_dumpAction->setEnabled(true); + m_loadExternalLogFile->setEnabled(false); clearTextMarks(); slotClear(); } @@ -819,6 +839,7 @@ void CallgrindToolPrivate::engineFinished() // enable/disable actions m_resetAction->setEnabled(false); m_dumpAction->setEnabled(false); + m_loadExternalLogFile->setEnabled(true); const ParseData *data = m_dataModel->parseData(); if (data) @@ -913,9 +934,35 @@ void CallgrindToolPrivate::slotRequestDump() dumpRequested(); } +void CallgrindToolPrivate::loadExternalXmlLogFile() +{ + const QString filePath = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), + tr("Open Callgrind XML Log File")); + if (filePath.isEmpty()) + return; + + QFile logFile(filePath); + if (!logFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(AnalyzerManager::mainWindow(), tr("Internal Error"), + tr("Failed to open file for reading: %1").arg(filePath)); + return; + } + + AnalyzerManager::showStatusMessage(tr("Parsing Profile Data...")); + QCoreApplication::processEvents(); + + Parser parser; + parser.parse(&logFile); + takeParserData(parser.takeData()); +} + void CallgrindToolPrivate::takeParserData(CallgrindRunControl *rc) { - ParseData *data = rc->takeParserData(); + takeParserData(rc->takeParserData()); +} + +void CallgrindToolPrivate::takeParserData(ParseData *data) +{ showParserResults(data); if (!data) diff --git a/src/plugins/valgrind/callgrindtool.h b/src/plugins/valgrind/callgrindtool.h index a3d0b1424c4..68a6c54e86d 100644 --- a/src/plugins/valgrind/callgrindtool.h +++ b/src/plugins/valgrind/callgrindtool.h @@ -53,6 +53,7 @@ public: QWidget *createWidgets(); void startTool(Analyzer::StartMode mode); + void loadExternalXmlLogFile(); public slots: void handleShowCostsOfFunction(); diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 622b44bfea8..89921aa9d80 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -69,6 +69,7 @@ #include <QString> #include <QLatin1String> +#include <QFileDialog> #include <QFileInfo> #include <QFile> #include <QDir> @@ -223,6 +224,31 @@ void MemcheckTool::settingsDestroyed(QObject *settings) m_settings = ValgrindPlugin::globalSettings(); } +void MemcheckTool::updateFromSettings() +{ + foreach (QAction *action, m_errorFilterActions) { + bool contained = true; + foreach (const QVariant &v, action->data().toList()) { + bool ok; + int kind = v.toInt(&ok); + if (ok && !m_settings->visibleErrorKinds().contains(kind)) + contained = false; + } + action->setChecked(contained); + } + + m_filterProjectAction->setChecked(!m_settings->filterExternalIssues()); + m_errorView->settingsChanged(m_settings); + + connect(m_settings, SIGNAL(visibleErrorKindsChanged(QList<int>)), + m_errorProxyModel, SLOT(setAcceptedKinds(QList<int>))); + m_errorProxyModel->setAcceptedKinds(m_settings->visibleErrorKinds()); + + connect(m_settings, SIGNAL(filterExternalIssuesChanged(bool)), + m_errorProxyModel, SLOT(setFilterExternalIssues(bool))); + m_errorProxyModel->setFilterExternalIssues(m_settings->filterExternalIssues()); +} + void MemcheckTool::maybeActiveRunConfigurationChanged() { ValgrindBaseSettings *settings = 0; @@ -249,27 +275,7 @@ void MemcheckTool::maybeActiveRunConfigurationChanged() QTC_ASSERT(m_settings, return); connect(m_settings, SIGNAL(destroyed(QObject*)), SLOT(settingsDestroyed(QObject*))); - foreach (QAction *action, m_errorFilterActions) { - bool contained = true; - foreach (const QVariant &v, action->data().toList()) { - bool ok; - int kind = v.toInt(&ok); - if (ok && !m_settings->visibleErrorKinds().contains(kind)) - contained = false; - } - action->setChecked(contained); - } - - m_filterProjectAction->setChecked(!m_settings->filterExternalIssues()); - m_errorView->settingsChanged(m_settings); - - connect(m_settings, SIGNAL(visibleErrorKindsChanged(QList<int>)), - m_errorProxyModel, SLOT(setAcceptedKinds(QList<int>))); - m_errorProxyModel->setAcceptedKinds(m_settings->visibleErrorKinds()); - - connect(m_settings, SIGNAL(filterExternalIssuesChanged(bool)), - m_errorProxyModel, SLOT(setFilterExternalIssues(bool))); - m_errorProxyModel->setFilterExternalIssues(m_settings->filterExternalIssues()); + updateFromSettings(); } RunMode MemcheckTool::runMode() const @@ -371,6 +377,16 @@ QWidget *MemcheckTool::createWidgets() layout->setMargin(0); layout->setSpacing(0); + // Load external XML log file + action = new QAction(this); + action->setIcon(QIcon(QLatin1String(Core::Constants::ICON_OPENFILE))); + action->setToolTip(tr("Load External XML Log File.")); + connect(action, SIGNAL(triggered(bool)), this, SLOT(loadExternalXmlLogFile())); + button = new QToolButton; + button->setDefaultAction(action); + layout->addWidget(button); + m_loadExternalLogFile = action; + // Go to previous leak. action = new QAction(this); action->setDisabled(true); @@ -429,7 +445,7 @@ AnalyzerRunControl *MemcheckTool::createRunControl(const AnalyzerStartParameters this, SLOT(parserError(Valgrind::XmlProtocol::Error))); connect(engine, SIGNAL(internalParserError(QString)), this, SLOT(internalParserError(QString))); - connect(engine, SIGNAL(finished()), this, SLOT(finished())); + connect(engine, SIGNAL(finished()), this, SLOT(engineFinished())); return engine; } @@ -437,6 +453,7 @@ void MemcheckTool::engineStarting(const AnalyzerRunControl *engine) { setBusyCursor(true); clearErrorView(); + m_loadExternalLogFile->setDisabled(true); QString dir; if (RunConfiguration *rc = engine->runConfiguration()) @@ -468,6 +485,42 @@ void MemcheckTool::suppressionActionTriggered() Core::EditorManager::openEditorAt(file, 0); } +void MemcheckTool::loadExternalXmlLogFile() +{ + const QString filePath = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), + tr("Open Memcheck XML Log File")); + if (filePath.isEmpty()) + return; + + QFile *logFile = new QFile(filePath); + if (!logFile->open(QIODevice::ReadOnly | QIODevice::Text)) { + delete logFile; + QMessageBox::critical(m_errorView, tr("Internal Error"), + tr("Failed to open file for reading: %1").arg(filePath)); + return; + } + + setBusyCursor(true); + clearErrorView(); + m_loadExternalLogFile->setDisabled(true); + + if (!m_settings || m_settings != ValgrindPlugin::globalSettings()) { + m_settings = ValgrindPlugin::globalSettings(); + m_errorView->settingsChanged(m_settings); + updateFromSettings(); + } + + ThreadedParser *parser = new ThreadedParser; + connect(parser, SIGNAL(error(Valgrind::XmlProtocol::Error)), + this, SLOT(parserError(Valgrind::XmlProtocol::Error))); + connect(parser, SIGNAL(internalError(QString)), + this, SLOT(internalParserError(QString))); + connect(parser, SIGNAL(finished()), this, SLOT(loadingExternalXmlLogFileFinished())); + connect(parser, SIGNAL(finished()), parser, SLOT(deleteLater())); + + parser->parse(logFile); // ThreadedParser owns the file +} + void MemcheckTool::parserError(const Valgrind::XmlProtocol::Error &error) { m_errorModel->addError(error); @@ -510,16 +563,30 @@ void MemcheckTool::updateErrorFilter() m_settings->setVisibleErrorKinds(errorKinds); } -void MemcheckTool::finished() +int MemcheckTool::updateUiAfterFinishedHelper() { const int issuesFound = m_errorModel->rowCount(); m_goBack->setEnabled(issuesFound > 1); m_goNext->setEnabled(issuesFound > 1); + m_loadExternalLogFile->setEnabled(true); + setBusyCursor(false); + return issuesFound; +} + +void MemcheckTool::engineFinished() +{ + const int issuesFound = updateUiAfterFinishedHelper(); AnalyzerManager::showStatusMessage(issuesFound > 0 ? AnalyzerManager::tr("Memory Analyzer Tool finished, %n issues were found.", 0, issuesFound) : AnalyzerManager::tr("Memory Analyzer Tool finished, no issues were found.")); +} - setBusyCursor(false); +void MemcheckTool::loadingExternalXmlLogFileFinished() +{ + const int issuesFound = updateUiAfterFinishedHelper(); + AnalyzerManager::showStatusMessage(issuesFound > 0 + ? AnalyzerManager::tr("Log file processed, %n issues were found.", 0, issuesFound) + : AnalyzerManager::tr("Log file processed, no issues were found.")); } void MemcheckTool::setBusyCursor(bool busy) diff --git a/src/plugins/valgrind/memchecktool.h b/src/plugins/valgrind/memchecktool.h index e12120077a5..93d913477af 100644 --- a/src/plugins/valgrind/memchecktool.h +++ b/src/plugins/valgrind/memchecktool.h @@ -88,13 +88,16 @@ private slots: void maybeActiveRunConfigurationChanged(); void engineStarting(const Analyzer::AnalyzerRunControl *engine); - void finished(); + void engineFinished(); + void loadingExternalXmlLogFileFinished(); void parserError(const Valgrind::XmlProtocol::Error &error); void internalParserError(const QString &errorString); void updateErrorFilter(); void suppressionActionTriggered(); + void loadExternalXmlLogFile(); + private: ToolMode toolMode() const; QWidget *createWidgets(); @@ -104,6 +107,8 @@ private: ProjectExplorer::RunConfiguration *runConfiguration = 0); void clearErrorView(); + void updateFromSettings(); + int updateUiAfterFinishedHelper(); private: ValgrindBaseSettings *m_settings; @@ -118,6 +123,7 @@ private: QAction *m_filterProjectAction; QList<QAction *> m_suppressionActions; QAction *m_suppressionSeparator; + QAction *m_loadExternalLogFile; QAction *m_goBack; QAction *m_goNext; }; -- GitLab