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