forked from qt-creator/qt-creator
analyzer: merge valgrind based tool plugins
It is hard to imagine there is a real use case that someone wants one but absolutely not the other. Change-Id: I58bb57912f2edeacf2d5a24e3b2eb5a81262eabd Reviewed-on: http://codereview.qt.nokia.com/66 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
20
src/plugins/valgrind/Valgrind.pluginspec.in
Normal file
20
src/plugins/valgrind/Valgrind.pluginspec.in
Normal file
@@ -0,0 +1,20 @@
|
||||
<plugin name=\"Valgrind\" 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 Plugin</description>
|
||||
<url>http://qt.nokia.com</url>
|
||||
<dependencyList>
|
||||
<dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
|
||||
<dependency name=\"AnalyzerBase\" version=\"$$QTCREATOR_VERSION\"/>
|
||||
</dependencyList>
|
||||
</plugin>
|
||||
94
src/plugins/valgrind/callgrindconfigwidget.cpp
Normal file
94
src/plugins/valgrind/callgrindconfigwidget.cpp
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "callgrindconfigwidget.h"
|
||||
|
||||
#include "ui_callgrindconfigwidget.h"
|
||||
|
||||
#include "callgrindsettings.h"
|
||||
|
||||
using namespace Valgrind::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)));
|
||||
|
||||
m_ui->enableEventToolTips->setChecked(m_settings->enableEventToolTips());
|
||||
connect(m_ui->enableEventToolTips, SIGNAL(toggled(bool)),
|
||||
m_settings, SLOT(setEnableEventToolTips(bool)));
|
||||
connect(m_settings, SIGNAL(enableEventToolTipsChanged(bool)),
|
||||
m_ui->enableEventToolTips, SLOT(setChecked(bool)));
|
||||
|
||||
m_ui->minimumInclusiveCostRatio->setValue(m_settings->minimumInclusiveCostRatio());
|
||||
connect(m_ui->minimumInclusiveCostRatio, SIGNAL(valueChanged(double)),
|
||||
m_settings, SLOT(setMinimumInclusiveCostRatio(double)));
|
||||
connect(m_settings, SIGNAL(minimumInclusiveCostRatioChanged(double)),
|
||||
m_ui->minimumInclusiveCostRatio, SLOT(setValue(double)));
|
||||
|
||||
m_ui->visualisationMinimumInclusiveCostRatio->setValue(m_settings->visualisationMinimumInclusiveCostRatio());
|
||||
connect(m_ui->visualisationMinimumInclusiveCostRatio, SIGNAL(valueChanged(double)),
|
||||
m_settings, SLOT(setVisualisationMinimumInclusiveCostRatio(double)));
|
||||
connect(m_settings, SIGNAL(visualisationMinimumInclusiveCostRatioChanged(double)),
|
||||
m_ui->visualisationMinimumInclusiveCostRatio, SLOT(setValue(double)));
|
||||
}
|
||||
|
||||
CallgrindConfigWidget::~CallgrindConfigWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
61
src/plugins/valgrind/callgrindconfigwidget.h
Normal file
61
src/plugins/valgrind/callgrindconfigwidget.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
|
||||
#define ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class CallgrindConfigWidget;
|
||||
}
|
||||
|
||||
class AbstractCallgrindSettings;
|
||||
|
||||
class CallgrindConfigWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
CallgrindConfigWidget(AbstractCallgrindSettings *settings, QWidget *parent);
|
||||
virtual ~CallgrindConfigWidget();
|
||||
|
||||
private:
|
||||
Ui::CallgrindConfigWidget *m_ui;
|
||||
AbstractCallgrindSettings *m_settings;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // ANALYZER_INTERNAL_CALLGRINDCONFIGWIDGET_H
|
||||
174
src/plugins/valgrind/callgrindconfigwidget.ui
Normal file
174
src/plugins/valgrind/callgrindconfigwidget.ui
Normal file
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Valgrind::Internal::CallgrindConfigWidget</class>
|
||||
<widget class="QWidget" name="Valgrind::Internal::CallgrindConfigWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>416</width>
|
||||
<height>565</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<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="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="minimumInclusiveCostRatioLabel">
|
||||
<property name="toolTip">
|
||||
<string>This option limits the amount of results the profiler will give you. A lower limit will likely increase performance.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Result view: Show events with inclusive costs higher than:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>minimumInclusiveCostRatio</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="minimumInclusiveCostRatio">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="enableEventToolTips">
|
||||
<property name="title">
|
||||
<string>Show additional information for events in tooltips</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="enableCacheSim">
|
||||
<property name="toolTip">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">
|
||||
<p>Specify if you want to do full cache simulation.</p>
|
||||
<p>By default, only instruction read accesses will be counted ("Ir").</p>
|
||||
|
||||
<p>
|
||||
With cache simulation, further event counters are enabled:
|
||||
<ul><li>Cache misses on instruction reads ("I1mr"/"I2mr")</li>
|
||||
<li>Data read accesses ("Dr") and related cache misses ("D1mr"/"D2mr")</li>
|
||||
<li>Data write accesses ("Dw") and related cache misses ("D1mw"/"D2mw")</li></ul>
|
||||
</p>
|
||||
|
||||
For more information, see ???.</p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p>Specify if you want to do branch prediction simulation.</p>
|
||||
<p>Further event counters are enabled: </p>
|
||||
<ul><li>Number of executed conditional branches and related predictor misses (
|
||||
"Bc"/"Bcm")</li>
|
||||
<li>Executed indirect jumps and related misses of the jump address predictor (
|
||||
"Bi"/"Bim")</li></ul></body></html></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 "Ge" is used for these events.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Collect global bus events:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="visualisationMinimumInclusiveCostRatioLabel">
|
||||
<property name="text">
|
||||
<string>Visualisation: Show events with inclusive costs higher than:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="visualisationMinimumInclusiveCostRatio">
|
||||
<property name="prefix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>50.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" 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>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
181
src/plugins/valgrind/callgrindcostdelegate.cpp
Normal file
181
src/plugins/valgrind/callgrindcostdelegate.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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 <QtGui/QApplication>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
using namespace Valgrind::Callgrind;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class CostDelegate::Private
|
||||
{
|
||||
public:
|
||||
Private();
|
||||
|
||||
QAbstractItemModel *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)
|
||||
{}
|
||||
|
||||
int CostDelegate::Private::toNativeRole(CostDelegate::CostFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case FormatAbsolute:
|
||||
case FormatRelative:
|
||||
return Valgrind::Callgrind::RelativeTotalCostRole;
|
||||
case FormatRelativeToParent:
|
||||
return Valgrind::Callgrind::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(QAbstractItemModel *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;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
75
src/plugins/valgrind/callgrindcostdelegate.h
Normal file
75
src/plugins/valgrind/callgrindcostdelegate.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDCOSTDELEGATE_H
|
||||
#define CALLGRINDCOSTDELEGATE_H
|
||||
|
||||
#include <QtGui/QStyledItemDelegate>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class CostDelegate : public QStyledItemDelegate
|
||||
{
|
||||
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(QAbstractItemModel *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;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
Q_DECLARE_METATYPE(Valgrind::Internal::CostDelegate::CostFormat)
|
||||
|
||||
#endif // CALLGRINDCOSTDELEGATE_H
|
||||
134
src/plugins/valgrind/callgrindcostview.cpp
Normal file
134
src/plugins/valgrind/callgrindcostview.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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 Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class CostView::Private
|
||||
{
|
||||
public:
|
||||
explicit Private(CostView *qq);
|
||||
|
||||
CostDelegate *m_costDelegate;
|
||||
NameDelegate *m_nameDelegate;
|
||||
};
|
||||
|
||||
CostView::Private::Private(CostView *qq)
|
||||
: m_costDelegate(new CostDelegate(qq))
|
||||
, m_nameDelegate(new NameDelegate(qq))
|
||||
{}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
forever {
|
||||
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 (qobject_cast<CallModel *>(model)) {
|
||||
headerView->setResizeMode(CallModel::CalleeColumn, QHeaderView::Stretch);
|
||||
headerView->setResizeMode(CallModel::CallerColumn, QHeaderView::Stretch);
|
||||
headerView->setResizeMode(CallModel::CallsColumn, QHeaderView::ResizeToContents);
|
||||
headerView->setResizeMode(CallModel::CostColumn, QHeaderView::ResizeToContents);
|
||||
setItemDelegateForColumn(CallModel::CalleeColumn, d->m_nameDelegate);
|
||||
setItemDelegateForColumn(CallModel::CallerColumn, d->m_nameDelegate);
|
||||
setItemDelegateForColumn(CallModel::CostColumn, d->m_costDelegate);
|
||||
} else if (qobject_cast<DataModel *>(model)) {
|
||||
headerView->setResizeMode(DataModel::InclusiveCostColumn, QHeaderView::ResizeToContents);
|
||||
headerView->setResizeMode(DataModel::LocationColumn, QHeaderView::Stretch);
|
||||
headerView->setResizeMode(DataModel::NameColumn, QHeaderView::Stretch);
|
||||
headerView->setResizeMode(DataModel::SelfCostColumn, QHeaderView::ResizeToContents);
|
||||
setItemDelegateForColumn(DataModel::InclusiveCostColumn, d->m_costDelegate);
|
||||
setItemDelegateForColumn(DataModel::NameColumn, d->m_nameDelegate);
|
||||
setItemDelegateForColumn(DataModel::SelfCostColumn, d->m_costDelegate);
|
||||
}
|
||||
|
||||
d->m_costDelegate->setModel(model);
|
||||
}
|
||||
|
||||
void CostView::setCostFormat(CostDelegate::CostFormat format)
|
||||
{
|
||||
d->m_costDelegate->setFormat(format);
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
CostDelegate::CostFormat CostView::costFormat() const
|
||||
{
|
||||
return d->m_costDelegate->format();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
71
src/plugins/valgrind/callgrindcostview.h
Normal file
71
src/plugins/valgrind/callgrindcostview.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDCOSTVIEW_H
|
||||
#define CALLGRINDCOSTVIEW_H
|
||||
|
||||
#include <QtGui/QTreeView>
|
||||
|
||||
#include "callgrindcostdelegate.h"
|
||||
|
||||
namespace Valgrind {
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // CALLGRINDCOSTVIEW_H
|
||||
170
src/plugins/valgrind/callgrindengine.cpp
Normal file
170
src/plugins/valgrind/callgrindengine.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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 Valgrind;
|
||||
using namespace Valgrind::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);
|
||||
}
|
||||
|
||||
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 only if it is attached to a valgrind process
|
||||
if (m_runner.controller()->valgrindProcess()) {
|
||||
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);;
|
||||
}
|
||||
94
src/plugins/valgrind/callgrindengine.h
Normal file
94
src/plugins/valgrind/callgrindengine.h
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDENGINE_H
|
||||
#define CALLGRINDENGINE_H
|
||||
|
||||
#include <valgrind/valgrindengine.h>
|
||||
|
||||
#include <valgrind/callgrind/callgrindrunner.h>
|
||||
#include <valgrind/callgrind/callgrindparsedata.h>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class CallgrindEngine : public Valgrind::Internal::ValgrindEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CallgrindEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
|
||||
void start();
|
||||
|
||||
Valgrind::Callgrind::ParseData *takeParserData();
|
||||
|
||||
public slots:
|
||||
// controller actions
|
||||
void dump();
|
||||
void reset();
|
||||
void pause();
|
||||
void unpause();
|
||||
|
||||
/// marks the callgrind process as paused
|
||||
/// calls pause() and unpause() if there's an active run
|
||||
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 Valgrind
|
||||
|
||||
#endif // CALLGRINDENGINE_H
|
||||
77
src/plugins/valgrind/callgrindhelper.cpp
Normal file
77
src/plugins/valgrind/callgrindhelper.cpp
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "callgrindhelper.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace 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();
|
||||
if (costs > 9.99f)
|
||||
return locale.toString(costs, 'f', 1) + locale.percent();
|
||||
if (costs > 0.009f)
|
||||
return locale.toString(costs, 'f', 2) + locale.percent();
|
||||
return QString("<") + locale.toString(0.01f) + locale.percent();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
68
src/plugins/valgrind/callgrindhelper.h
Normal file
68
src/plugins/valgrind/callgrindhelper.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDHELPER_H
|
||||
#define CALLGRINDHELPER_H
|
||||
|
||||
#include <QtCore/QLocale>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QColor;
|
||||
class QString;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Valgrind {
|
||||
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());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // CALLGRINDHELPER_H
|
||||
95
src/plugins/valgrind/callgrindnamedelegate.cpp
Normal file
95
src/plugins/valgrind/callgrindnamedelegate.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "callgrindnamedelegate.h"
|
||||
|
||||
#include "callgrindhelper.h"
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
namespace Valgrind {
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
56
src/plugins/valgrind/callgrindnamedelegate.h
Normal file
56
src/plugins/valgrind/callgrindnamedelegate.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDNAMEDELEGATE_H
|
||||
#define CALLGRINDNAMEDELEGATE_H
|
||||
|
||||
#include <QtGui/QStyledItemDelegate>
|
||||
|
||||
namespace Valgrind {
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // CALLGRINDNAMEDELEGATE_H
|
||||
226
src/plugins/valgrind/callgrindsettings.cpp
Normal file
226
src/plugins/valgrind/callgrindsettings.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "callgrindsettings.h"
|
||||
|
||||
#include "callgrindconfigwidget.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace Analyzer;
|
||||
|
||||
static const char callgrindEnableCacheSimC[] = "Analyzer.Valgrind.Callgrind.EnableCacheSim";
|
||||
static const char callgrindEnableBranchSimC[] = "Analyzer.Valgrind.Callgrind.EnableBranchSim";
|
||||
static const char callgrindCollectSystimeC[] = "Analyzer.Valgrind.Callgrind.CollectSystime";
|
||||
static const char callgrindCollectBusEventsC[] = "Analyzer.Valgrind.Callgrind.CollectBusEvents";
|
||||
static const char callgrindEnableEventToolTipsC[] = "Analyzer.Valgrind.Callgrind.EnableEventToolTips";
|
||||
static const char callgrindMinimumCostRatioC[] = "Analyzer.Valgrind.Callgrind.MinimumCostRatio";
|
||||
static const char callgrindVisualisationMinimumCostRatioC[] = "Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio";
|
||||
|
||||
static const char callgrindCycleDetectionC[] = "Analyzer.Valgrind.Callgrind.CycleDetection";
|
||||
static const char callgrindCostFormatC[] = "Analyzer.Valgrind.Callgrind.CostFormat";
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void AbstractCallgrindSettings::setEnableEventToolTips(bool enable)
|
||||
{
|
||||
if (m_enableEventToolTips == enable)
|
||||
return;
|
||||
|
||||
m_enableEventToolTips = enable;
|
||||
emit enableEventToolTipsChanged(enable);
|
||||
}
|
||||
|
||||
void AbstractCallgrindSettings::setMinimumInclusiveCostRatio(
|
||||
double minimumInclusiveCostRatio)
|
||||
{
|
||||
if (m_minimumInclusiveCostRatio == minimumInclusiveCostRatio)
|
||||
return;
|
||||
|
||||
m_minimumInclusiveCostRatio = qBound(0.0, minimumInclusiveCostRatio, 100.0);
|
||||
emit minimumInclusiveCostRatioChanged(minimumInclusiveCostRatio);
|
||||
}
|
||||
|
||||
void AbstractCallgrindSettings::setVisualisationMinimumInclusiveCostRatio(
|
||||
double minimumInclusiveCostRatio)
|
||||
{
|
||||
if (m_visualisationMinimumInclusiveCostRatio == minimumInclusiveCostRatio)
|
||||
return;
|
||||
|
||||
m_visualisationMinimumInclusiveCostRatio = qBound(0.0, minimumInclusiveCostRatio, 100.0);
|
||||
emit visualisationMinimumInclusiveCostRatioChanged(minimumInclusiveCostRatio);
|
||||
}
|
||||
|
||||
QVariantMap AbstractCallgrindSettings::defaults() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(QLatin1String(callgrindEnableCacheSimC), false);
|
||||
map.insert(QLatin1String(callgrindEnableBranchSimC), false);
|
||||
map.insert(QLatin1String(callgrindCollectSystimeC), false);
|
||||
map.insert(QLatin1String(callgrindCollectBusEventsC), false);
|
||||
map.insert(QLatin1String(callgrindEnableEventToolTipsC), true);
|
||||
map.insert(QLatin1String(callgrindMinimumCostRatioC), 0.01);
|
||||
map.insert(QLatin1String(callgrindVisualisationMinimumCostRatioC), 10.0);
|
||||
return map;
|
||||
}
|
||||
|
||||
bool AbstractCallgrindSettings::fromMap(const QVariantMap &map)
|
||||
{
|
||||
setIfPresent(map, QLatin1String(callgrindEnableCacheSimC), &m_enableCacheSim);
|
||||
setIfPresent(map, QLatin1String(callgrindEnableBranchSimC), &m_enableBranchSim);
|
||||
setIfPresent(map, QLatin1String(callgrindCollectSystimeC), &m_collectSystime);
|
||||
setIfPresent(map, QLatin1String(callgrindCollectBusEventsC), &m_collectBusEvents);
|
||||
setIfPresent(map, QLatin1String(callgrindEnableEventToolTipsC), &m_enableEventToolTips);
|
||||
setIfPresent(map, QLatin1String(callgrindMinimumCostRatioC), &m_minimumInclusiveCostRatio);
|
||||
setIfPresent(map, QLatin1String(callgrindVisualisationMinimumCostRatioC),
|
||||
&m_visualisationMinimumInclusiveCostRatio);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap AbstractCallgrindSettings::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(QLatin1String(callgrindEnableCacheSimC), m_enableCacheSim);
|
||||
map.insert(QLatin1String(callgrindEnableBranchSimC), m_enableBranchSim);
|
||||
map.insert(QLatin1String(callgrindCollectSystimeC), m_collectSystime);
|
||||
map.insert(QLatin1String(callgrindCollectBusEventsC), m_collectBusEvents);
|
||||
map.insert(QLatin1String(callgrindEnableEventToolTipsC), m_enableEventToolTips);
|
||||
map.insert(QLatin1String(callgrindMinimumCostRatioC), m_minimumInclusiveCostRatio);
|
||||
map.insert(QLatin1String(callgrindVisualisationMinimumCostRatioC),
|
||||
m_visualisationMinimumInclusiveCostRatio);
|
||||
return map;
|
||||
}
|
||||
|
||||
QString AbstractCallgrindSettings::id() const
|
||||
{
|
||||
return QLatin1String("Analyzer.Valgrind.Settings.Callgrind");
|
||||
}
|
||||
|
||||
QString AbstractCallgrindSettings::displayName() const
|
||||
{
|
||||
return tr("Profiling");
|
||||
}
|
||||
|
||||
QWidget *AbstractCallgrindSettings::createConfigWidget(QWidget *parent)
|
||||
{
|
||||
return new CallgrindConfigWidget(this, parent);
|
||||
}
|
||||
|
||||
|
||||
QVariantMap CallgrindGlobalSettings::defaults() const
|
||||
{
|
||||
QVariantMap map = AbstractCallgrindSettings::defaults();
|
||||
map.insert(QLatin1String(callgrindCostFormatC), CostDelegate::FormatRelative);
|
||||
map.insert(QLatin1String(callgrindCycleDetectionC), true);
|
||||
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(QLatin1String(callgrindCostFormatC))) {
|
||||
m_costFormat = static_cast<CostDelegate::CostFormat>(map.value(QLatin1String(callgrindCostFormatC)).toInt());
|
||||
}
|
||||
setIfPresent(map, QLatin1String(callgrindCycleDetectionC), &m_detectCycles);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap CallgrindGlobalSettings::toMap() const
|
||||
{
|
||||
QVariantMap map = AbstractCallgrindSettings::toMap();
|
||||
map.insert(QLatin1String(callgrindCostFormatC), m_costFormat);
|
||||
map.insert(QLatin1String(callgrindCycleDetectionC), m_detectCycles);
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
153
src/plugins/valgrind/callgrindsettings.h
Normal file
153
src/plugins/valgrind/callgrindsettings.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
|
||||
#define ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
|
||||
|
||||
#include "callgrindcostdelegate.h"
|
||||
|
||||
#include <analyzerbase/analyzersettings.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
/**
|
||||
* Generic callgrind settings
|
||||
*/
|
||||
class AbstractCallgrindSettings : public Analyzer::AbstractAnalyzerSubConfig
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AbstractCallgrindSettings() {}
|
||||
|
||||
bool enableCacheSim() const { return m_enableCacheSim; }
|
||||
bool enableBranchSim() const { return m_enableBranchSim; }
|
||||
bool collectSystime() const { return m_collectSystime; }
|
||||
bool collectBusEvents() const { return m_collectBusEvents; }
|
||||
bool enableEventToolTips() const { return m_enableEventToolTips; }
|
||||
|
||||
/// \return Minimum cost ratio, range [0.0..100.0]
|
||||
double minimumInclusiveCostRatio() const { return m_minimumInclusiveCostRatio; }
|
||||
|
||||
/// \return Minimum cost ratio, range [0.0..100.0]
|
||||
double visualisationMinimumInclusiveCostRatio() const { return m_visualisationMinimumInclusiveCostRatio; }
|
||||
|
||||
// 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 slots:
|
||||
void setEnableCacheSim(bool enable);
|
||||
void setEnableBranchSim(bool enable);
|
||||
void setCollectSystime(bool collect);
|
||||
void setCollectBusEvents(bool collect);
|
||||
void setEnableEventToolTips(bool enable);
|
||||
|
||||
/// \param minimumInclusiveCostRatio Minimum inclusive cost ratio, valid values are [0.0..100.0]
|
||||
void setMinimumInclusiveCostRatio(double minimumInclusiveCostRatio);
|
||||
|
||||
/// \param minimumInclusiveCostRatio Minimum inclusive cost ratio, valid values are [0.0..100.0]
|
||||
void setVisualisationMinimumInclusiveCostRatio(double minimumInclusiveCostRatio);
|
||||
|
||||
signals:
|
||||
void enableCacheSimChanged(bool);
|
||||
void enableBranchSimChanged(bool);
|
||||
void collectSystimeChanged(bool);
|
||||
void collectBusEventsChanged(bool);
|
||||
void enableEventToolTipsChanged(bool);
|
||||
void minimumInclusiveCostRatioChanged(double);
|
||||
void visualisationMinimumInclusiveCostRatioChanged(double);
|
||||
|
||||
protected:
|
||||
virtual QVariantMap toMap() const;
|
||||
|
||||
private:
|
||||
bool m_enableCacheSim;
|
||||
bool m_collectSystime;
|
||||
bool m_collectBusEvents;
|
||||
bool m_enableBranchSim;
|
||||
bool m_enableEventToolTips;
|
||||
double m_minimumInclusiveCostRatio;
|
||||
double m_visualisationMinimumInclusiveCostRatio;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global callgrind settings
|
||||
*/
|
||||
class CallgrindGlobalSettings : public AbstractCallgrindSettings
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CallgrindGlobalSettings() {}
|
||||
|
||||
virtual bool fromMap(const QVariantMap &map);
|
||||
virtual QVariantMap defaults() const;
|
||||
|
||||
CostDelegate::CostFormat costFormat() const;
|
||||
bool detectCycles() const;
|
||||
|
||||
public slots:
|
||||
void setCostFormat(Valgrind::Internal::CostDelegate::CostFormat format);
|
||||
void setDetectCycles(bool detect);
|
||||
|
||||
protected:
|
||||
virtual QVariantMap toMap() const;
|
||||
|
||||
private:
|
||||
CostDelegate::CostFormat m_costFormat;
|
||||
bool m_detectCycles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-project callgrind settings, saves a diff to the global suppression files list
|
||||
*/
|
||||
class CallgrindProjectSettings : public AbstractCallgrindSettings
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CallgrindProjectSettings() {}
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // ANALYZER_INTERNAL_CALLGRINDSETTINGS_H
|
||||
107
src/plugins/valgrind/callgrindtextmark.cpp
Normal file
107
src/plugins/valgrind/callgrindtextmark.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "callgrindtextmark.h"
|
||||
|
||||
#include "callgrindhelper.h"
|
||||
|
||||
#include <valgrind/callgrind/callgrinddatamodel.h>
|
||||
#include <valgrind/callgrind/callgrindfunction.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Valgrind::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);
|
||||
}
|
||||
|
||||
void CallgrindTextMark::paint(QPainter *painter, const QRect &paintRect) const
|
||||
{
|
||||
if (!m_modelIndex.isValid())
|
||||
return;
|
||||
|
||||
bool ok;
|
||||
qreal costs = m_modelIndex.data(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;
|
||||
}
|
||||
74
src/plugins/valgrind/callgrindtextmark.h
Normal file
74
src/plugins/valgrind/callgrindtextmark.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDTEXTMARK_H
|
||||
#define CALLGRINDTEXTMARK_H
|
||||
|
||||
#include <texteditor/basetextmark.h>
|
||||
|
||||
#include <QtCore/QPersistentModelIndex>
|
||||
|
||||
namespace Valgrind {
|
||||
|
||||
namespace Callgrind {
|
||||
class Function;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 Valgrind
|
||||
|
||||
#endif // CALLGRINDTEXTMARK_H
|
||||
1003
src/plugins/valgrind/callgrindtool.cpp
Normal file
1003
src/plugins/valgrind/callgrindtool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
src/plugins/valgrind/callgrindtool.h
Normal file
73
src/plugins/valgrind/callgrindtool.h
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDTOOL_H
|
||||
#define CALLGRINDTOOL_H
|
||||
|
||||
#include <analyzerbase/ianalyzertool.h>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class CallgrindToolPrivate;
|
||||
|
||||
class CallgrindTool : public Analyzer::IAnalyzerTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CallgrindTool(QObject *parent = 0);
|
||||
~CallgrindTool();
|
||||
|
||||
QString id() const;
|
||||
QString displayName() const;
|
||||
ToolMode mode() const;
|
||||
|
||||
void initialize();
|
||||
void extensionsInitialized();
|
||||
void initializeDockWidgets();
|
||||
|
||||
Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration = 0);
|
||||
QWidget *createControlWidget();
|
||||
|
||||
bool canRunRemotely() const { return true; }
|
||||
bool needsOutputPane() const { return false; }
|
||||
|
||||
private:
|
||||
CallgrindToolPrivate *d;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // CALLGRINDTOOL_H
|
||||
464
src/plugins/valgrind/callgrindvisualisation.cpp
Normal file
464
src/plugins/valgrind/callgrindvisualisation.cpp
Normal file
@@ -0,0 +1,464 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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 <QtGui/QGraphicsRectItem>
|
||||
#include <QtGui/QGraphicsScene>
|
||||
#include <QtGui/QGraphicsSimpleTextItem>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QStaticText>
|
||||
#include <QtGui/QStyleOptionGraphicsItem>
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QPersistentModelIndex>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#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
|
||||
static const int FIT_IN_VIEW_MARGIN = 2;
|
||||
|
||||
using namespace Valgrind::Callgrind;
|
||||
|
||||
namespace Valgrind {
|
||||
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;
|
||||
|
||||
private:
|
||||
QString m_text;
|
||||
QStaticText m_staticText;
|
||||
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_previousViewportDimension(0)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIgnoresTransformations);
|
||||
setAcceptedMouseButtons(0); // do not steal focus from parent item
|
||||
setToolTip(text);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (textHeight > maxHeight)
|
||||
return;
|
||||
|
||||
if (viewportRect.width() != m_previousViewportDimension) {
|
||||
const QString &elidedText =
|
||||
painter->fontMetrics().elidedText(m_text, Qt::ElideRight,
|
||||
maxWidth);
|
||||
m_staticText.setText(elidedText);
|
||||
m_staticText.prepare();
|
||||
|
||||
m_previousViewportDimension = viewportRect.width();
|
||||
}
|
||||
|
||||
#if VISUALISATION_DEBUG
|
||||
painter->setPen(Qt::red);
|
||||
painter->drawRect(boundingRect());
|
||||
#endif
|
||||
|
||||
painter->save();
|
||||
int textLeft = 0;
|
||||
int textTop = 0;
|
||||
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(), 0);
|
||||
gradient.setColorAt(0, color.darker(100));
|
||||
gradient.setColorAt(0.5, color.lighter(200));
|
||||
gradient.setColorAt(1, color.darker(100));
|
||||
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);
|
||||
|
||||
void handleMousePressEvent(QMouseEvent *event, bool doubleClicked);
|
||||
qreal sceneHeight() const;
|
||||
qreal sceneWidth() const;
|
||||
|
||||
Visualisation *q;
|
||||
DataProxyModel *m_model;
|
||||
QGraphicsScene m_scene;
|
||||
};
|
||||
|
||||
Visualisation::Private::Private(Visualisation *qq)
|
||||
: q(qq)
|
||||
, m_model(new DataProxyModel(qq))
|
||||
{
|
||||
// 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()));
|
||||
}
|
||||
|
||||
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::setMinimumInclusiveCostRatio(double ratio)
|
||||
{
|
||||
d->m_model->setMinimumInclusiveCostRatio(ratio);
|
||||
}
|
||||
|
||||
void Visualisation::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTC_ASSERT(!d->m_model->sourceModel() && model, return); // only set once!
|
||||
d->m_model->setSourceModel(model);
|
||||
|
||||
connect(model,
|
||||
SIGNAL(columnsInserted(QModelIndex,int,int)),
|
||||
SLOT(populateScene()));
|
||||
connect(model,
|
||||
SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||
SLOT(populateScene()));
|
||||
connect(model,
|
||||
SIGNAL(columnsRemoved(QModelIndex,int,int)),
|
||||
SLOT(populateScene()));
|
||||
connect(model,
|
||||
SIGNAL(dataChanged(QModelIndex,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(QModelIndex,int,int)),
|
||||
SLOT(populateScene()));
|
||||
connect(model,
|
||||
SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
|
||||
SLOT(populateScene()));
|
||||
connect(model,
|
||||
SIGNAL(rowsRemoved(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()));
|
||||
// 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 = sceneHeight * 0.1;
|
||||
foreach (const Pair &cost, costs) {
|
||||
const QModelIndex &index = cost.first;
|
||||
const QString text = index.data().toString();
|
||||
|
||||
const qreal height = (sceneHeight * 0.9 * cost.second) / total;
|
||||
|
||||
FunctionGraphicsItem *item = new FunctionGraphicsItem(text, 0, used, sceneWidth, height);
|
||||
const QColor background = CallgrindHelper::colorForString(text);
|
||||
item->setBrush(background);
|
||||
item->setData(FunctionGraphicsItem::FunctionCallKey, index.data(DataModel::FunctionRole));
|
||||
d->m_scene.addItem(item);
|
||||
used += height;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
94
src/plugins/valgrind/callgrindvisualisation.h
Normal file
94
src/plugins/valgrind/callgrindvisualisation.h
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CALLGRINDVISUALISATION_H
|
||||
#define CALLGRINDVISUALISATION_H
|
||||
|
||||
#include <QtGui/QGraphicsView>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemModel;
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Callgrind {
|
||||
class Function;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class Visualisation : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Visualisation(QWidget *parent = 0);
|
||||
virtual ~Visualisation();
|
||||
|
||||
void setModel(QAbstractItemModel *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;
|
||||
|
||||
void setMinimumInclusiveCostRatio(double ratio);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // VALGRIND_CALLGRIND_CALLGRINDVISUALISATION_H
|
||||
32
src/plugins/valgrind/memcheck.pro
Normal file
32
src/plugins/valgrind/memcheck.pro
Normal file
@@ -0,0 +1,32 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = Memcheck
|
||||
|
||||
DEFINES += MEMCHECK_LIBRARY
|
||||
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(memcheck_dependencies.pri)
|
||||
|
||||
# Memcheck files
|
||||
|
||||
HEADERS += \
|
||||
memcheckplugin.h \
|
||||
memcheck_global.h \
|
||||
memchecktool.h \
|
||||
memcheckengine.h \
|
||||
memcheckerrorview.h \
|
||||
memchecksettings.h \
|
||||
memcheckconfigwidget.h \
|
||||
suppressiondialog.h
|
||||
|
||||
SOURCES += \
|
||||
memcheckplugin.cpp \
|
||||
memchecktool.cpp \
|
||||
memcheckengine.cpp \
|
||||
memcheckerrorview.cpp \
|
||||
memchecksettings.cpp \
|
||||
memcheckconfigwidget.cpp \
|
||||
suppressiondialog.cpp
|
||||
|
||||
FORMS += \
|
||||
suppressiondialog.ui \
|
||||
memcheckconfigwidget.ui \
|
||||
182
src/plugins/valgrind/memcheckconfigwidget.cpp
Normal file
182
src/plugins/valgrind/memcheckconfigwidget.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "memcheckconfigwidget.h"
|
||||
|
||||
#include "ui_memcheckconfigwidget.h"
|
||||
|
||||
#include "memchecksettings.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
MemcheckConfigWidget::MemcheckConfigWidget(AbstractMemcheckSettings *settings, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_settings(settings),
|
||||
m_model(new QStandardItemModel(this)),
|
||||
m_ui(new Ui::MemcheckConfigWidget)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->suppressionList->setModel(m_model);
|
||||
m_ui->suppressionList->setSelectionMode(QAbstractItemView::MultiSelection);
|
||||
|
||||
connect(m_ui->addSuppression, SIGNAL(clicked()),
|
||||
this, SLOT(slotAddSuppression()));
|
||||
connect(m_ui->removeSuppression, SIGNAL(clicked()),
|
||||
this, SLOT(slotRemoveSuppression()));
|
||||
|
||||
m_ui->numCallers->setValue(m_settings->numCallers());
|
||||
connect(m_ui->numCallers, SIGNAL(valueChanged(int)), m_settings, SLOT(setNumCallers(int)));
|
||||
connect(m_settings, SIGNAL(numCallersChanged(int)), m_ui->numCallers, SLOT(setValue(int)));
|
||||
|
||||
m_ui->trackOrigins->setChecked(m_settings->trackOrigins());
|
||||
connect(m_ui->trackOrigins, SIGNAL(toggled(bool)), m_settings, SLOT(setTrackOrigins(bool)));
|
||||
connect(m_settings, SIGNAL(trackOriginsChanged(bool)), m_ui->trackOrigins, SLOT(setChecked(bool)));
|
||||
|
||||
connect(m_settings, SIGNAL(suppressionFilesRemoved(QStringList)),
|
||||
this, SLOT(slotSuppressionsRemoved(QStringList)));
|
||||
connect(m_settings, SIGNAL(suppressionFilesAdded(QStringList)),
|
||||
this, SLOT(slotSuppressionsAdded(QStringList)));
|
||||
|
||||
m_model->clear();
|
||||
foreach (const QString &file, m_settings->suppressionFiles())
|
||||
m_model->appendRow(new QStandardItem(file));
|
||||
|
||||
connect(m_ui->suppressionList->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(slotSuppressionSelectionChanged()));
|
||||
slotSuppressionSelectionChanged();
|
||||
}
|
||||
|
||||
MemcheckConfigWidget::~MemcheckConfigWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::slotAddSuppression()
|
||||
{
|
||||
QFileDialog dialog;
|
||||
dialog.setNameFilter(tr("Valgrind Suppression File (*.supp);;All Files (*)"));
|
||||
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
dialog.setFileMode(QFileDialog::ExistingFiles);
|
||||
MemcheckGlobalSettings *conf = Analyzer::AnalyzerGlobalSettings::instance()->subConfig<MemcheckGlobalSettings>();
|
||||
QTC_ASSERT(conf, return);
|
||||
dialog.setDirectory(conf->lastSuppressionDialogDirectory());
|
||||
dialog.setHistory(conf->lastSuppressionDialogHistory());
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
foreach (const QString &file, dialog.selectedFiles())
|
||||
m_model->appendRow(new QStandardItem(file));
|
||||
|
||||
m_settings->addSuppressionFiles(dialog.selectedFiles());
|
||||
}
|
||||
|
||||
conf->setLastSuppressionDialogDirectory(dialog.directory().absolutePath());
|
||||
conf->setLastSuppressionDialogHistory(dialog.history());
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::slotSuppressionsAdded(const QStringList &files)
|
||||
{
|
||||
QStringList filesToAdd = files;
|
||||
for (int i = 0, c = m_model->rowCount(); i < c; ++i)
|
||||
filesToAdd.removeAll(m_model->item(i)->text());
|
||||
|
||||
foreach (const QString &file, filesToAdd)
|
||||
m_model->appendRow(new QStandardItem(file));
|
||||
}
|
||||
|
||||
bool sortReverse(int l, int r)
|
||||
{
|
||||
return l > r;
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::slotRemoveSuppression()
|
||||
{
|
||||
// remove from end so no rows get invalidated
|
||||
QList<int> rows;
|
||||
|
||||
QStringList removed;
|
||||
foreach (const QModelIndex &index, m_ui->suppressionList->selectionModel()->selectedIndexes()) {
|
||||
rows << index.row();
|
||||
removed << index.data().toString();
|
||||
}
|
||||
|
||||
qSort(rows.begin(), rows.end(), sortReverse);
|
||||
|
||||
foreach (int row, rows)
|
||||
m_model->removeRow(row);
|
||||
|
||||
m_settings->removeSuppressionFiles(removed);
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::slotSuppressionsRemoved(const QStringList &files)
|
||||
{
|
||||
for (int i = 0; i < m_model->rowCount(); ++i) {
|
||||
if (files.contains(m_model->item(i)->text())) {
|
||||
m_model->removeRow(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::setSuppressions(const QStringList &files)
|
||||
{
|
||||
m_model->clear();
|
||||
foreach (const QString &file, files)
|
||||
m_model->appendRow(new QStandardItem(file));
|
||||
}
|
||||
|
||||
QStringList MemcheckConfigWidget::suppressions() const
|
||||
{
|
||||
QStringList ret;
|
||||
|
||||
for (int i = 0; i < m_model->rowCount(); ++i)
|
||||
ret << m_model->item(i)->text();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MemcheckConfigWidget::slotSuppressionSelectionChanged()
|
||||
{
|
||||
m_ui->removeSuppression->setEnabled(m_ui->suppressionList->selectionModel()->hasSelection());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
80
src/plugins/valgrind/memcheckconfigwidget.h
Normal file
80
src/plugins/valgrind/memcheckconfigwidget.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_MEMCHECKCONFIGWIDGET_H
|
||||
#define ANALYZER_INTERNAL_MEMCHECKCONFIGWIDGET_H
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class MemcheckConfigWidget;
|
||||
}
|
||||
|
||||
class AbstractMemcheckSettings;
|
||||
|
||||
class MemcheckConfigWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemcheckConfigWidget(AbstractMemcheckSettings *settings, QWidget *parent);
|
||||
virtual ~MemcheckConfigWidget();
|
||||
|
||||
void setSuppressions(const QStringList &files);
|
||||
QStringList suppressions() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotAddSuppression();
|
||||
void slotRemoveSuppression();
|
||||
void slotSuppressionsRemoved(const QStringList &files);
|
||||
void slotSuppressionsAdded(const QStringList &files);
|
||||
void slotSuppressionSelectionChanged();
|
||||
|
||||
private:
|
||||
AbstractMemcheckSettings *m_settings;
|
||||
QStandardItemModel *m_model;
|
||||
Ui::MemcheckConfigWidget *m_ui;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // ANALYZER_INTERNAL_MEMCHECKCONFIGWIDGET_H
|
||||
130
src/plugins/valgrind/memcheckconfigwidget.ui
Normal file
130
src/plugins/valgrind/memcheckconfigwidget.ui
Normal file
@@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Valgrind::Internal::MemcheckConfigWidget</class>
|
||||
<widget class="QWidget" name="Valgrind::Internal::MemcheckConfigWidget">
|
||||
<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>Memory Analysis Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="numCallersLabel">
|
||||
<property name="text">
|
||||
<string>Backtrace frame count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>numCallers</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Suppression files:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>suppressionList</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="suppressionList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,1">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addSuppression">
|
||||
<property name="text">
|
||||
<string>Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeSuppression">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="numCallers">
|
||||
<property name="minimum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>12</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="trackOrigins">
|
||||
<property name="text">
|
||||
<string>Track origins of uninitialized memory</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
148
src/plugins/valgrind/memcheckengine.cpp
Normal file
148
src/plugins/valgrind/memcheckengine.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "memcheckengine.h"
|
||||
|
||||
#include "memchecksettings.h"
|
||||
|
||||
#include <analyzerbase/analyzersettings.h>
|
||||
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
#include <valgrind/xmlprotocol/status.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
MemcheckEngine::MemcheckEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration)
|
||||
: ValgrindEngine(sp, runConfiguration)
|
||||
{
|
||||
connect(&m_parser, SIGNAL(error(Valgrind::XmlProtocol::Error)),
|
||||
SIGNAL(parserError(Valgrind::XmlProtocol::Error)));
|
||||
connect(&m_parser, SIGNAL(suppressionCount(QString,qint64)),
|
||||
SIGNAL(suppressionCount(QString,qint64)));
|
||||
connect(&m_parser, SIGNAL(internalError(QString)),
|
||||
SIGNAL(internalParserError(QString)));
|
||||
connect(&m_parser, SIGNAL(status(Valgrind::XmlProtocol::Status)),
|
||||
SLOT(status(Valgrind::XmlProtocol::Status)));
|
||||
|
||||
m_progress->setProgressRange(0, Valgrind::XmlProtocol::Status::Finished + 1);
|
||||
}
|
||||
|
||||
QString MemcheckEngine::progressTitle() const
|
||||
{
|
||||
return tr("Analyzing Memory");
|
||||
}
|
||||
|
||||
Valgrind::ValgrindRunner *MemcheckEngine::runner()
|
||||
{
|
||||
return &m_runner;
|
||||
}
|
||||
|
||||
void MemcheckEngine::start()
|
||||
{
|
||||
m_runner.setParser(&m_parser);
|
||||
|
||||
emit standardOutputReceived(tr("Analyzing memory of %1").arg(executable()));
|
||||
ValgrindEngine::start();
|
||||
}
|
||||
|
||||
void MemcheckEngine::stop()
|
||||
{
|
||||
disconnect(&m_parser, SIGNAL(internalError(QString)),
|
||||
this, SIGNAL(internalParserError(QString)));
|
||||
ValgrindEngine::stop();
|
||||
}
|
||||
|
||||
QStringList MemcheckEngine::toolArguments() const
|
||||
{
|
||||
QStringList arguments;
|
||||
arguments << QLatin1String("--gen-suppressions=all");
|
||||
|
||||
AbstractMemcheckSettings *memcheckSettings = m_settings->subConfig<AbstractMemcheckSettings>();
|
||||
QTC_ASSERT(memcheckSettings, return arguments);
|
||||
|
||||
if (memcheckSettings->trackOrigins())
|
||||
arguments << QLatin1String("--track-origins=yes");
|
||||
|
||||
foreach (const QString &file, memcheckSettings->suppressionFiles())
|
||||
arguments << QString("--suppressions=%1").arg(file);
|
||||
|
||||
arguments << QString("--num-callers=%1").arg(memcheckSettings->numCallers());
|
||||
return arguments;
|
||||
}
|
||||
|
||||
QStringList MemcheckEngine::suppressionFiles() const
|
||||
{
|
||||
return m_settings->subConfig<AbstractMemcheckSettings>()->suppressionFiles();
|
||||
}
|
||||
|
||||
void MemcheckEngine::status(const Status &status)
|
||||
{
|
||||
m_progress->setProgressValue(status.state() + 1);
|
||||
}
|
||||
|
||||
void MemcheckEngine::receiveLogMessage(const QByteArray &b)
|
||||
{
|
||||
QString error = QString::fromLocal8Bit(b);
|
||||
// workaround https://bugs.kde.org/show_bug.cgi?id=255888
|
||||
error.remove(QRegExp("==*== </valgrindoutput>", Qt::CaseSensitive, QRegExp::Wildcard));
|
||||
|
||||
error = error.trimmed();
|
||||
|
||||
if (error.isEmpty())
|
||||
return;
|
||||
|
||||
stop();
|
||||
|
||||
QString file;
|
||||
int line = -1;
|
||||
|
||||
const QRegExp suppressionError(QLatin1String("in suppressions file \"([^\"]+)\" near line (\\d+)"),
|
||||
Qt::CaseSensitive, QRegExp::RegExp2);
|
||||
if (suppressionError.indexIn(error) != -1) {
|
||||
file = suppressionError.cap(1);
|
||||
line = suppressionError.cap(2).toInt();
|
||||
}
|
||||
|
||||
emit taskToBeAdded(ProjectExplorer::Task::Error, error, file, line);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
80
src/plugins/valgrind/memcheckengine.h
Normal file
80
src/plugins/valgrind/memcheckengine.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MEMCHECKENGINE_H
|
||||
#define MEMCHECKENGINE_H
|
||||
|
||||
#include "valgrindengine.h"
|
||||
|
||||
#include <valgrind/memcheck/memcheckrunner.h>
|
||||
#include <valgrind/xmlprotocol/threadedparser.h>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class MemcheckEngine : public ValgrindEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MemcheckEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
QStringList suppressionFiles() const;
|
||||
|
||||
signals:
|
||||
void internalParserError(const QString &errorString);
|
||||
void parserError(const Valgrind::XmlProtocol::Error &error);
|
||||
void suppressionCount(const QString &name, qint64 count);
|
||||
|
||||
protected:
|
||||
virtual QString progressTitle() const;
|
||||
virtual QStringList toolArguments() const;
|
||||
virtual Valgrind::ValgrindRunner *runner();
|
||||
|
||||
private slots:
|
||||
void receiveLogMessage(const QByteArray &);
|
||||
void status(const Valgrind::XmlProtocol::Status &status);
|
||||
|
||||
private:
|
||||
Valgrind::XmlProtocol::ThreadedParser m_parser;
|
||||
Valgrind::Memcheck::MemcheckRunner m_runner;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // MEMCHECKENGINE_H
|
||||
511
src/plugins/valgrind/memcheckerrorview.cpp
Normal file
511
src/plugins/valgrind/memcheckerrorview.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Andreas Hartmetz, KDAB (andreas.hartmetz@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "memcheckerrorview.h"
|
||||
|
||||
#include "suppressiondialog.h"
|
||||
#include "valgrindsettings.h"
|
||||
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
#include <valgrind/xmlprotocol/errorlistmodel.h>
|
||||
#include <valgrind/xmlprotocol/frame.h>
|
||||
#include <valgrind/xmlprotocol/stack.h>
|
||||
#include <valgrind/xmlprotocol/modelhelpers.h>
|
||||
#include <valgrind/xmlprotocol/suppression.h>
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QListView>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QScrollBar>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QMenu>
|
||||
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
MemcheckErrorDelegate::MemcheckErrorDelegate(QListView *parent)
|
||||
: QStyledItemDelegate(parent),
|
||||
m_detailsWidget(0)
|
||||
{
|
||||
connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
||||
SLOT(verticalScrolled()));
|
||||
}
|
||||
|
||||
QSize MemcheckErrorDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
|
||||
{
|
||||
const QListView *view = qobject_cast<const QListView *>(parent());
|
||||
const int viewportWidth = view->viewport()->width();
|
||||
const bool isSelected = view->selectionModel()->currentIndex() == index;
|
||||
|
||||
int dy = 2 * s_itemMargin;
|
||||
|
||||
if (!isSelected) {
|
||||
QFontMetrics fm(opt.font);
|
||||
return QSize(viewportWidth, fm.height() + dy);
|
||||
}
|
||||
|
||||
if (m_detailsWidget && m_detailsIndex != index) {
|
||||
m_detailsWidget->deleteLater();
|
||||
m_detailsWidget = 0;
|
||||
}
|
||||
|
||||
if (!m_detailsWidget) {
|
||||
m_detailsWidget = createDetailsWidget(index, view->viewport());
|
||||
QTC_ASSERT(m_detailsWidget->parent() == view->viewport(),
|
||||
m_detailsWidget->setParent(view->viewport()));
|
||||
m_detailsIndex = index;
|
||||
} else {
|
||||
QTC_ASSERT(m_detailsIndex == index, qt_noop());
|
||||
}
|
||||
const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin;
|
||||
m_detailsWidget->setFixedWidth(widthExcludingMargins);
|
||||
|
||||
m_detailsWidgetHeight = m_detailsWidget->heightForWidth(widthExcludingMargins);
|
||||
// HACK: it's a bug in QLabel(?) that we have to force the widget to have the size it said
|
||||
// it would have.
|
||||
m_detailsWidget->setFixedHeight(m_detailsWidgetHeight);
|
||||
return QSize(viewportWidth, dy + m_detailsWidget->heightForWidth(widthExcludingMargins));
|
||||
}
|
||||
|
||||
static QString makeFrameName(const Frame &frame, const QString &relativeTo,
|
||||
bool link = true, const QString &linkAttr = QString())
|
||||
{
|
||||
const QString d = frame.directory();
|
||||
const QString f = frame.file();
|
||||
const QString fn = frame.functionName();
|
||||
const QString fullPath = d + QDir::separator() + f;
|
||||
|
||||
QString path;
|
||||
if (!d.isEmpty() && !f.isEmpty())
|
||||
path = fullPath;
|
||||
else
|
||||
path = frame.object();
|
||||
|
||||
if (QFile::exists(path))
|
||||
path = QFileInfo(path).canonicalFilePath();
|
||||
|
||||
if (path.startsWith(relativeTo))
|
||||
path.remove(0, relativeTo.length());
|
||||
|
||||
if (frame.line() != -1)
|
||||
path += QLatin1Char(':') + QString::number(frame.line());
|
||||
|
||||
path = Qt::escape(path);
|
||||
|
||||
if (link && !f.isEmpty() && QFile::exists(fullPath)) {
|
||||
// make a hyperlink label
|
||||
path = QString("<a href=\"file://%1:%2\" %4>%3</a>")
|
||||
.arg(fullPath, QString::number(frame.line()), path, linkAttr);
|
||||
}
|
||||
|
||||
if (!fn.isEmpty())
|
||||
return QCoreApplication::translate("Valgrind::Internal", "%1 in %2").arg(Qt::escape(fn), path);
|
||||
if (!path.isEmpty())
|
||||
return path;
|
||||
return QString("0x%1").arg(frame.instructionPointer(), 0, 16);
|
||||
}
|
||||
|
||||
QString relativeToPath()
|
||||
{
|
||||
// project for which we insert the snippet
|
||||
const ProjectExplorer::Project *project =
|
||||
ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
|
||||
|
||||
QString relativeTo( project ? project->projectDirectory() : QDir::homePath() );
|
||||
if (!relativeTo.endsWith(QDir::separator()))
|
||||
relativeTo.append(QDir::separator());
|
||||
|
||||
return relativeTo;
|
||||
}
|
||||
|
||||
QString errorLocation(const QModelIndex &index, const Error &error,
|
||||
bool link = false, const QString &linkAttr = QString())
|
||||
{
|
||||
const ErrorListModel *model = 0;
|
||||
const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel *>(index.model());
|
||||
while (!model && proxy) {
|
||||
model = qobject_cast<const ErrorListModel *>(proxy->sourceModel());
|
||||
proxy = qobject_cast<const QAbstractProxyModel *>(proxy->sourceModel());
|
||||
}
|
||||
QTC_ASSERT(model, return QString());
|
||||
|
||||
return QCoreApplication::translate("Valgrind::Internal", "in %1").
|
||||
arg(makeFrameName(model->findRelevantFrame(error), relativeToPath(),
|
||||
link, linkAttr));
|
||||
}
|
||||
|
||||
QWidget *MemcheckErrorDelegate::createDetailsWidget(const QModelIndex &errorIndex, QWidget *parent) const
|
||||
{
|
||||
QWidget *widget = new QWidget(parent);
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
// code + white-space:pre so the padding (see below) works properly
|
||||
// don't include frameName here as it should wrap if required and pre-line is not supported
|
||||
// by Qt yet it seems
|
||||
const QString displayTextTemplate = QString("<code style='white-space:pre'>%1:</code> %2");
|
||||
|
||||
QString relativeTo = relativeToPath();
|
||||
|
||||
const Error error = errorIndex.data(ErrorListModel::ErrorRole).value<Error>();
|
||||
|
||||
QLabel *errorLabel = new QLabel();
|
||||
errorLabel->setWordWrap(true);
|
||||
errorLabel->setContentsMargins(0, 0, 0, 0);
|
||||
errorLabel->setMargin(0);
|
||||
errorLabel->setIndent(0);
|
||||
QPalette p = errorLabel->palette();
|
||||
QColor lc = p.color(QPalette::Text);
|
||||
QString linkStyle = QString("style=\"color:rgba(%1, %2, %3, %4);\"")
|
||||
.arg(lc.red()).arg(lc.green()).arg(lc.blue()).arg(int(0.7 * 255));
|
||||
p.setBrush(QPalette::Text, p.highlightedText());
|
||||
errorLabel->setPalette(p);
|
||||
errorLabel->setText(QString("%1 <span %4>%2</span>")
|
||||
.arg(error.what(), errorLocation(errorIndex, error, true, linkStyle),
|
||||
linkStyle));
|
||||
connect(errorLabel, SIGNAL(linkActivated(QString)), SLOT(openLinkInEditor(QString)));
|
||||
layout->addWidget(errorLabel);
|
||||
|
||||
const QVector<Stack> stacks = error.stacks();
|
||||
for (int i = 0; i < stacks.count(); ++i) {
|
||||
const Stack &stack = stacks.at(i);
|
||||
// auxwhat for additional stacks
|
||||
if (i > 0) {
|
||||
QLabel *stackLabel = new QLabel(stack.auxWhat());
|
||||
stackLabel->setWordWrap(true);
|
||||
stackLabel->setContentsMargins(0, 0, 0, 0);
|
||||
stackLabel->setMargin(0);
|
||||
stackLabel->setIndent(0);
|
||||
QPalette p = stackLabel->palette();
|
||||
p.setBrush(QPalette::Text, p.highlightedText());
|
||||
stackLabel->setPalette(p);
|
||||
layout->addWidget(stackLabel);
|
||||
}
|
||||
int frameNr = 1;
|
||||
foreach (const Frame &frame, stack.frames()) {
|
||||
QString frameName = makeFrameName(frame, relativeTo);
|
||||
QTC_ASSERT(!frameName.isEmpty(), qt_noop());
|
||||
|
||||
QLabel *frameLabel = new QLabel(widget);
|
||||
frameLabel->setAutoFillBackground(true);
|
||||
if (frameNr % 2 == 0) {
|
||||
// alternating rows
|
||||
QPalette p = frameLabel->palette();
|
||||
p.setBrush(QPalette::Base, p.alternateBase());
|
||||
frameLabel->setPalette(p);
|
||||
}
|
||||
frameLabel->setFont(QFont("monospace"));
|
||||
connect(frameLabel, SIGNAL(linkActivated(QString)), SLOT(openLinkInEditor(QString)));
|
||||
// pad frameNr to 2 chars since only 50 frames max are supported by valgrind
|
||||
const QString displayText = displayTextTemplate
|
||||
.arg(frameNr++, 2).arg(frameName);
|
||||
frameLabel->setText(displayText);
|
||||
|
||||
frameLabel->setToolTip(Valgrind::XmlProtocol::toolTipForFrame(frame));
|
||||
frameLabel->setWordWrap(true);
|
||||
frameLabel->setContentsMargins(0, 0, 0, 0);
|
||||
frameLabel->setMargin(0);
|
||||
frameLabel->setIndent(10);
|
||||
layout->addWidget(frameLabel);
|
||||
}
|
||||
}
|
||||
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
widget->setLayout(layout);
|
||||
return widget;
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &basicOption,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt(basicOption);
|
||||
initStyleOption(&opt, index);
|
||||
|
||||
const QListView *const view = qobject_cast<const QListView *>(parent());
|
||||
const bool isSelected = view->selectionModel()->currentIndex() == index;
|
||||
|
||||
QFontMetrics fm(opt.font);
|
||||
QPoint pos = opt.rect.topLeft();
|
||||
|
||||
painter->save();
|
||||
|
||||
const QColor bgColor = isSelected ? opt.palette.highlight().color() : opt.palette.background().color();
|
||||
painter->setBrush(bgColor);
|
||||
|
||||
// clear background
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(opt.rect);
|
||||
|
||||
pos.rx() += s_itemMargin;
|
||||
pos.ry() += s_itemMargin;
|
||||
|
||||
const Error error = index.data(ErrorListModel::ErrorRole).value<Error>();
|
||||
|
||||
if (isSelected) {
|
||||
// only show detailed widget and let it handle everything
|
||||
QTC_ASSERT(m_detailsIndex == index, qt_noop());
|
||||
QTC_ASSERT(m_detailsWidget, return); // should have been set in sizeHint()
|
||||
m_detailsWidget->move(pos);
|
||||
// when scrolling quickly, the widget can get stuck in a visible part of the scroll area
|
||||
// even though it should not be visible. therefore we hide it every time the scroll value
|
||||
// changes and un-hide it when the item with details widget is paint()ed, i.e. visible.
|
||||
m_detailsWidget->show();
|
||||
|
||||
const int viewportWidth = view->viewport()->width();
|
||||
const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin;
|
||||
QTC_ASSERT(m_detailsWidget->width() == widthExcludingMargins, qt_noop());
|
||||
QTC_ASSERT(m_detailsWidgetHeight == m_detailsWidget->height(), qt_noop());
|
||||
} else {
|
||||
// the reference coordinate for text drawing is the text baseline; move it inside the view rect.
|
||||
pos.ry() += fm.ascent();
|
||||
|
||||
const QColor textColor = opt.palette.text().color();
|
||||
painter->setPen(textColor);
|
||||
// draw only text + location
|
||||
const QString what = error.what();
|
||||
painter->drawText(pos, what);
|
||||
|
||||
const QString name = errorLocation(index, error);
|
||||
const int whatWidth = QFontMetrics(opt.font).width(what);
|
||||
const int space = 10;
|
||||
const int widthLeft = opt.rect.width() - (pos.x() + whatWidth + space + s_itemMargin);
|
||||
if (widthLeft > 0) {
|
||||
QFont monospace = opt.font;
|
||||
monospace.setFamily("monospace");
|
||||
QFontMetrics metrics(monospace);
|
||||
QColor nameColor = textColor;
|
||||
nameColor.setAlphaF(0.7);
|
||||
|
||||
painter->setFont(monospace);
|
||||
painter->setPen(nameColor);
|
||||
|
||||
QPoint namePos = pos;
|
||||
namePos.rx() += whatWidth + space;
|
||||
painter->drawText(namePos, metrics.elidedText(name, Qt::ElideLeft, widthLeft));
|
||||
}
|
||||
}
|
||||
|
||||
// Separator lines (like build issues pane)
|
||||
painter->setPen(QColor::fromRgb(150,150,150));
|
||||
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::currentChanged(const QModelIndex &now, const QModelIndex &previous)
|
||||
{
|
||||
if (m_detailsWidget) {
|
||||
m_detailsWidget->deleteLater();
|
||||
m_detailsWidget = 0;
|
||||
}
|
||||
|
||||
m_detailsIndex = QModelIndex();
|
||||
if (now.isValid())
|
||||
emit sizeHintChanged(now);
|
||||
if (previous.isValid())
|
||||
emit sizeHintChanged(previous);
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::layoutChanged()
|
||||
{
|
||||
if (m_detailsWidget) {
|
||||
m_detailsWidget->deleteLater();
|
||||
m_detailsWidget = 0;
|
||||
m_detailsIndex = QModelIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::viewResized()
|
||||
{
|
||||
const QListView *view = qobject_cast<const QListView *>(parent());
|
||||
if (m_detailsWidget)
|
||||
emit sizeHintChanged(view->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::verticalScrolled()
|
||||
{
|
||||
if (m_detailsWidget)
|
||||
m_detailsWidget->hide();
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::copy()
|
||||
{
|
||||
QTC_ASSERT(m_detailsIndex.isValid(), return);
|
||||
|
||||
QString content;
|
||||
QTextStream stream(&content);
|
||||
const Error error = m_detailsIndex.data(ErrorListModel::ErrorRole).value<Error>();
|
||||
|
||||
stream << error.what() << "\n";
|
||||
stream << " " << errorLocation(m_detailsIndex, error) << "\n";
|
||||
|
||||
const QString relativeTo = relativeToPath();
|
||||
|
||||
foreach (const Stack &stack, error.stacks()) {
|
||||
if (!stack.auxWhat().isEmpty()) {
|
||||
stream << stack.auxWhat();
|
||||
}
|
||||
int i = 1;
|
||||
foreach (const Frame &frame, stack.frames()) {
|
||||
stream << " " << i++ << ": " << makeFrameName(frame, relativeTo) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
stream.flush();
|
||||
QApplication::clipboard()->setText(content);
|
||||
}
|
||||
|
||||
void MemcheckErrorDelegate::openLinkInEditor(const QString &link)
|
||||
{
|
||||
const int pathStart = strlen("file://");
|
||||
const int pathEnd = link.lastIndexOf(':');
|
||||
const QString path = link.mid(pathStart, pathEnd - pathStart);
|
||||
const int line = link.mid(pathEnd + 1).toInt(0);
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(path, qMax(line, 0));
|
||||
}
|
||||
|
||||
MemcheckErrorView::MemcheckErrorView(QWidget *parent)
|
||||
: QListView(parent),
|
||||
m_settings(0)
|
||||
{
|
||||
setItemDelegate(new MemcheckErrorDelegate(this));
|
||||
connect(this, SIGNAL(resized()), itemDelegate(), SLOT(viewResized()));
|
||||
|
||||
m_copyAction = new QAction(this);
|
||||
m_copyAction->setText(tr("Copy Selection"));
|
||||
m_copyAction->setIcon(QIcon(Core::Constants::ICON_COPY));
|
||||
m_copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));
|
||||
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(m_copyAction, SIGNAL(triggered()), itemDelegate(), SLOT(copy()));
|
||||
addAction(m_copyAction);
|
||||
|
||||
m_suppressAction = new QAction(this);
|
||||
m_suppressAction->setText(tr("Suppress Error"));
|
||||
m_suppressAction->setIcon(QIcon(QLatin1String(":/qmldesigner/images/eye_crossed.png")));
|
||||
m_suppressAction->setShortcut(QKeySequence(Qt::Key_Delete));
|
||||
m_suppressAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(m_suppressAction, SIGNAL(triggered()), this, SLOT(suppressError()));
|
||||
addAction(m_suppressAction);
|
||||
}
|
||||
|
||||
MemcheckErrorView::~MemcheckErrorView()
|
||||
{
|
||||
itemDelegate()->deleteLater();
|
||||
}
|
||||
|
||||
void MemcheckErrorView::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QListView::setModel(model);
|
||||
connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
itemDelegate(), SLOT(currentChanged(QModelIndex,QModelIndex)));
|
||||
|
||||
connect(model, SIGNAL(layoutChanged()),
|
||||
itemDelegate(), SLOT(layoutChanged()));
|
||||
}
|
||||
|
||||
void MemcheckErrorView::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
emit resized();
|
||||
QListView::resizeEvent(e);
|
||||
}
|
||||
|
||||
void MemcheckErrorView::setDefaultSuppressionFile(const QString &suppFile)
|
||||
{
|
||||
m_defaultSuppFile = suppFile;
|
||||
}
|
||||
|
||||
QString MemcheckErrorView::defaultSuppressionFile() const
|
||||
{
|
||||
return m_defaultSuppFile;
|
||||
}
|
||||
|
||||
// slot, can (for now) be invoked either when the settings were modified *or* when the active
|
||||
// settings object has changed.
|
||||
void MemcheckErrorView::settingsChanged(Analyzer::AnalyzerSettings *settings)
|
||||
{
|
||||
QTC_ASSERT(settings, return);
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
void MemcheckErrorView::contextMenuEvent(QContextMenuEvent *e)
|
||||
{
|
||||
const QModelIndexList indizes = selectionModel()->selectedRows();
|
||||
if (indizes.isEmpty())
|
||||
return;
|
||||
|
||||
QList<Error> errors;
|
||||
foreach (const QModelIndex &index, indizes) {
|
||||
Error error = model()->data(index, ErrorListModel::ErrorRole).value<Error>();
|
||||
if (!error.suppression().isNull())
|
||||
errors << error;
|
||||
}
|
||||
|
||||
QMenu menu;
|
||||
menu.addAction(m_copyAction);
|
||||
menu.addSeparator();
|
||||
menu.addAction(m_suppressAction);
|
||||
m_suppressAction->setEnabled(!errors.isEmpty());
|
||||
menu.exec(e->globalPos());
|
||||
}
|
||||
|
||||
void MemcheckErrorView::suppressError()
|
||||
{
|
||||
SuppressionDialog *dialog = new SuppressionDialog(this);
|
||||
if (dialog->shouldShow()) {
|
||||
dialog->setModal(true);
|
||||
dialog->show();
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
} else {
|
||||
delete dialog;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
125
src/plugins/valgrind/memcheckerrorview.h
Normal file
125
src/plugins/valgrind/memcheckerrorview.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Andreas Hartmetz, KDAB (andreas.hartmetz@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MEMCHECKERRORVIEW_H
|
||||
#define MEMCHECKERRORVIEW_H
|
||||
|
||||
#include <QtGui/QListView>
|
||||
#include <QtGui/QStyledItemDelegate>
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
namespace Analyzer {
|
||||
class AnalyzerSettings;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
}
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class MemcheckErrorDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/// This delegate can only work on one view at a time, parent. parent will also be the parent
|
||||
/// in the QObject parent-child system.
|
||||
explicit MemcheckErrorDelegate(QListView *parent);
|
||||
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
public slots:
|
||||
void currentChanged(const QModelIndex &now, const QModelIndex &previous);
|
||||
void viewResized();
|
||||
void layoutChanged();
|
||||
void copy();
|
||||
|
||||
private slots:
|
||||
void verticalScrolled();
|
||||
void openLinkInEditor(const QString &link);
|
||||
|
||||
private:
|
||||
// the constness of this method is a necessary lie because it is called from paint() const.
|
||||
QWidget *createDetailsWidget(const QModelIndex &errorIndex, QWidget *parent) const;
|
||||
|
||||
static const int s_itemMargin = 2;
|
||||
mutable QPersistentModelIndex m_detailsIndex;
|
||||
mutable QWidget *m_detailsWidget;
|
||||
mutable int m_detailsWidgetHeight;
|
||||
};
|
||||
|
||||
class MemcheckErrorView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemcheckErrorView(QWidget *parent = 0);
|
||||
~MemcheckErrorView();
|
||||
|
||||
// reimplemented to connect delegate to connection model after it has been set by
|
||||
// superclass implementation
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
void setDefaultSuppressionFile(const QString &suppFile);
|
||||
QString defaultSuppressionFile() const;
|
||||
Analyzer::AnalyzerSettings *settings() const { return m_settings; }
|
||||
|
||||
signals:
|
||||
void resized();
|
||||
|
||||
public slots:
|
||||
void settingsChanged(Analyzer::AnalyzerSettings *settings);
|
||||
|
||||
private slots:
|
||||
void suppressError();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
private:
|
||||
QAction *m_copyAction;
|
||||
QAction *m_suppressAction;
|
||||
QString m_defaultSuppFile;
|
||||
Analyzer::AnalyzerSettings *m_settings;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // MEMCHECKERRORVIEW_H
|
||||
280
src/plugins/valgrind/memchecksettings.cpp
Normal file
280
src/plugins/valgrind/memchecksettings.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "memchecksettings.h"
|
||||
#include "memcheckconfigwidget.h"
|
||||
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
|
||||
static const char numCallersC[] = "Analyzer.Valgrind.NumCallers";
|
||||
static const char trackOriginsC[] = "Analyzer.Valgrind.TrackOrigins";
|
||||
static const char suppressionFilesC[] = "Analyzer.Valgrind.SupressionFiles";
|
||||
static const char removedSuppressionFilesC[] = "Analyzer.Valgrind.RemovedSuppressionFiles";
|
||||
static const char addedSuppressionFilesC[] = "Analyzer.Valgrind.AddedSuppressionFiles";
|
||||
static const char filterExternalIssuesC[] = "Analyzer.Valgrind.FilterExternalIssues";
|
||||
static const char visibleErrorKindsC[] = "Analyzer.Valgrind.VisibleErrorKinds";
|
||||
|
||||
static const char lastSuppressionDirectoryC[] = "Analyzer.Valgrind.LastSuppressionDirectory";
|
||||
static const char lastSuppressionHistoryC[] = "Analyzer.Valgrind.LastSuppressionHistory";
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
QVariantMap AbstractMemcheckSettings::defaults() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(QLatin1String(numCallersC), 25);
|
||||
map.insert(QLatin1String(trackOriginsC), true);
|
||||
map.insert(QLatin1String(filterExternalIssuesC), true);
|
||||
|
||||
QVariantList defaultErrorKinds;
|
||||
for (int i = 0; i < Valgrind::XmlProtocol::MemcheckErrorKindCount; ++i)
|
||||
defaultErrorKinds << i;
|
||||
map.insert(QLatin1String(visibleErrorKindsC), defaultErrorKinds);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
bool AbstractMemcheckSettings::fromMap(const QVariantMap &map)
|
||||
{
|
||||
setIfPresent(map, QLatin1String(numCallersC), &m_numCallers);
|
||||
setIfPresent(map, QLatin1String(trackOriginsC), &m_trackOrigins);
|
||||
setIfPresent(map, QLatin1String(filterExternalIssuesC), &m_filterExternalIssues);
|
||||
|
||||
// if we get more of these try a template specialization of setIfPresent for lists...
|
||||
if (map.contains(QLatin1String(visibleErrorKindsC))) {
|
||||
m_visibleErrorKinds.clear();
|
||||
foreach (const QVariant &val, map.value(QLatin1String(visibleErrorKindsC)).toList())
|
||||
m_visibleErrorKinds << val.toInt();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap AbstractMemcheckSettings::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(QLatin1String(numCallersC), m_numCallers);
|
||||
map.insert(QLatin1String(trackOriginsC), m_trackOrigins);
|
||||
map.insert(QLatin1String(filterExternalIssuesC), m_filterExternalIssues);
|
||||
|
||||
QVariantList errorKinds;
|
||||
foreach (int i, m_visibleErrorKinds)
|
||||
errorKinds << i;
|
||||
map.insert(QLatin1String(visibleErrorKindsC), errorKinds);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void AbstractMemcheckSettings::setNumCallers(int numCallers)
|
||||
{
|
||||
if (m_numCallers != numCallers) {
|
||||
m_numCallers = numCallers;
|
||||
emit numCallersChanged(numCallers);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractMemcheckSettings::setTrackOrigins(bool trackOrigins)
|
||||
{
|
||||
if (m_trackOrigins != trackOrigins) {
|
||||
m_trackOrigins = trackOrigins;
|
||||
emit trackOriginsChanged(trackOrigins);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractMemcheckSettings::setFilterExternalIssues(bool filterExternalIssues)
|
||||
{
|
||||
if (m_filterExternalIssues != filterExternalIssues) {
|
||||
m_filterExternalIssues = filterExternalIssues;
|
||||
emit filterExternalIssuesChanged(filterExternalIssues);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractMemcheckSettings::setVisibleErrorKinds(const QList<int> &visibleErrorKinds)
|
||||
{
|
||||
if (m_visibleErrorKinds != visibleErrorKinds) {
|
||||
m_visibleErrorKinds = visibleErrorKinds;
|
||||
emit visibleErrorKindsChanged(visibleErrorKinds);
|
||||
}
|
||||
}
|
||||
|
||||
QString AbstractMemcheckSettings::id() const
|
||||
{
|
||||
return "Analyzer.Valgrind.Settings.Memcheck";
|
||||
}
|
||||
|
||||
QString AbstractMemcheckSettings::displayName() const
|
||||
{
|
||||
return tr("Memory Analysis");
|
||||
}
|
||||
|
||||
QWidget *AbstractMemcheckSettings::createConfigWidget(QWidget *parent)
|
||||
{
|
||||
return new MemcheckConfigWidget(this, parent);
|
||||
}
|
||||
|
||||
QStringList MemcheckGlobalSettings::suppressionFiles() const
|
||||
{
|
||||
return m_suppressionFiles;
|
||||
}
|
||||
|
||||
void MemcheckGlobalSettings::addSuppressionFiles(const QStringList &suppressions)
|
||||
{
|
||||
foreach (const QString &s, suppressions)
|
||||
if (!m_suppressionFiles.contains(s))
|
||||
m_suppressionFiles.append(s);
|
||||
}
|
||||
|
||||
void MemcheckGlobalSettings::removeSuppressionFiles(const QStringList &suppressions)
|
||||
{
|
||||
foreach (const QString &s, suppressions)
|
||||
m_suppressionFiles.removeAll(s);
|
||||
}
|
||||
|
||||
QString MemcheckGlobalSettings::lastSuppressionDialogDirectory() const
|
||||
{
|
||||
return m_lastSuppressionDirectory;
|
||||
}
|
||||
|
||||
void MemcheckGlobalSettings::setLastSuppressionDialogDirectory(const QString &directory)
|
||||
{
|
||||
m_lastSuppressionDirectory = directory;
|
||||
}
|
||||
|
||||
QStringList MemcheckGlobalSettings::lastSuppressionDialogHistory() const
|
||||
{
|
||||
return m_lastSuppressionHistory;
|
||||
}
|
||||
|
||||
void MemcheckGlobalSettings::setLastSuppressionDialogHistory(const QStringList &history)
|
||||
{
|
||||
m_lastSuppressionHistory = history;
|
||||
}
|
||||
|
||||
QVariantMap MemcheckGlobalSettings::defaults() const
|
||||
{
|
||||
QVariantMap ret = AbstractMemcheckSettings::defaults();
|
||||
ret.insert(suppressionFilesC, QStringList());
|
||||
ret.insert(lastSuppressionDirectoryC, QString());
|
||||
ret.insert(lastSuppressionHistoryC, QStringList());
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MemcheckGlobalSettings::fromMap(const QVariantMap &map)
|
||||
{
|
||||
AbstractMemcheckSettings::fromMap(map);
|
||||
m_suppressionFiles = map.value(suppressionFilesC).toStringList();
|
||||
m_lastSuppressionDirectory = map.value(lastSuppressionDirectoryC).toString();
|
||||
m_lastSuppressionHistory = map.value(lastSuppressionHistoryC).toStringList();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap MemcheckGlobalSettings::toMap() const
|
||||
{
|
||||
QVariantMap map = AbstractMemcheckSettings::toMap();
|
||||
map.insert(suppressionFilesC, m_suppressionFiles);
|
||||
map.insert(lastSuppressionDirectoryC, m_lastSuppressionDirectory);
|
||||
map.insert(lastSuppressionHistoryC, m_lastSuppressionHistory);
|
||||
return map;
|
||||
}
|
||||
|
||||
MemcheckGlobalSettings *globalMemcheckSettings()
|
||||
{
|
||||
MemcheckGlobalSettings *ret = AnalyzerGlobalSettings::instance()->subConfig<MemcheckGlobalSettings>();
|
||||
QTC_ASSERT(ret, return 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap MemcheckProjectSettings::defaults() const
|
||||
{
|
||||
QVariantMap ret = AbstractMemcheckSettings::defaults();
|
||||
ret.insert(addedSuppressionFilesC, QStringList());
|
||||
ret.insert(removedSuppressionFilesC, QStringList());
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MemcheckProjectSettings::fromMap(const QVariantMap &map)
|
||||
{
|
||||
AbstractMemcheckSettings::fromMap(map);
|
||||
setIfPresent(map, addedSuppressionFilesC, &m_addedSuppressionFiles);
|
||||
setIfPresent(map, removedSuppressionFilesC, &m_disabledGlobalSuppressionFiles);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap MemcheckProjectSettings::toMap() const
|
||||
{
|
||||
QVariantMap map = AbstractMemcheckSettings::toMap();
|
||||
map.insert(addedSuppressionFilesC, m_addedSuppressionFiles);
|
||||
map.insert(removedSuppressionFilesC, m_disabledGlobalSuppressionFiles);
|
||||
return map;
|
||||
}
|
||||
|
||||
void MemcheckProjectSettings::addSuppressionFiles(const QStringList &suppressions)
|
||||
{
|
||||
QStringList globalSuppressions = globalMemcheckSettings()->suppressionFiles();
|
||||
foreach (const QString &s, suppressions) {
|
||||
if (m_addedSuppressionFiles.contains(s))
|
||||
continue;
|
||||
m_disabledGlobalSuppressionFiles.removeAll(s);
|
||||
if (!globalSuppressions.contains(s))
|
||||
m_addedSuppressionFiles.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
void MemcheckProjectSettings::removeSuppressionFiles(const QStringList &suppressions)
|
||||
{
|
||||
QStringList globalSuppressions = globalMemcheckSettings()->suppressionFiles();
|
||||
foreach (const QString &s, suppressions) {
|
||||
m_addedSuppressionFiles.removeAll(s);
|
||||
if (globalSuppressions.contains(s))
|
||||
m_disabledGlobalSuppressionFiles.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList MemcheckProjectSettings::suppressionFiles() const
|
||||
{
|
||||
QStringList ret = globalMemcheckSettings()->suppressionFiles();
|
||||
foreach (const QString &s, m_disabledGlobalSuppressionFiles)
|
||||
ret.removeAll(s);
|
||||
ret.append(m_addedSuppressionFiles);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
152
src/plugins/valgrind/memchecksettings.h
Normal file
152
src/plugins/valgrind/memchecksettings.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_MEMCHECKSETTINGS_H
|
||||
#define ANALYZER_INTERNAL_MEMCHECKSETTINGS_H
|
||||
|
||||
#include <analyzerbase/analyzersettings.h>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
/**
|
||||
* Generic memcheck settings
|
||||
*/
|
||||
class AbstractMemcheckSettings : public Analyzer::AbstractAnalyzerSubConfig
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AbstractMemcheckSettings() {}
|
||||
|
||||
virtual bool fromMap(const QVariantMap &map);
|
||||
|
||||
int numCallers() const { return m_numCallers; }
|
||||
bool trackOrigins() const { return m_trackOrigins; }
|
||||
bool filterExternalIssues() const { return m_filterExternalIssues; }
|
||||
QList<int> visibleErrorKinds() const { return m_visibleErrorKinds; }
|
||||
|
||||
virtual QStringList suppressionFiles() const = 0;
|
||||
virtual void addSuppressionFiles(const QStringList &) = 0;
|
||||
virtual void removeSuppressionFiles(const QStringList &) = 0;
|
||||
|
||||
virtual QVariantMap defaults() const;
|
||||
|
||||
virtual QString id() const;
|
||||
virtual QString displayName() const;
|
||||
virtual QWidget *createConfigWidget(QWidget *parent);
|
||||
|
||||
public slots:
|
||||
void setNumCallers(int);
|
||||
void setTrackOrigins(bool);
|
||||
void setFilterExternalIssues(bool);
|
||||
void setVisibleErrorKinds(const QList<int> &);
|
||||
|
||||
signals:
|
||||
void numCallersChanged(int);
|
||||
void trackOriginsChanged(bool);
|
||||
void filterExternalIssuesChanged(bool);
|
||||
void visibleErrorKindsChanged(const QList<int> &);
|
||||
void suppressionFilesRemoved(const QStringList &);
|
||||
void suppressionFilesAdded(const QStringList &);
|
||||
|
||||
protected:
|
||||
virtual QVariantMap toMap() const;
|
||||
|
||||
int m_numCallers;
|
||||
bool m_trackOrigins;
|
||||
bool m_filterExternalIssues;
|
||||
QList<int> m_visibleErrorKinds;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global memcheck settings
|
||||
*/
|
||||
class MemcheckGlobalSettings : public AbstractMemcheckSettings
|
||||
{
|
||||
public:
|
||||
MemcheckGlobalSettings() {}
|
||||
|
||||
QStringList suppressionFiles() const;
|
||||
// in the global settings we change the internal list directly
|
||||
void addSuppressionFiles(const QStringList &);
|
||||
void removeSuppressionFiles(const QStringList &);
|
||||
|
||||
QVariantMap toMap() const;
|
||||
QVariantMap defaults() const;
|
||||
|
||||
// internal settings which don't require any UI
|
||||
void setLastSuppressionDialogDirectory(const QString &directory);
|
||||
QString lastSuppressionDialogDirectory() const;
|
||||
|
||||
void setLastSuppressionDialogHistory(const QStringList &history);
|
||||
QStringList lastSuppressionDialogHistory() const;
|
||||
|
||||
protected:
|
||||
bool fromMap(const QVariantMap &map);
|
||||
|
||||
private:
|
||||
QStringList m_suppressionFiles;
|
||||
QString m_lastSuppressionDirectory;
|
||||
QStringList m_lastSuppressionHistory;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-project memcheck settings, saves a diff to the global suppression files list
|
||||
*/
|
||||
class MemcheckProjectSettings : public AbstractMemcheckSettings
|
||||
{
|
||||
public:
|
||||
MemcheckProjectSettings() {}
|
||||
|
||||
QStringList suppressionFiles() const;
|
||||
// in the project-specific settings we store a diff to the global list
|
||||
void addSuppressionFiles(const QStringList &suppressions);
|
||||
void removeSuppressionFiles(const QStringList &suppressions);
|
||||
|
||||
QVariantMap toMap() const;
|
||||
QVariantMap defaults() const;
|
||||
|
||||
protected:
|
||||
bool fromMap(const QVariantMap &map);
|
||||
|
||||
private:
|
||||
QStringList m_disabledGlobalSuppressionFiles;
|
||||
QStringList m_addedSuppressionFiles;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // ANALYZER_INTERNAL_MEMCHECKSETTINGS_H
|
||||
549
src/plugins/valgrind/memchecktool.cpp
Normal file
549
src/plugins/valgrind/memchecktool.cpp
Normal file
@@ -0,0 +1,549 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "memchecktool.h"
|
||||
#include "memcheckengine.h"
|
||||
#include "memcheckerrorview.h"
|
||||
#include "memchecksettings.h"
|
||||
#include "valgrindsettings.h"
|
||||
|
||||
#include <analyzerbase/analyzermanager.h>
|
||||
#include <analyzerbase/analyzerconstants.h>
|
||||
#include <analyzerbase/ianalyzeroutputpaneadapter.h>
|
||||
|
||||
#include <valgrind/xmlprotocol/errorlistmodel.h>
|
||||
#include <valgrind/xmlprotocol/stackmodel.h>
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
#include <valgrind/xmlprotocol/frame.h>
|
||||
#include <valgrind/xmlprotocol/stack.h>
|
||||
#include <valgrind/xmlprotocol/suppression.h>
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/command.h>
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <utils/styledbar.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QLatin1String>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#include <QtGui/QDockWidget>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QComboBox>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QSpinBox>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QToolButton>
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
// Adapter for output pane.
|
||||
class MemCheckOutputPaneAdapter : public Analyzer::ListItemViewOutputPaneAdapter
|
||||
{
|
||||
public:
|
||||
explicit MemCheckOutputPaneAdapter(MemcheckTool *mct) :
|
||||
ListItemViewOutputPaneAdapter(mct), m_tool(mct) {}
|
||||
|
||||
virtual QWidget *toolBarWidget() { return m_tool->createPaneToolBarWidget(); }
|
||||
virtual void clearContents() { m_tool->clearErrorView(); }
|
||||
|
||||
protected:
|
||||
virtual QAbstractItemView *createItemView() { return m_tool->ensurePaneErrorView(); }
|
||||
|
||||
private:
|
||||
MemcheckTool *m_tool;
|
||||
};
|
||||
|
||||
// ---------------------------- MemcheckErrorFilterProxyModel
|
||||
MemcheckErrorFilterProxyModel::MemcheckErrorFilterProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent),
|
||||
m_filterExternalIssues(false)
|
||||
{
|
||||
}
|
||||
|
||||
void MemcheckErrorFilterProxyModel::setAcceptedKinds(const QList<int> &acceptedKinds)
|
||||
{
|
||||
if (m_acceptedKinds != acceptedKinds) {
|
||||
m_acceptedKinds = acceptedKinds;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void MemcheckErrorFilterProxyModel::setFilterExternalIssues(bool filter)
|
||||
{
|
||||
if (m_filterExternalIssues != filter) {
|
||||
m_filterExternalIssues = filter;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
// we only deal with toplevel items
|
||||
if (sourceParent.isValid())
|
||||
return true;
|
||||
|
||||
// because toplevel items have no parent, we can't use sourceParent to find them. we just use
|
||||
// sourceParent as an invalid index, telling the model that the index we're looking for has no
|
||||
// parent.
|
||||
QAbstractItemModel *model = sourceModel();
|
||||
QModelIndex sourceIndex = model->index(sourceRow, filterKeyColumn(), sourceParent);
|
||||
if (!sourceIndex.isValid())
|
||||
return true;
|
||||
|
||||
const Error error = sourceIndex.data(ErrorListModel::ErrorRole).value<Error>();
|
||||
|
||||
// filter on kind
|
||||
if (!m_acceptedKinds.contains(error.kind()))
|
||||
return false;
|
||||
|
||||
// filter non-project stuff
|
||||
if (m_filterExternalIssues && !error.stacks().isEmpty()) {
|
||||
// ALGORITHM: look at last five stack frames, if none of these is inside any open projects,
|
||||
// assume this error was created by an external library
|
||||
ProjectExplorer::SessionManager *session
|
||||
= ProjectExplorer::ProjectExplorerPlugin::instance()->session();
|
||||
QSet<QString> validFolders;
|
||||
foreach (ProjectExplorer::Project *project, session->projects()) {
|
||||
validFolders << project->projectDirectory();
|
||||
foreach (ProjectExplorer::Target *target, project->targets()) {
|
||||
foreach (ProjectExplorer::BuildConfiguration *config, target->buildConfigurations()) {
|
||||
validFolders << config->buildDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QVector< Frame > frames = error.stacks().first().frames();
|
||||
|
||||
const int framesToLookAt = qMin(6, frames.size());
|
||||
|
||||
bool inProject = false;
|
||||
for ( int i = 0; i < framesToLookAt; ++i ) {
|
||||
const Frame &frame = frames.at(i);
|
||||
foreach (const QString &folder, validFolders) {
|
||||
if (frame.object().startsWith(folder)) {
|
||||
inProject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!inProject)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void initKindFilterAction(QAction *action, const QList<int> &kinds)
|
||||
{
|
||||
action->setCheckable(true);
|
||||
QVariantList data;
|
||||
foreach (int kind, kinds)
|
||||
data << kind;
|
||||
action->setData(data);
|
||||
}
|
||||
|
||||
MemcheckTool::MemcheckTool(QObject *parent) :
|
||||
Analyzer::IAnalyzerTool(parent),
|
||||
m_settings(0),
|
||||
m_errorModel(0),
|
||||
m_errorProxyModel(0),
|
||||
m_errorView(0),
|
||||
m_filterProjectAction(new QAction(tr("External Errors"), this)),
|
||||
m_suppressionSeparator(new QAction(tr("Suppressions"), this)),
|
||||
m_outputPaneAdapter(0)
|
||||
{
|
||||
setObjectName(QLatin1String("MemcheckTool"));
|
||||
connect(ProjectExplorer::ProjectExplorerPlugin::instance(),
|
||||
SIGNAL(updateRunActions()), SLOT(maybeActiveRunConfigurationChanged()));
|
||||
|
||||
QAction *a = new QAction(tr("Definite Memory Leaks"), this);
|
||||
initKindFilterAction(a, QList<int>() << Leak_DefinitelyLost << Leak_IndirectlyLost);
|
||||
m_errorFilterActions << a;
|
||||
|
||||
a = new QAction(tr("Possible Memory Leaks"), this);
|
||||
initKindFilterAction(a, QList<int>() << Leak_PossiblyLost << Leak_StillReachable);
|
||||
m_errorFilterActions << a;
|
||||
|
||||
a = new QAction(tr("Use of Uninitialized Memory"), this);
|
||||
initKindFilterAction(a, QList<int>() << InvalidRead << InvalidWrite << InvalidJump << Overlap
|
||||
<< InvalidMemPool << UninitCondition << UninitValue
|
||||
<< SyscallParam << ClientCheck);
|
||||
m_errorFilterActions << a;
|
||||
|
||||
a = new QAction(tr("Invalid Frees"), this);
|
||||
initKindFilterAction(a, QList<int>() << InvalidFree << MismatchedFree);
|
||||
m_errorFilterActions << a;
|
||||
|
||||
m_filterProjectAction->setToolTip(tr("Show issues originating outside currently opened projects."));
|
||||
m_filterProjectAction->setCheckable(true);
|
||||
|
||||
m_suppressionSeparator->setSeparator(true);
|
||||
m_suppressionSeparator->setToolTip(tr("These suppression files were used in the last memory analyzer run."));
|
||||
}
|
||||
|
||||
void MemcheckTool::settingsDestroyed(QObject *settings)
|
||||
{
|
||||
QTC_ASSERT(m_settings == settings, return);
|
||||
m_settings = AnalyzerGlobalSettings::instance();
|
||||
}
|
||||
|
||||
void MemcheckTool::maybeActiveRunConfigurationChanged()
|
||||
{
|
||||
AnalyzerSettings *settings = 0;
|
||||
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
|
||||
if (ProjectExplorer::Project *project = pe->startupProject()) {
|
||||
if (ProjectExplorer::Target *target = project->activeTarget()) {
|
||||
if (ProjectExplorer::RunConfiguration *rc = target->activeRunConfiguration()) {
|
||||
settings = rc->extraAspect<AnalyzerProjectSettings>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings) // fallback to global settings
|
||||
settings = AnalyzerGlobalSettings::instance();
|
||||
|
||||
if (m_settings == settings)
|
||||
return;
|
||||
|
||||
// disconnect old settings class if any
|
||||
if (m_settings) {
|
||||
m_settings->disconnect(this);
|
||||
m_settings->disconnect(m_errorProxyModel);
|
||||
}
|
||||
|
||||
// now make the new settings current, update and connect input widgets
|
||||
m_settings = settings;
|
||||
QTC_ASSERT(m_settings, return);
|
||||
|
||||
connect(m_settings, SIGNAL(destroyed(QObject *)), SLOT(settingsDestroyed(QObject *)));
|
||||
|
||||
AbstractMemcheckSettings *memcheckSettings = m_settings->subConfig<AbstractMemcheckSettings>();
|
||||
QTC_ASSERT(memcheckSettings, return);
|
||||
|
||||
foreach (QAction *action, m_errorFilterActions) {
|
||||
bool contained = true;
|
||||
foreach (const QVariant &v, action->data().toList()) {
|
||||
bool ok;
|
||||
int kind = v.toInt(&ok);
|
||||
if (ok && !memcheckSettings->visibleErrorKinds().contains(kind))
|
||||
contained = false;
|
||||
}
|
||||
action->setChecked(contained);
|
||||
}
|
||||
|
||||
m_filterProjectAction->setChecked(!memcheckSettings->filterExternalIssues());
|
||||
|
||||
m_errorView->settingsChanged(m_settings);
|
||||
|
||||
connect(memcheckSettings, SIGNAL(visibleErrorKindsChanged(QList<int>)),
|
||||
m_errorProxyModel, SLOT(setAcceptedKinds(QList<int>)));
|
||||
m_errorProxyModel->setAcceptedKinds(memcheckSettings->visibleErrorKinds());
|
||||
|
||||
connect(memcheckSettings, SIGNAL(filterExternalIssuesChanged(bool)),
|
||||
m_errorProxyModel, SLOT(setFilterExternalIssues(bool)));
|
||||
m_errorProxyModel->setFilterExternalIssues(memcheckSettings->filterExternalIssues());
|
||||
}
|
||||
|
||||
QString MemcheckTool::id() const
|
||||
{
|
||||
return "Memcheck";
|
||||
}
|
||||
|
||||
QString MemcheckTool::displayName() const
|
||||
{
|
||||
return tr("Analyze Memory");
|
||||
}
|
||||
|
||||
IAnalyzerTool::ToolMode MemcheckTool::mode() const
|
||||
{
|
||||
return DebugMode;
|
||||
}
|
||||
|
||||
class FrameFinder : public ErrorListModel::RelevantFrameFinder
|
||||
{
|
||||
public:
|
||||
Frame findRelevant(const Error &error) const
|
||||
{
|
||||
const QVector<Stack> stacks = error.stacks();
|
||||
if (stacks.isEmpty())
|
||||
return Frame();
|
||||
const Stack &stack = stacks[0];
|
||||
const QVector<Frame> frames = stack.frames();
|
||||
if (frames.isEmpty())
|
||||
return Frame();
|
||||
|
||||
//find the first frame belonging to the project
|
||||
if (!m_projectFiles.isEmpty()) {
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (frame.directory().isEmpty() || frame.file().isEmpty())
|
||||
continue;
|
||||
|
||||
//filepaths can contain "..", clean them:
|
||||
const QString f = QFileInfo(frame.directory() + QLatin1Char('/') + frame.file()).absoluteFilePath();
|
||||
if (m_projectFiles.contains(f))
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//if no frame belonging to the project was found, return the first one that is not malloc/new
|
||||
foreach (const Frame &frame, frames) {
|
||||
if (!frame.functionName().isEmpty() && frame.functionName() != QLatin1String("malloc")
|
||||
&& !frame.functionName().startsWith("operator new(") )
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
//else fallback to the first frame
|
||||
return frames.first();
|
||||
}
|
||||
void setFiles(const QStringList &files)
|
||||
{
|
||||
m_projectFiles = files;
|
||||
}
|
||||
private:
|
||||
QStringList m_projectFiles;
|
||||
};
|
||||
|
||||
MemcheckErrorView *MemcheckTool::ensurePaneErrorView()
|
||||
{
|
||||
if (!m_errorView) {
|
||||
m_errorView = new MemcheckErrorView;
|
||||
m_errorView->setObjectName(QLatin1String("MemcheckErrorView"));
|
||||
m_errorView->setFrameStyle(QFrame::NoFrame);
|
||||
m_errorView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_errorModel = new ErrorListModel(m_errorView);
|
||||
m_frameFinder = new Internal::FrameFinder;
|
||||
m_errorModel->setRelevantFrameFinder(QSharedPointer<Internal::FrameFinder>(m_frameFinder));
|
||||
m_errorProxyModel = new MemcheckErrorFilterProxyModel(m_errorView);
|
||||
m_errorProxyModel->setSourceModel(m_errorModel);
|
||||
m_errorProxyModel->setDynamicSortFilter(true);
|
||||
m_errorView->setModel(m_errorProxyModel);
|
||||
m_errorView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
// make m_errorView->selectionModel()->selectedRows() return something
|
||||
m_errorView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_errorView->setAutoScroll(false);
|
||||
m_errorView->setObjectName("Valgrind.MemcheckTool.ErrorView");
|
||||
}
|
||||
return m_errorView;
|
||||
}
|
||||
|
||||
QWidget *MemcheckTool::createPaneToolBarWidget()
|
||||
{
|
||||
QWidget *toolbarWidget = new QWidget;
|
||||
toolbarWidget->setObjectName(QLatin1String("MemCheckToolBarWidget"));
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
// filter
|
||||
QToolButton *filterButton = new QToolButton;
|
||||
filterButton->setIcon(QIcon(Core::Constants::ICON_FILTER));
|
||||
filterButton->setText(tr("Error Filter"));
|
||||
filterButton->setPopupMode(QToolButton::InstantPopup);
|
||||
QMenu *filterMenu = new QMenu(filterButton);
|
||||
foreach (QAction *filterAction, m_errorFilterActions)
|
||||
filterMenu->addAction(filterAction);
|
||||
filterMenu->addSeparator();
|
||||
filterMenu->addAction(m_filterProjectAction);
|
||||
filterMenu->addAction(m_suppressionSeparator);
|
||||
connect(filterMenu, SIGNAL(triggered(QAction *)), SLOT(updateErrorFilter()));
|
||||
filterButton->setMenu(filterMenu);
|
||||
layout->addWidget(filterButton);
|
||||
layout->addStretch();
|
||||
toolbarWidget->setLayout(layout);
|
||||
return toolbarWidget;
|
||||
}
|
||||
|
||||
void MemcheckTool::initialize()
|
||||
{
|
||||
ensurePaneErrorView();
|
||||
// register shortcuts
|
||||
maybeActiveRunConfigurationChanged();
|
||||
}
|
||||
|
||||
IAnalyzerEngine *MemcheckTool::createEngine(const AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration)
|
||||
{
|
||||
m_frameFinder->setFiles(runConfiguration ? runConfiguration->target()->project()->files(ProjectExplorer::Project::AllFiles) : QStringList());
|
||||
|
||||
MemcheckEngine *engine = new MemcheckEngine(sp, runConfiguration);
|
||||
|
||||
connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)),
|
||||
this, SLOT(engineStarting(const Analyzer::IAnalyzerEngine*)));
|
||||
connect(engine, SIGNAL(parserError(Valgrind::XmlProtocol::Error)),
|
||||
this, SLOT(parserError(Valgrind::XmlProtocol::Error)));
|
||||
connect(engine, SIGNAL(internalParserError(QString)),
|
||||
this, SLOT(internalParserError(QString)));
|
||||
connect(engine, SIGNAL(finished()), this, SLOT(finished()));
|
||||
AnalyzerManager::instance()->showStatusMessage(AnalyzerManager::msgToolStarted(displayName()));
|
||||
return engine;
|
||||
}
|
||||
|
||||
void MemcheckTool::engineStarting(const IAnalyzerEngine *engine)
|
||||
{
|
||||
clearErrorView();
|
||||
|
||||
QString dir;
|
||||
if (ProjectExplorer::RunConfiguration *rc = engine->runConfiguration())
|
||||
dir = rc->target()->project()->projectDirectory() + QDir::separator();
|
||||
|
||||
const MemcheckEngine *mEngine = dynamic_cast<const MemcheckEngine *>(engine);
|
||||
QTC_ASSERT(mEngine, return);
|
||||
const QString name = QFileInfo(mEngine->executable()).fileName();
|
||||
|
||||
m_errorView->setDefaultSuppressionFile(dir + name + QLatin1String(".supp"));
|
||||
|
||||
QMenu *menu = filterMenu();
|
||||
QTC_ASSERT(menu, return);
|
||||
foreach (const QString &file, mEngine->suppressionFiles()) {
|
||||
QAction *action = menu->addAction(QFileInfo(file).fileName());
|
||||
action->setToolTip(file);
|
||||
action->setData(file);
|
||||
connect(action, SIGNAL(triggered(bool)),
|
||||
this, SLOT(suppressionActionTriggered()));
|
||||
m_suppressionActions << action;
|
||||
}
|
||||
}
|
||||
|
||||
QMenu *MemcheckTool::filterMenu() const
|
||||
{
|
||||
QTC_ASSERT(m_suppressionSeparator, return 0);
|
||||
foreach (QWidget *w, m_suppressionSeparator->associatedWidgets())
|
||||
if (QMenu *menu = qobject_cast<QMenu *>(w))
|
||||
return menu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemcheckTool::suppressionActionTriggered()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction *>(sender());
|
||||
QTC_ASSERT(action, return);
|
||||
const QString file = action->data().toString();
|
||||
QTC_ASSERT(!file.isEmpty(), return);
|
||||
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(file, 0);
|
||||
}
|
||||
|
||||
void MemcheckTool::parserError(const Valgrind::XmlProtocol::Error &error)
|
||||
{
|
||||
m_errorModel->addError(error);
|
||||
}
|
||||
|
||||
void MemcheckTool::internalParserError(const QString &errorString)
|
||||
{
|
||||
QMessageBox::critical(m_errorView, tr("Internal Error"),
|
||||
tr("Error occurred parsing valgrind output: %1").arg(errorString));
|
||||
}
|
||||
|
||||
void MemcheckTool::clearErrorView()
|
||||
{
|
||||
m_errorModel->clear();
|
||||
|
||||
qDeleteAll(m_suppressionActions);
|
||||
m_suppressionActions.clear();
|
||||
QTC_ASSERT(filterMenu()->actions().last() == m_suppressionSeparator, qt_noop());
|
||||
}
|
||||
|
||||
void MemcheckTool::updateErrorFilter()
|
||||
{
|
||||
QTC_ASSERT(m_settings, return);
|
||||
|
||||
AbstractMemcheckSettings *memcheckSettings = m_settings->subConfig<AbstractMemcheckSettings>();
|
||||
QTC_ASSERT(memcheckSettings, return);
|
||||
memcheckSettings->setFilterExternalIssues(!m_filterProjectAction->isChecked());
|
||||
|
||||
QList<int> errorKinds;
|
||||
foreach (QAction *a, m_errorFilterActions) {
|
||||
if (!a->isChecked())
|
||||
continue;
|
||||
foreach (const QVariant &v, a->data().toList()) {
|
||||
bool ok;
|
||||
int kind = v.toInt(&ok);
|
||||
if (ok)
|
||||
errorKinds << kind;
|
||||
}
|
||||
}
|
||||
memcheckSettings->setVisibleErrorKinds(errorKinds);
|
||||
}
|
||||
|
||||
IAnalyzerOutputPaneAdapter *MemcheckTool::outputPaneAdapter()
|
||||
{
|
||||
if (!m_outputPaneAdapter)
|
||||
m_outputPaneAdapter = new MemCheckOutputPaneAdapter(this);
|
||||
return m_outputPaneAdapter;
|
||||
}
|
||||
|
||||
void MemcheckTool::finished()
|
||||
{
|
||||
const QString msg = AnalyzerManager::msgToolFinished(displayName(), m_errorModel->rowCount());
|
||||
AnalyzerManager::instance()->showStatusMessage(msg);
|
||||
}
|
||||
|
||||
bool MemcheckTool::canRunRemotely() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
149
src/plugins/valgrind/memchecktool.h
Normal file
149
src/plugins/valgrind/memchecktool.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MEMCHECKTOOL_H
|
||||
#define MEMCHECKTOOL_H
|
||||
|
||||
#include <analyzerbase/ianalyzertool.h>
|
||||
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QItemSelection;
|
||||
class QTreeView;
|
||||
class QModelIndex;
|
||||
class QAction;
|
||||
class QSpinBox;
|
||||
class QCheckBox;
|
||||
class QMenu;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Valgrind {
|
||||
namespace XmlProtocol {
|
||||
class ErrorListModel;
|
||||
class Error;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Analyzer
|
||||
{
|
||||
class AnalyzerSettings;
|
||||
}
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class MemCheckOutputPaneAdapter;
|
||||
class MemcheckErrorView;
|
||||
class FrameFinder;
|
||||
|
||||
class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemcheckErrorFilterProxyModel(QObject *parent = 0);
|
||||
|
||||
public slots:
|
||||
void setAcceptedKinds(const QList<int> &acceptedKinds);
|
||||
void setFilterExternalIssues(bool filter);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
private:
|
||||
QList<int> m_acceptedKinds;
|
||||
bool m_filterExternalIssues;
|
||||
};
|
||||
|
||||
class MemcheckTool : public Analyzer::IAnalyzerTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MemcheckTool(QObject *parent = 0);
|
||||
|
||||
QString id() const;
|
||||
QString displayName() const;
|
||||
ToolMode mode() const;
|
||||
|
||||
void initialize();
|
||||
void extensionsInitialized() {}
|
||||
|
||||
Analyzer::IAnalyzerOutputPaneAdapter *outputPaneAdapter();
|
||||
Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration = 0);
|
||||
|
||||
// For the output pane adapter.
|
||||
MemcheckErrorView *ensurePaneErrorView();
|
||||
QWidget *createPaneToolBarWidget();
|
||||
void clearErrorView();
|
||||
|
||||
bool canRunRemotely() const;
|
||||
bool needsOutputPane() const { return true; }
|
||||
|
||||
private slots:
|
||||
void settingsDestroyed(QObject *settings);
|
||||
void maybeActiveRunConfigurationChanged();
|
||||
|
||||
void engineStarting(const Analyzer::IAnalyzerEngine *engine);
|
||||
void finished();
|
||||
|
||||
void parserError(const Valgrind::XmlProtocol::Error &error);
|
||||
void internalParserError(const QString &errorString);
|
||||
void updateErrorFilter();
|
||||
void suppressionActionTriggered();
|
||||
|
||||
private:
|
||||
QMenu *filterMenu() const;
|
||||
|
||||
Analyzer::AnalyzerSettings *m_settings;
|
||||
|
||||
FrameFinder *m_frameFinder;
|
||||
Valgrind::XmlProtocol::ErrorListModel *m_errorModel;
|
||||
MemcheckErrorFilterProxyModel *m_errorProxyModel;
|
||||
MemcheckErrorView *m_errorView;
|
||||
|
||||
QList<QAction *> m_errorFilterActions;
|
||||
QAction *m_filterProjectAction;
|
||||
QList<QAction *> m_suppressionActions;
|
||||
QAction *m_suppressionSeparator;
|
||||
MemCheckOutputPaneAdapter *m_outputPaneAdapter;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // MEMCHECKTOOL_H
|
||||
259
src/plugins/valgrind/suppressiondialog.cpp
Normal file
259
src/plugins/valgrind/suppressiondialog.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "suppressiondialog.h"
|
||||
#include "ui_suppressiondialog.h"
|
||||
|
||||
#include "memcheckerrorview.h"
|
||||
#include "memchecksettings.h"
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtGui/QPushButton>
|
||||
|
||||
#include <valgrind/xmlprotocol/suppression.h>
|
||||
#include <valgrind/xmlprotocol/errorlistmodel.h>
|
||||
#include <valgrind/xmlprotocol/stack.h>
|
||||
#include <valgrind/xmlprotocol/frame.h>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
namespace {
|
||||
|
||||
QString suppressionText(const Error &error)
|
||||
{
|
||||
Suppression sup(error.suppression());
|
||||
|
||||
// workaround: https://bugs.kde.org/show_bug.cgi?id=255822
|
||||
if (sup.frames().size() >= 24) {
|
||||
sup.setFrames(sup.frames().mid(0, 23));
|
||||
}
|
||||
QTC_ASSERT(sup.frames().size() < 24, qt_noop());
|
||||
|
||||
// try to set some useful name automatically, instead of "insert_name_here"
|
||||
// we take the last stack frame and append the suppression kind, e.g.:
|
||||
// QDebug::operator<<(bool) [Memcheck:Cond]
|
||||
if (!error.stacks().isEmpty() && !error.stacks().first().frames().isEmpty()) {
|
||||
const Frame &frame = error.stacks().first().frames().first();
|
||||
|
||||
QString newName;
|
||||
if (!frame.functionName().isEmpty())
|
||||
newName = frame.functionName();
|
||||
else if (!frame.object().isEmpty())
|
||||
newName = frame.object();
|
||||
|
||||
if (!newName.isEmpty()) {
|
||||
sup.setName(newName + '[' + sup.kind() + ']');
|
||||
}
|
||||
}
|
||||
|
||||
return sup.toString();
|
||||
}
|
||||
|
||||
/// @p error input error, which might get hidden when it has the same stack
|
||||
/// @p suppressed the error that got suppressed already
|
||||
static bool equalSuppression(const Error &error, const Error &suppressed)
|
||||
{
|
||||
if (error.kind() != suppressed.kind() || error.suppression().isNull())
|
||||
return false;
|
||||
|
||||
const SuppressionFrames errorFrames = error.suppression().frames();
|
||||
const SuppressionFrames suppressedFrames = suppressed.suppression().frames();
|
||||
|
||||
// limit to 23 frames, see: https://bugs.kde.org/show_bug.cgi?id=255822
|
||||
if (qMin(23, suppressedFrames.size()) > errorFrames.size())
|
||||
return false;
|
||||
|
||||
int frames = 23;
|
||||
if (errorFrames.size() < frames)
|
||||
frames = errorFrames.size();
|
||||
|
||||
if (suppressedFrames.size() < frames)
|
||||
frames = suppressedFrames.size();
|
||||
|
||||
for (int i = 0; i < frames; ++i) {
|
||||
if (errorFrames.at(i) != suppressedFrames.at(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sortIndizesReverse(const QModelIndex &l, const QModelIndex &r)
|
||||
{
|
||||
return l.row() > r.row();
|
||||
}
|
||||
|
||||
} // namespace anoe
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
SuppressionDialog::SuppressionDialog(MemcheckErrorView *view, QWidget *parent, Qt::WindowFlags f)
|
||||
: QDialog(parent, f),
|
||||
m_view(view),
|
||||
m_ui(new Ui::SuppressionDialog),
|
||||
m_settings(view->settings()),
|
||||
m_cleanupIfCanceled(false)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
///NOTE: pathchooser requires existing files...
|
||||
QFile defaultSuppFile(view->defaultSuppressionFile());
|
||||
if (!defaultSuppFile.exists()) {
|
||||
if (defaultSuppFile.open(QIODevice::WriteOnly)) {
|
||||
defaultSuppFile.close();
|
||||
m_cleanupIfCanceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: first set kind, then set path since otherwise the file will be seen as "invalid"
|
||||
m_ui->fileChooser->setExpectedKind(Utils::PathChooser::File);
|
||||
m_ui->fileChooser->setPath(defaultSuppFile.fileName());
|
||||
m_ui->fileChooser->setPromptDialogFilter(QLatin1String("*.supp"));
|
||||
m_ui->fileChooser->setPromptDialogTitle(tr("Select Suppression File"));
|
||||
connect(m_ui->fileChooser, SIGNAL(validChanged()),
|
||||
SLOT(validate()));
|
||||
connect(m_ui->suppressionEdit->document(), SIGNAL(contentsChanged()),
|
||||
SLOT(validate()));
|
||||
|
||||
QString suppressions;
|
||||
QModelIndexList indizes = m_view->selectionModel()->selectedRows();
|
||||
if (indizes.isEmpty() && m_view->selectionModel()->currentIndex().isValid()) {
|
||||
// can happen when using arrow keys to navigate and shortcut to trigger suppression
|
||||
indizes << m_view->selectionModel()->currentIndex();
|
||||
}
|
||||
foreach (const QModelIndex &index, indizes) {
|
||||
Error error = m_view->model()->data(index, ErrorListModel::ErrorRole).value<Error>();
|
||||
if (!error.suppression().isNull())
|
||||
m_errors << error;
|
||||
}
|
||||
|
||||
foreach (const Error &error, m_errors)
|
||||
suppressions += suppressionText(error);
|
||||
|
||||
m_ui->suppressionEdit->setPlainText(suppressions);
|
||||
|
||||
setWindowTitle(tr("Save Suppression"));
|
||||
}
|
||||
|
||||
bool SuppressionDialog::shouldShow() const
|
||||
{
|
||||
return !m_errors.isEmpty();
|
||||
}
|
||||
|
||||
void SuppressionDialog::accept()
|
||||
{
|
||||
const QString path = m_ui->fileChooser->path();
|
||||
QTC_ASSERT(!path.isEmpty(), return);
|
||||
QTC_ASSERT(!m_ui->suppressionEdit->toPlainText().trimmed().isEmpty(), return);
|
||||
|
||||
Utils::FileSaver saver(path, QIODevice::Append);
|
||||
QTextStream stream(saver.file());
|
||||
stream << m_ui->suppressionEdit->toPlainText();
|
||||
saver.setResult(&stream);
|
||||
if (!saver.finalize(this))
|
||||
return;
|
||||
|
||||
// add file to project (if there is a project that contains this file on the file system)
|
||||
ProjectExplorer::SessionManager *session = ProjectExplorer::ProjectExplorerPlugin::instance()->session();
|
||||
if (!session->projectForFile(path)) {
|
||||
foreach (ProjectExplorer::Project *p, session->projects()) {
|
||||
if (path.startsWith(p->projectDirectory())) {
|
||||
p->rootProjectNode()->addFiles(ProjectExplorer::UnknownFileType, QStringList() << path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_settings->subConfig<AbstractMemcheckSettings>()->addSuppressionFiles(QStringList(path));
|
||||
|
||||
QModelIndexList indizes = m_view->selectionModel()->selectedRows();
|
||||
qSort(indizes.begin(), indizes.end(), sortIndizesReverse);
|
||||
foreach (const QModelIndex &index, indizes) {
|
||||
bool removed = m_view->model()->removeRow(index.row());
|
||||
QTC_ASSERT(removed, qt_noop());
|
||||
Q_UNUSED(removed);
|
||||
}
|
||||
|
||||
// one suppression might hide multiple rows, care for that
|
||||
for (int row = 0; row < m_view->model()->rowCount(); ++row ) {
|
||||
const Error rowError = m_view->model()->data(
|
||||
m_view->model()->index(row, 0), ErrorListModel::ErrorRole).value<Error>();
|
||||
|
||||
foreach (const Error &error, m_errors) {
|
||||
if (equalSuppression(rowError, error)) {
|
||||
bool removed = m_view->model()->removeRow(row);
|
||||
QTC_ASSERT(removed, qt_noop());
|
||||
Q_UNUSED(removed);
|
||||
// gets increased in the for loop again
|
||||
--row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select a new item
|
||||
m_view->setCurrentIndex(indizes.first());
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void SuppressionDialog::reject()
|
||||
{
|
||||
if (m_cleanupIfCanceled)
|
||||
QFile::remove(m_view->defaultSuppressionFile());
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void SuppressionDialog::validate()
|
||||
{
|
||||
bool valid = m_ui->fileChooser->isValid()
|
||||
&& !m_ui->suppressionEdit->toPlainText().trimmed().isEmpty();
|
||||
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(valid);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
81
src/plugins/valgrind/suppressiondialog.h
Normal file
81
src/plugins/valgrind/suppressiondialog.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_VALGRIND_INTERNAL_SUPPRESSIONDIALOG_H
|
||||
#define ANALYZER_VALGRIND_INTERNAL_SUPPRESSIONDIALOG_H
|
||||
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
|
||||
namespace Analyzer {
|
||||
class AnalyzerSettings;
|
||||
}
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class SuppressionDialog;
|
||||
}
|
||||
|
||||
class MemcheckErrorView;
|
||||
|
||||
class SuppressionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SuppressionDialog(MemcheckErrorView *view, QWidget *parent = 0,
|
||||
Qt::WindowFlags f = 0);
|
||||
virtual void accept();
|
||||
virtual void reject();
|
||||
|
||||
bool shouldShow() const;
|
||||
|
||||
private slots:
|
||||
void validate();
|
||||
|
||||
private:
|
||||
MemcheckErrorView *m_view;
|
||||
Ui::SuppressionDialog *m_ui;
|
||||
Analyzer::AnalyzerSettings *m_settings;
|
||||
bool m_cleanupIfCanceled;
|
||||
QList<Valgrind::XmlProtocol::Error> m_errors;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // ANALYZER_VALGRIND_INTERNAL_SUPPRESSIONDIALOG_H
|
||||
107
src/plugins/valgrind/suppressiondialog.ui
Normal file
107
src/plugins/valgrind/suppressiondialog.ui
Normal file
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Valgrind::Internal::SuppressionDialog</class>
|
||||
<widget class="QDialog" name="Valgrind::Internal::SuppressionDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>718</width>
|
||||
<height>424</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="fileLabel">
|
||||
<property name="text">
|
||||
<string>Suppression File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Utils::PathChooser" name="fileChooser" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="suppressionsLabel">
|
||||
<property name="text">
|
||||
<string>Suppression:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>suppressionEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPlainTextEdit" name="suppressionEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Utils::PathChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Memcheck::Internal::SuppressionDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>322</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Memcheck::Internal::SuppressionDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>254</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
4
src/plugins/valgrind/valgrind.pri
Normal file
4
src/plugins/valgrind/valgrind.pri
Normal file
@@ -0,0 +1,4 @@
|
||||
include(valgrind_dependencies.pri)
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
LIBS *= -l$$qtLibraryName(Valgrind)
|
||||
67
src/plugins/valgrind/valgrind.pro
Normal file
67
src/plugins/valgrind/valgrind.pro
Normal file
@@ -0,0 +1,67 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = Valgrind
|
||||
|
||||
DEFINES += VALGRIND_LIBRARY
|
||||
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(valgrind.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
HEADERS += \
|
||||
valgrindplugin.h \
|
||||
valgrind_global.h \
|
||||
valgrindengine.h \
|
||||
valgrindconfigwidget.h \
|
||||
valgrindsettings.h \
|
||||
\
|
||||
callgrindconfigwidget.h \
|
||||
callgrindcostdelegate.h \
|
||||
callgrindcostview.h \
|
||||
callgrindhelper.h \
|
||||
callgrindnamedelegate.h \
|
||||
callgrindsettings.h \
|
||||
callgrindtool.h \
|
||||
callgrindvisualisation.h \
|
||||
callgrindengine.h \
|
||||
workarounds.h \
|
||||
callgrindtextmark.h \
|
||||
\
|
||||
memchecktool.h \
|
||||
memcheckengine.h \
|
||||
memcheckerrorview.h \
|
||||
memchecksettings.h \
|
||||
memcheckconfigwidget.h \
|
||||
suppressiondialog.h
|
||||
|
||||
SOURCES += \
|
||||
valgrindplugin.cpp \
|
||||
valgrindengine.cpp \
|
||||
valgrindconfigwidget.cpp \
|
||||
valgrindsettings.cpp \
|
||||
\
|
||||
callgrindconfigwidget.cpp \
|
||||
callgrindcostdelegate.cpp \
|
||||
callgrindcostview.cpp \
|
||||
callgrindhelper.cpp \
|
||||
callgrindnamedelegate.cpp \
|
||||
callgrindsettings.cpp \
|
||||
callgrindtool.cpp \
|
||||
callgrindvisualisation.cpp \
|
||||
callgrindengine.cpp \
|
||||
workarounds.cpp \
|
||||
callgrindtextmark.cpp \
|
||||
\
|
||||
memchecktool.cpp \
|
||||
memcheckengine.cpp \
|
||||
memcheckerrorview.cpp \
|
||||
memchecksettings.cpp \
|
||||
memcheckconfigwidget.cpp \
|
||||
suppressiondialog.cpp
|
||||
|
||||
FORMS += \
|
||||
valgrindconfigwidget.ui \
|
||||
callgrindconfigwidget.ui \
|
||||
suppressiondialog.ui \
|
||||
memcheckconfigwidget.ui
|
||||
|
||||
4
src/plugins/valgrind/valgrind_dependencies.pri
Normal file
4
src/plugins/valgrind/valgrind_dependencies.pri
Normal file
@@ -0,0 +1,4 @@
|
||||
include(../../libs/cplusplus/cplusplus.pri)
|
||||
include(../../plugins/analyzerbase/analyzerbase.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../plugins/texteditor/texteditor.pri)
|
||||
46
src/plugins/valgrind/valgrind_global.h
Normal file
46
src/plugins/valgrind/valgrind_global.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef VALGRINDTOOLBASE_GLOBAL_H
|
||||
#define VALGRINDTOOLBASE_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(VALGRINDTOOLBASE_LIBRARY)
|
||||
# define VALGRINDTOOLBASE_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define VALGRINDTOOLBASE_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // VALGRINDTOOLBASE_GLOBAL_H
|
||||
63
src/plugins/valgrind/valgrindconfigwidget.cpp
Normal file
63
src/plugins/valgrind/valgrindconfigwidget.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "valgrindconfigwidget.h"
|
||||
|
||||
#include "ui_valgrindconfigwidget.h"
|
||||
|
||||
#include "valgrindsettings.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace Valgrind::Internal;
|
||||
|
||||
ValgrindConfigWidget::ValgrindConfigWidget(ValgrindSettings *settings, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_settings(settings),
|
||||
m_ui(new Ui::ValgrindConfigWidget)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->valgrindExeChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_ui->valgrindExeChooser->setPromptDialogTitle(tr("Valgrind Command"));
|
||||
|
||||
m_ui->valgrindExeChooser->setPath(m_settings->valgrindExecutable());
|
||||
connect(m_ui->valgrindExeChooser, SIGNAL(changed(QString)), m_settings, SLOT(setValgrindExecutable(QString)));
|
||||
connect(m_settings, SIGNAL(valgrindExecutableChanged(QString)), m_ui->valgrindExeChooser, SLOT(setPath(QString)));
|
||||
}
|
||||
|
||||
ValgrindConfigWidget::~ValgrindConfigWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
66
src/plugins/valgrind/valgrindconfigwidget.h
Normal file
66
src/plugins/valgrind/valgrindconfigwidget.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_VALGRINDCONFIGWIDGET_H
|
||||
#define ANALYZER_INTERNAL_VALGRINDCONFIGWIDGET_H
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class ValgrindConfigWidget;
|
||||
}
|
||||
|
||||
class ValgrindSettings;
|
||||
|
||||
class ValgrindConfigWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ValgrindConfigWidget(ValgrindSettings *settings, QWidget *parent);
|
||||
virtual ~ValgrindConfigWidget();
|
||||
|
||||
private:
|
||||
ValgrindSettings *m_settings;
|
||||
Ui::ValgrindConfigWidget *m_ui;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ANALYZER_INTERNAL_VALGRINDCONFIGWIDGET_H
|
||||
54
src/plugins/valgrind/valgrindconfigwidget.ui
Normal file
54
src/plugins/valgrind/valgrindconfigwidget.ui
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Valgrind::Internal::ValgrindConfigWidget</class>
|
||||
<widget class="QWidget" name="Valgrind::Internal::ValgrindConfigWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>445</width>
|
||||
<height>543</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="commonValgrindOptions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Generic Settings</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="valgrindExeLabel">
|
||||
<property name="text">
|
||||
<string>Valgrind executable:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Utils::PathChooser" name="valgrindExeChooser" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Utils::PathChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
197
src/plugins/valgrind/valgrindengine.cpp
Normal file
197
src/plugins/valgrind/valgrindengine.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "valgrindengine.h"
|
||||
#include "valgrindsettings.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/ioutputpane.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <coreplugin/progressmanager/futureprogress.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/applicationrunconfiguration.h>
|
||||
#include <analyzerbase/analyzermanager.h>
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QMainWindow>
|
||||
|
||||
#define VALGRIND_DEBUG_OUTPUT 0
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Valgrind::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
ValgrindEngine::ValgrindEngine(const AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration)
|
||||
: IAnalyzerEngine(sp, runConfiguration),
|
||||
m_settings(0),
|
||||
m_progress(new QFutureInterface<void>()),
|
||||
m_progressWatcher(new QFutureWatcher<void>()),
|
||||
m_isStopping(false)
|
||||
{
|
||||
if (runConfiguration)
|
||||
m_settings = runConfiguration->extraAspect<AnalyzerProjectSettings>();
|
||||
|
||||
if (!m_settings)
|
||||
m_settings = AnalyzerGlobalSettings::instance();
|
||||
|
||||
connect(m_progressWatcher, SIGNAL(canceled()),
|
||||
this, SLOT(handleProgressCanceled()));
|
||||
connect(m_progressWatcher, SIGNAL(finished()),
|
||||
this, SLOT(handleProgressFinished()));
|
||||
}
|
||||
|
||||
ValgrindEngine::~ValgrindEngine()
|
||||
{
|
||||
delete m_progress;
|
||||
}
|
||||
|
||||
void ValgrindEngine::start()
|
||||
{
|
||||
emit starting(this);
|
||||
|
||||
Core::FutureProgress *fp = Core::ICore::instance()->progressManager()->addTask(m_progress->future(),
|
||||
progressTitle(), "valgrind");
|
||||
fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
|
||||
m_progress->reportStarted();
|
||||
m_progressWatcher->setFuture(m_progress->future());
|
||||
|
||||
#if VALGRIND_DEBUG_OUTPUT
|
||||
emit standardOutputReceived(tr("Valgrind options: %1").arg(toolArguments().join(" ")));
|
||||
emit standardOutputReceived(tr("Working directory: %1").arg(m_workingDirectory));
|
||||
emit standardOutputReceived(tr("Command-line arguments: %1").arg(m_commandLineArguments));
|
||||
#endif
|
||||
|
||||
const AnalyzerStartParameters &sp = startParameters();
|
||||
runner()->setWorkingDirectory(sp.workingDirectory);
|
||||
QString valgrindExe = m_settings->subConfig<ValgrindSettings>()->valgrindExecutable();
|
||||
if (!sp.analyzerCmdPrefix.isEmpty())
|
||||
valgrindExe = sp.analyzerCmdPrefix + ' ' + valgrindExe;
|
||||
runner()->setValgrindExecutable(valgrindExe);
|
||||
runner()->setValgrindArguments(toolArguments());
|
||||
runner()->setDebuggeeExecutable(sp.debuggee);
|
||||
runner()->setDebuggeeArguments(sp.debuggeeArgs);
|
||||
runner()->setEnvironment(sp.environment);
|
||||
|
||||
connect(runner(), SIGNAL(standardOutputReceived(QByteArray)),
|
||||
SLOT(receiveStandardOutput(QByteArray)));
|
||||
connect(runner(), SIGNAL(standardErrorReceived(QByteArray)),
|
||||
SLOT(receiveStandardError(QByteArray)));
|
||||
connect(runner(), SIGNAL(processErrorReceived(QString, QProcess::ProcessError)),
|
||||
SLOT(receiveProcessError(QString, QProcess::ProcessError)));
|
||||
connect(runner(), SIGNAL(finished()),
|
||||
SLOT(runnerFinished()));
|
||||
|
||||
if (sp.startMode == StartRemote)
|
||||
runner()->startRemotely(sp.connParams);
|
||||
else
|
||||
runner()->start();
|
||||
}
|
||||
|
||||
void ValgrindEngine::stop()
|
||||
{
|
||||
m_isStopping = true;
|
||||
runner()->stop();
|
||||
}
|
||||
|
||||
QString ValgrindEngine::executable() const
|
||||
{
|
||||
return startParameters().debuggee;
|
||||
}
|
||||
|
||||
void ValgrindEngine::handleProgressCanceled()
|
||||
{
|
||||
AnalyzerManager::instance()->stopTool();
|
||||
}
|
||||
|
||||
void ValgrindEngine::handleProgressFinished()
|
||||
{
|
||||
QApplication::alert(Core::ICore::instance()->mainWindow(), 3000);
|
||||
}
|
||||
|
||||
void ValgrindEngine::runnerFinished()
|
||||
{
|
||||
emit standardOutputReceived(tr("** Analyzing finished **"));
|
||||
emit finished();
|
||||
|
||||
m_progress->reportFinished();
|
||||
|
||||
disconnect(runner(), SIGNAL(standardOutputReceived(QByteArray)),
|
||||
this, SLOT(receiveStandardOutput(QByteArray)));
|
||||
disconnect(runner(), SIGNAL(standardErrorReceived(QByteArray)),
|
||||
this, SLOT(receiveStandardError(QByteArray)));
|
||||
disconnect(runner(), SIGNAL(processErrorReceived(QString, QProcess::ProcessError)),
|
||||
this, SLOT(receiveProcessError(QString, QProcess::ProcessError)));
|
||||
disconnect(runner(), SIGNAL(finished()),
|
||||
this, SLOT(runnerFinished()));
|
||||
}
|
||||
|
||||
void ValgrindEngine::receiveStandardOutput(const QByteArray &b)
|
||||
{
|
||||
emit standardOutputReceived(QString::fromLocal8Bit(b));
|
||||
}
|
||||
|
||||
void ValgrindEngine::receiveStandardError(const QByteArray &b)
|
||||
{
|
||||
emit standardErrorReceived(QString::fromLocal8Bit(b));
|
||||
}
|
||||
|
||||
void ValgrindEngine::receiveProcessError(const QString &error, QProcess::ProcessError e)
|
||||
{
|
||||
if (e == QProcess::FailedToStart) {
|
||||
const QString &valgrind = m_settings->subConfig<ValgrindSettings>()->valgrindExecutable();
|
||||
if (!valgrind.isEmpty()) {
|
||||
emit standardErrorReceived(tr("** Error: \"%1\" could not be started: %2 **").arg(valgrind).arg(error));
|
||||
} else {
|
||||
emit standardErrorReceived(tr("** Error: no valgrind executable set **"));
|
||||
}
|
||||
} else if (m_isStopping && e == QProcess::Crashed) { // process gets killed on stop
|
||||
emit standardErrorReceived(tr("** Process Terminated **"));
|
||||
} else {
|
||||
emit standardErrorReceived(QString("** %1 **").arg(error));
|
||||
}
|
||||
|
||||
if (m_isStopping)
|
||||
return;
|
||||
|
||||
///FIXME: get a better API for this into Qt Creator
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
QList<Core::IOutputPane *> panes = pm->getObjects<Core::IOutputPane>();
|
||||
foreach (Core::IOutputPane *pane, panes) {
|
||||
if (pane->displayName() == tr("Application Output")) {
|
||||
pane->popup(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
97
src/plugins/valgrind/valgrindengine.h
Normal file
97
src/plugins/valgrind/valgrindengine.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef VALGRINDENGINE_H
|
||||
#define VALGRINDENGINE_H
|
||||
|
||||
#include "valgrind_global.h"
|
||||
|
||||
#include <analyzerbase/ianalyzerengine.h>
|
||||
#include <analyzerbase/ianalyzerengine.h>
|
||||
|
||||
#include <utils/environment.h>
|
||||
|
||||
#include <valgrind/valgrindrunner.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QFutureInterface>
|
||||
#include <QtCore/QFutureWatcher>
|
||||
|
||||
namespace Analyzer {
|
||||
class AnalyzerSettings;
|
||||
}
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class VALGRINDTOOLBASE_EXPORT ValgrindEngine : public Analyzer::IAnalyzerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ValgrindEngine(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
virtual ~ValgrindEngine();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
QString executable() const;
|
||||
|
||||
protected:
|
||||
virtual QString progressTitle() const = 0;
|
||||
virtual QStringList toolArguments() const = 0;
|
||||
virtual Valgrind::ValgrindRunner *runner() = 0;
|
||||
|
||||
Analyzer::AnalyzerSettings *m_settings;
|
||||
QFutureInterface<void> *m_progress;
|
||||
QFutureWatcher<void> *m_progressWatcher;
|
||||
|
||||
private slots:
|
||||
void handleProgressCanceled();
|
||||
void handleProgressFinished();
|
||||
void runnerFinished();
|
||||
|
||||
void receiveStandardOutput(const QByteArray &);
|
||||
void receiveStandardError(const QByteArray &);
|
||||
void receiveProcessError(const QString &, QProcess::ProcessError);
|
||||
|
||||
private:
|
||||
bool m_isStopping;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // VALGRINDENGINE_H
|
||||
93
src/plugins/valgrind/valgrindplugin.cpp
Normal file
93
src/plugins/valgrind/valgrindplugin.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "valgrindplugin.h"
|
||||
#include "valgrindsettings.h"
|
||||
#include "callgrindtool.h"
|
||||
#include "callgrindsettings.h"
|
||||
#include "memchecktool.h"
|
||||
#include "memchecksettings.h"
|
||||
|
||||
#include <analyzerbase/analyzersettings.h>
|
||||
#include <analyzerbase/analyzermanager.h>
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
using namespace Analyzer;
|
||||
using namespace Valgrind::Internal;
|
||||
|
||||
|
||||
static AbstractAnalyzerSubConfig *valgrindConfigFactory()
|
||||
{
|
||||
return new ValgrindSettings();
|
||||
}
|
||||
|
||||
static AbstractAnalyzerSubConfig *globalCallgrindFactory()
|
||||
{
|
||||
return new CallgrindGlobalSettings();
|
||||
}
|
||||
|
||||
static AbstractAnalyzerSubConfig *projectCallgrindFactory()
|
||||
{
|
||||
return new CallgrindProjectSettings();
|
||||
}
|
||||
|
||||
static AbstractAnalyzerSubConfig *globalMemcheckFactory()
|
||||
{
|
||||
return new MemcheckGlobalSettings();
|
||||
}
|
||||
|
||||
static AbstractAnalyzerSubConfig *projectMemcheckFactory()
|
||||
{
|
||||
return new MemcheckProjectSettings();
|
||||
}
|
||||
|
||||
bool ValgrindPlugin::initialize(const QStringList &, QString *)
|
||||
{
|
||||
AnalyzerGlobalSettings::instance()->registerSubConfigs(&valgrindConfigFactory, &valgrindConfigFactory);
|
||||
AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalCallgrindFactory, &projectCallgrindFactory);
|
||||
AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalMemcheckFactory, &projectMemcheckFactory);
|
||||
|
||||
AnalyzerManager::instance()->addTool(new MemcheckTool(this));
|
||||
AnalyzerManager::instance()->addTool(new CallgrindTool(this));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ValgrindPlugin::extensionsInitialized()
|
||||
{
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN(Valgrind::Internal::ValgrindPlugin)
|
||||
57
src/plugins/valgrind/valgrindplugin.h
Normal file
57
src/plugins/valgrind/valgrindplugin.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef VALGRINDTOOLBASEPLUGIN_H
|
||||
#define VALGRINDTOOLBASEPLUGIN_H
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
class ValgrindPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ValgrindPlugin() {}
|
||||
|
||||
virtual bool initialize(const QStringList &arguments, QString *errorString);
|
||||
virtual void extensionsInitialized();
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // VALGRINDTOOLBASEPLUGIN_H
|
||||
98
src/plugins/valgrind/valgrindsettings.cpp
Normal file
98
src/plugins/valgrind/valgrindsettings.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "valgrindsettings.h"
|
||||
|
||||
#include "valgrindconfigwidget.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
using namespace Valgrind::Internal;
|
||||
using namespace Analyzer;
|
||||
|
||||
static const QLatin1String groupC("Analyzer");
|
||||
|
||||
static const QLatin1String valgrindExeC("Analyzer.Valgrind.ValgrindExecutable");
|
||||
|
||||
QVariantMap ValgrindSettings::defaults() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(valgrindExeC, QLatin1String("valgrind"));
|
||||
return map;
|
||||
}
|
||||
|
||||
bool ValgrindSettings::fromMap(const QVariantMap &map)
|
||||
{
|
||||
setIfPresent(map, valgrindExeC, &m_valgrindExecutable);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap ValgrindSettings::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(valgrindExeC, m_valgrindExecutable);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void ValgrindSettings::setValgrindExecutable(const QString &valgrindExecutable)
|
||||
{
|
||||
if (m_valgrindExecutable != valgrindExecutable) {
|
||||
m_valgrindExecutable = valgrindExecutable;
|
||||
emit valgrindExecutableChanged(valgrindExecutable);
|
||||
}
|
||||
}
|
||||
|
||||
QString ValgrindSettings::valgrindExecutable() const
|
||||
{
|
||||
return m_valgrindExecutable;
|
||||
}
|
||||
|
||||
QString ValgrindSettings::id() const
|
||||
{
|
||||
return "Analyzer.Valgrind.Settings.Generic";
|
||||
}
|
||||
|
||||
QString ValgrindSettings::displayName() const
|
||||
{
|
||||
return tr("Generic Settings");
|
||||
}
|
||||
|
||||
QWidget *ValgrindSettings::createConfigWidget(QWidget *parent)
|
||||
{
|
||||
return new ValgrindConfigWidget(this, parent);
|
||||
}
|
||||
82
src/plugins/valgrind/valgrindsettings.h
Normal file
82
src/plugins/valgrind/valgrindsettings.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator Instrumentation Tools
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ANALYZER_INTERNAL_VALGRINDSETTINGS_H
|
||||
#define ANALYZER_INTERNAL_VALGRINDSETTINGS_H
|
||||
|
||||
#include "valgrind_global.h"
|
||||
|
||||
#include <analyzerbase/analyzersettings.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Internal {
|
||||
|
||||
/**
|
||||
* Generic Valgrind settings shared by all tools.
|
||||
*/
|
||||
class VALGRINDTOOLBASE_EXPORT ValgrindSettings : public Analyzer::AbstractAnalyzerSubConfig
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ValgrindSettings() {}
|
||||
|
||||
virtual QVariantMap toMap() const;
|
||||
virtual QVariantMap defaults() const;
|
||||
|
||||
QString valgrindExecutable() const;
|
||||
|
||||
virtual QString id() const;
|
||||
virtual QString displayName() const;
|
||||
virtual QWidget *createConfigWidget(QWidget *parent);
|
||||
|
||||
public slots:
|
||||
void setValgrindExecutable(const QString &);
|
||||
|
||||
signals:
|
||||
void valgrindExecutableChanged(const QString &);
|
||||
|
||||
protected:
|
||||
virtual bool fromMap(const QVariantMap &map);
|
||||
|
||||
private:
|
||||
QString m_valgrindExecutable;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
#endif // VALGRIND_INTERNAL_ANALZYZERSETTINGS_H
|
||||
51
src/plugins/valgrind/workarounds.cpp
Normal file
51
src/plugins/valgrind/workarounds.cpp
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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;
|
||||
}
|
||||
45
src/plugins/valgrind/workarounds.h
Normal file
45
src/plugins/valgrind/workarounds.h
Normal 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 (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.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
|
||||
Reference in New Issue
Block a user