File indexing completed on 2024-05-12 16:01:49
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2001 Werner Trobin <trobin@kde.org> 0005 SPDX-FileCopyrightText: 2002 Werner Trobin <trobin@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "KisImportExportFilter.h" 0011 0012 #include <QFile> 0013 #include <QFileInfo> 0014 #include <kis_debug.h> 0015 #include <QStack> 0016 #include "KisImportExportManager.h" 0017 #include <KoColorSpaceRegistry.h> 0018 #include <KoColorModelStandardIds.h> 0019 #include <KisExportCheckBase.h> 0020 #include <KisExportCheckRegistry.h> 0021 #include "KoUpdater.h" 0022 #include <klocalizedstring.h> 0023 #include "kis_config.h" 0024 #include <KoStore.h> 0025 #include <KisDocument.h> 0026 0027 const QString KisImportExportFilter::ImageContainsTransparencyTag = "ImageContainsTransparency"; 0028 const QString KisImportExportFilter::ColorModelIDTag = "ColorModelID"; 0029 const QString KisImportExportFilter::ColorDepthIDTag = "ColorDepthID"; 0030 const QString KisImportExportFilter::sRGBTag = "sRGB"; 0031 const QString KisImportExportFilter::CICPPrimariesTag = "CICPCompatiblePrimaries"; 0032 const QString KisImportExportFilter::CICPTransferCharacteristicsTag = "CICPCompatibleTransferFunction"; 0033 const QString KisImportExportFilter::HDRTag = "HDRSupported"; 0034 0035 class Q_DECL_HIDDEN KisImportExportFilter::Private 0036 { 0037 public: 0038 QPointer<KoUpdater> updater; 0039 QByteArray mime; 0040 QString filename; 0041 QString realFilename; 0042 bool batchmode; 0043 0044 QMap<QString, KisExportCheckBase*> capabilities; 0045 0046 Private() 0047 : updater(0), mime("") 0048 , batchmode(false) 0049 {} 0050 0051 ~Private() 0052 { 0053 qDeleteAll(capabilities); 0054 } 0055 0056 }; 0057 0058 0059 KisImportExportFilter::KisImportExportFilter(QObject *parent) 0060 : QObject(parent) 0061 , d(new Private) 0062 { 0063 } 0064 0065 KisImportExportFilter::~KisImportExportFilter() 0066 { 0067 if (d->updater) { 0068 d->updater->setProgress(100); 0069 } 0070 delete d; 0071 } 0072 0073 QString KisImportExportFilter::filename() const 0074 { 0075 return d->filename; 0076 } 0077 0078 QString KisImportExportFilter::realFilename() const 0079 { 0080 return d->realFilename; 0081 } 0082 0083 bool KisImportExportFilter::batchMode() const 0084 { 0085 return d->batchmode; 0086 } 0087 0088 0089 void KisImportExportFilter::setBatchMode(bool batchmode) 0090 { 0091 d->batchmode = batchmode; 0092 } 0093 0094 void KisImportExportFilter::setFilename(const QString &filename) 0095 { 0096 d->filename = filename; 0097 } 0098 0099 void KisImportExportFilter::setRealFilename(const QString &filename) 0100 { 0101 d->realFilename = filename; 0102 } 0103 0104 0105 void KisImportExportFilter::setMimeType(const QString &mime) 0106 { 0107 d->mime = mime.toLatin1(); 0108 } 0109 0110 QByteArray KisImportExportFilter::mimeType() const 0111 { 0112 return d->mime; 0113 } 0114 0115 KisPropertiesConfigurationSP KisImportExportFilter::defaultConfiguration(const QByteArray &from, const QByteArray &to) const 0116 { 0117 Q_UNUSED(from); 0118 Q_UNUSED(to); 0119 return 0; 0120 } 0121 0122 KisPropertiesConfigurationSP KisImportExportFilter::lastSavedConfiguration(const QByteArray &from, const QByteArray &to) const 0123 { 0124 KisPropertiesConfigurationSP cfg = defaultConfiguration(from, to); 0125 const QString filterConfig = KisConfig(true).exportConfigurationXML(to); 0126 if (cfg && !filterConfig.isEmpty()) { 0127 cfg->fromXML(filterConfig, false); 0128 } 0129 return cfg; 0130 } 0131 0132 KisConfigWidget *KisImportExportFilter::createConfigurationWidget(QWidget *, const QByteArray &from, const QByteArray &to) const 0133 { 0134 Q_UNUSED(from); 0135 Q_UNUSED(to); 0136 return 0; 0137 } 0138 0139 QMap<QString, KisExportCheckBase *> KisImportExportFilter::exportChecks() 0140 { 0141 qDeleteAll(d->capabilities); 0142 initializeCapabilities(); 0143 return d->capabilities; 0144 } 0145 0146 QString KisImportExportFilter::verify(const QString &fileName) const 0147 { 0148 QFileInfo fi(fileName); 0149 0150 if (!fi.exists()) { 0151 return i18n("%1 does not exist after writing. Try saving again under a different name, in another location.", fileName); 0152 } 0153 0154 if (!fi.isReadable()) { 0155 return i18n("%1 is not readable", fileName); 0156 } 0157 0158 if (fi.size() < 10) { 0159 return i18n("%1 is smaller than 10 bytes, it must be corrupt. Try saving again under a different name, in another location.", fileName); 0160 } 0161 0162 QFile f(fileName); 0163 f.open(QFile::ReadOnly); 0164 QByteArray ba = f.read(std::min(f.size(), (qint64)1000)); 0165 bool found = false; 0166 for(int i = 0; i < ba.size(); ++i) { 0167 if (ba.at(i) > 0) { 0168 found = true; 0169 break; 0170 } 0171 } 0172 0173 if (!found) { 0174 return i18n("%1 has only zero bytes in the first 1000 bytes, it's probably corrupt. Try saving again under a different name, in another location.", fileName); 0175 } 0176 0177 return QString(); 0178 } 0179 0180 void KisImportExportFilter::setUpdater(QPointer<KoUpdater> updater) 0181 { 0182 d->updater = updater; 0183 } 0184 0185 QPointer<KoUpdater> KisImportExportFilter::updater() 0186 { 0187 return d->updater; 0188 } 0189 0190 void KisImportExportFilter::setProgress(int value) 0191 { 0192 if (d->updater) { 0193 d->updater->setValue(value); 0194 } 0195 } 0196 0197 void KisImportExportFilter::initializeCapabilities() 0198 { 0199 // XXX: Initialize everything to fully supported? 0200 } 0201 0202 void KisImportExportFilter::addCapability(KisExportCheckBase *capability) 0203 { 0204 d->capabilities[capability->id()] = capability; 0205 } 0206 0207 0208 0209 void KisImportExportFilter::addSupportedColorModels(QList<QPair<KoID, KoID> > supportedColorModels, const QString &name, KisExportCheckBase::Level level) 0210 { 0211 Q_ASSERT(level != KisExportCheckBase::SUPPORTED); 0212 QString layerMessage; 0213 QString imageMessage; 0214 QList<KoID> allColorModels = KoColorSpaceRegistry::instance()->colorModelsList(KoColorSpaceRegistry::AllColorSpaces); 0215 Q_FOREACH(const KoID &colorModelID, allColorModels) { 0216 QList<KoID> allColorDepths = KoColorSpaceRegistry::instance()->colorDepthList(colorModelID.id(), KoColorSpaceRegistry::AllColorSpaces); 0217 Q_FOREACH(const KoID &colorDepthID, allColorDepths) { 0218 0219 KisExportCheckFactory *colorModelCheckFactory = 0220 KisExportCheckRegistry::instance()->get("ColorModelCheck/" + colorModelID.id() + "/" + colorDepthID.id()); 0221 KisExportCheckFactory *colorModelPerLayerCheckFactory = 0222 KisExportCheckRegistry::instance()->get("ColorModelPerLayerCheck/" + colorModelID.id() + "/" + colorDepthID.id()); 0223 0224 if(!colorModelCheckFactory || !colorModelPerLayerCheckFactory) { 0225 qWarning() << "No factory for" << colorModelID << colorDepthID; 0226 continue; 0227 } 0228 0229 if (supportedColorModels.contains(QPair<KoID, KoID>(colorModelID, colorDepthID))) { 0230 addCapability(colorModelCheckFactory->create(KisExportCheckBase::SUPPORTED)); 0231 addCapability(colorModelPerLayerCheckFactory->create(KisExportCheckBase::SUPPORTED)); 0232 } 0233 else { 0234 0235 0236 if (level == KisExportCheckBase::PARTIALLY) { 0237 imageMessage = i18nc("image conversion warning", 0238 "%1 cannot save images with color model <b>%2</b> and depth <b>%3</b>. The image will be converted." 0239 ,name, colorModelID.name(), colorDepthID.name()); 0240 0241 layerMessage = 0242 i18nc("image conversion warning", 0243 "%1 cannot save layers with color model <b>%2</b> and depth <b>%3</b>. The layers will be converted or skipped." 0244 ,name, colorModelID.name(), colorDepthID.name()); 0245 } 0246 else { 0247 imageMessage = i18nc("image conversion warning", 0248 "%1 cannot save images with color model <b>%2</b> and depth <b>%3</b>. The image will not be saved." 0249 ,name, colorModelID.name(), colorDepthID.name()); 0250 0251 layerMessage = 0252 i18nc("image conversion warning", 0253 "%1 cannot save layers with color model <b>%2</b> and depth <b>%3</b>. The layers will be skipped." 0254 , name, colorModelID.name(), colorDepthID.name()); 0255 } 0256 0257 0258 0259 addCapability(colorModelCheckFactory->create(level, imageMessage)); 0260 addCapability(colorModelPerLayerCheckFactory->create(level, layerMessage)); 0261 } 0262 } 0263 } 0264 } 0265 0266 QString KisImportExportFilter::verifyZiPBasedFiles(const QString &fileName, const QStringList &filesToCheck) const 0267 { 0268 QScopedPointer<KoStore> store(KoStore::createStore(fileName, KoStore::Read, KIS_MIME_TYPE, KoStore::Zip)); 0269 0270 if (!store || store->bad()) { 0271 return i18n("Could not open the saved file %1. Please try to save again in a different location.", fileName); 0272 } 0273 0274 Q_FOREACH(const QString &file, filesToCheck) { 0275 if (!store->hasFile(file)) { 0276 return i18n("File %1 is missing in %2 and is broken. Please try to save again in a different location.", file, fileName); 0277 } 0278 } 0279 0280 return QString(); 0281 0282 }