File indexing completed on 2024-11-03 09:52:32

0001 /*
0002    This file is part of the KDE libraries
0003    Copyright 1999 Waldo Bastian <bastian@kde.org>
0004    Copyright 2006 Jaison Lee <lee.jaison@gmail.com>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License version 2 as published by the Free Software Foundation.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #ifndef KSAVEFILE_H
0022 #define KSAVEFILE_H
0023 
0024 #include <kdelibs4support_export.h>
0025 
0026 #include "kbackup.h"
0027 
0028 #include <QFile>
0029 #include <QString>
0030 
0031 /**
0032  * \class KSaveFile ksavefile.h <KSaveFile>
0033  *
0034  * @brief Class to allow for atomic file I/O, as well as utility functions.
0035  *
0036  * The KSaveFile class has been made to write out changes to an existing
0037  * file atomically. This means that either <b>ALL</b> changes will be written
0038  * to the file, or <b>NO</b> changes have been written, and the original file
0039  * (if any) has been unchanged. This is useful if you have lots of
0040  * time-consuming processing to perform during which an interruption could
0041  * occur, or if any error in the file structure will cause the entire file
0042  * to be corrupt.
0043  *
0044  * When you create a KSaveFile for a given file, a temporary file is instead
0045  * created and all your I/O occurs in the save file. Once you call finalize()
0046  * the temporary file is renamed to the target file, so that all your changes
0047  * happen at once. If abort() is called then the temporary file is removed and
0048  * the target file is untouched. KSaveFile derives from QFile so you can use
0049  * it just as you would a normal QFile.
0050  *
0051  * This class also includes several static utility functions available that
0052  * can help ensure data integrity. See the individual functions for details.
0053  *
0054  * Here is a quick example of how to use KSaveFile:
0055  *
0056  * First we create the KSaveFile and open it.
0057  *
0058  * @code
0059  * KSaveFile saveFile;
0060  * saveFile.setFileName("/lib/foo/bar.dat");
0061  * if ( !saveFile.open() ) {
0062  *     //Handle error
0063  * }
0064  * @endcode
0065  *
0066  * At this point the file "/lib/foo/bar.dat" has not been altered in any way.
0067  * Now, let's write out some data to the file.
0068  *
0069  * @code
0070  * QTextStream stream ( &saveFile );
0071  * stream << "Add some data.";
0072  * // Perform long processing
0073  * stream << "Add some more data.";
0074  * stream.flush();
0075  * @endcode
0076  *
0077  * Even after writing this data, the target file "/lib/foo/bar.dat" still has
0078  * not been altered in any way. Now that we are done writing our data, we can
0079  * write out all the changes that we have made by calling finalize().
0080  *
0081  * @code
0082  * if ( !saveFile.finalize() ) {
0083  *     //Handle error
0084  * }
0085  * @endcode
0086  *
0087  * If a user interruption or error occurred while we were writing out our
0088  * changes, we would instead call abort() to cancel all the I/O without
0089  * affecting the target file.
0090  *
0091  * @see QFile
0092  *
0093  * @author Jaison Lee <lee.jaison@gmail.com>
0094  * @author Waldo Bastian <bastian@kde.org>
0095  *
0096  * @deprecated since 5.0, port to QSaveFile.
0097  */
0098 class KDELIBS4SUPPORT_DEPRECATED_EXPORT KSaveFile : public QFile
0099 {
0100 public:
0101     /**
0102      * Default constructor.
0103      */
0104     KSaveFile();
0105 
0106     /**
0107      * Creates a new KSaveFile and sets the target file to @p filename.
0108      *
0109      * @param filename the path of the file
0110      */
0111     KDELIBS4SUPPORT_DEPRECATED explicit KSaveFile(const QString &filename);
0112 
0113     /**
0114      * Destructor.
0115      * @note If the file has been opened but not yet finalized, the
0116      * destructor will call finalize(). If you do not want the target file
0117      * to be affected you need to call abort() before destroying the object.
0118      **/
0119     ~KSaveFile() override;
0120 
0121     /**
0122      * @brief Set the target filename for the save file.
0123      * You must use this to set the filename of the target file if you do
0124      * not use the contructor that does so.
0125      * @param filename Name of the target file.
0126      */
0127     void setFileName(const QString &filename);
0128 
0129     /**
0130      * @brief Returns the name of the target file.
0131      * This function returns the name of the target file, or an empty
0132      * QString if it has not yet been set.
0133      * @returns The name of the target file.
0134      */
0135     QString fileName() const override;
0136 
0137     /**
0138      * @brief Returns the last error that occurred.
0139      * Use this function to check for errors.
0140      * @returns The last error that occurred, or QFile::NoError.
0141      */
0142     QFile::FileError error() const;
0143 
0144     /**
0145      * @brief Returns a human-readable description of the last error.
0146      * Use this function to get a human-readable description of the
0147      * last error that occurred.
0148      * @return A string describing the last error that occurred.
0149      */
0150     QString errorString() const;
0151 
0152     /**
0153      * @brief Open the save file.
0154      * This function will open the save file by creating a temporary file to write
0155      * to. It will also check to ensure that there are sufficient permissions to
0156      * write to the target file.
0157      *
0158      * @param flags Sets the QIODevice::OpenMode. It should contain the write flag, otherwise you
0159      * have a save file you cannot save to.
0160      *
0161      * @return true if successful, or false if an error has occurred.
0162      */
0163     bool open(OpenMode flags = QIODevice::ReadWrite) override;
0164 
0165     /**
0166      * @brief Discard changes without affecting the target file.
0167      * This will discard all changes that have been made to this file.
0168      * The target file will not be altered in any way.
0169      **/
0170     void abort();
0171 
0172     /**
0173      * @brief Finalize changes to the file.
0174      * This will commit all the changes that have been made to the file.
0175      * @return true if successful, or false if an error has occurred.
0176      **/
0177     bool finalize();
0178 
0179     /**
0180      * Allows writing over the existing file if necessary.
0181      *
0182      * QSaveFile creates a temporary file in the same directory as the final
0183      * file and atomically renames it. However this is not possible if the
0184      * directory permissions do not allow creating new files.
0185      * In order to preserve atomicity guarantees, open() fails when it
0186      * cannot create the temporary file.
0187      *
0188      * In order to allow users to edit files with write permissions in a
0189      * directory with restricted permissions, call setDirectWriteFallback() with
0190      * \a enabled set to true, and the following calls to open() will fallback to
0191      * opening the existing file directly and writing into it, without the use of
0192      * a temporary file.
0193      * This does not have atomicity guarantees, i.e. an application crash or
0194      * for instance a power failure could lead to a partially-written file on disk.
0195      * It also means cancelWriting() has no effect, in such a case.
0196      *
0197      * Typically, to save documents edited by the user, call setDirectWriteFallback(true),
0198      * and to save application internal files (configuration files, data files, ...), keep
0199      * the default setting which ensures atomicity.
0200      *
0201      * @since 4.10.3
0202      */
0203     void setDirectWriteFallback(bool enabled);
0204 
0205     /**
0206      * Returns true if the fallback solution for saving files in read-only
0207      * directories is enabled.
0208      *
0209      * @since 4.10.3
0210      */
0211     bool directWriteFallback() const;
0212 
0213 private:
0214     Q_DISABLE_COPY(KSaveFile)
0215 
0216     class Private;
0217     Private *const d;
0218 };
0219 
0220 #endif