1 /* This file is part of the KDE project
2  * Copyright (C) 2012 Boudewijn Rempt <boud@valdyas.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "RecentImageImageProvider.h"
20 #include <QFile>
21 #include <QDir>
22 #include <QProcess>
23 #include <QApplication>
24 #include <QImage>
25 #include <QImageReader>
26 #include <QPainter>
27 
28 #include <KoStore.h>
29 #include <KoDocument.h>
30 #include <KoPart.h>
31 
RecentImageImageProvider()32 RecentImageImageProvider::RecentImageImageProvider()
33     : QQuickImageProvider(QQuickImageProvider::Image)
34 {
35 }
36 
requestImage(const QString & id,QSize * size,const QSize & requestedSize)37 QImage RecentImageImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
38 {
39     int width = 512;
40     int height = 512;
41     if(id.endsWith(QLatin1String("odt"), Qt::CaseInsensitive) ||
42        id.endsWith(QLatin1String("doc"), Qt::CaseInsensitive) ||
43        id.endsWith(QLatin1String("docx"), Qt::CaseInsensitive)) {
44         width *= 0.72413793;
45     } else {
46         height *= 0.72413793;
47     }
48 
49     if (size) {
50         *size = QSize(width, height);
51     }
52 
53     QSize sz(requestedSize.width() > 0 ? requestedSize.width() : width,
54              requestedSize.height() > 0 ? requestedSize.height() : height);
55 
56     QFile f(id);
57     QImage thumbnail(sz, QImage::Format_ARGB32_Premultiplied);
58     thumbnail.fill(Qt::white);
59 
60     if (f.exists()) {
61         // try to use any embedded thumbnail
62         KoStore *store = KoStore::createStore(id, KoStore::Read);
63 
64         bool thumbnailFound = false;
65         if (store &&
66             // ODF thumbnail?
67             (store->open(QLatin1String("Thumbnails/thumbnail.png")) ||
68             // old KOffice/Calligra thumbnail?
69             store->open(QLatin1String("preview.png")) ||
70             // OOXML?
71             store->open(QLatin1String("docProps/thumbnail.jpeg")))) {
72             // Hooray! No long delay for the user...
73             const QByteArray thumbnailData = store->read(store->size());
74 
75             QImage thumbnailImage;
76             if (thumbnailImage.loadFromData(thumbnailData) ){//&&
77                 //thumbnailImage.width() >= width && thumbnailImage.height() >= height) {
78                 // put a white background behind the thumbnail
79                 // as lots of old(?) OOo files have thumbnails with transparent background
80                 thumbnail = QImage(thumbnailImage.size(), QImage::Format_RGB32);
81                 thumbnail.fill(QColor(Qt::white).rgb());
82                 QPainter p(&thumbnail);
83                 p.drawImage(QPoint(0, 0), thumbnailImage);
84                 p.end();
85                 thumbnail = thumbnail.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation);
86                 delete store;
87                 thumbnailFound = true;
88             }
89         }
90 
91          if(!thumbnailFound) {
92             // load document and render the thumbnail ourselves
93             QProcess thumbnailer;
94             QString thumbnailerProgram = QString("%1%2calligrageminithumbnailhelper").arg(qApp->applicationDirPath()).arg(QDir::separator());
95             QStringList arguments;
96             arguments << "--in" << id;
97             QString thumbFile = id;
98             thumbFile.replace("/", "-").replace("\\", "-");
99             thumbFile.prepend(QDir::separator()).prepend(QDir::tempPath());
100             thumbFile.append(".png");
101             arguments << "--out" << thumbFile;
102             arguments << "--width" << QString::number(sz.width());
103             arguments << "--height" << QString::number(sz.height());
104             bool fileExists = QFile::exists(thumbFile);
105             if(!fileExists)
106                 thumbnailer.start(thumbnailerProgram, arguments);
107             if(fileExists || thumbnailer.waitForFinished(3000)) {
108                 thumbnail.load(thumbFile);
109                 thumbnail = thumbnail.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation);
110             }
111             else {
112                 // some error, final failure...
113                 qDebug() << "Failed completely to find a preview for" << id;
114             }
115         }
116     }
117     return thumbnail;
118 }
119