author | mickeyl <mickeyl> | 2004-04-18 18:25:24 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2004-04-18 18:25:24 (UTC) |
commit | df539f67050ebe61b5dc589f9c138bb9ef1719f6 (patch) (unidiff) | |
tree | 7baa2dc1e44be92dec2736b8205f9642fffc4302 | |
parent | 56f49e8293110e488f3ea6bc6dad282981c81d4b (diff) | |
download | opie-df539f67050ebe61b5dc589f9c138bb9ef1719f6.zip opie-df539f67050ebe61b5dc589f9c138bb9ef1719f6.tar.gz opie-df539f67050ebe61b5dc589f9c138bb9ef1719f6.tar.bz2 |
the notifier interface is shaping up
Brad: I sorted the "DN_xxx undeclared" issue out, please test
-rw-r--r-- | libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp | 41 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 152 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 36 |
3 files changed, 171 insertions, 58 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 | |||
@@ -7,14 +7,15 @@ | |||
7 | using namespace Opie::Core; | 7 | 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 | { |
20 | Q_OBJECT | 21 | Q_OBJECT |
@@ -26,9 +27,12 @@ public: | |||
26 | setMainWidget( vbox ); | 27 | setMainWidget( vbox ); |
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 | ||
34 | g2 = new QVButtonGroup( "Specify Trigger Type", hbox ); | 38 | g2 = new QVButtonGroup( "Specify Trigger Type", hbox ); |
@@ -44,8 +48,9 @@ public: | |||
44 | g2->insert( c4, Create ); | 48 | g2->insert( c4, Create ); |
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 ); |
51 | QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 ); | 56 | QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 ); |
@@ -67,34 +72,54 @@ public: | |||
67 | 72 | ||
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 | { |
83 | odebug << "cancelled." << oendl; | 99 | odebug << "cancelled." << oendl; |
84 | } | 100 | } |
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(); |
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 ) ); | ||
95 | odebug << "Filename = " << filename << oendl; | 119 | odebug << "Filename = " << filename << oendl; |
96 | } | 120 | } |
121 | } | ||
97 | 122 | ||
98 | void trigger() | 123 | void trigger() |
99 | { | 124 | { |
100 | owarn << "FIRE!" << oendl; | 125 | owarn << "FIRE!" << oendl; |
@@ -103,9 +128,9 @@ public slots: | |||
103 | private: | 128 | 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 ) |
111 | { | 136 | { |
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 | |||
@@ -31,128 +31,196 @@ using namespace Opie::Core; | |||
31 | 31 | ||
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> |
38 | 39 | ||
39 | /* STD */ | 40 | /* STD */ |
40 | #include <sys/types.h> | 41 | #include <sys/types.h> |
41 | #include <sys/stat.h> | 42 | #include <sys/stat.h> |
43 | #ifndef _GNU_SOURCE | ||
44 | #define _GNU_SOURCE | ||
42 | #include <fcntl.h> | 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 ) |
50 | { | 60 | :QObject( parent, name ), _active( false ) |
51 | public: | ||
52 | OFileNotification( QObject* receiver, const char* member, OFileNotificationType type ) : _type( type ) | ||
53 | { | ||
54 | _signal.connect( receiver, member ); | ||
55 | } | ||
56 | ~OFileNotification() | ||
57 | { | 61 | { |
62 | qDebug( "OFileNotification::OFileNotification()" ); | ||
58 | } | 63 | } |
59 | 64 | ||
60 | void activate() | ||
61 | { | ||
62 | _signal.activate(); | ||
63 | } | ||
64 | 65 | ||
65 | OFileNotificationType type() | 66 | OFileNotification::~OFileNotification() |
66 | { | 67 | { |
67 | return _type; | 68 | qDebug( "OFileNotification::~OFileNotification()" ); |
68 | } | 69 | } |
69 | 70 | ||
70 | private: | ||
71 | OFileNotificationType _type; | ||
72 | QSignal _signal; | ||
73 | }; | ||
74 | |||
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; |
103 | } | ||
104 | qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) path, fd, type ); | ||
105 | notification_list.insert( fd, this ); | ||
106 | _type = type; | ||
107 | _path = path; | ||
108 | _fd = fd; | ||
109 | return fd; | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); | ||
114 | return -1; | ||
99 | } | 115 | } |
100 | qDebug( "OFileNotifier::singleShot(): Subscribed for changes to %s (fd = %d)", (const char*) path, fd ); | 116 | } |
101 | notification_list.insert( fd, new OFileNotification( receiver, member, type ) ); | 117 | |
118 | |||
119 | void OFileNotification::stop() | ||
120 | { | ||
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 ) ); | ||
102 | } | 127 | } |
103 | else | 128 | else |
104 | { | 129 | { |
105 | qWarning( "OFileNotifier::singleShot(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); | 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; | ||
106 | } | 153 | } |
154 | |||
155 | void OFileNotification::activate() | ||
156 | { | ||
157 | emit triggered(); | ||
158 | _signal.activate(); | ||
107 | } | 159 | } |
108 | 160 | ||
109 | 161 | ||
110 | void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) | 162 | void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) |
111 | { | 163 | { |
112 | qWarning( "OFileNotifier::__signalHandler(): reached." ); | 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 ) |
116 | { | 176 | { |
117 | fn->activate(); | 177 | fn->activate(); |
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 | ||
158 | } | 226 | } |
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 | |||
@@ -29,10 +29,11 @@ _;:, .> :=|. This program is free software; you can | |||
29 | #ifndef OFILENOTIFY_H | 29 | #ifndef OFILENOTIFY_H |
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> |
38 | #include <fcntl.h> | 39 | #include <fcntl.h> |
@@ -48,22 +49,41 @@ enum OFileNotificationType { Single = 0x0000000, | |||
48 | Delete = DN_DELETE, | 49 | Delete = DN_DELETE, |
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 | } |
69 | } | 89 | } |