diff --git a/QXlsx/header/xlsxzipwriter_p.h b/QXlsx/header/xlsxzipwriter_p.h index 42b5acab..39a54be0 100644 --- a/QXlsx/header/xlsxzipwriter_p.h +++ b/QXlsx/header/xlsxzipwriter_p.h @@ -6,6 +6,7 @@ #include "xlsxglobal.h" #include +#include #include class QZipWriter; @@ -25,6 +26,7 @@ class ZipWriter void close(); private: + QScopedPointer m_deviceProxy; QZipWriter *m_writer; }; diff --git a/QXlsx/source/xlsxdocument.cpp b/QXlsx/source/xlsxdocument.cpp index beb4e833..9e278787 100644 --- a/QXlsx/source/xlsxdocument.cpp +++ b/QXlsx/source/xlsxdocument.cpp @@ -1365,7 +1365,8 @@ bool Document::saveAs(const QString &name) const * \overload * This function writes a document to the given \a device. * - * \warning The \a device will be closed when this function returned. + * \warning The \a device will be closed when this function returns, except for + * QSaveFile. A QSaveFile remains open and must be committed by the caller. */ bool Document::saveAs(QIODevice *device) const { diff --git a/QXlsx/source/xlsxzipwriter.cpp b/QXlsx/source/xlsxzipwriter.cpp index 3c2fb19e..e0922afc 100644 --- a/QXlsx/source/xlsxzipwriter.cpp +++ b/QXlsx/source/xlsxzipwriter.cpp @@ -5,9 +5,55 @@ #include #include +#ifndef QT_NO_TEMPORARYFILE +#include +#endif QT_BEGIN_NAMESPACE_XLSX +namespace { + +class NonClosingDevice : public QIODevice +{ +public: + explicit NonClosingDevice(QIODevice *device) + : m_device(device) + { + if (device->isOpen()) + QIODevice::open(device->openMode()); + } + + bool open(OpenMode mode) override + { + if (!m_device->isOpen() && !m_device->open(mode)) + return false; + return QIODevice::open(m_device->openMode()); + } + + bool isSequential() const override { return m_device->isSequential(); } + qint64 pos() const override { return m_device->pos(); } + qint64 size() const override { return m_device->size(); } + + bool seek(qint64 position) override + { + if (!m_device->seek(position)) + return false; + return QIODevice::seek(position); + } + +protected: + qint64 readData(char *data, qint64 maxSize) override { return m_device->read(data, maxSize); } + qint64 writeData(const char *data, qint64 maxSize) override + { + return m_device->write(data, maxSize); + } + +private: + QIODevice *m_device; +}; + +} // namespace + ZipWriter::ZipWriter(const QString &filePath) { m_writer = new QZipWriter(filePath, QIODevice::WriteOnly); @@ -16,7 +62,11 @@ ZipWriter::ZipWriter(const QString &filePath) ZipWriter::ZipWriter(QIODevice *device) { - m_writer = new QZipWriter(device); +#ifndef QT_NO_TEMPORARYFILE + if (qobject_cast(device)) + m_deviceProxy.reset(new NonClosingDevice(device)); +#endif + m_writer = new QZipWriter(m_deviceProxy ? m_deviceProxy.data() : device); m_writer->setCompressionPolicy(QZipWriter::AutoCompress); }