From c57373cdb64ad8f69909b37dd231a726b8828dc3 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 6 Aug 2009 17:40:37 +1000 Subject: Avoid locking when the QVariant type is well known --- src/declarative/qml/qmlmetatype.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 50bc676..512650f 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -798,6 +798,9 @@ QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType) { if (userType < 0) return Unknown; + if (userType == QMetaType::QObjectStar) + return Object; + QReadLocker lock(metaTypeDataLock()); QmlMetaTypeData *data = metaTypeData(); if (userType < data->objects.size() && data->objects.testBit(userType)) @@ -812,6 +815,9 @@ QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType) bool QmlMetaType::isObject(int userType) { + if (userType == QMetaType::QObjectStar) + return true; + QReadLocker lock(metaTypeDataLock()); QmlMetaTypeData *data = metaTypeData(); return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType); -- cgit v0.12 From d6843baff3f344de4c63c5559d23595dbf2bdfea Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 7 Aug 2009 13:24:28 +1000 Subject: Optimization: Use setparent_noevent. --- src/declarative/util/qmlstategroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp index 3a07fbe..bb40a8b 100644 --- a/src/declarative/util/qmlstategroup.cpp +++ b/src/declarative/util/qmlstategroup.cpp @@ -274,7 +274,7 @@ void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state, } if (oldState == 0 || newState == 0) { - if (!nullState) { nullState = new QmlState(q); } + if (!nullState) { nullState = new QmlState; QFx_setParent_noEvent(nullState, q); } if (!oldState) oldState = nullState; if (!newState) newState = nullState; } -- cgit v0.12 From 459c3f5971597f2ebcc04fcb437a297218928113 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 7 Aug 2009 14:25:16 +1000 Subject: Store QObject*'s in the QVariant data structure Rather than requiring an allocation of the "shared data" region, QObject *'s should be stored directly in the data structure. This very marginally, but measurably, improves QVariant performance. This is a manual cherry-pick of 01f6bb95151f1852020aa7b149f33c49c1229a39 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 16 +++++++++++++--- src/corelib/kernel/qvariant.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2b5ea0a..4166944 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -161,6 +161,9 @@ static void construct(QVariant::Private *x, const void *copy) case QMetaType::Float: x->data.f = copy ? *static_cast(copy) : 0.0f; break; + case QMetaType::QObjectStar: + x->data.o = copy ? *static_cast(copy) : 0; + break; case QVariant::LongLong: x->data.ll = copy ? *static_cast(copy) : Q_INT64_C(0); break; @@ -257,6 +260,7 @@ static void clear(QVariant::Private *d) case QVariant::ULongLong: case QVariant::Double: case QMetaType::Float: + case QMetaType::QObjectStar: break; case QVariant::Invalid: case QVariant::UserType: @@ -326,6 +330,7 @@ static bool isNull(const QVariant::Private *d) case QVariant::Bool: case QVariant::Double: case QMetaType::Float: + case QMetaType::QObjectStar: break; } return d->is_null; @@ -419,6 +424,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) return a->data.d == b->data.d; case QMetaType::Float: return a->data.f == b->data.f; + case QMetaType::QObjectStar: + return a->data.o == b->data.o; case QVariant::Date: return *v_cast(a) == *v_cast(b); case QVariant::Time: @@ -1048,6 +1055,9 @@ static void streamDebug(QDebug dbg, const QVariant &v) case QMetaType::Float: dbg.nospace() << qVariantValue(v); break; + case QMetaType::QObjectStar: + dbg.nospace() << qVariantValue(v); + break; case QVariant::Double: dbg.nospace() << v.toDouble(); break; @@ -1361,7 +1371,7 @@ void QVariant::create(int type, const void *copy) QVariant::~QVariant() { - if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref())) + if (d.type > Char && d.type != QMetaType::Float && d.type != QMetaType::QObjectStar && (!d.is_shared || !d.data.shared->ref.deref())) handler->clear(&d); } @@ -1377,7 +1387,7 @@ QVariant::QVariant(const QVariant &p) { if (d.is_shared) { d.data.shared->ref.ref(); - } else if (p.d.type > Char && p.d.type != QMetaType::Float) { + } else if (p.d.type > Char && p.d.type != QMetaType::Float && p.d.type != QMetaType::QObjectStar) { handler->construct(&d, p.constData()); d.is_null = p.d.is_null; } @@ -1733,7 +1743,7 @@ QVariant& QVariant::operator=(const QVariant &variant) if (variant.d.is_shared) { variant.d.data.shared->ref.ref(); d = variant.d; - } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) { + } else if (variant.d.type > Char && variant.d.type != QMetaType::Float && variant.d.type != QMetaType::QObjectStar) { d.type = variant.d.type; handler->construct(&d, variant.constData()); d.is_null = variant.d.is_null; diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index a68939d..4489e95 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -358,6 +358,7 @@ class Q_CORE_EXPORT QVariant float f; qlonglong ll; qulonglong ull; + QObject *o; void *ptr; PrivateShared *shared; } data; -- cgit v0.12 From 53d7bcc2f535807ec6edd1df20194675d3cc357e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 7 Aug 2009 15:04:13 +1000 Subject: Start refactoring QFxPixmap so it isn't as slow to use. --- src/declarative/extra/qfxparticles.cpp | 15 ++++- src/declarative/fx/qfximage.cpp | 36 +++++++++--- src/declarative/fx/qfxpixmap.cpp | 100 +++++++++++---------------------- src/declarative/fx/qfxpixmap.h | 22 +------- 4 files changed, 77 insertions(+), 96 deletions(-) diff --git a/src/declarative/extra/qfxparticles.cpp b/src/declarative/extra/qfxparticles.cpp index 26c176b..f05f233 100644 --- a/src/declarative/extra/qfxparticles.cpp +++ b/src/declarative/extra/qfxparticles.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include "qfxparticles.h" #include @@ -404,6 +405,7 @@ public: bool emitting; QFxParticleMotion *motion; QFxParticlesPainter *paintItem; + QPointer reply; QList particles; QTickAnimationProxy clock; @@ -636,7 +638,7 @@ QUrl QFxParticles::source() const void QFxParticles::imageLoaded() { Q_D(QFxParticles); - d->image = QFxPixmap(d->url); + QFxPixmap::find(d->url, &d->image); d->paintItem->updateSize(); d->paintItem->update(); } @@ -645,7 +647,7 @@ void QFxParticles::setSource(const QUrl &name) { Q_D(QFxParticles); - if (name == d->url) + if ((d->url.isEmpty() == name.isEmpty()) && name == d->url) return; if (!d->url.isEmpty()) @@ -658,7 +660,14 @@ void QFxParticles::setSource(const QUrl &name) } else { d->url = name; Q_ASSERT(!name.isRelative()); - QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded())); + d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->image); + if (d->reply) + connect(d->reply, SIGNAL(finished()), this, SLOT(imageLoaded())); + else { + //### unify with imageLoaded + d->paintItem->updateSize(); + d->paintItem->update(); + } } } diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 792b015..26e2727 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -437,7 +437,8 @@ void QFxImage::setSource(const QUrl &url) QFxPerfTimer perf; #endif Q_D(QFxImage); - if (url == d->url) + //equality is fairly expensive, so we bypass for simple, common case + if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) return; if (d->sciReply) { @@ -485,13 +486,23 @@ void QFxImage::setSource(const QUrl &url) this, SLOT(sciRequestFinished())); } } else { - d->reply = QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished())); + d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; d->progress = 1.0; - emit progressChanged(d->progress); + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); } } } @@ -503,15 +514,16 @@ void QFxImage::requestFinished() { Q_D(QFxImage); if (d->url.path().endsWith(QLatin1String(".sci"))) { - d->pix = QFxPixmap(d->sciurl); + QFxPixmap::find(d->sciurl, &d->pix); } else { if (d->reply) { + //###disconnect really needed? disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); if (d->reply->error() != QNetworkReply::NoError) d->status = Error; } - d->pix = QFxPixmap(d->url); + QFxPixmap::find(d->url, &d->pix); } setImplicitWidth(d->pix.width()); setImplicitHeight(d->pix.height()); @@ -566,13 +578,23 @@ void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci) sg->setVerticalTileRule(sci.verticalTileRule()); d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished())); + d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; d->progress = 1.0; - emit progressChanged(d->progress); + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); } } } diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp index 6647b21..99b8128 100644 --- a/src/declarative/fx/qfxpixmap.cpp +++ b/src/declarative/fx/qfxpixmap.cpp @@ -81,14 +81,7 @@ public: } }; -class QFxPixmapPrivate -{ -public: - QFxPixmapPrivate() {} - - QPixmap pixmap; - - bool readImage(QIODevice *dev) +static bool readImage(QIODevice *dev, QPixmap *pixmap) { QImageReader imgio(dev); @@ -114,13 +107,12 @@ public: if (!sz.isValid()) img = img.scaled(limit,Qt::KeepAspectRatio); #endif - pixmap = QPixmap::fromImage(img); + *pixmap = QPixmap::fromImage(img); return true; } else { return false; } } -}; /*! \internal @@ -131,25 +123,26 @@ public: This class is NOT reentrant. The pixmap cache will grow indefinately. */ -QFxPixmap::QFxPixmap() -: d(new QFxPixmapPrivate) -{ -} -QFxPixmap::QFxPixmap(const QUrl &url) -: d(new QFxPixmapPrivate) + +bool QFxPixmap::find(const QUrl& url, QPixmap *pixmap) { #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer perf; #endif + QString key = url.toString(); - if (!QPixmapCache::find(key,&d->pixmap)) { + if (!QPixmapCache::find(key,pixmap)) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML if (url.scheme()==QLatin1String("file")) { QFile f(url.toLocalFile()); - if (f.open(QIODevice::ReadOnly)) - if (!d->readImage(&f)) + if (f.open(QIODevice::ReadOnly)) { + if (!readImage(&f, pixmap)) { qWarning() << "Format error loading" << url; + *pixmap = QPixmap(); + } + } else + *pixmap = QPixmap(); } else #endif { @@ -158,55 +151,21 @@ QFxPixmap::QFxPixmap(const QUrl &url) // API usage error qWarning() << "QFxPixmap: URL not loaded" << url; } else { - if ((*iter)->reply->error()) + if ((*iter)->reply->error()) { qWarning() << "Network error loading" << url << (*iter)->reply->errorString(); - else - if (!d->readImage((*iter)->reply)) + *pixmap = QPixmap(); + } else + if (!readImage((*iter)->reply, pixmap)) { qWarning() << "Format error loading" << url; + *pixmap = QPixmap(); + } (*iter)->release(); } } - QPixmapCache::insert(key, d->pixmap); + QPixmapCache::insert(key, *pixmap); } } -QFxPixmap::QFxPixmap(const QFxPixmap &o) -: d(new QFxPixmapPrivate) -{ - d->pixmap = o.d->pixmap; -} - -QFxPixmap::~QFxPixmap() -{ - delete d; -} - -QFxPixmap &QFxPixmap::operator=(const QFxPixmap &o) -{ - d->pixmap = o.d->pixmap; - return *this; -} - -bool QFxPixmap::isNull() const -{ - return d->pixmap.isNull(); -} - -int QFxPixmap::width() const -{ - return d->pixmap.width(); -} - -int QFxPixmap::height() const -{ - return d->pixmap.height(); -} - -QFxPixmap::operator const QPixmap &() const -{ - return d->pixmap; -} - /*! Starts a network request to load \a url. When the URL is loaded, the given slot is invoked. Note that if the image is already cached, @@ -215,20 +174,28 @@ QFxPixmap::operator const QPixmap &() const Returns a QNetworkReply if the image is not immediately available, otherwise returns 0. The QNetworkReply must not be stored - it may be destroyed at any time. */ -QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot) +QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QPixmap *pixmap) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML if (url.scheme()==QLatin1String("file")) { - QObject dummy; - QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot); + QString key = url.toString(); + if (!QPixmapCache::find(key,pixmap)) { + QFile f(url.toLocalFile()); + if (f.open(QIODevice::ReadOnly)) { + if (!readImage(&f, pixmap)) { + qWarning() << "Format error loading" << url; + *pixmap = QPixmap(); + } + } else + *pixmap = QPixmap(); + QPixmapCache::insert(key, *pixmap); + } return 0; } #endif QString key = url.toString(); - if (QPixmapCache::find(key,0)) { - QObject dummy; - QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot); + if (QPixmapCache::find(key,pixmap)) { return 0; } @@ -242,7 +209,6 @@ QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, (*iter)->addRef(); } - QObject::connect((*iter)->reply, SIGNAL(finished()), obj, slot); return (*iter)->reply; } diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h index f63299b..ec8d2be 100644 --- a/src/declarative/fx/qfxpixmap.h +++ b/src/declarative/fx/qfxpixmap.h @@ -54,29 +54,13 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QmlEngine; class QNetworkReply; -class QFxPixmapPrivate; -class Q_DECLARATIVE_EXPORT QFxPixmap +class Q_DECLARATIVE_EXPORT QFxPixmap //### rename QFxPixmapCache { public: - QFxPixmap(); - QFxPixmap(const QUrl& url); // url must have been passed to QFxPixmap::get, and finished. - QFxPixmap(const QFxPixmap &); - virtual ~QFxPixmap(); - - QFxPixmap &operator=(const QFxPixmap &); - - static QNetworkReply *get(QmlEngine *, const QUrl& url, QObject*, const char* slot); + static QNetworkReply *get(QmlEngine *, const QUrl& url, QPixmap *pixmap); static void cancelGet(const QUrl& url, QObject* obj); - bool isNull() const; - - int width() const; - int height() const; - - operator const QPixmap &() const; - -private: - QFxPixmapPrivate *d; + static bool find(const QUrl& url, QPixmap *pixmap); // url must have been passed to QFxPixmap::get, and finished. Or must be a local file. }; -- cgit v0.12 From 970dae1b8d9b9a668406fd3a77bf3e3847e077eb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 7 Aug 2009 15:05:27 +1000 Subject: Use a linked list for QObject's connection list. This slightly increase memory use, but slightly improves the performance of signal/slot connections. Pending review. --- src/corelib/kernel/qobject.cpp | 116 +++++++++++++++++++++++++++-------------- src/corelib/kernel/qobject_p.h | 9 +++- 2 files changed, 86 insertions(+), 39 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ab91799..36b2e8b 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -254,11 +254,13 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const QMutexLocker locker(signalSlotLock(q)); if (connectionLists) { if (signal_index < connectionLists->count()) { - const ConnectionList &connectionList = connectionLists->at(signal_index); - for (int i = 0; i < connectionList.count(); ++i) { - const QObjectPrivate::Connection *c = connectionList.at(i); + const QObjectPrivate::Connection *c = + connectionLists->at(signal_index).first; + + while (c) { if (c->receiver == receiver) return true; + c = c->nextConnectionList; } } } @@ -276,11 +278,12 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const QMutexLocker locker(signalSlotLock(q)); if (connectionLists) { if (signal_index < connectionLists->count()) { - const ConnectionList &connectionList = connectionLists->at(signal_index); - for (int i = 0; i < connectionList.count(); ++i) { - const QObjectPrivate::Connection *c = connectionList.at(i); + const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; + + while (c) { if (c->receiver) returnValue << c->receiver; + c = c->nextConnectionList; } } } @@ -305,7 +308,13 @@ void QObjectPrivate::addConnection(int signal, Connection *c) connectionLists->resize(signal + 1); ConnectionList &connectionList = (*connectionLists)[signal]; - connectionList.append(c); + if (connectionList.last) { + connectionList.last->nextConnectionList = c; + } else { + connectionList.first = c; + } + connectionList.last = c; + cleanConnectionLists(); } @@ -314,14 +323,32 @@ void QObjectPrivate::cleanConnectionLists() if (connectionLists->dirty && !connectionLists->inUse) { // remove broken connections for (int signal = -1; signal < connectionLists->count(); ++signal) { - QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal]; - for (int i = 0; i < connectionList.count(); ++i) { - QObjectPrivate::Connection *c = connectionList.at(i); - if (!c->receiver) { + QObjectPrivate::ConnectionList &connectionList = + (*connectionLists)[signal]; + + // Set to the last entry in the connection list that was *not* + // deleted. This is needed to update the list's last pointer + // at the end of the cleanup. + QObjectPrivate::Connection *last = 0; + + QObjectPrivate::Connection **prev = &connectionList.first; + QObjectPrivate::Connection *c = *prev; + while (c) { + if (c->receiver) { + last = c; + prev = &c->nextConnectionList; + c = *prev; + } else { + QObjectPrivate::Connection *next = c->nextConnectionList; + *prev = next; delete c; - connectionList.removeAt(i--); + c = next; } } + + // Correct the connection list's last pointer. As + // conectionList.last could equal last, this could be a noop + connectionList.last = last; } connectionLists->dirty = false; } @@ -780,17 +807,19 @@ QObject::~QObject() if (d->connectionLists) { ++d->connectionLists->inUse; for (int signal = -1; signal < d->connectionLists->count(); ++signal) { - QObjectPrivate::ConnectionList &connectionList = (*d->connectionLists)[signal]; - for (int i = 0; i < connectionList.count(); ++i) { - QObjectPrivate::Connection *c = connectionList[i]; + QObjectPrivate::ConnectionList &connectionList = + (*d->connectionLists)[signal]; + + while (QObjectPrivate::Connection *c = connectionList.first) { if (!c->receiver) { + connectionList.first = c->nextConnectionList; delete c; continue; } QMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); - c = connectionList[i]; + if (c->receiver) { *c->prev = c->next; if (c->next) c->next->prev = c->prev; @@ -798,6 +827,7 @@ QObject::~QObject() if (needToUnlock) m->unlock(); + connectionList.first = c->nextConnectionList; delete c; } } @@ -2403,11 +2433,11 @@ int QObject::receivers(const char *signal) const QMutexLocker locker(signalSlotLock(this)); if (d->connectionLists) { if (signal_index < d->connectionLists->count()) { - const QObjectPrivate::ConnectionList &connectionList = - d->connectionLists->at(signal_index); - for (int i = 0; i < connectionList.count(); ++i) { - const QObjectPrivate::Connection *c = connectionList.at(i); + const QObjectPrivate::Connection *c = + d->connectionLists->at(signal_index).first; + while (c) { receivers += c->receiver ? 1 : 0; + c = c->nextConnectionList; } } } @@ -2852,11 +2882,13 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, if (type & Qt::UniqueConnection) { QObjectConnectionListVector *connectionLists = s->d_func()->connectionLists; if (connectionLists && connectionLists->count() > signal_index) { - QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index]; - for (int i = 0; i < connectionList.count(); ++i) { - QObjectPrivate::Connection *c2 = connectionList.at(i); + const QObjectPrivate::Connection *c2 = + (*connectionLists)[signal_index].first; + + while (c2) { if (c2->receiver == receiver && c2->method == method_index) return false; + c2 = c2->nextConnectionList; } } type &= Qt::UniqueConnection - 1; @@ -2868,6 +2900,7 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, c->method = method_index; c->connectionType = type; c->argumentTypes = types; + c->nextConnectionList = 0; c->prev = &r->d_func()->senders; c->next = *c->prev; *c->prev = c; @@ -2917,9 +2950,9 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, if (signal_index < 0) { // remove from all connection lists for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) { - QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index]; - for (int i = 0; i < connectionList.count(); ++i) { - QObjectPrivate::Connection *c = connectionList[i]; + QObjectPrivate::Connection *c = + (*connectionLists)[signal_index].first; + while (c) { if (c->receiver && (r == 0 || (c->receiver == r && (method_index < 0 || c->method == method_index)))) { @@ -2928,7 +2961,6 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, if (!receiverMutex && senderMutex != m) { // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); - c = connectionList[i]; } if (c->receiver) { *c->prev = c->next; @@ -2943,12 +2975,13 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, success = true; connectionLists->dirty = true; } + c = c->nextConnectionList; } } } else if (signal_index < connectionLists->count()) { - QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index]; - for (int i = 0; i < connectionList.count(); ++i) { - QObjectPrivate::Connection *c = connectionList[i]; + QObjectPrivate::Connection *c = + (*connectionLists)[signal_index].first; + while (c) { if (c->receiver && (r == 0 || (c->receiver == r && (method_index < 0 || c->method == method_index)))) { @@ -2957,7 +2990,6 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, if (!receiverMutex && senderMutex != m) { // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); - c = connectionList[i]; } if (c->receiver) { *c->prev = c->next; @@ -2971,6 +3003,7 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, success = true; connectionLists->dirty = true; } + c = c->nextConnectionList; } } @@ -3135,9 +3168,14 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal signal = to_signal_index; continue; } - int count = connectionLists->at(signal).count(); - for (int i = 0; i < count; ++i) { - QObjectPrivate::Connection *c = connectionLists->at(signal)[i]; + + QObjectPrivate::Connection *c = connectionLists->at(signal).first; + if (!c) continue; + // We need to check against last here to ensure that signals added + // during the signal emission are not emitted in this emission. + QObjectPrivate::Connection *last = connectionLists->at(signal).last; + + do { if (!c->receiver) continue; @@ -3199,7 +3237,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal if (connectionLists->orphaned) break; - } + } while (c != last && (c = c->nextConnectionList) != 0); if (connectionLists->orphaned) break; @@ -3518,11 +3556,12 @@ void QObject::dumpObjectInfo() qDebug(" signal: %s", signal.signature()); // receivers - const QObjectPrivate::ConnectionList &connectionList = d->connectionLists->at(signal_index); - for (int i = 0; i < connectionList.count(); ++i) { - const QObjectPrivate::Connection *c = connectionList.at(i); + const QObjectPrivate::Connection *c = + d->connectionLists->at(signal_index).first; + while (c) { if (!c->receiver) { qDebug(" "); + c = c->nextConnectionList; continue; } const QMetaObject *receiverMetaObject = c->receiver->metaObject(); @@ -3531,6 +3570,7 @@ void QObject::dumpObjectInfo() receiverMetaObject->className(), c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()), method.signature()); + c = c->nextConnectionList; } } } else { diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index e908753..d1a2714 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -163,12 +163,19 @@ public: int method; uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking QBasicAtomicPointer argumentTypes; + // The next pointer for the singly-linked ConnectionList + Connection *nextConnectionList; //senders linked list Connection *next; Connection **prev; ~Connection(); }; - typedef QList ConnectionList; + // ConnectionList is a singly-linked list + struct ConnectionList { + ConnectionList() : first(0), last(0) {} + Connection *first; + Connection *last; + }; QObjectConnectionListVector *connectionLists; void addConnection(int signal, Connection *c); -- cgit v0.12 From ef178f4d7d7545920bf8dbc8f43d571ffd9ddf09 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 7 Aug 2009 16:20:30 +1000 Subject: Remove unused parameters --- src/declarative/qml/qmlbasicscript.cpp | 48 +++------------------------------- src/declarative/qml/qmlbasicscript_p.h | 5 +--- src/declarative/qml/qmlexpression.cpp | 18 +++---------- src/declarative/qml/qmlexpression_p.h | 3 +-- 4 files changed, 9 insertions(+), 65 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index ca137c7..5800f71 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -243,12 +243,7 @@ struct QmlBasicScriptCompiler To see if the QmlBasicScript engine can handle a binding, call compile() and check the return value, or isValid() afterwards. - To evaluate the binding, the QmlBasicScript instance needs some memory in - which to cache state. This may be allocated by calling newScriptState() - and destroyed by calling deleteScriptState(). The state data is then passed - to the run() method when evaluating the binding. - - To further accelerate binding, QmlBasicScript can return a precompiled + To accelerate binding, QmlBasicScript can return a precompiled version of itself that can be saved for future use. Call compileData() to get an opaque pointer to the compiled state, and compileDataSize() for the size of this data in bytes. This data can be saved and passed to future @@ -320,22 +315,6 @@ void QmlBasicScript::clear() } /*! - Return the script state memory for this script instance. This memory should - only be destroyed by calling deleteScriptState(). - */ -void *QmlBasicScript::newScriptState() -{ - return 0; -} - -/*! - Delete the \a data previously allocated by newScriptState(). - */ -void QmlBasicScript::deleteScriptState(void *) -{ -} - -/*! Dump the script instructions to stderr for debugging. */ void QmlBasicScript::dump() @@ -635,23 +614,10 @@ bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node) } /*! - \enum QmlBasicScript::CacheState - \value NoChange The query has not change. Any previous monitoring is still - valid. - \value Incremental The query has been incrementally changed. Any previous - monitoring is still valid, but needs to have the fresh properties added to - it. - \value Reset The entire query has been reset from the beginning. Any previous - monitoring is now invalid. -*/ - -/*! - Run the script in \a context and return the result. \a voidCache should - contain state memory previously acquired from newScript. + Run the script in \a context and return the result. */ -QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached) +QVariant QmlBasicScript::run(QmlContext *context) { - Q_UNUSED(voidCache); if (!isValid()) return QVariant(); @@ -660,8 +626,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c QStack stack; - CacheState state = NoChange; - for (int idx = 0; idx < d->instructionCount; ++idx) { const ScriptInstruction &instr = d->instructions()[idx]; @@ -671,7 +635,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c stack.push(QVariant::fromValue(contextPrivate->idValues[instr.fetch.idx].data())); enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(context, -1, contextPrivate->notifyIndex + instr.fetch.idx); - state = Reset; } break; @@ -683,7 +646,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); - state = Reset; } break; @@ -695,7 +657,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); - state = Reset; } break; @@ -708,7 +669,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); - state = Reset; } break; @@ -733,8 +693,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c } } - *cached = Reset; - if (stack.isEmpty()) return QVariant(); else diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 539227f..152dbe5c 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -95,11 +95,8 @@ public: void clear(); void dump(); - void *newScriptState(); - void deleteScriptState(void *); - enum CacheState { NoChange, Incremental, Reset }; - QVariant run(QmlContext *, void *, CacheState *); + QVariant run(QmlContext *); private: int flags; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index a9175ea..da8b59f 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -51,7 +51,7 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE QmlExpressionPrivate::QmlExpressionPrivate() -: nextExpression(0), prevExpression(0), ctxt(0), expressionFunctionValid(false), expressionRewritten(false), sseData(0), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0) +: nextExpression(0), prevExpression(0), ctxt(0), expressionFunctionValid(false), expressionRewritten(false), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0) { } @@ -101,8 +101,6 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QmlExpressionPrivate::~QmlExpressionPrivate() { - sse.deleteScriptState(sseData); - sseData = 0; if (guardList) { delete [] guardList; guardList = 0; } } @@ -215,10 +213,6 @@ void QmlExpression::clearExpression() void QmlExpression::setExpression(const QString &expression) { Q_D(QmlExpression); - if (d->sseData) { - d->sse.deleteScriptState(d->sseData); - d->sseData = 0; - } d->clearGuards(); @@ -230,7 +224,7 @@ void QmlExpression::setExpression(const QString &expression) d->sse.clear(); } -QVariant QmlExpressionPrivate::evalSSE(QmlBasicScript::CacheState &cacheState) +QVariant QmlExpressionPrivate::evalSSE() { #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer perfsse; @@ -240,9 +234,7 @@ QVariant QmlExpressionPrivate::evalSSE(QmlBasicScript::CacheState &cacheState) if (me) ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount , me); - if (!sseData) - sseData = sse.newScriptState(); - QVariant rv = sse.run(ctxt, sseData, &cacheState); + QVariant rv = sse.run(ctxt); if (me) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); @@ -367,8 +359,6 @@ QVariant QmlExpression::value() QFxPerfTimer perf; #endif - QmlBasicScript::CacheState cacheState = QmlBasicScript::Reset; - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine()); QmlExpression *lastCurrentExpression = ep->currentExpression; @@ -378,7 +368,7 @@ QVariant QmlExpression::value() ep->currentExpression = this; if (d->sse.isValid()) { - rv = d->evalSSE(cacheState); + rv = d->evalSSE(); } else { rv = d->evalQtScript(); } diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index f607898..bf95c0e0 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -89,14 +89,13 @@ public: QScriptValue expressionFunction; QmlBasicScript sse; - void *sseData; QObject *me; bool trackChange; QString fileName; int line; - QVariant evalSSE(QmlBasicScript::CacheState &cacheState); + QVariant evalSSE(); QVariant evalQtScript(); struct SignalGuard : public QGuard { -- cgit v0.12 From 76dccb8afe640ec6e22ba8a6e5843c47fd2bd832 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 7 Aug 2009 16:36:13 +1000 Subject: Pass the "me" context directly to QmlBasicScript This saves pointlessly manipulating the context's default object list --- src/declarative/qml/qmlbasicscript.cpp | 12 +++++------- src/declarative/qml/qmlbasicscript_p.h | 2 +- src/declarative/qml/qmlexpression.cpp | 7 +------ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 5800f71..21860a5 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -616,7 +616,7 @@ bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node) /*! Run the script in \a context and return the result. */ -QVariant QmlBasicScript::run(QmlContext *context) +QVariant QmlBasicScript::run(QmlContext *context, QObject *me) { if (!isValid()) return QVariant(); @@ -640,18 +640,16 @@ QVariant QmlBasicScript::run(QmlContext *context) case ScriptInstruction::FetchContextConstant: { - QObject *obj = contextPrivate->defaultObjects.at(0); - - stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (obj && instr.constant.notify != 0) + stack.push(fetch_value(me, instr.constant.idx, instr.constant.type)); + if (me && instr.constant.notify != 0) enginePrivate->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); + QmlEnginePrivate::CapturedProperty(me, instr.constant.idx, instr.constant.notify); } break; case ScriptInstruction::FetchRootConstant: { - QObject *obj = contextPrivate->defaultObjects.at(1); + QObject *obj = contextPrivate->defaultObjects.at(0); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); if (obj && instr.constant.notify != 0) diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 152dbe5c..92d58f9 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -96,7 +96,7 @@ public: void dump(); - QVariant run(QmlContext *); + QVariant run(QmlContext *, QObject *); private: int flags; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index da8b59f..6e9a7a1 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -231,13 +231,8 @@ QVariant QmlExpressionPrivate::evalSSE() #endif QmlContextPrivate *ctxtPriv = ctxt->d_func(); - if (me) - ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount , me); - - QVariant rv = sse.run(ctxt); - if (me) - ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); + QVariant rv = sse.run(ctxt, me); return rv; } -- cgit v0.12 From 85631d5469f7a55165b8f2c0f08e4ba2cb08cd8e Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 7 Aug 2009 16:59:44 +1000 Subject: Fix build --- src/declarative/fx/qfxpixmap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp index 99b8128..43e94e5 100644 --- a/src/declarative/fx/qfxpixmap.cpp +++ b/src/declarative/fx/qfxpixmap.cpp @@ -164,6 +164,7 @@ bool QFxPixmap::find(const QUrl& url, QPixmap *pixmap) } QPixmapCache::insert(key, *pixmap); } + return true; } /*! -- cgit v0.12 From d93e8b21fafb546c9f8fefbb170bbb2d66fe6e93 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 7 Aug 2009 15:13:40 +1000 Subject: Add new class QFxImageBase New base class for QFxImage and QFxBorderImage. --- src/declarative/fx/fx.pri | 3 ++ src/declarative/fx/qfximage.cpp | 6 ++-- src/declarative/fx/qfximage.h | 5 ++- src/declarative/fx/qfximage_p.h | 3 +- src/declarative/fx/qfximagebase.cpp | 57 +++++++++++++++++++++++++++++ src/declarative/fx/qfximagebase.h | 62 ++++++++++++++++++++++++++++++++ src/declarative/fx/qfximagebase_p.h | 72 +++++++++++++++++++++++++++++++++++++ 7 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 src/declarative/fx/qfximagebase.cpp create mode 100644 src/declarative/fx/qfximagebase.h create mode 100644 src/declarative/fx/qfximagebase_p.h diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri index a6c5281..266fd71 100644 --- a/src/declarative/fx/fx.pri +++ b/src/declarative/fx/fx.pri @@ -9,9 +9,11 @@ HEADERS += \ fx/qfxflipable.h \ fx/qfxgridview.h \ fx/qfximage.h \ + fx/qfximagebase.h \ fx/qfxpainteditem.h \ fx/qfxpainteditem_p.h \ fx/qfximage_p.h \ + fx/qfximagebase_p.h \ fx/qfxitem.h \ fx/qfxitem_p.h \ fx/qfxfocusscope.h \ @@ -52,6 +54,7 @@ SOURCES += \ fx/qfxflipable.cpp \ fx/qfxgridview.cpp \ fx/qfximage.cpp \ + fx/qfximagebase.cpp \ fx/qfxpainteditem.cpp \ fx/qfxitem.cpp \ fx/qfxfocusscope.cpp \ diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 26e2727..b1c6bda 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -41,7 +41,7 @@ #include "qfximage.h" #include "qfximage_p.h" -#include +//#include #include #include #include @@ -144,13 +144,13 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) */ QFxImage::QFxImage(QFxItem *parent) - : QFxItem(*(new QFxImagePrivate), parent) + : QFxImageBase(*(new QFxImagePrivate), parent) { setFlag(QGraphicsItem::ItemHasNoContents, false); } QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) - : QFxItem(dd, parent) + : QFxImageBase(dd, parent) { setFlag(QGraphicsItem::ItemHasNoContents, false); } diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index fc9cfe0..642e4c8 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -42,9 +42,8 @@ #ifndef QFXIMAGE_H #define QFXIMAGE_H -#include #include - +#include "qfximagebase.h" QT_BEGIN_HEADER @@ -55,7 +54,7 @@ class QFxImagePrivate; class QFxScaleGrid; class QFxGridScaledImage; -class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem +class Q_DECLARATIVE_EXPORT QFxImage : public QFxImageBase { Q_OBJECT Q_ENUMS(Status) diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index 2ce41f8..d198c27 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -55,6 +55,7 @@ #include "qfxitem_p.h" #include "qfxscalegrid_p.h" +#include "qfximagebase_p.h" #include @@ -65,7 +66,7 @@ class QWebPage; class QNetworkReply; class QIODevice; -class QFxImagePrivate : public QFxItemPrivate +class QFxImagePrivate : public QFxImageBasePrivate { Q_DECLARE_PUBLIC(QFxImage) diff --git a/src/declarative/fx/qfximagebase.cpp b/src/declarative/fx/qfximagebase.cpp new file mode 100644 index 0000000..e0b72c2 --- /dev/null +++ b/src/declarative/fx/qfximagebase.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfximagebase.h" +#include "qfximagebase_p.h" + +QT_BEGIN_NAMESPACE + +QFxImageBase::QFxImageBase(QFxItem *parent) + : QFxItem(*(new QFxImageBasePrivate), parent) +{ +} + +QFxImageBase::QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent) + : QFxItem(dd, parent) +{ +} + +QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximagebase.h b/src/declarative/fx/qfximagebase.h new file mode 100644 index 0000000..7e04f0d --- /dev/null +++ b/src/declarative/fx/qfximagebase.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXIMAGEBASE_H +#define QFXIMAGEBASE_H + +#include + +QT_BEGIN_NAMESPACE + +class QFxImageBasePrivate; +class QFxImageBase : public QFxItem +{ +public: + QFxImageBase(QFxItem *parent = 0); + +protected: + QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent); + +}; + +QT_END_NAMESPACE + +#endif // QFXIMAGEBASE_H diff --git a/src/declarative/fx/qfximagebase_p.h b/src/declarative/fx/qfximagebase_p.h new file mode 100644 index 0000000..7e5d722 --- /dev/null +++ b/src/declarative/fx/qfximagebase_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXIMAGEBASE_P_H +#define QFXIMAGEBASE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qfxitem_p.h" + +QT_BEGIN_NAMESPACE + +class QFxImageBasePrivate : public QFxItemPrivate +{ + Q_DECLARE_PUBLIC(QFxImageBase) + +public: + QFxImageBasePrivate() + { + } +}; + +QT_END_NAMESPACE + +#endif -- cgit v0.12 From 7105e534a980554277fbe1da2698fca6a5bc49aa Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 7 Aug 2009 16:54:32 +1000 Subject: Start moving code from QFxImage to QFxImageBase --- src/declarative/fx/qfximage.cpp | 331 +++++------------------------------- src/declarative/fx/qfximage.h | 26 --- src/declarative/fx/qfximage_p.h | 35 +--- src/declarative/fx/qfximagebase.cpp | 246 +++++++++++++++++++++++++++ src/declarative/fx/qfximagebase.h | 35 ++++ src/declarative/fx/qfximagebase_p.h | 33 ++++ 6 files changed, 358 insertions(+), 348 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index b1c6bda..5c9e1f9 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -41,11 +41,6 @@ #include "qfximage.h" #include "qfximage_p.h" -//#include -#include -#include -#include -#include #include #include @@ -157,13 +152,6 @@ QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) QFxImage::~QFxImage() { - Q_D(QFxImage); - if (d->sciReply) - d->sciReply->deleteLater(); - if (!d->url.isEmpty()) - QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); } /*! @@ -194,37 +182,6 @@ void QFxImage::setPixmap(const QPixmap &pix) } /*! - \qmlproperty int Image::scaleGrid.left - \qmlproperty int Image::scaleGrid.right - \qmlproperty int Image::scaleGrid.top - \qmlproperty int Image::scaleGrid.bottom - - \target ImagexmlpropertiesscaleGrid - - A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: - - \image declarative-scalegrid.png - - When the image is scaled: - \list - \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled both horizontally and vertically - \i sections 2 and 8 are scaled horizontally - \i sections 4 and 6 are scaled vertically - \endlist - - Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image. - - A scale grid can also be specified using a - \l {Image::source}{.sci file}. -*/ -QFxScaleGrid *QFxImage::scaleGrid() -{ - Q_D(QFxImage); - return d->getScaleGrid(); -} - -/*! \qmlproperty FillMode Image::fillMode Set this property to define what happens when the image set for the item is smaller @@ -261,14 +218,50 @@ void QFxImage::setFillMode(FillMode mode) emit fillModeChanged(); } -void QFxImage::componentComplete() -{ - QFxItem::componentComplete(); -} +/*! + \qmlproperty enum Image::status + + This property holds the status of image loading. It can be one of: + \list + \o Null - no image has been set + \o Ready - the image has been loaded + \o Loading - the image is currently being loaded + \o Error - an error occurred while loading the image + \endlist + + \sa progress +*/ /*! - \property QFxImage::scaleGrid - \brief the 3x3 grid used to scale an image, excluding the corners. + \qmlproperty real Image::progress + + This property holds the progress of image loading, from 0.0 (nothing loaded) + to 1.0 (finished). + + \sa status +*/ + +/*! + \qmlproperty url Image::source + + Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. + + It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies + \list + \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}. + \i an image file. + \endlist + + The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: + \code + gridLeft: 10 + gridTop: 10 + gridBottom: 10 + gridRight: 10 + imageFile: picture.png + \endcode + + The URL may be absolute, or relative to the URL of the component. */ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) @@ -360,244 +353,4 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) } } -/*! - \qmlproperty enum Image::status - - This property holds the status of image loading. It can be one of: - \list - \o Null - no image has been set - \o Ready - the image has been loaded - \o Loading - the image is currently being loaded - \o Error - an error occurred while loading the image - \endlist - - \sa progress -*/ - -QFxImage::Status QFxImage::status() const -{ - Q_D(const QFxImage); - return d->status; -} - -/*! - \qmlproperty real Image::progress - - This property holds the progress of image loading, from 0.0 (nothing loaded) - to 1.0 (finished). - - \sa status -*/ - -qreal QFxImage::progress() const -{ - Q_D(const QFxImage); - return d->progress; -} - -/*! - \qmlproperty url Image::source - - Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. - - It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies - \list - \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}. - \i an image file. - \endlist - - The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: - \code - gridLeft: 10 - gridTop: 10 - gridBottom: 10 - gridRight: 10 - imageFile: picture.png - \endcode - - The URL may be absolute, or relative to the URL of the component. -*/ - -/*! - \property QFxImage::source - \brief the url of the image to be displayed in this item. - - The content specified can be of any image type loadable by QImage. Alternatively, - you can specify an sci format file, which specifies both an image and it's scale grid. -*/ -QUrl QFxImage::source() const -{ - Q_D(const QFxImage); - return d->url; -} - -void QFxImage::setSource(const QUrl &url) -{ -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxPerfTimer perf; -#endif - Q_D(QFxImage); - //equality is fairly expensive, so we bypass for simple, common case - if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) - return; - - if (d->sciReply) { - d->sciReply->deleteLater(); - d->sciReply = 0; - } - - if (!d->url.isEmpty()) - QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); - - d->url = url; - d->sciurl = QUrl(); - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - - if (url.isEmpty()) { - d->pix = QPixmap(); - d->status = Null; - d->progress = 1.0; - setImplicitWidth(0); - setImplicitHeight(0); - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } else { - d->status = Loading; - if (d->url.path().endsWith(QLatin1String(".sci"))) { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); - file.open(QIODevice::ReadOnly); - setGridScaledImage(QFxGridScaledImage(&file)); - } else -#endif - { - QNetworkRequest req(d->url); - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->sciReply, SIGNAL(finished()), - this, SLOT(sciRequestFinished())); - } - } else { - d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } - } - } - - emit statusChanged(d->status); -} - -void QFxImage::requestFinished() -{ - Q_D(QFxImage); - if (d->url.path().endsWith(QLatin1String(".sci"))) { - QFxPixmap::find(d->sciurl, &d->pix); - } else { - if (d->reply) { - //###disconnect really needed? - disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - if (d->reply->error() != QNetworkReply::NoError) - d->status = Error; - } - QFxPixmap::find(d->url, &d->pix); - } - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); -} - -void QFxImage::sciRequestFinished() -{ - Q_D(QFxImage); - if (d->sciReply->error() != QNetworkReply::NoError) { - d->status = Error; - d->sciReply->deleteLater(); - d->sciReply = 0; - emit statusChanged(d->status); - } else { - QFxGridScaledImage sci(d->sciReply); - d->sciReply->deleteLater(); - d->sciReply = 0; - setGridScaledImage(sci); - } -} - -void QFxImage::requestProgress(qint64 received, qint64 total) -{ - Q_D(QFxImage); - if (d->status == Loading && total > 0) { - d->progress = qreal(received)/total; - emit progressChanged(d->progress); - } -} - -void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci) -{ - Q_D(QFxImage); - if (!sci.isValid()) { - d->status = Error; - emit statusChanged(d->status); - } else { - QFxScaleGrid *sg = scaleGrid(); - sg->setTop(sci.gridTop()); - sg->setBottom(sci.gridBottom()); - sg->setLeft(sci.gridLeft()); - sg->setRight(sci.gridRight()); - sg->setHorizontalTileRule(sci.horizontalTileRule()); - sg->setVerticalTileRule(sci.verticalTileRule()); - - d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } - } -} - - QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index 642e4c8..b31da29 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -51,20 +51,12 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QFxImagePrivate; -class QFxScaleGrid; -class QFxGridScaledImage; class Q_DECLARATIVE_EXPORT QFxImage : public QFxImageBase { Q_OBJECT - Q_ENUMS(Status) Q_ENUMS(FillMode) - Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) - - Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid) Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap DESIGNABLE false) Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged); @@ -79,35 +71,17 @@ public: QPixmap pixmap() const; void setPixmap(const QPixmap &); - enum Status { Null, Ready, Loading, Error }; - Status status() const; - qreal progress() const; - - QUrl source() const; - virtual void setSource(const QUrl &url); - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); Q_SIGNALS: - void sourceChanged(const QUrl &); - void statusChanged(Status); - void progressChanged(qreal progress); void fillModeChanged(); protected: QFxImage(QFxImagePrivate &dd, QFxItem *parent); - virtual void componentComplete(); - -private Q_SLOTS: - void requestFinished(); - void sciRequestFinished(); - void requestProgress(qint64,qint64); private: Q_DISABLE_COPY(QFxImage) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxImage) - void setGridScaledImage(const QFxGridScaledImage& sci); - QFxScaleGrid *scaleGrid(); }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index d198c27..825da5b 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -54,55 +54,24 @@ // #include "qfxitem_p.h" -#include "qfxscalegrid_p.h" #include "qfximagebase_p.h" #include QT_BEGIN_NAMESPACE -class QSvgRenderer; -class QWebPage; -class QNetworkReply; -class QIODevice; - class QFxImagePrivate : public QFxImageBasePrivate { Q_DECLARE_PUBLIC(QFxImage) public: QFxImagePrivate() - : scaleGrid(0), - fillMode(QFxImage::Stretch), - status(QFxImage::Null), sciReply(0), - progress(0.0) - { - } - - ~QFxImagePrivate() - { - delete scaleGrid; - } - - void setContent(QIODevice* dev, const QString &url); - - QFxScaleGrid *getScaleGrid() + : fillMode(QFxImage::Stretch) { - if (!scaleGrid) - scaleGrid = new QFxScaleGrid; - return scaleGrid; } - QFxScaleGrid *scaleGrid; - QPixmap pix; - QFxImage::FillMode fillMode; - QFxImage::Status status; - QUrl url; - QUrl sciurl; - QNetworkReply *sciReply; - QPointer reply; - qreal progress; + }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximagebase.cpp b/src/declarative/fx/qfximagebase.cpp index e0b72c2..39c43d3 100644 --- a/src/declarative/fx/qfximagebase.cpp +++ b/src/declarative/fx/qfximagebase.cpp @@ -41,17 +41,263 @@ #include "qfximagebase.h" #include "qfximagebase_p.h" +#include +#include +#include +#include QT_BEGIN_NAMESPACE QFxImageBase::QFxImageBase(QFxItem *parent) : QFxItem(*(new QFxImageBasePrivate), parent) { + setFlag(QGraphicsItem::ItemHasNoContents, true); } QFxImageBase::QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent) : QFxItem(dd, parent) { + setFlag(QGraphicsItem::ItemHasNoContents, true); +} + +QFxImageBase::~QFxImageBase() +{ + Q_D(QFxImageBase); + if (d->sciReply) + d->sciReply->deleteLater(); + if (!d->url.isEmpty()) + QFxPixmap::cancelGet(d->url, this); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); +} + +/*! + \qmlproperty int Image::scaleGrid.left + \qmlproperty int Image::scaleGrid.right + \qmlproperty int Image::scaleGrid.top + \qmlproperty int Image::scaleGrid.bottom + + \target ImagexmlpropertiesscaleGrid + + A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: + + \image declarative-scalegrid.png + + When the image is scaled: + \list + \i the corners (sections 1, 3, 7, and 9) are not scaled at all + \i the middle (section 5) is scaled both horizontally and vertically + \i sections 2 and 8 are scaled horizontally + \i sections 4 and 6 are scaled vertically + \endlist + + Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image. + + A scale grid can also be specified using a + \l {Image::source}{.sci file}. +*/ +QFxScaleGrid *QFxImageBase::scaleGrid() +{ + Q_D(QFxImageBase); + return d->getScaleGrid(); +} + +void QFxImageBase::componentComplete() +{ + QFxItem::componentComplete(); +} + + +QFxImageBase::Status QFxImageBase::status() const +{ + Q_D(const QFxImageBase); + return d->status; +} + + +qreal QFxImageBase::progress() const +{ + Q_D(const QFxImageBase); + return d->progress; +} + + +/*! + \property QFxImage::source + \brief the url of the image to be displayed in this item. + + The content specified can be of any image type loadable by QImage. Alternatively, + you can specify an sci format file, which specifies both an image and it's scale grid. +*/ +QUrl QFxImageBase::source() const +{ + Q_D(const QFxImageBase); + return d->url; +} + +void QFxImageBase::setSource(const QUrl &url) +{ + Q_D(QFxImageBase); + //equality is fairly expensive, so we bypass for simple, common case + if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) + return; + + if (d->sciReply) { + d->sciReply->deleteLater(); + d->sciReply = 0; + } + + if (!d->url.isEmpty()) + QFxPixmap::cancelGet(d->url, this); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); + + d->url = url; + d->sciurl = QUrl(); + if (d->progress != 0.0) { + d->progress = 0.0; + emit progressChanged(d->progress); + } + + if (url.isEmpty()) { + d->pix = QPixmap(); + d->status = Null; + d->progress = 1.0; + setImplicitWidth(0); + setImplicitHeight(0); + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } else { + d->status = Loading; + if (d->url.path().endsWith(QLatin1String(".sci"))) { +#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML + if (d->url.scheme() == QLatin1String("file")) { + QFile file(d->url.toLocalFile()); + file.open(QIODevice::ReadOnly); + setGridScaledImage(QFxGridScaledImage(&file)); + } else +#endif + { + QNetworkRequest req(d->url); + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); + QObject::connect(d->sciReply, SIGNAL(finished()), + this, SLOT(sciRequestFinished())); + } + } else { + d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } + } + + emit statusChanged(d->status); +} + +void QFxImageBase::requestFinished() +{ + Q_D(QFxImageBase); + if (d->url.path().endsWith(QLatin1String(".sci"))) { + QFxPixmap::find(d->sciurl, &d->pix); + } else { + if (d->reply) { + //###disconnect really needed? + disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + if (d->reply->error() != QNetworkReply::NoError) + d->status = Error; + } + QFxPixmap::find(d->url, &d->pix); + } + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); +} + +void QFxImageBase::sciRequestFinished() +{ + Q_D(QFxImageBase); + if (d->sciReply->error() != QNetworkReply::NoError) { + d->status = Error; + d->sciReply->deleteLater(); + d->sciReply = 0; + emit statusChanged(d->status); + } else { + QFxGridScaledImage sci(d->sciReply); + d->sciReply->deleteLater(); + d->sciReply = 0; + setGridScaledImage(sci); + } +} + +void QFxImageBase::requestProgress(qint64 received, qint64 total) +{ + Q_D(QFxImageBase); + if (d->status == Loading && total > 0) { + d->progress = qreal(received)/total; + emit progressChanged(d->progress); + } +} + +void QFxImageBase::setGridScaledImage(const QFxGridScaledImage& sci) +{ + Q_D(QFxImageBase); + if (!sci.isValid()) { + d->status = Error; + emit statusChanged(d->status); + } else { + QFxScaleGrid *sg = scaleGrid(); + sg->setTop(sci.gridTop()); + sg->setBottom(sci.gridBottom()); + sg->setLeft(sci.gridLeft()); + sg->setRight(sci.gridRight()); + sg->setHorizontalTileRule(sci.horizontalTileRule()); + sg->setVerticalTileRule(sci.verticalTileRule()); + + d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); + d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } } QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximagebase.h b/src/declarative/fx/qfximagebase.h index 7e04f0d..78e391e 100644 --- a/src/declarative/fx/qfximagebase.h +++ b/src/declarative/fx/qfximagebase.h @@ -46,15 +46,50 @@ QT_BEGIN_NAMESPACE +class QFxScaleGrid; +class QFxGridScaledImage; class QFxImageBasePrivate; class QFxImageBase : public QFxItem { + Q_OBJECT + Q_ENUMS(Status) + + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) + Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid) + public: QFxImageBase(QFxItem *parent = 0); + ~QFxImageBase(); + enum Status { Null, Ready, Loading, Error }; + Status status() const; + qreal progress() const; + + QUrl source() const; + virtual void setSource(const QUrl &url); + +Q_SIGNALS: + void sourceChanged(const QUrl &); + void statusChanged(Status); + void progressChanged(qreal progress); protected: QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent); + virtual void componentComplete(); + +private Q_SLOTS: + void requestFinished(); + void sciRequestFinished(); + void requestProgress(qint64,qint64); + +private: + void setGridScaledImage(const QFxGridScaledImage& sci); + QFxScaleGrid *scaleGrid(); +private: + Q_DISABLE_COPY(QFxImageBase) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxImageBase) }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximagebase_p.h b/src/declarative/fx/qfximagebase_p.h index 7e5d722..e84fffe 100644 --- a/src/declarative/fx/qfximagebase_p.h +++ b/src/declarative/fx/qfximagebase_p.h @@ -54,17 +54,50 @@ // #include "qfxitem_p.h" +#include "qfxscalegrid_p.h" QT_BEGIN_NAMESPACE +class QSvgRenderer; +class QWebPage; +class QNetworkReply; +class QIODevice; + class QFxImageBasePrivate : public QFxItemPrivate { Q_DECLARE_PUBLIC(QFxImageBase) public: QFxImageBasePrivate() + : scaleGrid(0), + status(QFxImageBase::Null), sciReply(0), + progress(0.0) + { + } + + ~QFxImageBasePrivate() + { + delete scaleGrid; + } + + void setContent(QIODevice* dev, const QString &url); + + QFxScaleGrid *getScaleGrid() { + if (!scaleGrid) + scaleGrid = new QFxScaleGrid; + return scaleGrid; } + + QFxScaleGrid *scaleGrid; + QPixmap pix; + + QFxImageBase::Status status; + QUrl url; + QUrl sciurl; + QNetworkReply *sciReply; + QPointer reply; + qreal progress; }; QT_END_NAMESPACE -- cgit v0.12 From 1a05457011ca570b1f082f2e4312ad4897fbeb2d Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 10 Aug 2009 08:35:18 +1000 Subject: Add new class QFxBorderImage. * Move scalegrid code into QFxBorderImage * Update examples --- demos/declarative/flickr/content/MediaLineEdit.qml | 4 +- examples/declarative/border-image/BorderImage.qml | 36 -- .../declarative/border-image/MyBorderImage.qml | 36 ++ examples/declarative/border-image/animated.qml | 16 +- examples/declarative/border-image/borders.qml | 4 +- src/declarative/fx/fx.pri | 3 + src/declarative/fx/qfxborderimage.cpp | 397 +++++++++++++++++++++ src/declarative/fx/qfxborderimage.h | 101 ++++++ src/declarative/fx/qfxborderimage_p.h | 94 +++++ src/declarative/fx/qfximage.cpp | 139 +++----- src/declarative/fx/qfximage.h | 5 +- src/declarative/fx/qfximage_p.h | 2 - src/declarative/fx/qfximagebase.cpp | 123 +------ src/declarative/fx/qfximagebase.h | 13 +- src/declarative/fx/qfximagebase_p.h | 27 +- src/declarative/fx/qfxscalegrid.cpp | 28 +- src/declarative/fx/qfxscalegrid_p.h | 24 +- 17 files changed, 715 insertions(+), 337 deletions(-) delete mode 100644 examples/declarative/border-image/BorderImage.qml create mode 100644 examples/declarative/border-image/MyBorderImage.qml create mode 100644 src/declarative/fx/qfxborderimage.cpp create mode 100644 src/declarative/fx/qfxborderimage.h create mode 100644 src/declarative/fx/qfxborderimage_p.h diff --git a/demos/declarative/flickr/content/MediaLineEdit.qml b/demos/declarative/flickr/content/MediaLineEdit.qml index b8d30ce..4a55ff5 100644 --- a/demos/declarative/flickr/content/MediaLineEdit.qml +++ b/demos/declarative/flickr/content/MediaLineEdit.qml @@ -47,14 +47,14 @@ Item { ] - Image { + BorderImage { id: Image source: "pics/button.sci" anchors.left: Container.left anchors.right: Container.right } - Image { + BorderImage { id: Pressed source: "pics/button-pressed.sci" opacity: 0 diff --git a/examples/declarative/border-image/BorderImage.qml b/examples/declarative/border-image/BorderImage.qml deleted file mode 100644 index a809d5d..0000000 --- a/examples/declarative/border-image/BorderImage.qml +++ /dev/null @@ -1,36 +0,0 @@ -import Qt 4.6 - -Item { - property var horizontalMode : "Stretch" - property var verticalMode : "Stretch" - property string source - property int minWidth - property int minHeight - property int maxWidth - property int maxHeight - property int margin - - id: Container - width: 240; height: 240 - Image { - x: Container.width / 2 - width / 2 - y: Container.height / 2 - height / 2 - width: SequentialAnimation { - running: true; repeat: true - NumberAnimation { from: Container.minWidth; to: Container.maxWidth; duration: 2000; easing: "easeInOutQuad"} - NumberAnimation { from: Container.maxWidth; to: Container.minWidth; duration: 2000; easing: "easeInOutQuad" } - } - height: SequentialAnimation { - running: true; repeat: true - NumberAnimation { from: Container.minHeight; to: Container.maxHeight; duration: 2000; easing: "easeInOutQuad"} - NumberAnimation { from: Container.maxHeight; to: Container.minHeight; duration: 2000; easing: "easeInOutQuad" } - } - source: Container.source - scaleGrid.horizontalTileRule: Container.horizontalMode - scaleGrid.verticalTileRule: Container.verticalMode - scaleGrid.top: Container.margin - scaleGrid.left: Container.margin - scaleGrid.bottom: Container.margin - scaleGrid.right: Container.margin - } -} diff --git a/examples/declarative/border-image/MyBorderImage.qml b/examples/declarative/border-image/MyBorderImage.qml new file mode 100644 index 0000000..f9531df --- /dev/null +++ b/examples/declarative/border-image/MyBorderImage.qml @@ -0,0 +1,36 @@ +import Qt 4.6 + +Item { + property var horizontalMode : "Stretch" + property var verticalMode : "Stretch" + property string source + property int minWidth + property int minHeight + property int maxWidth + property int maxHeight + property int margin + + id: Container + width: 240; height: 240 + BorderImage { + x: Container.width / 2 - width / 2 + y: Container.height / 2 - height / 2 + width: SequentialAnimation { + running: true; repeat: true + NumberAnimation { from: Container.minWidth; to: Container.maxWidth; duration: 2000; easing: "easeInOutQuad"} + NumberAnimation { from: Container.maxWidth; to: Container.minWidth; duration: 2000; easing: "easeInOutQuad" } + } + height: SequentialAnimation { + running: true; repeat: true + NumberAnimation { from: Container.minHeight; to: Container.maxHeight; duration: 2000; easing: "easeInOutQuad"} + NumberAnimation { from: Container.maxHeight; to: Container.minHeight; duration: 2000; easing: "easeInOutQuad" } + } + source: Container.source + horizontalTileMode: Container.horizontalMode + verticalTileMode: Container.verticalMode + border.top: Container.margin + border.left: Container.margin + border.bottom: Container.margin + border.right: Container.margin + } +} diff --git a/examples/declarative/border-image/animated.qml b/examples/declarative/border-image/animated.qml index 58eb44c..ce4de16 100644 --- a/examples/declarative/border-image/animated.qml +++ b/examples/declarative/border-image/animated.qml @@ -5,47 +5,47 @@ Rect { color: "white" width: 1030; height: 540 - BorderImage { + MyBorderImage { x: 20; y: 20; minWidth: 120; maxWidth: 240 minHeight: 120; maxHeight: 240 source: "colors.png"; margin: 30 } - BorderImage { + MyBorderImage { x: 270; y: 20; minWidth: 120; maxWidth: 240 minHeight: 120; maxHeight: 240 source: "colors.png"; margin: 30 horizontalMode: "Repeat"; verticalMode: "Repeat" } - BorderImage { + MyBorderImage { x: 520; y: 20; minWidth: 120; maxWidth: 240 minHeight: 120; maxHeight: 240 source: "colors.png"; margin: 30 horizontalMode: "Stretch"; verticalMode: "Repeat" } - BorderImage { + MyBorderImage { x: 770; y: 20; minWidth: 120; maxWidth: 240 minHeight: 120; maxHeight: 240 source: "colors.png"; margin: 30 horizontalMode: "Round"; verticalMode: "Round" } - BorderImage { + MyBorderImage { x: 20; y: 280; minWidth: 60; maxWidth: 200 minHeight: 40; maxHeight: 200 source: "bw.png"; margin: 10 } - BorderImage { + MyBorderImage { x: 270; y: 280; minWidth: 60; maxWidth: 200 minHeight: 40; maxHeight: 200 source: "bw.png"; margin: 10 horizontalMode: "Repeat"; verticalMode: "Repeat" } - BorderImage { + MyBorderImage { x: 520; y: 280; minWidth: 60; maxWidth: 200 minHeight: 40; maxHeight: 200 source: "bw.png"; margin: 10 horizontalMode: "Stretch"; verticalMode: "Repeat" } - BorderImage { + MyBorderImage { x: 770; y: 280; minWidth: 60; maxWidth: 200 minHeight: 40; maxHeight: 200 source: "bw.png"; margin: 10 diff --git a/examples/declarative/border-image/borders.qml b/examples/declarative/border-image/borders.qml index a4a329b..e8c581e 100644 --- a/examples/declarative/border-image/borders.qml +++ b/examples/declarative/border-image/borders.qml @@ -5,12 +5,12 @@ Rect { color: "white" width: 520; height: 280 - Image { + BorderImage { x: 20; y: 20; width: 230; height: 240 smooth: true source: "colors-stretch.sci" } - Image { + BorderImage { x: 270; y: 20; width: 230; height: 240 smooth: true source: "colors-round.sci" diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri index 266fd71..34f4f67 100644 --- a/src/declarative/fx/fx.pri +++ b/src/declarative/fx/fx.pri @@ -10,9 +10,11 @@ HEADERS += \ fx/qfxgridview.h \ fx/qfximage.h \ fx/qfximagebase.h \ + fx/qfxborderimage.h \ fx/qfxpainteditem.h \ fx/qfxpainteditem_p.h \ fx/qfximage_p.h \ + fx/qfxborderimage_p.h \ fx/qfximagebase_p.h \ fx/qfxitem.h \ fx/qfxitem_p.h \ @@ -54,6 +56,7 @@ SOURCES += \ fx/qfxflipable.cpp \ fx/qfxgridview.cpp \ fx/qfximage.cpp \ + fx/qfxborderimage.cpp \ fx/qfximagebase.cpp \ fx/qfxpainteditem.cpp \ fx/qfxitem.cpp \ diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp new file mode 100644 index 0000000..34f0e66 --- /dev/null +++ b/src/declarative/fx/qfxborderimage.cpp @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfxborderimage.h" +#include "qfxborderimage_p.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,BorderImage,QFxBorderImage) + +/*! + \qmlclass BorderImage QFxBorderImage + \brief The BorderImage element allows you to add an image used as a border to a scene. + \inherits Item + + Example: + \qml + BorderImage { border.left: 20; border.right: 10 + border.top: 14; border.bottom: 14 + width: 160; height: 160 + source: "pics/qtlogo.png" + } + \endqml + */ + +/*! + \internal + \class QFxBorderImage BorderImage + \brief The QFxBorderImage class provides an image item that you can add to a QFxView. + + \ingroup group_coreitems + + Example: + \qml + BorderImage { source: "pics/star.png" } + \endqml + + A QFxBorderImage object can be instantiated in Qml using the tag \l BorderImage. +*/ + +QFxBorderImage::QFxBorderImage(QFxItem *parent) + : QFxImageBase(*(new QFxBorderImagePrivate), parent) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); +} + +QFxBorderImage::~QFxBorderImage() +{ + Q_D(QFxBorderImage); + if (d->sciReply) + d->sciReply->deleteLater(); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); +} +/*! + \qmlproperty enum BorderImage::status + + This property holds the status of image loading. It can be one of: + \list + \o Null - no image has been set + \o Ready - the image has been loaded + \o Loading - the image is currently being loaded + \o Error - an error occurred while loading the image + \endlist + + \sa progress +*/ + +/*! + \qmlproperty real BorderImage::progress + + This property holds the progress of image loading, from 0.0 (nothing loaded) + to 1.0 (finished). + + \sa status +*/ + +/*! + \qmlproperty url BorderImage::source + + BorderImage can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. + + It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies + \list + \i the grid lines describing a \l {BorderImage::border.left}{scale grid}. + \i an image file. + \endlist + + The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: + \code + gridLeft: 10 + gridTop: 10 + gridBottom: 10 + gridRight: 10 + imageFile: picture.png + \endcode + + The URL may be absolute, or relative to the URL of the component. +*/ + +void QFxBorderImage::setSource(const QUrl &url) +{ + Q_D(QFxBorderImage); + //equality is fairly expensive, so we bypass for simple, common case + if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) + return; + + if (d->sciReply) { + d->sciReply->deleteLater(); + d->sciReply = 0; + } + + if (!d->url.isEmpty()) + QFxPixmap::cancelGet(d->url, this); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); + + d->url = url; + d->sciurl = QUrl(); + if (d->progress != 0.0) { + d->progress = 0.0; + emit progressChanged(d->progress); + } + + if (url.isEmpty()) { + d->pix = QPixmap(); + d->status = Null; + d->progress = 1.0; + setImplicitWidth(0); + setImplicitHeight(0); + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } else { + d->status = Loading; + if (d->url.path().endsWith(QLatin1String(".sci"))) { +#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML + if (d->url.scheme() == QLatin1String("file")) { + QFile file(d->url.toLocalFile()); + file.open(QIODevice::ReadOnly); + setGridScaledImage(QFxGridScaledImage(&file)); + } else +#endif + { + QNetworkRequest req(d->url); + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); + QObject::connect(d->sciReply, SIGNAL(finished()), + this, SLOT(sciRequestFinished())); + } + } else { + d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } + } + + emit statusChanged(d->status); +} + +/*! + \qmlproperty int BorderImage::border.left + \qmlproperty int BorderImage::border.right + \qmlproperty int BorderImage::border.top + \qmlproperty int BorderImage::border.bottom + + \target ImagexmlpropertiesscaleGrid + + A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: + + \image declarative-scalegrid.png + + When the image is scaled: + \list + \i the corners (sections 1, 3, 7, and 9) are not scaled at all + \i the middle (section 5) is scaled both horizontally and vertically + \i sections 2 and 8 are scaled horizontally + \i sections 4 and 6 are scaled vertically + \endlist + + Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom scale grid line 10 pixels up from the bottom of the image. + + A scale grid can also be specified using a + \l {BorderImage::source}{.sci file}. +*/ + +QFxScaleGrid *QFxBorderImage::border() +{ + Q_D(QFxBorderImage); + return d->getScaleGrid(); +} + +/*! + \qmlproperty TileMode BorderImage::horizontalTileMode + \qmlproperty TileMode BorderImage::verticalTileMode + + This property describes how to repeat or stretch the middle parts of the border image. + + \list + \o Stretch - Scale the image to fit to the available area. + \o Repeat - Tile the image until there is no more space. May crop the last image. + \o Round - Like Repeat, but scales the images down to ensure that the last image is not cropped. + \endlist + + \sa examples/declarative/border-image +*/ +QFxBorderImage::TileMode QFxBorderImage::horizontalTileMode() const +{ + Q_D(const QFxBorderImage); + return d->horizontalTileMode; +} + +void QFxBorderImage::setHorizontalTileMode(TileMode t) +{ + Q_D(QFxBorderImage); + d->horizontalTileMode = t; +} + +QFxBorderImage::TileMode QFxBorderImage::verticalTileMode() const +{ + Q_D(const QFxBorderImage); + return d->verticalTileMode; +} + +void QFxBorderImage::setVerticalTileMode(TileMode t) +{ + Q_D(QFxBorderImage); + d->verticalTileMode = t; +} + +void QFxBorderImage::setGridScaledImage(const QFxGridScaledImage& sci) +{ + Q_D(QFxBorderImage); + if (!sci.isValid()) { + d->status = Error; + emit statusChanged(d->status); + } else { + QFxScaleGrid *sg = border(); + sg->setTop(sci.gridTop()); + sg->setBottom(sci.gridBottom()); + sg->setLeft(sci.gridLeft()); + sg->setRight(sci.gridRight()); + d->horizontalTileMode = sci.horizontalTileRule(); + d->verticalTileMode = sci.verticalTileRule(); + + d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); + d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } +} + +void QFxBorderImage::requestFinished() +{ + Q_D(QFxBorderImage); + if (d->url.path().endsWith(QLatin1String(".sci"))) { + QFxPixmap::find(d->sciurl, &d->pix); + } else { + if (d->reply) { + //###disconnect really needed? + disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + if (d->reply->error() != QNetworkReply::NoError) + d->status = Error; + } + QFxPixmap::find(d->url, &d->pix); + } + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); +} + +void QFxBorderImage::sciRequestFinished() +{ + Q_D(QFxBorderImage); + if (d->sciReply->error() != QNetworkReply::NoError) { + d->status = Error; + d->sciReply->deleteLater(); + d->sciReply = 0; + emit statusChanged(d->status); + } else { + QFxGridScaledImage sci(d->sciReply); + d->sciReply->deleteLater(); + d->sciReply = 0; + setGridScaledImage(sci); + } +} + +void QFxBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) +{ + Q_D(QFxBorderImage); + if (d->pix.isNull()) + return; + + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + + QPixmap pix = d->pix; + + QMargins margins(border()->top(), border()->left(), border()->bottom(), border()->right()); + QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode); + qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); + if (d->smooth) { + p->setRenderHint(QPainter::Antialiasing, oldAA); + p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); + } +} + +QFxBorderImage::QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent) + : QFxImageBase(dd, parent) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); +} + +QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxborderimage.h b/src/declarative/fx/qfxborderimage.h new file mode 100644 index 0000000..26ba9cf --- /dev/null +++ b/src/declarative/fx/qfxborderimage.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXBORDERIMAGE_H +#define QFXBORDERIMAGE_H + +#include +#include "qfximagebase.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QFxScaleGrid; +class QFxGridScaledImage; +class QFxBorderImagePrivate; +class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase +{ + Q_OBJECT + Q_ENUMS(TileMode) + + Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) + Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode) + Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode) + +public: + QFxBorderImage(QFxItem *parent=0); + ~QFxBorderImage(); + + QFxScaleGrid *border(); + + enum TileMode { Stretch = Qt::Stretch, Repeat = Qt::Repeat, Round = Qt::Round }; + + TileMode horizontalTileMode() const; + void setHorizontalTileMode(TileMode); + + TileMode verticalTileMode() const; + void setVerticalTileMode(TileMode); + + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void setSource(const QUrl &url); + +protected: + QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); + +private: + void setGridScaledImage(const QFxGridScaledImage& sci); + +private Q_SLOTS: + void requestFinished(); + void sciRequestFinished(); + +private: + Q_DISABLE_COPY(QFxBorderImage) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxBorderImage) +}; + +QT_END_NAMESPACE +QML_DECLARE_TYPE(QFxBorderImage) +QT_END_HEADER + +#endif // QFXBORDERIMAGE_H diff --git a/src/declarative/fx/qfxborderimage_p.h b/src/declarative/fx/qfxborderimage_p.h new file mode 100644 index 0000000..50f3311 --- /dev/null +++ b/src/declarative/fx/qfxborderimage_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXBORDERIMAGE_P_H +#define QFXBORDERIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qfximagebase_p.h" +#include "qfxscalegrid_p.h" + +QT_BEGIN_NAMESPACE + +class QNetworkReply; +class QFxBorderImagePrivate : public QFxImageBasePrivate +{ + Q_DECLARE_PUBLIC(QFxBorderImage) + +public: + QFxBorderImagePrivate() + : border(0), sciReply(0), + horizontalTileMode(QFxBorderImage::Stretch), + verticalTileMode(QFxBorderImage::Stretch) + { + } + + ~QFxBorderImagePrivate() + { + } + + QFxScaleGrid *getScaleGrid() + { + if (!border) + border = new QFxScaleGrid; + return border; + } + + QFxScaleGrid *border; + QUrl sciurl; + QNetworkReply *sciReply; + QFxBorderImage::TileMode horizontalTileMode; + QFxBorderImage::TileMode verticalTileMode; +}; + +QT_END_NAMESPACE + +#endif // QFXBORDERIMAGE_P_H diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 5c9e1f9..79c11b1 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -55,13 +55,10 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) \brief The Image element allows you to add bitmaps to a scene. \inherits Item - The Image element supports untransformed, stretched, tiled, and grid-scaled images. + The Image element supports untransformed, stretched and tiled. For an explanation of stretching and tiling, see the fillMode property description. - For an explanation of grid-scaling see the scaleGrid property description - or the QFxScaleGrid class description. - Examples: \table \row @@ -81,16 +78,6 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) } \endqml \row - \o \image declarative-qtlogo4.png - \o Grid-scaled (only with fillMode: Stretch) - \qml - Image { scaleGrid.left: 20; scaleGrid.right: 10 - scaleGrid.top: 14; scaleGrid.bottom: 14 - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - \row \o \image declarative-qtlogo3.png \o fillMode: Tile \qml @@ -155,10 +142,10 @@ QFxImage::~QFxImage() } /*! - \property QFxImage::image + \property QFxImage::pixmap \brief the image displayed in this item. - This property contains the image currently being displayed by this item, + This property contains the pixmap currently being displayed by this item, which may be empty if nothing is currently displayed. Setting the source property overrides any setting of this property. */ @@ -196,10 +183,6 @@ void QFxImage::setPixmap(const QPixmap &pix) \endlist \image declarative-image_fillMode.gif - - Only fillMode: Stretch can be used with scaleGrid. Other settings - will cause a run-time warning. - \sa examples/declarative/aspectratio */ QFxImage::FillMode QFxImage::fillMode() const @@ -246,21 +229,6 @@ void QFxImage::setFillMode(FillMode mode) Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. - It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies - \list - \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}. - \i an image file. - \endlist - - The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: - \code - gridLeft: 10 - gridTop: 10 - gridBottom: 10 - gridRight: 10 - imageFile: picture.png - \endcode - The URL may be absolute, or relative to the URL of the component. */ @@ -277,74 +245,67 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) QPixmap pix = d->pix; - if (!d->scaleGrid || d->scaleGrid->isNull()) { - if (width() != pix.width() || height() != pix.height()) { - if (d->fillMode >= Tile) { - p->save(); - p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); - - if (d->fillMode == Tile) { - const int pw = pix.width(); - const int ph = pix.height(); - int yy = 0; - - while(yy < height()) { - int xx = 0; - while(xx < width()) { - p->drawPixmap(xx, yy, pix); - xx += pw; - } - yy += ph; - } - } else if (d->fillMode == TileVertically) { - const int ph = pix.height(); - int yy = 0; + if (width() != pix.width() || height() != pix.height()) { + if (d->fillMode >= Tile) { + p->save(); + p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); - while(yy < height()) { - p->drawPixmap(QRect(0, yy, width(), ph), pix); - yy += ph; - } - } else { - const int pw = pix.width(); - int xx = 0; + if (d->fillMode == Tile) { + const int pw = pix.width(); + const int ph = pix.height(); + int yy = 0; + while(yy < height()) { + int xx = 0; while(xx < width()) { - p->drawPixmap(QRect(xx, 0, pw, height()), pix); + p->drawPixmap(xx, yy, pix); xx += pw; } + yy += ph; } + } else if (d->fillMode == TileVertically) { + const int ph = pix.height(); + int yy = 0; - p->restore(); - } else { - qreal widthScale = width() / qreal(pix.width()); - qreal heightScale = height() / qreal(pix.height()); - - QTransform scale; - - if (d->fillMode == PreserveAspect) { - if (widthScale < heightScale) { - heightScale = widthScale; - scale.translate(0, (height() - heightScale * pix.height()) / 2); - } else if(heightScale < widthScale) { - widthScale = heightScale; - scale.translate((width() - widthScale * pix.width()) / 2, 0); - } + while(yy < height()) { + p->drawPixmap(QRect(0, yy, width(), ph), pix); + yy += ph; } + } else { + const int pw = pix.width(); + int xx = 0; - scale.scale(widthScale, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawPixmap(0, 0, pix); - p->setWorldTransform(old); + while(xx < width()) { + p->drawPixmap(QRect(xx, 0, pw, height()), pix); + xx += pw; + } } + + p->restore(); } else { + qreal widthScale = width() / qreal(pix.width()); + qreal heightScale = height() / qreal(pix.height()); + + QTransform scale; + + if (d->fillMode == PreserveAspect) { + if (widthScale < heightScale) { + heightScale = widthScale; + scale.translate(0, (height() - heightScale * pix.height()) / 2); + } else if(heightScale < widthScale) { + widthScale = heightScale; + scale.translate((width() - widthScale * pix.width()) / 2, 0); + } + } + + scale.scale(widthScale, heightScale); + QTransform old = p->transform(); + p->setWorldTransform(scale * old); p->drawPixmap(0, 0, pix); + p->setWorldTransform(old); } } else { - QMargins margins(d->scaleGrid->top(), d->scaleGrid->left(), d->scaleGrid->bottom(), d->scaleGrid->right()); - QTileRules rules((Qt::TileRule)d->scaleGrid->horizontalTileRule(), - (Qt::TileRule)d->scaleGrid->verticalTileRule()); - qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); + p->drawPixmap(0, 0, pix); } if (d->smooth) { diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index b31da29..0a9d2df 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -46,12 +46,11 @@ #include "qfximagebase.h" QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QFxImagePrivate; +class QFxImagePrivate; class Q_DECLARATIVE_EXPORT QFxImage : public QFxImageBase { Q_OBJECT @@ -85,9 +84,7 @@ private: }; QT_END_NAMESPACE - QML_DECLARE_TYPE(QFxImage) - QT_END_HEADER #endif // QFXIMAGE_H diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index 825da5b..8bdcc14 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -56,8 +56,6 @@ #include "qfxitem_p.h" #include "qfximagebase_p.h" -#include - QT_BEGIN_NAMESPACE class QFxImagePrivate : public QFxImageBasePrivate diff --git a/src/declarative/fx/qfximagebase.cpp b/src/declarative/fx/qfximagebase.cpp index 39c43d3..f96ff6f 100644 --- a/src/declarative/fx/qfximagebase.cpp +++ b/src/declarative/fx/qfximagebase.cpp @@ -45,6 +45,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -63,51 +64,10 @@ QFxImageBase::QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent) QFxImageBase::~QFxImageBase() { Q_D(QFxImageBase); - if (d->sciReply) - d->sciReply->deleteLater(); if (!d->url.isEmpty()) QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); } -/*! - \qmlproperty int Image::scaleGrid.left - \qmlproperty int Image::scaleGrid.right - \qmlproperty int Image::scaleGrid.top - \qmlproperty int Image::scaleGrid.bottom - - \target ImagexmlpropertiesscaleGrid - - A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: - - \image declarative-scalegrid.png - - When the image is scaled: - \list - \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled both horizontally and vertically - \i sections 2 and 8 are scaled horizontally - \i sections 4 and 6 are scaled vertically - \endlist - - Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image. - - A scale grid can also be specified using a - \l {Image::source}{.sci file}. -*/ -QFxScaleGrid *QFxImageBase::scaleGrid() -{ - Q_D(QFxImageBase); - return d->getScaleGrid(); -} - -void QFxImageBase::componentComplete() -{ - QFxItem::componentComplete(); -} - - QFxImageBase::Status QFxImageBase::status() const { Q_D(const QFxImageBase); @@ -142,18 +102,10 @@ void QFxImageBase::setSource(const QUrl &url) if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) return; - if (d->sciReply) { - d->sciReply->deleteLater(); - d->sciReply = 0; - } - if (!d->url.isEmpty()) QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); d->url = url; - d->sciurl = QUrl(); if (d->progress != 0.0) { d->progress = 0.0; emit progressChanged(d->progress); @@ -171,22 +123,6 @@ void QFxImageBase::setSource(const QUrl &url) update(); } else { d->status = Loading; - if (d->url.path().endsWith(QLatin1String(".sci"))) { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); - file.open(QIODevice::ReadOnly); - setGridScaledImage(QFxGridScaledImage(&file)); - } else -#endif - { - QNetworkRequest req(d->url); - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->sciReply, SIGNAL(finished()), - this, SLOT(sciRequestFinished())); - } - } else { d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); if (d->reply) { connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); @@ -206,7 +142,6 @@ void QFxImageBase::setSource(const QUrl &url) update(); } } - } emit statusChanged(d->status); } @@ -214,9 +149,6 @@ void QFxImageBase::setSource(const QUrl &url) void QFxImageBase::requestFinished() { Q_D(QFxImageBase); - if (d->url.path().endsWith(QLatin1String(".sci"))) { - QFxPixmap::find(d->sciurl, &d->pix); - } else { if (d->reply) { //###disconnect really needed? disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), @@ -225,7 +157,6 @@ void QFxImageBase::requestFinished() d->status = Error; } QFxPixmap::find(d->url, &d->pix); - } setImplicitWidth(d->pix.width()); setImplicitHeight(d->pix.height()); @@ -238,22 +169,6 @@ void QFxImageBase::requestFinished() update(); } -void QFxImageBase::sciRequestFinished() -{ - Q_D(QFxImageBase); - if (d->sciReply->error() != QNetworkReply::NoError) { - d->status = Error; - d->sciReply->deleteLater(); - d->sciReply = 0; - emit statusChanged(d->status); - } else { - QFxGridScaledImage sci(d->sciReply); - d->sciReply->deleteLater(); - d->sciReply = 0; - setGridScaledImage(sci); - } -} - void QFxImageBase::requestProgress(qint64 received, qint64 total) { Q_D(QFxImageBase); @@ -263,41 +178,5 @@ void QFxImageBase::requestProgress(qint64 received, qint64 total) } } -void QFxImageBase::setGridScaledImage(const QFxGridScaledImage& sci) -{ - Q_D(QFxImageBase); - if (!sci.isValid()) { - d->status = Error; - emit statusChanged(d->status); - } else { - QFxScaleGrid *sg = scaleGrid(); - sg->setTop(sci.gridTop()); - sg->setBottom(sci.gridBottom()); - sg->setLeft(sci.gridLeft()); - sg->setRight(sci.gridRight()); - sg->setHorizontalTileRule(sci.horizontalTileRule()); - sg->setVerticalTileRule(sci.verticalTileRule()); - - d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } - } -} QT_END_NAMESPACE diff --git a/src/declarative/fx/qfximagebase.h b/src/declarative/fx/qfximagebase.h index 78e391e..ce9c0c3 100644 --- a/src/declarative/fx/qfximagebase.h +++ b/src/declarative/fx/qfximagebase.h @@ -44,10 +44,9 @@ #include +QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QFxScaleGrid; -class QFxGridScaledImage; class QFxImageBasePrivate; class QFxImageBase : public QFxItem { @@ -57,7 +56,6 @@ class QFxImageBase : public QFxItem Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) - Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid) public: QFxImageBase(QFxItem *parent = 0); @@ -76,22 +74,17 @@ Q_SIGNALS: protected: QFxImageBase(QFxImageBasePrivate &dd, QFxItem *parent); - virtual void componentComplete(); private Q_SLOTS: - void requestFinished(); - void sciRequestFinished(); + virtual void requestFinished(); void requestProgress(qint64,qint64); private: - void setGridScaledImage(const QFxGridScaledImage& sci); - QFxScaleGrid *scaleGrid(); - -private: Q_DISABLE_COPY(QFxImageBase) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxImageBase) }; QT_END_NAMESPACE +QT_END_HEADER #endif // QFXIMAGEBASE_H diff --git a/src/declarative/fx/qfximagebase_p.h b/src/declarative/fx/qfximagebase_p.h index e84fffe..b468b90 100644 --- a/src/declarative/fx/qfximagebase_p.h +++ b/src/declarative/fx/qfximagebase_p.h @@ -54,48 +54,25 @@ // #include "qfxitem_p.h" -#include "qfxscalegrid_p.h" +#include QT_BEGIN_NAMESPACE -class QSvgRenderer; -class QWebPage; class QNetworkReply; -class QIODevice; - class QFxImageBasePrivate : public QFxItemPrivate { Q_DECLARE_PUBLIC(QFxImageBase) public: QFxImageBasePrivate() - : scaleGrid(0), - status(QFxImageBase::Null), sciReply(0), + : status(QFxImageBase::Null), progress(0.0) { } - ~QFxImageBasePrivate() - { - delete scaleGrid; - } - - void setContent(QIODevice* dev, const QString &url); - - QFxScaleGrid *getScaleGrid() - { - if (!scaleGrid) - scaleGrid = new QFxScaleGrid; - return scaleGrid; - } - - QFxScaleGrid *scaleGrid; QPixmap pix; - QFxImageBase::Status status; QUrl url; - QUrl sciurl; - QNetworkReply *sciReply; QPointer reply; qreal progress; }; diff --git a/src/declarative/fx/qfxscalegrid.cpp b/src/declarative/fx/qfxscalegrid.cpp index 8eb9890..4856c15 100644 --- a/src/declarative/fx/qfxscalegrid.cpp +++ b/src/declarative/fx/qfxscalegrid.cpp @@ -74,8 +74,7 @@ QT_BEGIN_NAMESPACE */ QML_DEFINE_NOCREATE_TYPE(QFxScaleGrid) -QFxScaleGrid::QFxScaleGrid() : QObject(), _left(0), _top(0), _right(0), _bottom(0), - _horizontalTileRule(Stretch), _verticalTileRule(Stretch) +QFxScaleGrid::QFxScaleGrid() : QObject(), _left(0), _top(0), _right(0), _bottom(0) { } @@ -124,20 +123,9 @@ void QFxScaleGrid::setBottom(int pos) _bottom = pos; } -void QFxScaleGrid::setHorizontalTileRule(TileRule r) -{ - _horizontalTileRule = r; -} - -void QFxScaleGrid::setVerticalTileRule(TileRule r) -{ - _verticalTileRule = r; -} - - QFxGridScaledImage::QFxGridScaledImage() : _l(-1), _r(-1), _t(-1), _b(-1), - _h(QFxScaleGrid::Stretch), _v(QFxScaleGrid::Stretch) + _h(QFxBorderImage::Stretch), _v(QFxBorderImage::Stretch) { } @@ -159,7 +147,7 @@ QFxGridScaledImage &QFxGridScaledImage::operator=(const QFxGridScaledImage &o) } QFxGridScaledImage::QFxGridScaledImage(QIODevice *data) -: _l(-1), _r(-1), _t(-1), _b(-1), _h(QFxScaleGrid::Stretch), _v(QFxScaleGrid::Stretch) +: _l(-1), _r(-1), _t(-1), _b(-1), _h(QFxBorderImage::Stretch), _v(QFxBorderImage::Stretch) { int l = -1; int r = -1; @@ -203,17 +191,17 @@ QFxGridScaledImage::QFxGridScaledImage(QIODevice *data) _pix = imgFile; } -QFxScaleGrid::TileRule QFxGridScaledImage::stringToRule(const QString &s) +QFxBorderImage::TileMode QFxGridScaledImage::stringToRule(const QString &s) { if (s == QLatin1String("Stretch")) - return QFxScaleGrid::Stretch; + return QFxBorderImage::Stretch; if (s == QLatin1String("Repeat")) - return QFxScaleGrid::Repeat; + return QFxBorderImage::Repeat; if (s == QLatin1String("Round")) - return QFxScaleGrid::Round; + return QFxBorderImage::Round; qWarning() << "Unknown tile rule specified. Using Stretch"; - return QFxScaleGrid::Stretch; + return QFxBorderImage::Stretch; } bool QFxGridScaledImage::isValid() const diff --git a/src/declarative/fx/qfxscalegrid_p.h b/src/declarative/fx/qfxscalegrid_p.h index 483ade1..9d0a84c 100644 --- a/src/declarative/fx/qfxscalegrid_p.h +++ b/src/declarative/fx/qfxscalegrid_p.h @@ -47,6 +47,7 @@ #include #include #include +#include "qfxborderimage.h" QT_BEGIN_HEADER @@ -54,6 +55,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) + class Q_DECLARATIVE_EXPORT QFxScaleGrid : public QObject { Q_OBJECT @@ -63,8 +65,6 @@ class Q_DECLARATIVE_EXPORT QFxScaleGrid : public QObject Q_PROPERTY(int top READ top WRITE setTop) Q_PROPERTY(int right READ right WRITE setRight) Q_PROPERTY(int bottom READ bottom WRITE setBottom) - Q_PROPERTY(TileRule horizontalTileRule READ horizontalTileRule WRITE setHorizontalTileRule) - Q_PROPERTY(TileRule verticalTileRule READ verticalTileRule WRITE setVerticalTileRule) public: QFxScaleGrid(); @@ -84,21 +84,11 @@ public: int bottom() const { return _bottom; } void setBottom(int); - enum TileRule { Stretch = Qt::Stretch, Repeat = Qt::Repeat, Round = Qt::Round }; - - TileRule horizontalTileRule() const { return _horizontalTileRule; } - void setHorizontalTileRule(TileRule); - - TileRule verticalTileRule() const { return _verticalTileRule; } - void setVerticalTileRule(TileRule); - private: int _left; int _top; int _right; int _bottom; - TileRule _horizontalTileRule; - TileRule _verticalTileRule; }; class Q_DECLARATIVE_EXPORT QFxGridScaledImage @@ -113,21 +103,21 @@ public: int gridRight() const; int gridTop() const; int gridBottom() const; - QFxScaleGrid::TileRule horizontalTileRule() const { return _h; } - QFxScaleGrid::TileRule verticalTileRule() const { return _v; } + QFxBorderImage::TileMode horizontalTileRule() const { return _h; } + QFxBorderImage::TileMode verticalTileRule() const { return _v; } QString pixmapUrl() const; private: - static QFxScaleGrid::TileRule stringToRule(const QString &); + static QFxBorderImage::TileMode stringToRule(const QString &); private: int _l; int _r; int _t; int _b; - QFxScaleGrid::TileRule _h; - QFxScaleGrid::TileRule _v; + QFxBorderImage::TileMode _h; + QFxBorderImage::TileMode _v; QString _pix; }; -- cgit v0.12 From c4235f6f90613f1a877da067354b912ef0004259 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 10 Aug 2009 10:11:08 +1000 Subject: Documentation --- src/declarative/fx/qfxborderimage.cpp | 13 +++++++++++++ src/declarative/fx/qfximage.cpp | 13 +++++++++++++ src/declarative/fx/qfxitem.cpp | 14 -------------- src/declarative/fx/qfxlineedit.cpp | 15 ++++++++++++++- src/declarative/fx/qfxrect.cpp | 13 +++++++++++++ src/declarative/fx/qfxtext.cpp | 13 +++++++++++++ src/declarative/fx/qfxtextedit.cpp | 15 ++++++++++++++- 7 files changed, 80 insertions(+), 16 deletions(-) diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 34f0e66..7e2e3c6 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -118,6 +118,19 @@ QFxBorderImage::~QFxBorderImage() */ /*! + \qmlproperty bool BorderImage::smooth + + Set this property if you want the image to be smoothly filtered when scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the image is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the image is stationary on + the screen. A common pattern when animating an image is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + +/*! \qmlproperty url BorderImage::source BorderImage can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 79c11b1..0cb7988 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -225,6 +225,19 @@ void QFxImage::setFillMode(FillMode mode) */ /*! + \qmlproperty bool Image::smooth + + Set this property if you want the image to be smoothly filtered when scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the image is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the image is stationary on + the screen. A common pattern when animating an image is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + +/*! \qmlproperty url Image::source Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index b36e994..66d5fc7 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -1701,20 +1701,6 @@ void QFxItem::setTransformOrigin(TransformOrigin origin) } /*! - \qmlproperty bool Item::smooth - - Set this property if you want the item to be smoothly scaled or - transformed. Smooth filtering gives better visual quality, but is slower. If - the item is displayed at its natural size, this property has no visual or - performance effect. - Currently, only the \c Image, \c Text , \c TextEdit and \c LineEdit items implement smooth filtering. - - \note Generally scaling artifacts are only visible if the item is stationary on - the screen. A common pattern when animating an item is to disable smooth - filtering at the beginning of the animation and reenable it at the conclusion. - */ - -/*! \property QFxItem::smooth \brief whether the item is smoothly transformed. diff --git a/src/declarative/fx/qfxlineedit.cpp b/src/declarative/fx/qfxlineedit.cpp index 13267f2..760344d 100644 --- a/src/declarative/fx/qfxlineedit.cpp +++ b/src/declarative/fx/qfxlineedit.cpp @@ -467,13 +467,26 @@ void QFxLineEdit::drawContents(QPainter *p, const QRect &r) p->restore(); } +/*! + \qmlproperty bool LineEdit::smooth + + Set this property if you want the text to be smoothly scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the item is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the item is stationary on + the screen. A common pattern when animating an item is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + void QFxLineEditPrivate::init() { Q_Q(QFxLineEdit); control->setCursorWidth(1); control->setPasswordCharacter(QLatin1Char('*')); control->setLayoutDirection(Qt::LeftToRight); - q->setSmoothTransform(true); + q->setSmoothTransform(smooth); q->setAcceptedMouseButtons(Qt::LeftButton); q->setFlag(QGraphicsItem::ItemHasNoContents, false); q->setFlag(QGraphicsItem::ItemAcceptsInputMethod); diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index 29321b8..0bd240e 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -591,6 +591,19 @@ void QFxRect::drawRect(QPainter &p) } } +/*! + \qmlproperty bool Rect::smooth + + Set this property if you want the item to be smoothly scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the item is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the item is stationary on + the screen. A common pattern when animating an item is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + QRectF QFxRect::boundingRect() const { Q_D(const QFxRect); diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 0c3f4e9..c3872c4 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -809,6 +809,19 @@ void QFxText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) } } +/*! + \qmlproperty bool Text::smooth + + Set this property if you want the text to be smoothly scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the item is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the item is stationary on + the screen. A common pattern when animating an item is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + void QFxText::componentComplete() { Q_D(QFxText); diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index e4001b2..dbaba79 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -1010,11 +1010,24 @@ void QFxTextEdit::updateImgCache(const QRectF &r) emit update(); } +/*! + \qmlproperty bool TextEdit::smooth + + Set this property if you want the text to be smoothly scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the item is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the item is stationary on + the screen. A common pattern when animating an item is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + void QFxTextEditPrivate::init() { Q_Q(QFxTextEdit); - q->setSmoothTransform(true); + q->setSmoothTransform(smooth); q->setAcceptedMouseButtons(Qt::LeftButton); q->setFlag(QGraphicsItem::ItemHasNoContents, false); q->setFlag(QGraphicsItem::ItemAcceptsInputMethod); -- cgit v0.12 From 94badeee58b6d81ba01966fa21461f31b51fa206 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 10:38:41 +1000 Subject: Avoid pointless QMetaProperty lookup --- src/declarative/qml/qmlmetaproperty.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 09ca872..64dd9cd 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -901,12 +901,11 @@ void QmlMetaProperty::write(const QVariant &value) const if (!d->object) return; - QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); if (type() & SignalProperty) { d->writeSignalProperty(value); - } else if (prop.name()) { + } else if (d->coreIdx != -1) { d->writeValueProperty(value); -- cgit v0.12 From d222608c961c0b2dd5509488e5aa89864aafb675 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 10:38:55 +1000 Subject: Add a WebView::evaluateJavaScript() method Authored-by: Tapani Mikola --- src/declarative/fx/qfxwebview.cpp | 9 +++++++++ src/declarative/fx/qfxwebview.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index 47199ef..d9108f3 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -416,6 +416,15 @@ void QFxWebView::setInteractive(bool i) emit interactiveChanged(); } +/*! + Evaluates the \a scriptSource JavaScript inside the main frame + context and returns the result of the last executed statement. +*/ +QVariant QFxWebView::evaluateJavaScript(const QString &scriptSource) +{ + return this->page()->mainFrame()->evaluateJavaScript(scriptSource); +} + void QFxWebView::expandToWebPage() { Q_D(QFxWebView); diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 1200162..64b9176 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -178,6 +178,9 @@ Q_SIGNALS: void singleClick(); void doubleClick(); +public Q_SLOTS: + QVariant evaluateJavaScript (const QString&); + private Q_SLOTS: void expandToWebPage(); void paintPage(const QRect&); -- cgit v0.12 From c5865c9a8dbd3c5be11069aff59935aa9b9a75bb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 11:24:54 +1000 Subject: Mark synthesized properties as SCRIPTABLE --- src/declarative/qml/qmlcompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 6ef7cc2..1c535d4 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1904,7 +1904,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) dynamicData.append((char *)&propertyData, sizeof(propertyData)); builder.addSignal(p.name + "Changed()"); - builder.addProperty(p.name, type, ii); + builder.addProperty(p.name, type, ii).setScriptable(true); } if (mode == ResolveAliases) { -- cgit v0.12 From 1682279a946955e8a08a3287e0642c32fa6e0d01 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 11:34:21 +1000 Subject: Fix crash in property aliases Since 588093b3e12dd5039bcc4ee545d9d9112d25394f id objects are stored in the special idValues array, not in the generic propertyValues list. --- src/declarative/qml/qmlvmemetaobject.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index 33a31a4..9ce63b1 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -168,8 +168,7 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) QmlContextPrivate *ctxtPriv = (QmlContextPrivate *)QObjectPrivate::get(ctxt); - QObject *target = - *(QObject **)ctxtPriv->propertyValues[d->contextIdx].data(); + QObject *target = ctxtPriv->idValues[d->contextIdx].data(); if (!target) return -1; if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { -- cgit v0.12 From 64d78252c65edc6dbb2294cac9e4f6281fbdc39f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 11:44:44 +1000 Subject: Support adding "window objects" to webview This functionality is equivalent to the C++ QWebFrame::addToJavaScriptWindowObject() API. --- src/declarative/fx/qfxwebview.cpp | 76 +++++++++++++++++++++++++++++++++++++-- src/declarative/fx/qfxwebview.h | 8 +++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index d9108f3..37e5d59 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -139,7 +139,7 @@ class QFxWebViewPrivate : public QFxPaintedItemPrivate public: QFxWebViewPrivate() : QFxPaintedItemPrivate(), page(0), idealwidth(0), idealheight(0), interactive(true), lastPress(0), lastRelease(0), mouseX(0), mouseY(0), - progress(1.0), pending(PendingNone) + progress(1.0), pending(PendingNone), windowObjects(this) { } @@ -158,8 +158,21 @@ public: QString pending_string; QByteArray pending_data; mutable QFxWebSettings settings; -}; + void updateWindowObjects(); + class WindowObjectList : public QmlConcreteList + { + public: + WindowObjectList(QFxWebViewPrivate *p) + : priv(p) {} + virtual void append(QObject *v) { + QmlConcreteList::append(v); + priv->updateWindowObjects(); + } + private: + QFxWebViewPrivate *priv; + } windowObjects; +}; /*! \qmlclass WebView @@ -258,6 +271,7 @@ void QFxWebView::componentComplete() break; } d->pending = QFxWebViewPrivate::PendingNone; + d->updateWindowObjects(); } /*! @@ -509,6 +523,56 @@ void QFxWebView::setCacheSize(int pixels) d->max_imagecache_size = pixels; } +QmlList *QFxWebView::javaScriptWindowObjects() +{ + Q_D(QFxWebView); + return &d->windowObjects; +} + +class QFxWebViewAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString windowObjectName READ windowObjectName WRITE setWindowObjectName) +public: + QFxWebViewAttached(QObject *parent) + : QObject(parent) + { + } + + QString windowObjectName() const + { + return m_windowObjectName; + } + + void setWindowObjectName(const QString &n) + { + m_windowObjectName = n; + } + +private: + QString m_windowObjectName; +}; + +QFxWebViewAttached *QFxWebView::qmlAttachedProperties(QObject *o) +{ + return new QFxWebViewAttached(o); +} + +void QFxWebViewPrivate::updateWindowObjects() +{ + Q_Q(QFxWebView); + if (!q->isComponentComplete() || !page) + return; + + for (int ii = 0; ii < windowObjects.count(); ++ii) { + QObject *object = windowObjects.at(ii); + QFxWebViewAttached *attached = static_cast(qmlAttachedPropertiesObject(object)); + if (attached && !attached->windowObjectName().isEmpty()) { + page->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object); + } + } +} + void QFxWebView::drawContents(QPainter *p, const QRect &r) { page()->mainFrame()->render(p,r); @@ -787,6 +851,12 @@ void QFxWebView::setStatusBarMessage(const QString& s) emit statusChanged(); } +void QFxWebView::windowObjectCleared() +{ + Q_D(QFxWebView); + d->updateWindowObjects(); +} + QString QFxWebView::status() const { Q_D(const QFxWebView); @@ -880,6 +950,8 @@ void QFxWebView::setPage(QWebPage *page) connect(d->page,SIGNAL(loadProgress(int)),this,SLOT(doLoadProgress(int))); connect(d->page,SIGNAL(loadFinished(bool)),this,SLOT(doLoadFinished(bool))); connect(d->page,SIGNAL(statusBarMessage(QString)),this,SLOT(setStatusBarMessage(QString))); + + connect(d->page->mainFrame(),SIGNAL(javaScriptWindowObjectCleared()),this,SLOT(windowObjectCleared())); } void QFxWebView::load(const QNetworkRequest &request, diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 64b9176..8df3d18 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -74,6 +74,7 @@ private: }; +class QFxWebViewAttached; class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem { Q_OBJECT @@ -103,6 +104,8 @@ class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem Q_PROPERTY(QObject* settings READ settingsObject CONSTANT) + Q_PROPERTY(QmlList* javaScriptWindowObjects READ javaScriptWindowObjects CONSTANT) + public: QFxWebView(QFxItem *parent=0); ~QFxWebView(); @@ -160,6 +163,10 @@ public: int cacheSize() const; void setCacheSize(int pixels); + QmlList *javaScriptWindowObjects(); + + static QFxWebViewAttached *qmlAttachedProperties(QObject *); + Q_SIGNALS: void idealWidthChanged(); void idealHeightChanged(); @@ -187,6 +194,7 @@ private Q_SLOTS: void doLoadProgress(int p); void doLoadFinished(bool ok); void setStatusBarMessage(const QString&); + void windowObjectCleared(); protected: QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent); -- cgit v0.12 From 3ee9db1d892927522832b6bc8e1d806e27015bc4 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 11:51:09 +1000 Subject: As WebView now has attached properties, it can't be used as an id --- demos/declarative/webbrowser/webbrowser.qml | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index 28e5f16..7a7d9e2 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -17,8 +17,8 @@ Item { } function toggleZoom() { if(WebBrowser.state == "ZoomedOut") { - Flick.centerX = WebView.mouseX; - Flick.centerY = WebView.mouseY; + Flick.centerX = MyWebView.mouseX; + Flick.centerY = MyWebView.mouseY; WebBrowser.state = "Normal"; } else { zoomOut(); @@ -48,8 +48,8 @@ Item { RectSoftShadow { x: -Flick.xPosition y: -Flick.yPosition - width: WebView.width*WebView.scale - height: Flick.y+WebView.height*WebView.scale + width: MyWebView.width*MyWebView.scale + height: Flick.y+MyWebView.height*MyWebView.scale } Item { id: HeaderSpace @@ -70,7 +70,7 @@ Item { Text { id: HeaderText - text: WebView.title!='' || WebView.progress == 1.0 ? WebView.title : 'Loading...' + text: MyWebView.title!='' || MyWebView.progress == 1.0 ? MyWebView.title : 'Loading...' elide: "ElideRight" color: "white" @@ -111,7 +111,7 @@ Item { Image { id: UrlBoxhl source: "content/pics/addressbar-filled.sci" - width: parent.width*WebView.progress + width: parent.width*MyWebView.progress height: parent.height opacity: 1-Header.progressOff clip: true @@ -132,7 +132,7 @@ Item { TextEdit { id: EditUrl - text: WebView.url == '' ? ' ' : WebView.url + text: MyWebView.url == '' ? ' ' : MyWebView.url wrap: false font.size: 11 color: "#555555" @@ -151,12 +151,12 @@ Item { states: [ State { name: "Normal" - when: WebView.progress == 1.0 + when: MyWebView.progress == 1.0 SetProperties { target: Header; progressOff: 1 } }, State { name: "ProgressShown" - when: WebView.progress < 1.0 + when: MyWebView.progress < 1.0 SetProperties { target: Header; progressOff: 0; } } ] @@ -175,8 +175,8 @@ Item { Flickable { id: Flick width: parent.width - viewportWidth: Math.max(parent.width,WebView.width*WebView.scale) - viewportHeight: Math.max(parent.height,WebView.height*WebView.scale) + viewportWidth: Math.max(parent.width,MyWebView.width*MyWebView.scale) + viewportHeight: Math.max(parent.height,MyWebView.height*MyWebView.scale) anchors.top: HeaderSpace.bottom anchors.bottom: Footer.top anchors.left: parent.left @@ -186,7 +186,7 @@ Item { property real centerY : 0 WebView { - id: WebView + id: MyWebView cacheSize: 4000000 url: WebBrowser.url @@ -207,7 +207,7 @@ Item { id: WebViewTint color: "black" opacity: 0 - anchors.fill: WebView + anchors.fill: MyWebView MouseRegion { anchors.fill: WebViewTint onClicked: { proxy.focus=false } @@ -246,13 +246,13 @@ Item { states: [ State { name: "Enabled" - when: WebView.back.enabled==true + when: MyWebView.back.enabled==true SetProperties { target: back_e; opacity: 1 } SetProperties { target: back_d; opacity: 0 } }, State { name: "Disabled" - when: WebView.back.enabled==false + when: MyWebView.back.enabled==false SetProperties { target: back_e; opacity: 0 } SetProperties { target: back_d; opacity: 1 } } @@ -268,7 +268,7 @@ Item { ] MouseRegion { anchors.fill: back_e - onClicked: { if (WebView.back.enabled) WebView.back.trigger() } + onClicked: { if (MyWebView.back.enabled) MyWebView.back.trigger() } } } Image { @@ -279,7 +279,7 @@ Item { } MouseRegion { anchors.fill: reload - onClicked: { WebView.reload.trigger() } + onClicked: { MyWebView.reload.trigger() } } Item { id: forwardbutton @@ -302,13 +302,13 @@ Item { states: [ State { name: "Enabled" - when: WebView.forward.enabled==true + when: MyWebView.forward.enabled==true SetProperties { target: forward_e; opacity: 1 } SetProperties { target: forward_d; opacity: 0 } }, State { name: "Disabled" - when: WebView.forward.enabled==false + when: MyWebView.forward.enabled==false SetProperties { target: forward_e; opacity: 0 } SetProperties { target: forward_d; opacity: 1 } } @@ -324,7 +324,7 @@ Item { ] MouseRegion { anchors.fill: parent - onClicked: { if (WebView.forward.enabled) WebView.forward.trigger() } + onClicked: { if (MyWebView.forward.enabled) MyWebView.forward.trigger() } } } } @@ -332,26 +332,26 @@ Item { states: [ State { name: "Normal" - SetProperties { target: WebView; zoomedOut: 0 } - SetProperties { target: Flick; explicit: true; xPosition: Math.min(WebView.width-Flick.width,Math.max(0,Flick.centerX-Flick.width/2)) } - SetProperties { target: Flick; explicit: true; yPosition: Math.min(WebView.height-Flick.height,Math.max(0,Flick.centerY-Flick.height/2)) } + SetProperties { target: MyWebView; zoomedOut: 0 } + SetProperties { target: Flick; explicit: true; xPosition: Math.min(MyWebView.width-Flick.width,Math.max(0,Flick.centerX-Flick.width/2)) } + SetProperties { target: Flick; explicit: true; yPosition: Math.min(MyWebView.height-Flick.height,Math.max(0,Flick.centerY-Flick.height/2)) } }, State { name: "ZoomedOut" - SetProperties { target: WebView; zoomedOut: 1 } + SetProperties { target: MyWebView; zoomedOut: 1 } } ] transitions: [ Transition { SequentialAnimation { SetPropertyAction { - target: WebView + target: MyWebView property: "smooth" value: false } ParallelAnimation { NumberAnimation { - target: WebView + target: MyWebView properties: "zoomedOut" easing: "easeInOutQuad" duration: 200 @@ -364,7 +364,7 @@ Item { } } SetPropertyAction { - target: WebView + target: MyWebView property: "smooth" value: !Flick.moving } -- cgit v0.12 From 12ffa33ddc725cd94662a383af6e1793049c807c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 13:44:48 +1000 Subject: Simplify QmlDeclarativeData to a single class --- src/declarative/qml/qmlcontext.cpp | 11 +-- src/declarative/qml/qmlcontext.h | 1 - src/declarative/qml/qmlcontext_p.h | 3 +- src/declarative/qml/qmldeclarativedata_p.h | 113 +++++------------------------ src/declarative/qml/qmlengine.cpp | 37 ++++++---- src/declarative/qml/qmlvme.cpp | 6 +- 6 files changed, 46 insertions(+), 125 deletions(-) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 8a2732d..18ba906 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -106,8 +106,6 @@ void QmlContextPrivate::init() else scopeChain = parent->d_func()->scopeChain; scopeChain.prepend(scopeObj); - - contextData.context = q; } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) @@ -291,13 +289,10 @@ QmlContext::~QmlContext() for (int ii = 0; ii < d->contextObjects.count(); ++ii) { QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii)); - QmlSimpleDeclarativeData *data = - static_cast(p->declarativeData); - if(data && (data->flags & QmlSimpleDeclarativeData::Extended)) { + QmlDeclarativeData *data = + static_cast(p->declarativeData); + if(data) data->context = 0; - } else { - p->declarativeData = 0; - } } d->contextObjects.clear(); diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 1f29ca2..70a81fc 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -89,7 +89,6 @@ private: friend class QmlComponent; friend class QmlScriptPrivate; friend class QmlBoundSignalProxy; - friend class QmlSimpleDeclarativeData; QmlContext(QmlContext *parent, QObject *objParent, bool); QmlContext(QmlEngine *, bool); }; diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 60655ae..0424a85 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -106,7 +106,6 @@ public: QmlExpressionPrivate *expressions; - QmlSimpleDeclarativeData contextData; QObjectList contextObjects; struct ContextGuard : public QGuard @@ -115,7 +114,7 @@ public: ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } - void objectDestroyed(QObject *o) { priv->destroyed(this); } + void objectDestroyed(QObject *) { priv->destroyed(this); } }; ContextGuard *idValues; int idValueCount; diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index b473e77..8d30bcc 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -57,113 +57,36 @@ QT_BEGIN_NAMESPACE -class QmlSimpleDeclarativeData : public QDeclarativeData -{ -public: - QmlSimpleDeclarativeData() : flags(0), context(0) {} - - virtual void destroyed(QObject *); - enum Flag { Instance = 0x00000001, Extended = 0x00000002 }; - quint32 flags; - QmlContext *context; - - static inline QmlSimpleDeclarativeData *get(QObject *object, - bool create = false); -}; - class QmlCompiledData; -class QmlInstanceDeclarativeData : public QmlSimpleDeclarativeData +class QmlBinding; +class QmlDeclarativeData : public QDeclarativeData { public: - QmlInstanceDeclarativeData() : deferredComponent(0) { flags |= Instance; } + QmlDeclarativeData(QmlContext *context = 0); virtual void destroyed(QObject *); - QmlCompiledData *deferredComponent; - unsigned int deferredIdx; - - static inline QmlInstanceDeclarativeData *get(QObject *object, - bool create = false); -}; - -class QmlExtendedDeclarativeData : public QmlInstanceDeclarativeData -{ -public: - QmlExtendedDeclarativeData() { flags |= Extended; } - - QHash attachedProperties; - - static inline QmlExtendedDeclarativeData *get(QObject *object, - bool create = false); -}; - -QmlSimpleDeclarativeData * -QmlSimpleDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (create && !priv->declarativeData) - priv->declarativeData = new QmlInstanceDeclarativeData; - - return static_cast(priv->declarativeData); -} - -QmlInstanceDeclarativeData * -QmlInstanceDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); - - QmlSimpleDeclarativeData *simple = - static_cast(priv->declarativeData); - - if (simple && (simple->flags & Instance)) { - return static_cast(simple); - } else if (create && simple) { - QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; - rv->context = simple->context; - simple->destroyed(object); - priv->declarativeData = rv; - return rv; - } else if (create) { - QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; - priv->declarativeData = rv; - return rv; - } - return 0; -} - -QmlExtendedDeclarativeData * -QmlExtendedDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); + QmlContext *context; + QmlBinding *bindings; - QmlSimpleDeclarativeData *simple = - static_cast(priv->declarativeData); + QmlCompiledData *deferredComponent; // Can't this be found from the context? + unsigned int deferredIdx; - if (simple && (simple->flags & Extended)) { - return static_cast(simple); - } else if (create && simple) { - QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; - rv->context = simple->context; + QHash *attachedProperties; - if (simple->flags & Instance) { - QmlInstanceDeclarativeData *instance = - static_cast(priv->declarativeData); - rv->deferredComponent = instance->deferredComponent; - rv->deferredIdx = instance->deferredIdx; - delete simple; + static QmlDeclarativeData *get(const QObject *object, bool create = false) { + QObjectPrivate *priv = + QObjectPrivate::get(const_cast(object)); + if (priv && priv->declarativeData) { + return static_cast(priv->declarativeData); + } else if (create && priv) { + priv->declarativeData = new QmlDeclarativeData; + return static_cast(priv->declarativeData); } else { - simple->destroyed(object); + return 0; } - priv->declarativeData = rv; - return rv; - } else if (create) { - QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; - priv->declarativeData = rv; - return rv; } - return 0; -} +}; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 68ad655..09539bc 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -427,8 +427,8 @@ QmlContext *QmlEngine::contextForObject(const QObject *object) QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); - QmlSimpleDeclarativeData *data = - static_cast(priv->declarativeData); + QmlDeclarativeData *data = + static_cast(priv->declarativeData); return data?data->context:0; } @@ -444,8 +444,8 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) { QObjectPrivate *priv = QObjectPrivate::get(object); - QmlSimpleDeclarativeData *data = - static_cast(priv->declarativeData); + QmlDeclarativeData *data = + static_cast(priv->declarativeData); if (data && data->context) { qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext"); @@ -453,7 +453,7 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) } if (!data) { - priv->declarativeData = &context->d_func()->contextData; + priv->declarativeData = new QmlDeclarativeData(context); } else { data->context = context; } @@ -463,7 +463,7 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) void qmlExecuteDeferred(QObject *object) { - QmlInstanceDeclarativeData *data = QmlInstanceDeclarativeData::get(object); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); if (data && data->deferredComponent) { QmlVME vme; @@ -487,10 +487,9 @@ QmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { - QmlExtendedDeclarativeData *edata = - QmlExtendedDeclarativeData::get(const_cast(object), true); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); - QObject *rv = edata->attachedProperties.value(id); + QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0; if (rv || !create) return rv; @@ -500,23 +499,29 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre rv = pf(const_cast(object)); - if (rv) - edata->attachedProperties.insert(id, rv); + if (rv) { + if (!data->attachedProperties) + data->attachedProperties = new QHash(); + data->attachedProperties->insert(id, rv); + } return rv; } -void QmlSimpleDeclarativeData::destroyed(QObject *object) +QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt) +: context(ctxt), bindings(0), deferredComponent(0), attachedProperties(0) { - if (context) - context->d_func()->contextObjects.removeAll(object); } -void QmlInstanceDeclarativeData::destroyed(QObject *object) +void QmlDeclarativeData::destroyed(QObject *object) { - QmlSimpleDeclarativeData::destroyed(object); if (deferredComponent) deferredComponent->release(); + if (attachedProperties) + delete attachedProperties; + if (context) + static_cast(QObjectPrivate::get(context))->contextObjects.removeAll(object); + delete this; } diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index bf3b31a..ffe8591 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -111,7 +111,7 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp, int start, int cou void QmlVME::runDeferred(QObject *object) { - QmlInstanceDeclarativeData *data = QmlInstanceDeclarativeData::get(object); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); if (!data || !data->context || !data->deferredComponent) return; @@ -725,8 +725,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData { if (instr.defer.deferCount) { QObject *target = stack.top(); - QmlInstanceDeclarativeData *data = - QmlInstanceDeclarativeData::get(target, true); + QmlDeclarativeData *data = + QmlDeclarativeData::get(target, true); comp->addref(); data->deferredComponent = comp; data->deferredIdx = ii; -- cgit v0.12 From ede82d1abfeadf81a294bdb91eb932b36c437c03 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 10 Aug 2009 14:52:04 +1000 Subject: Add a PreserveAspectFill mode (needs a better name) --- examples/declarative/fillmode/fillmode.qml | 3 +++ src/declarative/fx/qfximage.cpp | 9 +++++++++ src/declarative/fx/qfximage.h | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/declarative/fillmode/fillmode.qml b/examples/declarative/fillmode/fillmode.qml index 6bf1c12..d5d6bb5 100644 --- a/examples/declarative/fillmode/fillmode.qml +++ b/examples/declarative/fillmode/fillmode.qml @@ -13,6 +13,9 @@ Image { SetPropertyAction { value: "PreserveAspect" } SetPropertyAction { target: Label; property: "text"; value: "PreserveAspect" } PauseAnimation { duration: 1000 } + SetPropertyAction { value: "PreserveAspectFill" } + SetPropertyAction { target: Label; property: "text"; value: "PreserveAspectFill" } + PauseAnimation { duration: 1000 } SetPropertyAction { value: "Tile" } SetPropertyAction { target: Label; property: "text"; value: "Tile" } PauseAnimation { duration: 1000 } diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 0cb7988..985ddec 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -177,6 +177,7 @@ void QFxImage::setPixmap(const QPixmap &pix) \list \o Stretch - the image is scaled to fit \o PreserveAspect - the image is scaled uniformly to fit + \o PreserveAspectFill - the image is scaled uniformly to fill \o Tile - the image is duplicated horizontally and vertically \o TileVertically - the image is stretched horizontally and tiled vertically \o TileHorizontally - the image is stretched vertically and tiled horizontally @@ -309,6 +310,14 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) widthScale = heightScale; scale.translate((width() - widthScale * pix.width()) / 2, 0); } + } else if (d->fillMode == PreserveAspectFill) { + if (widthScale < heightScale) { + widthScale = heightScale; + scale.translate((width() - widthScale * pix.width()) / 2, 0); + } else if(heightScale < widthScale) { + heightScale = widthScale; + scale.translate(0, (height() - heightScale * pix.height()) / 2); + } } scale.scale(widthScale, heightScale); diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index 0a9d2df..91b10ef 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -63,7 +63,7 @@ public: QFxImage(QFxItem *parent=0); ~QFxImage(); - enum FillMode { Stretch, PreserveAspect, Tile, TileVertically, TileHorizontally }; + enum FillMode { Stretch, PreserveAspect, PreserveAspectFill, Tile, TileVertically, TileHorizontally }; FillMode fillMode() const; void setFillMode(FillMode); -- cgit v0.12 From f33b89ae82dcb6fa711bd61bf33752960aa9675b Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 10 Aug 2009 14:52:53 +1000 Subject: docs --- examples/declarative/border-image/colors.png | Bin 1809 -> 1655 bytes src/declarative/fx/qfxborderimage.cpp | 14 +++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/declarative/border-image/colors.png b/examples/declarative/border-image/colors.png index c0e137c..dfb62f3 100644 Binary files a/examples/declarative/border-image/colors.png and b/examples/declarative/border-image/colors.png differ diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 7e2e3c6..7911437 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -52,7 +52,7 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,BorderImage,QFxBorderImage) /*! \qmlclass BorderImage QFxBorderImage - \brief The BorderImage element allows you to add an image used as a border to a scene. + \brief The BorderImage element allows you use an image as a border. \inherits Item Example: @@ -237,21 +237,21 @@ void QFxBorderImage::setSource(const QUrl &url) \target ImagexmlpropertiesscaleGrid - A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: + The 4 border lines (2 horizontal and 2 vertical) break an image into 9 sections, as shown below: \image declarative-scalegrid.png When the image is scaled: \list \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled both horizontally and vertically - \i sections 2 and 8 are scaled horizontally - \i sections 4 and 6 are scaled vertically + \i the middle (section 5) is scaled according to BorderImage::horizontalTileMode and BorderImage::verticalTileMode + \i sections 2 and 8 are scaled according to BorderImage::horizontalTileMode + \i sections 4 and 6 are scaled according to BorderImage::verticalTileMode \endlist - Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom scale grid line 10 pixels up from the bottom of the image. + Each border line (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom line 10 pixels up from the bottom of the image. - A scale grid can also be specified using a + The border lines can also be specified using a \l {BorderImage::source}{.sci file}. */ -- cgit v0.12 From 8c3405bbf65826f0ab0be0bd090d723f8efaa3af Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 15:37:19 +1000 Subject: Abstract expression and binding APIs By splitting the interface through which the system interacts with bindings away from a specific implementation, we can introduce highly specialized implementations for specific optimizations. This commit also includes a sample optimization for object properties being assigned directly from a local id. --- src/declarative/qml/qml.pri | 6 +- src/declarative/qml/qmlbasicscript.cpp | 17 ++++ src/declarative/qml/qmlbasicscript_p.h | 3 + src/declarative/qml/qmlbinding.cpp | 82 +++++++++++++----- src/declarative/qml/qmlbinding.h | 36 ++++++-- src/declarative/qml/qmlbinding_p.h | 3 +- src/declarative/qml/qmlbindingoptimizations.cpp | 109 ++++++++++++++++++++++++ src/declarative/qml/qmlbindingoptimizations_p.h | 91 ++++++++++++++++++++ src/declarative/qml/qmlcompiler.cpp | 19 +++++ src/declarative/qml/qmlcompiler_p.h | 2 + src/declarative/qml/qmlcomponent.cpp | 4 +- src/declarative/qml/qmlcomponent_p.h | 2 +- src/declarative/qml/qmlcontext.cpp | 14 +-- src/declarative/qml/qmlcontext_p.h | 6 +- src/declarative/qml/qmldeclarativedata_p.h | 4 +- src/declarative/qml/qmlengine.cpp | 19 +++-- src/declarative/qml/qmlengine_p.h | 5 +- src/declarative/qml/qmlenginedebug.cpp | 2 +- src/declarative/qml/qmlexpression.cpp | 92 ++++++++++++-------- src/declarative/qml/qmlexpression_p.h | 25 ++++-- src/declarative/qml/qmlinstruction_p.h | 5 ++ src/declarative/qml/qmlmetaproperty.cpp | 63 ++++++-------- src/declarative/qml/qmlmetaproperty.h | 6 +- src/declarative/qml/qmlvme.cpp | 19 ++++- src/declarative/util/qmlsetproperties.cpp | 5 +- src/declarative/util/qmlstate.h | 4 +- src/declarative/util/qmlstate_p.h | 2 +- src/declarative/util/qmltransitionmanager.cpp | 2 - 28 files changed, 505 insertions(+), 142 deletions(-) create mode 100644 src/declarative/qml/qmlbindingoptimizations.cpp create mode 100644 src/declarative/qml/qmlbindingoptimizations_p.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 75e5692..575876f 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -29,7 +29,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlenginedebug.cpp \ qml/qmlrewrite.cpp \ qml/qmlbasicscript.cpp \ - qml/qmlvaluetype.cpp + qml/qmlvaluetype.cpp \ + qml/qmlbindingoptimizations.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -75,7 +76,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlenginedebug_p.h \ qml/qmlrewrite_p.h \ qml/qpodvector_p.h \ - qml/qmlvaluetype_p.h + qml/qmlvaluetype_p.h \ + qml/qmlbindingoptimizations_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 21860a5..8993845 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -697,6 +697,23 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) return stack.top(); } +bool QmlBasicScript::isSingleIdFetch() const +{ + if (!isValid()) + return false; + + return d->instructionCount == 1 && + d->instructions()[0].type == ScriptInstruction::LoadIdObject; +} + +int QmlBasicScript::singleIdFetchIndex() const +{ + if (!isSingleIdFetch()) + return -1; + + return d->instructions()[0].fetch.idx; +} + /*! Return a pointer to the script's compile data, or null if there is no data. */ diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 92d58f9..d096746 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -98,6 +98,9 @@ public: QVariant run(QmlContext *, QObject *); + bool isSingleIdFetch() const; + int singleIdFetchIndex() const; + private: int flags; QmlBasicScriptPrivate *d; diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 41cef49..7c5b366 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include Q_DECLARE_METATYPE(QList); @@ -55,7 +57,7 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); QmlBindingPrivate::QmlBindingPrivate() -: inited(false), updating(false), enabled(true), mePtr(0) +: updating(false), enabled(false), mePtr(0) { } @@ -92,25 +94,6 @@ QmlMetaProperty QmlBinding::property() const return d->property; } -void QmlBinding::init() -{ - Q_D(QmlBinding); - - if (d->inited) - return; - d->inited = true; - update(); -} - -void QmlBinding::forceUpdate() -{ - Q_D(QmlBinding); - if (!d->inited) - init(); - else - update(); -} - void QmlBinding::update() { Q_D(QmlBinding); @@ -118,7 +101,7 @@ void QmlBinding::update() #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer bu; #endif - if (!d->inited || !d->enabled) + if (!d->enabled) return; if (!d->updating) { @@ -168,6 +151,20 @@ void QmlBinding::setEnabled(bool e) Q_D(QmlBinding); d->enabled = e; setTrackChange(e); + + if (e) { + d->mePtr = 0; + addToObject(d->property.object()); + update(); + } else { + removeFromObject(); + } +} + +int QmlBinding::propertyIndex() +{ + Q_D(QmlBinding); + return d->property.coreIndex(); } bool QmlBinding::enabled() const @@ -177,4 +174,47 @@ bool QmlBinding::enabled() const return d->enabled; } +QString QmlBinding::expression() const +{ + return QmlExpression::expression(); +} + +QmlAbstractBinding::QmlAbstractBinding() +: m_prevBinding(0), m_nextBinding(0) +{ +} + +QmlAbstractBinding::~QmlAbstractBinding() +{ + removeFromObject(); +} + +void QmlAbstractBinding::addToObject(QObject *object) +{ + removeFromObject(); + + if (object) { + QmlDeclarativeData *data = QmlDeclarativeData::get(object, true); + m_nextBinding = data->bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &data->bindings; + data->bindings = this; + } +} + +void QmlAbstractBinding::removeFromObject() +{ + if (m_prevBinding) { + *m_prevBinding = m_nextBinding; + if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; + m_prevBinding = 0; + m_nextBinding = 0; + } +} + +QString QmlAbstractBinding::expression() const +{ + return QLatin1String(""); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index c2182d5..ad25c16 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -54,9 +54,34 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QmlAbstractBinding +{ +public: + QmlAbstractBinding(); + virtual ~QmlAbstractBinding(); + + virtual QString expression() const; + + virtual void setEnabled(bool) = 0; + virtual int propertyIndex() = 0; + + virtual void update() = 0; + + void addToObject(QObject *); + void removeFromObject(); + +private: + friend class QmlDeclarativeData; + friend class QmlMetaProperty; + + QmlAbstractBinding **m_prevBinding; + QmlAbstractBinding *m_nextBinding; +}; + class QmlContext; class QmlBindingPrivate; -class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression +class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, + public QmlAbstractBinding { Q_OBJECT public: @@ -67,12 +92,13 @@ public: void setTarget(const QmlMetaProperty &); QmlMetaProperty property() const; - void init(); - void forceUpdate(); - - void setEnabled(bool); bool enabled() const; + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + virtual QString expression() const; + public Q_SLOTS: void update(); diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index ec1a04a..767e6af 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -65,13 +65,12 @@ class QmlBindingPrivate : public QmlExpressionPrivate public: QmlBindingPrivate(); - bool inited:1; bool updating:1; bool enabled:1; QmlMetaProperty property; - QmlBinding **mePtr; + QmlAbstractBinding **mePtr; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp new file mode 100644 index 0000000..235c034 --- /dev/null +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlbindingoptimizations_p.h" +#include + +QT_BEGIN_NAMESPACE + + +QmlBindingIdOptimization::QmlBindingIdOptimization(QObject *object, + int propertyIdx, + QmlContext *context, + int id) +: m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id) +{ + QmlAbstractExpression::setContext(context); +} + +void QmlBindingIdOptimization::setEnabled(bool e) +{ + if (e) { + addToObject(m_object); + update(); + } else { + removeFromObject(); + } +} + +int QmlBindingIdOptimization::propertyIndex() +{ + return m_propertyIdx; +} + +void QmlBindingIdOptimization::update() +{ + QmlContextPrivate *ctxtPriv = + static_cast(QObjectPrivate::get(context())); + + if (ctxtPriv) { + + if (!m_prev) { + m_next = ctxtPriv->idValues[m_id].bindings; + if (m_next) m_next->m_prev = &m_next; + + m_prev = &ctxtPriv->idValues[m_id].bindings; + ctxtPriv->idValues[m_id].bindings = this; + } + + QObject *o = ctxtPriv->idValues[m_id].data(); + void *a[] = { &o, 0 }; + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); + } +} + +void QmlBindingIdOptimization::reset() +{ + if (m_prev) { + *m_prev = m_next; + if (m_next) m_next->m_prev = m_prev; + m_next = 0; + m_prev = 0; + } + + QObject *o = 0; + void *a[] = { &o, 0 }; + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h new file mode 100644 index 0000000..f50972d --- /dev/null +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLBINDINGOPTIMIZATIONS_P_H +#define QMLBINDINGOPTIMIZATIONS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QmlBindingIdOptimization : public QmlAbstractExpression, + public QmlAbstractBinding +{ +public: + QmlBindingIdOptimization(QObject *object, int propertyIdx, + QmlContext *context, int id); + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + virtual void update(); + + void reset(); + +private: + QmlBindingIdOptimization **m_prev; + QmlBindingIdOptimization *m_next; + + QObject *m_object; + int m_propertyIdx; + int m_id; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLBINDINGOPTIMIZATIONS_P_H + diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 1c535d4..7c0964b 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1394,6 +1394,7 @@ void QmlCompiler::addId(const QString &id, QmlParser::Object *obj) Q_ASSERT(obj->id == id); obj->idIndex = compileState.ids.count(); compileState.ids.insert(id, obj); + compileState.idIndexes.insert(obj->idIndex, obj); } void QmlCompiler::addBindingReference(const BindingReference &ref) @@ -2064,6 +2065,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, const BindingReference &ref = compileState.bindings.value(binding); QmlInstruction store; + + QmlBasicScript bs; + if (ref.isBasicScript) + bs.load(ref.compiledData.constData() + sizeof(quint32)); + if (bs.isSingleIdFetch()) { + int idIndex = bs.singleIdFetchIndex(); + QmlParser::Object *idObj = compileState.idIndexes.value(idIndex); + if (canCoerce(prop->type, idObj)) { + store.type = QmlInstruction::StoreIdOptBinding; + store.assignIdOptBinding.id = idIndex; + store.assignIdOptBinding.property = prop->index; + output->bytecode << store; + return; + } + } + store.type = QmlInstruction::StoreCompiledBinding; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; @@ -2109,6 +2126,7 @@ bool QmlCompiler::completeComponentBuild() binding.compiledData = QByteArray(bs.compileData(), bs.compileDataSize()); type = QmlExpressionPrivate::BasicScriptEngineData; + binding.isBasicScript = true; } else { type = QmlExpressionPrivate::PreTransformedQtScriptData; @@ -2122,6 +2140,7 @@ bool QmlCompiler::completeComponentBuild() QByteArray((const char *)&length, sizeof(quint32)) + QByteArray((const char *)expression.constData(), expression.length() * sizeof(QChar)); + binding.isBasicScript = false; } binding.compiledData.prepend(QByteArray((const char *)&type, sizeof(quint32))); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 094c05a..3d79e32 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -236,6 +236,7 @@ private: QmlParser::Variant expression; QmlParser::Property *property; QmlParser::Value *value; + bool isBasicScript; QByteArray compiledData; BindingContext bindingContext; }; @@ -247,6 +248,7 @@ private: : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {} QHash ids; + QHash idIndexes; int parserStatusCount; int savedObjects; int pushedProperties; diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index d4e383d..c30efca 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -533,11 +533,11 @@ void QmlComponent::completeCreate() QFxPerfTimer bi; #endif for (int ii = 0; ii < d->bindValues.count(); ++ii) { - QmlEnginePrivate::SimpleList bv = + QmlEnginePrivate::SimpleList bv = d->bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) - bv.at(jj)->init(); + bv.at(jj)->setEnabled(true); } QmlEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index a7a3230..4b459c2 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -88,7 +88,7 @@ public: int count; QmlCompiledData *cc; - QList > bindValues; + QList > bindValues; QList > parserStatus; bool completePending; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 18ba906..451dbcc 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -47,6 +47,7 @@ #include #include #include +#include // 6-bits #define MAXIMUM_DEFAULT_OBJECTS 63 @@ -82,6 +83,9 @@ void QmlContextPrivate::destroyed(ContextGuard *guard) if (parent && QObjectPrivate::get(parent)->wasDeleted) return; + while(guard->bindings) + guard->bindings->reset(); + for (int ii = 0; ii < idValueCount; ++ii) { if (&idValues[ii] == guard) { QMetaObject::activate(q, ii + notifyIndex, 0); @@ -276,13 +280,13 @@ QmlContext::~QmlContext() (*iter)->d_func()->parent = 0; } - QmlExpressionPrivate *expression = d->expressions; + QmlAbstractExpression *expression = d->expressions; while (expression) { - QmlExpressionPrivate *nextExpression = expression->nextExpression; + QmlAbstractExpression *nextExpression = expression->m_nextExpression; - expression->ctxt = 0; - expression->prevExpression = 0; - expression->nextExpression = 0; + expression->m_context = 0; + expression->m_prevExpression = 0; + expression->m_nextExpression = 0; expression = nextExpression; } diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 0424a85..b5479d9 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -68,6 +68,8 @@ class QmlExpression; class QmlEngine; class QmlExpression; class QmlExpressionPrivate; +class QmlAbstractExpression; +class QmlBindingIdOptimization; class QmlContextPrivate : public QObjectPrivate { @@ -104,13 +106,15 @@ public: void invalidateEngines(); QSet childContexts; - QmlExpressionPrivate *expressions; + QmlAbstractExpression *expressions; QObjectList contextObjects; struct ContextGuard : public QGuard { + ContextGuard() : priv(0), bindings(0) {} QmlContextPrivate *priv; + QmlBindingIdOptimization *bindings; ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index 8d30bcc..5a51eb7 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE class QmlCompiledData; -class QmlBinding; +class QmlAbstractBinding; class QmlDeclarativeData : public QDeclarativeData { public: @@ -67,7 +67,7 @@ public: virtual void destroyed(QObject *); QmlContext *context; - QmlBinding *bindings; + QmlAbstractBinding *bindings; QmlCompiledData *deferredComponent; // Can't this be found from the context? unsigned int deferredIdx; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 09539bc..bdbf2e7 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -121,16 +121,8 @@ QmlEnginePrivate::~QmlEnginePrivate() clear(parserStatus[ii]); } -void QmlEnginePrivate::clear(SimpleList &bvs) +void QmlEnginePrivate::clear(SimpleList &bvs) { - for (int ii = 0; ii < bvs.count; ++ii) { - QmlBinding *bv = bvs.at(ii); - if(bv) { - QmlBindingPrivate *p = - static_cast(QObjectPrivate::get(bv)); - p->mePtr = 0; - } - } bvs.clear(); } @@ -522,6 +514,15 @@ void QmlDeclarativeData::destroyed(QObject *object) if (context) static_cast(QObjectPrivate::get(context))->contextObjects.removeAll(object); + QmlAbstractBinding *binding = bindings; + while (binding) { + QmlAbstractBinding *next = binding->m_nextBinding; + binding->m_prevBinding = 0; + binding->m_nextBinding = 0; + delete binding; + binding = next; + } + delete this; } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 602321d..d2e3ef4 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -86,6 +86,7 @@ class QmlValueTypeScriptClass; class QScriptEngineDebugger; class QNetworkReply; class QNetworkAccessManager; +class QmlAbstractBinding; class QmlEnginePrivate : public QObjectPrivate { @@ -160,10 +161,10 @@ public: } }; - static void clear(SimpleList &); + static void clear(SimpleList &); static void clear(SimpleList &); - QList > bindValues; + QList > bindValues; QList > parserStatus; QmlComponent *rootComponent; diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index c26f3b7..0e78cad 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -97,7 +97,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) rv.type = QmlObjectProperty::Unknown; rv.name = prop.name(); - QmlBinding *binding = QmlMetaProperty(obj, rv.name).binding(); + QmlAbstractBinding *binding = QmlMetaProperty(obj, rv.name).binding(); if (binding) rv.binding = binding->expression(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 6e9a7a1..f8e78d7 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -51,33 +51,23 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE QmlExpressionPrivate::QmlExpressionPrivate() -: nextExpression(0), prevExpression(0), ctxt(0), expressionFunctionValid(false), expressionRewritten(false), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0) +: expressionFunctionValid(false), expressionRewritten(false), me(0), + trackChange(true), line(-1), guardList(0), guardListLength(0) { } void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, QObject *me) { - Q_Q(QmlExpression); - expression = expr; - this->ctxt = ctxt; - if (ctxt) { - QmlContextPrivate *cp = ctxt->d_func(); - nextExpression = cp->expressions; - if (nextExpression) nextExpression->prevExpression = &nextExpression; - prevExpression = &cp->expressions; - cp->expressions = this; - } + QmlAbstractExpression::setContext(ctxt); this->me = me; } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me) { - Q_Q(QmlExpression); - quint32 *data = (quint32 *)expr; Q_ASSERT(*data == BasicScriptEngineData || *data == PreTransformedQtScriptData); @@ -88,14 +78,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, expressionRewritten = true; } - this->ctxt = ctxt; - if (ctxt) { - QmlContextPrivate *cp = ctxt->d_func(); - nextExpression = cp->expressions; - if (nextExpression) nextExpression->prevExpression = &nextExpression; - prevExpression = &cp->expressions; - cp->expressions = this; - } + QmlAbstractExpression::setContext(ctxt); this->me = me; } @@ -159,12 +142,6 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression, */ QmlExpression::~QmlExpression() { - Q_D(QmlExpression); - if (d->prevExpression) { - *(d->prevExpression) = d->nextExpression; - if (d->nextExpression) - d->nextExpression->prevExpression = d->prevExpression; - } } /*! @@ -174,7 +151,7 @@ QmlExpression::~QmlExpression() QmlEngine *QmlExpression::engine() const { Q_D(const QmlExpression); - return d->ctxt?d->ctxt->engine():0; + return d->context()?d->context()->engine():0; } /*! @@ -184,7 +161,7 @@ QmlEngine *QmlExpression::engine() const QmlContext *QmlExpression::context() const { Q_D(const QmlExpression); - return d->ctxt; + return d->context(); } /*! @@ -230,9 +207,7 @@ QVariant QmlExpressionPrivate::evalSSE() QFxPerfTimer perfsse; #endif - QmlContextPrivate *ctxtPriv = ctxt->d_func(); - - QVariant rv = sse.run(ctxt, me); + QVariant rv = sse.run(context(), me); return rv; } @@ -243,8 +218,8 @@ QVariant QmlExpressionPrivate::evalQtScript() QFxPerfTimer perfqt; #endif - QmlContextPrivate *ctxtPriv = ctxt->d_func(); - QmlEngine *engine = ctxt->engine(); + QmlContextPrivate *ctxtPriv = context()->d_func(); + QmlEngine *engine = context()->engine(); if (me) ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me); @@ -347,7 +322,7 @@ QVariant QmlExpression::value() Q_D(QmlExpression); QVariant rv; - if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty())) + if (!d->context() || (!d->sse.isValid() && d->expression.isEmpty())) return rv; #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -574,5 +549,52 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorm_prevExpression = m_prevExpression; + } +} + +QmlContext *QmlAbstractExpression::context() const +{ + return m_context; +} + +void QmlAbstractExpression::setContext(QmlContext *context) +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + m_prevExpression = 0; + m_nextExpression = 0; + } + + m_context = context; + + if (m_context) { + QmlContextPrivate *cp = + static_cast(QObjectPrivate::get(m_context)); + m_nextExpression = cp->expressions; + if (m_nextExpression) + m_nextExpression->m_prevExpression = &m_nextExpression; + m_prevExpression = &cp->expressions; + cp->expressions = this; + } +} + +bool QmlAbstractExpression::isValid() const +{ + return m_context != 0; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index bf95c0e0..997bf8d 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -61,19 +61,33 @@ QT_BEGIN_NAMESPACE +class QmlAbstractExpression +{ +public: + QmlAbstractExpression(); + virtual ~QmlAbstractExpression(); + + bool isValid() const; + + QmlContext *context() const; + void setContext(QmlContext *); + +private: + friend class QmlContext; + QmlContext *m_context; + QmlAbstractExpression **m_prevExpression; + QmlAbstractExpression *m_nextExpression; +}; + class QmlExpression; class QString; -class QmlExpressionPrivate : public QObjectPrivate +class QmlExpressionPrivate : public QObjectPrivate, public QmlAbstractExpression { Q_DECLARE_PUBLIC(QmlExpression) public: QmlExpressionPrivate(); ~QmlExpressionPrivate(); - // Forms the QmlContext "expressions" linked list - QmlExpressionPrivate *nextExpression; - QmlExpressionPrivate **prevExpression; - enum CompiledDataType { BasicScriptEngineData = 1, PreTransformedQtScriptData = 2 @@ -82,7 +96,6 @@ public: void init(QmlContext *, const QString &, QObject *); void init(QmlContext *, void *, QmlRefCount *, QObject *); - QmlContext *ctxt; QString expression; bool expressionFunctionValid:1; bool expressionRewritten:1; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index e6b8de6..16bc8cf 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -125,6 +125,7 @@ public: AssignCustomType, /* assignCustomType */ StoreCompiledBinding, /* assignBinding */ + StoreIdOptBinding, /* assignIdOptBinding */ StoreValueSource, /* assignValueSource */ BeginObject, /* begin */ @@ -189,6 +190,10 @@ public: } assignBinding; struct { int property; + int id; + } assignIdOptBinding; + struct { + int property; } fetch; struct { int property; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 64dd9cd..d986077 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -51,6 +51,7 @@ #include #include #include +#include Q_DECLARE_METATYPE(QList); @@ -509,20 +510,21 @@ QMetaProperty QmlMetaProperty::property() const Returns the binding associated with this property, or 0 if no binding exists. */ -QmlBinding *QmlMetaProperty::binding() const +QmlAbstractBinding *QmlMetaProperty::binding() const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - const QObjectList &children = object()->children(); - for (QObjectList::ConstIterator iter = children.begin(); - iter != children.end(); ++iter) { - QObject *child = *iter; - if (child->metaObject() == &QmlBinding::staticMetaObject) { - QmlBinding *v = static_cast(child); - if (v->property() == *this && v->enabled()) - return v; - } + QmlDeclarativeData *data = QmlDeclarativeData::get(d->object); + if (!data) + return 0; + + QmlAbstractBinding *binding = data->bindings; + while (binding) { + // ### This wont work for value types + if (binding->propertyIndex() == d->coreIdx) + return binding; + binding = binding->m_nextBinding; } return 0; } @@ -534,41 +536,32 @@ QmlBinding *QmlMetaProperty::binding() const \a binding will be enabled, and the returned binding (if any) will be disabled. */ -QmlBinding *QmlMetaProperty::setBinding(QmlBinding *binding) const +QmlAbstractBinding * +QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - const QObjectList &children = object()->children(); - for (QObjectList::ConstIterator iter = children.begin(); - iter != children.end(); ++iter) { - QObject *child = *iter; - if (child->metaObject() == &QmlBinding::staticMetaObject) { - QmlBinding *v = static_cast(child); - if (v->property() == *this && v->enabled()) { - - v->setEnabled(false); - - if (binding) { - binding->setParent(object()); - binding->setTarget(*this); - binding->setEnabled(true); - binding->forceUpdate(); - } + QmlDeclarativeData *data = QmlDeclarativeData::get(d->object, true); - return v; + QmlAbstractBinding *binding = data->bindings; + while (binding) { + // ### This wont work for value types + if (binding->propertyIndex() == d->coreIdx) { + binding->setEnabled(false); - } + if (newBinding) + newBinding->setEnabled(true); + + return binding; // ### QmlAbstractBinding; } - } - if (binding) { - binding->setParent(object()); - binding->setTarget(*this); - binding->setEnabled(true); - binding->forceUpdate(); + binding = binding->m_nextBinding; } + if (newBinding) + newBinding->setEnabled(true); + return 0; } diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 434ff55..7b9ff47 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QObject; -class QmlBinding; +class QmlAbstractBinding; class QStringList; class QVariant; struct QMetaObject; @@ -122,8 +122,8 @@ public: QMetaProperty property() const; - QmlBinding *binding() const; - QmlBinding *setBinding(QmlBinding *) const; + QmlAbstractBinding *binding() const; + QmlAbstractBinding *setBinding(QmlAbstractBinding *) const; static QmlMetaProperty createProperty(QObject *, const QString &); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index ffe8591..dccf5c4 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -65,6 +65,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -138,7 +139,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData const QList &floatData = comp->floatData; - QmlEnginePrivate::SimpleList bindValues; + QmlEnginePrivate::SimpleList bindValues; QmlEnginePrivate::SimpleList parserStatus; QStack qliststack; @@ -154,7 +155,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::Init: { if (instr.init.bindingsSize) - bindValues = QmlEnginePrivate::SimpleList(instr.init.bindingsSize); + bindValues = QmlEnginePrivate::SimpleList(instr.init.bindingsSize); if (instr.init.parserStatusSize) parserStatus = QmlEnginePrivate::SimpleList(instr.init.parserStatusSize); @@ -543,12 +544,24 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlBindingPrivate *p = static_cast(QObjectPrivate::get(bind)); p->mePtr = &bindValues.values[bindValues.count - 1]; - QFx_setParent_noEvent(bind, target); + bind->addToObject(target); bind->setTarget(mp); } break; + case QmlInstruction::StoreIdOptBinding: + { + QObject *target = stack.top(); + + QmlBindingIdOptimization *bind = + new QmlBindingIdOptimization(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); + bindValues.append(bind); + // ### Need a mePtr + bind->addToObject(target); + } + break; + case QmlInstruction::StoreValueSource: { QmlPropertyValueSource *vs = diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index 1cd4a79..482405c 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -334,9 +334,10 @@ QmlSetProperties::ActionList QmlSetProperties::actions() if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->value(); } else { - a.toBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + QmlBinding *newBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + newBinding->setTarget(prop); + a.toBinding = newBinding; a.deletableToBinding = true; - a.toBinding->setTarget(prop); } list << a; diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 9eb7aee..46659c6 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -70,8 +70,8 @@ public: QVariant fromValue; QVariant toValue; - QmlBinding *fromBinding; - QmlBinding *toBinding; + QmlAbstractBinding *fromBinding; + QmlAbstractBinding *toBinding; ActionEvent *event; //strictly for matching diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index b601b57..63fc6da 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -83,7 +83,7 @@ public: QmlMetaProperty property; QVariant value; - QmlBinding *binding; + QmlAbstractBinding *binding; QObject *specifiedObject; QString specifiedProperty; ActionEvent *event; diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index f04a821..3e2e05f 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -94,7 +94,6 @@ void QmlTransitionManagerPrivate::applyBindings() foreach(const Action &action, bindingsList) { if (action.toBinding) { action.property.setBinding(action.toBinding); - action.toBinding->forceUpdate(); } else if (action.event) { if (action.reverseEvent) action.event->reverse(); @@ -146,7 +145,6 @@ void QmlTransitionManager::transition(const QList &list, const Action &action = applyList.at(ii); if (action.toBinding) { action.property.setBinding(action.toBinding); - action.toBinding->forceUpdate(); } else if (!action.event) { action.property.write(action.toValue); } else if (action.event->isReversable()) { -- cgit v0.12 From e3bb214199381bedf058fa797b514abc95142856 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 10 Aug 2009 10:31:37 +0200 Subject: CRLF => LF. --- src/declarative/fx/qfxborderimage.cpp | 820 +++++++++++++++++----------------- src/declarative/fx/qfxborderimage.h | 202 ++++----- src/declarative/fx/qfxborderimage_p.h | 188 ++++---- 3 files changed, 605 insertions(+), 605 deletions(-) diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 7911437..adb70a3 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -1,410 +1,410 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfxborderimage.h" -#include "qfxborderimage_p.h" -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,BorderImage,QFxBorderImage) - -/*! - \qmlclass BorderImage QFxBorderImage - \brief The BorderImage element allows you use an image as a border. - \inherits Item - - Example: - \qml - BorderImage { border.left: 20; border.right: 10 - border.top: 14; border.bottom: 14 - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - */ - -/*! - \internal - \class QFxBorderImage BorderImage - \brief The QFxBorderImage class provides an image item that you can add to a QFxView. - - \ingroup group_coreitems - - Example: - \qml - BorderImage { source: "pics/star.png" } - \endqml - - A QFxBorderImage object can be instantiated in Qml using the tag \l BorderImage. -*/ - -QFxBorderImage::QFxBorderImage(QFxItem *parent) - : QFxImageBase(*(new QFxBorderImagePrivate), parent) -{ - setFlag(QGraphicsItem::ItemHasNoContents, false); -} - -QFxBorderImage::~QFxBorderImage() -{ - Q_D(QFxBorderImage); - if (d->sciReply) - d->sciReply->deleteLater(); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); -} -/*! - \qmlproperty enum BorderImage::status - - This property holds the status of image loading. It can be one of: - \list - \o Null - no image has been set - \o Ready - the image has been loaded - \o Loading - the image is currently being loaded - \o Error - an error occurred while loading the image - \endlist - - \sa progress -*/ - -/*! - \qmlproperty real BorderImage::progress - - This property holds the progress of image loading, from 0.0 (nothing loaded) - to 1.0 (finished). - - \sa status -*/ - -/*! - \qmlproperty bool BorderImage::smooth - - Set this property if you want the image to be smoothly filtered when scaled or - transformed. Smooth filtering gives better visual quality, but is slower. If - the image is displayed at its natural size, this property has no visual or - performance effect. - - \note Generally scaling artifacts are only visible if the image is stationary on - the screen. A common pattern when animating an image is to disable smooth - filtering at the beginning of the animation and reenable it at the conclusion. -*/ - -/*! - \qmlproperty url BorderImage::source - - BorderImage can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. - - It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies - \list - \i the grid lines describing a \l {BorderImage::border.left}{scale grid}. - \i an image file. - \endlist - - The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: - \code - gridLeft: 10 - gridTop: 10 - gridBottom: 10 - gridRight: 10 - imageFile: picture.png - \endcode - - The URL may be absolute, or relative to the URL of the component. -*/ - -void QFxBorderImage::setSource(const QUrl &url) -{ - Q_D(QFxBorderImage); - //equality is fairly expensive, so we bypass for simple, common case - if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) - return; - - if (d->sciReply) { - d->sciReply->deleteLater(); - d->sciReply = 0; - } - - if (!d->url.isEmpty()) - QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); - - d->url = url; - d->sciurl = QUrl(); - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - - if (url.isEmpty()) { - d->pix = QPixmap(); - d->status = Null; - d->progress = 1.0; - setImplicitWidth(0); - setImplicitHeight(0); - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } else { - d->status = Loading; - if (d->url.path().endsWith(QLatin1String(".sci"))) { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); - file.open(QIODevice::ReadOnly); - setGridScaledImage(QFxGridScaledImage(&file)); - } else -#endif - { - QNetworkRequest req(d->url); - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->sciReply, SIGNAL(finished()), - this, SLOT(sciRequestFinished())); - } - } else { - d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } - } - } - - emit statusChanged(d->status); -} - -/*! - \qmlproperty int BorderImage::border.left - \qmlproperty int BorderImage::border.right - \qmlproperty int BorderImage::border.top - \qmlproperty int BorderImage::border.bottom - - \target ImagexmlpropertiesscaleGrid - - The 4 border lines (2 horizontal and 2 vertical) break an image into 9 sections, as shown below: - - \image declarative-scalegrid.png - - When the image is scaled: - \list - \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled according to BorderImage::horizontalTileMode and BorderImage::verticalTileMode - \i sections 2 and 8 are scaled according to BorderImage::horizontalTileMode - \i sections 4 and 6 are scaled according to BorderImage::verticalTileMode - \endlist - - Each border line (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom line 10 pixels up from the bottom of the image. - - The border lines can also be specified using a - \l {BorderImage::source}{.sci file}. -*/ - -QFxScaleGrid *QFxBorderImage::border() -{ - Q_D(QFxBorderImage); - return d->getScaleGrid(); -} - -/*! - \qmlproperty TileMode BorderImage::horizontalTileMode - \qmlproperty TileMode BorderImage::verticalTileMode - - This property describes how to repeat or stretch the middle parts of the border image. - - \list - \o Stretch - Scale the image to fit to the available area. - \o Repeat - Tile the image until there is no more space. May crop the last image. - \o Round - Like Repeat, but scales the images down to ensure that the last image is not cropped. - \endlist - - \sa examples/declarative/border-image -*/ -QFxBorderImage::TileMode QFxBorderImage::horizontalTileMode() const -{ - Q_D(const QFxBorderImage); - return d->horizontalTileMode; -} - -void QFxBorderImage::setHorizontalTileMode(TileMode t) -{ - Q_D(QFxBorderImage); - d->horizontalTileMode = t; -} - -QFxBorderImage::TileMode QFxBorderImage::verticalTileMode() const -{ - Q_D(const QFxBorderImage); - return d->verticalTileMode; -} - -void QFxBorderImage::setVerticalTileMode(TileMode t) -{ - Q_D(QFxBorderImage); - d->verticalTileMode = t; -} - -void QFxBorderImage::setGridScaledImage(const QFxGridScaledImage& sci) -{ - Q_D(QFxBorderImage); - if (!sci.isValid()) { - d->status = Error; - emit statusChanged(d->status); - } else { - QFxScaleGrid *sg = border(); - sg->setTop(sci.gridTop()); - sg->setBottom(sci.gridBottom()); - sg->setLeft(sci.gridLeft()); - sg->setRight(sci.gridRight()); - d->horizontalTileMode = sci.horizontalTileRule(); - d->verticalTileMode = sci.verticalTileRule(); - - d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } - } -} - -void QFxBorderImage::requestFinished() -{ - Q_D(QFxBorderImage); - if (d->url.path().endsWith(QLatin1String(".sci"))) { - QFxPixmap::find(d->sciurl, &d->pix); - } else { - if (d->reply) { - //###disconnect really needed? - disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - if (d->reply->error() != QNetworkReply::NoError) - d->status = Error; - } - QFxPixmap::find(d->url, &d->pix); - } - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); -} - -void QFxBorderImage::sciRequestFinished() -{ - Q_D(QFxBorderImage); - if (d->sciReply->error() != QNetworkReply::NoError) { - d->status = Error; - d->sciReply->deleteLater(); - d->sciReply = 0; - emit statusChanged(d->status); - } else { - QFxGridScaledImage sci(d->sciReply); - d->sciReply->deleteLater(); - d->sciReply = 0; - setGridScaledImage(sci); - } -} - -void QFxBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) -{ - Q_D(QFxBorderImage); - if (d->pix.isNull()) - return; - - bool oldAA = p->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); - if (d->smooth) - p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - - QPixmap pix = d->pix; - - QMargins margins(border()->top(), border()->left(), border()->bottom(), border()->right()); - QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode); - qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); - if (d->smooth) { - p->setRenderHint(QPainter::Antialiasing, oldAA); - p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); - } -} - -QFxBorderImage::QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent) - : QFxImageBase(dd, parent) -{ - setFlag(QGraphicsItem::ItemHasNoContents, false); -} - -QT_END_NAMESPACE +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfxborderimage.h" +#include "qfxborderimage_p.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,BorderImage,QFxBorderImage) + +/*! + \qmlclass BorderImage QFxBorderImage + \brief The BorderImage element allows you use an image as a border. + \inherits Item + + Example: + \qml + BorderImage { border.left: 20; border.right: 10 + border.top: 14; border.bottom: 14 + width: 160; height: 160 + source: "pics/qtlogo.png" + } + \endqml + */ + +/*! + \internal + \class QFxBorderImage BorderImage + \brief The QFxBorderImage class provides an image item that you can add to a QFxView. + + \ingroup group_coreitems + + Example: + \qml + BorderImage { source: "pics/star.png" } + \endqml + + A QFxBorderImage object can be instantiated in Qml using the tag \l BorderImage. +*/ + +QFxBorderImage::QFxBorderImage(QFxItem *parent) + : QFxImageBase(*(new QFxBorderImagePrivate), parent) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); +} + +QFxBorderImage::~QFxBorderImage() +{ + Q_D(QFxBorderImage); + if (d->sciReply) + d->sciReply->deleteLater(); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); +} +/*! + \qmlproperty enum BorderImage::status + + This property holds the status of image loading. It can be one of: + \list + \o Null - no image has been set + \o Ready - the image has been loaded + \o Loading - the image is currently being loaded + \o Error - an error occurred while loading the image + \endlist + + \sa progress +*/ + +/*! + \qmlproperty real BorderImage::progress + + This property holds the progress of image loading, from 0.0 (nothing loaded) + to 1.0 (finished). + + \sa status +*/ + +/*! + \qmlproperty bool BorderImage::smooth + + Set this property if you want the image to be smoothly filtered when scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the image is displayed at its natural size, this property has no visual or + performance effect. + + \note Generally scaling artifacts are only visible if the image is stationary on + the screen. A common pattern when animating an image is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. +*/ + +/*! + \qmlproperty url BorderImage::source + + BorderImage can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. + + It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies + \list + \i the grid lines describing a \l {BorderImage::border.left}{scale grid}. + \i an image file. + \endlist + + The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: + \code + gridLeft: 10 + gridTop: 10 + gridBottom: 10 + gridRight: 10 + imageFile: picture.png + \endcode + + The URL may be absolute, or relative to the URL of the component. +*/ + +void QFxBorderImage::setSource(const QUrl &url) +{ + Q_D(QFxBorderImage); + //equality is fairly expensive, so we bypass for simple, common case + if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) + return; + + if (d->sciReply) { + d->sciReply->deleteLater(); + d->sciReply = 0; + } + + if (!d->url.isEmpty()) + QFxPixmap::cancelGet(d->url, this); + if (!d->sciurl.isEmpty()) + QFxPixmap::cancelGet(d->sciurl, this); + + d->url = url; + d->sciurl = QUrl(); + if (d->progress != 0.0) { + d->progress = 0.0; + emit progressChanged(d->progress); + } + + if (url.isEmpty()) { + d->pix = QPixmap(); + d->status = Null; + d->progress = 1.0; + setImplicitWidth(0); + setImplicitHeight(0); + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } else { + d->status = Loading; + if (d->url.path().endsWith(QLatin1String(".sci"))) { +#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML + if (d->url.scheme() == QLatin1String("file")) { + QFile file(d->url.toLocalFile()); + file.open(QIODevice::ReadOnly); + setGridScaledImage(QFxGridScaledImage(&file)); + } else +#endif + { + QNetworkRequest req(d->url); + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); + QObject::connect(d->sciReply, SIGNAL(finished()), + this, SLOT(sciRequestFinished())); + } + } else { + d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } + } + + emit statusChanged(d->status); +} + +/*! + \qmlproperty int BorderImage::border.left + \qmlproperty int BorderImage::border.right + \qmlproperty int BorderImage::border.top + \qmlproperty int BorderImage::border.bottom + + \target ImagexmlpropertiesscaleGrid + + The 4 border lines (2 horizontal and 2 vertical) break an image into 9 sections, as shown below: + + \image declarative-scalegrid.png + + When the image is scaled: + \list + \i the corners (sections 1, 3, 7, and 9) are not scaled at all + \i the middle (section 5) is scaled according to BorderImage::horizontalTileMode and BorderImage::verticalTileMode + \i sections 2 and 8 are scaled according to BorderImage::horizontalTileMode + \i sections 4 and 6 are scaled according to BorderImage::verticalTileMode + \endlist + + Each border line (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom line 10 pixels up from the bottom of the image. + + The border lines can also be specified using a + \l {BorderImage::source}{.sci file}. +*/ + +QFxScaleGrid *QFxBorderImage::border() +{ + Q_D(QFxBorderImage); + return d->getScaleGrid(); +} + +/*! + \qmlproperty TileMode BorderImage::horizontalTileMode + \qmlproperty TileMode BorderImage::verticalTileMode + + This property describes how to repeat or stretch the middle parts of the border image. + + \list + \o Stretch - Scale the image to fit to the available area. + \o Repeat - Tile the image until there is no more space. May crop the last image. + \o Round - Like Repeat, but scales the images down to ensure that the last image is not cropped. + \endlist + + \sa examples/declarative/border-image +*/ +QFxBorderImage::TileMode QFxBorderImage::horizontalTileMode() const +{ + Q_D(const QFxBorderImage); + return d->horizontalTileMode; +} + +void QFxBorderImage::setHorizontalTileMode(TileMode t) +{ + Q_D(QFxBorderImage); + d->horizontalTileMode = t; +} + +QFxBorderImage::TileMode QFxBorderImage::verticalTileMode() const +{ + Q_D(const QFxBorderImage); + return d->verticalTileMode; +} + +void QFxBorderImage::setVerticalTileMode(TileMode t) +{ + Q_D(QFxBorderImage); + d->verticalTileMode = t; +} + +void QFxBorderImage::setGridScaledImage(const QFxGridScaledImage& sci) +{ + Q_D(QFxBorderImage); + if (!sci.isValid()) { + d->status = Error; + emit statusChanged(d->status); + } else { + QFxScaleGrid *sg = border(); + sg->setTop(sci.gridTop()); + sg->setBottom(sci.gridBottom()); + sg->setLeft(sci.gridLeft()); + sg->setRight(sci.gridRight()); + d->horizontalTileMode = sci.horizontalTileRule(); + d->verticalTileMode = sci.verticalTileRule(); + + d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); + d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); + if (d->reply) { + connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + //### should be unified with requestFinished + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); + } + } +} + +void QFxBorderImage::requestFinished() +{ + Q_D(QFxBorderImage); + if (d->url.path().endsWith(QLatin1String(".sci"))) { + QFxPixmap::find(d->sciurl, &d->pix); + } else { + if (d->reply) { + //###disconnect really needed? + disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + if (d->reply->error() != QNetworkReply::NoError) + d->status = Error; + } + QFxPixmap::find(d->url, &d->pix); + } + setImplicitWidth(d->pix.width()); + setImplicitHeight(d->pix.height()); + + if (d->status == Loading) + d->status = Ready; + d->progress = 1.0; + emit statusChanged(d->status); + emit sourceChanged(d->url); + emit progressChanged(1.0); + update(); +} + +void QFxBorderImage::sciRequestFinished() +{ + Q_D(QFxBorderImage); + if (d->sciReply->error() != QNetworkReply::NoError) { + d->status = Error; + d->sciReply->deleteLater(); + d->sciReply = 0; + emit statusChanged(d->status); + } else { + QFxGridScaledImage sci(d->sciReply); + d->sciReply->deleteLater(); + d->sciReply = 0; + setGridScaledImage(sci); + } +} + +void QFxBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) +{ + Q_D(QFxBorderImage); + if (d->pix.isNull()) + return; + + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + + QPixmap pix = d->pix; + + QMargins margins(border()->top(), border()->left(), border()->bottom(), border()->right()); + QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode); + qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); + if (d->smooth) { + p->setRenderHint(QPainter::Antialiasing, oldAA); + p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); + } +} + +QFxBorderImage::QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent) + : QFxImageBase(dd, parent) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); +} + +QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxborderimage.h b/src/declarative/fx/qfxborderimage.h index 26ba9cf..b0ec3bc 100644 --- a/src/declarative/fx/qfxborderimage.h +++ b/src/declarative/fx/qfxborderimage.h @@ -1,101 +1,101 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFXBORDERIMAGE_H -#define QFXBORDERIMAGE_H - -#include -#include "qfximagebase.h" - -QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QFxScaleGrid; -class QFxGridScaledImage; -class QFxBorderImagePrivate; -class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase -{ - Q_OBJECT - Q_ENUMS(TileMode) - - Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) - Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode) - Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode) - -public: - QFxBorderImage(QFxItem *parent=0); - ~QFxBorderImage(); - - QFxScaleGrid *border(); - - enum TileMode { Stretch = Qt::Stretch, Repeat = Qt::Repeat, Round = Qt::Round }; - - TileMode horizontalTileMode() const; - void setHorizontalTileMode(TileMode); - - TileMode verticalTileMode() const; - void setVerticalTileMode(TileMode); - - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - void setSource(const QUrl &url); - -protected: - QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); - -private: - void setGridScaledImage(const QFxGridScaledImage& sci); - -private Q_SLOTS: - void requestFinished(); - void sciRequestFinished(); - -private: - Q_DISABLE_COPY(QFxBorderImage) - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxBorderImage) -}; - -QT_END_NAMESPACE -QML_DECLARE_TYPE(QFxBorderImage) -QT_END_HEADER - -#endif // QFXBORDERIMAGE_H +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXBORDERIMAGE_H +#define QFXBORDERIMAGE_H + +#include +#include "qfximagebase.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QFxScaleGrid; +class QFxGridScaledImage; +class QFxBorderImagePrivate; +class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase +{ + Q_OBJECT + Q_ENUMS(TileMode) + + Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) + Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode) + Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode) + +public: + QFxBorderImage(QFxItem *parent=0); + ~QFxBorderImage(); + + QFxScaleGrid *border(); + + enum TileMode { Stretch = Qt::Stretch, Repeat = Qt::Repeat, Round = Qt::Round }; + + TileMode horizontalTileMode() const; + void setHorizontalTileMode(TileMode); + + TileMode verticalTileMode() const; + void setVerticalTileMode(TileMode); + + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void setSource(const QUrl &url); + +protected: + QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); + +private: + void setGridScaledImage(const QFxGridScaledImage& sci); + +private Q_SLOTS: + void requestFinished(); + void sciRequestFinished(); + +private: + Q_DISABLE_COPY(QFxBorderImage) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxBorderImage) +}; + +QT_END_NAMESPACE +QML_DECLARE_TYPE(QFxBorderImage) +QT_END_HEADER + +#endif // QFXBORDERIMAGE_H diff --git a/src/declarative/fx/qfxborderimage_p.h b/src/declarative/fx/qfxborderimage_p.h index 50f3311..104f0f3 100644 --- a/src/declarative/fx/qfxborderimage_p.h +++ b/src/declarative/fx/qfxborderimage_p.h @@ -1,94 +1,94 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFXBORDERIMAGE_P_H -#define QFXBORDERIMAGE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qfximagebase_p.h" -#include "qfxscalegrid_p.h" - -QT_BEGIN_NAMESPACE - -class QNetworkReply; -class QFxBorderImagePrivate : public QFxImageBasePrivate -{ - Q_DECLARE_PUBLIC(QFxBorderImage) - -public: - QFxBorderImagePrivate() - : border(0), sciReply(0), - horizontalTileMode(QFxBorderImage::Stretch), - verticalTileMode(QFxBorderImage::Stretch) - { - } - - ~QFxBorderImagePrivate() - { - } - - QFxScaleGrid *getScaleGrid() - { - if (!border) - border = new QFxScaleGrid; - return border; - } - - QFxScaleGrid *border; - QUrl sciurl; - QNetworkReply *sciReply; - QFxBorderImage::TileMode horizontalTileMode; - QFxBorderImage::TileMode verticalTileMode; -}; - -QT_END_NAMESPACE - -#endif // QFXBORDERIMAGE_P_H +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXBORDERIMAGE_P_H +#define QFXBORDERIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qfximagebase_p.h" +#include "qfxscalegrid_p.h" + +QT_BEGIN_NAMESPACE + +class QNetworkReply; +class QFxBorderImagePrivate : public QFxImageBasePrivate +{ + Q_DECLARE_PUBLIC(QFxBorderImage) + +public: + QFxBorderImagePrivate() + : border(0), sciReply(0), + horizontalTileMode(QFxBorderImage::Stretch), + verticalTileMode(QFxBorderImage::Stretch) + { + } + + ~QFxBorderImagePrivate() + { + } + + QFxScaleGrid *getScaleGrid() + { + if (!border) + border = new QFxScaleGrid; + return border; + } + + QFxScaleGrid *border; + QUrl sciurl; + QNetworkReply *sciReply; + QFxBorderImage::TileMode horizontalTileMode; + QFxBorderImage::TileMode verticalTileMode; +}; + +QT_END_NAMESPACE + +#endif // QFXBORDERIMAGE_P_H -- cgit v0.12 From 2b9be8a7e00405626664dc9d21cd59e236b899a8 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 11 Aug 2009 09:01:14 +1000 Subject: Clearer name for two PreserveAspect modes. --- doc/src/images/declarative-image_fillMode.gif | Bin 42648 -> 79561 bytes examples/declarative/fillmode/fillmode.qml | 8 ++++---- src/declarative/fx/qfximage.cpp | 9 +++++---- src/declarative/fx/qfximage.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/src/images/declarative-image_fillMode.gif b/doc/src/images/declarative-image_fillMode.gif index c81b4d7..eb0a9af 100644 Binary files a/doc/src/images/declarative-image_fillMode.gif and b/doc/src/images/declarative-image_fillMode.gif differ diff --git a/examples/declarative/fillmode/fillmode.qml b/examples/declarative/fillmode/fillmode.qml index d5d6bb5..f2a87c8 100644 --- a/examples/declarative/fillmode/fillmode.qml +++ b/examples/declarative/fillmode/fillmode.qml @@ -10,11 +10,11 @@ Image { SetPropertyAction { value: "Stretch" } SetPropertyAction { target: Label; property: "text"; value: "Stretch" } PauseAnimation { duration: 1000 } - SetPropertyAction { value: "PreserveAspect" } - SetPropertyAction { target: Label; property: "text"; value: "PreserveAspect" } + SetPropertyAction { value: "PreserveAspectFit" } + SetPropertyAction { target: Label; property: "text"; value: "PreserveAspectFit" } PauseAnimation { duration: 1000 } - SetPropertyAction { value: "PreserveAspectFill" } - SetPropertyAction { target: Label; property: "text"; value: "PreserveAspectFill" } + SetPropertyAction { value: "PreserveAspectCrop" } + SetPropertyAction { target: Label; property: "text"; value: "PreserveAspectCrop" } PauseAnimation { duration: 1000 } SetPropertyAction { value: "Tile" } SetPropertyAction { target: Label; property: "text"; value: "Tile" } diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 985ddec..ec3fdab 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -176,14 +176,15 @@ void QFxImage::setPixmap(const QPixmap &pix) \list \o Stretch - the image is scaled to fit - \o PreserveAspect - the image is scaled uniformly to fit - \o PreserveAspectFill - the image is scaled uniformly to fill + \o PreserveAspectFit - the image is scaled uniformly to fit without cropping + \o PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary \o Tile - the image is duplicated horizontally and vertically \o TileVertically - the image is stretched horizontally and tiled vertically \o TileHorizontally - the image is stretched vertically and tiled horizontally \endlist \image declarative-image_fillMode.gif + \sa examples/declarative/fillmode \sa examples/declarative/aspectratio */ QFxImage::FillMode QFxImage::fillMode() const @@ -302,7 +303,7 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) QTransform scale; - if (d->fillMode == PreserveAspect) { + if (d->fillMode == PreserveAspectFit) { if (widthScale < heightScale) { heightScale = widthScale; scale.translate(0, (height() - heightScale * pix.height()) / 2); @@ -310,7 +311,7 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) widthScale = heightScale; scale.translate((width() - widthScale * pix.width()) / 2, 0); } - } else if (d->fillMode == PreserveAspectFill) { + } else if (d->fillMode == PreserveAspectCrop) { if (widthScale < heightScale) { widthScale = heightScale; scale.translate((width() - widthScale * pix.width()) / 2, 0); diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index 91b10ef..c8e21ea 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -63,7 +63,7 @@ public: QFxImage(QFxItem *parent=0); ~QFxImage(); - enum FillMode { Stretch, PreserveAspect, PreserveAspectFill, Tile, TileVertically, TileHorizontally }; + enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally }; FillMode fillMode() const; void setFillMode(FillMode); -- cgit v0.12 From a57bcdde329ef4c9a71aa6ba714f5e30ffd5dc6d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 11 Aug 2009 13:59:56 +1000 Subject: Object property binding optimization Add a binding optimization that hits anchors.fill: parent --- src/declarative/qml/qmlbasicscript.cpp | 17 +++++ src/declarative/qml/qmlbasicscript_p.h | 2 + src/declarative/qml/qmlbindingoptimizations.cpp | 92 ++++++++++++++++++++++--- src/declarative/qml/qmlbindingoptimizations_p.h | 35 ++++++++-- src/declarative/qml/qmlcompiler.cpp | 40 ++++++++++- src/declarative/qml/qmlcompiler_p.h | 1 + src/declarative/qml/qmlcontext_p.h | 4 +- src/declarative/qml/qmlinstruction.cpp | 2 +- src/declarative/qml/qmlinstruction_p.h | 11 ++- src/declarative/qml/qmlvme.cpp | 22 +++++- 10 files changed, 202 insertions(+), 24 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 8993845..f3f9289 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -714,6 +714,23 @@ int QmlBasicScript::singleIdFetchIndex() const return d->instructions()[0].fetch.idx; } +bool QmlBasicScript::isSingleContextProperty() const +{ + if (!isValid()) + return false; + + return d->instructionCount == 1 && + d->instructions()[0].type == ScriptInstruction::FetchContextConstant; +} + +int QmlBasicScript::singleContextPropertyIndex() const +{ + if (!isSingleContextProperty()) + return -1; + + return d->instructions()[0].constant.idx; +} + /*! Return a pointer to the script's compile data, or null if there is no data. */ diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index d096746..5ad7735 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -101,6 +101,8 @@ public: bool isSingleIdFetch() const; int singleIdFetchIndex() const; + bool isSingleContextProperty() const; + int singleContextPropertyIndex() const; private: int flags; QmlBasicScriptPrivate *d; diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index 235c034..a10b1e3 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -44,17 +44,27 @@ QT_BEGIN_NAMESPACE +/* + The QmlBinding_Id optimization handles expressions of the type: -QmlBindingIdOptimization::QmlBindingIdOptimization(QObject *object, - int propertyIdx, - QmlContext *context, - int id) + property: id + + where id is a local context id, and property is an object property. + Coercian between id and property must be checked outside the QmlBinding_Id - + it assumes that they coerce successfully. + + The QmlBinding_Id class avoids any signal slot connections, through the + special "bindings" linked list maintained in the + QmlContextPrivate::ContextGuard instance for each id object. +*/ +QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx, + QmlContext *context, int id) : m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id) { QmlAbstractExpression::setContext(context); } -void QmlBindingIdOptimization::setEnabled(bool e) +void QmlBinding_Id::setEnabled(bool e) { if (e) { addToObject(m_object); @@ -64,12 +74,12 @@ void QmlBindingIdOptimization::setEnabled(bool e) } } -int QmlBindingIdOptimization::propertyIndex() +int QmlBinding_Id::propertyIndex() { return m_propertyIdx; } -void QmlBindingIdOptimization::update() +void QmlBinding_Id::update() { QmlContextPrivate *ctxtPriv = static_cast(QObjectPrivate::get(context())); @@ -91,7 +101,7 @@ void QmlBindingIdOptimization::update() } } -void QmlBindingIdOptimization::reset() +void QmlBinding_Id::reset() { if (m_prev) { *m_prev = m_next; @@ -106,4 +116,70 @@ void QmlBindingIdOptimization::reset() m_propertyIdx, a); } +/* + The QmlBinding_ObjectProperty optimization handles expressions of the type: + + property: objectProperty + + where both property and objectProperty are object properties on the target + object. Coercian between the two must be checked outside the + QmlBinding_ObjectProperty - it assumes that they coerce successfully. + + Due to dot properties, property does not have to be on the same object as + objectProperty. For example: + + anchors.fill: parent +*/ +QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx, + QObject *context, int contextIdx, + int notifyIdx) +: m_enabled(false), m_object(object), m_propertyIdx(propertyIdx), + m_context(context), m_contextIdx(contextIdx), m_notifyIdx(notifyIdx) +{ +} + +void QmlBinding_ObjProperty::setEnabled(bool e) +{ + m_enabled = e; + if (e) { + addToObject(m_object); + update(); + } else { + removeFromObject(); + } +} + +int QmlBinding_ObjProperty::propertyIndex() +{ + return m_propertyIdx; +} + +void QmlBinding_ObjProperty::update() +{ + if (!m_enabled) + return; + + QObject *value = 0; + void *a[] = { &value, 0 }; + + // Read + QMetaObject::metacall(m_context, QMetaObject::ReadProperty, + m_contextIdx, a); + + // Write + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); + + // Connect notify if needed. Only need to connect once, so we set + // m_notifyIdx back to -1 afterwards + static int slotIdx = -1; + if (m_notifyIdx != -1) { + if (slotIdx == -1) + slotIdx = QmlBinding_ObjProperty::staticMetaObject.indexOfMethod("update()"); + + QMetaObject::connect(m_context, m_notifyIdx, this, slotIdx); + m_notifyIdx = -1; + } +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index f50972d..2d2ffec 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -60,11 +60,11 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QmlBindingIdOptimization : public QmlAbstractExpression, - public QmlAbstractBinding +class QmlBinding_Id : public QmlAbstractExpression, + public QmlAbstractBinding { public: - QmlBindingIdOptimization(QObject *object, int propertyIdx, + QmlBinding_Id(QObject *object, int propertyIdx, QmlContext *context, int id); // Inherited from QmlAbstractBinding @@ -75,14 +75,39 @@ public: void reset(); private: - QmlBindingIdOptimization **m_prev; - QmlBindingIdOptimization *m_next; + QmlBinding_Id **m_prev; + QmlBinding_Id *m_next; QObject *m_object; int m_propertyIdx; int m_id; }; +class QmlBinding_ObjProperty : public QObject, + public QmlAbstractExpression, + public QmlAbstractBinding +{ + Q_OBJECT +public: + QmlBinding_ObjProperty(QObject *object, int propertyIdx, + QObject *context, int contextIdx, int notifyIdx); + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + +private slots: + virtual void update(); + +private: + bool m_enabled; + QObject *m_object; + int m_propertyIdx; + QObject *m_context; + int m_contextIdx; + int m_notifyIdx; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 7c0964b..75ed94b 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2069,6 +2069,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, QmlBasicScript bs; if (ref.isBasicScript) bs.load(ref.compiledData.constData() + sizeof(quint32)); + if (bs.isSingleIdFetch()) { int idIndex = bs.singleIdFetchIndex(); QmlParser::Object *idObj = compileState.idIndexes.value(idIndex); @@ -2079,9 +2080,26 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, output->bytecode << store; return; } + } else if (bs.isSingleContextProperty()) { + int propIndex = bs.singleContextPropertyIndex(); + + QMetaProperty p = + ref.bindingContext.object->metaObject()->property(propIndex); + if ((p.notifySignalIndex() != -1 || p.isConstant()) && + canCoerce(prop->type, p.userType())) { + + store.type = QmlInstruction::StoreObjPropBinding; + store.assignObjPropBinding.property = prop->index; + store.assignObjPropBinding.contextIdx = propIndex; + store.assignObjPropBinding.context = ref.bindingContext.stack; + store.assignObjPropBinding.notifyIdx = p.notifySignalIndex(); + + output->bytecode << store; + return; + } } - store.type = QmlInstruction::StoreCompiledBinding; + store.type = QmlInstruction::StoreBinding; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; @@ -2157,8 +2175,7 @@ bool QmlCompiler::completeComponentBuild() */ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) { - const QMetaObject *toMo = - QmlMetaType::rawMetaObjectForType(to); + const QMetaObject *toMo = QmlMetaType::rawMetaObjectForType(to); const QMetaObject *fromMo = from->metaObject(); while (fromMo) { @@ -2169,6 +2186,23 @@ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) return false; } +/*! + Returns true if from can be assigned to a (QObject) property of type + to. +*/ +bool QmlCompiler::canCoerce(int to, int from) +{ + const QMetaObject *toMo = QmlMetaType::rawMetaObjectForType(to); + const QMetaObject *fromMo = QmlMetaType::rawMetaObjectForType(from); + + while (fromMo) { + if (fromMo == toMo) + return true; + fromMo = fromMo->superClass(); + } + return false; +} + QmlType *QmlCompiler::toQmlType(QmlParser::Object *from) { // ### Optimize diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 3d79e32..4f56169 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -226,6 +226,7 @@ private: static int findSignalByName(const QMetaObject *, const QByteArray &name); static bool canCoerce(int to, QmlParser::Object *from); + static bool canCoerce(int to, int from); static QmlType *toQmlType(QmlParser::Object *from); QStringList deferredProperties(QmlParser::Object *); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index b5479d9..84d990c 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -69,7 +69,7 @@ class QmlEngine; class QmlExpression; class QmlExpressionPrivate; class QmlAbstractExpression; -class QmlBindingIdOptimization; +class QmlBinding_Id; class QmlContextPrivate : public QObjectPrivate { @@ -114,7 +114,7 @@ public: { ContextGuard() : priv(0), bindings(0) {} QmlContextPrivate *priv; - QmlBindingIdOptimization *bindings; + QmlBinding_Id *bindings; ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 889a057..fd912ac 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -140,7 +140,7 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::AssignCustomType: qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex; break; - case QmlInstruction::StoreCompiledBinding: + case QmlInstruction::StoreBinding: qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context; break; case QmlInstruction::StoreValueSource: diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 16bc8cf..7f3498f 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -122,10 +122,11 @@ public: // Unresolved single assignment // AssignSignalObject, /* assignSignalObject */ - AssignCustomType, /* assignCustomType */ + AssignCustomType, /* assignCustomType */ - StoreCompiledBinding, /* assignBinding */ + StoreBinding, /* assignBinding */ StoreIdOptBinding, /* assignIdOptBinding */ + StoreObjPropBinding, /* assignObjPropBinding */ StoreValueSource, /* assignValueSource */ BeginObject, /* begin */ @@ -194,6 +195,12 @@ public: } assignIdOptBinding; struct { int property; + int contextIdx; + short context; + short notifyIdx; + } assignObjPropBinding; + struct { + int property; } fetch; struct { int property; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index dccf5c4..fdfeddc 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -529,7 +529,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData } break; - case QmlInstruction::StoreCompiledBinding: + case QmlInstruction::StoreBinding: { QObject *target = stack.at(stack.count() - 1 - instr.assignBinding.owner); @@ -554,14 +554,30 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData { QObject *target = stack.top(); - QmlBindingIdOptimization *bind = - new QmlBindingIdOptimization(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); + QmlBinding_Id *bind = + new QmlBinding_Id(target, instr.assignIdOptBinding.property, + ctxt, instr.assignIdOptBinding.id); bindValues.append(bind); // ### Need a mePtr bind->addToObject(target); } break; + case QmlInstruction::StoreObjPropBinding: + { + QObject *target = stack.top(); + QObject *context = + stack.at(stack.count() - 1 - instr.assignObjPropBinding.context); + + QmlBinding_ObjProperty *bind = + new QmlBinding_ObjProperty(target, instr.assignObjPropBinding.property, context, instr.assignObjPropBinding.contextIdx, instr.assignObjPropBinding.notifyIdx); + + bindValues.append(bind); + // ### Need a mePtr + bind->addToObject(target); + } + break; + case QmlInstruction::StoreValueSource: { QmlPropertyValueSource *vs = -- cgit v0.12 From 2c8772a2ca824c8b86b823498b444b0370ccdc96 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 11 Aug 2009 14:12:33 +1000 Subject: Cleanup QFxLineEdit API Synchronized properties with a previous discussion and with QFxTextEdit. Note that not all properties are fully implemented yet. This commit also fixes a typo in QFxTextEdit. --- src/declarative/fx/qfxlineedit.cpp | 110 ++++++++++++++++++++++++++++--------- src/declarative/fx/qfxlineedit.h | 54 ++++++++++++------ src/declarative/fx/qfxlineedit_p.h | 11 ++-- src/declarative/fx/qfxtextedit.cpp | 2 +- 4 files changed, 127 insertions(+), 50 deletions(-) diff --git a/src/declarative/fx/qfxlineedit.cpp b/src/declarative/fx/qfxlineedit.cpp index 760344d..f92a6fe 100644 --- a/src/declarative/fx/qfxlineedit.cpp +++ b/src/declarative/fx/qfxlineedit.cpp @@ -140,13 +140,66 @@ void QFxLineEdit::setColor(const QColor &c) d->color = c; } -QFxText::HAlignment QFxLineEdit::hAlign() const + +/*! + \qmlproperty color LineEdit::highlightColor + + The text highlight color, used behind selections. +*/ + +/*! + \property QFxLineEdit::highlightColor + \brief the line edit's default text highlight color +*/ +QColor QFxLineEdit::highlightColor() const +{ + Q_D(const QFxLineEdit); + return d->highlightColor; +} + +void QFxLineEdit::setHighlightColor(const QColor &color) +{ + Q_D(QFxLineEdit); + if (d->highlightColor == color) + return; + + d->highlightColor = color; + //TODO: implement +} + +/*! + \qmlproperty color LineEdit::highlightedTextColor + + The highlighted text color, used in selections. +*/ + +/*! + \property QFxLineEdit::highlightedTextColor + \brief the line edit's default highlighted text color +*/ +QColor QFxLineEdit::highlightedTextColor() const +{ + Q_D(const QFxLineEdit); + return d->highlightedTextColor; +} + +void QFxLineEdit::setHighlightedTextColor(const QColor &color) +{ + Q_D(QFxLineEdit); + if (d->highlightedTextColor == color) + return; + + d->highlightedTextColor = color; + //TODO: implement +} + +QFxLineEdit::HAlignment QFxLineEdit::hAlign() const { Q_D(const QFxLineEdit); return d->hAlign; } -void QFxLineEdit::setHAlign(QFxText::HAlignment align) +void QFxLineEdit::setHAlign(HAlignment align) { Q_D(QFxLineEdit); d->hAlign = align; @@ -177,6 +230,29 @@ void QFxLineEdit::setMaxLength(int ml) } /*! + \qmlproperty LineEdit::cursorVisible + \brief If true the text edit shows a cursor. + + This property is set and unset when the line edit gets focus, but it can also + be set directly (useful, for example, if a KeyProxy might forward keys to it). +*/ +bool QFxLineEdit::isCursorVisible() const +{ + Q_D(const QFxLineEdit); + return d->cursorVisible; +} + +void QFxLineEdit::setCursorVisible(bool on) +{ + Q_D(QFxLineEdit); + if (d->cursorVisible == on) + return; + d->cursorVisible = on; + d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0); + updateAll();//TODO: Only update cursor rect +} + +/*! \qmlproperty LineEdit::cursorPosition \brief The position of the cursor in the LineEdit. */ @@ -380,20 +456,6 @@ void QFxLineEdit::moveCursor() d->cursorItem->setX(d->control->cursorToX() - d->hscroll); } -/* -int QFxLineEdit::scrollDuration() const -{ - Q_D(const QFxLineEdit); - return d->scrollDur; -} - -void QFxLineEdit::setScrollDuration(int s) -{ - Q_D(QFxLineEdit); - d->scrollDur = s; - //Need to update cur anims as well -} -*/ int QFxLineEdit::xToPos(int x) { Q_D(const QFxLineEdit); @@ -403,14 +465,8 @@ int QFxLineEdit::xToPos(int x) void QFxLineEdit::focusChanged(bool hasFocus) { Q_D(QFxLineEdit); - if(d->focused && !hasFocus){ - d->focused = false; - d->control->setCursorBlinkPeriod(0); - updateAll();//Only need the cursor rect - }else{ - d->focused = hasFocus; - updateAll();//Only need the cursor rect - } + d->focused = hasFocus; + setCursorVisible(hasFocus); } void QFxLineEdit::keyPressEvent(QKeyEvent* ev) @@ -422,8 +478,8 @@ void QFxLineEdit::keyPressEvent(QKeyEvent* ev) void QFxLineEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QFxLineEdit); - setFocus(true); - d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + setFocus(true);//###Should we make 'focusOnPress' be optional like TextEdit? + setCursorVisible(true); d->focused = true; d->control->processEvent(event); //event->accept(); @@ -457,7 +513,7 @@ void QFxLineEdit::drawContents(QPainter *p, const QRect &r) p->save(); p->setPen(QPen(d->color)); int flags = QLineControl::DrawText; - if(!isReadOnly() && d->focused && !d->cursorItem) + if(!isReadOnly() && d->cursorVisible && !d->cursorItem) flags |= QLineControl::DrawCursor; if (d->control->hasSelectedText()) flags |= QLineControl::DrawSelections; diff --git a/src/declarative/fx/qfxlineedit.h b/src/declarative/fx/qfxlineedit.h index 846ef52..f78dbfc 100644 --- a/src/declarative/fx/qfxlineedit.h +++ b/src/declarative/fx/qfxlineedit.h @@ -58,29 +58,43 @@ class QValidator; class Q_DECLARATIVE_EXPORT QFxLineEdit : public QFxPaintedItem { Q_OBJECT + Q_ENUMS(HAlignment) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) - Q_PROPERTY(QmlFont *font READ font CONSTANT) Q_PROPERTY(QColor color READ color WRITE setColor) - Q_PROPERTY(QFxText::HAlignment hAlign READ hAlign WRITE setHAlign) + Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor) + Q_PROPERTY(QColor highlightedTextColor READ highlightedTextColor WRITE setHighlightedTextColor) + Q_PROPERTY(QmlFont *font READ font CONSTANT) + Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign) - Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly); - Q_PROPERTY(int maxLength READ maxLength WRITE setMaxLength); - Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged); + Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) + Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible) + Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) + Q_PROPERTY(QmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate) Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) - Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged); + Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged) - Q_PROPERTY(QObject* validator READ validator WRITE setValidator); - Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask); - Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged); - Q_PROPERTY(uint echoMode READ echoMode WRITE setEchoMode); + Q_PROPERTY(int maxLength READ maxLength WRITE setMaxLength) + Q_PROPERTY(QObject* validator READ validator WRITE setValidator) + Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask) + Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged) + Q_PROPERTY(uint echoMode READ echoMode WRITE setEchoMode) - Q_PROPERTY(QmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate); public: QFxLineEdit(QFxItem* parent=0); ~QFxLineEdit(); + enum HAlignment { + AlignLeft = Qt::AlignLeft, + AlignRight = Qt::AlignRight, + AlignHCenter = Qt::AlignHCenter + }; + + //### Should we have this function, x based properties, + //### or copy TextEdit with x instead of QTextCursor? + Q_INVOKABLE int xToPos(int x); + QString text() const; void setText(const QString &); @@ -89,17 +103,20 @@ public: QColor color() const; void setColor(const QColor &c); - //### Should we have this function or x variants of properties? - Q_INVOKABLE int xToPos(int x); + QColor highlightColor() const; + void setHighlightColor(const QColor &c); - QFxText::HAlignment hAlign() const; - void setHAlign(QFxText::HAlignment align); + QColor highlightedTextColor() const; + void setHighlightedTextColor(const QColor &c); + + HAlignment hAlign() const; + void setHAlign(HAlignment align); bool isReadOnly() const; void setReadOnly(bool); - int maxLength() const; - void setMaxLength(int ml); + bool isCursorVisible() const; + void setCursorVisible(bool on); int cursorPosition() const; void setCursorPosition(int cp); @@ -112,6 +129,9 @@ public: QString selectedText() const; + int maxLength() const; + void setMaxLength(int ml); + QObject * validator() const; void setValidator(QObject* v); diff --git a/src/declarative/fx/qfxlineedit_p.h b/src/declarative/fx/qfxlineedit_p.h index a18dea7..a087a32 100644 --- a/src/declarative/fx/qfxlineedit_p.h +++ b/src/declarative/fx/qfxlineedit_p.h @@ -65,9 +65,8 @@ class QFxLineEditPrivate : public QFxPaintedItemPrivate public: QFxLineEditPrivate() : control(new QLineControl(QString())), font(0), color((QRgb)0), style(QFxText::Normal), - styleColor((QRgb)0), - hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), - hscroll(0), oldScroll(0), focused(false) + styleColor((QRgb)0), hAlign(QFxLineEdit::AlignLeft), + hscroll(0), oldScroll(0), focused(false), cursorVisible(false) { } @@ -82,10 +81,11 @@ public: QmlFont *font; QColor color; + QColor highlightColor; + QColor highlightedTextColor; QFxText::TextStyle style; QColor styleColor; - QFxText::HAlignment hAlign; - QFxText::VAlignment vAlign; + QFxLineEdit::HAlignment hAlign; QPointer cursorComponent; QPointer cursorItem; @@ -97,6 +97,7 @@ public: int hscroll; int oldScroll; bool focused; + bool cursorVisible; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index dbaba79..509b3da 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -329,7 +329,7 @@ void QFxTextEdit::setHighlightColor(const QColor &color) QColor QFxTextEdit::highlightedTextColor() const { Q_D(const QFxTextEdit); - return d->highlightColor; + return d->highlightedTextColor; } void QFxTextEdit::setHighlightedTextColor(const QColor &color) -- cgit v0.12 From fed8d73b0752b5f737082c534d39f350ca737a7b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 11 Aug 2009 14:15:30 +1000 Subject: Move the binding's "mePtr" into QmlAbstractBinding Now optimizations get deletion protection too. --- src/declarative/qml/qmlbinding.cpp | 17 +++++++++++------ src/declarative/qml/qmlbinding.h | 2 ++ src/declarative/qml/qmlbinding_p.h | 2 -- src/declarative/qml/qmlbindingoptimizations.cpp | 4 ++++ src/declarative/qml/qmlvme.cpp | 8 +++----- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 7c5b366..45d20f4 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); QmlBindingPrivate::QmlBindingPrivate() -: updating(false), enabled(false), mePtr(0) +: updating(false), enabled(false) { } @@ -75,9 +75,6 @@ QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObje QmlBinding::~QmlBinding() { - Q_D(QmlBinding); - if(d->mePtr) - *(d->mePtr) = 0; } void QmlBinding::setTarget(const QmlMetaProperty &prop) @@ -153,12 +150,13 @@ void QmlBinding::setEnabled(bool e) setTrackChange(e); if (e) { - d->mePtr = 0; addToObject(d->property.object()); update(); } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding::propertyIndex() @@ -180,13 +178,15 @@ QString QmlBinding::expression() const } QmlAbstractBinding::QmlAbstractBinding() -: m_prevBinding(0), m_nextBinding(0) +: m_mePtr(0), m_prevBinding(0), m_nextBinding(0) { } QmlAbstractBinding::~QmlAbstractBinding() { removeFromObject(); + if (m_mePtr) + *m_mePtr = 0; } void QmlAbstractBinding::addToObject(QObject *object) @@ -217,4 +217,9 @@ QString QmlAbstractBinding::expression() const return QLatin1String(""); } +void QmlAbstractBinding::setEnabled(bool e) +{ + if (e) m_mePtr = 0; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index ad25c16..63b8a15 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -73,7 +73,9 @@ public: private: friend class QmlDeclarativeData; friend class QmlMetaProperty; + friend class QmlVME; + QmlAbstractBinding **m_mePtr; QmlAbstractBinding **m_prevBinding; QmlAbstractBinding *m_nextBinding; }; diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index 767e6af..963e2c1 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -69,8 +69,6 @@ public: bool enabled:1; QmlMetaProperty property; - - QmlAbstractBinding **mePtr; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index a10b1e3..e1f4a90 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -72,6 +72,8 @@ void QmlBinding_Id::setEnabled(bool e) } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding_Id::propertyIndex() @@ -147,6 +149,8 @@ void QmlBinding_ObjProperty::setEnabled(bool e) } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding_ObjProperty::propertyIndex() diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index fdfeddc..79b1d89 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -541,9 +541,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); bindValues.append(bind); - QmlBindingPrivate *p = - static_cast(QObjectPrivate::get(bind)); - p->mePtr = &bindValues.values[bindValues.count - 1]; + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); bind->setTarget(mp); @@ -558,7 +556,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData new QmlBinding_Id(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); bindValues.append(bind); - // ### Need a mePtr + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); } break; @@ -573,7 +571,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData new QmlBinding_ObjProperty(target, instr.assignObjPropBinding.property, context, instr.assignObjPropBinding.contextIdx, instr.assignObjPropBinding.notifyIdx); bindValues.append(bind); - // ### Need a mePtr + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); } break; -- cgit v0.12