QmlProfiler: Require model manager when constructing timeline models

This relieves us of the headaches created by figuring out what should
happen if the model manager is changed later. Extension models can be
safely created through a factory.

Change-Id: I8cf8fd6d639e4e6c9da66351ea44cfc35fd614a5
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2014-10-28 17:37:11 +01:00
committed by Ulf Hermann
parent 307d45ecaa
commit 91cb52d40b
15 changed files with 136 additions and 72 deletions

View File

@@ -140,13 +140,14 @@ void QmlProfiler::AbstractTimelineModel::setExpandedRowCount(int rows)
}
void AbstractTimelineModel::AbstractTimelineModelPrivate::init(AbstractTimelineModel *q,
QmlProfilerModelManager *manager,
const QString &newDisplayName,
QmlDebug::Message newMessage,
QmlDebug::RangeType newRangeType)
{
q_ptr = q;
modelId = 0;
modelManager = 0;
modelId = manager->registerModelProxy();
modelManager = manager;
expanded = false;
hidden = false;
displayName = newDisplayName;
@@ -154,6 +155,7 @@ void AbstractTimelineModel::AbstractTimelineModelPrivate::init(AbstractTimelineM
rangeType = newRangeType;
expandedRowCount = 1;
collapsedRowCount = 1;
connect(modelManager->qmlModel(), SIGNAL(changed()), q, SLOT(_q_dataChanged()));
connect(q,SIGNAL(rowHeightChanged()),q,SIGNAL(heightChanged()));
connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged()));
connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged()));
@@ -161,18 +163,19 @@ void AbstractTimelineModel::AbstractTimelineModelPrivate::init(AbstractTimelineM
AbstractTimelineModel::AbstractTimelineModel(AbstractTimelineModelPrivate *dd,
const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType,
QObject *parent) :
QmlProfilerModelManager *manager, const QString &displayName, QmlDebug::Message message,
QmlDebug::RangeType rangeType, QObject *parent) :
QObject(parent), d_ptr(dd)
{
dd->init(this, displayName, message, rangeType);
d_ptr->init(this, manager, displayName, message, rangeType);
}
AbstractTimelineModel::AbstractTimelineModel(const QString &displayName, QmlDebug::Message message,
QmlDebug::RangeType rangeType, QObject *parent) :
AbstractTimelineModel::AbstractTimelineModel(QmlProfilerModelManager *manager,
const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType,
QObject *parent) :
QObject(parent), d_ptr(new AbstractTimelineModelPrivate)
{
d_ptr->init(this, displayName, message, rangeType);
d_ptr->init(this, manager, displayName, message, rangeType);
}
AbstractTimelineModel::~AbstractTimelineModel()
@@ -181,25 +184,6 @@ AbstractTimelineModel::~AbstractTimelineModel()
delete d;
}
void AbstractTimelineModel::setModelManager(QmlProfilerModelManager *modelManager)
{
Q_D(AbstractTimelineModel);
if (modelManager != d->modelManager) {
if (d->modelManager != 0) {
disconnect(d->modelManager->qmlModel(), SIGNAL(changed()),
this, SLOT(_q_dataChanged()));
// completely unregistering is not supported
d->modelManager->setProxyCountWeight(d->modelId, 0);
}
d->modelManager = modelManager;
connect(d->modelManager->qmlModel(), SIGNAL(changed()),
this, SLOT(_q_dataChanged()));
d->modelId = d->modelManager->registerModelProxy();
d->modelManager->announceFeatures(d->modelId, features());
emit modelManagerChanged();
}
}
QmlProfilerModelManager *AbstractTimelineModel::modelManager() const
{
Q_D(const AbstractTimelineModel);
@@ -447,6 +431,12 @@ void AbstractTimelineModel::updateProgress(qint64 count, qint64 max) const
d->modelManager->modelProxyCountUpdated(d->modelId, count, max);
}
void AbstractTimelineModel::announceFeatures(quint64 features) const
{
Q_D(const AbstractTimelineModel);
d->modelManager->announceFeatures(d->modelId, features);
}
QColor AbstractTimelineModel::colorBySelectionId(int index) const
{
return colorByHue(selectionId(index) * AbstractTimelineModelPrivate::SelectionIdHueMultiplier);

View File

@@ -47,18 +47,17 @@ class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject
Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager WRITE setModelManager
NOTIFY modelManagerChanged)
Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager)
public:
class AbstractTimelineModelPrivate;
AbstractTimelineModel(const QString &displayName, QmlDebug::Message message,
QmlDebug::RangeType rangeType, QObject *parent);
AbstractTimelineModel(QmlProfilerModelManager *manager, const QString &displayName,
QmlDebug::Message message, QmlDebug::RangeType rangeType,
QObject *parent);
~AbstractTimelineModel();
// Trivial methods implemented by the abstract model itself
void setModelManager(QmlProfilerModelManager *modelManager);
QmlProfilerModelManager *modelManager() const;
bool isEmpty() const;
@@ -91,7 +90,6 @@ public:
virtual QVariantList labels() const = 0;
virtual QVariantMap details(int index) const = 0;
virtual int row(int index) const = 0;
virtual quint64 features() const = 0;
// Methods which can optionally be implemented by child models.
// returned map should contain "file", "line", "column" properties, or be empty
@@ -113,7 +111,6 @@ signals:
void rowHeightChanged();
void emptyChanged();
void heightChanged();
void modelManagerChanged();
protected:
QColor colorBySelectionId(int index) const;
@@ -135,8 +132,10 @@ protected:
QmlDebug::Message message() const;
void updateProgress(qint64 count, qint64 max) const;
void announceFeatures(quint64 features) const;
explicit AbstractTimelineModel(AbstractTimelineModelPrivate *dd, const QString &displayName,
explicit AbstractTimelineModel(AbstractTimelineModelPrivate *dd,
QmlProfilerModelManager *manager, const QString &displayName,
QmlDebug::Message message, QmlDebug::RangeType rangeType,
QObject *parent);
AbstractTimelineModelPrivate *d_ptr;

View File

@@ -67,8 +67,8 @@ public:
inline qint64 timestamp() const {return end;}
};
void init(AbstractTimelineModel *q, const QString &displayName, QmlDebug::Message message,
QmlDebug::RangeType rangeType);
void init(AbstractTimelineModel *q, QmlProfilerModelManager *manager,
const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType);
inline qint64 lastEndTime() const { return endTimes.last().end; }
inline qint64 firstStartTime() const { return ranges.first().start; }

View File

@@ -23,6 +23,7 @@ SOURCES += \
qmlprofilerruncontrolfactory.cpp \
qmlprofilerstatemanager.cpp \
qmlprofilerstatewidget.cpp \
qmlprofilertimelinemodelfactory.cpp \
qmlprofilertool.cpp \
qmlprofilertracefile.cpp \
qmlprofilertraceview.cpp \
@@ -58,6 +59,7 @@ HEADERS += \
qmlprofilerruncontrolfactory.h \
qmlprofilerstatemanager.h \
qmlprofilerstatewidget.h \
qmlprofilertimelinemodelfactory.h \
qmlprofilertool.h \
qmlprofilertracefile.h \
qmlprofilertraceview.h \

View File

@@ -41,6 +41,7 @@ QtcPlugin {
"qmlprofilerstatemanager.cpp", "qmlprofilerstatemanager.h",
"qmlprofilerstatewidget.cpp", "qmlprofilerstatewidget.h",
"qmlprofilerrangemodel.cpp", "qmlprofilerrangemodel.h",
"qmlprofilertimelinemodelfactory.cpp", "qmlprofilertimelinemodelfactory.h",
"qmlprofilertool.cpp", "qmlprofilertool.h",
"qmlprofilertracefile.cpp", "qmlprofilertracefile.h",
"qmlprofilertraceview.cpp", "qmlprofilertraceview.h",

View File

@@ -46,16 +46,14 @@
namespace QmlProfiler {
namespace Internal {
QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QObject *parent)
: AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)),
QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager,
QObject *parent)
: AbstractTimelineModel(manager,
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)),
QmlDebug::Event, QmlDebug::MaximumRangeType, parent)
{
m_maxGuiThreadAnimations = m_maxRenderThreadAnimations = 0;
}
quint64 QmlProfilerAnimationsModel::features() const
{
return 1 << QmlDebug::ProfileAnimations;
announceFeatures(1 << QmlDebug::ProfileAnimations);
}
void QmlProfilerAnimationsModel::clear()

View File

@@ -60,7 +60,7 @@ public:
int typeId;
};
QmlProfilerAnimationsModel(QObject *parent = 0);
QmlProfilerAnimationsModel(QmlProfilerModelManager *manager, QObject *parent = 0);
int rowMaxValue(int rowNumber) const;
@@ -72,7 +72,6 @@ public:
QVariantList labels() const;
QVariantMap details(int index) const;
quint64 features() const;
bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;

View File

@@ -92,7 +92,7 @@ bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorS
void QmlProfilerPlugin::extensionsInitialized()
{
timelineModels = ExtensionSystem::PluginManager::getObjects<AbstractTimelineModel>();
factory = ExtensionSystem::PluginManager::getObject<QmlProfilerTimelineModelFactory>();
}
ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown()
@@ -103,9 +103,9 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown()
return SynchronousShutdown;
}
QList<AbstractTimelineModel *> QmlProfilerPlugin::getModels() const
QList<AbstractTimelineModel *> QmlProfilerPlugin::getModels(QmlProfilerModelManager *manager) const
{
return timelineModels;
return factory->create(manager);
}
} // namespace Internal

View File

@@ -32,7 +32,7 @@
#define QMLPROFILERPLUGIN_H
#include "qmlprofiler_global.h"
#include "qmlprofilertimelinemodelfactory.h"
#include <extensionsystem/iplugin.h>
#include "abstracttimelinemodel.h"
@@ -55,10 +55,10 @@ public:
static bool debugOutput;
static QmlProfilerPlugin *instance;
QList<AbstractTimelineModel *> getModels() const;
QList<AbstractTimelineModel *> getModels(QmlProfilerModelManager *manager) const;
private:
QList<AbstractTimelineModel*> timelineModels;
QmlProfilerTimelineModelFactory *factory;
};
} // namespace Internal

View File

@@ -45,15 +45,12 @@ namespace QmlProfiler {
namespace Internal {
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlDebug::RangeType rangeType, QObject *parent)
: AbstractTimelineModel(categoryLabel(rangeType), QmlDebug::MaximumMessage, rangeType, parent)
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager,
QmlDebug::RangeType range, QObject *parent)
: AbstractTimelineModel(manager, categoryLabel(range), QmlDebug::MaximumMessage, range, parent)
{
m_expandedRowTypes << -1;
}
quint64 QmlProfilerRangeModel::features() const
{
return 1ULL << QmlDebug::featureFromRangeType(rangeType());
announceFeatures(1ULL << QmlDebug::featureFromRangeType(rangeType()));
}
void QmlProfilerRangeModel::clear()

View File

@@ -61,10 +61,10 @@ public:
int bindingLoopHead;
};
QmlProfilerRangeModel(QmlDebug::RangeType rangeType, QObject *parent = 0);
QmlProfilerRangeModel(QmlProfilerModelManager *manager, QmlDebug::RangeType range,
QObject *parent = 0);
static QString categoryLabel(QmlDebug::RangeType categoryIndex);
quint64 features() const;
int row(int index) const;
int bindingLoopDest(int index) const;

View File

@@ -0,0 +1,36 @@
/****************************************************************************
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "qmlprofilertimelinemodelfactory.h"
// The presence of this file makes sure that moc generates metadata
namespace QmlProfiler {
}

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 QMLPROFILERTIMELINEMODELFACTORY_H
#define QMLPROFILERTIMELINEMODELFACTORY_H
#include "abstracttimelinemodel.h"
#include "qmlprofilermodelmanager.h"
namespace QmlProfiler {
class QMLPROFILER_EXPORT QmlProfilerTimelineModelFactory : public QObject
{
Q_OBJECT
public:
virtual QList<AbstractTimelineModel *> create(QmlProfilerModelManager *manager) = 0;
};
}
#endif // QMLPROFILERTIMELINEMODELFACTORY_H

View File

@@ -80,20 +80,15 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana
connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable()));
// external models pushed on top
foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) {
timelineModel->setModelManager(modelManager);
foreach (AbstractTimelineModel *timelineModel,
QmlProfilerPlugin::instance->getModels(modelManager)) {
addModel(timelineModel);
}
QmlProfilerAnimationsModel *paintEventsModelProxy = new QmlProfilerAnimationsModel(this);
paintEventsModelProxy->setModelManager(modelManager);
addModel(paintEventsModelProxy);
addModel(new QmlProfilerAnimationsModel(modelManager, this));
for (int i = 0; i < QmlDebug::MaximumRangeType; ++i) {
QmlProfilerRangeModel *rangeModel = new QmlProfilerRangeModel((QmlDebug::RangeType)i, this);
rangeModel->setModelManager(modelManager);
addModel(rangeModel);
}
for (int i = 0; i < QmlDebug::MaximumRangeType; ++i)
addModel(new QmlProfilerRangeModel(modelManager, (QmlDebug::RangeType)i, this));
// Connect this last so that it's executed after the models have updated their data.
connect(modelManager->qmlModel(),SIGNAL(changed()),this,SIGNAL(stateChanged()));

View File

@@ -53,7 +53,6 @@ public:
QVariantList labels() const { return QVariantList(); }
QVariantMap details(int) const { return QVariantMap(); }
int row(int) const { return 1; }
quint64 features() const { return 0; }
protected:
void loadData();