Commit 593dba2b authored by Boudewijn Rempt's avatar Boudewijn Rempt

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@kde.org
parent 06cc0c1d
......@@ -208,3 +208,4 @@ if (NOT APPLE)
endif ()
add_subdirectory(ext_giflib)
add_subdirectory(ext_quazip)
......@@ -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/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}
)
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/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)
......@@ -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
##
......
# 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)
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}
......
/*
* Copyright (C) 2019 Boudewijn Rempt <boud@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);
}
/*
* Copyright (C) 2019 Boudewijn Rempt <boud@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
......@@ -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;
......
......@@ -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)
......
......@@ -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;
......
/* This file is part of the KDE project
Copyright (C) 2000-2002 David Faure <faure@kde.org>
Copyright (C) 2010 C. Boemann <cbo@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();