Add setContextProperties()

Setting all properties in one batch avoids unnecessary
refreshing of expressions and is therefore a lot
faster if there are many expressions in the context.

In an example I created it takes 500ms to set 10 context properties
using setContextProperty() and it takes about 150ms to set the
context properties using setContextProperties.

Change-Id: Ic7cf03cda292b316198f37f963b61a2388a288c9
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Thomas Hartmann 2018-01-10 15:59:07 +01:00
parent 6318a43ffc
commit 4d68305466
3 changed files with 75 additions and 0 deletions

View File

@ -329,6 +329,49 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value)
setContextProperty(name, QVariant::fromValue(value));
}
/*!
\since 5.11
Set a batch of \a properties on this context.
Setting all properties in one batch avoids unnecessary
refreshing expressions, and is therefore recommended
instead of calling \l setContextProperty() for each individual property.
\sa QQmlContext::setContextProperty()
*/
void QQmlContext::setContextProperties(const QVector<PropertyPair> &properties)
{
Q_D(const QQmlContext);
QQmlContextData *data = d->data;
QQmlJavaScriptExpression *expressions = data->expressions;
QQmlContextData *childContexts = data->childContexts;
data->expressions = 0;
data->childContexts = 0;
for (auto property : properties)
setContextProperty(property.name, property.value);
data->expressions = expressions;
data->childContexts = childContexts;
data->refreshExpressions();
}
/*!
\since 5.11
\class QQmlContext::PropertyPair
This struct contains a property name and a property value.
It is used as a parameter for the \c setContextProperties function.
\sa QQQmlContext::setContextProperties()
*/
/*!
Returns the value of the \a name property for this context
as a QVariant.

View File

@ -42,6 +42,8 @@
#include <QtCore/qurl.h>
#include <QtCore/qobject.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtQml/qjsvalue.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qvariant.h>
@ -62,6 +64,8 @@ class Q_QML_EXPORT QQmlContext : public QObject
Q_DECLARE_PRIVATE(QQmlContext)
public:
struct PropertyPair { QString name; QVariant value; };
QQmlContext(QQmlEngine *parent, QObject *objParent = nullptr);
QQmlContext(QQmlContext *parent, QObject *objParent = nullptr);
virtual ~QQmlContext();
@ -77,6 +81,7 @@ public:
QVariant contextProperty(const QString &) const;
void setContextProperty(const QString &, QObject *);
void setContextProperty(const QString &, const QVariant &);
void setContextProperties(const QVector<PropertyPair> &properties);
// ### Qt 6: no need for a mutable object, this should become a const QObject pointer
QString nameForObject(QObject *) const;

View File

@ -47,6 +47,7 @@ private slots:
void engineMethod();
void parentContext();
void setContextProperty();
void setContextProperties();
void setContextObject();
void destruction();
void idAsContextProperty();
@ -363,6 +364,32 @@ void tst_qqmlcontext::setContextProperty()
}
}
void tst_qqmlcontext::setContextProperties()
{
QQmlContext ctxt(&engine);
TestObject obj1;
obj1.setA(3345);
TestObject obj2;
obj2.setA(-19);
QVector<QQmlContext::PropertyPair> properties;
properties.append({QString("a"), QVariant(10)});
properties.append({QString("b"), QVariant(19)});
properties.append({QString("d"), QVariant::fromValue<TestObject*>(&obj2)});
properties.append({QString("c"), QVariant(QString("Hello World!"))});
properties.append({QString("e"), QVariant::fromValue<TestObject*>(&obj1)});
ctxt.setContextProperties(properties);
TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(10));
TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(19));
TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(QString("Hello World!")));
TEST_CONTEXT_PROPERTY(&ctxt, d.a, QVariant(-19));
TEST_CONTEXT_PROPERTY(&ctxt, e.a, QVariant(3345));
}
void tst_qqmlcontext::setContextObject()
{
QQmlContext ctxt(&engine);