File indexing completed on 2024-04-14 04:43:59

0001 /*
0002    SPDX-FileCopyrightText: 2018 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #include "embeddedcoverageimageprovider.h"
0008 
0009 #include <KFileMetaData/EmbeddedImageData>
0010 #include <KFileMetaData/ExtractorCollection>
0011 #include <KFileMetaData/SimpleExtractionResult>
0012 
0013 #include <QImage>
0014 #include <QMimeDatabase>
0015 
0016 class AsyncImageResponse : public QQuickImageResponse, public QRunnable
0017 {
0018     Q_OBJECT
0019 
0020 public:
0021     AsyncImageResponse(QString id, QSize requestedSize)
0022         : QQuickImageResponse(), mId(std::move(id)), mRequestedSize(requestedSize)
0023     {
0024         setAutoDelete(false);
0025 
0026         if (!mRequestedSize.width()) {
0027             mRequestedSize.setWidth(mRequestedSize.height());
0028         }
0029 
0030         if (!mRequestedSize.height()) {
0031             mRequestedSize.setHeight(mRequestedSize.width());
0032         }
0033     }
0034 
0035     [[nodiscard]] QQuickTextureFactory *textureFactory() const override
0036     {
0037         return QQuickTextureFactory::textureFactoryForImage(mCoverImage);
0038     }
0039 
0040     void run() override
0041     {
0042         QMimeDatabase mimeDatabase;
0043         const auto fileMimeType = mimeDatabase.mimeTypeForFile(mId).name();
0044         KFileMetaData::ExtractorCollection ec;
0045         KFileMetaData::SimpleExtractionResult result(mId, fileMimeType, KFileMetaData::ExtractionResult::ExtractImageData);
0046 
0047         mErrorMessage = QLatin1String{""};
0048 
0049         auto extractors = ec.fetchExtractors(fileMimeType);
0050         for (const auto& ex : extractors) {
0051             ex->extract(&result);
0052         }
0053 
0054         auto imageData = result.imageData();
0055 
0056         if (imageData.isEmpty()) {
0057           mErrorMessage = QString{QLatin1String{"Unable to load image data from "} + mId};
0058           Q_EMIT finished();
0059           return;
0060         }
0061 
0062         if (imageData.contains(KFileMetaData::EmbeddedImageData::FrontCover)) {
0063           mCoverImage = QImage::fromData(imageData[KFileMetaData::EmbeddedImageData::FrontCover]);
0064         } else {
0065           mCoverImage = QImage::fromData(imageData.first());
0066         }
0067 
0068         if (mCoverImage.isNull()) {
0069           mErrorMessage = QString{QLatin1String{"Invalid embedded cover image in "} + mId};
0070           Q_EMIT finished();
0071           return;
0072         }
0073 
0074         auto newCoverImage = mCoverImage.scaled(mRequestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0075         if (!newCoverImage.isNull()) {
0076           mCoverImage = std::move(newCoverImage);
0077         }
0078 
0079         Q_EMIT finished();
0080     }
0081 
0082     QString errorString() const override
0083     {
0084       return mErrorMessage;
0085     }
0086 
0087     QString mId;
0088     QString mErrorMessage;
0089     QSize mRequestedSize;
0090     QImage mCoverImage;
0091 };
0092 
0093 EmbeddedCoverageImageProvider::EmbeddedCoverageImageProvider()
0094     : QQuickAsyncImageProvider()
0095 {
0096 }
0097 
0098 QQuickImageResponse *EmbeddedCoverageImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
0099 {
0100     auto response = std::make_unique<AsyncImageResponse>(id, requestedSize);
0101     pool.start(response.get());
0102     return response.release();
0103 }
0104 
0105 #include "embeddedcoverageimageprovider.moc"