summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristiaan Janssen <christiaan.janssen@digia.com>2013-06-19 15:12:32 +0200
committerKai Koehne <kai.koehne@digia.com>2013-06-20 12:19:08 +0300
commit0ce1d6751c81476220d9e14e29a0c1d814847873 (patch)
tree9db1928afc05cc08768f7a716c518950a2919944
parent698958c92dbed25129c6cb6c4e58de3ab965bba0 (diff)
downloadqt-creator-0ce1d6751c81476220d9e14e29a0c1d814847873.tar.gz
QmlProfilerExtended: Pixmap Cache model
Change-Id: Ib0ac48b30406269a6090dbbc6e047653e279a9bf Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r--libs/qmldebug/qmlprofilertraceclient.cpp15
-rw-r--r--libs/qmldebug/qmlprofilertraceclient.h12
-rw-r--r--plugins/qmlprofiler/qmlprofilerclientmanager.cpp8
-rw-r--r--plugins/qmlprofiler/qmlprofilerclientmanager.h1
-rw-r--r--plugins/qmlprofiler/qmlprofilermodelmanager.cpp11
-rw-r--r--plugins/qmlprofiler/qmlprofilermodelmanager.h2
-rw-r--r--plugins/qmlprofiler/qmlprofilersimplemodel.cpp7
-rw-r--r--plugins/qmlprofiler/qmlprofilersimplemodel.h1
-rw-r--r--plugins/qmlprofiler/qmlprofilertool.cpp4
-rw-r--r--plugins/qmlprofilerextended/pixmapcachemodel.cpp550
-rw-r--r--plugins/qmlprofilerextended/pixmapcachemodel.h120
-rw-r--r--plugins/qmlprofilerextended/qmlprofilerextended.pro10
-rw-r--r--plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp2
13 files changed, 739 insertions, 4 deletions
diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp
index 22c38b81fb..49a4b2bb8d 100644
--- a/libs/qmldebug/qmlprofilertraceclient.cpp
+++ b/libs/qmldebug/qmlprofilertraceclient.cpp
@@ -191,6 +191,21 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
stream >> params[count++];
}
emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]);
+ } else if (messageType == PixmapCacheEvent) {
+ int pixEvTy, width = -1, height = -1, refcount = -1;
+ QString pixUrl;
+ stream >> pixEvTy >> pixUrl;
+ if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) {
+ stream >> refcount;
+ emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, refcount);
+ } else
+ if (pixEvTy == (int)PixmapSizeKnown) {
+ stream >> width >> height;
+ emit pixmapCacheEvent(time,pixEvTy, pixUrl, width, height, 1);
+ } else { // Other
+ emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, 0);
+ }
+ d->maximumTime = qMax(time, d->maximumTime);
} else {
int range;
stream >> range;
diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h
index 83c4e8772c..21c7d4eae1 100644
--- a/libs/qmldebug/qmlprofilertraceclient.h
+++ b/libs/qmldebug/qmlprofilertraceclient.h
@@ -77,6 +77,17 @@ public:
MaximumMessage
};
+ enum PixmapEventType {
+ PixmapSizeKnown,
+ PixmapReferenceCountChanged,
+ PixmapCacheCountChanged,
+ PixmapLoadingStarted,
+ PixmapLoadingFinished,
+ PixmapLoadingError,
+
+ MaximumPixmapEventType
+ };
+
bool isEnabled() const;
bool isRecording() const;
void setRecording(bool);
@@ -95,6 +106,7 @@ signals:
const QStringList &data, const QmlDebug::QmlEventLocation &location);
void frame(qint64 time, int frameRate, int animationCount);
void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5);
+ void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount);
void recordingChanged(bool arg);
diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
index 72fabc7a58..b29344699e 100644
--- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
+++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
@@ -171,6 +171,10 @@ void QmlProfilerClientManager::connectClientSignals()
connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
this, SIGNAL(addFrameEvent(qint64,int,int)));
connect(d->qmlclientplugin.data(),
+ SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)),
+ this,
+ SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)));
+ connect(d->qmlclientplugin.data(),
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)),
this,
SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)));
@@ -207,6 +211,10 @@ void QmlProfilerClientManager::disconnectClientSignals()
disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
this, SIGNAL(addFrameEvent(qint64,int,int)));
disconnect(d->qmlclientplugin.data(),
+ SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)),
+ this,
+ SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)));
+ disconnect(d->qmlclientplugin.data(),
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)),
this,
SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)));
diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h
index fdf643ae1c..9401b554f0 100644
--- a/plugins/qmlprofiler/qmlprofilerclientmanager.h
+++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h
@@ -67,6 +67,7 @@ signals:
void traceFinished(qint64);
void dataReadyForProcessing();
void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64);
+ void addPixmapCacheEvent(qint64,int,QString,int,int,int);
public slots:
void connectClient(quint16 port);
diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
index 9f6b8725dc..bd47bea32b 100644
--- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
+++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
@@ -222,6 +222,17 @@ void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qin
emit countChanged();
}
+void QmlProfilerModelManager::addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, int pixmapWidth, int pixmapHeight, int referenceCount)
+{
+ if (d->traceTime->startTime() == -1)
+ d->traceTime->setStartTime(time);
+
+ QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/);
+ d->model->addPixmapCacheEvent(time, pixmapEventType, Url, pixmapWidth, pixmapHeight, referenceCount);
+ emit countChanged();
+}
+
+
void QmlProfilerModelManager::complete()
{
if (state() == QmlProfilerDataState::AcquiringData) {
diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h
index faa4d53fe8..df033ff122 100644
--- a/plugins/qmlprofiler/qmlprofilermodelmanager.h
+++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h
@@ -122,6 +122,8 @@ public slots:
const QStringList &data, const QmlDebug::QmlEventLocation &location);
void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime,
qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5);
+ void addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url,
+ int pixmapWidth, int pixmapHeight, int referenceCount);
void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber,
double totalTime, double selfTime);
diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp
index bf2985de45..52ddc3ac99 100644
--- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp
+++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp
@@ -88,6 +88,13 @@ void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint
eventList.append(eventData);
}
+void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType, const QString &url, int width, int height, int refCount)
+{
+ QmlDebug::QmlEventLocation location(url, 0, 0);
+ QmlEventData eventData = {QString(), QmlDebug::PixmapCacheEvent, cacheEventType, time, 0, QStringList(), location, width, height, refCount, -1, -1};
+ eventList.append(eventData);
+}
+
qint64 QmlProfilerSimpleModel::lastTimeMark() const
{
if (eventList.isEmpty())
diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h
index c2c2c01bb0..e556a7a5d3 100644
--- a/plugins/qmlprofiler/qmlprofilersimplemodel.h
+++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h
@@ -71,6 +71,7 @@ public:
void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location);
void addFrameEvent(qint64 time, int framerate, int animationcount);
void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5);
+ void addPixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount);
qint64 lastTimeMark() const;
virtual void complete();
diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp
index 52bc43d207..a0e0cfe454 100644
--- a/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -158,6 +158,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_profilerModelManager,
SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)));
connect(d->m_profilerConnections,
+ SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)),
+ d->m_profilerModelManager,
+ SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int)));
+ connect(d->m_profilerConnections,
SIGNAL(addV8Event(int,QString,QString,int,double,double)),
d->m_profilerModelManager,
SLOT(addV8Event(int,QString,QString,int,double,double)));
diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextended/pixmapcachemodel.cpp
new file mode 100644
index 0000000000..4fb118eb29
--- /dev/null
+++ b/plugins/qmlprofilerextended/pixmapcachemodel.cpp
@@ -0,0 +1,550 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+****************************************************************************/
+
+#include "pixmapcachemodel.h"
+#include "qmldebug/qmlprofilereventtypes.h"
+#include "qmlprofiler/qmlprofilermodelmanager.h"
+
+#include <QDebug>
+
+namespace QmlProfilerExtended {
+namespace Internal {
+
+using namespace QmlProfiler::Internal;
+
+class PixmapCacheModel::PixmapCacheModelPrivate {
+public:
+ PixmapCacheModelPrivate(PixmapCacheModel *qq):q(qq) {}
+
+ ~PixmapCacheModelPrivate();
+
+ PixmapCacheModel *q;
+
+ void computeCacheSizes();
+ void resizeUnfinishedLoads();
+ void flattenLoads();
+ void computeRowCounts();
+
+ QVector < PixmapCacheModel::PixmapCacheEvent > eventList;
+ QVector < QString > pixmapUrls;
+ QVector < QPair<int, int> > pixmapSizes;
+ bool isExpanded;
+ int expandedRowCount;
+ int collapsedRowCount;
+ QString displayTime(double time);
+ void addVP(QVariantList &l, QString label, qint64 time);
+
+ qint64 minCacheSize;
+ qint64 maxCacheSize;
+};
+
+PixmapCacheModel::PixmapCacheModel(QObject *parent)
+ : AbstractTimelineModel(parent), d(new PixmapCacheModelPrivate(this))
+{
+ d->collapsedRowCount = 1;
+ d->expandedRowCount = 1;
+}
+
+PixmapCacheModel::~PixmapCacheModel()
+{
+}
+
+int PixmapCacheModel::categories() const
+{
+ return 1;
+}
+
+QStringList PixmapCacheModel::categoryTitles() const
+{
+ QStringList retString;
+ retString << categoryLabel(0);
+ return retString;
+}
+
+QString PixmapCacheModel::name() const
+{
+ return QLatin1String("PixmapCacheTimeLineModel");
+}
+
+int PixmapCacheModel::count() const
+{
+ return d->eventList.count();
+}
+
+bool PixmapCacheModel::isEmpty() const
+{
+ return d->eventList.isEmpty();
+}
+
+bool PixmapCacheModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const
+{
+ return (event.eventType == QmlDebug::PixmapCacheEvent);
+}
+
+qint64 PixmapCacheModel::lastTimeMark() const
+{
+ return d->eventList.last().startTime;
+}
+
+void PixmapCacheModel::setExpanded(int category, bool expanded)
+{
+ d->isExpanded = expanded;
+}
+
+int PixmapCacheModel::categoryDepth(int categoryIndex) const
+{
+ Q_UNUSED(categoryIndex);
+ if (isEmpty())
+ return 1;
+ if (d->isExpanded)
+ return d->expandedRowCount;
+ return d->collapsedRowCount;
+}
+
+int PixmapCacheModel::categoryCount() const
+{
+ return 1;
+}
+
+const QString PixmapCacheModel::categoryLabel(int categoryIndex) const
+{
+ Q_UNUSED(categoryIndex);
+ return QLatin1String("Pixmap Cache");
+}
+
+int PixmapCacheModel::findFirstIndex(qint64 startTime) const
+{
+ // TODO properly
+ int candidate = -2;
+ for (int i=0; i < d->eventList.count(); i++)
+ if (d->eventList[i].startTime + d->eventList[i].duration > startTime) {
+ candidate = i;
+ break;
+ }
+
+ if (candidate == -1)
+ return 0;
+ if (candidate == -2)
+ return d->eventList.count() - 1;
+
+ return candidate;
+}
+
+int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const
+{
+ // TODO properly
+ return findFirstIndex(startTime);
+
+// int candidate = -1;
+// // in the "endtime" list, find the first event that ends after startTime
+// if (d->endTimeData.isEmpty())
+// return 0; // -1
+// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime)
+// candidate = 0;
+// else
+// if (d->endTimeData.last().endTime <= startTime)
+// return 0; // -1
+
+// if (candidate == -1) {
+// int fromIndex = 0;
+// int toIndex = d->endTimeData.count()-1;
+// while (toIndex - fromIndex > 1) {
+// int midIndex = (fromIndex + toIndex)/2;
+// if (d->endTimeData[midIndex].endTime < startTime)
+// fromIndex = midIndex;
+// else
+// toIndex = midIndex;
+// }
+
+// candidate = toIndex;
+// }
+
+// int ndx = d->endTimeData[candidate].startTimeIndex;
+
+// return ndx;
+}
+
+int PixmapCacheModel::findLastIndex(qint64 endTime) const
+{
+ // TODO properly
+ int candidate = 0;
+ for (int i = d->eventList.count()-1; i >= 0; i--)
+ if (d->eventList[i].startTime < endTime) {
+ candidate = i;
+ break;
+ }
+ return candidate;
+}
+
+int PixmapCacheModel::getEventType(int index) const
+{
+ return QmlDebug::PixmapCacheEvent;
+}
+
+int PixmapCacheModel::getEventCategory(int index) const
+{
+ Q_UNUSED(index);
+ return 0;
+}
+
+int PixmapCacheModel::getEventRow(int index) const
+{
+ if (d->isExpanded)
+ return d->eventList[index].rowNumberExpanded;
+ return d->eventList[index].rowNumberCollapsed;
+}
+
+qint64 PixmapCacheModel::getDuration(int index) const
+{
+ return d->eventList[index].duration;
+}
+
+qint64 PixmapCacheModel::getStartTime(int index) const
+{
+ return d->eventList[index].startTime;
+}
+
+qint64 PixmapCacheModel::getEndTime(int index) const
+{
+ return getStartTime(index)+getDuration(index);
+}
+
+int PixmapCacheModel::getEventId(int index) const
+{
+ return d->eventList[index].eventId;
+}
+
+QColor PixmapCacheModel::getColor(int index) const
+{
+ if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged)
+ return QColor::fromHsl(240, 76, 166);
+
+ int ndx = getEventId(index);
+ return QColor::fromHsl((ndx*25)%360, 76, 166);
+}
+
+float PixmapCacheModel::getHeight(int index) const
+{
+ if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) {
+ float scale = d->maxCacheSize - d->minCacheSize;
+ float fraction = 1.0f;
+ if (scale > 1)
+ fraction = (float)(d->eventList[index].cacheSize -
+ d->minCacheSize) / scale;
+
+ return fraction * 0.85f + 0.15f;
+ }
+
+ return 1.0f;
+}
+
+QString getFilenameOnly(QString absUrl)
+{
+ int characterPos = absUrl.lastIndexOf(QLatin1Char('/'))+1;
+ if (characterPos < absUrl.length())
+ absUrl = absUrl.mid(characterPos);
+ return absUrl;
+}
+
+const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const
+{
+ QVariantList result;
+
+ if (d->isExpanded && !isEmpty()) {
+ {
+ // Cache Size
+ QVariantMap element;
+ element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Cache Size")));
+ element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size")));
+
+ element.insert(QLatin1String("id"), QVariant(0));
+ result << element;
+ }
+
+ for (int i=0; i < d->pixmapUrls.count(); i++) {
+ // Loading
+ QVariantMap element;
+ element.insert(QLatin1String("displayName"), QVariant(getFilenameOnly(d->pixmapUrls[i])));
+ element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmapUrls[i])));
+
+ element.insert(QLatin1String("id"), QVariant(i+1));
+ result << element;
+ }
+ }
+
+ return result;
+}
+
+QString PixmapCacheModel::PixmapCacheModelPrivate::displayTime(double time)
+{
+ if (time < 1e6)
+ return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s");
+ if (time < 1e9)
+ return QString::number(time/1e6,'f',3) + tr(" ms");
+
+ return QString::number(time/1e9,'f',3) + tr(" s");
+}
+
+void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time)
+{
+ if (time > 0) {
+ QVariantMap res;
+ res.insert(label, QVariant(displayTime(time)));
+ l << res;
+ }
+}
+
+const QVariantList PixmapCacheModel::getEventDetails(int index) const
+{
+ QVariantList result;
+ PixmapCacheEvent *ev = &d->eventList[index];
+
+ {
+ QVariantMap res;
+ if (ev->pixmapEventType == PixmapCacheCountChanged)
+ res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Cached")));
+ else if (ev->pixmapEventType == PixmapLoadingStarted)
+ res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Loaded")));
+ result << res;
+ }
+
+ if (ev->pixmapEventType != PixmapCacheCountChanged) {
+ d->addVP(result, tr("Duration"), ev->duration );
+ }
+
+ {
+ QVariantMap res;
+ res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmapUrls[ev->urlIndex])));
+ result << res;
+ }
+
+ {
+ QVariantMap res;
+ res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].first)));
+ result << res;
+ res.clear();
+ res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].second)));
+ result << res;
+ }
+
+ if (ev->pixmapEventType == PixmapLoadingStarted && ev->cacheSize == -1) {
+ QVariantMap res;
+ res.insert(tr("Result"), QVariant(QLatin1String("Load Error")));
+ result << res;
+ }
+
+ return result;
+}
+
+const QVariantMap PixmapCacheModel::getEventLocation(int /*index*/) const
+{
+ QVariantMap map;
+ return map;
+}
+
+bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const PixmapCacheModel::PixmapCacheEvent &t2)
+{
+ return t1.startTime < t2.startTime;
+}
+
+void PixmapCacheModel::loadData()
+{
+ clear();
+ QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel();
+ if (simpleModel->isEmpty())
+ return;
+
+ int lastCacheSizeEvent = -1;
+ int cumulatedCount = 0;
+ QVector < int > pixmapStartPoints;
+
+ foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) {
+ if (!eventAccepted(event))
+ continue;
+
+ PixmapCacheEvent newEvent;
+ newEvent.pixmapEventType = event.bindingType;
+ newEvent.startTime = event.startTime;
+ newEvent.duration = 0;
+
+ bool isNewEntry = false;
+ newEvent.urlIndex = d->pixmapUrls.indexOf(event.location.filename);
+ if (newEvent.urlIndex == -1) {
+ isNewEntry = true;
+ newEvent.urlIndex = d->pixmapUrls.count();
+ d->pixmapUrls << event.location.filename;
+ d->pixmapSizes << QPair<int, int>(0,0); // default value
+ pixmapStartPoints << d->eventList.count(); // index to the starting point
+ }
+
+ if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size
+ d->pixmapSizes[newEvent.urlIndex] = QPair<int,int>((int)event.numericData1, (int)event.numericData2);
+ }
+
+ newEvent.eventId = newEvent.urlIndex + 1;
+
+ // Cache Size Changed Event
+ if (newEvent.pixmapEventType == PixmapCacheCountChanged) {
+ newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting
+ newEvent.eventId = 0;
+ newEvent.rowNumberExpanded = 1;
+ newEvent.rowNumberCollapsed = 1;
+
+ qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second;
+ qint64 prevSize = 0;
+ if (lastCacheSizeEvent != -1) {
+ prevSize = d->eventList[lastCacheSizeEvent].cacheSize;
+ if (event.numericData3 < cumulatedCount)
+ pixSize = -pixSize;
+ cumulatedCount = event.numericData3;
+
+ d->eventList[lastCacheSizeEvent].duration = newEvent.startTime - d->eventList[lastCacheSizeEvent].startTime;
+ }
+ newEvent.cacheSize = prevSize + pixSize;
+ d->eventList << newEvent;
+ lastCacheSizeEvent = d->eventList.count() - 1;
+ }
+
+ // Load
+ if (newEvent.pixmapEventType == PixmapLoadingStarted) {
+ pixmapStartPoints[newEvent.urlIndex] = d->eventList.count();
+ newEvent.rowNumberExpanded = newEvent.urlIndex + 2;
+ d->eventList << newEvent;
+ }
+
+ if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) {
+ int loadIndex = pixmapStartPoints[newEvent.urlIndex];
+ if (!isNewEntry) {
+ d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime;
+ } else {
+ // if it's a new entry it means that we don't have a corresponding start
+ newEvent.pixmapEventType = PixmapLoadingStarted;
+ newEvent.rowNumberExpanded = newEvent.urlIndex + 2;
+ newEvent.startTime = traceStartTime();
+ newEvent.duration = event.startTime - traceStartTime();
+ d->eventList << newEvent;
+ }
+ if (event.bindingType == PixmapLoadingFinished)
+ d->eventList[loadIndex].cacheSize = 1; // use count to mark success
+ else
+ d->eventList[loadIndex].cacheSize = -1; // ... or failure
+ }
+ }
+
+ if (lastCacheSizeEvent != -1) {
+ d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime;
+ }
+
+ d->resizeUnfinishedLoads();
+
+ qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes);
+
+ d->computeCacheSizes();
+ d->flattenLoads();
+ d->computeRowCounts();
+}
+
+void PixmapCacheModel::clear()
+{
+ d->eventList.clear();
+ d->pixmapUrls.clear();
+ d->pixmapSizes.clear();
+ d->collapsedRowCount = 1;
+ d->expandedRowCount = 1;
+}
+
+void PixmapCacheModel::dataChanged()
+{
+ if (m_modelManager->state() == QmlProfilerDataState::Done)
+ loadData();
+
+ if (m_modelManager->state() == QmlProfilerDataState::Empty)
+ clear();
+
+ emit stateChanged();
+ emit dataAvailable();
+ emit emptyChanged();
+ return;
+}
+
+void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes()
+{
+ minCacheSize = -1;
+ maxCacheSize = -1;
+ foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) {
+ if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) {
+ if (minCacheSize == -1 || event.cacheSize < minCacheSize)
+ minCacheSize = event.cacheSize;
+ if (maxCacheSize == -1 || event.cacheSize > maxCacheSize)
+ maxCacheSize = event.cacheSize;
+ }
+ }
+}
+
+void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads()
+{
+ // all the "load start" events with duration 0 continue till the end of the trace
+ for (int i = 0; i < eventList.count(); i++) {
+ if (eventList[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted &&
+ eventList[i].duration == 0) {
+ eventList[i].duration = q->traceEndTime() - eventList[i].startTime;
+ }
+ }
+}
+
+void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads()
+{
+ // computes "compressed row"
+ QVector <qint64> eventEndTimes;
+ for (int i = 0; i < eventList.count(); i++) {
+ PixmapCacheModel::PixmapCacheEvent *event = &eventList[i];
+ if (event->pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) {
+ event->rowNumberCollapsed = 0;
+ while (eventEndTimes.count() > event->rowNumberCollapsed &&
+ eventEndTimes[event->rowNumberCollapsed] > event->startTime)
+ event->rowNumberCollapsed++;
+
+ if (eventEndTimes.count() == event->rowNumberCollapsed)
+ eventEndTimes << 0; // increase stack length, proper value added below
+ eventEndTimes[event->rowNumberCollapsed] = event->startTime + event->duration;
+
+ // readjust to account for category empty row and bargraph
+ event->rowNumberCollapsed += 2;
+ }
+ }
+}
+
+void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts()
+{
+ expandedRowCount = 0;
+ collapsedRowCount = 0;
+ foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) {
+ if (event.rowNumberExpanded > expandedRowCount)
+ expandedRowCount = event.rowNumberExpanded;
+ if (event.rowNumberCollapsed > collapsedRowCount)
+ collapsedRowCount = event.rowNumberCollapsed;
+ }
+
+ // Starting from 0, count is maxIndex+1
+ expandedRowCount++;
+ collapsedRowCount++;
+}
+
+
+
+} // namespace Internal
+} // namespace QmlProfilerExtended
diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.h b/plugins/qmlprofilerextended/pixmapcachemodel.h
new file mode 100644
index 0000000000..d2bbfee06a
--- /dev/null
+++ b/plugins/qmlprofilerextended/pixmapcachemodel.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+****************************************************************************/
+
+#ifndef PIXMAPCACHEMODEL_H
+#define PIXMAPCACHEMODEL_H
+
+#include "qmlprofiler/abstracttimelinemodel.h"
+#include "qmlprofiler/qmlprofilermodelmanager.h"
+#include "qmlprofiler/qmlprofilersimplemodel.h"
+
+#include <QStringList>
+#include <QColor>
+
+namespace QmlProfilerExtended {
+namespace Internal {
+
+class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel
+{
+ Q_OBJECT
+public:
+
+ struct PixmapCacheEvent {
+ int eventId;
+ qint64 startTime;
+ qint64 duration;
+ int pixmapEventType;
+ int urlIndex;
+ qint64 cacheSize;
+ int rowNumberExpanded;
+ int rowNumberCollapsed;
+ };
+
+ enum PixmapEventType {
+ PixmapSizeKnown,
+ PixmapReferenceCountChanged,
+ PixmapCacheCountChanged,
+ PixmapLoadingStarted,
+ PixmapLoadingFinished,
+ PixmapLoadingError,
+
+ MaximumPixmapEventType
+ };
+
+ PixmapCacheModel(QObject *parent = 0);
+ ~PixmapCacheModel();
+
+
+// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager);
+
+ int categories() const;
+ QStringList categoryTitles() const;
+ QString name() const;
+ int count() const;
+
+ bool isEmpty() const;
+
+ bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const;
+
+ Q_INVOKABLE qint64 lastTimeMark() const;
+
+ Q_INVOKABLE void setExpanded(int category, bool expanded);
+ Q_INVOKABLE int categoryDepth(int categoryIndex) const;
+ Q_INVOKABLE int categoryCount() const;
+ Q_INVOKABLE const QString categoryLabel(int categoryIndex) const;
+
+ int findFirstIndex(qint64 startTime) const;
+ int findFirstIndexNoParents(qint64 startTime) const;
+ int findLastIndex(qint64 endTime) const;
+
+ int getEventType(int index) const;
+ int getEventCategory(int index) const;
+ int getEventRow(int index) const;
+ Q_INVOKABLE qint64 getDuration(int index) const;
+ Q_INVOKABLE qint64 getStartTime(int index) const;
+ Q_INVOKABLE qint64 getEndTime(int index) const;
+ Q_INVOKABLE int getEventId(int index) const;
+ Q_INVOKABLE QColor getColor(int index) const;
+ Q_INVOKABLE float getHeight(int index) const;
+
+ Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const;
+
+ Q_INVOKABLE const QVariantList getEventDetails(int index) const;
+ Q_INVOKABLE const QVariantMap getEventLocation(int index) const;
+
+ void loadData();
+ void clear();
+//signals:
+// void countChanged();
+// void dataAvailable();
+// void stateChanged();
+// void emptyChanged();
+// void expandedChanged();
+
+protected slots:
+ void dataChanged();
+
+private:
+ class PixmapCacheModelPrivate;
+ PixmapCacheModelPrivate *d;
+
+};
+
+} // namespace Internal
+} // namespace QmlProfilerExtended
+
+#endif // PIXMAPCACHEMODEL_H
diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro
index 213f149817..e35215883d 100644
--- a/plugins/qmlprofilerextended/qmlprofilerextended.pro
+++ b/plugins/qmlprofilerextended/qmlprofilerextended.pro
@@ -9,12 +9,14 @@ DEFINES += QMLPROFILEREXTENDED_LIBRARY
# QmlProfilerExtended files
SOURCES += qmlprofilerextendedplugin.cpp \
- scenegraphtimelinemodel.cpp
+ scenegraphtimelinemodel.cpp \
+ pixmapcachemodel.cpp
-HEADERS += qmlprofilerextendedplugin.h\
- qmlprofilerextended_global.h\
+HEADERS += qmlprofilerextendedplugin.h \
+ qmlprofilerextended_global.h \
qmlprofilerextendedconstants.h \
- scenegraphtimelinemodel.h
+ scenegraphtimelinemodel.h \
+ pixmapcachemodel.h
OTHER_FILES += \
QmlProfilerExtended.json
diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp
index 5c6fcb8e70..1eeb64a173 100644
--- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp
+++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp
@@ -33,6 +33,7 @@
#include <QtPlugin>
#include "scenegraphtimelinemodel.h"
+#include "pixmapcachemodel.h"
using namespace QmlProfilerExtended::Internal;
@@ -59,6 +60,7 @@ bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString
Q_UNUSED(arguments)
Q_UNUSED(errorString)
+ addAutoReleasedObject(new PixmapCacheModel);
addAutoReleasedObject(new SceneGraphTimelineModel);
return true;