Warning, file /office/calligra/libs/flake/KoImageData_p.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007, 2009 Thomas Zander <zander@kde.org>
0003  * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
0004  * Copyright (C) 2008 C. Boemann <cbo@boemann.dk>
0005  * Copyright (C) 2008 Thorsten Zachmann <zachmann@kde.org>
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Library General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Library General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Library General Public License
0018  * along with this library; see the file COPYING.LIB.  If not, write to
0019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  */
0022 
0023 #include "KoImageData_p.h"
0024 #include "KoImageCollection.h"
0025 
0026 #include <QApplication>
0027 #include <QTemporaryFile>
0028 #include <QImageWriter>
0029 #include <QCryptographicHash>
0030 #include <QFileInfo>
0031 #include <FlakeDebug.h>
0032 #include <QBuffer>
0033 
0034 KoImageDataPrivate::KoImageDataPrivate(KoImageData *q)
0035     : collection(0),
0036     errorCode(KoImageData::Success),
0037     key(0),
0038     refCount(0),
0039     dataStoreState(StateEmpty),
0040     temporaryFile(0)
0041 {
0042     cleanCacheTimer.setSingleShot(true);
0043     cleanCacheTimer.setInterval(1000);
0044     QObject::connect(&cleanCacheTimer, SIGNAL(timeout()), q, SLOT(cleanupImageCache()));
0045 }
0046 
0047 KoImageDataPrivate::~KoImageDataPrivate()
0048 {
0049     if (collection)
0050         collection->removeOnKey(key);
0051     delete temporaryFile;
0052 }
0053 
0054 // called from the collection
0055 bool KoImageDataPrivate::saveData(QIODevice &device)
0056 {
0057     // if we have a temp file save that to the store. This is needed as to not lose data when
0058     // saving lossy formats. Also writing out gif is not supported by qt so saving temp file
0059     // also fixes the problem that gif images are empty after saving.
0060     if (temporaryFile) {
0061         if (!temporaryFile->open()) {
0062             warnFlake << "Read file from temporary store failed";
0063             return false;
0064         }
0065         char buf[4096];
0066         while (true) {
0067             temporaryFile->waitForReadyRead(-1);
0068             qint64 bytes = temporaryFile->read(buf, sizeof(buf));
0069             if (bytes <= 0)
0070                 break; // done!
0071             do {
0072                 qint64 nWritten = device.write(buf, bytes);
0073                 if (nWritten == -1) {
0074                     temporaryFile->close();
0075                     return false;
0076                 }
0077                 bytes -= nWritten;
0078             } while (bytes > 0);
0079         }
0080         temporaryFile->close();
0081         return true;
0082     }
0083 
0084     switch (dataStoreState) {
0085     case KoImageDataPrivate::StateEmpty:
0086         return false;
0087     case KoImageDataPrivate::StateNotLoaded:
0088         // we should not reach this state as above this will already be saved.
0089         Q_ASSERT(temporaryFile);
0090         return true;
0091     case KoImageDataPrivate::StateImageLoaded:
0092     case KoImageDataPrivate::StateImageOnly: {
0093         // save image
0094         QBuffer buffer;
0095         QImageWriter writer(&buffer, suffix.toLatin1());
0096         bool result = writer.write(image);
0097         device.write(buffer.data(), buffer.size());
0098         return result;
0099       }
0100     }
0101     return false;
0102 }
0103 
0104 void KoImageDataPrivate::setSuffix(const QString &name)
0105 {
0106     QFileInfo fi(name);
0107     suffix = fi.suffix();
0108 }
0109 
0110 void KoImageDataPrivate::copyToTemporary(QIODevice &device)
0111 {
0112     delete temporaryFile;
0113     temporaryFile = new QTemporaryFile(QDir::tempPath() + "/" + qAppName() + QLatin1String("_XXXXXX"));
0114     if (!temporaryFile->open()) {
0115         warnFlake << "open temporary file for writing failed";
0116         errorCode = KoImageData::StorageFailed;
0117         return;
0118     }
0119     QCryptographicHash md5(QCryptographicHash::Md5);
0120     char buf[8096];
0121     while (true) {
0122         device.waitForReadyRead(-1);
0123         qint64 bytes = device.read(buf, sizeof(buf));
0124         if (bytes <= 0)
0125             break; // done!
0126         md5.addData(buf, bytes);
0127         do {
0128             bytes -= temporaryFile->write(buf, bytes);
0129         } while (bytes > 0);
0130     }
0131     key = KoImageDataPrivate::generateKey(md5.result());
0132 
0133     temporaryFile->close();
0134 
0135     dataStoreState = StateNotLoaded;
0136 }
0137 
0138 void KoImageDataPrivate::cleanupImageCache()
0139 {
0140     if (dataStoreState == KoImageDataPrivate::StateImageLoaded) {
0141         image = QImage();
0142         dataStoreState = KoImageDataPrivate::StateNotLoaded;
0143     }
0144 }
0145 
0146 void KoImageDataPrivate::clear()
0147 {
0148     errorCode = KoImageData::Success;
0149     dataStoreState = StateEmpty;
0150     imageLocation.clear();
0151     imageSize = QSizeF();
0152     key = 0;
0153     image = QImage();
0154     pixmap = QPixmap();
0155 }
0156 
0157 qint64 KoImageDataPrivate::generateKey(const QByteArray &bytes)
0158 {
0159     qint64 answer = 1;
0160     const int max = qMin(8, bytes.count());
0161     for (int x = 0; x < max; ++x)
0162         answer += bytes[x] << (8 * x);
0163     return answer;
0164 }