1 | /* This file is part of the KDE libraries |
2 | Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at> |
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 version 2 as published by the Free Software Foundation. |
7 | |
8 | This library is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 | Library General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU Library General Public License |
14 | along with this library; see the file COPYING.LIB. If not, write to |
15 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
16 | Boston, MA 02110-1301, USA. |
17 | */ |
18 | #ifndef _KDIRWATCH_H |
19 | #define _KDIRWATCH_H |
20 | |
21 | #include <QtCore/QDateTime> |
22 | #include <QtCore/QObject> |
23 | #include <QtCore/QString> |
24 | |
25 | #include <kdecore_export.h> |
26 | |
27 | class KDirWatchPrivate; |
28 | |
29 | /** |
30 | * @short Class for watching directory and file changes. |
31 | * |
32 | * Watch directories and files for changes. |
33 | * The watched directories or files don't have to exist yet. |
34 | * |
35 | * When a watched directory is changed, i.e. when files therein are |
36 | * created or deleted, KDirWatch will emit the signal dirty(). |
37 | * |
38 | * When a watched, but previously not existing directory gets created, |
39 | * KDirWatch will emit the signal created(). |
40 | * |
41 | * When a watched directory gets deleted, KDirWatch will emit the |
42 | * signal deleted(). The directory is still watched for new |
43 | * creation. |
44 | * |
45 | * When a watched file is changed, i.e. attributes changed or written |
46 | * to, KDirWatch will emit the signal dirty(). |
47 | * |
48 | * Scanning of particular directories or files can be stopped temporarily |
49 | * and restarted. The whole class can be stopped and restarted. |
50 | * Directories and files can be added/removed from the list in any state. |
51 | * |
52 | * The implementation uses the INOTIFY functionality on LINUX. |
53 | * Otherwise the FAM service is used, when available. |
54 | * As a last resort, a regular polling for change of modification times |
55 | * is done; the polling interval is a global config option: |
56 | * DirWatch/PollInterval and DirWatch/NFSPollInterval for NFS mounted |
57 | * directories. |
58 | * The choice of implementation can be adjusted by the user, with the key |
59 | * [DirWatch] PreferredMethod={Fam|Stat|QFSWatch|inotify} |
60 | * |
61 | * @see self() |
62 | * @author Sven Radej (in 1998) |
63 | */ |
64 | class KDECORE_EXPORT KDirWatch : public QObject |
65 | { |
66 | Q_OBJECT |
67 | |
68 | public: |
69 | |
70 | /** |
71 | * Available watch modes for directory monitoring |
72 | **/ |
73 | enum WatchMode { |
74 | WatchDirOnly = 0, ///< Watch just the specified directory |
75 | WatchFiles = 0x01, ///< Watch also all files contained by the directory |
76 | WatchSubDirs = 0x02 ///< Watch also all the subdirs contained by the directory |
77 | }; |
78 | Q_DECLARE_FLAGS(WatchModes, WatchMode) |
79 | |
80 | /** |
81 | * Constructor. |
82 | * |
83 | * Scanning begins immediately when a dir/file watch |
84 | * is added. |
85 | * @param parent the parent of the QObject (or 0 for parent-less KDataTools) |
86 | */ |
87 | KDirWatch(QObject* parent = 0); |
88 | |
89 | /** |
90 | * Destructor. |
91 | * |
92 | * Stops scanning and cleans up. |
93 | */ |
94 | ~KDirWatch(); |
95 | |
96 | /** |
97 | * Adds a directory to be watched. |
98 | * |
99 | * The directory does not have to exist. When @p watchModes is set to |
100 | * WatchDirOnly (the default), the signals dirty(), created(), deleted() |
101 | * can be emitted, all for the watched directory. |
102 | * When @p watchModes is set to WatchFiles, all files in the watched |
103 | * directory are watched for changes, too. Thus, the signals dirty(), |
104 | * created(), deleted() can be emitted. |
105 | * When @p watchModes is set to WatchSubDirs, all subdirs are watched using |
106 | * the same flags specified in @p watchModes (symlinks aren't followed). |
107 | * If the @p path points to a symlink to a directory, the target directory |
108 | * is watched instead. If you want to watch the link, use @p addFile(). |
109 | * |
110 | * @param path the path to watch |
111 | * @param watchModes watch modes |
112 | * |
113 | * @sa KDirWatch::WatchMode |
114 | */ |
115 | void addDir(const QString& path, WatchModes watchModes = WatchDirOnly); |
116 | |
117 | /** |
118 | * Adds a file to be watched. |
119 | * If it's a symlink to a directory, it watches the symlink itself. |
120 | * @param file the file to watch |
121 | */ |
122 | void addFile(const QString& file); |
123 | |
124 | /** |
125 | * Returns the time the directory/file was last changed. |
126 | * @param path the file to check |
127 | * @return the date of the last modification |
128 | */ |
129 | QDateTime ctime(const QString& path) const; |
130 | |
131 | /** |
132 | * Removes a directory from the list of scanned directories. |
133 | * |
134 | * If specified path is not in the list this does nothing. |
135 | * @param path the path of the dir to be removed from the list |
136 | */ |
137 | void removeDir(const QString& path); |
138 | |
139 | /** |
140 | * Removes a file from the list of watched files. |
141 | * |
142 | * If specified path is not in the list this does nothing. |
143 | * @param file the file to be removed from the list |
144 | */ |
145 | void removeFile(const QString& file); |
146 | |
147 | /** |
148 | * Stops scanning the specified path. |
149 | * |
150 | * The @p path is not deleted from the internal list, it is just skipped. |
151 | * Call this function when you perform an huge operation |
152 | * on this directory (copy/move big files or many files). When finished, |
153 | * call restartDirScan(path). |
154 | * |
155 | * @param path the path to skip |
156 | * @return true if the @p path is being watched, otherwise false |
157 | * @see restartDirScanning() |
158 | */ |
159 | bool stopDirScan(const QString& path); |
160 | |
161 | /** |
162 | * Restarts scanning for specified path. |
163 | * |
164 | * It doesn't notify about the changes (by emitting a signal). |
165 | * The ctime value is reset. |
166 | * |
167 | * Call it when you are finished with big operations on that path, |
168 | * @em and when @em you have refreshed that path. |
169 | * |
170 | * @param path the path to restart scanning |
171 | * @return true if the @p path is being watched, otherwise false |
172 | * @see stopDirScanning() |
173 | */ |
174 | bool restartDirScan(const QString& path); |
175 | |
176 | /** |
177 | * Starts scanning of all dirs in list. |
178 | * |
179 | * @param notify If true, all changed directories (since |
180 | * stopScan() call) will be notified for refresh. If notify is |
181 | * false, all ctimes will be reset (except those who are stopped, |
182 | * but only if @p skippedToo is false) and changed dirs won't be |
183 | * notified. You can start scanning even if the list is |
184 | * empty. First call should be called with @p false or else all |
185 | * directories |
186 | * in list will be notified. |
187 | * @param skippedToo if true, the skipped directoris (scanning of which was |
188 | * stopped with stopDirScan() ) will be reset and notified |
189 | * for change. Otherwise, stopped directories will continue to be |
190 | * unnotified. |
191 | */ |
192 | void startScan( bool notify=false, bool skippedToo=false ); |
193 | |
194 | /** |
195 | * Stops scanning of all directories in internal list. |
196 | * |
197 | * The timer is stopped, but the list is not cleared. |
198 | */ |
199 | void stopScan(); |
200 | |
201 | /** |
202 | * Is scanning stopped? |
203 | * After creation of a KDirWatch instance, this is false. |
204 | * @return true when scanning stopped |
205 | */ |
206 | bool isStopped(); |
207 | |
208 | /** |
209 | * Check if a directory is being watched by this KDirWatch instance |
210 | * @param path the directory to check |
211 | * @return true if the directory is being watched |
212 | */ |
213 | bool contains( const QString& path ) const; |
214 | |
215 | void deleteQFSWatcher(); |
216 | |
217 | /** |
218 | * Dump statistic information about the KDirWatch::self() instance. |
219 | * This checks for consistency, too. |
220 | */ |
221 | static void statistics(); // TODO implement a QDebug operator for KDirWatch instead. |
222 | |
223 | enum Method { FAM, INotify, DNotify /*now unused*/, Stat, QFSWatch }; |
224 | /** |
225 | * Returns the preferred internal method to |
226 | * watch for changes. |
227 | */ |
228 | Method internalMethod(); // TODO KDE5: make const |
229 | |
230 | /** |
231 | * The KDirWatch instance usually globally used in an application. |
232 | * It is automatically deleted when the application exits. |
233 | * |
234 | * However, you can create an arbitrary number of KDirWatch instances |
235 | * aside from this one - for those you have to take care of memory management. |
236 | * |
237 | * This function returns an instance of KDirWatch. If there is none, it |
238 | * will be created. |
239 | * |
240 | * @return a KDirWatch instance |
241 | */ |
242 | static KDirWatch* self(); |
243 | /** |
244 | * Returns true if there is an instance of KDirWatch. |
245 | * @return true if there is an instance of KDirWatch. |
246 | * @see KDirWatch::self() |
247 | */ |
248 | static bool exists(); |
249 | |
250 | public Q_SLOTS: |
251 | |
252 | /** |
253 | * Emits created(). |
254 | * @param path the path of the file or directory |
255 | */ |
256 | void setCreated( const QString &path ); |
257 | |
258 | /** |
259 | * Emits dirty(). |
260 | * @param path the path of the file or directory |
261 | */ |
262 | void setDirty( const QString &path ); |
263 | |
264 | /** |
265 | * Emits deleted(). |
266 | * @param path the path of the file or directory |
267 | */ |
268 | void setDeleted( const QString &path ); |
269 | |
270 | Q_SIGNALS: |
271 | |
272 | /** |
273 | * Emitted when a watched object is changed. |
274 | * For a directory this signal is emitted when files |
275 | * therein are created or deleted. |
276 | * For a file this signal is emitted when its size or attributes change. |
277 | * |
278 | * When you watch a directory, changes in the size or attributes of |
279 | * contained files may or may not trigger this signal to be emitted |
280 | * depending on which backend is used by KDirWatch. |
281 | * |
282 | * The new ctime is set before the signal is emitted. |
283 | * @param path the path of the file or directory |
284 | */ |
285 | void dirty(const QString &path); |
286 | |
287 | /** |
288 | * Emitted when a file or directory is created. |
289 | * @param path the path of the file or directory |
290 | */ |
291 | void created(const QString &path); |
292 | |
293 | /** |
294 | * Emitted when a file or directory is deleted. |
295 | * |
296 | * The object is still watched for new creation. |
297 | * @param path the path of the file or directory |
298 | */ |
299 | void deleted(const QString &path); |
300 | |
301 | private: |
302 | KDirWatchPrivate *const d; |
303 | }; |
304 | |
305 | Q_DECLARE_OPERATORS_FOR_FLAGS(KDirWatch::WatchModes) |
306 | |
307 | #endif |
308 | |
309 | // vim: sw=3 et |
310 | |