File indexing completed on 2024-09-22 05:02:11

0001 /*
0002     SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "packageimageprovider.h"
0008 
0009 #include <QImageReader>
0010 #include <QPalette>
0011 #include <QUrlQuery>
0012 
0013 #include <KPackage/PackageLoader>
0014 
0015 #include <KSvg/Svg>
0016 
0017 #include "finder/packagefinder.h"
0018 
0019 class AsyncPackageImageResponseRunnable : public QObject, public QRunnable
0020 {
0021     Q_OBJECT
0022 
0023 public:
0024     explicit AsyncPackageImageResponseRunnable(const QString &path, const QSize &requestedSize);
0025 
0026     /**
0027      * Read the image and resize it if the requested size is valid.
0028      */
0029     void run() override;
0030 
0031 Q_SIGNALS:
0032     void done(const QImage &image);
0033 
0034 private:
0035     QString m_path;
0036     QSize m_requestedSize;
0037 };
0038 
0039 class AsyncPackageImageResponse : public QQuickImageResponse
0040 {
0041     Q_OBJECT
0042 
0043 public:
0044     explicit AsyncPackageImageResponse(const QString &path, const QSize &requestedSize, QThreadPool *pool);
0045 
0046     QQuickTextureFactory *textureFactory() const override;
0047 
0048 protected Q_SLOTS:
0049     void slotHandleDone(const QImage &image);
0050 
0051 protected:
0052     QImage m_image;
0053 };
0054 
0055 AsyncPackageImageResponseRunnable::AsyncPackageImageResponseRunnable(const QString &path, const QSize &requestedSize)
0056     : m_path(path)
0057     , m_requestedSize(requestedSize)
0058 {
0059 }
0060 
0061 void AsyncPackageImageResponseRunnable::run()
0062 {
0063     const QUrlQuery urlQuery(QUrl(QStringLiteral("image://package/%1").arg(m_path)));
0064     const QString dir = urlQuery.queryItemValue(QStringLiteral("dir"));
0065 
0066     if (dir.isEmpty()) {
0067         Q_EMIT done(QImage());
0068         return;
0069     }
0070 
0071     KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Wallpaper/Images"));
0072     package.setPath(dir);
0073 
0074     if (!package.isValid()) {
0075         Q_EMIT done(QImage());
0076         return;
0077     }
0078 
0079     PackageFinder::findPreferredImageInPackage(package, m_requestedSize);
0080 
0081     QString path = package.filePath("preferred");
0082     // 192 is from kcm_colors
0083     if (urlQuery.queryItemValue(QStringLiteral("darkMode")).toInt() == 1) {
0084         QString darkPath = package.filePath("preferredDark");
0085 
0086         if (!darkPath.isEmpty()) {
0087             path = darkPath;
0088         }
0089     }
0090 
0091     QImageReader imageReader(path);
0092     QImage image;
0093     if (imageReader.format() == "svg" || imageReader.format() == "svgz") {
0094         KSvg::Svg svgRender;
0095         svgRender.setImagePath(path);
0096         image = svgRender.image(m_requestedSize.isValid() ? svgRender.size().toSize().scaled(m_requestedSize, Qt::KeepAspectRatioByExpanding)
0097                                                           : svgRender.size().toSize());
0098     } else if (imageReader.read(&image)) {
0099         if (m_requestedSize.isValid()) {
0100             image = image.scaled(m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0101         }
0102     }
0103 
0104     Q_EMIT done(image);
0105 }
0106 
0107 AsyncPackageImageResponse::AsyncPackageImageResponse(const QString &path, const QSize &requestedSize, QThreadPool *pool)
0108 {
0109     auto runnable = new AsyncPackageImageResponseRunnable(path, requestedSize);
0110     connect(runnable, &AsyncPackageImageResponseRunnable::done, this, &AsyncPackageImageResponse::slotHandleDone);
0111     pool->start(runnable);
0112 }
0113 
0114 void AsyncPackageImageResponse::slotHandleDone(const QImage &image)
0115 {
0116     m_image = image;
0117     Q_EMIT finished();
0118 }
0119 
0120 QQuickTextureFactory *AsyncPackageImageResponse::textureFactory() const
0121 {
0122     return QQuickTextureFactory::textureFactoryForImage(m_image);
0123 }
0124 
0125 PackageImageProvider::PackageImageProvider()
0126 {
0127 }
0128 
0129 QQuickImageResponse *PackageImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
0130 {
0131     AsyncPackageImageResponse *response = new AsyncPackageImageResponse(id, requestedSize, &m_pool);
0132 
0133     return response;
0134 }
0135 
0136 #include "packageimageprovider.moc"