author | mickeyl <mickeyl> | 2005-05-10 13:30:51 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2005-05-10 13:30:51 (UTC) |
commit | e31f22952f47aeb54b206349f1e469704a6a6e8f (patch) (unidiff) | |
tree | 2aa06bf1ebd9850b1e987d1dcc94794699a0c9fe | |
parent | 9bcf6a5112d31ffdc196ebcd22a584c68f9f7b1e (diff) | |
download | opie-e31f22952f47aeb54b206349f1e469704a6a6e8f.zip opie-e31f22952f47aeb54b206349f1e469704a6a6e8f.tar.gz opie-e31f22952f47aeb54b206349f1e469704a6a6e8f.tar.bz2 |
add foundation for a much more intuitive API for file notifications
-rw-r--r-- | examples/opiecore/onotifytest/.cvsignore | 6 | ||||
-rw-r--r-- | examples/opiecore/onotifytest/main.cpp | 59 | ||||
-rw-r--r-- | examples/opiecore/onotifytest/onotifytest.pro | 16 | ||||
-rw-r--r-- | examples/opiecore/opiecore.pro | 2 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 58 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 37 |
6 files changed, 176 insertions, 2 deletions
diff --git a/examples/opiecore/onotifytest/.cvsignore b/examples/opiecore/onotifytest/.cvsignore new file mode 100644 index 0000000..8f7300c --- a/dev/null +++ b/examples/opiecore/onotifytest/.cvsignore | |||
@@ -0,0 +1,6 @@ | |||
1 | Makefile* | ||
2 | moc* | ||
3 | *moc | ||
4 | *.o | ||
5 | ~* | ||
6 | |||
diff --git a/examples/opiecore/onotifytest/main.cpp b/examples/opiecore/onotifytest/main.cpp new file mode 100644 index 0000000..467ebc9 --- a/dev/null +++ b/examples/opiecore/onotifytest/main.cpp | |||
@@ -0,0 +1,59 @@ | |||
1 | // (C) Michael 'Mickey' Lauer <mickey@Vanille.de> | ||
2 | // LICENSE = "GPLv2" | ||
3 | |||
4 | /* OPIE */ | ||
5 | #include <opie2/odebug.h> | ||
6 | #include <opie2/oapplication.h> | ||
7 | #include <opie2/ofilenotify.h> | ||
8 | using namespace Opie::Core; | ||
9 | |||
10 | /* QT */ | ||
11 | #include <qpushbutton.h> | ||
12 | #include <qtextstream.h> | ||
13 | |||
14 | class App : public OApplication | ||
15 | { | ||
16 | |||
17 | public: | ||
18 | OFile* tmpfoo; | ||
19 | |||
20 | App( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify test" ) | ||
21 | { | ||
22 | odebug << "App()" << oendl; | ||
23 | |||
24 | tmpfoo = new OFile( "/tmp/foo" ); | ||
25 | if ( tmpfoo->open( IO_ReadWrite ) ) | ||
26 | { | ||
27 | QTextStream stream( tmpfoo ); | ||
28 | stream << "This is my content"; | ||
29 | } | ||
30 | |||
31 | QObject::connect( tmpfoo, SIGNAL(accessed(const QString&)), this, SLOT(quit()) ); | ||
32 | QObject::connect( tmpfoo, SIGNAL(closed(const QString&,bool)), this, SLOT(quit()) ); | ||
33 | } | ||
34 | |||
35 | ~App() | ||
36 | { | ||
37 | odebug << "~App()" << oendl; | ||
38 | |||
39 | delete tmpfoo; | ||
40 | } | ||
41 | |||
42 | }; | ||
43 | |||
44 | int main( int argc, char** argv ) | ||
45 | { | ||
46 | App* app = new App( argc, argv ); | ||
47 | QPushButton* b = new QPushButton( "Click me to close", 0 ); | ||
48 | QObject::connect( b, SIGNAL(clicked()), app, SLOT(quit()) ); | ||
49 | b->resize( 200, 200 ); | ||
50 | b->move( 150, 150 ); | ||
51 | b->show(); | ||
52 | app->setMainWidget( b ); | ||
53 | app->exec(); | ||
54 | delete app; | ||
55 | |||
56 | return 0; | ||
57 | |||
58 | } | ||
59 | |||
diff --git a/examples/opiecore/onotifytest/onotifytest.pro b/examples/opiecore/onotifytest/onotifytest.pro new file mode 100644 index 0000000..4e0faec --- a/dev/null +++ b/examples/opiecore/onotifytest/onotifytest.pro | |||
@@ -0,0 +1,16 @@ | |||
1 | TEMPLATE = app | ||
2 | CONFIG = qt warn_on | ||
3 | SOURCES = main.cpp | ||
4 | INCLUDEPATH += $(OPIEDIR)/include | ||
5 | DEPENDPATH += $(OPIEDIR)/include | ||
6 | LIBS += -lopiecore2 | ||
7 | TARGET = onotifytest | ||
8 | |||
9 | !contains( platform, x11 ) { | ||
10 | include( $(OPIEDIR)/include.pro ) | ||
11 | } | ||
12 | |||
13 | contains( platform, x11 ) { | ||
14 | LIBS += -L$(OPIEDIR)/lib -Wl,-rpath,$(OPIEDIR)/lib | ||
15 | } | ||
16 | |||
diff --git a/examples/opiecore/opiecore.pro b/examples/opiecore/opiecore.pro index 1f86a40..3550055 100644 --- a/examples/opiecore/opiecore.pro +++ b/examples/opiecore/opiecore.pro | |||
@@ -1,2 +1,2 @@ | |||
1 | TEMPLATE = subdirs | 1 | TEMPLATE = subdirs |
2 | unix:SUBDIRS = odebugdemo oconfigdemo oglobalsettingsdemo onotifydemo oprocessdemo oplugins oinputsystemdemo | 2 | unix:SUBDIRS = odebugdemo oconfigdemo oglobalsettingsdemo onotifydemo onotifytest oprocessdemo oplugins oinputsystemdemo |
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 4264327..36ec6bf 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp | |||
@@ -1,350 +1,406 @@ | |||
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 | #include "ofilenotify.h" | 29 | #include "ofilenotify.h" |
30 | using namespace Opie::Core; | 30 | using namespace Opie::Core; |
31 | 31 | ||
32 | /* OPIE */ | 32 | /* OPIE */ |
33 | 33 | ||
34 | /* QT */ | 34 | /* QT */ |
35 | #include <qobject.h> | 35 | #include <qobject.h> |
36 | #include <qsocketnotifier.h> | 36 | #include <qsocketnotifier.h> |
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 | ||
63 | //================================================================================================= | ||
64 | |||
65 | OFile::OFile() : QObject( 0, 0 ), QFile() | ||
66 | { | ||
67 | qDebug( "OFile()" ); | ||
68 | } | ||
69 | |||
70 | OFile::OFile( const QString& name ) : QObject( 0, 0 ), QFile( name ) | ||
71 | { | ||
72 | qDebug( "OFile()" ); | ||
73 | } | ||
74 | |||
75 | OFile::~OFile() | ||
76 | { | ||
77 | qDebug( "~OFile()" ); | ||
78 | } | ||
79 | |||
80 | void OFile::connectNotify( const char *signal ) | ||
81 | { | ||
82 | QString s = normalizeSignalSlot( signal+1 ); | ||
83 | qDebug( "OFile::connectNotify() signal = '%s'", (const char*) s ); | ||
84 | |||
85 | if ( s.startsWith( "accessed" ) ) | ||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | |||
92 | |||
93 | QObject::connectNotify( signal ); | ||
94 | |||
95 | /* | ||
96 | void accessed( const QString& ); | ||
97 | void modified( const QString& ); | ||
98 | void attributed( const QString& ); | ||
99 | void closed( const QString&, bool ); | ||
100 | void opened( const QString& ); | ||
101 | void deleted( const QString& ); | ||
102 | void unmounted( const QString& ); | ||
103 | */ | ||
104 | |||
105 | } | ||
106 | |||
107 | void OFile::disconnectNotify( const char* signal ) | ||
108 | { | ||
109 | qDebug( "OFile::disconnectNotify() signal = '%s'", signal ); | ||
110 | QObject::disconnectNotify( signal ); | ||
111 | } | ||
112 | |||
113 | int OFile::startWatch( int mode ) | ||
114 | { | ||
115 | } | ||
116 | |||
117 | //================================================================================================= | ||
62 | // OFileNotificationEvent | 118 | // OFileNotificationEvent |
63 | //================================================================================================= | 119 | //================================================================================================= |
64 | 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 ) |
65 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) | 121 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) |
66 | { | 122 | { |
67 | qDebug( "OFileNotificationEvent()" ); | 123 | qDebug( "OFileNotificationEvent()" ); |
68 | } | 124 | } |
69 | 125 | ||
70 | 126 | ||
71 | OFileNotificationEvent::~OFileNotificationEvent() | 127 | OFileNotificationEvent::~OFileNotificationEvent() |
72 | { | 128 | { |
73 | qDebug( "~OFileNotificationEvent()" ); | 129 | qDebug( "~OFileNotificationEvent()" ); |
74 | } | 130 | } |
75 | 131 | ||
76 | //================================================================================================= | 132 | //================================================================================================= |
77 | // OFileNotification | 133 | // OFileNotification |
78 | //================================================================================================= | 134 | //================================================================================================= |
79 | OFileNotification::OFileNotification( QObject* parent, const char* name ) | 135 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
80 | :QObject( parent, name ), _active( false ), _multi( true ) | 136 | :QObject( parent, name ), _active( false ), _multi( true ) |
81 | { | 137 | { |
82 | qDebug( "OFileNotification::OFileNotification()" ); | 138 | qDebug( "OFileNotification::OFileNotification()" ); |
83 | } | 139 | } |
84 | 140 | ||
85 | 141 | ||
86 | OFileNotification::~OFileNotification() | 142 | OFileNotification::~OFileNotification() |
87 | { | 143 | { |
88 | stop(); | 144 | stop(); |
89 | qDebug( "OFileNotification::~OFileNotification()" ); | 145 | qDebug( "OFileNotification::~OFileNotification()" ); |
90 | } | 146 | } |
91 | 147 | ||
92 | 148 | ||
93 | bool OFileNotification::isActive() const | 149 | bool OFileNotification::isActive() const |
94 | { | 150 | { |
95 | return _active; | 151 | return _active; |
96 | } | 152 | } |
97 | 153 | ||
98 | 154 | ||
99 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) | 155 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) |
100 | { | 156 | { |
101 | // check if path exists and is a regular file | 157 | // check if path exists and is a regular file |
102 | struct stat s; | 158 | struct stat s; |
103 | if ( ::stat( (const char*) path, &s ) == -1 ) | 159 | if ( ::stat( (const char*) path, &s ) == -1 ) |
104 | { | 160 | { |
105 | 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 ) ); |
106 | return -1; | 162 | return -1; |
107 | } | 163 | } |
108 | if ( !S_ISREG( s.st_mode ) ) | 164 | if ( !S_ISREG( s.st_mode ) ) |
109 | { | 165 | { |
110 | 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" ); |
111 | return -1; | 167 | return -1; |
112 | } | 168 | } |
113 | 169 | ||
114 | return startWatching( path, sshot, type ); | 170 | return startWatching( path, sshot, type ); |
115 | } | 171 | } |
116 | 172 | ||
117 | 173 | ||
118 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) | 174 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) |
119 | { | 175 | { |
120 | if ( notification_list.isEmpty() ) | 176 | if ( notification_list.isEmpty() ) |
121 | { | 177 | { |
122 | OFileNotification::registerEventHandler(); | 178 | OFileNotification::registerEventHandler(); |
123 | } | 179 | } |
124 | 180 | ||
125 | struct inotify_watch_request iwr; | 181 | struct inotify_watch_request iwr; |
126 | ::memset( &iwr, 0, sizeof iwr ); | 182 | ::memset( &iwr, 0, sizeof iwr ); |
127 | iwr.name = const_cast<char*>( (const char*) path ); | 183 | iwr.name = const_cast<char*>( (const char*) path ); |
128 | iwr.mask = type; | 184 | iwr.mask = type; |
129 | 185 | ||
130 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); | 186 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); |
131 | 187 | ||
132 | if ( _wd < 0 ) | 188 | if ( _wd < 0 ) |
133 | { | 189 | { |
134 | 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 ) ); |
135 | return -1; | 191 | return -1; |
136 | } | 192 | } |
137 | 193 | ||
138 | notification_list.insert( _wd, this ); | 194 | notification_list.insert( _wd, this ); |
139 | _path = path; | 195 | _path = path; |
140 | _multi = !sshot; | 196 | _multi = !sshot; |
141 | _type = type; | 197 | _type = type; |
142 | _active = true; | 198 | _active = true; |
143 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); | 199 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); |
144 | return _wd; | 200 | return _wd; |
145 | } | 201 | } |
146 | 202 | ||
147 | 203 | ||
148 | void OFileNotification::stop() | 204 | void OFileNotification::stop() |
149 | { | 205 | { |
150 | notification_list.remove( _wd ); | 206 | notification_list.remove( _wd ); |
151 | _path = QString::null; | 207 | _path = QString::null; |
152 | _wd = 0; | 208 | _wd = 0; |
153 | _active = false; | 209 | _active = false; |
154 | if ( notification_list.isEmpty() ) | 210 | if ( notification_list.isEmpty() ) |
155 | { | 211 | { |
156 | OFileNotification::unregisterEventHandler(); | 212 | OFileNotification::unregisterEventHandler(); |
157 | } | 213 | } |
158 | } | 214 | } |
159 | 215 | ||
160 | 216 | ||
161 | OFileNotificationType OFileNotification::type() const | 217 | OFileNotificationType OFileNotification::type() const |
162 | { | 218 | { |
163 | return _type; | 219 | return _type; |
164 | } | 220 | } |
165 | 221 | ||
166 | 222 | ||
167 | QString OFileNotification::path() const | 223 | QString OFileNotification::path() const |
168 | { | 224 | { |
169 | return _path; | 225 | return _path; |
170 | } | 226 | } |
171 | 227 | ||
172 | 228 | ||
173 | bool OFileNotification::activate( const OFileNotificationEvent* e ) | 229 | bool OFileNotification::activate( const OFileNotificationEvent* e ) |
174 | { | 230 | { |
175 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); | 231 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); |
176 | 232 | ||
177 | // dumb signal | 233 | // dumb signal |
178 | _signal.activate(); | 234 | _signal.activate(); |
179 | 235 | ||
180 | // generic signal | 236 | // generic signal |
181 | emit triggered( _path, e->mask(), e->name() ); | 237 | emit triggered( _path, e->mask(), e->name() ); |
182 | 238 | ||
183 | // specialized signals | 239 | // specialized signals |
184 | switch ( e->mask() ) | 240 | switch ( e->mask() ) |
185 | { | 241 | { |
186 | case Access: emit accessed( _path ); break; | 242 | case Access: emit accessed( _path ); break; |
187 | case Modify: emit modified( _path ); break; | 243 | case Modify: emit modified( _path ); break; |
188 | case Attrib: emit attributed( _path); break; | 244 | case Attrib: emit attributed( _path); break; |
189 | case CloseWrite: emit closed( _path, true ); break; | 245 | case CloseWrite: emit closed( _path, true ); break; |
190 | case CloseNoWrite: emit closed( _path, false ); break; | 246 | case CloseNoWrite: emit closed( _path, false ); break; |
191 | case Open: emit opened( _path ); break; | 247 | case Open: emit opened( _path ); break; |
192 | case MovedFrom: emit movedFrom( _path, e->name() ); break; | 248 | case MovedFrom: emit movedFrom( _path, e->name() ); break; |
193 | case MovedTo: emit movedTo( _path, e->name() ); break; | 249 | case MovedTo: emit movedTo( _path, e->name() ); break; |
194 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; | 250 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; |
195 | case DeleteFile: emit deletedFile( _path, e->name() ); break; | 251 | case DeleteFile: emit deletedFile( _path, e->name() ); break; |
196 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; | 252 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; |
197 | case CreateFile: emit createdFile( _path, e->name() ); break; | 253 | case CreateFile: emit createdFile( _path, e->name() ); break; |
198 | case DeleteSelf: emit deleted( _path ); break; | 254 | case DeleteSelf: emit deleted( _path ); break; |
199 | case Unmount: emit unmounted( _path ); break; | 255 | case Unmount: emit unmounted( _path ); break; |
200 | default: assert( 0 ); | 256 | default: assert( 0 ); |
201 | } | 257 | } |
202 | 258 | ||
203 | if ( !_multi ) stop(); | 259 | if ( !_multi ) stop(); |
204 | 260 | ||
205 | return true; | 261 | return true; |
206 | } | 262 | } |
207 | 263 | ||
208 | 264 | ||
209 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 265 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) |
210 | { | 266 | { |
211 | OFileNotification* ofn = new OFileNotification(); | 267 | OFileNotification* ofn = new OFileNotification(); |
212 | ofn->_signal.connect( receiver, member ); | 268 | ofn->_signal.connect( receiver, member ); |
213 | return ofn->watch( path, true, type ) != -1; | 269 | return ofn->watch( path, true, type ) != -1; |
214 | } | 270 | } |
215 | 271 | ||
216 | 272 | ||
217 | void OFileNotification::inotifyEventHandler() | 273 | void OFileNotification::inotifyEventHandler() |
218 | { | 274 | { |
219 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); | 275 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); |
220 | 276 | ||
221 | char buffer[16384]; | 277 | char buffer[16384]; |
222 | size_t buffer_i; | 278 | ssize_t buffer_i; |
223 | struct inotify_event *pevent, *event; | 279 | struct inotify_event *pevent, *event; |
224 | ssize_t r; | 280 | ssize_t r; |
225 | size_t event_size; | 281 | size_t event_size; |
226 | int count = 0; | 282 | int count = 0; |
227 | 283 | ||
228 | r = ::read(_fd, buffer, 16384); | 284 | r = ::read(_fd, buffer, 16384); |
229 | 285 | ||
230 | if ( r <= 0 ) | 286 | if ( r <= 0 ) |
231 | return; | 287 | return; |
232 | 288 | ||
233 | buffer_i = 0; | 289 | buffer_i = 0; |
234 | while ( buffer_i < r ) | 290 | while ( buffer_i < r ) |
235 | { | 291 | { |
236 | pevent = (struct inotify_event *)&buffer[buffer_i]; | 292 | pevent = (struct inotify_event *)&buffer[buffer_i]; |
237 | event_size = sizeof(struct inotify_event) + pevent->len; | 293 | event_size = sizeof(struct inotify_event) + pevent->len; |
238 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, | 294 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, |
239 | pevent->cookie, pevent->len ? pevent->name : 0 ); | 295 | pevent->cookie, pevent->len ? pevent->name : 0 ); |
240 | e->activate(); | 296 | e->activate(); |
241 | buffer_i += event_size; | 297 | buffer_i += event_size; |
242 | count++; | 298 | count++; |
243 | } | 299 | } |
244 | 300 | ||
245 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); | 301 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); |
246 | } | 302 | } |
247 | 303 | ||
248 | 304 | ||
249 | bool OFileNotification::registerEventHandler() | 305 | bool OFileNotification::registerEventHandler() |
250 | { | 306 | { |
251 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); | 307 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); |
252 | if ( OFileNotification::_fd < 0 ) | 308 | if ( OFileNotification::_fd < 0 ) |
253 | { | 309 | { |
254 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); | 310 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); |
255 | return false; | 311 | return false; |
256 | } | 312 | } |
257 | 313 | ||
258 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); | 314 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); |
259 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); | 315 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); |
260 | 316 | ||
261 | qDebug( "OFileNotification::registerEventHandler(): done" ); | 317 | qDebug( "OFileNotification::registerEventHandler(): done" ); |
262 | return true; | 318 | return true; |
263 | } | 319 | } |
264 | 320 | ||
265 | 321 | ||
266 | void OFileNotification::unregisterEventHandler() | 322 | void OFileNotification::unregisterEventHandler() |
267 | { | 323 | { |
268 | if ( _sn ) delete _sn; | 324 | if ( _sn ) delete _sn; |
269 | if ( OFileNotification::_fd ) | 325 | if ( OFileNotification::_fd ) |
270 | ::close( OFileNotification::_fd ); | 326 | ::close( OFileNotification::_fd ); |
271 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); | 327 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); |
272 | } | 328 | } |
273 | 329 | ||
274 | //================================================================================================= | 330 | //================================================================================================= |
275 | // ODirNotification | 331 | // ODirNotification |
276 | //================================================================================================= | 332 | //================================================================================================= |
277 | ODirNotification::ODirNotification( QObject* parent, const char* name ) | 333 | ODirNotification::ODirNotification( QObject* parent, const char* name ) |
278 | :QObject( parent, name ) | 334 | :QObject( parent, name ) |
279 | { | 335 | { |
280 | qDebug( "ODirNotification::ODirNotification()" ); | 336 | qDebug( "ODirNotification::ODirNotification()" ); |
281 | } | 337 | } |
282 | 338 | ||
283 | 339 | ||
284 | ODirNotification::~ODirNotification() | 340 | ODirNotification::~ODirNotification() |
285 | { | 341 | { |
286 | qDebug( "ODirNotification::~ODirNotification()" ); | 342 | qDebug( "ODirNotification::~ODirNotification()" ); |
287 | } | 343 | } |
288 | 344 | ||
289 | 345 | ||
290 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) | 346 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) |
291 | { | 347 | { |
292 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); | 348 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); |
293 | 349 | ||
294 | if ( recurse == 0 ) | 350 | if ( recurse == 0 ) |
295 | { | 351 | { |
296 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); | 352 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); |
297 | int result = fn->startWatching( path, sshot, type ); | 353 | int result = fn->startWatching( path, sshot, type ); |
298 | if ( result != -1 ) | 354 | if ( result != -1 ) |
299 | { | 355 | { |
300 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); | 356 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); |
301 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); | 357 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); |
302 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); | 358 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); |
303 | connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); | 359 | 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 ) ) ); | 360 | 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& ) ) ); | 361 | 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& ) ) ); | 362 | 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& ) ) ); | 363 | 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& ) ) ); | 364 | 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& ) ) );; | 365 | 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& ) ) ); | 366 | 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& ) ) ); | 367 | 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& ) ) ); | 368 | connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) ); |
313 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); | 369 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); |
314 | } | 370 | } |
315 | return result; | 371 | return result; |
316 | } | 372 | } |
317 | else | 373 | else |
318 | { | 374 | { |
319 | 375 | ||
320 | return 1; | 376 | return 1; |
321 | } | 377 | } |
322 | } | 378 | } |
323 | 379 | ||
324 | 380 | ||
325 | // void ODirNotification::subdirCreated( const QString& name ) | 381 | // void ODirNotification::subdirCreated( const QString& name ) |
326 | 382 | ||
327 | 383 | ||
328 | /* | 384 | /* |
329 | Love-Trowbridge recursive directory scanning algorithm: | 385 | Love-Trowbridge recursive directory scanning algorithm: |
330 | 386 | ||
331 | Step 1. Start at initial directory foo. Add watch. | 387 | Step 1. Start at initial directory foo. Add watch. |
332 | 388 | ||
333 | Step 2. Setup handlers for watch created in Step 1. | 389 | Step 2. Setup handlers for watch created in Step 1. |
334 | Specifically, ensure that a directory created | 390 | Specifically, ensure that a directory created |
335 | in foo will result in a handled CREATE_SUBDIR | 391 | in foo will result in a handled CREATE_SUBDIR |
336 | event. | 392 | event. |
337 | 393 | ||
338 | Step 3. Read the contents of foo. | 394 | Step 3. Read the contents of foo. |
339 | 395 | ||
340 | Step 4. For each subdirectory of foo read in step 3, repeat | 396 | Step 4. For each subdirectory of foo read in step 3, repeat |
341 | step 1. | 397 | step 1. |
342 | 398 | ||
343 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is | 399 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is |
344 | not yet created on bar, repeat step 1 on bar. | 400 | not yet created on bar, repeat step 1 on bar. |
345 | */ | 401 | */ |
346 | 402 | ||
347 | 403 | ||
348 | } // namespace Ui | 404 | } // namespace Ui |
349 | 405 | ||
350 | } // namespace Opie | 406 | } // namespace Opie |
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h index 5bbf421..05343b9 100644 --- a/libopie2/opiecore/ofilenotify.h +++ b/libopie2/opiecore/ofilenotify.h | |||
@@ -1,289 +1,326 @@ | |||
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> | ||
42 | #include <qfile.h> | ||
41 | 43 | ||
42 | namespace Opie { | 44 | namespace Opie { |
43 | namespace Core { | 45 | namespace Core { |
44 | 46 | ||
47 | class OFile : public QObject, public QFile | ||
48 | { | ||
49 | Q_OBJECT | ||
50 | |||
51 | public: | ||
52 | OFile(); | ||
53 | OFile( const QString & name ); | ||
54 | virtual ~OFile(); | ||
55 | |||
56 | protected: | ||
57 | virtual void connectNotify( const char* signal ); | ||
58 | virtual void disconnectNotify( const char* signal ); | ||
59 | |||
60 | private: | ||
61 | int startWatch( int mode ); | ||
62 | |||
63 | signals: | ||
64 | void accessed( const QString& ); | ||
65 | void modified( const QString& ); | ||
66 | void attributed( const QString& ); | ||
67 | void closed( const QString&, bool ); | ||
68 | void opened( const QString& ); | ||
69 | void deleted( const QString& ); | ||
70 | void unmounted( const QString& ); | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | void movedTo( const QString&, const QString& ); | ||
75 | void movedFrom( const QString&, const QString& ); | ||
76 | void deletedSubdir( const QString&, const QString& ); | ||
77 | void deletedFile( const QString&, const QString& ); | ||
78 | void createdSubdir( const QString&, const QString& ); | ||
79 | void createdFile( const QString&, const QString& ); | ||
80 | */ | ||
81 | |||
45 | class OFileNotificationEvent; | 82 | class OFileNotificationEvent; |
46 | 83 | ||
47 | /*====================================================================================== | 84 | /*====================================================================================== |
48 | * OFileNotificationType | 85 | * OFileNotificationType |
49 | *======================================================================================*/ | 86 | *======================================================================================*/ |
50 | 87 | ||
51 | /** | 88 | /** |
52 | * @brief An enumerate for the different types of file notifications | 89 | * @brief An enumerate for the different types of file notifications |
53 | * | 90 | * |
54 | * 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. |
55 | * Valid values are: | 92 | * Valid values are: |
56 | * <ul> | 93 | * <ul> |
57 | * <li>Access: The file was accessed (read) | 94 | * <li>Access: The file was accessed (read) |
58 | * <li>Modify The file was modified (write,truncate) | 95 | * <li>Modify The file was modified (write,truncate) |
59 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) | 96 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) |
60 | * <li>CloseWrite = Writable file was closed | 97 | * <li>CloseWrite = Writable file was closed |
61 | * <li>CloseNoWrite = Unwritable file was closed | 98 | * <li>CloseNoWrite = Unwritable file was closed |
62 | * <li>Open = File was opened | 99 | * <li>Open = File was opened |
63 | * <li>MovedFrom = File was moved from X | 100 | * <li>MovedFrom = File was moved from X |
64 | * <li>MovedTo = File was moved to Y | 101 | * <li>MovedTo = File was moved to Y |
65 | * <li>DeleteSubdir = Subdir was deleted | 102 | * <li>DeleteSubdir = Subdir was deleted |
66 | * <li>DeleteFile = Subfile was deleted | 103 | * <li>DeleteFile = Subfile was deleted |
67 | * <li>CreateSubdir = Subdir was created | 104 | * <li>CreateSubdir = Subdir was created |
68 | * <li>CreateFile = Subfile was created | 105 | * <li>CreateFile = Subfile was created |
69 | * <li>DeleteSelf = Self was deleted | 106 | * <li>DeleteSelf = Self was deleted |
70 | * <li>Unmount = The backing filesystem was unmounted | 107 | * <li>Unmount = The backing filesystem was unmounted |
71 | * </ul> | 108 | * </ul> |
72 | * | 109 | * |
73 | **/ | 110 | **/ |
74 | 111 | ||
75 | enum OFileNotificationType | 112 | enum OFileNotificationType |
76 | { | 113 | { |
77 | Access = IN_ACCESS, | 114 | Access = IN_ACCESS, |
78 | Modify = IN_MODIFY, | 115 | Modify = IN_MODIFY, |
79 | Attrib = IN_ATTRIB, | 116 | Attrib = IN_ATTRIB, |
80 | CloseWrite = IN_CLOSE_WRITE, | 117 | CloseWrite = IN_CLOSE_WRITE, |
81 | CloseNoWrite = IN_CLOSE_NOWRITE, | 118 | CloseNoWrite = IN_CLOSE_NOWRITE, |
82 | Open = IN_OPEN, | 119 | Open = IN_OPEN, |
83 | MovedFrom = IN_MOVED_FROM, | 120 | MovedFrom = IN_MOVED_FROM, |
84 | MovedTo = IN_MOVED_TO, | 121 | MovedTo = IN_MOVED_TO, |
85 | DeleteSubdir = IN_DELETE_SUBDIR, | 122 | DeleteSubdir = IN_DELETE_SUBDIR, |
86 | DeleteFile = IN_DELETE_FILE, | 123 | DeleteFile = IN_DELETE_FILE, |
87 | CreateSubdir = IN_CREATE_SUBDIR, | 124 | CreateSubdir = IN_CREATE_SUBDIR, |
88 | CreateFile = IN_CREATE_FILE, | 125 | CreateFile = IN_CREATE_FILE, |
89 | DeleteSelf = IN_DELETE_SELF, | 126 | DeleteSelf = IN_DELETE_SELF, |
90 | Unmount = IN_UNMOUNT, | 127 | Unmount = IN_UNMOUNT, |
91 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ | 128 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ |
92 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ | 129 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ |
93 | }; | 130 | }; |
94 | 131 | ||
95 | /*====================================================================================== | 132 | /*====================================================================================== |
96 | * OFileNotification | 133 | * OFileNotification |
97 | *======================================================================================*/ | 134 | *======================================================================================*/ |
98 | 135 | ||
99 | /** | 136 | /** |
100 | * @brief Represents a file notification | 137 | * @brief Represents a file notification |
101 | * | 138 | * |
102 | * This class allows to watch for events happening to files. | 139 | * This class allows to watch for events happening to files. |
103 | * It uses the inotify linux (2.6.x) kernel interface. | 140 | * It uses the inotify linux (2.6.x) kernel interface. |
104 | * | 141 | * |
105 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 142 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
106 | * | 143 | * |
107 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 144 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
108 | * | 145 | * |
109 | **/ | 146 | **/ |
110 | 147 | ||
111 | class OFileNotification : public QObject | 148 | class OFileNotification : public QObject |
112 | { | 149 | { |
113 | Q_OBJECT | 150 | Q_OBJECT |
114 | 151 | ||
115 | public: | 152 | public: |
116 | OFileNotification( QObject* parent = 0, const char* name = 0 ); | 153 | OFileNotification( QObject* parent = 0, const char* name = 0 ); |
117 | ~OFileNotification(); | 154 | ~OFileNotification(); |
118 | /** | 155 | /** |
119 | * This static function calls a slot when an event with @a type happens to file @a path. | 156 | * This static function calls a slot when an event with @a type happens to file @a path. |
120 | * | 157 | * |
121 | * It is very convenient to use this function because you do not need to | 158 | * It is very convenient to use this function because you do not need to |
122 | * bother with a timerEvent or to create a local QTimer object. | 159 | * bother with a timerEvent or to create a local QTimer object. |
123 | * | 160 | * |
124 | * Example: | 161 | * Example: |
125 | * <pre> | 162 | * <pre> |
126 | * | 163 | * |
127 | * #include <opie2/oapplication.h> | 164 | * #include <opie2/oapplication.h> |
128 | * #include <opie2/ofilenotify.h> | 165 | * #include <opie2/ofilenotify.h> |
129 | * using namespace Opie::Core; | 166 | * using namespace Opie::Core; |
130 | * | 167 | * |
131 | * int main( int argc, char **argv ) | 168 | * int main( int argc, char **argv ) |
132 | * { | 169 | * { |
133 | * OApplication a( argc, argv, "File Notification Example" ); | 170 | * OApplication a( argc, argv, "File Notification Example" ); |
134 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); | 171 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); |
135 | * ... // create and show your widgets | 172 | * ... // create and show your widgets |
136 | * return a.exec(); | 173 | * return a.exec(); |
137 | * } | 174 | * } |
138 | * </pre> | 175 | * </pre> |
139 | * | 176 | * |
140 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. | 177 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. |
141 | * | 178 | * |
142 | * | 179 | * |
143 | * The @a receiver is the receiving object and the @a member is the slot. | 180 | * The @a receiver is the receiving object and the @a member is the slot. |
144 | **/ | 181 | **/ |
145 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); | 182 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); |
146 | /** | 183 | /** |
147 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. | 184 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. |
148 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. | 185 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. |
149 | **/ | 186 | **/ |
150 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 187 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
151 | /** | 188 | /** |
152 | * Stop watching for file events. | 189 | * Stop watching for file events. |
153 | **/ | 190 | **/ |
154 | void stop(); | 191 | void stop(); |
155 | /** | 192 | /** |
156 | * @returns the notification type as set by @ref start(). | 193 | * @returns the notification type as set by @ref start(). |
157 | **/ | 194 | **/ |
158 | OFileNotificationType type() const; | 195 | OFileNotificationType type() const; |
159 | /** | 196 | /** |
160 | * @returns the path to the file being watched by this instance. | 197 | * @returns the path to the file being watched by this instance. |
161 | **/ | 198 | **/ |
162 | QString path() const; | 199 | QString path() const; |
163 | /** | 200 | /** |
164 | * @returns if a file is currently being watched. | 201 | * @returns if a file is currently being watched. |
165 | **/ | 202 | **/ |
166 | bool isActive() const; | 203 | bool isActive() const; |
167 | /** | 204 | /** |
168 | * @internal | 205 | * @internal |
169 | */ | 206 | */ |
170 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 207 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
171 | 208 | ||
172 | signals: | 209 | signals: |
173 | void triggered( const QString&, unsigned int, const QString& ); | 210 | void triggered( const QString&, unsigned int, const QString& ); |
174 | void accessed( const QString& ); | 211 | void accessed( const QString& ); |
175 | void modified( const QString& ); | 212 | void modified( const QString& ); |
176 | void attributed( const QString& ); | 213 | void attributed( const QString& ); |
177 | void closed( const QString&, bool ); | 214 | void closed( const QString&, bool ); |
178 | void opened( const QString& ); | 215 | void opened( const QString& ); |
179 | void movedTo( const QString&, const QString& ); | 216 | void movedTo( const QString&, const QString& ); |
180 | void movedFrom( const QString&, const QString& ); | 217 | void movedFrom( const QString&, const QString& ); |
181 | void deletedSubdir( const QString&, const QString& ); | 218 | void deletedSubdir( const QString&, const QString& ); |
182 | void deletedFile( const QString&, const QString& ); | 219 | void deletedFile( const QString&, const QString& ); |
183 | void createdSubdir( const QString&, const QString& ); | 220 | void createdSubdir( const QString&, const QString& ); |
184 | void createdFile( const QString&, const QString& ); | 221 | void createdFile( const QString&, const QString& ); |
185 | void deleted( const QString& ); | 222 | void deleted( const QString& ); |
186 | void unmounted( const QString& ); | 223 | void unmounted( const QString& ); |
187 | 224 | ||
188 | protected: | 225 | protected: |
189 | bool activate( const OFileNotificationEvent* e ); | 226 | bool activate( const OFileNotificationEvent* e ); |
190 | 227 | ||
191 | private slots: | 228 | private slots: |
192 | void inotifyEventHandler(); | 229 | void inotifyEventHandler(); |
193 | 230 | ||
194 | private: | 231 | private: |
195 | bool registerEventHandler(); | 232 | bool registerEventHandler(); |
196 | void unregisterEventHandler(); | 233 | void unregisterEventHandler(); |
197 | 234 | ||
198 | QString _path; | 235 | QString _path; |
199 | OFileNotificationType _type; | 236 | OFileNotificationType _type; |
200 | QSignal _signal; | 237 | QSignal _signal; |
201 | bool _active; | 238 | bool _active; |
202 | bool _multi; | 239 | bool _multi; |
203 | static QSocketNotifier* _sn; | 240 | static QSocketNotifier* _sn; |
204 | int _wd; // inotify watch descriptor | 241 | int _wd; // inotify watch descriptor |
205 | static int _fd; // inotify device descriptor | 242 | static int _fd; // inotify device descriptor |
206 | 243 | ||
207 | friend class OFileNotificationEvent; | 244 | friend class OFileNotificationEvent; |
208 | }; | 245 | }; |
209 | 246 | ||
210 | /*====================================================================================== | 247 | /*====================================================================================== |
211 | * ODirNotification | 248 | * ODirNotification |
212 | *======================================================================================*/ | 249 | *======================================================================================*/ |
213 | 250 | ||
214 | /** | 251 | /** |
215 | * @brief Represents a directory notification | 252 | * @brief Represents a directory notification |
216 | * | 253 | * |
217 | * This class allows to watch for events happening to directories | 254 | * This class allows to watch for events happening to directories |
218 | * It uses the OFileNotification class | 255 | * It uses the OFileNotification class |
219 | * | 256 | * |
220 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 257 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
221 | * | 258 | * |
222 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 259 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
223 | * | 260 | * |
224 | **/ | 261 | **/ |
225 | 262 | ||
226 | class ODirNotification : public QObject | 263 | class ODirNotification : public QObject |
227 | { | 264 | { |
228 | Q_OBJECT | 265 | Q_OBJECT |
229 | 266 | ||
230 | public: | 267 | public: |
231 | ODirNotification( QObject* parent = 0, const char* name = 0 ); | 268 | ODirNotification( QObject* parent = 0, const char* name = 0 ); |
232 | ~ODirNotification(); | 269 | ~ODirNotification(); |
233 | /** | 270 | /** |
234 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, | 271 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, |
235 | * use 0 for no recursion and -1 for unlimited recursion. | 272 | * use 0 for no recursion and -1 for unlimited recursion. |
236 | * Set @a sshot to True if you want to be notified only once. | 273 | * Set @a sshot to True if you want to be notified only once. |
237 | **/ | 274 | **/ |
238 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); | 275 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); |
239 | 276 | ||
240 | signals: | 277 | signals: |
241 | /** | 278 | /** |
242 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. | 279 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. |
243 | **/ | 280 | **/ |
244 | void triggered( const QString&, unsigned int, const QString& ); | 281 | void triggered( const QString&, unsigned int, const QString& ); |
245 | void accessed( const QString& ); | 282 | void accessed( const QString& ); |
246 | void modified( const QString& ); | 283 | void modified( const QString& ); |
247 | void attributed( const QString& ); | 284 | void attributed( const QString& ); |
248 | void closed( const QString&, bool ); | 285 | void closed( const QString&, bool ); |
249 | void opened( const QString& ); | 286 | void opened( const QString& ); |
250 | void movedTo( const QString&, const QString& ); | 287 | void movedTo( const QString&, const QString& ); |
251 | void movedFrom( const QString&, const QString& ); | 288 | void movedFrom( const QString&, const QString& ); |
252 | void deletedSubdir( const QString&, const QString& ); | 289 | void deletedSubdir( const QString&, const QString& ); |
253 | void deletedFile( const QString&, const QString& ); | 290 | void deletedFile( const QString&, const QString& ); |
254 | void createdSubdir( const QString&, const QString& ); | 291 | void createdSubdir( const QString&, const QString& ); |
255 | void createdFile( const QString&, const QString& ); | 292 | void createdFile( const QString&, const QString& ); |
256 | void deleted( const QString& ); | 293 | void deleted( const QString& ); |
257 | void unmounted( const QString& ); | 294 | void unmounted( const QString& ); |
258 | }; | 295 | }; |
259 | 296 | ||
260 | /*====================================================================================== | 297 | /*====================================================================================== |
261 | * OFileNotificationEvent | 298 | * OFileNotificationEvent |
262 | *======================================================================================*/ | 299 | *======================================================================================*/ |
263 | 300 | ||
264 | class OFileNotificationEvent | 301 | class OFileNotificationEvent |
265 | { | 302 | { |
266 | public: | 303 | public: |
267 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); | 304 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); |
268 | ~OFileNotificationEvent(); | 305 | ~OFileNotificationEvent(); |
269 | OFileNotification* parent() const { return _parent; }; | 306 | OFileNotification* parent() const { return _parent; }; |
270 | int descriptor() const { return _wd; }; | 307 | int descriptor() const { return _wd; }; |
271 | unsigned int mask() const { return _mask; }; | 308 | unsigned int mask() const { return _mask; }; |
272 | unsigned int cookie() const { return _cookie; }; | 309 | unsigned int cookie() const { return _cookie; }; |
273 | QString name() const { return _name; }; | 310 | QString name() const { return _name; }; |
274 | void activate() { _parent->activate( this ); }; | 311 | void activate() { _parent->activate( this ); }; |
275 | 312 | ||
276 | private: | 313 | private: |
277 | OFileNotification* _parent; | 314 | OFileNotification* _parent; |
278 | int _wd; | 315 | int _wd; |
279 | unsigned int _mask; | 316 | unsigned int _mask; |
280 | unsigned int _cookie; | 317 | unsigned int _cookie; |
281 | QString _name; | 318 | QString _name; |
282 | }; | 319 | }; |
283 | 320 | ||
284 | 321 | ||
285 | } | 322 | } |
286 | } | 323 | } |
287 | 324 | ||
288 | #endif | 325 | #endif |
289 | 326 | ||