summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristiaan Janssen <christiaan.janssen@nokia.com>2011-04-08 13:05:39 +0200
committerChristiaan Janssen <christiaan.janssen@nokia.com>2011-04-08 13:35:38 +0200
commit6ab68a1a5fd27526e041f1e0ae453f279e1e3c00 (patch)
treefee040812b786c9cbf943af6e7870d696f1f9fcc /src
parentd5ad4e8dd4873c78687a67815c172e6f0db8f621 (diff)
downloadqt-creator-6ab68a1a5fd27526e041f1e0ae453f279e1e3c00.tar.gz
QmlProfiler: added summary view
Reviewed-by: Kai Koehne
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qmlprofiler/qmlprofiler.pro6
-rw-r--r--src/plugins/qmlprofiler/qmlprofilersummaryview.cpp261
-rw-r--r--src/plugins/qmlprofiler/qmlprofilersummaryview.h79
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.cpp25
-rw-r--r--src/plugins/qmlprofiler/tracewindow.cpp1
-rw-r--r--src/plugins/qmlprofiler/tracewindow.h1
6 files changed, 368 insertions, 5 deletions
diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro
index 5b6d5c4506..acde7d9b03 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.pro
+++ b/src/plugins/qmlprofiler/qmlprofiler.pro
@@ -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
diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp b/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
new file mode 100644
index 0000000000..eedbf309ee
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp
@@ -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")));
+}
diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.h b/src/plugins/qmlprofiler/qmlprofilersummaryview.h
new file mode 100644
index 0000000000..e8d462044d
--- /dev/null
+++ b/src/plugins/qmlprofiler/qmlprofilersummaryview.h
@@ -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
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 23da1e3baa..bd148c8551 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -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()
diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp
index f1ec839a0e..8c3f3dbb26 100644
--- a/src/plugins/qmlprofiler/tracewindow.cpp
+++ b/src/plugins/qmlprofiler/tracewindow.cpp
@@ -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);
diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h
index 091ba0219c..4f0fb72e8d 100644
--- a/src/plugins/qmlprofiler/tracewindow.h
+++ b/src/plugins/qmlprofiler/tracewindow.h
@@ -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;