File indexing completed on 2024-05-12 15:59:59

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 1998, 1999 David Faure <faure@kde.org>
0003    SPDX-FileCopyrightText: 2010 C. Boemann <cbo@boemann.dk>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef __koStore_h_
0009 #define __koStore_h_
0010 
0011 #include <QByteArray>
0012 #include <QIODevice>
0013 #include "kritastore_export.h"
0014 
0015 class QWidget;
0016 class QUrl;
0017 class KoStorePrivate;
0018 
0019 /**
0020  * Saves and loads Krita documents using various backends. Currently supported
0021  * backends are zip and directory.
0022  * We call a "store" the file on the hard disk (the one the users sees)
0023  * and call a "file" a file inside the store.
0024  */
0025 class KRITASTORE_EXPORT KoStore
0026 {
0027 public:
0028 
0029     enum Mode { Read, Write };
0030     enum Backend { Auto, Zip, Directory };
0031 
0032     /**
0033      * Open a store (i.e. the representation on disk of a Krita document).
0034      *
0035      * @param fileName the name of the file to open
0036      * @param mode if KoStore::Read, open an existing store to read it.
0037      *             if KoStore::Write, create or replace a store.
0038      * @param backend the backend to use for the data storage.
0039      * Auto means automatically-determined for reading,
0040      * and the current format (now Zip) for writing.
0041      *
0042      * @param appIdentification the application's mimetype,
0043      * to be written in the file for "mime-magic" identification.
0044      * Only meaningful if mode is Write, and if backend!=Directory.
0045      *
0046      * @param writeMimetype If true, some backends (notably the Zip
0047      * store) will write a file called 'mimetype' automatically and
0048      * fill it with data from the appIdentification. This is only
0049      * applicable if Mode is set to Write.
0050      */
0051     static KoStore *createStore(const QString &fileName, Mode mode,
0052                                 const QByteArray &appIdentification = QByteArray(),
0053                                 Backend backend = Auto, bool writeMimetype = true);
0054 
0055     /**
0056      * Create a store for any kind of QIODevice: file, memory buffer...
0057      * KoStore will take care of opening the QIODevice.
0058      * This method doesn't support the Directory store!
0059      */
0060     static KoStore *createStore(QIODevice *device, Mode mode,
0061                                 const QByteArray &appIdentification = QByteArray(),
0062                                 Backend backend = Auto, bool writeMimetype = true);
0063 
0064 
0065     /**
0066      * Destroys the store (i.e. closes the file on the hard disk)
0067      */
0068     virtual ~KoStore();
0069 
0070     /**
0071      * Open a new file inside the store
0072      * @param name The filename, internal representation ("root", "tar:/0"... ).
0073      *        If the tar:/ prefix is missing it's assumed to be a relative URI.
0074      * @return true on success.
0075      */
0076     bool open(const QString &name);
0077 
0078     /**
0079      * Check whether a file inside the store is currently opened with open(),
0080      * ready to be read or written.
0081      * @return true if a file is currently opened.
0082      */
0083     bool isOpen() const;
0084 
0085     /**
0086      * Close the file inside the store
0087      * @return true on success.
0088      */
0089     bool close();
0090 
0091     /**
0092      * Get a device for reading a file from the store directly
0093      * (slightly faster than read() calls)
0094      * You need to call @ref open first, and @ref close afterwards.
0095      */
0096     QIODevice *device() const;
0097 
0098     /**
0099      * Read data from the currently opened file. You can also use the streams
0100      * for this.
0101      */
0102     QByteArray read(qint64 max);
0103 
0104     /**
0105      * Write data into the currently opened file. You can also use the streams
0106      * for this.
0107      */
0108     qint64 write(const QByteArray &data);
0109 
0110     /**
0111      * Read data from the currently opened file. You can also use the streams
0112      * for this.
0113      * @return size of data read, -1 on error
0114      */
0115     qint64 read(char *buffer, qint64 length);
0116 
0117     /**
0118      * Write data into the currently opened file. You can also use the streams
0119      * for this.
0120      */
0121     virtual qint64 write(const char* data, qint64 length);
0122 
0123     /**
0124      * @return the size of the currently opened file, -1 on error.
0125      * Can be used as an argument for the read methods, for instance
0126      */
0127     qint64 size() const;
0128 
0129     /**
0130      * @return true if an error occurred
0131      */
0132     bool bad() const;
0133 
0134     /**
0135      * @return the mode used when opening, read or write
0136      */
0137     Mode mode() const;
0138 
0139     /**
0140      * If an store is opened for reading, then the directories
0141      * of the store can be accessed via this function.
0142      *
0143      * @return a stringlist with all directories found
0144      */
0145     virtual QStringList directoryList() const;
0146 
0147     /**
0148      * Enters one or multiple directories. In Read mode this actually
0149      * checks whether the specified directories exist and returns false
0150      * if they don't. In Write mode we don't create the directory, we
0151      * just use the "current directory" to generate the absolute path
0152      * if you pass a relative path (one not starting with tar:/) when
0153      * opening a stream.
0154      * Note: Operates on internal names
0155      */
0156     virtual bool enterDirectory(const QString &directory);
0157 
0158     /**
0159      * Leaves a directory. Equivalent to "cd .."
0160      * @return true on success, false if we were at the root already to
0161      * make it possible to "loop to the root"
0162      */
0163     bool leaveDirectory();
0164 
0165     /**
0166      * Returns the current path including a trailing slash.
0167      * Note: Returns a path in "internal name" style
0168      */
0169     QString currentPath() const;
0170 
0171     /**
0172      * Stacks the current directory. Restore the current path using
0173      * @ref popDirectory .
0174      */
0175     void pushDirectory();
0176 
0177     /**
0178      * Restores the previously pushed directory. No-op if the stack is
0179      * empty.
0180      */
0181     void popDirectory();
0182 
0183     /**
0184      * @return true if the given file exists in the current directory,
0185      * i.e. if open(fileName) will work.
0186      */
0187     bool hasFile(const QString &fileName) const;
0188 
0189     /**
0190      *@return true if the given directory exists in the archive
0191      */
0192     bool hasDirectory(const QString &directoryName);
0193 
0194     /**
0195      * Extracts a file out of the store to a buffer
0196      * @param sourceName file in the store
0197      * @param data memory buffer
0198      */
0199     bool extractFile(const QString &sourceName, QByteArray &data);
0200 
0201     //@{
0202     /// See QIODevice
0203     bool seek(qint64 pos);
0204     qint64 pos() const;
0205     bool atEnd() const;
0206     //@}
0207 
0208     /**
0209      * Call this before destroying the store, to be able to catch errors
0210      * (e.g. from ksavefile)
0211      */
0212     bool finalize();
0213 
0214     /**
0215      * Allow to enable or disable compression of the files. Only supported by the
0216      * ZIP backend.
0217      */
0218     virtual void setCompressionEnabled(bool e);
0219 
0220     /// When reading, in the paths in the store where name occurs, substitution is used.
0221     void setSubstitution(const QString &name, const QString &substitution);
0222 
0223 protected:
0224     KoStore(Mode mode, bool writeMimetype = true);
0225 
0226     /**
0227      * Finalize store - called by finalize.
0228      * @return true on success
0229      */
0230     virtual bool doFinalize() {
0231         return true;
0232     }
0233 
0234     /**
0235      * Open the file @p name in the store, for writing
0236      * On success, this method must set m_stream to a stream in which we can write.
0237      * @param name "absolute path" (in the archive) to the file to open
0238      * @return true on success
0239      */
0240     virtual bool openWrite(const QString &name) = 0;
0241     /**
0242      * Open the file @p name in the store, for reading.
0243      * On success, this method must set m_stream to a stream from which we can read,
0244      * as well as setting m_iSize to the size of the file.
0245      * @param name "absolute path" (in the archive) to the file to open
0246      * @return true on success
0247      */
0248     virtual bool openRead(const QString &name) = 0;
0249 
0250     /**
0251      * @return true on success
0252      */
0253     virtual bool closeRead() = 0;
0254     /**
0255      * @return true on success
0256      */
0257     virtual bool closeWrite() = 0;
0258 
0259     /**
0260      * Enter a subdirectory of the current directory.
0261      * The directory might not exist yet in Write mode.
0262      */
0263     virtual bool enterRelativeDirectory(const QString &dirName) = 0;
0264 
0265     /**
0266      * Enter a directory where we've been before.
0267      * It is guaranteed to always exist.
0268      */
0269     virtual bool enterAbsoluteDirectory(const QString &path) = 0;
0270 
0271     /**
0272      * Check if a file exists inside the store.
0273      * @param absPath the absolute path inside the store, i.e. not relative to the current directory
0274      */
0275     virtual bool fileExists(const QString &absPath) const = 0;
0276 
0277 protected:
0278     KoStorePrivate *d_ptr;
0279 
0280 private:
0281     Q_DECLARE_PRIVATE(KoStore)
0282 
0283 private:
0284     KoStore(const KoStore& store);    ///< don't copy
0285     KoStore& operator=(const KoStore& store);    ///< don't assign
0286 };
0287 
0288 #endif