forked from qt-creator/qt-creator
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:
@@ -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
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "analyzerplugin.h"
|
||||
#include "analyzerruncontrol.h"
|
||||
#include "analyzeroptionspage.h"
|
||||
#include "analyzeroutputpane.h"
|
||||
|
||||
#include <coreplugin/actionmanager/command.h>
|
||||
#include <coreplugin/findplaceholder.h>
|
||||
@@ -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<Qt::DockWidgetArea, QDockWidget*> ToolWidgetPair;
|
||||
typedef QList<ToolWidgetPair> ToolWidgetPairList;
|
||||
QMap<IAnalyzerTool*, ToolWidgetPairList> m_toolWidgets;
|
||||
DockWidgetEventFilter *m_resizeEventFilter;
|
||||
QMap<IAnalyzerTool*, QWidget*> m_toolToolbarWidgets;
|
||||
QStackedWidget *m_toolbarStackedWidget;
|
||||
QMap<IAnalyzerTool *, QSettings *> 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;
|
||||
|
||||
if (useAnalyzeMode) {
|
||||
m_mode = new AnalyzerMode(q);
|
||||
m_mode->setWidget(createContents());
|
||||
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,9 +439,10 @@ 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
|
||||
m_outputpane->popup();
|
||||
if (m_mode)
|
||||
ModeManager::instance()->activateMode(m_mode->id());
|
||||
|
||||
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
|
||||
@@ -520,12 +512,14 @@ 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;
|
||||
|
||||
if (useAnalyzeMode)
|
||||
connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
|
||||
this, SLOT(modeChanged(Core::IMode*)));
|
||||
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
|
||||
@@ -545,6 +539,7 @@ bool AnalyzerManager::isInitialized() const
|
||||
|
||||
void AnalyzerManager::shutdown()
|
||||
{
|
||||
if (useAnalyzeMode)
|
||||
saveToolSettings(currentTool());
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
if (useAnalyzeMode) {
|
||||
foreach (const AnalyzerManagerPrivate::ToolWidgetPair &widget, d->m_toolWidgets.value(newTool)) {
|
||||
d->addDock(newTool, widget.first, widget.second);
|
||||
}
|
||||
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);
|
||||
|
||||
if (useAnalyzeMode) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<QWidget *> outputPaneToolBarWidgets() const;
|
||||
|
||||
private slots:
|
||||
void startTool();
|
||||
void stopTool();
|
||||
|
||||
318
src/plugins/analyzerbase/analyzeroutputpane.cpp
Normal file
318
src/plugins/analyzerbase/analyzeroutputpane.cpp
Normal 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
|
||||
101
src/plugins/analyzerbase/analyzeroutputpane.h
Normal file
101
src/plugins/analyzerbase/analyzeroutputpane.h
Normal 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
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "analyzerplugin.h"
|
||||
#include "analyzerconstants.h"
|
||||
#include "analyzermanager.h"
|
||||
#include "analyzeroutputpane.h"
|
||||
|
||||
#include <coreplugin/imode.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,14 +34,158 @@
|
||||
**************************************************************************/
|
||||
|
||||
#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) :
|
||||
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
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,10 +91,29 @@
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
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<int> &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<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)
|
||||
@@ -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,28 +360,17 @@ public:
|
||||
private:
|
||||
QStringList m_projectFiles;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static void initKindFilterAction(QAction *action, const QList<int> &kinds)
|
||||
MemcheckErrorView *MemcheckTool::ensurePaneErrorView()
|
||||
{
|
||||
action->setCheckable(true);
|
||||
QVariantList data;
|
||||
foreach (int kind, kinds)
|
||||
data << kind;
|
||||
action->setData(data);
|
||||
}
|
||||
|
||||
void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
|
||||
{
|
||||
AnalyzerManager *am = AnalyzerManager::instance();
|
||||
|
||||
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 FrameFinder;
|
||||
m_errorModel->setRelevantFrameFinder(QSharedPointer<FrameFinder>(m_frameFinder));
|
||||
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);
|
||||
@@ -342,98 +381,40 @@ void MemcheckTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
|
||||
m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_errorView->setAutoScroll(false);
|
||||
m_errorView->setObjectName("Valgrind.MemcheckTool.ErrorView");
|
||||
}
|
||||
return m_errorView;
|
||||
}
|
||||
|
||||
am->createDockWidget(this, tr("Memory Errors"), m_errorView, Qt::BottomDockWidgetArea);
|
||||
|
||||
QWidget *MemcheckTool::createPaneToolBarWidget()
|
||||
{
|
||||
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<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;
|
||||
|
||||
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<const MemcheckEngine*>(engine);
|
||||
@@ -463,7 +444,7 @@ void MemcheckTool::engineStarting(const IAnalyzerEngine *engine)
|
||||
|
||||
m_errorView->setDefaultSuppressionFile(dir + QDir::separator() + name + QLatin1String(".supp"));
|
||||
|
||||
QMenu *menu = qobject_cast<QMenu*>(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<QMenu*>(w))
|
||||
return menu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemcheckTool::suppressionActionTriggered()
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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<QAction *> m_errorFilterActions;
|
||||
QAction *m_filterProjectAction;
|
||||
QList<QAction *> m_suppressionActions;
|
||||
QAction *m_suppressionSeparator;
|
||||
MemCheckOutputPaneAdapter *m_outputPaneAdapter;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user