summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2004-04-18 18:25:24 (UTC)
committer mickeyl <mickeyl>2004-04-18 18:25:24 (UTC)
commitdf539f67050ebe61b5dc589f9c138bb9ef1719f6 (patch) (unidiff)
tree7baa2dc1e44be92dec2736b8205f9642fffc4302
parent56f49e8293110e488f3ea6bc6dad282981c81d4b (diff)
downloadopie-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
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/examples/opiecore/onotifydemo/onotifydemo.cpp43
-rw-r--r--libopie2/opiecore/ofilenotify.cpp160
-rw-r--r--libopie2/opiecore/ofilenotify.h36
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
@@ -3,36 +3,40 @@
3#include <opie2/oapplication.h> 3#include <opie2/oapplication.h>
4#include <opie2/ofiledialog.h> 4#include <opie2/ofiledialog.h>
5#include <opie2/olistview.h> 5#include <opie2/olistview.h>
6#include <opie2/ofilenotify.h> 6#include <opie2/ofilenotify.h>
7using namespace Opie::Core; 7using namespace Opie::Core;
8using namespace Opie::Ui; 8using 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
18class DemoApp : public OApplication 19class DemoApp : public OApplication
19{ 20{
20 Q_OBJECT 21 Q_OBJECT
21public: 22public:
22 DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" ) 23 DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" )
23 { 24 {
24 25
25 QVBox* vbox = new QVBox(); 26 QVBox* vbox = new QVBox();
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 );
35 //QCheckBox* c1 = new QCheckBox( "Multi", g2 ); 39 //QCheckBox* c1 = new QCheckBox( "Multi", g2 );
36 QCheckBox* c2 = new QCheckBox( "Access", g2 ); 40 QCheckBox* c2 = new QCheckBox( "Access", g2 );
37 QCheckBox* c3 = new QCheckBox( "Modify", g2 ); 41 QCheckBox* c3 = new QCheckBox( "Modify", g2 );
38 QCheckBox* c4 = new QCheckBox( "Create", g2 ); 42 QCheckBox* c4 = new QCheckBox( "Create", g2 );
@@ -40,16 +44,17 @@ public:
40 QCheckBox* c6 = new QCheckBox( "Rename", g2 ); 44 QCheckBox* c6 = new QCheckBox( "Rename", g2 );
41 QCheckBox* c7 = new QCheckBox( "Attrib", g2 ); 45 QCheckBox* c7 = new QCheckBox( "Attrib", g2 );
42 g2->insert( c2, Access ); 46 g2->insert( c2, Access );
43 g2->insert( c3, Modify ); 47 g2->insert( c3, Modify );
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 );
52 QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 ); 57 QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 );
53 g1->insert( plus1, 0 ); 58 g1->insert( plus1, 0 );
54 g1->insert( plus2, 1 ); 59 g1->insert( plus2, 1 );
55 g1->insert( minus, 2 ); 60 g1->insert( minus, 2 );
@@ -63,53 +68,73 @@ public:
63 hbox->show(); 68 hbox->show();
64 vbox->show(); 69 vbox->show();
65 showMainWidget( vbox ); 70 showMainWidget( vbox );
66 } 71 }
67 72
68public: 73public:
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
87public slots: 103public 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()
99 { 124 {
100 owarn << "FIRE!" << oendl; 125 owarn << "FIRE!" << oendl;
101 } 126 }
102 127
103private: 128private:
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
110int main( int argc, char** argv ) 135int main( int argc, char** argv )
111{ 136{
112 DemoApp* app = new DemoApp( argc, argv ); 137 DemoApp* app = new DemoApp( argc, argv );
113 app->exec(); 138 app->exec();
114 139
115 return 0; 140 return 0;
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
@@ -27,133 +27,201 @@ _;:,     .>    :=|. This program is free software; you can
27*/ 27*/
28 28
29#include "ofilenotify.h" 29#include "ofilenotify.h"
30using namespace Opie::Core; 30using 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>
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
54static QIntDict<OFileNotification> notification_list;
45 55
46namespace Opie { 56namespace Opie {
47namespace Core { 57namespace Core {
48 58
49class OFileNotification 59OFileNotification::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: 66OFileNotification::~OFileNotification()
71 OFileNotificationType _type; 67{
72 QSignal _signal; 68 qDebug( "OFileNotification::~OFileNotification()" );
73}; 69}
74 70
75 71
76static QIntDict<OFileNotification> notification_list; 72bool OFileNotification::isActive() const
73{
74 return _active;
75}
77 76
78 77
79void OFileNotifier::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) 78int 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
110void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) 119void 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
139OFileNotificationType OFileNotification::type() const
140{
141 return _type;
142}
143
144
145QString OFileNotification::path() const
146{
147 return _path;
148}
149
150int OFileNotification::fileno() const
151{
152 return _fd;
153}
154
155void OFileNotification::activate()
156{
157 emit triggered();
158 _signal.activate();
159}
160
161
162void 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
170void 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
137void OFileNotifier::registerSignalHandler() 197bool 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
148void OFileNotifier::unregisterSignalHandler() 212void 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}
159} 227}
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
@@ -25,18 +25,19 @@ _;:,     .>    :=|. This program is free software; you can
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 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>
39 40
40namespace Opie { 41namespace Opie {
41namespace Core { 42namespace Core {
42 43
@@ -44,29 +45,48 @@ enum OFileNotificationType { Single = 0x0000000,
44 Multi = DN_MULTISHOT, 45 Multi = DN_MULTISHOT,
45 Access = DN_ACCESS, 46 Access = DN_ACCESS,
46 Modify = DN_MODIFY, 47 Modify = DN_MODIFY,
47 Create = DN_CREATE, 48 Create = DN_CREATE,
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
52class OFileNotifier : public QObject 53class 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}
70 90
71#endif 91#endif
72 92