summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorDavid Boddie <dboddie@trolltech.com>2010-07-16 15:46:21 (GMT)
committerDavid Boddie <dboddie@trolltech.com>2010-07-16 15:46:21 (GMT)
commit6b1b666574d6e27efdd3b243de8815a5278c3666 (patch)
tree7a5ac02fe569b3fc497ca8d0a333d10587eb3567 /src/declarative/qml
parenteef1d13743baddf41bd135d98fc2ad12944b8477 (diff)
parentab4dde176cfa314522964e5e5fbf9f2d388f8fdf (diff)
downloadQt-6b1b666574d6e27efdd3b243de8815a5278c3666.zip
Qt-6b1b666574d6e27efdd3b243de8815a5278c3666.tar.gz
Qt-6b1b666574d6e27efdd3b243de8815a5278c3666.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7
Conflicts: tools/qdoc3/test/qt.qdocconf
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp145
-rw-r--r--src/declarative/qml/qdeclarativebinding_p_p.h28
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp6
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp65
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp2
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h1
-rw-r--r--src/declarative/qml/qdeclarativedom.cpp2
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp72
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h4
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp82
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp502
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h83
-rw-r--r--src/declarative/qml/qdeclarativeextensionplugin.cpp4
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.cpp176
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.h18
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp24
-rw-r--r--src/declarative/qml/qdeclarativelist.cpp2
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp2
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp30
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h2
21 files changed, 849 insertions, 403 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 882e981..e096305 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -54,27 +54,20 @@
QT_BEGIN_NAMESPACE
-QDeclarativeBindingData::QDeclarativeBindingData()
-: updating(false), enabled(false)
+void QDeclarativeBindingPrivate::refresh()
{
+ Q_Q(QDeclarativeBinding);
+ q->update();
}
-QDeclarativeBindingData::~QDeclarativeBindingData()
-{
- removeError();
-}
-
-void QDeclarativeBindingData::refresh()
+QDeclarativeBindingPrivate::QDeclarativeBindingPrivate()
+: updating(false), enabled(false), deleted(0)
{
- if (enabled && !updating && q) {
- QDeclarativeBinding *b = static_cast<QDeclarativeBinding *>(QDeclarativeExpressionPrivate::get(q));
- b->update();
- }
}
-QDeclarativeBindingPrivate::QDeclarativeBindingPrivate()
-: QDeclarativeExpressionPrivate(new QDeclarativeBindingData)
+QDeclarativeBindingPrivate::~QDeclarativeBindingPrivate()
{
+ if (deleted) *deleted = true;
}
QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, QObject *obj,
@@ -109,7 +102,7 @@ QDeclarativeBinding::~QDeclarativeBinding()
void QDeclarativeBinding::setTarget(const QDeclarativeProperty &prop)
{
Q_D(QDeclarativeBinding);
- d->bindingData()->property = prop;
+ d->property = prop;
update();
}
@@ -117,50 +110,53 @@ void QDeclarativeBinding::setTarget(const QDeclarativeProperty &prop)
QDeclarativeProperty QDeclarativeBinding::property() const
{
Q_D(const QDeclarativeBinding);
- return d->bindingData()->property;
+ return d->property;
}
void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
{
Q_D(QDeclarativeBinding);
- QDeclarativeBindingData *data = d->bindingData();
-
- if (!data->enabled || !data->context() || !data->context()->isValid())
+ if (!d->enabled || !d->context() || !d->context()->isValid())
return;
- data->addref();
-
- if (!data->updating) {
- data->updating = true;
+ if (!d->updating) {
+ d->updating = true;
+ bool wasDeleted = false;
+ d->deleted = &wasDeleted;
- if (data->property.propertyType() == qMetaTypeId<QDeclarativeBinding *>()) {
+ if (d->property.propertyType() == qMetaTypeId<QDeclarativeBinding *>()) {
- int idx = data->property.index();
+ int idx = d->property.index();
Q_ASSERT(idx != -1);
-
QDeclarativeBinding *t = this;
int status = -1;
void *a[] = { &t, 0, &status, &flags };
- QMetaObject::metacall(data->property.object(),
+ QMetaObject::metacall(d->property.object(),
QMetaObject::WriteProperty,
idx, a);
+ if (wasDeleted)
+ return;
+
} else {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context()->engine);
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine);
bool isUndefined = false;
QVariant value;
QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
- if (data->property.propertyTypeCategory() == QDeclarativeProperty::List) {
+ if (wasDeleted)
+ return;
+
+ if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >());
} else if (scriptValue.isNull() &&
- data->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
+ d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
value = QVariant::fromValue((QObject *)0);
} else {
- value = ep->scriptValueToVariant(scriptValue, data->property.propertyType());
+ value = ep->scriptValueToVariant(scriptValue, d->property.propertyType());
if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) {
// If the object is null, we extract the predicted type. While this isn't
// 100% reliable, in many cases it gives us better error messages if we
@@ -172,73 +168,78 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
}
- if (data->error.isValid()) {
+ if (d->error.isValid()) {
- } else if (isUndefined && data->property.isResettable()) {
+ } else if (isUndefined && d->property.isResettable()) {
- data->property.reset();
+ d->property.reset();
- } else if (isUndefined && data->property.propertyType() == qMetaTypeId<QVariant>()) {
+ } else if (isUndefined && d->property.propertyType() == qMetaTypeId<QVariant>()) {
- QDeclarativePropertyPrivate::write(data->property, QVariant(), flags);
+ QDeclarativePropertyPrivate::write(d->property, QVariant(), flags);
} else if (isUndefined) {
- QUrl url = QUrl(data->url);
- int line = data->line;
+ QUrl url = QUrl(d->url);
+ int line = d->line;
if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
- data->error.setUrl(url);
- data->error.setLine(line);
- data->error.setColumn(-1);
- data->error.setDescription(QLatin1String("Unable to assign [undefined] to ")
- + QLatin1String(QMetaType::typeName(data->property.propertyType()))
- + QLatin1String(" ") + data->property.name());
+ d->error.setUrl(url);
+ d->error.setLine(line);
+ d->error.setColumn(-1);
+ d->error.setDescription(QLatin1String("Unable to assign [undefined] to ") +
+ QLatin1String(QMetaType::typeName(d->property.propertyType())) +
+ QLatin1String(" ") + d->property.name());
} else if (!scriptValue.isRegExp() && scriptValue.isFunction()) {
- QUrl url = QUrl(data->url);
- int line = data->line;
+ QUrl url = QUrl(d->url);
+ int line = d->line;
if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
- data->error.setUrl(url);
- data->error.setLine(line);
- data->error.setColumn(-1);
- data->error.setDescription(QLatin1String("Unable to assign a function to a property."));
+ d->error.setUrl(url);
+ d->error.setLine(line);
+ d->error.setColumn(-1);
+ d->error.setDescription(QLatin1String("Unable to assign a function to a property."));
+
+ } else if (d->property.object() &&
+ !QDeclarativePropertyPrivate::write(d->property, value, flags)) {
- } else if (data->property.object() &&
- !QDeclarativePropertyPrivate::write(data->property, value, flags)) {
+ if (wasDeleted)
+ return;
- QUrl url = QUrl(data->url);
- int line = data->line;
+ QUrl url = QUrl(d->url);
+ int line = d->line;
if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
const char *valueType = 0;
if (value.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(value.userType());
- data->error.setUrl(url);
- data->error.setLine(line);
- data->error.setColumn(-1);
- data->error.setDescription(QLatin1String("Unable to assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(data->property.propertyType())));
+ d->error.setUrl(url);
+ d->error.setLine(line);
+ d->error.setColumn(-1);
+ d->error.setDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(d->property.propertyType())));
}
- if (data->error.isValid()) {
- if (!data->addError(ep)) ep->warning(this->error());
+ if (wasDeleted)
+ return;
+
+ if (d->error.isValid()) {
+ if (!d->addError(ep)) ep->warning(this->error());
} else {
- data->removeError();
+ d->removeError();
}
}
- data->updating = false;
+ d->updating = false;
+ d->deleted = 0;
} else {
- qmlInfo(data->property.object()) << tr("Binding loop detected for property \"%1\"").arg(data->property.name());
+ qmlInfo(d->property.object()) << tr("Binding loop detected for property \"%1\"").arg(d->property.name());
}
-
- data->release();
}
void QDeclarativeBindingPrivate::emitValueChanged()
@@ -250,13 +251,13 @@ void QDeclarativeBindingPrivate::emitValueChanged()
void QDeclarativeBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
{
Q_D(QDeclarativeBinding);
- d->bindingData()->enabled = e;
+ d->enabled = e;
setNotifyOnValueChanged(e);
QDeclarativeAbstractBinding::setEnabled(e, flags);
if (e) {
- addToObject(d->bindingData()->property.object());
+ addToObject(d->property.object());
update(flags);
} else {
removeFromObject();
@@ -266,14 +267,14 @@ void QDeclarativeBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteF
int QDeclarativeBinding::propertyIndex()
{
Q_D(QDeclarativeBinding);
- return QDeclarativePropertyPrivate::bindingIndex(d->bindingData()->property);
+ return QDeclarativePropertyPrivate::bindingIndex(d->property);
}
bool QDeclarativeBinding::enabled() const
{
Q_D(const QDeclarativeBinding);
- return d->bindingData()->enabled;
+ return d->enabled;
}
QString QDeclarativeBinding::expression() const
diff --git a/src/declarative/qml/qdeclarativebinding_p_p.h b/src/declarative/qml/qdeclarativebinding_p_p.h
index 617ec4b..6926158 100644
--- a/src/declarative/qml/qdeclarativebinding_p_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p_p.h
@@ -60,30 +60,24 @@
QT_BEGIN_NAMESPACE
-class QDeclarativeBindingData : public QDeclarativeExpressionData
-{
-public:
- QDeclarativeBindingData();
- virtual ~QDeclarativeBindingData();
-
- bool updating:1;
- bool enabled:1;
-
- QDeclarativeProperty property;
-
- virtual void refresh();
-};
-
class QDeclarativeBindingPrivate : public QDeclarativeExpressionPrivate
{
Q_DECLARE_PUBLIC(QDeclarativeBinding)
public:
QDeclarativeBindingPrivate();
-
- QDeclarativeBindingData *bindingData() { return static_cast<QDeclarativeBindingData *>(data); }
- const QDeclarativeBindingData *bindingData() const { return static_cast<const QDeclarativeBindingData *>(data); }
+ ~QDeclarativeBindingPrivate();
virtual void emitValueChanged();
+
+protected:
+ virtual void refresh();
+
+private:
+ bool updating:1;
+ bool enabled:1;
+ QDeclarativeProperty property;
+
+ bool *deleted;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 623e3df..23307c9 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -228,10 +228,10 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
}
break;
case QMetaType::Float:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected"));
+ if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
break;
case QVariant::Double:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected"));
+ if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
break;
case QVariant::Color:
{
@@ -2449,7 +2449,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
Object::DynamicSlot &s = obj->dynamicSlots[ii];
QByteArray sig(s.name + '(');
- QString funcScript(QLatin1String("(function("));
+ QString funcScript(QLatin1String("(function ") + s.name + QLatin1Char('('));
for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
if (jj) {
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index 9d3032c..36c4b49 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -68,37 +68,85 @@ class QByteArray;
/*!
\class QDeclarativeComponent
\since 4.7
- \brief The QDeclarativeComponent class encapsulates a QML component description.
+ \brief The QDeclarativeComponent class encapsulates a QML component definition.
\mainclass
+
+ Components are reusable, encapsulated QML elements with well-defined interfaces.
+ They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
+
+ A QDeclarativeComponent instance can be created from a QML file.
+ For example, if there is a \c main.qml file like this:
+
+ \qml
+ import Qt 4.7
+
+ Item {
+ width: 200
+ height: 200
+ }
+ \endqml
+
+ The following code loads this QML file as a component, creates an instance of
+ this component using create(), and then queries the \l Item's \l {Item::}{width}
+ value:
+
+ \code
+ QDeclarativeEngine *engine = new QDeclarativeEngine;
+ QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
+
+ QObject *myObject = component.create();
+ QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(myObject);
+ int width = item->width(); // width = 200
+ \endcode
+
+ \sa {Using QML in C++ Applications}, {Integrating QML with existing Qt UI code}
*/
/*!
\qmlclass Component QDeclarativeComponent
\since 4.7
- \brief The Component element encapsulates a QML component description.
+ \brief The Component element encapsulates a QML component definition.
Components are reusable, encapsulated QML elements with well-defined interfaces.
- They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
- The \e Component element allows defining components within a QML file.
- This can be useful for reusing a small component within a single QML
- file, or for defining a component that logically belongs with the
- file containing it.
+ Components are often defined by \l {qdeclarativedocuments.html}{component files} -
+ that is, \c .qml files. The \e Component element allows components to be defined
+ within QML items rather than in a separate file. This may be useful for reusing
+ a small component within a QML file, or for defining a component that logically
+ belongs with other QML components within a file.
+
+ For example, here is a component that is used by multiple \l Loader objects:
\qml
Item {
Component {
id: redSquare
+
Rectangle {
color: "red"
width: 10
height: 10
}
}
+
Loader { sourceComponent: redSquare }
Loader { sourceComponent: redSquare; x: 20 }
}
\endqml
+
+ Notice that while a \l Rectangle by itself would be automatically
+ rendered and displayed, this is not the case for the above rectangle
+ because it is defined inside a \c Component. The component encapsulates the
+ QML elements within, as if they were defined in a separate \c .qml
+ file, and is not loaded until requested (in this case, by the
+ two \l Loader objects).
+
+ The Component element is commonly used to provide graphical components
+ for views. For example, the ListView::delegate property requires a Component
+ to specify how each list item is to be displayed.
+
+ Component objects can also be dynamically generated using
+ \l{Qt::createComponent}{Qt.createComponent()}.
*/
/*!
@@ -448,7 +496,8 @@ void QDeclarativeComponent::loadUrl(const QUrl &url)
d->clear();
- if (url.isRelative() && !url.isEmpty())
+ if ((url.isRelative() && !url.isEmpty())
+ || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
d->url = d->engine->baseUrl().resolved(url);
else
d->url = url;
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index 60e9dd3..3d25291 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -145,6 +145,8 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate()
has been created in that context is an expensive operation (essentially forcing all bindings
to reevaluate). Thus whenever possible you should complete "setup" of the context
before using it to create any objects.
+
+ \sa {Using QML in C++ Applications}
*/
/*! \internal */
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 1f5aaf1..c5a039a 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -198,6 +198,7 @@ public:
// context
QDeclarativeComponentAttached *componentAttached;
+ // Return the outermost id for obj, if any.
QString findObjectId(const QObject *obj) const;
static QDeclarativeContextData *get(QDeclarativeContext *context) {
diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp
index a3cddb5..5b30bde 100644
--- a/src/declarative/qml/qdeclarativedom.cpp
+++ b/src/declarative/qml/qdeclarativedom.cpp
@@ -493,7 +493,7 @@ int QDeclarativeDomDynamicProperty::propertyType() const
return QMetaType::type("int");
case QDeclarativeParser::Object::DynamicProperty::Real:
- return QMetaType::type("double");
+ return sizeof(qreal) == sizeof(double) ? QMetaType::type("double") : QMetaType::type("float");
case QDeclarativeParser::Object::DynamicProperty::String:
return QMetaType::type("QString");
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 1ce668c..f2eb770 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -151,6 +151,7 @@ void QDeclarativeEnginePrivate::defineModule()
}
/*!
+\keyword QmlGlobalQtObject
\qmlclass Qt QDeclarativeEnginePrivate
\brief The QML global Qt object provides useful enums and functions from Qt.
@@ -218,7 +219,7 @@ of their use.
QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
-: captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false),
+: captureProperties(false), rootContext(0), isDebugging(false),
outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0),
objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0),
inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0),
@@ -620,24 +621,16 @@ QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
/*!
Sets the \a provider to use for images requested via the \e
- image: url scheme, with host \a providerId.
+ image: url scheme, with host \a providerId. The QDeclarativeEngine
+ takes ownership of \a provider.
- QDeclarativeImageProvider allows images to be provided to QML
- asynchronously. The image request will be run in a low priority
- thread. This allows potentially costly image loading to be done in
- the background, without affecting the performance of the UI.
+ Image providers enable support for pixmap and threaded image
+ requests. See the QDeclarativeImageProvider documentation for details on
+ implementing and using image providers.
Note that images loaded from a QDeclarativeImageProvider are cached
by QPixmapCache, similar to any image loaded by QML.
- The QDeclarativeEngine assumes ownership of the provider.
-
- This example creates a provider with id \e colors:
-
- \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 0
-
- \snippet examples/declarative/cppextensions/imageprovider/imageprovider-example.qml 0
-
\sa removeImageProvider()
*/
void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
@@ -671,16 +664,35 @@ void QDeclarativeEngine::removeImageProvider(const QString &providerId)
delete d->imageProviders.take(providerId);
}
+QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
+{
+ QMutexLocker locker(&mutex);
+ QDeclarativeImageProvider *provider = imageProviders.value(url.host());
+ if (provider)
+ return provider->imageType();
+ return static_cast<QDeclarativeImageProvider::ImageType>(-1);
+}
+
QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
{
QMutexLocker locker(&mutex);
QImage image;
QDeclarativeImageProvider *provider = imageProviders.value(url.host());
if (provider)
- image = provider->request(url.path().mid(1), size, req_size);
+ image = provider->requestImage(url.path().mid(1), size, req_size);
return image;
}
+QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
+{
+ QMutexLocker locker(&mutex);
+ QPixmap pixmap;
+ QDeclarativeImageProvider *provider = imageProviders.value(url.host());
+ if (provider)
+ pixmap = provider->requestPixmap(url.path().mid(1), size, req_size);
+ return pixmap;
+}
+
/*!
Return the base URL for this engine. The base URL is only used to
resolve components when a relative URL is passed to the
@@ -1259,11 +1271,12 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE
QDate date = ctxt->argument(0).toDateTime().date();
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
if (argCount == 2) {
- if (ctxt->argument(1).isString()) {
- QString format = ctxt->argument(1).toString();
+ QScriptValue formatArg = ctxt->argument(1);
+ if (formatArg.isString()) {
+ QString format = formatArg.toString();
return engine->newVariant(qVariantFromValue(date.toString(format)));
- } else if (ctxt->argument(1).isNumber()) {
- enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else if (formatArg.isNumber()) {
+ enumFormat = Qt::DateFormat(formatArg.toUInt32());
} else {
return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format"));
}
@@ -1286,11 +1299,12 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE
QTime date = ctxt->argument(0).toDateTime().time();
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
if (argCount == 2) {
- if (ctxt->argument(1).isString()) {
- QString format = ctxt->argument(1).toString();
+ QScriptValue formatArg = ctxt->argument(1);
+ if (formatArg.isString()) {
+ QString format = formatArg.toString();
return engine->newVariant(qVariantFromValue(date.toString(format)));
- } else if (ctxt->argument(1).isNumber()) {
- enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else if (formatArg.isNumber()) {
+ enumFormat = Qt::DateFormat(formatArg.toUInt32());
} else {
return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format"));
}
@@ -1376,11 +1390,12 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr
QDateTime date = ctxt->argument(0).toDateTime();
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
if (argCount == 2) {
- if (ctxt->argument(1).isString()) {
- QString format = ctxt->argument(1).toString();
+ QScriptValue formatArg = ctxt->argument(1);
+ if (formatArg.isString()) {
+ QString format = formatArg.toString();
return engine->newVariant(qVariantFromValue(date.toString(format)));
- } else if (ctxt->argument(1).isNumber()) {
- enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else if (formatArg.isNumber()) {
+ enumFormat = Qt::DateFormat(formatArg.toUInt32());
} else {
return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
}
@@ -1728,8 +1743,7 @@ void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const
/*!
\qmlmethod Qt::quit()
This function causes the QDeclarativeEngine::quit() signal to be emitted.
-Within the \l {Qt Declarative UI Runtime}{qml} application this causes the
-launcher application to exit.
+Within the \l {QML Viewer}, this causes the launcher application to exit.
*/
QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index cfa9d73..a5c8c38 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -64,6 +64,7 @@
#include "qdeclarativecontext.h"
#include "private/qdeclarativecontext_p.h"
#include "qdeclarativeexpression.h"
+#include "qdeclarativeimageprovider.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativepropertycache_p.h"
#include "private/qdeclarativeobjectscriptclass_p.h"
@@ -161,7 +162,6 @@ public:
QPODVector<CapturedProperty> capturedProperties;
QDeclarativeContext *rootContext;
- QDeclarativeExpression *currentExpression;
bool isDebugging;
bool outputWarningsToStdErr;
@@ -233,7 +233,9 @@ public:
mutable QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory;
QHash<QString,QDeclarativeImageProvider*> imageProviders;
+ QDeclarativeImageProvider::ImageType getImageProviderType(const QUrl &url);
QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
+ QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
mutable QMutex mutex;
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
index d765649..001da46 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -50,6 +50,8 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativewatcher_p.h"
#include "private/qdeclarativevaluetype_p.h"
+#include "private/qdeclarativevmemetaobject_p.h"
+#include "private/qdeclarativeexpression_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
@@ -453,20 +455,30 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
sendMessage(reply);
} else if (type == "SET_BINDING") {
- int queryId;
int objectId;
QString propertyName;
QVariant expr;
bool isLiteralValue;
- ds >> queryId >> objectId >> propertyName >> expr >> isLiteralValue;
+ ds >> objectId >> propertyName >> expr >> isLiteralValue;
setBinding(objectId, propertyName, expr, isLiteralValue);
+ } else if (type == "RESET_BINDING") {
+ int objectId;
+ QString propertyName;
+ ds >> objectId >> propertyName;
+ resetBinding(objectId, propertyName);
+ } else if (type == "SET_METHOD_BODY") {
+ int objectId;
+ QString methodName;
+ QString methodBody;
+ ds >> objectId >> methodName >> methodBody;
+ setMethodBody(objectId, methodName, methodBody);
}
}
void QDeclarativeEngineDebugServer::setBinding(int objectId,
- const QString &propertyName,
- const QVariant &expression,
- bool isLiteralValue)
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue)
{
QObject *object = objectForId(objectId);
QDeclarativeContext *context = qmlContext(object);
@@ -493,7 +505,67 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId,
}
}
}
+}
+
+void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &propertyName)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+
+ if (object && context) {
+ if (object->property(propertyName.toLatin1()).isValid()) {
+ QDeclarativeProperty property(object, propertyName);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(property);
+ if (oldBinding) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0);
+ if (oldBinding)
+ oldBinding->destroy();
+ } else {
+ if (property.isResettable()) {
+ property.reset();
+ }
+ }
+ }
+ }
+}
+
+void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &method, const QString &body)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+ if (!object || !context || !context->engine())
+ return;
+ QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
+ if (!contextData)
+ return;
+
+ QDeclarativePropertyCache::Data dummy;
+ QDeclarativePropertyCache::Data *prop =
+ QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
+
+ if (!prop || !(prop->flags & QDeclarativePropertyCache::Data::IsVMEFunction))
+ return;
+
+ QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
+ QList<QByteArray> paramNames = metaMethod.parameterNames();
+
+ QString paramStr;
+ for (int ii = 0; ii < paramNames.count(); ++ii) {
+ if (ii != 0) paramStr.append(QLatin1String(","));
+ paramStr.append(QString::fromUtf8(paramNames.at(ii)));
+ }
+
+ QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
+ QLatin1String(") {");
+ jsfunction += body;
+ jsfunction += QLatin1String("\n})");
+
+ QDeclarativeVMEMetaObject *vmeMetaObject =
+ static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
+ Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
+ int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
+ vmeMetaObject->setVmeMethod(prop->coreIndex, QDeclarativeExpressionPrivate::evalInObjectScope(contextData, object, jsfunction, contextData->url.toString(), lineNumber, 0));
}
void QDeclarativeEngineDebugServer::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h
index b3c23bd..ea35b40 100644
--- a/src/declarative/qml/qdeclarativeenginedebug_p.h
+++ b/src/declarative/qml/qdeclarativeenginedebug_p.h
@@ -108,6 +108,8 @@ private:
QDeclarativeObjectProperty propertyData(QObject *, int);
QVariant valueContents(const QVariant &defaultValue) const;
void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue);
+ void resetBinding(int objectId, const QString &propertyName);
+ void setMethodBody(int objectId, const QString &method, const QString &body);
static QList<QDeclarativeEngine *> m_engines;
QDeclarativeWatcher *m_watch;
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index 8ae5f2f..9935e38 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -71,109 +71,95 @@ bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
return true;
}
-QDeclarativeExpressionData::QDeclarativeExpressionData()
-: q(0), dataRef(0), expressionFunctionValid(false), expressionRewritten(false), me(0),
- trackChange(false), isShared(false), line(-1), guardList(0), guardListLength(0)
+QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression()
+: dataRef(0), expressionFunctionMode(ExplicitContext), scopeObject(0), trackChange(false),
+ guardList(0), guardListLength(0), guardObject(0), guardObjectNotifyIndex(-1), deleted(0)
{
}
-QDeclarativeExpressionData::~QDeclarativeExpressionData()
+QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression()
{
if (guardList) { delete [] guardList; guardList = 0; }
if (dataRef) dataRef->release();
+ if (deleted) *deleted = true;
}
QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate()
-: data(new QDeclarativeExpressionData)
+: expressionFunctionValid(true), line(-1)
{
- data->q = this;
-}
-
-QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate(QDeclarativeExpressionData *d)
-: data(d)
-{
- data->q = this;
}
QDeclarativeExpressionPrivate::~QDeclarativeExpressionPrivate()
{
- if (data) {
- delete [] data->guardList;
- data->guardList = 0;
- data->guardListLength = 0;
- data->q = 0;
- data->release();
- data = 0;
- }
}
void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr,
QObject *me)
{
- data->expression = expr;
+ expression = expr;
- data->QDeclarativeAbstractExpression::setContext(ctxt);
- data->me = me;
+ QDeclarativeAbstractExpression::setContext(ctxt);
+ scopeObject = me;
+ expressionFunctionValid = false;
}
-void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr, QDeclarativeRefCount *rc,
- QObject *me, const QString &url, int lineNumber)
+void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr,
+ QDeclarativeRefCount *rc,
+ QObject *me, const QString &srcUrl, int lineNumber)
{
- data->url = url;
- data->line = lineNumber;
+ url = srcUrl;
+ line = lineNumber;
- if (data->dataRef) data->dataRef->release();
- data->dataRef = rc;
- if (data->dataRef) data->dataRef->addref();
+ if (dataRef) dataRef->release();
+ dataRef = rc;
+ if (dataRef) dataRef->addref();
quint32 *exprData = (quint32 *)expr;
QDeclarativeCompiledData *dd = (QDeclarativeCompiledData *)rc;
- data->expressionRewritten = true;
- data->expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
+ expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
int progIdx = *(exprData);
- bool isShared = progIdx & 0x80000000;
+ bool isSharedProgram = progIdx & 0x80000000;
progIdx &= 0x7FFFFFFF;
QDeclarativeEngine *engine = ctxt->engine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- if (isShared) {
+ if (isSharedProgram) {
if (!dd->cachedClosures.at(progIdx)) {
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
scriptContext->pushScope(ep->contextClass->newSharedContext());
scriptContext->pushScope(ep->globalClass->staticGlobalObject());
- dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line));
+ dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(expression, url, line));
scriptEngine->popContext();
}
- data->expressionFunction = *dd->cachedClosures.at(progIdx);
- data->isShared = true;
- data->expressionFunctionValid = true;
+ expressionFunction = *dd->cachedClosures.at(progIdx);
+ expressionFunctionMode = SharedContext;
+ expressionFunctionValid = true;
} else {
#if !defined(Q_OS_SYMBIAN) //XXX Why doesn't this work?
if (!dd->cachedPrograms.at(progIdx)) {
- dd->cachedPrograms[progIdx] =
- new QScriptProgram(data->expression, data->url, data->line);
+ dd->cachedPrograms[progIdx] = new QScriptProgram(expression, url, line);
}
- data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
- &data->expressionContext);
+ expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
+ &expressionContext);
#else
- data->expressionFunction = evalInObjectScope(ctxt, me, data->expression,
- &data->expressionContext);
+ expressionFunction = evalInObjectScope(ctxt, me, expression, &expressionContext);
#endif
- data->expressionFunctionValid = true;
+ expressionFunctionMode = ExplicitContext;
+ expressionFunctionValid = true;
}
- data->QDeclarativeAbstractExpression::setContext(ctxt);
- data->me = me;
+ QDeclarativeAbstractExpression::setContext(ctxt);
+ scopeObject = me;
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
@@ -214,10 +200,34 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
/*!
\class QDeclarativeExpression
- \since 4.7
+ \since 4.7
\brief The QDeclarativeExpression class evaluates JavaScript in a QML context.
+
+ For example, given a file \c main.qml like this:
+
+ \qml
+ import Qt 4.7
+
+ Item {
+ width: 200; height: 200
+ }
+ \endqml
+
+ The following code evaluates a JavaScript expression in the context of the
+ above QML:
+
+ \code
+ QDeclarativeEngine *engine = new QDeclarativeEngine;
+ QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
+
+ QObject *myObject = component.create();
+ QDeclarativeExpression *expr = new QDeclarativeExpression(engine->rootContext(), myObject, "width * 2");
+ int result = expr->evaluate().toInt(); // result = 400
+ \endcode
*/
+static int QDeclarativeExpression_notifyIdx = -1;
+
/*!
Create an invalid QDeclarativeExpression.
@@ -227,6 +237,11 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
QDeclarativeExpression::QDeclarativeExpression()
: QObject(*new QDeclarativeExpressionPrivate, 0)
{
+ Q_D(QDeclarativeExpression);
+
+ if (QDeclarativeExpression_notifyIdx == -1)
+ QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+ d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
/*! \internal */
@@ -238,6 +253,10 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, vo
{
Q_D(QDeclarativeExpression);
d->init(ctxt, expr, rc, me, url, lineNumber);
+
+ if (QDeclarativeExpression_notifyIdx == -1)
+ QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+ d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
/*!
@@ -255,6 +274,10 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt,
{
Q_D(QDeclarativeExpression);
d->init(QDeclarativeContextData::get(ctxt), expression, scope);
+
+ if (QDeclarativeExpression_notifyIdx == -1)
+ QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+ d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
/*!
@@ -266,6 +289,10 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
{
Q_D(QDeclarativeExpression);
d->init(ctxt, expression, scope);
+
+ if (QDeclarativeExpression_notifyIdx == -1)
+ QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+ d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
/*! \internal */
@@ -275,6 +302,10 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
{
Q_D(QDeclarativeExpression);
d->init(ctxt, expression, scope);
+
+ if (QDeclarativeExpression_notifyIdx == -1)
+ QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+ d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
/*!
@@ -291,7 +322,7 @@ QDeclarativeExpression::~QDeclarativeExpression()
QDeclarativeEngine *QDeclarativeExpression::engine() const
{
Q_D(const QDeclarativeExpression);
- return d->data->context()?d->data->context()->engine:0;
+ return d->context()?d->context()->engine:0;
}
/*!
@@ -301,7 +332,7 @@ QDeclarativeEngine *QDeclarativeExpression::engine() const
QDeclarativeContext *QDeclarativeExpression::context() const
{
Q_D(const QDeclarativeExpression);
- QDeclarativeContextData *data = d->data->context();
+ QDeclarativeContextData *data = d->context();
return data?data->asQDeclarativeContext():0;
}
@@ -311,7 +342,7 @@ QDeclarativeContext *QDeclarativeExpression::context() const
QString QDeclarativeExpression::expression() const
{
Q_D(const QDeclarativeExpression);
- return d->data->expression;
+ return d->expression;
}
/*!
@@ -321,12 +352,10 @@ void QDeclarativeExpression::setExpression(const QString &expression)
{
Q_D(QDeclarativeExpression);
- d->clearGuards();
-
- d->data->expression = expression;
- d->data->expressionFunctionValid = false;
- d->data->expressionRewritten = false;
- d->data->expressionFunction = QScriptValue();
+ d->resetNotifyOnChange();
+ d->expression = expression;
+ d->expressionFunctionValid = false;
+ d->expressionFunction = QScriptValue();
}
void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
@@ -356,59 +385,108 @@ void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine
}
}
-QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool *isUndefined)
+bool QDeclarativeQtScriptExpression::notifyOnValueChange() const
{
- QDeclarativeExpressionData *data = this->data;
- QDeclarativeEngine *engine = data->context()->engine;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ return trackChange;
+}
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+void QDeclarativeQtScriptExpression::setNotifyOnValueChange(bool notify)
+{
+ trackChange = notify;
+ if (!notify && guardList)
+ clearGuards();
+}
- if (!data->expressionFunctionValid) {
+void QDeclarativeQtScriptExpression::resetNotifyOnChange()
+{
+ clearGuards();
+}
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- data->expressionContext = ep->contextClass->newContext(data->context(), data->me);
- scriptContext->pushScope(data->expressionContext);
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
+void QDeclarativeQtScriptExpression::setNotifyObject(QObject *object, int notifyIndex)
+{
+ if (guardList) clearGuards();
+
+ if (!object || notifyIndex == -1) {
+ guardObject = 0;
+ notifyIndex = -1;
+ } else {
+ guardObject = object;
+ guardObjectNotifyIndex = notifyIndex;
+
+ }
+}
+
+QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined)
+{
+ Q_ASSERT(context() && context()->engine);
+ Q_ASSERT(!trackChange || (guardObject && guardObjectNotifyIndex != -1));
+
+ if (!expressionFunction.isValid()) {
+ if (isUndefined) *isUndefined = true;
+ return QScriptValue();
+ }
+
+ DeleteWatcher watcher(this);
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
+
+ bool lastCaptureProperties = ep->captureProperties;
+ QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
+ ep->captureProperties = trackChange;
+ ep->capturedProperties.copyAndClear(lastCapturedProperties);
+
+ QScriptValue value = eval(secondaryScope, isUndefined);
+
+ if (!watcher.wasDeleted() && trackChange) {
+ if (ep->capturedProperties.count() == 0) {
+
+ if (guardList) clearGuards();
- if (data->expressionRewritten) {
- data->expressionFunction = scriptEngine->evaluate(data->expression,
- data->url, data->line);
} else {
- QDeclarativeRewrite::RewriteBinding rewriteBinding;
- bool ok = true;
- const QString code = rewriteBinding(data->expression, &ok);
- if (!ok) {
- scriptEngine->popContext();
- return QScriptValue();
- }
- data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line);
- }
+ updateGuards(ep->capturedProperties);
- scriptEngine->popContext();
- data->expressionFunctionValid = true;
+ }
}
+ lastCapturedProperties.copyAndClear(ep->capturedProperties);
+ ep->captureProperties = lastCaptureProperties;
+
+ return value;
+}
+
+QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
+{
+ Q_ASSERT(context() && context()->engine);
+
+ DeleteWatcher watcher(this);
+
+ QDeclarativeEngine *engine = context()->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+
+ QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+
QDeclarativeContextData *oldSharedContext = 0;
QObject *oldSharedScope = 0;
QObject *oldOverride = 0;
- if (data->isShared) {
+ bool isShared = (expressionFunctionMode == SharedContext);
+
+ if (isShared) {
oldSharedContext = ep->sharedContext;
oldSharedScope = ep->sharedScope;
- ep->sharedContext = data->context();
- ep->sharedScope = data->me;
+ ep->sharedContext = context();
+ ep->sharedScope = scopeObject;
} else {
- oldOverride = ep->contextClass->setOverrideObject(data->expressionContext, secondaryScope);
+ oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope);
}
- QScriptValue svalue = data->expressionFunction.call();
+ QScriptValue svalue = expressionFunction.call(); // This could cause this to be deleted
- if (data->isShared) {
+ if (isShared) {
ep->sharedContext = oldSharedContext;
ep->sharedScope = oldSharedScope;
- } else {
- ep->contextClass->setOverrideObject(data->expressionContext, oldOverride);
+ } else if (!watcher.wasDeleted()) {
+ ep->contextClass->setOverrideObject(expressionContext, oldOverride);
}
if (isUndefined)
@@ -416,63 +494,134 @@ QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool *
// Handle exception
if (scriptEngine->hasUncaughtException()) {
- exceptionToError(scriptEngine, data->error);
+ if (!watcher.wasDeleted())
+ QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
+
scriptEngine->clearExceptions();
return QScriptValue();
} else {
- data->error = QDeclarativeError();
+ if (!watcher.wasDeleted())
+ error = QDeclarativeError();
+
return svalue;
}
}
-QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
+void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
{
- Q_Q(QDeclarativeExpression);
- Q_ASSERT(q->engine());
+ Q_ASSERT(guardObject);
+ Q_ASSERT(guardObjectNotifyIndex != -1);
- if (data->expression.isEmpty())
- return QScriptValue();
+ if (properties.count() != guardListLength) {
+ QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
+ for (int ii = 0; ii < qMin(guardListLength, properties.count()); ++ii)
+ guardList[ii].copyAndClear(newGuardList[ii]);
- QDeclarativeExpression *lastCurrentExpression = ep->currentExpression;
- bool lastCaptureProperties = ep->captureProperties;
- QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
- ep->capturedProperties.copyAndClear(lastCapturedProperties);
+ delete [] guardList;
+ guardList = newGuardList;
+ guardListLength = properties.count();
+ }
- ep->currentExpression = q;
- ep->captureProperties = data->trackChange;
+ bool outputWarningHeader = false;
+ bool noChanges = true;
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ QDeclarativeNotifierEndpoint &guard = guardList[ii];
+ const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
- // This object might be deleted during the eval
- QDeclarativeExpressionData *localData = data;
- localData->addref();
+ guard.target = guardObject;
+ guard.targetMethod = guardObjectNotifyIndex;
- QScriptValue value = eval(secondaryScope, isUndefined);
+ if (property.notifier != 0) {
- ep->currentExpression = lastCurrentExpression;
- ep->captureProperties = lastCaptureProperties;
+ if (!noChanges && guard.isConnected(property.notifier)) {
+ // Nothing to do
- // Check if we were deleted
- if (localData->q) {
- if ((!data->trackChange || !ep->capturedProperties.count()) && data->guardList) {
- clearGuards();
- } else if(data->trackChange) {
- updateGuards(ep->capturedProperties);
+ } else {
+ noChanges = false;
+
+ bool existing = false;
+ for (int jj = 0; !existing && jj < ii; ++jj)
+ if (guardList[jj].isConnected(property.notifier))
+ existing = true;
+
+ if (existing) {
+ // duplicate
+ guard.disconnect();
+ } else {
+ guard.connect(property.notifier);
+ }
+ }
+
+
+ } else if (property.notifyIndex != -1) {
+
+ if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
+ // Nothing to do
+
+ } else {
+ noChanges = false;
+
+ bool existing = false;
+ for (int jj = 0; !existing && jj < ii; ++jj)
+ if (guardList[jj].isConnected(property.object, property.notifyIndex))
+ existing = true;
+
+ if (existing) {
+ // duplicate
+ guard.disconnect();
+ } else {
+ guard.connect(property.object, property.notifyIndex);
+ }
+ }
+
+ } else {
+ if (!outputWarningHeader) {
+ outputWarningHeader = true;
+ qWarning() << "QDeclarativeExpression: Expression" << expression
+ << "depends on non-NOTIFYable properties:";
+ }
+
+ const QMetaObject *metaObj = property.object->metaObject();
+ QMetaProperty metaProp = metaObj->property(property.coreIndex);
+
+ qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
}
}
+}
- localData->release();
+QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
+{
+ if (!expressionFunctionValid) {
+ QDeclarativeEngine *engine = context()->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- lastCapturedProperties.copyAndClear(ep->capturedProperties);
+ QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return value;
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ expressionContext = ep->contextClass->newContext(context(), scopeObject);
+ scriptContext->pushScope(expressionContext);
+ scriptContext->pushScope(ep->globalClass->staticGlobalObject());
+
+ QDeclarativeRewrite::RewriteBinding rewriteBinding;
+ bool ok = true;
+ const QString code = rewriteBinding(expression, &ok);
+ if (ok)
+ expressionFunction = scriptEngine->evaluate(code, url, line);
+
+ scriptEngine->popContext();
+ expressionFunctionMode = ExplicitContext;
+ expressionFunctionValid = true;
+ }
+
+ return QDeclarativeQtScriptExpression::scriptValue(secondaryScope, isUndefined);
}
QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
{
Q_Q(QDeclarativeExpression);
- if (!data || !data->context() || !data->context()->isValid()) {
+ if (!context() || !context()->isValid()) {
qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
return QVariant();
}
@@ -504,7 +653,7 @@ value changes.
bool QDeclarativeExpression::notifyOnValueChanged() const
{
Q_D(const QDeclarativeExpression);
- return d->data->trackChange;
+ return d->notifyOnValueChange();
}
/*!
@@ -526,7 +675,7 @@ bool QDeclarativeExpression::notifyOnValueChanged() const
void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
{
Q_D(QDeclarativeExpression);
- d->data->trackChange = notifyOnChange;
+ d->setNotifyOnValueChange(notifyOnChange);
}
/*!
@@ -536,7 +685,7 @@ void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
QString QDeclarativeExpression::sourceFile() const
{
Q_D(const QDeclarativeExpression);
- return d->data->url;
+ return d->url;
}
/*!
@@ -546,7 +695,7 @@ QString QDeclarativeExpression::sourceFile() const
int QDeclarativeExpression::lineNumber() const
{
Q_D(const QDeclarativeExpression);
- return d->data->line;
+ return d->line;
}
/*!
@@ -556,8 +705,8 @@ int QDeclarativeExpression::lineNumber() const
void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
{
Q_D(QDeclarativeExpression);
- d->data->url = url;
- d->data->line = line;
+ d->url = url;
+ d->line = line;
}
/*!
@@ -569,7 +718,7 @@ void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
QObject *QDeclarativeExpression::scopeObject() const
{
Q_D(const QDeclarativeExpression);
- return d->data->me;
+ return d->scopeObject;
}
/*!
@@ -581,7 +730,7 @@ QObject *QDeclarativeExpression::scopeObject() const
bool QDeclarativeExpression::hasError() const
{
Q_D(const QDeclarativeExpression);
- return d->data->error.isValid();
+ return d->error.isValid();
}
/*!
@@ -593,7 +742,7 @@ bool QDeclarativeExpression::hasError() const
void QDeclarativeExpression::clearError()
{
Q_D(QDeclarativeExpression);
- d->data->error = QDeclarativeError();
+ d->error = QDeclarativeError();
}
/*!
@@ -606,7 +755,7 @@ void QDeclarativeExpression::clearError()
QDeclarativeError QDeclarativeExpression::error() const
{
Q_D(const QDeclarativeExpression);
- return d->data->error;
+ return d->error;
}
/*! \internal */
@@ -615,98 +764,11 @@ void QDeclarativeExpressionPrivate::_q_notify()
emitValueChanged();
}
-void QDeclarativeExpressionPrivate::clearGuards()
+void QDeclarativeQtScriptExpression::clearGuards()
{
- delete [] data->guardList;
- data->guardList = 0;
- data->guardListLength = 0;
-}
-
-void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
-{
- Q_Q(QDeclarativeExpression);
-
- static int notifyIdx = -1;
- if (notifyIdx == -1)
- notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-
- if (properties.count() != data->guardListLength) {
- QDeclarativeNotifierEndpoint *newGuardList =
- new QDeclarativeNotifierEndpoint[properties.count()];
-
- for (int ii = 0; ii < qMin(data->guardListLength, properties.count()); ++ii)
- data->guardList[ii].copyAndClear(newGuardList[ii]);
-
- delete [] data->guardList;
- data->guardList = newGuardList;
- data->guardListLength = properties.count();
- }
-
- bool outputWarningHeader = false;
- bool noChanges = true;
- for (int ii = 0; ii < properties.count(); ++ii) {
- QDeclarativeNotifierEndpoint &guard = data->guardList[ii];
- const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
-
- guard.target = q;
- guard.targetMethod = notifyIdx;
-
- if (property.notifier != 0) {
-
- if (!noChanges && guard.isConnected(property.notifier)) {
- // Nothing to do
-
- } else {
- noChanges = false;
-
- bool existing = false;
- for (int jj = 0; !existing && jj < ii; ++jj)
- if (data->guardList[jj].isConnected(property.notifier))
- existing = true;
-
- if (existing) {
- // duplicate
- guard.disconnect();
- } else {
- guard.connect(property.notifier);
- }
- }
-
-
- } else if (property.notifyIndex != -1) {
-
- if (!noChanges && guard.isConnected(property.object, property.notifyIndex)) {
- // Nothing to do
-
- } else {
- noChanges = false;
-
- bool existing = false;
- for (int jj = 0; !existing && jj < ii; ++jj)
- if (data->guardList[jj].isConnected(property.object, property.notifyIndex))
- existing = true;
-
- if (existing) {
- // duplicate
- guard.disconnect();
- } else {
- guard.connect(property.object, property.notifyIndex);
- }
- }
-
- } else {
- if (!outputWarningHeader) {
- outputWarningHeader = true;
- qWarning() << "QDeclarativeExpression: Expression" << q->expression()
- << "depends on non-NOTIFYable properties:";
- }
-
- const QMetaObject *metaObj = property.object->metaObject();
- QMetaProperty metaProp = metaObj->property(property.coreIndex);
-
- qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
- }
- }
+ delete [] guardList;
+ guardList = 0;
+ guardListLength = 0;
}
/*!
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 4ff3162..b629e20 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -107,56 +107,73 @@ private:
QDeclarativeDelayedError **prevError;
};
-class QDeclarativeExpressionData : public QDeclarativeAbstractExpression, public QDeclarativeDelayedError, public QDeclarativeRefCount
+class QDeclarativeQtScriptExpression : public QDeclarativeAbstractExpression,
+ public QDeclarativeDelayedError
{
public:
- QDeclarativeExpressionData();
- virtual ~QDeclarativeExpressionData();
+ enum Mode { SharedContext, ExplicitContext };
- QDeclarativeExpressionPrivate *q;
+ QDeclarativeQtScriptExpression();
+ virtual ~QDeclarativeQtScriptExpression();
QDeclarativeRefCount *dataRef;
+
QString expression;
- bool expressionFunctionValid:1;
- bool expressionRewritten:1;
+
+ Mode expressionFunctionMode;
QScriptValue expressionFunction;
- QScriptValue expressionContext;
- QObject *me;
- bool trackChange;
+ QScriptValue expressionContext; // Only used in ExplicitContext
+ QObject *scopeObject; // Only used in SharedContext
- bool isShared;
+ bool notifyOnValueChange() const;
+ void setNotifyOnValueChange(bool);
+ void resetNotifyOnChange();
+ void setNotifyObject(QObject *, int );
- QString url; // This is a QString for a reason. QUrls are slooooooow...
- int line;
+ QScriptValue scriptValue(QObject *secondaryScope, bool *isUndefined);
+
+ class DeleteWatcher {
+ public:
+ inline DeleteWatcher(QDeclarativeQtScriptExpression *data);
+ inline ~DeleteWatcher();
+ inline bool wasDeleted() const;
+ private:
+ bool *m_wasDeleted;
+ bool m_wasDeletedStorage;
+ QDeclarativeQtScriptExpression *m_d;
+ };
+
+private:
+ void clearGuards();
+ QScriptValue eval(QObject *secondaryScope, bool *isUndefined);
+ void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
+
+ bool trackChange;
QDeclarativeNotifierEndpoint *guardList;
int guardListLength;
+
+ QObject *guardObject;
+ int guardObjectNotifyIndex;
+ bool *deleted;
};
class QDeclarativeExpression;
class QString;
-class QDeclarativeExpressionPrivate : public QObjectPrivate
+class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeQtScriptExpression
{
Q_DECLARE_PUBLIC(QDeclarativeExpression)
public:
QDeclarativeExpressionPrivate();
- QDeclarativeExpressionPrivate(QDeclarativeExpressionData *);
~QDeclarativeExpressionPrivate();
void init(QDeclarativeContextData *, const QString &, QObject *);
void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int);
- QDeclarativeExpressionData *data;
-
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0);
- QScriptValue eval(QObject *secondaryScope, bool *isUndefined = 0);
-
- void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
- void clearGuards();
-
static QDeclarativeExpressionPrivate *get(QDeclarativeExpression *expr) {
return static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr));
}
@@ -172,8 +189,32 @@ public:
int, QScriptValue *);
static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &,
QScriptValue *);
+
+ bool expressionFunctionValid:1;
+
+ QString url; // This is a QString for a reason. QUrls are slooooooow...
+ int line;
};
+QDeclarativeQtScriptExpression::DeleteWatcher::DeleteWatcher(QDeclarativeQtScriptExpression *data)
+: m_wasDeletedStorage(false), m_d(data)
+{
+ if (!m_d->deleted)
+ m_d->deleted = &m_wasDeletedStorage;
+ m_wasDeleted = m_d->deleted;
+}
+
+QDeclarativeQtScriptExpression::DeleteWatcher::~DeleteWatcher()
+{
+ if (false == *m_wasDeleted && m_wasDeleted == m_d->deleted)
+ m_d->deleted = 0;
+}
+
+bool QDeclarativeQtScriptExpression::DeleteWatcher::wasDeleted() const
+{
+ return *m_wasDeleted;
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVEEXPRESSION_P_H
diff --git a/src/declarative/qml/qdeclarativeextensionplugin.cpp b/src/declarative/qml/qdeclarativeextensionplugin.cpp
index c2e8300..0660599 100644
--- a/src/declarative/qml/qdeclarativeextensionplugin.cpp
+++ b/src/declarative/qml/qdeclarativeextensionplugin.cpp
@@ -67,10 +67,8 @@ QT_BEGIN_NAMESPACE
See \l {Tutorial: Writing QML extensions with C++} for details on creating
QML extensions, including how to build a plugin with with QDeclarativeExtensionPlugin.
For a simple overview, see the \l{declarative/cppextensions/plugins}{plugins} example.
-
- Also see \l {How to Create Qt Plugins} for general Qt plugin documentation.
- \sa QDeclarativeEngine::importPlugin()
+ \sa QDeclarativeEngine::importPlugin(), {How to Create Qt Plugins}
*/
/*!
diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp
index f4a8588..a294c38 100644
--- a/src/declarative/qml/qdeclarativeimageprovider.cpp
+++ b/src/declarative/qml/qdeclarativeimageprovider.cpp
@@ -43,42 +43,188 @@
QT_BEGIN_NAMESPACE
+class QDeclarativeImageProviderPrivate
+{
+public:
+ QDeclarativeImageProvider::ImageType type;
+};
+
/*!
\class QDeclarativeImageProvider
\since 4.7
- \brief The QDeclarativeImageProvider class provides an interface for threaded image requests in QML.
+ \brief The QDeclarativeImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.
- QDeclarativeImageProvider can be used by a QDeclarativeEngine to provide images to QML asynchronously.
- The image request will be run in a low priority thread, allowing potentially costly image
- loading to be done in the background, without affecting the performance of the UI.
+ QDeclarativeImageProvider is used to provide advanced image loading features
+ in QML applications. It allows images in QML to be:
- See the QDeclarativeEngine::addImageProvider() documentation for an
- example of how a custom QDeclarativeImageProvider can be constructed and used.
+ \list
+ \o Loaded using QPixmaps rather than actual image files
+ \o Loaded asynchronously in a separate thread, if imageType() is \l ImageType::Image
+ \endlist
- \note the request() method may be called by multiple threads, so ensure the
- implementation of this method is reentrant.
+ To specify that an image should be loaded by an image provider, use the
+ \bold {"image:"} scheme for the URL source of the image, followed by the
+ identifiers of the image provider and the requested image. For example:
+
+ \qml
+ Image { source: "image://myimageprovider/image.png" }
+ \endqml
+
+ This specifies that the image should be loaded by the image provider named
+ "myimageprovider", and the image to be loaded is named "image.png". The QML engine
+ invokes the appropriate image provider according to the providers that have
+ been registered through QDeclarativeEngine::addImageProvider().
+
+
+ \section2 An example
+
+ Here are two images. Their \c source values indicate they should be loaded by
+ an image provider named "colors", and the images to be loaded are "yellow"
+ and "red", respectively:
+
+ \snippet examples/declarative/cppextensions/imageprovider/imageprovider-example.qml 0
+
+ When these images are loaded by QML, it looks for a matching image provider
+ and calls its requestImage() or requestPixmap() method (depending on its
+ imageType()) to load the image. The method is called with the \c id
+ parameter set to "yellow" for the first image, and "red" for the second.
+
+ Here is an image provider implementation that can load the images
+ requested by the above QML. This implementation dynamically
+ generates QPixmap images that are filled with the requested color:
+
+ \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 0
+ \codeline
+ \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 1
+
+ To make this provider accessible to QML, it is registered with the QML engine
+ with a "colors" identifier:
+
+ \code
+ int main(int argc, char *argv[])
+ {
+ ...
+
+ QDeclarativeEngine engine;
+ engine->addImageProvider(QLatin1String("colors"), new ColorPixmapProvider);
+
+ ...
+ }
+ \endcode
+
+ Now the images can be succesfully loaded in QML:
+
+ \image imageprovider.png
+
+ A complete example is available in Qt's
+ \l {declarative/cppextensions/imageprovider}{examples/declarative/cppextensions/imageprovider}
+ directory. Note the example registers the provider via a \l{QDeclarativeExtensionPlugin}{plugin}
+ instead of registering it in the application \c main() function as shown above.
+
+
+ \section2 Asynchronous image loading
+
+ Image providers that support QImage loading automatically include support
+ for asychronous loading of images. To enable asynchronous loading for an
+ \l Image source, set \l Image::asynchronous to \c true. When this is enabled,
+ the image request to the provider is run in a low priority thread,
+ allowing image loading to be executed in the background, and reducing the
+ performance impact on the user interface.
+
+ Asynchronous loading is not supported for image providers that provide
+ QPixmap rather than QImage values, as pixmaps can only be created in the
+ main thread. In this case, if \l {Image::}{asynchronous} is set to
+ \c true, the value is ignored and the image is loaded
+ synchronously.
+
+ \sa QDeclarativeEngine::addImageProvider()
+*/
+
+/*!
+ \enum QDeclarativeImageProvider::ImageType
- \sa QDeclarativeEngine::addImageProvider(), {declarative/cppextensions/imageprovider}{ImageProvider example}
+ Defines the type of image supported by this image provider.
+
+ \value Image The Image Provider provides QImage images. The
+ requestImage() method will be called for all image requests.
+ \value Pixmap The Image Provider provides QPixmap images. The
+ requestPixmap() method will be called for all image requests.
+*/
+
+/*!
+ Creates an image provider that will provide images of the given \a type.
*/
+QDeclarativeImageProvider::QDeclarativeImageProvider(ImageType type)
+ : d(new QDeclarativeImageProviderPrivate)
+{
+ d->type = type;
+}
/*!
- Destroys the image provider.
- */
+ \internal
+*/
QDeclarativeImageProvider::~QDeclarativeImageProvider()
{
+ delete d;
+}
+
+/*!
+ Returns the image type supported by this provider.
+*/
+QDeclarativeImageProvider::ImageType QDeclarativeImageProvider::imageType() const
+{
+ return d->type;
}
/*!
- \fn QImage QDeclarativeImageProvider::request(const QString &id, QSize *size, const QSize& requestedSize)
+ Implement this method to return the image with \a id. The default
+ implementation returns an empty image.
- Implement this method to return the image with \a id.
+ The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
+ an Image element. If \a requestedSize is a valid size, the image
+ returned should be of that size.
- If \a requestedSize is a valid size, the image returned should be of that size.
+ In all cases, \a size must be set to the original size of the image. This
+ is used to set the \l {Item::}{width} and \l {Item::}{height} of image
+ elements that should be automatically sized to the loaded image.
- In all cases, \a size must be set to the original size of the image.
+ \note this method may be called by multiple threads, so ensure the
+ implementation of this method is reentrant.
+*/
+QImage QDeclarativeImageProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(size);
+ Q_UNUSED(requestedSize);
+ if (d->type == Image)
+ qWarning("ImageProvider supports Image type but has not implemented requestImage()");
+ return QImage();
+}
+
+/*!
+ Implement this method to return the pixmap with \a id. The default
+ implementation returns an empty pixmap.
+
+ The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
+ an Image element. If \a requestedSize is a valid size, the image
+ returned should be of that size.
+
+ In all cases, \a size must be set to the original size of the image. This
+ is used to set the \l {Item::}{width} and \l {Item::}{height} of image
+ elements that should be automatically sized to the loaded image.
\note this method may be called by multiple threads, so ensure the
implementation of this method is reentrant.
*/
+QPixmap QDeclarativeImageProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(size);
+ Q_UNUSED(requestedSize);
+ if (d->type == Pixmap)
+ qWarning("ImageProvider supports Pixmap type but has not implemented requestPixmap()");
+ return QPixmap();
+}
QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qdeclarativeimageprovider.h b/src/declarative/qml/qdeclarativeimageprovider.h
index cc9c9af..5a72943 100644
--- a/src/declarative/qml/qdeclarativeimageprovider.h
+++ b/src/declarative/qml/qdeclarativeimageprovider.h
@@ -43,6 +43,7 @@
#define QDECLARATIVEIMAGEPROVIDER_H
#include <QtGui/qimage.h>
+#include <QtGui/qpixmap.h>
QT_BEGIN_HEADER
@@ -50,11 +51,26 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
+class QDeclarativeImageProviderPrivate;
+
class Q_DECLARATIVE_EXPORT QDeclarativeImageProvider
{
public:
+ enum ImageType {
+ Image,
+ Pixmap
+ };
+
+ QDeclarativeImageProvider(ImageType type);
virtual ~QDeclarativeImageProvider();
- virtual QImage request(const QString &id, QSize *size, const QSize& requestedSize) = 0;
+
+ ImageType imageType() const;
+
+ virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
+ virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize);
+
+private:
+ QDeclarativeImageProviderPrivate *d;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index a2e3831..8d81b34 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -409,7 +409,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
if (!localFileOrQrc.isEmpty()) {
QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
- if (dir.isEmpty() || !QDir().exists(dir)) {
+ QFileInfo dirinfo(dir);
+ if (dir.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
if (errorString)
*errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg);
return false; // local import dirs must exist
@@ -425,7 +426,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (prefix.isEmpty()) {
// directory must at least exist for valid import
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
- if (localFileOrQrc.isEmpty() || !QDir().exists(localFileOrQrc)) {
+ QFileInfo dirinfo(localFileOrQrc);
+ if (localFileOrQrc.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
if (errorString) {
if (localFileOrQrc.isEmpty())
*errorString = QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri);
@@ -445,11 +447,23 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) {
QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin();
+ int lowest_maj = INT_MAX;
+ int lowest_min = INT_MAX;
+ int highest_maj = INT_MIN;
+ int highest_min = INT_MIN;
for (; it != qmldircomponents.end(); ++it) {
- if (it->majorVersion > vmaj || (it->majorVersion == vmaj && it->minorVersion >= vmin))
- break;
+ if (it->majorVersion > highest_maj || (it->majorVersion == highest_maj && it->minorVersion > highest_min)) {
+ highest_maj = it->majorVersion;
+ highest_min = it->minorVersion;
+ }
+ if (it->majorVersion < lowest_maj || (it->majorVersion == lowest_maj && it->minorVersion < lowest_min)) {
+ lowest_maj = it->majorVersion;
+ lowest_min = it->minorVersion;
+ }
}
- if (it == qmldircomponents.end()) {
+ if (lowest_maj > vmaj || (lowest_maj == vmaj && lowest_min > vmin)
+ || highest_maj < vmaj || (highest_maj == vmaj && highest_min < vmin))
+ {
*errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin);
return false;
}
diff --git a/src/declarative/qml/qdeclarativelist.cpp b/src/declarative/qml/qdeclarativelist.cpp
index 7c89672..9598d98 100644
--- a/src/declarative/qml/qdeclarativelist.cpp
+++ b/src/declarative/qml/qdeclarativelist.cpp
@@ -306,7 +306,7 @@ int QDeclarativeListReference::count() const
/*!
\class QDeclarativeListProperty
\since 4.7
-\brief The QDeclarativeListProperty class allows applications to explose list-like
+\brief The QDeclarativeListProperty class allows applications to expose list-like
properties to QML.
QML has many list properties, where more than one object value can be assigned.
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index c32cab6..153e2be 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -1152,7 +1152,7 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
*static_cast<float *>(data) = float(0);
return true;
case QMetaType::Double:
- *static_cast<double *>(data) = double();
+ *static_cast<double *>(data) = double(0);
return true;
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = NS(QChar)();
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 7aea7cb..689ed92 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -751,6 +751,22 @@ void QDeclarativeVMEMetaObject::registerInterceptor(int index, int valueIndex, Q
interceptors.insert(index, qMakePair(valueIndex, interceptor));
}
+int QDeclarativeVMEMetaObject::vmeMethodLineNumber(int index)
+{
+ if (index < methodOffset) {
+ Q_ASSERT(parent);
+ return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeMethodLineNumber(index);
+ }
+
+ int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
+ Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+
+ int rawIndex = index - methodOffset - plainSignals;
+
+ QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
+ return data->lineNumber;
+}
+
QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
{
if (index < methodOffset) {
@@ -762,6 +778,20 @@ QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
return method(index - methodOffset - plainSignals);
}
+void QDeclarativeVMEMetaObject::setVmeMethod(int index, const QScriptValue &value)
+{
+ if (index < methodOffset) {
+ Q_ASSERT(parent);
+ return static_cast<QDeclarativeVMEMetaObject *>(parent)->setVmeMethod(index, value);
+ }
+ int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
+ Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+
+ if (!methods)
+ methods = new QScriptValue[metaData->methodCount];
+ methods[index - methodOffset - plainSignals] = value;
+}
+
QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
{
if (index < propOffset) {
diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h
index 4fc3269..20ca80b 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject_p.h
+++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h
@@ -121,6 +121,8 @@ public:
void registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor);
QScriptValue vmeMethod(int index);
+ int vmeMethodLineNumber(int index);
+ void setVmeMethod(int index, const QScriptValue &);
QScriptValue vmeProperty(int index);
void setVMEProperty(int index, const QScriptValue &);