Add callgrind plugin.

Merge-request: 284
Reviewed-by: hjk <qtc-committer@nokia.com>
This commit is contained in:
Mike McQuaid
2011-04-04 14:39:29 +02:00
committed by hjk
parent e16f83a81d
commit 7b79dc3376
34 changed files with 4170 additions and 1 deletions

View File

@@ -0,0 +1,22 @@
<plugin name=\"Callgrind\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
<vendor>Nokia Corporation</vendor>
<copyright>(C) 2011 Nokia Corporation</copyright>
<license>
Commercial Usage
Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia.
GNU Lesser General Public License Usage
Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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.
</license>
<category>Code Analyzer</category>
<description>Valgrind Callgrind Tool Plugin</description>
<url>http://qt.nokia.com</url>
<dependencyList>
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"AnalyzerBase\" version=\"$$QTCREATOR_VERSION\"/>
<dependency name=\"ValgrindToolBase\" version=\"$$QTCREATOR_VERSION\"/>
</dependencyList>
</plugin>

View File

@@ -0,0 +1,5 @@
include(callgrind_dependencies.pri)
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
LIBS *= -l$$qtLibraryName(Callgrind)

View File

@@ -0,0 +1,43 @@
TEMPLATE = lib
TARGET = Callgrind
DEFINES += CALLGRIND_LIBRARY
include(../../qtcreatorplugin.pri)
include(callgrind_dependencies.pri)
# Callgrind files
HEADERS += \
callgrindplugin.h \
callgrind_global.h \
callgrindconfigwidget.h \
callgrindcostdelegate.h \
callgrindcostview.h \
callgrindhelper.h \
callgrindnamedelegate.h \
callgrindsettings.h \
callgrindtool.h \
callgrindvisualisation.h \
callgrindwidgethandler.h \
callgrindengine.h \
workarounds.h \
callgrindtextmark.h
SOURCES += \
callgrindplugin.cpp \
callgrindconfigwidget.cpp \
callgrindcostdelegate.cpp \
callgrindcostview.cpp \
callgrindhelper.cpp \
callgrindnamedelegate.cpp \
callgrindsettings.cpp \
callgrindtool.cpp \
callgrindvisualisation.cpp \
callgrindwidgethandler.cpp \
callgrindengine.cpp \
workarounds.cpp \
callgrindtextmark.cpp
FORMS += \
callgrindconfigwidget.ui

View File

@@ -0,0 +1,5 @@
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/analyzerbase/analyzerbase.pri)
include(../../plugins/valgrindtoolbase/valgrindtoolbase.pri)
include(../../libs/cplusplus/cplusplus.pri)

View File

@@ -0,0 +1,45 @@
/**************************************************************************
**
** 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 CALLGRIND_GLOBAL_H
#define CALLGRIND_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(CALLGRIND_LIBRARY)
# define CALLGRINDSHARED_EXPORT Q_DECL_EXPORT
#else
# define CALLGRINDSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // CALLGRIND_GLOBAL_H

View File

@@ -0,0 +1,77 @@
/**************************************************************************
**
** 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 "callgrindconfigwidget.h"
#include "ui_callgrindconfigwidget.h"
#include "callgrindsettings.h"
using namespace Callgrind::Internal;
CallgrindConfigWidget::CallgrindConfigWidget(AbstractCallgrindSettings *settings, QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::CallgrindConfigWidget)
, m_settings(settings)
{
m_ui->setupUi(this);
m_ui->enableCacheSim->setChecked(m_settings->enableCacheSim());
connect(m_ui->enableCacheSim, SIGNAL(toggled(bool)),
m_settings, SLOT(setEnableCacheSim(bool)));
connect(m_settings, SIGNAL(enableCacheSimChanged(bool)),
m_ui->enableCacheSim, SLOT(setChecked(bool)));
m_ui->enableBranchSim->setChecked(m_settings->enableBranchSim());
connect(m_ui->enableBranchSim, SIGNAL(toggled(bool)),
m_settings, SLOT(setEnableBranchSim(bool)));
connect(m_settings, SIGNAL(enableBranchSimChanged(bool)),
m_ui->enableBranchSim, SLOT(setChecked(bool)));
m_ui->collectSystime->setChecked(m_settings->collectSystime());
connect(m_ui->collectSystime, SIGNAL(toggled(bool)),
m_settings, SLOT(setCollectSystime(bool)));
connect(m_settings, SIGNAL(collectSystimeChanged(bool)),
m_ui->collectSystime, SLOT(setChecked(bool)));
m_ui->collectBusEvents->setChecked(m_settings->collectBusEvents());
connect(m_ui->collectBusEvents, SIGNAL(toggled(bool)),
m_settings, SLOT(setCollectBusEvents(bool)));
connect(m_settings, SIGNAL(collectBusEventsChanged(bool)),
m_ui->collectBusEvents, SLOT(setChecked(bool)));
}
CallgrindConfigWidget::~CallgrindConfigWidget()
{
delete m_ui;
}

View File

@@ -0,0 +1,66 @@
/**************************************************************************
**
** 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 ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
#define ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
#include <QtGui/QWidget>
namespace Callgrind {
namespace Internal {
namespace Ui {
class CallgrindConfigWidget;
}
class AbstractCallgrindSettings;
class CallgrindConfigWidget : public QWidget
{
Q_OBJECT
public:
CallgrindConfigWidget(AbstractCallgrindSettings *settings, QWidget *parent);
virtual ~CallgrindConfigWidget();
private:
Ui::CallgrindConfigWidget *m_ui;
AbstractCallgrindSettings *m_settings;
};
}
}
#endif // ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H

View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Callgrind::Internal::CallgrindConfigWidget</class>
<widget class="QWidget" name="Callgrind::Internal::CallgrindConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>416</width>
<height>565</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="memcheckOptions">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Profiling Options</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="enableCacheSim">
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;
&lt;p&gt;Specify if you want to do full cache simulation.&lt;/p&gt;
&lt;p&gt;By default, only instruction read accesses will be counted (&quot;Ir&quot;).&lt;/p&gt;
&lt;p&gt;
With cache simulation, further event counters are enabled:
&lt;ul&gt;&lt;li&gt;Cache misses on instruction reads (&quot;I1mr&quot;/&quot;I2mr&quot;)&lt;/li&gt;
&lt;li&gt;Data read accesses (&quot;Dr&quot;) and related cache misses (&quot;D1mr&quot;/&quot;D2mr&quot;)&lt;/li&gt;
&lt;li&gt;Data write accesses (&quot;Dw&quot;) and related cache misses (&quot;D1mw&quot;/&quot;D2mw&quot;)&lt;/li&gt;&lt;/ul&gt;
&lt;/p&gt;
For more information, see ???.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable cache simulation</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="enableBranchSim">
<property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p&gt;Specify if you want to do branch prediction simulation.&lt;/p&gt;
&lt;p&gt;Further event counters are enabled: &lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Number of executed conditional branches and related predictor misses (
&quot;Bc&quot;/&quot;Bcm&quot;)&lt;/li&gt;
&lt;li&gt;Executed indirect jumps and related misses of the jump address predictor (
&quot;Bi&quot;/&quot;Bim&quot;)&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable branch prediction simulation</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="collectSystime">
<property name="toolTip">
<string>This specifies whether information for system call times should be collected.</string>
</property>
<property name="text">
<string>Collect system call time</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="collectBusEvents">
<property name="toolTip">
<string>This specifies whether the number of global bus events executed should be collected. The event type &quot;Ge&quot; is used for these events.</string>
</property>
<property name="text">
<string>Collect global bus events</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,41 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef CALLGRINDCONSTANTS_H
#define CALLGRINDCONSTANTS_H
namespace Callgrind {
namespace Constants {
const char * const A_SHOWCOSTSOFFUNCTION = "Analyzer.Callgrind.ShowCostsOfFunction";
}
}
#endif // CALLGRINDCONSTANTS_H

View File

@@ -0,0 +1,192 @@
/**************************************************************************
**
** 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 "callgrindcostdelegate.h"
#include "callgrindcostview.h"
#include "callgrindhelper.h"
#include <valgrind/callgrind/callgrindabstractmodel.h>
#include <valgrind/callgrind/callgrindparsedata.h>
#include <utils/qtcassert.h>
#include <QPainter>
#include <QDebug>
#include <QApplication>
using namespace Valgrind::Callgrind;
namespace Callgrind {
namespace Internal {
//BEGIN CostDelegate::Private
class CostDelegate::Private {
public:
Private();
~Private();
Valgrind::Callgrind::AbstractModel *m_model;
CostDelegate::CostFormat m_format;
static int toNativeRole(CostFormat format);
float relativeCost(const QModelIndex &index) const;
QString displayText(const QModelIndex &index, const QLocale &locale) const;
};
CostDelegate::Private::Private()
: m_model(0)
, m_format(CostDelegate::FormatAbsolute)
{
}
CostDelegate::Private::~Private()
{
}
int CostDelegate::Private::toNativeRole(CostDelegate::CostFormat format)
{
switch(format)
{
case FormatAbsolute:
case FormatRelative:
return Valgrind::Callgrind::AbstractModel::RelativeTotalCostRole;
case FormatRelativeToParent:
return Valgrind::Callgrind::AbstractModel::RelativeParentCostRole;
default:
return -1;
}
}
float CostDelegate::Private::relativeCost(const QModelIndex &index) const
{
bool ok = false;
float cost = index.data(toNativeRole(m_format)).toFloat(&ok);
QTC_ASSERT(ok, return 0);
return cost;
}
QString CostDelegate::Private::displayText(const QModelIndex &index, const QLocale &locale) const
{
switch (m_format) {
case FormatAbsolute:
return locale.toString(index.data().toULongLong());
case FormatRelative:
case FormatRelativeToParent:
if (!m_model)
break;
float cost = relativeCost(index) * 100.0f;
return CallgrindHelper::toPercent(cost, locale);
}
return QString();
}
//END CostDelegate::Private
//BEGIN CostDelegate
CostDelegate::CostDelegate(QObject *parent)
: QStyledItemDelegate(parent)
, d(new Private)
{
}
CostDelegate::~CostDelegate()
{
delete d;
}
void CostDelegate::setModel(Valgrind::Callgrind::AbstractModel *model)
{
d->m_model = model;
}
void CostDelegate::setFormat(CostFormat format)
{
d->m_format = format;
}
CostDelegate::CostFormat CostDelegate::format() const
{
return d->m_format;
}
void CostDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
// init
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
// draw controls, but no text
opt.text.clear();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
painter->save();
// draw bar
float ratio = qBound(0.0f, d->relativeCost(index), 1.0f);
QRect barRect = opt.rect;
barRect.setWidth(opt.rect.width() * ratio);
painter->setPen(Qt::NoPen);
painter->setBrush(CallgrindHelper::colorForCostRatio(ratio));
painter->drawRect(barRect);
// draw text
const QString text = d->displayText(index, opt.locale);
const QBrush &textBrush = (option.state & QStyle::State_Selected ? opt.palette.highlightedText() : opt.palette.text());
painter->setBrush(Qt::NoBrush);
painter->setPen(textBrush.color());
painter->drawText(opt.rect, Qt::AlignRight, text);
painter->restore();
}
QSize CostDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
const QString text = d->displayText(index, opt.locale);
const QSize size = QSize(option.fontMetrics.width(text),
option.fontMetrics.height());
return size;
}
} // Internal
} // Callgrind

View File

@@ -0,0 +1,86 @@
/**************************************************************************
**
** 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 CALLGRINDCOSTDELEGATE_H
#define CALLGRINDCOSTDELEGATE_H
#include <QtGui/QStyledItemDelegate>
namespace Valgrind {
namespace Callgrind {
class AbstractModel;
}
}
namespace Callgrind {
namespace Internal {
class CostDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit CostDelegate(QObject *parent = 0);
virtual ~CostDelegate();
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setModel(Valgrind::Callgrind::AbstractModel *model);
enum CostFormat {
/// show absolute numbers
FormatAbsolute,
/// show percentages relative to the total inclusive cost
FormatRelative,
/// show percentages relative to the parent cost
FormatRelativeToParent
};
void setFormat(CostFormat format);
CostFormat format() const;
private:
class Private;
Private *d;
};
} // Internal
} // Callgrind
Q_DECLARE_METATYPE(Callgrind::Internal::CostDelegate::CostFormat)
#endif // CALLGRINDCOSTDELEGATE_H

View File

@@ -0,0 +1,152 @@
/**************************************************************************
**
** 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 "callgrindcostview.h"
#include "callgrindnamedelegate.h"
#include <valgrind/callgrind/callgrindabstractmodel.h>
#include <valgrind/callgrind/callgrinddatamodel.h>
#include <valgrind/callgrind/callgrindfunction.h>
#include <valgrind/callgrind/callgrindcallmodel.h>
#include <QtGui/QAbstractProxyModel>
#include <QtGui/QHeaderView>
#include <QtCore/QDebug>
using namespace Valgrind::Callgrind;
namespace Callgrind {
namespace Internal {
//BEGIN CostView::Private
class CostView::Private {
public:
explicit Private(CostView *qq);
~Private();
CostDelegate *m_costDelegate;
NameDelegate *m_nameDelegate;
};
CostView::Private::Private(CostView *qq)
: m_costDelegate(new CostDelegate(qq))
, m_nameDelegate(new NameDelegate(qq))
{
}
CostView::Private::~Private()
{
}
//END CostView::Private
//BEGIN CostView
CostView::CostView(QWidget *parent)
: QTreeView(parent)
, d(new Private(this))
{
setSelectionMode(QAbstractItemView::ExtendedSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
setAutoScroll(false);
setSortingEnabled(true);
setRootIsDecorated(false);
}
CostView::~CostView()
{
delete d;
}
void CostView::setModel(QAbstractItemModel *model)
{
QTreeView::setModel(model);
AbstractModel *abstractModel = 0;
forever {
abstractModel = dynamic_cast<AbstractModel *>(model);
if (abstractModel)
break;
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(model);
if (proxy)
model = proxy->sourceModel();
else
break;
}
QHeaderView *headerView = header();
setItemDelegate(new QStyledItemDelegate(this));
headerView->setResizeMode(QHeaderView::Interactive);
headerView->setStretchLastSection(false);
if (dynamic_cast<CallModel *>(abstractModel)) {
setItemDelegateForColumn(CallModel::CostColumn, d->m_costDelegate);
headerView->setResizeMode(CallModel::CostColumn, QHeaderView::ResizeToContents);
headerView->setResizeMode(CallModel::CallsColumn, QHeaderView::ResizeToContents);
headerView->setResizeMode(CallModel::CalleeColumn, QHeaderView::Stretch);
setItemDelegateForColumn(CallModel::CalleeColumn, d->m_nameDelegate);
headerView->setResizeMode(CallModel::CallerColumn, QHeaderView::Stretch);
setItemDelegateForColumn(CallModel::CallerColumn, d->m_nameDelegate);
} else if(dynamic_cast<DataModel *>(abstractModel)) {
setItemDelegateForColumn(DataModel::SelfCostColumn, d->m_costDelegate);
headerView->setResizeMode(DataModel::SelfCostColumn, QHeaderView::ResizeToContents);
setItemDelegateForColumn(DataModel::InclusiveCostColumn, d->m_costDelegate);
headerView->setResizeMode(DataModel::InclusiveCostColumn, QHeaderView::ResizeToContents);
setItemDelegateForColumn(DataModel::NameColumn, d->m_nameDelegate);
headerView->setResizeMode(DataModel::NameColumn, QHeaderView::Stretch);
headerView->setResizeMode(DataModel::LocationColumn, QHeaderView::Stretch);
}
d->m_costDelegate->setModel(abstractModel);
}
void CostView::setCostFormat(CostDelegate::CostFormat format)
{
d->m_costDelegate->setFormat(format);
viewport()->update();
}
CostDelegate::CostFormat CostView::costFormat() const
{
return d->m_costDelegate->format();
}
//END CostView
} // Internal
} // Callgrind

View File

@@ -0,0 +1,72 @@
/**************************************************************************
**
** 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 CALLGRINDCOSTVIEW_H
#define CALLGRINDCOSTVIEW_H
#include <QtGui/QTreeView>
#include "callgrindcostdelegate.h"
namespace Callgrind {
namespace Internal {
class CostView : public QTreeView
{
Q_OBJECT
public:
explicit CostView(QWidget *parent = 0);
virtual ~CostView();
/**
* Overload automatically updates the cost delegate
* and sets it for the cost columns of DataModel and CallModel.
*/
virtual void setModel(QAbstractItemModel *model);
/**
* How to format cost data columns in the view.
*/
void setCostFormat(CostDelegate::CostFormat format);
CostDelegate::CostFormat costFormat() const;
private:
class Private;
Private *d;
};
} // Internal
} // Callgrind
#endif // CALLGRINDCOSTVIEW_H

View File

@@ -0,0 +1,173 @@
/**************************************************************************
**
** 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 "callgrindengine.h"
#include "callgrindsettings.h"
#include <valgrind/callgrind/callgrindcontroller.h>
#include <valgrind/callgrind/callgrindparser.h>
#include <analyzerbase/analyzermanager.h>
#include <utils/qtcassert.h>
using namespace Analyzer;
using namespace Callgrind;
using namespace Callgrind::Internal;
CallgrindEngine::CallgrindEngine(const AnalyzerStartParameters &sp,
ProjectExplorer::RunConfiguration *runConfiguration)
: ValgrindEngine(sp, runConfiguration)
, m_markAsPaused(false)
{
connect(&m_runner, SIGNAL(finished()), this, SLOT(slotFinished()));
connect(&m_runner, SIGNAL(started()), this, SLOT(slotStarted()));
connect(m_runner.parser(), SIGNAL(parserDataReady()), this, SLOT(slotFinished()));
connect(&m_runner, SIGNAL(statusMessage(QString)),
Analyzer::AnalyzerManager::instance(), SLOT(showStatusMessage(QString)));
m_progress->setProgressRange(0, 2);
}
CallgrindEngine::~CallgrindEngine()
{
}
QStringList CallgrindEngine::toolArguments() const
{
QStringList arguments;
AbstractCallgrindSettings *callgrindSettings = m_settings->subConfig<AbstractCallgrindSettings>();
QTC_ASSERT(callgrindSettings, return arguments);
if (callgrindSettings->enableCacheSim())
arguments << "--cache-sim=yes";
if (callgrindSettings->enableBranchSim())
arguments << "--branch-sim=yes";
if (callgrindSettings->collectBusEvents())
arguments << "--collect-bus=yes";
if (callgrindSettings->collectSystime())
arguments << "--collect-systime=yes";
if (m_markAsPaused)
arguments << "--instr-atstart=no";
// add extra arguments
arguments << extraArguments();
return arguments;
}
QString CallgrindEngine::progressTitle() const
{
return tr("Profiling");
}
Valgrind::ValgrindRunner * CallgrindEngine::runner()
{
return &m_runner;
}
void CallgrindEngine::start()
{
emit standardOutputReceived(tr("Profiling %1").arg(executable()));
ValgrindEngine::start();
}
void CallgrindEngine::dump()
{
m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::Dump);
}
void CallgrindEngine::setExtraArguments(const QStringList &extraArguments)
{
m_extraArguments = extraArguments;
}
void CallgrindEngine::setPaused(bool paused)
{
if (m_markAsPaused == paused)
return;
m_markAsPaused = paused;
// call controller
if (paused)
pause();
else
unpause();
}
void CallgrindEngine::setToggleCollectFunction(const QString &toggleCollectFunction)
{
if (toggleCollectFunction.isEmpty())
return;
m_extraArguments << QString("--toggle-collect=%1").arg(toggleCollectFunction);
}
void CallgrindEngine::reset()
{
m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::ResetEventCounters);
}
void CallgrindEngine::pause()
{
m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::Pause);
}
void CallgrindEngine::unpause()
{
m_runner.controller()->run(Valgrind::Callgrind::CallgrindController::UnPause);
}
Valgrind::Callgrind::ParseData *CallgrindEngine::takeParserData()
{
return m_runner.parser()->takeData();
}
void CallgrindEngine::slotFinished()
{
emit parserDataReady(this);
}
void CallgrindEngine::slotStarted()
{
m_progress->setProgressValue(1);;
}

View File

@@ -0,0 +1,92 @@
/**************************************************************************
**
** 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 CALLGRINDENGINE_H
#define CALLGRINDENGINE_H
#include <valgrindtoolbase/valgrindengine.h>
#include <valgrind/callgrind/callgrindrunner.h>
#include <valgrind/callgrind/callgrindparsedata.h>
namespace Callgrind {
namespace Internal {
class CallgrindEngine : public Valgrind::Internal::ValgrindEngine
{
Q_OBJECT
public:
explicit CallgrindEngine(const Analyzer::AnalyzerStartParameters &sp,
ProjectExplorer::RunConfiguration *runConfiguration);
virtual ~CallgrindEngine();
void start();
Valgrind::Callgrind::ParseData *takeParserData();
public slots:
// controller actions
void dump();
void reset();
void pause();
void unpause();
void setPaused(bool paused);
void setToggleCollectFunction(const QString &toggleCollectFunction);
protected:
void setExtraArguments(const QStringList &extraArguments);
inline QStringList extraArguments() const { return m_extraArguments; }
virtual QStringList toolArguments() const;
virtual QString progressTitle() const;
virtual Valgrind::ValgrindRunner *runner();
signals:
void parserDataReady(CallgrindEngine *engine);
private:
Valgrind::Callgrind::CallgrindRunner m_runner;
bool m_markAsPaused;
QStringList m_extraArguments;
private slots:
void slotFinished();
void slotStarted();
};
} // namespace Internal
} // namespace Callgrind
#endif // CALLGRINDENGINE_H

View File

@@ -0,0 +1,71 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "callgrindhelper.h"
#include <cstdlib>
#include <QtGui/QColor>
#include <QtCore/QMap>
#include <QtCore/QString>
using namespace Callgrind::Internal;
QColor CallgrindHelper::colorForString(const QString &text)
{
static QMap<QString, QColor> colorCache;
if (colorCache.contains(text))
return colorCache.value(text);
// Minimum lightness of 100 to be readable with black text.
const QColor color = QColor::fromHsl(((qreal)qrand() / RAND_MAX * 359),
((qreal)qrand() / RAND_MAX * 255),
((qreal)qrand() / RAND_MAX * 127) + 128);
colorCache[text] = color;
return color;
}
QColor CallgrindHelper::colorForCostRatio(qreal ratio)
{
ratio = qBound(0.0, ratio, 1.0);
return QColor::fromHsv(120 - ratio * 120, 255, 255, (-((ratio-1) * (ratio-1))) * 120 + 120);
}
QString CallgrindHelper::toPercent(float costs, const QLocale &locale)
{
if (costs > 99.9f)
return locale.toString(100) + locale.percent();
else if (costs > 9.99f)
return locale.toString(costs, 'f', 1) + locale.percent();
else if (costs > 0.009f)
return locale.toString(costs, 'f', 2) + locale.percent();
else
return QString("<") + locale.toString(0.01f) + locale.percent();
}

View File

@@ -0,0 +1,65 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef CALLGRINDHELPER_H
#define CALLGRINDHELPER_H
#include <QtCore/QLocale>
QT_BEGIN_NAMESPACE
class QColor;
class QString;
QT_END_NAMESPACE
namespace Callgrind {
namespace Internal {
namespace CallgrindHelper
{
/**
* Returns color for a specific string, the string<->color mapping is cached
*/
QColor colorForString(const QString &text);
/**
* Returns color for a specific cost ratio
* \param ratio The cost ratio, ratio should be of [0,1]
*/
QColor colorForCostRatio(qreal ratio);
/**
* Returns a proper percent representation of a float limited to 5 chars
*/
QString toPercent(float costs, const QLocale &locale = QLocale());
}
}
}
#endif // CALLGRINDHELPER_H

View File

@@ -0,0 +1,92 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "callgrindnamedelegate.h"
#include "callgrindhelper.h"
#include <QApplication>
#include <QPainter>
namespace Callgrind {
namespace Internal {
NameDelegate::NameDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
NameDelegate::~NameDelegate()
{
}
void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
// init
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
const int margin = 2;
const int size = 10;
const QString text = index.data().toString();
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
// draw controls, but no text
opt.text.clear();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
// draw bar in the first few pixels
painter->save();
const QRectF barRect = opt.rect.adjusted(
margin, margin, -opt.rect.width() + size - margin, -margin);
painter->setPen(Qt::black);
painter->setBrush(CallgrindHelper::colorForString(text));
painter->drawRect(barRect);
// move cell rect to right
opt.rect.adjust(size+margin, 0, 0, 0);
// draw text
const QString elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight,
opt.rect.width());
const QBrush &textBrush = (option.state & QStyle::State_Selected)
? opt.palette.highlightedText()
: opt.palette.text();
painter->setBrush(Qt::NoBrush);
painter->setPen(textBrush.color());
painter->drawText(opt.rect, elidedText);
painter->restore();
}
} // Internal
} // Callgrind

View File

@@ -0,0 +1,53 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef CALLGRINDNAMEDELEGATE_H
#define CALLGRINDNAMEDELEGATE_H
#include <QtGui/QStyledItemDelegate>
namespace Callgrind {
namespace Internal {
class NameDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit NameDelegate(QObject *parent = 0);
virtual ~NameDelegate();
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
} // Internal
} // Callgrind
#endif // CALLGRINDNAMEDELEGATE_H

View File

@@ -0,0 +1,73 @@
/**************************************************************************
**
** 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 "callgrindplugin.h"
#include "callgrindtool.h"
#include "callgrindsettings.h"
#include <analyzerbase/analyzermanager.h>
#include <QStringList>
#include <QtPlugin>
using namespace Analyzer;
using namespace Callgrind;
using namespace Callgrind::Internal;
CallgrindPlugin::CallgrindPlugin()
{
}
CallgrindPlugin::~CallgrindPlugin()
{
}
bool CallgrindPlugin::initialize(const QStringList &/*arguments*/, QString */*errorString*/)
{
typedef AnalyzerSubConfigFactory<CallgrindGlobalSettings, CallgrindProjectSettings> CallgrindConfigFactory;
AnalyzerGlobalSettings::instance()->registerSubConfigFactory(new CallgrindConfigFactory);
AnalyzerManager::instance()->addTool(new CallgrindTool(this));
return true;
}
void CallgrindPlugin::extensionsInitialized()
{
}
Q_EXPORT_PLUGIN(CallgrindPlugin)

View File

@@ -0,0 +1,57 @@
/**************************************************************************
**
** 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 CALLGRINDPLUGIN_H
#define CALLGRINDPLUGIN_H
#include <extensionsystem/iplugin.h>
namespace Callgrind {
namespace Internal {
class CallgrindPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
CallgrindPlugin();
~CallgrindPlugin();
virtual bool initialize(const QStringList &arguments, QString *errorString);
virtual void extensionsInitialized();
};
} // namespace Internal
} // namespace Callgrind
#endif // CALLGRINDPLUGIN_H

View File

@@ -0,0 +1,229 @@
/**************************************************************************
**
** 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 "callgrindsettings.h"
#include "callgrindconfigwidget.h"
#include <QDebug>
using namespace Analyzer;
using namespace Callgrind::Internal;
using namespace Callgrind;
static const QLatin1String callgrindEnableCacheSimC("Analyzer.Valgrind.Callgrind.EnableCacheSim");
static const QLatin1String callgrindEnableBranchSimC("Analyzer.Valgrind.Callgrind.EnableBranchSim");
static const QLatin1String callgrindCollectSystimeC("Analyzer.Valgrind.Callgrind.CollectSystime");
static const QLatin1String callgrindCollectBusEventsC("Analyzer.Valgrind.Callgrind.CollectBusEvents");
static const QLatin1String callgrindCycleDetectionC("Analyzer.Valgrind.Callgrind.CycleDetection");
static const QLatin1String callgrindCostFormatC("Analyzer.Valgrind.Callgrind.CostFormat");
static const QLatin1String callgrindMinimumCostRatioC("Analyzer.Valgrind.Callgrind.MinimumCostRatio");
AbstractCallgrindSettings::AbstractCallgrindSettings(QObject *parent)
: AbstractAnalyzerSubConfig(parent)
{
}
AbstractCallgrindSettings::~AbstractCallgrindSettings()
{
}
void AbstractCallgrindSettings::setEnableCacheSim(bool enable)
{
if (m_enableCacheSim == enable)
return;
m_enableCacheSim = enable;
emit enableCacheSimChanged(enable);
}
void AbstractCallgrindSettings::setEnableBranchSim(bool enable)
{
if (m_enableBranchSim == enable)
return;
m_enableBranchSim = enable;
emit enableBranchSimChanged(enable);
}
void AbstractCallgrindSettings::setCollectSystime(bool collect)
{
if (m_collectSystime == collect)
return;
m_collectSystime = collect;
emit collectSystimeChanged(collect);
}
void AbstractCallgrindSettings::setCollectBusEvents(bool collect)
{
if (m_collectBusEvents == collect)
return;
m_collectBusEvents = collect;
emit collectBusEventsChanged(collect);
}
QVariantMap AbstractCallgrindSettings::defaults() const
{
QVariantMap map;
map.insert(callgrindEnableCacheSimC, false);
map.insert(callgrindEnableBranchSimC, false);
map.insert(callgrindCollectSystimeC, false);
map.insert(callgrindCollectBusEventsC, false);
return map;
}
bool AbstractCallgrindSettings::fromMap(const QVariantMap &map)
{
setIfPresent(map, callgrindEnableCacheSimC, &m_enableCacheSim);
setIfPresent(map, callgrindEnableBranchSimC, &m_enableBranchSim);
setIfPresent(map, callgrindCollectSystimeC, &m_collectSystime);
setIfPresent(map, callgrindCollectBusEventsC, &m_collectBusEvents);
return true;
}
QVariantMap AbstractCallgrindSettings::toMap() const
{
QVariantMap map;
map.insert(callgrindEnableCacheSimC, m_enableCacheSim);
map.insert(callgrindEnableBranchSimC, m_enableBranchSim);
map.insert(callgrindCollectSystimeC, m_collectSystime);
map.insert(callgrindCollectBusEventsC, m_collectBusEvents);
return map;
}
QString AbstractCallgrindSettings::id() const
{
return "Analyzer.Valgrind.Settings.Callgrind";
}
QString AbstractCallgrindSettings::displayName() const
{
return tr("Profiling");
}
QWidget *AbstractCallgrindSettings::createConfigWidget(QWidget *parent)
{
return new CallgrindConfigWidget(this, parent);
}
CallgrindGlobalSettings::CallgrindGlobalSettings(QObject *parent)
: AbstractCallgrindSettings(parent)
{
}
CallgrindGlobalSettings::~CallgrindGlobalSettings()
{
}
QVariantMap CallgrindGlobalSettings::defaults() const
{
QVariantMap map = AbstractCallgrindSettings::defaults();
map.insert(callgrindCostFormatC, CostDelegate::FormatRelative);
map.insert(callgrindCycleDetectionC, true);
map.insert(callgrindMinimumCostRatioC, 0.0001);
return map;
}
bool CallgrindGlobalSettings::fromMap(const QVariantMap &map)
{
AbstractCallgrindSettings::fromMap(map);
// special code as the default one does not cope with the enum properly
if (map.contains(callgrindCostFormatC)) {
m_costFormat = static_cast<CostDelegate::CostFormat>(map.value(callgrindCostFormatC).toInt());
}
setIfPresent(map, callgrindCycleDetectionC, &m_detectCycles);
setIfPresent(map, callgrindMinimumCostRatioC, &m_minimumInclusiveCostRatio);
return true;
}
QVariantMap CallgrindGlobalSettings::toMap() const
{
QVariantMap map = AbstractCallgrindSettings::toMap();
map.insert(callgrindCostFormatC, m_costFormat);
map.insert(callgrindCycleDetectionC, m_detectCycles);
map.insert(callgrindMinimumCostRatioC, m_minimumInclusiveCostRatio);
return map;
}
CostDelegate::CostFormat CallgrindGlobalSettings::costFormat() const
{
return m_costFormat;
}
void CallgrindGlobalSettings::setCostFormat(CostDelegate::CostFormat format)
{
m_costFormat = format;
AnalyzerGlobalSettings::instance()->writeSettings();
}
bool CallgrindGlobalSettings::detectCycles() const
{
return m_detectCycles;
}
void CallgrindGlobalSettings::setDetectCycles(bool detect)
{
m_detectCycles = detect;
AnalyzerGlobalSettings::instance()->writeSettings();
}
double CallgrindGlobalSettings::minimumInclusiveCostRatio() const
{
return m_minimumInclusiveCostRatio;
}
void CallgrindGlobalSettings::setMinimumInclusiveCostRatio(double minimumInclusiveCost)
{
m_minimumInclusiveCostRatio = minimumInclusiveCost;
AnalyzerGlobalSettings::instance()->writeSettings();
}
CallgrindProjectSettings::CallgrindProjectSettings(QObject *parent)
: AbstractCallgrindSettings(parent)
{
}
CallgrindProjectSettings::~CallgrindProjectSettings()
{
}

View File

@@ -0,0 +1,139 @@
/**************************************************************************
**
** 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 ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
#define ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
#include <analyzerbase/analyzersettings.h>
#include <QString>
#include "callgrindcostdelegate.h"
namespace Callgrind {
namespace Internal {
/**
* Generic callgrind settings
*/
class AbstractCallgrindSettings : public Analyzer::AbstractAnalyzerSubConfig
{
Q_OBJECT
public:
AbstractCallgrindSettings(QObject *parent = 0);
virtual ~AbstractCallgrindSettings();
inline bool enableCacheSim() const { return m_enableCacheSim; }
inline bool enableBranchSim() const { return m_enableBranchSim; }
inline bool collectSystime() const { return m_collectSystime; }
inline bool collectBusEvents() const { return m_collectBusEvents; }
// abstract virtual methods from base class
virtual bool fromMap(const QVariantMap &map);
virtual QVariantMap defaults() const;
virtual QString id() const;
virtual QString displayName() const;
virtual QWidget *createConfigWidget(QWidget *parent);
public Q_SLOTS:
void setEnableCacheSim(bool enable);
void setEnableBranchSim(bool enable);
void setCollectSystime(bool collect);
void setCollectBusEvents(bool collect);
Q_SIGNALS:
void enableCacheSimChanged(bool);
void enableBranchSimChanged(bool);
void collectSystimeChanged(bool);
void collectBusEventsChanged(bool);
protected:
virtual QVariantMap toMap() const;
private:
bool m_enableCacheSim;
bool m_collectSystime;
bool m_collectBusEvents;
bool m_enableBranchSim;
};
/**
* Global callgrind settings
*/
class CallgrindGlobalSettings : public AbstractCallgrindSettings
{
Q_OBJECT
public:
CallgrindGlobalSettings(QObject *parent = 0);
virtual ~CallgrindGlobalSettings();
virtual bool fromMap(const QVariantMap &map);
virtual QVariantMap defaults() const;
CostDelegate::CostFormat costFormat() const;
bool detectCycles() const;
double minimumInclusiveCostRatio() const;
public slots:
void setCostFormat(Callgrind::Internal::CostDelegate::CostFormat format);
void setDetectCycles(bool detect);
void setMinimumInclusiveCostRatio(double minimumInclusiveCost);
protected:
virtual QVariantMap toMap() const;
private:
CostDelegate::CostFormat m_costFormat;
bool m_detectCycles;
double m_minimumInclusiveCostRatio;
};
/**
* Per-project callgrind settings, saves a diff to the global suppression files list
*/
class CallgrindProjectSettings : public AbstractCallgrindSettings
{
Q_OBJECT
public:
CallgrindProjectSettings(QObject *parent = 0);
virtual ~CallgrindProjectSettings();
};
}
}
#endif // ANALYZER_INTERNAL_CALLGRINDSETTINGS_H

View File

@@ -0,0 +1,108 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "callgrindtextmark.h"
#include "callgrindhelper.h"
#include <valgrind/callgrind/callgrinddatamodel.h>
#include <valgrind/callgrind/callgrindfunction.h>
#include <QDebug>
#include <QPainter>
#include <utils/qtcassert.h>
using namespace Callgrind::Internal;
using namespace Valgrind::Callgrind;
CallgrindTextMark::CallgrindTextMark(const QPersistentModelIndex &index,
const QString &fileName, int lineNumber)
: m_modelIndex(index)
{
setLocation(fileName, lineNumber);
setPriority(TextEditor::ITextMark::HighPriority);
}
CallgrindTextMark::~CallgrindTextMark()
{
}
void CallgrindTextMark::paint(QPainter *painter, const QRect &paintRect) const
{
if (!m_modelIndex.isValid())
return;
bool ok;
qreal costs = m_modelIndex.data(DataModel::RelativeTotalCostRole).toReal(&ok);
QTC_ASSERT(ok, return)
QTC_ASSERT(costs >= 0.0 && costs <= 100.0, return)
painter->save();
// set up
painter->setPen(Qt::black);
// draw bar
QRect fillRect = paintRect;
fillRect.setWidth(paintRect.width() * costs);
painter->fillRect(paintRect, Qt::white);
painter->fillRect(fillRect, CallgrindHelper::colorForCostRatio(costs));
painter->drawRect(paintRect);
// draw text
const QTextOption flags = Qt::AlignHCenter | Qt::AlignVCenter;
const QString text = CallgrindHelper::toPercent(costs * 100.0f);
// decrease font size if paint rect is too small (very unlikely, but may happen)
QFont font = painter->font();
QFontMetrics fm = font;
while (fm.boundingRect(text).width() > paintRect.width()) {
font.setPointSize(font.pointSize() - 1);
fm = font;
}
painter->setFont(font);
painter->drawText(paintRect, text, flags);
painter->restore();
}
const Function* CallgrindTextMark::function() const
{
if (!m_modelIndex.isValid())
return 0;
return m_modelIndex.data(DataModel::FunctionRole).value<const Function *>();
}
double CallgrindTextMark::widthFactor() const
{
return 4.0;
}

View File

@@ -0,0 +1,76 @@
/**************************************************************************
**
** This file is part of Qt Creator Analyzer Tools
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef CALLGRINDTEXTMARK_H
#define CALLGRINDTEXTMARK_H
#include <texteditor/basetextmark.h>
#include <QtCore/QPersistentModelIndex>
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
namespace Valgrind {
namespace Callgrind {
class Function;
}
}
namespace Callgrind {
namespace Internal {
class CallgrindTextMark : public TextEditor::BaseTextMark
{
Q_OBJECT
public:
/**
* This creates a callgrind text mark for a specific Function
*
* \param index DataModel model index
* \note The index parameter must refer to one of the DataModel cost columns
*/
explicit CallgrindTextMark(const QPersistentModelIndex &index,
const QString &fileName, int lineNumber);
virtual ~CallgrindTextMark();
const Valgrind::Callgrind::Function *function() const;
virtual double widthFactor() const;
virtual void paint(QPainter *painter, const QRect &paintRect) const;
private:
QPersistentModelIndex m_modelIndex;
};
} // namespace Internal
} // namespace Callgrind
#endif // CALLGRINDTEXTMARK_H

View File

@@ -0,0 +1,506 @@
/**************************************************************************
**
** 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 "callgrindtool.h"
#include "callgrindconstants.h"
#include "callgrindcostview.h"
#include "callgrindengine.h"
#include "callgrindwidgethandler.h"
#include "callgrindtextmark.h"
#include "callgrindvisualisation.h"
#include "callgrindsettings.h"
#include <analyzerbase/analyzermanager.h>
#include <analyzerbase/analyzersettings.h>
#include <analyzerbase/analyzerutils.h>
#include <analyzerbase/ianalyzeroutputpaneadapter.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h>
#include <cppeditor/cppeditorconstants.h>
#include <extensionsystem/iplugin.h>
#include <texteditor/basetexteditor.h>
#include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
#include <utils/styledbar.h>
#include <valgrind/callgrind/callgrinddatamodel.h>
#include <valgrind/callgrind/callgrindparsedata.h>
#include <valgrind/callgrind/callgrindcostitem.h>
#include <valgrind/callgrind/callgrindproxymodel.h>
#include <valgrind/callgrind/callgrindfunction.h>
#include <valgrind/callgrind/callgrindstackbrowser.h>
#include <QtGui/QDockWidget>
#include <QtGui/QHBoxLayout>
#include <QtGui/QCheckBox>
#include <QtGui/QGraphicsItem>
#include <QtGui/QMenu>
#include <QtGui/QToolButton>
#include <QtGui/QAction>
#include <QtGui/QLineEdit>
#include <QtGui/QToolBar>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
// shared/cplusplus includes
#include <Symbols.h>
using namespace Callgrind;
using namespace Analyzer;
using namespace Core;
using namespace Valgrind::Callgrind;
namespace Callgrind {
namespace Internal {
// Adapter for output pane.
class CallgrindOutputPaneAdapter : public Analyzer::ListItemViewOutputPaneAdapter
{
public:
explicit CallgrindOutputPaneAdapter(CallgrindTool *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->callgrindWidgetHandler()->flatView();
}
private:
CallgrindTool *m_tool;
};
static QToolButton *createToolButton(QAction *action)
{
QToolButton *button = new QToolButton;
button->setDefaultAction(action);
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
return button;
}
CallgrindTool::CallgrindTool(QObject *parent)
: Analyzer::IAnalyzerTool(parent)
, m_callgrindWidgetHandler(0)
, m_dumpAction(0)
, m_resetAction(0)
, m_pauseAction(0)
, m_showCostsOfFunctionAction(0)
, m_outputPaneAdapter(0)
{
Core::ICore *core = Core::ICore::instance();
// EditorManager
QObject *editorManager = core->editorManager();
connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
SLOT(editorOpened(Core::IEditor*)));
}
CallgrindTool::~CallgrindTool()
{
qDeleteAll(m_textMarks);
}
QString CallgrindTool::id() const
{
return "Callgrind";
}
QString CallgrindTool::displayName() const
{
return tr("Profile");
}
IAnalyzerTool::ToolMode CallgrindTool::mode() const
{
return ReleaseMode;
}
void CallgrindTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
{
AnalyzerManager *am = AnalyzerManager::instance();
CallgrindWidgetHandler *handler = new CallgrindWidgetHandler(am->mainWindow());
m_callgrindWidgetHandler = handler;
QDockWidget *visDock = am->createDockWidget(this, tr("Visualisation"),
handler->visualisation(), Qt::LeftDockWidgetArea);
QDockWidget *calleesDock = am->createDockWidget(this, tr("Callees"),
handler->calleesView(), Qt::BottomDockWidgetArea);
QDockWidget *callersDock = am->createDockWidget(this, tr("Callers"),
handler->callersView(), Qt::BottomDockWidgetArea);
am->mainWindow()->tabifyDockWidget(callersDock, calleesDock);
am->mainWindow()->tabifyDockWidget(calleesDock, visDock);
connect(m_callgrindWidgetHandler, SIGNAL(functionSelected(const Valgrind::Callgrind::Function*)),
this, SLOT(slotFunctionSelected(const Valgrind::Callgrind::Function*)));
}
void CallgrindTool::extensionsInitialized()
{
Core::ICore *core = Core::ICore::instance();
Core::ActionManager *actionManager = core->actionManager();
Core::Context analyzerContext = Core::Context(Analyzer::Constants::C_ANALYZEMODE);
// check if there is a CppEditor context menu, if true, add our own context menu actions
if (Core::ActionContainer *editorContextMenu =
actionManager->actionContainer(CppEditor::Constants::M_CONTEXT)) {
QAction *action = 0;
Core::Command *cmd = 0;
action = new QAction(this);
action->setSeparator(true);
cmd = actionManager->registerAction(action, "Analyzer.Callgrind.ContextMenu.Sep",
analyzerContext);
editorContextMenu->addAction(cmd);
action = new QAction(tr("Profile costs of this function and its callees"), this);
action->setIcon(QIcon(Analyzer::Constants::ANALYZER_CONTROL_START_ICON));
connect(action, SIGNAL(triggered()), SLOT(handleShowCostsOfFunction()));
cmd = actionManager->registerAction(action, Callgrind::Constants::A_SHOWCOSTSOFFUNCTION,
analyzerContext);
editorContextMenu->addAction(cmd);
cmd->setAttribute(Core::Command::CA_Hide);
cmd->setAttribute(Core::Command::CA_NonConfigurable);
m_showCostsOfFunctionAction = action;
}
}
IAnalyzerEngine *CallgrindTool::createEngine(const AnalyzerStartParameters &sp,
ProjectExplorer::RunConfiguration *runConfiguration)
{
CallgrindEngine *engine = new CallgrindEngine(sp, runConfiguration);
connect(engine, SIGNAL(parserDataReady(CallgrindEngine *)), SLOT(takeParserData(CallgrindEngine *)));
connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)),
this, SLOT(engineStarting(const Analyzer::IAnalyzerEngine*)));
connect(engine, SIGNAL(finished()),
this, SLOT(engineFinished()));
connect(this, SIGNAL(dumpRequested()), engine, SLOT(dump()));
connect(this, SIGNAL(resetRequested()), engine, SLOT(reset()));
connect(this, SIGNAL(pauseToggled(bool)), engine, SLOT(setPaused(bool)));
// initialize engine
engine->setPaused(m_pauseAction->isChecked());
// we may want to toggle collect for one function only in this run
engine->setToggleCollectFunction(m_toggleCollectFunction);
m_toggleCollectFunction.clear();
AnalyzerManager::instance()->showStatusMessage(AnalyzerManager::msgToolStarted(displayName()));
return engine;
}
QWidget *CallgrindTool::createControlWidget()
{
QWidget *widget = new QWidget;
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
widget->setLayout(layout);
// dump action
m_dumpAction = new QAction(this);
m_dumpAction->setDisabled(true);
m_dumpAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_REDO)));
m_dumpAction->setText(tr("Dump"));
m_dumpAction->setToolTip(tr("Request the dumping of profile information. This will update the callgrind visualization."));
connect(m_dumpAction, SIGNAL(triggered()), this, SLOT(slotRequestDump()));
layout->addWidget(createToolButton(m_dumpAction));
// reset action
m_resetAction = new QAction(this);
m_resetAction->setDisabled(true);
m_resetAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_CLEAR)));
m_resetAction->setText(tr("Reset"));
m_resetAction->setToolTip(tr("Zero all event counters."));
connect(m_resetAction, SIGNAL(triggered()), this, SIGNAL(resetRequested()));
layout->addWidget(createToolButton(m_resetAction));
// pause action
m_pauseAction = new QAction(this);
m_pauseAction->setCheckable(true);
m_pauseAction->setIcon(QIcon(QLatin1String(":/qml/images/pause-small.png")));
m_pauseAction->setText(tr("Ignore"));
m_pauseAction->setToolTip(tr("If enabled, no events are counted which will speed up program execution during profiling."));
connect(m_pauseAction, SIGNAL(toggled(bool)), this, SIGNAL(pauseToggled(bool)));
layout->addWidget(createToolButton(m_pauseAction));
layout->addWidget(new Utils::StyledSeparator);
layout->addStretch();
return widget;
}
CallgrindWidgetHandler *CallgrindTool::callgrindWidgetHandler() const
{
return m_callgrindWidgetHandler;
}
QWidget *CallgrindTool::createPaneToolBarWidget()
{
QWidget *toolbarWidget = new QWidget;
toolbarWidget->setObjectName("CallgrindToolBarWidget");
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
toolbarWidget->setLayout(layout);
m_callgrindWidgetHandler->populateActions(layout);
CallgrindGlobalSettings *settings = AnalyzerGlobalSettings::instance()->subConfig<CallgrindGlobalSettings>();
m_callgrindWidgetHandler->setCostFormat(settings->costFormat());
m_callgrindWidgetHandler->enableCycleDetection(settings->detectCycles());
connect(m_callgrindWidgetHandler, SIGNAL(costFormatChanged(Callgrind::Internal::CostDelegate::CostFormat)),
settings, SLOT(setCostFormat(Callgrind::Internal::CostDelegate::CostFormat)));
connect(m_callgrindWidgetHandler, SIGNAL(cycleDetectionEnabled(bool)),
settings, SLOT(setDetectCycles(bool)));
// performance: add a minimum cost index so that we are not flooded by the results
m_callgrindWidgetHandler->proxyModel()->setMinimumInclusiveCostRatio(settings->minimumInclusiveCostRatio());
return toolbarWidget;
}
void CallgrindTool::clearErrorView()
{
clearTextMarks();
m_callgrindWidgetHandler->slotClear();
}
void CallgrindTool::clearTextMarks()
{
qDeleteAll(m_textMarks);
m_textMarks.clear();
}
void CallgrindTool::engineStarting(const Analyzer::IAnalyzerEngine *)
{
// enable/disable actions
m_resetAction->setEnabled(true);
m_dumpAction->setEnabled(true);
clearErrorView();
}
void CallgrindTool::engineFinished()
{
// enable/disable actions
m_resetAction->setEnabled(false);
m_dumpAction->setEnabled(false);
const ParseData *data = m_callgrindWidgetHandler->dataModel()->parseData();
if (data)
showParserResults(data);
else
AnalyzerManager::instance()->showStatusMessage(tr("Profiling aborted."));
}
void CallgrindTool::showParserResults(const ParseData *data)
{
QString msg;
if (data) {
// be careful, the list of events might be empty
if (data->events().isEmpty()) {
msg = tr("Parsing finished, no data.");
}
else {
const QString costStr = QString("%1 %2").arg(QString::number(data->totalCost(0)), data->events().first());
msg = tr("Parsing finished, total cost of %1 reported.").arg(costStr);
}
} else {
msg = tr("Parsing failed.");
}
AnalyzerManager::instance()->showStatusMessage(msg);
}
void CallgrindTool::editorOpened(Core::IEditor *editor)
{
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
if (!textEditor)
return;
connect(textEditor,
SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
}
void CallgrindTool::requestContextMenu(TextEditor::ITextEditor *editor, int line, QMenu *menu)
{
// find callgrind text mark that corresponds to this editor's file and line number
const Function *func = 0;
foreach(CallgrindTextMark *textMark, m_textMarks) {
if (textMark->fileName() == editor->file()->fileName() && textMark->lineNumber() == line) {
func = textMark->function();
break;
}
}
if (!func)
return; // no callgrind text mark under cursor, return
// add our action to the context menu
QAction *action = new QAction(tr("Select this function in the analyzer output"), menu);
connect(action, SIGNAL(triggered()), this, SLOT(handleShowCostsAction()));
action->setData(QVariant::fromValue<const Function *>(func));
menu->addAction(action);
}
void CallgrindTool::handleShowCostsAction()
{
const QAction *action = qobject_cast<QAction *>(sender());
QTC_ASSERT(action, return)
const Function *func = action->data().value<const Function *>();
QTC_ASSERT(func, return)
m_callgrindWidgetHandler->selectFunction(func);
}
void CallgrindTool::handleShowCostsOfFunction()
{
CPlusPlus::Symbol *symbol = AnalyzerUtils::findSymbolUnderCursor();
if (!symbol)
return;
if (!symbol->isFunction())
return;
CPlusPlus::Overview view;
const QString qualifiedFunctionName = view.prettyName(CPlusPlus::LookupContext::fullyQualifiedName(symbol));
m_toggleCollectFunction = QString("%1()").arg(qualifiedFunctionName);
AnalyzerManager::instance()->selectTool(this);
AnalyzerManager::instance()->startTool();
}
void CallgrindTool::slotRequestDump()
{
m_callgrindWidgetHandler->visualisation()->setText(tr("Populating..."));
emit dumpRequested();
}
void CallgrindTool::slotFunctionSelected(const Function *func)
{
if (func && QFile::exists(func->file())) {
///TODO: custom position support?
int line = func->lineNumber();
TextEditor::BaseTextEditorWidget::openEditorAt(func->file(), qMax(line, 0));
}
}
void CallgrindTool::takeParserData(CallgrindEngine *engine)
{
ParseData *data = engine->takeParserData();
showParserResults(data);
if (!data)
return;
// clear first
clearErrorView();
m_callgrindWidgetHandler->setParseData(data);
createTextMarks();
}
void CallgrindTool::createTextMarks()
{
DataModel *model = m_callgrindWidgetHandler->dataModel();
QTC_ASSERT(model, return)
QList<QString> locations;
for (int row = 0; row < model->rowCount(); ++row)
{
const QModelIndex index = model->index(row, DataModel::InclusiveCostColumn);
QString fileName = index.data(DataModel::FileNameRole).toString();
if (fileName.isEmpty() || fileName == "???")
continue;
bool ok = false;
const int lineNumber = index.data(DataModel::LineNumberRole).toInt(&ok);
QTC_ASSERT(ok, continue);
// sanitize filename, text marks need a canonical (i.e. no ".."s) path
// BaseTextMark::editorOpened(Core::IEditor *editor) compares file names on string basis
QFileInfo info(fileName);
fileName = info.canonicalFilePath();
if (fileName.isEmpty())
continue; // isEmpty == true => file does not exist, continue then
// create only one text mark per location
const QString location = QString("%1:%2").arg(fileName, QString::number(lineNumber));
if (locations.contains(location))
continue;
locations << location;
CallgrindTextMark *mark = new CallgrindTextMark(index, fileName, lineNumber);
m_textMarks << mark;
}
}
IAnalyzerOutputPaneAdapter *CallgrindTool::outputPaneAdapter()
{
if (!m_outputPaneAdapter)
m_outputPaneAdapter = new CallgrindOutputPaneAdapter(this);
return m_outputPaneAdapter;
}
bool CallgrindTool::canRunRemotely() const
{
return true;
}
}
}

View File

@@ -0,0 +1,155 @@
/**************************************************************************
**
** 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 CALLGRINDTOOL_H
#define CALLGRINDTOOL_H
#include <analyzerbase/ianalyzertool.h>
#include <QVector>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QAction;
class QComboBox;
class QSortFilterProxyModel;
class QMenu;
class QModelIndex;
QT_END_NAMESPACE
namespace Valgrind {
namespace Callgrind {
class CostView;
class DataModel;
class DataProxyModel;
class Function;
class ParseData;
class StackBrowser;
class Visualisation;
}
}
namespace TextEditor
{
class ITextEditor;
}
namespace Core
{
class IEditor;
}
namespace Callgrind {
namespace Internal {
class CallgrindEngine;
class CallgrindWidgetHandler;
class CallgrindOutputPaneAdapter;
class CallgrindTextMark;
class CallgrindTool : public Analyzer::IAnalyzerTool
{
Q_OBJECT
public:
explicit CallgrindTool(QObject *parent = 0);
virtual ~CallgrindTool();
virtual QString id() const;
virtual QString displayName() const;
virtual ToolMode mode() const;
virtual void initialize(ExtensionSystem::IPlugin *plugin);
virtual void extensionsInitialized();
virtual Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter();
virtual Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
ProjectExplorer::RunConfiguration *runConfiguration = 0);
virtual QWidget *createControlWidget();
// For the output pane adapter.
CallgrindWidgetHandler *callgrindWidgetHandler() const;
QWidget *createPaneToolBarWidget();
void clearErrorView();
virtual bool canRunRemotely() const;
signals:
void dumpRequested();
void resetRequested();
void pauseToggled(bool checked);
void profilingStartRequested(const QString &toggleCollectFunction);
private slots:
void showParserResults(const Valgrind::Callgrind::ParseData *data);
void slotRequestDump();
void slotFunctionSelected(const Valgrind::Callgrind::Function *);
void editorOpened(Core::IEditor *);
void requestContextMenu(TextEditor::ITextEditor *editor, int line, QMenu *menu);
void handleShowCostsAction();
void handleShowCostsOfFunction();
void takeParserData(CallgrindEngine *engine);
void engineStarting(const Analyzer::IAnalyzerEngine *);
void engineFinished();
private:
/// This function will add custom text marks to the editor
/// \note Call this after the data model has been populated
void createTextMarks();
/// This function will clear all text marks from the editor
void clearTextMarks();
CallgrindWidgetHandler *m_callgrindWidgetHandler;
QVector<CallgrindTextMark *> m_textMarks;
QAction *m_dumpAction;
QAction *m_resetAction;
QAction *m_pauseAction;
QAction *m_showCostsOfFunctionAction;
CallgrindOutputPaneAdapter *m_outputPaneAdapter;
QString m_toggleCollectFunction;
};
} // namespace Internal
} // namespace Callgrind
#endif // CALLGRINDTOOL_H

View File

@@ -0,0 +1,502 @@
/**************************************************************************
**
** 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 "callgrindvisualisation.h"
#include "callgrindhelper.h"
#include <valgrind/callgrind/callgrindabstractmodel.h>
#include <valgrind/callgrind/callgrinddatamodel.h>
#include <valgrind/callgrind/callgrindfunction.h>
#include <valgrind/callgrind/callgrindproxymodel.h>
#include <utils/qtcassert.h>
#include <QAbstractItemModel>
#include <QDebug>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsSimpleTextItem>
#include <QMouseEvent>
#include <QStaticText>
#include <QStyleOptionGraphicsItem>
#include <QPair>
#include <QPersistentModelIndex>
#include <QLinkedList>
#define VISUALISATION_DEBUG 0
// Margin from hardcoded value in:
// QGraphicsView::fitInView(const QRectF &rect,
// Qt::AspectRatioMode aspectRatioMode)
// Bug report here: http://bugreports.qt.nokia.com/browse/QTBUG-11945
#define FIT_IN_VIEW_MARGIN 2;
using namespace Valgrind::Callgrind;
namespace Callgrind {
namespace Internal {
class FunctionGraphicsTextItem : public QAbstractGraphicsShapeItem
{
public:
FunctionGraphicsTextItem(const QString &text, QGraphicsItem *parent);
virtual void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual QRectF boundingRect() const;
void setRotateText(bool rotate);
private:
QString m_text;
QStaticText m_staticText;
bool m_rotateText;
QColor m_textColor;
qreal m_previousViewportDimension;
};
class FunctionGraphicsItem : public QGraphicsRectItem
{
public:
enum DataKey {
FunctionCallKey
};
FunctionGraphicsItem(const QString &text, qreal x, qreal y,
qreal width, qreal height, QGraphicsItem *parent = 0);
virtual void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget);
FunctionGraphicsTextItem *textItem() const;
private:
FunctionGraphicsTextItem *m_text;
};
FunctionGraphicsTextItem::FunctionGraphicsTextItem(const QString &text,
QGraphicsItem *parent)
: QAbstractGraphicsShapeItem(parent)
, m_text(text)
, m_rotateText(true)
, m_previousViewportDimension(0)
{
setFlag(QGraphicsItem::ItemIgnoresTransformations);
setAcceptedMouseButtons(0); // do not steal focus from parent item
setToolTip(text);
}
void FunctionGraphicsTextItem::setRotateText(bool rotate)
{
m_rotateText = rotate;
}
void FunctionGraphicsTextItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *,
QWidget *widget)
{
const qreal textHeight = painter->fontMetrics().height();
// Magic number based on what looked best.
const int margin = 2 + FIT_IN_VIEW_MARGIN;
const QRectF viewportRect =
widget->rect().adjusted(margin, margin, -margin, -margin);
const qreal maxWidth = viewportRect.width()
* parentItem()->boundingRect().width()
/ scene()->sceneRect().width();
const qreal maxHeight = viewportRect.height()
* parentItem()->boundingRect().height()
/ scene()->sceneRect().height();
qreal textMaxHeight;
qreal textMaxWidth;
qreal viewportDim;
if (m_rotateText) {
viewportDim = viewportRect.height();
textMaxHeight = maxWidth;
textMaxWidth = maxHeight;
} else {
viewportDim = viewportRect.width();
textMaxHeight = maxHeight;
textMaxWidth = maxWidth;
}
if (textHeight > textMaxHeight)
return;
if (viewportDim != m_previousViewportDimension) {
const QString &elidedText =
painter->fontMetrics().elidedText(m_text, Qt::ElideRight,
textMaxWidth);
m_staticText.setText(elidedText);
m_staticText.prepare();
m_previousViewportDimension = viewportDim;
}
#if VISUALISATION_DEBUG
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
#endif
painter->save();
int textLeft = 0;
int textTop = 0;
if (m_rotateText) {
painter->rotate(90);
textLeft = 2;
textTop = -textHeight/2;
}
else {
const int textWidth = painter->fontMetrics().width(m_staticText.text());
textLeft = -textWidth/2;
textTop = (maxHeight - textHeight)/2;
}
painter->drawStaticText(textLeft, textTop, m_staticText);
painter->restore();
}
QRectF FunctionGraphicsTextItem::boundingRect() const
{
return mapRectFromParent(parentItem()->boundingRect());
}
FunctionGraphicsItem::FunctionGraphicsItem(const QString &text,
qreal x, qreal y, qreal width,
qreal height, QGraphicsItem *parent)
: QGraphicsRectItem(x, y, width, height, parent)
, m_text(0)
{
setFlag(QGraphicsItem::ItemIsSelectable);
setFlag(QGraphicsItem::ItemClipsToShape);
setFlag(QGraphicsItem::ItemClipsChildrenToShape);
setToolTip(text);
m_text = new FunctionGraphicsTextItem(text, this);
m_text->setPos(rect().center().x(), y);
}
FunctionGraphicsTextItem *FunctionGraphicsItem::textItem() const
{
return m_text;
}
void FunctionGraphicsItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *)
{
painter->save();
QRectF rect = this->rect();
const QColor &color = brush().color();
if (option->state & QStyle::State_Selected) {
QLinearGradient gradient(0, 0, rect.width(), rect.height());
gradient.setColorAt(0, color.lighter(250));
gradient.setColorAt(1, color.darker());
painter->setBrush(gradient);
}
else {
painter->setBrush(color);
}
#if VISUALISATION_DEBUG
painter->setPen(Qt::blue);
painter->drawRect(boundingRect());
#endif
QPen pen = painter->pen();
pen.setColor(color.darker());
pen.setWidthF(0.5);
painter->setPen(pen);
qreal halfPenWidth = pen.widthF()/2.0;
rect.adjust(halfPenWidth, halfPenWidth, -halfPenWidth, -halfPenWidth);
painter->drawRect(rect);
painter->restore();
}
class Visualisation::Private
{
public:
Private(Visualisation *qq);
~Private();
void handleMousePressEvent(QMouseEvent *event, bool doubleClicked);
qreal sceneHeight() const;
qreal sceneWidth() const;
Visualisation *q;
DataProxyModel *m_model;
QGraphicsScene m_scene;
int m_modelColumn;
};
Visualisation::Private::Private(Visualisation *qq)
: q(qq)
, m_model(new DataProxyModel(qq))
, m_modelColumn(-1)
{
// setup scene
m_scene.setObjectName("Visualisation Scene");
///NOTE: with size 100x100 the Qt-internal mouse selection fails...
m_scene.setSceneRect(0, 0, 1024, 1024);
// setup model
m_model->setMinimumInclusiveCostRatio(0.1);
connect(m_model,
SIGNAL(filterFunctionChanged(const Function*,const Function*)),
qq, SLOT(populateScene()));
}
Visualisation::Private::~Private()
{
}
void Visualisation::Private::handleMousePressEvent(QMouseEvent *event,
bool doubleClicked)
{
// find the first item that accepts mouse presses under the cursor position
QGraphicsItem *itemAtPos = 0;
foreach(QGraphicsItem *item, q->items(event->pos())) {
if (!(item->acceptedMouseButtons() & event->button()))
continue;
itemAtPos = item;
break;
}
// if there is an item, select it
if (itemAtPos) {
const Function *func = q->functionForItem(itemAtPos);
if (doubleClicked) {
q->functionActivated(func);
}
else {
q->scene()->clearSelection();
itemAtPos->setSelected(true);
q->functionSelected(func);
}
}
}
qreal Visualisation::Private::sceneHeight() const
{
return m_scene.height() - FIT_IN_VIEW_MARGIN;
}
qreal Visualisation::Private::sceneWidth() const
{
// Magic number to improve margins appearance
return m_scene.width() + 1;
}
Visualisation::Visualisation(QWidget *parent)
: QGraphicsView(parent)
, d(new Private(this))
{
setObjectName("Visualisation View");
setScene(&d->m_scene);
setRenderHint(QPainter::Antialiasing);
}
Visualisation::~Visualisation()
{
delete d;
}
const Function *Visualisation::functionForItem(QGraphicsItem *item) const
{
return item->data(FunctionGraphicsItem::FunctionCallKey).value<const Function *>();
}
QGraphicsItem *Visualisation::itemForFunction(const Function *function) const
{
foreach(QGraphicsItem *item, items()) {
if (functionForItem(item) == function)
return item;
}
return 0;
}
void Visualisation::setFunction(const Function *function)
{
d->m_model->setFilterFunction(function);
}
const Function *Visualisation::function() const
{
return d->m_model->filterFunction();
}
void Visualisation::setModel(DataModel *model)
{
QTC_ASSERT(!d->m_model->sourceModel() && model, return); // only set once!
d->m_model->setSourceModel(model);
connect(model,
SIGNAL(columnsInserted(const QModelIndex&, int, int)),
SLOT(populateScene()));
connect(model,
SIGNAL(columnsMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
SLOT(populateScene()));
connect(model,
SIGNAL(columnsRemoved(const QModelIndex&, int, int)),
SLOT(populateScene()));
connect(model,
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
SLOT(populateScene()));
connect(model,
SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
SLOT(populateScene()));
connect(model, SIGNAL(layoutChanged()), SLOT(populateScene()));
connect(model, SIGNAL(modelReset()), SLOT(populateScene()));
connect(model,
SIGNAL(rowsInserted(const QModelIndex&, int, int)),
SLOT(populateScene()));
connect(model,
SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
SLOT(populateScene()));
connect(model,
SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
SLOT(populateScene()));
populateScene();
}
void Visualisation::setText(const QString &message)
{
d->m_scene.clear();
QGraphicsSimpleTextItem *textItem = d->m_scene.addSimpleText(message);
textItem->setBrush(palette().foreground());
textItem->setPos((d->sceneWidth() - textItem->boundingRect().width()) / 2,
(d->sceneHeight() - textItem->boundingRect().height()) / 2);
textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
}
void Visualisation::populateScene()
{
// reset scene first
d->m_scene.clear();
const qreal sceneWidth = d->sceneWidth();
const qreal sceneHeight = d->sceneHeight();
// cache costs of each element, calculate total costs
qreal total = 0;
typedef QPair<QModelIndex, qreal> Pair;
QLinkedList<Pair> costs;
for (int row=0; row < d->m_model->rowCount(); ++row)
{
const QModelIndex index = d->m_model->index(row, DataModel::InclusiveCostColumn);
bool ok = false;
const qreal cost = index.data().toReal(&ok);
QTC_ASSERT(ok, continue);
costs << QPair<QModelIndex, qreal>(d->m_model->index(row, 0), cost);
total += cost;
}
if (!costs.isEmpty() || d->m_model->filterFunction()) {
// item showing the current filter function
QString text;
if (d->m_model->filterFunction())
text = d->m_model->filterFunction()->name();
else {
const float ratioPercent = d->m_model->minimumInclusiveCostRatio() * 100;
QString ratioPercentString = QString::number(ratioPercent);
ratioPercentString.append(QLocale::system().percent());
const int hiddenFunctions = d->m_model->sourceModel()->rowCount() - d->m_model->rowCount();
text = tr("All functions with an inclusive cost ratio higher than %1 (%2 are hidden)")
.arg(ratioPercentString)
.arg(hiddenFunctions);
}
const qreal height = sceneHeight* (costs.isEmpty() ? 1.0 : 0.1);
FunctionGraphicsItem *item = new FunctionGraphicsItem(text, 0, 0, sceneWidth, height);
const QColor background = CallgrindHelper::colorForString(text);
item->setBrush(background);
item->setData(FunctionGraphicsItem::FunctionCallKey, QVariant::fromValue(d->m_model->filterFunction()));
item->textItem()->setRotateText(false);
// NOTE: workaround wrong tooltip being show, no idea why...
item->setZValue(-1);
d->m_scene.addItem(item);
}
// add the canvas elements to the scene
qreal used = 0;
foreach(const Pair &cost, costs)
{
const QModelIndex &index = cost.first;
const QString text = index.data().toString();
const qreal width = (sceneWidth * cost.second) / total;
const qreal height = sceneHeight * 0.9;
FunctionGraphicsItem *item = new FunctionGraphicsItem(text, used, sceneHeight - height, width, height);
const QColor background = CallgrindHelper::colorForString(text);
item->setBrush(background);
item->setData(FunctionGraphicsItem::FunctionCallKey, index.data(DataModel::FunctionRole));
d->m_scene.addItem(item);
used += width;
}
}
void Visualisation::mousePressEvent(QMouseEvent *event)
{
d->handleMousePressEvent(event, false);
QGraphicsView::mousePressEvent(event);
}
void Visualisation::mouseDoubleClickEvent(QMouseEvent *event)
{
d->handleMousePressEvent(event, true);
QGraphicsView::mouseDoubleClickEvent(event);
}
void Visualisation::resizeEvent(QResizeEvent *event)
{
fitInView(sceneRect());
QGraphicsView::resizeEvent(event);
}
} // Internal
} // Callgrind

View File

@@ -0,0 +1,94 @@
/**************************************************************************
**
** 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 CALLGRINDVISUALISATION_H
#define CALLGRINDVISUALISATION_H
#include <QGraphicsView>
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QModelIndex;
QT_END_NAMESPACE
namespace Valgrind {
namespace Callgrind {
class Function;
class DataModel;
}
}
namespace Callgrind {
namespace Internal {
class Visualisation : public QGraphicsView
{
Q_OBJECT
public:
explicit Visualisation(QWidget *parent = 0);
virtual ~Visualisation();
void setModel(Valgrind::Callgrind::DataModel *model);
const Valgrind::Callgrind::Function *functionForItem(QGraphicsItem *item) const;
QGraphicsItem *itemForFunction(const Valgrind::Callgrind::Function *function) const;
void setFunction(const Valgrind::Callgrind::Function *function);
const Valgrind::Callgrind::Function *function() const;
public slots:
void setText(const QString &message);
signals:
void functionActivated(const Valgrind::Callgrind::Function *);
void functionSelected(const Valgrind::Callgrind::Function *);
protected slots:
void populateScene();
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
protected:
virtual void resizeEvent(QResizeEvent *event);
private:
class Private;
Private *d;
};
} // Internal
} // Callgrind
#endif // VALGRIND_CALLGRIND_CALLGRINDVISUALISATION_H

View File

@@ -0,0 +1,504 @@
/**************************************************************************
**
** 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 "callgrindwidgethandler.h"
#include "callgrindcostview.h"
#include "callgrindengine.h"
#include "callgrindvisualisation.h"
#ifndef DISABLE_CALLGRIND_WORKAROUNDS
#include "workarounds.h"
#endif
#include <analyzerbase/analyzerconstants.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <valgrind/callgrind/callgrinddatamodel.h>
#include <valgrind/callgrind/callgrindparsedata.h>
#include <valgrind/callgrind/callgrindfunction.h>
#include <valgrind/callgrind/callgrindcostitem.h>
#include <valgrind/callgrind/callgrindstackbrowser.h>
#include <valgrind/callgrind/callgrindcallmodel.h>
#include <valgrind/callgrind/callgrindproxymodel.h>
#include <valgrind/callgrind/callgrindfunctioncall.h>
#include <utils/fancymainwindow.h>
#include <utils/styledbar.h>
#include <utils/qtcassert.h>
#include <QtCore/QTimer>
#include <QtGui/QHBoxLayout>
#include <QtGui/QCheckBox>
#include <QtGui/QLineEdit>
#include <QtGui/QGraphicsItem>
#include <QtGui/QToolButton>
#include <QtGui/QAction>
#include <QtGui/QLineEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QMenu>
#include <QtGui/QActionGroup>
#include <QSortFilterProxyModel>
#include <QComboBox>
using namespace Valgrind::Callgrind;
namespace Callgrind {
namespace Internal {
CallgrindWidgetHandler::CallgrindWidgetHandler(QWidget *parent)
: QObject(parent)
, m_dataModel(new DataModel(this))
, m_dataProxy(new DataProxyModel(this))
, m_stackBrowser(new StackBrowser(this))
, m_callersModel(new CallModel(this))
, m_calleesModel(new CallModel(this))
, m_flatView(0)
, m_callersView(0)
, m_calleesView(0)
, m_visualisation(0)
, m_goToOverview(0)
, m_goBack(0)
, m_searchFilter(0)
, m_filterProjectCosts(0)
, m_costAbsolute(0)
, m_costRelative(0)
, m_costRelativeToParent(0)
, m_eventCombo(0)
, m_updateTimer(new QTimer(this))
{
connect(m_stackBrowser, SIGNAL(currentChanged()), this, SLOT(stackBrowserChanged()));
m_updateTimer->setInterval(200);
m_updateTimer->setSingleShot(true);
connect(m_updateTimer, SIGNAL(timeout()), SLOT(updateFilterString()));
m_dataProxy->setSourceModel(m_dataModel);
m_dataProxy->setDynamicSortFilter(true);
m_dataProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
m_dataProxy->setFilterKeyColumn(DataModel::NameColumn);
m_dataProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_flatView = new CostView(parent);
m_flatView->sortByColumn(DataModel::SelfCostColumn);
m_flatView->setFrameStyle(QFrame::NoFrame);
m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false);
m_flatView->setModel(m_dataProxy);
m_flatView->setObjectName("Valgrind.CallgrindWidgetHandler.FlatView");
connect(m_flatView, SIGNAL(activated(QModelIndex)),
this, SLOT(dataFunctionSelected(QModelIndex)));
m_visualisation = new Visualisation(parent);
m_visualisation->setObjectName("Valgrind.CallgrindWidgetHandler.Visualisation");
m_visualisation->setModel(m_dataModel);
connect(m_visualisation, SIGNAL(functionActivated(const Valgrind::Callgrind::Function*)),
this, SLOT(visualisationFunctionSelected(const Valgrind::Callgrind::Function*)));
{
m_calleesView = new CostView(parent);
m_calleesView->sortByColumn(CallModel::CostColumn);
m_calleesView->setObjectName("Valgrind.CallgrindWidgetHandler.CalleesView");
// enable sorting
QSortFilterProxyModel *calleeProxy = new QSortFilterProxyModel(m_calleesModel);
calleeProxy->setSourceModel(m_calleesModel);
m_calleesView->setModel(calleeProxy);
m_calleesView->hideColumn(CallModel::CallerColumn);
connect(m_calleesView, SIGNAL(activated(QModelIndex)),
this, SLOT(calleeFunctionSelected(QModelIndex)));
}
{
m_callersView = new CostView(parent);
m_callersView->sortByColumn(CallModel::CostColumn);
m_callersView->setObjectName("Valgrind.CallgrindWidgetHandler.CallersView");
// enable sorting
QSortFilterProxyModel *callerProxy = new QSortFilterProxyModel(m_callersModel);
callerProxy->setSourceModel(m_callersModel);
m_callersView->setModel(callerProxy);
m_callersView->hideColumn(CallModel::CalleeColumn);
connect(m_callersView, SIGNAL(activated(QModelIndex)),
this, SLOT(callerFunctionSelected(QModelIndex)));
}
}
void CallgrindWidgetHandler::populateActions(QLayout *layout)
{
// navigation
{
QToolButton *button;
QAction *action;
// go back
action = new QAction(this);
action->setDisabled(true);
action->setIcon(QIcon::fromTheme("go-previous"));
action->setText(tr("Back"));
action->setToolTip(tr("Go back one step in history. This will select the previously selected item."));
m_goBack = action;
connect(action, SIGNAL(triggered(bool)), m_stackBrowser, SLOT(goBack()));
button = new QToolButton;
button->setDefaultAction(action);
layout->addWidget(button);
// overview
action = new QAction(this);
action->setDisabled(true);
action->setIcon(QIcon::fromTheme("go-up"));
action->setText(tr("All Functions"));
action->setToolTip(tr("Show the overview of all function calls."));
m_goToOverview = action;
connect(action, SIGNAL(triggered(bool)), this, SLOT(slotGoToOverview()));
button = new QToolButton;
button->setDefaultAction(action);
layout->addWidget(button);
}
layout->addWidget(new Utils::StyledSeparator);
// event selection
{
m_eventCombo = new QComboBox;
m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized."));
connect(m_eventCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setCostEvent(int)));
updateEventCombo();
layout->addWidget(m_eventCombo);
}
// cost formatting
{
QMenu *menu = new QMenu(layout->parentWidget());
QActionGroup *group = new QActionGroup(this);
// show costs as absolute numbers
m_costAbsolute = new QAction(tr("Absolute Costs"), this);
///FIXME: icon
m_costAbsolute->setToolTip(tr("Show costs as absolute numbers."));
m_costAbsolute->setCheckable(true);
m_costAbsolute->setChecked(true);
connect(m_costAbsolute, SIGNAL(toggled(bool)),
this, SLOT(updateCostFormat()));
group->addAction(m_costAbsolute);
menu->addAction(m_costAbsolute);
// show costs in percentages
m_costRelative = new QAction(tr("Relative Costs"), this);
///FIXME: icon (percentage sign?)
m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost."));
m_costRelative->setCheckable(true);
connect(m_costRelative, SIGNAL(toggled(bool)),
this, SLOT(updateCostFormat()));
group->addAction(m_costRelative);
menu->addAction(m_costRelative);
// show costs relative to parent
m_costRelativeToParent = new QAction(tr("Relative Costs To Parent"), this);
///FIXME: icon
m_costRelativeToParent->setToolTip(tr("Show costs relative to parent functions inclusive cost."));
m_costRelativeToParent->setCheckable(true);
connect(m_costRelativeToParent, SIGNAL(toggled(bool)),
this, SLOT(updateCostFormat()));
group->addAction(m_costRelativeToParent);
menu->addAction(m_costRelativeToParent);
QToolButton *button = new QToolButton;
button->setMenu(menu);
button->setPopupMode(QToolButton::InstantPopup);
button->setText(tr("Cost Format"));
layout->addWidget(button);
}
{
// cycle detection
m_cycleDetection = new QAction(tr("Cycle Detection"), this);
///FIXME: icon
m_cycleDetection->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls."));
connect(m_cycleDetection, SIGNAL(toggled(bool)),
m_dataModel, SLOT(enableCycleDetection(bool)));
connect(m_cycleDetection, SIGNAL(toggled(bool)),
this, SIGNAL(cycleDetectionEnabled(bool)));
m_cycleDetection->setCheckable(true);
QToolButton *button = new QToolButton;
button->setDefaultAction(m_cycleDetection);
layout->addWidget(button);
}
// filtering
{
QToolButton *button;
m_filterProjectCosts = new QAction(tr("Show Project Costs Only"), this);
m_filterProjectCosts->setIcon(QIcon(Core::Constants::ICON_FILTER));
m_filterProjectCosts->setToolTip(tr("Show only profiling info that originated from this project source."));
m_filterProjectCosts->setCheckable(true);
connect(m_filterProjectCosts, SIGNAL(toggled(bool)),
this, SLOT( handleFilterProjectCosts()));
button = new QToolButton;
button->setDefaultAction(m_filterProjectCosts);
layout->addWidget(button);
// filter
///FIXME: find workaround for http://bugreports.qt.nokia.com/browse/QTCREATORBUG-3247
QLineEdit *filter = new QLineEdit;
filter->setPlaceholderText(tr("Filter..."));
connect(filter, SIGNAL(textChanged(QString)),
m_updateTimer, SLOT(start()));
layout->addWidget(filter);
m_searchFilter = filter;
}
layout->addWidget(new Utils::StyledSeparator);
}
CallgrindWidgetHandler::~CallgrindWidgetHandler()
{
slotClear();
}
void CallgrindWidgetHandler::slotGoToOverview()
{
selectFunction(0);
}
void CallgrindWidgetHandler::slotClear()
{
setParseData(0);
// clear filters
m_filterProjectCosts->setChecked(false);
m_dataProxy->setFilterBaseDir(QString());
m_searchFilter->setText(QString());
m_dataProxy->setFilterFixedString(QString());
}
void CallgrindWidgetHandler::slotRequestDump()
{
m_visualisation->setText(tr("Populating..."));
emit dumpRequested();
}
void CallgrindWidgetHandler::selectFunction(const Function *func)
{
if (!func) {
m_goToOverview->setDisabled(true);
m_flatView->clearSelection();
m_visualisation->setFunction(0);
m_callersModel->clear();
m_calleesModel->clear();
emit functionSelected(0);
return;
}
m_goToOverview->setEnabled(true);
const QModelIndex index = m_dataModel->indexForObject(func);
const QModelIndex proxyIndex = m_dataProxy->mapFromSource(index);
m_flatView->selectionModel()->clearSelection();
m_flatView->selectionModel()->setCurrentIndex(proxyIndex,
QItemSelectionModel::ClearAndSelect |
QItemSelectionModel::Rows);
m_flatView->scrollTo(proxyIndex);
m_callersModel->setCalls(func->incomingCalls(), func);
m_calleesModel->setCalls(func->outgoingCalls(), func);
m_visualisation->setFunction(func);
FunctionHistoryItem *item = dynamic_cast<FunctionHistoryItem *>(m_stackBrowser->current());
if (!item || item->function() != func)
m_stackBrowser->select(new FunctionHistoryItem(func));
emit functionSelected(func);
}
void CallgrindWidgetHandler::stackBrowserChanged()
{
FunctionHistoryItem *item = dynamic_cast<FunctionHistoryItem *>(m_stackBrowser->current());
if (!item || item->function() == 0)
m_goBack->setDisabled(true);
else
m_goBack->setEnabled(true);
selectFunction(item ? item->function() : 0);
}
void CallgrindWidgetHandler::updateFilterString()
{
m_dataProxy->setFilterFixedString(m_searchFilter->text());
}
void CallgrindWidgetHandler::setCostFormat(CostDelegate::CostFormat format)
{
switch(format) {
case CostDelegate::FormatAbsolute:
m_costAbsolute->setChecked(true);
break;
case CostDelegate::FormatRelative:
m_costRelative->setChecked(true);
break;
case CostDelegate::FormatRelativeToParent:
m_costRelativeToParent->setChecked(true);
break;
}
}
void CallgrindWidgetHandler::setCostEvent(int index)
{
// prevent assert in model, don't try to set event to -1
// happens when we clear the eventcombo
if (index == -1)
index = 0;
m_dataModel->setCostEvent(index);
m_calleesModel->setCostEvent(index);
m_callersModel->setCostEvent(index);
}
void CallgrindWidgetHandler::enableCycleDetection(bool enabled)
{
m_cycleDetection->setChecked(enabled);
}
void CallgrindWidgetHandler::updateCostFormat()
{
CostDelegate::CostFormat format = CostDelegate::FormatAbsolute;
if (m_costRelativeToParent->isChecked())
format = CostDelegate::FormatRelativeToParent;
else if (m_costRelative->isChecked())
format = CostDelegate::FormatRelative;
// else = Absolute
m_flatView->setCostFormat(format);
m_calleesView->setCostFormat(format);
m_callersView->setCostFormat(format);
emit costFormatChanged(format);
}
void CallgrindWidgetHandler::handleFilterProjectCosts()
{
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
ProjectExplorer::Project *pro = pe->currentProject();
QTC_ASSERT(pro, return)
if (m_filterProjectCosts->isChecked()) {
const QString projectDir = pro->projectDirectory();
m_dataProxy->setFilterBaseDir(projectDir);
}
else {
m_dataProxy->setFilterBaseDir(QString());
}
}
void CallgrindWidgetHandler::dataFunctionSelected(const QModelIndex &index)
{
const Function *func = index.data(DataModel::FunctionRole).value<const Function *>();
QTC_ASSERT(func, return);
selectFunction(func);
}
void CallgrindWidgetHandler::calleeFunctionSelected(const QModelIndex &index)
{
const FunctionCall *call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
QTC_ASSERT(call, return);
selectFunction(call->callee());
}
void CallgrindWidgetHandler::callerFunctionSelected(const QModelIndex &index)
{
const FunctionCall *call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
QTC_ASSERT(call, return);
selectFunction(call->caller());
}
void CallgrindWidgetHandler::visualisationFunctionSelected(const Function *function)
{
if (function && function == m_visualisation->function())
// up-navigation when the initial function was activated
m_stackBrowser->goBack();
else
selectFunction(function);
}
void CallgrindWidgetHandler::setParseData(ParseData *data)
{
// we have new parse data, invalidate filters in the proxy model
m_visualisation->setFunction(0);
// invalidate parse data in the data model
delete m_dataModel->parseData();
if (data && data->events().isEmpty()) {
// might happen if the user cancelled the profile run
// callgrind then sometimes produces empty callgrind.out.PID files
delete data;
data = 0;
}
m_dataModel->setParseData(data);
m_calleesModel->setParseData(data);
m_callersModel->setParseData(data);
updateEventCombo();
// clear history for new data
m_stackBrowser->clear();
}
void CallgrindWidgetHandler::updateEventCombo()
{
QTC_ASSERT(m_eventCombo, return)
m_eventCombo->clear();
const ParseData *data = m_dataModel->parseData();
if (!data || data->events().isEmpty()) {
m_eventCombo->hide();
return;
}
m_eventCombo->show();
foreach(const QString &event, data->events())
m_eventCombo->addItem(ParseData::prettyStringForEvent(event));
}
}
}

View File

@@ -0,0 +1,162 @@
/**************************************************************************
**
** 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 CALLGRINDWIDGETHANDLER_H
#define CALLGRINDWIDGETHANDLER_H
#include <QObject>
#include "callgrindcostdelegate.h"
QT_BEGIN_NAMESPACE
class QToolButton;
class QAction;
class QLineEdit;
class QModelIndex;
class QSortFilterProxyModel;
class QTimer;
class QComboBox;
QT_END_NAMESPACE
namespace Valgrind {
namespace Callgrind {
class DataModel;
class DataProxyModel;
class Function;
class ParseData;
class StackBrowser;
class CallModel;
}
}
namespace Callgrind {
namespace Internal {
class CallgrindEngine;
class Visualisation;
class CostView;
/**
* Encapsulates all widgets required for a fully operational callgrind UI.
* Prevents code duplication between QtC code and unit tests.
*/
class CallgrindWidgetHandler : public QObject
{
Q_OBJECT
public:
explicit CallgrindWidgetHandler(QWidget *parent);
virtual ~CallgrindWidgetHandler();
void populateActions(QLayout *layout);
void setParseData(Valgrind::Callgrind::ParseData *data);
Valgrind::Callgrind::DataModel *dataModel() const { return m_dataModel; }
Valgrind::Callgrind::DataProxyModel *proxyModel() const { return m_dataProxy; }
CostView *flatView() const { return m_flatView; }
Visualisation *visualisation() const { return m_visualisation; }
Valgrind::Callgrind::CallModel *callersModel() const { return m_callersModel; }
CostView *callersView() const { return m_callersView; }
Valgrind::Callgrind::CallModel *calleesModel() const { return m_calleesModel; }
CostView *calleesView() const { return m_calleesView; }
signals:
void dumpRequested();
void resetRequested();
void pauseToggled(bool checked);
void functionSelected(const Valgrind::Callgrind::Function *);
void costFormatChanged(Callgrind::Internal::CostDelegate::CostFormat format);
void cycleDetectionEnabled(bool enabled);
public slots:
void slotClear();
void slotRequestDump();
void selectFunction(const Valgrind::Callgrind::Function *);
void setCostFormat(Callgrind::Internal::CostDelegate::CostFormat format);
void enableCycleDetection(bool enabled);
void setCostEvent(int index);
private slots:
void updateFilterString();
void updateCostFormat();
void handleFilterProjectCosts();
void slotGoToOverview();
void stackBrowserChanged();
void dataFunctionSelected(const QModelIndex &index);
void calleeFunctionSelected(const QModelIndex &index);
void callerFunctionSelected(const QModelIndex &index);
void visualisationFunctionSelected(const Valgrind::Callgrind::Function *function);
private:
void updateEventCombo();
Valgrind::Callgrind::DataModel *m_dataModel;
Valgrind::Callgrind::DataProxyModel *m_dataProxy;
Valgrind::Callgrind::StackBrowser *m_stackBrowser;
Valgrind::Callgrind::CallModel *m_callersModel;
Valgrind::Callgrind::CallModel *m_calleesModel;
CostView *m_flatView;
CostView *m_callersView;
CostView *m_calleesView;
Visualisation *m_visualisation;
// navigation
QAction *m_goToOverview;
QAction *m_goBack;
QLineEdit *m_searchFilter;
// cost formatting
QAction *m_filterProjectCosts;
QAction *m_costAbsolute;
QAction *m_costRelative;
QAction *m_costRelativeToParent;
QAction *m_cycleDetection;
QComboBox *m_eventCombo;
QTimer *m_updateTimer;
};
} // namespace Internal
} // namespace Callgrind
#endif // CALLGRINDWIDGETHANDLER_H

View File

@@ -0,0 +1,51 @@
/**************************************************************************
**
** 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 "workarounds.h"
#include <QtGui/QPalette>
#include <utils/stylehelper.h>
QPalette panelPalette(const QPalette &oldPalette, bool lightColored)
{
QColor color = Utils::StyleHelper::panelTextColor(lightColored);
QPalette pal = oldPalette;
pal.setBrush(QPalette::All, QPalette::WindowText, color);
pal.setBrush(QPalette::All, QPalette::ButtonText, color);
pal.setBrush(QPalette::All, QPalette::Foreground, color);
color.setAlpha(100);
pal.setBrush(QPalette::Disabled, QPalette::WindowText, color);
pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
pal.setBrush(QPalette::Disabled, QPalette::Foreground, color);
return pal;
}

View File

@@ -0,0 +1,45 @@
/**************************************************************************
**
** 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 WORKAROUNDS_H
#define WORKAROUNDS_H
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
class QPalette;
QT_END_NAMESPACE
///FIXME: remove this once http://bugreports.qt.nokia.com/browse/QTCREATORBUG-3247 gets fixed
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false);
#endif // WORKAROUNDS_H

View File

@@ -44,7 +44,8 @@ SUBDIRS = plugin_coreplugin \
!win32 { !win32 {
SUBDIRS += plugin_valgrindtoolbase \ SUBDIRS += plugin_valgrindtoolbase \
plugin_memcheck plugin_memcheck \
plugin_callgrind
} }
linux-* { linux-* {
@@ -263,6 +264,11 @@ plugin_analyzerbase.depends += plugin_projectexplorer
plugin_memcheck.depends += plugin_analyzerbase plugin_memcheck.depends += plugin_analyzerbase
plugin_memcheck.depends += plugin_valgrindtoolbase plugin_memcheck.depends += plugin_valgrindtoolbase
plugin_callgrind.subdir = callgrind
plugin_callgrind.depends = plugin_coreplugin
plugin_callgrind.depends += plugin_analyzerbase
plugin_callgrind.depends += plugin_valgrindtoolbase
plugin_qmlprofiler.subdir = qmlprofiler plugin_qmlprofiler.subdir = qmlprofiler
plugin_qmlprofiler.depends = plugin_coreplugin plugin_qmlprofiler.depends = plugin_coreplugin
plugin_qmlprofiler.depends = plugin_analyzerbase plugin_qmlprofiler.depends = plugin_analyzerbase