-rw-r--r-- | examples/opiecore/onotifydemo/onotifydemo.cpp | 14 | ||||
-rw-r--r-- | examples/opiecore/onotifydemo/onotifydemo.h | 2 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 122 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 63 |
4 files changed, 163 insertions, 38 deletions
diff --git a/examples/opiecore/onotifydemo/onotifydemo.cpp b/examples/opiecore/onotifydemo/onotifydemo.cpp index 2beda2a..e147c6a 100644 --- a/examples/opiecore/onotifydemo/onotifydemo.cpp +++ b/examples/opiecore/onotifydemo/onotifydemo.cpp | |||
@@ -1,178 +1,180 @@ | |||
1 | #include "onotifydemo.h" | 1 | #include "onotifydemo.h" |
2 | 2 | ||
3 | /* OPIE */ | 3 | /* OPIE */ |
4 | #include <opie2/odebug.h> | 4 | #include <opie2/odebug.h> |
5 | #include <opie2/oapplication.h> | 5 | #include <opie2/oapplication.h> |
6 | #include <opie2/ofiledialog.h> | 6 | #include <opie2/ofiledialog.h> |
7 | #include <opie2/olistview.h> | 7 | #include <opie2/olistview.h> |
8 | #include <opie2/ofilenotify.h> | 8 | #include <opie2/ofilenotify.h> |
9 | using namespace Opie::Core; | 9 | using namespace Opie::Core; |
10 | using namespace Opie::Ui; | 10 | using namespace Opie::Ui; |
11 | 11 | ||
12 | /* QT */ | 12 | /* QT */ |
13 | #include <qcheckbox.h> | 13 | #include <qcheckbox.h> |
14 | #include <qfileinfo.h> | 14 | #include <qfileinfo.h> |
15 | #include <qvbox.h> | 15 | #include <qvbox.h> |
16 | #include <qhbox.h> | 16 | #include <qhbox.h> |
17 | #include <qhbuttongroup.h> | 17 | #include <qhbuttongroup.h> |
18 | #include <qvbuttongroup.h> | 18 | #include <qvbuttongroup.h> |
19 | #include <qmessagebox.h> | 19 | #include <qmessagebox.h> |
20 | #include <qpushbutton.h> | 20 | #include <qpushbutton.h> |
21 | 21 | ||
22 | DemoApp::DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" ) | 22 | DemoApp::DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" ) |
23 | { | 23 | { |
24 | 24 | ||
25 | QVBox* vbox = new QVBox(); | 25 | QVBox* vbox = new QVBox(); |
26 | setMainWidget( vbox ); | 26 | setMainWidget( vbox ); |
27 | 27 | ||
28 | l = new OListView( vbox ); | 28 | l = new OListView( vbox ); |
29 | l->addColumn( "Notification Path" ); | 29 | l->addColumn( "Notification Path" ); |
30 | l->addColumn( "Trigger Type" ); | 30 | l->addColumn( "Trigger Type" ); |
31 | l->addColumn( "Trigger Mask" ); | 31 | l->addColumn( "Trigger Mask" ); |
32 | l->setColumnAlignment( 1, AlignCenter ); | 32 | l->setColumnAlignment( 1, AlignCenter ); |
33 | l->setColumnAlignment( 2, AlignCenter ); | 33 | l->setColumnAlignment( 2, AlignCenter ); |
34 | 34 | ||
35 | QHBox* hbox = new QHBox( vbox ); | 35 | QHBox* hbox = new QHBox( vbox ); |
36 | g2 = new QVButtonGroup( "Specify Trigger Type", hbox ); | 36 | g2 = new QVButtonGroup( "Specify Trigger Type", hbox ); |
37 | QCheckBox* c1 = new QCheckBox( "Access", g2 ); | 37 | QCheckBox* c1 = new QCheckBox( "Access", g2 ); |
38 | QCheckBox* c2 = new QCheckBox( "Modify", g2 ); | 38 | QCheckBox* c2 = new QCheckBox( "Modify", g2 ); |
39 | QCheckBox* c3 = new QCheckBox( "Attrib", g2 ); | 39 | QCheckBox* c3 = new QCheckBox( "Attrib", g2 ); |
40 | QCheckBox* c4 = new QCheckBox( "CloseWrite", g2 ); | 40 | QCheckBox* c4 = new QCheckBox( "CloseWrite", g2 ); |
41 | QCheckBox* c5 = new QCheckBox( "CloseNoWrite", g2 ); | 41 | QCheckBox* c5 = new QCheckBox( "CloseNoWrite", g2 ); |
42 | QCheckBox* c6 = new QCheckBox( "MovedFrom", g2 ); | 42 | QCheckBox* c6 = new QCheckBox( "MovedFrom", g2 ); |
43 | QCheckBox* c7 = new QCheckBox( "MovedTo", g2 ); | 43 | QCheckBox* c7 = new QCheckBox( "MovedTo", g2 ); |
44 | QCheckBox* c8 = new QCheckBox( "DeleteSubdir", g2 ); | 44 | QCheckBox* c8 = new QCheckBox( "DeleteSubdir", g2 ); |
45 | QCheckBox* c9 = new QCheckBox( "DeleteFile", g2 ); | 45 | QCheckBox* c9 = new QCheckBox( "DeleteFile", g2 ); |
46 | QCheckBox* c10 = new QCheckBox( "CreateSubdir", g2 ); | 46 | QCheckBox* c10 = new QCheckBox( "CreateSubdir", g2 ); |
47 | QCheckBox* c11 = new QCheckBox( "CreateFile", g2 ); | 47 | QCheckBox* c11 = new QCheckBox( "CreateFile", g2 ); |
48 | QCheckBox* c12 = new QCheckBox( "Unmount", g2 ); | 48 | QCheckBox* c12 = new QCheckBox( "Unmount", g2 ); |
49 | g2->insert( c1, Access ); | 49 | g2->insert( c1, Access ); |
50 | g2->insert( c2, Modify ); | 50 | g2->insert( c2, Modify ); |
51 | g2->insert( c3, Attrib ); | 51 | g2->insert( c3, Attrib ); |
52 | g2->insert( c4, CloseWrite ); | 52 | g2->insert( c4, CloseWrite ); |
53 | g2->insert( c5, CloseNoWrite ); | 53 | g2->insert( c5, CloseNoWrite ); |
54 | g2->insert( c6, MovedFrom ); | 54 | g2->insert( c6, MovedFrom ); |
55 | g2->insert( c7, MovedTo ); | 55 | g2->insert( c7, MovedTo ); |
56 | g2->insert( c8, DeleteSubdir ); | 56 | g2->insert( c8, DeleteSubdir ); |
57 | g2->insert( c9, DeleteFile ); | 57 | g2->insert( c9, DeleteFile ); |
58 | g2->insert( c10, CreateSubdir ); | 58 | g2->insert( c10, CreateSubdir ); |
59 | g2->insert( c11, CreateFile ); | 59 | g2->insert( c11, CreateFile ); |
60 | g2->insert( c12, Unmount ); | 60 | g2->insert( c12, Unmount ); |
61 | connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); | 61 | connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); |
62 | 62 | ||
63 | g1 = new QVButtonGroup( "Add/Remove", hbox ); | 63 | g1 = new QVButtonGroup( "Add/Remove", hbox ); |
64 | QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); | 64 | QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); |
65 | QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 ); | 65 | QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 ); |
66 | QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 ); | 66 | QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 ); |
67 | g1->insert( plus1, 0 ); | 67 | g1->insert( plus1, 0 ); |
68 | g1->insert( plus2, 1 ); | 68 | g1->insert( plus2, 1 ); |
69 | g1->insert( minus, 2 ); | 69 | g1->insert( minus, 2 ); |
70 | connect( plus1, SIGNAL( clicked() ), this, SLOT( addSingle() ) ); | 70 | connect( plus1, SIGNAL( clicked() ), this, SLOT( addSingle() ) ); |
71 | connect( plus2, SIGNAL( clicked() ), this, SLOT( addMulti() ) ); | 71 | connect( plus2, SIGNAL( clicked() ), this, SLOT( addMulti() ) ); |
72 | connect( minus, SIGNAL( clicked() ), this, SLOT( delTrigger() ) ); | 72 | connect( minus, SIGNAL( clicked() ), this, SLOT( delTrigger() ) ); |
73 | 73 | ||
74 | g1->show(); | 74 | g1->show(); |
75 | g2->show(); | 75 | g2->show(); |
76 | l->show(); | 76 | l->show(); |
77 | hbox->show(); | 77 | hbox->show(); |
78 | vbox->show(); | 78 | vbox->show(); |
79 | showMainWidget( vbox ); | 79 | showMainWidget( vbox ); |
80 | } | 80 | } |
81 | 81 | ||
82 | void DemoApp::addTrigger( bool multi ) | 82 | void DemoApp::addTrigger( bool multi ) |
83 | { | 83 | { |
84 | if ( !m ) | 84 | if ( !m ) |
85 | { | 85 | { |
86 | QMessageBox::warning( 0, "Add Trigger", "<p>Can't add trigger without at least one selected trigger type</p>", "&Sorry", 0 ); | 86 | QMessageBox::warning( 0, "Add Trigger", "<p>Can't add trigger without at least one selected trigger type</p>", "&Sorry", 0 ); |
87 | return; | 87 | return; |
88 | } | 88 | } |
89 | 89 | ||
90 | QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); | 90 | QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); |
91 | if ( !filename.isEmpty() ) | 91 | if ( !filename.isEmpty() ) |
92 | { | 92 | { |
93 | bool success = true; | 93 | bool success = true; |
94 | odebug << "Filename = " << filename << oendl; | 94 | odebug << "Filename = " << filename << oendl; |
95 | 95 | ||
96 | int fntype = m; | 96 | int fntype = m; |
97 | QString modifier = QString().sprintf( " = 0x%08x", fntype ); | 97 | QString modifier = QString().sprintf( " = 0x%08x", fntype ); |
98 | 98 | ||
99 | if ( QFileInfo( filename ).isFile() ) | 99 | if ( QFileInfo( filename ).isFile() ) |
100 | { | 100 | { |
101 | if ( !multi ) | 101 | if ( !multi ) |
102 | { | 102 | { |
103 | success = OFileNotification::singleShot( filename, this, SLOT( unnamedTrigger() ), (OFileNotificationType) fntype ); | 103 | success = OFileNotification::singleShot( filename, this, SLOT(unnamedTrigger()), (OFileNotificationType) fntype ); |
104 | } | 104 | } |
105 | else | 105 | else |
106 | { | 106 | { |
107 | OFileNotification* fn = new OFileNotification(); | 107 | OFileNotification* fn = new OFileNotification(); |
108 | success = fn->watch( filename, false, (OFileNotificationType) fntype ); | 108 | success = fn->watch( filename, false, (OFileNotificationType) fntype ); |
109 | connect( fn, SIGNAL( triggered( const QString& ) ), this, SLOT( namedTrigger( const QString& ) ) ); | 109 | connect( fn, SIGNAL(triggered(const QString&,unsigned int,const QString&)), |
110 | } | 110 | this, SLOT(namedTrigger(const QString&,unsigned int,const QString&)) ); |
111 | } | ||
111 | } | 112 | } |
112 | else if ( QFileInfo( filename ).isDir() ) | 113 | else if ( QFileInfo( filename ).isDir() ) |
113 | { | 114 | { |
114 | ODirNotification* dn = new ODirNotification(); | 115 | ODirNotification* dn = new ODirNotification(); |
115 | success = dn->watch( filename, !multi, (OFileNotificationType) fntype ); | 116 | success = dn->watch( filename, !multi, (OFileNotificationType) fntype ); |
116 | connect( dn, SIGNAL( triggered( const QString& ) ), this, SLOT( namedTrigger( const QString& ) ) ); | 117 | connect( dn, SIGNAL(triggered(const QString&,unsigned int,const QString&)), |
118 | this, SLOT(namedTrigger(const QString&,unsigned int,const QString&)) ); | ||
117 | } | 119 | } |
118 | else | 120 | else |
119 | { | 121 | { |
120 | odebug << "Huh!? Neither file nor directory..." << oendl; | 122 | odebug << "Huh!? Neither file nor directory..." << oendl; |
121 | return; | 123 | return; |
122 | } | 124 | } |
123 | 125 | ||
124 | /* if ( !success ) | 126 | /* if ( !success ) |
125 | { | 127 | { |
126 | QMessageBox::warning( 0, "Add Trigger", "<p>Couldn't add trigger :(</p>", "&Sorry", 0 ); | 128 | QMessageBox::warning( 0, "Add Trigger", "<p>Couldn't add trigger :(</p>", "&Sorry", 0 ); |
127 | return; | 129 | return; |
128 | } | 130 | } |
129 | else | 131 | else |
130 | */ { | 132 | */ { |
131 | new OListViewItem( l, filename, multi ? "MULTI" : "SINGLE", modifier ); | 133 | new OListViewItem( l, filename, multi ? "MULTI" : "SINGLE", modifier ); |
132 | } | 134 | } |
133 | return; | 135 | return; |
134 | } | 136 | } |
135 | else | 137 | else |
136 | { | 138 | { |
137 | odebug << "cancelled." << oendl; | 139 | odebug << "cancelled." << oendl; |
138 | } | 140 | } |
139 | } | 141 | } |
140 | 142 | ||
141 | void DemoApp::modifierClicked( int modifier ) { m = static_cast<OFileNotificationType>( (int)m ^ int(modifier) ); }; | 143 | void DemoApp::modifierClicked( int modifier ) { m = static_cast<OFileNotificationType>( (int)m ^ int(modifier) ); }; |
142 | void DemoApp::addSingle() { addTrigger(); }; | 144 | void DemoApp::addSingle() { addTrigger(); }; |
143 | void DemoApp::addMulti() { addTrigger( true ); }; | 145 | void DemoApp::addMulti() { addTrigger( true ); }; |
144 | 146 | ||
145 | void DemoApp::delTrigger() | 147 | void DemoApp::delTrigger() |
146 | { | 148 | { |
147 | QListViewItem* item = l->selectedItem(); | 149 | QListViewItem* item = l->selectedItem(); |
148 | if ( !item ) | 150 | if ( !item ) |
149 | { | 151 | { |
150 | QMessageBox::warning( 0, "Del Trigger", "<p>No trigger selected!</p>", "&Sorry", 0 ); | 152 | QMessageBox::warning( 0, "Del Trigger", "<p>No trigger selected!</p>", "&Sorry", 0 ); |
151 | return; | 153 | return; |
152 | } | 154 | } |
153 | else | 155 | else |
154 | { | 156 | { |
155 | QString filename( item->text( 0 ) ); | 157 | QString filename( item->text( 0 ) ); |
156 | odebug << "Filename = " << filename << oendl; | 158 | odebug << "Filename = " << filename << oendl; |
157 | } | 159 | } |
158 | } | 160 | } |
159 | 161 | ||
160 | void DemoApp::unnamedTrigger() | 162 | void DemoApp::unnamedTrigger() |
161 | { | 163 | { |
162 | owarn << "DemoApp::singleShotStrigger() : F I R E !!!!!" << oendl; | 164 | owarn << "DemoApp::singleShotStrigger() : F I R E !!!!!" << oendl; |
163 | } | 165 | } |
164 | 166 | ||
165 | void DemoApp::namedTrigger( const QString& path ) | 167 | void DemoApp::namedTrigger( const QString& path, unsigned int type, const QString& name ) |
166 | { | 168 | { |
167 | owarn << "DemoApp::named trigger = " << path << " : F I R E !!!!!" << oendl; | 169 | owarn << "DemoApp::named trigger = ( " << path << ", " << type << ", " << name << " ) : F I R E !!!!!" << oendl; |
168 | } | 170 | } |
169 | 171 | ||
170 | int main( int argc, char** argv ) | 172 | int main( int argc, char** argv ) |
171 | { | 173 | { |
172 | DemoApp* app = new DemoApp( argc, argv ); | 174 | DemoApp* app = new DemoApp( argc, argv ); |
173 | app->exec(); | 175 | app->exec(); |
174 | 176 | ||
175 | return 0; | 177 | return 0; |
176 | 178 | ||
177 | } | 179 | } |
178 | 180 | ||
diff --git a/examples/opiecore/onotifydemo/onotifydemo.h b/examples/opiecore/onotifydemo/onotifydemo.h index f6ac5ea..20019e4 100644 --- a/examples/opiecore/onotifydemo/onotifydemo.h +++ b/examples/opiecore/onotifydemo/onotifydemo.h | |||
@@ -1,30 +1,30 @@ | |||
1 | /* OPIE */ | 1 | /* OPIE */ |
2 | #include <opie2/olistview.h> | 2 | #include <opie2/olistview.h> |
3 | #include <opie2/odebug.h> | 3 | #include <opie2/odebug.h> |
4 | #include <opie2/oapplication.h> | 4 | #include <opie2/oapplication.h> |
5 | #include <opie2/ofilenotify.h> | 5 | #include <opie2/ofilenotify.h> |
6 | 6 | ||
7 | class QButtonGroup; | 7 | class QButtonGroup; |
8 | 8 | ||
9 | class DemoApp : public Opie::Core::OApplication | 9 | class DemoApp : public Opie::Core::OApplication |
10 | { | 10 | { |
11 | Q_OBJECT | 11 | Q_OBJECT |
12 | public: | 12 | public: |
13 | DemoApp( int argc, char** argv ); | 13 | DemoApp( int argc, char** argv ); |
14 | 14 | ||
15 | public: | 15 | public: |
16 | void addTrigger( bool multi = false ); | 16 | void addTrigger( bool multi = false ); |
17 | public slots: | 17 | public slots: |
18 | void modifierClicked( int modifier ); | 18 | void modifierClicked( int modifier ); |
19 | void addSingle(); | 19 | void addSingle(); |
20 | void addMulti(); | 20 | void addMulti(); |
21 | void delTrigger(); | 21 | void delTrigger(); |
22 | void unnamedTrigger(); | 22 | void unnamedTrigger(); |
23 | void namedTrigger( const QString& name ); | 23 | void namedTrigger( const QString&, unsigned int, const QString& ); |
24 | 24 | ||
25 | private: | 25 | private: |
26 | Opie::Ui::OListView* l; | 26 | Opie::Ui::OListView* l; |
27 | QButtonGroup* g1; | 27 | QButtonGroup* g1; |
28 | QButtonGroup* g2; | 28 | QButtonGroup* g2; |
29 | Opie::Core::OFileNotificationType m; | 29 | Opie::Core::OFileNotificationType m; |
30 | }; | 30 | }; |
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 11d4f87..4264327 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp | |||
@@ -1,278 +1,350 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of the Opie Project | 2 | This file is part of the Opie Project |
3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> | 3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> |
4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> | 4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> |
5 | .>+-= | 5 | .>+-= |
6 | _;:, .> :=|. This program is free software; you can | 6 | _;:, .> :=|. This program is free software; you can |
7 | .> <`_, > . <= redistribute it and/or modify it under | 7 | .> <`_, > . <= redistribute it and/or modify it under |
8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | 8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public |
9 | .="- .-=="i, .._ License as published by the Free Software | 9 | .="- .-=="i, .._ License as published by the Free Software |
10 | - . .-<_> .<> Foundation; version 2 of the License. | 10 | - . .-<_> .<> Foundation; version 2 of the License. |
11 | ._= =} : | 11 | ._= =} : |
12 | .%`+i> _;_. | 12 | .%`+i> _;_. |
13 | .i_,=:_. -<s. This program is distributed in the hope that | 13 | .i_,=:_. -<s. This program is distributed in the hope that |
14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | 14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; |
15 | : .. .:, . . . without even the implied warranty of | 15 | : .. .:, . . . without even the implied warranty of |
16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | 16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A |
17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | 17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU |
18 | ..}^=.= = ; Library General Public License for more | 18 | ..}^=.= = ; Library General Public License for more |
19 | ++= -. .` .: details. | 19 | ++= -. .` .: details. |
20 | : = ...= . :.=- | 20 | : = ...= . :.=- |
21 | -. .:....=;==+<; You should have received a copy of the GNU | 21 | -. .:....=;==+<; You should have received a copy of the GNU |
22 | -_. . . )=. = Library General Public License along with | 22 | -_. . . )=. = Library General Public License along with |
23 | -- :-=` this library; see the file COPYING.LIB. | 23 | -- :-=` this library; see the file COPYING.LIB. |
24 | If not, write to the Free Software Foundation, | 24 | If not, write to the Free Software Foundation, |
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 | #include "ofilenotify.h" | 29 | #include "ofilenotify.h" |
30 | using namespace Opie::Core; | 30 | using namespace Opie::Core; |
31 | 31 | ||
32 | /* OPIE */ | 32 | /* OPIE */ |
33 | 33 | ||
34 | /* QT */ | 34 | /* QT */ |
35 | #include <qobject.h> | 35 | #include <qobject.h> |
36 | #include <qsocketnotifier.h> | 36 | #include <qsocketnotifier.h> |
37 | #include <qsignal.h> | 37 | #include <qsignal.h> |
38 | #include <qintdict.h> | 38 | #include <qintdict.h> |
39 | #include <qdir.h> | 39 | #include <qdir.h> |
40 | 40 | ||
41 | /* STD */ | 41 | /* STD */ |
42 | #include <sys/types.h> | 42 | #include <sys/types.h> |
43 | #include <sys/stat.h> | 43 | #include <sys/stat.h> |
44 | #include <sys/ioctl.h> | 44 | #include <sys/ioctl.h> |
45 | #include <fcntl.h> | 45 | #include <fcntl.h> |
46 | #include <assert.h> | 46 | #include <assert.h> |
47 | #include <string.h> | 47 | #include <string.h> |
48 | #include <errno.h> | 48 | #include <errno.h> |
49 | #include <unistd.h> | 49 | #include <unistd.h> |
50 | 50 | ||
51 | static QIntDict<OFileNotification> notification_list; | 51 | static QIntDict<OFileNotification> notification_list; |
52 | 52 | ||
53 | QSocketNotifier* OFileNotification::_sn; | 53 | QSocketNotifier* OFileNotification::_sn; |
54 | int OFileNotification::_fd = -1; | 54 | int OFileNotification::_fd = -1; |
55 | 55 | ||
56 | #define INOTIFY_DEVICE "/dev/inotify" | 56 | #define INOTIFY_DEVICE "/dev/inotify" |
57 | 57 | ||
58 | namespace Opie { | 58 | namespace Opie { |
59 | namespace Core { | 59 | namespace Core { |
60 | 60 | ||
61 | //================================================================================================= | ||
62 | // OFileNotificationEvent | ||
63 | //================================================================================================= | ||
64 | OFileNotificationEvent::OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ) | ||
65 | :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name ) | ||
66 | { | ||
67 | qDebug( "OFileNotificationEvent()" ); | ||
68 | } | ||
69 | |||
70 | |||
71 | OFileNotificationEvent::~OFileNotificationEvent() | ||
72 | { | ||
73 | qDebug( "~OFileNotificationEvent()" ); | ||
74 | } | ||
75 | |||
76 | //================================================================================================= | ||
77 | // OFileNotification | ||
78 | //================================================================================================= | ||
61 | OFileNotification::OFileNotification( QObject* parent, const char* name ) | 79 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
62 | :QObject( parent, name ), _active( false ), _multi( true ) | 80 | :QObject( parent, name ), _active( false ), _multi( true ) |
63 | { | 81 | { |
64 | qDebug( "OFileNotification::OFileNotification()" ); | 82 | qDebug( "OFileNotification::OFileNotification()" ); |
65 | } | 83 | } |
66 | 84 | ||
67 | 85 | ||
68 | OFileNotification::~OFileNotification() | 86 | OFileNotification::~OFileNotification() |
69 | { | 87 | { |
70 | stop(); | 88 | stop(); |
71 | qDebug( "OFileNotification::~OFileNotification()" ); | 89 | qDebug( "OFileNotification::~OFileNotification()" ); |
72 | } | 90 | } |
73 | 91 | ||
74 | 92 | ||
75 | bool OFileNotification::isActive() const | 93 | bool OFileNotification::isActive() const |
76 | { | 94 | { |
77 | return _active; | 95 | return _active; |
78 | } | 96 | } |
79 | 97 | ||
80 | 98 | ||
81 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) | 99 | int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) |
82 | { | 100 | { |
83 | // check if path exists and is a regular file | 101 | // check if path exists and is a regular file |
84 | struct stat s; | 102 | struct stat s; |
85 | if ( ::stat( (const char*) path, &s ) == -1 ) | 103 | if ( ::stat( (const char*) path, &s ) == -1 ) |
86 | { | 104 | { |
87 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) ); | 105 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) ); |
88 | return -1; | 106 | return -1; |
89 | } | 107 | } |
90 | if ( !S_ISREG( s.st_mode ) ) | 108 | if ( !S_ISREG( s.st_mode ) ) |
91 | { | 109 | { |
92 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, "not a regular file" ); | 110 | qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, "not a regular file" ); |
93 | return -1; | 111 | return -1; |
94 | } | 112 | } |
95 | 113 | ||
96 | return startWatching( path, sshot, type ); | 114 | return startWatching( path, sshot, type ); |
97 | } | 115 | } |
98 | 116 | ||
99 | 117 | ||
100 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) | 118 | int OFileNotification::startWatching( const QString& path, bool sshot, OFileNotificationType type ) |
101 | { | 119 | { |
102 | if ( notification_list.isEmpty() ) | 120 | if ( notification_list.isEmpty() ) |
103 | { | 121 | { |
104 | OFileNotification::registerEventHandler(); | 122 | OFileNotification::registerEventHandler(); |
105 | } | 123 | } |
106 | 124 | ||
107 | struct inotify_watch_request iwr; | 125 | struct inotify_watch_request iwr; |
108 | ::memset( &iwr, 0, sizeof iwr ); | 126 | ::memset( &iwr, 0, sizeof iwr ); |
109 | iwr.name = const_cast<char*>( (const char*) path ); | 127 | iwr.name = const_cast<char*>( (const char*) path ); |
110 | iwr.mask = type; | 128 | iwr.mask = type; |
111 | 129 | ||
112 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); | 130 | _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); |
113 | 131 | ||
114 | if ( _wd < 0 ) | 132 | if ( _wd < 0 ) |
115 | { | 133 | { |
116 | qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) ); | 134 | qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) ); |
117 | return -1; | 135 | return -1; |
118 | } | 136 | } |
119 | 137 | ||
120 | notification_list.insert( _wd, this ); | 138 | notification_list.insert( _wd, this ); |
121 | _path = path; | 139 | _path = path; |
122 | _multi = !sshot; | 140 | _multi = !sshot; |
123 | _type = type; | 141 | _type = type; |
124 | _active = true; | 142 | _active = true; |
125 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); | 143 | qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); |
126 | return _wd; | 144 | return _wd; |
127 | } | 145 | } |
128 | 146 | ||
129 | 147 | ||
130 | void OFileNotification::stop() | 148 | void OFileNotification::stop() |
131 | { | 149 | { |
132 | notification_list.remove( _wd ); | 150 | notification_list.remove( _wd ); |
133 | _path = QString::null; | 151 | _path = QString::null; |
134 | _wd = 0; | 152 | _wd = 0; |
135 | _active = false; | 153 | _active = false; |
136 | if ( notification_list.isEmpty() ) | 154 | if ( notification_list.isEmpty() ) |
137 | { | 155 | { |
138 | OFileNotification::unregisterEventHandler(); | 156 | OFileNotification::unregisterEventHandler(); |
139 | } | 157 | } |
140 | } | 158 | } |
141 | 159 | ||
142 | 160 | ||
143 | OFileNotificationType OFileNotification::type() const | 161 | OFileNotificationType OFileNotification::type() const |
144 | { | 162 | { |
145 | return _type; | 163 | return _type; |
146 | } | 164 | } |
147 | 165 | ||
148 | 166 | ||
149 | QString OFileNotification::path() const | 167 | QString OFileNotification::path() const |
150 | { | 168 | { |
151 | return _path; | 169 | return _path; |
152 | } | 170 | } |
153 | 171 | ||
154 | 172 | ||
155 | bool OFileNotification::activate() | 173 | bool OFileNotification::activate( const OFileNotificationEvent* e ) |
156 | { | 174 | { |
157 | emit triggered( _path ); | 175 | qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); |
176 | |||
177 | // dumb signal | ||
158 | _signal.activate(); | 178 | _signal.activate(); |
179 | |||
180 | // generic signal | ||
181 | emit triggered( _path, e->mask(), e->name() ); | ||
182 | |||
183 | // specialized signals | ||
184 | switch ( e->mask() ) | ||
185 | { | ||
186 | case Access: emit accessed( _path ); break; | ||
187 | case Modify: emit modified( _path ); break; | ||
188 | case Attrib: emit attributed( _path); break; | ||
189 | case CloseWrite: emit closed( _path, true ); break; | ||
190 | case CloseNoWrite: emit closed( _path, false ); break; | ||
191 | case Open: emit opened( _path ); break; | ||
192 | case MovedFrom: emit movedFrom( _path, e->name() ); break; | ||
193 | case MovedTo: emit movedTo( _path, e->name() ); break; | ||
194 | case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; | ||
195 | case DeleteFile: emit deletedFile( _path, e->name() ); break; | ||
196 | case CreateSubdir: emit createdSubdir( _path, e->name() ); break; | ||
197 | case CreateFile: emit createdFile( _path, e->name() ); break; | ||
198 | case DeleteSelf: emit deleted( _path ); break; | ||
199 | case Unmount: emit unmounted( _path ); break; | ||
200 | default: assert( 0 ); | ||
201 | } | ||
202 | |||
159 | if ( !_multi ) stop(); | 203 | if ( !_multi ) stop(); |
204 | |||
160 | return true; | 205 | return true; |
161 | } | 206 | } |
162 | 207 | ||
163 | 208 | ||
164 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 209 | bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) |
165 | { | 210 | { |
166 | OFileNotification* ofn = new OFileNotification(); | 211 | OFileNotification* ofn = new OFileNotification(); |
167 | ofn->_signal.connect( receiver, member ); | 212 | ofn->_signal.connect( receiver, member ); |
168 | return ofn->watch( path, true, type ) != -1; | 213 | return ofn->watch( path, true, type ) != -1; |
169 | } | 214 | } |
170 | 215 | ||
171 | 216 | ||
172 | void OFileNotification::inotifyEventHandler() | 217 | void OFileNotification::inotifyEventHandler() |
173 | { | 218 | { |
174 | qWarning( "OFileNotification::__eventHandler(): reached." ); | 219 | qDebug( "OFileNotification::inotifyEventHandler(): reached." ); |
175 | 220 | ||
176 | char buffer[16384]; | 221 | char buffer[16384]; |
177 | size_t buffer_i; | 222 | size_t buffer_i; |
178 | struct inotify_event *pevent, *event; | 223 | struct inotify_event *pevent, *event; |
179 | ssize_t r; | 224 | ssize_t r; |
180 | size_t event_size; | 225 | size_t event_size; |
181 | int count = 0; | 226 | int count = 0; |
182 | 227 | ||
183 | r = ::read(_fd, buffer, 16384); | 228 | r = ::read(_fd, buffer, 16384); |
184 | 229 | ||
185 | if ( r <= 0 ) | 230 | if ( r <= 0 ) |
186 | return; | 231 | return; |
187 | 232 | ||
188 | buffer_i = 0; | 233 | buffer_i = 0; |
189 | while ( buffer_i < r ) | 234 | while ( buffer_i < r ) |
190 | { | 235 | { |
191 | /* Parse events and queue them ! */ | 236 | pevent = (struct inotify_event *)&buffer[buffer_i]; |
192 | pevent = (struct inotify_event *)&buffer[buffer_i]; | 237 | event_size = sizeof(struct inotify_event) + pevent->len; |
193 | event_size = sizeof(struct inotify_event) + pevent->len; | 238 | OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, |
194 | qDebug( "pevent->len = %d\n", pevent->len); | 239 | pevent->cookie, pevent->len ? pevent->name : 0 ); |
195 | 240 | e->activate(); | |
196 | OFileNotification* fn = notification_list[ pevent->wd ]; | 241 | buffer_i += event_size; |
197 | if ( fn ) | 242 | count++; |
198 | fn->activate(); | ||
199 | else | ||
200 | assert( false ); | ||
201 | |||
202 | //event = malloc(event_size); | ||
203 | //memmove(event, pevent, event_size); | ||
204 | //queue_enqueue(event, q); | ||
205 | buffer_i += event_size; | ||
206 | count++; | ||
207 | } | 243 | } |
208 | 244 | ||
209 | qDebug( "received %d events...", count ); | 245 | qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); |
210 | return; | ||
211 | } | 246 | } |
212 | 247 | ||
213 | 248 | ||
214 | bool OFileNotification::registerEventHandler() | 249 | bool OFileNotification::registerEventHandler() |
215 | { | 250 | { |
216 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); | 251 | OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); |
217 | if ( OFileNotification::_fd < 0 ) | 252 | if ( OFileNotification::_fd < 0 ) |
218 | { | 253 | { |
219 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); | 254 | qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); |
220 | return false; | 255 | return false; |
221 | } | 256 | } |
222 | 257 | ||
223 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); | 258 | OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); |
224 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); | 259 | connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); |
225 | 260 | ||
226 | qDebug( "OFileNotification::registerEventHandler(): done" ); | 261 | qDebug( "OFileNotification::registerEventHandler(): done" ); |
227 | return true; | 262 | return true; |
228 | } | 263 | } |
229 | 264 | ||
230 | 265 | ||
231 | void OFileNotification::unregisterEventHandler() | 266 | void OFileNotification::unregisterEventHandler() |
232 | { | 267 | { |
233 | if ( _sn ) delete _sn; | 268 | if ( _sn ) delete _sn; |
234 | if ( OFileNotification::_fd ) | 269 | if ( OFileNotification::_fd ) |
235 | ::close( OFileNotification::_fd ); | 270 | ::close( OFileNotification::_fd ); |
236 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); | 271 | qDebug( "OFileNotification::unregisterEventHandler(): done" ); |
237 | } | 272 | } |
238 | 273 | ||
239 | //================================================================================================= | 274 | //================================================================================================= |
240 | // ODirNotification | 275 | // ODirNotification |
241 | //================================================================================================= | 276 | //================================================================================================= |
242 | ODirNotification::ODirNotification( QObject* parent, const char* name ) | 277 | ODirNotification::ODirNotification( QObject* parent, const char* name ) |
243 | :QObject( parent, name ) | 278 | :QObject( parent, name ) |
244 | { | 279 | { |
245 | qDebug( "ODirNotification::ODirNotification()" ); | 280 | qDebug( "ODirNotification::ODirNotification()" ); |
246 | } | 281 | } |
247 | 282 | ||
248 | 283 | ||
249 | ODirNotification::~ODirNotification() | 284 | ODirNotification::~ODirNotification() |
250 | { | 285 | { |
251 | qDebug( "ODirNotification::~ODirNotification()" ); | 286 | qDebug( "ODirNotification::~ODirNotification()" ); |
252 | } | 287 | } |
253 | 288 | ||
254 | 289 | ||
255 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) | 290 | int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) |
256 | { | 291 | { |
257 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); | 292 | qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); |
258 | 293 | ||
259 | if ( recurse == 0 ) | 294 | if ( recurse == 0 ) |
260 | { | 295 | { |
261 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); | 296 | OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); |
262 | int result = fn->startWatching( path, sshot, type ); | 297 | int result = fn->startWatching( path, sshot, type ); |
263 | if ( result != -1 ) | 298 | if ( result != -1 ) |
264 | { | 299 | { |
265 | connect( fn, SIGNAL( triggered( const QString& ) ), this, SIGNAL( triggered( const QString& ) ) ); | 300 | connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); |
266 | return result; | 301 | connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); |
302 | connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); | ||
303 | connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); | ||
304 | connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) ); | ||
305 | connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) ); | ||
306 | connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) ); | ||
307 | connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) ); | ||
308 | connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) ); | ||
309 | connect( fn, SIGNAL( deletedFile( const QString&, const QString& ) ), this, SIGNAL( deletedFile( const QString&, const QString& ) ) );; | ||
310 | connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SIGNAL( createdSubdir( const QString&, const QString& ) ) ); | ||
311 | connect( fn, SIGNAL( createdFile( const QString&, const QString& ) ), this, SIGNAL( createdFile( const QString&, const QString& ) ) ); | ||
312 | connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) ); | ||
313 | connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) ); | ||
267 | } | 314 | } |
315 | return result; | ||
268 | } | 316 | } |
269 | else | 317 | else |
270 | { | 318 | { |
271 | qDebug( "ODirNotification::watch(), recursion not yet implemented... :)" ); | 319 | |
272 | return -1; | 320 | return 1; |
273 | } | 321 | } |
274 | } | 322 | } |
275 | 323 | ||
324 | |||
325 | // void ODirNotification::subdirCreated( const QString& name ) | ||
326 | |||
327 | |||
328 | /* | ||
329 | Love-Trowbridge recursive directory scanning algorithm: | ||
330 | |||
331 | Step 1. Start at initial directory foo. Add watch. | ||
332 | |||
333 | Step 2. Setup handlers for watch created in Step 1. | ||
334 | Specifically, ensure that a directory created | ||
335 | in foo will result in a handled CREATE_SUBDIR | ||
336 | event. | ||
337 | |||
338 | Step 3. Read the contents of foo. | ||
339 | |||
340 | Step 4. For each subdirectory of foo read in step 3, repeat | ||
341 | step 1. | ||
342 | |||
343 | Step 5. For any CREATE_SUBDIR event on bar, if a watch is | ||
344 | not yet created on bar, repeat step 1 on bar. | ||
345 | */ | ||
346 | |||
347 | |||
276 | } // namespace Ui | 348 | } // namespace Ui |
277 | 349 | ||
278 | } // namespace Opie | 350 | } // namespace Opie |
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h index 3eb917e..5bbf421 100644 --- a/libopie2/opiecore/ofilenotify.h +++ b/libopie2/opiecore/ofilenotify.h | |||
@@ -1,238 +1,289 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of the Opie Project | 2 | This file is part of the Opie Project |
3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> | 3 | =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> |
4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> | 4 | .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> |
5 | .>+-= | 5 | .>+-= |
6 | _;:, .> :=|. This program is free software; you can | 6 | _;:, .> :=|. This program is free software; you can |
7 | .> <`_, > . <= redistribute it and/or modify it under | 7 | .> <`_, > . <= redistribute it and/or modify it under |
8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public | 8 | :`=1 )Y*s>-.-- : the terms of the GNU Library General Public |
9 | .="- .-=="i, .._ License as published by the Free Software | 9 | .="- .-=="i, .._ License as published by the Free Software |
10 | - . .-<_> .<> Foundation; version 2 of the License. | 10 | - . .-<_> .<> Foundation; version 2 of the License. |
11 | ._= =} : | 11 | ._= =} : |
12 | .%`+i> _;_. | 12 | .%`+i> _;_. |
13 | .i_,=:_. -<s. This program is distributed in the hope that | 13 | .i_,=:_. -<s. This program is distributed in the hope that |
14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; | 14 | + . -:. = it will be useful, but WITHOUT ANY WARRANTY; |
15 | : .. .:, . . . without even the implied warranty of | 15 | : .. .:, . . . without even the implied warranty of |
16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A | 16 | =_ + =;=|` MERCHANTABILITY or FITNESS FOR A |
17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU | 17 | _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU |
18 | ..}^=.= = ; Library General Public License for more | 18 | ..}^=.= = ; Library General Public License for more |
19 | ++= -. .` .: details. | 19 | ++= -. .` .: details. |
20 | : = ...= . :.=- | 20 | : = ...= . :.=- |
21 | -. .:....=;==+<; You should have received a copy of the GNU | 21 | -. .:....=;==+<; You should have received a copy of the GNU |
22 | -_. . . )=. = Library General Public License along with | 22 | -_. . . )=. = Library General Public License along with |
23 | -- :-=` this library; see the file COPYING.LIB. | 23 | -- :-=` this library; see the file COPYING.LIB. |
24 | If not, write to the Free Software Foundation, | 24 | If not, write to the Free Software Foundation, |
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 | #if defined (__GNUC__) && (__GNUC__ < 3) | 31 | #if defined (__GNUC__) && (__GNUC__ < 3) |
32 | #define _GNU_SOURCE | 32 | #define _GNU_SOURCE |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #include "linux_inotify.h" | 35 | #include "linux_inotify.h" |
36 | 36 | ||
37 | /* QT */ | 37 | /* QT */ |
38 | #include <qsocketnotifier.h> | 38 | #include <qsocketnotifier.h> |
39 | #include <qsignal.h> | 39 | #include <qsignal.h> |
40 | #include <qstring.h> | 40 | #include <qstring.h> |
41 | 41 | ||
42 | namespace Opie { | 42 | namespace Opie { |
43 | namespace Core { | 43 | namespace Core { |
44 | 44 | ||
45 | class OFileNotificationEvent; | ||
46 | |||
45 | /*====================================================================================== | 47 | /*====================================================================================== |
46 | * OFileNotificationType | 48 | * OFileNotificationType |
47 | *======================================================================================*/ | 49 | *======================================================================================*/ |
48 | 50 | ||
49 | /** | 51 | /** |
50 | * @brief An enumerate for the different types of file notifications | 52 | * @brief An enumerate for the different types of file notifications |
51 | * | 53 | * |
52 | * This enumerate provides a means to specify the type of events that you are interest in. | 54 | * This enumerate provides a means to specify the type of events that you are interest in. |
53 | * Valid values are: | 55 | * Valid values are: |
54 | * <ul> | 56 | * <ul> |
55 | * <li>Access: The file was accessed (read) | 57 | * <li>Access: The file was accessed (read) |
56 | * <li>Modify The file was modified (write,truncate) | 58 | * <li>Modify The file was modified (write,truncate) |
57 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) | 59 | * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) |
58 | * <li>CloseWrite = Writable file was closed | 60 | * <li>CloseWrite = Writable file was closed |
59 | * <li>CloseNoWrite = Unwritable file was closed | 61 | * <li>CloseNoWrite = Unwritable file was closed |
60 | * <li>Open = File was opened | 62 | * <li>Open = File was opened |
61 | * <li>MovedFrom = File was moved from X | 63 | * <li>MovedFrom = File was moved from X |
62 | * <li>MovedTo = File was moved to Y | 64 | * <li>MovedTo = File was moved to Y |
63 | * <li>DeleteSubdir = Subdir was deleted | 65 | * <li>DeleteSubdir = Subdir was deleted |
64 | * <li>DeleteFile = Subfile was deleted | 66 | * <li>DeleteFile = Subfile was deleted |
65 | * <li>CreateSubdir = Subdir was created | 67 | * <li>CreateSubdir = Subdir was created |
66 | * <li>CreateFile = Subfile was created | 68 | * <li>CreateFile = Subfile was created |
67 | * <li>DeleteSelf = Self was deleted | 69 | * <li>DeleteSelf = Self was deleted |
68 | * <li>Unmount = The backing filesystem was unmounted | 70 | * <li>Unmount = The backing filesystem was unmounted |
69 | * </ul> | 71 | * </ul> |
70 | * | 72 | * |
71 | **/ | 73 | **/ |
72 | 74 | ||
73 | enum OFileNotificationType | 75 | enum OFileNotificationType |
74 | { | 76 | { |
75 | Access = IN_ACCESS, | 77 | Access = IN_ACCESS, |
76 | Modify = IN_MODIFY, | 78 | Modify = IN_MODIFY, |
77 | Attrib = IN_ATTRIB, | 79 | Attrib = IN_ATTRIB, |
78 | CloseWrite = IN_CLOSE_WRITE, | 80 | CloseWrite = IN_CLOSE_WRITE, |
79 | CloseNoWrite = IN_CLOSE_NOWRITE, | 81 | CloseNoWrite = IN_CLOSE_NOWRITE, |
80 | Open = IN_OPEN, | 82 | Open = IN_OPEN, |
81 | MovedFrom = IN_MOVED_FROM, | 83 | MovedFrom = IN_MOVED_FROM, |
82 | MovedTo = IN_MOVED_TO, | 84 | MovedTo = IN_MOVED_TO, |
83 | DeleteSubdir = IN_DELETE_SUBDIR, | 85 | DeleteSubdir = IN_DELETE_SUBDIR, |
84 | DeleteFile = IN_DELETE_FILE, | 86 | DeleteFile = IN_DELETE_FILE, |
85 | CreateSubdir = IN_CREATE_SUBDIR, | 87 | CreateSubdir = IN_CREATE_SUBDIR, |
86 | CreateFile = IN_CREATE_FILE, | 88 | CreateFile = IN_CREATE_FILE, |
87 | DeleteSelf = IN_DELETE_SELF, | 89 | DeleteSelf = IN_DELETE_SELF, |
88 | Unmount = IN_UNMOUNT, | 90 | Unmount = IN_UNMOUNT, |
89 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ | 91 | _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ |
90 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ | 92 | _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ |
91 | }; | 93 | }; |
92 | 94 | ||
93 | /*====================================================================================== | 95 | /*====================================================================================== |
94 | * OFileNotification | 96 | * OFileNotification |
95 | *======================================================================================*/ | 97 | *======================================================================================*/ |
96 | 98 | ||
97 | /** | 99 | /** |
98 | * @brief Represents a file notification | 100 | * @brief Represents a file notification |
99 | * | 101 | * |
100 | * This class allows to watch for events happening to files. | 102 | * This class allows to watch for events happening to files. |
101 | * It uses the inotify linux (2.6.x) kernel interface. | 103 | * It uses the inotify linux (2.6.x) kernel interface. |
102 | * | 104 | * |
103 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 105 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
104 | * | 106 | * |
105 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 107 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
106 | * | 108 | * |
107 | **/ | 109 | **/ |
108 | 110 | ||
109 | class OFileNotification : public QObject | 111 | class OFileNotification : public QObject |
110 | { | 112 | { |
111 | Q_OBJECT | 113 | Q_OBJECT |
112 | 114 | ||
113 | public: | 115 | public: |
114 | OFileNotification( QObject* parent = 0, const char* name = 0 ); | 116 | OFileNotification( QObject* parent = 0, const char* name = 0 ); |
115 | ~OFileNotification(); | 117 | ~OFileNotification(); |
116 | /** | 118 | /** |
117 | * This static function calls a slot when an event with @a type happens to file @a path. | 119 | * This static function calls a slot when an event with @a type happens to file @a path. |
118 | * | 120 | * |
119 | * It is very convenient to use this function because you do not need to | 121 | * It is very convenient to use this function because you do not need to |
120 | * bother with a timerEvent or to create a local QTimer object. | 122 | * bother with a timerEvent or to create a local QTimer object. |
121 | * | 123 | * |
122 | * Example: | 124 | * Example: |
123 | * <pre> | 125 | * <pre> |
124 | * | 126 | * |
125 | * #include <opie2/oapplication.h> | 127 | * #include <opie2/oapplication.h> |
126 | * #include <opie2/ofilenotify.h> | 128 | * #include <opie2/ofilenotify.h> |
127 | * using namespace Opie::Core; | 129 | * using namespace Opie::Core; |
128 | * | 130 | * |
129 | * int main( int argc, char **argv ) | 131 | * int main( int argc, char **argv ) |
130 | * { | 132 | * { |
131 | * OApplication a( argc, argv, "File Notification Example" ); | 133 | * OApplication a( argc, argv, "File Notification Example" ); |
132 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); | 134 | * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Access ); |
133 | * ... // create and show your widgets | 135 | * ... // create and show your widgets |
134 | * return a.exec(); | 136 | * return a.exec(); |
135 | * } | 137 | * } |
136 | * </pre> | 138 | * </pre> |
137 | * | 139 | * |
138 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. | 140 | * This sample program automatically terminates when the file "/tmp/quit" has been accessed. |
139 | * | 141 | * |
140 | * | 142 | * |
141 | * The @a receiver is the receiving object and the @a member is the slot. | 143 | * The @a receiver is the receiving object and the @a member is the slot. |
142 | **/ | 144 | **/ |
143 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); | 145 | static bool singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); |
144 | /** | 146 | /** |
145 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. | 147 | * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. |
146 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. | 148 | * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. |
147 | **/ | 149 | **/ |
148 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 150 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
149 | /** | 151 | /** |
150 | * Stop watching for file events. | 152 | * Stop watching for file events. |
151 | **/ | 153 | **/ |
152 | void stop(); | 154 | void stop(); |
153 | /** | 155 | /** |
154 | * @returns the notification type as set by @ref start(). | 156 | * @returns the notification type as set by @ref start(). |
155 | **/ | 157 | **/ |
156 | OFileNotificationType type() const; | 158 | OFileNotificationType type() const; |
157 | /** | 159 | /** |
158 | * @returns the path to the file being watched by this instance. | 160 | * @returns the path to the file being watched by this instance. |
159 | **/ | 161 | **/ |
160 | QString path() const; | 162 | QString path() const; |
161 | /** | 163 | /** |
162 | * @returns if a file is currently being watched. | 164 | * @returns if a file is currently being watched. |
163 | **/ | 165 | **/ |
164 | bool isActive() const; | 166 | bool isActive() const; |
165 | /** | 167 | /** |
166 | * @internal | 168 | * @internal |
167 | */ | 169 | */ |
168 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); | 170 | int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); |
169 | 171 | ||
170 | signals: | 172 | signals: |
171 | /** | 173 | void triggered( const QString&, unsigned int, const QString& ); |
172 | * This signal is emitted if an event happens of the specified type happens to the file being watched. | 174 | void accessed( const QString& ); |
173 | **/ | 175 | void modified( const QString& ); |
174 | void triggered( const QString& name ); | 176 | void attributed( const QString& ); |
177 | void closed( const QString&, bool ); | ||
178 | void opened( const QString& ); | ||
179 | void movedTo( const QString&, const QString& ); | ||
180 | void movedFrom( const QString&, const QString& ); | ||
181 | void deletedSubdir( const QString&, const QString& ); | ||
182 | void deletedFile( const QString&, const QString& ); | ||
183 | void createdSubdir( const QString&, const QString& ); | ||
184 | void createdFile( const QString&, const QString& ); | ||
185 | void deleted( const QString& ); | ||
186 | void unmounted( const QString& ); | ||
175 | 187 | ||
176 | protected: | 188 | protected: |
177 | bool activate(); | 189 | bool activate( const OFileNotificationEvent* e ); |
178 | 190 | ||
179 | private slots: | 191 | private slots: |
180 | void inotifyEventHandler(); | 192 | void inotifyEventHandler(); |
181 | 193 | ||
182 | private: | 194 | private: |
183 | bool registerEventHandler(); | 195 | bool registerEventHandler(); |
184 | void unregisterEventHandler(); | 196 | void unregisterEventHandler(); |
185 | 197 | ||
186 | QString _path; | 198 | QString _path; |
187 | OFileNotificationType _type; | 199 | OFileNotificationType _type; |
188 | QSignal _signal; | 200 | QSignal _signal; |
189 | bool _active; | 201 | bool _active; |
190 | bool _multi; | 202 | bool _multi; |
191 | static QSocketNotifier* _sn; | 203 | static QSocketNotifier* _sn; |
192 | int _wd; // inotify watch descriptor | 204 | int _wd; // inotify watch descriptor |
193 | static int _fd; // inotify device descriptor | 205 | static int _fd; // inotify device descriptor |
206 | |||
207 | friend class OFileNotificationEvent; | ||
194 | }; | 208 | }; |
195 | 209 | ||
196 | /*====================================================================================== | 210 | /*====================================================================================== |
197 | * ODirNotification | 211 | * ODirNotification |
198 | *======================================================================================*/ | 212 | *======================================================================================*/ |
199 | 213 | ||
200 | /** | 214 | /** |
201 | * @brief Represents a directory notification | 215 | * @brief Represents a directory notification |
202 | * | 216 | * |
203 | * This class allows to watch for events happening to directories | 217 | * This class allows to watch for events happening to directories |
204 | * It uses the OFileNotification class | 218 | * It uses the OFileNotification class |
205 | * | 219 | * |
206 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ | 220 | * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ |
207 | * | 221 | * |
208 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> | 222 | * @author Michael 'Mickey' Lauer <mickey@vanille.de> |
209 | * | 223 | * |
210 | **/ | 224 | **/ |
211 | 225 | ||
212 | class ODirNotification : public QObject | 226 | class ODirNotification : public QObject |
213 | { | 227 | { |
214 | Q_OBJECT | 228 | Q_OBJECT |
215 | 229 | ||
216 | public: | 230 | public: |
217 | ODirNotification( QObject* parent = 0, const char* name = 0 ); | 231 | ODirNotification( QObject* parent = 0, const char* name = 0 ); |
218 | ~ODirNotification(); | 232 | ~ODirNotification(); |
219 | /** | 233 | /** |
220 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, | 234 | * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, |
221 | * use 0 for no recursion and -1 for unlimited recursion. | 235 | * use 0 for no recursion and -1 for unlimited recursion. |
222 | * Set @a sshot to True if you want to be notified only once. | 236 | * Set @a sshot to True if you want to be notified only once. |
223 | **/ | 237 | **/ |
224 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); | 238 | int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); |
225 | 239 | ||
226 | signals: | 240 | signals: |
227 | /** | 241 | /** |
228 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. | 242 | * This signal is emitted if an event happens of the specified type happens to the directory being watched. |
229 | **/ | 243 | **/ |
230 | void triggered( const QString& name ); | 244 | void triggered( const QString&, unsigned int, const QString& ); |
245 | void accessed( const QString& ); | ||
246 | void modified( const QString& ); | ||
247 | void attributed( const QString& ); | ||
248 | void closed( const QString&, bool ); | ||
249 | void opened( const QString& ); | ||
250 | void movedTo( const QString&, const QString& ); | ||
251 | void movedFrom( const QString&, const QString& ); | ||
252 | void deletedSubdir( const QString&, const QString& ); | ||
253 | void deletedFile( const QString&, const QString& ); | ||
254 | void createdSubdir( const QString&, const QString& ); | ||
255 | void createdFile( const QString&, const QString& ); | ||
256 | void deleted( const QString& ); | ||
257 | void unmounted( const QString& ); | ||
258 | }; | ||
259 | |||
260 | /*====================================================================================== | ||
261 | * OFileNotificationEvent | ||
262 | *======================================================================================*/ | ||
263 | |||
264 | class OFileNotificationEvent | ||
265 | { | ||
266 | public: | ||
267 | OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name ); | ||
268 | ~OFileNotificationEvent(); | ||
269 | OFileNotification* parent() const { return _parent; }; | ||
270 | int descriptor() const { return _wd; }; | ||
271 | unsigned int mask() const { return _mask; }; | ||
272 | unsigned int cookie() const { return _cookie; }; | ||
273 | QString name() const { return _name; }; | ||
274 | void activate() { _parent->activate( this ); }; | ||
275 | |||
276 | private: | ||
277 | OFileNotification* _parent; | ||
278 | int _wd; | ||
279 | unsigned int _mask; | ||
280 | unsigned int _cookie; | ||
281 | QString _name; | ||
231 | }; | 282 | }; |
232 | 283 | ||
233 | 284 | ||
234 | } | 285 | } |
235 | } | 286 | } |
236 | 287 | ||
237 | #endif | 288 | #endif |
238 | 289 | ||