From df539f67050ebe61b5dc589f9c138bb9ef1719f6 Mon Sep 17 00:00:00 2001 From: mickeyl Date: Sun, 18 Apr 2004 18:25:24 +0000 Subject: the notifier interface is shaping up Brad: I sorted the "DN_xxx undeclared" issue out, please test --- 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; using namespace Opie::Ui; /* QT */ +#include #include #include #include #include +#include #include -#include class DemoApp : public OApplication { @@ -27,7 +28,10 @@ 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 ); @@ -45,6 +49,7 @@ public: g2->insert( c5, Delete ); g2->insert( c6, Rename ); g2->insert( c7, Attrib ); + connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); g1 = new QVButtonGroup( "Add/Remove", hbox ); QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); @@ -68,15 +73,26 @@ public: public: void addTrigger( bool multi = false ) { + if ( !m ) + { + QMessageBox::warning( 0, "Add Trigger", "

Can't add trigger without at least one selected trigger type

", "&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 { @@ -85,14 +101,23 @@ public: } public slots: - + void modifierClicked( int modifier ) { (int)m ^= modifier; }; void addSingle() { addTrigger(); }; void addMulti() { addTrigger( true ); }; void delTrigger() { - QString filename( "bla" ); - odebug << "Filename = " << filename << oendl; + QListViewItem* item = l->selectedItem(); + if ( !item ) + { + QMessageBox::warning( 0, "Del Trigger", "

No trigger selected!

", "&Sorry", 0 ); + return; + } + else + { + QString filename( item->text( 0 ) ); + odebug << "Filename = " << filename << oendl; + } } void trigger() @@ -104,7 +129,7 @@ private: OListView* l; QButtonGroup* g1; QButtonGroup* g2; - int m; + OFileNotificationType m; }; 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; /* OPIE */ /* QT */ +#include #include #include #include @@ -39,77 +40,136 @@ using namespace Opie::Core; /* STD */ #include #include -#include +#ifndef _GNU_SOURCE + #define _GNU_SOURCE + #include + #undef _GNU_SOURCE +#else + #include +#endif #include #include +#include + +static QIntDict 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 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 ) { 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]; if ( fn ) @@ -118,40 +178,48 @@ void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) #if 1 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(); } } #endif } 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 @@ -30,8 +30,9 @@ _;:,     .>    :=|. This program is free software; you can #define OFILENOTIFY_H /* QT */ -#include #include +#include +#include /* STD */ #include @@ -49,20 +50,39 @@ enum OFileNotificationType { Single = 0x0000000, Rename = DN_RENAME, 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; }; } -- cgit v0.9.0.2