diff --git a/libs/ui/KisImportExportFilter.cpp b/libs/ui/KisImportExportFilter.cpp index baabd4875c..2885797d7a 100644 --- a/libs/ui/KisImportExportFilter.cpp +++ b/libs/ui/KisImportExportFilter.cpp @@ -1,344 +1,349 @@ /* This file is part of the KDE libraries Copyright (C) 2001 Werner Trobin 2002 Werner Trobin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisImportExportFilter.h" #include #include #include #include #include "KisImportExportManager.h" #include #include #include #include #include "KoUpdater.h" #include #include "kis_config.h" #include #include const QString KisImportExportFilter::ImageContainsTransparencyTag = "ImageContainsTransparency"; const QString KisImportExportFilter::ColorModelIDTag = "ColorModelID"; const QString KisImportExportFilter::ColorDepthIDTag = "ColorDepthID"; const QString KisImportExportFilter::sRGBTag = "sRGB"; class Q_DECL_HIDDEN KisImportExportFilter::Private { public: QPointer updater; QByteArray mime; QString filename; QString realFilename; bool batchmode; QMap capabilities; Private() : updater(0), mime("") , batchmode(false) {} ~Private() { qDeleteAll(capabilities); } }; KisImportExportFilter::KisImportExportFilter(QObject *parent) : QObject(parent) , d(new Private) { } KisImportExportFilter::~KisImportExportFilter() { if (d->updater) { d->updater->setProgress(100); } delete d; } QString KisImportExportFilter::filename() const { return d->filename; } QString KisImportExportFilter::realFilename() const { return d->realFilename; } bool KisImportExportFilter::batchMode() const { return d->batchmode; } void KisImportExportFilter::setBatchMode(bool batchmode) { d->batchmode = batchmode; } void KisImportExportFilter::setFilename(const QString &filename) { d->filename = filename; } void KisImportExportFilter::setRealFilename(const QString &filename) { d->realFilename = filename; } void KisImportExportFilter::setMimeType(const QString &mime) { d->mime = mime.toLatin1(); } QByteArray KisImportExportFilter::mimeType() const { return d->mime; } QString KisImportExportFilter::conversionStatusString(ConversionStatus status) { QString msg; switch (status) { case OK: break; case FilterCreationError: msg = i18n("Krita does not support this file format"); break; case CreationError: msg = i18n("Could not create the output document"); break; case FileNotFound: msg = i18n("File not found"); break; case StorageCreationError: msg = i18n("Cannot create storage"); break; case BadMimeType: msg = i18n("Bad MIME type"); break; case WrongFormat: msg = i18n("Format not recognized"); break; case NotImplemented: msg = i18n("Not implemented"); break; case ParsingError: msg = i18n("Parsing error"); break; case InvalidFormat: msg = i18n("Invalid file format"); break; case InternalError: case UsageError: msg = i18n("Internal error"); break; case ProgressCancelled: msg = i18n("Cancelled by user"); break; case BadConversionGraph: msg = i18n("Unknown file type"); break; case UnsupportedVersion: msg = i18n("Unsupported file version"); break; case UserCancelled: // intentionally we do not prompt the error message here break; default: msg = i18n("Unknown error"); break; } return msg; } KisPropertiesConfigurationSP KisImportExportFilter::defaultConfiguration(const QByteArray &from, const QByteArray &to) const { Q_UNUSED(from); Q_UNUSED(to); return 0; } KisPropertiesConfigurationSP KisImportExportFilter::lastSavedConfiguration(const QByteArray &from, const QByteArray &to) const { KisPropertiesConfigurationSP cfg = defaultConfiguration(from, to); const QString filterConfig = KisConfig(true).exportConfigurationXML(to); if (cfg && !filterConfig.isEmpty()) { cfg->fromXML(filterConfig, false); } return cfg; } KisConfigWidget *KisImportExportFilter::createConfigurationWidget(QWidget *, const QByteArray &from, const QByteArray &to) const { Q_UNUSED(from); Q_UNUSED(to); return 0; } QMap KisImportExportFilter::exportChecks() { qDeleteAll(d->capabilities); initializeCapabilities(); return d->capabilities; } QString KisImportExportFilter::verify(const QString &fileName) const { QFileInfo fi(fileName); if (!fi.exists()) { return i18n("%1 does not exist after writing. Try saving again under a different name, in another location.", fileName); } if (!fi.isReadable()) { return i18n("%1 is not readable", fileName); } if (fi.size() < 10) { return i18n("%1 is smaller than 10 bytes, it must be corrupt. Try saving again under a different name, in another location.", fileName); } QFile f(fileName); f.open(QFile::ReadOnly); QByteArray ba = f.read(std::min(f.size(), (qint64)1000)); bool found = false; for(int i = 0; i < ba.size(); ++i) { if (ba.at(i) > 0) { found = true; break; } } if (!found) { 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); } return QString(); } void KisImportExportFilter::setUpdater(QPointer updater) { d->updater = updater; } +QPointer KisImportExportFilter::updater() +{ + return d->updater; +} + void KisImportExportFilter::setProgress(int value) { if (d->updater) { d->updater->setValue(value); } } void KisImportExportFilter::initializeCapabilities() { // XXX: Initialize everything to fully supported? } void KisImportExportFilter::addCapability(KisExportCheckBase *capability) { d->capabilities[capability->id()] = capability; } void KisImportExportFilter::addSupportedColorModels(QList > supportedColorModels, const QString &name, KisExportCheckBase::Level level) { Q_ASSERT(level != KisExportCheckBase::SUPPORTED); QString layerMessage; QString imageMessage; QList allColorModels = KoColorSpaceRegistry::instance()->colorModelsList(KoColorSpaceRegistry::AllColorSpaces); Q_FOREACH(const KoID &colorModelID, allColorModels) { QList allColorDepths = KoColorSpaceRegistry::instance()->colorDepthList(colorModelID.id(), KoColorSpaceRegistry::AllColorSpaces); Q_FOREACH(const KoID &colorDepthID, allColorDepths) { KisExportCheckFactory *colorModelCheckFactory = KisExportCheckRegistry::instance()->get("ColorModelCheck/" + colorModelID.id() + "/" + colorDepthID.id()); KisExportCheckFactory *colorModelPerLayerCheckFactory = KisExportCheckRegistry::instance()->get("ColorModelPerLayerCheck/" + colorModelID.id() + "/" + colorDepthID.id()); if(!colorModelCheckFactory || !colorModelPerLayerCheckFactory) { qWarning() << "No factory for" << colorModelID << colorDepthID; continue; } if (supportedColorModels.contains(QPair(colorModelID, colorDepthID))) { addCapability(colorModelCheckFactory->create(KisExportCheckBase::SUPPORTED)); addCapability(colorModelPerLayerCheckFactory->create(KisExportCheckBase::SUPPORTED)); } else { if (level == KisExportCheckBase::PARTIALLY) { imageMessage = i18nc("image conversion warning", "%1 cannot save images with color model %2 and depth %3. The image will be converted." ,name, colorModelID.name(), colorDepthID.name()); layerMessage = i18nc("image conversion warning", "%1 cannot save layers with color model %2 and depth %3. The layers will be converted or skipped." ,name, colorModelID.name(), colorDepthID.name()); } else { imageMessage = i18nc("image conversion warning", "%1 cannot save images with color model %2 and depth %3. The image will not be saved." ,name, colorModelID.name(), colorDepthID.name()); layerMessage = i18nc("image conversion warning", "%1 cannot save layers with color model %2 and depth %3. The layers will be skipped." , name, colorModelID.name(), colorDepthID.name()); } addCapability(colorModelCheckFactory->create(level, imageMessage)); addCapability(colorModelPerLayerCheckFactory->create(level, layerMessage)); } } } } QString KisImportExportFilter::verifyZiPBasedFiles(const QString &fileName, const QStringList &filesToCheck) const { QScopedPointer store(KoStore::createStore(fileName, KoStore::Read, KIS_MIME_TYPE, KoStore::Zip)); if (!store || store->bad()) { return i18n("Could not open the saved file %1. Please try to save again in a different location.", fileName); } Q_FOREACH(const QString &file, filesToCheck) { if (!store->hasFile(file)) { return i18n("File %1 is missing in %2 and is broken. Please try to save again in a different location.", file, fileName); } } return QString(); } diff --git a/libs/ui/KisImportExportFilter.h b/libs/ui/KisImportExportFilter.h index 190b803617..455f47cb35 100644 --- a/libs/ui/KisImportExportFilter.h +++ b/libs/ui/KisImportExportFilter.h @@ -1,190 +1,191 @@ /* This file is part of the Calligra libraries Copyright (C) 2001 Werner Trobin 2002 Werner Trobin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMPORT_EXPORT_FILTER_H #define KIS_IMPORT_EXPORT_FILTER_H #include "KisImageBuilderResult.h" #include #include #include #include #include #include #include #include #include #include #include #include class KoUpdater; class KisDocument; class KisConfigWidget; #include "kritaui_export.h" #include "KisImportExportErrorCode.h" /** * @brief The base class for import and export filters. * * Derive your filter class from this base class and implement * the @ref convert() method. Don't forget to specify the Q_OBJECT * macro in your class even if you don't use signals or slots. * This is needed as filters are created on the fly. * * @note Take care: The m_chain pointer is invalid while the constructor * runs due to the implementation -- @em don't use it in the constructor. * After the constructor, when running the @ref convert() method it's * guaranteed to be valid, so no need to check against 0. * * @note If the code is compiled in debug mode, setting CALLIGRA_DEBUG_FILTERS * environment variable to any value disables deletion of temporary files while * importing/exporting. This is useful for testing purposes. * * @author Werner Trobin * @todo the class has no constructor and therefore cannot initialize its private class */ class KRITAUI_EXPORT KisImportExportFilter : public QObject { Q_OBJECT public: static const QString ImageContainsTransparencyTag; static const QString ColorModelIDTag; static const QString ColorDepthIDTag; static const QString sRGBTag; public: /** * This enum is used to signal the return state of your filter. * Return OK in @ref convert() in case everything worked as expected. * Feel free to add some more error conditions @em before the last item * if it's needed. */ enum ConversionStatus { OK, UsageError, CreationError, FileNotFound, StorageCreationError, BadMimeType, BadConversionGraph, WrongFormat, NotImplemented, ParsingError, InternalError, UserCancelled, InvalidFormat, FilterCreationError, ProgressCancelled, UnsupportedVersion, JustInCaseSomeBrokenCompilerUsesLessThanAByte = 255 }; ~KisImportExportFilter() override; void setBatchMode(bool batchmode); void setFilename(const QString &filename); void setRealFilename(const QString &filename); void setMimeType(const QString &mime); void setUpdater(QPointer updater); + QPointer updater(); /** * The filter chain calls this method to perform the actual conversion. * The passed mimetypes should be a pair of those you specified in your * .desktop file. * You @em have to implement this method to make the filter work. * * @return The error status, see the @ref #ConversionStatus enum. * KisImportExportFilter::OK means that everything is alright. */ virtual KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) = 0; /** * Get the text version of the status value */ static QString conversionStatusString(ConversionStatus status); /** * @brief defaultConfiguration defines the default settings for the given import export filter * @param from The mimetype of the source file/document * @param to The mimetype of the destination file/document * @return a serializable KisPropertiesConfiguration object */ virtual KisPropertiesConfigurationSP defaultConfiguration(const QByteArray& from = "", const QByteArray& to = "") const; /** * @brief lastSavedConfiguration return the last saved configuration for this filter * @param from The mimetype of the source file/document * @param to The mimetype of the destination file/document * @return a serializable KisPropertiesConfiguration object */ KisPropertiesConfigurationSP lastSavedConfiguration(const QByteArray &from = "", const QByteArray &to = "") const; /** * @brief createConfigurationWidget creates a widget that can be used to define the settings for a given import/export filter * @param parent the owner of the widget; the caller is responsible for deleting * @param from The mimetype of the source file/document * @param to The mimetype of the destination file/document * * @return the widget */ virtual KisConfigWidget *createConfigurationWidget(QWidget *parent, const QByteArray& from = "", const QByteArray& to = "") const; /** * @brief generate and return the list of capabilities of this export filter. The list * @return returns the list of capabilities of this export filter */ virtual QMap exportChecks(); /// Override and return false for the filters that use a library that cannot handle file handles, only file names. virtual bool supportsIO() const { return true; } /// Verify whether the given file is correct and readable virtual QString verify(const QString &fileName) const; protected: /** * This is the constructor your filter has to call, obviously. */ KisImportExportFilter(QObject *parent = 0); QString filename() const; QString realFilename() const; bool batchMode() const; QByteArray mimeType() const; void setProgress(int value); virtual void initializeCapabilities(); void addCapability(KisExportCheckBase *capability); void addSupportedColorModels(QList > supportedColorModels, const QString &name, KisExportCheckBase::Level level = KisExportCheckBase::PARTIALLY); QString verifyZiPBasedFiles(const QString &fileName, const QStringList &filesToCheck) const; private: KisImportExportFilter(const KisImportExportFilter& rhs); KisImportExportFilter& operator=(const KisImportExportFilter& rhs); class Private; Private *const d; }; #endif diff --git a/plugins/impex/kra/kra_converter.cpp b/plugins/impex/kra/kra_converter.cpp index 191042cb03..64b6f34de1 100644 --- a/plugins/impex/kra/kra_converter.cpp +++ b/plugins/impex/kra/kra_converter.cpp @@ -1,387 +1,407 @@ /* * Copyright (C) 2016 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kra_converter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char CURRENT_DTD_VERSION[] = "2.0"; KraConverter::KraConverter(KisDocument *doc) : m_doc(doc) , m_image(doc->savingImage()) { } +KraConverter::KraConverter(KisDocument *doc, QPointer updater) + : m_doc(doc) + , m_image(doc->savingImage()) + , m_updater(updater) +{ +} + KraConverter::~KraConverter() { delete m_store; delete m_kraSaver; delete m_kraLoader; } KisImportExportErrorCode KraConverter::buildImage(QIODevice *io) { m_store = KoStore::createStore(io, KoStore::Read, "", KoStore::Zip); if (m_store->bad()) { m_doc->setErrorMessage(i18n("Not a valid Krita file")); return ImportExportCodes::FileFormatIncorrect; } bool success; { if (m_store->hasFile("root") || m_store->hasFile("maindoc.xml")) { // Fallback to "old" file format (maindoc.xml) KoXmlDocument doc; KisImportExportErrorCode res = oldLoadAndParse(m_store, "root", doc); if (res.isOk()) res = loadXML(doc, m_store); if (!res.isOk()) { return res; } } else { errUI << "ERROR: No maindoc.xml" << endl; m_doc->setErrorMessage(i18n("Invalid document: no file 'maindoc.xml'.")); return ImportExportCodes::FileFormatIncorrect; } if (m_store->hasFile("documentinfo.xml")) { KoXmlDocument doc; if (oldLoadAndParse(m_store, "documentinfo.xml", doc).isOk()) { m_doc->documentInfo()->load(doc); } } success = completeLoading(m_store); } return success ? ImportExportCodes::OK : ImportExportCodes::Failure; } KisImageSP KraConverter::image() { return m_image; } vKisNodeSP KraConverter::activeNodes() { return m_activeNodes; } QList KraConverter::assistants() { return m_assistants; } KisImportExportErrorCode KraConverter::buildFile(QIODevice *io, const QString &filename) { + setProgress(5); m_store = KoStore::createStore(io, KoStore::Write, m_doc->nativeFormatMimeType(), KoStore::Zip); if (m_store->bad()) { m_doc->setErrorMessage(i18n("Could not create the file for saving")); return ImportExportCodes::CannotCreateFile; } + setProgress(20); m_kraSaver = new KisKraSaver(m_doc, filename); KisImportExportErrorCode resultCode = saveRootDocuments(m_store); if (!resultCode.isOk()) { return resultCode; } + setProgress(40); bool result; result = m_kraSaver->saveKeyframes(m_store, m_doc->url().toLocalFile(), true); if (!result) { qWarning() << "saving key frames failed"; } + setProgress(60); result = m_kraSaver->saveBinaryData(m_store, m_image, m_doc->url().toLocalFile(), true, m_doc->isAutosaving()); if (!result) { qWarning() << "saving binary data failed"; } + setProgress(70); result = m_kraSaver->savePalettes(m_store, m_image, m_doc->url().toLocalFile()); if (!result) { qWarning() << "saving palettes data failed"; } + setProgress(80); if (!m_store->finalize()) { return ImportExportCodes::Failure; } if (!m_kraSaver->errorMessages().isEmpty()) { m_doc->setErrorMessage(m_kraSaver->errorMessages().join(".\n")); return ImportExportCodes::Failure; } + setProgress(90); return ImportExportCodes::OK; } KisImportExportErrorCode KraConverter::saveRootDocuments(KoStore *store) { dbgFile << "Saving root"; if (store->open("root")) { KoStoreDevice dev(store); if (!saveToStream(&dev) || !store->close()) { dbgUI << "saveToStream failed"; return ImportExportCodes::NoAccessToWrite; } } else { m_doc->setErrorMessage(i18n("Not able to write '%1'. Partition full?", QString("maindoc.xml"))); return ImportExportCodes::ErrorWhileWriting; } if (store->open("documentinfo.xml")) { QDomDocument doc = KisDocument::createDomDocument("document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1"); doc = m_doc->documentInfo()->save(doc); KoStoreDevice dev(store); QByteArray s = doc.toByteArray(); // this is already Utf8! bool success = dev.write(s.data(), s.size()); if (!success) { return ImportExportCodes::ErrorWhileWriting; } store->close(); } else { return ImportExportCodes::Failure; } if (store->open("preview.png")) { // ### TODO: missing error checking (The partition could be full!) KisImportExportErrorCode result = savePreview(store); (void)store->close(); if (!result.isOk()) { return result; } } else { return ImportExportCodes::Failure; } dbgUI << "Saving done of url:" << m_doc->url().toLocalFile(); return ImportExportCodes::OK; } bool KraConverter::saveToStream(QIODevice *dev) { QDomDocument doc = createDomDocument(); // Save to buffer QByteArray s = doc.toByteArray(); // utf8 already dev->open(QIODevice::WriteOnly); int nwritten = dev->write(s.data(), s.size()); if (nwritten != (int)s.size()) { warnUI << "wrote " << nwritten << "- expected" << s.size(); } return nwritten == (int)s.size(); } QDomDocument KraConverter::createDomDocument() { QDomDocument doc = m_doc->createDomDocument("DOC", CURRENT_DTD_VERSION); QDomElement root = doc.documentElement(); root.setAttribute("editor", "Krita"); root.setAttribute("syntaxVersion", "2"); root.setAttribute("kritaVersion", KritaVersionWrapper::versionString(false)); root.appendChild(m_kraSaver->saveXML(doc, m_image)); if (!m_kraSaver->errorMessages().isEmpty()) { m_doc->setErrorMessage(m_kraSaver->errorMessages().join(".\n")); } return doc; } KisImportExportErrorCode KraConverter::savePreview(KoStore *store) { QPixmap pix = m_doc->generatePreview(QSize(256, 256)); QImage preview(pix.toImage().convertToFormat(QImage::Format_ARGB32, Qt::ColorOnly)); if (preview.size() == QSize(0,0)) { QSize newSize = m_doc->savingImage()->bounds().size(); newSize.scale(QSize(256, 256), Qt::KeepAspectRatio); preview = QImage(newSize, QImage::Format_ARGB32); preview.fill(QColor(0, 0, 0, 0)); } KoStoreDevice io(store); if (!io.open(QIODevice::WriteOnly)) { return ImportExportCodes::NoAccessToWrite; } bool ret = preview.save(&io, "PNG"); io.close(); return ret ? ImportExportCodes::OK : ImportExportCodes::ErrorWhileWriting; } KisImportExportErrorCode KraConverter::oldLoadAndParse(KoStore *store, const QString &filename, KoXmlDocument &xmldoc) { //dbgUI <<"Trying to open" << filename; if (!store->open(filename)) { warnUI << "Entry " << filename << " not found!"; m_doc->setErrorMessage(i18n("Could not find %1", filename)); return ImportExportCodes::FileNotExist; } // Error variables for QDomDocument::setContent QString errorMsg; int errorLine, errorColumn; bool ok = xmldoc.setContent(store->device(), &errorMsg, &errorLine, &errorColumn); store->close(); if (!ok) { errUI << "Parsing error in " << filename << "! Aborting!" << endl << " In line: " << errorLine << ", column: " << errorColumn << endl << " Error message: " << errorMsg << endl; m_doc->setErrorMessage(i18n("Parsing error in %1 at line %2, column %3\nError message: %4", filename, errorLine, errorColumn, QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0))); return ImportExportCodes::FileFormatIncorrect; } dbgUI << "File" << filename << " loaded and parsed"; return ImportExportCodes::OK; } KisImportExportErrorCode KraConverter::loadXML(const KoXmlDocument &doc, KoStore *store) { Q_UNUSED(store); KoXmlElement root; KoXmlNode node; if (doc.doctype().name() != "DOC") { errUI << "The format is not supported or the file is corrupted"; m_doc->setErrorMessage(i18n("The format is not supported or the file is corrupted")); return ImportExportCodes::FileFormatIncorrect; } root = doc.documentElement(); int syntaxVersion = root.attribute("syntaxVersion", "3").toInt(); if (syntaxVersion > 2) { errUI << "The file is too new for this version of Krita: " + QString::number(syntaxVersion); m_doc->setErrorMessage(i18n("The file is too new for this version of Krita (%1).", syntaxVersion)); return ImportExportCodes::FormatFeaturesUnsupported; } if (!root.hasChildNodes()) { errUI << "The file has no layers."; m_doc->setErrorMessage(i18n("The file has no layers.")); return ImportExportCodes::FileFormatIncorrect; } m_kraLoader = new KisKraLoader(m_doc, syntaxVersion); // reset the old image before loading the next one m_doc->setCurrentImage(0, false); for (node = root.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isElement()) { if (node.nodeName() == "IMAGE") { KoXmlElement elem = node.toElement(); if (!(m_image = m_kraLoader->loadXML(elem))) { if (m_kraLoader->errorMessages().isEmpty()) { errUI << "Unknown error while opening the .kra file."; m_doc->setErrorMessage(i18n("Unknown error.")); } else { m_doc->setErrorMessage(m_kraLoader->errorMessages().join("\n")); errUI << m_kraLoader->errorMessages().join("\n"); } return ImportExportCodes::Failure; } // HACK ALERT! m_doc->hackPreliminarySetImage(m_image); return ImportExportCodes::OK; } else { if (m_kraLoader->errorMessages().isEmpty()) { m_doc->setErrorMessage(i18n("The file does not contain an image.")); } return ImportExportCodes::FileFormatIncorrect; } } } return ImportExportCodes::Failure; } bool KraConverter::completeLoading(KoStore* store) { if (!m_image) { if (m_kraLoader->errorMessages().isEmpty()) { m_doc->setErrorMessage(i18n("Unknown error.")); } else { m_doc->setErrorMessage(m_kraLoader->errorMessages().join("\n")); } return false; } m_image->blockUpdates(); QString layerPathName = m_kraLoader->imageName(); if (!m_store->hasDirectory(layerPathName)) { // We might be hitting an encoding problem. Get the only folder in the toplevel Q_FOREACH (const QString &entry, m_store->directoryList()) { if (entry.contains("/layers/")) { layerPathName = entry.split("/layers/").first(); m_store->setSubstitution(m_kraLoader->imageName(), layerPathName); break; } } } m_kraLoader->loadBinaryData(store, m_image, m_doc->localFilePath(), true); m_kraLoader->loadPalettes(store, m_doc); m_image->unblockUpdates(); if (!m_kraLoader->warningMessages().isEmpty()) { // warnings do not interrupt loading process, so we do not return here m_doc->setWarningMessage(m_kraLoader->warningMessages().join("\n")); } m_activeNodes = m_kraLoader->selectedNodes(); m_assistants = m_kraLoader->assistants(); return true; } void KraConverter::cancel() { m_stop = true; } +void KraConverter::setProgress(int progress) +{ + if (m_updater) { + m_updater->setProgress(progress); + } +} diff --git a/plugins/impex/kra/kra_converter.h b/plugins/impex/kra/kra_converter.h index 46a634e9d7..aa7eeff718 100644 --- a/plugins/impex/kra/kra_converter.h +++ b/plugins/impex/kra/kra_converter.h @@ -1,80 +1,88 @@ /* * Copyright (C) 2016 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KRA_CONVERTER_H_ #define _KRA_CONVERTER_H_ #include #include #include #include #include #include #include #include +#include +#include +#include + class KisDocument; class KraConverter : public QObject { Q_OBJECT public: KraConverter(KisDocument *doc); + KraConverter(KisDocument *doc, QPointer updater); ~KraConverter() override; KisImportExportErrorCode buildImage(QIODevice *io); KisImportExportErrorCode buildFile(QIODevice *io, const QString &filename); /** * Retrieve the constructed image */ KisImageSP image(); vKisNodeSP activeNodes(); QList assistants(); public Q_SLOTS: virtual void cancel(); private: KisImportExportErrorCode saveRootDocuments(KoStore *store); bool saveToStream(QIODevice *dev); QDomDocument createDomDocument(); KisImportExportErrorCode savePreview(KoStore *store); KisImportExportErrorCode oldLoadAndParse(KoStore *store, const QString &filename, KoXmlDocument &xmldoc); KisImportExportErrorCode loadXML(const KoXmlDocument &doc, KoStore *store); bool completeLoading(KoStore *store); + void setProgress(int progress); + KisDocument *m_doc {0}; KisImageSP m_image; vKisNodeSP m_activeNodes; QList m_assistants; bool m_stop {false}; KoStore *m_store {0}; KisKraSaver *m_kraSaver {0}; KisKraLoader *m_kraLoader {0}; + QPointer m_updater; }; #endif diff --git a/plugins/impex/kra/kra_export.cpp b/plugins/impex/kra/kra_export.cpp index 5db4f6535d..a8a9346c35 100644 --- a/plugins/impex/kra/kra_export.cpp +++ b/plugins/impex/kra/kra_export.cpp @@ -1,93 +1,93 @@ /* * Copyright (C) 2016 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kra_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kra_converter.h" class KisExternalLayer; K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_kra_export.json", registerPlugin();) KraExport::KraExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KraExport::~KraExport() { } KisImportExportErrorCode KraExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { KisImageSP image = document->savingImage(); KIS_ASSERT_RECOVER_RETURN_VALUE(image, ImportExportCodes::InternalError); - KraConverter kraConverter(document); + KraConverter kraConverter(document, updater()); KisImportExportErrorCode res = kraConverter.buildFile(io, filename()); dbgFile << "KraExport::convert result =" << res; return res; } void KraExport::initializeCapabilities() { // Kra supports everything, by definition KisExportCheckFactory *factory = 0; Q_FOREACH(const QString &id, KisExportCheckRegistry::instance()->keys()) { factory = KisExportCheckRegistry::instance()->get(id); addCapability(factory->create(KisExportCheckBase::SUPPORTED)); } } QString KraExport::verify(const QString &fileName) const { QString error = KisImportExportFilter::verify(fileName); if (error.isEmpty()) { return KisImportExportFilter::verifyZiPBasedFiles(fileName, QStringList() << "mimetype" << "documentinfo.xml" << "maindoc.xml" << "preview.png"); } return error; } #include