author | mickeyl <mickeyl> | 2005-06-02 10:38:42 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2005-06-02 10:38:42 (UTC) |
commit | 9d6c759ac1adc5cb654bb3ada6b1d64cddc7217d (patch) (unidiff) | |
tree | 05f7572469fe6c5721b44ed64796bd1104ea3525 | |
parent | b30f28de8d5fa29001bc73a0a0e56ef653f1269f (diff) | |
download | opie-9d6c759ac1adc5cb654bb3ada6b1d64cddc7217d.zip opie-9d6c759ac1adc5cb654bb3ada6b1d64cddc7217d.tar.gz opie-9d6c759ac1adc5cb654bb3ada6b1d64cddc7217d.tar.bz2 |
more work on recursive watches
-rw-r--r-- | examples/opiecore/onotifytest/main.cpp | 2 | ||||
-rw-r--r-- | libopie2/opiecore/linux/ofilenotify.cpp | 79 | ||||
-rw-r--r-- | libopie2/opiecore/linux/ofilenotify.h | 13 |
3 files changed, 67 insertions, 27 deletions
diff --git a/examples/opiecore/onotifytest/main.cpp b/examples/opiecore/onotifytest/main.cpp index 8374c59..b773da9 100644 --- a/examples/opiecore/onotifytest/main.cpp +++ b/examples/opiecore/onotifytest/main.cpp | |||
@@ -1,66 +1,66 @@ | |||
1 | // (C) Michael 'Mickey' Lauer <mickey@Vanille.de> | 1 | // (C) Michael 'Mickey' Lauer <mickey@Vanille.de> |
2 | // LICENSE = "GPLv2" | 2 | // LICENSE = "GPLv2" |
3 | 3 | ||
4 | #include "main.h" | 4 | #include "main.h" |
5 | 5 | ||
6 | /* OPIE */ | 6 | /* OPIE */ |
7 | #include <opie2/odebug.h> | 7 | #include <opie2/odebug.h> |
8 | #include <opie2/oapplication.h> | 8 | #include <opie2/oapplication.h> |
9 | #include <opie2/ofilenotify.h> | 9 | #include <opie2/ofilenotify.h> |
10 | using namespace Opie::Core; | 10 | using namespace Opie::Core; |
11 | 11 | ||
12 | /* QT */ | 12 | /* QT */ |
13 | #include <qdir.h> | 13 | #include <qdir.h> |
14 | #include <qpushbutton.h> | 14 | #include <qpushbutton.h> |
15 | #include <qstringlist.h> | 15 | #include <qstringlist.h> |
16 | #include <qtextstream.h> | 16 | #include <qtextstream.h> |
17 | #include <qmessagebox.h> | 17 | #include <qmessagebox.h> |
18 | 18 | ||
19 | App::App( int argc, char** argv ) : QApplication( argc, argv ) | 19 | App::App( int argc, char** argv ) : QApplication( argc, argv ) |
20 | { | 20 | { |
21 | odebug << "App()" << oendl; | 21 | odebug << "App()" << oendl; |
22 | #if 0 | 22 | #if 0 |
23 | tmpfoo = new OFile( "/tmp/foo" ); | 23 | tmpfoo = new OFile( "/tmp/foo" ); |
24 | if ( tmpfoo->open( IO_ReadWrite ) ) | 24 | if ( tmpfoo->open( IO_ReadWrite ) ) |
25 | { | 25 | { |
26 | QTextStream stream( tmpfoo ); | 26 | QTextStream stream( tmpfoo ); |
27 | stream << "This is my content"; | 27 | stream << "This is my content"; |
28 | } | 28 | } |
29 | 29 | ||
30 | QObject::connect( tmpfoo, SIGNAL(accessed(const QString&)), this, SLOT(quit()) ); | 30 | QObject::connect( tmpfoo, SIGNAL(accessed(const QString&)), this, SLOT(quit()) ); |
31 | QObject::connect( tmpfoo, SIGNAL(closed(const QString&,bool)), this, SLOT(quit()) ); | 31 | QObject::connect( tmpfoo, SIGNAL(closed(const QString&,bool)), this, SLOT(quit()) ); |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | ODirNotification* tmpfoo = new ODirNotification( 0, 0 ); | 34 | ODirNotification* tmpfoo = new ODirNotification( 0, 0 ); |
35 | 35 | ||
36 | int result = tmpfoo->watch( "/tmp/foo", false, CreateFile, 1 ); | 36 | int result = tmpfoo->watch( "/tmp/foo", false, CreateFile, 2 ); |
37 | QObject::connect( tmpfoo, SIGNAL(triggered(const QString&,unsigned int,const QString&)), | 37 | QObject::connect( tmpfoo, SIGNAL(triggered(const QString&,unsigned int,const QString&)), |
38 | this, SLOT(triggered(const QString&,unsigned int,const QString&)) ); | 38 | this, SLOT(triggered(const QString&,unsigned int,const QString&)) ); |
39 | } | 39 | } |
40 | 40 | ||
41 | App::~App() | 41 | App::~App() |
42 | { | 42 | { |
43 | odebug << "~App()" << oendl; | 43 | odebug << "~App()" << oendl; |
44 | } | 44 | } |
45 | 45 | ||
46 | void App::triggered( const QString& str1, unsigned int id, const QString& str2 ) | 46 | void App::triggered( const QString& str1, unsigned int id, const QString& str2 ) |
47 | { | 47 | { |
48 | QMessageBox::information( qApp->desktop(), "info", QString( "%1\n%2\n%3" ).arg( str1 ).arg( id ).arg( str2 ) ); | 48 | QMessageBox::information( qApp->desktop(), "info", QString( "%1\n%2\n%3" ).arg( str1 ).arg( id ).arg( str2 ) ); |
49 | } | 49 | } |
50 | 50 | ||
51 | int main( int argc, char** argv ) | 51 | int main( int argc, char** argv ) |
52 | { | 52 | { |
53 | App* app = new App( argc, argv ); | 53 | App* app = new App( argc, argv ); |
54 | QPushButton* b = new QPushButton( "Click me to close", 0 ); | 54 | QPushButton* b = new QPushButton( "Click me to close", 0 ); |
55 | QObject::connect( b, SIGNAL(clicked()), qApp, SLOT(quit()) ); | 55 | QObject::connect( b, SIGNAL(clicked()), qApp, SLOT(quit()) ); |
56 | b->resize( 200, 200 ); | 56 | b->resize( 200, 200 ); |
57 | b->move( 150, 150 ); | 57 | b->move( 150, 150 ); |
58 | b->show(); | 58 | b->show(); |
59 | app->setMainWidget( b ); | 59 | app->setMainWidget( b ); |
60 | app->exec(); | 60 | app->exec(); |
61 | delete app; | 61 | delete app; |
62 | 62 | ||
63 | return 0; | 63 | return 0; |
64 | 64 | ||
65 | } | 65 | } |
66 | 66 | ||
diff --git a/libopie2/opiecore/linux/ofilenotify.cpp b/libopie2/opiecore/linux/ofilenotify.cpp index 3096f7e..a7820ee 100644 --- a/libopie2/opiecore/linux/ofilenotify.cpp +++ b/libopie2/opiecore/linux/ofilenotify.cpp | |||
@@ -37,381 +37,408 @@ using namespace Opie::Core; | |||
37 | #include <qsignal.h> | 37 | #include <qsignal.h> |
38 | #include <qintdict.h> | 38 | #include <qintdict.h> |
39 | #include <qdir.h> | 39 | #include <qdir.h> |
40 | 40 | ||
41 | /* STD */ | 41 | /* STD */ |
42 | #include <sys/types.h> | 42 | #include <sys/types.h> |
43 | #include <sys/stat.h> | 43 | #include <sys/stat.h> |
44 | #include <sys/ioctl.h> | 44 | #include <sys/ioctl.h> |
45 | #include <fcntl.h> | 45 | #include <fcntl.h> |
46 | #include <assert.h> | 46 | #include <assert.h> |
47 | #include <string.h> | 47 | #include <string.h> |
48 | #include <errno.h> | 48 | #include <errno.h> |
49 | #include <unistd.h> | 49 | #include <unistd.h> |
50 | 50 | ||
51 | static QIntDict<OFileNotification> notification_list; | 51 | static QIntDict<OFileNotification> notification_list; |
52 | 52 | ||
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 | //================================================================================================= | 61 | //================================================================================================= |
62 | // OFile | 62 | // OFile |
63 | //================================================================================================= | 63 | //================================================================================================= |
64 | 64 | ||
65 | OFile::OFile() : QObject( 0, 0 ), QFile() | 65 | OFile::OFile() : QObject( 0, 0 ), QFile() |
66 | { | 66 | { |
67 | qDebug( "OFile()" ); | 67 | qDebug( "OFile()" ); |
68 | } | 68 | } |
69 | 69 | ||
70 | OFile::OFile( const QString& name ) : QObject( 0, 0 ), QFile( name ) | 70 | OFile::OFile( const QString& name ) : QObject( 0, 0 ), QFile( name ) |
71 | { | 71 | { |
72 | qDebug( "OFile()" ); | 72 | qDebug( "OFile()" ); |
73 | } | 73 | } |
74 | 74 | ||
75 | OFile::~OFile() | 75 | OFile::~OFile() |
76 | { | 76 | { |
77 | qDebug( "~OFile()" ); | 77 | qDebug( "~OFile()" ); |
78 | } | 78 | } |
79 | 79 | ||
80 | void OFile::connectNotify( const char *signal ) | 80 | void OFile::connectNotify( const char *signal ) |
81 | { | 81 | { |
82 | QString s = normalizeSignalSlot( signal+1 ); | 82 | QString s = normalizeSignalSlot( signal+1 ); |
83 | qDebug( "OFile::connectNotify() signal = '%s'", (const char*) s ); | 83 | qDebug( "OFile::connectNotify() signal = '%s'", (const char*) s ); |
84 | 84 | ||
85 | if ( s.startsWith( "accessed" ) ) | 85 | if ( s.startsWith( "accessed" ) ) |
86 | 86 | ||
87 | 87 | ||
88 | 88 | ||
89 | 89 | ||
90 | 90 | ||
91 | 91 | ||
92 | 92 | ||
93 | QObject::connectNotify( signal ); | 93 | QObject::connectNotify( signal ); |
94 | 94 | ||
95 | /* | 95 | /* |
96 | void accessed( const QString& ); | 96 | void accessed( const QString& ); |
97 | void modified( const QString& ); | 97 | void modified( const QString& ); |
98 | void attributed( const QString& ); | 98 | void attributed( const QString& ); |
99 | void closed( const QString&, bool ); | 99 | void closed( const QString&, bool ); |
100 | void opened( const QString& ); | 100 | void opened( const QString& ); |
101 | void deleted( const QString& ); | 101 | void deleted( const QString& ); |
102 | void unmounted( const QString& ); | 102 | void unmounted( const QString& ); |
103 | */ | 103 | */ |
104 | 104 | ||
105 | } | 105 | } |
106 | 106 | ||
107 | void OFile::disconnectNotify( const char* signal ) | 107 | void OFile::disconnectNotify( const char* signal ) |
108 | { | 108 | { |
109 | qDebug( "OFile::disconnectNotify() signal = '%s'", signal ); | 109 | qDebug( "OFile::disconnectNotify() signal = '%s'", signal ); |
110 | QObject::disconnectNotify( signal ); | 110 | QObject::disconnectNotify( signal ); |
111 | } | 111 | } |
112 | 112 | ||
113 | int OFile::startWatch( int mode ) | 113 | int OFile::startWatch( int mode ) |
114 | { | 114 | { |
115 | } | 115 | } |
116 | 116 | ||
117 | //================================================================================================= | 117 | //================================================================================================= |
118 | // OFileNotificationEvent | 118 | // OFileNotificationEvent |
119 | //================================================================================================= | 119 | //================================================================================================= |
120 | OFileNotificationEvent::OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ) | 120 | OFileNotificationEvent::OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ) |
121 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) | 121 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) |
122 | { | 122 | { |
123 | qDebug( "OFileNotificationEvent()" ); | 123 | qDebug( "OFileNotificationEvent()" ); |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | OFileNotificationEvent::~OFileNotificationEvent() | 127 | OFileNotificationEvent::~OFileNotificationEvent() |
128 | { | 128 | { |
129 | qDebug( "~OFileNotificationEvent()" ); | 129 | qDebug( "~OFileNotificationEvent()" ); |
130 | } | 130 | } |
131 | 131 | ||
132 | //================================================================================================= | 132 | //================================================================================================= |
133 | // OFileNotification | 133 | // OFileNotification |
134 | //================================================================================================= | 134 | //================================================================================================= |
135 | OFileNotification::OFileNotification( QObject* parent, const char* name ) | 135 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
136 | :QObject( parent, name ), _active( false ), _multi( true ) | 136 | :QObject( parent, name ), _active( false ), _multi( true ) |
137 | { | 137 | { |
138 | qDebug( "OFileNotification::OFileNotification()" ); | 138 | qDebug( "OFileNotification::OFileNotification()" ); |
139 | } | 139 | } |
140 | 140 | ||
141 | 141 | ||
142 | OFileNotification::~OFileNotification() | 142 | OFileNotification::~OFileNotification() |
143 | { | 143 | { |
144 | stop(); | 144 | stop(); |
145 | qDebug( "OFileNotification::~OFileNotification()" ); | 145 | qDebug( "OFileNotification::~OFileNotification()" ); |
146 | } | 146 | } |
147 | 147 | ||
148 | 148 | ||
149 | bool OFileNotification::isActive() const | 149 | bool OFileNotification::isActive() const |
150 | { | 150 | { |
151 | return _active; | 151 | return _active; |
152 | } | 152 | } |
153 | 153 | ||
154 | 154 | ||
155 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) | 155 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) |
156 | { | 156 | { |
157 | // check if path exists and is a regular file | 157 | // check if path exists and is a regular file |
158 | struct stat s; | 158 | struct stat s; |
159 | if ( ::stat( (const char*) path, &s ) == -1 ) | 159 | if ( ::stat( (const char*) path, &s ) == -1 ) |
160 | { | 160 | { |
161 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) ); | 161 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) ); |
162 | return -1; | 162 | return -1; |
163 | } | 163 | } |
164 | if ( !S_ISREG( s.st_mode ) ) | 164 | if ( !S_ISREG( s.st_mode ) ) |
165 | { | 165 | { |
166 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, "not a regular file" ); | 166 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, "not a regular file" ); |
167 | return -1; | 167 | return -1; |
168 | } | 168 | } |
169 | 169 | ||
170 | return startWatching( path, sshot, type ); | 170 | return startWatching( path, sshot, type ); |
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) | 174 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) |
175 | { | 175 | { |
176 | if ( notification_list.isEmpty() ) | 176 | if ( notification_list.isEmpty() ) |
177 | { | 177 | { |
178 | OFileNotification::registerEventHandler(); | 178 | OFileNotification::registerEventHandler(); |
179 | } | 179 | } |
180 | 180 | ||
181 | struct inotify_watch_request iwr; | 181 | struct inotify_watch_request iwr; |
182 | ::memset( &iwr, 0, sizeof iwr ); | 182 | ::memset( &iwr, 0, sizeof iwr ); |
183 | iwr.name = const_cast<char*>( (const char*) path ); | 183 | iwr.name = const_cast<char*>( (const char*) path ); |
184 | iwr.mask = type; | 184 | iwr.mask = type; |
185 | 185 | ||
186 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); | 186 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); |
187 | 187 | ||
188 | if ( _wd < 0 ) | 188 | if ( _wd < 0 ) |
189 | { | 189 | { |
190 | qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) ); | 190 | qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) ); |
191 | return -1; | 191 | return -1; |
192 | } | 192 | } |
193 | 193 | ||
194 | notification_list.insert( _wd, this ); | 194 | notification_list.insert( _wd, this ); |
195 | _path = path; | 195 | _path = path; |
196 | _multi = !sshot; | 196 | _multi = !sshot; |
197 | _type = type; | 197 | _type = type; |
198 | _active = true; | 198 | _active = true; |
199 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); | 199 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); |
200 | return _wd; | 200 | return _wd; |
201 | } | 201 | } |
202 | 202 | ||
203 | 203 | ||
204 | void OFileNotification::stop() | 204 | void OFileNotification::stop() |
205 | { | 205 | { |
206 | notification_list.remove( _wd ); | 206 | notification_list.remove( _wd ); |
207 | _path = QString::null; | 207 | _path = QString::null; |
208 | _wd = 0; | 208 | _wd = 0; |
209 | _active = false; | 209 | _active = false; |
210 | if ( notification_list.isEmpty() ) | 210 | if ( notification_list.isEmpty() ) |
211 | { | 211 | { |
212 | OFileNotification::unregisterEventHandler(); | 212 | OFileNotification::unregisterEventHandler(); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | 215 | ||
216 | 216 | ||
217 | OFileNotificationType OFileNotification::type() const | 217 | OFileNotificationType OFileNotification::type() const |
218 | { | 218 | { |
219 | return _type; | 219 | return _type; |
220 | } | 220 | } |
221 | 221 | ||
222 | 222 | ||
223 | QString OFileNotification::path() const | 223 | QString OFileNotification::path() const |
224 | { | 224 | { |
225 | return _path; | 225 | return _path; |
226 | } | 226 | } |
227 | 227 | ||
228 | 228 | ||
229 | bool OFileNotification::isSingleShot() const | ||
230 | { | ||
231 | return !_multi; | ||
232 | } | ||
233 | |||
234 | |||
229 | bool OFileNotification::activate( const OFileNotificationEvent* e ) | 235 | bool OFileNotification::activate( const OFileNotificationEvent* e ) |
230 | { | 236 | { |
231 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); | 237 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); |
232 | 238 | ||
233 | // dumb signal | 239 | // dumb signal |
234 | _signal.activate(); | 240 | _signal.activate(); |
235 | 241 | ||
236 | // generic signal | 242 | // generic signal |
237 | emit triggered( _path, e->mask(), e->name() ); | 243 | emit triggered( _path, e->mask(), e->name() ); |
238 | 244 | ||
239 | // specialized signals | 245 | // specialized signals |
240 | switch ( e->mask() ) | 246 | switch ( e->mask() ) |
241 | { | 247 | { |
242 | case Access: emit accessed( _path ); break; | 248 | case Access: emit accessed( _path ); break; |
243 | case Modify: emit modified( _path ); break; | 249 | case Modify: emit modified( _path ); break; |
244 | case Attrib: emit attributed( _path); break; | 250 | case Attrib: emit attributed( _path); break; |
245 | case CloseWrite: emit closed( _path, true ); break; | 251 | case CloseWrite: emit closed( _path, true ); break; |
246 | case CloseNoWrite: emit closed( _path, false ); break; | 252 | case CloseNoWrite: emit closed( _path, false ); break; |
247 | case Open: emit opened( _path ); break; | 253 | case Open: emit opened( _path ); break; |
248 | case MovedFrom: emit movedFrom( _path, e->name() ); break; | 254 | case MovedFrom: emit movedFrom( _path, e->name() ); break; |
249 | case MovedTo: emit movedTo( _path, e->name() ); break; | 255 | case MovedTo: emit movedTo( _path, e->name() ); break; |
250 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; | 256 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; |
251 | case DeleteFile: emit deletedFile( _path, e->name() ); break; | 257 | case DeleteFile: emit deletedFile( _path, e->name() ); break; |
252 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; | 258 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; |
253 | case CreateFile: emit createdFile( _path, e->name() ); break; | 259 | case CreateFile: emit createdFile( _path, e->name() ); break; |
254 | case DeleteSelf: emit deleted( _path ); break; | 260 | case DeleteSelf: emit deleted( _path ); break; |
255 | case Unmount: emit unmounted( _path ); break; | 261 | case Unmount: emit unmounted( _path ); break; |
256 | default: assert( 0 ); | 262 | default: assert( 0 ); |
257 | } | 263 | } |
258 | 264 | ||
259 | if ( !_multi ) stop(); | 265 | if ( !_multi ) stop(); |
260 | 266 | ||
261 | return true; | 267 | return true; |
262 | } | 268 | } |
263 | 269 | ||
264 | 270 | ||
265 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 271 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) |
266 | { | 272 | { |
267 | OFileNotification* ofn = new OFileNotification(); | 273 | OFileNotification* ofn = new OFileNotification(); |
268 | ofn->_signal.connect( receiver, member ); | 274 | ofn->_signal.connect( receiver, member ); |
269 | return ofn->watch( path, true, type ) != -1; | 275 | return ofn->watch( path, true, type ) != -1; |
270 | } | 276 | } |
271 | 277 | ||
272 | 278 | ||
273 | void OFileNotification::inotifyEventHandler() | 279 | void OFileNotification::inotifyEventHandler() |
274 | { | 280 | { |
275 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); | 281 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); |
276 | 282 | ||
277 | char buffer[16384]; | 283 | char buffer[16384]; |
278 | ssize_t buffer_i; | 284 | ssize_t buffer_i; |
279 | struct inotify_event *pevent, *event; | 285 | struct inotify_event *pevent, *event; |
280 | ssize_t r; | 286 | ssize_t r; |
281 | size_t event_size; | 287 | size_t event_size; |
282 | int count = 0; | 288 | int count = 0; |
283 | 289 | ||
284 | r = ::read(_fd, buffer, 16384); | 290 | r = ::read(_fd, buffer, 16384); |
285 | 291 | ||
286 | if ( r <= 0 ) | 292 | if ( r <= 0 ) |
287 | return; | 293 | return; |
288 | 294 | ||
289 | buffer_i = 0; | 295 | buffer_i = 0; |
290 | while ( buffer_i < r ) | 296 | while ( buffer_i < r ) |
291 | { | 297 | { |
292 | pevent = (struct inotify_event *)&buffer[buffer_i]; | 298 | pevent = (struct inotify_event *)&buffer[buffer_i]; |
293 | event_size = sizeof(struct inotify_event) + pevent->len; | 299 | event_size = sizeof(struct inotify_event) + pevent->len; |
294 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, | 300 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, |
295 | pevent->cookie, pevent->len ? pevent->name : 0 ); | 301 | pevent->cookie, pevent->len ? pevent->name : 0 ); |
296 | e->activate(); | 302 | e->activate(); |
297 | buffer_i += event_size; | 303 | buffer_i += event_size; |
298 | count++; | 304 | count++; |
299 | } | 305 | } |
300 | 306 | ||
301 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); | 307 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); |
302 | } | 308 | } |
303 | 309 | ||
304 | 310 | ||
305 | bool OFileNotification::registerEventHandler() | 311 | bool OFileNotification::registerEventHandler() |
306 | { | 312 | { |
307 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); | 313 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); |
308 | if ( OFileNotification::_fd < 0 ) | 314 | if ( OFileNotification::_fd < 0 ) |
309 | { | 315 | { |
310 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); | 316 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); |
311 | return false; | 317 | return false; |
312 | } | 318 | } |
313 | 319 | ||
314 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); | 320 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); |
315 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); | 321 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); |
316 | 322 | ||
317 | qDebug( "OFileNotification::registerEventHandler(): done" ); | 323 | qDebug( "OFileNotification::registerEventHandler(): done" ); |
318 | return true; | 324 | return true; |
319 | } | 325 | } |
320 | 326 | ||
321 | 327 | ||
322 | void OFileNotification::unregisterEventHandler() | 328 | void OFileNotification::unregisterEventHandler() |
323 | { | 329 | { |
324 | if ( _sn ) delete _sn; | 330 | if ( _sn ) delete _sn; |
325 | if ( OFileNotification::_fd ) | 331 | if ( OFileNotification::_fd ) |
326 | ::close( OFileNotification::_fd ); | 332 | ::close( OFileNotification::_fd ); |
327 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); | 333 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); |
328 | } | 334 | } |
329 | 335 | ||
330 | //================================================================================================= | 336 | //================================================================================================= |
331 | // ODirNotification | 337 | // ODirNotification |
332 | //================================================================================================= | 338 | //================================================================================================= |
333 | ODirNotification::ODirNotification( QObject* parent, const char* name ) | 339 | ODirNotification::ODirNotification( QObject* parent, const char* name ) |
334 | :QObject( parent, name ) | 340 | :QObject( parent, name ), _topfilenotification( 0 ), _type( Nothing ), _depth( -123 ) |
335 | { | 341 | { |
336 | qDebug( "ODirNotification::ODirNotification()" ); | 342 | qDebug( "ODirNotification::ODirNotification()" ); |
337 | } | 343 | } |
338 | 344 | ||
339 | 345 | ||
340 | ODirNotification::~ODirNotification() | 346 | ODirNotification::~ODirNotification() |
341 | { | 347 | { |
342 | qDebug( "ODirNotification::~ODirNotification()" ); | 348 | qDebug( "ODirNotification::~ODirNotification()" ); |
343 | } | 349 | } |
344 | 350 | ||
351 | /* | ||
352 | Love-Trowbridge recursive directory scanning algorithm: | ||
353 | |||
354 | Step 1. Start at initial directory foo. Add watch. | ||
355 | |||
356 | Step 2. Setup handlers for watch created in Step 1. | ||
357 | Specifically, ensure that a directory created | ||
358 | in foo will result in a handled CREATE_SUBDIR | ||
359 | event. | ||
360 | |||
361 | Step 3. Read the contents of foo. | ||
362 | |||
363 | Step 4. For each subdirectory of foo read in step 3, repeat | ||
364 | step 1. | ||
365 | |||
366 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is | ||
367 | not yet created on bar, repeat step 1 on bar. | ||
368 | */ | ||
345 | 369 | ||
346 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) | 370 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) |
347 | { | 371 | { |
348 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); | 372 | if ( _type == Nothing ) _type = type; // only set it once - for the top level call |
349 | 373 | OFileNotificationType subtype = ( recurse != 0 ) ? (OFileNotificationType) int( _type | CreateSubdir ) : _type; | |
374 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, subtype, recurse ); | ||
350 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); | 375 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); |
351 | int result = fn->startWatching( path, sshot, type ); | 376 | |
377 | int result = fn->startWatching( path, sshot, subtype ); | ||
352 | if ( result != -1 ) | 378 | if ( result != -1 ) |
353 | { | 379 | { |
380 | |||
381 | if ( !_topfilenotification ) _topfilenotification = fn; // only set it once - for the top level call | ||
382 | if ( _depth == -123 ) _depth = recurse; // only set it once - for the top level call | ||
383 | |||
354 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); | 384 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); |
355 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); | 385 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); |
356 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); | 386 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); |
357 | connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); | 387 | connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); |
358 | connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) ); | 388 | connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) ); |
359 | connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) ); | 389 | connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) ); |
360 | connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) ); | 390 | connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) ); |
361 | connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) ); | 391 | connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) ); |
362 | connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) ); | 392 | connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) ); |
363 | connect( fn, SIGNAL( deletedFile( const QString&, const QString& ) ), this, SIGNAL( deletedFile( const QString&, const QString& ) ) );; | 393 | connect( fn, SIGNAL( deletedFile( const QString&, const QString& ) ), this, SIGNAL( deletedFile( const QString&, const QString& ) ) );; |
364 | connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SIGNAL( createdSubdir( const QString&, const QString& ) ) ); | 394 | connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SIGNAL( createdSubdir( const QString&, const QString& ) ) ); |
365 | connect( fn, SIGNAL( createdFile( const QString&, const QString& ) ), this, SIGNAL( createdFile( const QString&, const QString& ) ) ); | 395 | connect( fn, SIGNAL( createdFile( const QString&, const QString& ) ), this, SIGNAL( createdFile( const QString&, const QString& ) ) ); |
366 | connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) ); | 396 | connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) ); |
367 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); | 397 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); |
368 | 398 | ||
369 | if ( recurse ) | 399 | if ( recurse != 0 ) |
370 | { | 400 | { |
401 | connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SLOT( subdirCreated( const QString&, const QString& ) ) ); | ||
402 | |||
371 | QDir directory( path ); | 403 | QDir directory( path ); |
372 | QStringList subdirs = directory.entryList( QDir::Dirs ); | 404 | QStringList subdirs = directory.entryList( QDir::Dirs ); |
373 | 405 | ||
374 | for ( QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it ) | 406 | for ( QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it ) |
375 | { | 407 | { |
376 | if ( (*it) == "." || (*it) == ".." ) continue; | 408 | if ( (*it) == "." || (*it) == ".." ) continue; |
377 | QString subpath = QString( "%1/%2" ).arg( path ).arg( *it ); | 409 | QString subpath = QString( "%1/%2" ).arg( path ).arg( *it ); |
378 | int subresult = watch( subpath, sshot, type, recurse-1 ); | 410 | int subresult = watch( subpath, sshot, subtype, recurse-1 ); |
379 | if ( subresult == -1 ) | 411 | if ( subresult == -1 ) |
380 | { | 412 | { |
381 | qDebug( "ODirNotification::watch(): subresult for '%s' was -1. Interrupting", (const char*) (*it) ); | 413 | qDebug( "ODirNotification::watch(): subresult for '%s' was -1. Interrupting", (const char*) (*it) ); |
382 | return -1; | 414 | return -1; |
383 | } | 415 | } |
384 | } | 416 | } |
385 | } | 417 | } |
386 | //connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); | ||
387 | } | 418 | } |
388 | else return -1; | 419 | else return -1; |
389 | } | 420 | } |
390 | 421 | ||
391 | 422 | ||
392 | // void ODirNotification::subdirCreated( const QString& name ) | 423 | void ODirNotification::subdirCreated( const QString& dir, const QString& subdir ) |
393 | 424 | { | |
394 | 425 | qDebug( "*** ODirNotification::subdirCreated '%s/%s'", (const char*) dir, (const char*) subdir ); | |
395 | /* | 426 | QString newdir = dir; |
396 | Love-Trowbridge recursive directory scanning algorithm: | 427 | if ( newdir.startsWith( _topfilenotification->path() ) ) |
397 | 428 | { | |
398 | Step 1. Start at initial directory foo. Add watch. | 429 | newdir.replace( _topfilenotification->path(), "" ); |
399 | 430 | int level = newdir.contains( '/' ); | |
400 | Step 2. Setup handlers for watch created in Step 1. | 431 | qDebug( "*** dirpart = '%s' ==> level = %d", (const char*) newdir, level ); |
401 | Specifically, ensure that a directory created | ||
402 | in foo will result in a handled CREATE_SUBDIR | ||
403 | event. | ||
404 | |||
405 | Step 3. Read the contents of foo. | ||
406 | 432 | ||
407 | Step 4. For each subdirectory of foo read in step 3, repeat | 433 | if ( _depth == -1 || _depth > level ) |
408 | step 1. | 434 | { |
435 | watch( QString( "%1/%2" ).arg( dir ).arg( subdir ), _topfilenotification->isSingleShot(), _topfilenotification->type(), _depth == -1 ? -1 : _depth-level-1 ); | ||
436 | } | ||
409 | 437 | ||
410 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is | 438 | } |
411 | not yet created on bar, repeat step 1 on bar. | 439 | } |
412 | */ | ||
413 | 440 | ||
414 | 441 | ||
415 | } // namespace Ui | 442 | } // namespace Ui |
416 | 443 | ||
417 | } // namespace Opie | 444 | } // namespace Opie |
diff --git a/libopie2/opiecore/linux/ofilenotify.h b/libopie2/opiecore/linux/ofilenotify.h index 05343b9..17e6b5d 100644 --- a/libopie2/opiecore/linux/ofilenotify.h +++ b/libopie2/opiecore/linux/ofilenotify.h | |||
@@ -1,326 +1,339 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of the Opie Project | 2 | This file is part of the Opie Project |
3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> | 3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> |
4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> | 4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> |
5 | .>+-= | 5 | .>+-= |
6 | _;:, .> :=|. This program is free software; you can | 6 | _;:, .> :=|. This program is free software; you can |
7 | .> <`_, > . <= redistribute it and/or modify it under | 7 | .> <`_, > . <= redistribute it and/or modify it under |
8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | 8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public |
9 | .="- .-=="i, .._ License as published by the Free Software | 9 | .="- .-=="i, .._ License as published by the Free Software |
10 | - . .-<_> .<> Foundation; version 2 of the License. | 10 | - . .-<_> .<> Foundation; version 2 of the License. |
11 | ._= =} : | 11 | ._= =} : |
12 | .%`+i> _;_. | 12 | .%`+i> _;_. |
13 | .i_,=:_. -<s. This program is distributed in the hope that | 13 | .i_,=:_. -<s. This program is distributed in the hope that |
14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | 14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; |
15 | : .. .:, . . . without even the implied warranty of | 15 | : .. .:, . . . without even the implied warranty of |
16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | 16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A |
17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | 17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU |
18 | ..}^=.= = ; Library General Public License for more | 18 | ..}^=.= = ; Library General Public License for more |
19 | ++= -. .` .: details. | 19 | ++= -. .` .: details. |
20 | : = ...= . :.=- | 20 | : = ...= . :.=- |
21 | -. .:....=;==+<; You should have received a copy of the GNU | 21 | -. .:....=;==+<; You should have received a copy of the GNU |
22 | -_. . . )=. = Library General Public License along with | 22 | -_. . . )=. = Library General Public License along with |
23 | -- :-=` this library; see the file COPYING.LIB. | 23 | -- :-=` this library; see the file COPYING.LIB. |
24 | If not, write to the Free Software Foundation, | 24 | If not, write to the Free Software Foundation, |
25 | Inc., 59 Temple Place - Suite 330, | 25 | Inc., 59 Temple Place - Suite 330, |
26 | Boston, MA 02111-1307, USA. | 26 | Boston, MA 02111-1307, USA. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #ifndef OFILENOTIFY_H | 29 | #ifndef OFILENOTIFY_H |
30 | #define OFILENOTIFY_H | 30 | #define OFILENOTIFY_H |
31 | #if defined (__GNUC__) && (__GNUC__ < 3) | 31 | #if defined (__GNUC__) && (__GNUC__ < 3) |
32 | #define _GNU_SOURCE | 32 | #define _GNU_SOURCE |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #include "linux_inotify.h" | 35 | #include "linux_inotify.h" |
36 | 36 | ||
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 | #include <qobject.h> | 41 | #include <qobject.h> |
42 | #include <qfile.h> | 42 | #include <qfile.h> |
43 | 43 | ||
44 | namespace Opie { | 44 | namespace Opie { |
45 | namespace Core { | 45 | namespace Core { |
46 | 46 | ||
47 | class OFile : public QObject, public QFile | 47 | class OFile : public QObject, public QFile |
48 | { | 48 | { |
49 | Q_OBJECT | 49 | Q_OBJECT |
50 | 50 | ||
51 | public: | 51 | public: |
52 | OFile(); | 52 | OFile(); |
53 | OFile( const QString & name ); | 53 | OFile( const QString & name ); |
54 | virtual ~OFile(); | 54 | virtual ~OFile(); |
55 | 55 | ||
56 | protected: | 56 | protected: |
57 | virtual void connectNotify( const char* signal ); | 57 | virtual void connectNotify( const char* signal ); |
58 | virtual void disconnectNotify( const char* signal ); | 58 | virtual void disconnectNotify( const char* signal ); |
59 | 59 | ||
60 | private: | 60 | private: |
61 | int startWatch( int mode ); | 61 | int startWatch( int mode ); |
62 | 62 | ||
63 | signals: | 63 | signals: |
64 | void accessed( const QString& ); | 64 | void accessed( const QString& ); |
65 | void modified( const QString& ); | 65 | void modified( const QString& ); |
66 | void attributed( const QString& ); | 66 | void attributed( const QString& ); |
67 | void closed( const QString&, bool ); | 67 | void closed( const QString&, bool ); |
68 | void opened( const QString& ); | 68 | void opened( const QString& ); |
69 | void deleted( const QString& ); | 69 | void deleted( const QString& ); |
70 | void unmounted( const QString& ); | 70 | void unmounted( const QString& ); |
71 | }; | 71 | }; |
72 | 72 | ||
73 | /* | 73 | /* |
74 | void movedTo( const QString&, const QString& ); | 74 | void movedTo( const QString&, const QString& ); |
75 | void movedFrom( const QString&, const QString& ); | 75 | void movedFrom( const QString&, const QString& ); |
76 | void deletedSubdir( const QString&, const QString& ); | 76 | void deletedSubdir( const QString&, const QString& ); |
77 | void deletedFile( const QString&, const QString& ); | 77 | void deletedFile( const QString&, const QString& ); |
78 | void createdSubdir( const QString&, const QString& ); | 78 | void createdSubdir( const QString&, const QString& ); |
79 | void createdFile( const QString&, const QString& ); | 79 | void createdFile( const QString&, const QString& ); |
80 | */ | 80 | */ |
81 | 81 | ||
82 | class OFileNotificationEvent; | 82 | class OFileNotificationEvent; |
83 | 83 | ||
84 | /*====================================================================================== | 84 | /*====================================================================================== |
85 | * OFileNotificationType | 85 | * OFileNotificationType |
86 | *======================================================================================*/ | 86 | *======================================================================================*/ |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * @brief An enumerate for the different types of file notifications | 89 | * @brief An enumerate for the different types of file notifications |
90 | * | 90 | * |
91 | * This enumerate provides a means to specify the type of events that you are interest in. | 91 | * This enumerate provides a means to specify the type of events that you are interest in. |
92 | * Valid values are: | 92 | * Valid values are: |
93 | * <ul> | 93 | * <ul> |
94 | * <li>Access: The file was accessed (read) | 94 | * <li>Access: The file was accessed (read) |
95 | * <li>Modify The file was modified (write,truncate) | 95 | * <li>Modify The file was modified (write,truncate) |
96 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) | 96 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) |
97 | * <li>CloseWrite = Writable file was closed | 97 | * <li>CloseWrite = Writable file was closed |
98 | * <li>CloseNoWrite = Unwritable file was closed | 98 | * <li>CloseNoWrite = Unwritable file was closed |
99 | * <li>Open = File was opened | 99 | * <li>Open = File was opened |
100 | * <li>MovedFrom = File was moved from X | 100 | * <li>MovedFrom = File was moved from X |
101 | * <li>MovedTo = File was moved to Y | 101 | * <li>MovedTo = File was moved to Y |
102 | * <li>DeleteSubdir = Subdir was deleted | 102 | * <li>DeleteSubdir = Subdir was deleted |
103 | * <li>DeleteFile = Subfile was deleted | 103 | * <li>DeleteFile = Subfile was deleted |
104 | * <li>CreateSubdir = Subdir was created | 104 | * <li>CreateSubdir = Subdir was created |
105 | * <li>CreateFile = Subfile was created | 105 | * <li>CreateFile = Subfile was created |
106 | * <li>DeleteSelf = Self was deleted | 106 | * <li>DeleteSelf = Self was deleted |
107 | * <li>Unmount = The backing filesystem was unmounted | 107 | * <li>Unmount = The backing filesystem was unmounted |
108 | * </ul> | 108 | * </ul> |
109 | * | 109 | * |
110 | **/ | 110 | **/ |
111 | 111 | ||
112 | enum OFileNotificationType | 112 | enum OFileNotificationType |
113 | { | 113 | { |
114 | Nothing = 0, | ||
114 | Access = IN_ACCESS, | 115 | Access = IN_ACCESS, |
115 | Modify = IN_MODIFY, | 116 | Modify = IN_MODIFY, |
116 | Attrib = IN_ATTRIB, | 117 | Attrib = IN_ATTRIB, |
117 | CloseWrite = IN_CLOSE_WRITE, | 118 | CloseWrite = IN_CLOSE_WRITE, |
118 | CloseNoWrite = IN_CLOSE_NOWRITE, | 119 | CloseNoWrite = IN_CLOSE_NOWRITE, |
119 | Open = IN_OPEN, | 120 | Open = IN_OPEN, |
120 | MovedFrom = IN_MOVED_FROM, | 121 | MovedFrom = IN_MOVED_FROM, |
121 | MovedTo = IN_MOVED_TO, | 122 | MovedTo = IN_MOVED_TO, |
122 | DeleteSubdir = IN_DELETE_SUBDIR, | 123 | DeleteSubdir = IN_DELETE_SUBDIR, |
123 | DeleteFile = IN_DELETE_FILE, | 124 | DeleteFile = IN_DELETE_FILE, |
124 | CreateSubdir = IN_CREATE_SUBDIR, | 125 | CreateSubdir = IN_CREATE_SUBDIR, |
125 | CreateFile = IN_CREATE_FILE, | 126 | CreateFile = IN_CREATE_FILE, |
126 | DeleteSelf = IN_DELETE_SELF, | 127 | DeleteSelf = IN_DELETE_SELF, |
127 | Unmount = IN_UNMOUNT, | 128 | Unmount = IN_UNMOUNT, |
128 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ | 129 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ |
129 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ | 130 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ |
130 | }; | 131 | }; |
131 | 132 | ||
132 | /*====================================================================================== | 133 | /*====================================================================================== |
133 | * OFileNotification | 134 | * OFileNotification |
134 | *======================================================================================*/ | 135 | *======================================================================================*/ |
135 | 136 | ||
136 | /** | 137 | /** |
137 | * @brief Represents a file notification | 138 | * @brief Represents a file notification |
138 | * | 139 | * |
139 | * This class allows to watch for events happening to files. | 140 | * This class allows to watch for events happening to files. |
140 | * It uses the inotify linux (2.6.x) kernel interface. | 141 | * It uses the inotify linux (2.6.x) kernel interface. |
141 | * | 142 | * |
142 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 143 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
143 | * | 144 | * |
144 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 145 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
145 | * | 146 | * |
146 | **/ | 147 | **/ |
147 | 148 | ||
148 | class OFileNotification : public QObject | 149 | class OFileNotification : public QObject |
149 | { | 150 | { |
150 | Q_OBJECT | 151 | Q_OBJECT |
151 | 152 | ||
152 | public: | 153 | public: |
153 | OFileNotification( QObject* parent = 0, const char* name = 0 ); | 154 | OFileNotification( QObject* parent = 0, const char* name = 0 ); |
154 | ~OFileNotification(); | 155 | ~OFileNotification(); |
155 | /** | 156 | /** |
156 | * This static function calls a slot when an event with @a type happens to file @a path. | 157 | * This static function calls a slot when an event with @a type happens to file @a path. |
157 | * | 158 | * |
158 | * It is very convenient to use this function because you do not need to | 159 | * It is very convenient to use this function because you do not need to |
159 | * bother with a timerEvent or to create a local QTimer object. | 160 | * bother with a timerEvent or to create a local QTimer object. |
160 | * | 161 | * |
161 | * Example: | 162 | * Example: |
162 | * <pre> | 163 | * <pre> |
163 | * | 164 | * |
164 | * #include <opie2/oapplication.h> | 165 | * #include <opie2/oapplication.h> |
165 | * #include <opie2/ofilenotify.h> | 166 | * #include <opie2/ofilenotify.h> |
166 | * using namespace Opie::Core; | 167 | * using namespace Opie::Core; |
167 | * | 168 | * |
168 | * int main( int argc, char **argv ) | 169 | * int main( int argc, char **argv ) |
169 | * { | 170 | * { |
170 | * OApplication a( argc, argv, "File Notification Example" ); | 171 | * OApplication a( argc, argv, "File Notification Example" ); |
171 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); | 172 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); |
172 | * ... // create and show your widgets | 173 | * ... // create and show your widgets |
173 | * return a.exec(); | 174 | * return a.exec(); |
174 | * } | 175 | * } |
175 | * </pre> | 176 | * </pre> |
176 | * | 177 | * |
177 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. | 178 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. |
178 | * | 179 | * |
179 | * | 180 | * |
180 | * The @a receiver is the receiving object and the @a member is the slot. | 181 | * The @a receiver is the receiving object and the @a member is the slot. |
181 | **/ | 182 | **/ |
182 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); | 183 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); |
183 | /** | 184 | /** |
184 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. | 185 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. |
185 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. | 186 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. |
186 | **/ | 187 | **/ |
187 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 188 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
188 | /** | 189 | /** |
189 | * Stop watching for file events. | 190 | * Stop watching for file events. |
190 | **/ | 191 | **/ |
191 | void stop(); | 192 | void stop(); |
192 | /** | 193 | /** |
193 | * @returns the notification type as set by @ref start(). | 194 | * @returns the notification type as set by @ref start(). |
194 | **/ | 195 | **/ |
195 | OFileNotificationType type() const; | 196 | OFileNotificationType type() const; |
196 | /** | 197 | /** |
197 | * @returns the path to the file being watched by this instance. | 198 | * @returns the path to the file being watched by this instance. |
198 | **/ | 199 | **/ |
199 | QString path() const; | 200 | QString path() const; |
200 | /** | 201 | /** |
202 | * @returns if the notification is single-shot | ||
203 | */ | ||
204 | bool isSingleShot() const; | ||
205 | /** | ||
201 | * @returns if a file is currently being watched. | 206 | * @returns if a file is currently being watched. |
202 | **/ | 207 | **/ |
203 | bool isActive() const; | 208 | bool isActive() const; |
204 | /** | 209 | /** |
205 | * @internal | 210 | * @internal |
206 | */ | 211 | */ |
207 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 212 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
208 | 213 | ||
209 | signals: | 214 | signals: |
210 | void triggered( const QString&, unsigned int, const QString& ); | 215 | void triggered( const QString&, unsigned int, const QString& ); |
211 | void accessed( const QString& ); | 216 | void accessed( const QString& ); |
212 | void modified( const QString& ); | 217 | void modified( const QString& ); |
213 | void attributed( const QString& ); | 218 | void attributed( const QString& ); |
214 | void closed( const QString&, bool ); | 219 | void closed( const QString&, bool ); |
215 | void opened( const QString& ); | 220 | void opened( const QString& ); |
216 | void movedTo( const QString&, const QString& ); | 221 | void movedTo( const QString&, const QString& ); |
217 | void movedFrom( const QString&, const QString& ); | 222 | void movedFrom( const QString&, const QString& ); |
218 | void deletedSubdir( const QString&, const QString& ); | 223 | void deletedSubdir( const QString&, const QString& ); |
219 | void deletedFile( const QString&, const QString& ); | 224 | void deletedFile( const QString&, const QString& ); |
220 | void createdSubdir( const QString&, const QString& ); | 225 | void createdSubdir( const QString&, const QString& ); |
221 | void createdFile( const QString&, const QString& ); | 226 | void createdFile( const QString&, const QString& ); |
222 | void deleted( const QString& ); | 227 | void deleted( const QString& ); |
223 | void unmounted( const QString& ); | 228 | void unmounted( const QString& ); |
224 | 229 | ||
225 | protected: | 230 | protected: |
226 | bool activate( const OFileNotificationEvent* e ); | 231 | bool activate( const OFileNotificationEvent* e ); |
227 | 232 | ||
228 | private slots: | 233 | private slots: |
229 | void inotifyEventHandler(); | 234 | void inotifyEventHandler(); |
230 | 235 | ||
231 | private: | 236 | private: |
232 | bool registerEventHandler(); | 237 | bool registerEventHandler(); |
233 | void unregisterEventHandler(); | 238 | void unregisterEventHandler(); |
234 | 239 | ||
235 | QString _path; | 240 | QString _path; |
236 | OFileNotificationType _type; | 241 | OFileNotificationType _type; |
237 | QSignal _signal; | 242 | QSignal _signal; |
238 | bool _active; | 243 | bool _active; |
239 | bool _multi; | 244 | bool _multi; |
240 | static QSocketNotifier* _sn; | 245 | static QSocketNotifier* _sn; |
241 | int _wd; // inotify watch descriptor | 246 | int _wd; // inotify watch descriptor |
242 | static int _fd; // inotify device descriptor | 247 | static int _fd; // inotify device descriptor |
243 | 248 | ||
244 | friend class OFileNotificationEvent; | 249 | friend class OFileNotificationEvent; |
245 | }; | 250 | }; |
246 | 251 | ||
247 | /*====================================================================================== | 252 | /*====================================================================================== |
248 | * ODirNotification | 253 | * ODirNotification |
249 | *======================================================================================*/ | 254 | *======================================================================================*/ |
250 | 255 | ||
251 | /** | 256 | /** |
252 | * @brief Represents a directory notification | 257 | * @brief Represents a directory notification |
253 | * | 258 | * |
254 | * This class allows to watch for events happening to directories | 259 | * This class allows to watch for events happening to directories |
255 | * It uses the OFileNotification class | 260 | * It uses the OFileNotification class |
256 | * | 261 | * |
257 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 262 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
258 | * | 263 | * |
259 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 264 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
260 | * | 265 | * |
261 | **/ | 266 | **/ |
262 | 267 | ||
263 | class ODirNotification : public QObject | 268 | class ODirNotification : public QObject |
264 | { | 269 | { |
265 | Q_OBJECT | 270 | Q_OBJECT |
266 | 271 | ||
267 | public: | 272 | public: |
268 | ODirNotification( QObject* parent = 0, const char* name = 0 ); | 273 | ODirNotification( QObject* parent = 0, const char* name = 0 ); |
269 | ~ODirNotification(); | 274 | ~ODirNotification(); |
270 | /** | 275 | /** |
271 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, | 276 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, |
272 | * use 0 for no recursion and -1 for unlimited recursion. | 277 | * use 0 for no recursion and -1 for unlimited recursion. |
273 | * Set @a sshot to True if you want to be notified only once. | 278 | * Set @a sshot to True if you want to be notified only once. |
274 | **/ | 279 | **/ |
275 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); | 280 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); |
276 | 281 | ||
277 | signals: | 282 | signals: |
278 | /** | 283 | /** |
279 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. | 284 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. |
280 | **/ | 285 | **/ |
281 | void triggered( const QString&, unsigned int, const QString& ); | 286 | void triggered( const QString&, unsigned int, const QString& ); |
282 | void accessed( const QString& ); | 287 | void accessed( const QString& ); |
283 | void modified( const QString& ); | 288 | void modified( const QString& ); |
284 | void attributed( const QString& ); | 289 | void attributed( const QString& ); |
285 | void closed( const QString&, bool ); | 290 | void closed( const QString&, bool ); |
286 | void opened( const QString& ); | 291 | void opened( const QString& ); |
287 | void movedTo( const QString&, const QString& ); | 292 | void movedTo( const QString&, const QString& ); |
288 | void movedFrom( const QString&, const QString& ); | 293 | void movedFrom( const QString&, const QString& ); |
289 | void deletedSubdir( const QString&, const QString& ); | 294 | void deletedSubdir( const QString&, const QString& ); |
290 | void deletedFile( const QString&, const QString& ); | 295 | void deletedFile( const QString&, const QString& ); |
291 | void createdSubdir( const QString&, const QString& ); | 296 | void createdSubdir( const QString&, const QString& ); |
292 | void createdFile( const QString&, const QString& ); | 297 | void createdFile( const QString&, const QString& ); |
293 | void deleted( const QString& ); | 298 | void deleted( const QString& ); |
294 | void unmounted( const QString& ); | 299 | void unmounted( const QString& ); |
300 | |||
301 | private slots: | ||
302 | void subdirCreated( const QString&, const QString& ); | ||
303 | |||
304 | private: | ||
305 | OFileNotification* _topfilenotification; | ||
306 | OFileNotificationType _type; | ||
307 | int _depth; | ||
295 | }; | 308 | }; |
296 | 309 | ||
297 | /*====================================================================================== | 310 | /*====================================================================================== |
298 | * OFileNotificationEvent | 311 | * OFileNotificationEvent |
299 | *======================================================================================*/ | 312 | *======================================================================================*/ |
300 | 313 | ||
301 | class OFileNotificationEvent | 314 | class OFileNotificationEvent |
302 | { | 315 | { |
303 | public: | 316 | public: |
304 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); | 317 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); |
305 | ~OFileNotificationEvent(); | 318 | ~OFileNotificationEvent(); |
306 | OFileNotification* parent() const { return _parent; }; | 319 | OFileNotification* parent() const { return _parent; }; |
307 | int descriptor() const { return _wd; }; | 320 | int descriptor() const { return _wd; }; |
308 | unsigned int mask() const { return _mask; }; | 321 | unsigned int mask() const { return _mask; }; |
309 | unsigned int cookie() const { return _cookie; }; | 322 | unsigned int cookie() const { return _cookie; }; |
310 | QString name() const { return _name; }; | 323 | QString name() const { return _name; }; |
311 | void activate() { _parent->activate( this ); }; | 324 | void activate() { _parent->activate( this ); }; |
312 | 325 | ||
313 | private: | 326 | private: |
314 | OFileNotification* _parent; | 327 | OFileNotification* _parent; |
315 | int _wd; | 328 | int _wd; |
316 | unsigned int _mask; | 329 | unsigned int _mask; |
317 | unsigned int _cookie; | 330 | unsigned int _cookie; |
318 | QString _name; | 331 | QString _name; |
319 | }; | 332 | }; |
320 | 333 | ||
321 | 334 | ||
322 | } | 335 | } |
323 | } | 336 | } |
324 | 337 | ||
325 | #endif | 338 | #endif |
326 | 339 | ||