diff --git a/src/widgets/previewjob.h b/src/widgets/previewjob.h --- a/src/widgets/previewjob.h +++ b/src/widgets/previewjob.h @@ -186,6 +186,15 @@ **/ int sequenceIndex() const; + /** + * Request preview to use the device pixel ratio @p. + * The returned thumbnail may not respect the device pixel ratio returned. + * Use QPixmap::devicePixelRatio to check, or paint as neccesary. + * + * @since 5.71 + */ + void setDevicePixelRatio(qreal dpr); + /** * Returns a list of all available preview plugins. The list * contains the basenames of the plugins' .desktop files (no path, @@ -244,6 +253,15 @@ Q_PRIVATE_SLOT(d_func(), void startPreview()) Q_PRIVATE_SLOT(d_func(), void slotThumbData(KIO::Job *, const QByteArray &)) Q_DECLARE_PRIVATE(PreviewJob) + +public: + /** + * Sets a default device Pixel Ratio used for Previews + * Defaults to 1 + * + * @since 5.71 + */ + static void setDefaultDevicePixelRatio(qreal devicePixerRatio); }; #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(4, 7) diff --git a/src/widgets/previewjob.cpp b/src/widgets/previewjob.cpp --- a/src/widgets/previewjob.cpp +++ b/src/widgets/previewjob.cpp @@ -61,6 +61,10 @@ #include "job_p.h" +namespace { + static qreal s_defaultDevicePixelRatio = 1.0; +} + namespace KIO { struct PreviewItem; @@ -150,6 +154,7 @@ QString thumbRoot; // List of encrypted mount points for checking if we should save thumbnail KMountPoint::List encryptedMountsList; + qreal devicePixelRatio = s_defaultDevicePixelRatio; void getOrCreateThumbnail(); bool statResultThumbnail(); @@ -164,6 +169,11 @@ Q_DECLARE_PUBLIC(PreviewJob) }; + +void PreviewJob::setDefaultDevicePixelRatio(qreal devicePixerRatio) { + s_defaultDevicePixelRatio = devicePixerRatio; +} + PreviewJob::PreviewJob(const KFileItemList &items, int width, int height, int iconSize, int iconAlpha, bool scale, bool save, const QStringList *enabledPlugins) @@ -427,6 +437,11 @@ return d_func()->sequenceIndex; } +void KIO::PreviewJob::setDevicePixelRatio(qreal dpr) +{ + d_func()->devicePixelRatio = dpr; +} + void PreviewJob::setIgnoreMaximumSize(bool ignoreSize) { d_func()->ignoreMaximumSize = ignoreSize; @@ -564,6 +579,10 @@ thumb.text(QStringLiteral("Thumb::MTime")).toLongLong() != tOrig.toSecsSinceEpoch()) { return false; } + if (thumb.textKeys().contains(QStringLiteral("Thumb::DevicePixelRatio"))) { + qreal dpr = thumb.text(QStringLiteral("Thumb::DevicePixelRatio")).toDouble(); + thumb.setDevicePixelRatio(dpr); + } QString thumbnailerVersion = currentItem.plugin->property(QStringLiteral("ThumbnailerVersion"), QVariant::String).toString(); @@ -659,6 +678,7 @@ job->addMetaData(QStringLiteral("iconAlpha"), QString().setNum(iconAlpha)); job->addMetaData(QStringLiteral("plugin"), currentItem.plugin->library()); job->addMetaData(QStringLiteral("enabledPlugins"), enabledPlugins.join(QLatin1Char(','))); + job->addMetaData(QStringLiteral("devicePixelRatio"), QString::number(devicePixelRatio)); if (sequenceIndex) { job->addMetaData(QStringLiteral("sequence-index"), QString().setNum(sequenceIndex)); } @@ -669,7 +689,7 @@ shmdt((char *)shmaddr); shmctl(shmid, IPC_RMID, nullptr); } - shmid = shmget(IPC_PRIVATE, cacheWidth * cacheHeight * 4, IPC_CREAT | 0600); + shmid = shmget(IPC_PRIVATE, cacheWidth * cacheHeight * 4 * devicePixelRatio * devicePixelRatio, IPC_CREAT | 0600); if (shmid != -1) { shmaddr = (uchar *)(shmat(shmid, nullptr, SHM_RDONLY)); if (shmaddr == (uchar *) - 1) { @@ -702,9 +722,17 @@ QDataStream str(data); int width, height; quint8 iFormat; + qreal imgDevicePixelRatio = 1; + // TODO KF6: add a version number as first parameter str >> width >> height >> iFormat; + if (iFormat & 0x80) { + // HACK to deduce if imgDevicePixelRatio is present + iFormat &= 0x7f; + str >> imgDevicePixelRatio; + } QImage::Format format = static_cast(iFormat); thumb = QImage(shmaddr, width, height, format).copy(); + thumb.setDevicePixelRatio(imgDevicePixelRatio); } else #endif thumb.loadFromData(data); @@ -719,6 +747,7 @@ thumb.setText(QStringLiteral("Thumb::MTime"), QString::number(tOrig.toSecsSinceEpoch())); thumb.setText(QStringLiteral("Thumb::Size"), number(currentItem.item.size())); thumb.setText(QStringLiteral("Thumb::Mimetype"), currentItem.item.mimetype()); + thumb.setText(QStringLiteral("Thumb::DevicePixelRatio"), QString::number(thumb.devicePixelRatio())); QString thumbnailerVersion = currentItem.plugin->property(QStringLiteral("ThumbnailerVersion"), QVariant::String).toString(); QString signature = QLatin1String("KDE Thumbnail Generator ") + currentItem.plugin->name(); if (!thumbnailerVersion.isEmpty()) { @@ -740,11 +769,12 @@ { Q_Q(PreviewJob); QPixmap pix; - if (thumb.width() > width || thumb.height() > height) { - pix = QPixmap::fromImage(thumb.scaled(QSize(width, height), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + if (thumb.width() > width * devicePixelRatio || thumb.height() > height * devicePixelRatio) { + pix = QPixmap::fromImage(thumb.scaled(QSize(width * devicePixelRatio, height * devicePixelRatio), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } else { pix = QPixmap::fromImage(thumb); } + pix.setDevicePixelRatio(thumb.devicePixelRatioF()); emit q->gotPreview(currentItem.item, pix); } diff --git a/src/widgets/thumbcreator.h b/src/widgets/thumbcreator.h --- a/src/widgets/thumbcreator.h +++ b/src/widgets/thumbcreator.h @@ -20,6 +20,8 @@ #ifndef _THUMBCREATOR_H_ #define _THUMBCREATOR_H_ +#include + #include "kiowidgets_export.h" class QString; @@ -184,6 +186,41 @@ }; #endif +/** + * @class ThumbCreatorV3 thumbcreator.h + * @since 5.71 + */ +class KIOWIDGETS_EXPORT ThumbCreatorV3 : public ThumbCreator +{ +public: + // TODO KF6 merge ThumbCreatorV3 to ThumbCreator + virtual ~ThumbCreatorV3(); + + bool create(const QString &path, int width, int height, QImage &img) override; + + /** + * Creates a thumbnail. + * + * Note that this method should not do any scaling. The @p width and @p + * height parameters are provided as hints for images that are generated + * from non-image data (like text). + * + * @param path The path of the file to create a preview for. This is + * always a local path. + * @param width The requested preview width (see the note on scaling + * above). + * @param height The requested preview height (see the note on scaling + * above). + * @param img The QImage to store the preview in. + * @param devicePixelRatio + * + * @return @c true if a preview was successfully generated and store in @p + * img, @c false otherwise. + */ + virtual bool createV3(const QString &path, int width, int height, QImage &img, qreal devicePixelRatio = 1.0) = 0; +}; + + // KF6 TODO: rename this to something less generic typedef ThumbCreator *(*newCreator)(); diff --git a/src/widgets/thumbcreator.cpp b/src/widgets/thumbcreator.cpp --- a/src/widgets/thumbcreator.cpp +++ b/src/widgets/thumbcreator.cpp @@ -43,3 +43,12 @@ { Q_UNUSED(configurationWidget); } + + +ThumbCreatorV3::~ThumbCreatorV3() +{ +} + +bool ThumbCreatorV3::create(const QString &path, int width, int height, QImage &img) { + return createV3(path, width, height, img, 1); +}