File indexing completed on 2024-05-12 03:54:54
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2006 Jacob R Rideout <kde@jacobrideout.net> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KAUTOSAVEFILE_H 0010 #define KAUTOSAVEFILE_H 0011 0012 #include <kcoreaddons_export.h> 0013 0014 #include <QFile> 0015 #include <QList> 0016 #include <QUrl> 0017 0018 #include <memory> 0019 0020 class KAutoSaveFilePrivate; 0021 /** 0022 * \class KAutoSaveFile kautosavefile.h <KAutoSaveFile> 0023 * 0024 * @brief Creates and manages a temporary "auto-save" file. 0025 * Autosave files are temporary files that applications use to store 0026 * the unsaved data in a file they have open for 0027 * editing. KAutoSaveFile allows you to easily create and manage such 0028 * files, as well as to recover the unsaved data left over by a 0029 * crashed or otherwise gone process. 0030 * 0031 * Each KAutoSaveFile object is associated with one specific file that 0032 * the application holds open. KAutoSaveFile is also a QObject, so it 0033 * can be reparented to the actual opened file object, so as to manage 0034 * the lifetime of the temporary file. 0035 * 0036 * Typical use consists of: 0037 * - verifying whether stale autosave files exist for the opened file 0038 * - deciding whether to recover the old, autosaved data 0039 * - if not recovering, creating a KAutoSaveFile object for the opened file 0040 * - during normal execution of the program, periodically save unsaved 0041 * data into the KAutoSaveFile file. 0042 * 0043 * KAutoSaveFile holds a lock on the autosave file, so it's safe to 0044 * delete the file and recreate it later. Because of that, disposing 0045 * of stale autosave files should be done with releaseLock(). No lock is 0046 * held on the managed file. 0047 * 0048 * Examples: 0049 * Opening a new file: 0050 * @code 0051 * void Document::open(const QUrl &url) 0052 * { 0053 * // check whether autosave files exist: 0054 * const QList<KAutoSaveFile *> staleFiles = KAutoSaveFile::staleFiles(url); 0055 * if (!staleFiles.isEmpty()) { 0056 * if (KMessageBox::questionTwoActions(parent, 0057 * "Auto-saved files exist. Do you want to recover them now?", 0058 * "File Recovery", 0059 * KGuiItem("Recover"), KGuiItem("Do Not recover")) == KMessageBox::PrimaryAction) { 0060 * recoverFiles(staleFiles); 0061 * return; 0062 * } else { 0063 * // remove the stale files 0064 * for (KAutoSaveFile *stale : staleFiles) { 0065 * stale->open(QIODevice::ReadWrite); 0066 * delete stale; 0067 * } 0068 * } 0069 * } 0070 * 0071 * // create new autosave object 0072 * m_autosave = new KAutoSaveFile(url, this); 0073 * 0074 * // continue the process of opening file 'url' 0075 * ... 0076 * } 0077 * @endcode 0078 * 0079 * The function recoverFiles could loop over the list of files and do this: 0080 * @code 0081 * for (KAutoSaveFile *stale : staleFiles) { 0082 * if (!stale->open(QIODevice::ReadWrite)) { 0083 * // show an error message; we could not steal the lockfile 0084 * // maybe another application got to the file before us? 0085 * delete stale; 0086 * continue; 0087 * } 0088 * Document *doc = new Document; 0089 * doc->m_autosave = stale; 0090 * stale->setParent(doc); // reparent 0091 * 0092 * doc->setUrl(stale->managedFile()); 0093 * doc->setContents(stale->readAll()); 0094 * doc->setState(Document::Modified); // mark it as modified and unsaved 0095 * 0096 * documentManager->addDocument(doc); 0097 * } 0098 * @endcode 0099 * 0100 * If the file is unsaved, periodically write the contents to the save file: 0101 * @code 0102 * if (!m_autosave->isOpen() && !m_autosave->open(QIODevice::ReadWrite)) { 0103 * // show error: could not open the autosave file 0104 * } 0105 * m_autosave->write(contents()); 0106 * @endcode 0107 * 0108 * When the user saves the file, the autosaved file is no longer 0109 * necessary and can be removed or emptied. 0110 * @code 0111 * m_autosave->resize(0); // leaves the file open 0112 * @endcode 0113 * 0114 * @code 0115 * m_autosave->remove(); // closes the file 0116 * @endcode 0117 * 0118 * @author Jacob R Rideout <kde@jacobrideout.net> 0119 */ 0120 class KCOREADDONS_EXPORT KAutoSaveFile : public QFile 0121 { 0122 Q_OBJECT 0123 public: 0124 /** 0125 * Constructs a KAutoSaveFile for file @p filename. The temporary 0126 * file is not opened or created until actually needed. The file 0127 * @p filename does not have to exist for KAutoSaveFile to be 0128 * constructed (if it exists, it will not be touched). 0129 * 0130 * @param filename the filename that this KAutoSaveFile refers to 0131 * @param parent the parent object 0132 */ 0133 explicit KAutoSaveFile(const QUrl &filename, QObject *parent = nullptr); 0134 0135 /** 0136 * @overload 0137 * Constructs a KAutoSaveFile object. Note that you need to call 0138 * setManagedFile() before calling open(). 0139 * 0140 * @param parent the parent object 0141 */ 0142 explicit KAutoSaveFile(QObject *parent = nullptr); 0143 0144 /** 0145 * Destroys the KAutoSaveFile object, removes the autosave 0146 * file and drops the lock being held (if any). 0147 */ 0148 ~KAutoSaveFile() override; 0149 0150 /** 0151 * Retrieves the URL of the file managed by KAutoSaveFile. This 0152 * is the same URL that was given to setManagedFile() or the 0153 * KAutoSaveFile constructor. 0154 * 0155 * This is the name of the real file being edited by the 0156 * application. To get the name of the temporary file where data 0157 * can be saved, use fileName() (after you have called open()). 0158 */ 0159 QUrl managedFile() const; 0160 0161 /** 0162 * Sets the URL of the file managed by KAutoSaveFile. This should 0163 * be the name of the real file being edited by the application. 0164 * If the file was previously set, this function calls releaseLock(). 0165 * 0166 * @param filename the filename that this KAutoSaveFile refers to 0167 */ 0168 void setManagedFile(const QUrl &filename); 0169 0170 /** 0171 * Closes the autosave file resource and removes the lock 0172 * file. The file name returned by fileName() will no longer be 0173 * protected and can be overwritten by another application at any 0174 * time. To obtain a new lock, call open() again. 0175 * 0176 * This function calls remove(), so the autosave temporary file 0177 * will be removed too. 0178 */ 0179 virtual void releaseLock(); 0180 0181 /** 0182 * Opens the autosave file and locks it if it wasn't already 0183 * locked. The name of the temporary file where data can be saved 0184 * to will be set by this function and can be retrieved with 0185 * fileName(). It will not change unless releaseLock() is called. No 0186 * other application will attempt to edit such a file either while 0187 * the lock is held. 0188 * 0189 * @param openmode the mode that should be used to open the file, 0190 * probably QIODevice::ReadWrite 0191 * @returns true if the file could be opened (= locked and 0192 * created), false if the operation failed 0193 */ 0194 bool open(OpenMode openmode) override; 0195 0196 /** 0197 * Checks for stale autosave files for the file @p url. Returns a list 0198 * of autosave files that contain autosaved data left behind by 0199 * other instances of the application, due to crashing or 0200 * otherwise uncleanly exiting. 0201 * 0202 * It is the application's job to determine what to do with such 0203 * unsaved data. Generally, this is done by asking the user if he 0204 * wants to see the recovered data, and then allowing the user to 0205 * save if he wants to. 0206 * 0207 * If not given, the application name is obtained from 0208 * QCoreApplication, so be sure to have set it correctly before 0209 * calling this function. 0210 * 0211 * This function returns a list of unopened KAutoSaveFile 0212 * objects. By calling open() on them, the application will steal 0213 * the lock. Subsequent releaseLock() or deleting of the object will 0214 * then erase the stale autosave file. 0215 * 0216 * The application owns all returned KAutoSaveFile objects and is 0217 * responsible for deleting them when no longer needed. Remember that 0218 * deleting the KAutoSaveFile will release the file lock and remove the 0219 * stale autosave file. 0220 */ 0221 static QList<KAutoSaveFile *> staleFiles(const QUrl &url, const QString &applicationName = QString()); 0222 0223 /** 0224 * Returns all stale autosave files left behind by crashed or 0225 * otherwise gone instances of this application. 0226 * 0227 * If not given, the application name is obtained from 0228 * QCoreApplication, so be sure to have set it correctly before 0229 * calling this function. 0230 * 0231 * See staleFiles() for information on the returned objects. 0232 * 0233 * The application owns all returned KAutoSaveFile objects and is 0234 * responsible for deleting them when no longer needed. Remember that 0235 * deleting the KAutoSaveFile will release the file lock and remove the 0236 * stale autosave file. 0237 */ 0238 static QList<KAutoSaveFile *> allStaleFiles(const QString &applicationName = QString()); 0239 0240 private: 0241 Q_DISABLE_COPY(KAutoSaveFile) 0242 friend class KAutoSaveFilePrivate; 0243 std::unique_ptr<KAutoSaveFilePrivate> const d; 0244 }; 0245 0246 #endif // KAUTOSAVEFILE_H