-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 @@ -9,10 +9,11 @@ using namespace Opie::Ui; /* QT */ +#include <qcheckbox.h> #include <qvbox.h> #include <qhbox.h> #include <qhbuttongroup.h> #include <qvbuttongroup.h> +#include <qmessagebox.h> #include <qpushbutton.h> -#include <qcheckbox.h> class DemoApp : public OApplication @@ -28,5 +29,8 @@ public: l = new OListView( vbox ); l->addColumn( "Notification Path" ); - l->addColumn( "Trigger" ); + l->addColumn( "Trigger Type" ); + l->addColumn( "Trigger Mask" ); + l->setColumnAlignment( 1, AlignCenter ); + l->setColumnAlignment( 2, AlignCenter ); QHBox* hbox = new QHBox( vbox ); @@ -46,4 +50,5 @@ public: g2->insert( c6, Rename ); g2->insert( c7, Attrib ); + connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); g1 = new QVButtonGroup( "Add/Remove", hbox ); @@ -69,13 +74,24 @@ public: void addTrigger( bool multi = false ) { + if ( !m ) + { + QMessageBox::warning( 0, "Add Trigger", "<p>Can't add trigger without at least one selected trigger type</p>", "&Sorry", 0 ); + return; + } + QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); if ( !filename.isEmpty() ) { odebug << "Filename = " << filename << oendl; - new OListViewItem( l, filename, "Modify" ); - + int fntype = m; + if ( multi ) fntype |=(int) Multi; - OFileNotifier::singleShot( filename, this, SLOT( trigger() ) ); + QString modifier = QString().sprintf( " = 0x%08x", fntype ); + new OListViewItem( l, filename, multi ? "MULTI" : "SINGLE", modifier ); + if ( !multi ) + OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); + else + OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); } else @@ -86,5 +102,5 @@ public: public slots: - + void modifierClicked( int modifier ) { (int)m ^= modifier; }; void addSingle() { addTrigger(); }; void addMulti() { addTrigger( true ); }; @@ -92,6 +108,15 @@ public slots: void delTrigger() { - QString filename( "bla" ); - odebug << "Filename = " << filename << oendl; + QListViewItem* item = l->selectedItem(); + if ( !item ) + { + QMessageBox::warning( 0, "Del Trigger", "<p>No trigger selected!</p>", "&Sorry", 0 ); + return; + } + else + { + QString filename( item->text( 0 ) ); + odebug << "Filename = " << filename << oendl; + } } @@ -105,5 +130,5 @@ private: QButtonGroup* g1; QButtonGroup* g2; - int m; + OFileNotificationType m; }; 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 @@ -33,4 +33,5 @@ using namespace Opie::Core; /* QT */ +#include <qobject.h> #include <qsignal.h> #include <qintdict.h> @@ -40,43 +41,45 @@ using namespace Opie::Core; #include <sys/types.h> #include <sys/stat.h> -#include <fcntl.h> +#ifndef _GNU_SOURCE + #define _GNU_SOURCE + #include <fcntl.h> + #undef _GNU_SOURCE +#else + #include <fcntl.h> +#endif #include <string.h> #include <errno.h> +#include <unistd.h> + +static QIntDict<OFileNotification> notification_list; namespace Opie { namespace Core { -class OFileNotification +OFileNotification::OFileNotification( QObject* parent, const char* name ) + :QObject( parent, name ), _active( false ) { - public: - OFileNotification( QObject* receiver, const char* member, OFileNotificationType type ) : _type( type ) - { - _signal.connect( receiver, member ); - } - ~OFileNotification() - { - } - - void activate() - { - _signal.activate(); - } + qDebug( "OFileNotification::OFileNotification()" ); +} - OFileNotificationType type() - { - return _type; - } - private: - OFileNotificationType _type; - QSignal _signal; -}; +OFileNotification::~OFileNotification() +{ + qDebug( "OFileNotification::~OFileNotification()" ); +} -static QIntDict<OFileNotification> notification_list; +bool OFileNotification::isActive() const +{ + return _active; +} -void OFileNotifier::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) +int OFileNotification::start( const QString& path, bool sshot, OFileNotificationType type ) { + _path = QString::null; + _fd = 0; + if ( _active ) stop(); + int fd = ::open( (const char*) path, O_RDONLY ); if ( fd != -1 ) @@ -84,31 +87,88 @@ void OFileNotifier::singleShot( const QString& path, QObject* receiver, const ch if ( notification_list.isEmpty() ) { - OFileNotifier::registerSignalHandler(); + OFileNotification::registerSignalHandler(); } int result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); if ( result == -1 ) { - qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); - return; + qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); + return -1; } + if ( !sshot ) (int) type |= (int) Multi; result = ::fcntl( fd, F_NOTIFY, type ); if ( result == -1 ) { - qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); - return; + qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); + return -1; } - qDebug( "OFileNotifier::singleShot(): Subscribed for changes to %s (fd = %d)", (const char*) path, fd ); - notification_list.insert( fd, new OFileNotification( receiver, member, type ) ); + qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) path, fd, type ); + notification_list.insert( fd, this ); + _type = type; + _path = path; + _fd = fd; + return fd; } else { - qWarning( "OFileNotifier::singleShot(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); + qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); + return -1; } } -void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) +void OFileNotification::stop() { - qWarning( "OFileNotifier::__signalHandler(): reached." ); + if ( !_active ) return; + + int result = ::fcntl( _fd, F_NOTIFY, 0 ); + if ( result == -1 ) + { + qWarning( "OFileNotification::stop(): Can't remove subscription to '%s': %s.", (const char*) _path, strerror( errno ) ); + } + else + { + ::close( _fd ); + _type = Single; + _path = QString::null; + _fd = 0; + _active = false; + } +} + + +OFileNotificationType OFileNotification::type() const +{ + return _type; +} + + +QString OFileNotification::path() const +{ + return _path; +} + +int OFileNotification::fileno() const +{ + return _fd; +} + +void OFileNotification::activate() +{ + emit triggered(); + _signal.activate(); +} + + +void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) +{ + OFileNotification* ofn = new OFileNotification(); + ofn->_signal.connect( receiver, member ); + ofn->start( path, true, type ); +} + + +void OFileNotification::__signalHandler( int sig, siginfo_t *si, void *data ) +{ + qWarning( "OFileNotification::__signalHandler(): reached." ); int fd = si->si_fd; OFileNotification* fn = notification_list[fd]; @@ -119,9 +179,9 @@ void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) if ( !(fn->type() & Multi) ) { - qDebug( "OFileNotifier::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); + qDebug( "OFileNotification::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); notification_list.remove( fd ); if ( notification_list.isEmpty() ) { - OFileNotifier::unregisterSignalHandler(); + OFileNotification::unregisterSignalHandler(); } } @@ -130,27 +190,35 @@ void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) else { - qWarning( "OFileNotifier::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); + qWarning( "OFileNotification::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); } } -void OFileNotifier::registerSignalHandler() +bool OFileNotification::registerSignalHandler() { struct sigaction act; - act.sa_sigaction = OFileNotifier::__signalHandler; + act.sa_sigaction = OFileNotification::__signalHandler; ::sigemptyset( &act.sa_mask ); act.sa_flags = SA_SIGINFO; - ::sigaction( SIGRTMIN, &act, NULL ); - qDebug( "OFileNotifier::registerSignalHandler(): done" ); + if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) + { + qWarning( "OFileNotification::registerSignalHandler(): couldn't register signal handler: %s", strerror( errno ) ); + return false; + } + qDebug( "OFileNotification::registerSignalHandler(): done" ); } -void OFileNotifier::unregisterSignalHandler() +void OFileNotification::unregisterSignalHandler() { struct sigaction act; act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; - sigemptyset( &act.sa_mask ); - ::sigaction( SIGRTMIN, &act, NULL ); - qDebug( "OFileNotifier::unregisterSignalHandler(): done" ); + ::sigemptyset( &act.sa_mask ); + if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) + if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) + { + qWarning( "OFileNotification::unregisterSignalHandler(): couldn't deregister signal handler: %s", strerror( errno ) ); + } + qDebug( "OFileNotification::unregisterSignalHandler(): done" ); } 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 @@ -31,6 +31,7 @@ _;:, .> :=|. This program is free software; you can /* QT */ -#include <qstring.h> #include <qobject.h> +#include <qsignal.h> +#include <qstring.h> /* STD */ @@ -50,18 +51,37 @@ enum OFileNotificationType { Single = 0x0000000, Attrib = DN_ATTRIB }; -class OFileNotifier : public QObject +class OFileNotification : public QObject { + Q_OBJECT + public: - static void singleShot( const QString& path, - QObject *receiver, const char *member, - OFileNotificationType type = Modify ); + OFileNotification( QObject* parent = 0, const char* name = 0 ); + ~OFileNotification(); + + static void singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); + + int start( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); + void stop(); + + OFileNotificationType type() const; + QString path() const; + int fileno() const; + bool isActive() const; + + signals: + void triggered(); + protected: - static void registerSignalHandler(); + void activate(); + static bool registerSignalHandler(); static void unregisterSignalHandler(); static void __signalHandler( int sig, siginfo_t *si, void *data ); private: - OFileNotifier(); - ~OFileNotifier(); + QString _path; + OFileNotificationType _type; + QSignal _signal; + int _fd; + bool _active; }; |