From d9a73e5b8e344d6bf89dd602c21cbbbd17b7836f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 7 May 2009 09:08:44 +1000 Subject: Doc. --- src/declarative/util/qmllistmodel.cpp | 68 +++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 1cd2f69..8184bda 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -93,8 +93,7 @@ Q_DECLARE_METATYPE(QListModelInterface *); } \endcode - Elements beginning with a capital are items. Elements beginning - with lower-case are the data roles. The above example defines a + Item roles (properties) must begin with a lower-case letter. The above example defines a ListModel containing three items, with the roles "name" and "cost". The defined model can be used in views such as ListView: @@ -102,15 +101,9 @@ Q_DECLARE_METATYPE(QListModelInterface *); Component { id: FruitDelegate Item { - width: 200 - height: 50 - Text { - text: name - } - Text { - text: '$'+cost - anchors.right: parent.right - } + width: 200; height: 50 + Text { text: name } + Text { text: '$'+cost; anchors.right: parent.right } } } @@ -120,6 +113,59 @@ Q_DECLARE_METATYPE(QListModelInterface *); anchors.fill: parent } \endcode + + It is possible for roles to contain list data. In the example below we create a list of fruit attributes: + + \code + ListModel { + id: FruitModel + ListElement { + name: "Apple" + cost: 2.45 + attributes: [ + ListElement { description: "Core" }, + ListElement { description: "Deciduous" } + ] + } + ListElement { + name: "Orange" + cost: 3.25 + attributes: [ + ListElement { description: "Citrus" } + ] + } + ListElement { + name: "Banana" + cost: 1.95 + attributes: [ + ListElement { description: "Tropical" } + ListElement { description: "Seedless" } + ] + } + } + \endcode + + The delegate below will list all the fruit attributes: + \code + Component { + id: FruitDelegate + Item { + width: 200; height: 50 + Text { id: Name; text: name } + Text { text: '$'+cost; anchors.right: parent.right } + HorizontalLayout { + anchors.top: Name.bottom + spacing: 5 + Text { text: "Attributes:" } + Repeater { + dataSource: attributes + Component { Text { text: description } } + } + } + } + } + \endcode + */ struct ModelNode; -- cgit v0.12 From 44972c661c6cad9942cc8c8e42f02085b3bff0d5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 7 May 2009 10:59:29 +1000 Subject: Add progress reporting to Image and use it in the flickr demo. --- demos/declarative/flickr/content/ImageDetails.qml | 8 ++- src/declarative/fx/qfximage.cpp | 69 ++++++++++++++++++++++- src/declarative/fx/qfximage.h | 5 ++ src/declarative/fx/qfximage_p.h | 11 ++-- src/declarative/fx/qfxpixmap.cpp | 8 ++- src/declarative/fx/qfxpixmap.h | 3 +- 6 files changed, 93 insertions(+), 11 deletions(-) diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/content/ImageDetails.qml index 7b16831..45e191a 100644 --- a/demos/declarative/flickr/content/ImageDetails.qml +++ b/demos/declarative/flickr/content/ImageDetails.qml @@ -68,7 +68,8 @@ Flipable { Rect { anchors.fill: parent; color: "black"; opacity: 0.4; pen.color: "white"; pen.width: 2 } - Loading { anchors.centeredIn: parent; visible: BigImage.status } +// Loading { anchors.centeredIn: parent; visible: BigImage.status } + Progress { anchors.centeredIn: parent; width: 200; height: 18; progress: BigImage.progress; visible: BigImage.status } Flickable { id: Flick; width: Container.width - 10; height: Container.height - 10 x: 5; y: 5; clip: true; viewportWidth: (BigImage.width * BigImage.scale) + BigImage.x; @@ -84,6 +85,11 @@ Flipable { MediaButton { id: BackButton2; x: 630; y: 370; text: "Back"; onClicked: { Container.state = '' } } + Text { + text: "Image Unavailable" + visible: BigImage.status == 'Error' + anchors.centeredIn: parent; color: "white"; font.bold: true + } Slider { id: Slider; x: 25; y: 374; imageWidth: Container.photoWidth; imageHeight: Container.photoHeight } } diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 106d551..835a4ff 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -783,6 +783,19 @@ QString QFxImage::propertyInfo() const return d->url.toString(); } +/*! + \qmlproperty enum Image::status + + This property holds the status of image loading. It can be one of: + \list + \o Idle - no image has been set, or the image has been loaded + \o Loading - the images 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); @@ -790,6 +803,21 @@ QFxImage::Status QFxImage::status() const } /*! + \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 string Image::source Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. @@ -844,6 +872,10 @@ void QFxImage::setSource(const QString &url) d->source = url; d->url = qmlContext(this)->resolvedUrl(url); d->sciurl = QUrl(); + if (d->progress != 0.0) { + d->progress = 0.0; + emit progressChanged(d->progress); + } if (url.isEmpty()) { setPixmap(QPixmap()); @@ -866,7 +898,14 @@ void QFxImage::setSource(const QString &url) this, SLOT(sciRequestFinished())); } } else { - QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished())); + d->reply = QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished())); + if (d->reply) { + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + d->progress = 1.0; + emit progressChanged(d->progress); + } } } @@ -879,6 +918,12 @@ void QFxImage::requestFinished() if (d->url.path().endsWith(QLatin1String(".sci"))) { d->_pix = QFxPixmap(d->sciurl); } else { + if (d->reply) { + 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); d->_pix.setOpaque(d->_opaque); setOptions(QFxImage::SimpleItem, true); @@ -886,13 +931,16 @@ void QFxImage::requestFinished() setImplicitWidth(d->_pix.width()); setImplicitHeight(d->_pix.height()); - d->status = Idle; + if (d->status == Loading) + d->status = Idle; + d->progress = 1.0; #if defined(QFX_RENDER_OPENGL) d->_texDirty = true; d->_tex.clear(); #endif emit statusChanged(d->status); emit sourceChanged(d->source); + emit progressChanged(1.0); update(); } @@ -912,6 +960,14 @@ void QFxImage::sciRequestFinished() } } +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) { @@ -921,7 +977,14 @@ void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci) emit statusChanged(d->status); } else { d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished())); + d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished())); + if (d->reply) { + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(requestProgress(qint64,qint64))); + } else { + d->progress = 1.0; + emit progressChanged(d->progress); + } QFxScaleGrid *sg = scaleGrid(); sg->setTop(sci.gridTop()); sg->setBottom(sci.gridBottom()); diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index 37fe5be..dc13a97 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -43,6 +43,7 @@ #define QFXIMAGE_H #include +#include QT_BEGIN_HEADER @@ -58,6 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid) Q_PROPERTY(bool tile READ isTiled WRITE setTiled) @@ -84,6 +86,7 @@ public: enum Status { Idle, Loading, Error }; Status status() const; + qreal progress() const; QString source() const; virtual void setSource(const QString &url); @@ -101,6 +104,7 @@ public: Q_SIGNALS: void sourceChanged(const QString &); void statusChanged(Status); + void progressChanged(qreal progress); protected: QFxImage(QFxImagePrivate &dd, QFxItem *parent); @@ -109,6 +113,7 @@ protected: private Q_SLOTS: void requestFinished(); void sciRequestFinished(); + void requestProgress(qint64,qint64); private: Q_DISABLE_COPY(QFxImage) diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index fbb4c44..43942fe 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -76,7 +76,7 @@ public: #if defined(QFX_RENDER_OPENGL) _texDirty(true), #endif - status(QFxImage::Idle), reply(0) + status(QFxImage::Idle), reply(0), progress(0.0) { } @@ -95,10 +95,10 @@ public: } QFxScaleGrid *_scaleGrid; - bool _tiled; QFxPixmap _pix; - bool _smooth; - bool _opaque; + bool _tiled : 1; + bool _smooth : 1; + bool _opaque : 1; #if defined(QFX_RENDER_OPENGL) void checkDirty(); bool _texDirty; @@ -109,7 +109,8 @@ public: QString source; QUrl url; QUrl sciurl; - QNetworkReply *reply; + QPointer reply; + qreal progress; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp index 0d456c6..3fdd8e5 100644 --- a/src/declarative/fx/qfxpixmap.cpp +++ b/src/declarative/fx/qfxpixmap.cpp @@ -233,8 +233,11 @@ QFxPixmap::operator const QSimpleCanvasConfig::Image &() const 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, the slot may be invoked immediately. + + 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. */ -void QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot) +QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot) { QString key = url.toString(); QFxPixmapCache::Iterator iter = qfxPixmapCache.find(key); @@ -259,11 +262,14 @@ void QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char if ((*iter)->reply) { // still loading QObject::connect((*iter)->reply, SIGNAL(finished()), obj, slot); + return (*iter)->reply; } else { // already loaded QObject dummy; QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot); } + + return 0; } /*! diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h index 9a3ba4e..748991e 100644 --- a/src/declarative/fx/qfxpixmap.h +++ b/src/declarative/fx/qfxpixmap.h @@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QmlEngine; +class QNetworkReply; class QFxPixmapPrivate; class Q_DECLARATIVE_EXPORT QFxPixmap { @@ -65,7 +66,7 @@ public: QFxPixmap &operator=(const QFxPixmap &); - static void get(QmlEngine *, const QUrl& url, QObject*, const char* slot); + static QNetworkReply *get(QmlEngine *, const QUrl& url, QObject*, const char* slot); static void cancelGet(const QUrl& url, QObject* obj, const char* slot); bool isNull() const; -- cgit v0.12 From 1d1acbdf3161bc5d79ddd73704687f1c604c766a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 7 May 2009 13:44:36 +1000 Subject: Viewing the same image twice showed no image the second time. --- demos/declarative/flickr/content/ImageDetails.qml | 1 - demos/declarative/flickr/flickr.qml | 8 ++++++-- src/declarative/fx/qfximage.cpp | 11 +++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/content/ImageDetails.qml index 45e191a..8ed61ec 100644 --- a/demos/declarative/flickr/content/ImageDetails.qml +++ b/demos/declarative/flickr/content/ImageDetails.qml @@ -3,7 +3,6 @@ Flipable { property var frontContainer: ContainerFront property var flickableArea: Flickable - property var fullScreenArea: BigImage property string photoTitle: "" property string photoDescription: "" property int photoWidth diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr.qml index 5caffb9..95c808c 100644 --- a/demos/declarative/flickr/flickr.qml +++ b/demos/declarative/flickr/flickr.qml @@ -35,14 +35,18 @@ Item { Connection { sender: ImageDetails; signal: "closed()" - script: { if (Wrapper.state == 'Details') Wrapper.state = '' } + script: { + if (Wrapper.state == 'Details') { + Wrapper.state = ''; + ImageDetails.photoUrl = ""; + } + } } Script { function photoClicked() { ImageDetails.photoTitle = title; ImageDetails.flickableArea.yPosition = 0; - ImageDetails.fullScreenArea.source = ""; ImageDetails.photoDescription = description; ImageDetails.photoWidth = photoWidth; ImageDetails.photoHeight = photoHeight; diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 835a4ff..657e9a5 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -880,6 +880,17 @@ void QFxImage::setSource(const QString &url) if (url.isEmpty()) { setPixmap(QPixmap()); d->status = Idle; + d->progress = 1.0; + setImplicitWidth(0); + setImplicitHeight(0); +#if defined(QFX_RENDER_OPENGL) + d->_texDirty = true; + d->_tex.clear(); +#endif + emit statusChanged(d->status); + emit sourceChanged(d->source); + emit progressChanged(1.0); + update(); } else { d->status = Loading; if (d->url.path().endsWith(QLatin1String(".sci"))) { -- cgit v0.12 From 572f00d8c2684f6e396d17638ae08bfac57b410e Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 7 May 2009 14:23:51 +1000 Subject: Don't crash --- src/declarative/fx/qfximage.cpp | 26 +++++++++++++------------- src/declarative/fx/qfximage_p.h | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 657e9a5..d66846d 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -125,8 +125,8 @@ QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) QFxImage::~QFxImage() { Q_D(const QFxImage); - if (d->reply) - d->reply->deleteLater(); + if (d->sciReply) + d->sciReply->deleteLater(); } /*! @@ -859,9 +859,9 @@ void QFxImage::setSource(const QString &url) if (url == d->source) return; - if (d->reply) { - d->reply->deleteLater(); - d->reply = 0; + if (d->sciReply) { + d->sciReply->deleteLater(); + d->sciReply = 0; } if (!d->url.isEmpty()) @@ -904,8 +904,8 @@ void QFxImage::setSource(const QString &url) { QNetworkRequest req(d->url); req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - d->reply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->reply, SIGNAL(finished()), + d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); + QObject::connect(d->sciReply, SIGNAL(finished()), this, SLOT(sciRequestFinished())); } } else { @@ -958,15 +958,15 @@ void QFxImage::requestFinished() void QFxImage::sciRequestFinished() { Q_D(QFxImage); - if (d->reply->error() != QNetworkReply::NoError) { + if (d->sciReply->error() != QNetworkReply::NoError) { d->status = Error; - d->reply->deleteLater(); - d->reply = 0; + d->sciReply->deleteLater(); + d->sciReply = 0; emit statusChanged(d->status); } else { - QFxGridScaledImage sci(d->reply); - d->reply->deleteLater(); - d->reply = 0; + QFxGridScaledImage sci(d->sciReply); + d->sciReply->deleteLater(); + d->sciReply = 0; setGridScaledImage(sci); } } diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index 43942fe..8227ce4 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -76,7 +76,7 @@ public: #if defined(QFX_RENDER_OPENGL) _texDirty(true), #endif - status(QFxImage::Idle), reply(0), progress(0.0) + status(QFxImage::Idle), sciReply(0), progress(0.0) { } @@ -109,6 +109,7 @@ public: QString source; QUrl url; QUrl sciurl; + QNetworkReply *sciReply; QPointer reply; qreal progress; }; -- cgit v0.12