• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
kdirlister.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  2000 Carsten Pfeiffer <pfeiffer@kde.org>
4  2001-2005 Michael Brade <brade@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "kdirlister.h"
23 
24 #include <tqregexp.h>
25 #include <tqptrlist.h>
26 #include <tqtimer.h>
27 #include <tqeventloop.h>
28 
29 #include <tdeapplication.h>
30 #include <kdebug.h>
31 #include <tdelocale.h>
32 #include <tdeio/job.h>
33 #include <tdemessagebox.h>
34 #include <tdeglobal.h>
35 #include <tdeglobalsettings.h>
36 #include <kstaticdeleter.h>
37 #include <kprotocolinfo.h>
38 
39 #include "kdirlister_p.h"
40 
41 #include <assert.h>
42 #include <unistd.h>
43 
44 KDirListerCache* KDirListerCache::s_pSelf = 0;
45 static KStaticDeleter<KDirListerCache> sd_KDirListerCache;
46 
47 // Enable this to get printDebug() called often, to see the contents of the cache
48 //#define DEBUG_CACHE
49 
50 // Make really sure it doesn't get activated in the final build
51 #ifdef NDEBUG
52 #undef DEBUG_CACHE
53 #endif
54 
55 KDirListerCache::KDirListerCache( int maxCount )
56  : itemsCached( maxCount )
57 {
58  kdDebug(7004) << "+KDirListerCache" << endl;
59 
60  itemsInUse.setAutoDelete( false );
61  itemsCached.setAutoDelete( true );
62  urlsCurrentlyListed.setAutoDelete( true );
63  urlsCurrentlyHeld.setAutoDelete( true );
64  pendingUpdates.setAutoDelete( true );
65 
66  connect( kdirwatch, TQT_SIGNAL( dirty( const KURL& ) ),
67  this, TQT_SLOT( slotFileDirty( const KURL& ) ) );
68  connect( kdirwatch, TQT_SIGNAL( created( const TQString& ) ),
69  this, TQT_SLOT( slotFileCreated( const TQString& ) ) );
70  connect( kdirwatch, TQT_SIGNAL( deleted( const TQString& ) ),
71  this, TQT_SLOT( slotFileDeleted( const TQString& ) ) );
72 }
73 
74 KDirListerCache::~KDirListerCache()
75 {
76  kdDebug(7004) << "-KDirListerCache" << endl;
77 
78  itemsInUse.setAutoDelete( true );
79  itemsInUse.clear();
80  itemsCached.clear();
81  urlsCurrentlyListed.clear();
82  urlsCurrentlyHeld.clear();
83 
84  if ( KDirWatch::exists() )
85  kdirwatch->disconnect( this );
86 }
87 
88 // setting _reload to true will emit the old files and
89 // call updateDirectory
90 bool KDirListerCache::listDir( KDirLister *lister, const KURL& _u,
91  bool _keep, bool _reload )
92 {
93  // like this we don't have to worry about trailing slashes any further
94  KURL _url = _u;
95  _url.cleanPath(); // kill consecutive slashes
96  _url.adjustPath(-1);
97  TQString urlStr = _url.url();
98  TQString urlReferenceStr = _url.internalReferenceURL();
99 
100  if ( !lister->validURL( _url ) ) {
101  return false;
102  }
103 
104 #ifdef DEBUG_CACHE
105  printDebug();
106 #endif
107  kdDebug(7004) << k_funcinfo << lister << " url=" << _url
108  << " keep=" << _keep << " reload=" << _reload << endl;
109 
110  if ( !_keep )
111  {
112  // stop any running jobs for lister
113  stop( lister );
114 
115  // clear our internal list for lister
116  forgetDirs( lister );
117 
118  lister->d->rootFileItem = 0;
119  }
120  else if ( lister->d->lstDirs.find( _url ) != lister->d->lstDirs.end() )
121  {
122  // stop the job listing _url for this lister
123  stop( lister, _url );
124 
125  // clear _url for lister
126  forgetDirs( lister, _url, true );
127 
128  if ( lister->d->url == _url )
129  lister->d->rootFileItem = 0;
130  }
131 
132  lister->d->lstDirs.append( _url );
133 
134  if ( lister->d->url.isEmpty() || !_keep ) // set toplevel URL only if not set yet
135  lister->d->url = _url;
136 
137  DirItem *itemU = itemsInUse[urlStr + ":" + urlReferenceStr];
138  DirItem *itemC;
139 
140  if ( !urlsCurrentlyListed[urlStr + ":" + urlReferenceStr] )
141  {
142  // if there is an update running for _url already we get into
143  // the following case - it will just be restarted by updateDirectory().
144 
145  if ( itemU )
146  {
147  kdDebug(7004) << "listDir: Entry already in use: " << _url << endl;
148 
149  bool oldState = lister->d->complete;
150  lister->d->complete = false;
151 
152  emit lister->started( _url );
153 
154  if ( !lister->d->rootFileItem && lister->d->url == _url ) {
155  lister->d->rootFileItem = itemU->rootItem;
156  }
157 
158  lister->addNewItems( *(itemU->lstItems) );
159  lister->emitItems();
160 
161  // _url is already in use, so there is already an entry in urlsCurrentlyHeld
162  assert( urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr] );
163  urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr]->append( lister );
164 
165  lister->d->complete = oldState;
166 
167  lister->emitCompleted( _url );
168  if ( lister->d->complete ) {
169  emit lister->completed();
170  }
171 
172  if ( _reload || !itemU->complete ) {
173  updateDirectory( _url );
174  }
175  }
176  else if ( !_reload && (itemC = itemsCached.take( urlStr )) )
177  {
178  kdDebug(7004) << "listDir: Entry in cache: " << _url << endl;
179 
180  itemC->decAutoUpdate();
181  itemsInUse.insert( urlStr + ":" + urlReferenceStr, itemC );
182  itemU = itemC;
183 
184  bool oldState = lister->d->complete;
185  lister->d->complete = false;
186 
187  emit lister->started( _url );
188 
189  if ( !lister->d->rootFileItem && lister->d->url == _url ) {
190  lister->d->rootFileItem = itemC->rootItem;
191  }
192 
193  lister->addNewItems( *(itemC->lstItems) );
194  lister->emitItems();
195 
196  Q_ASSERT( !urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr] );
197  TQPtrList<KDirLister> *list = new TQPtrList<KDirLister>;
198  list->append( lister );
199  urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, list );
200 
201  lister->d->complete = oldState;
202 
203  lister->emitCompleted( _url );
204  if ( lister->d->complete ) {
205  emit lister->completed();
206  }
207 
208  if ( !itemC->complete ) {
209  updateDirectory( _url );
210  }
211  }
212  else // dir not in cache or _reload is true
213  {
214  kdDebug(7004) << "listDir: Entry not in cache or reloaded: " << _url << endl;
215 
216  TQPtrList<KDirLister> *list = new TQPtrList<KDirLister>;
217  list->append( lister );
218  urlsCurrentlyListed.insert( urlStr + ":" + urlReferenceStr, list );
219 
220  itemsCached.remove( urlStr );
221  itemU = new DirItem( _url );
222  itemsInUse.insert( urlStr + ":" + urlReferenceStr, itemU );
223 
224 // // we have a limit of MAX_JOBS_PER_LISTER concurrently running jobs
225 // if ( lister->numJobs() >= MAX_JOBS_PER_LISTER )
226 // {
227 // lstPendingUpdates.append( _url );
228 // }
229 // else
230 // {
231 
232  if ( lister->d->url == _url ) {
233  lister->d->rootFileItem = 0;
234  }
235 
236  TDEIO::ListJob* job = TDEIO::listDir( _url, false /* no default GUI */ );
237  jobs.insert( job, TQValueList<TDEIO::UDSEntry>() );
238 
239  lister->jobStarted( job );
240  lister->connectJob( job );
241 
242  if ( lister->d->window ) {
243  job->setWindow( lister->d->window );
244  }
245 
246  connect( job, TQT_SIGNAL( entries( TDEIO::Job *, const TDEIO::UDSEntryList & ) ),
247  this, TQT_SLOT( slotEntries( TDEIO::Job *, const TDEIO::UDSEntryList & ) ) );
248  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
249  this, TQT_SLOT( slotResult( TDEIO::Job * ) ) );
250  connect( job, TQT_SIGNAL( redirection( TDEIO::Job *, const KURL & ) ),
251  this, TQT_SLOT( slotRedirection( TDEIO::Job *, const KURL & ) ) );
252 
253  emit lister->started( _url );
254 
255 // }
256  }
257  }
258  else
259  {
260  kdDebug(7004) << "listDir: Entry currently being listed: " << _url << endl;
261 
262  emit lister->started( _url );
263 
264  urlsCurrentlyListed[urlStr + ":" + urlReferenceStr]->append( lister );
265 
266  TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
267  Q_ASSERT( job );
268 
269  lister->jobStarted( job );
270  lister->connectJob( job );
271 
272  Q_ASSERT( itemU );
273 
274  if ( !lister->d->rootFileItem && lister->d->url == _url ) {
275  lister->d->rootFileItem = itemU->rootItem;
276  }
277 
278  lister->addNewItems( *(itemU->lstItems) );
279  lister->emitItems();
280  }
281 
282  // automatic updating of directories
283  if ( lister->d->autoUpdate ) {
284  itemU->incAutoUpdate();
285  }
286 
287  return true;
288 }
289 
290 bool KDirListerCache::validURL( const KDirLister *lister, const KURL& url ) const
291 {
292  if ( !url.isValid() )
293  {
294  if ( lister->d->autoErrorHandling )
295  {
296  TQString tmp = i18n("Malformed URL\n%1").arg( url.prettyURL() );
297  KMessageBox::error( lister->d->errorParent, tmp );
298  }
299  return false;
300  }
301 
302  if ( !KProtocolInfo::supportsListing( url ) )
303  {
304  if ( lister->d->autoErrorHandling )
305  {
306  // TODO: this message should be changed during next string unfreeze!
307  TQString tmp = i18n("Malformed URL\n%1").arg( url.prettyURL() );
308  KMessageBox::error( lister->d->errorParent, tmp );
309  }
310  return false;
311  }
312 
313  return true;
314 }
315 
316 void KDirListerCache::stop( KDirLister *lister )
317 {
318 #ifdef DEBUG_CACHE
319  printDebug();
320 #endif
321  kdDebug(7004) << k_funcinfo << "lister: " << lister << endl;
322  bool stopped = false;
323 
324  TQDictIterator< TQPtrList<KDirLister> > it( urlsCurrentlyListed );
325  TQPtrList<KDirLister> *listers;
326  int curIndex;
327  while ( (listers = it.current()) )
328  {
329  curIndex = listers->findRef( lister );
330  if ( curIndex > -1 )
331  {
332  // lister is listing url
333  TQString url = it.currentKey();
334  KDirLister* curLister = listers->at( curIndex );
335 
336  //kdDebug(7004) << k_funcinfo << " found lister in list - for " << url << endl;
337  bool ret = listers->removeRef( lister );
338  Q_ASSERT( ret );
339 
340  TDEIO::ListJob *job = jobForUrl( url );
341  if ( job ) {
342  lister->jobDone( job );
343  }
344 
345  // move lister to urlsCurrentlyHeld
346  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[url];
347  if ( !holders )
348  {
349  holders = new TQPtrList<KDirLister>;
350  urlsCurrentlyHeld.insert( url, holders );
351  }
352 
353  holders->append( lister );
354 
355  emit lister->canceled( curLister->d->url );
356 
357  //kdDebug(7004) << k_funcinfo << "remaining list: " << listers->count() << " listers" << endl;
358 
359  if ( listers->isEmpty() )
360  {
361  // kill the job since it isn't used any more
362  if ( job ) {
363  killJob( job );
364  }
365 
366  urlsCurrentlyListed.remove( url );
367  }
368 
369  stopped = true;
370  }
371  else
372  ++it;
373  }
374 
375  if ( stopped )
376  {
377  emit lister->canceled();
378  lister->d->complete = true;
379  }
380 
381  // this is wrong if there is still an update running!
382  //Q_ASSERT( lister->d->complete );
383 }
384 
385 void KDirListerCache::stop( KDirLister *lister, const KURL& _u )
386 {
387  TQString urlStr( _u.url(-1) );
388  TQString urlReferenceStr = _u.internalReferenceURL();
389  KURL _url( urlStr );
390 
391  // TODO: consider to stop all the "child jobs" of _url as well
392  kdDebug(7004) << k_funcinfo << lister << " url=" << _url << endl;
393 
394  TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
395  if ( !listers || !listers->removeRef( lister ) )
396  return;
397 
398  // move lister to urlsCurrentlyHeld
399  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
400  if ( !holders )
401  {
402  holders = new TQPtrList<KDirLister>;
403  urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, holders );
404  }
405 
406  holders->append( lister );
407 
408 
409  TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
410  if ( job ) {
411  lister->jobDone( job );
412  }
413 
414  emit lister->canceled( _url );
415 
416  if ( listers->isEmpty() )
417  {
418  // kill the job since it isn't used any more
419  if ( job )
420  killJob( job );
421 
422  urlsCurrentlyListed.remove( urlStr + ":" + urlReferenceStr );
423  }
424 
425  if ( lister->numJobs() == 0 )
426  {
427  lister->d->complete = true;
428 
429  // we killed the last job for lister
430  emit lister->canceled();
431  }
432 }
433 
434 void KDirListerCache::setAutoUpdate( KDirLister *lister, bool enable )
435 {
436  // IMPORTANT: this method does not check for the current autoUpdate state!
437 
438  for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
439  it != lister->d->lstDirs.end(); ++it )
440  {
441  if ( enable ) {
442  itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->incAutoUpdate();
443  }
444  else {
445  itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->decAutoUpdate();
446  }
447  }
448 }
449 
450 void KDirListerCache::forgetDirs( KDirLister *lister )
451 {
452  kdDebug(7004) << k_funcinfo << lister << endl;
453 
454  emit lister->clear();
455 
456  // forgetDirs() will modify lstDirs, make a copy first
457  KURL::List lstDirsCopy = lister->d->lstDirs;
458  for ( KURL::List::Iterator it = lstDirsCopy.begin();
459  it != lstDirsCopy.end(); ++it )
460  {
461  forgetDirs( lister, *it, false );
462  }
463 }
464 
465 void KDirListerCache::forgetDirs( KDirLister *lister, const KURL& _url, bool notify )
466 {
467  kdDebug(7004) << k_funcinfo << lister << " _url: " << _url << endl;
468 
469  KURL url( _url );
470  url.adjustPath( -1 );
471  TQString urlStr = url.url();
472  TQString urlReferenceStr = url.internalReferenceURL();
473  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
474  //Q_ASSERT( holders );
475  if ( holders )
476  {
477  holders->removeRef( lister );
478  }
479 
480  // remove the dir from lister->d->lstDirs so that it doesn't contain things
481  // that itemsInUse doesn't. When emitting the canceled signals lstDirs must
482  // not contain anything that itemsInUse does not contain. (otherwise it
483  // might crash in findByName()).
484  lister->d->lstDirs.remove( lister->d->lstDirs.find( url ) );
485 
486  DirItem *item = itemsInUse[urlStr + ":" + urlReferenceStr];
487 
488  if ( holders && holders->isEmpty() )
489  {
490  urlsCurrentlyHeld.remove( urlStr + ":" + urlReferenceStr ); // this deletes the (empty) holders list
491  if ( !urlsCurrentlyListed[urlStr + ":" + urlReferenceStr] )
492  {
493  // item not in use anymore -> move into cache if complete
494  itemsInUse.remove( urlStr + ":" + urlReferenceStr );
495 
496  // this job is a running update
497  TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
498  if ( job )
499  {
500  lister->jobDone( job );
501  killJob( job );
502  kdDebug(7004) << k_funcinfo << "Killing update job for " << urlStr << endl;
503 
504  emit lister->canceled( url );
505  if ( lister->numJobs() == 0 )
506  {
507  lister->d->complete = true;
508  emit lister->canceled();
509  }
510  }
511 
512  if ( notify )
513  emit lister->clear( url );
514 
515  if ( item && item->complete )
516  {
517  kdDebug(7004) << k_funcinfo << lister << " item moved into cache: " << url << endl;
518  itemsCached.insert( urlStr, item ); // TODO: may return false!!
519 
520  // Should we forget the dir for good, or keep a watch on it?
521  // Generally keep a watch, except when it would prevent
522  // unmounting a removable device (#37780)
523  const bool isLocal = item->url.isLocalFile();
524  const bool isManuallyMounted = isLocal && TDEIO::manually_mounted( item->url.path() );
525  bool containsManuallyMounted = false;
526  if ( !isManuallyMounted && item->lstItems && isLocal )
527  {
528  // Look for a manually-mounted directory inside
529  // If there's one, we can't keep a watch either, FAM would prevent unmounting the CDROM
530  // I hope this isn't too slow (manually_mounted caches the last device so most
531  // of the time this is just a stat per subdir)
532  KFileItemListIterator kit( *item->lstItems );
533  for ( ; kit.current() && !containsManuallyMounted; ++kit )
534  if ( (*kit)->isDir() && TDEIO::manually_mounted( (*kit)->url().path() ) )
535  containsManuallyMounted = true;
536  }
537 
538  if ( isManuallyMounted || containsManuallyMounted )
539  {
540  kdDebug(7004) << "Not adding a watch on " << item->url << " because it " <<
541  ( isManuallyMounted ? "is manually mounted" : "contains a manually mounted subdir" ) << endl;
542  item->complete = false; // set to "dirty"
543  }
544  else
545  item->incAutoUpdate(); // keep watch
546  }
547  else
548  {
549  delete item;
550  item = 0;
551  }
552  }
553  }
554 
555  if ( item && lister->d->autoUpdate )
556  item->decAutoUpdate();
557 }
558 
559 void KDirListerCache::updateDirectory( const KURL& _dir )
560 {
561  kdDebug(7004) << k_funcinfo << _dir << endl;
562 
563  TQString urlStr = _dir.url(-1);
564  TQString urlReferenceStr = _dir.internalReferenceURL();
565  if ( !checkUpdate( _dir, -1 ) ) {
566  return;
567  }
568 
569  // A job can be running to
570  // - only list a new directory: the listers are in urlsCurrentlyListed
571  // - only update a directory: the listers are in urlsCurrentlyHeld
572  // - update a currently running listing: the listers are in urlsCurrentlyListed
573  // and urlsCurrentlyHeld
574 
575  TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
576  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
577 
578  // restart the job for _dir if it is running already
579  bool killed = false;
580  TQWidget *window = 0;
581  TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
582  if ( job )
583  {
584  window = job->window();
585 
586  killJob( job );
587  killed = true;
588 
589  if ( listers ) {
590  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
591  kdl->jobDone( job );
592  }
593  }
594 
595  if ( holders ) {
596  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() ) {
597  kdl->jobDone( job );
598  }
599  }
600  }
601  kdDebug(7004) << k_funcinfo << "Killed = " << killed << endl;
602 
603  // we don't need to emit canceled signals since we only replaced the job,
604  // the listing is continuing.
605 
606  Q_ASSERT( !listers || (listers && killed) );
607 
608  job = TDEIO::listDir( _dir, false /* no default GUI */ );
609  jobs.insert( job, TQValueList<TDEIO::UDSEntry>() );
610 
611  connect( job, TQT_SIGNAL(entries( TDEIO::Job *, const TDEIO::UDSEntryList & )),
612  this, TQT_SLOT(slotUpdateEntries( TDEIO::Job *, const TDEIO::UDSEntryList & )) );
613  connect( job, TQT_SIGNAL(result( TDEIO::Job * )),
614  this, TQT_SLOT(slotUpdateResult( TDEIO::Job * )) );
615 
616  kdDebug(7004) << k_funcinfo << "update started in " << _dir << endl;
617 
618  if ( listers ) {
619  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
620  kdl->jobStarted( job );
621  }
622  }
623 
624  if ( holders )
625  {
626  if ( !killed )
627  {
628  bool first = true;
629  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
630  {
631  kdl->jobStarted( job );
632  if ( first && kdl->d->window )
633  {
634  first = false;
635  job->setWindow( kdl->d->window );
636  }
637  emit kdl->started( _dir );
638  }
639  }
640  else
641  {
642  job->setWindow( window );
643 
644  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() ) {
645  kdl->jobStarted( job );
646  }
647  }
648  }
649 }
650 
651 bool KDirListerCache::checkUpdate( const KURL& _dir, int truncationMode )
652 {
653  if ( !itemsInUse[_dir.url(truncationMode) + ":" + _dir.internalReferenceURL()] )
654  {
655  DirItem *item = itemsCached[_dir.url(truncationMode)];
656  if ( item && item->complete )
657  {
658  item->complete = false;
659  item->decAutoUpdate();
660  // Hmm, this debug output might include login/password from the _dir URL.
661  //kdDebug(7004) << k_funcinfo << "directory " << _dir << " not in use, marked dirty." << endl;
662  }
663  //else
664  //kdDebug(7004) << k_funcinfo << "aborted, directory " << _dir << " not in cache." << endl;
665 
666  return false;
667  }
668  else
669  return true;
670 }
671 
672 KFileItemList *KDirListerCache::itemsForDir( const KURL &_dir ) const
673 {
674  TQString urlStr = _dir.url(-1);
675  TQString urlReferenceStr = _dir.internalReferenceURL();
676  DirItem *item = itemsInUse[ urlStr + ":" + urlReferenceStr ];
677  if ( !item ) {
678  item = itemsCached[ urlStr ];
679  }
680  return item ? item->lstItems : 0;
681 }
682 
683 KFileItem *KDirListerCache::findByName( const KDirLister *lister, const TQString& _name ) const
684 {
685  Q_ASSERT( lister );
686 
687  for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
688  it != lister->d->lstDirs.end(); ++it )
689  {
690  KFileItemListIterator kit( *itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->lstItems );
691  for ( ; kit.current(); ++kit )
692  if ( (*kit)->name() == _name )
693  return (*kit);
694  }
695 
696  return 0L;
697 }
698 
699 KFileItem *KDirListerCache::findByURL( const KDirLister *lister, const KURL& _u ) const
700 {
701  KURL _url = _u;
702  _url.adjustPath(-1);
703 
704  KURL parentDir( _url );
705  parentDir.setPath( parentDir.directory() );
706 
707  // If lister is set, check that it contains this dir
708  if ( lister && !lister->d->lstDirs.contains( parentDir ) )
709  return 0L;
710 
711  KFileItemList *itemList = itemsForDir( parentDir );
712  if ( itemList )
713  {
714  KFileItemListIterator kit( *itemList );
715  for ( ; kit.current(); ++kit )
716  if ( (*kit)->url() == _url )
717  return (*kit);
718  }
719  return 0L;
720 }
721 
722 void KDirListerCache::FilesAdded( const KURL &dir )
723 {
724  kdDebug(7004) << k_funcinfo << dir << endl;
725  updateDirectory( dir );
726 }
727 
728 void KDirListerCache::FilesRemoved( const KURL::List &fileList )
729 {
730  kdDebug(7004) << k_funcinfo << endl;
731  KURL::List::ConstIterator it = fileList.begin();
732  for ( ; it != fileList.end() ; ++it )
733  {
734  // emit the deleteItem signal if this file was shown in any view
735  KFileItem *fileitem = 0L;
736  KURL parentDir( *it );
737  parentDir.setPath( parentDir.directory() );
738  KFileItemList *lstItems = itemsForDir( parentDir );
739  if ( lstItems )
740  {
741  KFileItem *fit = lstItems->first();
742  for ( ; fit; fit = lstItems->next() )
743  if ( fit->url() == *it ) {
744  fileitem = fit;
745  lstItems->take(); // remove fileitem from list
746  break;
747  }
748  }
749 
750  // Tell the views about it before deleting the KFileItems. They might need the subdirs'
751  // file items (see the dirtree).
752  if ( fileitem )
753  {
754  TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDir.url() + ":" + parentDir.internalReferenceURL()];
755  if ( listers ) {
756  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
757  kdl->emitDeleteItem( fileitem );
758  }
759  }
760  }
761 
762  // If we found a fileitem, we can test if it's a dir. If not, we'll go to deleteDir just in case.
763  if ( !fileitem || fileitem->isDir() )
764  {
765  // in case of a dir, check if we have any known children, there's much to do in that case
766  // (stopping jobs, removing dirs from cache etc.)
767  deleteDir( *it );
768  }
769 
770  // now remove the item itself
771  delete fileitem;
772  }
773 }
774 
775 void KDirListerCache::FilesChanged( const KURL::List &fileList )
776 {
777  KURL::List dirsToUpdate;
778  kdDebug(7004) << k_funcinfo << "only half implemented" << endl;
779  KURL::List::ConstIterator it = fileList.begin();
780  for ( ; it != fileList.end() ; ++it )
781  {
782  if ( ( *it ).isLocalFile() )
783  {
784  kdDebug(7004) << "KDirListerCache::FilesChanged " << *it << endl;
785  KFileItem *fileitem = findByURL( 0, *it );
786  if ( fileitem )
787  {
788  // we need to refresh the item, because e.g. the permissions can have changed.
789  aboutToRefreshItem( fileitem );
790  fileitem->refresh();
791  emitRefreshItem( fileitem );
792  }
793  else {
794  kdDebug(7004) << "item not found" << endl;
795  }
796  } else {
797  // For remote files, refresh() won't be able to figure out the new information.
798  // Let's update the dir.
799  KURL dir( *it );
800  dir.setPath( dir.directory( true ) );
801  if ( dirsToUpdate.find( dir ) == dirsToUpdate.end() ) {
802  dirsToUpdate.prepend( dir );
803  }
804  }
805  }
806 
807  KURL::List::ConstIterator itdir = dirsToUpdate.begin();
808  for ( ; itdir != dirsToUpdate.end() ; ++itdir ) {
809  updateDirectory( *itdir );
810  }
811  // ## TODO problems with current jobs listing/updating that dir
812  // ( see kde-2.2.2's kdirlister )
813 }
814 
815 void KDirListerCache::FileRenamed( const KURL &src, const KURL &dst )
816 {
817  kdDebug(7004) << k_funcinfo << src.prettyURL() << " -> " << dst.prettyURL() << endl;
818 #ifdef DEBUG_CACHE
819  printDebug();
820 #endif
821 
822  // Somehow this should only be called if src is a dir. But how could we know if it is?
823  // (Note that looking into itemsInUse isn't good enough. One could rename a subdir in a view.)
824  renameDir( src, dst );
825 
826  // Now update the KFileItem representing that file or dir (not exclusive with the above!)
827  KURL oldurl( src );
828  oldurl.adjustPath( -1 );
829  KFileItem *fileitem = findByURL( 0, oldurl );
830  if ( fileitem )
831  {
832  if ( !fileitem->isLocalFile() && !fileitem->localPath().isEmpty() ) // it uses UDS_LOCAL_PATH? ouch, needs an update then
833  FilesChanged( src );
834  else
835  {
836  aboutToRefreshItem( fileitem );
837  fileitem->setURL( dst );
838  fileitem->refreshMimeType();
839  emitRefreshItem( fileitem );
840  }
841  }
842 #ifdef DEBUG_CACHE
843  printDebug();
844 #endif
845 }
846 
847 void KDirListerCache::aboutToRefreshItem( KFileItem *fileitem )
848 {
849  // Look whether this item was shown in any view, i.e. held by any dirlister
850  KURL parentDir( fileitem->url() );
851  parentDir.setPath( parentDir.directory() );
852  TQString parentDirURL = parentDir.url();
853  TQString parentDirReferenceURL = parentDir.internalReferenceURL();
854  TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL + ":" + parentDirReferenceURL];
855  if ( listers )
856  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
857  kdl->aboutToRefreshItem( fileitem );
858 
859  // Also look in urlsCurrentlyListed, in case the user manages to rename during a listing
860  listers = urlsCurrentlyListed[parentDirURL + ":" + parentDirReferenceURL];
861  if ( listers )
862  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
863  kdl->aboutToRefreshItem( fileitem );
864 }
865 
866 void KDirListerCache::emitRefreshItem( KFileItem *fileitem )
867 {
868  // Look whether this item was shown in any view, i.e. held by any dirlister
869  KURL parentDir( fileitem->url() );
870  parentDir.setPath( parentDir.directory() );
871  TQString parentDirURL = parentDir.url();
872  TQString parentDirReferenceURL = parentDir.internalReferenceURL();
873  TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL + ":" + parentDirReferenceURL];
874  if ( listers )
875  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
876  {
877  kdl->addRefreshItem( fileitem );
878  kdl->emitItems();
879  }
880 
881  // Also look in urlsCurrentlyListed, in case the user manages to rename during a listing
882  listers = urlsCurrentlyListed[parentDirURL + ":" + parentDirReferenceURL];
883  if ( listers )
884  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
885  {
886  kdl->addRefreshItem( fileitem );
887  kdl->emitItems();
888  }
889 }
890 
891 KDirListerCache* KDirListerCache::self()
892 {
893  if ( !s_pSelf )
894  s_pSelf = sd_KDirListerCache.setObject( s_pSelf, new KDirListerCache );
895 
896  return s_pSelf;
897 }
898 
899 bool KDirListerCache::exists()
900 {
901  return s_pSelf != 0;
902 }
903 
904 
905 // private slots
906 
907 // _file can also be a directory being currently held!
908 void KDirListerCache::slotFileDirty( const KURL& _url )
909 {
910  kdDebug(7004) << k_funcinfo << _url << endl;
911 
912  if ( !pendingUpdates[_url.path()] )
913  {
914  KURL dir;
915  dir.setPath( _url.path() );
916  dir.setInternalReferenceURL(_url.internalReferenceURL());
917  if ( checkUpdate( dir, -1 ) ) {
918  updateDirectory( _url );
919  }
920 
921  // the parent directory of _url.path()
922  dir.setPath( dir.directory() );
923  dir.setInternalReferenceURL(_url.internalReferenceURL());
924  if ( checkUpdate( dir ) )
925  {
926  // Nice hack to save memory: use the qt object name to store the filename
927  TQTimer *timer = new TQTimer( this, _url.path().utf8() );
928  connect( timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotFileDirtyDelayed()) );
929  pendingUpdates.insert( _url.path(), timer );
930  timer->start( 500, true );
931  }
932  }
933 }
934 
935 // delayed updating of files, FAM is flooding us with events
936 void KDirListerCache::slotFileDirtyDelayed()
937 {
938  TQString file = TQString::fromUtf8( TQT_TQOBJECT_CONST(sender())->name() );
939 
940  kdDebug(7004) << k_funcinfo << file << endl;
941 
942  // TODO: do it better: don't always create/delete the TQTimer but reuse it.
943  // Delete the timer after the parent directory is removed from the cache.
944  pendingUpdates.remove( file );
945 
946  KURL u;
947  u.setPath( file );
948  KFileItem *item = findByURL( 0, u ); // search all items
949  if ( item )
950  {
951  // we need to refresh the item, because e.g. the permissions can have changed.
952  aboutToRefreshItem( item );
953  item->refresh();
954  emitRefreshItem( item );
955  }
956 }
957 
958 void KDirListerCache::slotFileCreated( const TQString& _file )
959 {
960  kdDebug(7004) << k_funcinfo << _file << endl;
961  // XXX: how to avoid a complete rescan here?
962  KURL u;
963  u.setPath( _file );
964  u.setPath( u.directory() );
965  FilesAdded( u );
966 }
967 
968 void KDirListerCache::slotFileDeleted( const TQString& _file )
969 {
970  kdDebug(7004) << k_funcinfo << _file << endl;
971  KURL u;
972  u.setPath( _file );
973  FilesRemoved( u );
974 }
975 
976 void KDirListerCache::slotEntries( TDEIO::Job *job, const TDEIO::UDSEntryList &entries )
977 {
978  KURL url = joburl( static_cast<TDEIO::ListJob *>(job) );
979  url.adjustPath(-1);
980  TQString urlStr = url.url();
981  TQString urlReferenceStr = url.internalReferenceURL();
982 
983  kdDebug(7004) << k_funcinfo << "new entries for " << url << endl;
984 
985  DirItem *dir = itemsInUse[urlStr + ":" + urlReferenceStr];
986  Q_ASSERT( dir );
987 
988  TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
989  Q_ASSERT( listers );
990  Q_ASSERT( !listers->isEmpty() );
991 
992  // check if anyone wants the mimetypes immediately
993  bool delayedMimeTypes = true;
994  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
995  delayedMimeTypes = delayedMimeTypes && kdl->d->delayedMimeTypes;
996  }
997 
998  // avoid creating these QStrings again and again
999  static const TQString& dot = TDEGlobal::staticQString(".");
1000  static const TQString& dotdot = TDEGlobal::staticQString("..");
1001 
1002  TDEIO::UDSEntryListConstIterator it = entries.begin();
1003  TDEIO::UDSEntryListConstIterator end = entries.end();
1004 
1005  for ( ; it != end; ++it )
1006  {
1007  TQString name;
1008 
1009  // find out about the name
1010  TDEIO::UDSEntry::ConstIterator entit = (*it).begin();
1011  for( ; entit != (*it).end(); ++entit ) {
1012  if ( (*entit).m_uds == TDEIO::UDS_NAME ) {
1013  name = (*entit).m_str;
1014  break;
1015  }
1016  }
1017 
1018  Q_ASSERT( !name.isEmpty() );
1019  if ( name.isEmpty() ) {
1020  continue;
1021  }
1022 
1023  if ( name == dot )
1024  {
1025  Q_ASSERT( !dir->rootItem );
1026  dir->rootItem = new KFileItem( *it, url, delayedMimeTypes, true );
1027 
1028  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1029  if ( !kdl->d->rootFileItem && kdl->d->url == url ) {
1030  kdl->d->rootFileItem = dir->rootItem;
1031  }
1032  }
1033  }
1034  else if ( name != dotdot )
1035  {
1036  KFileItem* item = new KFileItem( *it, url, delayedMimeTypes, true );
1037  Q_ASSERT( item );
1038 
1039  //kdDebug(7004)<< "Adding item: " << item->url() << endl;
1040  dir->lstItems->append( item );
1041 
1042  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1043  kdl->addNewItem( item );
1044  }
1045  }
1046  }
1047 
1048  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1049  kdl->emitItems();
1050  }
1051 }
1052 
1053 void KDirListerCache::slotResult( TDEIO::Job *j )
1054 {
1055  Q_ASSERT( j );
1056  TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1057  jobs.remove( job );
1058 
1059  KURL jobUrl = joburl( job );
1060  jobUrl.adjustPath(-1); // need remove trailing slashes again, in case of redirections
1061  TQString jobUrlStr = jobUrl.url();
1062  TQString jobReferenceUrlStr = jobUrl.internalReferenceURL();
1063 
1064  kdDebug(7004) << k_funcinfo << "finished listing " << jobUrl << endl;
1065 #ifdef DEBUG_CACHE
1066  printDebug();
1067 #endif
1068 
1069  TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( jobUrlStr + ":" + jobReferenceUrlStr );
1070  Q_ASSERT( listers );
1071 
1072  // move the directory to the held directories, do it before emitting
1073  // the signals to make sure it exists in KDirListerCache in case someone
1074  // calls listDir during the signal emission
1075  Q_ASSERT( !urlsCurrentlyHeld[jobUrlStr + ":" + jobReferenceUrlStr] );
1076  urlsCurrentlyHeld.insert( jobUrlStr + ":" + jobReferenceUrlStr, listers );
1077 
1078  KDirLister *kdl;
1079 
1080  if ( job->error() )
1081  {
1082  for ( kdl = listers->first(); kdl; kdl = listers->next() )
1083  {
1084  kdl->jobDone( job );
1085  kdl->handleError( job );
1086  emit kdl->canceled( jobUrl );
1087  if ( kdl->numJobs() == 0 )
1088  {
1089  kdl->d->complete = true;
1090  emit kdl->canceled();
1091  }
1092  }
1093  }
1094  else
1095  {
1096  DirItem *dir = itemsInUse[jobUrlStr + ":" + jobReferenceUrlStr];
1097  Q_ASSERT( dir );
1098  dir->complete = true;
1099 
1100  for ( kdl = listers->first(); kdl; kdl = listers->next() )
1101  {
1102  kdl->jobDone( job );
1103  kdl->emitCompleted( jobUrl );
1104  if ( kdl->numJobs() == 0 )
1105  {
1106  kdl->d->complete = true;
1107  emit kdl->completed();
1108  }
1109  }
1110  }
1111 
1112  // TODO: hmm, if there was an error and job is a parent of one or more
1113  // of the pending urls we should cancel it/them as well
1114  processPendingUpdates();
1115 
1116 #ifdef DEBUG_CACHE
1117  printDebug();
1118 #endif
1119 }
1120 
1121 void KDirListerCache::slotRedirection( TDEIO::Job *j, const KURL& url )
1122 {
1123  Q_ASSERT( j );
1124  TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1125 
1126  KURL oldUrl = job->url(); // here we really need the old url!
1127  KURL newUrl = url;
1128 
1129  // strip trailing slashes
1130  oldUrl.adjustPath(-1);
1131  newUrl.adjustPath(-1);
1132 
1133  if ( oldUrl == newUrl )
1134  {
1135  kdDebug(7004) << k_funcinfo << "New redirection url same as old, giving up." << endl;
1136  return;
1137  }
1138 
1139  kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
1140 
1141 #ifdef DEBUG_CACHE
1142  printDebug();
1143 #endif
1144 
1145  // I don't think there can be dirItems that are childs of oldUrl.
1146  // Am I wrong here? And even if so, we don't need to delete them, right?
1147  // DF: redirection happens before listDir emits any item. Makes little sense otherwise.
1148 
1149  // oldUrl cannot be in itemsCached because only completed items are moved there
1150  DirItem *dir = itemsInUse.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1151  Q_ASSERT( dir );
1152 
1153  TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1154  Q_ASSERT( listers );
1155  Q_ASSERT( !listers->isEmpty() );
1156 
1157  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1158  {
1159  // TODO: put in own method?
1160  if ( kdl->d->url.equals( oldUrl, true ) )
1161  {
1162  kdl->d->rootFileItem = 0;
1163  kdl->d->url = newUrl;
1164  }
1165 
1166  *kdl->d->lstDirs.find( oldUrl ) = newUrl;
1167 
1168  if ( kdl->d->lstDirs.count() == 1 )
1169  {
1170  emit kdl->clear();
1171  emit kdl->redirection( newUrl );
1172  emit kdl->redirection( oldUrl, newUrl );
1173  }
1174  else
1175  {
1176  emit kdl->clear( oldUrl );
1177  emit kdl->redirection( oldUrl, newUrl );
1178  }
1179  }
1180 
1181  // when a lister was stopped before the job emits the redirection signal, the old url will
1182  // also be in urlsCurrentlyHeld
1183  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1184  if ( holders )
1185  {
1186  Q_ASSERT( !holders->isEmpty() );
1187 
1188  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1189  {
1190  kdl->jobStarted( job );
1191 
1192  // do it like when starting a new list-job that will redirect later
1193  emit kdl->started( oldUrl );
1194 
1195  // TODO: maybe don't emit started if there's an update running for newUrl already?
1196 
1197  if ( kdl->d->url.equals( oldUrl, true ) )
1198  {
1199  kdl->d->rootFileItem = 0;
1200  kdl->d->url = newUrl;
1201  }
1202 
1203  *kdl->d->lstDirs.find( oldUrl ) = newUrl;
1204 
1205  if ( kdl->d->lstDirs.count() == 1 )
1206  {
1207  emit kdl->clear();
1208  emit kdl->redirection( newUrl );
1209  emit kdl->redirection( oldUrl, newUrl );
1210  }
1211  else
1212  {
1213  emit kdl->clear( oldUrl );
1214  emit kdl->redirection( oldUrl, newUrl );
1215  }
1216  }
1217  }
1218 
1219  DirItem *newDir = itemsInUse[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1220  if ( newDir )
1221  {
1222  kdDebug(7004) << "slotRedirection: " << newUrl.url() << " already in use" << endl;
1223 
1224  // only in this case there can newUrl already be in urlsCurrentlyListed or urlsCurrentlyHeld
1225  delete dir;
1226 
1227  // get the job if one's running for newUrl already (can be a list-job or an update-job), but
1228  // do not return this 'job', which would happen because of the use of redirectionURL()
1229  TDEIO::ListJob *oldJob = jobForUrl( newUrl.url() + ":" + newUrl.internalReferenceURL(), job );
1230 
1231  // listers of newUrl with oldJob: forget about the oldJob and use the already running one
1232  // which will be converted to an updateJob
1233  TQPtrList<KDirLister> *curListers = urlsCurrentlyListed[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1234  if ( curListers )
1235  {
1236  kdDebug(7004) << "slotRedirection: and it is currently listed" << endl;
1237 
1238  Q_ASSERT( oldJob ); // ?!
1239 
1240  for ( KDirLister *kdl = curListers->first(); kdl; kdl = curListers->next() ) // listers of newUrl
1241  {
1242  kdl->jobDone( oldJob );
1243 
1244  kdl->jobStarted( job );
1245  kdl->connectJob( job );
1246  }
1247 
1248  // append listers of oldUrl with newJob to listers of newUrl with oldJob
1249  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1250  curListers->append( kdl );
1251  }
1252  else {
1253  urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1254  }
1255 
1256  if ( oldJob ) // kill the old job, be it a list-job or an update-job
1257  killJob( oldJob );
1258 
1259  // holders of newUrl: use the already running job which will be converted to an updateJob
1260  TQPtrList<KDirLister> *curHolders = urlsCurrentlyHeld[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1261  if ( curHolders )
1262  {
1263  kdDebug(7004) << "slotRedirection: and it is currently held." << endl;
1264 
1265  for ( KDirLister *kdl = curHolders->first(); kdl; kdl = curHolders->next() ) // holders of newUrl
1266  {
1267  kdl->jobStarted( job );
1268  emit kdl->started( newUrl );
1269  }
1270 
1271  // append holders of oldUrl to holders of newUrl
1272  if ( holders )
1273  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1274  curHolders->append( kdl );
1275  }
1276  else if ( holders )
1277  urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1278 
1279 
1280  // emit old items: listers, holders. NOT: newUrlListers/newUrlHolders, they already have them listed
1281  // TODO: make this a separate method?
1282  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1283  {
1284  if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1285  kdl->d->rootFileItem = newDir->rootItem;
1286 
1287  kdl->addNewItems( *(newDir->lstItems) );
1288  kdl->emitItems();
1289  }
1290 
1291  if ( holders )
1292  {
1293  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1294  {
1295  if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1296  kdl->d->rootFileItem = newDir->rootItem;
1297 
1298  kdl->addNewItems( *(newDir->lstItems) );
1299  kdl->emitItems();
1300  }
1301  }
1302  }
1303  else if ( (newDir = itemsCached.take( newUrl.url() )) )
1304  {
1305  kdDebug(7004) << "slotRedirection: " << newUrl.url() << " is unused, but already in the cache." << endl;
1306 
1307  delete dir;
1308  itemsInUse.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), newDir );
1309  urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1310  if ( holders )
1311  urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1312 
1313  // emit old items: listers, holders
1314  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1315  {
1316  if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1317  kdl->d->rootFileItem = newDir->rootItem;
1318 
1319  kdl->addNewItems( *(newDir->lstItems) );
1320  kdl->emitItems();
1321  }
1322 
1323  if ( holders )
1324  {
1325  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1326  {
1327  if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1328  kdl->d->rootFileItem = newDir->rootItem;
1329 
1330  kdl->addNewItems( *(newDir->lstItems) );
1331  kdl->emitItems();
1332  }
1333  }
1334  }
1335  else
1336  {
1337  kdDebug(7004) << "slotRedirection: " << newUrl.url() << " has not been listed yet." << endl;
1338 
1339  delete dir->rootItem;
1340  dir->rootItem = 0;
1341  dir->lstItems->clear();
1342  dir->redirect( newUrl );
1343  itemsInUse.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), dir );
1344  urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1345 
1346  if ( holders )
1347  urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1348  else
1349  {
1350 #ifdef DEBUG_CACHE
1351  printDebug();
1352 #endif
1353  return; // only in this case the job doesn't need to be converted,
1354  }
1355  }
1356 
1357  // make the job an update job
1358  job->disconnect( this );
1359 
1360  connect( job, TQT_SIGNAL(entries( TDEIO::Job *, const TDEIO::UDSEntryList & )),
1361  this, TQT_SLOT(slotUpdateEntries( TDEIO::Job *, const TDEIO::UDSEntryList & )) );
1362  connect( job, TQT_SIGNAL(result( TDEIO::Job * )),
1363  this, TQT_SLOT(slotUpdateResult( TDEIO::Job * )) );
1364 
1365  // FIXME: autoUpdate-Counts!!
1366 
1367 #ifdef DEBUG_CACHE
1368  printDebug();
1369 #endif
1370 }
1371 
1372 void KDirListerCache::renameDir( const KURL &oldUrl, const KURL &newUrl )
1373 {
1374  kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
1375  TQString oldUrlStr = oldUrl.url(-1);
1376  TQString newUrlStr = newUrl.url(-1);
1377 
1378  // Not enough. Also need to look at any child dir, even sub-sub-sub-dir.
1379  //DirItem *dir = itemsInUse.take( oldUrlStr );
1380  //emitRedirections( oldUrl, url );
1381 
1382  // Look at all dirs being listed/shown
1383  TQDictIterator<DirItem> itu( itemsInUse );
1384  bool goNext;
1385  while ( itu.current() )
1386  {
1387  goNext = true;
1388  DirItem *dir = itu.current();
1389  TQString oldDirURLIndep = itu.currentKey();
1390  oldDirURLIndep.truncate(oldDirURLIndep.length() - (dir->url.internalReferenceURL().length()+strlen(":")));
1391  KURL oldDirUrl ( oldDirURLIndep );
1392  //kdDebug(7004) << "itemInUse: " << oldDirUrl.prettyURL() << endl;
1393  // Check if this dir is oldUrl, or a subfolder of it
1394  if ( oldUrl.isParentOf( oldDirUrl ) )
1395  {
1396  // TODO should use KURL::cleanpath like isParentOf does
1397  TQString relPath = oldDirUrl.path().mid( oldUrl.path().length() );
1398 
1399  KURL newDirUrl( newUrl ); // take new base
1400  if ( !relPath.isEmpty() ) {
1401  newDirUrl.addPath( relPath ); // add unchanged relative path
1402  }
1403  //kdDebug(7004) << "KDirListerCache::renameDir new url=" << newDirUrl.prettyURL() << endl;
1404 
1405  // Update URL in dir item and in itemsInUse
1406  dir->redirect( newDirUrl );
1407  itemsInUse.remove( itu.currentKey() ); // implies ++itu
1408  itemsInUse.insert( newDirUrl.url(-1), dir );
1409  goNext = false; // because of the implied ++itu above
1410  if ( dir->lstItems )
1411  {
1412  // Rename all items under that dir
1413  KFileItemListIterator kit( *dir->lstItems );
1414  for ( ; kit.current(); ++kit )
1415  {
1416  KURL oldItemUrl = (*kit)->url();
1417  TQString oldItemUrlStr( oldItemUrl.url(-1) );
1418  KURL newItemUrl( oldItemUrl );
1419  newItemUrl.setPath( newDirUrl.path() );
1420  newItemUrl.addPath( oldItemUrl.fileName() );
1421  kdDebug(7004) << "KDirListerCache::renameDir renaming " << oldItemUrlStr << " to " << newItemUrl.url() << endl;
1422  (*kit)->setURL( newItemUrl );
1423  }
1424  }
1425  emitRedirections( oldDirUrl, newDirUrl );
1426  }
1427  if ( goNext )
1428  ++itu;
1429  }
1430 
1431  // Is oldUrl a directory in the cache?
1432  // Remove any child of oldUrl from the cache - even if the renamed dir itself isn't in it!
1433  removeDirFromCache( oldUrl );
1434  // TODO rename, instead.
1435 }
1436 
1437 void KDirListerCache::emitRedirections( const KURL &oldUrl, const KURL &url )
1438 {
1439  kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << url.prettyURL() << endl;
1440  TQString oldUrlStr = oldUrl.url(-1);
1441  TQString urlStr = url.url(-1);
1442  TQString oldReferenceUrlStr = oldUrl.internalReferenceURL();
1443  TQString urlReferenceStr = url.internalReferenceURL();
1444 
1445  TDEIO::ListJob *job = jobForUrl( oldUrlStr + ":" + oldReferenceUrlStr );
1446  if ( job )
1447  killJob( job );
1448 
1449  // Check if we were listing this dir. Need to abort and restart with new name in that case.
1450  TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrlStr + ":" + oldReferenceUrlStr );
1451  if ( listers )
1452  {
1453  // Tell the world that the job listing the old url is dead.
1454  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1455  {
1456  if ( job )
1457  kdl->jobDone( job );
1458 
1459  emit kdl->canceled( oldUrl );
1460  }
1461 
1462  urlsCurrentlyListed.insert( urlStr + ":" + urlReferenceStr, listers );
1463  }
1464 
1465  // Check if we are currently displaying this directory (odds opposite wrt above)
1466  // Update urlsCurrentlyHeld dict with new URL
1467  TQPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrlStr + ":" + oldReferenceUrlStr );
1468  if ( holders )
1469  {
1470  if ( job )
1471  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1472  kdl->jobDone( job );
1473 
1474  urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, holders );
1475  }
1476 
1477  if ( listers )
1478  {
1479  updateDirectory( url );
1480 
1481  // Tell the world about the new url
1482  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1483  emit kdl->started( url );
1484  }
1485 
1486  if ( holders )
1487  {
1488  // And notify the dirlisters of the redirection
1489  for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1490  {
1491  *kdl->d->lstDirs.find( oldUrl ) = url;
1492 
1493  if ( kdl->d->lstDirs.count() == 1 )
1494  emit kdl->redirection( url );
1495 
1496  emit kdl->redirection( oldUrl, url );
1497  }
1498  }
1499 }
1500 
1501 void KDirListerCache::removeDirFromCache( const KURL& dir )
1502 {
1503  kdDebug(7004) << "KDirListerCache::removeDirFromCache " << dir.prettyURL() << endl;
1504  TQCacheIterator<DirItem> itc( itemsCached );
1505  while ( itc.current() )
1506  {
1507  if ( dir.isParentOf( KURL( itc.currentKey() ) ) )
1508  itemsCached.remove( itc.currentKey() );
1509  else
1510  ++itc;
1511  }
1512 }
1513 
1514 void KDirListerCache::slotUpdateEntries( TDEIO::Job* job, const TDEIO::UDSEntryList& list )
1515 {
1516  jobs[static_cast<TDEIO::ListJob*>(job)] += list;
1517 }
1518 
1519 void KDirListerCache::slotUpdateResult( TDEIO::Job * j )
1520 {
1521  Q_ASSERT( j );
1522  TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1523 
1524  KURL jobUrl = joburl( job );
1525  jobUrl.adjustPath(-1); // need remove trailing slashes again, in case of redirections
1526  TQString jobUrlStr = jobUrl.url();
1527  TQString jobReferenceUrlStr = jobUrl.internalReferenceURL();
1528 
1529  kdDebug(7004) << k_funcinfo << "finished update " << jobUrl << endl;
1530 
1531  KDirLister *kdl;
1532 
1533  TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[jobUrlStr + ":" + jobReferenceUrlStr];
1534  TQPtrList<KDirLister> *tmpLst = urlsCurrentlyListed.take( jobUrlStr + ":" + jobReferenceUrlStr );
1535 
1536  if ( tmpLst )
1537  {
1538  if ( listers )
1539  for ( kdl = tmpLst->first(); kdl; kdl = tmpLst->next() )
1540  {
1541  Q_ASSERT( listers->containsRef( kdl ) == 0 );
1542  listers->append( kdl );
1543  }
1544  else
1545  {
1546  listers = tmpLst;
1547  urlsCurrentlyHeld.insert( jobUrlStr + ":" + jobReferenceUrlStr, listers );
1548  }
1549  }
1550 
1551  // once we are updating dirs that are only in the cache this will fail!
1552  Q_ASSERT( listers );
1553 
1554  if ( job->error() )
1555  {
1556  for ( kdl = listers->first(); kdl; kdl = listers->next() )
1557  {
1558  kdl->jobDone( job );
1559 
1560  //don't bother the user
1561  //kdl->handleError( job );
1562 
1563  emit kdl->canceled( jobUrl );
1564  if ( kdl->numJobs() == 0 )
1565  {
1566  kdl->d->complete = true;
1567  emit kdl->canceled();
1568  }
1569  }
1570 
1571  jobs.remove( job );
1572 
1573  // TODO: if job is a parent of one or more
1574  // of the pending urls we should cancel them
1575  processPendingUpdates();
1576  return;
1577  }
1578 
1579  DirItem *dir = itemsInUse[jobUrlStr + ":" + jobReferenceUrlStr];
1580  dir->complete = true;
1581 
1582 
1583  // check if anyone wants the mimetypes immediately
1584  bool delayedMimeTypes = true;
1585  for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1586  delayedMimeTypes = delayedMimeTypes && kdl->d->delayedMimeTypes;
1587  }
1588 
1589  // should be enough to get reasonable speed in most cases
1590  TQDict<KFileItem> fileItems( 9973 );
1591 
1592  KFileItemListIterator kit ( *(dir->lstItems) );
1593 
1594  // Unmark all items in url
1595  for ( ; kit.current(); ++kit )
1596  {
1597  (*kit)->unmark();
1598  if (!((*kit)->listerURL().isEmpty())) {
1599  fileItems.insert( (*kit)->listerURL().url(), *kit );
1600  }
1601  else {
1602  fileItems.insert( (*kit)->url().url(), *kit );
1603  }
1604  }
1605 
1606  static const TQString& dot = TDEGlobal::staticQString(".");
1607  static const TQString& dotdot = TDEGlobal::staticQString("..");
1608 
1609  KFileItem *item = 0, *tmp;
1610 
1611  TQValueList<TDEIO::UDSEntry> buf = jobs[job];
1612  TQValueListIterator<TDEIO::UDSEntry> it = buf.begin();
1613  for ( ; it != buf.end(); ++it )
1614  {
1615  // Form the complete url
1616  if ( !item ) {
1617  item = new KFileItem( *it, jobUrl, delayedMimeTypes, true );
1618  }
1619  else {
1620  item->setUDSEntry( *it, jobUrl, delayedMimeTypes, true );
1621  }
1622 
1623  // Find out about the name
1624  TQString name = item->name();
1625  Q_ASSERT( !name.isEmpty() );
1626 
1627  // we duplicate the check for dotdot here, to avoid iterating over
1628  // all items again and checking in matchesFilter() that way.
1629  if ( name.isEmpty() || name == dotdot ) {
1630  continue;
1631  }
1632 
1633  if ( name == dot )
1634  {
1635  // if the update was started before finishing the original listing
1636  // there is no root item yet
1637  if ( !dir->rootItem )
1638  {
1639  dir->rootItem = item;
1640  item = 0;
1641 
1642  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1643  if ( !kdl->d->rootFileItem && kdl->d->url == jobUrl ) {
1644  kdl->d->rootFileItem = dir->rootItem;
1645  }
1646  }
1647  }
1648 
1649  continue;
1650  }
1651 
1652  // Find this item
1653  if ( (tmp = fileItems[item->url().url()]) )
1654  {
1655  tmp->mark();
1656 
1657  // check if something changed for this file
1658  if ( !tmp->cmp( *item ) )
1659  {
1660  for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1661  kdl->aboutToRefreshItem( tmp );
1662  }
1663 
1664  //kdDebug(7004) << "slotUpdateResult: file changed: " << tmp->name() << endl;
1665  tmp->assign( *item );
1666 
1667  for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1668  kdl->addRefreshItem( tmp );
1669  }
1670  }
1671  }
1672  else // this is a new file
1673  {
1674  //kdDebug(7004) << "slotUpdateResult: new file: " << name << endl;
1675 
1676  item->mark();
1677  dir->lstItems->append( item );
1678 
1679  for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1680  kdl->addNewItem( item );
1681  }
1682 
1683  // item used, we need a new one for the next iteration
1684  item = 0;
1685  }
1686  }
1687 
1688  if ( item ) {
1689  delete item;
1690  }
1691 
1692  jobs.remove( job );
1693 
1694  deleteUnmarkedItems( listers, dir->lstItems );
1695 
1696  for ( kdl = listers->first(); kdl; kdl = listers->next() )
1697  {
1698  kdl->emitItems();
1699 
1700  kdl->jobDone( job );
1701 
1702  kdl->emitCompleted( jobUrl );
1703  if ( kdl->numJobs() == 0 )
1704  {
1705  kdl->d->complete = true;
1706  emit kdl->completed();
1707  }
1708  }
1709 
1710  // TODO: hmm, if there was an error and job is a parent of one or more
1711  // of the pending urls we should cancel it/them as well
1712  processPendingUpdates();
1713 }
1714 
1715 // private
1716 
1717 TDEIO::ListJob *KDirListerCache::jobForUrl( const TQString& url, TDEIO::ListJob *not_job )
1718 {
1719  TDEIO::ListJob *job;
1720  TQMap< TDEIO::ListJob *, TQValueList<TDEIO::UDSEntry> >::Iterator it = jobs.begin();
1721  while ( it != jobs.end() )
1722  {
1723  job = it.key();
1724  KURL itjoburl = joburl( job );
1725  if ( ((itjoburl.url(-1) + ":" + itjoburl.internalReferenceURL()) == url) && (job != not_job) ) {
1726  return job;
1727  }
1728  ++it;
1729  }
1730  return 0;
1731 }
1732 
1733 const KURL& KDirListerCache::joburl( TDEIO::ListJob *job )
1734 {
1735  if ( job->redirectionURL().isValid() ) {
1736  return job->redirectionURL();
1737  }
1738  else {
1739  return job->url();
1740  }
1741 }
1742 
1743 void KDirListerCache::killJob( TDEIO::ListJob *job )
1744 {
1745  jobs.remove( job );
1746  job->disconnect( this );
1747  job->kill();
1748 }
1749 
1750 void KDirListerCache::deleteUnmarkedItems( TQPtrList<KDirLister> *listers, KFileItemList *lstItems )
1751 {
1752  // Find all unmarked items and delete them
1753  KFileItem* item;
1754  lstItems->first();
1755  while ( (item = lstItems->current()) )
1756  if ( !item->isMarked() )
1757  {
1758  //kdDebug() << k_funcinfo << item->name() << endl;
1759  for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1760  kdl->emitDeleteItem( item );
1761  }
1762 
1763  if ( item->isDir() ) {
1764  deleteDir( item->url() );
1765  }
1766 
1767  // finally actually delete the item
1768  lstItems->take();
1769  delete item;
1770  }
1771  else
1772  lstItems->next();
1773 }
1774 
1775 void KDirListerCache::deleteDir( const KURL& dirUrl )
1776 {
1777  //kdDebug() << k_funcinfo << dirUrl.prettyURL() << endl;
1778  // unregister and remove the childs of the deleted item.
1779  // Idea: tell all the KDirListers that they should forget the dir
1780  // and then remove it from the cache.
1781 
1782  TQDictIterator<DirItem> itu( itemsInUse );
1783  while ( itu.current() )
1784  {
1785  TQString deletedUrlIndep = itu.currentKey();
1786  deletedUrlIndep.truncate(deletedUrlIndep.length() - ((*itu)->url.internalReferenceURL().length()+strlen(":")));
1787  KURL deletedUrl( deletedUrlIndep );
1788  if ( dirUrl.isParentOf( deletedUrl ) )
1789  {
1790  // stop all jobs for deletedUrl
1791 
1792  TQPtrList<KDirLister> *kdls = urlsCurrentlyListed[deletedUrl.url() + ":" + deletedUrl.internalReferenceURL()];
1793  if ( kdls ) // yeah, I lack good names
1794  {
1795  // we need a copy because stop modifies the list
1796  kdls = new TQPtrList<KDirLister>( *kdls );
1797  for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
1798  stop( kdl, deletedUrl );
1799 
1800  delete kdls;
1801  }
1802 
1803  // tell listers holding deletedUrl to forget about it
1804  // this will stop running updates for deletedUrl as well
1805 
1806  kdls = urlsCurrentlyHeld[deletedUrl.url() + ":" + deletedUrl.internalReferenceURL()];
1807  if ( kdls )
1808  {
1809  // we need a copy because forgetDirs modifies the list
1810  kdls = new TQPtrList<KDirLister>( *kdls );
1811 
1812  for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
1813  {
1814  // lister's root is the deleted item
1815  if ( kdl->d->url == deletedUrl )
1816  {
1817  // tell the view first. It might need the subdirs' items (which forgetDirs will delete)
1818  if ( kdl->d->rootFileItem )
1819  emit kdl->deleteItem( kdl->d->rootFileItem );
1820  forgetDirs( kdl );
1821  kdl->d->rootFileItem = 0;
1822  }
1823  else
1824  {
1825  bool treeview = kdl->d->lstDirs.count() > 1;
1826  if ( !treeview )
1827  emit kdl->clear();
1828 
1829  forgetDirs( kdl, deletedUrl, treeview );
1830  }
1831  }
1832 
1833  delete kdls;
1834  }
1835 
1836  // delete the entry for deletedUrl - should not be needed, it's in
1837  // items cached now
1838 
1839  DirItem *dir = itemsInUse.take( deletedUrl.url() + ":" + deletedUrl.internalReferenceURL() );
1840  Q_ASSERT( !dir );
1841  if ( !dir ) // take didn't find it - move on
1842  ++itu;
1843  }
1844  else
1845  ++itu;
1846  }
1847 
1848  // remove the children from the cache
1849  removeDirFromCache( dirUrl );
1850 }
1851 
1852 void KDirListerCache::processPendingUpdates()
1853 {
1854  // TODO
1855 }
1856 
1857 #ifndef NDEBUG
1858 void KDirListerCache::printDebug()
1859 {
1860  kdDebug(7004) << "Items in use: " << endl;
1861  TQDictIterator<DirItem> itu( itemsInUse );
1862  for ( ; itu.current() ; ++itu ) {
1863  kdDebug(7004) << " " << itu.currentKey() << " URL: " << itu.current()->url
1864  << " rootItem: " << ( itu.current()->rootItem ? itu.current()->rootItem->url() : KURL() )
1865  << " autoUpdates refcount: " << itu.current()->autoUpdates
1866  << " complete: " << itu.current()->complete
1867  << ( itu.current()->lstItems ? TQString(" with %1 items.").arg(itu.current()->lstItems->count()) : TQString(" lstItems=NULL") ) << endl;
1868  }
1869 
1870  kdDebug(7004) << "urlsCurrentlyHeld: " << endl;
1871  TQDictIterator< TQPtrList<KDirLister> > it( urlsCurrentlyHeld );
1872  for ( ; it.current() ; ++it )
1873  {
1874  TQString list;
1875  for ( TQPtrListIterator<KDirLister> listit( *it.current() ); listit.current(); ++listit )
1876  list += " 0x" + TQString::number( (long)listit.current(), 16 );
1877  kdDebug(7004) << " " << it.currentKey() << " " << it.current()->count() << " listers: " << list << endl;
1878  }
1879 
1880  kdDebug(7004) << "urlsCurrentlyListed: " << endl;
1881  TQDictIterator< TQPtrList<KDirLister> > it2( urlsCurrentlyListed );
1882  for ( ; it2.current() ; ++it2 )
1883  {
1884  TQString list;
1885  for ( TQPtrListIterator<KDirLister> listit( *it2.current() ); listit.current(); ++listit )
1886  list += " 0x" + TQString::number( (long)listit.current(), 16 );
1887  kdDebug(7004) << " " << it2.currentKey() << " " << it2.current()->count() << " listers: " << list << endl;
1888  }
1889 
1890  TQMap< TDEIO::ListJob *, TQValueList<TDEIO::UDSEntry> >::Iterator jit = jobs.begin();
1891  kdDebug(7004) << "Jobs: " << endl;
1892  for ( ; jit != jobs.end() ; ++jit )
1893  kdDebug(7004) << " " << jit.key() << " listing " << joburl( jit.key() ).prettyURL() << ": " << (*jit).count() << " entries." << endl;
1894 
1895  kdDebug(7004) << "Items in cache: " << endl;
1896  TQCacheIterator<DirItem> itc( itemsCached );
1897  for ( ; itc.current() ; ++itc )
1898  kdDebug(7004) << " " << itc.currentKey() << " rootItem: "
1899  << ( itc.current()->rootItem ? itc.current()->rootItem->url().prettyURL() : TQString("NULL") )
1900  << ( itc.current()->lstItems ? TQString(" with %1 items.").arg(itc.current()->lstItems->count()) : TQString(" lstItems=NULL") ) << endl;
1901 }
1902 #endif
1903 
1904 /*********************** -- The new KDirLister -- ************************/
1905 
1906 
1907 KDirLister::KDirLister( bool _delayedMimeTypes )
1908 {
1909  kdDebug(7003) << "+KDirLister" << endl;
1910 
1911  d = new KDirListerPrivate;
1912 
1913  d->complete = true;
1914  d->delayedMimeTypes = _delayedMimeTypes;
1915 
1916  setAutoUpdate( true );
1917  setDirOnlyMode( false );
1918  setShowingDotFiles( false );
1919 
1920  setAutoErrorHandlingEnabled( true, 0 );
1921 }
1922 
1923 KDirLister::~KDirLister()
1924 {
1925  kdDebug(7003) << "-KDirLister" << endl;
1926 
1927  if ( KDirListerCache::exists() )
1928  {
1929  // Stop all running jobs
1930  stop();
1931  s_pCache->forgetDirs( this );
1932  }
1933 
1934  delete d;
1935 }
1936 
1937 bool KDirLister::openURL( const KURL& _url, bool _keep, bool _reload )
1938 {
1939  kdDebug(7003) << k_funcinfo << _url.prettyURL()
1940  << " keep=" << _keep << " reload=" << _reload << endl;
1941 
1942  // emit the current changes made to avoid an inconsistent treeview
1943  if ( d->changes != NONE && _keep ) {
1944  emitChanges();
1945  }
1946 
1947  d->changes = NONE;
1948 
1949  // If a local path is available, monitor that instead of the given remote URL...
1950  if (!_url.isLocalFile()) {
1951  TDEIO::LocalURLJob* localURLJob = TDEIO::localURL(_url);
1952  if (localURLJob) {
1953  d->openURL_url[localURLJob] = _url;
1954  d->openURL_keep[localURLJob] = _keep;
1955  d->openURL_reload[localURLJob] = _reload;
1956  connect(localURLJob, TQT_SIGNAL(localURL(TDEIO::LocalURLJob*, const KURL&, bool)), this, TQT_SLOT(slotOpenURLGotLocalURL(TDEIO::LocalURLJob*, const KURL&, bool)));
1957  connect(localURLJob, TQT_SIGNAL(destroyed()), this, TQT_SLOT(slotLocalURLKIODestroyed()));
1958  }
1959  return true;
1960  }
1961  else {
1962  return s_pCache->listDir( this, _url, _keep, _reload );
1963  }
1964 }
1965 
1966 void KDirLister::slotOpenURLGotLocalURL(TDEIO::LocalURLJob *job, const KURL& url, bool isLocal) {
1967  KURL realURL = d->openURL_url[job];
1968  if (isLocal) {
1969  realURL = url;
1970  realURL.setInternalReferenceURL(d->openURL_url[job].url());
1971  d->m_referenceURLMap[d->openURL_url[job].url()] = url.path();
1972  }
1973  s_pCache->listDir( this, realURL, d->openURL_keep[job], d->openURL_reload[job] );
1974  d->openURL_url.remove(job);
1975  d->openURL_keep.remove(job);
1976  d->openURL_reload.remove(job);
1977 }
1978 
1979 void KDirLister::slotLocalURLKIODestroyed() {
1980  TDEIO::LocalURLJob* terminatedJob = const_cast<TDEIO::LocalURLJob*>(static_cast<const TDEIO::LocalURLJob*>(sender()));
1981 
1982  if (d->openURL_url.contains(terminatedJob)) {
1983  s_pCache->listDir( this, d->openURL_url[terminatedJob], d->openURL_keep[terminatedJob], d->openURL_reload[terminatedJob] );
1984  d->openURL_url.remove(terminatedJob);
1985  d->openURL_keep.remove(terminatedJob);
1986  d->openURL_reload.remove(terminatedJob);
1987  }
1988 }
1989 
1990 void KDirLister::stop()
1991 {
1992  kdDebug(7003) << k_funcinfo << endl;
1993  s_pCache->stop( this );
1994  d->m_referenceURLMap.clear();
1995 }
1996 
1997 void KDirLister::stop( const KURL& _url )
1998 {
1999  kdDebug(7003) << k_funcinfo << _url.prettyURL() << endl;
2000  s_pCache->stop( this, _url );
2001  d->m_referenceURLMap.remove(_url.url());
2002 }
2003 
2004 bool KDirLister::autoUpdate() const
2005 {
2006  return d->autoUpdate;
2007 }
2008 
2009 void KDirLister::setAutoUpdate( bool _enable )
2010 {
2011  if ( d->autoUpdate == _enable )
2012  return;
2013 
2014  d->autoUpdate = _enable;
2015  s_pCache->setAutoUpdate( this, _enable );
2016 }
2017 
2018 bool KDirLister::showingDotFiles() const
2019 {
2020  return d->isShowingDotFiles;
2021 }
2022 
2023 void KDirLister::setShowingDotFiles( bool _showDotFiles )
2024 {
2025  if ( d->isShowingDotFiles == _showDotFiles )
2026  return;
2027 
2028  d->isShowingDotFiles = _showDotFiles;
2029  d->changes ^= DOT_FILES;
2030 }
2031 
2032 bool KDirLister::dirOnlyMode() const
2033 {
2034  return d->dirOnlyMode;
2035 }
2036 
2037 void KDirLister::setDirOnlyMode( bool _dirsOnly )
2038 {
2039  if ( d->dirOnlyMode == _dirsOnly )
2040  return;
2041 
2042  d->dirOnlyMode = _dirsOnly;
2043  d->changes ^= DIR_ONLY_MODE;
2044 }
2045 
2046 bool KDirLister::autoErrorHandlingEnabled() const
2047 {
2048  return d->autoErrorHandling;
2049 }
2050 
2051 void KDirLister::setAutoErrorHandlingEnabled( bool enable, TQWidget* parent )
2052 {
2053  d->autoErrorHandling = enable;
2054  d->errorParent = parent;
2055 }
2056 
2057 const KURL& KDirLister::url() const
2058 {
2059  return d->url;
2060 }
2061 
2062 const KURL::List& KDirLister::directories() const
2063 {
2064  return d->lstDirs;
2065 }
2066 
2067 void KDirLister::emitChanges()
2068 {
2069  if ( d->changes == NONE )
2070  return;
2071 
2072  static const TQString& dot = TDEGlobal::staticQString(".");
2073  static const TQString& dotdot = TDEGlobal::staticQString("..");
2074 
2075  for ( KURL::List::Iterator it = d->lstDirs.begin();
2076  it != d->lstDirs.end(); ++it )
2077  {
2078  KFileItemListIterator kit( *s_pCache->itemsForDir( *it ) );
2079  for ( ; kit.current(); ++kit )
2080  {
2081  if ( (*kit)->text() == dot || (*kit)->text() == dotdot )
2082  continue;
2083 
2084  bool oldMime = true, newMime = true;
2085 
2086  if ( d->changes & MIME_FILTER )
2087  {
2088  oldMime = doMimeFilter( (*kit)->mimetype(), d->oldMimeFilter )
2089  && doMimeExcludeFilter( (*kit)->mimetype(), d->oldMimeExcludeFilter );
2090  newMime = doMimeFilter( (*kit)->mimetype(), d->mimeFilter )
2091  && doMimeExcludeFilter( (*kit)->mimetype(), d->mimeExcludeFilter );
2092 
2093  if ( oldMime && !newMime )
2094  {
2095  emit deleteItem( *kit );
2096  continue;
2097  }
2098  }
2099 
2100  if ( d->changes & DIR_ONLY_MODE )
2101  {
2102  // the lister switched to dirOnlyMode
2103  if ( d->dirOnlyMode )
2104  {
2105  if ( !(*kit)->isDir() )
2106  emit deleteItem( *kit );
2107  }
2108  else if ( !(*kit)->isDir() ) {
2109  addNewItem( *kit );
2110  }
2111 
2112  continue;
2113  }
2114 
2115  if ( (*kit)->isHidden() )
2116  {
2117  if ( d->changes & DOT_FILES )
2118  {
2119  // the lister switched to dot files mode
2120  if ( d->isShowingDotFiles ) {
2121  addNewItem( *kit );
2122  }
2123  else {
2124  emit deleteItem( *kit );
2125  }
2126 
2127  continue;
2128  }
2129  }
2130  else if ( d->changes & NAME_FILTER )
2131  {
2132  bool oldName = (*kit)->isDir() ||
2133  d->oldFilters.isEmpty() ||
2134  doNameFilter( (*kit)->text(), d->oldFilters );
2135 
2136  bool newName = (*kit)->isDir() ||
2137  d->lstFilters.isEmpty() ||
2138  doNameFilter( (*kit)->text(), d->lstFilters );
2139 
2140  if ( oldName && !newName )
2141  {
2142  emit deleteItem( *kit );
2143  continue;
2144  }
2145  else if ( !oldName && newName ) {
2146  addNewItem( *kit );
2147  }
2148  }
2149 
2150  if ( (d->changes & MIME_FILTER) && !oldMime && newMime ) {
2151  addNewItem( *kit );
2152  }
2153  }
2154 
2155  emitItems();
2156  }
2157 
2158  d->changes = NONE;
2159 }
2160 
2161 void KDirLister::updateDirectory( const KURL& _u )
2162 {
2163  s_pCache->updateDirectory( _u );
2164 }
2165 
2166 bool KDirLister::isFinished() const
2167 {
2168  return d->complete;
2169 }
2170 
2171 KFileItem *KDirLister::rootItem() const
2172 {
2173  return d->rootFileItem;
2174 }
2175 
2176 KFileItem *KDirLister::findByURL( const KURL& _url ) const
2177 {
2178  return s_pCache->findByURL( this, _url );
2179 }
2180 
2181 KFileItem *KDirLister::findByName( const TQString& _name ) const
2182 {
2183  return s_pCache->findByName( this, _name );
2184 }
2185 
2186 #ifndef KDE_NO_COMPAT
2187 KFileItem *KDirLister::find( const KURL& _url ) const
2188 {
2189  return findByURL( _url );
2190 }
2191 #endif
2192 
2193 
2194 // ================ public filter methods ================ //
2195 
2196 void KDirLister::setNameFilter( const TQString& nameFilter )
2197 {
2198  if ( !(d->changes & NAME_FILTER) )
2199  {
2200  d->oldFilters = d->lstFilters;
2201  d->lstFilters.setAutoDelete( false );
2202  }
2203 
2204  d->lstFilters.clear();
2205  d->lstFilters.setAutoDelete( true );
2206 
2207  d->nameFilter = nameFilter;
2208 
2209  // Split on white space
2210  TQStringList list = TQStringList::split( ' ', nameFilter );
2211  for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
2212  d->lstFilters.append( new TQRegExp(*it, false, true ) );
2213 
2214  d->changes |= NAME_FILTER;
2215 }
2216 
2217 const TQString& KDirLister::nameFilter() const
2218 {
2219  return d->nameFilter;
2220 }
2221 
2222 void KDirLister::setMimeFilter( const TQStringList& mimeFilter )
2223 {
2224  if ( !(d->changes & MIME_FILTER) )
2225  d->oldMimeFilter = d->mimeFilter;
2226 
2227  if ( mimeFilter.find("all/allfiles") != mimeFilter.end() ||
2228  mimeFilter.find("all/all") != mimeFilter.end() )
2229  d->mimeFilter.clear();
2230  else
2231  d->mimeFilter = mimeFilter;
2232 
2233  d->changes |= MIME_FILTER;
2234 }
2235 
2236 void KDirLister::setMimeExcludeFilter( const TQStringList& mimeExcludeFilter )
2237 {
2238  if ( !(d->changes & MIME_FILTER) )
2239  d->oldMimeExcludeFilter = d->mimeExcludeFilter;
2240 
2241  d->mimeExcludeFilter = mimeExcludeFilter;
2242  d->changes |= MIME_FILTER;
2243 }
2244 
2245 
2246 void KDirLister::clearMimeFilter()
2247 {
2248  if ( !(d->changes & MIME_FILTER) )
2249  {
2250  d->oldMimeFilter = d->mimeFilter;
2251  d->oldMimeExcludeFilter = d->mimeExcludeFilter;
2252  }
2253  d->mimeFilter.clear();
2254  d->mimeExcludeFilter.clear();
2255  d->changes |= MIME_FILTER;
2256 }
2257 
2258 const TQStringList& KDirLister::mimeFilters() const
2259 {
2260  return d->mimeFilter;
2261 }
2262 
2263 bool KDirLister::matchesFilter( const TQString& name ) const
2264 {
2265  return doNameFilter( name, d->lstFilters );
2266 }
2267 
2268 bool KDirLister::matchesMimeFilter( const TQString& mime ) const
2269 {
2270  return doMimeFilter( mime, d->mimeFilter ) && doMimeExcludeFilter(mime,d->mimeExcludeFilter);
2271 }
2272 
2273 // ================ protected methods ================ //
2274 
2275 bool KDirLister::matchesFilter( const KFileItem *item ) const
2276 {
2277  Q_ASSERT( item );
2278  static const TQString& dotdot = TDEGlobal::staticQString("..");
2279 
2280  if ( item->text() == dotdot )
2281  return false;
2282 
2283  if ( !d->isShowingDotFiles && item->isHidden() )
2284  return false;
2285 
2286  if ( item->isDir() || d->lstFilters.isEmpty() )
2287  return true;
2288 
2289  return matchesFilter( item->text() );
2290 }
2291 
2292 bool KDirLister::matchesMimeFilter( const KFileItem *item ) const
2293 {
2294  Q_ASSERT( item );
2295  // Don't lose time determining the mimetype if there is no filter
2296  if ( d->mimeFilter.isEmpty() && d->mimeExcludeFilter.isEmpty() )
2297  return true;
2298  return matchesMimeFilter( item->mimetype() );
2299 }
2300 
2301 bool KDirLister::doNameFilter( const TQString& name, const TQPtrList<TQRegExp>& filters ) const
2302 {
2303  for ( TQPtrListIterator<TQRegExp> it( filters ); it.current(); ++it )
2304  if ( it.current()->exactMatch( name ) )
2305  return true;
2306 
2307  return false;
2308 }
2309 
2310 bool KDirLister::doMimeFilter( const TQString& mime, const TQStringList& filters ) const
2311 {
2312  if ( filters.isEmpty() )
2313  return true;
2314 
2315  KMimeType::Ptr mimeptr = KMimeType::mimeType(mime);
2316  //kdDebug(7004) << "doMimeFilter: investigating: "<<mimeptr->name()<<endl;
2317  TQStringList::ConstIterator it = filters.begin();
2318  for ( ; it != filters.end(); ++it )
2319  if ( mimeptr->is(*it) )
2320  return true;
2321  //else kdDebug(7004) << "doMimeFilter: compared without result to "<<*it<<endl;
2322 
2323 
2324  return false;
2325 }
2326 
2327 bool KDirLister::doMimeExcludeFilter( const TQString& mime, const TQStringList& filters ) const
2328 {
2329  if ( filters.isEmpty() )
2330  return true;
2331 
2332  TQStringList::ConstIterator it = filters.begin();
2333  for ( ; it != filters.end(); ++it )
2334  if ( (*it) == mime )
2335  return false;
2336 
2337  return true;
2338 }
2339 
2340 
2341 bool KDirLister::validURL( const KURL& _url ) const
2342 {
2343  return s_pCache->validURL( this, _url );
2344 }
2345 
2346 void KDirLister::handleError( TDEIO::Job *job )
2347 {
2348  if ( d->autoErrorHandling ) {
2349  job->showErrorDialog( d->errorParent );
2350  }
2351 }
2352 
2353 
2354 // ================= private methods ================= //
2355 
2356 void KDirLister::addNewItem( const KFileItem *item )
2357 {
2358  TQString refURL = item->url().internalReferenceURL();
2359  if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2360  item->url().path().startsWith(d->m_referenceURLMap[refURL]))
2361  {
2362  // Likely a media:/ tdeioslave URL or similar
2363  // Rewrite the URL to ensure that the user remains within the media:/ tree!
2364  if (!refURL.endsWith("/"))
2365  {
2366  refURL.append("/");
2367  }
2368  KURL newItemURL(refURL);
2369  newItemURL.addPath(item->url().fileName());
2370  const_cast<KFileItem*>(item)->setListerURL(newItemURL);
2371  const_cast<KFileItem*>(item)->setURL(newItemURL);
2372  }
2373 
2374  if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) ) {
2375  return; // No reason to continue... bailing out here prevents a mimetype scan.
2376  }
2377 
2378  if ( matchesMimeFilter( item ) )
2379  {
2380  if ( !d->lstNewItems ) {
2381  d->lstNewItems = new KFileItemList;
2382  }
2383 
2384  d->lstNewItems->append( item ); // items not filtered
2385  }
2386  else
2387  {
2388  if ( !d->lstMimeFilteredItems ) {
2389  d->lstMimeFilteredItems = new KFileItemList;
2390  }
2391 
2392  d->lstMimeFilteredItems->append( item ); // only filtered by mime
2393  }
2394 }
2395 
2396 void KDirLister::addNewItems( const KFileItemList& items )
2397 {
2398  // TODO: make this faster - test if we have a filter at all first
2399  // DF: was this profiled? The matchesFoo() functions should be fast, w/o filters...
2400  // Of course if there is no filter and we can do a range-insertion instead of a loop, that might be good.
2401  // But that's for Qt4, not possible with TQPtrList.
2402  for ( KFileItemListIterator kit( items ); kit.current(); ++kit ) {
2403  addNewItem( *kit );
2404  }
2405 }
2406 
2407 void KDirLister::aboutToRefreshItem( const KFileItem *item )
2408 {
2409  // The code here follows the logic in addNewItem
2410  if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) )
2411  d->refreshItemWasFiltered = true;
2412  else if ( !matchesMimeFilter( item ) )
2413  d->refreshItemWasFiltered = true;
2414  else
2415  d->refreshItemWasFiltered = false;
2416 }
2417 
2418 void KDirLister::addRefreshItem( const KFileItem *item )
2419 {
2420  bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
2421 
2422  TQString refURL = item->url().internalReferenceURL();
2423  if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2424  item->url().path().startsWith(d->m_referenceURLMap[refURL]))
2425  {
2426  // Likely a media:/ tdeioslave URL or similar
2427  // Rewrite the URL to ensure that the user remains within the media:/ tree!
2428  if (!refURL.endsWith("/"))
2429  {
2430  refURL.append("/");
2431  }
2432  KURL newItemURL(refURL);
2433  newItemURL.addPath(item->url().fileName());
2434  const_cast<KFileItem*>(item)->setListerURL(newItemURL);
2435  const_cast<KFileItem*>(item)->setURL(newItemURL);
2436  }
2437 
2438  if ( !isExcluded && matchesMimeFilter( item ) )
2439  {
2440  if ( d->refreshItemWasFiltered )
2441  {
2442  if ( !d->lstNewItems ) {
2443  d->lstNewItems = new KFileItemList;
2444  }
2445 
2446  d->lstNewItems->append( item );
2447  }
2448  else
2449  {
2450  if ( !d->lstRefreshItems ) {
2451  d->lstRefreshItems = new KFileItemList;
2452  }
2453 
2454  d->lstRefreshItems->append( item );
2455  }
2456  }
2457  else if ( !d->refreshItemWasFiltered )
2458  {
2459  if ( !d->lstRemoveItems ) {
2460  d->lstRemoveItems = new KFileItemList;
2461  }
2462 
2463  // notify the user that the mimetype of a file changed that doesn't match
2464  // a filter or does match an exclude filter
2465  d->lstRemoveItems->append( item );
2466  }
2467 }
2468 
2469 void KDirLister::emitItems()
2470 {
2471  KFileItemList *tmpNew = d->lstNewItems;
2472  d->lstNewItems = 0;
2473 
2474  KFileItemList *tmpMime = d->lstMimeFilteredItems;
2475  d->lstMimeFilteredItems = 0;
2476 
2477  KFileItemList *tmpRefresh = d->lstRefreshItems;
2478  d->lstRefreshItems = 0;
2479 
2480  KFileItemList *tmpRemove = d->lstRemoveItems;
2481  d->lstRemoveItems = 0;
2482 
2483  if ( tmpNew )
2484  {
2485  // For historical reasons, items with different protocols and/or prefixes must be emitted separately
2486  TQString protocol;
2487  TQString prefix;
2488  TQString prevProtocol;
2489  TQString prevPrefix;
2490  KFileItemList emitList;
2491  for ( KFileItemListIterator kit( *tmpNew ); kit.current(); ++kit )
2492  {
2493  KFileItem *item = *kit;
2494  protocol = item->url().protocol();
2495  prefix = TQStringList::split("/", item->url().path())[0];
2496  if ((protocol != prevProtocol) || (prefix != prevPrefix)) {
2497  if (emitList.count() > 0) {
2498  emit newItems( emitList );
2499  emitList.clear();
2500  }
2501  }
2502  emitList.append(item);
2503  prevProtocol = protocol;
2504  prevPrefix = prefix;
2505  }
2506 
2507  if (emitList.count() > 0) {
2508  emit newItems( emitList );
2509  }
2510  delete tmpNew;
2511  }
2512 
2513  if ( tmpMime )
2514  {
2515  emit itemsFilteredByMime( *tmpMime );
2516  delete tmpMime;
2517  }
2518 
2519  if ( tmpRefresh )
2520  {
2521  emit refreshItems( *tmpRefresh );
2522  delete tmpRefresh;
2523  }
2524 
2525  if ( tmpRemove )
2526  {
2527  for ( KFileItem *tmp = tmpRemove->first(); tmp; tmp = tmpRemove->next() ) {
2528  emit deleteItem( tmp );
2529  }
2530  delete tmpRemove;
2531  }
2532 }
2533 
2534 void KDirLister::emitDeleteItem( KFileItem *item )
2535 {
2536  if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) ) {
2537  return; // No reason to continue... bailing out here prevents a mimetype scan.
2538  }
2539 
2540  if ( matchesMimeFilter( item ) ) {
2541  emit deleteItem( item );
2542  }
2543 }
2544 
2545 
2546 // ================ private slots ================ //
2547 
2548 void KDirLister::slotInfoMessage( TDEIO::Job *, const TQString& message )
2549 {
2550  emit infoMessage( message );
2551 }
2552 
2553 void KDirLister::slotPercent( TDEIO::Job *job, unsigned long pcnt )
2554 {
2555  d->jobData[static_cast<TDEIO::ListJob *>(job)].percent = pcnt;
2556 
2557  int result = 0;
2558 
2559  TDEIO::filesize_t size = 0;
2560 
2561  TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2562  while ( dataIt != d->jobData.end() )
2563  {
2564  result += (*dataIt).percent * (*dataIt).totalSize;
2565  size += (*dataIt).totalSize;
2566  ++dataIt;
2567  }
2568 
2569  if ( size != 0 )
2570  result /= size;
2571  else
2572  result = 100;
2573  emit percent( result );
2574 }
2575 
2576 void KDirLister::slotTotalSize( TDEIO::Job *job, TDEIO::filesize_t size )
2577 {
2578  d->jobData[static_cast<TDEIO::ListJob *>(job)].totalSize = size;
2579 
2580  TDEIO::filesize_t result = 0;
2581  TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2582  while ( dataIt != d->jobData.end() )
2583  {
2584  result += (*dataIt).totalSize;
2585  ++dataIt;
2586  }
2587 
2588  emit totalSize( result );
2589 }
2590 
2591 void KDirLister::slotProcessedSize( TDEIO::Job *job, TDEIO::filesize_t size )
2592 {
2593  d->jobData[static_cast<TDEIO::ListJob *>(job)].processedSize = size;
2594 
2595  TDEIO::filesize_t result = 0;
2596  TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2597  while ( dataIt != d->jobData.end() )
2598  {
2599  result += (*dataIt).processedSize;
2600  ++dataIt;
2601  }
2602 
2603  emit processedSize( result );
2604 }
2605 
2606 void KDirLister::slotSpeed( TDEIO::Job *job, unsigned long spd )
2607 {
2608  d->jobData[static_cast<TDEIO::ListJob *>(job)].speed = spd;
2609 
2610  int result = 0;
2611  TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2612  while ( dataIt != d->jobData.end() )
2613  {
2614  result += (*dataIt).speed;
2615  ++dataIt;
2616  }
2617 
2618  emit speed( result );
2619 }
2620 
2621 uint KDirLister::numJobs()
2622 {
2623  return d->jobData.count();
2624 }
2625 
2626 void KDirLister::jobDone( TDEIO::ListJob *job )
2627 {
2628  d->jobData.remove( job );
2629 }
2630 
2631 void KDirLister::jobStarted( TDEIO::ListJob *job )
2632 {
2633  KDirListerPrivate::JobData jobData;
2634  jobData.speed = 0;
2635  jobData.percent = 0;
2636  jobData.processedSize = 0;
2637  jobData.totalSize = 0;
2638 
2639  d->jobData.insert( job, jobData );
2640  d->complete = false;
2641 }
2642 
2643 void KDirLister::connectJob( TDEIO::ListJob *job )
2644 {
2645  connect( job, TQT_SIGNAL(infoMessage( TDEIO::Job *, const TQString& )),
2646  this, TQT_SLOT(slotInfoMessage( TDEIO::Job *, const TQString& )) );
2647  connect( job, TQT_SIGNAL(percent( TDEIO::Job *, unsigned long )),
2648  this, TQT_SLOT(slotPercent( TDEIO::Job *, unsigned long )) );
2649  connect( job, TQT_SIGNAL(totalSize( TDEIO::Job *, TDEIO::filesize_t )),
2650  this, TQT_SLOT(slotTotalSize( TDEIO::Job *, TDEIO::filesize_t )) );
2651  connect( job, TQT_SIGNAL(processedSize( TDEIO::Job *, TDEIO::filesize_t )),
2652  this, TQT_SLOT(slotProcessedSize( TDEIO::Job *, TDEIO::filesize_t )) );
2653  connect( job, TQT_SIGNAL(speed( TDEIO::Job *, unsigned long )),
2654  this, TQT_SLOT(slotSpeed( TDEIO::Job *, unsigned long )) );
2655 }
2656 
2657 void KDirLister::emitCompleted( const KURL& _url )
2658 {
2659  TQString refURL = _url.internalReferenceURL();
2660  if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2661  _url.path().startsWith(d->m_referenceURLMap[refURL]))
2662  {
2663  // Likely a media:/ tdeioslave URL or similar
2664  // Rewrite the URL to ensure that the user remains within the media:/ tree!
2665  if (!refURL.endsWith("/"))
2666  {
2667  refURL.append("/");
2668  }
2669  KURL newItemURL(refURL);
2670  newItemURL.addPath(_url.fileName());
2671  emit completed(newItemURL);
2672  }
2673  else
2674  {
2675  emit completed(_url);
2676  }
2677 }
2678 
2679 void KDirLister::setMainWindow( TQWidget *window )
2680 {
2681  d->window = window;
2682 }
2683 
2684 TQWidget *KDirLister::mainWindow()
2685 {
2686  return d->window;
2687 }
2688 
2689 KFileItemList KDirLister::items( WhichItems which ) const
2690 {
2691  return itemsForDir( url(), which );
2692 }
2693 
2694 KFileItemList KDirLister::itemsForDir( const KURL& dir, WhichItems which ) const
2695 {
2696  KFileItemList result;
2697  KFileItemList *allItems = s_pCache->itemsForDir( dir );
2698  if ( !allItems ) {
2699  return result;
2700  }
2701 
2702  if ( which == AllItems ) {
2703  result = *allItems; // shallow copy
2704  }
2705  else // only items passing the filters
2706  {
2707  for ( KFileItemListIterator kit( *allItems ); kit.current(); ++kit )
2708  {
2709  KFileItem *item = *kit;
2710  bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
2711  if ( !isExcluded && matchesMimeFilter( item ) ) {
2712  result.append( item );
2713  }
2714  }
2715  }
2716 
2717  return result;
2718 }
2719 
2720 // to keep BC changes
2721 
2722 void KDirLister::virtual_hook( int, void * )
2723 { /*BASE::virtual_hook( id, data );*/ }
2724 
2725 #include "kdirlister.moc"
2726 #include "kdirlister_p.moc"
KDirLister::matchesFilter
bool matchesFilter(const TQString &name) const
Checks whether name matches a filter in the list of name filters.
Definition: kdirlister.cpp:2263
KDirLister::percent
void percent(int percent)
Progress signal showing the overall progress of the KDirLister.
KDirLister::~KDirLister
virtual ~KDirLister()
Destroy the directory lister.
Definition: kdirlister.cpp:1923
KDirLister::setMimeExcludeFilter
void setMimeExcludeFilter(const TQStringList &mimeList)
Filtering should be done with KFileFilter.
Definition: kdirlister.cpp:2236
KDirLister::setShowingDotFiles
virtual void setShowingDotFiles(bool _showDotFiles)
Changes the "is viewing dot files" setting.
Definition: kdirlister.cpp:2023
KFileItem::url
const KURL & url() const
Returns the url of the file.
Definition: tdefileitem.h:113
KFileItem::isDir
bool isDir() const
Returns true if this item represents a directory.
Definition: tdefileitem.cpp:844
KDirLister::mainWindow
TQWidget * mainWindow()
Returns the main window associated with this object.
Definition: kdirlister.cpp:2684
KDirLister::setAutoUpdate
virtual void setAutoUpdate(bool enable)
Enable/disable automatic directory updating, when a directory changes (using KDirWatch).
Definition: kdirlister.cpp:2009
TDEIO::filesize_t
TQ_ULLONG filesize_t
64-bit file size
Definition: global.h:39
KDirLister::nameFilter
const TQString & nameFilter() const
Returns the current name filter, as set via setNameFilter()
Definition: kdirlister.cpp:2217
KFileItem::refresh
void refresh()
Throw away and re-read (for local files) all information about the file.
Definition: tdefileitem.cpp:285
TDEIO::SimpleJob::url
const KURL & url() const
Returns the SimpleJob's URL.
Definition: jobclasses.h:548
KDirLister::rootItem
KFileItem * rootItem() const
Returns the file item of the URL.
Definition: kdirlister.cpp:2171
KDirLister::clearMimeFilter
virtual void clearMimeFilter()
Clears the mime based filter.
Definition: kdirlister.cpp:2246
KFileItem::name
const TQString & name(bool lowerCase=false) const
Return the name of the file item (without a path).
Definition: tdefileitem.h:312
KDirLister::doNameFilter
virtual bool doNameFilter(const TQString &name, const TQPtrList< TQRegExp > &filters) const
Called by the public matchesFilter() to do the actual filtering.
Definition: kdirlister.cpp:2301
KMimeType::mimeType
static Ptr mimeType(const TQString &_name)
Retrieve a pointer to the mime type _name or a pointer to the default mime type "application/octet-st...
Definition: kmimetype.cpp:141
KDirLister::dirOnlyMode
bool dirOnlyMode() const
Checks whether the KDirLister only lists directories or all files.
Definition: kdirlister.cpp:2032
KDirLister::itemsForDir
KFileItemList itemsForDir(const KURL &dir, WhichItems which=FilteredItems) const
Returns the items listed for the given dir.
Definition: kdirlister.cpp:2694
KFileItem::mark
void mark()
Marks the item.
Definition: tdefileitem.h:440
KDirLister::refreshItems
void refreshItems(const KFileItemList &items)
Signal an item to refresh (its mimetype/icon/name has changed).
TDEIO::Job
The base class for all jobs.
Definition: jobclasses.h:67
KDirLister::mimeFilters
const TQStringList & mimeFilters() const
Returns the list of mime based filters, as set via setMimeFilter().
Definition: kdirlister.cpp:2258
KFileItem::isLocalFile
bool isLocalFile() const
Returns true if the file is a local file.
Definition: tdefileitem.h:296
KDirLister::autoErrorHandlingEnabled
bool autoErrorHandlingEnabled() const
Check whether auto error handling is enabled.
Definition: kdirlister.cpp:2046
KDirLister::stop
virtual void stop()
Stop listing all directories currently being listed.
Definition: kdirlister.cpp:1990
KDirLister::deleteItem
void deleteItem(KFileItem *_fileItem)
Signal an item to remove.
TDEIO::Job::setWindow
void setWindow(TQWidget *window)
Associate this job with a window given by window.
Definition: job.cpp:352
TDEIO::SimpleJob::kill
virtual void kill(bool quietly=true)
Abort job.
Definition: job.cpp:457
KDirLister::infoMessage
void infoMessage(const TQString &msg)
Emitted to display information about running jobs.
KDirLister::findByName
virtual KFileItem * findByName(const TQString &name) const
Find an item by its name.
Definition: kdirlister.cpp:2181
KDirLister::setDirOnlyMode
virtual void setDirOnlyMode(bool dirsOnly)
Call this to list only directories.
Definition: kdirlister.cpp:2037
KDirLister::totalSize
void totalSize(TDEIO::filesize_t size)
Emitted when we know the size of the jobs.
KFileItem::setURL
void setURL(const KURL &url)
Sets the item's URL.
Definition: tdefileitem.cpp:314
KDirLister::handleError
virtual void handleError(TDEIO::Job *)
Reimplement to customize error handling.
Definition: kdirlister.cpp:2346
KDirLister::items
KFileItemList items(WhichItems which=FilteredItems) const
Returns the items listed for the current url().
Definition: kdirlister.cpp:2689
KDirLister::directories
const KURL::List & directories() const
Returns all URLs that are listed by this KDirLister.
Definition: kdirlister.cpp:2062
KDirLister::newItems
void newItems(const KFileItemList &items)
Signal new items.
KDirLister::speed
void speed(int bytes_per_second)
Emitted to display information about the speed of the jobs.
TDEIO::Job::window
TQWidget * window() const
Returns the window this job is associated with.
Definition: job.cpp:358
TDEIO::localURL
TDEIO_EXPORT LocalURLJob * localURL(const KURL &remoteUrl)
Retrieve local URL if available.
Definition: job.cpp:841
KDirLister::updateDirectory
virtual void updateDirectory(const KURL &_dir)
Update the directory _dir.
Definition: kdirlister.cpp:2161
TDEIO::Job::error
int error() const
Returns the error code, if there has been an error.
Definition: jobclasses.h:94
KFileItem::mimetype
TQString mimetype() const
Returns the mimetype of the file item.
Definition: tdefileitem.cpp:551
KDirLister::matchesMimeFilter
bool matchesMimeFilter(const TQString &mime) const
Checks whether mime matches a filter in the list of mime types.
Definition: kdirlister.cpp:2268
KDirLister::setMimeFilter
virtual void setMimeFilter(const TQStringList &mimeList)
Set mime-based filter to only list items matching the given mimetypes.
Definition: kdirlister.cpp:2222
KDirLister::processedSize
void processedSize(TDEIO::filesize_t size)
Regularly emitted to show the progress of this KDirLister.
KProtocolInfo::supportsListing
static bool supportsListing(const KURL &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolinfo.cpp:121
KFileItem::localPath
TQString localPath() const
Returns the local path if isLocalFile() == true or the TDEIO item has a UDS_LOCAL_PATH atom...
Definition: tdefileitem.cpp:355
KDirLister::isFinished
bool isFinished() const
Returns true if no io operation is currently in progress.
Definition: kdirlister.cpp:2166
KDirLister::canceled
void canceled()
Tell the view that the user canceled the listing.
KDirLister::completed
void completed()
Tell the view that listing is finished.
TDEIO::LocalURLJob
A TDEIO job that finds a local URL.
Definition: jobclasses.h:1865
KDirLister::started
void started(const KURL &_url)
Tell the view that we started to list _url.
KDirLister::url
const KURL & url() const
Returns the top level URL that is listed by this KDirLister.
Definition: kdirlister.cpp:2057
KFileItem::refreshMimeType
void refreshMimeType()
Re-reads mimetype information.
Definition: tdefileitem.cpp:303
KDirLister::findByURL
virtual KFileItem * findByURL(const KURL &_url) const
Find an item by its URL.
Definition: kdirlister.cpp:2176
KDirLister::showingDotFiles
bool showingDotFiles() const
Checks whether hidden files (files beginning with a dot) will be shown.
Definition: kdirlister.cpp:2018
TDEIO::Job::showErrorDialog
void showErrorDialog(TQWidget *parent=0L)
Display a dialog box to inform the user of the error given by this job.
Definition: job.cpp:294
KDirLister::clear
void clear()
Signal to clear all items.
KDirLister::KDirLister
KDirLister(bool _delayedMimeTypes=false)
Create a directory lister.
Definition: kdirlister.cpp:1907
KDirLister::WhichItems
WhichItems
Used by items() and itemsForDir() to specify whether you want all items for a directory or just the f...
Definition: kdirlister.h:363
KDirLister::itemsFilteredByMime
void itemsFilteredByMime(const KFileItemList &items)
Send a list of items filtered-out by mime-type.
KDirLister::redirection
void redirection(const KURL &_url)
Signal a redirection.
TDEIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition: jobclasses.h:1391
KFileItem::setUDSEntry
void setUDSEntry(const TDEIO::UDSEntry &entry, const KURL &url, bool determineMimeTypeOnDemand=false, bool urlIsDirectory=false)
Reinitialize KFileItem with a new UDSEntry.
Definition: tdefileitem.cpp:1090
KDirLister::autoUpdate
bool autoUpdate() const
Checks whether KDirWatch will automatically update directories.
Definition: kdirlister.cpp:2004
KDirLister::setAutoErrorHandlingEnabled
void setAutoErrorHandlingEnabled(bool enable, TQWidget *parent)
Enable or disable auto error handling is enabled.
Definition: kdirlister.cpp:2051
TDEIO::UDS_NAME
Filename - as displayed in directory listings etc.
Definition: global.h:335
TDEIO::manually_mounted
TDEIO_EXPORT bool manually_mounted(const TQString &filename)
Checks if the path belongs to a filesystem that is manually mounted.
Definition: global.cpp:1957
KFileItem::isMarked
bool isMarked() const
Used when updating a directory.
Definition: tdefileitem.h:435
KDirLister::setMainWindow
void setMainWindow(TQWidget *window)
Pass the main window this object is associated with this is used for caching authentication data...
Definition: kdirlister.cpp:2679
KFileItem::isHidden
bool isHidden() const
Checks whether the file is hidden.
Definition: tdefileitem.cpp:833
KDirLister::setNameFilter
virtual void setNameFilter(const TQString &filter)
Set a name filter to only list items matching this name, e.g.
Definition: kdirlister.cpp:2196
KDirWatch::exists
static bool exists()
Returns true if there is an instance of KDirWatch.
Definition: kdirwatch.cpp:1637
KDirLister
The dir lister deals with the tdeiojob used to list and update a directory and has signals for the us...
Definition: kdirlister.h:55
TDEIO::listDir
TDEIO_EXPORT ListJob * listDir(const KURL &url, bool showProgressInfo=true, bool includeHidden=true)
List the contents of url, which is assumed to be a directory.
Definition: job.cpp:2187
KFileItem::text
const TQString & text() const
Returns the text of the file item.
Definition: tdefileitem.h:303
KDirLister::validURL
virtual bool validURL(const KURL &) const
Checks if an url is malformed or not and displays an error message if it is and autoErrorHandling is ...
Definition: kdirlister.cpp:2341
TDEIO::ListJob::redirectionURL
const KURL & redirectionURL() const
Returns the ListJob's redirection URL.
Definition: jobclasses.h:1423
KDirLister::emitChanges
virtual void emitChanges()
Actually emit the changes made with setShowingDotFiles, setDirOnlyMode, setNameFilter and setMimeFilt...
Definition: kdirlister.cpp:2067
KDirLister::doMimeFilter
virtual bool doMimeFilter(const TQString &mime, const TQStringList &filters) const
Called by the public matchesMimeFilter() to do the actual filtering.
Definition: kdirlister.cpp:2310
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: tdefileitem.h:41
KDirLister::openURL
virtual bool openURL(const KURL &_url, bool _keep=false, bool _reload=false)
Run the directory lister on the given url.
Definition: kdirlister.cpp:1937

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.8.8
This website is maintained by Timothy Pearson.