diff --git a/libs/ui/KisImportExportManager.cpp b/libs/ui/KisImportExportManager.cpp
index 909ec5d4b4..e3b8edb3f8 100644
--- a/libs/ui/KisImportExportManager.cpp
+++ b/libs/ui/KisImportExportManager.cpp
@@ -1,481 +1,495 @@
/*
* 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 "KisImportExportManager.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_config.h"
#include "KisImportExportFilter.h"
#include "KisDocument.h"
#include
#include
#include "kis_guides_config.h"
#include "kis_grid_config.h"
#include "kis_popup_button.h"
#include
// static cache for import and export mimetypes
QStringList KisImportExportManager::m_importMimeTypes;
QStringList KisImportExportManager::m_exportMimeTypes;
class Q_DECL_HIDDEN KisImportExportManager::Private
{
public:
bool batchMode {false};
QPointer progressUpdater {0};
};
KisImportExportManager::KisImportExportManager(KisDocument* document)
: m_document(document)
, d(new Private)
{
}
KisImportExportManager::~KisImportExportManager()
{
delete d;
}
KisImportExportFilter::ConversionStatus KisImportExportManager::importDocument(const QString& location, const QString& mimeType)
{
return convert(Import, location, location, mimeType, false, 0);
}
KisImportExportFilter::ConversionStatus KisImportExportManager::exportDocument(const QString& location, const QString& realLocation, QByteArray& mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
{
return convert(Export, location, realLocation, mimeType, showWarnings, exportConfiguration);
}
// The static method to figure out to which parts of the
// graph this mimetype has a connection to.
QStringList KisImportExportManager::mimeFilter(Direction direction)
{
// Find the right mimetype by the extension
QSet mimeTypes;
// mimeTypes << KisDocument::nativeFormatMimeType() << "application/x-krita-paintoppreset" << "image/openraster";
if (direction == KisImportExportManager::Import) {
if (m_importMimeTypes.isEmpty()) {
KoJsonTrader trader;
QListlist = trader.query("Krita/FileFilter", "");
Q_FOREACH(QPluginLoader *loader, list) {
QJsonObject json = loader->metaData().value("MetaData").toObject();
Q_FOREACH(const QString &mimetype, json.value("X-KDE-Import").toString().split(",", QString::SkipEmptyParts)) {
//qDebug() << "Adding import mimetype" << mimetype << KisMimeDatabase::descriptionForMimeType(mimetype) << "from plugin" << loader;
mimeTypes << mimetype;
}
}
qDeleteAll(list);
m_importMimeTypes = mimeTypes.toList();
}
return m_importMimeTypes;
}
else if (direction == KisImportExportManager::Export) {
if (m_exportMimeTypes.isEmpty()) {
KoJsonTrader trader;
QListlist = trader.query("Krita/FileFilter", "");
Q_FOREACH(QPluginLoader *loader, list) {
QJsonObject json = loader->metaData().value("MetaData").toObject();
Q_FOREACH(const QString &mimetype, json.value("X-KDE-Export").toString().split(",", QString::SkipEmptyParts)) {
//qDebug() << "Adding export mimetype" << mimetype << KisMimeDatabase::descriptionForMimeType(mimetype) << "from plugin" << loader;
mimeTypes << mimetype;
}
}
qDeleteAll(list);
m_exportMimeTypes = mimeTypes.toList();
}
return m_exportMimeTypes;
}
return QStringList();
}
KisImportExportFilter *KisImportExportManager::filterForMimeType(const QString &mimetype, KisImportExportManager::Direction direction)
{
int weight = -1;
KisImportExportFilter *filter = 0;
QListlist = KoJsonTrader::instance()->query("Krita/FileFilter", "");
Q_FOREACH(QPluginLoader *loader, list) {
QJsonObject json = loader->metaData().value("MetaData").toObject();
QString directionKey = direction == Export ? "X-KDE-Export" : "X-KDE-Import";
if (json.value(directionKey).toString().split(",", QString::SkipEmptyParts).contains(mimetype)) {
KLibFactory *factory = qobject_cast(loader->instance());
if (!factory) {
warnUI << loader->errorString();
continue;
}
QObject* obj = factory->create(0);
if (!obj || !obj->inherits("KisImportExportFilter")) {
delete obj;
continue;
}
KisImportExportFilter *f = qobject_cast(obj);
if (!f) {
delete obj;
continue;
}
int w = json.value("X-KDE-Weight").toInt();
if (w > weight) {
delete filter;
filter = f;
f->setObjectName(loader->fileName());
weight = w;
}
}
}
qDeleteAll(list);
if (filter) {
filter->setMimeType(mimetype);
}
return filter;
}
void KisImportExportManager::setBatchMode(const bool batch)
{
d->batchMode = batch;
}
bool KisImportExportManager::batchMode(void) const
{
return d->batchMode;
}
void KisImportExportManager::setProgresUpdater(KoProgressUpdater *updater)
{
d->progressUpdater = updater;
}
QString KisImportExportManager::askForAudioFileName(const QString &defaultDir, QWidget *parent)
{
KoFileDialog dialog(parent, KoFileDialog::ImportFiles, "ImportAudio");
if (!defaultDir.isEmpty()) {
dialog.setDefaultDir(defaultDir);
}
QStringList mimeTypes;
mimeTypes << "audio/mpeg";
mimeTypes << "audio/ogg";
mimeTypes << "audio/vorbis";
mimeTypes << "audio/vnd.wave";
mimeTypes << "audio/flac";
dialog.setMimeTypeFilters(mimeTypes);
dialog.setCaption(i18nc("@titile:window", "Open Audio"));
return dialog.filename();
}
KisImportExportFilter::ConversionStatus KisImportExportManager::convert(KisImportExportManager::Direction direction, const QString &location, const QString& realLocation, const QString &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
{
QString typeName = mimeType;
if (typeName.isEmpty()) {
typeName = KisMimeDatabase::mimeTypeForFile(location);
}
QSharedPointer filter(filterForMimeType(typeName, direction));
if (!filter) {
return KisImportExportFilter::FilterCreationError;
}
filter->setFilename(location);
filter->setRealFilename(realLocation);
filter->setBatchMode(batchMode());
filter->setMimeType(typeName);
if (d->progressUpdater) {
filter->setUpdater(d->progressUpdater->startSubtask());
}
QByteArray from, to;
if (direction == Export) {
from = m_document->nativeFormatMimeType();
to = mimeType.toLatin1();
}
else {
from = mimeType.toLatin1();
to = m_document->nativeFormatMimeType();
}
if (!exportConfiguration) {
exportConfiguration = filter->lastSavedConfiguration(from, to);
if (exportConfiguration) {
// Fill with some meta information about the image
KisImageWSP image = m_document->image();
KisPaintDeviceSP pd = image->projection();
bool isThereAlpha = false;
KisSequentialConstIterator it(pd, image->bounds());
const KoColorSpace* cs = pd->colorSpace();
do {
if (cs->opacityU8(it.oldRawData()) != OPACITY_OPAQUE_U8) {
isThereAlpha = true;
break;
}
} while (it.nextPixel());
exportConfiguration->setProperty("ImageContainsTransparency", isThereAlpha);
exportConfiguration->setProperty("ColorModelID", cs->colorModelId().id());
exportConfiguration->setProperty("ColorDepthID", cs->colorDepthId().id());
bool sRGB = (cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive) && !cs->profile()->name().contains(QLatin1String("g10")));
exportConfiguration->setProperty("sRGB", sRGB);
}
}
QStringList warnings;
QStringList errors;
if (direction == Export) {
KisPreExportChecker checker;
checker.check(m_document->image(), filter->exportChecks());
warnings = checker.warnings();
errors = checker.errors();
}
KisConfigWidget *wdg = filter->createConfigurationWidget(0, from, to);
bool alsoAsKra = false;
// Extra checks that cannot be done by the checker, because the checker only has access to the image.
if (!m_document->assistants().isEmpty() && typeName != m_document->nativeFormatMimeType()) {
warnings.append(i18nc("image conversion warning", "The image contains assistants. The assistants will not be saved."));
}
if (m_document->guidesConfig().hasGuides() && typeName != m_document->nativeFormatMimeType()) {
warnings.append(i18nc("image conversion warning", "The image contains guides. The guides will not be saved."));
}
if (!m_document->gridConfig().isDefault() && typeName != m_document->nativeFormatMimeType()) {
warnings.append(i18nc("image conversion warning", "The image contains a custom grid configuration. The configuration will not be saved."));
}
if (!batchMode() && !errors.isEmpty()) {
QString error = ""
+ i18n("Error: cannot save this image as a %1.", KisMimeDatabase::descriptionForMimeType(typeName))
+ " Reasons:
"
+ "";
Q_FOREACH(const QString &w, errors) {
error += "\n- " + w + "
";
}
error += "
";
QMessageBox::critical(KisPart::instance()->currentMainwindow(), i18nc("@title:window", "Krita: Export Error"), error);
return KisImportExportFilter::UserCancelled;
}
if (!batchMode() && (wdg || !warnings.isEmpty())) {
KoDialog dlg;
dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
dlg.setWindowTitle(KisMimeDatabase::descriptionForMimeType(mimeType));
QWidget *page = new QWidget(&dlg);
QVBoxLayout *layout = new QVBoxLayout(page);
if (!warnings.isEmpty()) {
if (showWarnings) {
QHBoxLayout *hLayout = new QHBoxLayout();
QLabel *labelWarning = new QLabel();
labelWarning->setPixmap(KisIconUtils::loadIcon("dialog-warning").pixmap(32, 32));
hLayout->addWidget(labelWarning);
KisPopupButton *bn = new KisPopupButton(0);
bn->setText(i18nc("Keep the extra space at the end of the sentence, please", "Warning: saving as %1 will lose information from your image. ", KisMimeDatabase::descriptionForMimeType(mimeType)));
hLayout->addWidget(bn);
layout->addLayout(hLayout);
QTextBrowser *browser = new QTextBrowser();
browser->setMinimumWidth(bn->width());
bn->setPopupWidget(browser);
QString warning = ""
+ i18n("You will lose information when saving this image as a %1.", KisMimeDatabase::descriptionForMimeType(typeName));
if (warnings.size() == 1) {
warning += " Reason:
";
}
else {
warning += " Reasons:
";
}
warning += "";
Q_FOREACH(const QString &w, warnings) {
warning += "\n- " + w + "
";
}
warning += "
";
browser->setHtml(warning);
}
}
if (wdg) {
QGroupBox *box = new QGroupBox(i18n("Options"));
QVBoxLayout *boxLayout = new QVBoxLayout(box);
wdg->setConfiguration(exportConfiguration);
boxLayout->addWidget(wdg);
layout->addWidget(box);
}
QCheckBox *chkAlsoAsKra = 0;
if (showWarnings && !warnings.isEmpty()) {
chkAlsoAsKra = new QCheckBox(i18n("Also save your image as a Krita file."));
chkAlsoAsKra->setChecked(KisConfig().readEntry("AlsoSaveAsKra", false));
layout->addWidget(chkAlsoAsKra);
}
dlg.setMainWidget(page);
dlg.resize(dlg.minimumSize());
if (showWarnings || wdg) {
if (!dlg.exec()) {
return KisImportExportFilter::UserCancelled;
}
}
if (chkAlsoAsKra) {
KisConfig().writeEntry("AlsoSaveAsKra", chkAlsoAsKra->isChecked());
alsoAsKra = chkAlsoAsKra->isChecked();
}
if (wdg) {
exportConfiguration = wdg->configuration();
}
}
- QFile io(location);
- QSaveFile out(location);
+ KIS_ASSERT_RECOVER_RETURN_VALUE(
+ direction == Import || direction == Export,
+ KisImportExportFilter::BadConversionGraph);
+ if (!batchMode()) {
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ }
+
+ KisImportExportFilter::ConversionStatus status = KisImportExportFilter::OK;
if (direction == Import) {
- if (!io.exists()) {
- return KisImportExportFilter::FileNotFound;
- }
+ status = doImport(location, filter);
+ } else /* if (direction == Export) */ {
+ status = doExport(location, filter, exportConfiguration);
- if (!io.open(QFile::ReadOnly) ) {
- return KisImportExportFilter::FileNotFound;
- }
- }
- else if (direction == Export) {
- if (filter->supportsIO()) {
- out.setDirectWriteFallback(true);
- if (!out.open(QFile::WriteOnly)) {
- out.cancelWriting();
- return KisImportExportFilter::CreationError;
+ if (alsoAsKra && status == KisImportExportFilter::OK) {
+ QString kraLocation = location + ".kra";
+ QByteArray mime = m_document->nativeFormatMimeType();
+ QSharedPointer filter(
+ filterForMimeType(QString::fromLatin1(mime), Export));
+
+ KIS_SAFE_ASSERT_RECOVER_NOOP(filter);
+
+ if (filter) {
+ filter->setFilename(kraLocation);
+
+ KisPropertiesConfigurationSP kraExportConfiguration =
+ filter->lastSavedConfiguration(mime, mime);
+
+ status = doExport(kraLocation, filter, kraExportConfiguration);
+ } else {
+ status = KisImportExportFilter::FilterCreationError;
}
}
}
- else {
- return KisImportExportFilter::BadConversionGraph;
+
+ if (exportConfiguration) {
+ KisConfig().setExportConfiguration(typeName, exportConfiguration);
}
if (!batchMode()) {
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QApplication::restoreOverrideCursor();
}
- KisImportExportFilter::ConversionStatus status;
- if (direction == Import || !filter->supportsIO()) {
- status = filter->convert(m_document, &io, exportConfiguration);
- if (io.isOpen()) io.close();
+ return status;
+
+}
+
+KisImportExportFilter::ConversionStatus KisImportExportManager::doImport(const QString &location, QSharedPointer filter)
+{
+ QFile file(location);
+ if (!file.exists()) {
+ return KisImportExportFilter::FileNotFound;
}
- else {
- status = filter->convert(m_document, &out, exportConfiguration);
- if (status != KisImportExportFilter::OK) {
- out.cancelWriting();
- }
- else {
- out.commit();
- }
+
+ if (filter->supportsIO() && !file.open(QFile::ReadOnly)) {
+ return KisImportExportFilter::FileNotFound;
}
- if (exportConfiguration) {
- KisConfig().setExportConfiguration(typeName, exportConfiguration);
+ KisImportExportFilter::ConversionStatus status =
+ filter->convert(m_document, &file, KisPropertiesConfigurationSP());
+
+ if (file.isOpen()) {
+ file.close();
}
- if (alsoAsKra) {
- QString l = location + ".kra";
- QByteArray ba = m_document->nativeFormatMimeType();
- KisImportExportFilter *filter = filterForMimeType(QString::fromLatin1(ba), Export);
- QSaveFile f(l);
- f.open(QIODevice::WriteOnly);
- if (filter) {
- filter->setFilename(l);
- if (filter->convert(m_document, &f) == KisImportExportFilter::OK) {
- f.commit();
- }
- else {
- f.cancelWriting();
- }
- }
- delete filter;
+ return status;
+}
+
+KisImportExportFilter::ConversionStatus KisImportExportManager::doExport(const QString &location, QSharedPointer filter, KisPropertiesConfigurationSP exportConfiguration)
+{
+ QSaveFile file(location);
+ file.setDirectWriteFallback(true);
+ if (filter->supportsIO() && !file.open(QFile::WriteOnly)) {
+ file.cancelWriting();
+ return KisImportExportFilter::CreationError;
}
- if (!batchMode()) {
- QApplication::restoreOverrideCursor();
+ KisImportExportFilter::ConversionStatus status =
+ filter->convert(m_document, &file, exportConfiguration);
+
+ if (status != KisImportExportFilter::OK) {
+ file.cancelWriting();
+ } else {
+ file.commit();
}
return status;
-
}
-
#include
diff --git a/libs/ui/KisImportExportManager.h b/libs/ui/KisImportExportManager.h
index bd07d42ad7..c9f53d9eb5 100644
--- a/libs/ui/KisImportExportManager.h
+++ b/libs/ui/KisImportExportManager.h
@@ -1,146 +1,149 @@
/*
* 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 KIS_IMPORT_EXPORT_MANAGER_H
#define KIS_IMPORT_EXPORT_MANAGER_H
#include
#include
#include
#include
#include "KisImportExportFilter.h"
#include "kritaui_export.h"
class KisDocument;
class KoProgressUpdater;
/**
* @brief The class managing all the filters.
*
* This class manages all filters for a %Calligra application. Normally
* you will not have to use it, since KisMainWindow takes care of loading
* and saving documents.
*
* @ref KisFilter
*
* @author Kalle Dalheimer
* @author Torben Weis
* @author Werner Trobin
*/
class KRITAUI_EXPORT KisImportExportManager : public QObject
{
Q_OBJECT
public:
/**
* This enum is used to distinguish the import/export cases
*/
enum Direction { Import = 1, Export = 2 };
/**
* Create a filter manager for a document
*/
explicit KisImportExportManager(KisDocument *document);
public:
virtual ~KisImportExportManager();
/**
* Imports the specified document and returns the resultant filename
* (most likely some file in /tmp).
* @p path can be either a URL or a filename.
* @p documentMimeType gives importDocument a hint about what type
* the document may be. It can be left empty.
*
* @return status signals the success/error of the conversion.
* If the QString which is returned isEmpty() and the status is OK,
* then we imported the file directly into the document.
*/
KisImportExportFilter::ConversionStatus importDocument(const QString &location, const QString &mimeType);
/**
* @brief Exports the given file/document to the specified URL/mimetype.
*
* If @p mimeType is empty, then the closest matching Calligra part is searched
* and when the method returns @p mimeType contains this mimetype.
* Oh, well, export is a C++ keyword ;)
*/
KisImportExportFilter::ConversionStatus exportDocument(const QString &location, const QString& realLocation, QByteArray &mimeType, bool showWarnings = true, KisPropertiesConfigurationSP exportConfiguration = 0);
///@name Static API
//@{
/**
* Suitable for passing to KoFileDialog::setMimeTypeFilters. The default mime
* gets set by the "users" of this method, as we do not have enough
* information here.
* Optionally, @p extraNativeMimeTypes are added after the native mimetype.
*/
static QStringList mimeFilter(Direction direction);
/**
* @brief filterForMimeType loads the relevant import/export plugin and returns it. The caller
* is responsible for deleting it!
* @param mimetype the mimetype we want to import/export. If there's more than one plugin, the one
* with the highest weight as defined in the json description will be taken
* @param direction import or export
* @return a pointer to the filter plugin or 0 if none could be found
*/
static KisImportExportFilter *filterForMimeType(const QString &mimetype, Direction direction);
/**
* Set the filter manager is batch mode (no dialog shown)
* instead of the interactive mode (dialog shown)
*/
void setBatchMode(const bool batch);
/**
* Get if the filter manager is batch mode (true)
* or in interactive mode (true)
*/
bool batchMode(void) const;
void setProgresUpdater(KoProgressUpdater *updater);
static QString askForAudioFileName(const QString &defaultDir, QWidget *parent);
private Q_SLOTS:
private:
KisImportExportFilter::ConversionStatus convert(Direction direction, const QString &location, const QString& realLocation, const QString &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration);
+ KisImportExportFilter::ConversionStatus doImport(const QString &location, QSharedPointer filter);
+ KisImportExportFilter::ConversionStatus doExport(const QString &location, QSharedPointer filter, KisPropertiesConfigurationSP exportConfiguration);
+
// Private API
KisImportExportManager(const KisImportExportManager& rhs);
KisImportExportManager &operator=(const KisImportExportManager& rhs);
KisDocument *m_document;
/// A static cache for the availability checks of filters
static QStringList m_importMimeTypes;
static QStringList m_exportMimeTypes;
class Private;
Private * const d;
};
#endif // __KO_FILTER_MANAGER_H__