70QQuickImageBase::QQuickImageBase(QQuickItem *parent)
71: QQuickImplicitSizeItem(*(
new QQuickImageBasePrivate), parent)
73 setFlag(ItemHasContents);
145QSize QQuickImageBase::sourceSize()
const
147 Q_D(
const QQuickImageBase);
149 int width = d->sourcesize.width();
150 int height = d->sourcesize.height();
151 return QSize(width != -1 ? width : d->currentPix->width(), height != -1 ? height : d->currentPix->height());
277void QQuickImageBase::loadEmptyUrl()
279 Q_D(QQuickImageBase);
280 d->loadedForDevicePixelRatio = 0;
281 d->currentPix->clear(
this);
282 d->pendingPix->clear(
this);
285 setImplicitSize(0, 0);
288 emit statusChanged(d->status);
289 if (sourceSize() != d->oldSourceSize) {
290 d->oldSourceSize = sourceSize();
291 emit sourceSizeChanged();
293 if (autoTransform() != d->oldAutoTransform) {
294 d->oldAutoTransform = autoTransform();
295 emitAutoTransformBaseChanged();
300void QQuickImageBase::loadPixmap(
const QUrl &url, LoadPixmapOptions loadOptions)
302 Q_D(QQuickImageBase);
303 QQuickPixmap::Options options;
305 options |= QQuickPixmap::Asynchronous;
307 options |= QQuickPixmap::Cache;
308 d->pendingPix->clear(
this);
310 const QQmlContext *context = qmlContext(
this);
312 loadUrl = context->resolvedUrl(url);
314 if (loadOptions & HandleDPR) {
315 const qreal targetDevicePixelRatio = d->devicePixelRatioForLoading();
316 d->devicePixelRatio = 1.0;
317 bool updatedDevicePixelRatio =
false;
318 const QUrl resolvedUrl = context ? context->resolvedUrl(d->url) : d->url;
319 const bool scalable = QQuickPixmap::isScalableImageFormat(resolvedUrl);
320 if (d->sourcesize.isValid() || (scalable && d->url.scheme() !=
"image"_L1))
321 updatedDevicePixelRatio = d->updateDevicePixelRatio(targetDevicePixelRatio, scalable);
323 if (!updatedDevicePixelRatio) {
326 resolve2xLocalFile(resolvedUrl, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
332 auto engine = qmlEngine(
this);
334 d->pendingPix->load(engine,
336 d->sourceClipRect.toRect(),
337 (loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(),
339 (loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(),
340 d->currentFrame, d->frameCount,
341 d->devicePixelRatio);
343 if (d->pendingPix->isLoading()) {
345 d->setStatus(Loading);
347 static int thisRequestProgress = -1;
348 static int thisRequestFinished = -1;
349 if (thisRequestProgress == -1) {
350 thisRequestProgress =
351 QQuickImageBase::staticMetaObject.indexOfSlot(
"requestProgress(qint64,qint64)");
352 thisRequestFinished =
353 QQuickImageBase::staticMetaObject.indexOfSlot(
"requestFinished()");
356 d->pendingPix->connectFinished(
this, thisRequestFinished);
357 d->pendingPix->connectDownloadProgress(
this, thisRequestProgress);
358 if (!d->retainWhileLoading)
383void QQuickImageBase::reloadIfTransientImageDropped()
385 Q_D(QQuickImageBase);
386 if (d->status == Loading
387 || !d->currentPix->hasDroppedTransientImage()
388 || d->url.scheme() == QQuickPixmap::itemGrabberScheme)
393 QMetaObject::invokeMethod(
this, [
this] {
394 Q_D(QQuickImageBase);
395 if (d->status == Loading || !d->currentPix->hasDroppedTransientImage())
397 d->currentPix->removeDroppedTransientImageFromCache();
399 }, Qt::QueuedConnection);
402void QQuickImageBase::requestFinished()
404 Q_D(QQuickImageBase);
405 if (d->pendingPix != d->currentPix
406 && d->pendingPix->status() != QQuickPixmap::Null
407 && d->pendingPix->status() != QQuickPixmap::Loading) {
408 std::swap(d->pendingPix, d->currentPix);
409 d->pendingPix->clear(
this);
412 if (d->currentPix->isError()) {
413 qmlWarning(
this) << d->currentPix->error();
420 if (d->url.scheme() == QQuickPixmap::itemGrabberScheme)
421 d->devicePixelRatio = d->currentPix->devicePixelRatio();
427 emit statusChanged(d->status);
429 if (sourceSize() != d->oldSourceSize) {
430 d->oldSourceSize = sourceSize();
431 emit sourceSizeChanged();
433 if (autoTransform() != d->oldAutoTransform) {
434 d->oldAutoTransform = autoTransform();
435 emitAutoTransformBaseChanged();
437 if (d->frameCount != d->currentPix->frameCount()) {
438 d->frameCount = d->currentPix->frameCount();
439 emit frameCountChanged();
441 if (d->colorSpace != d->currentPix->colorSpace()) {
442 d->colorSpace = d->currentPix->colorSpace();
443 emit colorSpaceChanged();
456void QQuickImageBase::itemChange(ItemChange change,
const ItemChangeData &value)
458 Q_D(QQuickImageBase);
460 if (change == ItemDevicePixelRatioHasChanged && value.realValue != d->devicePixelRatio) {
461 const auto oldDpr = d->devicePixelRatio;
467 if (qmlEngine(
this) && isComponentComplete()) {
470 if (d->devicePixelRatio == oldDpr) {
471 const QQmlContext *context = qmlContext(
this);
472 const QUrl resolvedUrl = context ? context->resolvedUrl(d->url) : d->url;
473 d->updateDevicePixelRatio(value.realValue,
474 QQuickPixmap::isScalableImageFormat(resolvedUrl));
477 }
else if (change == ItemSceneChange && d->needsReloadForDevicePixelRatio()) {
485 QQuickItem::itemChange(change, value);
510void QQuickImageBase::resolve2xLocalFile(
const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio)
513 Q_ASSERT(sourceDevicePixelRatio);
516 static const bool disable2xImageLoading = !qEnvironmentVariableIsEmpty(
"QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
517 if (disable2xImageLoading)
520 const QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
523 if (localFile.isEmpty())
527 int atLocation = localFile.lastIndexOf(QLatin1Char(
'@'));
528 if (atLocation > 0 && atLocation + 3 < localFile.size()) {
529 if (localFile[atLocation + 1].isDigit()
530 && localFile[atLocation + 2] == QLatin1Char(
'x')
531 && localFile[atLocation + 3] == QLatin1Char(
'.')) {
532 *sourceDevicePixelRatio = localFile[atLocation + 1].digitValue();
538 QString localFileX = qt_findAtNxFile(localFile, targetDevicePixelRatio, sourceDevicePixelRatio);
539 if (localFileX != localFile)
540 *sourceUrl = QUrl::fromLocalFile(localFileX);
543bool QQuickImageBase::autoTransform()
const
545 Q_D(
const QQuickImageBase);
546 if (d->providerOptions.autoTransform() == QQuickImageProviderOptions::UsePluginDefaultTransform)
547 return d->currentPix->autoTransform() == QQuickImageProviderOptions::ApplyTransform;
548 return d->providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform;
551void QQuickImageBase::setAutoTransform(
bool transform)
553 Q_D(QQuickImageBase);
554 if (d->providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform &&
555 transform == (d->providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform))
557 d->providerOptions.setAutoTransform(transform ? QQuickImageProviderOptions::ApplyTransform : QQuickImageProviderOptions::DoNotApplyTransform);
558 emitAutoTransformBaseChanged();
567void QQuickImageBase::setColorSpace(
const QColorSpace &colorSpace)
569 Q_D(QQuickImageBase);
570 if (d->colorSpace == colorSpace)
572 d->colorSpace = colorSpace;
573 d->providerOptions.setTargetColorSpace(colorSpace);
574 emit colorSpaceChanged();
583void QQuickImageBase::setRetainWhileLoading(
bool retainWhileLoading)
585 Q_D(QQuickImageBase);
586 if (d->retainWhileLoading == retainWhileLoading)
589 d->retainWhileLoading = retainWhileLoading;
590 if (d->retainWhileLoading) {
591 if (d->currentPix == &d->pix1)
592 d->pendingPix = &d->pix2;
594 d->pendingPix = &d->pix1;
596 d->pendingPix->clear();
597 d->pendingPix = d->currentPix;