-rw-r--r-- | libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp | 43 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 160 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 36 |
3 files changed, 176 insertions, 63 deletions
diff --git a/libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp b/libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp index a8a5717..74a8158 100644 --- a/libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp +++ b/libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp | |||
@@ -8,12 +8,13 @@ using namespace Opie::Core; | |||
8 | using namespace Opie::Ui; | 8 | using namespace Opie::Ui; |
9 | 9 | ||
10 | /* QT */ | 10 | /* QT */ |
11 | #include <qcheckbox.h> | ||
11 | #include <qvbox.h> | 12 | #include <qvbox.h> |
12 | #include <qhbox.h> | 13 | #include <qhbox.h> |
13 | #include <qhbuttongroup.h> | 14 | #include <qhbuttongroup.h> |
14 | #include <qvbuttongroup.h> | 15 | #include <qvbuttongroup.h> |
16 | #include <qmessagebox.h> | ||
15 | #include <qpushbutton.h> | 17 | #include <qpushbutton.h> |
16 | #include <qcheckbox.h> | ||
17 | 18 | ||
18 | class DemoApp : public OApplication | 19 | class DemoApp : public OApplication |
19 | { | 20 | { |
@@ -27,7 +28,10 @@ public: | |||
27 | 28 | ||
28 | l = new OListView( vbox ); | 29 | l = new OListView( vbox ); |
29 | l->addColumn( "Notification Path" ); | 30 | l->addColumn( "Notification Path" ); |
30 | l->addColumn( "Trigger" ); | 31 | l->addColumn( "Trigger Type" ); |
32 | l->addColumn( "Trigger Mask" ); | ||
33 | l->setColumnAlignment( 1, AlignCenter ); | ||
34 | l->setColumnAlignment( 2, AlignCenter ); | ||
31 | 35 | ||
32 | QHBox* hbox = new QHBox( vbox ); | 36 | QHBox* hbox = new QHBox( vbox ); |
33 | 37 | ||
@@ -45,6 +49,7 @@ public: | |||
45 | g2->insert( c5, Delete ); | 49 | g2->insert( c5, Delete ); |
46 | g2->insert( c6, Rename ); | 50 | g2->insert( c6, Rename ); |
47 | g2->insert( c7, Attrib ); | 51 | g2->insert( c7, Attrib ); |
52 | connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); | ||
48 | 53 | ||
49 | g1 = new QVButtonGroup( "Add/Remove", hbox ); | 54 | g1 = new QVButtonGroup( "Add/Remove", hbox ); |
50 | QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); | 55 | QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); |
@@ -68,15 +73,26 @@ public: | |||
68 | public: | 73 | public: |
69 | void addTrigger( bool multi = false ) | 74 | void addTrigger( bool multi = false ) |
70 | { | 75 | { |
76 | if ( !m ) | ||
77 | { | ||
78 | QMessageBox::warning( 0, "Add Trigger", "<p>Can't add trigger without at least one selected trigger type</p>", "&Sorry", 0 ); | ||
79 | return; | ||
80 | } | ||
81 | |||
71 | QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); | 82 | QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); |
72 | if ( !filename.isEmpty() ) | 83 | if ( !filename.isEmpty() ) |
73 | { | 84 | { |
74 | odebug << "Filename = " << filename << oendl; | 85 | odebug << "Filename = " << filename << oendl; |
75 | new OListViewItem( l, filename, "Modify" ); | ||
76 | |||
77 | 86 | ||
87 | int fntype = m; | ||
88 | if ( multi ) fntype |=(int) Multi; | ||
78 | 89 | ||
79 | OFileNotifier::singleShot( filename, this, SLOT( trigger() ) ); | 90 | QString modifier = QString().sprintf( " = 0x%08x", fntype ); |
91 | new OListViewItem( l, filename, multi ? "MULTI" : "SINGLE", modifier ); | ||
92 | if ( !multi ) | ||
93 | OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); | ||
94 | else | ||
95 | OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); | ||
80 | } | 96 | } |
81 | else | 97 | else |
82 | { | 98 | { |
@@ -85,14 +101,23 @@ public: | |||
85 | } | 101 | } |
86 | 102 | ||
87 | public slots: | 103 | public slots: |
88 | 104 | void modifierClicked( int modifier ) { (int)m ^= modifier; }; | |
89 | void addSingle() { addTrigger(); }; | 105 | void addSingle() { addTrigger(); }; |
90 | void addMulti() { addTrigger( true ); }; | 106 | void addMulti() { addTrigger( true ); }; |
91 | 107 | ||
92 | void delTrigger() | 108 | void delTrigger() |
93 | { | 109 | { |
94 | QString filename( "bla" ); | 110 | QListViewItem* item = l->selectedItem(); |
95 | odebug << "Filename = " << filename << oendl; | 111 | if ( !item ) |
112 | { | ||
113 | QMessageBox::warning( 0, "Del Trigger", "<p>No trigger selected!</p>", "&Sorry", 0 ); | ||
114 | return; | ||
115 | } | ||
116 | else | ||
117 | { | ||
118 | QString filename( item->text( 0 ) ); | ||
119 | odebug << "Filename = " << filename << oendl; | ||
120 | } | ||
96 | } | 121 | } |
97 | 122 | ||
98 | void trigger() | 123 | void trigger() |
@@ -104,7 +129,7 @@ private: | |||
104 | OListView* l; | 129 | OListView* l; |
105 | QButtonGroup* g1; | 130 | QButtonGroup* g1; |
106 | QButtonGroup* g2; | 131 | QButtonGroup* g2; |
107 | int m; | 132 | OFileNotificationType m; |
108 | }; | 133 | }; |
109 | 134 | ||
110 | int main( int argc, char** argv ) | 135 | int main( int argc, char** argv ) |
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 2242570..5e9f97b 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp | |||
@@ -32,6 +32,7 @@ using namespace Opie::Core; | |||
32 | /* OPIE */ | 32 | /* OPIE */ |
33 | 33 | ||
34 | /* QT */ | 34 | /* QT */ |
35 | #include <qobject.h> | ||
35 | #include <qsignal.h> | 36 | #include <qsignal.h> |
36 | #include <qintdict.h> | 37 | #include <qintdict.h> |
37 | #include <qdir.h> | 38 | #include <qdir.h> |
@@ -39,77 +40,136 @@ using namespace Opie::Core; | |||
39 | /* STD */ | 40 | /* STD */ |
40 | #include <sys/types.h> | 41 | #include <sys/types.h> |
41 | #include <sys/stat.h> | 42 | #include <sys/stat.h> |
42 | #include <fcntl.h> | 43 | #ifndef _GNU_SOURCE |
44 | #define _GNU_SOURCE | ||
45 | #include <fcntl.h> | ||
46 | #undef _GNU_SOURCE | ||
47 | #else | ||
48 | #include <fcntl.h> | ||
49 | #endif | ||
43 | #include <string.h> | 50 | #include <string.h> |
44 | #include <errno.h> | 51 | #include <errno.h> |
52 | #include <unistd.h> | ||
53 | |||
54 | static QIntDict<OFileNotification> notification_list; | ||
45 | 55 | ||
46 | namespace Opie { | 56 | namespace Opie { |
47 | namespace Core { | 57 | namespace Core { |
48 | 58 | ||
49 | class OFileNotification | 59 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
60 | :QObject( parent, name ), _active( false ) | ||
50 | { | 61 | { |
51 | public: | 62 | qDebug( "OFileNotification::OFileNotification()" ); |
52 | OFileNotification( QObject* receiver, const char* member, OFileNotificationType type ) : _type( type ) | 63 | } |
53 | { | ||
54 | _signal.connect( receiver, member ); | ||
55 | } | ||
56 | ~OFileNotification() | ||
57 | { | ||
58 | } | ||
59 | |||
60 | void activate() | ||
61 | { | ||
62 | _signal.activate(); | ||
63 | } | ||
64 | 64 | ||
65 | OFileNotificationType type() | ||
66 | { | ||
67 | return _type; | ||
68 | } | ||
69 | 65 | ||
70 | private: | 66 | OFileNotification::~OFileNotification() |
71 | OFileNotificationType _type; | 67 | { |
72 | QSignal _signal; | 68 | qDebug( "OFileNotification::~OFileNotification()" ); |
73 | }; | 69 | } |
74 | 70 | ||
75 | 71 | ||
76 | static QIntDict<OFileNotification> notification_list; | 72 | bool OFileNotification::isActive() const |
73 | { | ||
74 | return _active; | ||
75 | } | ||
77 | 76 | ||
78 | 77 | ||
79 | void OFileNotifier::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 78 | int OFileNotification::start( const QString& path, bool sshot, OFileNotificationType type ) |
80 | { | 79 | { |
80 | _path = QString::null; | ||
81 | _fd = 0; | ||
82 | if ( _active ) stop(); | ||
83 | |||
81 | int fd = ::open( (const char*) path, O_RDONLY ); | 84 | int fd = ::open( (const char*) path, O_RDONLY ); |
82 | if ( fd != -1 ) | 85 | if ( fd != -1 ) |
83 | { | 86 | { |
84 | if ( notification_list.isEmpty() ) | 87 | if ( notification_list.isEmpty() ) |
85 | { | 88 | { |
86 | OFileNotifier::registerSignalHandler(); | 89 | OFileNotification::registerSignalHandler(); |
87 | } | 90 | } |
88 | int result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); | 91 | int result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); |
89 | if ( result == -1 ) | 92 | if ( result == -1 ) |
90 | { | 93 | { |
91 | qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); | 94 | qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); |
92 | return; | 95 | return -1; |
93 | } | 96 | } |
97 | if ( !sshot ) (int) type |= (int) Multi; | ||
94 | result = ::fcntl( fd, F_NOTIFY, type ); | 98 | result = ::fcntl( fd, F_NOTIFY, type ); |
95 | if ( result == -1 ) | 99 | if ( result == -1 ) |
96 | { | 100 | { |
97 | qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); | 101 | qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); |
98 | return; | 102 | return -1; |
99 | } | 103 | } |
100 | qDebug( "OFileNotifier::singleShot(): Subscribed for changes to %s (fd = %d)", (const char*) path, fd ); | 104 | qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) path, fd, type ); |
101 | notification_list.insert( fd, new OFileNotification( receiver, member, type ) ); | 105 | notification_list.insert( fd, this ); |
106 | _type = type; | ||
107 | _path = path; | ||
108 | _fd = fd; | ||
109 | return fd; | ||
102 | } | 110 | } |
103 | else | 111 | else |
104 | { | 112 | { |
105 | qWarning( "OFileNotifier::singleShot(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); | 113 | qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); |
114 | return -1; | ||
106 | } | 115 | } |
107 | } | 116 | } |
108 | 117 | ||
109 | 118 | ||
110 | void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) | 119 | void OFileNotification::stop() |
111 | { | 120 | { |
112 | qWarning( "OFileNotifier::__signalHandler(): reached." ); | 121 | if ( !_active ) return; |
122 | |||
123 | int result = ::fcntl( _fd, F_NOTIFY, 0 ); | ||
124 | if ( result == -1 ) | ||
125 | { | ||
126 | qWarning( "OFileNotification::stop(): Can't remove subscription to '%s': %s.", (const char*) _path, strerror( errno ) ); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | ::close( _fd ); | ||
131 | _type = Single; | ||
132 | _path = QString::null; | ||
133 | _fd = 0; | ||
134 | _active = false; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | |||
139 | OFileNotificationType OFileNotification::type() const | ||
140 | { | ||
141 | return _type; | ||
142 | } | ||
143 | |||
144 | |||
145 | QString OFileNotification::path() const | ||
146 | { | ||
147 | return _path; | ||
148 | } | ||
149 | |||
150 | int OFileNotification::fileno() const | ||
151 | { | ||
152 | return _fd; | ||
153 | } | ||
154 | |||
155 | void OFileNotification::activate() | ||
156 | { | ||
157 | emit triggered(); | ||
158 | _signal.activate(); | ||
159 | } | ||
160 | |||
161 | |||
162 | void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | ||
163 | { | ||
164 | OFileNotification* ofn = new OFileNotification(); | ||
165 | ofn->_signal.connect( receiver, member ); | ||
166 | ofn->start( path, true, type ); | ||
167 | } | ||
168 | |||
169 | |||
170 | void OFileNotification::__signalHandler( int sig, siginfo_t *si, void *data ) | ||
171 | { | ||
172 | qWarning( "OFileNotification::__signalHandler(): reached." ); | ||
113 | int fd = si->si_fd; | 173 | int fd = si->si_fd; |
114 | OFileNotification* fn = notification_list[fd]; | 174 | OFileNotification* fn = notification_list[fd]; |
115 | if ( fn ) | 175 | if ( fn ) |
@@ -118,40 +178,48 @@ void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) | |||
118 | #if 1 | 178 | #if 1 |
119 | if ( !(fn->type() & Multi) ) | 179 | if ( !(fn->type() & Multi) ) |
120 | { | 180 | { |
121 | qDebug( "OFileNotifier::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); | 181 | qDebug( "OFileNotification::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); |
122 | notification_list.remove( fd ); | 182 | notification_list.remove( fd ); |
123 | if ( notification_list.isEmpty() ) | 183 | if ( notification_list.isEmpty() ) |
124 | { | 184 | { |
125 | OFileNotifier::unregisterSignalHandler(); | 185 | OFileNotification::unregisterSignalHandler(); |
126 | } | 186 | } |
127 | } | 187 | } |
128 | #endif | 188 | #endif |
129 | } | 189 | } |
130 | else | 190 | else |
131 | { | 191 | { |
132 | qWarning( "OFileNotifier::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); | 192 | qWarning( "OFileNotification::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); |
133 | } | 193 | } |
134 | } | 194 | } |
135 | 195 | ||
136 | 196 | ||
137 | void OFileNotifier::registerSignalHandler() | 197 | bool OFileNotification::registerSignalHandler() |
138 | { | 198 | { |
139 | struct sigaction act; | 199 | struct sigaction act; |
140 | act.sa_sigaction = OFileNotifier::__signalHandler; | 200 | act.sa_sigaction = OFileNotification::__signalHandler; |
141 | ::sigemptyset( &act.sa_mask ); | 201 | ::sigemptyset( &act.sa_mask ); |
142 | act.sa_flags = SA_SIGINFO; | 202 | act.sa_flags = SA_SIGINFO; |
143 | ::sigaction( SIGRTMIN, &act, NULL ); | 203 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
144 | qDebug( "OFileNotifier::registerSignalHandler(): done" ); | 204 | { |
205 | qWarning( "OFileNotification::registerSignalHandler(): couldn't register signal handler: %s", strerror( errno ) ); | ||
206 | return false; | ||
207 | } | ||
208 | qDebug( "OFileNotification::registerSignalHandler(): done" ); | ||
145 | } | 209 | } |
146 | 210 | ||
147 | 211 | ||
148 | void OFileNotifier::unregisterSignalHandler() | 212 | void OFileNotification::unregisterSignalHandler() |
149 | { | 213 | { |
150 | struct sigaction act; | 214 | struct sigaction act; |
151 | act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; | 215 | act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; |
152 | sigemptyset( &act.sa_mask ); | 216 | ::sigemptyset( &act.sa_mask ); |
153 | ::sigaction( SIGRTMIN, &act, NULL ); | 217 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
154 | qDebug( "OFileNotifier::unregisterSignalHandler(): done" ); | 218 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
219 | { | ||
220 | qWarning( "OFileNotification::unregisterSignalHandler(): couldn't deregister signal handler: %s", strerror( errno ) ); | ||
221 | } | ||
222 | qDebug( "OFileNotification::unregisterSignalHandler(): done" ); | ||
155 | } | 223 | } |
156 | 224 | ||
157 | 225 | ||
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h index 638eb6c..a14842a 100644 --- a/libopie2/opiecore/ofilenotify.h +++ b/libopie2/opiecore/ofilenotify.h | |||
@@ -30,8 +30,9 @@ _;:, .> :=|. This program is free software; you can | |||
30 | #define OFILENOTIFY_H | 30 | #define OFILENOTIFY_H |
31 | 31 | ||
32 | /* QT */ | 32 | /* QT */ |
33 | #include <qstring.h> | ||
34 | #include <qobject.h> | 33 | #include <qobject.h> |
34 | #include <qsignal.h> | ||
35 | #include <qstring.h> | ||
35 | 36 | ||
36 | /* STD */ | 37 | /* STD */ |
37 | #include <signal.h> | 38 | #include <signal.h> |
@@ -49,20 +50,39 @@ enum OFileNotificationType { Single = 0x0000000, | |||
49 | Rename = DN_RENAME, | 50 | Rename = DN_RENAME, |
50 | Attrib = DN_ATTRIB }; | 51 | Attrib = DN_ATTRIB }; |
51 | 52 | ||
52 | class OFileNotifier : public QObject | 53 | class OFileNotification : public QObject |
53 | { | 54 | { |
55 | Q_OBJECT | ||
56 | |||
54 | public: | 57 | public: |
55 | static void singleShot( const QString& path, | 58 | OFileNotification( QObject* parent = 0, const char* name = 0 ); |
56 | QObject *receiver, const char *member, | 59 | ~OFileNotification(); |
57 | OFileNotificationType type = Modify ); | 60 | |
61 | static void singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); | ||
62 | |||
63 | int start( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | ||
64 | void stop(); | ||
65 | |||
66 | OFileNotificationType type() const; | ||
67 | QString path() const; | ||
68 | int fileno() const; | ||
69 | bool isActive() const; | ||
70 | |||
71 | signals: | ||
72 | void triggered(); | ||
73 | |||
58 | protected: | 74 | protected: |
59 | static void registerSignalHandler(); | 75 | void activate(); |
76 | static bool registerSignalHandler(); | ||
60 | static void unregisterSignalHandler(); | 77 | static void unregisterSignalHandler(); |
61 | static void __signalHandler( int sig, siginfo_t *si, void *data ); | 78 | static void __signalHandler( int sig, siginfo_t *si, void *data ); |
62 | 79 | ||
63 | private: | 80 | private: |
64 | OFileNotifier(); | 81 | QString _path; |
65 | ~OFileNotifier(); | 82 | OFileNotificationType _type; |
83 | QSignal _signal; | ||
84 | int _fd; | ||
85 | bool _active; | ||
66 | }; | 86 | }; |
67 | 87 | ||
68 | } | 88 | } |