diff options
Diffstat (limited to 'src/quick/items/qquickimagebase.cpp')
-rw-r--r-- | src/quick/items/qquickimagebase.cpp | 163 |
1 files changed, 96 insertions, 67 deletions
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 78dfecc42a..61d6e90548 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -15,16 +15,7 @@ QT_BEGIN_NAMESPACE -bool isScalableImageFormat(const QUrl &url) -{ - if (url.scheme() == QLatin1String("image")) - return true; - - const QString stringUrl = url.path(QUrl::PrettyDecoded); - return stringUrl.endsWith(QLatin1String("svg")) - || stringUrl.endsWith(QLatin1String("svgz")) - || stringUrl.endsWith(QLatin1String("pdf")); -} +using namespace Qt::Literals::StringLiterals; // This function gives derived classes the chance set the devicePixelRatio // if they're not happy with our implementation of it. @@ -33,7 +24,7 @@ bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio // QQuickImageProvider and SVG and PDF can generate a high resolution image when // sourceSize is set. If sourceSize is not set then the provider default size will // be used, as usual. - const bool setDevicePixelRatio = isScalableImageFormat(url); + const bool setDevicePixelRatio = QQuickPixmap::isScalableImageFormat(url); if (setDevicePixelRatio) devicePixelRatio = targetDevicePixelRatio; @@ -41,6 +32,28 @@ bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio return setDevicePixelRatio; } +void QQuickImageBasePrivate::setStatus(QQuickImageBase::Status value) +{ + Q_Q(QQuickImageBase); + + if (status == value) + return; + + status = value; + emit q->statusChanged(status); +} + +void QQuickImageBasePrivate::setProgress(qreal value) +{ + Q_Q(QQuickImageBase); + + if (qFuzzyCompare(progress, value)) + return; + + progress = value; + emit q->progressChanged(progress); +} + QQuickImageBase::QQuickImageBase(QQuickItem *parent) : QQuickImplicitSizeItem(*(new QQuickImageBasePrivate), parent) { @@ -63,14 +76,12 @@ QQuickImageBase::Status QQuickImageBase::status() const return d->status; } - qreal QQuickImageBase::progress() const { Q_D(const QQuickImageBase); return d->progress; } - bool QQuickImageBase::asynchronous() const { Q_D(const QQuickImageBase); @@ -124,7 +135,7 @@ QSize QQuickImageBase::sourceSize() const int width = d->sourcesize.width(); int height = d->sourcesize.height(); - return QSize(width != -1 ? width : d->pix.width(), height != -1 ? height : d->pix.height()); + return QSize(width != -1 ? width : d->currentPix->width(), height != -1 ? height : d->currentPix->height()); } void QQuickImageBase::resetSourceSize() @@ -145,6 +156,7 @@ void QQuickImageBase::setSourceClipRect(const QRectF &r) return; d->sourceClipRect = r; + d->providerOptions.setSourceClipRect(r); emit sourceClipRectChanged(); if (isComponentComplete()) load(); @@ -176,7 +188,7 @@ void QQuickImageBase::setCache(bool cache) QImage QQuickImageBase::image() const { Q_D(const QQuickImageBase); - return d->pix.image(); + return d->currentPix->image(); } void QQuickImageBase::setMirror(bool mirror) @@ -222,7 +234,7 @@ bool QQuickImageBase::mirrorVertically() const void QQuickImageBase::setCurrentFrame(int frame) { Q_D(QQuickImageBase); - if (frame == d->currentFrame || frame < 0 || (isComponentComplete() && frame >= d->pix.frameCount())) + if (frame == d->currentFrame || frame < 0 || (isComponentComplete() && frame >= d->currentPix->frameCount())) return; d->currentFrame = frame; @@ -252,12 +264,10 @@ int QQuickImageBase::frameCount() const void QQuickImageBase::loadEmptyUrl() { Q_D(QQuickImageBase); - d->pix.clear(this); - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - d->status = Null; + d->currentPix->clear(this); + d->pendingPix->clear(this); + d->setProgress(0); + d->status = Null; // do not emit statusChanged until after setImplicitSize setImplicitSize(0, 0); // also called in QQuickImageBase::pixmapChange, but not QQuickImage/QQuickBorderImage overrides pixmapChange(); // This calls update() in QQuickBorderImage and QQuickImage, not in QQuickImageBase... @@ -281,7 +291,7 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) options |= QQuickPixmap::Asynchronous; if (d->cache) options |= QQuickPixmap::Cache; - d->pix.clear(this); + d->pendingPix->clear(this); QUrl loadUrl = url; const QQmlContext *context = qmlContext(this); if (context) @@ -292,7 +302,7 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) d->devicePixelRatio = 1.0; bool updatedDevicePixelRatio = false; if (d->sourcesize.isValid() - || (isScalableImageFormat(d->url) && d->url.scheme() != QLatin1String("image"))) { + || (QQuickPixmap::isScalableImageFormat(d->url) && d->url.scheme() != "image"_L1)) { updatedDevicePixelRatio = d->updateDevicePixelRatio(targetDevicePixelRatio); } @@ -304,24 +314,20 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) } } - d->pix.load(qmlEngine(this), - loadUrl, - d->sourceClipRect.toRect(), - (loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(), - options, - (loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(), - d->currentFrame, d->frameCount, - d->devicePixelRatio); - - if (d->pix.isLoading()) { - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - if (d->status != Loading) { - d->status = Loading; - emit statusChanged(d->status); - } + d->status = Null; // reset status, no emit + + d->pendingPix->load(qmlEngine(this), + loadUrl, + d->sourceClipRect.toRect(), + (loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(), + options, + (loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(), + d->currentFrame, d->frameCount, + d->devicePixelRatio); + + if (d->pendingPix->isLoading()) { + d->setProgress(0); + d->setStatus(Loading); static int thisRequestProgress = -1; static int thisRequestFinished = -1; @@ -332,9 +338,10 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) QQuickImageBase::staticMetaObject.indexOfSlot("requestFinished()"); } - d->pix.connectFinished(this, thisRequestFinished); - d->pix.connectDownloadProgress(this, thisRequestProgress); - update(); //pixmap may have invalidated texture, updatePaintNode needs to be called before the next repaint + d->pendingPix->connectFinished(this, thisRequestFinished); + d->pendingPix->connectDownloadProgress(this, thisRequestProgress); + if (!d->retainWhileLoading) + update(); //pixmap may have invalidated texture, updatePaintNode needs to be called before the next repaint } else { requestFinished(); } @@ -356,23 +363,23 @@ void QQuickImageBase::requestFinished() { Q_D(QQuickImageBase); - if (d->pix.isError()) { - qmlWarning(this) << d->pix.error(); - d->pix.clear(this); + if (d->pendingPix != d->currentPix) { + std::swap(d->pendingPix, d->currentPix); + d->pendingPix->clear(this); // Clear the old image + } + + if (d->currentPix->isError()) { + qmlWarning(this) << d->currentPix->error(); d->status = Error; - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } + d->setProgress(0); } else { - d->status = Ready; - if (d->progress != 1.0) { - d->progress = 1.0; - emit progressChanged(d->progress); - } + d->status = Ready; // do not emit statusChanged until after setImplicitSize + d->setProgress(1); } + pixmapChange(); emit statusChanged(d->status); + if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); @@ -381,12 +388,12 @@ void QQuickImageBase::requestFinished() d->oldAutoTransform = autoTransform(); emitAutoTransformBaseChanged(); } - if (d->frameCount != d->pix.frameCount()) { - d->frameCount = d->pix.frameCount(); + if (d->frameCount != d->currentPix->frameCount()) { + d->frameCount = d->currentPix->frameCount(); emit frameCountChanged(); } - if (d->colorSpace != d->pix.colorSpace()) { - d->colorSpace = d->pix.colorSpace(); + if (d->colorSpace != d->currentPix->colorSpace()) { + d->colorSpace = d->currentPix->colorSpace(); emit colorSpaceChanged(); } @@ -396,10 +403,8 @@ void QQuickImageBase::requestFinished() void QQuickImageBase::requestProgress(qint64 received, qint64 total) { Q_D(QQuickImageBase); - if (d->status == Loading && total > 0) { - d->progress = qreal(received)/total; - emit progressChanged(d->progress); - } + if (d->status == Loading && total > 0) + d->setProgress(qreal(received) / total); } void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value) @@ -431,7 +436,7 @@ void QQuickImageBase::componentComplete() void QQuickImageBase::pixmapChange() { Q_D(QQuickImageBase); - setImplicitSize(d->pix.width() / d->devicePixelRatio, d->pix.height() / d->devicePixelRatio); + setImplicitSize(d->currentPix->width() / d->devicePixelRatio, d->currentPix->height() / d->devicePixelRatio); } void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio) @@ -471,7 +476,7 @@ bool QQuickImageBase::autoTransform() const { Q_D(const QQuickImageBase); if (d->providerOptions.autoTransform() == QQuickImageProviderOptions::UsePluginDefaultTransform) - return d->pix.autoTransform() == QQuickImageProviderOptions::ApplyTransform; + return d->currentPix->autoTransform() == QQuickImageProviderOptions::ApplyTransform; return d->providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform; } @@ -501,6 +506,30 @@ void QQuickImageBase::setColorSpace(const QColorSpace &colorSpace) emit colorSpaceChanged(); } +bool QQuickImageBase::retainWhileLoading() const +{ + Q_D(const QQuickImageBase); + return d->retainWhileLoading; +} + +void QQuickImageBase::setRetainWhileLoading(bool retainWhileLoading) +{ + Q_D(QQuickImageBase); + if (d->retainWhileLoading == retainWhileLoading) + return; + + d->retainWhileLoading = retainWhileLoading; + if (d->retainWhileLoading) { + if (d->currentPix == &d->pix1) + d->pendingPix = &d->pix2; + else + d->pendingPix = &d->pix1; + } else { + d->pendingPix->clear(); + d->pendingPix = d->currentPix; + } +} + QT_END_NAMESPACE #include "moc_qquickimagebase_p.cpp" |