forked from qt-creator/qt-creator
QmlProfilerExtended: Pixmap Cache model
Change-Id: Ib0ac48b30406269a6090dbbc6e047653e279a9bf Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
committed by
Kai Koehne
parent
698958c92d
commit
0ce1d6751c
@@ -191,6 +191,21 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
stream >> params[count++];
|
stream >> params[count++];
|
||||||
}
|
}
|
||||||
emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]);
|
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 {
|
} else {
|
||||||
int range;
|
int range;
|
||||||
stream >> range;
|
stream >> range;
|
||||||
|
@@ -77,6 +77,17 @@ public:
|
|||||||
MaximumMessage
|
MaximumMessage
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PixmapEventType {
|
||||||
|
PixmapSizeKnown,
|
||||||
|
PixmapReferenceCountChanged,
|
||||||
|
PixmapCacheCountChanged,
|
||||||
|
PixmapLoadingStarted,
|
||||||
|
PixmapLoadingFinished,
|
||||||
|
PixmapLoadingError,
|
||||||
|
|
||||||
|
MaximumPixmapEventType
|
||||||
|
};
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
bool isRecording() const;
|
bool isRecording() const;
|
||||||
void setRecording(bool);
|
void setRecording(bool);
|
||||||
@@ -95,6 +106,7 @@ signals:
|
|||||||
const QStringList &data, const QmlDebug::QmlEventLocation &location);
|
const QStringList &data, const QmlDebug::QmlEventLocation &location);
|
||||||
void frame(qint64 time, int frameRate, int animationCount);
|
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 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);
|
void recordingChanged(bool arg);
|
||||||
|
|
||||||
|
@@ -170,6 +170,10 @@ void QmlProfilerClientManager::connectClientSignals()
|
|||||||
this, SIGNAL(traceStarted(qint64)));
|
this, SIGNAL(traceStarted(qint64)));
|
||||||
connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
||||||
this, SIGNAL(addFrameEvent(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(),
|
connect(d->qmlclientplugin.data(),
|
||||||
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)),
|
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)),
|
||||||
this,
|
this,
|
||||||
@@ -206,6 +210,10 @@ void QmlProfilerClientManager::disconnectClientSignals()
|
|||||||
this, SIGNAL(traceStarted(qint64)));
|
this, SIGNAL(traceStarted(qint64)));
|
||||||
disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)),
|
||||||
this, SIGNAL(addFrameEvent(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(),
|
disconnect(d->qmlclientplugin.data(),
|
||||||
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)),
|
SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)),
|
||||||
this,
|
this,
|
||||||
|
@@ -67,6 +67,7 @@ signals:
|
|||||||
void traceFinished(qint64);
|
void traceFinished(qint64);
|
||||||
void dataReadyForProcessing();
|
void dataReadyForProcessing();
|
||||||
void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64);
|
void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64);
|
||||||
|
void addPixmapCacheEvent(qint64,int,QString,int,int,int);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void connectClient(quint16 port);
|
void connectClient(quint16 port);
|
||||||
|
@@ -222,6 +222,17 @@ void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qin
|
|||||||
emit countChanged();
|
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()
|
void QmlProfilerModelManager::complete()
|
||||||
{
|
{
|
||||||
if (state() == QmlProfilerDataState::AcquiringData) {
|
if (state() == QmlProfilerDataState::AcquiringData) {
|
||||||
|
@@ -122,6 +122,8 @@ public slots:
|
|||||||
const QStringList &data, const QmlDebug::QmlEventLocation &location);
|
const QStringList &data, const QmlDebug::QmlEventLocation &location);
|
||||||
void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime,
|
void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime,
|
||||||
qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5);
|
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,
|
void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber,
|
||||||
double totalTime, double selfTime);
|
double totalTime, double selfTime);
|
||||||
|
|
||||||
|
@@ -88,6 +88,13 @@ void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint
|
|||||||
eventList.append(eventData);
|
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
|
qint64 QmlProfilerSimpleModel::lastTimeMark() const
|
||||||
{
|
{
|
||||||
if (eventList.isEmpty())
|
if (eventList.isEmpty())
|
||||||
|
@@ -71,6 +71,7 @@ public:
|
|||||||
void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location);
|
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 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 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;
|
qint64 lastTimeMark() const;
|
||||||
virtual void complete();
|
virtual void complete();
|
||||||
|
|
||||||
|
@@ -157,6 +157,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
|
|||||||
SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)),
|
SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)),
|
||||||
d->m_profilerModelManager,
|
d->m_profilerModelManager,
|
||||||
SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)));
|
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,
|
connect(d->m_profilerConnections,
|
||||||
SIGNAL(addV8Event(int,QString,QString,int,double,double)),
|
SIGNAL(addV8Event(int,QString,QString,int,double,double)),
|
||||||
d->m_profilerModelManager,
|
d->m_profilerModelManager,
|
||||||
|
550
plugins/qmlprofilerextended/pixmapcachemodel.cpp
Normal file
550
plugins/qmlprofilerextended/pixmapcachemodel.cpp
Normal file
@@ -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
|
120
plugins/qmlprofilerextended/pixmapcachemodel.h
Normal file
120
plugins/qmlprofilerextended/pixmapcachemodel.h
Normal file
@@ -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
|
@@ -9,12 +9,14 @@ DEFINES += QMLPROFILEREXTENDED_LIBRARY
|
|||||||
# QmlProfilerExtended files
|
# QmlProfilerExtended files
|
||||||
|
|
||||||
SOURCES += qmlprofilerextendedplugin.cpp \
|
SOURCES += qmlprofilerextendedplugin.cpp \
|
||||||
scenegraphtimelinemodel.cpp
|
scenegraphtimelinemodel.cpp \
|
||||||
|
pixmapcachemodel.cpp
|
||||||
|
|
||||||
HEADERS += qmlprofilerextendedplugin.h\
|
HEADERS += qmlprofilerextendedplugin.h \
|
||||||
qmlprofilerextended_global.h\
|
qmlprofilerextended_global.h \
|
||||||
qmlprofilerextendedconstants.h \
|
qmlprofilerextendedconstants.h \
|
||||||
scenegraphtimelinemodel.h
|
scenegraphtimelinemodel.h \
|
||||||
|
pixmapcachemodel.h
|
||||||
|
|
||||||
OTHER_FILES += \
|
OTHER_FILES += \
|
||||||
QmlProfilerExtended.json
|
QmlProfilerExtended.json
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include <QtPlugin>
|
#include <QtPlugin>
|
||||||
|
|
||||||
#include "scenegraphtimelinemodel.h"
|
#include "scenegraphtimelinemodel.h"
|
||||||
|
#include "pixmapcachemodel.h"
|
||||||
|
|
||||||
using namespace QmlProfilerExtended::Internal;
|
using namespace QmlProfilerExtended::Internal;
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString
|
|||||||
Q_UNUSED(arguments)
|
Q_UNUSED(arguments)
|
||||||
Q_UNUSED(errorString)
|
Q_UNUSED(errorString)
|
||||||
|
|
||||||
|
addAutoReleasedObject(new PixmapCacheModel);
|
||||||
addAutoReleasedObject(new SceneGraphTimelineModel);
|
addAutoReleasedObject(new SceneGraphTimelineModel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user