Warning, file /office/calligra/libs/flake/KoImageCollection.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) 2008 Thorsten Zachmann <zachmann@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 #include "KoImageCollection.h" 0021 #include "KoImageData.h" 0022 #include "KoImageData_p.h" 0023 #include "KoShapeSavingContext.h" 0024 0025 #include <KoStoreDevice.h> 0026 #include <QCryptographicHash> 0027 #include <KoXmlWriter.h> 0028 0029 #include <QMap> 0030 #include <FlakeDebug.h> 0031 #include <QMimeDatabase> 0032 #include <QMimeType> 0033 0034 0035 class Q_DECL_HIDDEN KoImageCollection::Private 0036 { 0037 public: 0038 ~Private() 0039 { 0040 foreach(KoImageDataPrivate *id, images) 0041 id->collection = 0; 0042 } 0043 0044 QMap<qint64, KoImageDataPrivate*> images; 0045 // an extra map to find all dataObjects based on the key of a store. 0046 QMap<QByteArray, KoImageDataPrivate*> storeImages; 0047 }; 0048 0049 KoImageCollection::KoImageCollection(QObject *parent) 0050 : QObject(parent), 0051 d(new Private()) 0052 { 0053 } 0054 0055 KoImageCollection::~KoImageCollection() 0056 { 0057 delete d; 0058 } 0059 0060 bool KoImageCollection::completeLoading(KoStore *store) 0061 { 0062 Q_UNUSED(store); 0063 d->storeImages.clear(); 0064 return true; 0065 } 0066 0067 bool KoImageCollection::completeSaving(KoStore *store, KoXmlWriter *manifestWriter, KoShapeSavingContext *context) 0068 { 0069 const QMap<qint64, QString> imagesToSave(context->imagesToSave()); 0070 QMap<qint64, QString>::ConstIterator imagesToSaveIter(imagesToSave.begin()); 0071 0072 QMap<qint64, KoImageDataPrivate *>::ConstIterator knownImagesIter(d->images.constBegin()); 0073 0074 while (imagesToSaveIter != imagesToSave.constEnd()) { 0075 if (knownImagesIter == d->images.constEnd()) { 0076 // this should not happen 0077 warnFlake << "image not found"; 0078 Q_ASSERT(0); 0079 break; 0080 } 0081 else if (knownImagesIter.key() == imagesToSaveIter.key()) { 0082 KoImageDataPrivate *imageData = knownImagesIter.value(); 0083 if (store->open(imagesToSaveIter.value())) { 0084 KoStoreDevice device(store); 0085 bool ok = imageData->saveData(device); 0086 store->close(); 0087 // TODO error handling 0088 if (ok) { 0089 QMimeDatabase db; 0090 const QString mimetype(db.mimeTypeForFile(imagesToSaveIter.value(), QMimeDatabase::MatchExtension).name()); 0091 manifestWriter->addManifestEntry(imagesToSaveIter.value(), mimetype); 0092 } else { 0093 warnFlake << "saving image" << imagesToSaveIter.value() << "failed"; 0094 } 0095 } else { 0096 warnFlake << "saving image failed: open store failed"; 0097 } 0098 ++knownImagesIter; 0099 ++imagesToSaveIter; 0100 } else if (knownImagesIter.key() < imagesToSaveIter.key()) { 0101 ++knownImagesIter; 0102 } else { 0103 // this should not happen 0104 warnFlake << "image not found"; 0105 abort(); 0106 Q_ASSERT(0); 0107 } 0108 } 0109 return true; 0110 } 0111 0112 KoImageData *KoImageCollection::createImageData(const QImage &image) 0113 { 0114 Q_ASSERT(!image.isNull()); 0115 KoImageData *data = new KoImageData(); 0116 data->setImage(image); 0117 0118 data = cacheImage(data); 0119 return data; 0120 } 0121 0122 KoImageData *KoImageCollection::createImageData(const QString &href, KoStore *store) 0123 { 0124 // the tricky thing with a 'store' is that we need to read the data now 0125 // as the store will no longer be readable after the loading completed. 0126 // 0127 // The solution we use is to read the data, store it in a QTemporaryFile 0128 // and read and parse it on demand when the image data is actually needed. 0129 // This leads to having two keys, one for the store and one for the 0130 // actual image data. We need the latter so if someone else gets the same 0131 // image data they can find this data and share (insert warm fuzzy feeling here). 0132 // 0133 QByteArray storeKey = (QString::number((qint64) store) + href).toLatin1(); 0134 if (d->storeImages.contains(storeKey)) 0135 return new KoImageData(d->storeImages.value(storeKey)); 0136 0137 KoImageData *data = new KoImageData(); 0138 data->setImage(href, store); 0139 0140 data = cacheImage(data); 0141 d->storeImages.insert(storeKey, data->priv()); 0142 return data; 0143 } 0144 0145 KoImageData *KoImageCollection::createImageData(const QByteArray &imageData) 0146 { 0147 QCryptographicHash md5(QCryptographicHash::Md5); 0148 md5.addData(imageData); 0149 qint64 key = KoImageDataPrivate::generateKey(md5.result()); 0150 if (d->images.contains(key)) 0151 return new KoImageData(d->images.value(key)); 0152 KoImageData *data = new KoImageData(); 0153 data->setImage(imageData); 0154 data->priv()->collection = this; 0155 Q_ASSERT(data->key() == key); 0156 d->images.insert(key, data->priv()); 0157 return data; 0158 } 0159 0160 KoImageData *KoImageCollection::cacheImage(KoImageData *data) 0161 { 0162 QMap<qint64, KoImageDataPrivate*>::const_iterator it(d->images.constFind(data->key())); 0163 if (it == d->images.constEnd()) { 0164 d->images.insert(data->key(), data->priv()); 0165 data->priv()->collection = this; 0166 } 0167 else { 0168 delete data; 0169 data = new KoImageData(it.value()); 0170 } 0171 return data; 0172 } 0173 0174 bool KoImageCollection::fillFromKey(KoImageData &idata, qint64 key) 0175 { 0176 if (d->images.contains(key)) { 0177 idata = KoImageData(d->images.value(key)); 0178 return true; 0179 } 0180 return false; 0181 } 0182 0183 int KoImageCollection::size() const 0184 { 0185 return d->images.count(); 0186 } 0187 0188 int KoImageCollection::count() const 0189 { 0190 return d->images.count(); 0191 } 0192 0193 void KoImageCollection::update(qint64 oldKey, qint64 newKey) 0194 { 0195 if (oldKey == newKey) { 0196 return; 0197 } 0198 if (d->images.contains(oldKey)) { 0199 KoImageDataPrivate *imageData = d->images[oldKey]; 0200 d->images.remove(oldKey); 0201 d->images.insert(newKey, imageData); 0202 } 0203 } 0204 0205 void KoImageCollection::removeOnKey(qint64 imageDataKey) 0206 { 0207 d->images.remove(imageDataKey); 0208 }