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 }