[krita] /: Use QuaZip instead of KArchive for ZIP64 support

Boudewijn Rempt null at kde.org
Wed Jan 23 08:30:24 GMT 2019


Git commit 593dba2b7098049092072a4260005996b34a8a56 by Boudewijn Rempt.
Committed on 23/01/2019 at 08:29.
Pushed by rempt into branch 'master'.

Use QuaZip instead of KArchive for ZIP64 support

This makes it possible to save and load .kra files that are larger
than 4GiB -- depending on available memory, of course. There is
an option in the settings dialog to enable this; it's off by default
because older versions of Krita cannot read Zip64 files.

Note that everything that uses zip files now uses quazip, the
karchive dependency is gone.

CCMAIL:kimageshop at kde.org

M  +1    -0    3rdparty/CMakeLists.txt
M  +0    -18   3rdparty/ext_frameworks/CMakeLists.txt
D  +0    -39   3rdparty/ext_frameworks/karchive.diff
A  +12   -0    3rdparty/ext_quazip/CMakeLists.txt
A  +10   -0    3rdparty/ext_quazip/find_quazip.diff
M  +14   -1    CMakeLists.txt
A  +43   -0    cmake/modules/FindQuaZip.cmake
M  +12   -2    libs/store/CMakeLists.txt
A  +260  -0    libs/store/KoQuaZipStore.cpp     [License: LGPL (v2+)]
A  +62   -0    libs/store/KoQuaZipStore.h     [License: LGPL (v2+)]
M  +3    -12   libs/store/KoStore.cpp
M  +0    -25   libs/store/KoStore.h
M  +1    -5    libs/store/KoStore_p.h
D  +0    -257  libs/store/KoZipStore.cpp
M  +1    -6    libs/store/KoZipStore.h
M  +1    -0    libs/ui/KisImportExportManager.cpp
M  +1    -1    libs/ui/KisWelcomePageWidget.cpp
M  +8    -0    libs/ui/dialogs/kis_dlg_preferences.cc
M  +1    -0    libs/ui/dialogs/kis_dlg_preferences.h
M  +21   -11   libs/ui/forms/wdggeneralsettings.ui
M  +10   -0    libs/ui/kis_config.cc
M  +2    -0    libs/ui/kis_config.h
M  +2    -2    plugins/impex/kra/kra_export.cpp

https://commits.kde.org/krita/593dba2b7098049092072a4260005996b34a8a56

diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
index c992e5fade0..81127ae7e42 100644
--- a/3rdparty/CMakeLists.txt
+++ b/3rdparty/CMakeLists.txt
@@ -208,3 +208,4 @@ if (NOT APPLE)
 endif ()
 
 add_subdirectory(ext_giflib)
+add_subdirectory(ext_quazip)
diff --git a/3rdparty/ext_frameworks/CMakeLists.txt b/3rdparty/ext_frameworks/CMakeLists.txt
index 5e5354204e2..1e9346574ab 100644
--- a/3rdparty/ext_frameworks/CMakeLists.txt
+++ b/3rdparty/ext_frameworks/CMakeLists.txt
@@ -2,7 +2,6 @@ SET(EXTPREFIX_frameworks "${EXTPREFIX}" )
 #
 # All needed frameworks:
 #
-#        Archive 
 #        Config 
 #        WidgetsAddons 
 #        Completion
@@ -31,23 +30,6 @@ ExternalProject_Add(
 )
 
 
-ExternalProject_Add(
-    ext_karchive
-    DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
-    URL http://download.kde.org/stable/frameworks/5.44/karchive-5.44.0.zip
-    URL_MD5 c60a8e22b88cc7328610041638459689
-    PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/karchive.diff
-    INSTALL_DIR ${EXTPREFIX_frameworks}
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTPREFIX_frameworks}
-               -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} 
-                ${GLOBAL_PROFILE}
-                -DCMAKE_SYSTEM_PREFIX_PATH=${EXTPREFIX} 
-                -DBUILD_TESTING=false
-    UPDATE_COMMAND ""
-    DEPENDS ext_extra_cmake_modules
-)
-
-
 ExternalProject_Add(
     ext_kconfig
     DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
diff --git a/3rdparty/ext_frameworks/karchive.diff b/3rdparty/ext_frameworks/karchive.diff
deleted file mode 100644
index 909d6beb591..00000000000
--- a/3rdparty/ext_frameworks/karchive.diff
+++ /dev/null
@@ -1,39 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 2441977..2a20a13 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -29,20 +29,20 @@ set_package_properties(ZLIB PROPERTIES
-     PURPOSE "Required by the core KDE libraries and some critical kioslaves"
- )
- 
--find_package(BZip2)
--set_package_properties(BZip2 PROPERTIES
--    URL "http://www.bzip.org"
--    DESCRIPTION "Support for BZip2 compressed files and data streams"
--    TYPE RECOMMENDED
--    PURPOSE "Support for BZip2 compressed files and data streams"
--)
--
--find_package(LibLZMA)
--set_package_properties(LibLZMA PROPERTIES
--    URL "http://tukaani.org/xz/"
--    DESCRIPTION "Support for xz compressed files and data streams"
--    PURPOSE "Support for xz compressed files and data streams"
--)
-+#find_package(BZip2)
-+#set_package_properties(BZip2 PROPERTIES
-+#    URL "http://www.bzip.org"
-+#    DESCRIPTION "Support for BZip2 compressed files and data streams"
-+#    TYPE RECOMMENDED
-+#    PURPOSE "Support for BZip2 compressed files and data streams"
-+#)
-+
-+#find_package(LibLZMA)
-+#set_package_properties(LibLZMA PROPERTIES
-+#    URL "http://tukaani.org/xz/"
-+#    DESCRIPTION "Support for xz compressed files and data streams"
-+#    PURPOSE "Support for xz compressed files and data streams"
-+#)
- include_directories(
-     ${ZLIB_INCLUDE_DIR}
- )
diff --git a/3rdparty/ext_quazip/CMakeLists.txt b/3rdparty/ext_quazip/CMakeLists.txt
new file mode 100644
index 00000000000..5819b107c4c
--- /dev/null
+++ b/3rdparty/ext_quazip/CMakeLists.txt
@@ -0,0 +1,12 @@
+SET(PREFIX_ext_quazip "${EXTPREFIX}" )
+ExternalProject_Add( ext_quazip
+    DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
+    URL https://github.com/stachenov/quazip/archive/0.7.6.zip
+    URL_MD5 a3335649c34053385d8390dd1a6f1ca4
+    PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/find_quazip.diff
+    INSTALL_DIR ${PREFIX_ext_quazip}
+    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_quazip} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} 
+    
+    UPDATE_COMMAND ""
+    DEPENDS ext_zlib ext_qt
+)
diff --git a/3rdparty/ext_quazip/find_quazip.diff b/3rdparty/ext_quazip/find_quazip.diff
new file mode 100644
index 00000000000..a5fb1a5291d
--- /dev/null
+++ b/3rdparty/ext_quazip/find_quazip.diff
@@ -0,0 +1,10 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 3d2fb55..5d8a5cc 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -60,4 +60,4 @@ set(QUAZIP_LIB_TARGET_NAME quazip${QUAZIP_LIB_VERSION_SUFFIX} CACHE
+ 
+ add_subdirectory(quazip)
+ 
+-install(FILES FindQuaZip.cmake RENAME FindQuaZip${QUAZIP_LIB_VERSION_SUFFIX}.cmake DESTINATION ${CMAKE_ROOT}/Modules)
++#install(FILES FindQuaZip.cmake RENAME FindQuaZip${QUAZIP_LIB_VERSION_SUFFIX}.cmake DESTINATION ${CMAKE_ROOT}/Modules)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f17a07e0eda..f32061cd9fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -275,7 +275,6 @@ include(KDECompilerSettings)
 # do not reorder to be alphabetical: this is the order in which the frameworks
 # depend on each other.
 find_package(KF5 ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS
-        Archive
         Config
         WidgetsAddons
         Completion
@@ -700,6 +699,20 @@ set_package_properties(Poppler PROPERTIES
     TYPE OPTIONAL
     PURPOSE "Required by the Krita PDF filter.")
 
+
+##
+## Test for quazip
+## 
+find_package(QuaZip 0.7)
+set_package_properties(QuaZip PROPERTIES
+    DESCRIPTION "A library for reading and writing zip files"
+    URL "https://stachenov.github.io/quazip/"
+    TYPE REQUIRED
+    PURPOSE "Needed for reading and writing KRA and ORA files"
+)
+
+
+
 ##
 ## Test for Atomics
 ##
diff --git a/cmake/modules/FindQuaZip.cmake b/cmake/modules/FindQuaZip.cmake
new file mode 100644
index 00000000000..23f4918db4f
--- /dev/null
+++ b/cmake/modules/FindQuaZip.cmake
@@ -0,0 +1,43 @@
+# QUAZIP_FOUND               - QuaZip library was found
+# QUAZIP_INCLUDE_DIR         - Path to QuaZip include dir
+# QUAZIP_INCLUDE_DIRS        - Path to QuaZip and zlib include dir (combined from QUAZIP_INCLUDE_DIR + ZLIB_INCLUDE_DIR)
+# QUAZIP_LIBRARIES           - List of QuaZip libraries
+# QUAZIP_ZLIB_INCLUDE_DIR    - The include dir of zlib headers
+
+
+IF (QUAZIP_INCLUDE_DIRS AND QUAZIP_LIBRARIES)
+	# in cache already
+	SET(QUAZIP_FOUND TRUE)
+ELSE (QUAZIP_INCLUDE_DIRS AND QUAZIP_LIBRARIES)
+    IF (Qt5Core_FOUND)
+        set(QUAZIP_LIB_VERSION_SUFFIX 5)
+    ENDIF()
+	IF (WIN32)
+		FIND_PATH(QUAZIP_LIBRARY_DIR
+			WIN32_DEBUG_POSTFIX d
+            NAMES libquazip${QUAZIP_LIB_VERSION_SUFFIX}.dll
+			HINTS "C:/Programme/" "C:/Program Files"
+			PATH_SUFFIXES QuaZip/lib
+		)
+        FIND_LIBRARY(QUAZIP_LIBRARIES NAMES libquazip${QUAZIP_LIB_VERSION_SUFFIX}.dll HINTS ${QUAZIP_LIBRARY_DIR})
+		FIND_PATH(QUAZIP_INCLUDE_DIR NAMES quazip.h HINTS ${QUAZIP_LIBRARY_DIR}/../ PATH_SUFFIXES include/quazip)
+		FIND_PATH(QUAZIP_ZLIB_INCLUDE_DIR NAMES zlib.h)
+	ELSE(WIN32)
+		FIND_PACKAGE(PkgConfig)
+#     pkg_check_modules(PC_QCA2 QUIET qca2)
+		pkg_check_modules(PC_QUAZIP quazip)
+		FIND_LIBRARY(QUAZIP_LIBRARIES
+			WIN32_DEBUG_POSTFIX d
+            NAMES quazip${QUAZIP_LIB_VERSION_SUFFIX}
+			HINTS /usr/lib /usr/lib64
+		)
+		FIND_PATH(QUAZIP_INCLUDE_DIR quazip.h
+			HINTS /usr/include /usr/local/include
+			PATH_SUFFIXES quazip${QUAZIP_LIB_VERSION_SUFFIX}
+		)
+		FIND_PATH(QUAZIP_ZLIB_INCLUDE_DIR zlib.h HINTS /usr/include /usr/local/include)
+	ENDIF (WIN32)
+	INCLUDE(FindPackageHandleStandardArgs)
+	SET(QUAZIP_INCLUDE_DIRS ${QUAZIP_INCLUDE_DIR} ${QUAZIP_ZLIB_INCLUDE_DIR})
+	find_package_handle_standard_args(QUAZIP DEFAULT_MSG  QUAZIP_LIBRARIES QUAZIP_INCLUDE_DIR QUAZIP_ZLIB_INCLUDE_DIR QUAZIP_INCLUDE_DIRS)
+ENDIF (QUAZIP_INCLUDE_DIRS AND QUAZIP_LIBRARIES)
diff --git a/libs/store/CMakeLists.txt b/libs/store/CMakeLists.txt
index 719fe00a796..b7c42996bdb 100644
--- a/libs/store/CMakeLists.txt
+++ b/libs/store/CMakeLists.txt
@@ -1,3 +1,5 @@
+include_directories(${QUAZIP_INCLUDE_DIRS})
+
 add_subdirectory(tests)
 
 set(kritastore_LIB_SRCS
@@ -8,14 +10,22 @@ set(kritastore_LIB_SRCS
     KoXmlNS.cpp
     KoXmlReader.cpp
     KoXmlWriter.cpp
-    KoZipStore.cpp
+    KoQuaZipStore.cpp
     StoreDebug.cpp
 )
 
 add_library(kritastore SHARED ${kritastore_LIB_SRCS})
 generate_export_header(kritastore BASE_NAME kritastore)
 
-target_link_libraries(kritastore kritaversion kritaglobal Qt5::Xml Qt5::Gui KF5::Archive)
+target_link_libraries(kritastore 
+    PRIVATE
+        kritaversion 
+        kritaglobal 
+        KF5::ConfigCore
+        Qt5::Xml 
+        Qt5::Gui 
+        ${QUAZIP_LIBRARIES}
+)
 
 set_target_properties(kritastore PROPERTIES
     VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
diff --git a/libs/store/KoQuaZipStore.cpp b/libs/store/KoQuaZipStore.cpp
new file mode 100644
index 00000000000..a48e9d81874
--- /dev/null
+++ b/libs/store/KoQuaZipStore.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2019 Boudewijn Rempt <boud at valdyas.org>
+ *
+ * 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 "KoQuaZipStore.h"
+#include "KoStore_p.h"
+
+#include <StoreDebug.h>
+
+#include <zlib.h>
+#include <quazip.h>
+#include <quazipfile.h>
+#include <quazipdir.h>
+#include <quazipfileinfo.h>
+#include <quazipnewinfo.h>
+
+#include <QTemporaryFile>
+#include <QTextCodec>
+
+#include <KConfig>
+#include <KSharedConfig>
+#include <KConfigGroup>
+
+struct KoQuaZipStore::Private {
+
+    Private() {}
+    ~Private() {}
+
+    QuaZip *archive {0};
+    QuaZipFile *currentFile {0};
+    int compressionLevel {Z_DEFAULT_COMPRESSION};
+    bool usingSaveFile {false};
+};
+
+
+KoQuaZipStore::KoQuaZipStore(const QString &_filename, KoStore::Mode _mode, const QByteArray &appIdentification, bool writeMimetype)
+    : KoStore(_mode, writeMimetype)
+    , dd(new Private())
+{
+    Q_D(KoStore);
+    d->localFileName = _filename;
+    dd->archive = new QuaZip(_filename);
+    init(appIdentification);
+
+}
+
+KoQuaZipStore::KoQuaZipStore(QIODevice *dev, KoStore::Mode _mode, const QByteArray &appIdentification, bool writeMimetype)
+    : KoStore(_mode, writeMimetype)
+    , dd(new Private())
+{
+    Q_D(KoStore);
+    dd->archive = new QuaZip(dev);
+    init(appIdentification);
+}
+
+KoQuaZipStore::~KoQuaZipStore()
+{
+    Q_D(KoStore);
+
+    if (dd->currentFile && dd->currentFile->isOpen()) {
+        dd->currentFile->close();
+    }
+
+    if (!d->finalized) {
+        finalize();
+    }
+
+    delete dd->archive;
+    delete dd->currentFile;
+}
+
+void KoQuaZipStore::setCompressionEnabled(bool enabled)
+{
+
+    if (enabled) {
+        dd->compressionLevel = Z_BEST_COMPRESSION;
+    }
+    else {
+        dd->compressionLevel = Z_NO_COMPRESSION;
+    }
+}
+
+qint64 KoQuaZipStore::write(const char *_data, qint64 _len)
+{
+    Q_D(KoStore);
+    if (_len == 0) return 0;
+
+    if (!d->isOpen) {
+        errorStore << "KoStore: You must open before writing" << endl;
+        return 0;
+    }
+
+    if (d->mode != Write) {
+        errorStore << "KoStore: Can not write to store that is opened for reading" << endl;
+        return 0;
+    }
+
+    d->size += _len;
+    if (dd->currentFile->write(_data, _len)) {    // writeData returns a bool!
+        return _len;
+    }
+    return 0;
+}
+
+QStringList KoQuaZipStore::directoryList() const
+{
+    return dd->archive->getFileNameList();
+}
+
+void KoQuaZipStore::init(const QByteArray &appIdentification)
+{
+    Q_D(KoStore);
+
+    bool enableZip64 = false;
+    if (appIdentification == "application/x-krita") {
+        enableZip64 = KSharedConfig::openConfig()->group("").readEntry<bool>("UseZip64", false);
+    }
+    dd->archive->setZip64Enabled(enableZip64);
+    dd->archive->setFileNameCodec("UTF-8");
+    dd->usingSaveFile = dd->archive->getIoDevice() && dd->archive->getIoDevice()->inherits("QSaveFile");
+    dd->archive->setAutoClose(!dd->usingSaveFile);
+
+    d->good = dd->archive->open(d->mode == Write ? QuaZip::mdCreate : QuaZip::mdUnzip);
+
+    if (!d->good) {
+        return;
+    }
+
+    if (d->mode == Write) {
+        if (d->writeMimetype) {
+            QuaZipFile f(dd->archive);
+            QuaZipNewInfo newInfo("mimetype");
+            newInfo.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther);
+            if (!f.open(QIODevice::WriteOnly, newInfo, 0, 0, Z_DEFLATED, Z_NO_COMPRESSION)) {
+                d->good = false;
+                return;
+            }
+            f.write(appIdentification);
+            f.close();
+        }
+    }
+    else {
+        d->good = dd->archive->getEntriesCount();
+    }
+}
+
+bool KoQuaZipStore::doFinalize()
+{
+    Q_D(KoStore);
+
+    d->stream = 0;
+    if (!dd->usingSaveFile) {
+        dd->archive->close();
+    }
+    return dd->archive->getZipError() == ZIP_OK;
+
+}
+
+bool KoQuaZipStore::openWrite(const QString &name)
+{
+    Q_D(KoStore);
+    QString fixedPath = name;
+    fixedPath.replace("//", "/");
+
+    delete d->stream;
+    d->stream = 0; // Not used when writing
+
+    delete dd->currentFile;
+    dd->currentFile = new QuaZipFile(dd->archive);
+    QuaZipNewInfo newInfo(fixedPath);
+    newInfo.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther);
+    bool r = dd->currentFile->open(QIODevice::WriteOnly, newInfo, 0, 0, Z_DEFLATED, dd->compressionLevel);
+    if (!r) {
+        qWarning() << "Could not open" << name << dd->currentFile->getZipError();
+    }
+    return r;
+}
+
+bool KoQuaZipStore::openRead(const QString &name)
+{
+    Q_D(KoStore);
+    QString fixedPath = name;
+    fixedPath.replace("//", "/");
+
+    delete d->stream;
+    d->stream = 0;
+    delete dd->currentFile;
+    dd->currentFile = 0;
+
+    if (!currentPath().isEmpty() && !fixedPath.startsWith(currentPath())) {
+        fixedPath = currentPath() + '/' + fixedPath;
+    }
+
+    if (!dd->archive->setCurrentFile(fixedPath)) {
+        warnStore << "\t\tCould not set current file" << dd->archive->getZipError();
+        return false;
+    }
+
+    dd->currentFile = new QuaZipFile(dd->archive);
+    if (!dd->currentFile->open(QIODevice::ReadOnly)) {
+        warnStore << "\t\t\tBut could not open!!!" << dd->archive->getZipError();
+        return false;
+    }
+    d->stream = dd->currentFile;
+    d->size = dd->currentFile->size();
+    return true;
+}
+
+bool KoQuaZipStore::closeWrite()
+{
+    Q_D(KoStore);
+    dd->currentFile->close();
+    d->stream = 0;
+    return dd->currentFile->getZipError() == ZIP_OK;
+}
+
+bool KoQuaZipStore::closeRead()
+{
+    Q_D(KoStore);
+    d->stream = 0;
+    return true;
+}
+
+bool KoQuaZipStore::enterRelativeDirectory(const QString &)
+{
+    return true;
+}
+
+bool KoQuaZipStore::enterAbsoluteDirectory(const QString &path)
+{
+    QString fixedPath = path;
+    fixedPath.replace("//", "/");
+
+    if (fixedPath.isEmpty()) {
+        return true;
+    }
+    QuaZipDir currentDir (dd->archive, fixedPath);
+    return currentDir.exists();
+}
+
+bool KoQuaZipStore::fileExists(const QString &absPath) const
+{
+    QString fixedPath = absPath;
+    fixedPath.replace("//", "/");
+    return dd->archive->getFileNameList().contains(fixedPath);
+}
diff --git a/libs/store/KoQuaZipStore.h b/libs/store/KoQuaZipStore.h
new file mode 100644
index 00000000000..e9fc320aab4
--- /dev/null
+++ b/libs/store/KoQuaZipStore.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 Boudewijn Rempt <boud at valdyas.org>
+ *
+ * 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 KoQuaZipStore_h
+#define KoQuaZipStore_h
+
+#include "KoStore.h"
+#include <QScopedPointer>
+
+class QUrl;
+
+class KoQuaZipStore : public KoStore
+{
+public:
+    KoQuaZipStore(const QString & _filename, Mode _mode, const QByteArray & appIdentification,
+                  bool writeMimetype = true);
+
+    KoQuaZipStore(QIODevice *dev, Mode mode, const QByteArray & appIdentification,
+                  bool writeMimetype = true);
+
+    ~KoQuaZipStore() override;
+
+    void setCompressionEnabled(bool enabled) override;
+    qint64 write(const char* _data, qint64 _len) override;
+
+    QStringList directoryList() const override;
+
+protected:
+    void init(const QByteArray& appIdentification);
+    bool doFinalize() override;
+    bool openWrite(const QString& name) override;
+    bool openRead(const QString& name) override;
+    bool closeWrite() override;
+    bool closeRead() override;
+    bool enterRelativeDirectory(const QString& dirName) override;
+    bool enterAbsoluteDirectory(const QString& path) override;
+    bool fileExists(const QString& absPath) const override;
+
+private:
+    struct Private;
+    const QScopedPointer<Private> dd;
+    Q_DECLARE_PRIVATE(KoStore)
+
+};
+
+#endif
diff --git a/libs/store/KoStore.cpp b/libs/store/KoStore.cpp
index ac6cc53021e..f0d3a4c9f16 100644
--- a/libs/store/KoStore.cpp
+++ b/libs/store/KoStore.cpp
@@ -22,7 +22,7 @@
 #include "KoStore.h"
 #include "KoStore_p.h"
 
-#include "KoZipStore.h"
+#include "KoQuaZipStore.h"
 #include "KoDirectoryStore.h"
 
 #include <QBuffer>
@@ -64,7 +64,7 @@ KoStore* KoStore::createStore(const QString& fileName, Mode mode, const QByteArr
     }
     switch (backend) {
     case Zip:
-        return new KoZipStore(fileName, mode, appIdentification, writeMimetype);
+        return new KoQuaZipStore(fileName, mode, appIdentification, writeMimetype);
     case Directory:
         return new KoDirectoryStore(fileName /* should be a dir name.... */, mode, writeMimetype);
     default:
@@ -90,19 +90,13 @@ KoStore* KoStore::createStore(QIODevice *device, Mode mode, const QByteArray & a
         errorStore << "Can't create a Directory store for a memory buffer!" << endl;
         return 0;
     case Zip:
-        return new KoZipStore(device, mode, appIdentification, writeMimetype);
+        return new KoQuaZipStore(device, mode, appIdentification, writeMimetype);
     default:
         warnStore << "Unsupported backend requested for KoStore : " << backend;
         return 0;
     }
 }
 
-KoStore* KoStore::createStore(const QUrl &url, Mode mode, const QByteArray & appIdentification, Backend backend, bool writeMimetype)
-{
-    Q_ASSERT(url.isLocalFile());
-    return createStore(url.toLocalFile(), mode,  appIdentification, backend, writeMimetype);
-}
-
 namespace
 {
 const char ROOTPART[] = "root";
@@ -168,15 +162,12 @@ bool KoStore::isOpen() const
 bool KoStore::close()
 {
     Q_D(KoStore);
-    debugStore << "Closing";
-
     if (!d->isOpen) {
         warnStore << "You must open before closing";
         return false;
     }
 
     bool ret = d->mode == Write ? closeWrite() : closeRead();
-
     delete d->stream;
     d->stream = 0;
     d->isOpen = false;
diff --git a/libs/store/KoStore.h b/libs/store/KoStore.h
index ae5370e46ed..56d10657043 100644
--- a/libs/store/KoStore.h
+++ b/libs/store/KoStore.h
@@ -74,31 +74,6 @@ public:
                                 const QByteArray &appIdentification = QByteArray(),
                                 Backend backend = Auto, bool writeMimetype = true);
 
-    /**
-     * Open a store (i.e. the representation on disk of a Krita document).
-     *
-     * @param url URL of the file to open
-     * @param mode if KoStore::Read, open an existing store to read it.
-     *             if KoStore::Write, create or replace a store.
-     * @param backend the backend to use for the data storage.
-     * Auto means automatically-determined for reading,
-     * and the current format (now Zip) for writing.
-     *
-     * @param appIdentification the application's mimetype,
-     * to be written in the file for "mime-magic" identification.
-     * Only meaningful if mode is Write, and if backend!=Directory.
-     *
-     * If the file is remote, the backend Directory cannot be used!
-     *
-     * @param writeMimetype If true, some backends (notably the Zip
-     * store) will write a file called 'mimetype' automatically and
-     * fill it with data from the appIdentification. This is only
-     * applicable if Mode is set to Write.
-     *
-     * @bug saving not completely implemented (fixed temporary file)
-     */
-    static KoStore *createStore(const QUrl &url, Mode mode,
-                                const QByteArray &appIdentification = QByteArray(), Backend backend = Auto, bool writeMimetype = true);
 
     /**
      * Destroys the store (i.e. closes the file on the hard disk)
diff --git a/libs/store/KoStore_p.h b/libs/store/KoStore_p.h
index 4a6c6e0ff44..565f6f4288f 100644
--- a/libs/store/KoStore_p.h
+++ b/libs/store/KoStore_p.h
@@ -70,11 +70,7 @@ public:
     bool extractFile(const QString &sourceName, QIODevice &buffer);
 
     KoStore *q;
-    /**
-     * original URL of the remote file
-     * (undefined for a local file)
-     */
-    QUrl url;
+
     QString localFileName;
     QWidget *window;
 
diff --git a/libs/store/KoZipStore.cpp b/libs/store/KoZipStore.cpp
deleted file mode 100644
index badd197841d..00000000000
--- a/libs/store/KoZipStore.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/* This file is part of the KDE project
-   Copyright (C) 2000-2002 David Faure <faure at kde.org>
-   Copyright (C) 2010 C. Boemann <cbo at boemann.dk>
-
-   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 "KoZipStore.h"
-#include "KoStore_p.h"
-
-#include <QBuffer>
-#include <QByteArray>
-#include <QTemporaryFile>
-
-#include <kzip.h>
-#include <StoreDebug.h>
-
-#include <QUrl>
-
-class SaveZip : public KZip {
-public:
-    SaveZip(const QString &filename) : KZip(filename) {}
-    SaveZip(QIODevice *dev) : KZip(dev) {}
-    ~SaveZip() override {}
-    void resetDevice() {
-        closeArchive();
-        setDevice(0);
-    }
-};
-
-KoZipStore::KoZipStore(const QString & _filename, Mode mode, const QByteArray & appIdentification,
-                       bool writeMimetype)
-    : KoStore(mode, writeMimetype)
-{
-    Q_D(KoStore);
-
-    d->localFileName = _filename;
-
-    m_pZip = new SaveZip(_filename);
-
-    init(appIdentification);   // open the zip file and init some vars
-}
-
-KoZipStore::KoZipStore(QIODevice *dev, Mode mode, const QByteArray & appIdentification,
-                       bool writeMimetype)
-    : KoStore(mode, writeMimetype)
-{
-    m_pZip = new SaveZip(dev);
-    init(appIdentification);
-}
-
-KoZipStore::KoZipStore(QWidget* window, const QUrl &_url, const QString & _filename, Mode mode,
-                       const QByteArray & appIdentification, bool writeMimetype)
-    : KoStore(mode, writeMimetype)
-{
-    debugStore << "KoZipStore Constructor url" << _url.url(QUrl::PreferLocalFile)
-               << " filename = " << _filename
-               << " mode = " << int(mode)
-               << " mimetype = " << appIdentification;
-    Q_D(KoStore);
-
-    d->url = _url;
-    d->window = window;
-
-    if (mode == KoStore::Read) {
-        d->localFileName = _filename;
-    } else {
-        QTemporaryFile f("kozip");
-        f.open();
-        d->localFileName = f.fileName();
-        f.close();
-    }
-
-    m_pZip = new SaveZip(d->localFileName);
-    init(appIdentification);   // open the zip file and init some vars
-}
-
-KoZipStore::~KoZipStore()
-{
-    Q_D(KoStore);
-    if (m_pZip->device() && m_pZip->device()->inherits("QSaveFile")) {
-        m_pZip->resetDevice(); // otherwise, kzip's destructor will call close(), which aborts on a qsavefile
-    }
-    else {
-        if (!d->finalized) {
-            finalize(); // ### no error checking when the app forgot to call finalize itself
-        }
-    }
-    delete m_pZip;
-
-    // When writing, we write to a temp file that then gets copied over the original filename
-    if (d->mode == Write && (!d->localFileName.isEmpty() && !d->url.isEmpty())) {
-        QFile f(d->localFileName);
-        if (f.copy(d->url.toLocalFile())) {
-            f.remove();
-        }
-    }
-}
-
-void KoZipStore::init(const QByteArray& appIdentification)
-{
-    Q_D(KoStore);
-
-    m_currentDir = 0;
-    d->good = m_pZip->open(d->mode == Write ? QIODevice::WriteOnly : QIODevice::ReadOnly);
-
-    if (!d->good)
-        return;
-
-    if (d->mode == Write) {
-
-        m_pZip->setCompression(KZip::NoCompression);
-        m_pZip->setExtraField(KZip::NoExtraField);
-
-        // Write identification
-        if (d->writeMimetype) {
-            (void)m_pZip->writeFile(QLatin1String("mimetype"), appIdentification);
-        }
-
-        m_pZip->setCompression(KZip::DeflateCompression);
-        // We don't need the extra field in Krita - so we leave it as "no extra field".
-    } else {
-        d->good = m_pZip->directory() != 0;
-    }
-}
-
-void KoZipStore::setCompressionEnabled(bool e)
-{
-    if (e) {
-        m_pZip->setCompression(KZip::DeflateCompression);
-    } else {
-        m_pZip->setCompression(KZip::NoCompression);
-    }
-}
-
-bool KoZipStore::doFinalize()
-{
-    if (m_pZip && m_pZip->device() && !m_pZip->device()->inherits("QSaveFile")) {
-        return m_pZip->close();
-    }
-    else {
-        return true;
-    }
-}
-
-bool KoZipStore::openWrite(const QString& name)
-{
-    Q_D(KoStore);
-    d->stream = 0; // Don't use!
-    return m_pZip->prepareWriting(name, "", "" /*m_pZip->rootDir()->user(), m_pZip->rootDir()->group()*/, 0);
-}
-
-bool KoZipStore::openRead(const QString& name)
-{
-    Q_D(KoStore);
-    const KArchiveEntry * entry = m_pZip->directory()->entry(name);
-    if (entry == 0) {
-        return false;
-    }
-    if (entry->isDirectory()) {
-        warnStore << name << " is a directory !";
-        return false;
-    }
-    // Must cast to KZipFileEntry, not only KArchiveFile, because device() isn't virtual!
-    const KZipFileEntry * f = static_cast<const KZipFileEntry *>(entry);
-    delete d->stream;
-    d->stream = f->createDevice();
-    d->size = f->size();
-    return true;
-}
-
-qint64 KoZipStore::write(const char* _data, qint64 _len)
-{
-    Q_D(KoStore);
-    if (_len == 0) return 0;
-    if (!d->isOpen) {
-        errorStore << "KoStore: You must open before writing" << endl;
-        return 0;
-    }
-    if (d->mode != Write) {
-        errorStore << "KoStore: Can not write to store that is opened for reading" << endl;
-        return 0;
-    }
-
-    d->size += _len;
-    if (m_pZip->writeData(_data, _len))     // writeData returns a bool!
-        return _len;
-    return 0;
-}
-
-QStringList KoZipStore::directoryList() const
-{
-    QStringList retval;
-    const KArchiveDirectory *directory = m_pZip->directory();
-    Q_FOREACH (const QString &name, directory->entries()) {
-        const KArchiveEntry* fileArchiveEntry = m_pZip->directory()->entry(name);
-        if (fileArchiveEntry->isDirectory()) {
-            retval << name;
-        }
-    }
-    return retval;
-}
-
-bool KoZipStore::closeWrite()
-{
-    Q_D(KoStore);
-    debugStore << "Wrote file" << d->fileName << " into ZIP archive. size" << d->size;
-    return m_pZip->finishWriting(d->size);
-}
-
-bool KoZipStore::enterRelativeDirectory(const QString& dirName)
-{
-    Q_D(KoStore);
-    if (d->mode == Read) {
-        if (!m_currentDir) {
-            m_currentDir = m_pZip->directory(); // initialize
-            Q_ASSERT(d->currentPath.isEmpty());
-        }
-        const KArchiveEntry *entry = m_currentDir->entry(dirName);
-        if (entry && entry->isDirectory()) {
-            m_currentDir = dynamic_cast<const KArchiveDirectory*>(entry);
-            return m_currentDir != 0;
-        }
-        return false;
-    } else // Write, no checking here
-        return true;
-}
-
-bool KoZipStore::enterAbsoluteDirectory(const QString& path)
-{
-    if (path.isEmpty()) {
-        m_currentDir = 0;
-        return true;
-    }
-    m_currentDir = dynamic_cast<const KArchiveDirectory*>(m_pZip->directory()->entry(path));
-    Q_ASSERT(m_currentDir);
-    return m_currentDir != 0;
-}
-
-bool KoZipStore::fileExists(const QString& absPath) const
-{
-    const KArchiveEntry *entry = m_pZip->directory()->entry(absPath);
-    return entry && entry->isFile();
-}
diff --git a/libs/store/KoZipStore.h b/libs/store/KoZipStore.h
index b1a4c0409fc..7e40bfa783c 100644
--- a/libs/store/KoZipStore.h
+++ b/libs/store/KoZipStore.h
@@ -33,12 +33,7 @@ public:
                bool writeMimetype = true);
     KoZipStore(QIODevice *dev, Mode mode, const QByteArray & appIdentification,
                bool writeMimetype = true);
-    /**
-     * QUrl-constructor
-     * @todo saving not completely implemented (fixed temporary file)
-     */
-    KoZipStore(QWidget* window, const QUrl &_url, const QString & _filename, Mode _mode,
-               const QByteArray & appIdentification, bool writeMimetype = true);
+
     ~KoZipStore() override;
 
     void setCompressionEnabled(bool e) override;
diff --git a/libs/ui/KisImportExportManager.cpp b/libs/ui/KisImportExportManager.cpp
index affa7e68937..7e8f616ad4b 100644
--- a/libs/ui/KisImportExportManager.cpp
+++ b/libs/ui/KisImportExportManager.cpp
@@ -648,6 +648,7 @@ KisImportExportFilter::ConversionStatus KisImportExportManager::doExportImpl(con
         } else {
 #ifdef USE_QSAVEFILE
             if (!file.commit()) {
+                qWarning() << "Could not commit QSaveFile";
                 QString error = file.errorString();
                 if (error.isEmpty()) {
                     error = i18n("Could not write to %1.", location);
diff --git a/libs/ui/KisWelcomePageWidget.cpp b/libs/ui/KisWelcomePageWidget.cpp
index 255a8e5e770..bc906e1dc2a 100644
--- a/libs/ui/KisWelcomePageWidget.cpp
+++ b/libs/ui/KisWelcomePageWidget.cpp
@@ -209,7 +209,7 @@ void KisWelcomePageWidget::populateRecentDocuments()
         else {
             if (QFileInfo(recentFileUrlPath).exists()) {
                 if (recentFileUrlPath.endsWith("ora") || recentFileUrlPath.endsWith("kra")) {
-                    QScopedPointer<KoStore> store(KoStore::createStore(QUrl::fromLocalFile(recentFileUrlPath), KoStore::Read));
+                    QScopedPointer<KoStore> store(KoStore::createStore(recentFileUrlPath, KoStore::Read));
                     if (store) {
                         if (store->open(QString("Thumbnails/thumbnail.png"))
                                 || store->open(QString("preview.png"))) {
diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc
index d6f197a16a3..d3d3c7ff4d3 100644
--- a/libs/ui/dialogs/kis_dlg_preferences.cc
+++ b/libs/ui/dialogs/kis_dlg_preferences.cc
@@ -185,6 +185,7 @@ GeneralTab::GeneralTab(QWidget *_parent, const char *_name)
     m_autosaveCheckBox->setChecked(autosaveInterval > 0);
 
     m_chkCompressKra->setChecked(cfg.compressKra());
+    chkZip64->setChecked(cfg.useZip64());
 
     m_backupFileCheckBox->setChecked(cfg.backupFile());
 
@@ -238,6 +239,7 @@ void GeneralTab::setDefault()
     m_backgroundimage->setText(cfg.getMDIBackgroundImage(true));
     m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true));
     m_chkCompressKra->setChecked(cfg.compressKra(true));
+    chkZip64->setChecked(cfg.useZip64(true));
     m_chkHiDPI->setChecked(false);
     m_chkSingleApplication->setChecked(true);
 
@@ -321,6 +323,11 @@ bool GeneralTab::compressKra()
     return m_chkCompressKra->isChecked();
 }
 
+bool GeneralTab::useZip64()
+{
+    return chkZip64->isChecked();
+}
+
 bool GeneralTab::toolOptionsInDocker()
 {
     return m_radioToolOptionsInDocker->isChecked();
@@ -1337,6 +1344,7 @@ bool KisDlgPreferences::editPreferences()
         cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked());
         cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages());
         cfg.setCompressKra(dialog->m_general->compressKra());
+        cfg.setUseZip64(dialog->m_general->useZip64());
 
         const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
         QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
diff --git a/libs/ui/dialogs/kis_dlg_preferences.h b/libs/ui/dialogs/kis_dlg_preferences.h
index 626c42a0974..c28ac9bdfdc 100644
--- a/libs/ui/dialogs/kis_dlg_preferences.h
+++ b/libs/ui/dialogs/kis_dlg_preferences.h
@@ -85,6 +85,7 @@ public:
     int favoritePresets();
     bool showCanvasMessages();
     bool compressKra();
+    bool useZip64();
     bool toolOptionsInDocker();
     bool kineticScrollingEnabled();
     int kineticScrollingGesture();
diff --git a/libs/ui/forms/wdggeneralsettings.ui b/libs/ui/forms/wdggeneralsettings.ui
index 5a49e1e2fee..66712afca50 100644
--- a/libs/ui/forms/wdggeneralsettings.ui
+++ b/libs/ui/forms/wdggeneralsettings.ui
@@ -601,21 +601,21 @@
          </property>
         </widget>
        </item>
-       <item row="5" column="1">
+       <item row="6" column="1">
         <widget class="QCheckBox" name="m_backupFileCheckBox">
          <property name="text">
           <string>Create backup file </string>
          </property>
         </widget>
        </item>
-       <item row="7" column="1">
+       <item row="8" column="1">
         <widget class="QCheckBox" name="m_chkConvertOnImport">
          <property name="text">
           <string>On importing images as layers, convert to the image colorspace</string>
          </property>
         </widget>
        </item>
-       <item row="9" column="0">
+       <item row="10" column="0">
         <widget class="QLabel" name="label">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -631,7 +631,7 @@
          </property>
         </widget>
        </item>
-       <item row="9" column="1">
+       <item row="10" column="1">
         <widget class="KisIntParseSpinBox" name="m_undoStackSize">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -659,7 +659,7 @@
          </property>
         </widget>
        </item>
-       <item row="10" column="0">
+       <item row="11" column="0">
         <widget class="QLabel" name="label_3">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -675,14 +675,14 @@
          </property>
         </widget>
        </item>
-       <item row="12" column="1">
+       <item row="13" column="1">
         <widget class="QCheckBox" name="chkShowRootLayer">
          <property name="text">
           <string>Show root layer</string>
          </property>
         </widget>
        </item>
-       <item row="13" column="1">
+       <item row="14" column="1">
         <widget class="QCheckBox" name="m_chkNativeFileDialog">
          <property name="toolTip">
           <string>Warning: if you enable this setting and the file dialogs do weird stuff, do not report a bug.</string>
@@ -692,14 +692,14 @@
          </property>
         </widget>
        </item>
-       <item row="15" column="0">
+       <item row="16" column="0">
         <widget class="QLabel" name="label_9">
          <property name="text">
           <string>Maximum brush size:</string>
          </property>
         </widget>
        </item>
-       <item row="15" column="1">
+       <item row="16" column="1">
         <layout class="QHBoxLayout" name="horizontalLayout_2">
          <item>
           <widget class="QSpinBox" name="intMaxBrushSize">
@@ -735,7 +735,7 @@
          </item>
         </layout>
        </item>
-       <item row="16" column="1">
+       <item row="17" column="1">
         <spacer name="verticalSpacer_4">
          <property name="orientation">
           <enum>Qt::Vertical</enum>
@@ -748,7 +748,7 @@
          </property>
         </spacer>
        </item>
-       <item row="10" column="1">
+       <item row="11" column="1">
         <widget class="KisIntParseSpinBox" name="m_favoritePresetsSpinBox">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -770,6 +770,16 @@
          </property>
         </widget>
        </item>
+       <item row="5" column="1">
+        <widget class="QCheckBox" name="chkZip64">
+         <property name="toolTip">
+          <string><html><head/><body><p>Only use this option for <span style=" font-weight:600;">very</span> large files: larger than 4 GiB on disk.</p></body></html></string>
+         </property>
+         <property name="text">
+          <string>Use Zip64 (for very large files: cannot be opened in versions of Krita older than 4.2.0)</string>
+         </property>
+        </widget>
+       </item>
       </layout>
      </widget>
     </widget>
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc
index 9551c4678e7..3bf4253a7ae 100644
--- a/libs/ui/kis_config.cc
+++ b/libs/ui/kis_config.cc
@@ -2004,6 +2004,16 @@ void KisConfig::setActivateTransformToolAfterPaste(bool value)
     m_cfg.writeEntry("activateTransformToolAfterPaste", value);
 }
 
+bool KisConfig::useZip64(bool defaultValue) const
+{
+    return defaultValue ? false : m_cfg.readEntry("UseZip64", false);
+}
+
+void KisConfig::setUseZip64(bool value)
+{
+    m_cfg.writeEntry("UseZip64", value);
+}
+
 #include <QDomDocument>
 #include <QDomElement>
 
diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h
index dbc8d05056c..8f8cdab216b 100644
--- a/libs/ui/kis_config.h
+++ b/libs/ui/kis_config.h
@@ -579,6 +579,8 @@ public:
     bool activateTransformToolAfterPaste(bool defaultValue = false) const;
     void setActivateTransformToolAfterPaste(bool value);
     
+    bool useZip64(bool defaultValue = false) const;
+    void setUseZip64(bool value);
 
     template<class T>
     void writeEntry(const QString& name, const T& value) {
diff --git a/plugins/impex/kra/kra_export.cpp b/plugins/impex/kra/kra_export.cpp
index f135675413c..69a1a6984bd 100644
--- a/plugins/impex/kra/kra_export.cpp
+++ b/plugins/impex/kra/kra_export.cpp
@@ -62,10 +62,10 @@ KisImportExportFilter::ConversionStatus KraExport::convert(KisDocument *document
     KisImageBuilder_Result res = kraConverter.buildFile(io, filename());
 
     if (res == KisImageBuilder_RESULT_OK) {
-        dbgFile << "success !";
+        dbgFile << "KraExport::convert success !";
         return KisImportExportFilter::OK;
     }
-    dbgFile << " Result =" << res;
+    dbgFile << "KraExport::convert result =" << res;
     return KisImportExportFilter::InternalError;
 }
 


More information about the kimageshop mailing list