00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kdirlister.h"
00023
00024 #include <qregexp.h>
00025 #include <qptrlist.h>
00026 #include <qtimer.h>
00027
00028 #include <kapplication.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <kio/job.h>
00032 #include <kmessagebox.h>
00033 #include <kglobal.h>
00034 #include <kglobalsettings.h>
00035 #include <kstaticdeleter.h>
00036
00037 #include "kdirlister_p.h"
00038
00039 #include <assert.h>
00040
00041 KDirListerCache* KDirListerCache::s_pSelf = 0;
00042 static KStaticDeleter<KDirListerCache> sd_KDirListerCache;
00043
00044
00045
00046
00047
00048 #ifdef NDEBUG
00049 #undef DEBUG_CACHE
00050 #endif
00051
00052 KDirListerCache::KDirListerCache( int maxCount )
00053 : itemsCached( maxCount )
00054 {
00055 kdDebug(7004) << "+KDirListerCache" << endl;
00056
00057 itemsInUse.setAutoDelete( false );
00058 itemsCached.setAutoDelete( true );
00059 urlsCurrentlyListed.setAutoDelete( true );
00060 urlsCurrentlyHeld.setAutoDelete( true );
00061 pendingUpdates.setAutoDelete( true );
00062
00063 connect( kdirwatch, SIGNAL( dirty( const QString& ) ),
00064 this, SLOT( slotFileDirty( const QString& ) ) );
00065 connect( kdirwatch, SIGNAL( created( const QString& ) ),
00066 this, SLOT( slotFileCreated( const QString& ) ) );
00067 connect( kdirwatch, SIGNAL( deleted( const QString& ) ),
00068 this, SLOT( slotFileDeleted( const QString& ) ) );
00069 }
00070
00071 KDirListerCache::~KDirListerCache()
00072 {
00073 kdDebug(7004) << "-KDirListerCache" << endl;
00074
00075 itemsInUse.setAutoDelete( true );
00076 itemsInUse.clear();
00077 itemsCached.clear();
00078 urlsCurrentlyListed.clear();
00079 urlsCurrentlyHeld.clear();
00080
00081 if ( KDirWatch::exists() )
00082 kdirwatch->disconnect( this );
00083 }
00084
00085
00086
00087 void KDirListerCache::listDir( KDirLister* lister, const KURL& _u,
00088 bool _keep, bool _reload )
00089 {
00090
00091 KURL _url = _u;
00092 _url.cleanPath();
00093 _url.adjustPath(-1);
00094 QString urlStr = _url.url();
00095
00096 #ifdef DEBUG_CACHE
00097 printDebug();
00098 #endif
00099 kdDebug(7004) << k_funcinfo << lister << " url=" << _url
00100 << " keep=" << _keep << " reload=" << _reload << endl;
00101
00102 if ( !_keep )
00103 {
00104
00105 stop( lister );
00106
00107
00108 forgetDirs( lister );
00109
00110 lister->d->rootFileItem = 0;
00111 }
00112 else if ( lister->d->lstDirs.find( _url ) != lister->d->lstDirs.end() )
00113 {
00114
00115 stop( lister, _url );
00116
00117
00118 forgetDirs( lister, _url, true );
00119
00120 if ( lister->d->url == _url )
00121 lister->d->rootFileItem = 0;
00122 }
00123
00124 lister->d->lstDirs.append( _url );
00125
00126 if ( lister->d->url.isEmpty() || !_keep )
00127 lister->d->url = _url;
00128
00129 DirItem *itemU = itemsInUse[urlStr];
00130 DirItem *itemC;
00131
00132 if ( !urlsCurrentlyListed[urlStr] )
00133 {
00134
00135
00136
00137 if ( itemU )
00138 {
00139 kdDebug(7004) << "listDir: Entry already in use: " << _url << endl;
00140
00141 bool oldState = lister->d->complete;
00142 lister->d->complete = false;
00143
00144 emit lister->started( _url );
00145
00146 if ( !lister->d->rootFileItem && lister->d->url == _url )
00147 lister->d->rootFileItem = itemU->rootItem;
00148
00149 lister->addNewItems( *(itemU->lstItems) );
00150 lister->emitItems();
00151
00152
00153 assert( urlsCurrentlyHeld[urlStr] );
00154 urlsCurrentlyHeld[urlStr]->append( lister );
00155
00156 lister->d->complete = oldState;
00157
00158 emit lister->completed( _url );
00159 if ( lister->d->complete )
00160 emit lister->completed();
00161
00162 if ( _reload || !itemU->complete )
00163 updateDirectory( _url );
00164 }
00165 else if ( !_reload && (itemC = itemsCached.take( urlStr )) )
00166 {
00167 kdDebug(7004) << "listDir: Entry in cache: " << _url << endl;
00168
00169 itemC->decAutoUpdate();
00170 itemsInUse.insert( urlStr, itemC );
00171 itemU = itemC;
00172
00173 bool oldState = lister->d->complete;
00174 lister->d->complete = false;
00175
00176 emit lister->started( _url );
00177
00178 if ( !lister->d->rootFileItem && lister->d->url == _url )
00179 lister->d->rootFileItem = itemC->rootItem;
00180
00181 lister->addNewItems( *(itemC->lstItems) );
00182 lister->emitItems();
00183
00184 Q_ASSERT( !urlsCurrentlyHeld[urlStr] );
00185 QPtrList<KDirLister> *list = new QPtrList<KDirLister>;
00186 list->append( lister );
00187 urlsCurrentlyHeld.insert( urlStr, list );
00188
00189 lister->d->complete = oldState;
00190
00191 emit lister->completed( _url );
00192 if ( lister->d->complete )
00193 emit lister->completed();
00194
00195 if ( !itemC->complete )
00196 updateDirectory( _url );
00197 }
00198 else
00199 {
00200 kdDebug(7004) << "listDir: Entry not in cache or reloaded: " << _url << endl;
00201
00202 QPtrList<KDirLister> *list = new QPtrList<KDirLister>;
00203 list->append( lister );
00204 urlsCurrentlyListed.insert( urlStr, list );
00205
00206 itemsCached.remove( urlStr );
00207 itemU = new DirItem( _url );
00208 itemsInUse.insert( urlStr, itemU );
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 if ( lister->d->url == _url )
00219 lister->d->rootFileItem = 0;
00220
00221 KIO::ListJob* job = KIO::listDir( _url, false );
00222 jobs.insert( job, QValueList<KIO::UDSEntry>() );
00223
00224 lister->jobStarted( job );
00225 lister->connectJob( job );
00226
00227 if ( lister->d->window )
00228 job->setWindow( lister->d->window );
00229
00230 connect( job, SIGNAL( entries( KIO::Job *, const KIO::UDSEntryList & ) ),
00231 this, SLOT( slotEntries( KIO::Job *, const KIO::UDSEntryList & ) ) );
00232 connect( job, SIGNAL( result( KIO::Job * ) ),
00233 this, SLOT( slotResult( KIO::Job * ) ) );
00234 connect( job, SIGNAL( redirection( KIO::Job *, const KURL & ) ),
00235 this, SLOT( slotRedirection( KIO::Job *, const KURL & ) ) );
00236
00237 emit lister->started( _url );
00238
00239
00240 }
00241 }
00242 else
00243 {
00244 kdDebug(7004) << "listDir: Entry currently being listed: " << _url << endl;
00245
00246 emit lister->started( _url );
00247
00248 urlsCurrentlyListed[urlStr]->append( lister );
00249
00250 KIO::ListJob *job = jobForUrl( urlStr );
00251 Q_ASSERT( job );
00252
00253 lister->jobStarted( job );
00254 lister->connectJob( job );
00255
00256 Q_ASSERT( itemU );
00257
00258 if ( !lister->d->rootFileItem && lister->d->url == _url )
00259 lister->d->rootFileItem = itemU->rootItem;
00260
00261 lister->addNewItems( *(itemU->lstItems) );
00262 lister->emitItems();
00263 }
00264
00265
00266 if ( lister->d->autoUpdate )
00267 itemU->incAutoUpdate();
00268 }
00269
00270 void KDirListerCache::stop( KDirLister *lister )
00271 {
00272 #ifdef DEBUG_CACHE
00273 printDebug();
00274 #endif
00275 kdDebug(7004) << k_funcinfo << "lister: " << lister << endl;
00276 bool stopped = false;
00277
00278 QDictIterator< QPtrList<KDirLister> > it( urlsCurrentlyListed );
00279 QPtrList<KDirLister> *listers;
00280 while ( (listers = it.current()) )
00281 {
00282 if ( listers->findRef( lister ) > -1 )
00283 {
00284
00285 QString url = it.currentKey();
00286
00287
00288 bool ret = listers->removeRef( lister );
00289 Q_ASSERT( ret );
00290
00291 KIO::ListJob *job = jobForUrl( url );
00292 if ( job )
00293 lister->jobDone( job );
00294
00295
00296 QPtrList<KDirLister> *holders = urlsCurrentlyHeld[url];
00297 if ( !holders )
00298 {
00299 holders = new QPtrList<KDirLister>;
00300 urlsCurrentlyHeld.insert( url, holders );
00301 }
00302
00303 holders->append( lister );
00304
00305 emit lister->canceled( KURL( url ) );
00306
00307
00308
00309 if ( listers->isEmpty() )
00310 {
00311
00312 if ( job )
00313 killJob( job );
00314
00315 urlsCurrentlyListed.remove( url );
00316 }
00317
00318 stopped = true;
00319 }
00320 else
00321 ++it;
00322 }
00323
00324 if ( stopped )
00325 {
00326 emit lister->canceled();
00327 lister->d->complete = true;
00328 }
00329
00330
00331
00332 }
00333
00334 void KDirListerCache::stop( KDirLister *lister, const KURL& _u )
00335 {
00336 QString urlStr( _u.url(-1) );
00337 KURL _url( urlStr );
00338
00339
00340 kdDebug(7004) << k_funcinfo << lister << " url=" << _url << endl;
00341
00342 QPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr];
00343 if ( !listers || !listers->removeRef( lister ) )
00344 return;
00345
00346
00347 QPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr];
00348 if ( !holders )
00349 {
00350 holders = new QPtrList<KDirLister>;
00351 urlsCurrentlyHeld.insert( urlStr, holders );
00352 }
00353
00354 holders->append( lister );
00355
00356
00357 KIO::ListJob *job = jobForUrl( urlStr );
00358 if ( job )
00359 lister->jobDone( job );
00360
00361 emit lister->canceled( _url );
00362
00363 if ( listers->isEmpty() )
00364 {
00365
00366 if ( job )
00367 killJob( job );
00368
00369 urlsCurrentlyListed.remove( urlStr );
00370 }
00371
00372 if ( lister->numJobs() == 0 )
00373 {
00374 lister->d->complete = true;
00375
00376
00377 emit lister->canceled();
00378 }
00379 }
00380
00381 void KDirListerCache::setAutoUpdate( KDirLister *lister, bool enable )
00382 {
00383
00384
00385 for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
00386 it != lister->d->lstDirs.end(); ++it )
00387 {
00388 if ( enable )
00389 itemsInUse[(*it).url()]->incAutoUpdate();
00390 else
00391 itemsInUse[(*it).url()]->decAutoUpdate();
00392 }
00393 }
00394
00395 void KDirListerCache::forgetDirs( KDirLister *lister )
00396 {
00397 kdDebug(7004) << k_funcinfo << lister << endl;
00398
00399 emit lister->clear();
00400
00401
00402 KURL::List lstDirsCopy = lister->d->lstDirs;
00403 for ( KURL::List::Iterator it = lstDirsCopy.begin();
00404 it != lstDirsCopy.end(); ++it )
00405 {
00406 forgetDirs( lister, *it, false );
00407 }
00408 }
00409
00410 void KDirListerCache::forgetDirs( KDirLister *lister, const KURL& _url, bool notify )
00411 {
00412 kdDebug(7004) << k_funcinfo << lister << " _url: " << _url << endl;
00413
00414 KURL url( _url );
00415 url.adjustPath( -1 );
00416 QString urlStr = url.url();
00417 QPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr];
00418
00419 if ( holders )
00420 {
00421 holders->removeRef( lister );
00422 }
00423
00424
00425
00426
00427
00428 lister->d->lstDirs.remove( lister->d->lstDirs.find( url ) );
00429
00430 DirItem *item = itemsInUse[urlStr];
00431
00432 if ( holders && holders->isEmpty() )
00433 {
00434 urlsCurrentlyHeld.remove( urlStr );
00435 if ( !urlsCurrentlyListed[urlStr] )
00436 {
00437
00438 itemsInUse.remove( urlStr );
00439
00440
00441 KIO::ListJob *job = jobForUrl( urlStr );
00442 if ( job )
00443 {
00444 lister->jobDone( job );
00445 killJob( job );
00446 kdDebug(7004) << k_funcinfo << "Killing update job for " << urlStr << endl;
00447
00448 emit lister->canceled( url );
00449 if ( lister->numJobs() == 0 )
00450 {
00451 lister->d->complete = true;
00452 emit lister->canceled();
00453 }
00454 }
00455
00456 if ( notify )
00457 emit lister->clear( url );
00458
00459 if ( item && item->complete )
00460 {
00461 kdDebug(7004) << k_funcinfo << lister << " item moved into cache: " << url << endl;
00462 itemsCached.insert( urlStr, item );
00463
00464
00465
00466
00467 const bool isLocal = item->url.isLocalFile();
00468 const bool isManuallyMounted = isLocal && KIO::manually_mounted( item->url.path() );
00469 bool containsManuallyMounted = false;
00470 if ( !isManuallyMounted && item->lstItems && isLocal )
00471 {
00472
00473
00474
00475
00476 KFileItemListIterator kit( *item->lstItems );
00477 for ( ; kit.current() && !containsManuallyMounted; ++kit )
00478 if ( (*kit)->isDir() && KIO::manually_mounted( (*kit)->url().path() ) )
00479 containsManuallyMounted = true;
00480 }
00481
00482 if ( isManuallyMounted || containsManuallyMounted )
00483 {
00484 kdDebug(7004) << "Not adding a watch on " << item->url << " because it " <<
00485 ( isManuallyMounted ? "is manually mounted" : "contains a manually mounted subdir" ) << endl;
00486 item->complete = false;
00487 }
00488 else
00489 item->incAutoUpdate();
00490 }
00491 else
00492 {
00493 delete item;
00494 item = 0;
00495 }
00496 }
00497 }
00498
00499 if ( item && lister->d->autoUpdate )
00500 item->decAutoUpdate();
00501 }
00502
00503 void KDirListerCache::updateDirectory( const KURL& _dir )
00504 {
00505 kdDebug(7004) << k_funcinfo << _dir << endl;
00506
00507 QString urlStr = _dir.url(-1);
00508 if ( !checkUpdate( urlStr ) )
00509 return;
00510
00511
00512
00513
00514
00515
00516
00517 QPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr];
00518 QPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr];
00519
00520
00521 bool killed = false;
00522 QWidget *window = 0;
00523 KIO::ListJob *job = jobForUrl( urlStr );
00524 if ( job )
00525 {
00526 window = job->window();
00527
00528 killJob( job );
00529 killed = true;
00530
00531 if ( listers )
00532 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00533 kdl->jobDone( job );
00534
00535 if ( holders )
00536 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
00537 kdl->jobDone( job );
00538 }
00539 kdDebug(7004) << k_funcinfo << "Killed = " << killed << endl;
00540
00541
00542
00543
00544 Q_ASSERT( !listers || (listers && killed) );
00545
00546 job = KIO::listDir( _dir, false );
00547 jobs.insert( job, QValueList<KIO::UDSEntry>() );
00548
00549 connect( job, SIGNAL(entries( KIO::Job *, const KIO::UDSEntryList & )),
00550 this, SLOT(slotUpdateEntries( KIO::Job *, const KIO::UDSEntryList & )) );
00551 connect( job, SIGNAL(result( KIO::Job * )),
00552 this, SLOT(slotUpdateResult( KIO::Job * )) );
00553
00554 kdDebug(7004) << k_funcinfo << "update started in " << _dir << endl;
00555
00556 if ( listers )
00557 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00558 kdl->jobStarted( job );
00559
00560 if ( holders )
00561 {
00562 if ( !killed )
00563 {
00564 bool first = true;
00565 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
00566 {
00567 kdl->jobStarted( job );
00568 if ( first && kdl->d->window )
00569 {
00570 first = false;
00571 job->setWindow( kdl->d->window );
00572 }
00573 emit kdl->started( _dir );
00574 }
00575 }
00576 else
00577 {
00578 job->setWindow( window );
00579
00580 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
00581 kdl->jobStarted( job );
00582 }
00583 }
00584 }
00585
00586 bool KDirListerCache::checkUpdate( const QString& _dir )
00587 {
00588 if ( !itemsInUse[_dir] )
00589 {
00590 DirItem *item = itemsCached[_dir];
00591 if ( item && item->complete )
00592 {
00593 item->complete = false;
00594 item->decAutoUpdate();
00595
00596
00597 }
00598
00599
00600
00601 return false;
00602 }
00603 else
00604 return true;
00605 }
00606
00607 KFileItemList *KDirListerCache::itemsForDir( const KURL &_dir ) const
00608 {
00609 QString urlStr = _dir.url(-1);
00610 DirItem *item = itemsInUse[ urlStr ];
00611 if ( !item )
00612 item = itemsCached[ urlStr ];
00613 return item ? item->lstItems : 0;
00614 }
00615
00616 KFileItem *KDirListerCache::findByName( const KDirLister *lister, const QString& _name ) const
00617 {
00618 Q_ASSERT( lister );
00619
00620 for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
00621 it != lister->d->lstDirs.end(); ++it )
00622 {
00623 KFileItemListIterator kit( *itemsInUse[(*it).url()]->lstItems );
00624 for ( ; kit.current(); ++kit )
00625 if ( (*kit)->name() == _name )
00626 return (*kit);
00627 }
00628
00629 return 0L;
00630 }
00631
00632 KFileItem *KDirListerCache::findByURL( const KDirLister *lister, const KURL& _u ) const
00633 {
00634 KURL _url = _u;
00635 _url.adjustPath(-1);
00636
00637 KURL parentDir( _url );
00638 parentDir.setPath( parentDir.directory() );
00639
00640
00641 if ( lister && !lister->d->lstDirs.contains( parentDir ) )
00642 return 0L;
00643
00644 KFileItemList *itemList = itemsForDir( parentDir );
00645 if ( itemList )
00646 {
00647 KFileItemListIterator kit( *itemList );
00648 for ( ; kit.current(); ++kit )
00649 if ( (*kit)->url() == _url )
00650 return (*kit);
00651 }
00652 return 0L;
00653 }
00654
00655 void KDirListerCache::FilesAdded( const KURL &dir )
00656 {
00657 kdDebug(7004) << k_funcinfo << dir << endl;
00658 updateDirectory( dir );
00659 }
00660
00661 void KDirListerCache::FilesRemoved( const KURL::List &fileList )
00662 {
00663 kdDebug(7004) << k_funcinfo << endl;
00664 KURL::List::ConstIterator it = fileList.begin();
00665 for ( ; it != fileList.end() ; ++it )
00666 {
00667
00668 KFileItem *fileitem = 0L;
00669 KURL parentDir( *it );
00670 parentDir.setPath( parentDir.directory() );
00671 KFileItemList *lstItems = itemsForDir( parentDir );
00672 if ( lstItems )
00673 {
00674 KFileItem *fit = lstItems->first();
00675 for ( ; fit; fit = lstItems->next() )
00676 if ( fit->url() == *it ) {
00677 fileitem = fit;
00678 lstItems->take();
00679 break;
00680 }
00681 }
00682
00683
00684
00685 if ( fileitem )
00686 {
00687 QPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDir.url()];
00688 if ( listers )
00689 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00690 kdl->emitDeleteItem( fileitem );
00691 }
00692
00693
00694 if ( !fileitem || fileitem->isDir() )
00695 {
00696
00697
00698 deleteDir( *it );
00699 }
00700
00701
00702 delete fileitem;
00703 }
00704 }
00705
00706 void KDirListerCache::FilesChanged( const KURL::List &fileList )
00707 {
00708 KURL::List dirsToUpdate;
00709 kdDebug(7004) << k_funcinfo << "only half implemented" << endl;
00710 KURL::List::ConstIterator it = fileList.begin();
00711 for ( ; it != fileList.end() ; ++it )
00712 {
00713 if ( ( *it ).isLocalFile() )
00714 {
00715 kdDebug(7004) << "KDirListerCache::FilesChanged " << *it << endl;
00716 KFileItem *fileitem = findByURL( 0, *it );
00717 if ( fileitem )
00718 {
00719
00720 aboutToRefreshItem( fileitem );
00721 fileitem->refresh();
00722 emitRefreshItem( fileitem );
00723 }
00724 else
00725 kdDebug(7004) << "item not found" << endl;
00726 } else {
00727
00728
00729 KURL dir( *it );
00730 dir.setPath( dir.directory( true ) );
00731 if ( dirsToUpdate.find( dir ) == dirsToUpdate.end() )
00732 dirsToUpdate.prepend( dir );
00733 }
00734 }
00735
00736 KURL::List::ConstIterator itdir = dirsToUpdate.begin();
00737 for ( ; itdir != dirsToUpdate.end() ; ++itdir )
00738 updateDirectory( *itdir );
00739
00740
00741 }
00742
00743 void KDirListerCache::FileRenamed( const KURL &src, const KURL &dst )
00744 {
00745 kdDebug(7004) << k_funcinfo << src.prettyURL() << " -> " << dst.prettyURL() << endl;
00746 #ifdef DEBUG_CACHE
00747 printDebug();
00748 #endif
00749
00750
00751
00752 renameDir( src, dst );
00753
00754
00755 KURL oldurl( src );
00756 oldurl.adjustPath( -1 );
00757 KFileItem *fileitem = findByURL( 0, oldurl );
00758 if ( fileitem )
00759 {
00760 if ( !fileitem->isLocalFile() && !fileitem->localPath().isEmpty() )
00761 FilesChanged( src );
00762 else
00763 {
00764 aboutToRefreshItem( fileitem );
00765 fileitem->setURL( dst );
00766 fileitem->refreshMimeType();
00767 emitRefreshItem( fileitem );
00768 }
00769 }
00770 #ifdef DEBUG_CACHE
00771 printDebug();
00772 #endif
00773 }
00774
00775 void KDirListerCache::aboutToRefreshItem( KFileItem *fileitem )
00776 {
00777
00778 KURL parentDir( fileitem->url() );
00779 parentDir.setPath( parentDir.directory() );
00780 QString parentDirURL = parentDir.url();
00781 QPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL];
00782 if ( listers )
00783 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00784 kdl->aboutToRefreshItem( fileitem );
00785
00786
00787 listers = urlsCurrentlyListed[parentDirURL];
00788 if ( listers )
00789 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00790 kdl->aboutToRefreshItem( fileitem );
00791 }
00792
00793 void KDirListerCache::emitRefreshItem( KFileItem *fileitem )
00794 {
00795
00796 KURL parentDir( fileitem->url() );
00797 parentDir.setPath( parentDir.directory() );
00798 QString parentDirURL = parentDir.url();
00799 QPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL];
00800 if ( listers )
00801 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00802 {
00803 kdl->addRefreshItem( fileitem );
00804 kdl->emitItems();
00805 }
00806
00807
00808 listers = urlsCurrentlyListed[parentDirURL];
00809 if ( listers )
00810 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00811 {
00812 kdl->addRefreshItem( fileitem );
00813 kdl->emitItems();
00814 }
00815 }
00816
00817 KDirListerCache* KDirListerCache::self()
00818 {
00819 if ( !s_pSelf )
00820 s_pSelf = sd_KDirListerCache.setObject( s_pSelf, new KDirListerCache );
00821
00822 return s_pSelf;
00823 }
00824
00825 bool KDirListerCache::exists()
00826 {
00827 return s_pSelf != 0;
00828 }
00829
00830
00831
00832
00833
00834 void KDirListerCache::slotFileDirty( const QString& _file )
00835 {
00836 kdDebug(7004) << k_funcinfo << _file << endl;
00837
00838 if ( !pendingUpdates[_file] )
00839 {
00840 KURL dir;
00841 dir.setPath( _file );
00842 if ( checkUpdate( dir.url(-1) ) )
00843 updateDirectory( dir );
00844
00845
00846 dir.setPath( dir.directory() );
00847 if ( checkUpdate( dir.url() ) )
00848 {
00849
00850 QTimer *timer = new QTimer( this, _file.utf8() );
00851 connect( timer, SIGNAL(timeout()), this, SLOT(slotFileDirtyDelayed()) );
00852 pendingUpdates.insert( _file, timer );
00853 timer->start( 500, true );
00854 }
00855 }
00856 }
00857
00858
00859 void KDirListerCache::slotFileDirtyDelayed()
00860 {
00861 QString file = QString::fromUtf8( sender()->name() );
00862
00863 kdDebug(7004) << k_funcinfo << file << endl;
00864
00865
00866
00867 pendingUpdates.remove( file );
00868
00869 KURL u;
00870 u.setPath( file );
00871 KFileItem *item = findByURL( 0, u );
00872 if ( item )
00873 {
00874
00875 aboutToRefreshItem( item );
00876 item->refresh();
00877 emitRefreshItem( item );
00878 }
00879 }
00880
00881 void KDirListerCache::slotFileCreated( const QString& _file )
00882 {
00883 kdDebug(7004) << k_funcinfo << _file << endl;
00884
00885 KURL u;
00886 u.setPath( _file );
00887 u.setPath( u.directory() );
00888 FilesAdded( u );
00889 }
00890
00891 void KDirListerCache::slotFileDeleted( const QString& _file )
00892 {
00893 kdDebug(7004) << k_funcinfo << _file << endl;
00894 KURL u;
00895 u.setPath( _file );
00896 FilesRemoved( u );
00897 }
00898
00899 void KDirListerCache::slotEntries( KIO::Job *job, const KIO::UDSEntryList &entries )
00900 {
00901 KURL url = joburl( static_cast<KIO::ListJob *>(job) );
00902 url.adjustPath(-1);
00903 QString urlStr = url.url();
00904
00905 kdDebug(7004) << k_funcinfo << "new entries for " << url << endl;
00906
00907 DirItem *dir = itemsInUse[urlStr];
00908 Q_ASSERT( dir );
00909
00910 QPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr];
00911 Q_ASSERT( listers );
00912 Q_ASSERT( !listers->isEmpty() );
00913
00914
00915 bool delayedMimeTypes = true;
00916 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00917 delayedMimeTypes &= kdl->d->delayedMimeTypes;
00918
00919
00920 static const QString& dot = KGlobal::staticQString(".");
00921 static const QString& dotdot = KGlobal::staticQString("..");
00922
00923 KIO::UDSEntryListConstIterator it = entries.begin();
00924 KIO::UDSEntryListConstIterator end = entries.end();
00925
00926 for ( ; it != end; ++it )
00927 {
00928 QString name;
00929
00930
00931 KIO::UDSEntry::ConstIterator entit = (*it).begin();
00932 for( ; entit != (*it).end(); ++entit )
00933 if ( (*entit).m_uds == KIO::UDS_NAME )
00934 {
00935 name = (*entit).m_str;
00936 break;
00937 }
00938
00939 Q_ASSERT( !name.isEmpty() );
00940 if ( name.isEmpty() )
00941 continue;
00942
00943 if ( name == dot )
00944 {
00945 Q_ASSERT( !dir->rootItem );
00946 dir->rootItem = new KFileItem( *it, url, delayedMimeTypes, true );
00947
00948 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00949 if ( !kdl->d->rootFileItem && kdl->d->url == url )
00950 kdl->d->rootFileItem = dir->rootItem;
00951 }
00952 else if ( name != dotdot )
00953 {
00954 KFileItem* item = new KFileItem( *it, url, delayedMimeTypes, true );
00955 Q_ASSERT( item );
00956
00957
00958 dir->lstItems->append( item );
00959
00960 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00961 kdl->addNewItem( item );
00962 }
00963 }
00964
00965 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
00966 kdl->emitItems();
00967 }
00968
00969 void KDirListerCache::slotResult( KIO::Job *j )
00970 {
00971 Q_ASSERT( j );
00972 KIO::ListJob *job = static_cast<KIO::ListJob *>( j );
00973 jobs.remove( job );
00974
00975 KURL jobUrl = joburl( job );
00976 jobUrl.adjustPath(-1);
00977 QString jobUrlStr = jobUrl.url();
00978
00979 kdDebug(7004) << k_funcinfo << "finished listing " << jobUrl << endl;
00980 #ifdef DEBUG_CACHE
00981 printDebug();
00982 #endif
00983
00984 QPtrList<KDirLister> *listers = urlsCurrentlyListed.take( jobUrlStr );
00985 Q_ASSERT( listers );
00986
00987
00988
00989
00990 Q_ASSERT( !urlsCurrentlyHeld[jobUrlStr] );
00991 urlsCurrentlyHeld.insert( jobUrlStr, listers );
00992
00993 KDirLister *kdl;
00994
00995 if ( job->error() )
00996 {
00997 for ( kdl = listers->first(); kdl; kdl = listers->next() )
00998 {
00999 kdl->jobDone( job );
01000 kdl->handleError( job );
01001 emit kdl->canceled( jobUrl );
01002 if ( kdl->numJobs() == 0 )
01003 {
01004 kdl->d->complete = true;
01005 emit kdl->canceled();
01006 }
01007 }
01008 }
01009 else
01010 {
01011 DirItem *dir = itemsInUse[jobUrlStr];
01012 Q_ASSERT( dir );
01013 dir->complete = true;
01014
01015 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01016 {
01017 kdl->jobDone( job );
01018 emit kdl->completed( jobUrl );
01019 if ( kdl->numJobs() == 0 )
01020 {
01021 kdl->d->complete = true;
01022 emit kdl->completed();
01023 }
01024 }
01025 }
01026
01027
01028
01029 processPendingUpdates();
01030
01031 #ifdef DEBUG_CACHE
01032 printDebug();
01033 #endif
01034 }
01035
01036 void KDirListerCache::slotRedirection( KIO::Job *j, const KURL& url )
01037 {
01038 Q_ASSERT( j );
01039 KIO::ListJob *job = static_cast<KIO::ListJob *>( j );
01040
01041 KURL oldUrl = job->url();
01042 KURL newUrl = url;
01043
01044
01045 oldUrl.adjustPath(-1);
01046 newUrl.adjustPath(-1);
01047
01048 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
01049
01050 #ifdef DEBUG_CACHE
01051 printDebug();
01052 #endif
01053
01054
01055
01056
01057
01058
01059 DirItem *dir = itemsInUse.take( oldUrl.url() );
01060 Q_ASSERT( dir );
01061
01062 QPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrl.url() );
01063 Q_ASSERT( listers );
01064 Q_ASSERT( !listers->isEmpty() );
01065
01066 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01067 {
01068
01069 if ( kdl->d->url.equals( oldUrl, true ) )
01070 {
01071 kdl->d->rootFileItem = 0;
01072 kdl->d->url = newUrl;
01073 }
01074
01075 *kdl->d->lstDirs.find( oldUrl ) = newUrl;
01076
01077 if ( kdl->d->lstDirs.count() == 1 )
01078 {
01079 emit kdl->clear();
01080 emit kdl->redirection( newUrl );
01081 emit kdl->redirection( oldUrl, newUrl );
01082 }
01083 else
01084 {
01085 emit kdl->clear( oldUrl );
01086 emit kdl->redirection( oldUrl, newUrl );
01087 }
01088 }
01089
01090
01091
01092 QPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrl.url() );
01093 if ( holders )
01094 {
01095 Q_ASSERT( !holders->isEmpty() );
01096
01097 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01098 {
01099 kdl->jobStarted( job );
01100
01101
01102 emit kdl->started( oldUrl );
01103
01104
01105
01106 if ( kdl->d->url.equals( oldUrl, true ) )
01107 {
01108 kdl->d->rootFileItem = 0;
01109 kdl->d->url = newUrl;
01110 }
01111
01112 *kdl->d->lstDirs.find( oldUrl ) = newUrl;
01113
01114 if ( kdl->d->lstDirs.count() == 1 )
01115 {
01116 emit kdl->clear();
01117 emit kdl->redirection( newUrl );
01118 emit kdl->redirection( oldUrl, newUrl );
01119 }
01120 else
01121 {
01122 emit kdl->clear( oldUrl );
01123 emit kdl->redirection( oldUrl, newUrl );
01124 }
01125 }
01126 }
01127
01128 DirItem *newDir = itemsInUse[newUrl.url()];
01129 if ( newDir )
01130 {
01131 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " already in use" << endl;
01132
01133
01134 delete dir;
01135
01136
01137
01138 KIO::ListJob *oldJob = jobForUrl( newUrl.url(), job );
01139
01140
01141
01142 QPtrList<KDirLister> *curListers = urlsCurrentlyListed[newUrl.url()];
01143 if ( curListers )
01144 {
01145 kdDebug(7004) << "slotRedirection: and it is currently listed" << endl;
01146
01147 Q_ASSERT( oldJob );
01148
01149 for ( KDirLister *kdl = curListers->first(); kdl; kdl = curListers->next() )
01150 {
01151 kdl->jobDone( oldJob );
01152
01153 kdl->jobStarted( job );
01154 kdl->connectJob( job );
01155 }
01156
01157
01158 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01159 curListers->append( kdl );
01160 }
01161 else
01162 urlsCurrentlyListed.insert( newUrl.url(), listers );
01163
01164 if ( oldJob )
01165 killJob( oldJob );
01166
01167
01168 QPtrList<KDirLister> *curHolders = urlsCurrentlyHeld[newUrl.url()];
01169 if ( curHolders )
01170 {
01171 kdDebug(7004) << "slotRedirection: and it is currently held." << endl;
01172
01173 for ( KDirLister *kdl = curHolders->first(); kdl; kdl = curHolders->next() )
01174 {
01175 kdl->jobStarted( job );
01176 emit kdl->started( newUrl );
01177 }
01178
01179
01180 if ( holders )
01181 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01182 curHolders->append( kdl );
01183 }
01184 else if ( holders )
01185 urlsCurrentlyHeld.insert( newUrl.url(), holders );
01186
01187
01188
01189
01190 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01191 {
01192 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
01193 kdl->d->rootFileItem = newDir->rootItem;
01194
01195 kdl->addNewItems( *(newDir->lstItems) );
01196 kdl->emitItems();
01197 }
01198
01199 if ( holders )
01200 {
01201 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01202 {
01203 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
01204 kdl->d->rootFileItem = newDir->rootItem;
01205
01206 kdl->addNewItems( *(newDir->lstItems) );
01207 kdl->emitItems();
01208 }
01209 }
01210 }
01211 else if ( (newDir = itemsCached.take( newUrl.url() )) )
01212 {
01213 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " is unused, but already in the cache." << endl;
01214
01215 delete dir;
01216 itemsInUse.insert( newUrl.url(), newDir );
01217 urlsCurrentlyListed.insert( newUrl.url(), listers );
01218 if ( holders )
01219 urlsCurrentlyHeld.insert( newUrl.url(), holders );
01220
01221
01222 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01223 {
01224 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
01225 kdl->d->rootFileItem = newDir->rootItem;
01226
01227 kdl->addNewItems( *(newDir->lstItems) );
01228 kdl->emitItems();
01229 }
01230
01231 if ( holders )
01232 {
01233 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01234 {
01235 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
01236 kdl->d->rootFileItem = newDir->rootItem;
01237
01238 kdl->addNewItems( *(newDir->lstItems) );
01239 kdl->emitItems();
01240 }
01241 }
01242 }
01243 else
01244 {
01245 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " has not been listed yet." << endl;
01246
01247 delete dir->rootItem;
01248 dir->rootItem = 0;
01249 dir->lstItems->clear();
01250 dir->redirect( newUrl );
01251 itemsInUse.insert( newUrl.url(), dir );
01252 urlsCurrentlyListed.insert( newUrl.url(), listers );
01253
01254 if ( holders )
01255 urlsCurrentlyHeld.insert( newUrl.url(), holders );
01256 else
01257 {
01258 #ifdef DEBUG_CACHE
01259 printDebug();
01260 #endif
01261 return;
01262 }
01263 }
01264
01265
01266 job->disconnect( this );
01267
01268 connect( job, SIGNAL(entries( KIO::Job *, const KIO::UDSEntryList & )),
01269 this, SLOT(slotUpdateEntries( KIO::Job *, const KIO::UDSEntryList & )) );
01270 connect( job, SIGNAL(result( KIO::Job * )),
01271 this, SLOT(slotUpdateResult( KIO::Job * )) );
01272
01273
01274
01275 #ifdef DEBUG_CACHE
01276 printDebug();
01277 #endif
01278 }
01279
01280 void KDirListerCache::renameDir( const KURL &oldUrl, const KURL &newUrl )
01281 {
01282 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
01283 QString oldUrlStr = oldUrl.url(-1);
01284 QString newUrlStr = newUrl.url(-1);
01285
01286
01287
01288
01289
01290
01291 QDictIterator<DirItem> itu( itemsInUse );
01292 bool goNext;
01293 while ( itu.current() )
01294 {
01295 goNext = true;
01296 DirItem *dir = itu.current();
01297 KURL oldDirUrl ( itu.currentKey() );
01298
01299
01300 if ( oldUrl.isParentOf( oldDirUrl ) )
01301 {
01302
01303 QString relPath = oldDirUrl.path().mid( oldUrl.path().length() );
01304
01305 KURL newDirUrl( newUrl );
01306 if ( !relPath.isEmpty() )
01307 newDirUrl.addPath( relPath );
01308
01309
01310
01311 dir->redirect( newDirUrl );
01312 itemsInUse.remove( itu.currentKey() );
01313 itemsInUse.insert( newDirUrl.url(-1), dir );
01314 goNext = false;
01315 if ( dir->lstItems )
01316 {
01317
01318 KFileItemListIterator kit( *dir->lstItems );
01319 for ( ; kit.current(); ++kit )
01320 {
01321 KURL oldItemUrl = (*kit)->url();
01322 QString oldItemUrlStr( oldItemUrl.url(-1) );
01323 KURL newItemUrl( oldItemUrl );
01324 newItemUrl.setPath( newDirUrl.path() );
01325 newItemUrl.addPath( oldItemUrl.fileName() );
01326 kdDebug(7004) << "KDirListerCache::renameDir renaming " << oldItemUrlStr << " to " << newItemUrl.url() << endl;
01327 (*kit)->setURL( newItemUrl );
01328 }
01329 }
01330 emitRedirections( oldDirUrl, newDirUrl );
01331 }
01332 if ( goNext )
01333 ++itu;
01334 }
01335
01336
01337
01338 removeDirFromCache( oldUrl );
01339
01340 }
01341
01342 void KDirListerCache::emitRedirections( const KURL &oldUrl, const KURL &url )
01343 {
01344 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << url.prettyURL() << endl;
01345 QString oldUrlStr = oldUrl.url(-1);
01346 QString urlStr = url.url(-1);
01347
01348 KIO::ListJob *job = jobForUrl( oldUrlStr );
01349 if ( job )
01350 killJob( job );
01351
01352
01353 QPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrlStr );
01354 if ( listers )
01355 {
01356
01357 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01358 {
01359 if ( job )
01360 kdl->jobDone( job );
01361
01362 emit kdl->canceled( oldUrl );
01363 }
01364
01365 urlsCurrentlyListed.insert( urlStr, listers );
01366 }
01367
01368
01369
01370 QPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrlStr );
01371 if ( holders )
01372 {
01373 if ( job )
01374 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01375 kdl->jobDone( job );
01376
01377 urlsCurrentlyHeld.insert( urlStr, holders );
01378 }
01379
01380 if ( listers )
01381 {
01382 updateDirectory( url );
01383
01384
01385 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01386 emit kdl->started( url );
01387 }
01388
01389 if ( holders )
01390 {
01391
01392 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
01393 {
01394 *kdl->d->lstDirs.find( oldUrl ) = url;
01395
01396 if ( kdl->d->lstDirs.count() == 1 )
01397 emit kdl->redirection( url );
01398
01399 emit kdl->redirection( oldUrl, url );
01400 }
01401 }
01402 }
01403
01404 void KDirListerCache::removeDirFromCache( const KURL& dir )
01405 {
01406 kdDebug(7004) << "KDirListerCache::removeDirFromCache " << dir.prettyURL() << endl;
01407 QCacheIterator<DirItem> itc( itemsCached );
01408 while ( itc.current() )
01409 {
01410 if ( dir.isParentOf( KURL( itc.currentKey() ) ) )
01411 itemsCached.remove( itc.currentKey() );
01412 else
01413 ++itc;
01414 }
01415 }
01416
01417 void KDirListerCache::slotUpdateEntries( KIO::Job* job, const KIO::UDSEntryList& list )
01418 {
01419 jobs[static_cast<KIO::ListJob*>(job)] += list;
01420 }
01421
01422 void KDirListerCache::slotUpdateResult( KIO::Job * j )
01423 {
01424 Q_ASSERT( j );
01425 KIO::ListJob *job = static_cast<KIO::ListJob *>( j );
01426
01427 KURL jobUrl = joburl( job );
01428 jobUrl.adjustPath(-1);
01429 QString jobUrlStr = jobUrl.url();
01430
01431 kdDebug(7004) << k_funcinfo << "finished update " << jobUrl << endl;
01432
01433 KDirLister *kdl;
01434
01435 QPtrList<KDirLister> *listers = urlsCurrentlyHeld[jobUrlStr];
01436 QPtrList<KDirLister> *tmpLst = urlsCurrentlyListed.take( jobUrlStr );
01437
01438 if ( tmpLst )
01439 {
01440 if ( listers )
01441 for ( kdl = tmpLst->first(); kdl; kdl = tmpLst->next() )
01442 {
01443 Q_ASSERT( listers->containsRef( kdl ) == 0 );
01444 listers->append( kdl );
01445 }
01446 else
01447 {
01448 listers = tmpLst;
01449 urlsCurrentlyHeld.insert( jobUrlStr, listers );
01450 }
01451 }
01452
01453
01454 Q_ASSERT( listers );
01455
01456 if ( job->error() )
01457 {
01458 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01459 {
01460 kdl->jobDone( job );
01461
01462
01463
01464
01465 emit kdl->canceled( jobUrl );
01466 if ( kdl->numJobs() == 0 )
01467 {
01468 kdl->d->complete = true;
01469 emit kdl->canceled();
01470 }
01471 }
01472
01473 jobs.remove( job );
01474
01475
01476
01477 processPendingUpdates();
01478 return;
01479 }
01480
01481 DirItem *dir = itemsInUse[jobUrlStr];
01482 dir->complete = true;
01483
01484
01485
01486 bool delayedMimeTypes = true;
01487 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01488 delayedMimeTypes &= kdl->d->delayedMimeTypes;
01489
01490
01491 QDict<KFileItem> fileItems( 9973 );
01492
01493 KFileItemListIterator kit ( *(dir->lstItems) );
01494
01495
01496 for ( ; kit.current(); ++kit )
01497 {
01498 (*kit)->unmark();
01499 fileItems.insert( (*kit)->url().url(), *kit );
01500 }
01501
01502 static const QString& dot = KGlobal::staticQString(".");
01503 static const QString& dotdot = KGlobal::staticQString("..");
01504
01505 KFileItem *item = 0, *tmp;
01506
01507 QValueList<KIO::UDSEntry> buf = jobs[job];
01508 QValueListIterator<KIO::UDSEntry> it = buf.begin();
01509 for ( ; it != buf.end(); ++it )
01510 {
01511
01512 if ( !item )
01513 item = new KFileItem( *it, jobUrl, delayedMimeTypes, true );
01514 else
01515 item->setUDSEntry( *it, jobUrl, delayedMimeTypes, true );
01516
01517
01518 QString name = item->name();
01519 Q_ASSERT( !name.isEmpty() );
01520
01521
01522
01523 if ( name.isEmpty() || name == dotdot )
01524 continue;
01525
01526 if ( name == dot )
01527 {
01528
01529
01530 if ( !dir->rootItem )
01531 {
01532 dir->rootItem = item;
01533 item = 0;
01534
01535 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01536 if ( !kdl->d->rootFileItem && kdl->d->url == jobUrl )
01537 kdl->d->rootFileItem = dir->rootItem;
01538 }
01539
01540 continue;
01541 }
01542
01543
01544 if ( (tmp = fileItems[item->url().url()]) )
01545 {
01546 tmp->mark();
01547
01548
01549 if ( !tmp->cmp( *item ) )
01550 {
01551 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01552 kdl->aboutToRefreshItem( tmp );
01553
01554
01555 tmp->assign( *item );
01556
01557 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01558 kdl->addRefreshItem( tmp );
01559 }
01560 }
01561 else
01562 {
01563
01564
01565 item->mark();
01566 dir->lstItems->append( item );
01567
01568 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01569 kdl->addNewItem( item );
01570
01571
01572 item = 0;
01573 }
01574 }
01575
01576 if ( item )
01577 delete item;
01578
01579 jobs.remove( job );
01580
01581 deleteUnmarkedItems( listers, dir->lstItems );
01582
01583 for ( kdl = listers->first(); kdl; kdl = listers->next() )
01584 {
01585 kdl->emitItems();
01586
01587 kdl->jobDone( job );
01588
01589 emit kdl->completed( jobUrl );
01590 if ( kdl->numJobs() == 0 )
01591 {
01592 kdl->d->complete = true;
01593 emit kdl->completed();
01594 }
01595 }
01596
01597
01598
01599 processPendingUpdates();
01600 }
01601
01602
01603
01604 KIO::ListJob *KDirListerCache::jobForUrl( const QString& url, KIO::ListJob *not_job )
01605 {
01606 KIO::ListJob *job;
01607 QMap< KIO::ListJob *, QValueList<KIO::UDSEntry> >::Iterator it = jobs.begin();
01608 while ( it != jobs.end() )
01609 {
01610 job = it.key();
01611 if ( joburl( job ).url(-1) == url && job != not_job )
01612 return job;
01613 ++it;
01614 }
01615 return 0;
01616 }
01617
01618 const KURL& KDirListerCache::joburl( KIO::ListJob *job )
01619 {
01620 if ( job->redirectionURL().isValid() )
01621 return job->redirectionURL();
01622 else
01623 return job->url();
01624 }
01625
01626 void KDirListerCache::killJob( KIO::ListJob *job )
01627 {
01628 jobs.remove( job );
01629 job->disconnect( this );
01630 job->kill();
01631 }
01632
01633 void KDirListerCache::deleteUnmarkedItems( QPtrList<KDirLister> *listers, KFileItemList *lstItems )
01634 {
01635
01636 KFileItem* item;
01637 lstItems->first();
01638 while ( (item = lstItems->current()) )
01639 if ( !item->isMarked() )
01640 {
01641
01642 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
01643 kdl->emitDeleteItem( item );
01644
01645 if ( item->isDir() )
01646 deleteDir( item->url() );
01647
01648
01649 lstItems->take();
01650 delete item;
01651 }
01652 else
01653 lstItems->next();
01654 }
01655
01656 void KDirListerCache::deleteDir( const KURL& dirUrl )
01657 {
01658
01659
01660
01661
01662
01663 QDictIterator<DirItem> itu( itemsInUse );
01664 while ( itu.current() )
01665 {
01666 KURL deletedUrl( itu.currentKey() );
01667 if ( dirUrl.isParentOf( deletedUrl ) )
01668 {
01669
01670
01671 QPtrList<KDirLister> *kdls = urlsCurrentlyListed[deletedUrl.url()];
01672 if ( kdls )
01673 {
01674
01675 kdls = new QPtrList<KDirLister>( *kdls );
01676 for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
01677 stop( kdl, deletedUrl );
01678
01679 delete kdls;
01680 }
01681
01682
01683
01684
01685 kdls = urlsCurrentlyHeld[deletedUrl.url()];
01686 if ( kdls )
01687 {
01688
01689 kdls = new QPtrList<KDirLister>( *kdls );
01690
01691 for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
01692 {
01693
01694 if ( kdl->d->url == deletedUrl )
01695 {
01696
01697 if ( kdl->d->rootFileItem )
01698 emit kdl->deleteItem( kdl->d->rootFileItem );
01699 forgetDirs( kdl );
01700 kdl->d->rootFileItem = 0;
01701 }
01702 else
01703 {
01704 bool treeview = kdl->d->lstDirs.count() > 1;
01705 if ( !treeview )
01706 emit kdl->clear();
01707
01708 forgetDirs( kdl, deletedUrl, treeview );
01709 }
01710 }
01711
01712 delete kdls;
01713 }
01714
01715
01716
01717
01718 DirItem *dir = itemsInUse.take( deletedUrl.url() );
01719 Q_ASSERT( !dir );
01720 if ( !dir )
01721 ++itu;
01722 }
01723 else
01724 ++itu;
01725 }
01726
01727
01728 removeDirFromCache( dirUrl );
01729 }
01730
01731 void KDirListerCache::processPendingUpdates()
01732 {
01733
01734 }
01735
01736 #ifndef NDEBUG
01737 void KDirListerCache::printDebug()
01738 {
01739 kdDebug(7004) << "Items in use: " << endl;
01740 QDictIterator<DirItem> itu( itemsInUse );
01741 for ( ; itu.current() ; ++itu ) {
01742 kdDebug(7004) << " " << itu.currentKey() << " URL: " << itu.current()->url
01743 << " rootItem: " << ( itu.current()->rootItem ? itu.current()->rootItem->url() : KURL() )
01744 << " autoUpdates refcount: " << itu.current()->autoUpdates
01745 << " complete: " << itu.current()->complete
01746 << ( itu.current()->lstItems ? QString(" with %1 items.").arg(itu.current()->lstItems->count()) : QString(" lstItems=NULL") ) << endl;
01747 }
01748
01749 kdDebug(7004) << "urlsCurrentlyHeld: " << endl;
01750 QDictIterator< QPtrList<KDirLister> > it( urlsCurrentlyHeld );
01751 for ( ; it.current() ; ++it )
01752 {
01753 QString list;
01754 for ( QPtrListIterator<KDirLister> listit( *it.current() ); listit.current(); ++listit )
01755 list += " 0x" + QString::number( (long)listit.current(), 16 );
01756 kdDebug(7004) << " " << it.currentKey() << " " << it.current()->count() << " listers: " << list << endl;
01757 }
01758
01759 kdDebug(7004) << "urlsCurrentlyListed: " << endl;
01760 QDictIterator< QPtrList<KDirLister> > it2( urlsCurrentlyListed );
01761 for ( ; it2.current() ; ++it2 )
01762 {
01763 QString list;
01764 for ( QPtrListIterator<KDirLister> listit( *it2.current() ); listit.current(); ++listit )
01765 list += " 0x" + QString::number( (long)listit.current(), 16 );
01766 kdDebug(7004) << " " << it2.currentKey() << " " << it2.current()->count() << " listers: " << list << endl;
01767 }
01768
01769 QMap< KIO::ListJob *, QValueList<KIO::UDSEntry> >::Iterator jit = jobs.begin();
01770 kdDebug(7004) << "Jobs: " << endl;
01771 for ( ; jit != jobs.end() ; ++jit )
01772 kdDebug(7004) << " " << jit.key() << " listing " << joburl( jit.key() ).prettyURL() << ": " << (*jit).count() << " entries." << endl;
01773
01774 kdDebug(7004) << "Items in cache: " << endl;
01775 QCacheIterator<DirItem> itc( itemsCached );
01776 for ( ; itc.current() ; ++itc )
01777 kdDebug(7004) << " " << itc.currentKey() << " rootItem: "
01778 << ( itc.current()->rootItem ? itc.current()->rootItem->url().prettyURL() : QString("NULL") )
01779 << ( itc.current()->lstItems ? QString(" with %1 items.").arg(itc.current()->lstItems->count()) : QString(" lstItems=NULL") ) << endl;
01780 }
01781 #endif
01782
01783
01784
01785
01786 KDirLister::KDirLister( bool _delayedMimeTypes )
01787 {
01788 kdDebug(7003) << "+KDirLister" << endl;
01789
01790 d = new KDirListerPrivate;
01791
01792 d->complete = true;
01793 d->delayedMimeTypes = _delayedMimeTypes;
01794
01795 setAutoUpdate( true );
01796 setDirOnlyMode( false );
01797 setShowingDotFiles( false );
01798
01799 setAutoErrorHandlingEnabled( true, 0 );
01800 }
01801
01802 KDirLister::~KDirLister()
01803 {
01804 kdDebug(7003) << "-KDirLister" << endl;
01805
01806 if ( KDirListerCache::exists() )
01807 {
01808
01809 stop();
01810 s_pCache->forgetDirs( this );
01811 }
01812
01813 delete d;
01814 }
01815
01816 bool KDirLister::openURL( const KURL& _url, bool _keep, bool _reload )
01817 {
01818 if ( !validURL( _url ) )
01819 return false;
01820
01821 kdDebug(7003) << k_funcinfo << _url.prettyURL()
01822 << " keep=" << _keep << " reload=" << _reload << endl;
01823
01824
01825 if ( d->changes != NONE && _keep )
01826 emitChanges();
01827
01828 d->changes = NONE;
01829
01830 s_pCache->listDir( this, _url, _keep, _reload );
01831
01832 return true;
01833 }
01834
01835 void KDirLister::stop()
01836 {
01837 kdDebug(7003) << k_funcinfo << endl;
01838 s_pCache->stop( this );
01839 }
01840
01841 void KDirLister::stop( const KURL& _url )
01842 {
01843 kdDebug(7003) << k_funcinfo << _url.prettyURL() << endl;
01844 s_pCache->stop( this, _url );
01845 }
01846
01847 bool KDirLister::autoUpdate() const
01848 {
01849 return d->autoUpdate;
01850 }
01851
01852 void KDirLister::setAutoUpdate( bool _enable )
01853 {
01854 if ( d->autoUpdate == _enable )
01855 return;
01856
01857 d->autoUpdate = _enable;
01858 s_pCache->setAutoUpdate( this, _enable );
01859 }
01860
01861 bool KDirLister::showingDotFiles() const
01862 {
01863 return d->isShowingDotFiles;
01864 }
01865
01866 void KDirLister::setShowingDotFiles( bool _showDotFiles )
01867 {
01868 if ( d->isShowingDotFiles == _showDotFiles )
01869 return;
01870
01871 d->isShowingDotFiles = _showDotFiles;
01872 d->changes ^= DOT_FILES;
01873 }
01874
01875 bool KDirLister::dirOnlyMode() const
01876 {
01877 return d->dirOnlyMode;
01878 }
01879
01880 void KDirLister::setDirOnlyMode( bool _dirsOnly )
01881 {
01882 if ( d->dirOnlyMode == _dirsOnly )
01883 return;
01884
01885 d->dirOnlyMode = _dirsOnly;
01886 d->changes ^= DIR_ONLY_MODE;
01887 }
01888
01889 bool KDirLister::autoErrorHandlingEnabled() const
01890 {
01891 return d->autoErrorHandling;
01892 }
01893
01894 void KDirLister::setAutoErrorHandlingEnabled( bool enable, QWidget* parent )
01895 {
01896 d->autoErrorHandling = enable;
01897 d->errorParent = parent;
01898 }
01899
01900 const KURL& KDirLister::url() const
01901 {
01902 return d->url;
01903 }
01904
01905 const KURL::List& KDirLister::directories() const
01906 {
01907 return d->lstDirs;
01908 }
01909
01910 void KDirLister::emitChanges()
01911 {
01912 if ( d->changes == NONE )
01913 return;
01914
01915 static const QString& dot = KGlobal::staticQString(".");
01916 static const QString& dotdot = KGlobal::staticQString("..");
01917
01918 for ( KURL::List::Iterator it = d->lstDirs.begin();
01919 it != d->lstDirs.end(); ++it )
01920 {
01921 KFileItemListIterator kit( *s_pCache->itemsForDir( *it ) );
01922 for ( ; kit.current(); ++kit )
01923 {
01924 if ( (*kit)->text() == dot || (*kit)->text() == dotdot )
01925 continue;
01926
01927 bool oldMime = true, newMime = true;
01928
01929 if ( d->changes & MIME_FILTER )
01930 {
01931 oldMime = doMimeFilter( (*kit)->mimetype(), d->oldMimeFilter )
01932 && doMimeExcludeFilter( (*kit)->mimetype(), d->oldMimeExcludeFilter );
01933 newMime = doMimeFilter( (*kit)->mimetype(), d->mimeFilter )
01934 && doMimeExcludeFilter( (*kit)->mimetype(), d->mimeExcludeFilter );
01935
01936 if ( oldMime && !newMime )
01937 {
01938 emit deleteItem( *kit );
01939 continue;
01940 }
01941 }
01942
01943 if ( d->changes & DIR_ONLY_MODE )
01944 {
01945
01946 if ( d->dirOnlyMode )
01947 {
01948 if ( !(*kit)->isDir() )
01949 emit deleteItem( *kit );
01950 }
01951 else if ( !(*kit)->isDir() )
01952 addNewItem( *kit );
01953
01954 continue;
01955 }
01956
01957 if ( (*kit)->isHidden() )
01958 {
01959 if ( d->changes & DOT_FILES )
01960 {
01961
01962 if ( d->isShowingDotFiles )
01963 addNewItem( *kit );
01964 else
01965 emit deleteItem( *kit );
01966
01967 continue;
01968 }
01969 }
01970 else if ( d->changes & NAME_FILTER )
01971 {
01972 bool oldName = (*kit)->isDir() ||
01973 d->oldFilters.isEmpty() ||
01974 doNameFilter( (*kit)->text(), d->oldFilters );
01975
01976 bool newName = (*kit)->isDir() ||
01977 d->lstFilters.isEmpty() ||
01978 doNameFilter( (*kit)->text(), d->lstFilters );
01979
01980 if ( oldName && !newName )
01981 {
01982 emit deleteItem( *kit );
01983 continue;
01984 }
01985 else if ( !oldName && newName )
01986 addNewItem( *kit );
01987 }
01988
01989 if ( (d->changes & MIME_FILTER) && !oldMime && newMime )
01990 addNewItem( *kit );
01991 }
01992
01993 emitItems();
01994 }
01995
01996 d->changes = NONE;
01997 }
01998
01999 void KDirLister::updateDirectory( const KURL& _u )
02000 {
02001 s_pCache->updateDirectory( _u );
02002 }
02003
02004 bool KDirLister::isFinished() const
02005 {
02006 return d->complete;
02007 }
02008
02009 KFileItem *KDirLister::rootItem() const
02010 {
02011 return d->rootFileItem;
02012 }
02013
02014 KFileItem *KDirLister::findByURL( const KURL& _url ) const
02015 {
02016 return s_pCache->findByURL( this, _url );
02017 }
02018
02019 KFileItem *KDirLister::findByName( const QString& _name ) const
02020 {
02021 return s_pCache->findByName( this, _name );
02022 }
02023
02024 #ifndef KDE_NO_COMPAT
02025 KFileItem *KDirLister::find( const KURL& _url ) const
02026 {
02027 return findByURL( _url );
02028 }
02029 #endif
02030
02031
02032
02033
02034 void KDirLister::setNameFilter( const QString& nameFilter )
02035 {
02036 if ( !(d->changes & NAME_FILTER) )
02037 {
02038 d->oldFilters = d->lstFilters;
02039 d->lstFilters.setAutoDelete( false );
02040 }
02041
02042 d->lstFilters.clear();
02043 d->lstFilters.setAutoDelete( true );
02044
02045 d->nameFilter = nameFilter;
02046
02047
02048 QStringList list = QStringList::split( ' ', nameFilter );
02049 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
02050 d->lstFilters.append( new QRegExp(*it, false, true ) );
02051
02052 d->changes |= NAME_FILTER;
02053 }
02054
02055 const QString& KDirLister::nameFilter() const
02056 {
02057 return d->nameFilter;
02058 }
02059
02060 void KDirLister::setMimeFilter( const QStringList& mimeFilter )
02061 {
02062 if ( !(d->changes & MIME_FILTER) )
02063 d->oldMimeFilter = d->mimeFilter;
02064
02065 if ( mimeFilter.find("all/allfiles") != mimeFilter.end() ||
02066 mimeFilter.find("all/all") != mimeFilter.end() )
02067 d->mimeFilter.clear();
02068 else
02069 d->mimeFilter = mimeFilter;
02070
02071 d->changes |= MIME_FILTER;
02072 }
02073
02074 void KDirLister::setMimeExcludeFilter( const QStringList& mimeExcludeFilter )
02075 {
02076 if ( !(d->changes & MIME_FILTER) )
02077 d->oldMimeExcludeFilter = d->mimeExcludeFilter;
02078
02079 d->mimeExcludeFilter = mimeExcludeFilter;
02080 d->changes |= MIME_FILTER;
02081 }
02082
02083
02084 void KDirLister::clearMimeFilter()
02085 {
02086 if ( !(d->changes & MIME_FILTER) )
02087 {
02088 d->oldMimeFilter = d->mimeFilter;
02089 d->oldMimeExcludeFilter = d->mimeExcludeFilter;
02090 }
02091 d->mimeFilter.clear();
02092 d->mimeExcludeFilter.clear();
02093 d->changes |= MIME_FILTER;
02094 }
02095
02096 const QStringList& KDirLister::mimeFilters() const
02097 {
02098 return d->mimeFilter;
02099 }
02100
02101 bool KDirLister::matchesFilter( const QString& name ) const
02102 {
02103 return doNameFilter( name, d->lstFilters );
02104 }
02105
02106 bool KDirLister::matchesMimeFilter( const QString& mime ) const
02107 {
02108 return doMimeFilter( mime, d->mimeFilter ) && doMimeExcludeFilter(mime,d->mimeExcludeFilter);
02109 }
02110
02111
02112
02113 bool KDirLister::matchesFilter( const KFileItem *item ) const
02114 {
02115 Q_ASSERT( item );
02116 static const QString& dotdot = KGlobal::staticQString("..");
02117
02118 if ( item->text() == dotdot )
02119 return false;
02120
02121 if ( !d->isShowingDotFiles && item->isHidden() )
02122 return false;
02123
02124 if ( item->isDir() || d->lstFilters.isEmpty() )
02125 return true;
02126
02127 return matchesFilter( item->text() );
02128 }
02129
02130 bool KDirLister::matchesMimeFilter( const KFileItem *item ) const
02131 {
02132 Q_ASSERT( item );
02133
02134 if ( d->mimeFilter.isEmpty() && d->mimeExcludeFilter.isEmpty() )
02135 return true;
02136 return matchesMimeFilter( item->mimetype() );
02137 }
02138
02139 bool KDirLister::doNameFilter( const QString& name, const QPtrList<QRegExp>& filters ) const
02140 {
02141 for ( QPtrListIterator<QRegExp> it( filters ); it.current(); ++it )
02142 if ( it.current()->exactMatch( name ) )
02143 return true;
02144
02145 return false;
02146 }
02147
02148 bool KDirLister::doMimeFilter( const QString& mime, const QStringList& filters ) const
02149 {
02150 if ( filters.isEmpty() )
02151 return true;
02152
02153 KMimeType::Ptr mimeptr = KMimeType::mimeType(mime);
02154
02155 QStringList::ConstIterator it = filters.begin();
02156 for ( ; it != filters.end(); ++it )
02157 if ( mimeptr->is(*it) )
02158 return true;
02159
02160
02161
02162 return false;
02163 }
02164
02165 bool KDirLister::doMimeExcludeFilter( const QString& mime, const QStringList& filters ) const
02166 {
02167 if ( filters.isEmpty() )
02168 return true;
02169
02170 QStringList::ConstIterator it = filters.begin();
02171 for ( ; it != filters.end(); ++it )
02172 if ( (*it) == mime )
02173 return false;
02174
02175 return true;
02176 }
02177
02178
02179 bool KDirLister::validURL( const KURL& _url ) const
02180 {
02181 if ( !_url.isValid() )
02182 {
02183 if ( d->autoErrorHandling )
02184 {
02185 QString tmp = i18n("Malformed URL\n%1").arg( _url.prettyURL() );
02186 KMessageBox::error( d->errorParent, tmp );
02187 }
02188 return false;
02189 }
02190
02191
02192
02193 return true;
02194 }
02195
02196 void KDirLister::handleError( KIO::Job *job )
02197 {
02198 if ( d->autoErrorHandling )
02199 job->showErrorDialog( d->errorParent );
02200 }
02201
02202
02203
02204
02205 void KDirLister::addNewItem( const KFileItem *item )
02206 {
02207 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) )
02208 return;
02209
02210 if ( matchesMimeFilter( item ) )
02211 {
02212 if ( !d->lstNewItems )
02213 d->lstNewItems = new KFileItemList;
02214
02215 d->lstNewItems->append( item );
02216 }
02217 else
02218 {
02219 if ( !d->lstMimeFilteredItems )
02220 d->lstMimeFilteredItems = new KFileItemList;
02221
02222 d->lstMimeFilteredItems->append( item );
02223 }
02224 }
02225
02226 void KDirLister::addNewItems( const KFileItemList& items )
02227 {
02228
02229
02230
02231
02232 for ( KFileItemListIterator kit( items ); kit.current(); ++kit )
02233 addNewItem( *kit );
02234 }
02235
02236 void KDirLister::aboutToRefreshItem( const KFileItem *item )
02237 {
02238
02239 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) )
02240 d->refreshItemWasFiltered = true;
02241 else if ( !matchesMimeFilter( item ) )
02242 d->refreshItemWasFiltered = true;
02243 else
02244 d->refreshItemWasFiltered = false;
02245 }
02246
02247 void KDirLister::addRefreshItem( const KFileItem *item )
02248 {
02249 bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
02250
02251 if ( !isExcluded && matchesMimeFilter( item ) )
02252 {
02253 if ( d->refreshItemWasFiltered )
02254 {
02255 if ( !d->lstNewItems )
02256 d->lstNewItems = new KFileItemList;
02257
02258 d->lstNewItems->append( item );
02259 }
02260 else
02261 {
02262 if ( !d->lstRefreshItems )
02263 d->lstRefreshItems = new KFileItemList;
02264
02265 d->lstRefreshItems->append( item );
02266 }
02267 }
02268 else if ( !d->refreshItemWasFiltered )
02269 {
02270 if ( !d->lstRemoveItems )
02271 d->lstRemoveItems = new KFileItemList;
02272
02273
02274
02275 d->lstRemoveItems->append( item );
02276 }
02277 }
02278
02279 void KDirLister::emitItems()
02280 {
02281 KFileItemList *tmpNew = d->lstNewItems;
02282 d->lstNewItems = 0;
02283
02284 KFileItemList *tmpMime = d->lstMimeFilteredItems;
02285 d->lstMimeFilteredItems = 0;
02286
02287 KFileItemList *tmpRefresh = d->lstRefreshItems;
02288 d->lstRefreshItems = 0;
02289
02290 KFileItemList *tmpRemove = d->lstRemoveItems;
02291 d->lstRemoveItems = 0;
02292
02293 if ( tmpNew )
02294 {
02295 emit newItems( *tmpNew );
02296 delete tmpNew;
02297 }
02298
02299 if ( tmpMime )
02300 {
02301 emit itemsFilteredByMime( *tmpMime );
02302 delete tmpMime;
02303 }
02304
02305 if ( tmpRefresh )
02306 {
02307 emit refreshItems( *tmpRefresh );
02308 delete tmpRefresh;
02309 }
02310
02311 if ( tmpRemove )
02312 {
02313 for ( KFileItem *tmp = tmpRemove->first(); tmp; tmp = tmpRemove->next() )
02314 emit deleteItem( tmp );
02315 delete tmpRemove;
02316 }
02317 }
02318
02319 void KDirLister::emitDeleteItem( KFileItem *item )
02320 {
02321 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) )
02322 return;
02323 if ( matchesMimeFilter( item ) )
02324 emit deleteItem( item );
02325 }
02326
02327
02328
02329
02330 void KDirLister::slotInfoMessage( KIO::Job *, const QString& message )
02331 {
02332 emit infoMessage( message );
02333 }
02334
02335 void KDirLister::slotPercent( KIO::Job *job, unsigned long pcnt )
02336 {
02337 d->jobData[static_cast<KIO::ListJob *>(job)].percent = pcnt;
02338
02339 int result = 0;
02340
02341 KIO::filesize_t size = 0;
02342
02343 QMap< KIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
02344 while ( dataIt != d->jobData.end() )
02345 {
02346 result += (*dataIt).percent * (*dataIt).totalSize;
02347 size += (*dataIt).totalSize;
02348 ++dataIt;
02349 }
02350
02351 if ( size != 0 )
02352 result /= size;
02353 else
02354 result = 100;
02355 emit percent( result );
02356 }
02357
02358 void KDirLister::slotTotalSize( KIO::Job *job, KIO::filesize_t size )
02359 {
02360 d->jobData[static_cast<KIO::ListJob *>(job)].totalSize = size;
02361
02362 KIO::filesize_t result = 0;
02363 QMap< KIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
02364 while ( dataIt != d->jobData.end() )
02365 {
02366 result += (*dataIt).totalSize;
02367 ++dataIt;
02368 }
02369
02370 emit totalSize( result );
02371 }
02372
02373 void KDirLister::slotProcessedSize( KIO::Job *job, KIO::filesize_t size )
02374 {
02375 d->jobData[static_cast<KIO::ListJob *>(job)].processedSize = size;
02376
02377 KIO::filesize_t result = 0;
02378 QMap< KIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
02379 while ( dataIt != d->jobData.end() )
02380 {
02381 result += (*dataIt).processedSize;
02382 ++dataIt;
02383 }
02384
02385 emit processedSize( result );
02386 }
02387
02388 void KDirLister::slotSpeed( KIO::Job *job, unsigned long spd )
02389 {
02390 d->jobData[static_cast<KIO::ListJob *>(job)].speed = spd;
02391
02392 int result = 0;
02393 QMap< KIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
02394 while ( dataIt != d->jobData.end() )
02395 {
02396 result += (*dataIt).speed;
02397 ++dataIt;
02398 }
02399
02400 emit speed( result );
02401 }
02402
02403 uint KDirLister::numJobs()
02404 {
02405 return d->jobData.count();
02406 }
02407
02408 void KDirLister::jobDone( KIO::ListJob *job )
02409 {
02410 d->jobData.remove( job );
02411 }
02412
02413 void KDirLister::jobStarted( KIO::ListJob *job )
02414 {
02415 KDirListerPrivate::JobData jobData;
02416 jobData.speed = 0;
02417 jobData.percent = 0;
02418 jobData.processedSize = 0;
02419 jobData.totalSize = 0;
02420
02421 d->jobData.insert( job, jobData );
02422 d->complete = false;
02423 }
02424
02425 void KDirLister::connectJob( KIO::ListJob *job )
02426 {
02427 connect( job, SIGNAL(infoMessage( KIO::Job *, const QString& )),
02428 this, SLOT(slotInfoMessage( KIO::Job *, const QString& )) );
02429 connect( job, SIGNAL(percent( KIO::Job *, unsigned long )),
02430 this, SLOT(slotPercent( KIO::Job *, unsigned long )) );
02431 connect( job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t )),
02432 this, SLOT(slotTotalSize( KIO::Job *, KIO::filesize_t )) );
02433 connect( job, SIGNAL(processedSize( KIO::Job *, KIO::filesize_t )),
02434 this, SLOT(slotProcessedSize( KIO::Job *, KIO::filesize_t )) );
02435 connect( job, SIGNAL(speed( KIO::Job *, unsigned long )),
02436 this, SLOT(slotSpeed( KIO::Job *, unsigned long )) );
02437 }
02438
02439 void KDirLister::setMainWindow( QWidget *window )
02440 {
02441 d->window = window;
02442 }
02443
02444 QWidget *KDirLister::mainWindow()
02445 {
02446 return d->window;
02447 }
02448
02449 KFileItemList KDirLister::items( WhichItems which ) const
02450 {
02451 return itemsForDir( url(), which );
02452 }
02453
02454 KFileItemList KDirLister::itemsForDir( const KURL& dir, WhichItems which ) const
02455 {
02456 KFileItemList result;
02457 KFileItemList *allItems = s_pCache->itemsForDir( dir );
02458 if ( !allItems )
02459 return result;
02460
02461 if ( which == AllItems )
02462 result = *allItems;
02463 else
02464 {
02465 for ( KFileItemListIterator kit( *allItems ); kit.current(); ++kit )
02466 {
02467 KFileItem *item = *kit;
02468 bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
02469 if ( !isExcluded && matchesMimeFilter( item ) )
02470 result.append( item );
02471 }
02472 }
02473
02474 return result;
02475 }
02476
02477
02478
02479 void KDirLister::virtual_hook( int, void * )
02480 { }
02481
02482 #include "kdirlister.moc"
02483 #include "kdirlister_p.moc"