File indexing completed on 2024-05-05 17:04:28

0001 /*
0002  * Assists in creating thumbnails for Gemini's file views
0003  * Copyright 2014  Dan Leinir Turthra Jensen <admin@leinir.dk>
0004  *
0005  * This program is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU General Public License as
0007  * published by the Free Software Foundation; either version 2 of
0008  * the License or (at your option) version 3 or any later version
0009  * accepted by the membership of KDE e.V. (or its successor approved
0010  * by the membership of KDE e.V.), which shall act as a proxy
0011  * defined in Section 14 of version 3 of the license.
0012  *
0013  * This program is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016  * GNU General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU General Public License
0019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0020  *
0021  */
0022 
0023 #include "ThumbnailHelperImpl.h"
0024 #include <QMimeDatabase>
0025 
0026 #include <KoDocument.h>
0027 #include <KoDocumentEntry.h>
0028 #include <KoPart.h>
0029 #include <KoStore.h>
0030 
0031 #include <QTimer>
0032 #include <QImage>
0033 #include <QApplication>
0034 #include <QPainter>
0035 #include <QMimeType>
0036 
0037 static const int minThumbnailSize = 400;
0038 static const int timeoutTime = 5000; // in msec
0039 
0040 ThumbnailHelperImpl::ThumbnailHelperImpl(QObject* parent)
0041     : QObject(parent)
0042     , m_part(0)
0043     , m_doc(0)
0044 {
0045 }
0046 
0047 ThumbnailHelperImpl::~ThumbnailHelperImpl()
0048 {
0049     if(m_doc)
0050         m_doc->deleteLater();
0051 }
0052 
0053 bool ThumbnailHelperImpl::convert(const QString& in, const QString& out, int width, int height)
0054 {
0055     // Other locations for thumbnails use the embedded thumbnails. This
0056     // application specifically exists to ensure less crashes in situations
0057     // where that embedded image doesn't exist or is invalid for whatever
0058     // reason. As a direct consequence, we do not attempt to load that image.
0059     QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
0060 
0061     QMimeDatabase db;
0062     const QString mimetype = db.mimeTypeForFile(in).name();
0063     QString error;
0064     KoDocumentEntry documentEntry = KoDocumentEntry::queryByMimeType(mimetype);
0065     m_part = documentEntry.createKoPart(&error);
0066 
0067     if (!m_part)
0068         return false;
0069 
0070     m_doc = m_part->document();
0071 
0072     // prepare the document object
0073     m_doc->setCheckAutoSaveFile(false);
0074     m_doc->setAutoErrorHandlingEnabled(false); // don't show message boxes
0075     connect(m_doc, SIGNAL(completed()), SLOT(onLoadingCompleted()));
0076 
0077     // load the document content
0078     QUrl url = QUrl::fromLocalFile(in);
0079     if (!m_doc->openUrl(url)) {
0080         delete m_doc;
0081         qDebug() << "Load failure! Document did not open" << url;
0082         return false;
0083     }
0084 
0085     while(m_doc->isLoading()) {
0086         qApp->processEvents();
0087     }
0088 
0089     // render the page on a bigger pixmap and use smoothScale,
0090     // looks better than directly scaling with the QPainter (malte)
0091     //const bool usePassedSize = (width > minThumbnailSize && height > minThumbnailSize);
0092     //const QSize size = usePassedSize ? QSize(width, height) : QSize(minThumbnailSize, minThumbnailSize);
0093     const QSize size = QSize(width, height);
0094     image = m_doc->generatePreview(size * 2).toImage().scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0095 
0096     m_doc->closeUrl();
0097 
0098     image.save(out);
0099 
0100     return m_loadingCompleted;
0101 }