From 11311b6e948f215d8d285448b02b91c15bf79fa6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Mar 2011 16:11:20 +0100 Subject: [PATCH] Remove 'Analyze' mode. - Introduce a shared analysis output pane using a stacked widgets, layouts for the tools' output panes and toolbar widgets. - Introduce IAnalyzerOutputPaneAdapter interface returned by IAnalyzerTool to manage them. - Remove mode and its mainwindow contents (depending on enum constants should use cases for it occur). Reviewed-by: con --- src/plugins/analyzerbase/analyzerbase.pro | 6 +- src/plugins/analyzerbase/analyzermanager.cpp | 143 +++++------ src/plugins/analyzerbase/analyzermanager.h | 14 +- src/plugins/analyzerbase/analyzeroutputpane.cpp | 318 ++++++++++++++++++++++++ src/plugins/analyzerbase/analyzeroutputpane.h | 101 ++++++++ src/plugins/analyzerbase/analyzerplugin.cpp | 5 +- src/plugins/analyzerbase/ianalyzertool.cpp | 153 +++++++++++- src/plugins/analyzerbase/ianalyzertool.h | 64 ++++- src/plugins/memcheck/memcheckplugin.cpp | 1 - src/plugins/memcheck/memchecktool.cpp | 265 +++++++++----------- src/plugins/memcheck/memchecktool.h | 21 +- 11 files changed, 837 insertions(+), 254 deletions(-) create mode 100644 src/plugins/analyzerbase/analyzeroutputpane.cpp create mode 100644 src/plugins/analyzerbase/analyzeroutputpane.h diff --git a/src/plugins/analyzerbase/analyzerbase.pro b/src/plugins/analyzerbase/analyzerbase.pro index a2af77de91..d224a2518b 100644 --- a/src/plugins/analyzerbase/analyzerbase.pro +++ b/src/plugins/analyzerbase/analyzerbase.pro @@ -18,7 +18,8 @@ SOURCES += \ analyzermanager.cpp \ analyzersettings.cpp \ analyzeroptionspage.cpp \ - analyzerrunconfigwidget.cpp + analyzerrunconfigwidget.cpp \ + analyzeroutputpane.cpp HEADERS += \ ianalyzerengine.h \ @@ -30,7 +31,8 @@ HEADERS += \ analyzermanager.h \ analyzersettings.h \ analyzeroptionspage.h \ - analyzerrunconfigwidget.h + analyzerrunconfigwidget.h \ + analyzeroutputpane.h RESOURCES += \ analyzerbase.qrc diff --git a/src/plugins/analyzerbase/analyzermanager.cpp b/src/plugins/analyzerbase/analyzermanager.cpp index 13c807cd2e..7b36348601 100644 --- a/src/plugins/analyzerbase/analyzermanager.cpp +++ b/src/plugins/analyzerbase/analyzermanager.cpp @@ -40,6 +40,7 @@ #include "analyzerplugin.h" #include "analyzerruncontrol.h" #include "analyzeroptionspage.h" +#include "analyzeroutputpane.h" #include #include @@ -94,6 +95,11 @@ using namespace Core; using namespace Analyzer; using namespace Analyzer::Internal; +// A separate 'Analzye' mode is not used in Qt Creator 2.2. +// Consider re-introducing it if a real use case for a separate main window with docks +// appears. +enum { useAnalyzeMode = 0 }; + namespace Analyzer { namespace Internal { @@ -183,14 +189,15 @@ public: void delayedInit(); void setupActions(); - QWidget *createContents(); - QWidget *createMainWindow(); + QWidget *createModeContents(); + QWidget *createModeMainWindow(); void addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, QDockWidget *dockWidget); void startTool(); AnalyzerManager *q; AnalyzerMode *m_mode; + AnalyzerOutputPane *m_outputpane; AnalyzerRunControlFactory *m_runControlFactory; ProjectExplorer::RunControl *m_currentRunControl; Utils::FancyMainWindow *m_mainWindow; @@ -200,14 +207,11 @@ public: QAction *m_stopAction; QMenu *m_menu; QComboBox *m_toolBox; - Utils::StyledSeparator *m_toolBoxSeparator; ActionContainer *m_viewsMenu; typedef QPair ToolWidgetPair; typedef QList ToolWidgetPairList; QMap m_toolWidgets; DockWidgetEventFilter *m_resizeEventFilter; - QMap m_toolToolbarWidgets; - QStackedWidget *m_toolbarStackedWidget; QMap m_defaultSettings; // list of dock widgets to prevent memory leak @@ -220,6 +224,7 @@ public: AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq): q(qq), m_mode(0), + m_outputpane(0), m_runControlFactory(0), m_currentRunControl(0), m_mainWindow(0), @@ -227,18 +232,20 @@ AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager m_startAction(0), m_stopAction(0), m_menu(0), - m_toolBox(0), - m_toolBoxSeparator(0), + m_toolBox(new QComboBox), m_viewsMenu(0), m_resizeEventFilter(new DockWidgetEventFilter(qq)), - m_toolbarStackedWidget(0), m_initialized(false) { + m_toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox")); m_runControlFactory = new AnalyzerRunControlFactory(); AnalyzerPlugin::instance()->addAutoReleasedObject(m_runControlFactory); connect(m_runControlFactory, SIGNAL(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)), q, SLOT(runControlCreated(Analyzer::Internal::AnalyzerRunControl *))); + connect(m_toolBox, SIGNAL(currentIndexChanged(int)), + q, SLOT(toolSelected(int))); + setupActions(); } @@ -295,17 +302,20 @@ void AnalyzerManager::AnalyzerManagerPrivate::delayedInit() if (m_initialized) return; - m_mode = new AnalyzerMode(q); - m_mode->setWidget(createContents()); - AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode); + if (useAnalyzeMode) { + m_mode = new AnalyzerMode(q); + m_mode->setWidget(createModeContents()); + AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode); + } m_initialized = true; } -QWidget *AnalyzerManager::AnalyzerManagerPrivate::createContents() +QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeContents() { + QTC_ASSERT(useAnalyzeMode, return 0; ) // right-side window with editor, output etc. MiniSplitter *mainWindowSplitter = new MiniSplitter; - mainWindowSplitter->addWidget(createMainWindow()); + mainWindowSplitter->addWidget(createModeMainWindow()); mainWindowSplitter->addWidget(new OutputPanePlaceHolder(m_mode, mainWindowSplitter)); mainWindowSplitter->setStretchFactor(0, 10); mainWindowSplitter->setStretchFactor(1, 0); @@ -327,9 +337,19 @@ static QToolButton *toolButton(QAction *action) return button; } -QWidget *AnalyzerManager::AnalyzerManagerPrivate::createMainWindow() +QWidgetList AnalyzerManager::outputPaneToolBarWidgets() const { + QWidgetList result; + result << toolButton(d->m_startAction) << toolButton(d->m_stopAction) + << new Utils::StyledSeparator << d->m_toolBox; + return result; +} + +QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeMainWindow() +{ + QTC_ASSERT(useAnalyzeMode, return 0; ) m_mainWindow = new Utils::FancyMainWindow(); + m_mainWindow->setObjectName(QLatin1String("AnalyzerManagerMainWindow")); connect(m_mainWindow, SIGNAL(resetLayout()), q, SLOT(resetLayout())); m_mainWindow->setDocumentMode(true); @@ -352,35 +372,6 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createMainWindow() documentAndRightPane->setStretchFactor(0, 1); documentAndRightPane->setStretchFactor(1, 0); - Utils::StyledBar *analyzeToolBar = new Utils::StyledBar; - analyzeToolBar->setProperty("topBorder", true); - QHBoxLayout *analyzeToolBarLayout = new QHBoxLayout(analyzeToolBar); - analyzeToolBarLayout->setMargin(0); - analyzeToolBarLayout->setSpacing(0); - QToolButton *startButton = toolButton(m_startAction); - analyzeToolBarLayout->addWidget(startButton); - analyzeToolBarLayout->addWidget(toolButton(m_stopAction)); - analyzeToolBarLayout->addWidget(new Utils::StyledSeparator); - m_toolBox = new QComboBox; - connect(m_toolBox, SIGNAL(currentIndexChanged(int)), - q, SLOT(toolSelected(int))); - analyzeToolBarLayout->addWidget(m_toolBox); - m_toolBoxSeparator = new Utils::StyledSeparator; - analyzeToolBarLayout->addWidget(m_toolBoxSeparator); - m_toolbarStackedWidget = new QStackedWidget; - analyzeToolBarLayout->addWidget(m_toolbarStackedWidget); - analyzeToolBarLayout->addStretch(); - - QDockWidget *dock = new QDockWidget(tr("Analyzer Toolbar")); - dock->setObjectName(QLatin1String("Analyzer Toolbar")); - dock->setWidget(analyzeToolBar); - dock->setFeatures(QDockWidget::NoDockWidgetFeatures); - dock->setProperty("managed_dockwidget", QLatin1String("true")); - dock->setAllowedAreas(Qt::BottomDockWidgetArea); - // hide title bar - dock->setTitleBarWidget(new QWidget(dock)); - m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); - m_mainWindow->setToolBarDockWidget(dock); QWidget *centralWidget = new QWidget; m_mainWindow->setCentralWidget(centralWidget); @@ -399,7 +390,7 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createMainWindow() void AnalyzerManager::AnalyzerManagerPrivate::addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, QDockWidget *dockWidget) { - QTC_ASSERT(tool == q->currentTool(), return) + QTC_ASSERT(useAnalyzeMode && tool == q->currentTool(), return) dockWidget->setParent(m_mainWindow); m_mainWindow->addDockWidget(area, dockWidget); @@ -448,10 +439,11 @@ bool buildTypeAcceppted(IAnalyzerTool::ToolMode toolMode, void AnalyzerManager::AnalyzerManagerPrivate::startTool() { - QTC_ASSERT(!m_currentRunControl, return); - + QTC_ASSERT(!m_currentRunControl && q->currentTool(), return); // make sure our mode is shown - ModeManager::instance()->activateMode(m_mode->id()); + m_outputpane->popup(); + if (m_mode) + ModeManager::instance()->activateMode(m_mode->id()); ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); @@ -520,14 +512,16 @@ void AnalyzerManager::AnalyzerManagerPrivate::startTool() // AnalyzerManager //////////////////////////////////////////////////// AnalyzerManager *AnalyzerManager::m_instance = 0; -AnalyzerManager::AnalyzerManager(QObject *parent) : +AnalyzerManager::AnalyzerManager(Internal::AnalyzerOutputPane *op, QObject *parent) : QObject(parent), d(new AnalyzerManagerPrivate(this)) { m_instance = this; + d->m_outputpane = op; - connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), - this, SLOT(modeChanged(Core::IMode*))); + if (useAnalyzeMode) + connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), + this, SLOT(modeChanged(Core::IMode*))); ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); connect(pe, SIGNAL(updateRunActions()), this, SLOT(updateRunActions())); @@ -545,7 +539,8 @@ bool AnalyzerManager::isInitialized() const void AnalyzerManager::shutdown() { - saveToolSettings(currentTool()); + if (useAnalyzeMode) + saveToolSettings(currentTool()); } AnalyzerManager * AnalyzerManager::instance() @@ -555,6 +550,7 @@ AnalyzerManager * AnalyzerManager::instance() void AnalyzerManager::modeChanged(IMode *mode) { + QTC_ASSERT(d->m_mainWindow, return; ) const bool makeVisible = mode->id() == Constants::MODE_ANALYZE; if (!makeVisible) return; @@ -576,7 +572,7 @@ void AnalyzerManager::toolSelected(int idx) selectingTool = true; IAnalyzerTool *oldTool = currentTool(); - if (oldTool) { + if (useAnalyzeMode && oldTool != 0) { saveToolSettings(oldTool); ActionManager *am = ICore::instance()->actionManager(); @@ -599,13 +595,13 @@ void AnalyzerManager::toolSelected(int idx) IAnalyzerTool *newTool = currentTool(); - if (QWidget *toolbarWidget = d->m_toolToolbarWidgets.value(newTool)) - d->m_toolbarStackedWidget->setCurrentWidget(toolbarWidget); - - foreach(const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) { - d->addDock(newTool, widget.first, widget.second); + if (useAnalyzeMode) { + foreach (const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) { + d->addDock(newTool, widget.first, widget.second); + } + loadToolSettings(newTool); } - loadToolSettings(newTool); + d->m_outputpane->setTool(newTool); selectingTool = false; } @@ -628,33 +624,23 @@ void AnalyzerManager::addTool(IAnalyzerTool *tool) d->m_toolGroup->setVisible(d->m_toolGroup->actions().count() > 1); d->m_tools.append(tool); d->m_toolBox->addItem(tool->displayName()); - d->m_toolBox->setVisible(d->m_toolBox->count() > 1); - d->m_toolBoxSeparator->setVisible(d->m_toolBox->isVisible()); - + d->m_toolBox->setEnabled(d->m_toolBox->count() > 1); if (currentTool() != tool) selectTool(tool); // the first tool gets selected automatically due to signal emission from toolbox tool->initialize(plugin); - QSettings *defaultSettings = new QSettings(this); - d->m_defaultSettings[tool] = defaultSettings; - d->m_mainWindow->saveSettings(defaultSettings); - - loadToolSettings(tool); -} - -void AnalyzerManager::setToolbar(IAnalyzerTool *tool, QWidget *widget) -{ - d->m_toolToolbarWidgets[tool] = widget; - d->m_toolbarStackedWidget->addWidget(widget); - - if (currentTool() == tool) - d->m_toolbarStackedWidget->setCurrentWidget(widget); + if (useAnalyzeMode) { + QSettings *defaultSettings = new QSettings(this); + d->m_defaultSettings[tool] = defaultSettings; + d->m_mainWindow->saveSettings(defaultSettings); + loadToolSettings(tool); + } } QDockWidget *AnalyzerManager::createDockWidget(IAnalyzerTool *tool, const QString &title, QWidget *widget, Qt::DockWidgetArea area) { - QTC_ASSERT(!widget->objectName().isEmpty(), qt_noop()); + QTC_ASSERT(useAnalyzeMode && !widget->objectName().isEmpty(), return 0;); QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget); d->m_dockWidgets << AnalyzerManagerPrivate::DockPtr(dockWidget); @@ -727,6 +713,7 @@ void AnalyzerManager::resetLayout() void AnalyzerManager::loadToolSettings(IAnalyzerTool *tool) { + QTC_ASSERT(d->m_mainWindow, return; ) QSettings *settings = Core::ICore::instance()->settings(); settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id()); if (settings->value("ToolSettingsSaved", false).toBool()) { @@ -739,6 +726,7 @@ void AnalyzerManager::saveToolSettings(IAnalyzerTool *tool) { if (!tool) return; // no active tool, do nothing + QTC_ASSERT(d->m_mainWindow, return ; ) QSettings *settings = Core::ICore::instance()->settings(); settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id()); @@ -751,7 +739,8 @@ void AnalyzerManager::updateRunActions() { ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); ProjectExplorer::Project *project = pe->startupProject(); - bool startEnabled = !d->m_currentRunControl && pe->canRun(project, Constants::MODE_ANALYZE); + bool startEnabled = !d->m_currentRunControl && pe->canRun(project, Constants::MODE_ANALYZE) + && currentTool(); d->m_startAction->setEnabled(startEnabled); } diff --git a/src/plugins/analyzerbase/analyzermanager.h b/src/plugins/analyzerbase/analyzermanager.h index b89359c46e..0187eeb3d3 100644 --- a/src/plugins/analyzerbase/analyzermanager.h +++ b/src/plugins/analyzerbase/analyzermanager.h @@ -57,6 +57,7 @@ namespace Analyzer { class IAnalyzerTool; namespace Internal { class AnalyzerRunControl; +class AnalyzerOutputPane; } // namespace Internal class ANALYZER_EXPORT AnalyzerManager : public QObject @@ -64,7 +65,7 @@ class ANALYZER_EXPORT AnalyzerManager : public QObject Q_OBJECT public: - explicit AnalyzerManager(QObject *parent = 0); + explicit AnalyzerManager(Internal::AnalyzerOutputPane *op, QObject *parent = 0); ~AnalyzerManager(); static AnalyzerManager *instance(); @@ -83,19 +84,12 @@ public: QDockWidget *createDockWidget(IAnalyzerTool *tool, const QString &title, QWidget *widget, Qt::DockWidgetArea area = Qt::TopDockWidgetArea); - /** - * Add the given @p widget into this mode's toolbar. - * - * It will be shown whenever this tool is selected by the user. - * - * @Note The manager will take ownership of @p widget. - */ - void setToolbar(Analyzer::IAnalyzerTool *tool, QWidget *widget); - Utils::FancyMainWindow *mainWindow() const; void selectTool(IAnalyzerTool *tool); + QList outputPaneToolBarWidgets() const; + private slots: void startTool(); void stopTool(); diff --git a/src/plugins/analyzerbase/analyzeroutputpane.cpp b/src/plugins/analyzerbase/analyzeroutputpane.cpp new file mode 100644 index 0000000000..cc384504b5 --- /dev/null +++ b/src/plugins/analyzerbase/analyzeroutputpane.cpp @@ -0,0 +1,318 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "analyzeroutputpane.h" +#include "analyzermanager.h" +#include "ianalyzertool.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include + +static const char dummyWidgetPropertyC[] = "dummyWidget"; + +enum { debug = 0 }; +enum { dummyIndex = 0 }; + +namespace Analyzer { +namespace Internal { + +static inline QWidget *createDummyWidget() +{ + QWidget *widget = new QWidget; + widget->setProperty(dummyWidgetPropertyC, QVariant(true)); + return widget; +} + +/*! + \class AnalyzerPane::Internal::AnalyzerOutputPane + + \brief Common analysis output pane managing several tools. + + Output pane for all tools derived from IAnalyzerTool. + The IAnalyzerOutputPaneAdapter (unless 0) provides + \list + \i Pane widget + \i Optional toolbar widget + \endlist + + Both are inserted into a pane stacked layout and a stacked toolbar widget respectively. + + The indexes of the stacked widgets/layouts and the adapter list go in sync + (dummy widgets on the toolbar are used to achieve this). + Dummy widgets that are shown in case there is no tool with an output pane + are added at index 0 to the stacks (usage of index 0 is to avoid using + QStackedWidget::insert() when adding adapters, which causes flicker). + + Besides the tool-specific toolbar widget, the start/stop buttons and the combo + box of the AnalyzerManager are shown in the toolbar. + + The initialization is a bit tricky here, as the sequence of calls to + setTool(), outputWindow()/toolBarWidgets() is basically undefined. The pane widget + should be created on the correct parent when outputWindow() + is called, tools will typically be added before. + + \sa AnalyzerPane::Internal::IAnalyzerOutputPaneAdapter +*/ + +AnalyzerOutputPane::AnalyzerOutputPane(QObject *parent) : + Core::IOutputPane(parent), + m_paneWidget(0), + m_paneStackedLayout(0), + m_toolbarStackedWidget(0), + m_toolBarSeparator(0) +{ + setObjectName(QLatin1String("AnalyzerOutputPane")); +} + +void AnalyzerOutputPane::clearTool() +{ + // No tool. Show dummy label, which is the last widget. + if (m_paneWidget) { + m_paneStackedLayout->setCurrentIndex(dummyIndex); + m_toolbarStackedWidget->setCurrentIndex(dummyIndex); + emit navigateStateChanged(); + } + hide(); +} + +int AnalyzerOutputPane::currentIndex() const +{ + return m_paneStackedLayout ? m_paneStackedLayout->currentIndex() : -1; +} + +IAnalyzerOutputPaneAdapter *AnalyzerOutputPane::currentAdapter() const +{ + const int index = currentIndex(); // Rule out leading dummy widget + if (index != dummyIndex && index < m_adapters.size()) + return m_adapters.at(index); + return 0; +} + +void AnalyzerOutputPane::setCurrentIndex(int i) +{ + QTC_ASSERT(isInitialized(), return ) + + if (i != currentIndex()) { + // Show up pane widget and optional toolbar widget. Hide + // the toolbar if the toolbar widget is a dummy. + m_paneStackedLayout->setCurrentIndex(i); + m_toolbarStackedWidget->setCurrentIndex(i); + const bool hasToolBarWidget = !m_toolbarStackedWidget->currentWidget()->property(dummyWidgetPropertyC).toBool(); + m_toolbarStackedWidget->setVisible(hasToolBarWidget); + m_toolBarSeparator->setVisible(hasToolBarWidget); + navigateStateChanged(); + } +} + +void AnalyzerOutputPane::add(IAnalyzerOutputPaneAdapter *adapter) +{ + if (m_adapters.isEmpty()) + m_adapters.push_back(0); // Index for leading dummy widgets. + m_adapters.push_back(adapter); + connect(adapter, SIGNAL(navigationStatusChanged()), this, SLOT(slotNavigationStatusChanged())); + connect(adapter, SIGNAL(popup(bool)), this, SLOT(slotPopup(bool))); + if (isInitialized()) + addToWidgets(adapter); +} + +void AnalyzerOutputPane::addToWidgets(IAnalyzerOutputPaneAdapter *adapter) +{ + QTC_ASSERT(m_paneWidget, return; ) + QWidget *toolPaneWidget = adapter->paneWidget(); + QTC_ASSERT(toolPaneWidget, return; ) + m_paneStackedLayout->addWidget(toolPaneWidget); + QWidget *toolBarWidget = adapter->toolBarWidget(); // Might be 0 + m_toolbarStackedWidget->addWidget(toolBarWidget ? toolBarWidget : createDummyWidget()); +} + +void AnalyzerOutputPane::setTool(IAnalyzerTool *t) +{ + if (debug) + qDebug() << "AnalyzerOutputPane::setTool" << t; + // No tool. show dummy label. + IAnalyzerOutputPaneAdapter *adapter = t ? t->outputPaneAdapter() : + static_cast(0); + // Re-show or add. + if (adapter) { + int index = m_adapters.indexOf(adapter); + if (index == -1) { + index = m_adapters.size(); + add(adapter); + } + if (isInitialized()) { + popup(false); + setCurrentIndex(index); + } + } else { + clearTool(); + } +} + +QWidget * AnalyzerOutputPane::outputWidget(QWidget *parent) +{ + if (debug) + qDebug() << "AnalyzerOutputPane::outputWidget"; + // Delayed creation of main pane widget. Add a trailing dummy widget + // and add all adapters. + if (!isInitialized()) + createWidgets(parent); + return m_paneWidget; +} + +void AnalyzerOutputPane::createWidgets(QWidget *paneParent) +{ + // Create pane and toolbar stack with leading dummy widget. + m_paneWidget = new QWidget(paneParent); + m_paneStackedLayout = new QStackedLayout(m_paneWidget); + m_paneWidget->setObjectName(objectName() + QLatin1String("Widget")); + m_paneStackedLayout->addWidget(new QLabel(tr("No current analysis tool"))); + + m_toolbarStackedWidget = new QStackedWidget; + m_toolBarSeparator = new Utils::StyledSeparator; + m_toolbarStackedWidget->setObjectName(objectName() + QLatin1String("ToolBarStackedWidget")); + + // Add adapters added before. + const int adapterCount = m_adapters.size(); + const int firstAdapter = dummyIndex + 1; + for (int i = firstAdapter; i < adapterCount; i++) + addToWidgets(m_adapters.at(i)); + // Make last one current + if (adapterCount > firstAdapter) + setCurrentIndex(firstAdapter); +} + +QWidgetList AnalyzerOutputPane::toolBarWidgets() const +{ + if (debug) + qDebug() << "AnalyzerOutputPane::toolBarWidget"; + QTC_ASSERT(isInitialized(), return QWidgetList(); ) + + QWidgetList list = AnalyzerManager::instance()->outputPaneToolBarWidgets(); + list << m_toolBarSeparator << m_toolbarStackedWidget; + return list; +} + +QString AnalyzerOutputPane::displayName() const +{ + return tr("Analysis"); +} + +int AnalyzerOutputPane::priorityInStatusBar() const +{ + return -1; // Not visible in status bar. +} + +void AnalyzerOutputPane::clearContents() +{ + if (IAnalyzerOutputPaneAdapter *adapter = currentAdapter()) + adapter->clearContents(); +} + +void AnalyzerOutputPane::visibilityChanged(bool v) +{ + Q_UNUSED(v) +} + +void AnalyzerOutputPane::setFocus() +{ + if (IAnalyzerOutputPaneAdapter *adapter = currentAdapter()) + adapter->setFocus(); +} + +bool AnalyzerOutputPane::hasFocus() +{ + const IAnalyzerOutputPaneAdapter *adapter = currentAdapter(); + return adapter ? adapter->hasFocus() : false; +} + +bool AnalyzerOutputPane::canFocus() +{ + const IAnalyzerOutputPaneAdapter *adapter = currentAdapter(); + return adapter ? adapter->canFocus() : false; +} + +bool AnalyzerOutputPane::canNavigate() +{ + const IAnalyzerOutputPaneAdapter *adapter = currentAdapter(); + return adapter ? adapter->canNavigate() : false; +} + +bool AnalyzerOutputPane::canNext() +{ + const IAnalyzerOutputPaneAdapter *adapter = currentAdapter(); + return adapter ? adapter->canNext() : false; +} + +bool AnalyzerOutputPane::canPrevious() +{ + const IAnalyzerOutputPaneAdapter *adapter = currentAdapter(); + return adapter ? adapter->canPrevious() : false; +} + +void AnalyzerOutputPane::goToNext() +{ + if (IAnalyzerOutputPaneAdapter *adapter = currentAdapter()) + adapter->goToNext(); +} + +void AnalyzerOutputPane::goToPrev() +{ + if (IAnalyzerOutputPaneAdapter *adapter = currentAdapter()) + adapter->goToPrev(); +} + +void AnalyzerOutputPane::slotPopup(bool withFocus) +{ + popup(withFocus); +} + +void AnalyzerOutputPane::slotNavigationStatusChanged() +{ + IAnalyzerOutputPaneAdapter *adapter = qobject_cast(sender()); + const int index = m_adapters.indexOf(adapter); + QTC_ASSERT(adapter != 0 && index != -1, return; ) + // Forward navigation status if it is the current pane. + if (index == currentIndex()) + navigateStateChanged(); +} + +} // namespace Internal +} // namespace Analyzer diff --git a/src/plugins/analyzerbase/analyzeroutputpane.h b/src/plugins/analyzerbase/analyzeroutputpane.h new file mode 100644 index 0000000000..8773d5205c --- /dev/null +++ b/src/plugins/analyzerbase/analyzeroutputpane.h @@ -0,0 +1,101 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef ANALYZEROUTPUTPANE_H +#define ANALYZEROUTPUTPANE_H + +#include + +QT_FORWARD_DECLARE_CLASS(QStackedLayout) +QT_FORWARD_DECLARE_CLASS(QStackedWidget) + +namespace Utils { +class StyledSeparator; +} + +namespace Analyzer { +class IAnalyzerTool; +class IAnalyzerOutputPaneAdapter; +namespace Internal { + +class AnalyzerOutputPane : public Core::IOutputPane +{ + Q_OBJECT +public: + explicit AnalyzerOutputPane(QObject *parent = 0); + + void setTool(IAnalyzerTool *t); + // IOutputPane + virtual QWidget *outputWidget(QWidget *parent); + virtual QList toolBarWidgets() const; + virtual QString displayName() const; + + virtual int priorityInStatusBar() const; + + virtual void clearContents(); + virtual void visibilityChanged(bool visible); + + virtual void setFocus(); + virtual bool hasFocus(); + virtual bool canFocus(); + virtual bool canNavigate(); + virtual bool canNext(); + virtual bool canPrevious(); + virtual void goToNext(); + virtual void goToPrev(); + +private slots: + void slotPopup(bool withFocus); + void slotNavigationStatusChanged(); + +private: + void clearTool(); + inline int currentIndex() const; + inline IAnalyzerOutputPaneAdapter *currentAdapter() const; + void setCurrentIndex(int ); + void add(IAnalyzerOutputPaneAdapter *adapter); + void addToWidgets(IAnalyzerOutputPaneAdapter *adapter); + void createWidgets(QWidget *paneParent); + bool isInitialized() const { return m_paneWidget != 0; } + + QWidget *m_paneWidget; + QStackedLayout *m_paneStackedLayout; + QList m_adapters; + QStackedWidget *m_toolbarStackedWidget; + Utils::StyledSeparator *m_toolBarSeparator; +}; + +} // namespace Internal +} // namespace Analyzer + +#endif // ANALYZEROUTPUTPANE_H diff --git a/src/plugins/analyzerbase/analyzerplugin.cpp b/src/plugins/analyzerbase/analyzerplugin.cpp index b202dc57c1..62d8f7b127 100644 --- a/src/plugins/analyzerbase/analyzerplugin.cpp +++ b/src/plugins/analyzerbase/analyzerplugin.cpp @@ -36,6 +36,7 @@ #include "analyzerplugin.h" #include "analyzerconstants.h" #include "analyzermanager.h" +#include "analyzeroutputpane.h" #include #include @@ -76,7 +77,9 @@ void AnalyzerPlugin::AnalyzerPluginPrivate::initialize(const QStringList &argume { Q_UNUSED(arguments) Q_UNUSED(errorString) - m_manager = new AnalyzerManager(q); + AnalyzerOutputPane *outputPane = new AnalyzerOutputPane; + q->addAutoReleasedObject(outputPane); + m_manager = new AnalyzerManager(outputPane, q); } diff --git a/src/plugins/analyzerbase/ianalyzertool.cpp b/src/plugins/analyzerbase/ianalyzertool.cpp index 110862dbb8..4596ce8c03 100644 --- a/src/plugins/analyzerbase/ianalyzertool.cpp +++ b/src/plugins/analyzerbase/ianalyzertool.cpp @@ -34,14 +34,158 @@ **************************************************************************/ #include "ianalyzertool.h" +#include "analyzeroutputpane.h" -using namespace Analyzer; +#include + +#include +#include +#include +#include + +namespace Analyzer { IAnalyzerTool::IAnalyzerTool(QObject *parent) : QObject(parent) { } +/*! + \class Analyzer::IAnalyzerOutputPaneAdapter + + \brief Adapter for handling multiple tools in the common 'Analysis' output pane. + + Provides the tool-specific output pane widget and optionally, a widget to be + inserted into into the toolbar. Ownership of them is taken by the output pane. + Forwards navigation calls issued by the output pane. +*/ + +IAnalyzerOutputPaneAdapter::IAnalyzerOutputPaneAdapter(QObject *parent) : + QObject(parent) +{ +} + +IAnalyzerOutputPaneAdapter::~IAnalyzerOutputPaneAdapter() +{ +} + +/*! + \class Analyzer::ListItemViewOutputPaneAdapter + + \brief Utility class implementing wrap-around navigation for flat lists. + + Provides an optional mechanism to pop up automatically in case errors show up. +*/ + +ListItemViewOutputPaneAdapter::ListItemViewOutputPaneAdapter(QObject *parent) : + IAnalyzerOutputPaneAdapter(parent), m_listView(0), m_showOnRowsInserted(true) +{ +} + +void ListItemViewOutputPaneAdapter::connectNavigationSignals(QAbstractItemModel *model) +{ + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SIGNAL(navigationStatusChanged())); + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(slotRowsInserted())); + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SIGNAL(navigationStatusChanged())); + connect(model, SIGNAL(modelReset()), + this, SIGNAL(navigationStatusChanged())); +} + +void ListItemViewOutputPaneAdapter::slotRowsInserted() +{ + if (m_showOnRowsInserted && !m_listView->isVisible()) + emit popup(true); +} + +QWidget *ListItemViewOutputPaneAdapter::paneWidget() +{ + if (!m_listView) { + m_listView = createItemView(); + if (QAbstractItemModel *model = m_listView->model()) + connectNavigationSignals(model); + } + return m_listView; +} + +void ListItemViewOutputPaneAdapter::setFocus() +{ + if (m_listView) + m_listView->setFocus(); +} + +bool ListItemViewOutputPaneAdapter::hasFocus() const +{ + return m_listView ? m_listView->hasFocus() : false; +} + +bool ListItemViewOutputPaneAdapter::canFocus() const +{ + return true; +} + +bool ListItemViewOutputPaneAdapter::canNavigate() const +{ + return true; +} + +bool ListItemViewOutputPaneAdapter::canNext() const +{ + return rowCount() > 0; +} + +bool ListItemViewOutputPaneAdapter::canPrevious() const +{ + return rowCount() > 0; +} + +void ListItemViewOutputPaneAdapter::goToNext() +{ + setCurrentRow((currentRow() + 1) % rowCount()); +} + +void ListItemViewOutputPaneAdapter::goToPrev() +{ + const int prevRow = currentRow() - 1; + setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1); +} + +bool ListItemViewOutputPaneAdapter::showOnRowsInserted() const +{ + return m_showOnRowsInserted; +} + +void ListItemViewOutputPaneAdapter::setShowOnRowsInserted(bool v) +{ + m_showOnRowsInserted = v; +} + +int ListItemViewOutputPaneAdapter::currentRow() const +{ + if (m_listView) { + const QModelIndex index = m_listView->selectionModel()->currentIndex(); + if (index.isValid()) + return index.row(); + } + return -1; +} + +void ListItemViewOutputPaneAdapter::setCurrentRow(int r) +{ + QTC_ASSERT(m_listView, return; ) + const QModelIndex index = m_listView->model()->index(r, 0); + m_listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current); + m_listView->scrollTo(index); +} + +int ListItemViewOutputPaneAdapter::rowCount() const +{ + return m_listView ? m_listView->model()->rowCount() : 0; +} + +// -------------IAnalyzerTool QString IAnalyzerTool::modeString() { switch (mode()) { @@ -54,3 +198,10 @@ QString IAnalyzerTool::modeString() } return QString(); } + +IAnalyzerOutputPaneAdapter *IAnalyzerTool::outputPaneAdapter() +{ + return 0; +} + +} // namespace Analyzer diff --git a/src/plugins/analyzerbase/ianalyzertool.h b/src/plugins/analyzerbase/ianalyzertool.h index f86b0e964a..849abde056 100644 --- a/src/plugins/analyzerbase/ianalyzertool.h +++ b/src/plugins/analyzerbase/ianalyzertool.h @@ -40,6 +40,9 @@ #include +QT_FORWARD_DECLARE_CLASS(QAbstractItemView) +QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) + namespace ProjectExplorer { class RunConfiguration; } @@ -49,9 +52,66 @@ class IPlugin; } namespace Analyzer { - class IAnalyzerEngine; +class ANALYZER_EXPORT IAnalyzerOutputPaneAdapter : public QObject +{ + Q_OBJECT +public: + explicit IAnalyzerOutputPaneAdapter(QObject *parent = 0); + virtual ~IAnalyzerOutputPaneAdapter(); + + virtual QWidget *toolBarWidget() = 0; + virtual QWidget *paneWidget() = 0; + virtual void clearContents() = 0; + virtual void setFocus() = 0; + virtual bool hasFocus() const = 0; + virtual bool canFocus() const = 0; + virtual bool canNavigate() const = 0; + virtual bool canNext() const = 0; + virtual bool canPrevious() const = 0; + virtual void goToNext() = 0; + virtual void goToPrev() = 0; + +signals: + void popup(bool withFocus); + void navigationStatusChanged(); +}; + +class ANALYZER_EXPORT ListItemViewOutputPaneAdapter : public IAnalyzerOutputPaneAdapter +{ + Q_OBJECT +public: + explicit ListItemViewOutputPaneAdapter(QObject *parent = 0); + + virtual QWidget *paneWidget(); + virtual void setFocus(); + virtual bool hasFocus() const; + virtual bool canFocus() const; + virtual bool canNavigate() const; + virtual bool canNext() const; + virtual bool canPrevious() const; + virtual void goToNext(); + virtual void goToPrev(); + + bool showOnRowsInserted() const; + void setShowOnRowsInserted(bool v); + +protected: + int currentRow() const; + void setCurrentRow(int); + int rowCount() const; + void connectNavigationSignals(QAbstractItemModel *); + virtual QAbstractItemView *createItemView() = 0; + +private slots: + void slotRowsInserted(); + +private: + QAbstractItemView *m_listView; + bool m_showOnRowsInserted; +}; + class ANALYZER_EXPORT IAnalyzerTool : public QObject { Q_OBJECT @@ -78,6 +138,8 @@ public: virtual void initialize(ExtensionSystem::IPlugin *plugin) = 0; + virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter(); + virtual IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration) = 0; }; diff --git a/src/plugins/memcheck/memcheckplugin.cpp b/src/plugins/memcheck/memcheckplugin.cpp index da888fc149..7c66ab53fe 100644 --- a/src/plugins/memcheck/memcheckplugin.cpp +++ b/src/plugins/memcheck/memcheckplugin.cpp @@ -63,7 +63,6 @@ bool MemcheckPlugin::initialize(const QStringList &/*arguments*/, QString */*err AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new MemcheckConfigFactory); AnalyzerManager::instance()->addTool(new MemcheckTool(this)); - return true; } diff --git a/src/plugins/memcheck/memchecktool.cpp b/src/plugins/memcheck/memchecktool.cpp index 3240c8a1ff..f5470a95a9 100644 --- a/src/plugins/memcheck/memchecktool.cpp +++ b/src/plugins/memcheck/memchecktool.cpp @@ -91,10 +91,29 @@ #include #include -using namespace Analyzer; -using namespace Analyzer::Internal; using namespace Valgrind::XmlProtocol; +namespace Analyzer { +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), m_filterExternalIssues(false) @@ -174,19 +193,52 @@ bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModel return true; } +static void initKindFilterAction(QAction *action, const QList &kinds) +{ + action->setCheckable(true); + QVariantList data; + foreach (int kind, kinds) + data << kind; + action->setData(data); +} + MemcheckTool::MemcheckTool(QObject *parent) : Analyzer::IAnalyzerTool(parent), m_settings(0), m_errorModel(0), m_errorProxyModel(0), m_errorView(0), - m_prevAction(0), - m_nextAction(0), - m_clearAction(0), - m_filterProjectAction(0) + m_filterProjectAction(new QAction(tr("External Errors"), this)), + m_suppressionSeparator(new QAction(tr("Suppressions"), this)), + m_outputPaneAdapter(0) { + setObjectName(QLatin1String("MemcheckTool")); connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged())); + + QAction *a = new QAction(tr("Definite Memory Leaks"), this); + initKindFilterAction(a, QList() << Leak_DefinitelyLost << Leak_IndirectlyLost); + m_errorFilterActions << a; + + a = new QAction(tr("Possible Memory Leaks"), this); + initKindFilterAction(a, QList() << Leak_PossiblyLost << Leak_StillReachable); + m_errorFilterActions << a; + + a = new QAction(tr("Use of Uninitialized Memory"), this); + initKindFilterAction(a, QList() << InvalidRead << InvalidWrite << InvalidJump << Overlap + << InvalidMemPool << UninitCondition << UninitValue + << SyscallParam << ClientCheck); + m_errorFilterActions << a; + + a = new QAction(tr("Invalid Frees"), this); + initKindFilterAction(a, QList() << 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 where used in the last memory analyzer run.")); } void MemcheckTool::settingsDestroyed(QObject *settings) @@ -267,8 +319,6 @@ IAnalyzerTool::ToolMode MemcheckTool::mode() const return DebugMode; } -namespace Analyzer { -namespace Internal { class FrameFinder : public ErrorListModel::RelevantFrameFinder { public: Frame findRelevant(const Error &error) const { @@ -310,130 +360,61 @@ public: private: QStringList m_projectFiles; }; -} -} -static void initKindFilterAction(QAction *action, const QList &kinds) +MemcheckErrorView *MemcheckTool::ensurePaneErrorView() { - action->setCheckable(true); - QVariantList data; - foreach (int kind, kinds) - data << kind; - action->setData(data); + 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(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; } -void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/) +QWidget *MemcheckTool::createPaneToolBarWidget() { - AnalyzerManager *am = AnalyzerManager::instance(); - - m_errorView = new MemcheckErrorView; - m_errorView->setFrameStyle(QFrame::NoFrame); - m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false); - m_errorModel = new ErrorListModel(m_errorView); - m_frameFinder = new FrameFinder; - m_errorModel->setRelevantFrameFinder(QSharedPointer(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"); - - am->createDockWidget(this, tr("Memory Errors"), m_errorView, Qt::BottomDockWidgetArea); - + QWidget *toolbarWidget = new QWidget; + toolbarWidget->setObjectName(QLatin1String("MemCheckToolBarWidget")); QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(0); - - { // clear / next / prev - QToolButton *button = 0; - - m_clearAction = new QAction(this); - m_clearAction->setIcon(QIcon(Core::Constants::ICON_CLEAN_PANE)); - m_clearAction->setText(tr("Clear")); - connect(m_clearAction, SIGNAL(triggered()), this, SLOT(slotClear())); - button = new QToolButton; - button->setDefaultAction(m_clearAction); - layout->addWidget(button); - - m_prevAction = new QAction(this); - m_prevAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PREV))); - m_prevAction->setText(tr("Previous Item")); - connect(m_prevAction, SIGNAL(triggered()), this, SLOT(slotPrev())); - button = new QToolButton; - button->setDefaultAction(m_prevAction); - layout->addWidget(button); - - m_nextAction = new QAction(this); - m_nextAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_NEXT))); - m_nextAction->setText(tr("Next Item")); - connect(m_nextAction, SIGNAL(triggered()), this, SLOT(slotNext())); - button = new QToolButton; - button->setDefaultAction(m_nextAction); - layout->addWidget(button); - } - { // filter 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); - - QAction *a = filterMenu->addAction(tr("Definite Memory Leaks")); - initKindFilterAction(a, QList() << Leak_DefinitelyLost << Leak_IndirectlyLost); - m_errorFilterActions << a; - - a = filterMenu->addAction(tr("Possible Memory Leaks")); - initKindFilterAction(a, QList() << Leak_PossiblyLost << Leak_StillReachable); - m_errorFilterActions << a; - - a = filterMenu->addAction(tr("Use of Uninitialized Memory")); - initKindFilterAction(a, QList() << InvalidRead << InvalidWrite << InvalidJump << Overlap - << InvalidMemPool << UninitCondition << UninitValue - << SyscallParam << ClientCheck); - m_errorFilterActions << a; - - a = filterMenu->addAction(tr("Invalid Frees")); - initKindFilterAction(a, QList() << InvalidFree << MismatchedFree); - m_errorFilterActions << a; - + foreach (QAction *filterAction, m_errorFilterActions) + filterMenu->addAction(filterAction); filterMenu->addSeparator(); - - m_filterProjectAction = filterMenu->addAction(tr("External Errors")); - m_filterProjectAction->setToolTip(tr("Show issues originating outside currently opened projects.")); - m_filterProjectAction->setCheckable(true); - - m_suppressionSeparator = filterMenu->addSeparator(); - m_suppressionSeparator->setText(tr("Suppressions")); - m_suppressionSeparator->setToolTip(tr("These suppression files where used in the last memory analyzer run.")); - + filterMenu->addAction(m_filterProjectAction); + filterMenu->addAction(m_suppressionSeparator); connect(filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter())); filterButton->setMenu(filterMenu); layout->addWidget(filterButton); - } - layout->addStretch(); - QWidget *toolbar = new QWidget; - toolbar->setLayout(layout); - am->setToolbar(this, toolbar); + toolbarWidget->setLayout(layout); + return toolbarWidget; +} +void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/) +{ + ensurePaneErrorView(); // register shortcuts - Core::ActionManager *actionManager = Core::ICore::instance()->actionManager(); - const Core::Context analyzeContext(Constants::C_ANALYZEMODE); - - Core::Command *cmd; - - cmd = actionManager->registerAction(m_prevAction, "Analyzer.MemcheckTool.previtem", analyzeContext); - cmd->setDefaultKeySequence(QKeySequence("Shift+F10")); - - cmd = actionManager->registerAction(m_nextAction, "Analyzer.MemcheckTool.nextitem", analyzeContext); - cmd->setDefaultKeySequence(QKeySequence("F10")); - maybeActiveRunConfigurationChanged(); } @@ -454,7 +435,7 @@ IAnalyzerEngine *MemcheckTool::createEngine(ProjectExplorer::RunConfiguration *r void MemcheckTool::engineStarting(const IAnalyzerEngine *engine) { - slotClear(); + clearErrorView(); const QString dir = engine->runConfiguration()->target()->project()->projectDirectory(); const MemcheckEngine *mEngine = dynamic_cast(engine); @@ -463,7 +444,7 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine) m_errorView->setDefaultSuppressionFile(dir + QDir::separator() + name + QLatin1String(".supp")); - QMenu *menu = qobject_cast(m_suppressionSeparator->parentWidget()); + QMenu *menu = filterMenu(); QTC_ASSERT(menu, return); foreach(const QString &file, mEngine->suppressionFiles()) { QAction *action = menu->addAction(QFileInfo(file).fileName()); @@ -475,6 +456,15 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine) } } +QMenu *MemcheckTool::filterMenu() const +{ + QTC_ASSERT(m_suppressionSeparator, return 0; ) + foreach (QWidget *w, m_suppressionSeparator->associatedWidgets()) + if (QMenu *menu = qobject_cast(w)) + return menu; + return 0; +} + void MemcheckTool::suppressionActionTriggered() { QAction *action = qobject_cast(sender()); @@ -495,48 +485,13 @@ void MemcheckTool::internalParserError(const QString &errorString) QMessageBox::critical(m_errorView, tr("Internal Error"), tr("Error occurred parsing valgrind output: %1").arg(errorString)); } -void MemcheckTool::slotNext() -{ - QModelIndex current = m_errorView->selectionModel()->currentIndex(); - if (!current.isValid()) { - if (!m_errorView->model()->rowCount()) - return; - - current = m_errorView->model()->index(0, 0); - } else if (current.row() < m_errorView->model()->rowCount(current.parent()) - 1) { - current = m_errorView->model()->index(current.row() + 1, 0); - } else { - return; - } - - m_errorView->selectionModel()->setCurrentIndex(current, QItemSelectionModel::ClearAndSelect); - m_errorView->scrollTo(current); -} - -void MemcheckTool::slotPrev() -{ - QModelIndex current = m_errorView->selectionModel()->currentIndex(); - if (!current.isValid()) { - if (!m_errorView->model()->rowCount()) - return; - current = m_errorView->model()->index(m_errorView->model()->rowCount() - 1, 0); - } else if (current.row() > 0) { - current = m_errorView->model()->index(current.row() - 1, 0); - } else { - return; - } - - m_errorView->selectionModel()->setCurrentIndex(current, QItemSelectionModel::ClearAndSelect); - m_errorView->scrollTo(current); -} - -void MemcheckTool::slotClear() +void MemcheckTool::clearErrorView() { m_errorModel->clear(); qDeleteAll(m_suppressionActions); m_suppressionActions.clear(); - QTC_ASSERT(m_suppressionSeparator->parentWidget()->actions().last() == m_suppressionSeparator, qt_noop()); + QTC_ASSERT(filterMenu()->actions().last() == m_suppressionSeparator, qt_noop()); } void MemcheckTool::updateErrorFilter() @@ -560,3 +515,13 @@ void MemcheckTool::updateErrorFilter() } memcheckSettings->setVisibleErrorKinds(errorKinds); } + +IAnalyzerOutputPaneAdapter *MemcheckTool::outputPaneAdapter() +{ + if (!m_outputPaneAdapter) + m_outputPaneAdapter = new MemCheckOutputPaneAdapter(this); + return m_outputPaneAdapter; +} + +} // namespace Internal +} // namespace Analyzer diff --git a/src/plugins/memcheck/memchecktool.h b/src/plugins/memcheck/memchecktool.h index 1aa26068fe..e71cb83ed8 100644 --- a/src/plugins/memcheck/memchecktool.h +++ b/src/plugins/memcheck/memchecktool.h @@ -48,6 +48,7 @@ class QModelIndex; class QAction; class QSpinBox; class QCheckBox; +class QMenu; QT_END_NAMESPACE namespace Valgrind { @@ -58,11 +59,9 @@ class Error; } namespace Analyzer { - class AnalyzerSettings; - namespace Internal { - +class MemCheckOutputPaneAdapter; class MemcheckErrorView; class FrameFinder; @@ -95,8 +94,14 @@ public: void initialize(ExtensionSystem::IPlugin *plugin); + virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter(); IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration); + // For the output pane adapter. + MemcheckErrorView *ensurePaneErrorView(); + QWidget *createPaneToolBarWidget(); + void clearErrorView(); + private slots: void settingsDestroyed(QObject *settings); void maybeActiveRunConfigurationChanged(); @@ -104,13 +109,9 @@ private slots: void engineStarting(const IAnalyzerEngine *engine); void parserError(const Valgrind::XmlProtocol::Error &error); void internalParserError(const QString &errorString); - - void slotNext(); - void slotPrev(); - void slotClear(); - void updateErrorFilter(); void suppressionActionTriggered(); + QMenu *filterMenu() const; private: AnalyzerSettings *m_settings; @@ -120,13 +121,11 @@ private: MemcheckErrorFilterProxyModel *m_errorProxyModel; MemcheckErrorView *m_errorView; - QAction *m_prevAction; - QAction *m_nextAction; - QAction *m_clearAction; QList m_errorFilterActions; QAction *m_filterProjectAction; QList m_suppressionActions; QAction *m_suppressionSeparator; + MemCheckOutputPaneAdapter *m_outputPaneAdapter; }; } // namespace Internal -- 2.11.0