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