diff options
-rw-r--r-- | src/plugins/valgrind/memcheckerrorview.cpp | 30 | ||||
-rw-r--r-- | src/plugins/valgrind/memcheckerrorview.h | 16 | ||||
-rw-r--r-- | src/plugins/valgrind/memchecktool.cpp | 219 | ||||
-rw-r--r-- | src/plugins/valgrind/memchecktool.h | 36 |
4 files changed, 171 insertions, 130 deletions
diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp index e89595a4fd..69957dd6be 100644 --- a/src/plugins/valgrind/memcheckerrorview.cpp +++ b/src/plugins/valgrind/memcheckerrorview.cpp @@ -507,5 +507,35 @@ void MemcheckErrorView::suppressError() } } +void MemcheckErrorView::goNext() +{ + setCurrentRow((currentRow() + 1) % rowCount()); +} + +void MemcheckErrorView::goBack() +{ + const int prevRow = currentRow() - 1; + setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1); +} + +int MemcheckErrorView::rowCount() const +{ + return model() ? model()->rowCount() : 0; +} + +int MemcheckErrorView::currentRow() const +{ + const QModelIndex index = selectionModel()->currentIndex(); + return index.row(); +} + +void MemcheckErrorView::setCurrentRow(int row) +{ + const QModelIndex index = model()->index(row, 0); + selectionModel()->setCurrentIndex(index, + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + scrollTo(index); +} + } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/memcheckerrorview.h b/src/plugins/valgrind/memcheckerrorview.h index d36453684a..f64bc5bd06 100644 --- a/src/plugins/valgrind/memcheckerrorview.h +++ b/src/plugins/valgrind/memcheckerrorview.h @@ -99,20 +99,24 @@ public: QString defaultSuppressionFile() const; Analyzer::AnalyzerSettings *settings() const { return m_settings; } -signals: - void resized(); - public slots: void settingsChanged(Analyzer::AnalyzerSettings *settings); + void goNext(); + void goBack(); -private slots: - void suppressError(); +signals: + void resized(); -protected: +private slots: void resizeEvent(QResizeEvent *e); void contextMenuEvent(QContextMenuEvent *e); + void suppressError(); + void setCurrentRow(int row); private: + int rowCount() const; + int currentRow() const; + QAction *m_copyAction; QAction *m_suppressAction; QString m_defaultSuppFile; diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 5388662e89..b391ca1697 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -40,7 +40,6 @@ #include <analyzerbase/analyzermanager.h> #include <analyzerbase/analyzerconstants.h> -#include <analyzerbase/ianalyzeroutputpaneadapter.h> #include <valgrind/xmlprotocol/errorlistmodel.h> #include <valgrind/xmlprotocol/stackmodel.h> @@ -96,23 +95,6 @@ using namespace Valgrind::XmlProtocol; namespace Valgrind { namespace Internal { -// Adapter for output pane. -class MemCheckOutputPaneAdapter : public Analyzer::ListItemViewOutputPaneAdapter -{ -public: - explicit MemCheckOutputPaneAdapter(MemcheckTool *mct) : - ListItemViewOutputPaneAdapter(mct), m_tool(mct) {} - - virtual QWidget *toolBarWidget() { return m_tool->createPaneToolBarWidget(); } - virtual void clearContents() { m_tool->clearErrorView(); } - -protected: - virtual QAbstractItemView *createItemView() { return m_tool->ensurePaneErrorView(); } - -private: - MemcheckTool *m_tool; -}; - // ---------------------------- MemcheckErrorFilterProxyModel MemcheckErrorFilterProxyModel::MemcheckErrorFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), @@ -202,43 +184,41 @@ static void initKindFilterAction(QAction *action, const QList<int> &kinds) action->setData(data); } -MemcheckTool::MemcheckTool(QObject *parent) : - Analyzer::IAnalyzerTool(parent), - m_settings(0), - m_errorModel(0), - m_errorProxyModel(0), - m_errorView(0), - m_filterProjectAction(new QAction(tr("External Errors"), this)), - m_suppressionSeparator(new QAction(tr("Suppressions"), this)), - m_outputPaneAdapter(0) +MemcheckTool::MemcheckTool(QObject *parent) + : Analyzer::IAnalyzerTool(parent) { + m_settings = 0; + m_errorModel = 0; + m_errorProxyModel = 0; + m_errorView = 0; + m_filterMenu = 0; setObjectName(QLatin1String("MemcheckTool")); - connect(ProjectExplorer::ProjectExplorerPlugin::instance(), - SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged())); + + m_filterProjectAction = new QAction(tr("External Errors"), this); + m_filterProjectAction->setToolTip(tr("Show issues originating outside currently opened projects.")); + m_filterProjectAction->setCheckable(true); + + m_suppressionSeparator = new QAction(tr("Suppressions"), this); + m_suppressionSeparator->setSeparator(true); + m_suppressionSeparator->setToolTip(tr("These suppression files were used in the last memory analyzer run.")); QAction *a = new QAction(tr("Definite Memory Leaks"), this); initKindFilterAction(a, QList<int>() << Leak_DefinitelyLost << Leak_IndirectlyLost); - m_errorFilterActions << a; + m_errorFilterActions.append(a); a = new QAction(tr("Possible Memory Leaks"), this); initKindFilterAction(a, QList<int>() << Leak_PossiblyLost << Leak_StillReachable); - m_errorFilterActions << a; + m_errorFilterActions.append(a); a = new QAction(tr("Use of Uninitialized Memory"), this); initKindFilterAction(a, QList<int>() << InvalidRead << InvalidWrite << InvalidJump << Overlap << InvalidMemPool << UninitCondition << UninitValue << SyscallParam << ClientCheck); - m_errorFilterActions << a; + m_errorFilterActions.append(a); - a = new QAction(tr("Invalid Frees"), this); + a = new QAction(tr("Invalid Calls to \"free()\""), this); initKindFilterAction(a, QList<int>() << InvalidFree << MismatchedFree); - m_errorFilterActions << a; - - m_filterProjectAction->setToolTip(tr("Show issues originating outside currently opened projects.")); - m_filterProjectAction->setCheckable(true); - - m_suppressionSeparator->setSeparator(true); - m_suppressionSeparator->setToolTip(tr("These suppression files were used in the last memory analyzer run.")); + m_errorFilterActions.append(a); } void MemcheckTool::settingsDestroyed(QObject *settings) @@ -247,8 +227,15 @@ void MemcheckTool::settingsDestroyed(QObject *settings) m_settings = AnalyzerGlobalSettings::instance(); } +void MemcheckTool::extensionsInitialized() +{ + //ensureWidgets(); // FIXME: Try to do that later. +} + void MemcheckTool::maybeActiveRunConfigurationChanged() { + ensureWidgets(); + AnalyzerSettings *settings = 0; ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); if (ProjectExplorer::Project *project = pe->startupProject()) { @@ -292,7 +279,6 @@ void MemcheckTool::maybeActiveRunConfigurationChanged() } m_filterProjectAction->setChecked(!memcheckSettings->filterExternalIssues()); - m_errorView->settingsChanged(m_settings); connect(memcheckSettings, SIGNAL(visibleErrorKindsChanged(QList<int>)), @@ -365,61 +351,99 @@ private: QStringList m_projectFiles; }; -MemcheckErrorView *MemcheckTool::ensurePaneErrorView() +void MemcheckTool::initializeDockWidgets() { - if (!m_errorView) { - m_errorView = new MemcheckErrorView; - m_errorView->setObjectName(QLatin1String("MemcheckErrorView")); - m_errorView->setFrameStyle(QFrame::NoFrame); - m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false); - m_errorModel = new ErrorListModel(m_errorView); - m_frameFinder = new Internal::FrameFinder; - m_errorModel->setRelevantFrameFinder(QSharedPointer<Internal::FrameFinder>(m_frameFinder)); - m_errorProxyModel = new MemcheckErrorFilterProxyModel(m_errorView); - m_errorProxyModel->setSourceModel(m_errorModel); - m_errorProxyModel->setDynamicSortFilter(true); - m_errorView->setModel(m_errorProxyModel); - m_errorView->setSelectionMode(QAbstractItemView::ExtendedSelection); - // make m_errorView->selectionModel()->selectedRows() return something - m_errorView->setSelectionBehavior(QAbstractItemView::SelectRows); - m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); - m_errorView->setAutoScroll(false); - m_errorView->setObjectName("Valgrind.MemcheckTool.ErrorView"); - } - return m_errorView; + ensureWidgets(); } -QWidget *MemcheckTool::createPaneToolBarWidget() +void MemcheckTool::ensureWidgets() { - QWidget *toolbarWidget = new QWidget; - toolbarWidget->setObjectName(QLatin1String("MemCheckToolBarWidget")); + if (m_errorView) + return; + + AnalyzerManager *am = AnalyzerManager::instance(); + Utils::FancyMainWindow *mw = am->mainWindow(); + + m_errorView = new MemcheckErrorView; + m_errorView->setObjectName(QLatin1String("MemcheckErrorView")); + m_errorView->setFrameStyle(QFrame::NoFrame); + m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false); + m_errorModel = new ErrorListModel(m_errorView); + m_frameFinder = new Internal::FrameFinder; + m_errorModel->setRelevantFrameFinder(QSharedPointer<Internal::FrameFinder>(m_frameFinder)); + m_errorProxyModel = new MemcheckErrorFilterProxyModel(m_errorView); + m_errorProxyModel->setSourceModel(m_errorModel); + m_errorProxyModel->setDynamicSortFilter(true); + m_errorView->setModel(m_errorProxyModel); + m_errorView->setSelectionMode(QAbstractItemView::ExtendedSelection); + // make m_errorView->selectionModel()->selectedRows() return something + m_errorView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_errorView->setAutoScroll(false); + m_errorView->setObjectName("Valgrind.MemcheckTool.ErrorView"); + + QDockWidget *errorDock = + am->createDockWidget(this, tr("Memory Issues"), m_errorView, + Qt::BottomDockWidgetArea); + mw->splitDockWidget(mw->toolBarDockWidget(), errorDock, Qt::Vertical); + + connect(ProjectExplorer::ProjectExplorerPlugin::instance(), + SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged())); +} + +QWidget *MemcheckTool::createControlWidget() +{ + ensureWidgets(); + + QAction *action = 0; QHBoxLayout *layout = new QHBoxLayout; + QToolButton *button = 0; + layout->setMargin(0); layout->setSpacing(0); - // filter + + // Go to previous leak. + action = new QAction(this); + action->setDisabled(true); + action->setIcon(QIcon(QLatin1String(":core/images/prev.png"))); + action->setToolTip(tr("Go to previous leak.")); + connect(action, SIGNAL(triggered(bool)), m_errorView, SLOT(goBack())); + button = new QToolButton; + button->setDefaultAction(action); + layout->addWidget(button); + m_goBack = action; + + // Go to next leak. + action = new QAction(this); + action->setDisabled(true); + action->setIcon(QIcon(QLatin1String(":core/images/next.png"))); + action->setToolTip(tr("Go to next leak.")); + connect(action, SIGNAL(triggered(bool)), m_errorView, SLOT(goNext())); + button = new QToolButton; + button->setDefaultAction(action); + layout->addWidget(button); + m_goNext = action; + QToolButton *filterButton = new QToolButton; filterButton->setIcon(QIcon(Core::Constants::ICON_FILTER)); filterButton->setText(tr("Error Filter")); filterButton->setPopupMode(QToolButton::InstantPopup); - QMenu *filterMenu = new QMenu(filterButton); + + m_filterMenu = new QMenu(filterButton); foreach (QAction *filterAction, m_errorFilterActions) - filterMenu->addAction(filterAction); - filterMenu->addSeparator(); - filterMenu->addAction(m_filterProjectAction); - filterMenu->addAction(m_suppressionSeparator); - connect(filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter())); - filterButton->setMenu(filterMenu); + m_filterMenu->addAction(filterAction); + m_filterMenu->addSeparator(); + m_filterMenu->addAction(m_filterProjectAction); + m_filterMenu->addAction(m_suppressionSeparator); + connect(m_filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter())); + filterButton->setMenu(m_filterMenu); layout->addWidget(filterButton); - layout->addStretch(); - toolbarWidget->setLayout(layout); - return toolbarWidget; -} -void MemcheckTool::initialize() -{ - ensurePaneErrorView(); - // register shortcuts - maybeActiveRunConfigurationChanged(); + layout->addStretch(); + QWidget *widget = new QWidget; + widget->setObjectName(QLatin1String("MemCheckToolBarWidget")); + widget->setLayout(layout); + return widget; } IAnalyzerEngine *MemcheckTool::createEngine(const AnalyzerStartParameters &sp, @@ -454,27 +478,16 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine) m_errorView->setDefaultSuppressionFile(dir + name + QLatin1String(".supp")); - QMenu *menu = filterMenu(); - QTC_ASSERT(menu, return); foreach (const QString &file, mEngine->suppressionFiles()) { - QAction *action = menu->addAction(QFileInfo(file).fileName()); + QAction *action = m_filterMenu->addAction(QFileInfo(file).fileName()); action->setToolTip(file); action->setData(file); connect(action, SIGNAL(triggered(bool)), this, SLOT(suppressionActionTriggered())); - m_suppressionActions << action; + m_suppressionActions.append(action); } } -QMenu *MemcheckTool::filterMenu() const -{ - QTC_ASSERT(m_suppressionSeparator, return 0); - foreach (QWidget *w, m_suppressionSeparator->associatedWidgets()) - if (QMenu *menu = qobject_cast<QMenu *>(w)) - return menu; - return 0; -} - void MemcheckTool::suppressionActionTriggered() { QAction *action = qobject_cast<QAction *>(sender()); @@ -498,15 +511,17 @@ void MemcheckTool::internalParserError(const QString &errorString) void MemcheckTool::clearErrorView() { + ensureWidgets(); m_errorModel->clear(); qDeleteAll(m_suppressionActions); m_suppressionActions.clear(); - QTC_ASSERT(filterMenu()->actions().last() == m_suppressionSeparator, qt_noop()); + //QTC_ASSERT(filterMenu()->actions().last() == m_suppressionSeparator, qt_noop()); } void MemcheckTool::updateErrorFilter() { + ensureWidgets(); QTC_ASSERT(m_settings, return); AbstractMemcheckSettings *memcheckSettings = m_settings->subConfig<AbstractMemcheckSettings>(); @@ -527,16 +542,12 @@ void MemcheckTool::updateErrorFilter() memcheckSettings->setVisibleErrorKinds(errorKinds); } -IAnalyzerOutputPaneAdapter *MemcheckTool::outputPaneAdapter() -{ - if (!m_outputPaneAdapter) - m_outputPaneAdapter = new MemCheckOutputPaneAdapter(this); - return m_outputPaneAdapter; -} - void MemcheckTool::finished() { - const QString msg = AnalyzerManager::msgToolFinished(displayName(), m_errorModel->rowCount()); + const int n = m_errorModel->rowCount(); + m_goBack->setEnabled(n > 0); + m_goNext->setEnabled(n > 0); + const QString msg = AnalyzerManager::msgToolFinished(displayName(), n); AnalyzerManager::instance()->showStatusMessage(msg); } diff --git a/src/plugins/valgrind/memchecktool.h b/src/plugins/valgrind/memchecktool.h index 35262a9993..273593ae7a 100644 --- a/src/plugins/valgrind/memchecktool.h +++ b/src/plugins/valgrind/memchecktool.h @@ -57,15 +57,13 @@ class Error; } } -namespace Analyzer -{ +namespace Analyzer { class AnalyzerSettings; } namespace Valgrind { namespace Internal { -class MemCheckOutputPaneAdapter; class MemcheckErrorView; class FrameFinder; @@ -99,21 +97,6 @@ public: QString displayName() const; ToolMode mode() const; - void initialize(); - void extensionsInitialized() {} - - Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter(); - Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp, - ProjectExplorer::RunConfiguration *runConfiguration = 0); - - // For the output pane adapter. - MemcheckErrorView *ensurePaneErrorView(); - QWidget *createPaneToolBarWidget(); - void clearErrorView(); - - bool canRunRemotely() const; - bool needsOutputPane() const { return true; } - private slots: void settingsDestroyed(QObject *settings); void maybeActiveRunConfigurationChanged(); @@ -127,9 +110,21 @@ private slots: void suppressionActionTriggered(); private: - QMenu *filterMenu() const; + void ensureWidgets(); + bool canRunRemotely() const; + bool needsOutputPane() const { return true; } + void initializeDockWidgets(); + void initialize() {} + void extensionsInitialized(); + QWidget *createControlWidget(); + + Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp, + ProjectExplorer::RunConfiguration *runConfiguration = 0); + + void clearErrorView(); Analyzer::AnalyzerSettings *m_settings; + QMenu *m_filterMenu; FrameFinder *m_frameFinder; Valgrind::XmlProtocol::ErrorListModel *m_errorModel; @@ -140,7 +135,8 @@ private: QAction *m_filterProjectAction; QList<QAction *> m_suppressionActions; QAction *m_suppressionSeparator; - MemCheckOutputPaneAdapter *m_outputPaneAdapter; + QAction *m_goBack; + QAction *m_goNext; }; } // namespace Internal |