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"