summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog7
-rw-r--r--examples/opiecore/onotifydemo/onotifydemo.cpp42
-rw-r--r--libopie2/opiecore/ofilenotify.cpp272
-rw-r--r--libopie2/opiecore/ofilenotify.h93
4 files changed, 168 insertions, 246 deletions
diff --git a/ChangeLog b/ChangeLog
index 2d5c886..7e81b7e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,279 +1,280 @@
2005-??-?? Opie 1.2.1
New Features
------------
* OpieStumbler: Scans WiFi networks using the wireless extension scanning (skyhusker)
Fixed Bugs
----------
+ * #1476 - Wrong order of application entries in the O-menu (skyhusker)
* #1535 - Missing line break and unnecessary location shown with Today-Calendar plugin (deller)
* #1565 - crash-fix in odevice.cpp while scanning the distribution table (deller)
* #1614 - Make Opie-console start in $HOME instead of / (skyhusker)
* n.a. - always show volume and wireless applet popups inside visible screen (deller)
* n.a. - scale O-Menu-Applets appropriately (mickeyl)
* n.a. - libopienet: fix bugs in wireless scanning and setting SSID (skyhusker)
* n.a. - Wellenreiter: relax WE version matching test a bit (mickeyl)
- * n.a. - scale BluezApplet appropriately (mickeyl)
+ * n.a. - scale BluezApplet appropriately and use larger icons (mickeyl)
* n.a. - memoryapplet: fix crash in memoryapplet on kernels without swap support (seneca cunningham)
- * #1476 - Wrong order of application entries in the O-menu (skyhusker)
Internal
--------
- * make BluezApplet use OTaskbarApplet (mickeyl)
+ * Make BluezApplet use OTaskbarApplet (mickeyl)
+ * Rewrite OFileNotification to use the upcoming inotify interface instead of the deprecated dnotify (mickeyl)
2005-03-25 Opie 1.2.0
Fixed Bugs
----------
* #1613 - AdvancedFM - scale toolbar icons appropriately (drw)
* #1620 - OFileSelector - show the button on press and not on press on hold (alwin)
* #1473 - Opie-Eye - Same as #1620 but we lack a common FileSystem Button class (zecke)
* n.a. - PackageManager - fix bug where messages show up multiple times in install dialog (drw)
* n.a. - make qpeglobal.h include qglobal.h (zecke)
2005-03-20 Opie 1.2.0-rc1
New Features
------------
* Launcher: Support a static background pixmap (mickeyl)
* LauncherSettings: Choose whether to have a static background pixmap (mickeyl)
* PackageManager supports the 'lists_dir' ipkg configuration option (drw)
* Added hi-res inline images for large resolution devices (drw)
* Improved launcher icons for consistency (ar)
* Datebook: Added plugin system to datebook so holidays and birthdays from contacts may displayed in datebook (alwin)
Fixed Bugs
----------
* #1236 - VCards contained empty home and work address entries causing Palms to crash (eilers)
* #1412 - Launcher Settings - fixed default settings for background in Edit tab dialog (drw)
* #1472 - Opie textedit now check for unsaved changes on ESC key (ljp)
* #1474 - Implement GUI for Scrollbars on the Left in Appearance (zecke)
* #1482 - Fix double '/' in paths (zecke)
* #1536 - Autosave of custom locations in opie backup (ar)
* #1539 - Fixed displaying too long path in the delete dialog in opie-eye (zecke)
* #1540 - Implemented deletion of DocLnks in opie-eye (zecke)
* #1542 - Fixed Todo crash when priority < 1 or > 5 (drw)
* #1550 - Browse for alarm sound start in QPEDIR/sounds/ (zecke)
* #1554 - Fixed Opie-Console name in .desktop file (mickeyl)
* #1556 - Start to look for sound files in /opt/QtPalmtop/sounds (zecke)
* #1558 - Fixed opie-login breaking opie startup (mickeyl)
* #1560 - Fixed Opie-Console picking up the wrong shell (bluelightning)
* #1570 - Confirmation needed befor Restore a backup and overwrite local data (ar)
* #1591 - Addressbook sortorder changed by clicking on column 0 (eilers)
* #1599 - Security - change recommendation for opie-multiauth to opie-securityplugin (gints)
* #1604 - Checkbook crashed on startup (drw)
* #1608 - Addressbook crashed after search, which may caused by not initialzed member variable (eilers)
* #1608 - QueryByExampe-Datediff on SQL database did not worked properly (eilers)
* n.a. - Netsystemtime - fixed UI to prevent error dialog from displaying when it shouldn't, get rid of some compiler warnings (drw)
* n.a. - PackageManager - fixed where last package in status file was not shown as installed when it should be (drw)
* n.a. - PackageManager - fixed bug where lists_dir was not being honored at startup (drw)
* n.a. - PackageManager - provided default value for lists_dir when none is entered in configuration dialog (drw)
* n.a. - OTabWidget - fixed scroll buttons, fix display position of tabs (drw)
* n.a. - AddressBook - fixed sorting by 'File As' name (drw)
* n.a. - AddressBook - fixed category handling for 'All' and 'Unfiled' (eilers)
* n.a. - AddressBook - fixed letter picker record selection and sort records afterwards (drw)
Internal
--------
* Worked around bug in Qt/Embedded 2.3.10: qt_version() returns 231 (mickeyl)
* Killed the need for weak symbols in QtE (zecke)
* Added optional building libqpe without inline images (mickeyl)
* OColorButton - fixed so does not emit a colorSelected signal inside of resizeEvent (drw)
2005-02-03 Opie 1.1.9
New Features
------------
* Number of icon columns in Launcher is customizable through Launcher.conf (hrw,zecke,mickeyl)
* Number of icon columns in Launcher is customizable through LauncherSettings (mickeyl)
* Usability enhancements in OpieIRC (skyhusker)
Fixed Bugs
----------
* #1501 - Fixed bug in todo sql backend (eilers)
* #1505 - Added more Swap sizes in memoryapplet (mickeyl)
* #1525 - Hopefully fixed double alarms and not removing alarms set with the Clock application (zecke)
* #1533 - Security Owner Dialog (shown in case of unsuccessfull authentiacation) wasn't able to display information in non latin1 encoding (zecke)
* n.a. - Removed hard coded font sizes in a couple of inputmethods (mickeyl)
* n.a. - Removed MediumDlg appearing prior to FirstUsage wizard (i.e. calibration) (mickeyl)
* n.a. - Fixed numerous buglets in OpieIRC (skyhusker)
Internal
--------
* Added the Qtopia 1.7 SDK macros for quick-apps to easa compilation of 3rd party apps against our headers (mickeyl)
* You can now use the Opie build system in combination with a OpenEmbedded staging area which makes a nice cross development environment (mickeyl)
* Made Opie compilable with Qt/Embedded 2.3.10 (ar)
* Changed Launcher to get default orientation from ODevice w/ QWS_DISPLAY overriding (mickeyl)
* Build tree cleanups (mickeyl)
2004-11-26 Opie 1.1.8
New Features
------------
* PackageManager supports installation of local ipkg files (drw)
* PackageManager supports linking of applications to root (drw)
* PackageManager supports src/gz feeds (drw,wimpie)
* Added a syslog information tab to sysinfo (mickeyl)
* Added new, more consistent, PIM icons + a GIMP teplate (ar)
Fixed Bugs
----------
* #1017 - Tetrix doesn't display correctly for high resolution screens (drw)
* #1269 - VCards were imported into personal area if it was activated (eilers)
* #1464 - Packagemanager dont set active filter after install a package (drw)
* #1479 - Improved VCard-Parser to import VCards created by Evolution 2 and Apple Addressbook (eilers)
* #1493 - Fixed one column layout bug of the launcher (hrw)
* n.a. - PackageManager - (Minor UI tweak) in filter dialog, when option is enabled, set focus to widget that corresponds to that option (drw)
* n.a. - PackageManager - (Minor UI tweak) fix double entry in source feed configuration when adding a new feed (drw)
* n.a. - Battery Applet - fix sizing of battery info popup (drw,mickeyl)
Internal
--------
* Moved libopie1 to unsupported (mickeyl)
* Implemented generic queryByExample() with incremental searching. A lot of internal changes of the Pim2-library (eilers)
* Added fast and full featured and incremental sorted() for SQL addressbook backend (eilers)
2004-11-14 Opie 1.1.7
New Features
------------
* libOpieDB now uses SQLite V3 instead V2. Remember to upgrade your database files! (eilers)
* Backup now uses the busy indicator when backing up and restore (ar)
* OpiePlayer2 gained adding of Directories to the playlist (zecke)
* OpiePlayer2 better error handling (zecke)
* OpiePlayer2 progress indication while streaming (zecke)
* OpiePlayer2 ported to use libxine 1.0.0-rc6a (brad,zecke)
* Ported brightnessapplet from Qtopia 1.7 (mickeyl)
* Opie-Eye got a Digital Camera File Backend (alwin,zecke)
* Support for Tuxpad1 of Tradesquare.NL (mickeyl,zecke)
* Opie-Console use Custom Font and Size in a Profile (harlekin)
* Opie-Console transparently log the Output and Input to a file (harlekin)
* Added new O-menu icon to lock the PDA immediately: opie-lockapplet (clem)
* Opie-Security now hides the plugin-based authentication tabs if no auth. plugin package is installed (clem)
* Opie-Security gained a 'test authentication' button (clem)
* Opie-Eye got a more unique layout (menubar), a slideshow, user can setup some defaults
* Opie-Mail improve the handling of POP mail boxes (alwin)
* Both Opie-Eye and Opie-Mail were greatly improved due the hard work of Rajko Albrecht(alwin)
* Opie IRC - backports of the 'NeIRC fork' (zecke)
Fixed Bugs
----------
* #501 - Pickboard is able to show 'Umlaute' (TT,zecke)
* #608 - Make Opie usable for left handed users (zecke)
* #957 - Import of VCards/VTodos/VEvents with BASE64 encoding (ljp,zecke)
* #1245 - Opie-Go 'paused' (zecke)
* #1358 - DocTab didn't show any MimeTypes (was fixed earlier) (zecke)
* #1380 - QDateBookAccess::remove() doesn't remove entries (eilers, zecke)
* #1395 - Build VNC Backend with gcc3.4
* #1440 - The icon of opie-mobilemsg is missing (CoreDump)
* #1426 - Add missing opie-bartender Icon (CoreDump)
* #1445 - Opie-Sheet Has No Icon (CoreDump)
* #1448 - Brightness Applet added (mickeyl)
* #1450 - ZSame didn't clear the bonus item after winning a game (zecke)
* #1482 - Fix OFileSelector to be able to sort by size (zecke)
* n.a. - Opie-mail: fixed some crasher, some layout-problems
* n.a. - Converted applications to not hardcode /opt/QtPalmtop but to use QPEApplication::qpeDir (zecke)
* n.a. - Converted usage of qpeDir() not to include a '/' as first charachter of the string (zecke)
* n.a. - Build system: Enable distcc and ccache when crosscompiling too, and use them everywhere we can (clem)
* n.a. - Build system: Fix deps in several config.in (and fix scripts/deps.pl too) to stop breaking builds, especially with make -j highNumber (clem)
* n.a. - Removed hardcoded icon size in a couple of applets (mickeyl)
Internal
--------
* Opie-Qashmoney has been moved to unsupported (mickeyl)
* Opie-Ubrowser has been moved to unsupported (mickeyl)
2004-09-17 Opie 1.1.6
New Features
------------
* Fifteen gained configurable number of items (zecke)
* Fifteen can have custom background images (zecke)
* Added daemonizing capabilities to QWS Server [via Qt/Embedded] (mickeyl)
* Integrated the new security framework into libopie2 (zecke,clem)
* Converted the launcher to use the new security framework (zecke)
* Backup can now handle custom locations for backup and restore (ar)
* Implemented right-on-hold feedback (wimpie,zecke)
* Lots of new features in opie-reader (tim,pohly)
* Build system cleanups (schurig)
Fixed Bugs
--------
* #1005 - Fixed backup to CompactFlash (ar)
* #1167 - Fixed Opie write crashing on more text than one page (ar)
* #1225 - Fixed repeated light flashing on Zaurus with keyz (mickeyl)
* #1359 - Fixed bookmarks in Gutenbrowser (ljp)
* #1361 - Fixed auto upercase in Opie-Addressbook (eilers)
* #1370 - Pimconverter now reacts on cancel key (eilers)
* #1376 - Bring back the capslock/numlock display (zecke)
* #1383 - Language settings now warns about losing open apps (Markus Litz)
* #1393 - Fixed line wrap issues in opie-console for the default profile (mickeyl)
* #1394 - Fixed oversized headline in opie-login (coredump)
* #1396 - Opie-console captures the escape key and vim is working (zecke)
* #1401 - Scrollbar is now only visible if necessary in DocTab (mickeyl)
2004-07-06 Opie 1.1.4
New Features
------------
* Added four themes courtesy Robert Griebl (http://www.softforge.de/zstyle)
* Added Conversion tool for pim-data (eilers)
* Introduced new OPimAccessFactory and OBackendFactory which simplyfies database access (eilers)
* Modified the PIM API for providing generic use of OPimRecords (eilers)
* Clicking on the application symbol now iterates over the application's top level widgets if already raised (zecke)
Fixed Bugs
--------
* #1068 - Country Drop Down Box Off Screen
* #1291 - Opie tinykate does not open .desktop files (ar)
* #1291 - Opie sheet not saving correctly (ar)
* #1294 - Opie does not know about British Summer Time
* #1314 - Drawpad initialization (mickeyl)
* #1317 - Packagemanager crashes on hold-down or install (chicken)
* #1321 - Batteryapplet graphic glitch (harlekin)
* #1324 - ZSafe not starting up (mickeyl)
* #1328 - Personal Home Address fields is trimmed to 1char (eilers)
* #1327 - Opie-mail ipk does not depend on libopiedb2 (chicken)
* #1345 - Networksettingsplugin wlan plugin dependency on libpcap0 (mickeyl)
* #1348 - Datebook dependency on libopiedb2 (chicken)
* #1328 - Switched SQLDatabase and VCards char encoding from latin1 to unicode (eilers)
2004-04-25 Opie 1.1.3
* Introduced first implementation of SQL-Support using SQLite (eilers)
* Added a new Gutenberg Project reader app - opie-gutenbrowser (ljp)
* Added a real system graffiti character set (brad)
* Added Generic Keyconfig Widget (zecke)
* Improved Screenshotapplet and Drawpad integration. You can now open a screenshot in drawpad and take notes (zecke)
* Added new Bible reader app - opie-dagger (drw)
* Added a new Image Viewer. Work is ongoing (zecke,alwin)
* Added namespace usage in libopie2 and everywhere (zecke,alwin)
* Enabled the possibility to pass command line arguments to applications (mickeyl)
* Added an about applet showing some credits and information about Opie (mickeyl)
* Added benchmarking functionality to sysinfo (mickeyl)
* Added applet and configuration application for switching hardware keyboard layouts (alwin)
* Ported applications from libopie1 to libopie2* (drw,ar,alwin)
* Imported fullscreen and font improvements from the Qkonsole fork to embeddedkonsole (waspe)
* Clean-up of package information in control files (drw)
* Repaired mediummount which was broken since integrating the quicklauncher (alwin)
* Improved big-screen support (zecke,ar)
* Improved multikeyboard support, added keyboard layout switching applet (mouse)
* Added a new mail client based on libetpan (harlekin,alwin,jgf)
* Added new package manager - opie-packagemanager (drw)
* Improved light-n-power for C7x0 (mickeyl)
* Added automatic rotation support for C7x0 (treke)
* Split libopie1 up into a set of smaller - functionally grouped - libraries (mickeyl)
* Added scanning the wireless network neighbourhood to networksettings (mickeyl)
2003-11-29 Opie 1.0.3
* Released as Version 1.0.3
* Improved i18n (various contributors)
* Reduced application startup time by integrating the TT quicklauncher (zecke,harlekin)
* Made the Documents Tab optional (mickeyl)
* Integrated basic support for HP iPAQ 54xx and the Jornada 5xx (chicken)
2003-08-04 Opie 1.0.0
diff --git a/examples/opiecore/onotifydemo/onotifydemo.cpp b/examples/opiecore/onotifydemo/onotifydemo.cpp
index a38ffee..0e84d80 100644
--- a/examples/opiecore/onotifydemo/onotifydemo.cpp
+++ b/examples/opiecore/onotifydemo/onotifydemo.cpp
@@ -1,132 +1,140 @@
#include "onotifydemo.h"
/* OPIE */
#include <opie2/odebug.h>
#include <opie2/oapplication.h>
#include <opie2/ofiledialog.h>
#include <opie2/olistview.h>
#include <opie2/ofilenotify.h>
using namespace Opie::Core;
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>
DemoApp::DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" )
{
QVBox* vbox = new QVBox();
setMainWidget( vbox );
l = new OListView( vbox );
l->addColumn( "Notification Path" );
l->addColumn( "Trigger Type" );
l->addColumn( "Trigger Mask" );
l->setColumnAlignment( 1, AlignCenter );
l->setColumnAlignment( 2, AlignCenter );
QHBox* hbox = new QHBox( vbox );
-
g2 = new QVButtonGroup( "Specify Trigger Type", hbox );
- //QCheckBox* c1 = new QCheckBox( "Multi", g2 );
- QCheckBox* c2 = new QCheckBox( "Access", g2 );
- QCheckBox* c3 = new QCheckBox( "Modify", g2 );
- QCheckBox* c4 = new QCheckBox( "Create", g2 );
- QCheckBox* c5 = new QCheckBox( "Delete", g2 );
- QCheckBox* c6 = new QCheckBox( "Rename", g2 );
- QCheckBox* c7 = new QCheckBox( "Attrib", g2 );
- g2->insert( c2, Access );
- g2->insert( c3, Modify );
- g2->insert( c4, Create );
- g2->insert( c5, Delete );
- g2->insert( c6, Rename );
- g2->insert( c7, Attrib );
+ QCheckBox* c1 = new QCheckBox( "Access", g2 );
+ QCheckBox* c2 = new QCheckBox( "Modify", g2 );
+ QCheckBox* c3 = new QCheckBox( "Attrib", g2 );
+ QCheckBox* c4 = new QCheckBox( "CloseWrite", g2 );
+ QCheckBox* c5 = new QCheckBox( "CloseNoWrite", g2 );
+ QCheckBox* c6 = new QCheckBox( "MovedFrom", g2 );
+ QCheckBox* c7 = new QCheckBox( "MovedTo", g2 );
+ QCheckBox* c8 = new QCheckBox( "DeleteSubdir", g2 );
+ QCheckBox* c9 = new QCheckBox( "DeleteFile", g2 );
+ QCheckBox* c10 = new QCheckBox( "CreateSubdir", g2 );
+ QCheckBox* c11 = new QCheckBox( "CreateFile", g2 );
+ QCheckBox* c12 = new QCheckBox( "Unmount", g2 );
+ g2->insert( c1, Access );
+ g2->insert( c2, Modify );
+ g2->insert( c3, Attrib );
+ g2->insert( c4, CloseWrite );
+ g2->insert( c5, CloseNoWrite );
+ g2->insert( c6, MovedFrom );
+ g2->insert( c7, MovedTo );
+ g2->insert( c8, DeleteSubdir );
+ g2->insert( c9, DeleteFile );
+ g2->insert( c10, CreateSubdir );
+ g2->insert( c11, CreateFile );
+ g2->insert( c12, Unmount );
connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) );
g1 = new QVButtonGroup( "Add/Remove", hbox );
QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 );
QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 );
QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 );
g1->insert( plus1, 0 );
g1->insert( plus2, 1 );
g1->insert( minus, 2 );
connect( plus1, SIGNAL( clicked() ), this, SLOT( addSingle() ) );
connect( plus2, SIGNAL( clicked() ), this, SLOT( addMulti() ) );
connect( minus, SIGNAL( clicked() ), this, SLOT( delTrigger() ) );
g1->show();
g2->show();
l->show();
hbox->show();
vbox->show();
showMainWidget( vbox );
}
void DemoApp::addTrigger( bool multi )
{
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;
int fntype = m;
- if ( multi ) fntype |=(int) Multi;
-
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 );
+ odebug << "not yet implemented..." << oendl;
}
else
{
odebug << "cancelled." << oendl;
}
}
void DemoApp::modifierClicked( int modifier ) { m = static_cast<OFileNotificationType>( (int)m ^ int(modifier) ); };
void DemoApp::addSingle() { addTrigger(); };
void DemoApp::addMulti() { addTrigger( true ); };
void DemoApp::delTrigger()
{
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;
}
}
void DemoApp::trigger()
{
owarn << "FIRE!" << oendl;
}
int main( int argc, char** argv )
{
DemoApp* app = new DemoApp( argc, argv );
app->exec();
return 0;
}
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp
index 2a9bb8c..c221e58 100644
--- a/libopie2/opiecore/ofilenotify.cpp
+++ b/libopie2/opiecore/ofilenotify.cpp
@@ -1,322 +1,228 @@
/*
                This file is part of the Opie Project
- =. Copyright (C) 2004 Michael 'Mickey' Lauer <mickey@Vanille.de>
+ =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
.=l. Copyright (C) The Opie Team <opie-devel@handhelds.org>
         .>+-=
_;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
-- .   .-<_>     .<> Foundation; either version 2 of the License,
-    ._= =}       : or (at your option) any later version.
+- .   .-<_>     .<> Foundation; version 2 of the License.
+    ._= =}       :
  .%`+i>       _;_.
  .i_,=:_.      -<s. This program is distributed in the hope that
   +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
  : ..    .:,     . . . without even the implied warranty of
  =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
:     =  ...= . :.=-
-.   .:....=;==+<; You should have received a copy of the GNU
-_. . .   )=.  = Library General Public License along with
  --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "ofilenotify.h"
using namespace Opie::Core;
/* OPIE */
/* QT */
#include <qobject.h>
+#include <qsocketnotifier.h>
#include <qsignal.h>
#include <qintdict.h>
#include <qdir.h>
/* STD */
#include <sys/types.h>
#include <sys/stat.h>
-#include <assert.h>
+#include <sys/ioctl.h>
#include <fcntl.h>
+#include <assert.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
static QIntDict<OFileNotification> notification_list;
+QSocketNotifier* OFileNotification::_sn;
+int OFileNotification::_fd = -1;
+
+#define INOTIFY_DEVICE "/dev/inotify"
+
namespace Opie {
namespace Core {
OFileNotification::OFileNotification( QObject* parent, const char* name )
- :QObject( parent, name ), _active( false )
+ :QObject( parent, name ), _active( false ), _multi( true )
{
qDebug( "OFileNotification::OFileNotification()" );
}
OFileNotification::~OFileNotification()
{
+ stop();
qDebug( "OFileNotification::~OFileNotification()" );
}
bool OFileNotification::isActive() const
{
return _active;
}
-int OFileNotification::start( const QString& path, bool sshot, OFileNotificationType type )
+int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type )
{
- _path = QString::null;
- _fd = 0;
- if ( _active ) stop();
- QString dirpath;
-
- // check if path exists and whether it is a file or a directory, if it exists at all
- int result = ::stat( (const char*) path, &_stat );
- if ( !(type & Create) && result == -1 )
- {
- qWarning( "OFileNotification::start(): Can't stat '%s': %s.", (const char*) path, strerror( errno ) );
- return -1;
- }
-
- // if it is not a directory, we need to find out in which directory the file is
- bool isDirectory = S_ISDIR( _stat.st_mode );
- if ( !isDirectory )
- {
- int slashpos;
- slashpos = path.findRev( '/' );
- if ( slashpos > 0 )
- {
- _path = path;
- dirpath = path.left( slashpos );
- }
- }
- else /* isDirectory */
- {
- qWarning( "FIXME FIXME FIXME = Directory Notification Not Yet Implemented!" );
- _path = path;
- dirpath = path;
- assert( 0 );
- }
-
- int fd = ::open( (const char*) dirpath, O_RDONLY );
- if ( fd != -1 )
+ if ( QFile::exists( path ) )
{
if ( notification_list.isEmpty() )
{
- OFileNotification::registerSignalHandler();
+ OFileNotification::registerEventHandler();
}
- result = ::fcntl( fd, F_SETSIG, SIGRTMIN );
- if ( result == -1 )
- {
- qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) dirpath, strerror( errno ) );
- return -1;
- }
- if ( !sshot ) type = static_cast<OFileNotificationType>( (int) type | (int) Multi );
- result = ::fcntl( fd, F_NOTIFY, type );
- if ( result == -1 )
+ struct inotify_watch_request iwr;
+ ::memset( &iwr, 0, sizeof iwr );
+ iwr.name = const_cast<char*>( (const char*) path );
+ iwr.mask = type;
+
+ _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr );
+
+ if ( _wd < 0 )
{
- qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) dirpath, strerror( errno ) );
+ qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) );
return -1;
}
- qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) dirpath, fd, type );
- notification_list.insert( fd, this );
+
+ notification_list.insert( _wd, this );
+ _multi = !sshot;
_type = type;
- _fd = fd;
_active = true;
- ::memset( &_stat, 0, sizeof _stat );
- ::stat( _path, &_stat );
- return fd;
+ qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd );
+ return _wd;
}
else
{
- qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) dirpath, strerror( errno ) );
+ qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) );
return -1;
}
}
void OFileNotification::stop()
{
- 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
+ notification_list.remove( _wd );
+ _path = QString::null;
+ _wd = 0;
+ _active = false;
+ if ( notification_list.isEmpty() )
{
- ::close( _fd );
- _type = Single;
- _path = QString::null;
- _fd = 0;
- _active = false;
+ OFileNotification::unregisterEventHandler();
}
}
OFileNotificationType OFileNotification::type() const
{
return _type;
}
QString OFileNotification::path() const
{
return _path;
}
-int OFileNotification::fileno() const
+bool OFileNotification::activate()
{
- return _fd;
+ emit triggered();
+ _signal.activate();
+ if ( !_multi ) stop();
+ return true;
}
-bool OFileNotification::activate()
+void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type )
{
- if ( hasChanged() )
- {
- emit triggered();
- _signal.activate();
- return true;
- }
- else
- return false;
+ OFileNotification* ofn = new OFileNotification();
+ ofn->_signal.connect( receiver, member );
+ ofn->watch( path, true, type );
}
-bool OFileNotification::hasChanged()
+void OFileNotification::inotifyEventHandler()
{
- bool c = false;
+ qWarning( "OFileNotification::__eventHandler(): reached." );
- struct stat newstat;
- ::memset( &newstat, 0, sizeof newstat );
- int result = ::stat( _path, &newstat ); // may fail if file has been renamed or deleted. that doesn't matter :)
+ char buffer[16384];
+ size_t buffer_i;
+ struct inotify_event *pevent, *event;
+ ssize_t r;
+ size_t event_size;
+ int count = 0;
- qDebug( "result of newstat call is %d (%s=%d)", result, result == -1 ? strerror( errno ) : "success", errno );
- qDebug( "stat.atime = %0lx, newstat.atime = %0lx", (long)_stat.st_atime, (long)newstat.st_atime );
- qDebug( "stat.mtime = %0lx, newstat.mtime = %0lx", (long)_stat.st_mtime, (long)newstat.st_mtime );
- qDebug( "stat.ctime = %0lx, newstat.ctime = %0lx", (long)_stat.st_ctime, (long)newstat.st_ctime );
+ r = ::read(_fd, buffer, 16384);
- if ( !c && (_type & Create) &&
- (long)_stat.st_atime == 0 && (long)_stat.st_mtime == 0 && (long)_stat.st_ctime == 0 &&
- (long)newstat.st_atime > 0 && (long)newstat.st_mtime > 0 && (long)newstat.st_ctime > 0)
- {
- qDebug( "OFileNotification::hasChanged(): file has been created" );
- c = true;
- }
- if ( !c && (_type & (Delete|Rename)) && (long)newstat.st_atime == 0 && (long)newstat.st_mtime == 0 && (long)newstat.st_ctime == 0)
- {
- qDebug( "OFileNotification::hasChanged(): file has been deleted or renamed" );
- c = true;
- }
- if ( !c && (_type & Access) && (long)_stat.st_atime < (long)newstat.st_atime )
- {
- qDebug( "OFileNotification::hasChanged(): atime changed" );
- c = true;
- }
- if ( !c && (_type & Modify) && (long)_stat.st_mtime < (long)newstat.st_mtime )
- {
- qDebug( "OFileNotification::hasChanged(): mtime changed" );
- c = true;
- }
- if ( !c && (_type & Attrib) && (long)_stat.st_ctime < (long)newstat.st_ctime )
+ if ( r <= 0 )
+ return;
+
+ buffer_i = 0;
+ while ( buffer_i < r )
{
- qDebug( "OFileNotification::hasChanged(): ctime changed" );
- c = true;
- }
+ /* Parse events and queue them ! */
+ pevent = (struct inotify_event *)&buffer[buffer_i];
+ event_size = sizeof(struct inotify_event) + pevent->len;
+ qDebug( "pevent->len = %d\n", pevent->len);
- return c;
-}
+ OFileNotification* fn = notification_list[ pevent->wd ];
+ if ( fn )
+ fn->activate();
+ else
+ assert( false );
+ //event = malloc(event_size);
+ //memmove(event, pevent, event_size);
+ //queue_enqueue(event, q);
+ buffer_i += event_size;
+ count++;
+ }
-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 );
+ qDebug( "received %d events...", count );
+ return;
}
-void OFileNotification::__signalHandler( int sig, siginfo_t *si, void *data )
+bool OFileNotification::registerEventHandler()
{
- Q_UNUSED( sig )
- Q_UNUSED( data )
- qWarning( "OFileNotification::__signalHandler(): reached." );
- int fd = si->si_fd;
- OFileNotification* fn = notification_list[fd];
- if ( fn )
- {
- // check if it really was the file (dnotify triggers on directory granularity, not file granularity)
- if ( !fn->activate() )
- {
- qDebug( "OFileNotification::__signalHandler(): false alarm ;) Restarting the trigger (if it was single)..." );
- if ( !(fn->type() & Multi ) )
- {
- int result = ::fcntl( fn->fileno(), F_NOTIFY, fn->type() );
- if ( result == -1 )
- {
- qWarning( "OFileNotification::__signalHandler(): Can't restart the trigger: %s.", strerror( errno ) );
- }
- }
- return;
- }
- #if 1
- if ( !(fn->type() & Multi) )
- {
- qDebug( "OFileNotification::__signalHandler(): '%d' was singleShot. Removing from list.", fd );
- notification_list.remove( fd );
- if ( notification_list.isEmpty() )
- {
- OFileNotification::unregisterSignalHandler();
- }
- }
- #endif
- }
- else
+ OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY );
+ if ( OFileNotification::_fd < 0 )
{
- qWarning( "OFileNotification::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" );
+ qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) );
+ return false;
}
-}
+ OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" );
+ connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) );
-bool OFileNotification::registerSignalHandler()
-{
- struct sigaction act;
- act.sa_sigaction = OFileNotification::__signalHandler;
- ::sigemptyset( &act.sa_mask );
- act.sa_flags = SA_SIGINFO;
- if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 )
- {
- qWarning( "OFileNotification::registerSignalHandler(): couldn't register signal handler: %s", strerror( errno ) );
- return false;
- }
- qDebug( "OFileNotification::registerSignalHandler(): done" );
+ qDebug( "OFileNotification::registerEventHandler(): done" );
return true;
}
-void OFileNotification::unregisterSignalHandler()
+void OFileNotification::unregisterEventHandler()
{
- struct sigaction act;
- act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL;
- ::sigemptyset( &act.sa_mask );
- if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 )
- {
- qWarning( "OFileNotification::unregisterSignalHandler(): couldn't deregister signal handler: %s", strerror( errno ) );
- }
- qDebug( "OFileNotification::unregisterSignalHandler(): done" );
+ if ( OFileNotification::_fd )
+ ::close( OFileNotification::_fd );
+ qDebug( "OFileNotification::unregisterEventHandler(): done" );
}
}
}
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h
index d820f7c..e3621cf 100644
--- a/libopie2/opiecore/ofilenotify.h
+++ b/libopie2/opiecore/ofilenotify.h
@@ -1,190 +1,197 @@
/*
                This file is part of the Opie Project
- =. Copyright (C) 2004 Michael 'Mickey' Lauer <mickey@Vanille.de>
+ =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
.=l. Copyright (C) The Opie Team <opie-devel@handhelds.org>
         .>+-=
_;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
-- .   .-<_>     .<> Foundation; either version 2 of the License,
-    ._= =}       : or (at your option) any later version.
+- .   .-<_>     .<> Foundation; version 2 of the License.
+    ._= =}       :
  .%`+i>       _;_.
  .i_,=:_.      -<s. This program is distributed in the hope that
   +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
  : ..    .:,     . . . without even the implied warranty of
  =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
:     =  ...= . :.=-
-.   .:....=;==+<; You should have received a copy of the GNU
-_. . .   )=.  = Library General Public License along with
  --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef OFILENOTIFY_H
#define OFILENOTIFY_H
#if defined (__GNUC__) && (__GNUC__ < 3)
#define _GNU_SOURCE
#endif
/* QT */
-#include <qobject.h>
+#include <qsocketnotifier.h>
#include <qsignal.h>
#include <qstring.h>
/* STD */
-#include <signal.h>
-#include <fcntl.h>
+#include "inotify.h"
namespace Opie {
namespace Core {
/*======================================================================================
* OFileNotificationType
*======================================================================================*/
/**
* @brief An enumerate for the different types of file notifications
*
* This enumerate provides a means to specify the type of events that you are interest in.
* Valid values are:
* <ul>
* <li>Access: The file was accessed (read)
* <li>Modify The file was modified (write,truncate)
- * <li>Create = The file was created in the directory
- * <li>Delete = The file was unlinked from directory
- * <li>Rename = The file was renamed
* <li>Attrib = The file had its attributes changed (chmod,chown,chgrp)
+ * <li>CloseWrite = Writable file was closed
+ * <li>CloseNoWrite = Unwritable file was closed
+ * <li>Open = File was opened
+ * <li>MovedFrom = File was moved from X
+ * <li>MovedTo = File was moved to Y
+ * <li>DeleteSubdir = Subdir was deleted
+ * <li>DeleteFile = Subfile was deleted
+ * <li>CreateSubdir = Subdir was created
+ * <li>CreateFile = Subfile was created
+ * <li>DeleteSelf = Self was deleted
+ * <li>Unmount = The backing filesystem was unmounted
* </ul>
*
**/
-enum OFileNotificationType { Single = 0x0000000,
- Multi = DN_MULTISHOT,
- Access = DN_ACCESS,
- Modify = DN_MODIFY,
- Create = DN_CREATE,
- Delete = DN_DELETE,
- Rename = DN_RENAME,
- Attrib = DN_ATTRIB };
+enum OFileNotificationType
+{
+ Access = IN_ACCESS,
+ Modify = IN_MODIFY,
+ Attrib = IN_ATTRIB,
+ CloseWrite = IN_CLOSE_WRITE,
+ CloseNoWrite = IN_CLOSE_NOWRITE,
+ Open = IN_OPEN,
+ MovedFrom = IN_MOVED_FROM,
+ MovedTo = IN_MOVED_TO,
+ DeleteSubdir = IN_DELETE_SUBDIR,
+ DeleteFile = IN_DELETE_FILE,
+ CreateSubdir = IN_CREATE_SUBDIR,
+ CreateFile = IN_CREATE_FILE,
+ DeleteSelf = IN_DELETE_SELF,
+ Unmount = IN_UNMOUNT,
+ _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */
+ _Ignored = IN_IGNORED, /* Internal, don't use this in client code */
+};
/*======================================================================================
* OFileNotification
*======================================================================================*/
/**
* @brief Represents a file notification
*
* This class allows to watch for events happening to files.
- * It uses the dnotify kernel interface which is a very efficient signalling interface.
+ * It uses the inotify kernel interface
*
- * @see <file:///usr/src/linux/Documentation/dnotify.txt>
+ * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/
*
* @author Michael 'Mickey' Lauer <mickey@vanille.de>
*
**/
class OFileNotification : public QObject
{
Q_OBJECT
public:
OFileNotification( QObject* parent = 0, const char* name = 0 );
~OFileNotification();
/**
* This static function calls a slot when an event with @a type happens to file @a path.
*
* It is very convenient to use this function because you do not need to
* bother with a timerEvent or to create a local QTimer object.
*
* Example:
* <pre>
*
* #include <opie2/oapplication.h>
- * #include <opie2/onitify.h>
+ * #include <opie2/ofilenotify.h>
* using namespace Opie::Core;
*
* int main( int argc, char **argv )
* {
* OApplication a( argc, argv, "File Notification Example" );
* OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Create );
* ... // create and show your widgets
* return a.exec();
* }
* </pre>
*
- * This sample program automatically terminates when the file "/tmp/quite" has been created.
+ * This sample program automatically terminates when the file "/tmp/quit" has been created.
*
*
* The @a receiver is the receiving object and the @a member is the slot.
**/
static void singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify );
/**
* Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once.
* Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then.
**/
- int start( const QString& path, bool sshot = false, OFileNotificationType type = Modify );
+ int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify );
/**
* Stop watching for file events.
**/
void stop();
/**
* @returns the notification type as set by @ref start().
**/
OFileNotificationType type() const;
/**
* @returns the path to the file being watched by this instance.
**/
QString path() const;
/**
- * @returns the UNIX file descriptor for the file being watched.
- **/
- int fileno() const;
- /**
* @returns if a file is currently being watched.
**/
bool isActive() const;
signals:
/**
* This signal is emitted if an event happens of the specified type happens to the file being watched.
**/
void triggered();
protected:
bool activate();
- virtual bool hasChanged();
- static bool registerSignalHandler();
- static void unregisterSignalHandler();
- static void __signalHandler( int sig, siginfo_t *si, void *data );
+
+ private slots:
+ void inotifyEventHandler();
private:
+ bool registerEventHandler();
+ void unregisterEventHandler();
+
QString _path;
OFileNotificationType _type;
QSignal _signal;
- int _fd;
bool _active;
- struct stat _stat;
-};
-
-#if 0
-
-class ODirectoryNotification : public OFileNotification
-{
-
- public:
- virtual bool hasChanged() { return true; };
+ bool _multi;
+ static QSocketNotifier* _sn;
+ int _wd; // inotify watch descriptor
+ static int _fd; // inotify device descriptor
};
-#endif
-
}
}
#endif