Commit 6ab68a1a authored by Christiaan Janssen's avatar Christiaan Janssen
Browse files

QmlProfiler: added summary view

Reviewed-by: Kai Koehne
parent d5ad4e8d
......@@ -19,7 +19,8 @@ SOURCES += \
qmlprofilerengine.cpp \
tracewindow.cpp \
timelineview.cpp \
qmlprofilerattachdialog.cpp
qmlprofilerattachdialog.cpp \
qmlprofilersummaryview.cpp
HEADERS += \
qmlprofilerconstants.h \
......@@ -29,7 +30,8 @@ HEADERS += \
qmlprofilerengine.h \
tracewindow.h \
timelineview.h \
qmlprofilerattachdialog.h
qmlprofilerattachdialog.h \
qmlprofilersummaryview.h
RESOURCES += \
qml/qml.qrc
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "qmlprofilersummaryview.h"
#include <QtCore/QUrl>
#include <QtGui/QHeaderView>
#include <QtGui/QStandardItemModel>
using namespace QmlProfiler::Internal;
class QmlProfilerSummaryView::QmlProfilerSummaryViewPrivate
{
public:
QmlProfilerSummaryViewPrivate(QmlProfilerSummaryView *qq):q(qq) {}
~QmlProfilerSummaryViewPrivate() {}
QmlProfilerSummaryView *q;
QStandardItemModel *m_model;
enum RangeType {
Painting,
Compiling,
Creating,
Binding,
HandlingSignal,
MaximumRangeType
};
};
class ProfilerItem : public QStandardItem
{
public:
ProfilerItem(const QString &text):QStandardItem ( text ) {}
virtual bool operator< ( const QStandardItem & other ) const
{
if (data().type() == QVariant::String) {
// first column
return data(Qt::UserRole+2).toString() == other.data(Qt::UserRole+2).toString() ?
data(Qt::UserRole+3).toInt() < other.data(Qt::UserRole+3).toInt() :
data(Qt::UserRole+2).toString() < other.data(Qt::UserRole+2).toString();
}
return data().toDouble() < other.data().toDouble();
}
};
QmlProfilerSummaryView::QmlProfilerSummaryView(QWidget *parent) :
QTreeView(parent), d(new QmlProfilerSummaryViewPrivate(this))
{
setRootIsDecorated(false);
header()->setResizeMode(QHeaderView::Interactive);
header()->setMinimumSectionSize(100);
setSortingEnabled(false);
d->m_model = new QStandardItemModel(this);
setModel(d->m_model);
d->m_model->setColumnCount(7);
setHeaderLabels();
connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
}
QmlProfilerSummaryView::~QmlProfilerSummaryView()
{
delete d->m_model;
}
void QmlProfilerSummaryView::clean()
{
d->m_model->clear();
d->m_model->setColumnCount(7);
setHeaderLabels();
setSortingEnabled(false);
}
void QmlProfilerSummaryView::addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line)
{
Q_UNUSED(startTime);
Q_UNUSED(data);
if (type != QmlProfilerSummaryViewPrivate::Binding && type != QmlProfilerSummaryViewPrivate::HandlingSignal)
return;
QString fname;
QString displayName;
if (!fileName.isEmpty()) {
fname = fileName;
QString localName = QUrl(fileName).toLocalFile();
displayName = localName.mid(localName.lastIndexOf(QChar('/'))+1)+QLatin1String(":")+QString::number(line);
} else {
// ignore anonymous bindings
return;
//fname = (type==QmlProfilerSummaryViewPrivate::Binding ? QLatin1String("[binding]") : QLatin1String("[signal]"));
//displayName = fname;
}
QString location = fname+":"+QString::number(line);
int rowNum = 0;
while (rowNum < d->m_model->rowCount()) {
if (d->m_model->item(rowNum,0)->data(Qt::UserRole+1) == location)
break;
rowNum++;
}
if (rowNum < d->m_model->rowCount()) {
double itemTime = d->m_model->item(rowNum,2)->data().toDouble() + length;
d->m_model->item(rowNum,2)->setData(QVariant(itemTime));
d->m_model->item(rowNum,2)->setText(displayTime(itemTime));
int callCount = d->m_model->item(rowNum,3)->data().toInt() + 1;
d->m_model->item(rowNum,3)->setData(QVariant(callCount));
d->m_model->item(rowNum,3)->setText(QString::number(callCount));
double maxTime = d->m_model->item(rowNum,5)->data().toDouble();
if (length > maxTime) {
d->m_model->item(rowNum,5)->setData(QVariant(length));
d->m_model->item(rowNum,5)->setText(displayTime(length));
}
double minTime = d->m_model->item(rowNum,6)->data().toDouble();
if (length < minTime) {
d->m_model->item(rowNum,6)->setData(QVariant(length));
d->m_model->item(rowNum,6)->setText(displayTime(length));
}
} else {
appendRow(displayName, fname, line, 0, length, 1, length, length, length);
}
}
void QmlProfilerSummaryView::complete()
{
// compute percentages
double totalTime = 0;
int i;
for (i=0; i < d->m_model->rowCount(); i++)
totalTime += d->m_model->item(i,2)->data().toDouble();
for (i=0; i < d->m_model->rowCount(); i++) {
double time = d->m_model->item(i,2)->data().toDouble();
double percent = time * 100.0 / totalTime;
d->m_model->item(i,1)->setData(QVariant(percent));
d->m_model->item(i,1)->setText(QString::number(percent,'g',2)+QLatin1String(" %"));
int callCount = d->m_model->item(i,3)->data().toInt();
double tpc = callCount>0? time / callCount : 0;
d->m_model->item(i,4)->setData(QVariant(tpc));
d->m_model->item(i,4)->setText(displayTime(tpc));
}
setSortingEnabled(true);
sortByColumn(1,Qt::DescendingOrder);
resizeColumnToContents(0);
}
void QmlProfilerSummaryView::jumpToItem(const QModelIndex &index)
{
int line = d->m_model->item(index.row(),0)->data(Qt::UserRole+3).toInt();
if (line == -1)
return;
QString fileName = d->m_model->item(index.row(),0)->data(Qt::UserRole+2).toString();
emit gotoSourceLocation(fileName, line);
}
void QmlProfilerSummaryView::appendRow(const QString &displayName,
const QString &fileName,
int line,
double percentTime,
double totalTime,
int nCalls,
double timePerCall,
double maxTime,
double minTime)
{
QString location =fileName+":"+QString::number(line);
ProfilerItem *locationColumn = new ProfilerItem(displayName);
locationColumn->setData(QVariant(location),Qt::UserRole+1);
locationColumn->setData(QVariant(fileName),Qt::UserRole+2);
locationColumn->setData(QVariant(line),Qt::UserRole+3);
locationColumn->setEditable(false);
ProfilerItem *percentColumn = new ProfilerItem(QString::number(percentTime)+QLatin1String(" %"));
percentColumn->setData(QVariant(percentTime));
percentColumn->setEditable(false);
ProfilerItem *timeColumn = new ProfilerItem(displayTime(totalTime));
timeColumn->setData(QVariant(totalTime));
timeColumn->setEditable(false);
ProfilerItem *callsColumn = new ProfilerItem(QString::number(nCalls));
callsColumn->setData(QVariant(nCalls));
callsColumn->setEditable(false);
ProfilerItem *tpcColumn = new ProfilerItem(displayTime(timePerCall));
tpcColumn->setData(QVariant(timePerCall));
tpcColumn->setEditable(false);
ProfilerItem *maxTimeColumn = new ProfilerItem(displayTime(maxTime));
maxTimeColumn->setData(QVariant(maxTime));
maxTimeColumn->setEditable(false);
ProfilerItem *minTimeColumn = new ProfilerItem(displayTime(minTime));
minTimeColumn->setData(QVariant(minTime));
minTimeColumn->setEditable(false);
QList<QStandardItem *> newRow;
newRow << locationColumn << percentColumn << timeColumn << callsColumn << tpcColumn << maxTimeColumn << minTimeColumn;
d->m_model->appendRow(newRow);
}
QString QmlProfilerSummaryView::displayTime(double time) const
{
if (time<1e6)
return QString::number(time/1e3,'f',3) + QString::fromUtf8(" \u03BCs");//(" \u03BCs");
if (time<1e9)
return QString::number(time/1e6,'f',3) + QLatin1String(" ms");
return QString::number(time/1e9,'f',3) + QLatin1String(" s");
}
void QmlProfilerSummaryView::setHeaderLabels()
{
d->m_model->setHeaderData(0,Qt::Horizontal,QVariant(tr("location")));
d->m_model->setHeaderData(1,Qt::Horizontal,QVariant(tr("% time")));
d->m_model->setHeaderData(2,Qt::Horizontal,QVariant(tr("total time")));
d->m_model->setHeaderData(3,Qt::Horizontal,QVariant(tr("calls")));
d->m_model->setHeaderData(4,Qt::Horizontal,QVariant(tr("time per call")));
d->m_model->setHeaderData(5,Qt::Horizontal,QVariant(tr("longest time")));
d->m_model->setHeaderData(6,Qt::Horizontal,QVariant(tr("shortest time")));
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef QMLPROFILERSUMMARYVIEW_H
#define QMLPROFILERSUMMARYVIEW_H
#include <QTreeView>
namespace QmlProfiler {
namespace Internal {
class QmlProfilerSummaryView : public QTreeView
{
Q_OBJECT
public:
explicit QmlProfilerSummaryView(QWidget *parent = 0);
~QmlProfilerSummaryView();
signals:
void gotoSourceLocation(const QString &fileName, int lineNumber);
public slots:
void clean();
void addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line);
void complete();
void jumpToItem(const QModelIndex &index);
private:
class QmlProfilerSummaryViewPrivate;
QmlProfilerSummaryViewPrivate *d;
void appendRow(const QString &displayname,
const QString &filename,
int line,
double percentTime,
double totalTime,
int ncalls,
double timepercall,
double maxtime,
double mintime);
void setHeaderLabels();
QString displayTime(double time) const;
};
}
}
#endif // QMLPROFILERSUMMARYVIEW_H
......@@ -70,6 +70,9 @@
#include <QtGui/QLabel>
#include <QtGui/QToolButton>
#include <QtGui/QTabWidget>
#include "qmlprofilersummaryview.h"
using namespace Analyzer;
using namespace QmlProfiler::Internal;
......@@ -111,6 +114,8 @@ public:
QDeclarativeDebugConnection *m_client;
TraceWindow *m_traceWindow;
QTabWidget *m_tabbed;
QmlProfilerSummaryView *m_summary;
QmlProfilerOutputPaneAdapter *m_outputPaneAdapter;
ProjectExplorer::Project *m_project;
Utils::FileInProjectFinder m_projectFinder;
......@@ -136,7 +141,8 @@ QmlProfilerTool::~QmlProfilerTool()
{
if (d->m_client->isConnected())
d->m_client->disconnectFromHost();
delete d->m_traceWindow;
delete d->m_tabbed;
delete d->m_outputPaneAdapter;
delete d;
}
......@@ -191,12 +197,24 @@ void QmlProfilerTool::initialize(ExtensionSystem::IPlugin */*plugin*/)
qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView");
d->m_client = new QDeclarativeDebugConnection;
d->m_traceWindow = new TraceWindow();
d->m_tabbed = new QTabWidget();
d->m_traceWindow = new TraceWindow(d->m_tabbed);
d->m_traceWindow->reset(d->m_client);
connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int)));
connect(d->m_traceWindow, SIGNAL(timeChanged(qreal)), this, SLOT(updateTimer(qreal)));
d->m_summary = new QmlProfilerSummaryView(d->m_tabbed);
d->m_tabbed->addTab(d->m_traceWindow, "timeline");
d->m_tabbed->addTab(d->m_summary, "summary");
connect(d->m_traceWindow,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)),
d->m_summary,SLOT(addRangedEvent(int,qint64,qint64,QStringList,QString,int)));
connect(d->m_traceWindow,SIGNAL(viewUpdated()), d->m_summary, SLOT(complete()));
connect(d->m_summary,SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int)));
Core::ICore *core = Core::ICore::instance();
Core::ActionManager *am = core->actionManager();
Core::ActionContainer *manalyzer = am->actionContainer(Analyzer::Constants::M_DEBUG_ANALYZER);
......@@ -260,7 +278,7 @@ QWidget *QmlProfilerTool::createToolBarWidget()
QWidget *QmlProfilerTool::createTimeLineWidget()
{
return d->m_traceWindow;
return d->m_tabbed;
}
void QmlProfilerTool::connectClient()
......@@ -353,6 +371,7 @@ bool QmlProfilerTool::canRunRemotely() const
void QmlProfilerTool::clearDisplay()
{
d->m_traceWindow->clearDisplay();
d->m_summary->clean();
}
void QmlProfilerTool::attach()
......
......@@ -299,6 +299,7 @@ void TraceWindow::reset(QDeclarativeDebugConnection *conn)
delete m_plugin;
m_plugin = new TracePlugin(conn);
connect(m_plugin,SIGNAL(complete()), this, SIGNAL(viewUpdated()));
connect(m_plugin,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)),this,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)));
if (m_recordAtStart)
m_plugin->setRecording(true);
......
......@@ -77,6 +77,7 @@ signals:
void viewUpdated();
void gotoSourceLocation(const QString &fileUrl, int lineNumber);
void timeChanged(qreal newTime);
void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line);
private:
TracePlugin *m_plugin;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment