forked from qt-creator/qt-creator
QmlProfiler: added summary view
Reviewed-by: Kai Koehne
This commit is contained in:
@@ -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
|
||||
|
261
src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
Normal file
261
src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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")));
|
||||
}
|
79
src/plugins/qmlprofiler/qmlprofilersummaryview.h
Normal file
79
src/plugins/qmlprofiler/qmlprofilersummaryview.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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;
|
||||
|
Reference in New Issue
Block a user