-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 122 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 63 |
2 files changed, 154 insertions, 31 deletions
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 11d4f87..4264327 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp | |||
@@ -53,16 +53,34 @@ static QIntDict<OFileNotification> notification_list; | |||
53 | QSocketNotifier* OFileNotification::_sn; | 53 | QSocketNotifier* OFileNotification::_sn; |
54 | int OFileNotification::_fd = -1; | 54 | int OFileNotification::_fd = -1; |
55 | 55 | ||
56 | #define INOTIFY_DEVICE "/dev/inotify" | 56 | #define INOTIFY_DEVICE "/dev/inotify" |
57 | 57 | ||
58 | namespace Opie { | 58 | namespace Opie { |
59 | namespace Core { | 59 | namespace Core { |
60 | 60 | ||
61 | //================================================================================================= | ||
62 | // OFileNotificationEvent | ||
63 | //================================================================================================= | ||
64 | OFileNotificationEvent::OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ) | ||
65 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) | ||
66 | { | ||
67 | qDebug( "OFileNotificationEvent()" ); | ||
68 | } | ||
69 | |||
70 | |||
71 | OFileNotificationEvent::~OFileNotificationEvent() | ||
72 | { | ||
73 | qDebug( "~OFileNotificationEvent()" ); | ||
74 | } | ||
75 | |||
76 | //================================================================================================= | ||
77 | // OFileNotification | ||
78 | //================================================================================================= | ||
61 | OFileNotification::OFileNotification( QObject* parent, const char* name ) | 79 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
62 | :QObject( parent, name ), _active( false ), _multi( true ) | 80 | :QObject( parent, name ), _active( false ), _multi( true ) |
63 | { | 81 | { |
64 | qDebug( "OFileNotification::OFileNotification()" ); | 82 | qDebug( "OFileNotification::OFileNotification()" ); |
65 | } | 83 | } |
66 | 84 | ||
67 | 85 | ||
68 | OFileNotification::~OFileNotification() | 86 | OFileNotification::~OFileNotification() |
@@ -147,72 +165,89 @@ OFileNotificationType OFileNotification::type() const | |||
147 | 165 | ||
148 | 166 | ||
149 | QString OFileNotification::path() const | 167 | QString OFileNotification::path() const |
150 | { | 168 | { |
151 | return _path; | 169 | return _path; |
152 | } | 170 | } |
153 | 171 | ||
154 | 172 | ||
155 | bool OFileNotification::activate() | 173 | bool OFileNotification::activate( const OFileNotificationEvent* e ) |
156 | { | 174 | { |
157 | emit triggered( _path ); | 175 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); |
176 | |||
177 | // dumb signal | ||
158 | _signal.activate(); | 178 | _signal.activate(); |
179 | |||
180 | // generic signal | ||
181 | emit triggered( _path, e->mask(), e->name() ); | ||
182 | |||
183 | // specialized signals | ||
184 | switch ( e->mask() ) | ||
185 | { | ||
186 | case Access: emit accessed( _path ); break; | ||
187 | case Modify: emit modified( _path ); break; | ||
188 | case Attrib: emit attributed( _path); break; | ||
189 | case CloseWrite: emit closed( _path, true ); break; | ||
190 | case CloseNoWrite: emit closed( _path, false ); break; | ||
191 | case Open: emit opened( _path ); break; | ||
192 | case MovedFrom: emit movedFrom( _path, e->name() ); break; | ||
193 | case MovedTo: emit movedTo( _path, e->name() ); break; | ||
194 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; | ||
195 | case DeleteFile: emit deletedFile( _path, e->name() ); break; | ||
196 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; | ||
197 | case CreateFile: emit createdFile( _path, e->name() ); break; | ||
198 | case DeleteSelf: emit deleted( _path ); break; | ||
199 | case Unmount: emit unmounted( _path ); break; | ||
200 | default: assert( 0 ); | ||
201 | } | ||
202 | |||
159 | if ( !_multi ) stop(); | 203 | if ( !_multi ) stop(); |
204 | |||
160 | return true; | 205 | return true; |
161 | } | 206 | } |
162 | 207 | ||
163 | 208 | ||
164 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 209 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) |
165 | { | 210 | { |
166 | OFileNotification* ofn = new OFileNotification(); | 211 | OFileNotification* ofn = new OFileNotification(); |
167 | ofn->_signal.connect( receiver, member ); | 212 | ofn->_signal.connect( receiver, member ); |
168 | return ofn->watch( path, true, type ) != -1; | 213 | return ofn->watch( path, true, type ) != -1; |
169 | } | 214 | } |
170 | 215 | ||
171 | 216 | ||
172 | void OFileNotification::inotifyEventHandler() | 217 | void OFileNotification::inotifyEventHandler() |
173 | { | 218 | { |
174 | qWarning( "OFileNotification::__eventHandler(): reached." ); | 219 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); |
175 | 220 | ||
176 | char buffer[16384]; | 221 | char buffer[16384]; |
177 | size_t buffer_i; | 222 | size_t buffer_i; |
178 | struct inotify_event *pevent, *event; | 223 | struct inotify_event *pevent, *event; |
179 | ssize_t r; | 224 | ssize_t r; |
180 | size_t event_size; | 225 | size_t event_size; |
181 | int count = 0; | 226 | int count = 0; |
182 | 227 | ||
183 | r = ::read(_fd, buffer, 16384); | 228 | r = ::read(_fd, buffer, 16384); |
184 | 229 | ||
185 | if ( r <= 0 ) | 230 | if ( r <= 0 ) |
186 | return; | 231 | return; |
187 | 232 | ||
188 | buffer_i = 0; | 233 | buffer_i = 0; |
189 | while ( buffer_i < r ) | 234 | while ( buffer_i < r ) |
190 | { | 235 | { |
191 | /* Parse events and queue them ! */ | 236 | pevent = (struct inotify_event *)&buffer[buffer_i]; |
192 | pevent = (struct inotify_event *)&buffer[buffer_i]; | 237 | event_size = sizeof(struct inotify_event) + pevent->len; |
193 | event_size = sizeof(struct inotify_event) + pevent->len; | 238 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, |
194 | qDebug( "pevent->len = %d\n", pevent->len); | 239 | pevent->cookie, pevent->len ? pevent->name : 0 ); |
195 | 240 | e->activate(); | |
196 | OFileNotification* fn = notification_list[ pevent->wd ]; | 241 | buffer_i += event_size; |
197 | if ( fn ) | 242 | count++; |
198 | fn->activate(); | ||
199 | else | ||
200 | assert( false ); | ||
201 | |||
202 | //event = malloc(event_size); | ||
203 | //memmove(event, pevent, event_size); | ||
204 | //queue_enqueue(event, q); | ||
205 | buffer_i += event_size; | ||
206 | count++; | ||
207 | } | 243 | } |
208 | 244 | ||
209 | qDebug( "received %d events...", count ); | 245 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); |
210 | return; | ||
211 | } | 246 | } |
212 | 247 | ||
213 | 248 | ||
214 | bool OFileNotification::registerEventHandler() | 249 | bool OFileNotification::registerEventHandler() |
215 | { | 250 | { |
216 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); | 251 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); |
217 | if ( OFileNotification::_fd < 0 ) | 252 | if ( OFileNotification::_fd < 0 ) |
218 | { | 253 | { |
@@ -257,22 +292,59 @@ int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationT | |||
257 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); | 292 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); |
258 | 293 | ||
259 | if ( recurse == 0 ) | 294 | if ( recurse == 0 ) |
260 | { | 295 | { |
261 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); | 296 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); |
262 | int result = fn->startWatching( path, sshot, type ); | 297 | int result = fn->startWatching( path, sshot, type ); |
263 | if ( result != -1 ) | 298 | if ( result != -1 ) |
264 | { | 299 | { |
265 | connect( fn, SIGNAL( triggered( const QString& ) ), this, SIGNAL( triggered( const QString& ) ) ); | 300 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); |
266 | return result; | 301 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); |
302 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); | ||
303 | connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); | ||
304 | connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) ); | ||
305 | connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) ); | ||
306 | connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) ); | ||
307 | connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) ); | ||
308 | connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) ); | ||
309 | connect( fn, SIGNAL( deletedFile( const QString&, const QString& ) ), this, SIGNAL( deletedFile( const QString&, const QString& ) ) );; | ||
310 | connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SIGNAL( createdSubdir( const QString&, const QString& ) ) ); | ||
311 | connect( fn, SIGNAL( createdFile( const QString&, const QString& ) ), this, SIGNAL( createdFile( const QString&, const QString& ) ) ); | ||
312 | connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) ); | ||
313 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); | ||
267 | } | 314 | } |
315 | return result; | ||
268 | } | 316 | } |
269 | else | 317 | else |
270 | { | 318 | { |
271 | qDebug( "ODirNotification::watch(), recursion not yet implemented... :)" ); | 319 | |
272 | return -1; | 320 | return 1; |
273 | } | 321 | } |
274 | } | 322 | } |
275 | 323 | ||
324 | |||
325 | // void ODirNotification::subdirCreated( const QString& name ) | ||
326 | |||
327 | |||
328 | /* | ||
329 | Love-Trowbridge recursive directory scanning algorithm: | ||
330 | |||
331 | Step 1. Start at initial directory foo. Add watch. | ||
332 | |||
333 | Step 2. Setup handlers for watch created in Step 1. | ||
334 | Specifically, ensure that a directory created | ||
335 | in foo will result in a handled CREATE_SUBDIR | ||
336 | event. | ||
337 | |||
338 | Step 3. Read the contents of foo. | ||
339 | |||
340 | Step 4. For each subdirectory of foo read in step 3, repeat | ||
341 | step 1. | ||
342 | |||
343 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is | ||
344 | not yet created on bar, repeat step 1 on bar. | ||
345 | */ | ||
346 | |||
347 | |||
276 | } // namespace Ui | 348 | } // namespace Ui |
277 | 349 | ||
278 | } // namespace Opie | 350 | } // namespace Opie |
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h index 3eb917e..5bbf421 100644 --- a/libopie2/opiecore/ofilenotify.h +++ b/libopie2/opiecore/ofilenotify.h | |||
@@ -37,16 +37,18 @@ _;:, .> :=|. This program is free software; you can | |||
37 | /* QT */ | 37 | /* QT */ |
38 | #include <qsocketnotifier.h> | 38 | #include <qsocketnotifier.h> |
39 | #include <qsignal.h> | 39 | #include <qsignal.h> |
40 | #include <qstring.h> | 40 | #include <qstring.h> |
41 | 41 | ||
42 | namespace Opie { | 42 | namespace Opie { |
43 | namespace Core { | 43 | namespace Core { |
44 | 44 | ||
45 | class OFileNotificationEvent; | ||
46 | |||
45 | /*====================================================================================== | 47 | /*====================================================================================== |
46 | * OFileNotificationType | 48 | * OFileNotificationType |
47 | *======================================================================================*/ | 49 | *======================================================================================*/ |
48 | 50 | ||
49 | /** | 51 | /** |
50 | * @brief An enumerate for the different types of file notifications | 52 | * @brief An enumerate for the different types of file notifications |
51 | * | 53 | * |
52 | * This enumerate provides a means to specify the type of events that you are interest in. | 54 | * This enumerate provides a means to specify the type of events that you are interest in. |
@@ -163,39 +165,51 @@ class OFileNotification : public QObject | |||
163 | **/ | 165 | **/ |
164 | bool isActive() const; | 166 | bool isActive() const; |
165 | /** | 167 | /** |
166 | * @internal | 168 | * @internal |
167 | */ | 169 | */ |
168 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 170 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
169 | 171 | ||
170 | signals: | 172 | signals: |
171 | /** | 173 | void triggered( const QString&, unsigned int, const QString& ); |
172 | * This signal is emitted if an event happens of the specified type happens to the file being watched. | 174 | void accessed( const QString& ); |
173 | **/ | 175 | void modified( const QString& ); |
174 | void triggered( const QString& name ); | 176 | void attributed( const QString& ); |
177 | void closed( const QString&, bool ); | ||
178 | void opened( const QString& ); | ||
179 | void movedTo( const QString&, const QString& ); | ||
180 | void movedFrom( const QString&, const QString& ); | ||
181 | void deletedSubdir( const QString&, const QString& ); | ||
182 | void deletedFile( const QString&, const QString& ); | ||
183 | void createdSubdir( const QString&, const QString& ); | ||
184 | void createdFile( const QString&, const QString& ); | ||
185 | void deleted( const QString& ); | ||
186 | void unmounted( const QString& ); | ||
175 | 187 | ||
176 | protected: | 188 | protected: |
177 | bool activate(); | 189 | bool activate( const OFileNotificationEvent* e ); |
178 | 190 | ||
179 | private slots: | 191 | private slots: |
180 | void inotifyEventHandler(); | 192 | void inotifyEventHandler(); |
181 | 193 | ||
182 | private: | 194 | private: |
183 | bool registerEventHandler(); | 195 | bool registerEventHandler(); |
184 | void unregisterEventHandler(); | 196 | void unregisterEventHandler(); |
185 | 197 | ||
186 | QString _path; | 198 | QString _path; |
187 | OFileNotificationType _type; | 199 | OFileNotificationType _type; |
188 | QSignal _signal; | 200 | QSignal _signal; |
189 | bool _active; | 201 | bool _active; |
190 | bool _multi; | 202 | bool _multi; |
191 | static QSocketNotifier* _sn; | 203 | static QSocketNotifier* _sn; |
192 | int _wd; // inotify watch descriptor | 204 | int _wd; // inotify watch descriptor |
193 | static int _fd; // inotify device descriptor | 205 | static int _fd; // inotify device descriptor |
206 | |||
207 | friend class OFileNotificationEvent; | ||
194 | }; | 208 | }; |
195 | 209 | ||
196 | /*====================================================================================== | 210 | /*====================================================================================== |
197 | * ODirNotification | 211 | * ODirNotification |
198 | *======================================================================================*/ | 212 | *======================================================================================*/ |
199 | 213 | ||
200 | /** | 214 | /** |
201 | * @brief Represents a directory notification | 215 | * @brief Represents a directory notification |
@@ -222,17 +236,54 @@ class ODirNotification : public QObject | |||
222 | * Set @a sshot to True if you want to be notified only once. | 236 | * Set @a sshot to True if you want to be notified only once. |
223 | **/ | 237 | **/ |
224 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); | 238 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); |
225 | 239 | ||
226 | signals: | 240 | signals: |
227 | /** | 241 | /** |
228 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. | 242 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. |
229 | **/ | 243 | **/ |
230 | void triggered( const QString& name ); | 244 | void triggered( const QString&, unsigned int, const QString& ); |
245 | void accessed( const QString& ); | ||
246 | void modified( const QString& ); | ||
247 | void attributed( const QString& ); | ||
248 | void closed( const QString&, bool ); | ||
249 | void opened( const QString& ); | ||
250 | void movedTo( const QString&, const QString& ); | ||
251 | void movedFrom( const QString&, const QString& ); | ||
252 | void deletedSubdir( const QString&, const QString& ); | ||
253 | void deletedFile( const QString&, const QString& ); | ||
254 | void createdSubdir( const QString&, const QString& ); | ||
255 | void createdFile( const QString&, const QString& ); | ||
256 | void deleted( const QString& ); | ||
257 | void unmounted( const QString& ); | ||
258 | }; | ||
259 | |||
260 | /*====================================================================================== | ||
261 | * OFileNotificationEvent | ||
262 | *======================================================================================*/ | ||
263 | |||
264 | class OFileNotificationEvent | ||
265 | { | ||
266 | public: | ||
267 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); | ||
268 | ~OFileNotificationEvent(); | ||
269 | OFileNotification* parent() const { return _parent; }; | ||
270 | int descriptor() const { return _wd; }; | ||
271 | unsigned int mask() const { return _mask; }; | ||
272 | unsigned int cookie() const { return _cookie; }; | ||
273 | QString name() const { return _name; }; | ||
274 | void activate() { _parent->activate( this ); }; | ||
275 | |||
276 | private: | ||
277 | OFileNotification* _parent; | ||
278 | int _wd; | ||
279 | unsigned int _mask; | ||
280 | unsigned int _cookie; | ||
281 | QString _name; | ||
231 | }; | 282 | }; |
232 | 283 | ||
233 | 284 | ||
234 | } | 285 | } |
235 | } | 286 | } |
236 | 287 | ||
237 | #endif | 288 | #endif |
238 | 289 | ||