diff options
Diffstat (limited to 'src/declarative/util')
33 files changed, 1074 insertions, 1131 deletions
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index f807866..bdb9510 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -142,6 +142,16 @@ bool QDeclarativeAbstractAnimation::isRunning() const return d->running; } +// the behavior calls this function +void QDeclarativeAbstractAnimation::notifyRunningChanged(bool running) +{ + Q_D(QDeclarativeAbstractAnimation); + if (d->disableUserControl && d->running != running) { + d->running = running; + emit runningChanged(running); + } +} + //commence is called to start an animation when it is used as a //simple animation, and not as part of a transition void QDeclarativeAbstractAnimationPrivate::commence() @@ -176,6 +186,8 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) { Q_D(QDeclarativeAbstractAnimation); if (!d->componentComplete) { + if (d->running && r == d->running) //don't re-register + return; d->running = r; if (r == false) d->avoidPropertyValueSourceStart = true; diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index 3f8fbdd..59bd465 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -134,9 +134,12 @@ public: private Q_SLOTS: void timelineComplete(); void componentFinalized(); - private: virtual void setTarget(const QDeclarativeProperty &); + void notifyRunningChanged(bool running); + friend class QDeclarativeBehavior; + + }; class QDeclarativePauseAnimationPrivate; diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp index 90e0ca3..2bb28c3 100644 --- a/src/declarative/util/qdeclarativebehavior.cpp +++ b/src/declarative/util/qdeclarativebehavior.cpp @@ -58,7 +58,8 @@ class QDeclarativeBehaviorPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QDeclarativeBehavior) public: - QDeclarativeBehaviorPrivate() : animation(0), enabled(true), finalized(false) {} + QDeclarativeBehaviorPrivate() : animation(0), enabled(true), finalized(false) + , blockRunningChanged(false) {} QDeclarativeProperty property; QVariant currentValue; @@ -66,6 +67,7 @@ public: QDeclarativeGuard<QDeclarativeAbstractAnimation> animation; bool enabled; bool finalized; + bool blockRunningChanged; }; /*! @@ -94,7 +96,7 @@ public: Currently only a single Behavior may be specified for a property; this Behavior can be enabled and disabled via the \l{enabled} property. - \sa QtDeclarative + \sa {declarative/animation/behaviors}{Behavior example}, QtDeclarative */ @@ -132,9 +134,22 @@ void QDeclarativeBehavior::setAnimation(QDeclarativeAbstractAnimation *animation if (d->animation) { d->animation->setDefaultTarget(d->property); d->animation->setDisableUserControl(); + connect(d->animation->qtAnimation(), + SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), + this, + SLOT(qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State))); } } + +void QDeclarativeBehavior::qtAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State) +{ + Q_D(QDeclarativeBehavior); + if (!d->blockRunningChanged) + d->animation->notifyRunningChanged(newState == QAbstractAnimation::Running); +} + + /*! \qmlproperty bool Behavior::enabled Whether the Behavior will be triggered when the property it is tracking changes. @@ -173,8 +188,11 @@ void QDeclarativeBehavior::write(const QVariant &value) d->currentValue = d->property.read(); d->targetValue = value; - if (d->animation->qtAnimation()->duration() != -1) + if (d->animation->qtAnimation()->duration() != -1 + && d->animation->qtAnimation()->state() != QAbstractAnimation::Stopped) { + d->blockRunningChanged = true; d->animation->qtAnimation()->stop(); + } QDeclarativeStateOperation::ActionList actions; QDeclarativeAction action; @@ -186,6 +204,7 @@ void QDeclarativeBehavior::write(const QVariant &value) QList<QDeclarativeProperty> after; d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward); d->animation->qtAnimation()->start(); + d->blockRunningChanged = false; if (!after.contains(d->property)) QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); } diff --git a/src/declarative/util/qdeclarativebehavior_p.h b/src/declarative/util/qdeclarativebehavior_p.h index 6c10eec..9801fb2 100644 --- a/src/declarative/util/qdeclarativebehavior_p.h +++ b/src/declarative/util/qdeclarativebehavior_p.h @@ -47,6 +47,7 @@ #include <qdeclarativepropertyvaluesource.h> #include <qdeclarativepropertyvalueinterceptor.h> #include <qdeclarative.h> +#include <QtCore/QAbstractAnimation> QT_BEGIN_HEADER @@ -85,6 +86,7 @@ Q_SIGNALS: private Q_SLOTS: void componentFinalized(); + void qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State); }; QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativebind_p.h b/src/declarative/util/qdeclarativebind_p.h index f89c2eb..3dc7dba 100644 --- a/src/declarative/util/qdeclarativebind_p.h +++ b/src/declarative/util/qdeclarativebind_p.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeBindPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeBind : public QObject, public QDeclarativeParserStatus +class Q_AUTOTEST_EXPORT QDeclarativeBind : public QObject, public QDeclarativeParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeBind) diff --git a/src/declarative/util/qdeclarativeconnections_p.h b/src/declarative/util/qdeclarativeconnections_p.h index a914166..e8105b4 100644 --- a/src/declarative/util/qdeclarativeconnections_p.h +++ b/src/declarative/util/qdeclarativeconnections_p.h @@ -58,7 +58,7 @@ QT_MODULE(Declarative) class QDeclarativeBoundSignal; class QDeclarativeContext; class QDeclarativeConnectionsPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeConnections : public QObject, public QDeclarativeParserStatus +class Q_AUTOTEST_EXPORT QDeclarativeConnections : public QObject, public QDeclarativeParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeConnections) diff --git a/src/declarative/util/qdeclarativefontloader_p.h b/src/declarative/util/qdeclarativefontloader_p.h index 14335ab..6947547 100644 --- a/src/declarative/util/qdeclarativefontloader_p.h +++ b/src/declarative/util/qdeclarativefontloader_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeFontLoaderPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeFontLoader : public QObject +class Q_AUTOTEST_EXPORT QDeclarativeFontLoader : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeFontLoader) diff --git a/src/declarative/util/qdeclarativelistaccessor_p.h b/src/declarative/util/qdeclarativelistaccessor_p.h index d8bb8af..41aacb9 100644 --- a/src/declarative/util/qdeclarativelistaccessor_p.h +++ b/src/declarative/util/qdeclarativelistaccessor_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeEngine; -class Q_DECLARATIVE_EXPORT QDeclarativeListAccessor +class Q_AUTOTEST_EXPORT QDeclarativeListAccessor { public: QDeclarativeListAccessor(); diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 9ed21a6..3ede335 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -551,9 +551,13 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser QDeclarativeCustomParserNode node = qvariant_cast<QDeclarativeCustomParserNode>(value); - if (node.name() != "ListElement") { - error(node, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); - return false; + if (node.name() != listElementTypeName) { + const QMetaObject *mo = resolveType(node.name()); + if (mo != &QDeclarativeListElement::staticMetaObject) { + error(node, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); + return false; + } + listElementTypeName = node.name(); // cache right name for next time } { @@ -650,6 +654,7 @@ QByteArray QDeclarativeListModelParser::compile(const QList<QDeclarativeCustomPa { QList<ListInstruction> instr; QByteArray data; + listElementTypeName = QByteArray(); // unknown for(int ii = 0; ii < customProps.count(); ++ii) { const QDeclarativeCustomParserProperty &prop = customProps.at(ii); @@ -1017,6 +1022,8 @@ QVariant NestedListModel::data(int index, int role) const Q_ASSERT(_root && index >= 0 && index < _root->values.count()); checkRoles(); QVariant rv; + if (roleStrings.count() < role) + return rv; ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); if (!node) diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index d09062e..6aff9c6 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -135,6 +135,8 @@ private: bool compileProperty(const QDeclarativeCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data); bool definesEmptyList(const QString &); + + QByteArray listElementTypeName; }; diff --git a/src/declarative/util/qdeclarativepackage.cpp b/src/declarative/util/qdeclarativepackage.cpp index 1e49ad9..1a4f2a7 100644 --- a/src/declarative/util/qdeclarativepackage.cpp +++ b/src/declarative/util/qdeclarativepackage.cpp @@ -65,12 +65,12 @@ QT_BEGIN_NAMESPACE \snippet examples/declarative/modelviews/package/Delegate.qml 0 These named items are used as the delegates by the two views who - reference the special VisualDataModel.parts property to select + reference the special \l{VisualDataModel::parts} property to select a model which provides the chosen delegate. \snippet examples/declarative/modelviews/package/view.qml 0 - \sa {declarative/modelviews/package}{Package example}, QtDeclarative + \sa {declarative/modelviews/package}{Package example}, {demos/declarative/photoviewer}{Photo Viewer demo}, QtDeclarative */ /*! diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index a4ddf46..00dd922 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -55,104 +55,209 @@ #include <QFile> #include <QThread> #include <QMutex> +#include <QMutexLocker> +#include <QWaitCondition> #include <QBuffer> #include <QWaitCondition> #include <QtCore/qdebug.h> #include <private/qobject_p.h> #include <QSslError> -// Maximum number of simultaneous image requests to send. -static const int maxImageRequestCount = 8; +#define IMAGEREQUEST_MAX_REQUEST_COUNT 8 +#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16 +#define CACHE_EXPIRE_TIME 30 +#define CACHE_REMOVAL_FRACTION 4 QT_BEGIN_NAMESPACE -class QDeclarativeImageReaderEvent : public QEvent +class QDeclarativePixmapReader; +class QDeclarativePixmapData; +class QDeclarativePixmapReply : public QObject { + Q_OBJECT public: enum ReadError { NoError, Loading, Decoding }; - QDeclarativeImageReaderEvent(QDeclarativeImageReaderEvent::ReadError err, const QString &errStr, const QImage &img) - : QEvent(QEvent::User), error(err), errorString(errStr), image(img) {} + QDeclarativePixmapReply(QDeclarativePixmapData *); + ~QDeclarativePixmapReply(); - ReadError error; - QString errorString; - QImage image; + QDeclarativePixmapData *data; + QDeclarativePixmapReader *reader; + + bool loading; + int redirectCount; + + class Event : public QEvent { + public: + Event(ReadError, const QString &, const QSize &, const QImage &); + + ReadError error; + QString errorString; + QSize implicitSize; + QImage image; + }; + void postReply(ReadError, const QString &, const QSize &, const QImage &); + + +Q_SIGNALS: + void finished(); + void downloadProgress(qint64, qint64); + +protected: + bool event(QEvent *event); + +private: + Q_DISABLE_COPY(QDeclarativePixmapReply) + +public: + static int finishedIndex; + static int downloadProgressIndex; }; -class QDeclarativeImageRequestHandler; -class QDeclarativeImageReader : public QThread +class QDeclarativePixmapData; +class QDeclarativePixmapReader : public QThread { Q_OBJECT public: - QDeclarativeImageReader(QDeclarativeEngine *eng); - ~QDeclarativeImageReader(); + QDeclarativePixmapReader(QDeclarativeEngine *eng); + ~QDeclarativePixmapReader(); - QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height); + QDeclarativePixmapReply *getImage(QDeclarativePixmapData *); void cancel(QDeclarativePixmapReply *rep); - static QDeclarativeImageReader *instance(QDeclarativeEngine *engine); + static QDeclarativePixmapReader *instance(QDeclarativeEngine *engine); protected: void run(); +private slots: + void networkRequestDone(); + private: + void processJobs(); + void processJob(QDeclarativePixmapReply *); + QList<QDeclarativePixmapReply*> jobs; QList<QDeclarativePixmapReply*> cancelled; QDeclarativeEngine *engine; - QDeclarativeImageRequestHandler *handler; QObject *eventLoopQuitHack; + QMutex mutex; + class ThreadObject : public QObject { + public: + ThreadObject(QDeclarativePixmapReader *); + void processJobs(); + virtual bool event(QEvent *e); + private: + QDeclarativePixmapReader *reader; + } *threadObject; + QWaitCondition waitCondition; + + QNetworkAccessManager *networkAccessManager(); + QNetworkAccessManager *accessManager; - static QHash<QDeclarativeEngine *,QDeclarativeImageReader*> readers; + QHash<QNetworkReply*,QDeclarativePixmapReply*> replies; + + static int replyDownloadProgress; + static int replyFinished; + static int downloadProgress; + static int thisNetworkRequestDone; + static QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> readers; static QMutex readerMutex; - friend class QDeclarativeImageRequestHandler; }; -QHash<QDeclarativeEngine *,QDeclarativeImageReader*> QDeclarativeImageReader::readers; -QMutex QDeclarativeImageReader::readerMutex; - - -class QDeclarativeImageRequestHandler : public QObject +class QDeclarativePixmapData { - Q_OBJECT public: - QDeclarativeImageRequestHandler(QDeclarativeImageReader *read, QDeclarativeEngine *eng) - : QObject(), accessManager(0), engine(eng), reader(read), redirectCount(0) + QDeclarativePixmapData(const QUrl &u, const QSize &s, const QString &e) + : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Error), + url(u), errorString(e), requestSize(s), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); } - QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height); - void cancel(QDeclarativePixmapReply *reply); - -protected: - bool event(QEvent *event); + QDeclarativePixmapData(const QUrl &u, const QSize &r) + : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Loading), + url(u), requestSize(r), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), + nextUnreferenced(0) + { + } -private slots: - void networkRequestDone(); + QDeclarativePixmapData(const QUrl &u, const QPixmap &p, const QSize &s, const QSize &r) + : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready), + url(u), pixmap(p), implicitSize(s), requestSize(r), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { + } -private: - QNetworkAccessManager *networkAccessManager() { - if (!accessManager) - accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(this); - return accessManager; + QDeclarativePixmapData(const QPixmap &p) + : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarativePixmap::Ready), + pixmap(p), implicitSize(p.size()), requestSize(p.size()), reply(0), prevUnreferenced(0), + prevUnreferencedPtr(0), nextUnreferenced(0) + { } - QHash<QNetworkReply*,QDeclarativePixmapReply*> replies; - QNetworkAccessManager *accessManager; - QDeclarativeEngine *engine; - QDeclarativeImageReader *reader; - int redirectCount; + int cost() const; + void addref(); + void release(); + void addToCache(); + void removeFromCache(); - static int replyDownloadProgress; - static int replyFinished; - static int downloadProgress; - static int thisNetworkRequestDone; + uint refCount; + + bool inCache:1; + bool privatePixmap:1; + + QDeclarativePixmap::Status pixmapStatus; + QUrl url; + QString errorString; + QPixmap pixmap; + QSize implicitSize; + QSize requestSize; + + QDeclarativePixmapReply *reply; + + QDeclarativePixmapData *prevUnreferenced; + QDeclarativePixmapData**prevUnreferencedPtr; + QDeclarativePixmapData *nextUnreferenced; }; -//=========================================================================== +int QDeclarativePixmapReply::finishedIndex = -1; +int QDeclarativePixmapReply::downloadProgressIndex = -1; + +// XXX +QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> QDeclarativePixmapReader::readers; +QMutex QDeclarativePixmapReader::readerMutex; + +int QDeclarativePixmapReader::replyDownloadProgress = -1; +int QDeclarativePixmapReader::replyFinished = -1; +int QDeclarativePixmapReader::downloadProgress = -1; +int QDeclarativePixmapReader::thisNetworkRequestDone = -1; -static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int req_width, int req_height) + +void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString, + const QSize &implicitSize, const QImage &image) +{ + loading = false; + QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, image)); +} + +QDeclarativePixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, const QImage &i) +: QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i) +{ +} + +QNetworkAccessManager *QDeclarativePixmapReader::networkAccessManager() +{ + if (!accessManager) { + Q_ASSERT(threadObject); + accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject); + } + return accessManager; +} + +static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, + const QSize &requestSize) { QImageReader imgio(dev); @@ -163,17 +268,17 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e } bool scaled = false; - if (req_width > 0 || req_height > 0) { + if (requestSize.width() > 0 || requestSize.height() > 0) { QSize s = imgio.size(); - if (req_width && (force_scale || req_width < s.width())) { - if (req_height <= 0) - s.setHeight(s.height()*req_width/s.width()); - s.setWidth(req_width); scaled = true; + if (requestSize.width() && (force_scale || requestSize.width() < s.width())) { + if (requestSize.height() <= 0) + s.setHeight(s.height()*requestSize.width()/s.width()); + s.setWidth(requestSize.width()); scaled = true; } - if (req_height && (force_scale || req_height < s.height())) { - if (req_width <= 0) - s.setWidth(s.width()*req_height/s.height()); - s.setHeight(req_height); scaled = true; + if (requestSize.height() && (force_scale || requestSize.height() < s.height())) { + if (requestSize.width() <= 0) + s.setWidth(s.width()*requestSize.height()/s.height()); + s.setHeight(requestSize.height()); scaled = true; } if (scaled) { imgio.setScaledSize(s); } } @@ -187,200 +292,196 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e return true; } else { if (errorString) - *errorString = QDeclarativePixmapCache::tr("Error decoding: %1: %2").arg(url.toString()) + *errorString = QDeclarativePixmap::tr("Error decoding: %1: %2").arg(url.toString()) .arg(imgio.errorString()); return false; } } - -//=========================================================================== - -int QDeclarativeImageRequestHandler::replyDownloadProgress = -1; -int QDeclarativeImageRequestHandler::replyFinished = -1; -int QDeclarativeImageRequestHandler::downloadProgress = -1; -int QDeclarativeImageRequestHandler::thisNetworkRequestDone = -1; - -typedef QHash<QUrl, QSize> QDeclarativePixmapSizeHash; -Q_GLOBAL_STATIC(QDeclarativePixmapSizeHash, qmlOriginalSizes); - -bool QDeclarativeImageRequestHandler::event(QEvent *event) +QDeclarativePixmapReader::QDeclarativePixmapReader(QDeclarativeEngine *eng) +: QThread(eng), engine(eng), threadObject(0), accessManager(0) { - if (event->type() == QEvent::User) { - if (replyDownloadProgress == -1) { - replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); - replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()"); - downloadProgress = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); - thisNetworkRequestDone = QDeclarativeImageRequestHandler::staticMetaObject.indexOfSlot("networkRequestDone()"); - } - - while (1) { - reader->mutex.lock(); - - if (reader->cancelled.count()) { - for (int i = 0; i < reader->cancelled.count(); ++i) { - QDeclarativePixmapReply *job = reader->cancelled.at(i); - // cancel any jobs already started - QNetworkReply *reply = replies.key(job, 0); - if (reply && reply->isRunning()) { - replies.remove(reply); - reply->close(); - } - // remove from pending job list - for (int j = 0; j < reader->jobs.count(); ++j) { - if (reader->jobs.at(j) == job) { - reader->jobs.removeAt(j); - job->release(true); - break; - } - } - } - reader->cancelled.clear(); - } - - if (!reader->jobs.count() || replies.count() > maxImageRequestCount) { - reader->mutex.unlock(); - break; - } + eventLoopQuitHack = new QObject; + eventLoopQuitHack->moveToThread(this); + connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection); + start(QThread::IdlePriority); +} - QDeclarativePixmapReply *runningJob = reader->jobs.takeLast(); - QUrl url = runningJob->url(); - reader->mutex.unlock(); - - // fetch - if (url.scheme() == QLatin1String("image")) { - // Use QmlImageProvider - QSize read_impsize; - QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url, &read_impsize, QSize(runningJob->forcedWidth(),runningJob->forcedHeight())); - qmlOriginalSizes()->insert(url, read_impsize); - QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError; - QString errorStr; - if (image.isNull()) { - errorCode = QDeclarativeImageReaderEvent::Loading; - errorStr = QDeclarativePixmapCache::tr("Failed to get image from provider: %1").arg(url.toString()); - } - QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image)); - } else { - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - // Image is local - load/decode immediately - QImage image; - QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError; - QString errorStr; - QFile f(lf); - if (f.open(QIODevice::ReadOnly)) { - QSize read_impsize; - if (readImage(url, &f, &image, &errorStr, &read_impsize, runningJob->forcedWidth(),runningJob->forcedHeight())) { - qmlOriginalSizes()->insert(url, read_impsize); - } else { - errorCode = QDeclarativeImageReaderEvent::Loading; - } - } else { - errorStr = QDeclarativePixmapCache::tr("Cannot open: %1").arg(url.toString()); - errorCode = QDeclarativeImageReaderEvent::Loading; - } - QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image)); - } else { - // Network resource - QNetworkRequest req(url); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - QNetworkReply *reply = networkAccessManager()->get(req); - - QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress); - QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone); - - replies.insert(reply, runningJob); - } - } - } - return true; - } +QDeclarativePixmapReader::~QDeclarativePixmapReader() +{ + readerMutex.lock(); + readers.remove(engine); + readerMutex.unlock(); - return QObject::event(event); + eventLoopQuitHack->deleteLater(); + wait(); } -#define IMAGEREQUESTHANDLER_MAX_REDIRECT_RECURSION 16 - -void QDeclarativeImageRequestHandler::networkRequestDone() +void QDeclarativePixmapReader::networkRequestDone() { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); QDeclarativePixmapReply *job = replies.take(reply); - redirectCount++; - if (redirectCount < IMAGEREQUESTHANDLER_MAX_REDIRECT_RECURSION) { - QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - QUrl url = reply->url().resolved(redirect.toUrl()); - QNetworkRequest req(url); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - - reply->deleteLater(); - reply = networkAccessManager()->get(req); - - QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress); - QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone); - - replies.insert(reply, job); - return; + if (job) { + job->redirectCount++; + if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + + reply->deleteLater(); + reply = networkAccessManager()->get(req); + + QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress); + QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone); + + replies.insert(reply, job); + return; + } } - } - redirectCount=0; - if (job) { QImage image; - QDeclarativeImageReaderEvent::ReadError error; + QDeclarativePixmapReply::ReadError error = QDeclarativePixmapReply::NoError; QString errorString; + QSize readSize; if (reply->error()) { - error = QDeclarativeImageReaderEvent::Loading; + error = QDeclarativePixmapReply::Loading; errorString = reply->errorString(); } else { - QSize read_impsize; QByteArray all = reply->readAll(); QBuffer buff(&all); buff.open(QIODevice::ReadOnly); - if (readImage(reply->url(), &buff, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) { - qmlOriginalSizes()->insert(reply->url(), read_impsize); - error = QDeclarativeImageReaderEvent::NoError; - } else { - error = QDeclarativeImageReaderEvent::Decoding; + if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->data->requestSize)) { + error = QDeclarativePixmapReply::Decoding; } } // send completion event to the QDeclarativePixmapReply - QCoreApplication::postEvent(job, new QDeclarativeImageReaderEvent(error, errorString, image)); + mutex.lock(); + if (!cancelled.contains(job)) job->postReply(error, errorString, readSize, image); + mutex.unlock(); } - // kick off event loop again if we have dropped below max request count - if (replies.count() == maxImageRequestCount) - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); reply->deleteLater(); + + // kick off event loop again incase we have dropped below max request count + threadObject->processJobs(); } -//=========================================================================== +QDeclarativePixmapReader::ThreadObject::ThreadObject(QDeclarativePixmapReader *i) +: reader(i) +{ +} -QDeclarativeImageReader::QDeclarativeImageReader(QDeclarativeEngine *eng) - : QThread(eng), engine(eng), handler(0) +void QDeclarativePixmapReader::ThreadObject::processJobs() +{ + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); +} + +bool QDeclarativePixmapReader::ThreadObject::event(QEvent *e) { - eventLoopQuitHack = new QObject; - eventLoopQuitHack->moveToThread(this); - connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection); - start(QThread::IdlePriority); + if (e->type() == QEvent::User) { + reader->processJobs(); + return true; + } else { + return QObject::event(e); + } } -QDeclarativeImageReader::~QDeclarativeImageReader() +void QDeclarativePixmapReader::processJobs() { - readerMutex.lock(); - readers.remove(engine); - readerMutex.unlock(); + QMutexLocker locker(&mutex); + + while (true) { + if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT)) + return; // Nothing else to do + + // Clean cancelled jobs + if (cancelled.count()) { + for (int i = 0; i < cancelled.count(); ++i) { + QDeclarativePixmapReply *job = cancelled.at(i); + QNetworkReply *reply = replies.key(job, 0); + if (reply && reply->isRunning()) { + // cancel any jobs already started + replies.remove(reply); + reply->close(); + } + delete job; + } + cancelled.clear(); + } - eventLoopQuitHack->deleteLater(); - wait(); + if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) { + QDeclarativePixmapReply *runningJob = jobs.takeLast(); + runningJob->loading = true; + + locker.unlock(); + processJob(runningJob); + locker.relock(); + } + } +} + +void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob) +{ + QUrl url = runningJob->data->url; + + // fetch + if (url.scheme() == QLatin1String("image")) { + // Use QmlImageProvider + QSize readSize; + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize); + + QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; + QString errorStr; + if (image.isNull()) { + errorCode = QDeclarativePixmapReply::Loading; + errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + } + + mutex.lock(); + if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image); + mutex.unlock(); + } else { + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + if (!lf.isEmpty()) { + // Image is local - load/decode immediately + QImage image; + QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; + QString errorStr; + QFile f(lf); + QSize readSize; + if (f.open(QIODevice::ReadOnly)) { + if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize)) + errorCode = QDeclarativePixmapReply::Loading; + } else { + errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString()); + errorCode = QDeclarativePixmapReply::Loading; + } + mutex.lock(); + if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image); + mutex.unlock(); + } else { + // Network resource + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + QNetworkReply *reply = networkAccessManager()->get(req); + + QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress); + QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone); + + replies.insert(reply, runningJob); + } + } } -QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *engine) +QDeclarativePixmapReader *QDeclarativePixmapReader::instance(QDeclarativeEngine *engine) { readerMutex.lock(); - QDeclarativeImageReader *reader = readers.value(engine); + QDeclarativePixmapReader *reader = readers.value(engine); if (!reader) { - reader = new QDeclarativeImageReader(engine); + reader = new QDeclarativePixmapReader(engine); readers.insert(engine, reader); } readerMutex.unlock(); @@ -388,342 +489,558 @@ QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *e return reader; } -QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url, int req_width, int req_height) +QDeclarativePixmapReply *QDeclarativePixmapReader::getImage(QDeclarativePixmapData *data) { mutex.lock(); - QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url, req_width, req_height); - reply->addRef(); - reply->setLoading(); + QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(data); + reply->reader = this; jobs.append(reply); - if (jobs.count() == 1 && handler) - QCoreApplication::postEvent(handler, new QEvent(QEvent::User)); + // XXX + if (threadObject) threadObject->processJobs(); mutex.unlock(); return reply; } -void QDeclarativeImageReader::cancel(QDeclarativePixmapReply *reply) +void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply) { mutex.lock(); - if (reply->isLoading()) { - // Add to cancel list to be cancelled in reader thread. + if (reply->loading) { cancelled.append(reply); - if (cancelled.count() == 1 && handler) - QCoreApplication::postEvent(handler, new QEvent(QEvent::User)); + // XXX + if (threadObject) threadObject->processJobs(); + } else { + jobs.removeAll(reply); + delete reply; } mutex.unlock(); } -void QDeclarativeImageReader::run() +void QDeclarativePixmapReader::run() { - readerMutex.lock(); - handler = new QDeclarativeImageRequestHandler(this, engine); - readerMutex.unlock(); + if (replyDownloadProgress == -1) { + const QMetaObject *nr = &QNetworkReply::staticMetaObject; + const QMetaObject *pr = &QDeclarativePixmapReply::staticMetaObject; + const QMetaObject *ir = &QDeclarativePixmapReader::staticMetaObject; + replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)"); + replyFinished = nr->indexOfSignal("finished()"); + downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)"); + thisNetworkRequestDone = ir->indexOfSlot("networkRequestDone()"); + } + mutex.lock(); + threadObject = new ThreadObject(this); + mutex.unlock(); + + processJobs(); exec(); - delete handler; - handler = 0; + delete threadObject; + threadObject = 0; } -//=========================================================================== - -/*! - \internal - \class QDeclarativePixmapCache - \brief Enacapsultes a pixmap for QDeclarativeGraphics items. +class QDeclarativePixmapKey +{ +public: + const QUrl *url; + const QSize *size; +}; - This class is NOT reentrant. - */ +inline bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs) +{ + return *lhs.size == *rhs.size && *lhs.url == *rhs.url; +} -typedef QHash<QUrl, QDeclarativePixmapReply *> QDeclarativePixmapReplyHash; -Q_GLOBAL_STATIC(QDeclarativePixmapReplyHash, qmlActivePixmapReplies); +inline uint qHash(const QDeclarativePixmapKey &key) +{ + return qHash(*key.url) ^ key.size->width() ^ key.size->height(); +} -class QDeclarativePixmapReplyPrivate : public QObjectPrivate +class QDeclarativePixmapStore : public QObject { - Q_DECLARE_PUBLIC(QDeclarativePixmapReply) + Q_OBJECT +public: + QDeclarativePixmapStore(); + + void unreferencePixmap(QDeclarativePixmapData *); + void referencePixmap(QDeclarativePixmapData *); + +protected: + virtual void timerEvent(QTimerEvent *); public: - QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u, int req_width, int req_height) - : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r), - forced_width(req_width), forced_height(req_height) - { - } + QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache; - int refCount; - QUrl url; - QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard - QDeclarativePixmapReply::Status status; - bool loading; - QDeclarativeImageReader *reader; - int forced_width, forced_height; - QString errorString; -}; +private: + QDeclarativePixmapData *m_unreferencedPixmaps; + QDeclarativePixmapData *m_lastUnreferencedPixmap; + int m_unreferencedCost; + int m_timerId; +}; +Q_GLOBAL_STATIC(QDeclarativePixmapStore, pixmapStore); -QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height) - : QObject(*new QDeclarativePixmapReplyPrivate(reader, url, req_width, req_height), 0) +QDeclarativePixmapStore::QDeclarativePixmapStore() +: m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1) { } -QDeclarativePixmapReply::~QDeclarativePixmapReply() +void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data) { + Q_ASSERT(data->prevUnreferenced == 0); + Q_ASSERT(data->prevUnreferencedPtr == 0); + Q_ASSERT(data->nextUnreferenced == 0); + + data->nextUnreferenced = m_unreferencedPixmaps; + data->prevUnreferencedPtr = &m_unreferencedPixmaps; + + m_unreferencedPixmaps = data; + if (m_unreferencedPixmaps->nextUnreferenced) { + m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps; + m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced; + } + + if (!m_lastUnreferencedPixmap) + m_lastUnreferencedPixmap = data; + + m_unreferencedCost += data->cost(); + + if (m_timerId == -1) + startTimer(CACHE_EXPIRE_TIME * 1000); } -const QUrl &QDeclarativePixmapReply::url() const +void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data) { - Q_D(const QDeclarativePixmapReply); - return d->url; + Q_ASSERT(data->prevUnreferencedPtr); + + *data->prevUnreferencedPtr = data->nextUnreferenced; + if (data->nextUnreferenced) { + data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr; + data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced; + } + if (m_lastUnreferencedPixmap == data) + m_lastUnreferencedPixmap = data->prevUnreferenced; + + data->nextUnreferenced = 0; + data->prevUnreferencedPtr = 0; + data->prevUnreferenced = 0; + + m_unreferencedCost -= data->cost(); } -int QDeclarativePixmapReply::forcedWidth() const +void QDeclarativePixmapStore::timerEvent(QTimerEvent *) { - Q_D(const QDeclarativePixmapReply); - return d->forced_width; + int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION; + + while (removalCost > 0 && m_lastUnreferencedPixmap) { + QDeclarativePixmapData *data = m_lastUnreferencedPixmap; + Q_ASSERT(data->nextUnreferenced == 0); + + *data->prevUnreferencedPtr = 0; + m_lastUnreferencedPixmap = data->prevUnreferenced; + data->prevUnreferencedPtr = 0; + data->prevUnreferenced = 0; + + removalCost -= data->cost(); + data->removeFromCache(); + delete data; + } + + if (m_unreferencedPixmaps == 0) { + killTimer(m_timerId); + m_timerId = -1; + } } -int QDeclarativePixmapReply::forcedHeight() const +QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativePixmapData *d) +: data(d), reader(0), loading(false), redirectCount(0) { - Q_D(const QDeclarativePixmapReply); - return d->forced_height; + if (finishedIndex == -1) { + finishedIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()"); + downloadProgressIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)"); + } } -QSize QDeclarativePixmapReply::implicitSize() const +QDeclarativePixmapReply::~QDeclarativePixmapReply() { - Q_D(const QDeclarativePixmapReply); - QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(d->url); - if (iter != qmlOriginalSizes()->end()) - return *iter; - else - return QSize(); } bool QDeclarativePixmapReply::event(QEvent *event) { - Q_D(QDeclarativePixmapReply); if (event->type() == QEvent::User) { - d->loading = false; - if (!release(true)) { - QDeclarativeImageReaderEvent *de = static_cast<QDeclarativeImageReaderEvent*>(event); - d->status = (de->error == QDeclarativeImageReaderEvent::NoError) ? Ready : Error; - if (d->status == Ready) - d->pixmap = QPixmap::fromImage(de->image); - else - d->errorString = de->errorString; - QByteArray key = d->url.toEncoded(QUrl::FormattingOption(0x100)); - QString strKey = QString::fromLatin1(key.constData(), key.count()); - QPixmapCache::insert(strKey, d->pixmap); // note: may fail (returns false) + + if (data) { + Event *de = static_cast<Event *>(event); + data->pixmapStatus = (de->error == NoError) ? QDeclarativePixmap::Ready : QDeclarativePixmap::Error; + + if (data->pixmapStatus == QDeclarativePixmap::Ready) { + data->pixmap = QPixmap::fromImage(de->image); + data->implicitSize = de->implicitSize; + } else { + data->errorString = de->errorString; + data->removeFromCache(); // We don't continue to cache error'd pixmaps + } + + data->reply = 0; emit finished(); } + + delete this; return true; + } else { + return QObject::event(event); } - - return QObject::event(event); } -QString QDeclarativePixmapReply::errorString() const +int QDeclarativePixmapData::cost() const { - Q_D(const QDeclarativePixmapReply); - return d->errorString; + return pixmap.width() * pixmap.height() * pixmap.depth(); } -QDeclarativePixmapReply::Status QDeclarativePixmapReply::status() const +void QDeclarativePixmapData::addref() { - Q_D(const QDeclarativePixmapReply); - return d->status; + ++refCount; + if (prevUnreferencedPtr) + pixmapStore()->referencePixmap(this); } -bool QDeclarativePixmapReply::isLoading() const +void QDeclarativePixmapData::release() { - Q_D(const QDeclarativePixmapReply); - return d->loading; + Q_ASSERT(refCount > 0); + --refCount; + + if (refCount == 0) { + if (reply) { + reply->data = 0; + reply->reader->cancel(reply); + reply = 0; + } + + if (pixmapStatus == QDeclarativePixmap::Ready) { + pixmapStore()->unreferencePixmap(this); + } else { + removeFromCache(); + delete this; + } + } } -void QDeclarativePixmapReply::setLoading() +void QDeclarativePixmapData::addToCache() { - Q_D(QDeclarativePixmapReply); - d->loading = true; + if (!inCache) { + QDeclarativePixmapKey key = { &url, &requestSize }; + pixmapStore()->m_cache.insert(key, this); + inCache = true; + } } -void QDeclarativePixmapReply::addRef() +void QDeclarativePixmapData::removeFromCache() { - Q_D(QDeclarativePixmapReply); - ++d->refCount; + if (inCache) { + QDeclarativePixmapKey key = { &url, &requestSize }; + pixmapStore()->m_cache.remove(key); + inCache = false; + } } -bool QDeclarativePixmapReply::release(bool defer) +static QDeclarativePixmapData* createPixmapDataSync(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok) { - Q_D(QDeclarativePixmapReply); - Q_ASSERT(d->refCount > 0); - --d->refCount; - if (d->refCount == 0) { - qmlActivePixmapReplies()->remove(d->url); - if (defer) - deleteLater(); - else - delete this; - return true; - } else if (d->refCount == 1 && d->loading) { - // The only reference left is the reader thread. - qmlActivePixmapReplies()->remove(d->url); - d->reader->cancel(this); + if (url.scheme() == QLatin1String("image")) { + QSize readSize; + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url); + + switch (imageType) { + case QDeclarativeImageProvider::Image: + { + QImage image = ep->getImageFromProvider(url, &readSize, requestSize); + if (!image.isNull()) { + *ok = true; + return new QDeclarativePixmapData(url, QPixmap::fromImage(image), readSize, requestSize); + } + } + case QDeclarativeImageProvider::Pixmap: + { + QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize); + if (!pixmap.isNull()) { + *ok = true; + return new QDeclarativePixmapData(url, pixmap, readSize, requestSize); + } + } + } + + // no matching provider, or provider has bad image type, or provider returned null image + return new QDeclarativePixmapData(url, requestSize, + QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString())); } - return false; + QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + if (localFile.isEmpty()) + return 0; + + QFile f(localFile); + QSize readSize; + QString errorString; + + if (f.open(QIODevice::ReadOnly)) { + QImage image; + if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) { + *ok = true; + return new QDeclarativePixmapData(url, QPixmap::fromImage(image), readSize, requestSize); + } + } else { + errorString = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString()); + } + return new QDeclarativePixmapData(url, requestSize, errorString); } -/*! - Finds the cached pixmap corresponding to \a url. - If the image is a network resource and has not yet - been retrieved and cached, request() must be called. - Returns Ready, or Error if the image has been retrieved, - otherwise the current retrieval status. +struct QDeclarativePixmapNull { + QUrl url; + QPixmap pixmap; + QSize size; +}; +Q_GLOBAL_STATIC(QDeclarativePixmapNull, nullPixmap); - If \a async is false the image will be loaded and decoded immediately; - otherwise the image will be loaded and decoded in a separate thread. +QDeclarativePixmap::QDeclarativePixmap() +: d(0) +{ +} - If \a req_width and \a req_height are non-zero, they are used for - the size of the rendered pixmap rather than the intrinsic size of the image. - Different request sizes add different cache items. +QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url) +: d(0) +{ + load(engine, url); +} - Note that images sourced from the network will always be loaded and - decoded asynchonously. -*/ -QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, QString *errorString, QSize *impsize, bool async, int req_width, int req_height) +QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url, const QSize &size) +: d(0) { - QDeclarativePixmapReply::Status status = QDeclarativePixmapReply::Unrequested; - QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100)); + load(engine, url, size); +} - if (req_width > 0 || req_height > 0) { - key += ':'; - key += QByteArray::number(req_width); - key += 'x'; - key += QByteArray::number(req_height); +QDeclarativePixmap::~QDeclarativePixmap() +{ + if (d) { + d->release(); + d = 0; } +} - QString strKey = QString::fromLatin1(key.constData(), key.count()); +bool QDeclarativePixmap::isNull() const +{ + return d == 0; +} -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (!async) { - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - status = QDeclarativePixmapReply::Ready; - if (!QPixmapCache::find(strKey,pixmap)) { - QFile f(lf); - QSize read_impsize; - if (f.open(QIODevice::ReadOnly)) { - QImage image; - if (readImage(url, &f, &image, errorString, &read_impsize, req_width, req_height)) { - *pixmap = QPixmap::fromImage(image); - } else { - *pixmap = QPixmap(); - status = QDeclarativePixmapReply::Error; - } - } else { - if (errorString) - *errorString = tr("Cannot open: %1").arg(url.toString()); - *pixmap = QPixmap(); - status = QDeclarativePixmapReply::Error; - } - if (status == QDeclarativePixmapReply::Ready) { - QPixmapCache::insert(strKey, *pixmap); - qmlOriginalSizes()->insert(url, read_impsize); - } - if (impsize) - *impsize = read_impsize; - } else { - if (impsize) { - QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url); - if (iter != qmlOriginalSizes()->end()) - *impsize = *iter; - } +bool QDeclarativePixmap::isReady() const +{ + return status() == Ready; +} + +bool QDeclarativePixmap::isError() const +{ + return status() == Error; +} + +bool QDeclarativePixmap::isLoading() const +{ + return status() == Loading; +} + +QString QDeclarativePixmap::error() const +{ + if (d) + return d->errorString; + else + return QString(); +} + +QDeclarativePixmap::Status QDeclarativePixmap::status() const +{ + if (d) + return d->pixmapStatus; + else + return Null; +} + +const QUrl &QDeclarativePixmap::url() const +{ + if (d) + return d->url; + else + return nullPixmap()->url; +} + +const QSize &QDeclarativePixmap::implicitSize() const +{ + if (d) + return d->implicitSize; + else + return nullPixmap()->size; +} + +const QSize &QDeclarativePixmap::requestSize() const +{ + if (d) + return d->requestSize; + else + return nullPixmap()->size; +} + +const QPixmap &QDeclarativePixmap::pixmap() const +{ + if (d) + return d->pixmap; + else + return nullPixmap()->pixmap; +} + +void QDeclarativePixmap::setPixmap(const QPixmap &p) +{ + clear(); + + if (!p.isNull()) + d = new QDeclarativePixmapData(p); +} + +int QDeclarativePixmap::width() const +{ + if (d) + return d->pixmap.width(); + else + return 0; +} + +int QDeclarativePixmap::height() const +{ + if (d) + return d->pixmap.height(); + else + return 0; +} + +QRect QDeclarativePixmap::rect() const +{ + if (d) + return d->pixmap.rect(); + else + return QRect(); +} + +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url) +{ + load(engine, url, QSize(), false); +} + +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, bool async) +{ + load(engine, url, QSize(), async); +} + +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size) +{ + load(engine, url, size, false); +} + +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool async) +{ + if (d) { d->release(); d = 0; } + + QDeclarativePixmapKey key = { &url, &requestSize }; + QDeclarativePixmapStore *store = pixmapStore(); + + QHash<QDeclarativePixmapKey, QDeclarativePixmapData *>::Iterator iter = store->m_cache.find(key); + + if (iter == store->m_cache.end()) { + if (async) { + // pixmaps can only be loaded synchronously + if (url.scheme() == QLatin1String("image") + && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) { + async = false; } - return status; } - } -#endif - - QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); - if (iter != qmlActivePixmapReplies()->end() && (*iter)->status() == QDeclarativePixmapReply::Ready) { - // Must check this, since QPixmapCache::insert may have failed. - *pixmap = (*iter)->d_func()->pixmap; - status = (*iter)->status(); - (*iter)->release(); - } else if (QPixmapCache::find(strKey, pixmap)) { - if (iter != qmlActivePixmapReplies()->end()) { - status = (*iter)->status(); - if (errorString) - *errorString = (*iter)->errorString(); - (*iter)->release(); - } else if (pixmap->isNull()) { - status = QDeclarativePixmapReply::Error; - if (errorString) - *errorString = tr("Unknown Error loading %1").arg(url.toString()); - } else { - status = QDeclarativePixmapReply::Ready; - } - } else if (iter != qmlActivePixmapReplies()->end()) { - status = QDeclarativePixmapReply::Loading; - } - if (impsize) { - QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url); - if (iter != qmlOriginalSizes()->end()) - *impsize = *iter; - } - return status; + if (!async) { + bool ok = false; + d = createPixmapDataSync(engine, url, requestSize, &ok); + if (ok) { + d->addToCache(); + return; + } + if (d) // loadable, but encountered error while loading + return; + } + + if (!engine) + return; + + QDeclarativePixmapReader *reader = QDeclarativePixmapReader::instance(engine); + + d = new QDeclarativePixmapData(url, requestSize); + d->addToCache(); + + d->reply = reader->getImage(d); + } else { + d = *iter; + d->addref(); + } } -/*! - Starts a network request to load \a url. +void QDeclarativePixmap::clear() +{ + if (d) { + d->release(); + d = 0; + } +} - Returns a QDeclarativePixmapReply. Caller should connect to QDeclarativePixmapReply::finished() - and call get() when the image is available. +void QDeclarativePixmap::clear(QObject *obj) +{ + if (d) { + if (d->reply) + QObject::disconnect(d->reply, 0, obj, 0); + d->release(); + d = 0; + } +} - The returned QDeclarativePixmapReply will be deleted when all request() calls are - matched by a corresponding get() call. -*/ -QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url, int req_width, int req_height) +bool QDeclarativePixmap::connectFinished(QObject *object, const char *method) { - QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); - if (iter == qmlActivePixmapReplies()->end()) { - QDeclarativeImageReader *reader = QDeclarativeImageReader::instance(engine); - QDeclarativePixmapReply *item = reader->getImage(url, req_width, req_height); - iter = qmlActivePixmapReplies()->insert(url, item); - } else { - (*iter)->addRef(); + if (!d || !d->reply) { + qWarning("QDeclarativePixmap: connectFinished() called when not loading."); + return false; } - return (*iter); + return QObject::connect(d->reply, SIGNAL(finished()), object, method); } -/*! - Cancels a previous call to request(). +bool QDeclarativePixmap::connectFinished(QObject *object, int method) +{ + if (!d || !d->reply) { + qWarning("QDeclarativePixmap: connectFinished() called when not loading."); + return false; + } - May also cancel loading (eg. if no other pending request). + return QMetaObject::connect(d->reply, QDeclarativePixmapReply::finishedIndex, object, method); +} - Any connections from the QDeclarativePixmapReply returned by request() to \a obj will be - disconnected. -*/ -void QDeclarativePixmapCache::cancel(const QUrl& url, QObject *obj) +bool QDeclarativePixmap::connectDownloadProgress(QObject *object, const char *method) { - QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); - if (iter == qmlActivePixmapReplies()->end()) - return; + if (!d || !d->reply) { + qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading."); + return false; + } - QDeclarativePixmapReply *reply = *iter; - if (obj) - QObject::disconnect(reply, 0, obj, 0); - reply->release(); + return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method); } -/*! - This function is mainly for test verification. It returns the number of - requests that are still unfinished. -*/ -int QDeclarativePixmapCache::pendingRequests() +bool QDeclarativePixmap::connectDownloadProgress(QObject *object, int method) { - return qmlActivePixmapReplies()->count(); + if (!d || !d->reply) { + qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading."); + return false; + } + + return QMetaObject::connect(d->reply, QDeclarativePixmapReply::downloadProgressIndex, object, method); } QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h index 33d9de1..b4d88bd 100644 --- a/src/declarative/util/qdeclarativepixmapcache_p.h +++ b/src/declarative/util/qdeclarativepixmapcache_p.h @@ -42,69 +42,70 @@ #ifndef QDECLARATIVEPIXMAPCACHE_H #define QDECLARATIVEPIXMAPCACHE_H -#include <QtCore/QString> -#include <QtGui/QPixmap> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qstring.h> +#include <QtGui/qpixmap.h> #include <QtCore/qurl.h> -#include <QtCore/QCoreApplication> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QDeclarativeEngine; -class QNetworkReply; -class QDeclarativeImageReader; -class QDeclarativePixmapReplyPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativePixmapReply : public QObject +class QDeclarativeEngine; +class QDeclarativePixmapData; +class Q_DECLARATIVE_EXPORT QDeclarativePixmap { - Q_OBJECT + Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmap) public: - ~QDeclarativePixmapReply(); + QDeclarativePixmap(); + QDeclarativePixmap(QDeclarativeEngine *, const QUrl &); + QDeclarativePixmap(QDeclarativeEngine *, const QUrl &, const QSize &); + ~QDeclarativePixmap(); - enum Status { Ready, Error, Unrequested, Loading }; - Status status() const; - QString errorString() const; + enum Status { Null, Ready, Error, Loading }; + bool isNull() const; + bool isReady() const; + bool isError() const; + bool isLoading() const; + + Status status() const; + QString error() const; const QUrl &url() const; - int forcedWidth() const; - int forcedHeight() const; - QSize implicitSize() const; + const QSize &implicitSize() const; + const QSize &requestSize() const; + const QPixmap &pixmap() const; + void setPixmap(const QPixmap &); -Q_SIGNALS: - void finished(); - void downloadProgress(qint64, qint64); + QRect rect() const; + int width() const; + int height() const; + inline operator const QPixmap &() const; -protected: - bool event(QEvent *event); + void load(QDeclarativeEngine *, const QUrl &); + void load(QDeclarativeEngine *, const QUrl &, bool); + void load(QDeclarativeEngine *, const QUrl &, const QSize &); + void load(QDeclarativeEngine *, const QUrl &, const QSize &, bool); -private: - void addRef(); - bool release(bool defer=false); - bool isLoading() const; - void setLoading(); + void clear(); + void clear(QObject *); + + bool connectFinished(QObject *, const char *); + bool connectFinished(QObject *, int); + bool connectDownloadProgress(QObject *, const char *); + bool connectDownloadProgress(QObject *, int); private: - QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height); - Q_DISABLE_COPY(QDeclarativePixmapReply) - Q_DECLARE_PRIVATE(QDeclarativePixmapReply) - friend class QDeclarativeImageRequestHandler; - friend class QDeclarativeImageReader; - friend class QDeclarativePixmapCache; + Q_DISABLE_COPY(QDeclarativePixmap); + QDeclarativePixmapData *d; }; -class Q_DECLARATIVE_EXPORT QDeclarativePixmapCache +inline QDeclarativePixmap::operator const QPixmap &() const { - Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmapCache) -public: - static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, QString *errorString, QSize *impsize=0, bool async=false, int req_width=0, int req_height=0); - static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url, int req_width=0, int req_height=0); - static void cancel(const QUrl& url, QObject *obj); - static int pendingRequests(); -}; - - + return pixmap(); +} QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 8e3ec82..12c6353 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE an Item's parent should be done using the associated change elements (ParentChange and AnchorChanges, respectively). - \sa {qmlstate}{States}, QtDeclarative + \sa {declarative/animation/states}{states example}, {qmlstate}{States}, QtDeclarative */ /*! diff --git a/src/declarative/util/qdeclarativepropertychanges_p.h b/src/declarative/util/qdeclarativepropertychanges_p.h index c2ed466..8578086 100644 --- a/src/declarative/util/qdeclarativepropertychanges_p.h +++ b/src/declarative/util/qdeclarativepropertychanges_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativePropertyChangesPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation +class Q_AUTOTEST_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyChanges) @@ -79,6 +79,9 @@ public: class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser { public: + QDeclarativePropertyChangesParser() + : QDeclarativeCustomParser(AcceptsAttachedProperties) {} + void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QDeclarativeCustomParserProperty &prop); virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &); diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp index 6b6df4d..5d47c30 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation.cpp +++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp @@ -307,7 +307,7 @@ Rectangle { set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity of 0.5 will take 2000 ms to complete. - \sa SpringFollow, {QML Animation}, {declarative/animation/basics}{Animation basics example} + \sa {QML Animation}, {declarative/animation/basics}{Animation basics example} */ QDeclarativeSmoothedAnimation::QDeclarativeSmoothedAnimation(QObject *parent) diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h index f45d19f..8b51209 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation_p.h +++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h @@ -55,7 +55,7 @@ QT_MODULE(Declarative) class QDeclarativeProperty; class QDeclarativeSmoothedAnimationPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation +class Q_AUTOTEST_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation) diff --git a/src/declarative/util/qdeclarativesmoothedfollow.cpp b/src/declarative/util/qdeclarativesmoothedfollow.cpp deleted file mode 100644 index f70df9d..0000000 --- a/src/declarative/util/qdeclarativesmoothedfollow.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativesmoothedfollow_p.h" -#include "qdeclarativesmoothedanimation_p_p.h" - -#include <private/qobject_p.h> -#include <QtCore/qnumeric.h> - -#include "qdeclarativeglobal_p.h" - - -QT_BEGIN_NAMESPACE - -class QDeclarativeSmoothedFollowPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeSmoothedFollow) -public: - QDeclarativeSmoothedFollowPrivate(); - - bool enabled; - QSmoothedAnimation *anim; -}; - -/*! - \qmlclass SmoothedFollow QDeclarativeSmoothedFollow - \since 4.7 - \inherits NumberAnimation - \brief The SmoothedFollow element allows a property to smoothly track a value. - - The SmoothedFollow animates a property's value to a set target value - using an ease in/out quad easing curve. If the animation is restarted - with a different target value, the easing curves used to animate to the old - and the new target values are smoothly spliced together to avoid any obvious - visual glitches by maintaining the current velocity. - - The property animation is configured by setting the velocity at which the - animation should occur, or the duration that the animation should take. - If both a velocity and a duration are specified, the one that results in - the quickest animation is chosen for each change in the target value. - - For example, animating from 0 to 800 will take 4 seconds if a velocity - of 200 is set, will take 8 seconds with a duration of 8000 set, and will - take 4 seconds with both a velocity of 200 and a duration of 8000 set. - Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, - will take 8 seconds with a duration of 8000 set, and will take 8 seconds - with both a velocity of 200 and a duration of 8000 set. - - The follow example shows one rectangle tracking the position of another. -\code -import Qt 4.7 - -Rectangle { - width: 800; height: 600; color: "blue" - - Rectangle { - color: "green" - width: 60; height: 60; - SmoothedFollow on x { to: rect1.x - 5; velocity: 200 } - SmoothedFollow on y { to: rect1.y - 5; velocity: 200 } - } - - Rectangle { - id: rect1 - color: "red" - width: 50; height: 50; - } - - focus: true - Keys.onRightPressed: rect1.x = rect1.x + 100 - Keys.onLeftPressed: rect1.x = rect1.x - 100 - Keys.onUpPressed: rect1.y = rect1.y - 100 - Keys.onDownPressed: rect1.y = rect1.y + 100 -} -\endcode - - The default velocity of SmoothedFollow is 200 units/second. Note that if the range of the - value being animated is small, then the velocity will need to be adjusted - appropriately. For example, the opacity of an item ranges from 0 - 1.0. - To enable a smooth animation in this range the velocity will need to be - set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity - of 0.5 will take 2000 ms to complete. - - \sa SpringFollow -*/ - -QDeclarativeSmoothedFollow::QDeclarativeSmoothedFollow(QObject *parent) - : QObject(*(new QDeclarativeSmoothedFollowPrivate), parent) -{ -} - -QDeclarativeSmoothedFollow::~QDeclarativeSmoothedFollow() -{ -} - -QDeclarativeSmoothedFollowPrivate::QDeclarativeSmoothedFollowPrivate() - : enabled(true), anim(new QSmoothedAnimation) -{ - Q_Q(QDeclarativeSmoothedFollow); - QDeclarative_setParent_noEvent(anim, q); -} - -/*! - \qmlproperty enumeration SmoothedFollow::reversingMode - - Sets how the SmoothedFollow behaves if an animation direction is reversed. - - If reversing mode is \c SmoothedFollow.Eased, the animation will smoothly decelerate, and - then reverse direction. If the reversing mode is \c SmoothedFollow.Immediate, the - animation will immediately begin accelerating in the reverse direction, - begining with a velocity of 0. If the reversing mode is \c SmoothedFollow.Sync, the - property is immediately set to the target value. -*/ -QDeclarativeSmoothedFollow::ReversingMode QDeclarativeSmoothedFollow::reversingMode() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return (ReversingMode) d->anim->reversingMode; -} - -void QDeclarativeSmoothedFollow::setReversingMode(ReversingMode m) -{ - Q_D(QDeclarativeSmoothedFollow); - if (d->anim->reversingMode == (QDeclarativeSmoothedAnimation::ReversingMode) m) - return; - - d->anim->reversingMode = (QDeclarativeSmoothedAnimation::ReversingMode) m; - emit reversingModeChanged(); -} - -/*! - \qmlproperty int SmoothedFollow::duration - - This property holds the animation duration, in msecs, used when tracking the source. - - Setting this to -1 (the default) disables the duration value. -*/ -int QDeclarativeSmoothedFollow::duration() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return d->anim->userDuration; -} - -void QDeclarativeSmoothedFollow::setDuration(int duration) -{ - Q_D(QDeclarativeSmoothedFollow); - if (duration == d->anim->duration()) - return; - - d->anim->userDuration = duration; - emit durationChanged(); -} - -qreal QDeclarativeSmoothedFollow::velocity() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return d->anim->velocity; -} - -/*! - \qmlproperty real SmoothedFollow::velocity - - This property holds the average velocity allowed when tracking the 'to' value. - - The default velocity of SmoothedFollow is 200 units/second. - - Setting this to -1 disables the velocity value. -*/ -void QDeclarativeSmoothedFollow::setVelocity(qreal v) -{ - Q_D(QDeclarativeSmoothedFollow); - if (d->anim->velocity == v) - return; - - d->anim->velocity = v; - emit velocityChanged(); -} - -/*! - \qmlproperty int SmoothedFollow::maximumEasingTime - - This property specifies the maximum time, in msecs, an "eases" during the follow should take. - Setting this property causes the velocity to "level out" after at a time. Setting - a negative value reverts to the normal mode of easing over the entire animation - duration. - - The default value is -1. -*/ -int QDeclarativeSmoothedFollow::maximumEasingTime() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return d->anim->maximumEasingTime; -} - -void QDeclarativeSmoothedFollow::setMaximumEasingTime(int v) -{ - Q_D(QDeclarativeSmoothedFollow); - d->anim->maximumEasingTime = v; - emit maximumEasingTimeChanged(); -} - -/*! - \qmlproperty real SmoothedFollow::to - This property holds the ending value. - If not set, then the value defined in the end state of the transition or Behavior. -*/ -qreal QDeclarativeSmoothedFollow::to() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return d->anim->to; -} - -void QDeclarativeSmoothedFollow::setTo(qreal t) -{ - Q_D(QDeclarativeSmoothedFollow); - - if (qIsNaN(t)) - return; - - if (d->anim->to == t) - return; - - d->anim->to = t; - - if (d->enabled) - d->anim->restart(); -} - -/*! - \qmlproperty bool SmoothedFollow::enabled - This property whether this animation should automatically restart when - the 'to' property is upated. - - The default value of this property is 'true'. -*/ -bool QDeclarativeSmoothedFollow::enabled() const -{ - Q_D(const QDeclarativeSmoothedFollow); - return d->enabled; -} - -void QDeclarativeSmoothedFollow::setEnabled(bool e) -{ - Q_D(QDeclarativeSmoothedFollow); - if (d->enabled == e) - return; - d->enabled = e; - - if (d->enabled) - d->anim->restart(); - else - d->anim->stop(); - emit enabledChanged(); -} - -void QDeclarativeSmoothedFollow::setTarget(const QDeclarativeProperty &t) -{ - Q_D(QDeclarativeSmoothedFollow); - d->anim->target = t; -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativesmoothedfollow_p.h b/src/declarative/util/qdeclarativesmoothedfollow_p.h deleted file mode 100644 index 6319192..0000000 --- a/src/declarative/util/qdeclarativesmoothedfollow_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVESMOOTHEDFOLLOW_H -#define QDECLARATIVESMOOTHEDFOLLOW_H - -#include <qdeclarative.h> -#include <qdeclarativepropertyvaluesource.h> - -#include <QtCore/qobject.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QDeclarativeProperty; -class QDeclarativeSmoothedFollowPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedFollow : public QObject, - public QDeclarativePropertyValueSource -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeSmoothedFollow) - Q_INTERFACES(QDeclarativePropertyValueSource) - Q_ENUMS(ReversingMode) - - Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) - Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged) - Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged) - Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged) - Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) - -public: - enum ReversingMode { Eased, Immediate, Sync }; - - QDeclarativeSmoothedFollow(QObject *parent = 0); - ~QDeclarativeSmoothedFollow(); - - qreal to() const; - void setTo(qreal); - - ReversingMode reversingMode() const; - void setReversingMode(ReversingMode); - - int duration() const; - void setDuration(int); - - qreal velocity() const; - void setVelocity(qreal); - - int maximumEasingTime() const; - void setMaximumEasingTime(int); - - bool enabled() const; - void setEnabled(bool); - - virtual void setTarget(const QDeclarativeProperty &); - -Q_SIGNALS: - void velocityChanged(); - void durationChanged(); - void reversingModeChanged(); - void maximumEasingTimeChanged(); - void enabledChanged(); -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QDeclarativeSmoothedFollow) - -QT_END_HEADER - -#endif // QDECLARATIVESMOOTHEDFOLLOW_H diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringanimation.cpp index aae66ac..4cf2fc0 100644 --- a/src/declarative/util/qdeclarativespringfollow.cpp +++ b/src/declarative/util/qdeclarativespringanimation.cpp @@ -39,9 +39,10 @@ ** ****************************************************************************/ -#include "private/qdeclarativespringfollow_p.h" +#include "private/qdeclarativespringanimation_p.h" #include "private/qdeclarativeanimation_p_p.h" +#include <qdeclarativeproperty_p.h> #include <QtCore/qdebug.h> @@ -54,18 +55,20 @@ QT_BEGIN_NAMESPACE -class QDeclarativeSpringFollowPrivate : public QObjectPrivate +class QDeclarativeSpringAnimationPrivate : public QDeclarativeAbstractAnimationPrivate { - Q_DECLARE_PUBLIC(QDeclarativeSpringFollow) + Q_DECLARE_PUBLIC(QDeclarativeSpringAnimation) public: - QDeclarativeSpringFollowPrivate() - : currentValue(0), to(0), maxVelocity(0), lastTime(0) + QDeclarativeSpringAnimationPrivate() + : currentValue(0), to(0), from(0), maxVelocity(0), lastTime(0) , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.01) - , modulus(0.0), useMass(false), haveModulus(false), enabled(true), mode(Track), clock(this) {} + , modulus(0.0), useMass(false), haveModulus(false), enabled(true) + , fromDefined(false), toDefined(false) + , mode(Track), clock(this) {} - QDeclarativeProperty property; qreal currentValue; qreal to; + qreal from; qreal maxVelocity; qreal velocityms; int lastTime; @@ -79,6 +82,8 @@ public: bool useMass : 1; bool haveModulus : 1; bool enabled : 1; + bool fromDefined : 1; + bool toDefined : 1; enum Mode { Track, @@ -89,20 +94,24 @@ public: void tick(int); void updateMode(); - void start(); - void stop(); - QTickAnimationProxy<QDeclarativeSpringFollowPrivate, &QDeclarativeSpringFollowPrivate::tick> clock; + QTickAnimationProxy<QDeclarativeSpringAnimationPrivate, &QDeclarativeSpringAnimationPrivate::tick> clock; }; -void QDeclarativeSpringFollowPrivate::tick(int time) +void QDeclarativeSpringAnimationPrivate::tick(int time) { - Q_Q(QDeclarativeSpringFollow); + if (mode == Track) { + clock.stop(); + return; + } int elapsed = time - lastTime; if (!elapsed) return; qreal srcVal = to; + + bool stop = false; + if (haveModulus) { currentValue = fmod(currentValue, modulus); srcVal = fmod(srcVal, modulus); @@ -142,7 +151,7 @@ void QDeclarativeSpringFollowPrivate::tick(int time) if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) { velocity = 0.0; currentValue = srcVal; - clock.stop(); + stop = true; } lastTime = time - (elapsed - count * 16); } else { @@ -160,7 +169,7 @@ void QDeclarativeSpringFollowPrivate::tick(int time) currentValue = fmod(currentValue, modulus); if (currentValue > to) { currentValue = to; - clock.stop(); + stop = true; } } else { currentValue -= moveBy; @@ -168,18 +177,23 @@ void QDeclarativeSpringFollowPrivate::tick(int time) currentValue = fmod(currentValue, modulus) + modulus; if (currentValue < to) { currentValue = to; - clock.stop(); + stop = true; } } lastTime = time; } - property.write(currentValue); - emit q->valueChanged(currentValue); - if (clock.state() != QAbstractAnimation::Running) - emit q->syncChanged(); + + qreal old_to = to; + + QDeclarativePropertyPrivate::write(defaultProperty, currentValue, + QDeclarativePropertyPrivate::BypassInterceptor | + QDeclarativePropertyPrivate::DontRemoveBinding); + + if (stop && old_to == to) // do not stop if we got restarted + clock.stop(); } -void QDeclarativeSpringFollowPrivate::updateMode() +void QDeclarativeSpringAnimationPrivate::updateMode() { if (spring == 0. && maxVelocity == 0.) mode = Track; @@ -189,121 +203,105 @@ void QDeclarativeSpringFollowPrivate::updateMode() mode = Velocity; } -void QDeclarativeSpringFollowPrivate::start() -{ - if (!enabled) - return; +/*! + \qmlclass SpringAnimation QDeclarativeSpringAnimation + \since 4.7 - Q_Q(QDeclarativeSpringFollow); - if (mode == QDeclarativeSpringFollowPrivate::Track) { - currentValue = to; - property.write(currentValue); - } else if (to != currentValue && clock.state() != QAbstractAnimation::Running) { - lastTime = 0; - currentValue = property.read().toReal(); - clock.start(); // infinity?? - emit q->syncChanged(); - } -} + \brief The SpringAnimation element allows a property to track a value in a spring-like motion + + SpringAnimation mimics the oscillatory behavior of a spring, with the appropriate \l spring constant to + control the acceleration and the \l damping to control how quickly the effect dies away. + + You can also limit the maximum \l velocity of the animation. -void QDeclarativeSpringFollowPrivate::stop() -{ - clock.stop(); -} -/*! - \qmlclass SpringFollow QDeclarativeSpringFollow - \since 4.7 - \brief The SpringFollow element allows a property to track a value. - - In example below, \e rect2 will follow \e rect1 moving with a velocity of up to 200: - \code - Rectangle { - id: rect1 - width: 20; height: 20 - color: "#00ff00" - y: 200 // initial value - SequentialAnimation on y { - loops: Animation.Infinite - NumberAnimation { - to: 200 - easing.type: Easing.OutBounce - easing.amplitude: 100 - duration: 2000 - } - PauseAnimation { duration: 1000 } - } - } - Rectangle { - id: rect2 - x: rect1.width - width: 20; height: 20 - color: "#ff0000" - SpringFollow on y { to: rect1.y; velocity: 200 } - } - \endcode */ -QDeclarativeSpringFollow::QDeclarativeSpringFollow(QObject *parent) -: QObject(*(new QDeclarativeSpringFollowPrivate),parent) +QDeclarativeSpringAnimation::QDeclarativeSpringAnimation(QObject *parent) +: QDeclarativeAbstractAnimation(*(new QDeclarativeSpringAnimationPrivate),parent) { } -QDeclarativeSpringFollow::~QDeclarativeSpringFollow() +QDeclarativeSpringAnimation::~QDeclarativeSpringAnimation() { } -void QDeclarativeSpringFollow::setTarget(const QDeclarativeProperty &property) +void QDeclarativeSpringAnimation::setTarget(const QDeclarativeProperty &property) { - Q_D(QDeclarativeSpringFollow); - d->property = property; + Q_D(QDeclarativeSpringAnimation); + d->defaultProperty = property; d->currentValue = property.read().toReal(); + if (!d->avoidPropertyValueSourceStart) { + setRunning(true); + } } -qreal QDeclarativeSpringFollow::to() const +qreal QDeclarativeSpringAnimation::to() const { - Q_D(const QDeclarativeSpringFollow); - return d->to; + Q_D(const QDeclarativeSpringAnimation); + return d->toDefined ? d->to : 0; } /*! - \qmlproperty real SpringFollow::to - This property holds the target value which will be tracked. - - Bind to a property in order to track its changes. + \qmlproperty real SpringAnimation::to */ -void QDeclarativeSpringFollow::setTo(qreal value) +void QDeclarativeSpringAnimation::setTo(qreal value) { - Q_D(QDeclarativeSpringFollow); - if (d->clock.state() == QAbstractAnimation::Running && d->to == value) + Q_D(QDeclarativeSpringAnimation); + if (d->to == value) return; d->to = value; - d->start(); + d->toDefined = true; + d->lastTime = 0; + emit toChanged(value); +} + +qreal QDeclarativeSpringAnimation::from() const +{ + Q_D(const QDeclarativeSpringAnimation); + return d->fromDefined ? d->from : 0; } /*! - \qmlproperty real SpringFollow::velocity + \qmlproperty real SpringAnimation::from +*/ + +void QDeclarativeSpringAnimation::setFrom(qreal value) +{ + Q_D(QDeclarativeSpringAnimation); + if (d->from == value) + return; + + d->currentValue = d->from = value; + d->fromDefined = true; + d->lastTime = 0; + emit fromChanged(value); +} + + +/*! + \qmlproperty real SpringAnimation::velocity This property holds the maximum velocity allowed when tracking the source. */ -qreal QDeclarativeSpringFollow::velocity() const +qreal QDeclarativeSpringAnimation::velocity() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->maxVelocity; } -void QDeclarativeSpringFollow::setVelocity(qreal velocity) +void QDeclarativeSpringAnimation::setVelocity(qreal velocity) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); d->maxVelocity = velocity; d->velocityms = velocity / 1000.0; d->updateMode(); } /*! - \qmlproperty real SpringFollow::spring + \qmlproperty real SpringAnimation::spring This property holds the spring constant The spring constant describes how strongly the target is pulled towards the @@ -312,35 +310,35 @@ void QDeclarativeSpringFollow::setVelocity(qreal velocity) When a spring constant is set and the velocity property is greater than 0, velocity limits the maximum speed. */ -qreal QDeclarativeSpringFollow::spring() const +qreal QDeclarativeSpringAnimation::spring() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->spring; } -void QDeclarativeSpringFollow::setSpring(qreal spring) +void QDeclarativeSpringAnimation::setSpring(qreal spring) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); d->spring = spring; d->updateMode(); } /*! - \qmlproperty real SpringFollow::damping + \qmlproperty real SpringAnimation::damping This property holds the spring damping constant The damping constant describes how quickly a sprung follower comes to rest. Useful range is 0 - 1.0 */ -qreal QDeclarativeSpringFollow::damping() const +qreal QDeclarativeSpringAnimation::damping() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->damping; } -void QDeclarativeSpringFollow::setDamping(qreal damping) +void QDeclarativeSpringAnimation::setDamping(qreal damping) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); if (damping > 1.) damping = 1.; @@ -349,7 +347,7 @@ void QDeclarativeSpringFollow::setDamping(qreal damping) /*! - \qmlproperty real SpringFollow::epsilon + \qmlproperty real SpringAnimation::epsilon This property holds the spring epsilon The epsilon is the rate and amount of change in the value which is close enough @@ -358,34 +356,34 @@ void QDeclarativeSpringFollow::setDamping(qreal damping) The default is 0.01. Tuning this value can provide small performance improvements. */ -qreal QDeclarativeSpringFollow::epsilon() const +qreal QDeclarativeSpringAnimation::epsilon() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->epsilon; } -void QDeclarativeSpringFollow::setEpsilon(qreal epsilon) +void QDeclarativeSpringAnimation::setEpsilon(qreal epsilon) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); d->epsilon = epsilon; } /*! - \qmlproperty real SpringFollow::modulus + \qmlproperty real SpringAnimation::modulus This property holds the modulus value. Setting a \a modulus forces the target value to "wrap around" at the modulus. For example, setting the modulus to 360 will cause a value of 370 to wrap around to 10. */ -qreal QDeclarativeSpringFollow::modulus() const +qreal QDeclarativeSpringAnimation::modulus() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->modulus; } -void QDeclarativeSpringFollow::setModulus(qreal modulus) +void QDeclarativeSpringAnimation::setModulus(qreal modulus) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); if (d->modulus != modulus) { d->haveModulus = modulus != 0.0; d->modulus = modulus; @@ -394,21 +392,21 @@ void QDeclarativeSpringFollow::setModulus(qreal modulus) } /*! - \qmlproperty real SpringFollow::mass + \qmlproperty real SpringAnimation::mass This property holds the "mass" of the property being moved. mass is 1.0 by default. Setting a different mass changes the dynamics of a \l spring follow. */ -qreal QDeclarativeSpringFollow::mass() const +qreal QDeclarativeSpringAnimation::mass() const { - Q_D(const QDeclarativeSpringFollow); + Q_D(const QDeclarativeSpringAnimation); return d->mass; } -void QDeclarativeSpringFollow::setMass(qreal mass) +void QDeclarativeSpringAnimation::setMass(qreal mass) { - Q_D(QDeclarativeSpringFollow); + Q_D(QDeclarativeSpringAnimation); if (d->mass != mass && mass > 0.0) { d->useMass = mass != 1.0; d->mass = mass; @@ -416,49 +414,33 @@ void QDeclarativeSpringFollow::setMass(qreal mass) } } -/*! - \qmlproperty bool SpringFollow::enabled - This property holds whether the target will track the source. - - The default value of this property is 'true'. -*/ -bool QDeclarativeSpringFollow::enabled() const -{ - Q_D(const QDeclarativeSpringFollow); - return d->enabled; -} - -void QDeclarativeSpringFollow::setEnabled(bool enabled) +void QDeclarativeSpringAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) { - Q_D(QDeclarativeSpringFollow); - d->enabled = enabled; - if (enabled) - d->start(); - else - d->stop(); + Q_D(QDeclarativeSpringAnimation); + Q_UNUSED(direction); + + if (d->clock.state() != QAbstractAnimation::Running) + d->lastTime = 0; + + if (!actions.isEmpty()) { + for (int i = 0; i < actions.size(); ++i) { + if (!d->toDefined) + d->to = actions.at(i).toValue.toReal(); + if (!d->fromDefined) + d->currentValue = actions.at(i).fromValue.toReal(); + if (d->mode != QDeclarativeSpringAnimationPrivate::Track) + modified << d->defaultProperty; + } + } } -/*! - \qmlproperty bool SpringFollow::inSync - This property is true when target is equal to the source; otherwise - false. If inSync is true the target is not being animated. - If \l enabled is false then inSync will also be false. -*/ -bool QDeclarativeSpringFollow::inSync() const -{ - Q_D(const QDeclarativeSpringFollow); - return d->enabled && d->clock.state() != QAbstractAnimation::Running; -} - -/*! - \qmlproperty real SpringFollow::value - The current value. -*/ -qreal QDeclarativeSpringFollow::value() const +QAbstractAnimation *QDeclarativeSpringAnimation::qtAnimation() { - Q_D(const QDeclarativeSpringFollow); - return d->currentValue; + Q_D(QDeclarativeSpringAnimation); + return &d->clock; } QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativespringfollow_p.h b/src/declarative/util/qdeclarativespringanimation_p.h index b829c57..6f574ef 100644 --- a/src/declarative/util/qdeclarativespringfollow_p.h +++ b/src/declarative/util/qdeclarativespringanimation_p.h @@ -39,11 +39,13 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVESMOOTHFOLLOW_H -#define QDECLARATIVESMOOTHFOLLOW_H +#ifndef QDECLARATIVESPRINGANIMATION_H +#define QDECLARATIVESPRINGANIMATION_H -#include <qdeclarativepropertyvaluesource.h> #include <qdeclarative.h> +#include "private/qdeclarativeanimation_p.h" + +#include <QtCore/qobject.h> QT_BEGIN_HEADER @@ -51,34 +53,34 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QDeclarativeSpringFollowPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeSpringFollow : public QObject, - public QDeclarativePropertyValueSource +class QDeclarativeSpringAnimationPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeSpringAnimation : public QDeclarativeAbstractAnimation { Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeSpringFollow) + Q_DECLARE_PRIVATE(QDeclarativeSpringAnimation) Q_INTERFACES(QDeclarativePropertyValueSource) - Q_PROPERTY(qreal to READ to WRITE setTo) + Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) + Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged) Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity) Q_PROPERTY(qreal spring READ spring WRITE setSpring) Q_PROPERTY(qreal damping READ damping WRITE setDamping) Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) - Q_PROPERTY(qreal value READ value NOTIFY valueChanged) Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged) Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged) - Q_PROPERTY(bool inSync READ inSync NOTIFY syncChanged) public: - QDeclarativeSpringFollow(QObject *parent=0); - ~QDeclarativeSpringFollow(); + QDeclarativeSpringAnimation(QObject *parent=0); + ~QDeclarativeSpringAnimation(); virtual void setTarget(const QDeclarativeProperty &); qreal to() const; void setTo(qreal value); + qreal from() const; + void setFrom(qreal value); + qreal velocity() const; void setVelocity(qreal velocity); @@ -100,12 +102,16 @@ public: bool enabled() const; void setEnabled(bool enabled); - bool inSync() const; + virtual void transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction); - qreal value() const; +protected: + virtual QAbstractAnimation *qtAnimation(); Q_SIGNALS: - void valueChanged(qreal); + void toChanged(qreal); + void fromChanged(qreal); void modulusChanged(); void massChanged(); void syncChanged(); @@ -113,8 +119,8 @@ Q_SIGNALS: QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeSpringFollow) +QML_DECLARE_TYPE(QDeclarativeSpringAnimation) QT_END_HEADER -#endif // QDECLARATIVESMOOTHFOLLOW_H +#endif // QDECLARATIVESPRINGANIMATION_H diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h index 05ad052..4f905b6 100644 --- a/src/declarative/util/qdeclarativestateoperations_p.h +++ b/src/declarative/util/qdeclarativestateoperations_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeParentChangePrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeParentChange : public QDeclarativeStateOperation, public QDeclarativeActionEvent +class Q_AUTOTEST_EXPORT QDeclarativeParentChange : public QDeclarativeStateOperation, public QDeclarativeActionEvent { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeParentChange) @@ -118,7 +118,7 @@ public: }; class QDeclarativeStateChangeScriptPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeStateChangeScript : public QDeclarativeStateOperation, public QDeclarativeActionEvent +class Q_AUTOTEST_EXPORT QDeclarativeStateChangeScript : public QDeclarativeStateOperation, public QDeclarativeActionEvent { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeStateChangeScript) @@ -251,7 +251,7 @@ private: }; class QDeclarativeAnchorChangesPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent +class Q_AUTOTEST_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAnchorChanges) diff --git a/src/declarative/util/qdeclarativestyledtext.cpp b/src/declarative/util/qdeclarativestyledtext.cpp index babd71b..91566bc 100644 --- a/src/declarative/util/qdeclarativestyledtext.cpp +++ b/src/declarative/util/qdeclarativestyledtext.cpp @@ -152,8 +152,6 @@ void QDeclarativeStyledTextPrivate::parse() QTextCharFormat format; if (formatStack.count()) format = formatStack.top(); - else - format.setFont(baseFont); if (parseTag(ch, text, drawText, format)) formatStack.push(format); } @@ -198,8 +196,10 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te if (char0 == QLatin1Char('b')) { if (tagLength == 1) format.setFontWeight(QFont::Bold); - else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) + else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) { textOut.append(QChar(QChar::LineSeparator)); + return false; + } } else if (char0 == QLatin1Char('i')) { if (tagLength == 1) format.setFontItalic(true); diff --git a/src/declarative/util/qdeclarativestyledtext_p.h b/src/declarative/util/qdeclarativestyledtext_p.h index 8d2c42d..d80ff9d 100644 --- a/src/declarative/util/qdeclarativestyledtext_p.h +++ b/src/declarative/util/qdeclarativestyledtext_p.h @@ -52,7 +52,7 @@ class QString; class QDeclarativeStyledTextPrivate; class QTextLayout; -class Q_DECLARATIVE_EXPORT QDeclarativeStyledText +class Q_AUTOTEST_EXPORT QDeclarativeStyledText { public: static void parse(const QString &string, QTextLayout &layout); diff --git a/src/declarative/util/qdeclarativesystempalette_p.h b/src/declarative/util/qdeclarativesystempalette_p.h index 9fa6b08..4dfbeff 100644 --- a/src/declarative/util/qdeclarativesystempalette_p.h +++ b/src/declarative/util/qdeclarativesystempalette_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeSystemPalettePrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeSystemPalette : public QObject +class Q_AUTOTEST_EXPORT QDeclarativeSystemPalette : public QObject { Q_OBJECT Q_ENUMS(ColorGroup) diff --git a/src/declarative/util/qdeclarativetimer.cpp b/src/declarative/util/qdeclarativetimer.cpp index 9e18eb5..576995f 100644 --- a/src/declarative/util/qdeclarativetimer.cpp +++ b/src/declarative/util/qdeclarativetimer.cpp @@ -103,6 +103,8 @@ public: 1000ms has its \e repeat property changed 500ms after starting, the elapsed time will be reset to 0, and the Timer will be triggered 1000ms later. + + \sa {declarative/toys/clocks}{Clocks example} */ QDeclarativeTimer::QDeclarativeTimer(QObject *parent) diff --git a/src/declarative/util/qdeclarativetimer_p.h b/src/declarative/util/qdeclarativetimer_p.h index 08c3d4e..93b0965 100644 --- a/src/declarative/util/qdeclarativetimer_p.h +++ b/src/declarative/util/qdeclarativetimer_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeTimerPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeTimer : public QObject, public QDeclarativeParserStatus +class Q_AUTOTEST_EXPORT QDeclarativeTimer : public QObject, public QDeclarativeParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeTimer) diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp index ab8b116..38ed97e 100644 --- a/src/declarative/util/qdeclarativetransition.cpp +++ b/src/declarative/util/qdeclarativetransition.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE \since 4.7 \brief The Transition element defines animated transitions that occur on state changes. - \sa {qmlstates}{States}, {state-transitions}{Transitions}, {QtDeclarative} + \sa {declarative/animation/states}{states example}, {qmlstates}{States}, {state-transitions}{Transitions}, {QtDeclarative} */ /*! diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 3cf07a7..c5bfebd 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -46,7 +46,6 @@ #include "private/qdeclarativebind_p.h" #include "private/qdeclarativeconnections_p.h" #include "private/qdeclarativesmoothedanimation_p.h" -#include "private/qdeclarativesmoothedfollow_p.h" #include "private/qdeclarativefontloader_p.h" #include "private/qdeclarativelistaccessor_p.h" #include "private/qdeclarativelistmodel_p.h" @@ -56,7 +55,7 @@ #include "private/qdeclarativepixmapcache_p.h" #include "private/qdeclarativepropertychanges_p.h" #include "qdeclarativepropertymap.h" -#include "private/qdeclarativespringfollow_p.h" +#include "private/qdeclarativespringanimation_p.h" #include "private/qdeclarativestategroup_p.h" #include "private/qdeclarativestateoperations_p.h" #include "private/qdeclarativestate_p.h" @@ -83,7 +82,6 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,7,"ColorAnimation"); qmlRegisterType<QDeclarativeConnections>("Qt",4,7,"Connections"); qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,7,"SmoothedAnimation"); - qmlRegisterType<QDeclarativeSmoothedFollow>("Qt",4,7,"SmoothedFollow"); qmlRegisterType<QDeclarativeFontLoader>("Qt",4,7,"FontLoader"); qmlRegisterType<QDeclarativeListElement>("Qt",4,7,"ListElement"); qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,7,"NumberAnimation"); @@ -97,7 +95,7 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeRotationAnimation>("Qt",4,7,"RotationAnimation"); qmlRegisterType<QDeclarativeScriptAction>("Qt",4,7,"ScriptAction"); qmlRegisterType<QDeclarativeSequentialAnimation>("Qt",4,7,"SequentialAnimation"); - qmlRegisterType<QDeclarativeSpringFollow>("Qt",4,7,"SpringFollow"); + qmlRegisterType<QDeclarativeSpringAnimation>("Qt",4,7,"SpringAnimation"); qmlRegisterType<QDeclarativeStateChangeScript>("Qt",4,7,"StateChangeScript"); qmlRegisterType<QDeclarativeStateGroup>("Qt",4,7,"StateGroup"); qmlRegisterType<QDeclarativeState>("Qt",4,7,"State"); diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 0414e65..496f2ad 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -194,45 +194,46 @@ void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, \since 4.7 \brief The QDeclarativeView class provides a widget for displaying a Qt Declarative user interface. - Any QGraphicsObject or QDeclarativeItem - created via QML can be placed on a standard QGraphicsScene and viewed with a standard - QGraphicsView. + QDeclarativeItem objects can be placed on a standard QGraphicsScene and + displayed with QGraphicsView. QDeclarativeView is a QGraphicsView subclass + provided as a convenience for displaying QML files, and connecting between + QML and C++ Qt objects. - QDeclarativeView is a QGraphicsView subclass provided as a convenience for displaying QML - files, and connecting between QML and C++ Qt objects. - - QDeclarativeView performs the following functions: + QDeclarativeView provides: \list - \o Manages QDeclarativeComponent loading and object creation. - \o Initializes QGraphicsView for optimal performance with QML: + \o Management of QDeclarativeComponent loading and object creation + \o Initialization of QGraphicsView for optimal performance with QML using these settings: \list - \o QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState); - \o QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - \o QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex); + \o QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState) + \o QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate) + \o QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex) \endlist - \o Initializes QGraphicsView for QML key handling: + \o Initialization of QGraphicsView for QML key handling using these settings: \list - \o QGraphicsView::viewport()->setFocusPolicy(Qt::NoFocus); - \o QGraphicsView::setFocusPolicy(Qt::StrongFocus); - \o QGraphicsScene::setStickyFocus(true); + \o QGraphicsView::viewport()->setFocusPolicy(Qt::NoFocus) + \o QGraphicsView::setFocusPolicy(Qt::StrongFocus) + \o QGraphicsScene::setStickyFocus(true) \endlist \endlist Typical usage: - \code - ... - QDeclarativeView *view = new QDeclarativeView(this); - vbox->addWidget(view); - QUrl url = QUrl::fromLocalFile(fileName); - view->setSource(url); + \code + QDeclarativeView *view = new QDeclarativeView; + view->setSource(QUrl::fromLocalFile("myqmlfile.qml")); view->show(); \endcode + Since QDeclarativeView is a QWidget-based class, it can be used to + display QML interfaces within QWidget-based GUI applications that do not + use the Graphics View framework. + To receive errors related to loading and executing QML with QDeclarativeView, you can connect to the statusChanged() signal and monitor for QDeclarativeView::Error. The errors are available via QDeclarativeView::errors(). + + \sa {Integrating QML with existing Qt UI code}, {Using QML in C++ Applications} */ @@ -611,7 +612,7 @@ void QDeclarativeView::timerEvent(QTimerEvent* e) } } -/*! \reimp */ +/*! \internal */ bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e) { Q_D(QDeclarativeView); diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index bfd25be..00169db 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -588,6 +588,8 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla If multiple key roles are specified, the model only adds and reload items with a combined value of all key roles that is not already present in the model. + + \sa {demos/declarative/rssnews}{RSS News demo} */ QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent) @@ -665,7 +667,7 @@ QString QDeclarativeXmlListModel::toString(int role) const \qmlproperty url XmlListModel::source The location of the XML data source. - If both source and xml are set, xml will be used. + If both \c source and \l xml are set, \l xml is used. */ QUrl QDeclarativeXmlListModel::source() const { @@ -690,7 +692,7 @@ void QDeclarativeXmlListModel::setSource(const QUrl &src) The text is assumed to be UTF-8 encoded. - If both \l source and \c xml are set, \c xml will be used. + If both \l source and \c xml are set, \c xml is used. */ QString QDeclarativeXmlListModel::xml() const { diff --git a/src/declarative/util/qdeclarativexmllistmodel_p.h b/src/declarative/util/qdeclarativexmllistmodel_p.h index 8d848c8..832847e 100644 --- a/src/declarative/util/qdeclarativexmllistmodel_p.h +++ b/src/declarative/util/qdeclarativexmllistmodel_p.h @@ -70,7 +70,7 @@ struct QDeclarativeXmlQueryResult { QStringList keyRoleResultsCache; }; -class Q_DECLARATIVE_EXPORT QDeclarativeXmlListModel : public QListModelInterface, public QDeclarativeParserStatus +class Q_AUTOTEST_EXPORT QDeclarativeXmlListModel : public QListModelInterface, public QDeclarativeParserStatus { Q_OBJECT Q_INTERFACES(QDeclarativeParserStatus) @@ -149,7 +149,7 @@ private: Q_DISABLE_COPY(QDeclarativeXmlListModel) }; -class Q_DECLARATIVE_EXPORT QDeclarativeXmlListModelRole : public QObject +class Q_AUTOTEST_EXPORT QDeclarativeXmlListModelRole : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index 04cfc68..fd57144 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -7,9 +7,8 @@ SOURCES += \ $$PWD/qdeclarativepackage.cpp \ $$PWD/qdeclarativeanimation.cpp \ $$PWD/qdeclarativesystempalette.cpp \ - $$PWD/qdeclarativespringfollow.cpp \ + $$PWD/qdeclarativespringanimation.cpp \ $$PWD/qdeclarativesmoothedanimation.cpp \ - $$PWD/qdeclarativesmoothedfollow.cpp \ $$PWD/qdeclarativestate.cpp\ $$PWD/qdeclarativetransitionmanager.cpp \ $$PWD/qdeclarativestateoperations.cpp \ @@ -38,9 +37,8 @@ HEADERS += \ $$PWD/qdeclarativeanimation_p.h \ $$PWD/qdeclarativeanimation_p_p.h \ $$PWD/qdeclarativesystempalette_p.h \ - $$PWD/qdeclarativespringfollow_p.h \ + $$PWD/qdeclarativespringanimation_p.h \ $$PWD/qdeclarativesmoothedanimation_p.h \ - $$PWD/qdeclarativesmoothedfollow_p.h \ $$PWD/qdeclarativesmoothedanimation_p_p.h \ $$PWD/qdeclarativestate_p.h\ $$PWD/qdeclarativestateoperations_p.h \ |