[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