summaryrefslogtreecommitdiffabout
path: root/microkde/kio
authorMichael Krelin <hacker@klever.net>2007-07-04 11:23:42 (UTC)
committer Michael Krelin <hacker@klever.net>2007-07-04 11:23:42 (UTC)
commita08aff328d4393031d5ba7d622c2b05705a89d73 (patch) (unidiff)
tree8ee90d686081c52e7c69b5ce946e9b1a7d690001 /microkde/kio
parent11edc920afe4f274c0964436633aa632c8288a40 (diff)
downloadkdepimpi-a08aff328d4393031d5ba7d622c2b05705a89d73.zip
kdepimpi-a08aff328d4393031d5ba7d622c2b05705a89d73.tar.gz
kdepimpi-a08aff328d4393031d5ba7d622c2b05705a89d73.tar.bz2
initial public commit of qt4 portp1
Diffstat (limited to 'microkde/kio') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kio/kfile/kurlrequester.cpp10
-rw-r--r--microkde/kio/kfile/kurlrequester.h4
-rw-r--r--microkde/kio/kio/kdirwatch.cpp12
-rw-r--r--microkde/kio/kio/kdirwatch_p.h10
4 files changed, 20 insertions, 16 deletions
diff --git a/microkde/kio/kfile/kurlrequester.cpp b/microkde/kio/kfile/kurlrequester.cpp
index ca94570..ce62da7 100644
--- a/microkde/kio/kfile/kurlrequester.cpp
+++ b/microkde/kio/kfile/kurlrequester.cpp
@@ -1,409 +1,411 @@
1/* This file is part of the KDE libraries 1/* This file is part of the KDE libraries
2 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> 2 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
3 3
4 library is free software; you can redistribute it and/or 4 library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License version 2, as published by the Free Software Foundation. 6 License version 2, as published by the Free Software Foundation.
7 7
8 This library is distributed in the hope that it will be useful, 8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details. 11 Library General Public License for more details.
12 12
13 You should have received a copy of the GNU Library General Public License 13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to 14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA. 16 Boston, MA 02111-1307, USA.
17*/ 17*/
18 18
19 19
20#include <sys/stat.h> 20#include <sys/stat.h>
21#ifdef _WIN32_ 21#ifdef _WIN32_
22 22
23#else 23#else
24#include <unistd.h> 24#include <unistd.h>
25#endif 25#endif
26#include <qstring.h> 26#include <qstring.h>
27//US #include <qtooltip.h> 27//US #include <qtooltip.h>
28 28
29#include <qpushbutton.h> 29#include <qpushbutton.h>
30//Added by qt3to4:
31#include <QPixmap>
30 32
31//US #include <kaccel.h> 33//US #include <kaccel.h>
32//US #include <kcombobox.h> 34//US #include <kcombobox.h>
33#include <kdebug.h> 35#include <kdebug.h>
34#include <kdialog.h> 36#include <kdialog.h>
35#include <kfiledialog.h> 37#include <kfiledialog.h>
36#include <kglobal.h> 38#include <kglobal.h>
37#include <kiconloader.h> 39#include <kiconloader.h>
38#include <klineedit.h> 40#include <klineedit.h>
39#include <klocale.h> 41#include <klocale.h>
40//US #include <kurlcompletion.h> 42//US #include <kurlcompletion.h>
41//US #include <kurldrag.h> 43//US #include <kurldrag.h>
42//US #include <kprotocolinfo.h> 44//US #include <kprotocolinfo.h>
43 45
44 46
45#include "kurlrequester.h" 47#include "kurlrequester.h"
46 48
47 49
48class KURLDragPushButton : public QPushButton 50class KURLDragPushButton : public QPushButton
49{ 51{
50public: 52public:
51 KURLDragPushButton( QWidget *parent, const char *name=0 ) 53 KURLDragPushButton( QWidget *parent, const char *name=0 )
52 : QPushButton( parent, name ) { 54 : QPushButton( parent, name ) {
53 //US setDragEnabled( true ); 55 //US setDragEnabled( true );
54 } 56 }
55 ~KURLDragPushButton() {} 57 ~KURLDragPushButton() {}
56 58
57 void setURL( const KURL& url ) { 59 void setURL( const KURL& url ) {
58 m_urls.clear(); 60 m_urls.clear();
59 m_urls.append( url ); 61 m_urls.append( url );
60 } 62 }
61 63
62 /* not needed so far 64 /* not needed so far
63 void setURLs( const KURL::List& urls ) { 65 void setURLs( const KURL::List& urls ) {
64 m_urls = urls; 66 m_urls = urls;
65 } 67 }
66 const KURL::List& urls() const { return m_urls; } 68 const KURL::List& urls() const { return m_urls; }
67 */ 69 */
68 70
69protected: 71protected:
70/*US 72/*US
71 virtual QDragObject *dragObject() { 73 virtual QDragObject *dragObject() {
72 if ( m_urls.isEmpty() ) 74 if ( m_urls.isEmpty() )
73 return 0L; 75 return 0L;
74 76
75 QDragObject *drag = KURLDrag::newDrag( m_urls, this, "url drag" ); 77 QDragObject *drag = KURLDrag::newDrag( m_urls, this, "url drag" );
76 return drag; 78 return drag;
77 } 79 }
78*/ 80*/
79private: 81private:
80 KURL::List m_urls; 82 KURL::List m_urls;
81 83
82}; 84};
83 85
84 86
85/* 87/*
86************************************************************************* 88*************************************************************************
87*/ 89*/
88 90
89class KURLRequester::KURLRequesterPrivate 91class KURLRequester::KURLRequesterPrivate
90{ 92{
91public: 93public:
92 KURLRequesterPrivate() { 94 KURLRequesterPrivate() {
93 edit = 0L; 95 edit = 0L;
94 //UScombo = 0L; 96 //UScombo = 0L;
95//US fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly; 97//US fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly;
96 } 98 }
97 99
98 void setText( const QString& text ) { 100 void setText( const QString& text ) {
99/*US 101/*US
100 if ( combo ) 102 if ( combo )
101 { 103 {
102 if (combo->editable()) 104 if (combo->editable())
103 { 105 {
104 combo->setEditText( text ); 106 combo->setEditText( text );
105 } 107 }
106 else 108 else
107 { 109 {
108 combo->insertItem( text ); 110 combo->insertItem( text );
109 combo->setCurrentItem( combo->count()-1 ); 111 combo->setCurrentItem( combo->count()-1 );
110 } 112 }
111 } 113 }
112 else 114 else
113*/ 115*/
114 { 116 {
115 edit->setText( text ); 117 edit->setText( text );
116 } 118 }
117 } 119 }
118 120
119 void connectSignals( QObject *receiver ) { 121 void connectSignals( QObject *receiver ) {
120 QObject *sender; 122 QObject *sender;
121 /*USif ( combo ) 123 /*USif ( combo )
122 sender = combo; 124 sender = combo;
123 else 125 else
124*/ 126*/
125 sender = edit; 127 sender = edit;
126 128
127 connect( sender, SIGNAL( textChanged( const QString& )), 129 connect( sender, SIGNAL( textChanged( const QString& )),
128 receiver, SIGNAL( textChanged( const QString& ))); 130 receiver, SIGNAL( textChanged( const QString& )));
129 connect( sender, SIGNAL( returnPressed() ), 131 connect( sender, SIGNAL( returnPressed() ),
130 receiver, SIGNAL( returnPressed() )); 132 receiver, SIGNAL( returnPressed() ));
131 //USconnect( sender, SIGNAL( returnPressed( const QString& ) ), 133 //USconnect( sender, SIGNAL( returnPressed( const QString& ) ),
132 //US receiver, SIGNAL( returnPressed( const QString& ) )); 134 //US receiver, SIGNAL( returnPressed( const QString& ) ));
133 } 135 }
134/*US 136/*US
135 void setCompletionObject( KCompletion *comp ) { 137 void setCompletionObject( KCompletion *comp ) {
136 if ( combo ) 138 if ( combo )
137 combo->setCompletionObject( comp ); 139 combo->setCompletionObject( comp );
138 else 140 else
139 edit->setCompletionObject( comp ); 141 edit->setCompletionObject( comp );
140 } 142 }
141 */ 143 */
142 /** 144 /**
143 * replaces ~user or $FOO, if necessary 145 * replaces ~user or $FOO, if necessary
144 */ 146 */
145 QString url() { 147 QString url() {
146 QString txt = /*US combo ? combo->currentText() : */ edit->text(); 148 QString txt = /*US combo ? combo->currentText() : */ edit->text();
147/*US KURLCompletion *comp; 149/*US KURLCompletion *comp;
148 if ( combo ) 150 if ( combo )
149 comp = dynamic_cast<KURLCompletion*>(combo->completionObject()); 151 comp = dynamic_cast<KURLCompletion*>(combo->completionObject());
150 else 152 else
151 comp = dynamic_cast<KURLCompletion*>(edit->completionObject()); 153 comp = dynamic_cast<KURLCompletion*>(edit->completionObject());
152 154
153 if ( comp ) 155 if ( comp )
154 return comp->replacedPath( txt ); 156 return comp->replacedPath( txt );
155 else 157 else
156*/ 158*/
157 return txt; 159 return txt;
158 } 160 }
159 161
160 KLineEdit *edit; 162 KLineEdit *edit;
161//US KComboBox *combo; 163//US KComboBox *combo;
162 int fileDialogMode; 164 int fileDialogMode;
163 QString fileDialogFilter; 165 QString fileDialogFilter;
164}; 166};
165 167
166 168
167/*US 169/*US
168KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent, 170KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent,
169 const char *name ) 171 const char *name )
170 : QHBox( parent, name ) 172 : QHBox( parent, name )
171{ 173{
172 d = new KURLRequesterPrivate; 174 d = new KURLRequesterPrivate;
173 175
174 // must have this as parent 176 // must have this as parent
175 editWidget->reparent( this, 0, QPoint(0,0) ); 177 editWidget->reparent( this, 0, QPoint(0,0) );
176//US d->edit = dynamic_cast<KLineEdit*>( editWidget ); 178//US d->edit = dynamic_cast<KLineEdit*>( editWidget );
177 d->edit = (KLineEdit*)( editWidget ); 179 d->edit = (KLineEdit*)( editWidget );
178//US d->combo = dynamic_cast<KComboBox*>( editWidget ); 180//US d->combo = dynamic_cast<KComboBox*>( editWidget );
179 181
180 init(); 182 init();
181} 183}
182*/ 184*/
183 185
184KURLRequester::KURLRequester( QWidget *parent, const char *name ) 186KURLRequester::KURLRequester( QWidget *parent, const char *name )
185 : QHBox( parent, name ) 187 : Q3HBox( parent, name )
186{ 188{
187 d = new KURLRequesterPrivate; 189 d = new KURLRequesterPrivate;
188 init(); 190 init();
189} 191}
190 192
191 193
192KURLRequester::KURLRequester( const QString& url, QWidget *parent, 194KURLRequester::KURLRequester( const QString& url, QWidget *parent,
193 const char *name ) 195 const char *name )
194 : QHBox( parent, name ) 196 : Q3HBox( parent, name )
195{ 197{
196 d = new KURLRequesterPrivate; 198 d = new KURLRequesterPrivate;
197 init(); 199 init();
198 setURL( url ); 200 setURL( url );
199} 201}
200 202
201 203
202KURLRequester::~KURLRequester() 204KURLRequester::~KURLRequester()
203{ 205{
204//US delete myCompletion; 206//US delete myCompletion;
205 delete myFileDialog; 207 delete myFileDialog;
206 delete d; 208 delete d;
207} 209}
208 210
209 211
210void KURLRequester::init() 212void KURLRequester::init()
211{ 213{
212 myFileDialog = 0L; 214 myFileDialog = 0L;
213 myShowLocalProt = false; 215 myShowLocalProt = false;
214 mPathIsDir = false; 216 mPathIsDir = false;
215 if (/*US !d->combo && */ !d->edit ) 217 if (/*US !d->combo && */ !d->edit )
216 d->edit = new KLineEdit( this, "KURLRequester::KLineEdit" ); 218 d->edit = new KLineEdit( this, "KURLRequester::KLineEdit" );
217 219
218 myButton = new KURLDragPushButton( this, "kfile button"); 220 myButton = new KURLDragPushButton( this, "kfile button");
219 QIconSet iconSet = SmallIconSet("fileopen"); 221 QIcon iconSet = SmallIconSet("fileopen");
220 QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); 222 QPixmap pixMap = iconSet.pixmap( QIcon::Small, QIcon::Normal );
221 myButton->setIconSet( iconSet ); 223 myButton->setIconSet( iconSet );
222 myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); 224 myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
223//US QToolTip::add(myButton, i18n("Open file dialog")); 225//US QToolTip::add(myButton, i18n("Open file dialog"));
224 226
225 connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() )); 227 connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() ));
226 228
227 setSpacing( KDialog::spacingHint() ); 229 setSpacing( KDialog::spacingHint() );
228 230
229 QWidget *widget = /*US d->combo ? (QWidget*) d->combo : */ (QWidget*) d->edit; 231 QWidget *widget = /*US d->combo ? (QWidget*) d->combo : */ (QWidget*) d->edit;
230 setFocusProxy( widget ); 232 setFocusProxy( widget );
231 233
232 d->connectSignals( this ); 234 d->connectSignals( this );
233 connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() )); 235 connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() ));
234/*US 236/*US
235 myCompletion = new KURLCompletion(); 237 myCompletion = new KURLCompletion();
236 d->setCompletionObject( myCompletion ); 238 d->setCompletionObject( myCompletion );
237 239
238 KAccel *accel = new KAccel( this ); 240 KAccel *accel = new KAccel( this );
239 accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() )); 241 accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() ));
240 accel->readSettings(); 242 accel->readSettings();
241*/ 243*/
242} 244}
243 245
244 246
245void KURLRequester::setURL( const QString& url ) 247void KURLRequester::setURL( const QString& url )
246{ 248{
247 bool hasLocalPrefix = (url.startsWith("file:")); 249 bool hasLocalPrefix = (url.startsWith("file:"));
248 250
249 if ( !myShowLocalProt && hasLocalPrefix ) 251 if ( !myShowLocalProt && hasLocalPrefix )
250 d->setText( url.mid( 5, url.length()-5 )); 252 d->setText( url.mid( 5, url.length()-5 ));
251 else 253 else
252 d->setText( url ); 254 d->setText( url );
253} 255}
254 256
255void KURLRequester::setCaption( const QString& caption ) 257void KURLRequester::setCaption( const QString& caption )
256{ 258{
257 //USfileDialog()->setCaption( caption ); 259 //USfileDialog()->setCaption( caption );
258 //USQWidget::setCaption( caption ); 260 //USQWidget::setCaption( caption );
259} 261}
260 262
261QString KURLRequester::url() const 263QString KURLRequester::url() const
262{ 264{
263 return d->url(); 265 return d->url();
264} 266}
265 267
266 268
267void KURLRequester::slotOpenDialog() 269void KURLRequester::slotOpenDialog()
268{ 270{
269 emit openFileDialog( this ); 271 emit openFileDialog( this );
270 272
271//US use our special KFIleDialog instead 273//US use our special KFIleDialog instead
272 KURL u( url() ); 274 KURL u( url() );
273 //QString fn = u.url(); 275 //QString fn = u.url();
274 QString fn = d->edit->text(); 276 QString fn = d->edit->text();
275 if ( mPathIsDir ) 277 if ( mPathIsDir )
276 fn = KFileDialog::getExistingDirectory ( fn, "", this ); 278 fn = KFileDialog::getExistingDirectory ( fn, "", this );
277 else 279 else
278 fn = KFileDialog::getSaveFileName( fn, "", this ); 280 fn = KFileDialog::getSaveFileName( fn, "", this );
279 281
280 if ( fn == "" ) 282 if ( fn == "" )
281 return; 283 return;
282 284
283 setURL( fn ); 285 setURL( fn );
284 emit urlSelected( d->url() ); 286 emit urlSelected( d->url() );
285/*US 287/*US
286 KFileDialog *dlg = fileDialog(); 288 KFileDialog *dlg = fileDialog();
287 if ( !d->url().isEmpty() ) { 289 if ( !d->url().isEmpty() ) {
288 KURL u( url() ); 290 KURL u( url() );
289 // If we won't be able to list it (e.g. http), then don't try :) 291 // If we won't be able to list it (e.g. http), then don't try :)
290 if ( KProtocolInfo::supportsListing( u.protocol() ) ) 292 if ( KProtocolInfo::supportsListing( u.protocol() ) )
291 dlg->setSelection( u.url() ); 293 dlg->setSelection( u.url() );
292 } 294 }
293 295
294 if ( dlg->exec() == QDialog::Accepted ) 296 if ( dlg->exec() == QDialog::Accepted )
295 { 297 {
296 setURL( dlg->selectedURL().prettyURL() ); 298 setURL( dlg->selectedURL().prettyURL() );
297 emit urlSelected( d->url() ); 299 emit urlSelected( d->url() );
298 } 300 }
299*/ 301*/
300 302
301} 303}
302 304
303void KURLRequester::setMode(unsigned int mode) 305void KURLRequester::setMode(unsigned int mode)
304{ 306{
305/*US 307/*US
306 Q_ASSERT( (mode & KFile::Files) == 0 ); 308 Q_ASSERT( (mode & KFile::Files) == 0 );
307 d->fileDialogMode = mode; 309 d->fileDialogMode = mode;
308 if ( (mode & KFile::Directory) && !(mode & KFile::File) ) 310 if ( (mode & KFile::Directory) && !(mode & KFile::File) )
309 myCompletion->setMode( KURLCompletion::DirCompletion ); 311 myCompletion->setMode( KURLCompletion::DirCompletion );
310 312
311 if (myFileDialog) 313 if (myFileDialog)
312 myFileDialog->setMode( d->fileDialogMode ); 314 myFileDialog->setMode( d->fileDialogMode );
313*/ 315*/
314} 316}
315 317
316void KURLRequester::setFilter(const QString &filter) 318void KURLRequester::setFilter(const QString &filter)
317{ 319{
318/*US 320/*US
319 d->fileDialogFilter = filter; 321 d->fileDialogFilter = filter;
320 if (myFileDialog) 322 if (myFileDialog)
321 myFileDialog->setFilter( d->fileDialogFilter ); 323 myFileDialog->setFilter( d->fileDialogFilter );
322*/ 324*/
323} 325}
324 326
325KFileDialog * KURLRequester::fileDialog() const 327KFileDialog * KURLRequester::fileDialog() const
326{ 328{
327/*US 329/*US
328 if ( !myFileDialog ) { 330 if ( !myFileDialog ) {
329 QWidget *p = parentWidget(); 331 QWidget *p = parentWidget();
330 myFileDialog = new KFileDialog( QString::null, QString::null, p, 332 myFileDialog = new KFileDialog( QString::null, QString::null, p,
331 "file dialog", true ); 333 "file dialog", true );
332 334
333 myFileDialog->setMode( d->fileDialogMode ); 335 myFileDialog->setMode( d->fileDialogMode );
334 myFileDialog->setFilter( d->fileDialogFilter ); 336 myFileDialog->setFilter( d->fileDialogFilter );
335 } 337 }
336 338
337 return myFileDialog; 339 return myFileDialog;
338*/ 340*/
339 return 0; 341 return 0;
340} 342}
341 343
342 344
343void KURLRequester::setShowLocalProtocol( bool b ) 345void KURLRequester::setShowLocalProtocol( bool b )
344{ 346{
345 if ( myShowLocalProt == b ) 347 if ( myShowLocalProt == b )
346 return; 348 return;
347 349
348 myShowLocalProt = b; 350 myShowLocalProt = b;
349 setURL( url() ); 351 setURL( url() );
350} 352}
351 353
352void KURLRequester::clear() 354void KURLRequester::clear()
353{ 355{
354 d->setText( QString::null ); 356 d->setText( QString::null );
355} 357}
356 358
357KLineEdit * KURLRequester::lineEdit() const 359KLineEdit * KURLRequester::lineEdit() const
358{ 360{
359 return d->edit; 361 return d->edit;
360} 362}
361/*US 363/*US
362KComboBox * KURLRequester::comboBox() const 364KComboBox * KURLRequester::comboBox() const
363{ 365{
364 return d->combo; 366 return d->combo;
365} 367}
366*/ 368*/
367void KURLRequester::slotUpdateURL() 369void KURLRequester::slotUpdateURL()
368{ 370{
369 // bin compat, myButton is declared as QPushButton 371 // bin compat, myButton is declared as QPushButton
370//US KURL u( QDir::currentDirPath() + '/', url() ); 372//US KURL u( QDir::currentDirPath() + '/', url() );
371 KURL u( url() ); 373 KURL u( url() );
372 (static_cast<KURLDragPushButton *>( myButton))->setURL( u ); 374 (static_cast<KURLDragPushButton *>( myButton))->setURL( u );
373} 375}
374 376
375QPushButton * KURLRequester::button() const 377QPushButton * KURLRequester::button() const
376{ 378{
377 return myButton; 379 return myButton;
378} 380}
379/*US 381/*US
380KEditListBox::CustomEditor KURLRequester::customEditor() 382KEditListBox::CustomEditor KURLRequester::customEditor()
381{ 383{
382 setSizePolicy(QSizePolicy( QSizePolicy::Preferred, 384 setSizePolicy(QSizePolicy( QSizePolicy::Preferred,
383 QSizePolicy::Fixed)); 385 QSizePolicy::Fixed));
384 386
385 KLineEdit *edit = d->edit; 387 KLineEdit *edit = d->edit;
386 if ( !edit && d->combo ) 388 if ( !edit && d->combo )
387 edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() ); 389 edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() );
388 390
389#ifndef NDEBUG 391#ifndef NDEBUG
390 if ( !edit ) 392 if ( !edit )
391 kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n"; 393 kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n";
392#endif 394#endif
393 395
394 KEditListBox::CustomEditor editor( this, edit ); 396 KEditListBox::CustomEditor editor( this, edit );
395 return editor; 397 return editor;
396} 398}
397*/ 399*/
398void KURLRequester::virtual_hook( int, void* ) 400void KURLRequester::virtual_hook( int, void* )
399{ /*BASE::virtual_hook( id, data );*/ } 401{ /*BASE::virtual_hook( id, data );*/ }
400 402
401/*US 403/*US
402KURLComboRequester::KURLComboRequester( QWidget *parent, 404KURLComboRequester::KURLComboRequester( QWidget *parent,
403 const char *name ) 405 const char *name )
404 : KURLRequester( new KComboBox(false), parent, name) 406 : KURLRequester( new KComboBox(false), parent, name)
405{ 407{
406} 408}
407*/ 409*/
408 410
409//US #include "kurlrequester.moc" 411//US #include "kurlrequester.moc"
diff --git a/microkde/kio/kfile/kurlrequester.h b/microkde/kio/kfile/kurlrequester.h
index faa3326..5d4fa11 100644
--- a/microkde/kio/kfile/kurlrequester.h
+++ b/microkde/kio/kfile/kurlrequester.h
@@ -1,271 +1,271 @@
1/* This file is part of the KDE libraries 1/* This file is part of the KDE libraries
2 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> 2 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
3 3
4 library is free software; you can redistribute it and/or 4 library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License version 2, as published by the Free Software Foundation. 6 License version 2, as published by the Free Software Foundation.
7 7
8 This library is distributed in the hope that it will be useful, 8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details. 11 Library General Public License for more details.
12 12
13 You should have received a copy of the GNU Library General Public License 13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to 14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA. 16 Boston, MA 02111-1307, USA.
17*/ 17*/
18 18
19 19
20#ifndef KURLREQUESTER_H 20#ifndef KURLREQUESTER_H
21#define KURLREQUESTER_H 21#define KURLREQUESTER_H
22 22
23#include <qhbox.h> 23#include <q3hbox.h>
24 24
25#include <keditlistbox.h> 25#include <keditlistbox.h>
26//US #include <kfile.h> 26//US #include <kfile.h>
27//US #include <kpushbutton.h> 27//US #include <kpushbutton.h>
28#include <kurl.h> 28#include <kurl.h>
29 29
30//US class KComboBox; 30//US class KComboBox;
31 31
32class KFileDialog; 32class KFileDialog;
33class KLineEdit; 33class KLineEdit;
34//US class KURLCompletion; 34//US class KURLCompletion;
35class KURLDragPushButton; 35class KURLDragPushButton;
36 36
37class QPushButton; 37class QPushButton;
38class QString; 38class QString;
39class QTimer; 39class QTimer;
40 40
41/** 41/**
42 * This class is a widget showing a lineedit and a button, which invokes a 42 * This class is a widget showing a lineedit and a button, which invokes a
43 * filedialog. File name completion is available in the lineedit. 43 * filedialog. File name completion is available in the lineedit.
44 * 44 *
45 * The defaults for the filedialog are to ask for one existing local file, i.e. 45 * The defaults for the filedialog are to ask for one existing local file, i.e.
46 * KFileDialog::setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ) 46 * KFileDialog::setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly )
47 * The default filter is "*", i.e. show all files, and the start directory is 47 * The default filter is "*", i.e. show all files, and the start directory is
48 * the current working directory, or the last directory where a file has been 48 * the current working directory, or the last directory where a file has been
49 * selected. 49 * selected.
50 * 50 *
51 * You can change this behavior by using @ref setMode() or @ref setFilter(). 51 * You can change this behavior by using @ref setMode() or @ref setFilter().
52 * 52 *
53 * @short A widget to request a filename/url from the user 53 * @short A widget to request a filename/url from the user
54 * @author Carsten Pfeiffer <pfeiffer@kde.org> 54 * @author Carsten Pfeiffer <pfeiffer@kde.org>
55 */ 55 */
56class KURLRequester : public QHBox 56class KURLRequester : public Q3HBox
57{ 57{
58 Q_OBJECT 58 Q_OBJECT
59 Q_PROPERTY( QString url READ url WRITE setURL ) 59 Q_PROPERTY( QString url READ url WRITE setURL )
60 60
61public: 61public:
62 /** 62 /**
63 * Constructs a KURLRequester widget. 63 * Constructs a KURLRequester widget.
64 */ 64 */
65 KURLRequester( QWidget *parent=0, const char *name=0 ); 65 KURLRequester( QWidget *parent=0, const char *name=0 );
66 66
67 /** 67 /**
68 * Constructs a KURLRequester widget with the initial URL @p url. 68 * Constructs a KURLRequester widget with the initial URL @p url.
69 */ 69 */
70 KURLRequester( const QString& url, QWidget *parent=0, const char *name=0 ); 70 KURLRequester( const QString& url, QWidget *parent=0, const char *name=0 );
71 71
72 /** 72 /**
73 * Special constructor, which creates a KURLRequester widget with a custom 73 * Special constructor, which creates a KURLRequester widget with a custom
74 * edit-widget. The edit-widget can be either a KComboBox or a KLineEdit 74 * edit-widget. The edit-widget can be either a KComboBox or a KLineEdit
75 * (or inherited thereof). Note: for geometry management reasons, the 75 * (or inherited thereof). Note: for geometry management reasons, the
76 * edit-widget is reparented to have the KURLRequester as parent. 76 * edit-widget is reparented to have the KURLRequester as parent.
77 * @param modal specifies whether the filedialog should be opened as modal 77 * @param modal specifies whether the filedialog should be opened as modal
78 * or not. 78 * or not.
79 */ 79 */
80//US KURLRequester( QWidget *editWidget, QWidget *parent, const char *name=0 ); 80//US KURLRequester( QWidget *editWidget, QWidget *parent, const char *name=0 );
81 /** 81 /**
82 * Destructs the KURLRequester. 82 * Destructs the KURLRequester.
83 */ 83 */
84 ~KURLRequester(); 84 ~KURLRequester();
85 85
86 /** 86 /**
87 * @returns the current url in the lineedit. May be malformed, if the user 87 * @returns the current url in the lineedit. May be malformed, if the user
88 * entered something weird. ~user or environment variables are substituted 88 * entered something weird. ~user or environment variables are substituted
89 * for local files. 89 * for local files.
90 */ 90 */
91 QString url() const; 91 QString url() const;
92 92
93 /** 93 /**
94 * Enables/disables showing file:/ in the lineedit, when a local file has 94 * Enables/disables showing file:/ in the lineedit, when a local file has
95 * been selected in the filedialog or was set via @ref setURL(). 95 * been selected in the filedialog or was set via @ref setURL().
96 * Default is false, not showing file:/ 96 * Default is false, not showing file:/
97 * @see #showLocalProtocol 97 * @see #showLocalProtocol
98 */ 98 */
99 void setShowLocalProtocol( bool b ); 99 void setShowLocalProtocol( bool b );
100 100
101 /** 101 /**
102 * Sets the mode of the file dialog. 102 * Sets the mode of the file dialog.
103 * Note: you can only select one file with the filedialog, 103 * Note: you can only select one file with the filedialog,
104 * so KFile::Files doesn't make much sense. 104 * so KFile::Files doesn't make much sense.
105 * @see KFileDialog::setMode() 105 * @see KFileDialog::setMode()
106 */ 106 */
107 void setMode( unsigned int m ); 107 void setMode( unsigned int m );
108 void setPathIsDir( ) {mPathIsDir = true;} 108 void setPathIsDir( ) {mPathIsDir = true;}
109 109
110 /** 110 /**
111 * Sets the filter for the file dialog. 111 * Sets the filter for the file dialog.
112 * @see KFileDialog::setFilter() 112 * @see KFileDialog::setFilter()
113 */ 113 */
114 void setFilter( const QString& filter ); 114 void setFilter( const QString& filter );
115 115
116 /** 116 /**
117 * @returns whether local files will be prefixed with file:/ in the 117 * @returns whether local files will be prefixed with file:/ in the
118 * lineedit 118 * lineedit
119 * @see #setShowLocalProtocol 119 * @see #setShowLocalProtocol
120 */ 120 */
121 bool showLocalProtocol() const { return myShowLocalProt; } 121 bool showLocalProtocol() const { return myShowLocalProt; }
122 122
123 /** 123 /**
124 * @returns a pointer to the filedialog 124 * @returns a pointer to the filedialog
125 * You can use this to customize the dialog, e.g. to specify a filter. 125 * You can use this to customize the dialog, e.g. to specify a filter.
126 * Never returns 0L. 126 * Never returns 0L.
127 */ 127 */
128 virtual KFileDialog * fileDialog() const; 128 virtual KFileDialog * fileDialog() const;
129 129
130 /** 130 /**
131 * @returns a pointer to the lineedit, either the default one, or the 131 * @returns a pointer to the lineedit, either the default one, or the
132 * special one, if you used the special constructor. 132 * special one, if you used the special constructor.
133 * 133 *
134 * It is provided so that you can e.g. set an own completion object 134 * It is provided so that you can e.g. set an own completion object
135 * (e.g. @ref KShellCompletion) into it. 135 * (e.g. @ref KShellCompletion) into it.
136 */ 136 */
137 KLineEdit * lineEdit() const; 137 KLineEdit * lineEdit() const;
138 138
139 /** 139 /**
140 * @returns a pointer to the combobox, in case you have set one using the 140 * @returns a pointer to the combobox, in case you have set one using the
141 * special constructor. Returns 0L otherwise. 141 * special constructor. Returns 0L otherwise.
142 */ 142 */
143//US KComboBox * comboBox() const; 143//US KComboBox * comboBox() const;
144 144
145 /** 145 /**
146 * @returns a pointer to the pushbutton. It is provided so that you can 146 * @returns a pointer to the pushbutton. It is provided so that you can
147 * specify an own pixmap or a text, if you really need to. 147 * specify an own pixmap or a text, if you really need to.
148 */ 148 */
149 QPushButton * button() const; 149 QPushButton * button() const;
150 150
151 /** 151 /**
152 * @returns the KURLCompletion object used in the lineedit/combobox. 152 * @returns the KURLCompletion object used in the lineedit/combobox.
153 */ 153 */
154//US KURLCompletion *completionObject() const { return myCompletion; } 154//US KURLCompletion *completionObject() const { return myCompletion; }
155 155
156 /** 156 /**
157 * @returns an object, suitable for use with KEditListBox. It allows you 157 * @returns an object, suitable for use with KEditListBox. It allows you
158 * to put this KURLRequester into a KEditListBox. 158 * to put this KURLRequester into a KEditListBox.
159 * Basically, do it like this: 159 * Basically, do it like this:
160 * <pre> 160 * <pre>
161 * KURLRequester *req = new KURLRequester( someWidget ); 161 * KURLRequester *req = new KURLRequester( someWidget );
162 * [...] 162 * [...]
163 * KEditListBox *editListBox = new KEditListBox( i18n("Some Title"), req->customEditor(), someWidget ); 163 * KEditListBox *editListBox = new KEditListBox( i18n("Some Title"), req->customEditor(), someWidget );
164 * </pre> 164 * </pre>
165 * @since 3.1 165 * @since 3.1
166 */ 166 */
167//US KEditListBox::CustomEditor customEditor(); 167//US KEditListBox::CustomEditor customEditor();
168 168
169public slots: 169public slots:
170 /** 170 /**
171 * Sets the url in the lineedit to @p url. Depending on the state of 171 * Sets the url in the lineedit to @p url. Depending on the state of
172 * @ref showLocalProtocol(), file:/ on local files will be shown or not. 172 * @ref showLocalProtocol(), file:/ on local files will be shown or not.
173 * @since 3.1 173 * @since 3.1
174 */ 174 */
175 void setURL( const QString& url ); 175 void setURL( const QString& url );
176 176
177 /** 177 /**
178 * @reimp 178 * @reimp
179 * Sets the caption of the file dialog. 179 * Sets the caption of the file dialog.
180 * @since 3.1 180 * @since 3.1
181 */ 181 */
182 virtual void setCaption( const QString& caption ); 182 virtual void setCaption( const QString& caption );
183 183
184 /** 184 /**
185 * Clears the lineedit/combobox. 185 * Clears the lineedit/combobox.
186 */ 186 */
187 void clear(); 187 void clear();
188 188
189signals: 189signals:
190 // forwards from LineEdit 190 // forwards from LineEdit
191 /** 191 /**
192 * Emitted when the text in the lineedit changes. 192 * Emitted when the text in the lineedit changes.
193 * The parameter contains the contents of the lineedit. 193 * The parameter contains the contents of the lineedit.
194 * @since 3.1 194 * @since 3.1
195 */ 195 */
196 void textChanged( const QString& ); 196 void textChanged( const QString& );
197 197
198 /** 198 /**
199 * Emitted when return or enter was pressed in the lineedit. 199 * Emitted when return or enter was pressed in the lineedit.
200 */ 200 */
201 void returnPressed(); 201 void returnPressed();
202 202
203 /** 203 /**
204 * Emitted when return or enter was pressed in the lineedit. 204 * Emitted when return or enter was pressed in the lineedit.
205 * The parameter contains the contents of the lineedit. 205 * The parameter contains the contents of the lineedit.
206 */ 206 */
207 void returnPressed( const QString& ); 207 void returnPressed( const QString& );
208 208
209 /** 209 /**
210 * Emitted before the filedialog is going to open. Connect 210 * Emitted before the filedialog is going to open. Connect
211 * to this signal to "configure" the filedialog, e.g. set the 211 * to this signal to "configure" the filedialog, e.g. set the
212 * filefilter, the mode, a preview-widget, etc. It's usually 212 * filefilter, the mode, a preview-widget, etc. It's usually
213 * not necessary to set a URL for the filedialog, as it will 213 * not necessary to set a URL for the filedialog, as it will
214 * get set properly from the editfield contents. 214 * get set properly from the editfield contents.
215 * 215 *
216 * If you use multiple KURLRequesters, you can connect all of them 216 * If you use multiple KURLRequesters, you can connect all of them
217 * to the same slot and use the given KURLRequester pointer to know 217 * to the same slot and use the given KURLRequester pointer to know
218 * which one is going to open. 218 * which one is going to open.
219 */ 219 */
220 void openFileDialog( KURLRequester * ); 220 void openFileDialog( KURLRequester * );
221 221
222 /** 222 /**
223 * Emitted when the user changed the URL via the file dialog. 223 * Emitted when the user changed the URL via the file dialog.
224 * The parameter contains the contents of the lineedit. 224 * The parameter contains the contents of the lineedit.
225 */ 225 */
226 void urlSelected( const QString& ); 226 void urlSelected( const QString& );
227 227
228protected: 228protected:
229 void init(); 229 void init();
230 230
231//US KURLCompletion * myCompletion; 231//US KURLCompletion * myCompletion;
232 232
233 233
234private: 234private:
235 KURLDragPushButton * myButton; 235 KURLDragPushButton * myButton;
236 bool myShowLocalProt; 236 bool myShowLocalProt;
237 mutable KFileDialog * myFileDialog; 237 mutable KFileDialog * myFileDialog;
238 bool mPathIsDir; 238 bool mPathIsDir;
239 239
240 240
241protected slots: 241protected slots:
242 /** 242 /**
243 * Called when the button is pressed to open the filedialog. 243 * Called when the button is pressed to open the filedialog.
244 * Also called when @ref KStdAccel::Open (default is Ctrl-O) is pressed. 244 * Also called when @ref KStdAccel::Open (default is Ctrl-O) is pressed.
245 */ 245 */
246 void slotOpenDialog(); 246 void slotOpenDialog();
247 247
248private slots: 248private slots:
249 void slotUpdateURL(); 249 void slotUpdateURL();
250 250
251protected: 251protected:
252 virtual void virtual_hook( int id, void* data ); 252 virtual void virtual_hook( int id, void* data );
253private: 253private:
254 class KURLRequesterPrivate; 254 class KURLRequesterPrivate;
255 KURLRequesterPrivate *d; 255 KURLRequesterPrivate *d;
256}; 256};
257/*US 257/*US
258class KURLComboRequester : public KURLRequester // For use in Qt Designer 258class KURLComboRequester : public KURLRequester // For use in Qt Designer
259{ 259{
260 Q_OBJECT 260 Q_OBJECT
261public: 261public:
262*/ 262*/
263 /** 263 /**
264 * Constructs a KURLRequester widget with a combobox. 264 * Constructs a KURLRequester widget with a combobox.
265 */ 265 */
266/*US 266/*US
267 KURLComboRequester( QWidget *parent=0, const char *name=0 ); 267 KURLComboRequester( QWidget *parent=0, const char *name=0 );
268}; 268};
269*/ 269*/
270 270
271#endif // KURLREQUESTER_H 271#endif // KURLREQUESTER_H
diff --git a/microkde/kio/kio/kdirwatch.cpp b/microkde/kio/kio/kdirwatch.cpp
index 1596d1f..5f07c54 100644
--- a/microkde/kio/kio/kdirwatch.cpp
+++ b/microkde/kio/kio/kdirwatch.cpp
@@ -1,1443 +1,1445 @@
1// -*- c-basic-offset: 2 -*- 1// -*- c-basic-offset: 2 -*-
2/* This file is part of the KDE libraries 2/* This file is part of the KDE libraries
3 Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at> 3 Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation. 7 License version 2 as published by the Free Software Foundation.
8 8
9 This library is distributed in the hope that it will be useful, 9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details. 12 Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to 15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. 17 Boston, MA 02111-1307, USA.
18*/ 18*/
19 19
20/* 20/*
21Enhanced Version of the file for platform independent KDE tools. 21Enhanced Version of the file for platform independent KDE tools.
22Copyright (c) 2004 Ulf Schenk 22Copyright (c) 2004 Ulf Schenk
23 23
24$Id$ 24$Id$
25*/ 25*/
26 26
27 27
28// CHANGES: 28// CHANGES:
29// Februar 2002 - Add file watching and remote mount check for STAT 29// Februar 2002 - Add file watching and remote mount check for STAT
30// Mar 30, 2001 - Native support for Linux dir change notification. 30// Mar 30, 2001 - Native support for Linux dir change notification.
31// Jan 28, 2000 - Usage of FAM service on IRIX (Josef.Weidendorfer@in.tum.de) 31// Jan 28, 2000 - Usage of FAM service on IRIX (Josef.Weidendorfer@in.tum.de)
32// May 24. 1998 - List of times introduced, and some bugs are fixed. (sven) 32// May 24. 1998 - List of times introduced, and some bugs are fixed. (sven)
33// May 23. 1998 - Removed static pointer - you can have more instances. 33// May 23. 1998 - Removed static pointer - you can have more instances.
34// It was Needed for KRegistry. KDirWatch now emits signals and doesn't 34// It was Needed for KRegistry. KDirWatch now emits signals and doesn't
35// call (or need) KFM. No more URL's - just plain paths. (sven) 35// call (or need) KFM. No more URL's - just plain paths. (sven)
36// Mar 29. 1998 - added docs, stop/restart for particular Dirs and 36// Mar 29. 1998 - added docs, stop/restart for particular Dirs and
37// deep copies for list of dirs. (sven) 37// deep copies for list of dirs. (sven)
38// Mar 28. 1998 - Created. (sven) 38// Mar 28. 1998 - Created. (sven)
39 39
40 40
41//US #include <config.h> 41//US #include <config.h>
42 42
43#ifdef HAVE_DNOTIFY 43#ifdef HAVE_DNOTIFY
44#include <unistd.h> 44#include <unistd.h>
45#include <time.h> 45#include <time.h>
46#include <fcntl.h> 46#include <fcntl.h>
47#include <signal.h> 47#include <signal.h>
48#include <errno.h> 48#include <errno.h>
49#endif 49#endif
50 50
51#include <sys/stat.h> 51#include <sys/stat.h>
52#include <assert.h> 52#include <assert.h>
53#include <qdir.h> 53#include <qdir.h>
54#include <qfile.h> 54#include <qfile.h>
55#include <qintdict.h> 55#include <q3intdict.h>
56#include <qptrlist.h> 56#include <q3ptrlist.h>
57#include <qsocketnotifier.h> 57#include <qsocketnotifier.h>
58#include <qstringlist.h> 58#include <qstringlist.h>
59#include <qtimer.h> 59#include <qtimer.h>
60//Added by qt3to4:
61#include <Q3CString>
60 62
61#include <kapplication.h> 63#include <kapplication.h>
62#include <kdebug.h> 64#include <kdebug.h>
63#include <kconfig.h> 65#include <kconfig.h>
64#include <kconfigbase.h> 66#include <kconfigbase.h>
65#include <kglobal.h> 67#include <kglobal.h>
66#include <kstaticdeleter.h> 68#include <kstaticdeleter.h>
67 69
68#include "kdirwatch.h" 70#include "kdirwatch.h"
69#include "kdirwatch_p.h" 71#include "kdirwatch_p.h"
70//US #include "global.h" // KIO::probably_slow_mounted 72//US #include "global.h" // KIO::probably_slow_mounted
71 73
72#define NO_NOTIFY (time_t) 0 74#define NO_NOTIFY (time_t) 0
73 75
74static KDirWatchPrivate* dwp_self = 0; 76static KDirWatchPrivate* dwp_self = 0;
75 77
76#ifdef HAVE_DNOTIFY 78#ifdef HAVE_DNOTIFY
77 79
78#include <sys/utsname.h> 80#include <sys/utsname.h>
79 81
80static int dnotify_signal = 0; 82static int dnotify_signal = 0;
81 83
82/* DNOTIFY signal handler 84/* DNOTIFY signal handler
83 * 85 *
84 * As this is called asynchronously, only a flag is set and 86 * As this is called asynchronously, only a flag is set and
85 * a rescan is requested. 87 * a rescan is requested.
86 * This is done by writing into a pipe to trigger a QSocketNotifier 88 * This is done by writing into a pipe to trigger a QSocketNotifier
87 * watching on this pipe: a timer is started and after a timeout, 89 * watching on this pipe: a timer is started and after a timeout,
88 * the rescan is done. 90 * the rescan is done.
89 */ 91 */
90void KDirWatchPrivate::dnotify_handler(int, siginfo_t *si, void *) 92void KDirWatchPrivate::dnotify_handler(int, siginfo_t *si, void *)
91{ 93{
92 // write might change errno, we have to save it and restore it 94 // write might change errno, we have to save it and restore it
93 // (Richard Stevens, Advanced programming in the Unix Environment) 95 // (Richard Stevens, Advanced programming in the Unix Environment)
94 int saved_errno = errno; 96 int saved_errno = errno;
95 97
96 Entry* e = (dwp_self) ? dwp_self->fd_Entry.find(si->si_fd) :0; 98 Entry* e = (dwp_self) ? dwp_self->fd_Entry.find(si->si_fd) :0;
97 99
98// kdDebug(7001) << "DNOTIFY Handler: fd " << si->si_fd << " path " 100// kdDebug(7001) << "DNOTIFY Handler: fd " << si->si_fd << " path "
99 // << QString(e ? e->path:"unknown") << endl; 101 // << QString(e ? e->path:"unknown") << endl;
100 102
101 if(!e || e->dn_fd != si->si_fd) { 103 if(!e || e->dn_fd != si->si_fd) {
102 qDebug("fatal error in KDirWatch"); 104 qDebug("fatal error in KDirWatch");
103 } else 105 } else
104 e->dn_dirty = true; 106 e->dn_dirty = true;
105 107
106 char c = 0; 108 char c = 0;
107 write(dwp_self->mPipe[1], &c, 1); 109 write(dwp_self->mPipe[1], &c, 1);
108 errno = saved_errno; 110 errno = saved_errno;
109} 111}
110 112
111static struct sigaction old_sigio_act; 113static struct sigaction old_sigio_act;
112/* DNOTIFY SIGIO signal handler 114/* DNOTIFY SIGIO signal handler
113 * 115 *
114 * When the kernel queue for the dnotify_signal overflows, a SIGIO is send. 116 * When the kernel queue for the dnotify_signal overflows, a SIGIO is send.
115 */ 117 */
116void KDirWatchPrivate::dnotify_sigio_handler(int sig, siginfo_t *si, void *p) 118void KDirWatchPrivate::dnotify_sigio_handler(int sig, siginfo_t *si, void *p)
117{ 119{
118 // write might change errno, we have to save it and restore it 120 // write might change errno, we have to save it and restore it
119 // (Richard Stevens, Advanced programming in the Unix Environment) 121 // (Richard Stevens, Advanced programming in the Unix Environment)
120 int saved_errno = errno; 122 int saved_errno = errno;
121 123
122 if (dwp_self) 124 if (dwp_self)
123 dwp_self->rescan_all = true; 125 dwp_self->rescan_all = true;
124 126
125 char c = 0; 127 char c = 0;
126 write(dwp_self->mPipe[1], &c, 1); 128 write(dwp_self->mPipe[1], &c, 1);
127 129
128 errno = saved_errno; 130 errno = saved_errno;
129 131
130 // Call previous signal handler 132 // Call previous signal handler
131 if (old_sigio_act.sa_flags & SA_SIGINFO) 133 if (old_sigio_act.sa_flags & SA_SIGINFO)
132 { 134 {
133 if (old_sigio_act.sa_sigaction) 135 if (old_sigio_act.sa_sigaction)
134 (*old_sigio_act.sa_sigaction)(sig, si, p); 136 (*old_sigio_act.sa_sigaction)(sig, si, p);
135 } 137 }
136 else 138 else
137 { 139 {
138 if ((old_sigio_act.sa_handler != SIG_DFL) && 140 if ((old_sigio_act.sa_handler != SIG_DFL) &&
139 (old_sigio_act.sa_handler != SIG_IGN)) 141 (old_sigio_act.sa_handler != SIG_IGN))
140 (*old_sigio_act.sa_handler)(sig); 142 (*old_sigio_act.sa_handler)(sig);
141 } 143 }
142} 144}
143#endif 145#endif
144 146
145 147
146// 148//
147// Class KDirWatchPrivate (singleton) 149// Class KDirWatchPrivate (singleton)
148// 150//
149 151
150/* All entries (files/directories) to be watched in the 152/* All entries (files/directories) to be watched in the
151 * application (coming from multiple KDirWatch instances) 153 * application (coming from multiple KDirWatch instances)
152 * are registered in a single KDirWatchPrivate instance. 154 * are registered in a single KDirWatchPrivate instance.
153 * 155 *
154 * At the moment, the following methods for file watching 156 * At the moment, the following methods for file watching
155 * are supported: 157 * are supported:
156 * - Polling: All files to be watched are polled regularly 158 * - Polling: All files to be watched are polled regularly
157 * using stat (more precise: QFileInfo.lastModified()). 159 * using stat (more precise: QFileInfo.lastModified()).
158 * The polling frequency is determined from global kconfig 160 * The polling frequency is determined from global kconfig
159 * settings, defaulting to 500 ms for local directories 161 * settings, defaulting to 500 ms for local directories
160 * and 5000 ms for remote mounts 162 * and 5000 ms for remote mounts
161 * - FAM (File Alternation Monitor): first used on IRIX, SGI 163 * - FAM (File Alternation Monitor): first used on IRIX, SGI
162 * has ported this method to LINUX. It uses a kernel part 164 * has ported this method to LINUX. It uses a kernel part
163 * (IMON, sending change events to /dev/imon) and a user 165 * (IMON, sending change events to /dev/imon) and a user
164 * level damon (fam), to which applications connect for 166 * level damon (fam), to which applications connect for
165 * notification of file changes. For NFS, the fam damon 167 * notification of file changes. For NFS, the fam damon
166 * on the NFS server machine is used; if IMON is not built 168 * on the NFS server machine is used; if IMON is not built
167 * into the kernel, fam uses polling for local files. 169 * into the kernel, fam uses polling for local files.
168 * - DNOTIFY: In late LINUX 2.3.x, directory notification was 170 * - DNOTIFY: In late LINUX 2.3.x, directory notification was
169 * introduced. By opening a directory, you can request for 171 * introduced. By opening a directory, you can request for
170 * UNIX signals to be sent to the process when a directory 172 * UNIX signals to be sent to the process when a directory
171 * is changed. 173 * is changed.
172 */ 174 */
173 175
174KDirWatchPrivate::KDirWatchPrivate() 176KDirWatchPrivate::KDirWatchPrivate()
175{ 177{
176 timer = new QTimer(this); 178 timer = new QTimer(this);
177 connect (timer, SIGNAL(timeout()), this, SLOT(slotRescan())); 179 connect (timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
178 freq = 3600000; // 1 hour as upper bound 180 freq = 3600000; // 1 hour as upper bound
179 statEntries = 0; 181 statEntries = 0;
180 delayRemove = false; 182 delayRemove = false;
181 m_ref = 0; 183 m_ref = 0;
182 184
183//US KConfigGroup config(KGlobal::config(), QCString("DirWatch")); 185//US KConfigGroup config(KGlobal::config(), QCString("DirWatch"));
184//US m_nfsPollInterval = config.readNumEntry("NFSPollInterval", 5000); 186//US m_nfsPollInterval = config.readNumEntry("NFSPollInterval", 5000);
185//US m_PollInterval = config.readNumEntry("PollInterval", 500); 187//US m_PollInterval = config.readNumEntry("PollInterval", 500);
186 KConfig *config = KGlobal::config(); 188 KConfig *config = KGlobal::config();
187 KConfigGroupSaver saver( config, QCString("DirWatch") ); 189 KConfigGroupSaver saver( config, Q3CString("DirWatch") );
188 190
189 m_nfsPollInterval = config->readNumEntry("NFSPollInterval", 5000); 191 m_nfsPollInterval = config->readNumEntry("NFSPollInterval", 5000);
190 m_PollInterval = config->readNumEntry("PollInterval", 500); 192 m_PollInterval = config->readNumEntry("PollInterval", 500);
191 193
192 194
193 QString available("Stat"); 195 QString available("Stat");
194 196
195#ifdef HAVE_FAM 197#ifdef HAVE_FAM
196 // It's possible that FAM server can't be started 198 // It's possible that FAM server can't be started
197 if (FAMOpen(&fc) ==0) { 199 if (FAMOpen(&fc) ==0) {
198 available += ", FAM"; 200 available += ", FAM";
199 use_fam=true; 201 use_fam=true;
200 sn = new QSocketNotifier( FAMCONNECTION_GETFD(&fc), 202 sn = new QSocketNotifier( FAMCONNECTION_GETFD(&fc),
201 QSocketNotifier::Read, this); 203 QSocketNotifier::Read, this);
202 connect( sn, SIGNAL(activated(int)), 204 connect( sn, SIGNAL(activated(int)),
203 this, SLOT(famEventReceived()) ); 205 this, SLOT(famEventReceived()) );
204 } 206 }
205 else { 207 else {
206 kdDebug(7001) << "Can't use FAM (fam daemon not running?)" << endl; 208 kdDebug(7001) << "Can't use FAM (fam daemon not running?)" << endl;
207 use_fam=false; 209 use_fam=false;
208 } 210 }
209#endif 211#endif
210 212
211#ifdef HAVE_DNOTIFY 213#ifdef HAVE_DNOTIFY
212 supports_dnotify = true; // not guilty until proven guilty 214 supports_dnotify = true; // not guilty until proven guilty
213 rescan_all = false; 215 rescan_all = false;
214 struct utsname uts; 216 struct utsname uts;
215 int major, minor, patch; 217 int major, minor, patch;
216 if (uname(&uts) < 0) 218 if (uname(&uts) < 0)
217 supports_dnotify = false; // *shrug* 219 supports_dnotify = false; // *shrug*
218 else if (sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3) 220 else if (sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3)
219 supports_dnotify = false; // *shrug* 221 supports_dnotify = false; // *shrug*
220 else if( major * 1000000 + minor * 1000 + patch < 2004019 ) { // <2.4.19 222 else if( major * 1000000 + minor * 1000 + patch < 2004019 ) { // <2.4.19
221 kdDebug(7001) << "Can't use DNotify, Linux kernel too old" << endl; 223 kdDebug(7001) << "Can't use DNotify, Linux kernel too old" << endl;
222 supports_dnotify = false; 224 supports_dnotify = false;
223 } 225 }
224 226
225 if( supports_dnotify ) { 227 if( supports_dnotify ) {
226 available += ", DNotify"; 228 available += ", DNotify";
227 229
228 pipe(mPipe); 230 pipe(mPipe);
229 fcntl(mPipe[0], F_SETFD, FD_CLOEXEC); 231 fcntl(mPipe[0], F_SETFD, FD_CLOEXEC);
230 fcntl(mPipe[1], F_SETFD, FD_CLOEXEC); 232 fcntl(mPipe[1], F_SETFD, FD_CLOEXEC);
231 mSn = new QSocketNotifier( mPipe[0], QSocketNotifier::Read, this); 233 mSn = new QSocketNotifier( mPipe[0], QSocketNotifier::Read, this);
232 connect(mSn, SIGNAL(activated(int)), this, SLOT(slotActivated())); 234 connect(mSn, SIGNAL(activated(int)), this, SLOT(slotActivated()));
233 connect(&mTimer, SIGNAL(timeout()), this, SLOT(slotRescan())); 235 connect(&mTimer, SIGNAL(timeout()), this, SLOT(slotRescan()));
234 struct sigaction act; 236 struct sigaction act;
235 act.sa_sigaction = KDirWatchPrivate::dnotify_handler; 237 act.sa_sigaction = KDirWatchPrivate::dnotify_handler;
236 sigemptyset(&act.sa_mask); 238 sigemptyset(&act.sa_mask);
237 act.sa_flags = SA_SIGINFO; 239 act.sa_flags = SA_SIGINFO;
238#ifdef SA_RESTART 240#ifdef SA_RESTART
239 act.sa_flags |= SA_RESTART; 241 act.sa_flags |= SA_RESTART;
240#endif 242#endif
241 if( dnotify_signal == 0 ) 243 if( dnotify_signal == 0 )
242 dnotify_signal = SIGRTMIN + 8; 244 dnotify_signal = SIGRTMIN + 8;
243 sigaction(dnotify_signal, &act, NULL); 245 sigaction(dnotify_signal, &act, NULL);
244 246
245 act.sa_sigaction = KDirWatchPrivate::dnotify_sigio_handler; 247 act.sa_sigaction = KDirWatchPrivate::dnotify_sigio_handler;
246 sigaction(SIGIO, &act, &old_sigio_act); 248 sigaction(SIGIO, &act, &old_sigio_act);
247 } 249 }
248#endif 250#endif
249 251
250 kdDebug(7001) << "Available methods: " << available << endl; 252 kdDebug(7001) << "Available methods: " << available << endl;
251} 253}
252 254
253/* This should never be called, but doesn't harm */ 255/* This should never be called, but doesn't harm */
254KDirWatchPrivate::~KDirWatchPrivate() 256KDirWatchPrivate::~KDirWatchPrivate()
255{ 257{
256 timer->stop(); 258 timer->stop();
257 259
258 /* remove all entries being watched */ 260 /* remove all entries being watched */
259 removeEntries(0); 261 removeEntries(0);
260 262
261#ifdef HAVE_FAM 263#ifdef HAVE_FAM
262 if (use_fam) { 264 if (use_fam) {
263 FAMClose(&fc); 265 FAMClose(&fc);
264 kdDebug(7001) << "KDirWatch deleted (FAM closed)" << endl; 266 kdDebug(7001) << "KDirWatch deleted (FAM closed)" << endl;
265 } 267 }
266#endif 268#endif
267 269
268} 270}
269 271
270#ifdef HAVE_DNOTIFY 272#ifdef HAVE_DNOTIFY
271void KDirWatchPrivate::slotActivated() 273void KDirWatchPrivate::slotActivated()
272{ 274{
273 char dummy_buf[100]; 275 char dummy_buf[100];
274 read(mPipe[0], &dummy_buf, 100); 276 read(mPipe[0], &dummy_buf, 100);
275 277
276 if (!mTimer.isActive()) 278 if (!mTimer.isActive())
277 mTimer.start(200, true); 279 mTimer.start(200, true);
278} 280}
279 281
280/* In DNOTIFY mode, only entries which are marked dirty are scanned. 282/* In DNOTIFY mode, only entries which are marked dirty are scanned.
281 * We first need to mark all yet nonexistant, but possible created 283 * We first need to mark all yet nonexistant, but possible created
282 * entries as dirty... 284 * entries as dirty...
283 */ 285 */
284void KDirWatchPrivate::Entry::propagate_dirty() 286void KDirWatchPrivate::Entry::propagate_dirty()
285{ 287{
286 Entry* sub_entry; 288 Entry* sub_entry;
287 for(sub_entry = m_entries.first(); sub_entry; sub_entry = m_entries.next()) 289 for(sub_entry = m_entries.first(); sub_entry; sub_entry = m_entries.next())
288 { 290 {
289 if (!sub_entry->dn_dirty) 291 if (!sub_entry->dn_dirty)
290 { 292 {
291 sub_entry->dn_dirty = true; 293 sub_entry->dn_dirty = true;
292 sub_entry->propagate_dirty(); 294 sub_entry->propagate_dirty();
293 } 295 }
294 } 296 }
295} 297}
296 298
297#else // !HAVE_DNOTIFY 299#else // !HAVE_DNOTIFY
298// slots always have to be defined... 300// slots always have to be defined...
299void KDirWatchPrivate::slotActivated() {} 301void KDirWatchPrivate::slotActivated() {}
300#endif 302#endif
301 303
302/* A KDirWatch instance is interested in getting events for 304/* A KDirWatch instance is interested in getting events for
303 * this file/Dir entry. 305 * this file/Dir entry.
304 */ 306 */
305void KDirWatchPrivate::Entry::addClient(KDirWatch* instance) 307void KDirWatchPrivate::Entry::addClient(KDirWatch* instance)
306{ 308{
307 Client* client = m_clients.first(); 309 Client* client = m_clients.first();
308 for(;client; client = m_clients.next()) 310 for(;client; client = m_clients.next())
309 if (client->instance == instance) break; 311 if (client->instance == instance) break;
310 312
311 if (client) { 313 if (client) {
312 client->count++; 314 client->count++;
313 return; 315 return;
314 } 316 }
315 317
316 client = new Client; 318 client = new Client;
317 client->instance = instance; 319 client->instance = instance;
318 client->count = 1; 320 client->count = 1;
319 client->watchingStopped = instance->isStopped(); 321 client->watchingStopped = instance->isStopped();
320 client->pending = NoChange; 322 client->pending = NoChange;
321 323
322 m_clients.append(client); 324 m_clients.append(client);
323} 325}
324 326
325void KDirWatchPrivate::Entry::removeClient(KDirWatch* instance) 327void KDirWatchPrivate::Entry::removeClient(KDirWatch* instance)
326{ 328{
327 Client* client = m_clients.first(); 329 Client* client = m_clients.first();
328 for(;client; client = m_clients.next()) 330 for(;client; client = m_clients.next())
329 if (client->instance == instance) break; 331 if (client->instance == instance) break;
330 332
331 if (client) { 333 if (client) {
332 client->count--; 334 client->count--;
333 if (client->count == 0) { 335 if (client->count == 0) {
334 m_clients.removeRef(client); 336 m_clients.removeRef(client);
335 delete client; 337 delete client;
336 } 338 }
337 } 339 }
338} 340}
339 341
340/* get number of clients */ 342/* get number of clients */
341int KDirWatchPrivate::Entry::clients() 343int KDirWatchPrivate::Entry::clients()
342{ 344{
343 int clients = 0; 345 int clients = 0;
344 Client* client = m_clients.first(); 346 Client* client = m_clients.first();
345 for(;client; client = m_clients.next()) 347 for(;client; client = m_clients.next())
346 clients += client->count; 348 clients += client->count;
347 349
348 return clients; 350 return clients;
349} 351}
350 352
351 353
352KDirWatchPrivate::Entry* KDirWatchPrivate::entry(const QString& _path) 354KDirWatchPrivate::Entry* KDirWatchPrivate::entry(const QString& _path)
353{ 355{
354// we only support absolute paths 356// we only support absolute paths
355 if (_path.left(1) != "/") { 357 if (_path.left(1) != "/") {
356 return 0; 358 return 0;
357 } 359 }
358 360
359 QString path = _path; 361 QString path = _path;
360 362
361 if ( path.length() > 1 && path.right(1) == "/" ) 363 if ( path.length() > 1 && path.right(1) == "/" )
362 path.truncate( path.length() - 1 ); 364 path.truncate( path.length() - 1 );
363 365
364 EntryMap::Iterator it = m_mapEntries.find( path ); 366 EntryMap::Iterator it = m_mapEntries.find( path );
365 if ( it == m_mapEntries.end() ) 367 if ( it == m_mapEntries.end() )
366 return 0; 368 return 0;
367 else 369 else
368 return &(*it); 370 return &(*it);
369} 371}
370 372
371// set polling frequency for a entry and adjust global freq if needed 373// set polling frequency for a entry and adjust global freq if needed
372void KDirWatchPrivate::useFreq(Entry* e, int newFreq) 374void KDirWatchPrivate::useFreq(Entry* e, int newFreq)
373{ 375{
374 e->freq = newFreq; 376 e->freq = newFreq;
375 377
376 // a reasonable frequency for the global polling timer 378 // a reasonable frequency for the global polling timer
377 if (e->freq < freq) { 379 if (e->freq < freq) {
378 freq = e->freq; 380 freq = e->freq;
379 if (timer->isActive()) timer->changeInterval(freq); 381 if (timer->isActive()) timer->changeInterval(freq);
380 kdDebug(7001) << "Global Poll Freq is now " << freq << " msec" << endl; 382 kdDebug(7001) << "Global Poll Freq is now " << freq << " msec" << endl;
381 } 383 }
382} 384}
383 385
384 386
385#if defined(HAVE_FAM) 387#if defined(HAVE_FAM)
386// setup FAM notification, returns false if not possible 388// setup FAM notification, returns false if not possible
387bool KDirWatchPrivate::useFAM(Entry* e) 389bool KDirWatchPrivate::useFAM(Entry* e)
388{ 390{
389 if (!use_fam) return false; 391 if (!use_fam) return false;
390 392
391 e->m_mode = FAMMode; 393 e->m_mode = FAMMode;
392 394
393 if (e->isDir) { 395 if (e->isDir) {
394 if (e->m_status == NonExistent) { 396 if (e->m_status == NonExistent) {
395 // If the directory does not exist we watch the parent directory 397 // If the directory does not exist we watch the parent directory
396 addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true); 398 addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
397 } 399 }
398 else { 400 else {
399 int res =FAMMonitorDirectory(&fc, QFile::encodeName(e->path), 401 int res =FAMMonitorDirectory(&fc, QFile::encodeName(e->path),
400 &(e->fr), e); 402 &(e->fr), e);
401 if (res<0) { 403 if (res<0) {
402 e->m_mode = UnknownMode; 404 e->m_mode = UnknownMode;
403 use_fam=false; 405 use_fam=false;
404 return false; 406 return false;
405 } 407 }
406 kdDebug(7001) << " Setup FAM (Req " 408 kdDebug(7001) << " Setup FAM (Req "
407 << FAMREQUEST_GETREQNUM(&(e->fr)) 409 << FAMREQUEST_GETREQNUM(&(e->fr))
408 << ") for " << e->path << endl; 410 << ") for " << e->path << endl;
409 } 411 }
410 } 412 }
411 else { 413 else {
412 if (e->m_status == NonExistent) { 414 if (e->m_status == NonExistent) {
413 // If the file does not exist we watch the directory 415 // If the file does not exist we watch the directory
414 addEntry(0, QFileInfo(e->path).dirPath(true), e, true); 416 addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
415 } 417 }
416 else { 418 else {
417 int res = FAMMonitorFile(&fc, QFile::encodeName(e->path), 419 int res = FAMMonitorFile(&fc, QFile::encodeName(e->path),
418 &(e->fr), e); 420 &(e->fr), e);
419 if (res<0) { 421 if (res<0) {
420 e->m_mode = UnknownMode; 422 e->m_mode = UnknownMode;
421 use_fam=false; 423 use_fam=false;
422 return false; 424 return false;
423 } 425 }
424 426
425 kdDebug(7001) << " Setup FAM (Req " 427 kdDebug(7001) << " Setup FAM (Req "
426 << FAMREQUEST_GETREQNUM(&(e->fr)) 428 << FAMREQUEST_GETREQNUM(&(e->fr))
427 << ") for " << e->path << endl; 429 << ") for " << e->path << endl;
428 } 430 }
429 } 431 }
430 432
431 // handle FAM events to avoid deadlock 433 // handle FAM events to avoid deadlock
432 // (FAM sends back all files in a directory when monitoring) 434 // (FAM sends back all files in a directory when monitoring)
433 famEventReceived(); 435 famEventReceived();
434 436
435 return true; 437 return true;
436} 438}
437#endif 439#endif
438 440
439 441
440#ifdef HAVE_DNOTIFY 442#ifdef HAVE_DNOTIFY
441// setup DNotify notification, returns false if not possible 443// setup DNotify notification, returns false if not possible
442bool KDirWatchPrivate::useDNotify(Entry* e) 444bool KDirWatchPrivate::useDNotify(Entry* e)
443{ 445{
444 e->dn_fd = 0; 446 e->dn_fd = 0;
445 if (!supports_dnotify) return false; 447 if (!supports_dnotify) return false;
446 448
447 e->m_mode = DNotifyMode; 449 e->m_mode = DNotifyMode;
448 450
449 if (e->isDir) { 451 if (e->isDir) {
450 e->dn_dirty = false; 452 e->dn_dirty = false;
451 if (e->m_status == Normal) { 453 if (e->m_status == Normal) {
452 int fd = open(QFile::encodeName(e->path).data(), O_RDONLY); 454 int fd = open(QFile::encodeName(e->path).data(), O_RDONLY);
453 // Migrate fd to somewhere above 128. Some libraries have 455 // Migrate fd to somewhere above 128. Some libraries have
454 // constructs like: 456 // constructs like:
455 // fd = socket(...) 457 // fd = socket(...)
456 // if (fd > ARBITRARY_LIMIT) 458 // if (fd > ARBITRARY_LIMIT)
457 // return error; 459 // return error;
458 // 460 //
459 // Since programs might end up using a lot of KDirWatch objects 461 // Since programs might end up using a lot of KDirWatch objects
460 // for a rather long time the above braindamage could get 462 // for a rather long time the above braindamage could get
461 // triggered. 463 // triggered.
462 // 464 //
463 // By moving the kdirwatch fd's to > 128, calls like socket() will keep 465 // By moving the kdirwatch fd's to > 128, calls like socket() will keep
464 // returning fd's < ARBITRARY_LIMIT for a bit longer. 466 // returning fd's < ARBITRARY_LIMIT for a bit longer.
465 int fd2 = fcntl(fd, F_DUPFD, 128); 467 int fd2 = fcntl(fd, F_DUPFD, 128);
466 if (fd2 >= 0) 468 if (fd2 >= 0)
467 { 469 {
468 close(fd); 470 close(fd);
469 fd = fd2; 471 fd = fd2;
470 } 472 }
471 if (fd<0) { 473 if (fd<0) {
472 e->m_mode = UnknownMode; 474 e->m_mode = UnknownMode;
473 return false; 475 return false;
474 } 476 }
475 477
476 int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT; 478 int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT;
477 // if dependant is a file watch, we check for MODIFY & ATTRIB too 479 // if dependant is a file watch, we check for MODIFY & ATTRIB too
478 for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next()) 480 for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next())
479 if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; } 481 if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; }
480 482
481 if(fcntl(fd, F_SETSIG, dnotify_signal) < 0 || 483 if(fcntl(fd, F_SETSIG, dnotify_signal) < 0 ||
482 fcntl(fd, F_NOTIFY, mask) < 0) { 484 fcntl(fd, F_NOTIFY, mask) < 0) {
483 485
484 kdDebug(7001) << "Not using Linux Directory Notifications." 486 kdDebug(7001) << "Not using Linux Directory Notifications."
485 << endl; 487 << endl;
486 supports_dnotify = false; 488 supports_dnotify = false;
487 ::close(fd); 489 ::close(fd);
488 e->m_mode = UnknownMode; 490 e->m_mode = UnknownMode;
489 return false; 491 return false;
490 } 492 }
491 493
492 fd_Entry.replace(fd, e); 494 fd_Entry.replace(fd, e);
493 e->dn_fd = fd; 495 e->dn_fd = fd;
494 496
495 kdDebug(7001) << " Setup DNotify (fd " << fd 497 kdDebug(7001) << " Setup DNotify (fd " << fd
496 << ") for " << e->path << endl; 498 << ") for " << e->path << endl;
497 } 499 }
498 else { // NotExisting 500 else { // NotExisting
499 addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true); 501 addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
500 } 502 }
501 } 503 }
502 else { // File 504 else { // File
503 // we always watch the directory (DNOTIFY can't watch files alone) 505 // we always watch the directory (DNOTIFY can't watch files alone)
504 // this notifies us about changes of files therein 506 // this notifies us about changes of files therein
505 addEntry(0, QFileInfo(e->path).dirPath(true), e, true); 507 addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
506 } 508 }
507 509
508 return true; 510 return true;
509} 511}
510#endif 512#endif
511 513
512 514
513bool KDirWatchPrivate::useStat(Entry* e) 515bool KDirWatchPrivate::useStat(Entry* e)
514{ 516{
515//US we have no KIO::probably_slow_mounted. So disable this part 517//US we have no KIO::probably_slow_mounted. So disable this part
516//US if (KIO::probably_slow_mounted(e->path)) 518//US if (KIO::probably_slow_mounted(e->path))
517//US useFreq(e, m_nfsPollInterval); 519//US useFreq(e, m_nfsPollInterval);
518//US else 520//US else
519 useFreq(e, m_PollInterval); 521 useFreq(e, m_PollInterval);
520 522
521 if (e->m_mode != StatMode) { 523 if (e->m_mode != StatMode) {
522 e->m_mode = StatMode; 524 e->m_mode = StatMode;
523 statEntries++; 525 statEntries++;
524 526
525 if ( statEntries == 1 ) { 527 if ( statEntries == 1 ) {
526 // if this was first STAT entry (=timer was stopped) 528 // if this was first STAT entry (=timer was stopped)
527 timer->start(freq); // then start the timer 529 timer->start(freq); // then start the timer
528 kdDebug(7001) << " Started Polling Timer, freq " << freq << endl; 530 kdDebug(7001) << " Started Polling Timer, freq " << freq << endl;
529 } 531 }
530 } 532 }
531 533
532 kdDebug(7001) << " Setup Stat (freq " << e->freq 534 kdDebug(7001) << " Setup Stat (freq " << e->freq
533 << ") for " << e->path << endl; 535 << ") for " << e->path << endl;
534 536
535 return true; 537 return true;
536} 538}
537 539
538 540
539/* If <instance> !=0, this KDirWatch instance wants to watch at <_path>, 541/* If <instance> !=0, this KDirWatch instance wants to watch at <_path>,
540 * providing in <isDir> the type of the entry to be watched. 542 * providing in <isDir> the type of the entry to be watched.
541 * Sometimes, entries are dependant on each other: if <sub_entry> !=0, 543 * Sometimes, entries are dependant on each other: if <sub_entry> !=0,
542 * this entry needs another entry to watch himself (when notExistent). 544 * this entry needs another entry to watch himself (when notExistent).
543 */ 545 */
544void KDirWatchPrivate::addEntry(KDirWatch* instance, const QString& _path, 546void KDirWatchPrivate::addEntry(KDirWatch* instance, const QString& _path,
545 Entry* sub_entry, bool isDir) 547 Entry* sub_entry, bool isDir)
546{ 548{
547 QString path = _path; 549 QString path = _path;
548 if (path.startsWith("/dev/") || (path == "/dev")) 550 if (path.startsWith("/dev/") || (path == "/dev"))
549 return; // Don't even go there. 551 return; // Don't even go there.
550 552
551 if ( path.length() > 1 && path.right(1) == "/" ) 553 if ( path.length() > 1 && path.right(1) == "/" )
552 path.truncate( path.length() - 1 ); 554 path.truncate( path.length() - 1 );
553 555
554 EntryMap::Iterator it = m_mapEntries.find( path ); 556 EntryMap::Iterator it = m_mapEntries.find( path );
555 if ( it != m_mapEntries.end() ) 557 if ( it != m_mapEntries.end() )
556 { 558 {
557 if (sub_entry) { 559 if (sub_entry) {
558 (*it).m_entries.append(sub_entry); 560 (*it).m_entries.append(sub_entry);
559 kdDebug(7001) << "Added already watched Entry " << path 561 kdDebug(7001) << "Added already watched Entry " << path
560 << " (for " << sub_entry->path << ")" << endl; 562 << " (for " << sub_entry->path << ")" << endl;
561#ifdef HAVE_DNOTIFY 563#ifdef HAVE_DNOTIFY
562 Entry* e = &(*it); 564 Entry* e = &(*it);
563 if( e->dn_fd > 0 ) { 565 if( e->dn_fd > 0 ) {
564 int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT; 566 int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT;
565 // if dependant is a file watch, we check for MODIFY & ATTRIB too 567 // if dependant is a file watch, we check for MODIFY & ATTRIB too
566 for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next()) 568 for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next())
567 if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; } 569 if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; }
568 if( fcntl(e->dn_fd, F_NOTIFY, mask) < 0) { // shouldn't happen 570 if( fcntl(e->dn_fd, F_NOTIFY, mask) < 0) { // shouldn't happen
569 ::close(e->dn_fd); 571 ::close(e->dn_fd);
570 e->m_mode = UnknownMode; 572 e->m_mode = UnknownMode;
571 fd_Entry.remove(e->dn_fd); 573 fd_Entry.remove(e->dn_fd);
572 e->dn_fd = 0; 574 e->dn_fd = 0;
573 useStat( e ); 575 useStat( e );
574 } 576 }
575 } 577 }
576#endif 578#endif
577 } 579 }
578 else { 580 else {
579 (*it).addClient(instance); 581 (*it).addClient(instance);
580 kdDebug(7001) << "Added already watched Entry " << path 582 kdDebug(7001) << "Added already watched Entry " << path
581 << " (now " << (*it).clients() << " clients)" 583 << " (now " << (*it).clients() << " clients)"
582 << QString(" [%1]").arg(instance->name()) << endl; 584 << QString(" [%1]").arg(instance->name()) << endl;
583 } 585 }
584 return; 586 return;
585 } 587 }
586 588
587 // we have a new path to watch 589 // we have a new path to watch
588 590
589 struct stat stat_buf; 591 struct stat stat_buf;
590 bool exists = (stat(QFile::encodeName(path), &stat_buf) == 0); 592 bool exists = (stat(QFile::encodeName(path), &stat_buf) == 0);
591 593
592 Entry newEntry; 594 Entry newEntry;
593 m_mapEntries.insert( path, newEntry ); 595 m_mapEntries.insert( path, newEntry );
594 // the insert does a copy, so we have to use <e> now 596 // the insert does a copy, so we have to use <e> now
595 Entry* e = &(m_mapEntries[path]); 597 Entry* e = &(m_mapEntries[path]);
596 598
597 if (exists) { 599 if (exists) {
598 QFileInfo fi ( path ); 600 QFileInfo fi ( path );
599 e->isDir = fi.isDir(); 601 e->isDir = fi.isDir();
600 602
601 if (e->isDir && !isDir) 603 if (e->isDir && !isDir)
602 qWarning("KDirWatch: %s is a directory. Use addDir!", path.ascii()); 604 qWarning("KDirWatch: %s is a directory. Use addDir!", path.ascii());
603 else if (!e->isDir && isDir) 605 else if (!e->isDir && isDir)
604 qWarning("KDirWatch: %s is a file. Use addFile!", path.ascii()); 606 qWarning("KDirWatch: %s is a file. Use addFile!", path.ascii());
605 607
606 e->m_ctime = stat_buf.st_ctime; 608 e->m_ctime = stat_buf.st_ctime;
607 e->m_status = Normal; 609 e->m_status = Normal;
608 e->m_nlink = stat_buf.st_nlink; 610 e->m_nlink = stat_buf.st_nlink;
609 } 611 }
610 else { 612 else {
611 e->isDir = isDir; 613 e->isDir = isDir;
612 e->m_ctime = invalid_ctime; 614 e->m_ctime = invalid_ctime;
613 e->m_status = NonExistent; 615 e->m_status = NonExistent;
614 e->m_nlink = 0; 616 e->m_nlink = 0;
615 } 617 }
616 618
617 e->path = path; 619 e->path = path;
618 if (sub_entry) 620 if (sub_entry)
619 e->m_entries.append(sub_entry); 621 e->m_entries.append(sub_entry);
620 else 622 else
621 e->addClient(instance); 623 e->addClient(instance);
622 624
623 kdDebug(7001) << "Added " << (e->isDir ? "Dir ":"File ") << path 625 kdDebug(7001) << "Added " << (e->isDir ? "Dir ":"File ") << path
624 << (e->m_status == NonExistent ? " NotExisting" : "") 626 << (e->m_status == NonExistent ? " NotExisting" : "")
625 << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString("")) 627 << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString(""))
626 << (instance ? QString(" [%1]").arg(instance->name()) : QString("")) 628 << (instance ? QString(" [%1]").arg(instance->name()) : QString(""))
627 << endl; 629 << endl;
628 630
629 631
630 // now setup the notification method 632 // now setup the notification method
631 e->m_mode = UnknownMode; 633 e->m_mode = UnknownMode;
632 e->msecLeft = 0; 634 e->msecLeft = 0;
633 635
634#if defined(HAVE_FAM) 636#if defined(HAVE_FAM)
635 if (useFAM(e)) return; 637 if (useFAM(e)) return;
636#endif 638#endif
637 639
638#ifdef HAVE_DNOTIFY 640#ifdef HAVE_DNOTIFY
639 if (useDNotify(e)) return; 641 if (useDNotify(e)) return;
640#endif 642#endif
641 643
642 useStat(e); 644 useStat(e);
643} 645}
644 646
645 647
646void KDirWatchPrivate::removeEntry( KDirWatch* instance, 648void KDirWatchPrivate::removeEntry( KDirWatch* instance,
647 const QString& _path, Entry* sub_entry ) 649 const QString& _path, Entry* sub_entry )
648{ 650{
649 Entry* e = entry(_path); 651 Entry* e = entry(_path);
650 if (!e) { 652 if (!e) {
651 kdWarning(7001) << "KDirWatch::removeDir can't handle '" << _path << "'" << endl; 653 kdWarning(7001) << "KDirWatch::removeDir can't handle '" << _path << "'" << endl;
652 return; 654 return;
653 } 655 }
654 656
655 if (sub_entry) 657 if (sub_entry)
656 e->m_entries.removeRef(sub_entry); 658 e->m_entries.removeRef(sub_entry);
657 else 659 else
658 e->removeClient(instance); 660 e->removeClient(instance);
659 661
660 if (e->m_clients.count() || e->m_entries.count()) 662 if (e->m_clients.count() || e->m_entries.count())
661 return; 663 return;
662 664
663 if (delayRemove) { 665 if (delayRemove) {
664 // removeList is allowed to contain any entry at most once 666 // removeList is allowed to contain any entry at most once
665 if (removeList.findRef(e)==-1) 667 if (removeList.findRef(e)==-1)
666 removeList.append(e); 668 removeList.append(e);
667 // now e->isValid() is false 669 // now e->isValid() is false
668 return; 670 return;
669 } 671 }
670 672
671#ifdef HAVE_FAM 673#ifdef HAVE_FAM
672 if (e->m_mode == FAMMode) { 674 if (e->m_mode == FAMMode) {
673 if ( e->m_status == Normal) { 675 if ( e->m_status == Normal) {
674 FAMCancelMonitor(&fc, &(e->fr) ); 676 FAMCancelMonitor(&fc, &(e->fr) );
675 kdDebug(7001) << "Cancelled FAM (Req " 677 kdDebug(7001) << "Cancelled FAM (Req "
676 << FAMREQUEST_GETREQNUM(&(e->fr)) 678 << FAMREQUEST_GETREQNUM(&(e->fr))
677 << ") for " << e->path << endl; 679 << ") for " << e->path << endl;
678 } 680 }
679 else { 681 else {
680 if (e->isDir) 682 if (e->isDir)
681 removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e); 683 removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e);
682 else 684 else
683 removeEntry(0, QFileInfo(e->path).dirPath(true), e); 685 removeEntry(0, QFileInfo(e->path).dirPath(true), e);
684 } 686 }
685 } 687 }
686#endif 688#endif
687 689
688#ifdef HAVE_DNOTIFY 690#ifdef HAVE_DNOTIFY
689 if (e->m_mode == DNotifyMode) { 691 if (e->m_mode == DNotifyMode) {
690 if (!e->isDir) { 692 if (!e->isDir) {
691 removeEntry(0, QFileInfo(e->path).dirPath(true), e); 693 removeEntry(0, QFileInfo(e->path).dirPath(true), e);
692 } 694 }
693 else { // isDir 695 else { // isDir
694 // must close the FD. 696 // must close the FD.
695 if ( e->m_status == Normal) { 697 if ( e->m_status == Normal) {
696 if (e->dn_fd) { 698 if (e->dn_fd) {
697 ::close(e->dn_fd); 699 ::close(e->dn_fd);
698 fd_Entry.remove(e->dn_fd); 700 fd_Entry.remove(e->dn_fd);
699 701
700 kdDebug(7001) << "Cancelled DNotify (fd " << e->dn_fd 702 kdDebug(7001) << "Cancelled DNotify (fd " << e->dn_fd
701 << ") for " << e->path << endl; 703 << ") for " << e->path << endl;
702 e->dn_fd = 0; 704 e->dn_fd = 0;
703 705
704 } 706 }
705 } 707 }
706 else { 708 else {
707 removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e); 709 removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e);
708 } 710 }
709 } 711 }
710 } 712 }
711#endif 713#endif
712 714
713 if (e->m_mode == StatMode) { 715 if (e->m_mode == StatMode) {
714 statEntries--; 716 statEntries--;
715 if ( statEntries == 0 ) { 717 if ( statEntries == 0 ) {
716 timer->stop(); // stop timer if lists are empty 718 timer->stop(); // stop timer if lists are empty
717 kdDebug(7001) << " Stopped Polling Timer" << endl; 719 kdDebug(7001) << " Stopped Polling Timer" << endl;
718 } 720 }
719 } 721 }
720 722
721 kdDebug(7001) << "Removed " << (e->isDir ? "Dir ":"File ") << e->path 723 kdDebug(7001) << "Removed " << (e->isDir ? "Dir ":"File ") << e->path
722 << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString("")) 724 << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString(""))
723 << (instance ? QString(" [%1]").arg(instance->name()) : QString("")) 725 << (instance ? QString(" [%1]").arg(instance->name()) : QString(""))
724 << endl; 726 << endl;
725 m_mapEntries.remove( e->path ); // <e> not valid any more 727 m_mapEntries.remove( e->path ); // <e> not valid any more
726} 728}
727 729
728 730
729/* Called from KDirWatch destructor: 731/* Called from KDirWatch destructor:
730 * remove <instance> as client from all entries 732 * remove <instance> as client from all entries
731 */ 733 */
732void KDirWatchPrivate::removeEntries( KDirWatch* instance ) 734void KDirWatchPrivate::removeEntries( KDirWatch* instance )
733{ 735{
734 QPtrList<Entry> list; 736 Q3PtrList<Entry> list;
735 int minfreq = 3600000; 737 int minfreq = 3600000;
736 738
737 // put all entries where instance is a client in list 739 // put all entries where instance is a client in list
738 EntryMap::Iterator it = m_mapEntries.begin(); 740 EntryMap::Iterator it = m_mapEntries.begin();
739 for( ; it != m_mapEntries.end(); ++it ) { 741 for( ; it != m_mapEntries.end(); ++it ) {
740 Client* c = (*it).m_clients.first(); 742 Client* c = (*it).m_clients.first();
741 for(;c;c=(*it).m_clients.next()) 743 for(;c;c=(*it).m_clients.next())
742 if (c->instance == instance) break; 744 if (c->instance == instance) break;
743 if (c) { 745 if (c) {
744 c->count = 1; // forces deletion of instance as client 746 c->count = 1; // forces deletion of instance as client
745 list.append(&(*it)); 747 list.append(&(*it));
746 } 748 }
747 else if ( (*it).m_mode == StatMode && (*it).freq < minfreq ) 749 else if ( (*it).m_mode == StatMode && (*it).freq < minfreq )
748 minfreq = (*it).freq; 750 minfreq = (*it).freq;
749 } 751 }
750 752
751 for(Entry* e=list.first();e;e=list.next()) 753 for(Entry* e=list.first();e;e=list.next())
752 removeEntry(instance, e->path, 0); 754 removeEntry(instance, e->path, 0);
753 755
754 if (minfreq > freq) { 756 if (minfreq > freq) {
755 // we can decrease the global polling frequency 757 // we can decrease the global polling frequency
756 freq = minfreq; 758 freq = minfreq;
757 if (timer->isActive()) timer->changeInterval(freq); 759 if (timer->isActive()) timer->changeInterval(freq);
758 kdDebug(7001) << "Poll Freq now " << freq << " msec" << endl; 760 kdDebug(7001) << "Poll Freq now " << freq << " msec" << endl;
759 } 761 }
760} 762}
761 763
762// instance ==0: stop scanning for all instances 764// instance ==0: stop scanning for all instances
763bool KDirWatchPrivate::stopEntryScan( KDirWatch* instance, Entry* e) 765bool KDirWatchPrivate::stopEntryScan( KDirWatch* instance, Entry* e)
764{ 766{
765 int stillWatching = 0; 767 int stillWatching = 0;
766 Client* c = e->m_clients.first(); 768 Client* c = e->m_clients.first();
767 for(;c;c=e->m_clients.next()) { 769 for(;c;c=e->m_clients.next()) {
768 if (!instance || instance == c->instance) 770 if (!instance || instance == c->instance)
769 c->watchingStopped = true; 771 c->watchingStopped = true;
770 else if (!c->watchingStopped) 772 else if (!c->watchingStopped)
771 stillWatching += c->count; 773 stillWatching += c->count;
772 } 774 }
773 775
774 kdDebug(7001) << instance->name() << " stopped scanning " << e->path 776 kdDebug(7001) << instance->name() << " stopped scanning " << e->path
775 << " (now " << stillWatching << " watchers)" << endl; 777 << " (now " << stillWatching << " watchers)" << endl;
776 778
777 if (stillWatching == 0) { 779 if (stillWatching == 0) {
778 // if nobody is interested, we don't watch 780 // if nobody is interested, we don't watch
779 e->m_ctime = invalid_ctime; // invalid 781 e->m_ctime = invalid_ctime; // invalid
780 // e->m_status = Normal; 782 // e->m_status = Normal;
781 } 783 }
782 return true; 784 return true;
783} 785}
784 786
785// instance ==0: start scanning for all instances 787// instance ==0: start scanning for all instances
786bool KDirWatchPrivate::restartEntryScan( KDirWatch* instance, Entry* e, 788bool KDirWatchPrivate::restartEntryScan( KDirWatch* instance, Entry* e,
787 bool notify) 789 bool notify)
788{ 790{
789 int wasWatching = 0, newWatching = 0; 791 int wasWatching = 0, newWatching = 0;
790 Client* c = e->m_clients.first(); 792 Client* c = e->m_clients.first();
791 for(;c;c=e->m_clients.next()) { 793 for(;c;c=e->m_clients.next()) {
792 if (!c->watchingStopped) 794 if (!c->watchingStopped)
793 wasWatching += c->count; 795 wasWatching += c->count;
794 else if (!instance || instance == c->instance) { 796 else if (!instance || instance == c->instance) {
795 c->watchingStopped = false; 797 c->watchingStopped = false;
796 newWatching += c->count; 798 newWatching += c->count;
797 } 799 }
798 } 800 }
799 if (newWatching == 0) 801 if (newWatching == 0)
800 return false; 802 return false;
801 803
802 kdDebug(7001) << instance->name() << " restarted scanning " << e->path 804 kdDebug(7001) << instance->name() << " restarted scanning " << e->path
803 << " (now " << wasWatching+newWatching << " watchers)" << endl; 805 << " (now " << wasWatching+newWatching << " watchers)" << endl;
804 806
805 // restart watching and emit pending events 807 // restart watching and emit pending events
806 808
807 int ev = NoChange; 809 int ev = NoChange;
808 if (wasWatching == 0) { 810 if (wasWatching == 0) {
809 if (!notify) { 811 if (!notify) {
810 struct stat stat_buf; 812 struct stat stat_buf;
811 bool exists = (stat(QFile::encodeName(e->path), &stat_buf) == 0); 813 bool exists = (stat(QFile::encodeName(e->path), &stat_buf) == 0);
812 if (exists) { 814 if (exists) {
813 e->m_ctime = stat_buf.st_ctime; 815 e->m_ctime = stat_buf.st_ctime;
814 e->m_status = Normal; 816 e->m_status = Normal;
815 e->m_nlink = stat_buf.st_nlink; 817 e->m_nlink = stat_buf.st_nlink;
816 } 818 }
817 else { 819 else {
818 e->m_ctime = invalid_ctime; 820 e->m_ctime = invalid_ctime;
819 e->m_status = NonExistent; 821 e->m_status = NonExistent;
820 e->m_nlink = 0; 822 e->m_nlink = 0;
821 } 823 }
822 } 824 }
823 e->msecLeft = 0; 825 e->msecLeft = 0;
824 ev = scanEntry(e); 826 ev = scanEntry(e);
825 } 827 }
826 emitEvent(e,ev); 828 emitEvent(e,ev);
827 829
828 return true; 830 return true;
829} 831}
830 832
831// instance ==0: stop scanning for all instances 833// instance ==0: stop scanning for all instances
832void KDirWatchPrivate::stopScan(KDirWatch* instance) 834void KDirWatchPrivate::stopScan(KDirWatch* instance)
833{ 835{
834 EntryMap::Iterator it = m_mapEntries.begin(); 836 EntryMap::Iterator it = m_mapEntries.begin();
835 for( ; it != m_mapEntries.end(); ++it ) 837 for( ; it != m_mapEntries.end(); ++it )
836 stopEntryScan(instance, &(*it)); 838 stopEntryScan(instance, &(*it));
837} 839}
838 840
839 841
840void KDirWatchPrivate::startScan(KDirWatch* instance, 842void KDirWatchPrivate::startScan(KDirWatch* instance,
841 bool notify, bool skippedToo ) 843 bool notify, bool skippedToo )
842{ 844{
843 if (!notify) 845 if (!notify)
844 resetList(instance,skippedToo); 846 resetList(instance,skippedToo);
845 847
846 EntryMap::Iterator it = m_mapEntries.begin(); 848 EntryMap::Iterator it = m_mapEntries.begin();
847 for( ; it != m_mapEntries.end(); ++it ) 849 for( ; it != m_mapEntries.end(); ++it )
848 restartEntryScan(instance, &(*it), notify); 850 restartEntryScan(instance, &(*it), notify);
849 851
850 // timer should still be running when in polling mode 852 // timer should still be running when in polling mode
851} 853}
852 854
853 855
854// clear all pending events, also from stopped 856// clear all pending events, also from stopped
855void KDirWatchPrivate::resetList( KDirWatch* /*instance*/, 857void KDirWatchPrivate::resetList( KDirWatch* /*instance*/,
856 bool skippedToo ) 858 bool skippedToo )
857{ 859{
858 EntryMap::Iterator it = m_mapEntries.begin(); 860 EntryMap::Iterator it = m_mapEntries.begin();
859 for( ; it != m_mapEntries.end(); ++it ) { 861 for( ; it != m_mapEntries.end(); ++it ) {
860 862
861 Client* c = (*it).m_clients.first(); 863 Client* c = (*it).m_clients.first();
862 for(;c;c=(*it).m_clients.next()) 864 for(;c;c=(*it).m_clients.next())
863 if (!c->watchingStopped || skippedToo) 865 if (!c->watchingStopped || skippedToo)
864 c->pending = NoChange; 866 c->pending = NoChange;
865 } 867 }
866} 868}
867 869
868// Return event happened on <e> 870// Return event happened on <e>
869// 871//
870int KDirWatchPrivate::scanEntry(Entry* e) 872int KDirWatchPrivate::scanEntry(Entry* e)
871{ 873{
872#ifdef HAVE_FAM 874#ifdef HAVE_FAM
873 // we do not stat entries using FAM 875 // we do not stat entries using FAM
874 if (e->m_mode == FAMMode) return NoChange; 876 if (e->m_mode == FAMMode) return NoChange;
875#endif 877#endif
876 878
877 // Shouldn't happen: Ignore "unknown" notification method 879 // Shouldn't happen: Ignore "unknown" notification method
878 if (e->m_mode == UnknownMode) return NoChange; 880 if (e->m_mode == UnknownMode) return NoChange;
879 881
880#ifdef HAVE_DNOTIFY 882#ifdef HAVE_DNOTIFY
881 if (e->m_mode == DNotifyMode) { 883 if (e->m_mode == DNotifyMode) {
882 // we know nothing has changed, no need to stat 884 // we know nothing has changed, no need to stat
883 if(!e->dn_dirty) return NoChange; 885 if(!e->dn_dirty) return NoChange;
884 e->dn_dirty = false; 886 e->dn_dirty = false;
885 } 887 }
886#endif 888#endif
887 889
888 if (e->m_mode == StatMode) { 890 if (e->m_mode == StatMode) {
889 // only scan if timeout on entry timer happens; 891 // only scan if timeout on entry timer happens;
890 // e.g. when using 500msec global timer, a entry 892 // e.g. when using 500msec global timer, a entry
891 // with freq=5000 is only watched every 10th time 893 // with freq=5000 is only watched every 10th time
892 894
893 e->msecLeft -= freq; 895 e->msecLeft -= freq;
894 if (e->msecLeft>0) return NoChange; 896 if (e->msecLeft>0) return NoChange;
895 e->msecLeft += e->freq; 897 e->msecLeft += e->freq;
896 } 898 }
897 899
898 struct stat stat_buf; 900 struct stat stat_buf;
899 bool exists = (stat(QFile::encodeName(e->path), &stat_buf) == 0); 901 bool exists = (stat(QFile::encodeName(e->path), &stat_buf) == 0);
900 if (exists) { 902 if (exists) {
901 903
902 if (e->m_status == NonExistent) { 904 if (e->m_status == NonExistent) {
903 e->m_ctime = stat_buf.st_ctime; 905 e->m_ctime = stat_buf.st_ctime;
904 e->m_status = Normal; 906 e->m_status = Normal;
905 e->m_nlink = stat_buf.st_nlink; 907 e->m_nlink = stat_buf.st_nlink;
906 return Created; 908 return Created;
907 } 909 }
908 910
909 if ( (e->m_ctime != invalid_ctime) && 911 if ( (e->m_ctime != invalid_ctime) &&
910 ((stat_buf.st_ctime != e->m_ctime) || 912 ((stat_buf.st_ctime != e->m_ctime) ||
911 // (stat_buf.st_nlink != (nlink_t) e->m_nlink)) ) { 913 // (stat_buf.st_nlink != (nlink_t) e->m_nlink)) ) {
912 (stat_buf.st_nlink != e->m_nlink)) ) { 914 (stat_buf.st_nlink != e->m_nlink)) ) {
913 e->m_ctime = stat_buf.st_ctime; 915 e->m_ctime = stat_buf.st_ctime;
914 e->m_nlink = stat_buf.st_nlink; 916 e->m_nlink = stat_buf.st_nlink;
915 return Changed; 917 return Changed;
916 } 918 }
917 919
918 return NoChange; 920 return NoChange;
919 } 921 }
920 922
921 // dir/file doesn't exist 923 // dir/file doesn't exist
922 924
923 if (e->m_ctime == invalid_ctime) 925 if (e->m_ctime == invalid_ctime)
924 return NoChange; 926 return NoChange;
925 927
926 e->m_ctime = invalid_ctime; 928 e->m_ctime = invalid_ctime;
927 e->m_nlink = 0; 929 e->m_nlink = 0;
928 e->m_status = NonExistent; 930 e->m_status = NonExistent;
929 931
930 return Deleted; 932 return Deleted;
931} 933}
932 934
933/* Notify all interested KDirWatch instances about a given event on an entry 935/* Notify all interested KDirWatch instances about a given event on an entry
934 * and stored pending events. When watching is stopped, the event is 936 * and stored pending events. When watching is stopped, the event is
935 * added to the pending events. 937 * added to the pending events.
936 */ 938 */
937void KDirWatchPrivate::emitEvent(Entry* e, int event, const QString &fileName) 939void KDirWatchPrivate::emitEvent(Entry* e, int event, const QString &fileName)
938{ 940{
939 QString path = e->path; 941 QString path = e->path;
940 if (!fileName.isEmpty()) { 942 if (!fileName.isEmpty()) {
941 if (fileName[0] == '/') 943 if (fileName[0] == '/')
942 path = fileName; 944 path = fileName;
943 else 945 else
944 path += "/" + fileName; 946 path += "/" + fileName;
945 } 947 }
946 948
947 Client* c = e->m_clients.first(); 949 Client* c = e->m_clients.first();
948 for(;c;c=e->m_clients.next()) { 950 for(;c;c=e->m_clients.next()) {
949 if (c->instance==0 || c->count==0) continue; 951 if (c->instance==0 || c->count==0) continue;
950 952
951 if (c->watchingStopped) { 953 if (c->watchingStopped) {
952 // add event to pending... 954 // add event to pending...
953 if (event == Changed) 955 if (event == Changed)
954 c->pending |= event; 956 c->pending |= event;
955 else if (event == Created || event == Deleted) 957 else if (event == Created || event == Deleted)
956 c->pending = event; 958 c->pending = event;
957 continue; 959 continue;
958 } 960 }
959 // not stopped 961 // not stopped
960 if (event == NoChange || event == Changed) 962 if (event == NoChange || event == Changed)
961 event |= c->pending; 963 event |= c->pending;
962 c->pending = NoChange; 964 c->pending = NoChange;
963 if (event == NoChange) continue; 965 if (event == NoChange) continue;
964 966
965 if (event & Deleted) { 967 if (event & Deleted) {
966 c->instance->setDeleted(path); 968 c->instance->setDeleted(path);
967 // emit only Deleted event... 969 // emit only Deleted event...
968 continue; 970 continue;
969 } 971 }
970 972
971 if (event & Created) { 973 if (event & Created) {
972 c->instance->setCreated(path); 974 c->instance->setCreated(path);
973 // possible emit Change event after creation 975 // possible emit Change event after creation
974 } 976 }
975 977
976 if (event & Changed) 978 if (event & Changed)
977 c->instance->setDirty(path); 979 c->instance->setDirty(path);
978 } 980 }
979} 981}
980 982
981// Remove entries which were marked to be removed 983// Remove entries which were marked to be removed
982void KDirWatchPrivate::slotRemoveDelayed() 984void KDirWatchPrivate::slotRemoveDelayed()
983{ 985{
984 Entry* e; 986 Entry* e;
985 delayRemove = false; 987 delayRemove = false;
986 for(e=removeList.first();e;e=removeList.next()) 988 for(e=removeList.first();e;e=removeList.next())
987 removeEntry(0, e->path, 0); 989 removeEntry(0, e->path, 0);
988 removeList.clear(); 990 removeList.clear();
989} 991}
990 992
991/* Scan all entries to be watched for changes. This is done regularly 993/* Scan all entries to be watched for changes. This is done regularly
992 * when polling and once after a DNOTIFY signal. This is NOT used by FAM. 994 * when polling and once after a DNOTIFY signal. This is NOT used by FAM.
993 */ 995 */
994void KDirWatchPrivate::slotRescan() 996void KDirWatchPrivate::slotRescan()
995{ 997{
996 EntryMap::Iterator it; 998 EntryMap::Iterator it;
997 999
998 // People can do very long things in the slot connected to dirty(), 1000 // People can do very long things in the slot connected to dirty(),
999 // like showing a message box. We don't want to keep polling during 1001 // like showing a message box. We don't want to keep polling during
1000 // that time, otherwise the value of 'delayRemove' will be reset. 1002 // that time, otherwise the value of 'delayRemove' will be reset.
1001 bool timerRunning = timer->isActive(); 1003 bool timerRunning = timer->isActive();
1002 if ( timerRunning ) 1004 if ( timerRunning )
1003 timer->stop(); 1005 timer->stop();
1004 1006
1005 // We delay deletions of entries this way. 1007 // We delay deletions of entries this way.
1006 // removeDir(), when called in slotDirty(), can cause a crash otherwise 1008 // removeDir(), when called in slotDirty(), can cause a crash otherwise
1007 delayRemove = true; 1009 delayRemove = true;
1008 1010
1009#ifdef HAVE_DNOTIFY 1011#ifdef HAVE_DNOTIFY
1010 QPtrList<Entry> dList, cList; 1012 Q3PtrList<Entry> dList, cList;
1011 1013
1012 // for DNotify method, 1014 // for DNotify method,
1013 if (rescan_all) 1015 if (rescan_all)
1014 { 1016 {
1015 // mark all as dirty 1017 // mark all as dirty
1016 it = m_mapEntries.begin(); 1018 it = m_mapEntries.begin();
1017 for( ; it != m_mapEntries.end(); ++it ) 1019 for( ; it != m_mapEntries.end(); ++it )
1018 (*it).dn_dirty = true; 1020 (*it).dn_dirty = true;
1019 rescan_all = false; 1021 rescan_all = false;
1020 } 1022 }
1021 else 1023 else
1022 { 1024 {
1023 // progate dirty flag to dependant entries (e.g. file watches) 1025 // progate dirty flag to dependant entries (e.g. file watches)
1024 it = m_mapEntries.begin(); 1026 it = m_mapEntries.begin();
1025 for( ; it != m_mapEntries.end(); ++it ) 1027 for( ; it != m_mapEntries.end(); ++it )
1026 if ( ((*it).m_mode == DNotifyMode) && (*it).dn_dirty ) 1028 if ( ((*it).m_mode == DNotifyMode) && (*it).dn_dirty )
1027 (*it).propagate_dirty(); 1029 (*it).propagate_dirty();
1028 } 1030 }
1029 1031
1030#endif 1032#endif
1031 1033
1032 it = m_mapEntries.begin(); 1034 it = m_mapEntries.begin();
1033 for( ; it != m_mapEntries.end(); ++it ) { 1035 for( ; it != m_mapEntries.end(); ++it ) {
1034 // we don't check invalid entries (i.e. remove delayed) 1036 // we don't check invalid entries (i.e. remove delayed)
1035 if (!(*it).isValid()) continue; 1037 if (!(*it).isValid()) continue;
1036 1038
1037 int ev = scanEntry( &(*it) ); 1039 int ev = scanEntry( &(*it) );
1038 1040
1039#ifdef HAVE_DNOTIFY 1041#ifdef HAVE_DNOTIFY
1040 if ((*it).m_mode == DNotifyMode) { 1042 if ((*it).m_mode == DNotifyMode) {
1041 if ((*it).isDir && (ev == Deleted)) { 1043 if ((*it).isDir && (ev == Deleted)) {
1042 dList.append( &(*it) ); 1044 dList.append( &(*it) );
1043 1045
1044 // must close the FD. 1046 // must close the FD.
1045 if ((*it).dn_fd) { 1047 if ((*it).dn_fd) {
1046 ::close((*it).dn_fd); 1048 ::close((*it).dn_fd);
1047 fd_Entry.remove((*it).dn_fd); 1049 fd_Entry.remove((*it).dn_fd);
1048 (*it).dn_fd = 0; 1050 (*it).dn_fd = 0;
1049 } 1051 }
1050 } 1052 }
1051 1053
1052 else if ((*it).isDir && (ev == Created)) { 1054 else if ((*it).isDir && (ev == Created)) {
1053 // For created, but yet without DNOTIFYing ... 1055 // For created, but yet without DNOTIFYing ...
1054 if ( (*it).dn_fd == 0) { 1056 if ( (*it).dn_fd == 0) {
1055 cList.append( &(*it) ); 1057 cList.append( &(*it) );
1056 if (! useDNotify( &(*it) )) { 1058 if (! useDNotify( &(*it) )) {
1057 // if DNotify setup fails... 1059 // if DNotify setup fails...
1058 useStat( &(*it) ); 1060 useStat( &(*it) );
1059 } 1061 }
1060 } 1062 }
1061 } 1063 }
1062 } 1064 }
1063#endif 1065#endif
1064 1066
1065 if ( ev != NoChange ) 1067 if ( ev != NoChange )
1066 emitEvent( &(*it), ev); 1068 emitEvent( &(*it), ev);
1067 } 1069 }
1068 1070
1069 1071
1070#ifdef HAVE_DNOTIFY 1072#ifdef HAVE_DNOTIFY
1071 // Scan parent of deleted directories for new creation 1073 // Scan parent of deleted directories for new creation
1072 Entry* e; 1074 Entry* e;
1073 for(e=dList.first();e;e=dList.next()) 1075 for(e=dList.first();e;e=dList.next())
1074 addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true); 1076 addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
1075 1077
1076 // Remove watch of parent of new created directories 1078 // Remove watch of parent of new created directories
1077 for(e=cList.first();e;e=cList.next()) 1079 for(e=cList.first();e;e=cList.next())
1078 removeEntry(0, QDir::cleanDirPath( e->path+"/.."), e); 1080 removeEntry(0, QDir::cleanDirPath( e->path+"/.."), e);
1079#endif 1081#endif
1080 1082
1081 if ( timerRunning ) 1083 if ( timerRunning )
1082 timer->start(freq); 1084 timer->start(freq);
1083 1085
1084 QTimer::singleShot(0, this, SLOT(slotRemoveDelayed())); 1086 QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
1085} 1087}
1086 1088
1087#ifdef HAVE_FAM 1089#ifdef HAVE_FAM
1088void KDirWatchPrivate::famEventReceived() 1090void KDirWatchPrivate::famEventReceived()
1089{ 1091{
1090 static FAMEvent fe; 1092 static FAMEvent fe;
1091 1093
1092 delayRemove = true; 1094 delayRemove = true;
1093 1095
1094 while(use_fam && FAMPending(&fc)) { 1096 while(use_fam && FAMPending(&fc)) {
1095 if (FAMNextEvent(&fc, &fe) == -1) { 1097 if (FAMNextEvent(&fc, &fe) == -1) {
1096 kdWarning(7001) << "FAM connection problem, switching to polling." 1098 kdWarning(7001) << "FAM connection problem, switching to polling."
1097 << endl; 1099 << endl;
1098 use_fam = false; 1100 use_fam = false;
1099 delete sn; sn = 0; 1101 delete sn; sn = 0;
1100 1102
1101 // Replace all FAMMode entries with DNotify/Stat 1103 // Replace all FAMMode entries with DNotify/Stat
1102 EntryMap::Iterator it; 1104 EntryMap::Iterator it;
1103 it = m_mapEntries.begin(); 1105 it = m_mapEntries.begin();
1104 for( ; it != m_mapEntries.end(); ++it ) 1106 for( ; it != m_mapEntries.end(); ++it )
1105 if ((*it).m_mode == FAMMode && (*it).m_clients.count()>0) { 1107 if ((*it).m_mode == FAMMode && (*it).m_clients.count()>0) {
1106#ifdef HAVE_DNOTIFY 1108#ifdef HAVE_DNOTIFY
1107 if (useDNotify( &(*it) )) continue; 1109 if (useDNotify( &(*it) )) continue;
1108#endif 1110#endif
1109 useStat( &(*it) ); 1111 useStat( &(*it) );
1110 } 1112 }
1111 } 1113 }
1112 else 1114 else
1113 checkFAMEvent(&fe); 1115 checkFAMEvent(&fe);
1114 } 1116 }
1115 1117
1116 QTimer::singleShot(0, this, SLOT(slotRemoveDelayed())); 1118 QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
1117} 1119}
1118 1120
1119void KDirWatchPrivate::checkFAMEvent(FAMEvent* fe) 1121void KDirWatchPrivate::checkFAMEvent(FAMEvent* fe)
1120{ 1122{
1121 // Don't be too verbose ;-) 1123 // Don't be too verbose ;-)
1122 if ((fe->code == FAMExists) || 1124 if ((fe->code == FAMExists) ||
1123 (fe->code == FAMEndExist) || 1125 (fe->code == FAMEndExist) ||
1124 (fe->code == FAMAcknowledge)) return; 1126 (fe->code == FAMAcknowledge)) return;
1125 1127
1126 // $HOME/.X.err grows with debug output, so don't notify change 1128 // $HOME/.X.err grows with debug output, so don't notify change
1127 if ( *(fe->filename) == '.') { 1129 if ( *(fe->filename) == '.') {
1128 if (strncmp(fe->filename, ".X.err", 6) == 0) return; 1130 if (strncmp(fe->filename, ".X.err", 6) == 0) return;
1129 if (strncmp(fe->filename, ".xsession-errors", 16) == 0) return; 1131 if (strncmp(fe->filename, ".xsession-errors", 16) == 0) return;
1130 } 1132 }
1131 1133
1132 Entry* e = 0; 1134 Entry* e = 0;
1133 EntryMap::Iterator it = m_mapEntries.begin(); 1135 EntryMap::Iterator it = m_mapEntries.begin();
1134 for( ; it != m_mapEntries.end(); ++it ) 1136 for( ; it != m_mapEntries.end(); ++it )
1135 if (FAMREQUEST_GETREQNUM(&( (*it).fr )) == 1137 if (FAMREQUEST_GETREQNUM(&( (*it).fr )) ==
1136 FAMREQUEST_GETREQNUM(&(fe->fr)) ) { 1138 FAMREQUEST_GETREQNUM(&(fe->fr)) ) {
1137 e = &(*it); 1139 e = &(*it);
1138 break; 1140 break;
1139 } 1141 }
1140 1142
1141 // Entry* e = static_cast<Entry*>(fe->userdata); 1143 // Entry* e = static_cast<Entry*>(fe->userdata);
1142 1144
1143 kdDebug(7001) << "Processing FAM event (" 1145 kdDebug(7001) << "Processing FAM event ("
1144 << ((fe->code == FAMChanged) ? "FAMChanged" : 1146 << ((fe->code == FAMChanged) ? "FAMChanged" :
1145 (fe->code == FAMDeleted) ? "FAMDeleted" : 1147 (fe->code == FAMDeleted) ? "FAMDeleted" :
1146 (fe->code == FAMStartExecuting) ? "FAMStartExecuting" : 1148 (fe->code == FAMStartExecuting) ? "FAMStartExecuting" :
1147 (fe->code == FAMStopExecuting) ? "FAMStopExecuting" : 1149 (fe->code == FAMStopExecuting) ? "FAMStopExecuting" :
1148 (fe->code == FAMCreated) ? "FAMCreated" : 1150 (fe->code == FAMCreated) ? "FAMCreated" :
1149 (fe->code == FAMMoved) ? "FAMMoved" : 1151 (fe->code == FAMMoved) ? "FAMMoved" :
1150 (fe->code == FAMAcknowledge) ? "FAMAcknowledge" : 1152 (fe->code == FAMAcknowledge) ? "FAMAcknowledge" :
1151 (fe->code == FAMExists) ? "FAMExists" : 1153 (fe->code == FAMExists) ? "FAMExists" :
1152 (fe->code == FAMEndExist) ? "FAMEndExist" : "Unknown Code") 1154 (fe->code == FAMEndExist) ? "FAMEndExist" : "Unknown Code")
1153 << ", " << fe->filename 1155 << ", " << fe->filename
1154 << ", Req " << FAMREQUEST_GETREQNUM(&(fe->fr)) 1156 << ", Req " << FAMREQUEST_GETREQNUM(&(fe->fr))
1155 << ")" << endl; 1157 << ")" << endl;
1156 1158
1157 if (!e) { 1159 if (!e) {
1158 // this happens e.g. for FAMAcknowledge after deleting a dir... 1160 // this happens e.g. for FAMAcknowledge after deleting a dir...
1159 // kdDebug(7001) << "No entry for FAM event ?!" << endl; 1161 // kdDebug(7001) << "No entry for FAM event ?!" << endl;
1160 return; 1162 return;
1161 } 1163 }
1162 1164
1163 if (e->m_status == NonExistent) { 1165 if (e->m_status == NonExistent) {
1164 kdDebug(7001) << "FAM event for nonExistent entry " << e->path << endl; 1166 kdDebug(7001) << "FAM event for nonExistent entry " << e->path << endl;
1165 return; 1167 return;
1166 } 1168 }
1167 1169
1168 if (e->isDir) 1170 if (e->isDir)
1169 switch (fe->code) 1171 switch (fe->code)
1170 { 1172 {
1171 case FAMDeleted: 1173 case FAMDeleted:
1172 // file absolute: watched dir 1174 // file absolute: watched dir
1173 if (fe->filename[0] == '/') 1175 if (fe->filename[0] == '/')
1174 { 1176 {
1175 // a watched directory was deleted 1177 // a watched directory was deleted
1176 1178
1177 e->m_status = NonExistent; 1179 e->m_status = NonExistent;
1178 FAMCancelMonitor(&fc, &(e->fr) ); // needed ? 1180 FAMCancelMonitor(&fc, &(e->fr) ); // needed ?
1179 kdDebug(7001) << "Cancelled FAMReq " 1181 kdDebug(7001) << "Cancelled FAMReq "
1180 << FAMREQUEST_GETREQNUM(&(e->fr)) 1182 << FAMREQUEST_GETREQNUM(&(e->fr))
1181 << " for " << e->path << endl; 1183 << " for " << e->path << endl;
1182 // Scan parent for a new creation 1184 // Scan parent for a new creation
1183 addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true); 1185 addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
1184 } 1186 }
1185 emitEvent(e, Deleted, QFile::decodeName(fe->filename)); 1187 emitEvent(e, Deleted, QFile::decodeName(fe->filename));
1186 break; 1188 break;
1187 1189
1188 case FAMCreated: { 1190 case FAMCreated: {
1189 // check for creation of a directory we have to watch 1191 // check for creation of a directory we have to watch
1190 Entry *sub_entry = e->m_entries.first(); 1192 Entry *sub_entry = e->m_entries.first();
1191 for(;sub_entry; sub_entry = e->m_entries.next()) 1193 for(;sub_entry; sub_entry = e->m_entries.next())
1192 if (sub_entry->path == e->path + "/" + fe->filename) break; 1194 if (sub_entry->path == e->path + "/" + fe->filename) break;
1193 if (sub_entry && sub_entry->isDir) { 1195 if (sub_entry && sub_entry->isDir) {
1194 QString path = e->path; 1196 QString path = e->path;
1195 removeEntry(0,e->path,sub_entry); // <e> can be invalid here!! 1197 removeEntry(0,e->path,sub_entry); // <e> can be invalid here!!
1196 sub_entry->m_status = Normal; 1198 sub_entry->m_status = Normal;
1197 if (!useFAM(sub_entry)) 1199 if (!useFAM(sub_entry))
1198 useStat(sub_entry); 1200 useStat(sub_entry);
1199 1201
1200 emitEvent(sub_entry, Created); 1202 emitEvent(sub_entry, Created);
1201 } 1203 }
1202 else emitEvent(e, Created, QFile::decodeName(fe->filename)); 1204 else emitEvent(e, Created, QFile::decodeName(fe->filename));
1203 break; 1205 break;
1204 } 1206 }
1205 1207
1206 case FAMChanged: 1208 case FAMChanged:
1207 emitEvent(e, Changed, QFile::decodeName(fe->filename)); 1209 emitEvent(e, Changed, QFile::decodeName(fe->filename));
1208 1210
1209 default: 1211 default:
1210 break; 1212 break;
1211 } 1213 }
1212 else switch (fe->code) 1214 else switch (fe->code)
1213 { 1215 {
1214 case FAMCreated: emitEvent(e, Created); 1216 case FAMCreated: emitEvent(e, Created);
1215 break; 1217 break;
1216 case FAMDeleted: emitEvent(e, Deleted); 1218 case FAMDeleted: emitEvent(e, Deleted);
1217 break; 1219 break;
1218 case FAMChanged: emitEvent(e, Changed); 1220 case FAMChanged: emitEvent(e, Changed);
1219 break; 1221 break;
1220 default: break; 1222 default: break;
1221 } 1223 }
1222} 1224}
1223#else 1225#else
1224void KDirWatchPrivate::famEventReceived() {} 1226void KDirWatchPrivate::famEventReceived() {}
1225#endif 1227#endif
1226 1228
1227 1229
1228void KDirWatchPrivate::statistics() 1230void KDirWatchPrivate::statistics()
1229{ 1231{
1230 EntryMap::Iterator it; 1232 EntryMap::Iterator it;
1231 1233
1232 kdDebug(7001) << "Entries watched:" << endl; 1234 kdDebug(7001) << "Entries watched:" << endl;
1233 if (m_mapEntries.count()==0) { 1235 if (m_mapEntries.count()==0) {
1234 kdDebug(7001) << " None." << endl; 1236 kdDebug(7001) << " None." << endl;
1235 } 1237 }
1236 else { 1238 else {
1237 it = m_mapEntries.begin(); 1239 it = m_mapEntries.begin();
1238 for( ; it != m_mapEntries.end(); ++it ) { 1240 for( ; it != m_mapEntries.end(); ++it ) {
1239 Entry* e = &(*it); 1241 Entry* e = &(*it);
1240 kdDebug(7001) << " " << e->path << " (" 1242 kdDebug(7001) << " " << e->path << " ("
1241 << ((e->m_status==Normal)?"":"Nonexistent ") 1243 << ((e->m_status==Normal)?"":"Nonexistent ")
1242 << (e->isDir ? "Dir":"File") << ", using " 1244 << (e->isDir ? "Dir":"File") << ", using "
1243 << ((e->m_mode == FAMMode) ? "FAM" : 1245 << ((e->m_mode == FAMMode) ? "FAM" :
1244 (e->m_mode == DNotifyMode) ? "DNotify" : 1246 (e->m_mode == DNotifyMode) ? "DNotify" :
1245 (e->m_mode == StatMode) ? "Stat" : "Unknown Method") 1247 (e->m_mode == StatMode) ? "Stat" : "Unknown Method")
1246 << ")" << endl; 1248 << ")" << endl;
1247 1249
1248 Client* c = e->m_clients.first(); 1250 Client* c = e->m_clients.first();
1249 for(;c; c = e->m_clients.next()) { 1251 for(;c; c = e->m_clients.next()) {
1250 QString pending; 1252 QString pending;
1251 if (c->watchingStopped) { 1253 if (c->watchingStopped) {
1252 if (c->pending & Deleted) pending += "deleted "; 1254 if (c->pending & Deleted) pending += "deleted ";
1253 if (c->pending & Created) pending += "created "; 1255 if (c->pending & Created) pending += "created ";
1254 if (c->pending & Changed) pending += "changed "; 1256 if (c->pending & Changed) pending += "changed ";
1255 if (!pending.isEmpty()) pending = " (pending: " + pending + ")"; 1257 if (!pending.isEmpty()) pending = " (pending: " + pending + ")";
1256 pending = ", stopped" + pending; 1258 pending = ", stopped" + pending;
1257 } 1259 }
1258 kdDebug(7001) << " by " << c->instance->name() 1260 kdDebug(7001) << " by " << c->instance->name()
1259 << " (" << c->count << " times)" 1261 << " (" << c->count << " times)"
1260 << pending << endl; 1262 << pending << endl;
1261 } 1263 }
1262 if (e->m_entries.count()>0) { 1264 if (e->m_entries.count()>0) {
1263 kdDebug(7001) << " dependent entries:" << endl; 1265 kdDebug(7001) << " dependent entries:" << endl;
1264 Entry* d = e->m_entries.first(); 1266 Entry* d = e->m_entries.first();
1265 for(;d; d = e->m_entries.next()) { 1267 for(;d; d = e->m_entries.next()) {
1266 kdDebug(7001) << " " << d->path << endl; 1268 kdDebug(7001) << " " << d->path << endl;
1267 } 1269 }
1268 } 1270 }
1269 } 1271 }
1270 } 1272 }
1271} 1273}
1272 1274
1273 1275
1274// 1276//
1275// Class KDirWatch 1277// Class KDirWatch
1276// 1278//
1277 1279
1278static KStaticDeleter<KDirWatch> sd_dw; 1280static KStaticDeleter<KDirWatch> sd_dw;
1279KDirWatch* KDirWatch::s_pSelf = 0L; 1281KDirWatch* KDirWatch::s_pSelf = 0L;
1280 1282
1281KDirWatch* KDirWatch::self() 1283KDirWatch* KDirWatch::self()
1282{ 1284{
1283 if ( !s_pSelf ) { 1285 if ( !s_pSelf ) {
1284//US sd_dw.setObject( s_pSelf, new KDirWatch ); 1286//US sd_dw.setObject( s_pSelf, new KDirWatch );
1285 s_pSelf = sd_dw.setObject( new KDirWatch ); 1287 s_pSelf = sd_dw.setObject( new KDirWatch );
1286 } 1288 }
1287 1289
1288 return s_pSelf; 1290 return s_pSelf;
1289} 1291}
1290 1292
1291bool KDirWatch::exists() 1293bool KDirWatch::exists()
1292{ 1294{
1293 return s_pSelf != 0; 1295 return s_pSelf != 0;
1294} 1296}
1295 1297
1296KDirWatch::KDirWatch (QObject* parent, const char* name) 1298KDirWatch::KDirWatch (QObject* parent, const char* name)
1297 : QObject(parent,name) 1299 : QObject(parent,name)
1298{ 1300{
1299 if (!name) { 1301 if (!name) {
1300 static int nameCounter = 0; 1302 static int nameCounter = 0;
1301 1303
1302 nameCounter++; 1304 nameCounter++;
1303 setName(QString("KDirWatch-%1").arg(nameCounter).ascii()); 1305 setName(QString("KDirWatch-%1").arg(nameCounter).ascii());
1304 } 1306 }
1305 1307
1306 if (!dwp_self) 1308 if (!dwp_self)
1307 dwp_self = new KDirWatchPrivate; 1309 dwp_self = new KDirWatchPrivate;
1308 d = dwp_self; 1310 d = dwp_self;
1309 d->ref(); 1311 d->ref();
1310 1312
1311 _isStopped = false; 1313 _isStopped = false;
1312} 1314}
1313 1315
1314KDirWatch::~KDirWatch() 1316KDirWatch::~KDirWatch()
1315{ 1317{
1316 if (d) d->removeEntries(this); 1318 if (d) d->removeEntries(this);
1317 if ( d->deref() ) 1319 if ( d->deref() )
1318 { 1320 {
1319 // delete it if it's the last one 1321 // delete it if it's the last one
1320 delete d; 1322 delete d;
1321 dwp_self = 0L; 1323 dwp_self = 0L;
1322 } 1324 }
1323} 1325}
1324 1326
1325 1327
1326// TODO: add watchFiles/recursive support 1328// TODO: add watchFiles/recursive support
1327void KDirWatch::addDir( const QString& _path, 1329void KDirWatch::addDir( const QString& _path,
1328 bool watchFiles, bool recursive) 1330 bool watchFiles, bool recursive)
1329{ 1331{
1330 if (watchFiles || recursive) { 1332 if (watchFiles || recursive) {
1331 kdDebug(7001) << "addDir - recursive/watchFiles not supported in KDE 3.0" 1333 kdDebug(7001) << "addDir - recursive/watchFiles not supported in KDE 3.0"
1332 << endl; 1334 << endl;
1333 } 1335 }
1334 if (d) d->addEntry(this, _path, 0, true); 1336 if (d) d->addEntry(this, _path, 0, true);
1335} 1337}
1336 1338
1337void KDirWatch::addFile( const QString& _path ) 1339void KDirWatch::addFile( const QString& _path )
1338{ 1340{
1339 if (d) d->addEntry(this, _path, 0, false); 1341 if (d) d->addEntry(this, _path, 0, false);
1340} 1342}
1341 1343
1342QDateTime KDirWatch::ctime( const QString &_path ) 1344QDateTime KDirWatch::ctime( const QString &_path )
1343{ 1345{
1344 KDirWatchPrivate::Entry* e = d->entry(_path); 1346 KDirWatchPrivate::Entry* e = d->entry(_path);
1345 1347
1346 if (!e) 1348 if (!e)
1347 return QDateTime(); 1349 return QDateTime();
1348 1350
1349 QDateTime result; 1351 QDateTime result;
1350 result.setTime_t(e->m_ctime); 1352 result.setTime_t(e->m_ctime);
1351 return result; 1353 return result;
1352} 1354}
1353 1355
1354void KDirWatch::removeDir( const QString& _path ) 1356void KDirWatch::removeDir( const QString& _path )
1355{ 1357{
1356 if (d) d->removeEntry(this, _path, 0); 1358 if (d) d->removeEntry(this, _path, 0);
1357} 1359}
1358 1360
1359void KDirWatch::removeFile( const QString& _path ) 1361void KDirWatch::removeFile( const QString& _path )
1360{ 1362{
1361 if (d) d->removeEntry(this, _path, 0); 1363 if (d) d->removeEntry(this, _path, 0);
1362} 1364}
1363 1365
1364bool KDirWatch::stopDirScan( const QString& _path ) 1366bool KDirWatch::stopDirScan( const QString& _path )
1365{ 1367{
1366 if (d) { 1368 if (d) {
1367 KDirWatchPrivate::Entry *e = d->entry(_path); 1369 KDirWatchPrivate::Entry *e = d->entry(_path);
1368 if (e && e->isDir) return d->stopEntryScan(this, e); 1370 if (e && e->isDir) return d->stopEntryScan(this, e);
1369 } 1371 }
1370 return false; 1372 return false;
1371} 1373}
1372 1374
1373bool KDirWatch::restartDirScan( const QString& _path ) 1375bool KDirWatch::restartDirScan( const QString& _path )
1374{ 1376{
1375 if (d) { 1377 if (d) {
1376 KDirWatchPrivate::Entry *e = d->entry(_path); 1378 KDirWatchPrivate::Entry *e = d->entry(_path);
1377 if (e && e->isDir) 1379 if (e && e->isDir)
1378 // restart without notifying pending events 1380 // restart without notifying pending events
1379 return d->restartEntryScan(this, e, false); 1381 return d->restartEntryScan(this, e, false);
1380 } 1382 }
1381 return false; 1383 return false;
1382} 1384}
1383 1385
1384void KDirWatch::stopScan() 1386void KDirWatch::stopScan()
1385{ 1387{
1386 if (d) d->stopScan(this); 1388 if (d) d->stopScan(this);
1387 _isStopped = true; 1389 _isStopped = true;
1388} 1390}
1389 1391
1390void KDirWatch::startScan( bool notify, bool skippedToo ) 1392void KDirWatch::startScan( bool notify, bool skippedToo )
1391{ 1393{
1392 _isStopped = false; 1394 _isStopped = false;
1393 if (d) d->startScan(this, notify, skippedToo); 1395 if (d) d->startScan(this, notify, skippedToo);
1394} 1396}
1395 1397
1396 1398
1397bool KDirWatch::contains( const QString& _path ) const 1399bool KDirWatch::contains( const QString& _path ) const
1398{ 1400{
1399 KDirWatchPrivate::Entry* e = d->entry(_path); 1401 KDirWatchPrivate::Entry* e = d->entry(_path);
1400 if (!e) 1402 if (!e)
1401 return false; 1403 return false;
1402 1404
1403 KDirWatchPrivate::Client* c = e->m_clients.first(); 1405 KDirWatchPrivate::Client* c = e->m_clients.first();
1404 for(;c;c=e->m_clients.next()) 1406 for(;c;c=e->m_clients.next())
1405 if (c->instance == this) return true; 1407 if (c->instance == this) return true;
1406 1408
1407 return false; 1409 return false;
1408} 1410}
1409 1411
1410void KDirWatch::statistics() 1412void KDirWatch::statistics()
1411{ 1413{
1412 if (!dwp_self) { 1414 if (!dwp_self) {
1413 kdDebug(7001) << "KDirWatch not used" << endl; 1415 kdDebug(7001) << "KDirWatch not used" << endl;
1414 return; 1416 return;
1415 } 1417 }
1416 dwp_self->statistics(); 1418 dwp_self->statistics();
1417} 1419}
1418 1420
1419 1421
1420void KDirWatch::setCreated( const QString & _file ) 1422void KDirWatch::setCreated( const QString & _file )
1421{ 1423{
1422 kdDebug(7001) << name() << " emitting created " << _file << endl; 1424 kdDebug(7001) << name() << " emitting created " << _file << endl;
1423 emit created( _file ); 1425 emit created( _file );
1424} 1426}
1425 1427
1426void KDirWatch::setDirty( const QString & _file ) 1428void KDirWatch::setDirty( const QString & _file )
1427{ 1429{
1428 kdDebug(7001) << name() << " emitting dirty " << _file << endl; 1430 kdDebug(7001) << name() << " emitting dirty " << _file << endl;
1429 emit dirty( _file ); 1431 emit dirty( _file );
1430} 1432}
1431 1433
1432void KDirWatch::setDeleted( const QString & _file ) 1434void KDirWatch::setDeleted( const QString & _file )
1433{ 1435{
1434 kdDebug(7001) << name() << " emitting deleted " << _file << endl; 1436 kdDebug(7001) << name() << " emitting deleted " << _file << endl;
1435 emit deleted( _file ); 1437 emit deleted( _file );
1436} 1438}
1437 1439
1438//US #include "kdirwatch.moc" 1440//US #include "kdirwatch.moc"
1439//US #include "kdirwatch_p.moc" 1441//US #include "kdirwatch_p.moc"
1440 1442
1441//sven 1443//sven
1442 1444
1443// vim: sw=2 ts=8 et 1445// vim: sw=2 ts=8 et
diff --git a/microkde/kio/kio/kdirwatch_p.h b/microkde/kio/kio/kdirwatch_p.h
index 0ab482f..be74f2a 100644
--- a/microkde/kio/kio/kdirwatch_p.h
+++ b/microkde/kio/kio/kdirwatch_p.h
@@ -1,153 +1,153 @@
1/* Private Header for class of KDirWatchPrivate 1/* Private Header for class of KDirWatchPrivate
2 * 2 *
3 * this separate header file is needed for MOC processing 3 * this separate header file is needed for MOC processing
4 * because KDirWatchPrivate has signals and slots 4 * because KDirWatchPrivate has signals and slots
5 */ 5 */
6 6
7/* 7/*
8Enhanced Version of the file for platform independent KDE tools. 8Enhanced Version of the file for platform independent KDE tools.
9Copyright (c) 2004 Ulf Schenk 9Copyright (c) 2004 Ulf Schenk
10 10
11$Id$ 11$Id$
12*/ 12*/
13 13
14#ifndef _KDIRWATCH_P_H 14#ifndef _KDIRWATCH_P_H
15#define _KDIRWATCH_P_H 15#define _KDIRWATCH_P_H
16 16
17#ifdef HAVE_FAM 17#ifdef HAVE_FAM
18#include <fam.h> 18#include <fam.h>
19#endif 19#endif
20 20
21#include <qptrlist.h> 21#include <q3ptrlist.h>
22 22
23#include <kdirwatch.h> 23#include <kdirwatch.h>
24 24
25#include <ctime> 25#include <ctime>
26 26
27#define invalid_ctime ((time_t)-1) 27#define invalid_ctime ((time_t)-1)
28 28
29/* KDirWatchPrivate is a singleton and does the watching 29/* KDirWatchPrivate is a singleton and does the watching
30 * for every KDirWatch instance in the application. 30 * for every KDirWatch instance in the application.
31 */ 31 */
32class KDirWatchPrivate : public QObject 32class KDirWatchPrivate : public QObject
33{ 33{
34 Q_OBJECT 34 Q_OBJECT
35public: 35public:
36 36
37 enum entryStatus { Normal = 0, NonExistent }; 37 enum entryStatus { Normal = 0, NonExistent };
38 enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, FAMMode }; 38 enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, FAMMode };
39 enum { NoChange=0, Changed=1, Created=2, Deleted=4 }; 39 enum { NoChange=0, Changed=1, Created=2, Deleted=4 };
40 40
41 struct Client { 41 struct Client {
42 KDirWatch* instance; 42 KDirWatch* instance;
43 int count; 43 int count;
44 // did the instance stop watching 44 // did the instance stop watching
45 bool watchingStopped; 45 bool watchingStopped;
46 // events blocked when stopped 46 // events blocked when stopped
47 int pending; 47 int pending;
48 }; 48 };
49 49
50 class Entry 50 class Entry
51 { 51 {
52 public: 52 public:
53 // the last observed modification time 53 // the last observed modification time
54 time_t m_ctime; 54 time_t m_ctime;
55 // the last observed link count 55 // the last observed link count
56 int m_nlink; 56 int m_nlink;
57 entryStatus m_status; 57 entryStatus m_status;
58 entryMode m_mode; 58 entryMode m_mode;
59 bool isDir; 59 bool isDir;
60 // instances interested in events 60 // instances interested in events
61 QPtrList<Client> m_clients; 61 Q3PtrList<Client> m_clients;
62 // nonexistent entries of this directory 62 // nonexistent entries of this directory
63 QPtrList<Entry> m_entries; 63 Q3PtrList<Entry> m_entries;
64 QString path; 64 QString path;
65 65
66 int msecLeft, freq; 66 int msecLeft, freq;
67 67
68 void addClient(KDirWatch*); 68 void addClient(KDirWatch*);
69 void removeClient(KDirWatch*); 69 void removeClient(KDirWatch*);
70 int clients(); 70 int clients();
71 bool isValid() { return m_clients.count() || m_entries.count(); } 71 bool isValid() { return m_clients.count() || m_entries.count(); }
72 72
73#ifdef HAVE_FAM 73#ifdef HAVE_FAM
74 FAMRequest fr; 74 FAMRequest fr;
75#endif 75#endif
76 76
77#ifdef HAVE_DNOTIFY 77#ifdef HAVE_DNOTIFY
78 int dn_fd; 78 int dn_fd;
79 bool dn_dirty; 79 bool dn_dirty;
80 void propagate_dirty(); 80 void propagate_dirty();
81#endif 81#endif
82 }; 82 };
83 83
84 typedef QMap<QString,Entry> EntryMap; 84 typedef QMap<QString,Entry> EntryMap;
85 85
86 KDirWatchPrivate(); 86 KDirWatchPrivate();
87 ~KDirWatchPrivate(); 87 ~KDirWatchPrivate();
88 88
89 void resetList (KDirWatch*,bool); 89 void resetList (KDirWatch*,bool);
90 void useFreq(Entry* e, int newFreq); 90 void useFreq(Entry* e, int newFreq);
91 void addEntry(KDirWatch*,const QString&, Entry*, bool); 91 void addEntry(KDirWatch*,const QString&, Entry*, bool);
92 void removeEntry(KDirWatch*,const QString&, Entry*); 92 void removeEntry(KDirWatch*,const QString&, Entry*);
93 bool stopEntryScan(KDirWatch*, Entry*); 93 bool stopEntryScan(KDirWatch*, Entry*);
94 bool restartEntryScan(KDirWatch*, Entry*, bool ); 94 bool restartEntryScan(KDirWatch*, Entry*, bool );
95 void stopScan(KDirWatch*); 95 void stopScan(KDirWatch*);
96 void startScan(KDirWatch*, bool, bool); 96 void startScan(KDirWatch*, bool, bool);
97 97
98 void removeEntries(KDirWatch*); 98 void removeEntries(KDirWatch*);
99 void statistics(); 99 void statistics();
100 100
101 Entry* entry(const QString&); 101 Entry* entry(const QString&);
102 int scanEntry(Entry* e); 102 int scanEntry(Entry* e);
103 void emitEvent(Entry* e, int event, const QString &fileName = QString::null); 103 void emitEvent(Entry* e, int event, const QString &fileName = QString::null);
104 104
105 // Memory management - delete when last KDirWatch gets deleted 105 // Memory management - delete when last KDirWatch gets deleted
106 void ref() { m_ref++; } 106 void ref() { m_ref++; }
107 bool deref() { return ( --m_ref == 0 ); } 107 bool deref() { return ( --m_ref == 0 ); }
108 108
109public slots: 109public slots:
110 void slotRescan(); 110 void slotRescan();
111 void famEventReceived(); // for FAM 111 void famEventReceived(); // for FAM
112 void slotActivated(); // for DNOTIFY 112 void slotActivated(); // for DNOTIFY
113 void slotRemoveDelayed(); 113 void slotRemoveDelayed();
114 114
115public: 115public:
116 QTimer *timer; 116 QTimer *timer;
117 EntryMap m_mapEntries; 117 EntryMap m_mapEntries;
118 118
119private: 119private:
120 int freq; 120 int freq;
121 int statEntries; 121 int statEntries;
122 int m_nfsPollInterval, m_PollInterval; 122 int m_nfsPollInterval, m_PollInterval;
123 int m_ref; 123 int m_ref;
124 bool useStat(Entry*); 124 bool useStat(Entry*);
125 125
126 bool delayRemove; 126 bool delayRemove;
127 QPtrList<Entry> removeList; 127 Q3PtrList<Entry> removeList;
128 128
129#ifdef HAVE_FAM 129#ifdef HAVE_FAM
130 QSocketNotifier *sn; 130 QSocketNotifier *sn;
131 FAMConnection fc; 131 FAMConnection fc;
132 bool use_fam; 132 bool use_fam;
133 133
134 void checkFAMEvent(FAMEvent*); 134 void checkFAMEvent(FAMEvent*);
135 bool useFAM(Entry*); 135 bool useFAM(Entry*);
136#endif 136#endif
137 137
138#ifdef HAVE_DNOTIFY 138#ifdef HAVE_DNOTIFY
139 bool supports_dnotify; 139 bool supports_dnotify;
140 bool rescan_all; 140 bool rescan_all;
141 int mPipe[2]; 141 int mPipe[2];
142 QTimer mTimer; 142 QTimer mTimer;
143 QSocketNotifier *mSn; 143 QSocketNotifier *mSn;
144 QIntDict<Entry> fd_Entry; 144 Q3IntDict<Entry> fd_Entry;
145 145
146 static void dnotify_handler(int, siginfo_t *si, void *); 146 static void dnotify_handler(int, siginfo_t *si, void *);
147 static void dnotify_sigio_handler(int, siginfo_t *si, void *); 147 static void dnotify_sigio_handler(int, siginfo_t *si, void *);
148 bool useDNotify(Entry*); 148 bool useDNotify(Entry*);
149#endif 149#endif
150}; 150};
151 151
152#endif // KDIRWATCH_P_H 152#endif // KDIRWATCH_P_H
153 153