1/* This file is part of the KDE libraries
2 Copyright (c) 2006 Jacob R Rideout <kde@jacobrideout.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef KAUTOSAVEFILE_H
21#define KAUTOSAVEFILE_H
22
23#include <kdecore_export.h>
24#include "kurl.h"
25
26#include <QtCore/QFile>
27#include <QtCore/QList>
28
29class KAutoSaveFilePrivate;
30/**
31 * \class KAutoSaveFile kautosavefile.h <KAutoSaveFile>
32 *
33 * @brief Creates and manages a temporary "auto-save" file.
34 * Autosave files are temporary files that applications use to store
35 * the unsaved data in a file they have open for
36 * editing. KAutoSaveFile allows you to easily create and manage such
37 * files, as well as to recover the unsaved data left over by a
38 * crashed or otherwise gone process.
39 *
40 * Each KAutoSaveFile object is associated with one specific file that
41 * the application holds open. KAutoSaveFile is also a QObject, so it
42 * can be reparented to the actual opened file object, so as to manage
43 * the lifetime of the temporary file.
44 *
45 * Typical use consists of:
46 * - verifying whether stale autosave files exist for the opened file
47 * - deciding whether to recover the old, autosaved data
48 * - if not recovering, creating a KAutoSaveFile object for the opened file
49 * - during normal execution of the program, periodically save unsaved
50 * data into the KAutoSaveFile file.
51 *
52 * KAutoSaveFile holds a lock on the autosave file, so it's safe to
53 * delete the file and recreate it later. Because of that, disposing
54 * of stale autosave files should be done with releaseLock(). No lock is
55 * held on the managed file.
56 *
57 * Examples:
58 * Opening a new file:
59 * @code
60 * void Document::open(const KUrl &url)
61 * {
62 * // check whether autosave files exist:
63 * QList<KAutoSaveFile *> staleFiles = KAutoSaveFile::staleFiles(url);
64 * if (!staleFiles.isEmpty()) {
65 * if (KMessageBox::questionYesNo(parent,
66 * "Auto-saved files exist. Do you want to recover them now?",
67 * "File Recovery",
68 * "Recover", "Don't recover") == KMessage::Yes) {
69 * recoverFiles(staleFiles);
70 * return;
71 * } else {
72 * // remove the stale files
73 * foreach (KAutoSaveFile *stale, staleFiles) {
74 * stale->open(QIODevice::ReadWrite);
75 * delete stale;
76 * }
77 * }
78 * }
79 *
80 * // create new autosave object
81 * m_autosave = new KAutoSaveFile(url, this);
82 *
83 * // continue the process of opening file 'url'
84 * ...
85 * }
86 * @endcode
87 *
88 * The function recoverFiles could loop over the list of files and do this:
89 * @code
90 * foreach (KAutoSaveFile *stale, staleFiles) {
91 * if (!stale->open(QIODevice::ReadWrite)) {
92 * // show an error message; we could not steal the lockfile
93 * // maybe another application got to the file before us?
94 * delete stale;
95 * continue;
96 * }
97 * Document *doc = new Document;
98 * doc->m_autosave = stale;
99 * stale->setParent(doc); // reparent
100 *
101 * doc->setUrl(stale->managedFile());
102 * doc->setContents(stale->readAll());
103 * doc->setState(Document::Modified); // mark it as modified and unsaved
104 *
105 * documentManager->addDocument(doc);
106 * }
107 * @endcode
108 *
109 * If the file is unsaved, periodically write the contents to the save file:
110 * @code
111 * if (!m_autosave->isOpen() && !m_autosave->open(QIODevice::ReadWrite)) {
112 * // show error: could not open the autosave file
113 * }
114 * m_autosave->write(contents());
115 * @endcode
116 *
117 * When the user saves the file, the autosaved file is no longer
118 * necessary and can be removed or emptied.
119 * @code
120 * m_autosave->resize(0); // leaves the file open
121 * @endcode
122 *
123 * @code
124 * m_autosave->remove(); // closes the file
125 * @endcode
126 *
127 * @author Jacob R Rideout <kde@jacobrideout.net>
128 */
129class KDECORE_EXPORT KAutoSaveFile : public QFile
130{
131 Q_OBJECT
132public:
133 /**
134 * Constructs a KAutoSaveFile for file @p filename. The temporary
135 * file is not opened or created until actually needed. The file
136 * @p filename does not have to exist for KAutoSaveFile to be
137 * constructed (if it exists, it will not be touched).
138 *
139 * @param filename the filename that this KAutoSaveFile refers to
140 * @param parent the parent object
141 */
142 explicit KAutoSaveFile(const KUrl &filename, QObject *parent = 0);
143
144 /**
145 * @overload
146 * Constructs a KAutoSaveFile object. Note that you need to call
147 * setManagedFile() before calling open().
148 *
149 * @param parent the parent object
150 */
151 explicit KAutoSaveFile(QObject *parent = 0);
152
153 /**
154 * Destroys the KAutoSaveFile object, removes the autosave
155 * file and drops the lock being held (if any).
156 */
157 ~KAutoSaveFile();
158
159 /**
160 * Retrieves the URL of the file managed by KAutoSaveFile. This
161 * is the same URL that was given to setManagedFile() or the
162 * KAutoSaveFile constructor.
163 *
164 * This is the name of the real file being edited by the
165 * application. To get the name of the temporary file where data
166 * can be saved, use fileName() (after you have called open()).
167 */
168 KUrl managedFile() const;
169
170 /**
171 * Sets the URL of the file managed by KAutoSaveFile. This should
172 * be the name of the real file being edited by the application.
173 * If the file was previously set, this function calls releaseLock().
174 *
175 * @param filename the filename that this KAutoSaveFile refers to
176 */
177 void setManagedFile(const KUrl &filename);
178
179 /**
180 * Closes the autosave file resource and removes the lock
181 * file. The file name returned by fileName() will no longer be
182 * protected and can be overwritten by another application at any
183 * time. To obtain a new lock, call open() again.
184 *
185 * This function calls remove(), so the autosave temporary file
186 * will be removed too.
187 */
188 virtual void releaseLock();
189
190 /**
191 * Opens the autosave file and locks it if it wasn't already
192 * locked. The name of the temporary file where data can be saved
193 * to will be set by this function and can be retrieved with
194 * fileName(). It will not change unless releaseLock() is called. No
195 * other application will attempt to edit such a file either while
196 * the lock is held.
197 *
198 * @param openmode the mode that should be used to open the file,
199 * probably QIODevice::ReadWrite
200 * @returns true if the file could be opened (= locked and
201 * created), false if the operation failed
202 */
203 virtual bool open(OpenMode openmode);
204
205 /**
206 * Checks for stale autosave files for @p filename. Returns a list
207 * of autosave files that contain autosaved data left behind by
208 * other instances of the application, due to crashing or
209 * otherwise uncleanly exiting.
210 *
211 * It is the application's job to determine what to do with such
212 * unsaved data. Generally, this is done by asking the user if he
213 * wants to see the recovered data, and then allowing the user to
214 * save if he wants to.
215 *
216 * If not given, the application name is obtained from
217 * QCoreApplication, so be sure to have set it correctly before
218 * calling this function.
219 *
220 * This function returns a list of unopened KAutoSaveFile
221 * objects. By calling open() on them, the application will steal
222 * the lock. Subsequent releaseLock() or deleting of the object will
223 * then erase the stale autosave file.
224 */
225 static QList<KAutoSaveFile *> staleFiles(const KUrl &filename,
226 const QString &applicationName =
227 QString());
228
229 /**
230 * Returns all stale autosave files left behind by crashed or
231 * otherwise gone instances of this application.
232 *
233 * If not given, the application name is obtained from
234 * QCoreApplication, so be sure to have set it correctly before
235 * calling this function.
236 *
237 * See staleFiles() for information on the returned objects.
238 */
239 static QList<KAutoSaveFile *> allStaleFiles(const QString &applicationName =
240 QString());
241
242private:
243 Q_DISABLE_COPY(KAutoSaveFile)
244 friend class KAutoSaveFilePrivate;
245 KAutoSaveFilePrivate* const d;
246};
247
248#endif // KAUTOSAVEFILE_H
249