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