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