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
This commit is contained in:
Friedemann Kleint
2011-03-10 16:11:20 +01:00
committed by con
parent 3ab75ac979
commit 11311b6e94
11 changed files with 837 additions and 254 deletions

View File

@@ -18,7 +18,8 @@ SOURCES += \
analyzermanager.cpp \ analyzermanager.cpp \
analyzersettings.cpp \ analyzersettings.cpp \
analyzeroptionspage.cpp \ analyzeroptionspage.cpp \
analyzerrunconfigwidget.cpp analyzerrunconfigwidget.cpp \
analyzeroutputpane.cpp
HEADERS += \ HEADERS += \
ianalyzerengine.h \ ianalyzerengine.h \
@@ -30,7 +31,8 @@ HEADERS += \
analyzermanager.h \ analyzermanager.h \
analyzersettings.h \ analyzersettings.h \
analyzeroptionspage.h \ analyzeroptionspage.h \
analyzerrunconfigwidget.h analyzerrunconfigwidget.h \
analyzeroutputpane.h
RESOURCES += \ RESOURCES += \
analyzerbase.qrc analyzerbase.qrc

View File

@@ -40,6 +40,7 @@
#include "analyzerplugin.h" #include "analyzerplugin.h"
#include "analyzerruncontrol.h" #include "analyzerruncontrol.h"
#include "analyzeroptionspage.h" #include "analyzeroptionspage.h"
#include "analyzeroutputpane.h"
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <coreplugin/findplaceholder.h> #include <coreplugin/findplaceholder.h>
@@ -94,6 +95,11 @@ using namespace Core;
using namespace Analyzer; using namespace Analyzer;
using namespace Analyzer::Internal; 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 Analyzer {
namespace Internal { namespace Internal {
@@ -183,14 +189,15 @@ public:
void delayedInit(); void delayedInit();
void setupActions(); void setupActions();
QWidget *createContents(); QWidget *createModeContents();
QWidget *createMainWindow(); QWidget *createModeMainWindow();
void addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, QDockWidget *dockWidget); void addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, QDockWidget *dockWidget);
void startTool(); void startTool();
AnalyzerManager *q; AnalyzerManager *q;
AnalyzerMode *m_mode; AnalyzerMode *m_mode;
AnalyzerOutputPane *m_outputpane;
AnalyzerRunControlFactory *m_runControlFactory; AnalyzerRunControlFactory *m_runControlFactory;
ProjectExplorer::RunControl *m_currentRunControl; ProjectExplorer::RunControl *m_currentRunControl;
Utils::FancyMainWindow *m_mainWindow; Utils::FancyMainWindow *m_mainWindow;
@@ -200,14 +207,11 @@ public:
QAction *m_stopAction; QAction *m_stopAction;
QMenu *m_menu; QMenu *m_menu;
QComboBox *m_toolBox; QComboBox *m_toolBox;
Utils::StyledSeparator *m_toolBoxSeparator;
ActionContainer *m_viewsMenu; ActionContainer *m_viewsMenu;
typedef QPair<Qt::DockWidgetArea, QDockWidget*> ToolWidgetPair; typedef QPair<Qt::DockWidgetArea, QDockWidget*> ToolWidgetPair;
typedef QList<ToolWidgetPair> ToolWidgetPairList; typedef QList<ToolWidgetPair> ToolWidgetPairList;
QMap<IAnalyzerTool*, ToolWidgetPairList> m_toolWidgets; QMap<IAnalyzerTool*, ToolWidgetPairList> m_toolWidgets;
DockWidgetEventFilter *m_resizeEventFilter; DockWidgetEventFilter *m_resizeEventFilter;
QMap<IAnalyzerTool*, QWidget*> m_toolToolbarWidgets;
QStackedWidget *m_toolbarStackedWidget;
QMap<IAnalyzerTool *, QSettings *> m_defaultSettings; QMap<IAnalyzerTool *, QSettings *> m_defaultSettings;
// list of dock widgets to prevent memory leak // list of dock widgets to prevent memory leak
@@ -220,6 +224,7 @@ public:
AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq): AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager *qq):
q(qq), q(qq),
m_mode(0), m_mode(0),
m_outputpane(0),
m_runControlFactory(0), m_runControlFactory(0),
m_currentRunControl(0), m_currentRunControl(0),
m_mainWindow(0), m_mainWindow(0),
@@ -227,18 +232,20 @@ AnalyzerManager::AnalyzerManagerPrivate::AnalyzerManagerPrivate(AnalyzerManager
m_startAction(0), m_startAction(0),
m_stopAction(0), m_stopAction(0),
m_menu(0), m_menu(0),
m_toolBox(0), m_toolBox(new QComboBox),
m_toolBoxSeparator(0),
m_viewsMenu(0), m_viewsMenu(0),
m_resizeEventFilter(new DockWidgetEventFilter(qq)), m_resizeEventFilter(new DockWidgetEventFilter(qq)),
m_toolbarStackedWidget(0),
m_initialized(false) m_initialized(false)
{ {
m_toolBox->setObjectName(QLatin1String("AnalyzerManagerToolBox"));
m_runControlFactory = new AnalyzerRunControlFactory(); m_runControlFactory = new AnalyzerRunControlFactory();
AnalyzerPlugin::instance()->addAutoReleasedObject(m_runControlFactory); AnalyzerPlugin::instance()->addAutoReleasedObject(m_runControlFactory);
connect(m_runControlFactory, SIGNAL(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)), connect(m_runControlFactory, SIGNAL(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)),
q, SLOT(runControlCreated(Analyzer::Internal::AnalyzerRunControl *))); q, SLOT(runControlCreated(Analyzer::Internal::AnalyzerRunControl *)));
connect(m_toolBox, SIGNAL(currentIndexChanged(int)),
q, SLOT(toolSelected(int)));
setupActions(); setupActions();
} }
@@ -295,17 +302,20 @@ void AnalyzerManager::AnalyzerManagerPrivate::delayedInit()
if (m_initialized) if (m_initialized)
return; return;
m_mode = new AnalyzerMode(q); if (useAnalyzeMode) {
m_mode->setWidget(createContents()); m_mode = new AnalyzerMode(q);
AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode); m_mode->setWidget(createModeContents());
AnalyzerPlugin::instance()->addAutoReleasedObject(m_mode);
}
m_initialized = true; m_initialized = true;
} }
QWidget *AnalyzerManager::AnalyzerManagerPrivate::createContents() QWidget *AnalyzerManager::AnalyzerManagerPrivate::createModeContents()
{ {
QTC_ASSERT(useAnalyzeMode, return 0; )
// right-side window with editor, output etc. // right-side window with editor, output etc.
MiniSplitter *mainWindowSplitter = new MiniSplitter; MiniSplitter *mainWindowSplitter = new MiniSplitter;
mainWindowSplitter->addWidget(createMainWindow()); mainWindowSplitter->addWidget(createModeMainWindow());
mainWindowSplitter->addWidget(new OutputPanePlaceHolder(m_mode, mainWindowSplitter)); mainWindowSplitter->addWidget(new OutputPanePlaceHolder(m_mode, mainWindowSplitter));
mainWindowSplitter->setStretchFactor(0, 10); mainWindowSplitter->setStretchFactor(0, 10);
mainWindowSplitter->setStretchFactor(1, 0); mainWindowSplitter->setStretchFactor(1, 0);
@@ -327,9 +337,19 @@ static QToolButton *toolButton(QAction *action)
return button; 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 = new Utils::FancyMainWindow();
m_mainWindow->setObjectName(QLatin1String("AnalyzerManagerMainWindow"));
connect(m_mainWindow, SIGNAL(resetLayout()), connect(m_mainWindow, SIGNAL(resetLayout()),
q, SLOT(resetLayout())); q, SLOT(resetLayout()));
m_mainWindow->setDocumentMode(true); m_mainWindow->setDocumentMode(true);
@@ -352,35 +372,6 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createMainWindow()
documentAndRightPane->setStretchFactor(0, 1); documentAndRightPane->setStretchFactor(0, 1);
documentAndRightPane->setStretchFactor(1, 0); 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; QWidget *centralWidget = new QWidget;
m_mainWindow->setCentralWidget(centralWidget); m_mainWindow->setCentralWidget(centralWidget);
@@ -399,7 +390,7 @@ QWidget *AnalyzerManager::AnalyzerManagerPrivate::createMainWindow()
void AnalyzerManager::AnalyzerManagerPrivate::addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area, void AnalyzerManager::AnalyzerManagerPrivate::addDock(IAnalyzerTool *tool, Qt::DockWidgetArea area,
QDockWidget *dockWidget) QDockWidget *dockWidget)
{ {
QTC_ASSERT(tool == q->currentTool(), return) QTC_ASSERT(useAnalyzeMode && tool == q->currentTool(), return)
dockWidget->setParent(m_mainWindow); dockWidget->setParent(m_mainWindow);
m_mainWindow->addDockWidget(area, dockWidget); m_mainWindow->addDockWidget(area, dockWidget);
@@ -448,10 +439,11 @@ bool buildTypeAcceppted(IAnalyzerTool::ToolMode toolMode,
void AnalyzerManager::AnalyzerManagerPrivate::startTool() void AnalyzerManager::AnalyzerManagerPrivate::startTool()
{ {
QTC_ASSERT(!m_currentRunControl, return); QTC_ASSERT(!m_currentRunControl && q->currentTool(), return);
// make sure our mode is shown // 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(); ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
@@ -520,14 +512,16 @@ void AnalyzerManager::AnalyzerManagerPrivate::startTool()
// AnalyzerManager //////////////////////////////////////////////////// // AnalyzerManager ////////////////////////////////////////////////////
AnalyzerManager *AnalyzerManager::m_instance = 0; AnalyzerManager *AnalyzerManager::m_instance = 0;
AnalyzerManager::AnalyzerManager(QObject *parent) : AnalyzerManager::AnalyzerManager(Internal::AnalyzerOutputPane *op, QObject *parent) :
QObject(parent), QObject(parent),
d(new AnalyzerManagerPrivate(this)) d(new AnalyzerManagerPrivate(this))
{ {
m_instance = this; m_instance = this;
d->m_outputpane = op;
connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), if (useAnalyzeMode)
this, SLOT(modeChanged(Core::IMode*))); connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
this, SLOT(modeChanged(Core::IMode*)));
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
connect(pe, SIGNAL(updateRunActions()), connect(pe, SIGNAL(updateRunActions()),
this, SLOT(updateRunActions())); this, SLOT(updateRunActions()));
@@ -545,7 +539,8 @@ bool AnalyzerManager::isInitialized() const
void AnalyzerManager::shutdown() void AnalyzerManager::shutdown()
{ {
saveToolSettings(currentTool()); if (useAnalyzeMode)
saveToolSettings(currentTool());
} }
AnalyzerManager * AnalyzerManager::instance() AnalyzerManager * AnalyzerManager::instance()
@@ -555,6 +550,7 @@ AnalyzerManager * AnalyzerManager::instance()
void AnalyzerManager::modeChanged(IMode *mode) void AnalyzerManager::modeChanged(IMode *mode)
{ {
QTC_ASSERT(d->m_mainWindow, return; )
const bool makeVisible = mode->id() == Constants::MODE_ANALYZE; const bool makeVisible = mode->id() == Constants::MODE_ANALYZE;
if (!makeVisible) if (!makeVisible)
return; return;
@@ -576,7 +572,7 @@ void AnalyzerManager::toolSelected(int idx)
selectingTool = true; selectingTool = true;
IAnalyzerTool *oldTool = currentTool(); IAnalyzerTool *oldTool = currentTool();
if (oldTool) { if (useAnalyzeMode && oldTool != 0) {
saveToolSettings(oldTool); saveToolSettings(oldTool);
ActionManager *am = ICore::instance()->actionManager(); ActionManager *am = ICore::instance()->actionManager();
@@ -599,13 +595,13 @@ void AnalyzerManager::toolSelected(int idx)
IAnalyzerTool *newTool = currentTool(); IAnalyzerTool *newTool = currentTool();
if (QWidget *toolbarWidget = d->m_toolToolbarWidgets.value(newTool)) if (useAnalyzeMode) {
d->m_toolbarStackedWidget->setCurrentWidget(toolbarWidget); foreach (const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) {
d->addDock(newTool, widget.first, widget.second);
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; selectingTool = false;
} }
@@ -628,33 +624,23 @@ void AnalyzerManager::addTool(IAnalyzerTool *tool)
d->m_toolGroup->setVisible(d->m_toolGroup->actions().count() > 1); d->m_toolGroup->setVisible(d->m_toolGroup->actions().count() > 1);
d->m_tools.append(tool); d->m_tools.append(tool);
d->m_toolBox->addItem(tool->displayName()); d->m_toolBox->addItem(tool->displayName());
d->m_toolBox->setVisible(d->m_toolBox->count() > 1); d->m_toolBox->setEnabled(d->m_toolBox->count() > 1);
d->m_toolBoxSeparator->setVisible(d->m_toolBox->isVisible());
if (currentTool() != tool) if (currentTool() != tool)
selectTool(tool); // the first tool gets selected automatically due to signal emission from toolbox selectTool(tool); // the first tool gets selected automatically due to signal emission from toolbox
tool->initialize(plugin); tool->initialize(plugin);
QSettings *defaultSettings = new QSettings(this); if (useAnalyzeMode) {
d->m_defaultSettings[tool] = defaultSettings; QSettings *defaultSettings = new QSettings(this);
d->m_mainWindow->saveSettings(defaultSettings); d->m_defaultSettings[tool] = defaultSettings;
d->m_mainWindow->saveSettings(defaultSettings);
loadToolSettings(tool); 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);
} }
QDockWidget *AnalyzerManager::createDockWidget(IAnalyzerTool *tool, const QString &title, QDockWidget *AnalyzerManager::createDockWidget(IAnalyzerTool *tool, const QString &title,
QWidget *widget, Qt::DockWidgetArea area) 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); QDockWidget *dockWidget = d->m_mainWindow->addDockForWidget(widget);
d->m_dockWidgets << AnalyzerManagerPrivate::DockPtr(dockWidget); d->m_dockWidgets << AnalyzerManagerPrivate::DockPtr(dockWidget);
@@ -727,6 +713,7 @@ void AnalyzerManager::resetLayout()
void AnalyzerManager::loadToolSettings(IAnalyzerTool *tool) void AnalyzerManager::loadToolSettings(IAnalyzerTool *tool)
{ {
QTC_ASSERT(d->m_mainWindow, return; )
QSettings *settings = Core::ICore::instance()->settings(); QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id()); settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id());
if (settings->value("ToolSettingsSaved", false).toBool()) { if (settings->value("ToolSettingsSaved", false).toBool()) {
@@ -739,6 +726,7 @@ void AnalyzerManager::saveToolSettings(IAnalyzerTool *tool)
{ {
if (!tool) if (!tool)
return; // no active tool, do nothing return; // no active tool, do nothing
QTC_ASSERT(d->m_mainWindow, return ; )
QSettings *settings = Core::ICore::instance()->settings(); QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id()); settings->beginGroup(QLatin1String("AnalyzerViewSettings_") + tool->id());
@@ -751,7 +739,8 @@ void AnalyzerManager::updateRunActions()
{ {
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
ProjectExplorer::Project *project = pe->startupProject(); 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); d->m_startAction->setEnabled(startEnabled);
} }

View File

@@ -57,6 +57,7 @@ namespace Analyzer {
class IAnalyzerTool; class IAnalyzerTool;
namespace Internal { namespace Internal {
class AnalyzerRunControl; class AnalyzerRunControl;
class AnalyzerOutputPane;
} // namespace Internal } // namespace Internal
class ANALYZER_EXPORT AnalyzerManager : public QObject class ANALYZER_EXPORT AnalyzerManager : public QObject
@@ -64,7 +65,7 @@ class ANALYZER_EXPORT AnalyzerManager : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AnalyzerManager(QObject *parent = 0); explicit AnalyzerManager(Internal::AnalyzerOutputPane *op, QObject *parent = 0);
~AnalyzerManager(); ~AnalyzerManager();
static AnalyzerManager *instance(); static AnalyzerManager *instance();
@@ -83,19 +84,12 @@ public:
QDockWidget *createDockWidget(IAnalyzerTool *tool, const QString &title, QWidget *widget, QDockWidget *createDockWidget(IAnalyzerTool *tool, const QString &title, QWidget *widget,
Qt::DockWidgetArea area = Qt::TopDockWidgetArea); 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; Utils::FancyMainWindow *mainWindow() const;
void selectTool(IAnalyzerTool *tool); void selectTool(IAnalyzerTool *tool);
QList<QWidget *> outputPaneToolBarWidgets() const;
private slots: private slots:
void startTool(); void startTool();
void stopTool(); void stopTool();

View File

@@ -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 <utils/qtcassert.h>
#include <utils/styledbar.h>
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtGui/QWidget>
#include <QtGui/QStackedLayout>
#include <QtGui/QLabel>
#include <QtGui/QStackedWidget>
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<IAnalyzerOutputPaneAdapter *>(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<IAnalyzerOutputPaneAdapter *>(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

View File

@@ -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 <coreplugin/ioutputpane.h>
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<QWidget*> 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<IAnalyzerOutputPaneAdapter *> m_adapters;
QStackedWidget *m_toolbarStackedWidget;
Utils::StyledSeparator *m_toolBarSeparator;
};
} // namespace Internal
} // namespace Analyzer
#endif // ANALYZEROUTPUTPANE_H

View File

@@ -36,6 +36,7 @@
#include "analyzerplugin.h" #include "analyzerplugin.h"
#include "analyzerconstants.h" #include "analyzerconstants.h"
#include "analyzermanager.h" #include "analyzermanager.h"
#include "analyzeroutputpane.h"
#include <coreplugin/imode.h> #include <coreplugin/imode.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
@@ -76,7 +77,9 @@ void AnalyzerPlugin::AnalyzerPluginPrivate::initialize(const QStringList &argume
{ {
Q_UNUSED(arguments) Q_UNUSED(arguments)
Q_UNUSED(errorString) Q_UNUSED(errorString)
m_manager = new AnalyzerManager(q); AnalyzerOutputPane *outputPane = new AnalyzerOutputPane;
q->addAutoReleasedObject(outputPane);
m_manager = new AnalyzerManager(outputPane, q);
} }

View File

@@ -34,14 +34,158 @@
**************************************************************************/ **************************************************************************/
#include "ianalyzertool.h" #include "ianalyzertool.h"
#include "analyzeroutputpane.h"
using namespace Analyzer; #include <utils/qtcassert.h>
#include <QtGui/QAbstractItemView>
#include <QtGui/QItemSelectionModel>
#include <QtCore/QAbstractItemModel>
#include <QtCore/QModelIndex>
namespace Analyzer {
IAnalyzerTool::IAnalyzerTool(QObject *parent) : IAnalyzerTool::IAnalyzerTool(QObject *parent) :
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() QString IAnalyzerTool::modeString()
{ {
switch (mode()) { switch (mode()) {
@@ -54,3 +198,10 @@ QString IAnalyzerTool::modeString()
} }
return QString(); return QString();
} }
IAnalyzerOutputPaneAdapter *IAnalyzerTool::outputPaneAdapter()
{
return 0;
}
} // namespace Analyzer

View File

@@ -40,6 +40,9 @@
#include <QtCore/QObject> #include <QtCore/QObject>
QT_FORWARD_DECLARE_CLASS(QAbstractItemView)
QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
namespace ProjectExplorer { namespace ProjectExplorer {
class RunConfiguration; class RunConfiguration;
} }
@@ -49,9 +52,66 @@ class IPlugin;
} }
namespace Analyzer { namespace Analyzer {
class IAnalyzerEngine; 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 class ANALYZER_EXPORT IAnalyzerTool : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -78,6 +138,8 @@ public:
virtual void initialize(ExtensionSystem::IPlugin *plugin) = 0; virtual void initialize(ExtensionSystem::IPlugin *plugin) = 0;
virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter();
virtual IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration) = 0; virtual IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration) = 0;
}; };

View File

@@ -63,7 +63,6 @@ bool MemcheckPlugin::initialize(const QStringList &/*arguments*/, QString */*err
AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new MemcheckConfigFactory); AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new MemcheckConfigFactory);
AnalyzerManager::instance()->addTool(new MemcheckTool(this)); AnalyzerManager::instance()->addTool(new MemcheckTool(this));
return true; return true;
} }

View File

@@ -91,10 +91,29 @@
#include <QtGui/QCheckBox> #include <QtGui/QCheckBox>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
using namespace Analyzer;
using namespace Analyzer::Internal;
using namespace Valgrind::XmlProtocol; 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) MemcheckErrorFilterProxyModel::MemcheckErrorFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent), : QSortFilterProxyModel(parent),
m_filterExternalIssues(false) m_filterExternalIssues(false)
@@ -174,19 +193,52 @@ bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModel
return true; return true;
} }
static void initKindFilterAction(QAction *action, const QList<int> &kinds)
{
action->setCheckable(true);
QVariantList data;
foreach (int kind, kinds)
data << kind;
action->setData(data);
}
MemcheckTool::MemcheckTool(QObject *parent) : MemcheckTool::MemcheckTool(QObject *parent) :
Analyzer::IAnalyzerTool(parent), Analyzer::IAnalyzerTool(parent),
m_settings(0), m_settings(0),
m_errorModel(0), m_errorModel(0),
m_errorProxyModel(0), m_errorProxyModel(0),
m_errorView(0), m_errorView(0),
m_prevAction(0), m_filterProjectAction(new QAction(tr("External Errors"), this)),
m_nextAction(0), m_suppressionSeparator(new QAction(tr("Suppressions"), this)),
m_clearAction(0), m_outputPaneAdapter(0)
m_filterProjectAction(0)
{ {
setObjectName(QLatin1String("MemcheckTool"));
connect(ProjectExplorer::ProjectExplorerPlugin::instance(), connect(ProjectExplorer::ProjectExplorerPlugin::instance(),
SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged())); SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged()));
QAction *a = new QAction(tr("Definite Memory Leaks"), this);
initKindFilterAction(a, QList<int>() << Leak_DefinitelyLost << Leak_IndirectlyLost);
m_errorFilterActions << a;
a = new QAction(tr("Possible Memory Leaks"), this);
initKindFilterAction(a, QList<int>() << Leak_PossiblyLost << Leak_StillReachable);
m_errorFilterActions << 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;
a = new QAction(tr("Invalid Frees"), 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 where used in the last memory analyzer run."));
} }
void MemcheckTool::settingsDestroyed(QObject *settings) void MemcheckTool::settingsDestroyed(QObject *settings)
@@ -267,8 +319,6 @@ IAnalyzerTool::ToolMode MemcheckTool::mode() const
return DebugMode; return DebugMode;
} }
namespace Analyzer {
namespace Internal {
class FrameFinder : public ErrorListModel::RelevantFrameFinder { class FrameFinder : public ErrorListModel::RelevantFrameFinder {
public: public:
Frame findRelevant(const Error &error) const { Frame findRelevant(const Error &error) const {
@@ -310,130 +360,61 @@ public:
private: private:
QStringList m_projectFiles; QStringList m_projectFiles;
}; };
}
}
static void initKindFilterAction(QAction *action, const QList<int> &kinds) MemcheckErrorView *MemcheckTool::ensurePaneErrorView()
{ {
action->setCheckable(true); if (!m_errorView) {
QVariantList data; m_errorView = new MemcheckErrorView;
foreach (int kind, kinds) m_errorView->setObjectName(QLatin1String("MemcheckErrorView"));
data << kind; m_errorView->setFrameStyle(QFrame::NoFrame);
action->setData(data); 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;
} }
void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/) QWidget *MemcheckTool::createPaneToolBarWidget()
{ {
AnalyzerManager *am = AnalyzerManager::instance(); QWidget *toolbarWidget = new QWidget;
toolbarWidget->setObjectName(QLatin1String("MemCheckToolBarWidget"));
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<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");
am->createDockWidget(this, tr("Memory Errors"), m_errorView, Qt::BottomDockWidgetArea);
QHBoxLayout *layout = new QHBoxLayout; QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0); layout->setMargin(0);
layout->setSpacing(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 // filter
QToolButton *filterButton = new QToolButton; QToolButton *filterButton = new QToolButton;
filterButton->setIcon(QIcon(Core::Constants::ICON_FILTER)); filterButton->setIcon(QIcon(Core::Constants::ICON_FILTER));
filterButton->setText(tr("Error Filter")); filterButton->setText(tr("Error Filter"));
filterButton->setPopupMode(QToolButton::InstantPopup); filterButton->setPopupMode(QToolButton::InstantPopup);
QMenu *filterMenu = new QMenu(filterButton); QMenu *filterMenu = new QMenu(filterButton);
foreach (QAction *filterAction, m_errorFilterActions)
QAction *a = filterMenu->addAction(tr("Definite Memory Leaks")); filterMenu->addAction(filterAction);
initKindFilterAction(a, QList<int>() << Leak_DefinitelyLost << Leak_IndirectlyLost);
m_errorFilterActions << a;
a = filterMenu->addAction(tr("Possible Memory Leaks"));
initKindFilterAction(a, QList<int>() << Leak_PossiblyLost << Leak_StillReachable);
m_errorFilterActions << a;
a = filterMenu->addAction(tr("Use of Uninitialized Memory"));
initKindFilterAction(a, QList<int>() << InvalidRead << InvalidWrite << InvalidJump << Overlap
<< InvalidMemPool << UninitCondition << UninitValue
<< SyscallParam << ClientCheck);
m_errorFilterActions << a;
a = filterMenu->addAction(tr("Invalid Frees"));
initKindFilterAction(a, QList<int>() << InvalidFree << MismatchedFree);
m_errorFilterActions << a;
filterMenu->addSeparator(); filterMenu->addSeparator();
filterMenu->addAction(m_filterProjectAction);
m_filterProjectAction = filterMenu->addAction(tr("External Errors")); filterMenu->addAction(m_suppressionSeparator);
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."));
connect(filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter())); connect(filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter()));
filterButton->setMenu(filterMenu); filterButton->setMenu(filterMenu);
layout->addWidget(filterButton); layout->addWidget(filterButton);
}
layout->addStretch(); layout->addStretch();
QWidget *toolbar = new QWidget; toolbarWidget->setLayout(layout);
toolbar->setLayout(layout); return toolbarWidget;
am->setToolbar(this, toolbar); }
void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
{
ensurePaneErrorView();
// register shortcuts // 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(); maybeActiveRunConfigurationChanged();
} }
@@ -454,7 +435,7 @@ IAnalyzerEngine *MemcheckTool::createEngine(ProjectExplorer::RunConfiguration *r
void MemcheckTool::engineStarting(const IAnalyzerEngine *engine) void MemcheckTool::engineStarting(const IAnalyzerEngine *engine)
{ {
slotClear(); clearErrorView();
const QString dir = engine->runConfiguration()->target()->project()->projectDirectory(); const QString dir = engine->runConfiguration()->target()->project()->projectDirectory();
const MemcheckEngine *mEngine = dynamic_cast<const MemcheckEngine*>(engine); const MemcheckEngine *mEngine = dynamic_cast<const MemcheckEngine*>(engine);
@@ -463,7 +444,7 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine)
m_errorView->setDefaultSuppressionFile(dir + QDir::separator() + name + QLatin1String(".supp")); m_errorView->setDefaultSuppressionFile(dir + QDir::separator() + name + QLatin1String(".supp"));
QMenu *menu = qobject_cast<QMenu*>(m_suppressionSeparator->parentWidget()); QMenu *menu = filterMenu();
QTC_ASSERT(menu, return); QTC_ASSERT(menu, return);
foreach(const QString &file, mEngine->suppressionFiles()) { foreach(const QString &file, mEngine->suppressionFiles()) {
QAction *action = menu->addAction(QFileInfo(file).fileName()); 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<QMenu*>(w))
return menu;
return 0;
}
void MemcheckTool::suppressionActionTriggered() void MemcheckTool::suppressionActionTriggered()
{ {
QAction *action = qobject_cast<QAction*>(sender()); QAction *action = qobject_cast<QAction*>(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)); QMessageBox::critical(m_errorView, tr("Internal Error"), tr("Error occurred parsing valgrind output: %1").arg(errorString));
} }
void MemcheckTool::slotNext() void MemcheckTool::clearErrorView()
{
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()
{ {
m_errorModel->clear(); m_errorModel->clear();
qDeleteAll(m_suppressionActions); qDeleteAll(m_suppressionActions);
m_suppressionActions.clear(); 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() void MemcheckTool::updateErrorFilter()
@@ -560,3 +515,13 @@ void MemcheckTool::updateErrorFilter()
} }
memcheckSettings->setVisibleErrorKinds(errorKinds); memcheckSettings->setVisibleErrorKinds(errorKinds);
} }
IAnalyzerOutputPaneAdapter *MemcheckTool::outputPaneAdapter()
{
if (!m_outputPaneAdapter)
m_outputPaneAdapter = new MemCheckOutputPaneAdapter(this);
return m_outputPaneAdapter;
}
} // namespace Internal
} // namespace Analyzer

View File

@@ -48,6 +48,7 @@ class QModelIndex;
class QAction; class QAction;
class QSpinBox; class QSpinBox;
class QCheckBox; class QCheckBox;
class QMenu;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Valgrind { namespace Valgrind {
@@ -58,11 +59,9 @@ class Error;
} }
namespace Analyzer { namespace Analyzer {
class AnalyzerSettings; class AnalyzerSettings;
namespace Internal { namespace Internal {
class MemCheckOutputPaneAdapter;
class MemcheckErrorView; class MemcheckErrorView;
class FrameFinder; class FrameFinder;
@@ -95,8 +94,14 @@ public:
void initialize(ExtensionSystem::IPlugin *plugin); void initialize(ExtensionSystem::IPlugin *plugin);
virtual IAnalyzerOutputPaneAdapter *outputPaneAdapter();
IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration); IAnalyzerEngine *createEngine(ProjectExplorer::RunConfiguration *runConfiguration);
// For the output pane adapter.
MemcheckErrorView *ensurePaneErrorView();
QWidget *createPaneToolBarWidget();
void clearErrorView();
private slots: private slots:
void settingsDestroyed(QObject *settings); void settingsDestroyed(QObject *settings);
void maybeActiveRunConfigurationChanged(); void maybeActiveRunConfigurationChanged();
@@ -104,13 +109,9 @@ private slots:
void engineStarting(const IAnalyzerEngine *engine); void engineStarting(const IAnalyzerEngine *engine);
void parserError(const Valgrind::XmlProtocol::Error &error); void parserError(const Valgrind::XmlProtocol::Error &error);
void internalParserError(const QString &errorString); void internalParserError(const QString &errorString);
void slotNext();
void slotPrev();
void slotClear();
void updateErrorFilter(); void updateErrorFilter();
void suppressionActionTriggered(); void suppressionActionTriggered();
QMenu *filterMenu() const;
private: private:
AnalyzerSettings *m_settings; AnalyzerSettings *m_settings;
@@ -120,13 +121,11 @@ private:
MemcheckErrorFilterProxyModel *m_errorProxyModel; MemcheckErrorFilterProxyModel *m_errorProxyModel;
MemcheckErrorView *m_errorView; MemcheckErrorView *m_errorView;
QAction *m_prevAction;
QAction *m_nextAction;
QAction *m_clearAction;
QList<QAction *> m_errorFilterActions; QList<QAction *> m_errorFilterActions;
QAction *m_filterProjectAction; QAction *m_filterProjectAction;
QList<QAction *> m_suppressionActions; QList<QAction *> m_suppressionActions;
QAction *m_suppressionSeparator; QAction *m_suppressionSeparator;
MemCheckOutputPaneAdapter *m_outputPaneAdapter;
}; };
} // namespace Internal } // namespace Internal