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