aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickimagebase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickimagebase.cpp')
-rw-r--r--src/quick/items/qquickimagebase.cpp163
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"