forked from qt-creator/qt-creator
QmlProfiler: Sanitize the signal exchange between models a bit
The model manager should only set its state to 'Done' if all models are actually done. When that is the case it can safely emit dataAvailable, too, freeing us of the need to apply a heuristic to the progress percentage. In order to have a unified interface to the completion of model processing an abstract base class for QML and V8 models is introduced. Task-number: QTCREATORBUG-11466 Change-Id: Id89c7ef5e24004baab7f37ee5486b69e7611aee0 Reviewed-by: Christian Stenger <christian.stenger@digia.com> Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
@@ -81,7 +81,7 @@ int AbstractTimelineModel::getBindingLoopDest(int index) const
|
||||
void AbstractTimelineModel::dataChanged()
|
||||
{
|
||||
switch (m_modelManager->state()) {
|
||||
case QmlProfilerDataState::Done:
|
||||
case QmlProfilerDataState::ProcessingData:
|
||||
loadData();
|
||||
break;
|
||||
case QmlProfilerDataState::ClearingData:
|
||||
|
||||
@@ -31,7 +31,8 @@ SOURCES += \
|
||||
abstracttimelinemodel.cpp \
|
||||
timelinemodelaggregator.cpp \
|
||||
qmlprofilerpainteventsmodelproxy.cpp \
|
||||
sortedtimelinemodel.cpp
|
||||
sortedtimelinemodel.cpp \
|
||||
qmlprofilerbasemodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
qmlprofilerconstants.h \
|
||||
@@ -63,7 +64,8 @@ HEADERS += \
|
||||
abstracttimelinemodel.h \
|
||||
timelinemodelaggregator.h \
|
||||
qmlprofilerpainteventsmodelproxy.h \
|
||||
sortedtimelinemodel.h
|
||||
sortedtimelinemodel.h \
|
||||
qmlprofilerbasemodel.h
|
||||
|
||||
RESOURCES += \
|
||||
qml/qmlprofiler.qrc
|
||||
|
||||
@@ -28,6 +28,7 @@ QtcPlugin {
|
||||
"localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h",
|
||||
"qmlprofiler_global.h",
|
||||
"qmlprofilerattachdialog.cpp", "qmlprofilerattachdialog.h",
|
||||
"qmlprofilerbasemodel.cpp", "qmlprofilerbasemodel.h",
|
||||
"qmlprofilerclientmanager.cpp", "qmlprofilerclientmanager.h",
|
||||
"qmlprofilerconstants.h",
|
||||
"qmlprofilerdetailsrewriter.cpp", "qmlprofilerdetailsrewriter.h",
|
||||
|
||||
57
src/plugins/qmlprofiler/qmlprofilerbasemodel.cpp
Normal file
57
src/plugins/qmlprofiler/qmlprofilerbasemodel.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 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.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qmlprofilerbasemodel.h"
|
||||
#include "qmlprofilermodelmanager.h"
|
||||
|
||||
namespace QmlProfiler {
|
||||
|
||||
QmlProfilerBaseModel::QmlProfilerBaseModel(QmlProfilerModelManager *manager) :
|
||||
m_modelManager(manager), m_processingDone(false)
|
||||
{
|
||||
Q_ASSERT(m_modelManager);
|
||||
m_modelId = m_modelManager->registerModelProxy();
|
||||
}
|
||||
|
||||
void QmlProfilerBaseModel::clear()
|
||||
{
|
||||
m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1);
|
||||
m_processingDone = false;
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void QmlProfilerBaseModel::complete()
|
||||
{
|
||||
emit changed();
|
||||
m_processingDone = true;
|
||||
m_modelManager->modelProxyCountUpdated(m_modelId, isEmpty() ? 0 : 1, 1);
|
||||
m_modelManager->modelProcessingDone();
|
||||
}
|
||||
|
||||
}
|
||||
62
src/plugins/qmlprofiler/qmlprofilerbasemodel.h
Normal file
62
src/plugins/qmlprofiler/qmlprofilerbasemodel.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 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.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMLPROFILERBASEMODEL_H
|
||||
#define QMLPROFILERBASEMODEL_H
|
||||
|
||||
#include "qmlprofiler_global.h"
|
||||
#include <QObject>
|
||||
|
||||
namespace QmlProfiler {
|
||||
|
||||
class QmlProfilerModelManager;
|
||||
|
||||
class QMLPROFILER_EXPORT QmlProfilerBaseModel : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
QmlProfilerBaseModel(QmlProfilerModelManager *manager);
|
||||
virtual ~QmlProfilerBaseModel() {}
|
||||
|
||||
virtual void complete();
|
||||
virtual void clear();
|
||||
virtual bool isEmpty() const = 0;
|
||||
bool processingDone() const { return m_processingDone; }
|
||||
|
||||
protected:
|
||||
QmlProfilerModelManager *m_modelManager;
|
||||
int m_modelId;
|
||||
bool m_processingDone;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMLPROFILERBASEMODEL_H
|
||||
@@ -96,7 +96,7 @@ void QmlProfilerEventsModelProxy::limitToRange(qint64 rangeStart, qint64 rangeEn
|
||||
|
||||
void QmlProfilerEventsModelProxy::dataChanged()
|
||||
{
|
||||
if (d->modelManager->state() == QmlProfilerDataState::Done)
|
||||
if (d->modelManager->state() == QmlProfilerDataState::ProcessingData)
|
||||
loadData();
|
||||
else if (d->modelManager->state() == QmlProfilerDataState::ClearingData)
|
||||
clear();
|
||||
|
||||
@@ -216,8 +216,6 @@ void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count,
|
||||
d->progress += d->partialCounts[proxyId] / d->partialCounts.count();
|
||||
|
||||
emit progressChanged();
|
||||
if (d->progress > 0.99)
|
||||
emit dataAvailable();
|
||||
}
|
||||
|
||||
qint64 QmlProfilerModelManager::estimatedProfilingTime() const
|
||||
@@ -259,25 +257,37 @@ void QmlProfilerModelManager::addV8Event(int depth, const QString &function, con
|
||||
|
||||
void QmlProfilerModelManager::complete()
|
||||
{
|
||||
if (state() == QmlProfilerDataState::AcquiringData) {
|
||||
switch (state()) {
|
||||
case QmlProfilerDataState::ProcessingData:
|
||||
setState(QmlProfilerDataState::Done);
|
||||
emit dataAvailable();
|
||||
break;
|
||||
case QmlProfilerDataState::AcquiringData:
|
||||
// If trace end time was not explicitly set, use the last event
|
||||
if (d->traceTime->endTime() == 0)
|
||||
d->traceTime->setEndTime(d->model->lastTimeMark());
|
||||
setState(QmlProfilerDataState::ProcessingData);
|
||||
d->model->complete();
|
||||
d->v8Model->complete();
|
||||
break;
|
||||
case QmlProfilerDataState::Empty:
|
||||
setState(QmlProfilerDataState::Done);
|
||||
} else
|
||||
if (state() == QmlProfilerDataState::Empty) {
|
||||
setState(QmlProfilerDataState::Done);
|
||||
} else
|
||||
if (state() == QmlProfilerDataState::Done) {
|
||||
// repeated Done states are ignored
|
||||
} else {
|
||||
break;
|
||||
case QmlProfilerDataState::Done:
|
||||
break;
|
||||
default:
|
||||
emit error(tr("Unexpected complete signal in data model."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerModelManager::modelProcessingDone()
|
||||
{
|
||||
Q_ASSERT(state() == QmlProfilerDataState::ProcessingData);
|
||||
if (d->model->processingDone() && d->v8Model->processingDone())
|
||||
complete();
|
||||
}
|
||||
|
||||
void QmlProfilerModelManager::save(const QString &filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
|
||||
@@ -141,6 +141,7 @@ public slots:
|
||||
double totalTime, double selfTime);
|
||||
|
||||
void complete();
|
||||
void modelProcessingDone();
|
||||
|
||||
void save(const QString &filename);
|
||||
void load(const QString &filename);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qmlprofilerprocessedmodel.h"
|
||||
#include "qmlprofilermodelmanager.h"
|
||||
#include <qmldebug/qmlprofilereventtypes.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <QUrl>
|
||||
@@ -96,10 +97,9 @@ bool compareStartTimes(const QmlProfilerSimpleModel::QmlEventData &t1, const Qml
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QmlProfilerProcessedModel::QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent)
|
||||
QmlProfilerProcessedModel::QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QmlProfilerModelManager *parent)
|
||||
: QmlProfilerSimpleModel(parent)
|
||||
, m_detailsRewriter(new QmlProfilerDetailsRewriter(this, fileFinder))
|
||||
, m_emitChanged(false)
|
||||
{
|
||||
connect(m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QString)),
|
||||
this, SLOT(detailsChanged(int,QString)));
|
||||
@@ -117,8 +117,6 @@ void QmlProfilerProcessedModel::clear()
|
||||
|
||||
// This call emits changed(). Don't emit it again here.
|
||||
QmlProfilerSimpleModel::clear();
|
||||
|
||||
m_emitChanged = false;
|
||||
}
|
||||
|
||||
void QmlProfilerProcessedModel::complete()
|
||||
@@ -154,12 +152,9 @@ void QmlProfilerProcessedModel::complete()
|
||||
m_detailsRewriter->requestDetailsForLocation(i, event->location);
|
||||
}
|
||||
|
||||
// Allow QmlProfilerBaseModel::complete() only after documents have been reloaded to avoid
|
||||
// unnecessary updates of child models.
|
||||
m_detailsRewriter->reloadDocuments();
|
||||
|
||||
// This call emits changed(). Don't emit it again here.
|
||||
QmlProfilerSimpleModel::complete();
|
||||
|
||||
m_emitChanged = false;
|
||||
}
|
||||
|
||||
void QmlProfilerProcessedModel::detailsChanged(int requestId, const QString &newString)
|
||||
@@ -168,16 +163,13 @@ void QmlProfilerProcessedModel::detailsChanged(int requestId, const QString &new
|
||||
|
||||
QmlEventData *event = &eventList[requestId];
|
||||
event->data = QStringList(newString);
|
||||
|
||||
m_emitChanged = true;
|
||||
}
|
||||
|
||||
void QmlProfilerProcessedModel::detailsDone()
|
||||
{
|
||||
if (m_emitChanged) {
|
||||
emit changed();
|
||||
m_emitChanged = false;
|
||||
}
|
||||
// The child models are supposed to synchronously update on changed(), triggered by
|
||||
// QmlProfilerBaseModel::complete().
|
||||
QmlProfilerSimpleModel::complete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class QmlProfilerProcessedModel : public QmlProfilerSimpleModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent = 0);
|
||||
explicit QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QmlProfilerModelManager *parent = 0);
|
||||
~QmlProfilerProcessedModel();
|
||||
|
||||
virtual void clear();
|
||||
@@ -53,7 +53,6 @@ private slots:
|
||||
|
||||
private:
|
||||
QmlProfilerDetailsRewriter *m_detailsRewriter;
|
||||
bool m_emitChanged;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -39,12 +39,9 @@
|
||||
|
||||
namespace QmlProfiler {
|
||||
|
||||
QmlProfilerSimpleModel::QmlProfilerSimpleModel(QObject *parent)
|
||||
: QObject(parent)
|
||||
QmlProfilerSimpleModel::QmlProfilerSimpleModel(QmlProfilerModelManager *parent)
|
||||
: QmlProfilerBaseModel(parent)
|
||||
{
|
||||
m_modelManager = qobject_cast<QmlProfilerModelManager *>(parent);
|
||||
Q_ASSERT(m_modelManager);
|
||||
m_modelId = m_modelManager->registerModelProxy();
|
||||
}
|
||||
|
||||
QmlProfilerSimpleModel::~QmlProfilerSimpleModel()
|
||||
@@ -53,9 +50,8 @@ QmlProfilerSimpleModel::~QmlProfilerSimpleModel()
|
||||
|
||||
void QmlProfilerSimpleModel::clear()
|
||||
{
|
||||
m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1);
|
||||
eventList.clear();
|
||||
emit changed();
|
||||
QmlProfilerBaseModel::clear();
|
||||
}
|
||||
|
||||
bool QmlProfilerSimpleModel::isEmpty() const
|
||||
@@ -98,12 +94,6 @@ qint64 QmlProfilerSimpleModel::lastTimeMark() const
|
||||
return eventList.last().startTime + eventList.last().duration;
|
||||
}
|
||||
|
||||
void QmlProfilerSimpleModel::complete()
|
||||
{
|
||||
m_modelManager->modelProxyCountUpdated(m_modelId, isEmpty() ? 0 : 1, 1);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
QString QmlProfilerSimpleModel::getHashString(const QmlProfilerSimpleModel::QmlEventData &event)
|
||||
{
|
||||
return QString::fromLatin1("%1:%2:%3:%4:%5").arg(
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define QMLPROFILERSIMPLEMODEL_H
|
||||
|
||||
#include "qmlprofiler_global.h"
|
||||
#include "qmlprofilerbasemodel.h"
|
||||
|
||||
#include <qmldebug/qmlprofilereventlocation.h>
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace QmlProfiler {
|
||||
class QmlProfilerModelManager;
|
||||
|
||||
// stores the data from the client as-is
|
||||
class QMLPROFILER_EXPORT QmlProfilerSimpleModel : public QObject
|
||||
class QMLPROFILER_EXPORT QmlProfilerSimpleModel : public QmlProfilerBaseModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
qint64 numericData5;
|
||||
};
|
||||
|
||||
explicit QmlProfilerSimpleModel(QObject *parent = 0);
|
||||
explicit QmlProfilerSimpleModel(QmlProfilerModelManager *parent);
|
||||
~QmlProfilerSimpleModel();
|
||||
|
||||
virtual void clear();
|
||||
@@ -72,17 +73,11 @@ public:
|
||||
void addQmlEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location,
|
||||
qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5);
|
||||
qint64 lastTimeMark() const;
|
||||
virtual void complete();
|
||||
|
||||
static QString getHashString(const QmlProfilerSimpleModel::QmlEventData &event);
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
protected:
|
||||
QVector<QmlEventData> eventList;
|
||||
QmlProfilerModelManager *m_modelManager;
|
||||
int m_modelId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ void QmlProfilerStateWidget::updateDisplay()
|
||||
void QmlProfilerStateWidget::dataStateChanged()
|
||||
{
|
||||
// consider possible rounding errors
|
||||
d->loadingDone = d->m_modelManager->progress() >= 0.99 ||
|
||||
d->loadingDone = d->m_modelManager->state() == QmlProfilerDataState::Done ||
|
||||
d->m_modelManager->state() == QmlProfilerDataState::Empty;
|
||||
d->traceAvailable = d->m_modelManager->traceTime()->duration() > 0;
|
||||
d->emptyList = d->m_modelManager->isEmpty() || d->m_modelManager->progress() == 0;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qv8profilerdatamodel.h"
|
||||
#include "qmlprofilermodelmanager.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
@@ -107,8 +108,8 @@ public:
|
||||
qint64 v8MeasuredTime;
|
||||
};
|
||||
|
||||
QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent)
|
||||
: QObject(parent)
|
||||
QV8ProfilerDataModel::QV8ProfilerDataModel(QmlProfilerModelManager *parent)
|
||||
: QmlProfilerBaseModel(parent)
|
||||
, d(new QV8ProfilerDataModelPrivate(this))
|
||||
{
|
||||
d->v8MeasuredTime = 0;
|
||||
@@ -128,7 +129,7 @@ void QV8ProfilerDataModel::clear()
|
||||
d->clearV8RootEvent();
|
||||
d->v8MeasuredTime = 0;
|
||||
|
||||
emit changed();
|
||||
QmlProfilerBaseModel::clear();
|
||||
}
|
||||
|
||||
bool QV8ProfilerDataModel::isEmpty() const
|
||||
@@ -482,7 +483,7 @@ void QV8ProfilerDataModel::load(QXmlStreamReader &stream)
|
||||
void QV8ProfilerDataModel::complete()
|
||||
{
|
||||
collectV8Statistics();
|
||||
emit changed();
|
||||
QmlProfilerBaseModel::complete();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#ifndef QV8PROFILERDATAMODEL_H
|
||||
#define QV8PROFILERDATAMODEL_H
|
||||
|
||||
#include "qmlprofilerbasemodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
|
||||
@@ -70,11 +72,11 @@ struct QV8EventSub {
|
||||
qint64 totalTime;
|
||||
};
|
||||
|
||||
class QV8ProfilerDataModel : public QObject
|
||||
class QV8ProfilerDataModel : public QmlProfilerBaseModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QV8ProfilerDataModel(QObject *parent = 0);
|
||||
QV8ProfilerDataModel(QmlProfilerModelManager *parent);
|
||||
~QV8ProfilerDataModel();
|
||||
|
||||
void clear();
|
||||
@@ -90,9 +92,6 @@ public:
|
||||
|
||||
void complete();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
public slots:
|
||||
void addV8Event(int depth,
|
||||
const QString &function,
|
||||
|
||||
Reference in New Issue
Block a user