diff options
Diffstat (limited to 'src/declarative')
20 files changed, 514 insertions, 173 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index c81c2d2..32a6321 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -45,7 +45,7 @@ #ifndef QT_NO_MOVIE #include <qdeclarativeinfo.h> -#include <qdeclarativeengine.h> +#include <private/qdeclarativeengine_p.h> #include <QMovie> #include <QNetworkRequest> @@ -180,14 +180,6 @@ int QDeclarativeAnimatedImage::frameCount() const return d->_movie->frameCount(); } -static QString toLocalFileOrQrc(const QUrl& url) -{ - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; -} - void QDeclarativeAnimatedImage::setSource(const QUrl &url) { Q_D(QDeclarativeAnimatedImage); @@ -209,7 +201,7 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) d->status = Null; } else { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = toLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); if (!lf.isEmpty()) { //### should be unified with movieRequestFinished d->_movie = new QMovie(lf); diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 229e15b..1f1e453 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -42,8 +42,8 @@ #include "private/qdeclarativeborderimage_p.h" #include "private/qdeclarativeborderimage_p_p.h" -#include <qdeclarativeengine.h> #include <qdeclarativeinfo.h> +#include <private/qdeclarativeengine_p.h> #include <QNetworkRequest> #include <QNetworkReply> @@ -152,16 +152,6 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() The URL may be absolute, or relative to the URL of the component. */ - -static QString toLocalFileOrQrc(const QUrl& url) -{ - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; -} - - void QDeclarativeBorderImage::setSource(const QUrl &url) { Q_D(QDeclarativeBorderImage); @@ -210,7 +200,7 @@ void QDeclarativeBorderImage::load() d->status = Loading; if (d->url.path().endsWith(QLatin1String("sci"))) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = toLocalFileOrQrc(d->url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { QFile file(lf); file.open(QIODevice::ReadOnly); diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 9547884..2841ac3 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -2681,7 +2681,13 @@ bool QDeclarativeItem::sceneEvent(QEvent *event) } } -/*! \internal */ +/*! + \reimp + + Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is \e not called + during initial widget polishing. Items wishing to optimize start-up construction + should instead consider using componentComplete(). +*/ QVariant QDeclarativeItem::itemChange(GraphicsItemChange change, const QVariant &value) { diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 40d37a2..7b00d2f 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -523,7 +523,7 @@ void QDeclarativeTextEdit::setCursorVisible(bool on) QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut); if (!on && !d->persistentSelection) d->control->setCursorIsFocusIndicator(true); - d->control->processEvent(&focusEvent, QPointF(0, 0)); + d->control->processEvent(&focusEvent, QPointF(0, -d->yoff)); emit cursorVisibleChanged(d->cursorVisible); } @@ -860,7 +860,7 @@ Qt::TextInteractionFlags QDeclarativeTextEdit::textInteractionFlags() const QRect QDeclarativeTextEdit::cursorRect() const { Q_D(const QDeclarativeTextEdit); - return d->control->cursorRect().toRect(); + return d->control->cursorRect().toRect().translated(0,-d->yoff); } @@ -872,7 +872,7 @@ bool QDeclarativeTextEdit::event(QEvent *event) { Q_D(QDeclarativeTextEdit); if (event->type() == QEvent::ShortcutOverride) { - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); return event->isAccepted(); } return QDeclarativePaintedItem::event(event); @@ -887,7 +887,7 @@ void QDeclarativeTextEdit::keyPressEvent(QKeyEvent *event) Q_D(QDeclarativeTextEdit); keyPressPreHandler(event); if (!event->isAccepted()) - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::keyPressEvent(event); } @@ -901,7 +901,7 @@ void QDeclarativeTextEdit::keyReleaseEvent(QKeyEvent *event) Q_D(QDeclarativeTextEdit); keyReleasePreHandler(event); if (!event->isAccepted()) - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::keyReleaseEvent(event); } @@ -942,7 +942,7 @@ void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) if (!hadFocus && hasFocus()) d->clickCausedFocus = true; if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse) - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mousePressEvent(event); } @@ -959,7 +959,7 @@ void QDeclarativeTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); d->clickCausedFocus = false; - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mouseReleaseEvent(event); } @@ -972,7 +972,7 @@ void QDeclarativeTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event { Q_D(QDeclarativeTextEdit); if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mouseDoubleClickEvent(event); } else { @@ -988,7 +988,7 @@ void QDeclarativeTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mouseMoveEvent(event); event->setAccepted(true); @@ -1004,7 +1004,7 @@ Handles the given input method \a event. void QDeclarativeTextEdit::inputMethodEvent(QInputMethodEvent *event) { Q_D(QDeclarativeTextEdit); - d->control->processEvent(event, QPointF(0, 0)); + d->control->processEvent(event, QPointF(0, -d->yoff)); } /*! @@ -1026,13 +1026,20 @@ void QDeclarativeTextEdit::drawContents(QPainter *painter, const QRect &bounds) Q_D(QDeclarativeTextEdit); painter->setRenderHint(QPainter::TextAntialiasing, true); + painter->translate(0,d->yoff); - d->control->drawContents(painter, bounds); + d->control->drawContents(painter, bounds.translated(0,-d->yoff)); + + painter->translate(0,-d->yoff); } -void QDeclarativeTextEdit::updateImgCache(const QRectF &r) +void QDeclarativeTextEdit::updateImgCache(const QRectF &rf) { - dirtyCache(r.toRect()); + Q_D(const QDeclarativeTextEdit); + QRect r = rf.toRect(); + if (r != QRect(0,0,INT_MAX,INT_MAX)) // Don't translate "everything" + r = r.translated(0,d->yoff); + dirtyCache(r); emit update(); } @@ -1141,18 +1148,20 @@ void QDeclarativeTextEdit::updateSize() d->document->setTextWidth(width()); dy -= (int)d->document->size().height(); - int yoff = 0; if (heightValid()) { if (d->vAlign == AlignBottom) - yoff = dy; + d->yoff = dy; else if (d->vAlign == AlignVCenter) - yoff = dy/2; + d->yoff = dy/2; + } else { + d->yoff = 0; } - setBaselineOffset(fm.ascent() + yoff + d->textMargin); + setBaselineOffset(fm.ascent() + d->yoff + d->textMargin); //### need to comfirm cost of always setting these int newWidth = qCeil(d->document->idealWidth()); - d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set. Does Text need this line as well? + if (!widthValid()) + d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug) int cursorWidth = 1; if(d->cursor) cursorWidth = d->cursor->width(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 885620d..d96796c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -73,7 +73,8 @@ public: persistentSelection(true), clickCausedFocus(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap), - selectByMouse(false) + selectByMouse(false), + yoff(0) { } @@ -112,6 +113,7 @@ public: QTextControl *control; QDeclarativeTextEdit::WrapMode wrapMode; bool selectByMouse; + int yoff; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 8230941..882e981 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -191,7 +191,9 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) 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()))); + data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + + QLatin1String(QMetaType::typeName(data->property.propertyType())) + + QLatin1String(" ") + data->property.name()); } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) { @@ -353,8 +355,6 @@ void QDeclarativeAbstractBinding::removeFromObject() if (m_prevBinding) { int index = propertyIndex(); - Q_ASSERT(m_object); - *m_prevBinding = m_nextBinding; if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; m_prevBinding = 0; @@ -363,7 +363,7 @@ void QDeclarativeAbstractBinding::removeFromObject() if (index & 0xFF000000) { // Value type - we don't remove the proxy from the object. It will sit their happily // doing nothing for ever more. - } else { + } else if (m_object) { QDeclarativeData *data = QDeclarativeData::get(m_object, false); if (data) data->clearBindingBit(index); } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b5bf972..d27aced 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1089,6 +1089,23 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) fetch.line = prop->location.start.line; output->bytecode << fetch; + if (!prop->value->metadata.isEmpty()) { + QDeclarativeInstruction meta; + meta.type = QDeclarativeInstruction::StoreMetaObject; + meta.line = 0; + meta.storeMeta.data = output->indexForByteArray(prop->value->metadata); + meta.storeMeta.aliasData = output->indexForByteArray(prop->value->synthdata); + meta.storeMeta.propertyCache = output->propertyCaches.count(); + // ### Surely the creation of this property cache could be more efficient + QDeclarativePropertyCache *propertyCache = + enginePrivate->cache(prop->value->metaObject()->superClass())->copy(); + propertyCache->append(engine, prop->value->metaObject(), QDeclarativePropertyCache::Data::NoFlags, + QDeclarativePropertyCache::Data::IsVMEFunction); + + output->propertyCaches << propertyCache; + output->bytecode << meta; + } + genObjectBody(prop->value); QDeclarativeInstruction pop; diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 3f11425..7aa17e8 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -549,15 +549,19 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q Returns an object instance from this component, or null if object creation fails. The object will be created in the same context as the one in which the component - was created. + was created. This function will always return null when called on components + which were not created in QML. Note that if the returned object is to be displayed, its \c parent must be set to - an existing item in a scene, or else the object will not be visible. + an existing item in a scene, or else the object will not be visible. The parent + argument is required to help you avoid this, you must explicitly pass in null if + you wish to create an object without setting a parent. */ /*! \internal - A version of create which returns a scriptObject, for use in script + A version of create which returns a scriptObject, for use in script. + This function will only work on components created in QML. Sets graphics object parent because forgetting to do this is a frequent and serious problem. @@ -576,10 +580,12 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent) bool needParent = (gobj != 0); if(parent){ ret->setParent(parent); - QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parent); - if(gparent){ - gobj->setParentItem(gparent); - needParent = false; + if (gobj) { + QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parent); + if(gparent){ + gobj->setParentItem(gparent); + needParent = false; + } } } if(needParent) diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp index e4405f7..26b2a9b 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp @@ -334,23 +334,11 @@ void QDeclarativeCompositeTypeManager::resourceReplyFinished() reply->deleteLater(); } -// XXX this beyonds in QUrl::toLocalFile() -// WARNING, there is a copy of this function in qdeclarativeengine.cpp -static QString toLocalFileOrQrc(const QUrl& url) -{ - if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { - if (url.authority().isEmpty()) - return QLatin1Char(':') + url.path(); - return QString(); - } - return url.toLocalFile(); -} - void QDeclarativeCompositeTypeManager::loadResource(QDeclarativeCompositeTypeResource *resource) { QUrl url(resource->url); - QString lf = toLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); if (!lf.isEmpty()) { QFile file(lf); @@ -378,7 +366,7 @@ void QDeclarativeCompositeTypeManager::loadSource(QDeclarativeCompositeTypeData { QUrl url(unit->imports.baseUrl()); - QString lf = toLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); if (!lf.isEmpty()) { QFile file(lf); @@ -716,7 +704,7 @@ void QDeclarativeCompositeTypeManager::compile(QDeclarativeCompositeTypeData *un foreach (QDeclarativeScriptParser::Import imp, unit->data.imports()) { if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))); - if (toLocalFileOrQrc(importUrl).isEmpty()) { + if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { // Import requires remote qmldir resourceList.prepend(importUrl); } @@ -726,7 +714,7 @@ void QDeclarativeCompositeTypeManager::compile(QDeclarativeCompositeTypeData *un QUrl importUrl; if (!unit->imports.baseUrl().scheme().isEmpty()) importUrl = unit->imports.baseUrl().resolved(QUrl(QLatin1String("qmldir"))); - if (!importUrl.scheme().isEmpty() && toLocalFileOrQrc(importUrl).isEmpty()) + if (!importUrl.scheme().isEmpty() && QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) resourceList.prepend(importUrl); for (int ii = 0; ii < resourceList.count(); ++ii) { diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 0a75532..a7384a9 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -151,6 +151,61 @@ void QDeclarativeEnginePrivate::defineModule() qmlRegisterType<QDeclarativeBinding>(); } +/*! +\qmlclass Qt QDeclarativeEnginePrivate +\brief The QML Global Qt Object + +The Qt object provides useful enums and functions from Qt, for use in all QML +files. Note that you do note create instances of this type, but instead use +the members of the global "Qt" object. + +\section1 Enums + +The Qt object contains all enums in the Qt namespace. For example, you can +access the AlignLeft member of the Qt::AlignmentFlag enum with \c Qt.AlignLeft. + +For a full list of enums, see the \l{Qt Namespace} documentation. + +\section1 Types +The Qt object also contains helper functions for creating objects of specific +data types. This is primarily useful when setting the properties of an item +when the property has one of the following types: + +\list +\o Color +\o Rect +\o Point +\o Size +\o Vector3D +\endlist + +There are also string based constructors for these types, see \l{qdeclarativebasictypes.html}{Qml Types}. + +\section1 Date/Time Formatters + +The Qt object contains several functions for formatting dates and times. + +\list + \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format) + \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format) + \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format) +\endlist + +The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}. + + +\section1 Dynamic Object Creation +The following functions on the global object allow you to dynamically create QML +items from files or strings. See \l{Dynamic Object Management} for an overview +of their use. + +\list + \o \l{Qt::createComponent}{object Qt.createComponent(url)} + \o \l{Qt::createQmlObject}{object Qt.createQmlObject(string qml, object parent, string filepath)} +\endlist +*/ + + QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) : captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false), outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0), @@ -169,6 +224,11 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine); } +/*! +\qmlmethod url Qt::resolvedUrl(url) +This function returns \c url resolved relative to the URL of the +caller. +*/ QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url) { if (p) { @@ -216,7 +276,7 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4)); qtObject.setProperty(QLatin1String("point"), newFunction(QDeclarativeEnginePrivate::point, 2)); qtObject.setProperty(QLatin1String("size"), newFunction(QDeclarativeEnginePrivate::size, 2)); - qtObject.setProperty(QLatin1String("vector3d"), newFunction(QDeclarativeEnginePrivate::vector, 3)); + qtObject.setProperty(QLatin1String("vector3d"), newFunction(QDeclarativeEnginePrivate::vector3d, 3)); if (mainthread) { //color helpers @@ -961,6 +1021,47 @@ QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *c return contextClass->contextFromValue(scopeNode); } + +QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url) +{ + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + return QString(); + } + return url.toLocalFile(); +} + +/*! +\qmlmethod object Qt::createComponent(url) + +This function takes the URL of a QML file as its only argument. It returns +a component object which can be used to create and load that QML file. + +Here is an example. Remember that QML files that might be loaded +over the network cannot be expected to be ready immediately. + +\snippet doc/src/snippets/declarative/componentCreation.js 0 +\codeline +\snippet doc/src/snippets/declarative/componentCreation.js 1 + +If you are certain the files will be local, you could simplify to: + +\snippet doc/src/snippets/declarative/componentCreation.js 2 + +The methods and properties of the \l {Component} element are defined in its own +page, but when using it dynamically only two methods are usually used. + \l {Component::createObject()}{Component.createObject()} returns the created object or \c null if there is an error. +If there is an error, \l {Component::errorString()}{Component.errorString()} describes +the error that occurred. Note that createObject() takes exactly one argument, which is set +to the parent of the created object. Graphical objects without a parent will not appear +on the scene, but if you do not wish to parent the item at this point you can safely pass +in null. + +If you want to just create an arbitrary string of QML, instead of +loading a QML file, consider the \l{Qt.createQmlObject(string qml, object parent, string filepath)}{Qt.createQmlObject()} function. +*/ + QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine) { QDeclarativeEnginePrivate *activeEnginePriv = @@ -984,6 +1085,34 @@ QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QS } } +/*! +\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath) + +Creates a new object from the specified string of QML. It requires a +second argument, which is the id of an existing QML object to use as +the new object's parent. If a third argument is provided, this is used +for error reporting as the filepath that the QML came from. + +Example (where \c targetItem is the id of an existing QML item): + +\snippet doc/src/snippets/declarative/createQmlObject.qml 0 + +This function is intended for use inside QML only. It is intended to behave +similarly to eval, but for creating QML elements. + +Returns the created object, \c or null if there is an error. In the case of an +error, a QtScript Error object is thrown. This object has the additional property, +qmlErrors, which is an array of all the errors encountered when trying to execute the +QML. Each object in the array has the members \c lineNumber, \c columnNumber, \c fileName and \c message. + +Note that this function returns immediately, and therefore may not work if +the QML loads new components. If you are trying to load a new component, +for example from a QML file, consider the \l{Qt.createComponent(url file)}{Qt.createComponent()} function +instead. 'New components' refers to external QML files that have not yet +been loaded, and so it is safe to use \c Qt.createQmlObject() to load built-in +components. +*/ + QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine) { QDeclarativeEnginePrivate *activeEnginePriv = @@ -1074,6 +1203,10 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar); } +/*! +\qmlmethod bool Qt::isQtObject(object) +Returns true if \c object is a valid reference to a Qt or QML object, otherwise false. +*/ QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine) { if (ctxt->argumentCount() == 0) @@ -1082,7 +1215,11 @@ QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScript return QScriptValue(engine, 0 != ctxt->argument(0).toQObject()); } -QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) +/*! +\qmlmethod Qt::vector3d(real x, real y, real z) +This function returns a Vector3D with the specified \c x, \c y and \c z. +*/ +QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 3) return ctxt->throwError(QLatin1String("Qt.vector(): Invalid arguments")); @@ -1092,6 +1229,10 @@ QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngi return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QVector3D(x, y, z))); } +/*! +\qmlmethod string Qt::formatDate(datetime date, variant format) +This function returns the string representation of \c date, formatted according to \c format. +*/ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine) { int argCount = ctxt->argumentCount(); @@ -1113,6 +1254,12 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } +/*! +\qmlmethod string Qt::formatTime(datetime time, variant format) +This function returns the string representation of \c time, formatted according to \c format. + +See Qt::formatDateTime for how to define \c format. +*/ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine) { int argCount = ctxt->argumentCount(); @@ -1134,6 +1281,75 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } +/*! +\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format) +This function returns the string representation of \c dateTime, formatted according to \c format. + +\c format for the date/time formatting functions is be specified as follows. + + These expressions may be used for the date: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1 to 31) + \row \i dd \i the day as number with a leading zero (01 to 31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number + \endtable + + These expressions may be used for the time: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. Any sequence of characters that + are enclosed in singlequotes will be treated as text and not be used as an + expression. Two consecutive singlequotes ("''") are replaced by a singlequote + in the output. + + Example format strings (assumed that the date and time is 21 May 2001 + 14:13:09): + + \table + \header \i Format \i Result + \row \i dd.MM.yyyy \i 21.05.2001 + \row \i ddd MMMM d yy \i Tue May 21 01 + \row \i hh:mm:ss.zzz \i 14:13:09.042 + \row \i h:m:s ap \i 2:13:9 pm + \endtable + +If no format is specified the locale's short format is used. Alternatively, you can specify +\c Qt.DefaultLocaleLongDate to get the locale's long format. +*/ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine) { int argCount = ctxt->argumentCount(); @@ -1155,6 +1371,12 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } +/*! +\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha) + +This function returns a Color with the specified \c red, \c green, \c blue and \c alpha components. +All components should be in the range 0-1 inclusive. +*/ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine) { int argCount = ctxt->argumentCount(); @@ -1177,6 +1399,12 @@ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a))); } +/*! +\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha) + +This function returns a Color with the specified \c hue, \c saturation, \c lightness and \c alpha components. +All components should be in the range 0-1 inclusive. +*/ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine) { int argCount = ctxt->argumentCount(); @@ -1199,6 +1427,11 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a))); } +/*! +\qmlmethod rect Qt::rect(int x, int y, int width, int height) + +This function returns a Rect with the top-left corner at \c x, \c y and the specified \c width and \c height. +*/ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 4) @@ -1215,6 +1448,10 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QRectF(x, y, w, h))); } +/*! +\qmlmethod point Qt::point(int x, int y) +This function returns a Point with the specified \c x and \c y coordinates. +*/ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) @@ -1224,6 +1461,10 @@ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngin return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QPointF(x, y))); } +/*! +\qmlmethod Qt::size(int width, int height) +This function returns as Size with the specified \c width and \c height. +*/ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) @@ -1233,6 +1474,20 @@ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QSizeF(w, h))); } +/*! +\qmlmethod color Qt::lighter(color baseColor, real factor) +This function returns a color lighter than \c baseColor by the \c factor provided. + +If the factor is greater than 1.0, this functions returns a lighter color. +Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0, +the return color is darker, but we recommend using the Qt.darker() function for this purpose. +If the factor is 0 or negative, the return value is unspecified. + +The function converts the current RGB color to HSV, multiplies the value (V) component +by factor and converts the color back to RGB. + +If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5). +*/ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2) @@ -1255,6 +1510,21 @@ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEng return qScriptValueFromValue(engine, qVariantFromValue(color)); } +/*! +\qmlmethod color Qt::darker(color baseColor, real factor) +This function returns a color darker than \c baseColor by the \c factor provided. + +If the factor is greater than 1.0, this function returns a darker color. +Setting factor to 3.0 returns a color that has one-third the brightness. +If the factor is less than 1.0, the return color is lighter, but we recommend using +the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return +value is unspecified. + +The function converts the current RGB color to HSV, divides the value (V) component +by factor and converts the color back to RGB. + +If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0). +*/ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2) @@ -1277,6 +1547,10 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi return qScriptValueFromValue(engine, qVariantFromValue(color)); } +/*! +\qmlmethod bool Qt::openUrlExternally(url target) +This function attempts to open the specified \c target url in an external application, based on the user's desktop preferences. It will return true if it succeeds, and false otherwise. +*/ QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e) { if(ctxt->argumentCount() < 1) @@ -1288,6 +1562,11 @@ QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QSc return QScriptValue(e, ret); } +/*! +\qmlmethod list<string> Qt::fontFamilies() +This function returns a list of the font families available to the application. +*/ + QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e) { if(ctxt->argumentCount() != 0) @@ -1298,6 +1577,10 @@ QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScri return p->scriptValueFromVariant(database.families()); } +/*! +\qmlmethod string Qt::md5(data) +This function returns a hex string of the md5 hash of \c data. +*/ QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *) { if (ctxt->argumentCount() != 1) @@ -1309,6 +1592,10 @@ QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine return QScriptValue(QLatin1String(result.toHex())); } +/*! +\qmlmethod string Qt::btoa(data) +Binary to ASCII - this function returns a base64 encoding of \c data. +*/ QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *) { if (ctxt->argumentCount() != 1) @@ -1319,6 +1606,11 @@ QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine return QScriptValue(QLatin1String(data.toBase64())); } +/*! +\qmlmethod string Qt::atob(data) +ASCII to binary - this function returns a base64 decoding of \c data. +*/ + QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *) { if (ctxt->argumentCount() != 1) @@ -1413,6 +1705,13 @@ void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const dumpwarning(error); } +/*! +\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. +*/ + QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e) { QDeclarativeEnginePrivate *qe = get (e); @@ -1420,6 +1719,20 @@ QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptE return QScriptValue(); } +/*! +\qmlmethod color Qt::tint(color baseColor, color tintColor) + This function allows tinting one color with another. + + The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque. + + \qml + Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" } + Rectangle { x: 100; width: 80; height: 80; color: Qt.tint("lightsteelblue", "#10FF0000") } + \endqml + \image declarative-rect_tint.png + + Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color. +*/ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 0b1c17d..804476c 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -283,7 +283,7 @@ public: static QScriptValue createComponent(QScriptContext*, QScriptEngine*); static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*); static QScriptValue isQtObject(QScriptContext*, QScriptEngine*); - static QScriptValue vector(QScriptContext*, QScriptEngine*); + static QScriptValue vector3d(QScriptContext*, QScriptEngine*); static QScriptValue rgba(QScriptContext*, QScriptEngine*); static QScriptValue hsla(QScriptContext*, QScriptEngine*); static QScriptValue point(QScriptContext*, QScriptEngine*); @@ -315,6 +315,8 @@ public: static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p) { return p->q_func(); } QDeclarativeContextData *getContext(QScriptContext *); + static QString urlToLocalFileOrQrc(const QUrl& url); + static void defineModule(); }; diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 0c87671..c658a31 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -49,22 +49,13 @@ #include <QtDeclarative/qdeclarativeextensioninterface.h> #include <private/qdeclarativeglobal_p.h> #include <private/qdeclarativetypenamecache_p.h> +#include <private/qdeclarativeengine_p.h> QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE) DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES) -static QString toLocalFileOrQrc(const QUrl& url) -{ - if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { - if (url.authority().isEmpty()) - return QLatin1Char(':') + url.path(); - return QString(); - } - return url.toLocalFile(); -} - static bool greaterThan(const QString &s1, const QString &s2) { return s1 > s2; @@ -262,7 +253,7 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i if (!typeWasDeclaredInQmldir && !isLibrary.at(i)) { // XXX search non-files too! (eg. zip files, see QT-524) - QFileInfo f(toLocalFileOrQrc(url)); + QFileInfo f(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)); if (f.exists()) { if (base && *base == url) { // no recursion if (typeRecursionDetected) @@ -415,15 +406,15 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) { QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir"))); - QString localFileOrQrc = toLocalFileOrQrc(importUrl); + QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl); if (!localFileOrQrc.isEmpty()) { - QString dir = toLocalFileOrQrc(base.resolved(QUrl(uri))); + QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); if (dir.isEmpty() || !QDir().exists(dir)) { if (errorString) *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg); return false; // local import dirs must exist } - uri = resolvedUri(toLocalFileOrQrc(base.resolved(QUrl(uri))), database); + uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database); if (uri.endsWith(QLatin1Char('/'))) uri.chop(1); if (QFile::exists(localFileOrQrc)) { @@ -433,7 +424,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } else { if (prefix.isEmpty()) { // directory must at least exist for valid import - QString localFileOrQrc = toLocalFileOrQrc(base.resolved(QUrl(uri))); + QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); if (localFileOrQrc.isEmpty() || !QDir().exists(localFileOrQrc)) { if (errorString) { if (localFileOrQrc.isEmpty()) diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp index 4cde54b..388f252 100644 --- a/src/declarative/qml/qdeclarativeinclude.cpp +++ b/src/declarative/qml/qdeclarativeinclude.cpp @@ -172,16 +172,6 @@ void QDeclarativeInclude::callback(QScriptEngine *engine, QScriptValue &callback } } -static QString toLocalFileOrQrc(const QUrl& url) -{ - if (url.scheme() == QLatin1String("qrc")) { - if (url.authority().isEmpty()) - return QLatin1Char(':') + url.path(); - return QString(); - } - return url.toLocalFile(); -} - QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine) { if (ctxt->argumentCount() == 0) @@ -200,7 +190,7 @@ QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *e urlString = url.toString(); } - QString localFile = toLocalFileOrQrc(url); + QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); QScriptValue func = ctxt->argument(1); if (!func.isFunction()) @@ -269,7 +259,7 @@ QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEn urlString = url.toString(); } - QString localFile = toLocalFileOrQrc(url); + QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); QScriptValue func = ctxt->argument(1); if (!func.isFunction()) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 8b64e0e..aca01b2 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -623,7 +623,7 @@ private: inline void cleanup(); - void *data[4]; + char data[4 * sizeof(void *)]; int type; }; } diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 13e9c26..7aea7cb 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -381,7 +381,7 @@ QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj, const QMetaObject *other, const QDeclarativeVMEMetaData *meta, QDeclarativeCompiledData *cdata) -: object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj)->outerContext), +: object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj, true)->outerContext), metaData(meta), data(0), methods(0), parent(0) { compiledData->addref(); diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 8182998..1550351 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -189,7 +189,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ct if (!script) return engine->undefinedValue(); - if (ctxt->argumentCount() >= 1) + if (ctxt->argumentCount() >= 1) script->callback = ctxt->argument(0); return script->callback; @@ -277,10 +277,10 @@ void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVarian void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) { - if (url.isRelative() || url.scheme() != QLatin1String("file")) + if (url.isRelative()) return; - QString fileName = url.toLocalFile(); + QString fileName = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); QFile f(fileName); if (f.open(QIODevice::ReadOnly)) { diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index adfcd62..c73f827 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -53,6 +53,7 @@ #include <QFontDatabase> #include <private/qobject_p.h> +#include <private/qdeclarativeengine_p.h> #include <qdeclarativeinfo.h> QT_BEGIN_NAMESPACE @@ -98,15 +99,6 @@ QDeclarativeFontLoader::~QDeclarativeFontLoader() { } -static QString toLocalFileOrQrc(const QUrl& url) -{ - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; -} - - /*! \qmlproperty url FontLoader::source The url of the font to load. @@ -127,7 +119,7 @@ void QDeclarativeFontLoader::setSource(const QUrl &url) d->status = Loading; emit statusChanged(); #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = toLocalFileOrQrc(d->url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { int id = QFontDatabase::addApplicationFont(lf); if (id != -1) { diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index d9ce42c..a4ddf46 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -66,14 +66,6 @@ static const int maxImageRequestCount = 8; QT_BEGIN_NAMESPACE -static QString toLocalFileOrQrc(const QUrl& url) -{ - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; -} - class QDeclarativeImageReaderEvent : public QEvent { public: @@ -269,7 +261,7 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event) } QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image)); } else { - QString lf = toLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); if (!lf.isEmpty()) { // Image is local - load/decode immediately QImage image; @@ -613,7 +605,7 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML if (!async) { - QString lf = toLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); if (!lf.isEmpty()) { status = QDeclarativePixmapReply::Ready; if (!QPixmapCache::find(strKey,pixmap)) { diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index cae1d3a..d08e37b 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -42,7 +42,7 @@ #include "private/qdeclarativexmllistmodel_p.h" #include <qdeclarativecontext.h> -#include <qdeclarativeengine.h> +#include <qdeclarativeengine_p.h> #include <QDebug> #include <QStringList> @@ -83,12 +83,14 @@ typedef QPair<int, int> QDeclarativeXmlListRange; The name for the role. This name is used to access the model data for this role from Qml. \qml - XmlRole { name: "title"; query: "title/string()" } - - ... + XmlListModel { + id: xmlModel + ... + XmlRole { name: "title"; query: "title/string()" } + } - Component { - id: myDelegate + ListView { + model: xmlModel Text { text: title } } \endqml @@ -122,11 +124,11 @@ struct XmlQueryJob QString query; QString namespaces; QStringList roleQueries; + QList<void*> roleQueryErrorId; // the ptr to send back if there is an error QStringList keyRoleQueries; QStringList keyRoleResultsCache; }; - class QDeclarativeXmlQuery : public QThread { Q_OBJECT @@ -166,6 +168,7 @@ public: continue; } job.roleQueries << roleObjects->at(i)->query(); + job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i)); if (roleObjects->at(i)->isKey()) job.keyRoleQueries << job.roleQueries.last(); } @@ -181,6 +184,7 @@ public: Q_SIGNALS: void queryCompleted(const QDeclarativeXmlQueryResult &); + void error(void*, const QString&); protected: void run() { @@ -346,26 +350,24 @@ void QDeclarativeXmlQuery::doSubQueryJob() } job.keyRoleResultsCache = keyRoleResults; - // Get the new values for each role. //### we might be able to condense even further (query for everything in one go) const QStringList &queries = job.roleQueries; for (int i = 0; i < queries.size(); ++i) { - if (queries[i].isEmpty()) { - QList<QVariant> resultList; - for (int j = 0; j < m_size; ++j) - resultList << QVariant(); - m_modelData << resultList; - continue; - } - subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); - QXmlResultItems resultItems; - subquery.evaluateTo(&resultItems); - QXmlItem item(resultItems.next()); QList<QVariant> resultList; - while (!item.isNull()) { - resultList << item.toAtomicValue(); //### we used to trim strings - item = resultItems.next(); + if (!queries[i].isEmpty()) { + subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); + if (subquery.isValid()) { + QXmlResultItems resultItems; + subquery.evaluateTo(&resultItems); + QXmlItem item(resultItems.next()); + while (!item.isNull()) { + resultList << item.toAtomicValue(); //### we used to trim strings + item = resultItems.next(); + } + } else { + emit error(job.roleQueryErrorId.at(i), queries[i]); + } } //### should warn here if things have gone wrong. while (resultList.count() < m_size) @@ -412,6 +414,16 @@ public: , reply(0), status(QDeclarativeXmlListModel::Null), progress(0.0) , queryId(-1), roleObjects(), redirectCount(0) {} + + void notifyQueryStarted(bool remoteSource) { + Q_Q(QDeclarativeXmlListModel); + progress = remoteSource ? 0.0 : 1.0; + status = QDeclarativeXmlListModel::Loading; + errorString.clear(); + emit q->progressChanged(progress); + emit q->statusChanged(status); + } + bool isComponentComplete; QUrl src; QString xml; @@ -556,6 +568,8 @@ QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent) { connect(globalXmlQuery(), SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)), this, SLOT(queryCompleted(QDeclarativeXmlQueryResult))); + connect(globalXmlQuery(), SIGNAL(error(void*,QString)), + this, SLOT(queryError(void*,QString))); } QDeclarativeXmlListModel::~QDeclarativeXmlListModel() @@ -727,6 +741,42 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati } /*! + \qmlmethod object XmlListModel::get(int index) + + Returns the item at \a index in the model. + + For example, for a model like this: + + \qml + XmlListModel { + id: model + source: "http://mysite.com/feed.xml" + query: "/feed/entry" + XmlRole { name: "title"; query: "title/string()" } + } + \endqml + + This will access the \c title value for the first item in the model: + + \qml + var title = model.get(0).title; + \endqml +*/ +QScriptValue QDeclarativeXmlListModel::get(int index) const +{ + Q_D(const QDeclarativeXmlListModel); + + QScriptEngine *sengine = QDeclarativeEnginePrivate::getScriptEngine(qmlContext(this)->engine()); + if (index < 0 || index >= count()) + return sengine->undefinedValue(); + + QScriptValue sv = sengine->newObject(); + for (int i=0; i<d->roleObjects.count(); i++) + sv.setProperty(d->roleObjects[i]->name(), qScriptValueFromValue(sengine, d->data.value(i).value(index))); + return sv; +} + +/*! \qmlproperty enumeration XmlListModel::status Specifies the model loading status, which can be one of the following: @@ -824,36 +874,21 @@ void QDeclarativeXmlListModel::reload() if (!d->xml.isEmpty()) { d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache); - d->progress = 1.0; - d->status = Loading; - d->errorString.clear(); - emit progressChanged(d->progress); - emit statusChanged(d->status); - return; - } + d->notifyQueryStarted(false); - if (d->src.isEmpty()) { + } else if (d->src.isEmpty()) { d->queryId = XMLLISTMODEL_CLEAR_ID; - d->progress = 1.0; - d->status = Loading; - d->errorString.clear(); - emit progressChanged(d->progress); - emit statusChanged(d->status); + d->notifyQueryStarted(false); QTimer::singleShot(0, this, SLOT(dataCleared())); - return; - } - d->progress = 0.0; - d->status = Loading; - d->errorString.clear(); - emit progressChanged(d->progress); - emit statusChanged(d->status); - - QNetworkRequest req(d->src); - d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req); - QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); + } else { + d->notifyQueryStarted(true); + QNetworkRequest req(d->src); + d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req); + QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } } #define XMLLISTMODEL_MAX_REDIRECT 16 @@ -929,6 +964,19 @@ void QDeclarativeXmlListModel::dataCleared() queryCompleted(r); } +void QDeclarativeXmlListModel::queryError(void* object, const QString& error) +{ + // Be extra careful, object may no longer exist, it's just an ID. + Q_D(QDeclarativeXmlListModel); + for (int i=0; i<d->roleObjects.count(); i++) { + if (d->roleObjects.at(i) == static_cast<QDeclarativeXmlListModelRole*>(object)) { + qmlInfo(d->roleObjects.at(i)) << QObject::tr("invalid query: \"%1\"").arg(error); + return; + } + } + qmlInfo(this) << QObject::tr("invalid query: \"%1\"").arg(error); +} + void QDeclarativeXmlListModel::queryCompleted(const QDeclarativeXmlQueryResult &result) { Q_D(QDeclarativeXmlListModel); @@ -960,7 +1008,6 @@ void QDeclarativeXmlListModel::queryCompleted(const QDeclarativeXmlQueryResult & } } else { - for (int i=0; i<result.removed.count(); i++) emit itemsRemoved(result.removed[i].first, result.removed[i].second); for (int i=0; i<result.inserted.count(); i++) diff --git a/src/declarative/util/qdeclarativexmllistmodel_p.h b/src/declarative/util/qdeclarativexmllistmodel_p.h index 7101c57..8d848c8 100644 --- a/src/declarative/util/qdeclarativexmllistmodel_p.h +++ b/src/declarative/util/qdeclarativexmllistmodel_p.h @@ -47,6 +47,7 @@ #include <QtCore/qurl.h> #include <QtCore/qstringlist.h> +#include <QtScript/qscriptvalue.h> #include <private/qlistmodelinterface_p.h> @@ -109,6 +110,8 @@ public: QString namespaceDeclarations() const; void setNamespaceDeclarations(const QString&); + Q_INVOKABLE QScriptValue get(int index) const; + enum Status { Null, Ready, Loading, Error }; Status status() const; qreal progress() const; @@ -139,6 +142,7 @@ private Q_SLOTS: void requestProgress(qint64,qint64); void dataCleared(); void queryCompleted(const QDeclarativeXmlQueryResult &); + void queryError(void* object, const QString& error); private: Q_DECLARE_PRIVATE(QDeclarativeXmlListModel) |