• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
kdirlister.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 2001-2005 Michael Brade <brade@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "kdirlister.h"
23
24#include <tqregexp.h>
25#include <tqptrlist.h>
26#include <tqtimer.h>
27#include <tqeventloop.h>
28
29#include <tdeapplication.h>
30#include <kdebug.h>
31#include <tdelocale.h>
32#include <tdeio/job.h>
33#include <tdemessagebox.h>
34#include <tdeglobal.h>
35#include <tdeglobalsettings.h>
36#include <kstaticdeleter.h>
37#include <kprotocolinfo.h>
38
39#include "kdirlister_p.h"
40
41#include <assert.h>
42#include <unistd.h>
43
44KDirListerCache* KDirListerCache::s_pSelf = 0;
45static KStaticDeleter<KDirListerCache> sd_KDirListerCache;
46
47// Enable this to get printDebug() called often, to see the contents of the cache
48//#define DEBUG_CACHE
49
50// Make really sure it doesn't get activated in the final build
51#ifdef NDEBUG
52#undef DEBUG_CACHE
53#endif
54
55KDirListerCache::KDirListerCache( int maxCount )
56 : itemsCached( maxCount )
57{
58 kdDebug(7004) << "+KDirListerCache" << endl;
59
60 itemsInUse.setAutoDelete( false );
61 itemsCached.setAutoDelete( true );
62 urlsCurrentlyListed.setAutoDelete( true );
63 urlsCurrentlyHeld.setAutoDelete( true );
64 pendingUpdates.setAutoDelete( true );
65
66 connect( kdirwatch, TQ_SIGNAL( dirty( const KURL& ) ),
67 this, TQ_SLOT( slotFileDirty( const KURL& ) ) );
68 connect( kdirwatch, TQ_SIGNAL( created( const TQString& ) ),
69 this, TQ_SLOT( slotFileCreated( const TQString& ) ) );
70 connect( kdirwatch, TQ_SIGNAL( deleted( const TQString& ) ),
71 this, TQ_SLOT( slotFileDeleted( const TQString& ) ) );
72}
73
74KDirListerCache::~KDirListerCache()
75{
76 kdDebug(7004) << "-KDirListerCache" << endl;
77
78 itemsInUse.setAutoDelete( true );
79 itemsInUse.clear();
80 itemsCached.clear();
81 urlsCurrentlyListed.clear();
82 urlsCurrentlyHeld.clear();
83
84 if ( KDirWatch::exists() )
85 kdirwatch->disconnect( this );
86}
87
88// setting _reload to true will emit the old files and
89// call updateDirectory
90bool KDirListerCache::listDir( KDirLister *lister, const KURL& _u,
91 bool _keep, bool _reload )
92{
93 // like this we don't have to worry about trailing slashes any further
94 KURL _url = _u;
95 _url.cleanPath(); // kill consecutive slashes
96 _url.adjustPath(-1);
97 TQString urlStr = _url.url();
98 TQString urlReferenceStr = _url.internalReferenceURL();
99
100 if ( !lister->validURL( _url ) ) {
101 return false;
102 }
103
104#ifdef DEBUG_CACHE
105 printDebug();
106#endif
107 kdDebug(7004) << k_funcinfo << lister << " url=" << _url
108 << " keep=" << _keep << " reload=" << _reload << endl;
109
110 if ( !_keep )
111 {
112 // stop any running jobs for lister
113 stop( lister );
114
115 // clear our internal list for lister
116 forgetDirs( lister );
117
118 lister->d->rootFileItem = 0;
119 }
120 else if ( lister->d->lstDirs.find( _url ) != lister->d->lstDirs.end() )
121 {
122 // stop the job listing _url for this lister
123 stop( lister, _url );
124
125 // clear _url for lister
126 forgetDirs( lister, _url, true );
127
128 if ( lister->d->url == _url )
129 lister->d->rootFileItem = 0;
130 }
131
132 lister->d->lstDirs.append( _url );
133
134 if ( lister->d->url.isEmpty() || !_keep ) // set toplevel URL only if not set yet
135 lister->d->url = _url;
136
137 DirItem *itemU = itemsInUse[urlStr + ":" + urlReferenceStr];
138 DirItem *itemC;
139
140 if ( !urlsCurrentlyListed[urlStr + ":" + urlReferenceStr] )
141 {
142 // if there is an update running for _url already we get into
143 // the following case - it will just be restarted by updateDirectory().
144
145 if ( itemU )
146 {
147 kdDebug(7004) << "listDir: Entry already in use: " << _url << endl;
148
149 bool oldState = lister->d->complete;
150 lister->d->complete = false;
151
152 emit lister->started( _url );
153
154 if ( !lister->d->rootFileItem && lister->d->url == _url ) {
155 lister->d->rootFileItem = itemU->rootItem;
156 }
157
158 lister->addNewItems( *(itemU->lstItems) );
159 lister->emitItems();
160
161 // _url is already in use, so there is already an entry in urlsCurrentlyHeld
162 assert( urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr] );
163 urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr]->append( lister );
164
165 lister->d->complete = oldState;
166
167 lister->emitCompleted( _url );
168 if ( lister->d->complete ) {
169 emit lister->completed();
170 }
171
172 if ( _reload || !itemU->complete ) {
173 updateDirectory( _url );
174 }
175 }
176 else if ( !_reload && (itemC = itemsCached.take( urlStr )) )
177 {
178 kdDebug(7004) << "listDir: Entry in cache: " << _url << endl;
179
180 itemC->decAutoUpdate();
181 itemsInUse.insert( urlStr + ":" + urlReferenceStr, itemC );
182 itemU = itemC;
183
184 bool oldState = lister->d->complete;
185 lister->d->complete = false;
186
187 emit lister->started( _url );
188
189 if ( !lister->d->rootFileItem && lister->d->url == _url ) {
190 lister->d->rootFileItem = itemC->rootItem;
191 }
192
193 lister->addNewItems( *(itemC->lstItems) );
194 lister->emitItems();
195
196 Q_ASSERT( !urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr] );
197 TQPtrList<KDirLister> *list = new TQPtrList<KDirLister>;
198 list->append( lister );
199 urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, list );
200
201 lister->d->complete = oldState;
202
203 lister->emitCompleted( _url );
204 if ( lister->d->complete ) {
205 emit lister->completed();
206 }
207
208 if ( !itemC->complete ) {
209 updateDirectory( _url );
210 }
211 }
212 else // dir not in cache or _reload is true
213 {
214 kdDebug(7004) << "listDir: Entry not in cache or reloaded: " << _url << endl;
215
216 TQPtrList<KDirLister> *list = new TQPtrList<KDirLister>;
217 list->append( lister );
218 urlsCurrentlyListed.insert( urlStr + ":" + urlReferenceStr, list );
219
220 itemsCached.remove( urlStr );
221 itemU = new DirItem( _url );
222 itemsInUse.insert( urlStr + ":" + urlReferenceStr, itemU );
223
224// // we have a limit of MAX_JOBS_PER_LISTER concurrently running jobs
225// if ( lister->numJobs() >= MAX_JOBS_PER_LISTER )
226// {
227// lstPendingUpdates.append( _url );
228// }
229// else
230// {
231
232 if ( lister->d->url == _url ) {
233 lister->d->rootFileItem = 0;
234 }
235
236 TDEIO::ListJob* job = TDEIO::listDir( _url, false /* no default GUI */ );
237 jobs.insert( job, TQValueList<TDEIO::UDSEntry>() );
238
239 lister->jobStarted( job );
240 lister->connectJob( job );
241
242 if ( lister->d->window ) {
243 job->setWindow( lister->d->window );
244 }
245
246 connect( job, TQ_SIGNAL( entries( TDEIO::Job *, const TDEIO::UDSEntryList & ) ),
247 this, TQ_SLOT( slotEntries( TDEIO::Job *, const TDEIO::UDSEntryList & ) ) );
248 connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
249 this, TQ_SLOT( slotResult( TDEIO::Job * ) ) );
250 connect( job, TQ_SIGNAL( redirection( TDEIO::Job *, const KURL & ) ),
251 this, TQ_SLOT( slotRedirection( TDEIO::Job *, const KURL & ) ) );
252
253 emit lister->started( _url );
254
255// }
256 }
257 }
258 else
259 {
260 kdDebug(7004) << "listDir: Entry currently being listed: " << _url << endl;
261
262 emit lister->started( _url );
263
264 urlsCurrentlyListed[urlStr + ":" + urlReferenceStr]->append( lister );
265
266 TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
267 Q_ASSERT( job );
268
269 lister->jobStarted( job );
270 lister->connectJob( job );
271
272 Q_ASSERT( itemU );
273
274 if ( !lister->d->rootFileItem && lister->d->url == _url ) {
275 lister->d->rootFileItem = itemU->rootItem;
276 }
277
278 lister->addNewItems( *(itemU->lstItems) );
279 lister->emitItems();
280 }
281
282 // automatic updating of directories
283 if ( lister->d->autoUpdate ) {
284 itemU->incAutoUpdate();
285 }
286
287 return true;
288}
289
290bool KDirListerCache::validURL( const KDirLister *lister, const KURL& url ) const
291{
292 if ( !url.isValid() )
293 {
294 if ( lister->d->autoErrorHandling )
295 {
296 TQString tmp = i18n("Malformed URL\n%1").arg( url.prettyURL() );
297 KMessageBox::error( lister->d->errorParent, tmp );
298 }
299 return false;
300 }
301
302 if ( !KProtocolInfo::supportsListing( url ) )
303 {
304 if ( lister->d->autoErrorHandling )
305 {
306 // TODO: this message should be changed during next string unfreeze!
307 TQString tmp = i18n("Malformed URL\n%1").arg( url.prettyURL() );
308 KMessageBox::error( lister->d->errorParent, tmp );
309 }
310 return false;
311 }
312
313 return true;
314}
315
316void KDirListerCache::stop( KDirLister *lister )
317{
318#ifdef DEBUG_CACHE
319 printDebug();
320#endif
321 kdDebug(7004) << k_funcinfo << "lister: " << lister << endl;
322 bool stopped = false;
323
324 TQDictIterator< TQPtrList<KDirLister> > it( urlsCurrentlyListed );
325 TQPtrList<KDirLister> *listers;
326 int curIndex;
327 while ( (listers = it.current()) )
328 {
329 curIndex = listers->findRef( lister );
330 if ( curIndex > -1 )
331 {
332 // lister is listing url
333 TQString url = it.currentKey();
334 KDirLister* curLister = listers->at( curIndex );
335
336 //kdDebug(7004) << k_funcinfo << " found lister in list - for " << url << endl;
337 bool ret = listers->removeRef( lister );
338 Q_ASSERT( ret );
339
340 TDEIO::ListJob *job = jobForUrl( url );
341 if ( job ) {
342 lister->jobDone( job );
343 }
344
345 // move lister to urlsCurrentlyHeld
346 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[url];
347 if ( !holders )
348 {
349 holders = new TQPtrList<KDirLister>;
350 urlsCurrentlyHeld.insert( url, holders );
351 }
352
353 holders->append( lister );
354
355 emit lister->canceled( curLister->d->url );
356
357 //kdDebug(7004) << k_funcinfo << "remaining list: " << listers->count() << " listers" << endl;
358
359 if ( listers->isEmpty() )
360 {
361 // kill the job since it isn't used any more
362 if ( job ) {
363 killJob( job );
364 }
365
366 urlsCurrentlyListed.remove( url );
367 }
368
369 stopped = true;
370 }
371 else
372 ++it;
373 }
374
375 if ( stopped )
376 {
377 emit lister->canceled();
378 lister->d->complete = true;
379 }
380
381 // this is wrong if there is still an update running!
382 //Q_ASSERT( lister->d->complete );
383}
384
385void KDirListerCache::stop( KDirLister *lister, const KURL& _u )
386{
387 TQString urlStr( _u.url(-1) );
388 TQString urlReferenceStr = _u.internalReferenceURL();
389 KURL _url( urlStr );
390
391 // TODO: consider to stop all the "child jobs" of _url as well
392 kdDebug(7004) << k_funcinfo << lister << " url=" << _url << endl;
393
394 TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
395 if ( !listers || !listers->removeRef( lister ) )
396 return;
397
398 // move lister to urlsCurrentlyHeld
399 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
400 if ( !holders )
401 {
402 holders = new TQPtrList<KDirLister>;
403 urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, holders );
404 }
405
406 holders->append( lister );
407
408
409 TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
410 if ( job ) {
411 lister->jobDone( job );
412 }
413
414 emit lister->canceled( _url );
415
416 if ( listers->isEmpty() )
417 {
418 // kill the job since it isn't used any more
419 if ( job )
420 killJob( job );
421
422 urlsCurrentlyListed.remove( urlStr + ":" + urlReferenceStr );
423 }
424
425 if ( lister->numJobs() == 0 )
426 {
427 lister->d->complete = true;
428
429 // we killed the last job for lister
430 emit lister->canceled();
431 }
432}
433
434void KDirListerCache::setAutoUpdate( KDirLister *lister, bool enable )
435{
436 // IMPORTANT: this method does not check for the current autoUpdate state!
437
438 for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
439 it != lister->d->lstDirs.end(); ++it )
440 {
441 if ( enable ) {
442 itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->incAutoUpdate();
443 }
444 else {
445 itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->decAutoUpdate();
446 }
447 }
448}
449
450void KDirListerCache::forgetDirs( KDirLister *lister )
451{
452 kdDebug(7004) << k_funcinfo << lister << endl;
453
454 emit lister->clear();
455
456 // forgetDirs() will modify lstDirs, make a copy first
457 KURL::List lstDirsCopy = lister->d->lstDirs;
458 for ( KURL::List::Iterator it = lstDirsCopy.begin();
459 it != lstDirsCopy.end(); ++it )
460 {
461 forgetDirs( lister, *it, false );
462 }
463}
464
465void KDirListerCache::forgetDirs( KDirLister *lister, const KURL& _url, bool notify )
466{
467 kdDebug(7004) << k_funcinfo << lister << " _url: " << _url << endl;
468
469 KURL url( _url );
470 url.adjustPath( -1 );
471 TQString urlStr = url.url();
472 TQString urlReferenceStr = url.internalReferenceURL();
473 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
474 //Q_ASSERT( holders );
475 if ( holders )
476 {
477 holders->removeRef( lister );
478 }
479
480 // remove the dir from lister->d->lstDirs so that it doesn't contain things
481 // that itemsInUse doesn't. When emitting the canceled signals lstDirs must
482 // not contain anything that itemsInUse does not contain. (otherwise it
483 // might crash in findByName()).
484 lister->d->lstDirs.remove( lister->d->lstDirs.find( url ) );
485
486 DirItem *item = itemsInUse[urlStr + ":" + urlReferenceStr];
487
488 if ( holders && holders->isEmpty() )
489 {
490 urlsCurrentlyHeld.remove( urlStr + ":" + urlReferenceStr ); // this deletes the (empty) holders list
491 if ( !urlsCurrentlyListed[urlStr + ":" + urlReferenceStr] )
492 {
493 // item not in use anymore -> move into cache if complete
494 itemsInUse.remove( urlStr + ":" + urlReferenceStr );
495
496 // this job is a running update
497 TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
498 if ( job )
499 {
500 lister->jobDone( job );
501 killJob( job );
502 kdDebug(7004) << k_funcinfo << "Killing update job for " << urlStr << endl;
503
504 emit lister->canceled( url );
505 if ( lister->numJobs() == 0 )
506 {
507 lister->d->complete = true;
508 emit lister->canceled();
509 }
510 }
511
512 if ( notify )
513 emit lister->clear( url );
514
515 if ( item && item->complete )
516 {
517 kdDebug(7004) << k_funcinfo << lister << " item moved into cache: " << url << endl;
518 itemsCached.insert( urlStr, item ); // TODO: may return false!!
519
520 // Should we forget the dir for good, or keep a watch on it?
521 // Generally keep a watch, except when it would prevent
522 // unmounting a removable device (#37780)
523 const bool isLocal = item->url.isLocalFile();
524 const bool isManuallyMounted = isLocal && TDEIO::manually_mounted( item->url.path() );
525 bool containsManuallyMounted = false;
526 if ( !isManuallyMounted && item->lstItems && isLocal )
527 {
528 // Look for a manually-mounted directory inside
529 // If there's one, we can't keep a watch either, FAM would prevent unmounting the CDROM
530 // I hope this isn't too slow (manually_mounted caches the last device so most
531 // of the time this is just a stat per subdir)
532 KFileItemListIterator kit( *item->lstItems );
533 for ( ; kit.current() && !containsManuallyMounted; ++kit )
534 if ( (*kit)->isDir() && TDEIO::manually_mounted( (*kit)->url().path() ) )
535 containsManuallyMounted = true;
536 }
537
538 if ( isManuallyMounted || containsManuallyMounted )
539 {
540 kdDebug(7004) << "Not adding a watch on " << item->url << " because it " <<
541 ( isManuallyMounted ? "is manually mounted" : "contains a manually mounted subdir" ) << endl;
542 item->complete = false; // set to "dirty"
543 }
544 else
545 item->incAutoUpdate(); // keep watch
546 }
547 else
548 {
549 delete item;
550 item = 0;
551 }
552 }
553 }
554
555 if ( item && lister->d->autoUpdate )
556 item->decAutoUpdate();
557}
558
559void KDirListerCache::updateDirectory( const KURL& _dir )
560{
561 kdDebug(7004) << k_funcinfo << _dir << endl;
562
563 TQString urlStr = _dir.url(-1);
564 TQString urlReferenceStr = _dir.internalReferenceURL();
565 if ( !checkUpdate( _dir, -1 ) ) {
566 return;
567 }
568
569 // A job can be running to
570 // - only list a new directory: the listers are in urlsCurrentlyListed
571 // - only update a directory: the listers are in urlsCurrentlyHeld
572 // - update a currently running listing: the listers are in urlsCurrentlyListed
573 // and urlsCurrentlyHeld
574
575 TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
576 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld[urlStr + ":" + urlReferenceStr];
577
578 // restart the job for _dir if it is running already
579 bool killed = false;
580 TQWidget *window = 0;
581 TDEIO::ListJob *job = jobForUrl( urlStr + ":" + urlReferenceStr );
582 if ( job )
583 {
584 window = job->window();
585
586 killJob( job );
587 killed = true;
588
589 if ( listers ) {
590 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
591 kdl->jobDone( job );
592 }
593 }
594
595 if ( holders ) {
596 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() ) {
597 kdl->jobDone( job );
598 }
599 }
600 }
601 kdDebug(7004) << k_funcinfo << "Killed = " << killed << endl;
602
603 // we don't need to emit canceled signals since we only replaced the job,
604 // the listing is continuing.
605
606 Q_ASSERT( !listers || (listers && killed) );
607
608 job = TDEIO::listDir( _dir, false /* no default GUI */ );
609 jobs.insert( job, TQValueList<TDEIO::UDSEntry>() );
610
611 connect( job, TQ_SIGNAL(entries( TDEIO::Job *, const TDEIO::UDSEntryList & )),
612 this, TQ_SLOT(slotUpdateEntries( TDEIO::Job *, const TDEIO::UDSEntryList & )) );
613 connect( job, TQ_SIGNAL(result( TDEIO::Job * )),
614 this, TQ_SLOT(slotUpdateResult( TDEIO::Job * )) );
615
616 kdDebug(7004) << k_funcinfo << "update started in " << _dir << endl;
617
618 if ( listers ) {
619 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
620 kdl->jobStarted( job );
621 }
622 }
623
624 if ( holders )
625 {
626 if ( !killed )
627 {
628 bool first = true;
629 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
630 {
631 kdl->jobStarted( job );
632 if ( first && kdl->d->window )
633 {
634 first = false;
635 job->setWindow( kdl->d->window );
636 }
637 emit kdl->started( _dir );
638 }
639 }
640 else
641 {
642 job->setWindow( window );
643
644 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() ) {
645 kdl->jobStarted( job );
646 }
647 }
648 }
649}
650
651bool KDirListerCache::checkUpdate( const KURL& _dir, int truncationMode )
652{
653 if ( !itemsInUse[_dir.url(truncationMode) + ":" + _dir.internalReferenceURL()] )
654 {
655 DirItem *item = itemsCached[_dir.url(truncationMode)];
656 if ( item && item->complete )
657 {
658 item->complete = false;
659 item->decAutoUpdate();
660 // Hmm, this debug output might include login/password from the _dir URL.
661 //kdDebug(7004) << k_funcinfo << "directory " << _dir << " not in use, marked dirty." << endl;
662 }
663 //else
664 //kdDebug(7004) << k_funcinfo << "aborted, directory " << _dir << " not in cache." << endl;
665
666 return false;
667 }
668 else
669 return true;
670}
671
672KFileItemList *KDirListerCache::itemsForDir( const KURL &_dir ) const
673{
674 TQString urlStr = _dir.url(-1);
675 TQString urlReferenceStr = _dir.internalReferenceURL();
676 DirItem *item = itemsInUse[ urlStr + ":" + urlReferenceStr ];
677 if ( !item ) {
678 item = itemsCached[ urlStr ];
679 }
680 return item ? item->lstItems : 0;
681}
682
683KFileItem *KDirListerCache::findByName( const KDirLister *lister, const TQString& _name ) const
684{
685 Q_ASSERT( lister );
686
687 for ( KURL::List::Iterator it = lister->d->lstDirs.begin();
688 it != lister->d->lstDirs.end(); ++it )
689 {
690 KFileItemListIterator kit( *itemsInUse[(*it).url() + ":" + (*it).internalReferenceURL()]->lstItems );
691 for ( ; kit.current(); ++kit )
692 if ( (*kit)->name() == _name )
693 return (*kit);
694 }
695
696 return 0L;
697}
698
699KFileItem *KDirListerCache::findByURL( const KDirLister *lister, const KURL& _u ) const
700{
701 KURL _url = _u;
702 _url.adjustPath(-1);
703
704 KURL parentDir( _url );
705 parentDir.setPath( parentDir.directory() );
706
707 // If lister is set, check that it contains this dir
708 if ( lister && !lister->d->lstDirs.contains( parentDir ) )
709 return 0L;
710
711 KFileItemList *itemList = itemsForDir( parentDir );
712 if ( itemList )
713 {
714 KFileItemListIterator kit( *itemList );
715 for ( ; kit.current(); ++kit )
716 if ( (*kit)->url() == _url )
717 return (*kit);
718 }
719 return 0L;
720}
721
722void KDirListerCache::FilesAdded( const KURL &dir )
723{
724 kdDebug(7004) << k_funcinfo << dir << endl;
725 updateDirectory( dir );
726}
727
728void KDirListerCache::FilesRemoved( const KURL::List &fileList )
729{
730 kdDebug(7004) << k_funcinfo << endl;
731 KURL::List::ConstIterator it = fileList.begin();
732 for ( ; it != fileList.end() ; ++it )
733 {
734 // emit the deleteItem signal if this file was shown in any view
735 KFileItem *fileitem = 0L;
736 KURL parentDir( *it );
737 parentDir.setPath( parentDir.directory() );
738 KFileItemList *lstItems = itemsForDir( parentDir );
739 if ( lstItems )
740 {
741 KFileItem *fit = lstItems->first();
742 for ( ; fit; fit = lstItems->next() )
743 if ( fit->url() == *it ) {
744 fileitem = fit;
745 lstItems->take(); // remove fileitem from list
746 break;
747 }
748 }
749
750 // Tell the views about it before deleting the KFileItems. They might need the subdirs'
751 // file items (see the dirtree).
752 if ( fileitem )
753 {
754 TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDir.url() + ":" + parentDir.internalReferenceURL()];
755 if ( listers ) {
756 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
757 kdl->emitDeleteItem( fileitem );
758 }
759 }
760 }
761
762 // If we found a fileitem, we can test if it's a dir. If not, we'll go to deleteDir just in case.
763 if ( !fileitem || fileitem->isDir() )
764 {
765 // in case of a dir, check if we have any known children, there's much to do in that case
766 // (stopping jobs, removing dirs from cache etc.)
767 deleteDir( *it );
768 }
769
770 // now remove the item itself
771 delete fileitem;
772 }
773}
774
775void KDirListerCache::FilesChanged( const KURL::List &fileList )
776{
777 KURL::List dirsToUpdate;
778 kdDebug(7004) << k_funcinfo << "only half implemented" << endl;
779 KURL::List::ConstIterator it = fileList.begin();
780 for ( ; it != fileList.end() ; ++it )
781 {
782 if ( ( *it ).isLocalFile() )
783 {
784 kdDebug(7004) << "KDirListerCache::FilesChanged " << *it << endl;
785 KFileItem *fileitem = findByURL( 0, *it );
786 if ( fileitem )
787 {
788 // we need to refresh the item, because e.g. the permissions can have changed.
789 aboutToRefreshItem( fileitem );
790 fileitem->refresh();
791 emitRefreshItem( fileitem );
792 }
793 else {
794 kdDebug(7004) << "item not found" << endl;
795 }
796 } else {
797 // For remote files, refresh() won't be able to figure out the new information.
798 // Let's update the dir.
799 KURL dir( *it );
800 dir.setPath( dir.directory( true ) );
801 if ( dirsToUpdate.find( dir ) == dirsToUpdate.end() ) {
802 dirsToUpdate.prepend( dir );
803 }
804 }
805 }
806
807 KURL::List::ConstIterator itdir = dirsToUpdate.begin();
808 for ( ; itdir != dirsToUpdate.end() ; ++itdir ) {
809 updateDirectory( *itdir );
810 }
811 // ## TODO problems with current jobs listing/updating that dir
812 // ( see kde-2.2.2's kdirlister )
813}
814
815void KDirListerCache::FileRenamed( const KURL &src, const KURL &dst )
816{
817 kdDebug(7004) << k_funcinfo << src.prettyURL() << " -> " << dst.prettyURL() << endl;
818#ifdef DEBUG_CACHE
819 printDebug();
820#endif
821
822 // Somehow this should only be called if src is a dir. But how could we know if it is?
823 // (Note that looking into itemsInUse isn't good enough. One could rename a subdir in a view.)
824 renameDir( src, dst );
825
826 // Now update the KFileItem representing that file or dir (not exclusive with the above!)
827 KURL oldurl( src );
828 oldurl.adjustPath( -1 );
829 KFileItem *fileitem = findByURL( 0, oldurl );
830 if ( fileitem )
831 {
832 if ( !fileitem->isLocalFile() && !fileitem->localPath().isEmpty() ) // it uses UDS_LOCAL_PATH? ouch, needs an update then
833 FilesChanged( src );
834 else
835 {
836 aboutToRefreshItem( fileitem );
837 fileitem->setURL( dst );
838 fileitem->refreshMimeType();
839 emitRefreshItem( fileitem );
840 }
841 }
842#ifdef DEBUG_CACHE
843 printDebug();
844#endif
845}
846
847void KDirListerCache::aboutToRefreshItem( KFileItem *fileitem )
848{
849 // Look whether this item was shown in any view, i.e. held by any dirlister
850 KURL parentDir( fileitem->url() );
851 parentDir.setPath( parentDir.directory() );
852 TQString parentDirURL = parentDir.url();
853 TQString parentDirReferenceURL = parentDir.internalReferenceURL();
854 TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL + ":" + parentDirReferenceURL];
855 if ( listers )
856 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
857 kdl->aboutToRefreshItem( fileitem );
858
859 // Also look in urlsCurrentlyListed, in case the user manages to rename during a listing
860 listers = urlsCurrentlyListed[parentDirURL + ":" + parentDirReferenceURL];
861 if ( listers )
862 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
863 kdl->aboutToRefreshItem( fileitem );
864}
865
866void KDirListerCache::emitRefreshItem( KFileItem *fileitem )
867{
868 // Look whether this item was shown in any view, i.e. held by any dirlister
869 KURL parentDir( fileitem->url() );
870 parentDir.setPath( parentDir.directory() );
871 TQString parentDirURL = parentDir.url();
872 TQString parentDirReferenceURL = parentDir.internalReferenceURL();
873 TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[parentDirURL + ":" + parentDirReferenceURL];
874 if ( listers )
875 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
876 {
877 kdl->addRefreshItem( fileitem );
878 kdl->emitItems();
879 }
880
881 // Also look in urlsCurrentlyListed, in case the user manages to rename during a listing
882 listers = urlsCurrentlyListed[parentDirURL + ":" + parentDirReferenceURL];
883 if ( listers )
884 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
885 {
886 kdl->addRefreshItem( fileitem );
887 kdl->emitItems();
888 }
889}
890
891KDirListerCache* KDirListerCache::self()
892{
893 if ( !s_pSelf )
894 s_pSelf = sd_KDirListerCache.setObject( s_pSelf, new KDirListerCache );
895
896 return s_pSelf;
897}
898
899bool KDirListerCache::exists()
900{
901 return s_pSelf != 0;
902}
903
904
905// private slots
906
907// _file can also be a directory being currently held!
908void KDirListerCache::slotFileDirty( const KURL& _url )
909{
910 kdDebug(7004) << k_funcinfo << _url << endl;
911
912 if ( !pendingUpdates[_url.path()] )
913 {
914 KURL dir;
915 dir.setPath( _url.path() );
916 dir.setInternalReferenceURL(_url.internalReferenceURL());
917 if ( checkUpdate( dir, -1 ) ) {
918 updateDirectory( _url );
919 }
920
921 // the parent directory of _url.path()
922 dir.setPath( dir.directory() );
923 dir.setInternalReferenceURL(_url.internalReferenceURL());
924 if ( checkUpdate( dir ) )
925 {
926 // Nice hack to save memory: use the qt object name to store the filename
927 TQTimer *timer = new TQTimer( this, _url.path().utf8() );
928 connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotFileDirtyDelayed()) );
929 pendingUpdates.insert( _url.path(), timer );
930 timer->start( 500, true );
931 }
932 }
933}
934
935// delayed updating of files, FAM is flooding us with events
936void KDirListerCache::slotFileDirtyDelayed()
937{
938 TQString file = TQString::fromUtf8( sender()->name() );
939
940 kdDebug(7004) << k_funcinfo << file << endl;
941
942 // TODO: do it better: don't always create/delete the TQTimer but reuse it.
943 // Delete the timer after the parent directory is removed from the cache.
944 pendingUpdates.remove( file );
945
946 KURL u;
947 u.setPath( file );
948 KFileItem *item = findByURL( 0, u ); // search all items
949 if ( item )
950 {
951 // we need to refresh the item, because e.g. the permissions can have changed.
952 aboutToRefreshItem( item );
953 item->refresh();
954 emitRefreshItem( item );
955 }
956}
957
958void KDirListerCache::slotFileCreated( const TQString& _file )
959{
960 kdDebug(7004) << k_funcinfo << _file << endl;
961 // XXX: how to avoid a complete rescan here?
962 KURL u;
963 u.setPath( _file );
964 u.setPath( u.directory() );
965 FilesAdded( u );
966}
967
968void KDirListerCache::slotFileDeleted( const TQString& _file )
969{
970 kdDebug(7004) << k_funcinfo << _file << endl;
971 KURL u;
972 u.setPath( _file );
973 FilesRemoved( u );
974}
975
976void KDirListerCache::slotEntries( TDEIO::Job *job, const TDEIO::UDSEntryList &entries )
977{
978 KURL url = joburl( static_cast<TDEIO::ListJob *>(job) );
979 url.adjustPath(-1);
980 TQString urlStr = url.url();
981 TQString urlReferenceStr = url.internalReferenceURL();
982
983 kdDebug(7004) << k_funcinfo << "new entries for " << url << endl;
984
985 DirItem *dir = itemsInUse[urlStr + ":" + urlReferenceStr];
986 Q_ASSERT( dir );
987
988 TQPtrList<KDirLister> *listers = urlsCurrentlyListed[urlStr + ":" + urlReferenceStr];
989 Q_ASSERT( listers );
990 Q_ASSERT( !listers->isEmpty() );
991
992 // check if anyone wants the mimetypes immediately
993 bool delayedMimeTypes = true;
994 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
995 delayedMimeTypes = delayedMimeTypes && kdl->d->delayedMimeTypes;
996 }
997
998 // avoid creating these QStrings again and again
999 static const TQString& dot = TDEGlobal::staticQString(".");
1000 static const TQString& dotdot = TDEGlobal::staticQString("..");
1001
1002 TDEIO::UDSEntryListConstIterator it = entries.begin();
1003 TDEIO::UDSEntryListConstIterator end = entries.end();
1004
1005 for ( ; it != end; ++it )
1006 {
1007 TQString name;
1008
1009 // find out about the name
1010 TDEIO::UDSEntry::ConstIterator entit = (*it).begin();
1011 for( ; entit != (*it).end(); ++entit ) {
1012 if ( (*entit).m_uds == TDEIO::UDS_NAME ) {
1013 name = (*entit).m_str;
1014 break;
1015 }
1016 }
1017
1018 Q_ASSERT( !name.isEmpty() );
1019 if ( name.isEmpty() ) {
1020 continue;
1021 }
1022
1023 if ( name == dot )
1024 {
1025 Q_ASSERT( !dir->rootItem );
1026 dir->rootItem = new KFileItem( *it, url, delayedMimeTypes, true );
1027
1028 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1029 if ( !kdl->d->rootFileItem && kdl->d->url == url ) {
1030 kdl->d->rootFileItem = dir->rootItem;
1031 }
1032 }
1033 }
1034 else if ( name != dotdot )
1035 {
1036 KFileItem* item = new KFileItem( *it, url, delayedMimeTypes, true );
1037 Q_ASSERT( item );
1038
1039 //kdDebug(7004)<< "Adding item: " << item->url() << endl;
1040 dir->lstItems->append( item );
1041
1042 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1043 kdl->addNewItem( item );
1044 }
1045 }
1046 }
1047
1048 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1049 kdl->emitItems();
1050 }
1051}
1052
1053void KDirListerCache::slotResult( TDEIO::Job *j )
1054{
1055 Q_ASSERT( j );
1056 TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1057 jobs.remove( job );
1058
1059 KURL jobUrl = joburl( job );
1060 jobUrl.adjustPath(-1); // need remove trailing slashes again, in case of redirections
1061 TQString jobUrlStr = jobUrl.url();
1062 TQString jobReferenceUrlStr = jobUrl.internalReferenceURL();
1063
1064 kdDebug(7004) << k_funcinfo << "finished listing " << jobUrl << endl;
1065#ifdef DEBUG_CACHE
1066 printDebug();
1067#endif
1068
1069 TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( jobUrlStr + ":" + jobReferenceUrlStr );
1070 Q_ASSERT( listers );
1071
1072 // move the directory to the held directories, do it before emitting
1073 // the signals to make sure it exists in KDirListerCache in case someone
1074 // calls listDir during the signal emission
1075 Q_ASSERT( !urlsCurrentlyHeld[jobUrlStr + ":" + jobReferenceUrlStr] );
1076 urlsCurrentlyHeld.insert( jobUrlStr + ":" + jobReferenceUrlStr, listers );
1077
1078 KDirLister *kdl;
1079
1080 if ( job->error() )
1081 {
1082 for ( kdl = listers->first(); kdl; kdl = listers->next() )
1083 {
1084 kdl->jobDone( job );
1085 kdl->handleError( job );
1086 emit kdl->canceled( jobUrl );
1087 if ( kdl->numJobs() == 0 )
1088 {
1089 kdl->d->complete = true;
1090 emit kdl->canceled();
1091 }
1092 }
1093 }
1094 else
1095 {
1096 DirItem *dir = itemsInUse[jobUrlStr + ":" + jobReferenceUrlStr];
1097 Q_ASSERT( dir );
1098 dir->complete = true;
1099
1100 for ( kdl = listers->first(); kdl; kdl = listers->next() )
1101 {
1102 kdl->jobDone( job );
1103 kdl->emitCompleted( jobUrl );
1104 if ( kdl->numJobs() == 0 )
1105 {
1106 kdl->d->complete = true;
1107 emit kdl->completed();
1108 }
1109 }
1110 }
1111
1112 // TODO: hmm, if there was an error and job is a parent of one or more
1113 // of the pending urls we should cancel it/them as well
1114 processPendingUpdates();
1115
1116#ifdef DEBUG_CACHE
1117 printDebug();
1118#endif
1119}
1120
1121void KDirListerCache::slotRedirection( TDEIO::Job *j, const KURL& url )
1122{
1123 Q_ASSERT( j );
1124 TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1125
1126 KURL oldUrl = job->url(); // here we really need the old url!
1127 KURL newUrl = url;
1128
1129 // strip trailing slashes
1130 oldUrl.adjustPath(-1);
1131 newUrl.adjustPath(-1);
1132
1133 if ( oldUrl == newUrl )
1134 {
1135 kdDebug(7004) << k_funcinfo << "New redirection url same as old, giving up." << endl;
1136 return;
1137 }
1138
1139 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
1140
1141#ifdef DEBUG_CACHE
1142 printDebug();
1143#endif
1144
1145 // I don't think there can be dirItems that are childs of oldUrl.
1146 // Am I wrong here? And even if so, we don't need to delete them, right?
1147 // DF: redirection happens before listDir emits any item. Makes little sense otherwise.
1148
1149 // oldUrl cannot be in itemsCached because only completed items are moved there
1150 DirItem *dir = itemsInUse.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1151 Q_ASSERT( dir );
1152
1153 TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1154 Q_ASSERT( listers );
1155 Q_ASSERT( !listers->isEmpty() );
1156
1157 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1158 {
1159 // TODO: put in own method?
1160 if ( kdl->d->url.equals( oldUrl, true ) )
1161 {
1162 kdl->d->rootFileItem = 0;
1163 kdl->d->url = newUrl;
1164 }
1165
1166 *kdl->d->lstDirs.find( oldUrl ) = newUrl;
1167
1168 if ( kdl->d->lstDirs.count() == 1 )
1169 {
1170 emit kdl->clear();
1171 emit kdl->redirection( newUrl );
1172 emit kdl->redirection( oldUrl, newUrl );
1173 }
1174 else
1175 {
1176 emit kdl->clear( oldUrl );
1177 emit kdl->redirection( oldUrl, newUrl );
1178 }
1179 }
1180
1181 // when a lister was stopped before the job emits the redirection signal, the old url will
1182 // also be in urlsCurrentlyHeld
1183 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrl.url() + ":" + oldUrl.internalReferenceURL() );
1184 if ( holders )
1185 {
1186 Q_ASSERT( !holders->isEmpty() );
1187
1188 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1189 {
1190 kdl->jobStarted( job );
1191
1192 // do it like when starting a new list-job that will redirect later
1193 emit kdl->started( oldUrl );
1194
1195 // TODO: maybe don't emit started if there's an update running for newUrl already?
1196
1197 if ( kdl->d->url.equals( oldUrl, true ) )
1198 {
1199 kdl->d->rootFileItem = 0;
1200 kdl->d->url = newUrl;
1201 }
1202
1203 *kdl->d->lstDirs.find( oldUrl ) = newUrl;
1204
1205 if ( kdl->d->lstDirs.count() == 1 )
1206 {
1207 emit kdl->clear();
1208 emit kdl->redirection( newUrl );
1209 emit kdl->redirection( oldUrl, newUrl );
1210 }
1211 else
1212 {
1213 emit kdl->clear( oldUrl );
1214 emit kdl->redirection( oldUrl, newUrl );
1215 }
1216 }
1217 }
1218
1219 DirItem *newDir = itemsInUse[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1220 if ( newDir )
1221 {
1222 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " already in use" << endl;
1223
1224 // only in this case there can newUrl already be in urlsCurrentlyListed or urlsCurrentlyHeld
1225 delete dir;
1226
1227 // get the job if one's running for newUrl already (can be a list-job or an update-job), but
1228 // do not return this 'job', which would happen because of the use of redirectionURL()
1229 TDEIO::ListJob *oldJob = jobForUrl( newUrl.url() + ":" + newUrl.internalReferenceURL(), job );
1230
1231 // listers of newUrl with oldJob: forget about the oldJob and use the already running one
1232 // which will be converted to an updateJob
1233 TQPtrList<KDirLister> *curListers = urlsCurrentlyListed[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1234 if ( curListers )
1235 {
1236 kdDebug(7004) << "slotRedirection: and it is currently listed" << endl;
1237
1238 Q_ASSERT( oldJob ); // ?!
1239
1240 for ( KDirLister *kdl = curListers->first(); kdl; kdl = curListers->next() ) // listers of newUrl
1241 {
1242 kdl->jobDone( oldJob );
1243
1244 kdl->jobStarted( job );
1245 kdl->connectJob( job );
1246 }
1247
1248 // append listers of oldUrl with newJob to listers of newUrl with oldJob
1249 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1250 curListers->append( kdl );
1251 }
1252 else {
1253 urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1254 }
1255
1256 if ( oldJob ) // kill the old job, be it a list-job or an update-job
1257 killJob( oldJob );
1258
1259 // holders of newUrl: use the already running job which will be converted to an updateJob
1260 TQPtrList<KDirLister> *curHolders = urlsCurrentlyHeld[newUrl.url() + ":" + newUrl.internalReferenceURL()];
1261 if ( curHolders )
1262 {
1263 kdDebug(7004) << "slotRedirection: and it is currently held." << endl;
1264
1265 for ( KDirLister *kdl = curHolders->first(); kdl; kdl = curHolders->next() ) // holders of newUrl
1266 {
1267 kdl->jobStarted( job );
1268 emit kdl->started( newUrl );
1269 }
1270
1271 // append holders of oldUrl to holders of newUrl
1272 if ( holders )
1273 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1274 curHolders->append( kdl );
1275 }
1276 else if ( holders )
1277 urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1278
1279
1280 // emit old items: listers, holders. NOT: newUrlListers/newUrlHolders, they already have them listed
1281 // TODO: make this a separate method?
1282 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1283 {
1284 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1285 kdl->d->rootFileItem = newDir->rootItem;
1286
1287 kdl->addNewItems( *(newDir->lstItems) );
1288 kdl->emitItems();
1289 }
1290
1291 if ( holders )
1292 {
1293 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1294 {
1295 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1296 kdl->d->rootFileItem = newDir->rootItem;
1297
1298 kdl->addNewItems( *(newDir->lstItems) );
1299 kdl->emitItems();
1300 }
1301 }
1302 }
1303 else if ( (newDir = itemsCached.take( newUrl.url() )) )
1304 {
1305 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " is unused, but already in the cache." << endl;
1306
1307 delete dir;
1308 itemsInUse.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), newDir );
1309 urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1310 if ( holders )
1311 urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1312
1313 // emit old items: listers, holders
1314 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1315 {
1316 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1317 kdl->d->rootFileItem = newDir->rootItem;
1318
1319 kdl->addNewItems( *(newDir->lstItems) );
1320 kdl->emitItems();
1321 }
1322
1323 if ( holders )
1324 {
1325 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1326 {
1327 if ( !kdl->d->rootFileItem && kdl->d->url == newUrl )
1328 kdl->d->rootFileItem = newDir->rootItem;
1329
1330 kdl->addNewItems( *(newDir->lstItems) );
1331 kdl->emitItems();
1332 }
1333 }
1334 }
1335 else
1336 {
1337 kdDebug(7004) << "slotRedirection: " << newUrl.url() << " has not been listed yet." << endl;
1338
1339 delete dir->rootItem;
1340 dir->rootItem = 0;
1341 dir->lstItems->clear();
1342 dir->redirect( newUrl );
1343 itemsInUse.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), dir );
1344 urlsCurrentlyListed.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), listers );
1345
1346 if ( holders )
1347 urlsCurrentlyHeld.insert( newUrl.url() + ":" + newUrl.internalReferenceURL(), holders );
1348 else
1349 {
1350#ifdef DEBUG_CACHE
1351 printDebug();
1352#endif
1353 return; // only in this case the job doesn't need to be converted,
1354 }
1355 }
1356
1357 // make the job an update job
1358 job->disconnect( this );
1359
1360 connect( job, TQ_SIGNAL(entries( TDEIO::Job *, const TDEIO::UDSEntryList & )),
1361 this, TQ_SLOT(slotUpdateEntries( TDEIO::Job *, const TDEIO::UDSEntryList & )) );
1362 connect( job, TQ_SIGNAL(result( TDEIO::Job * )),
1363 this, TQ_SLOT(slotUpdateResult( TDEIO::Job * )) );
1364
1365 // FIXME: autoUpdate-Counts!!
1366
1367#ifdef DEBUG_CACHE
1368 printDebug();
1369#endif
1370}
1371
1372void KDirListerCache::renameDir( const KURL &oldUrl, const KURL &newUrl )
1373{
1374 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << newUrl.prettyURL() << endl;
1375 TQString oldUrlStr = oldUrl.url(-1);
1376 TQString newUrlStr = newUrl.url(-1);
1377
1378 // Not enough. Also need to look at any child dir, even sub-sub-sub-dir.
1379 //DirItem *dir = itemsInUse.take( oldUrlStr );
1380 //emitRedirections( oldUrl, url );
1381
1382 // Look at all dirs being listed/shown
1383 TQDictIterator<DirItem> itu( itemsInUse );
1384 bool goNext;
1385 while ( itu.current() )
1386 {
1387 goNext = true;
1388 DirItem *dir = itu.current();
1389 TQString oldDirURLIndep = itu.currentKey();
1390 oldDirURLIndep.truncate(oldDirURLIndep.length() - (dir->url.internalReferenceURL().length()+strlen(":")));
1391 KURL oldDirUrl ( oldDirURLIndep );
1392 //kdDebug(7004) << "itemInUse: " << oldDirUrl.prettyURL() << endl;
1393 // Check if this dir is oldUrl, or a subfolder of it
1394 if ( oldUrl.isParentOf( oldDirUrl ) )
1395 {
1396 // TODO should use KURL::cleanpath like isParentOf does
1397 TQString relPath = oldDirUrl.path().mid( oldUrl.path().length() );
1398
1399 KURL newDirUrl( newUrl ); // take new base
1400 if ( !relPath.isEmpty() ) {
1401 newDirUrl.addPath( relPath ); // add unchanged relative path
1402 }
1403 //kdDebug(7004) << "KDirListerCache::renameDir new url=" << newDirUrl.prettyURL() << endl;
1404
1405 // Update URL in dir item and in itemsInUse
1406 dir->redirect( newDirUrl );
1407 itemsInUse.remove( itu.currentKey() ); // implies ++itu
1408 itemsInUse.insert( newDirUrl.url(-1), dir );
1409 goNext = false; // because of the implied ++itu above
1410 if ( dir->lstItems )
1411 {
1412 // Rename all items under that dir
1413 KFileItemListIterator kit( *dir->lstItems );
1414 for ( ; kit.current(); ++kit )
1415 {
1416 KURL oldItemUrl = (*kit)->url();
1417 TQString oldItemUrlStr( oldItemUrl.url(-1) );
1418 KURL newItemUrl( oldItemUrl );
1419 newItemUrl.setPath( newDirUrl.path() );
1420 newItemUrl.addPath( oldItemUrl.fileName() );
1421 kdDebug(7004) << "KDirListerCache::renameDir renaming " << oldItemUrlStr << " to " << newItemUrl.url() << endl;
1422 (*kit)->setURL( newItemUrl );
1423 }
1424 }
1425 emitRedirections( oldDirUrl, newDirUrl );
1426 }
1427 if ( goNext )
1428 ++itu;
1429 }
1430
1431 // Is oldUrl a directory in the cache?
1432 // Remove any child of oldUrl from the cache - even if the renamed dir itself isn't in it!
1433 removeDirFromCache( oldUrl );
1434 // TODO rename, instead.
1435}
1436
1437void KDirListerCache::emitRedirections( const KURL &oldUrl, const KURL &url )
1438{
1439 kdDebug(7004) << k_funcinfo << oldUrl.prettyURL() << " -> " << url.prettyURL() << endl;
1440 TQString oldUrlStr = oldUrl.url(-1);
1441 TQString urlStr = url.url(-1);
1442 TQString oldReferenceUrlStr = oldUrl.internalReferenceURL();
1443 TQString urlReferenceStr = url.internalReferenceURL();
1444
1445 TDEIO::ListJob *job = jobForUrl( oldUrlStr + ":" + oldReferenceUrlStr );
1446 if ( job )
1447 killJob( job );
1448
1449 // Check if we were listing this dir. Need to abort and restart with new name in that case.
1450 TQPtrList<KDirLister> *listers = urlsCurrentlyListed.take( oldUrlStr + ":" + oldReferenceUrlStr );
1451 if ( listers )
1452 {
1453 // Tell the world that the job listing the old url is dead.
1454 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1455 {
1456 if ( job )
1457 kdl->jobDone( job );
1458
1459 emit kdl->canceled( oldUrl );
1460 }
1461
1462 urlsCurrentlyListed.insert( urlStr + ":" + urlReferenceStr, listers );
1463 }
1464
1465 // Check if we are currently displaying this directory (odds opposite wrt above)
1466 // Update urlsCurrentlyHeld dict with new URL
1467 TQPtrList<KDirLister> *holders = urlsCurrentlyHeld.take( oldUrlStr + ":" + oldReferenceUrlStr );
1468 if ( holders )
1469 {
1470 if ( job )
1471 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1472 kdl->jobDone( job );
1473
1474 urlsCurrentlyHeld.insert( urlStr + ":" + urlReferenceStr, holders );
1475 }
1476
1477 if ( listers )
1478 {
1479 updateDirectory( url );
1480
1481 // Tell the world about the new url
1482 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() )
1483 emit kdl->started( url );
1484 }
1485
1486 if ( holders )
1487 {
1488 // And notify the dirlisters of the redirection
1489 for ( KDirLister *kdl = holders->first(); kdl; kdl = holders->next() )
1490 {
1491 *kdl->d->lstDirs.find( oldUrl ) = url;
1492
1493 if ( kdl->d->lstDirs.count() == 1 )
1494 emit kdl->redirection( url );
1495
1496 emit kdl->redirection( oldUrl, url );
1497 }
1498 }
1499}
1500
1501void KDirListerCache::removeDirFromCache( const KURL& dir )
1502{
1503 kdDebug(7004) << "KDirListerCache::removeDirFromCache " << dir.prettyURL() << endl;
1504 TQCacheIterator<DirItem> itc( itemsCached );
1505 while ( itc.current() )
1506 {
1507 if ( dir.isParentOf( KURL( itc.currentKey() ) ) )
1508 itemsCached.remove( itc.currentKey() );
1509 else
1510 ++itc;
1511 }
1512}
1513
1514void KDirListerCache::slotUpdateEntries( TDEIO::Job* job, const TDEIO::UDSEntryList& list )
1515{
1516 jobs[static_cast<TDEIO::ListJob*>(job)] += list;
1517}
1518
1519void KDirListerCache::slotUpdateResult( TDEIO::Job * j )
1520{
1521 Q_ASSERT( j );
1522 TDEIO::ListJob *job = static_cast<TDEIO::ListJob *>( j );
1523
1524 KURL jobUrl = joburl( job );
1525 jobUrl.adjustPath(-1); // need remove trailing slashes again, in case of redirections
1526 TQString jobUrlStr = jobUrl.url();
1527 TQString jobReferenceUrlStr = jobUrl.internalReferenceURL();
1528
1529 kdDebug(7004) << k_funcinfo << "finished update " << jobUrl << endl;
1530
1531 KDirLister *kdl;
1532
1533 TQPtrList<KDirLister> *listers = urlsCurrentlyHeld[jobUrlStr + ":" + jobReferenceUrlStr];
1534 TQPtrList<KDirLister> *tmpLst = urlsCurrentlyListed.take( jobUrlStr + ":" + jobReferenceUrlStr );
1535
1536 if ( tmpLst )
1537 {
1538 if ( listers )
1539 for ( kdl = tmpLst->first(); kdl; kdl = tmpLst->next() )
1540 {
1541 Q_ASSERT( listers->containsRef( kdl ) == 0 );
1542 listers->append( kdl );
1543 }
1544 else
1545 {
1546 listers = tmpLst;
1547 urlsCurrentlyHeld.insert( jobUrlStr + ":" + jobReferenceUrlStr, listers );
1548 }
1549 }
1550
1551 // once we are updating dirs that are only in the cache this will fail!
1552 Q_ASSERT( listers );
1553
1554 if ( job->error() )
1555 {
1556 for ( kdl = listers->first(); kdl; kdl = listers->next() )
1557 {
1558 kdl->jobDone( job );
1559
1560 //don't bother the user
1561 //kdl->handleError( job );
1562
1563 emit kdl->canceled( jobUrl );
1564 if ( kdl->numJobs() == 0 )
1565 {
1566 kdl->d->complete = true;
1567 emit kdl->canceled();
1568 }
1569 }
1570
1571 jobs.remove( job );
1572
1573 // TODO: if job is a parent of one or more
1574 // of the pending urls we should cancel them
1575 processPendingUpdates();
1576 return;
1577 }
1578
1579 DirItem *dir = itemsInUse[jobUrlStr + ":" + jobReferenceUrlStr];
1580 dir->complete = true;
1581
1582
1583 // check if anyone wants the mimetypes immediately
1584 bool delayedMimeTypes = true;
1585 for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1586 delayedMimeTypes = delayedMimeTypes && kdl->d->delayedMimeTypes;
1587 }
1588
1589 // should be enough to get reasonable speed in most cases
1590 TQDict<KFileItem> fileItems( 9973 );
1591
1592 KFileItemListIterator kit ( *(dir->lstItems) );
1593
1594 // Unmark all items in url
1595 for ( ; kit.current(); ++kit )
1596 {
1597 (*kit)->unmark();
1598 if (!((*kit)->listerURL().isEmpty())) {
1599 fileItems.insert( (*kit)->listerURL().url(), *kit );
1600 }
1601 else {
1602 fileItems.insert( (*kit)->url().url(), *kit );
1603 }
1604 }
1605
1606 static const TQString& dot = TDEGlobal::staticQString(".");
1607 static const TQString& dotdot = TDEGlobal::staticQString("..");
1608
1609 KFileItem *item = 0, *tmp;
1610
1611 TQValueList<TDEIO::UDSEntry> buf = jobs[job];
1612 TQValueListIterator<TDEIO::UDSEntry> it = buf.begin();
1613 for ( ; it != buf.end(); ++it )
1614 {
1615 // Form the complete url
1616 if ( !item ) {
1617 item = new KFileItem( *it, jobUrl, delayedMimeTypes, true );
1618 }
1619 else {
1620 item->setUDSEntry( *it, jobUrl, delayedMimeTypes, true );
1621 }
1622
1623 // Find out about the name
1624 TQString name = item->name();
1625 Q_ASSERT( !name.isEmpty() );
1626
1627 // we duplicate the check for dotdot here, to avoid iterating over
1628 // all items again and checking in matchesFilter() that way.
1629 if ( name.isEmpty() || name == dotdot ) {
1630 continue;
1631 }
1632
1633 if ( name == dot )
1634 {
1635 // if the update was started before finishing the original listing
1636 // there is no root item yet
1637 if ( !dir->rootItem )
1638 {
1639 dir->rootItem = item;
1640 item = 0;
1641
1642 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1643 if ( !kdl->d->rootFileItem && kdl->d->url == jobUrl ) {
1644 kdl->d->rootFileItem = dir->rootItem;
1645 }
1646 }
1647 }
1648
1649 continue;
1650 }
1651
1652 // Find this item
1653 if ( (tmp = fileItems[item->url().url()]) )
1654 {
1655 tmp->mark();
1656
1657 // check if something changed for this file
1658 if ( !tmp->cmp( *item ) )
1659 {
1660 for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1661 kdl->aboutToRefreshItem( tmp );
1662 }
1663
1664 //kdDebug(7004) << "slotUpdateResult: file changed: " << tmp->name() << endl;
1665 tmp->assign( *item );
1666
1667 for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1668 kdl->addRefreshItem( tmp );
1669 }
1670 }
1671 }
1672 else // this is a new file
1673 {
1674 //kdDebug(7004) << "slotUpdateResult: new file: " << name << endl;
1675
1676 item->mark();
1677 dir->lstItems->append( item );
1678
1679 for ( kdl = listers->first(); kdl; kdl = listers->next() ) {
1680 kdl->addNewItem( item );
1681 }
1682
1683 // item used, we need a new one for the next iteration
1684 item = 0;
1685 }
1686 }
1687
1688 if ( item ) {
1689 delete item;
1690 }
1691
1692 jobs.remove( job );
1693
1694 deleteUnmarkedItems( listers, dir->lstItems );
1695
1696 for ( kdl = listers->first(); kdl; kdl = listers->next() )
1697 {
1698 kdl->emitItems();
1699
1700 kdl->jobDone( job );
1701
1702 kdl->emitCompleted( jobUrl );
1703 if ( kdl->numJobs() == 0 )
1704 {
1705 kdl->d->complete = true;
1706 emit kdl->completed();
1707 }
1708 }
1709
1710 // TODO: hmm, if there was an error and job is a parent of one or more
1711 // of the pending urls we should cancel it/them as well
1712 processPendingUpdates();
1713}
1714
1715// private
1716
1717TDEIO::ListJob *KDirListerCache::jobForUrl( const TQString& url, TDEIO::ListJob *not_job )
1718{
1719 TDEIO::ListJob *job;
1720 TQMap< TDEIO::ListJob *, TQValueList<TDEIO::UDSEntry> >::Iterator it = jobs.begin();
1721 while ( it != jobs.end() )
1722 {
1723 job = it.key();
1724 KURL itjoburl = joburl( job );
1725 if ( ((itjoburl.url(-1) + ":" + itjoburl.internalReferenceURL()) == url) && (job != not_job) ) {
1726 return job;
1727 }
1728 ++it;
1729 }
1730 return 0;
1731}
1732
1733const KURL& KDirListerCache::joburl( TDEIO::ListJob *job )
1734{
1735 if ( job->redirectionURL().isValid() ) {
1736 return job->redirectionURL();
1737 }
1738 else {
1739 return job->url();
1740 }
1741}
1742
1743void KDirListerCache::killJob( TDEIO::ListJob *job )
1744{
1745 jobs.remove( job );
1746 job->disconnect( this );
1747 job->kill();
1748}
1749
1750void KDirListerCache::deleteUnmarkedItems( TQPtrList<KDirLister> *listers, KFileItemList *lstItems )
1751{
1752 // Find all unmarked items and delete them
1753 KFileItem* item;
1754 lstItems->first();
1755 while ( (item = lstItems->current()) )
1756 if ( !item->isMarked() )
1757 {
1758 //kdDebug() << k_funcinfo << item->name() << endl;
1759 for ( KDirLister *kdl = listers->first(); kdl; kdl = listers->next() ) {
1760 kdl->emitDeleteItem( item );
1761 }
1762
1763 if ( item->isDir() ) {
1764 deleteDir( item->url() );
1765 }
1766
1767 // finally actually delete the item
1768 lstItems->take();
1769 delete item;
1770 }
1771 else
1772 lstItems->next();
1773}
1774
1775void KDirListerCache::deleteDir( const KURL& dirUrl )
1776{
1777 //kdDebug() << k_funcinfo << dirUrl.prettyURL() << endl;
1778 // unregister and remove the childs of the deleted item.
1779 // Idea: tell all the KDirListers that they should forget the dir
1780 // and then remove it from the cache.
1781
1782 TQDictIterator<DirItem> itu( itemsInUse );
1783 while ( itu.current() )
1784 {
1785 TQString deletedUrlIndep = itu.currentKey();
1786 deletedUrlIndep.truncate(deletedUrlIndep.length() - ((*itu)->url.internalReferenceURL().length()+strlen(":")));
1787 KURL deletedUrl( deletedUrlIndep );
1788 if ( dirUrl.isParentOf( deletedUrl ) )
1789 {
1790 // stop all jobs for deletedUrl
1791
1792 TQPtrList<KDirLister> *kdls = urlsCurrentlyListed[deletedUrl.url() + ":" + deletedUrl.internalReferenceURL()];
1793 if ( kdls ) // yeah, I lack good names
1794 {
1795 // we need a copy because stop modifies the list
1796 kdls = new TQPtrList<KDirLister>( *kdls );
1797 for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
1798 stop( kdl, deletedUrl );
1799
1800 delete kdls;
1801 }
1802
1803 // tell listers holding deletedUrl to forget about it
1804 // this will stop running updates for deletedUrl as well
1805
1806 kdls = urlsCurrentlyHeld[deletedUrl.url() + ":" + deletedUrl.internalReferenceURL()];
1807 if ( kdls )
1808 {
1809 // we need a copy because forgetDirs modifies the list
1810 kdls = new TQPtrList<KDirLister>( *kdls );
1811
1812 for ( KDirLister *kdl = kdls->first(); kdl; kdl = kdls->next() )
1813 {
1814 // lister's root is the deleted item
1815 if ( kdl->d->url == deletedUrl )
1816 {
1817 // tell the view first. It might need the subdirs' items (which forgetDirs will delete)
1818 if ( kdl->d->rootFileItem )
1819 emit kdl->deleteItem( kdl->d->rootFileItem );
1820 forgetDirs( kdl );
1821 kdl->d->rootFileItem = 0;
1822 }
1823 else
1824 {
1825 bool treeview = kdl->d->lstDirs.count() > 1;
1826 if ( !treeview )
1827 emit kdl->clear();
1828
1829 forgetDirs( kdl, deletedUrl, treeview );
1830 }
1831 }
1832
1833 delete kdls;
1834 }
1835
1836 // delete the entry for deletedUrl - should not be needed, it's in
1837 // items cached now
1838
1839 DirItem *dir = itemsInUse.take( deletedUrl.url() + ":" + deletedUrl.internalReferenceURL() );
1840 Q_ASSERT( !dir );
1841 if ( !dir ) // take didn't find it - move on
1842 ++itu;
1843 }
1844 else
1845 ++itu;
1846 }
1847
1848 // remove the children from the cache
1849 removeDirFromCache( dirUrl );
1850}
1851
1852void KDirListerCache::processPendingUpdates()
1853{
1854 // TODO
1855}
1856
1857#ifndef NDEBUG
1858void KDirListerCache::printDebug()
1859{
1860 kdDebug(7004) << "Items in use: " << endl;
1861 TQDictIterator<DirItem> itu( itemsInUse );
1862 for ( ; itu.current() ; ++itu ) {
1863 kdDebug(7004) << " " << itu.currentKey() << " URL: " << itu.current()->url
1864 << " rootItem: " << ( itu.current()->rootItem ? itu.current()->rootItem->url() : KURL() )
1865 << " autoUpdates refcount: " << itu.current()->autoUpdates
1866 << " complete: " << itu.current()->complete
1867 << ( itu.current()->lstItems ? TQString(" with %1 items.").arg(itu.current()->lstItems->count()) : TQString(" lstItems=NULL") ) << endl;
1868 }
1869
1870 kdDebug(7004) << "urlsCurrentlyHeld: " << endl;
1871 TQDictIterator< TQPtrList<KDirLister> > it( urlsCurrentlyHeld );
1872 for ( ; it.current() ; ++it )
1873 {
1874 TQString list;
1875 for ( TQPtrListIterator<KDirLister> listit( *it.current() ); listit.current(); ++listit )
1876 list += " 0x" + TQString::number( (long)listit.current(), 16 );
1877 kdDebug(7004) << " " << it.currentKey() << " " << it.current()->count() << " listers: " << list << endl;
1878 }
1879
1880 kdDebug(7004) << "urlsCurrentlyListed: " << endl;
1881 TQDictIterator< TQPtrList<KDirLister> > it2( urlsCurrentlyListed );
1882 for ( ; it2.current() ; ++it2 )
1883 {
1884 TQString list;
1885 for ( TQPtrListIterator<KDirLister> listit( *it2.current() ); listit.current(); ++listit )
1886 list += " 0x" + TQString::number( (long)listit.current(), 16 );
1887 kdDebug(7004) << " " << it2.currentKey() << " " << it2.current()->count() << " listers: " << list << endl;
1888 }
1889
1890 TQMap< TDEIO::ListJob *, TQValueList<TDEIO::UDSEntry> >::Iterator jit = jobs.begin();
1891 kdDebug(7004) << "Jobs: " << endl;
1892 for ( ; jit != jobs.end() ; ++jit )
1893 kdDebug(7004) << " " << jit.key() << " listing " << joburl( jit.key() ).prettyURL() << ": " << (*jit).count() << " entries." << endl;
1894
1895 kdDebug(7004) << "Items in cache: " << endl;
1896 TQCacheIterator<DirItem> itc( itemsCached );
1897 for ( ; itc.current() ; ++itc )
1898 kdDebug(7004) << " " << itc.currentKey() << " rootItem: "
1899 << ( itc.current()->rootItem ? itc.current()->rootItem->url().prettyURL() : TQString("NULL") )
1900 << ( itc.current()->lstItems ? TQString(" with %1 items.").arg(itc.current()->lstItems->count()) : TQString(" lstItems=NULL") ) << endl;
1901}
1902#endif
1903
1904/*********************** -- The new KDirLister -- ************************/
1905
1906
1907KDirLister::KDirLister( bool _delayedMimeTypes )
1908{
1909 kdDebug(7003) << "+KDirLister" << endl;
1910
1911 d = new KDirListerPrivate;
1912
1913 d->complete = true;
1914 d->delayedMimeTypes = _delayedMimeTypes;
1915
1916 setAutoUpdate( true );
1917 setDirOnlyMode( false );
1918 setShowingDotFiles( false );
1919
1920 setAutoErrorHandlingEnabled( true, 0 );
1921}
1922
1923KDirLister::~KDirLister()
1924{
1925 kdDebug(7003) << "-KDirLister" << endl;
1926
1927 if ( KDirListerCache::exists() )
1928 {
1929 // Stop all running jobs
1930 stop();
1931 s_pCache->forgetDirs( this );
1932 }
1933
1934 delete d;
1935}
1936
1937bool KDirLister::openURL( const KURL& _url, bool _keep, bool _reload )
1938{
1939 kdDebug(7003) << k_funcinfo << _url.prettyURL()
1940 << " keep=" << _keep << " reload=" << _reload << endl;
1941
1942 // emit the current changes made to avoid an inconsistent treeview
1943 if ( d->changes != NONE && _keep ) {
1944 emitChanges();
1945 }
1946
1947 d->changes = NONE;
1948
1949 if ( !validURL( _url ) ) {
1950 return false;
1951 }
1952
1953 // Some ioslaves like media:/ or home:/ can provide a local url istead of a remote one
1954 // If a local path is available, monitor that instead of the given remote URL...
1955 if (!_url.isLocalFile()) {
1956 TDEIO::LocalURLJob* localURLJob = TDEIO::localURL(_url);
1957 if (localURLJob) {
1958 d->openURLContext[localURLJob] = KDirListerPrivate::OpenURLContext{_url, _keep, _reload};
1959 connect(localURLJob, TQ_SIGNAL(localURL(TDEIO::LocalURLJob*, const KURL&, bool)),
1960 this, TQ_SLOT(slotOpenURLGotLocalURL(TDEIO::LocalURLJob*, const KURL&, bool)));
1961 connect(localURLJob, TQ_SIGNAL(destroyed()), this, TQ_SLOT(slotLocalURLKIODestroyed()));
1962 d->complete = false;
1963 return true;
1964 }
1965 }
1966
1967 return s_pCache->listDir( this, _url, _keep, _reload );
1968}
1969
1970void KDirLister::slotOpenURLGotLocalURL(TDEIO::LocalURLJob *job, const KURL& url, bool isLocal) {
1971 auto jobIt = d->openURLContext.find(job);
1972
1973 Q_ASSERT( jobIt != d->openURLContext.end() );
1974
1975 auto ctx = jobIt.data();
1976 KURL realURL = ctx.url;
1977 if (isLocal) {
1978 realURL = url;
1979 realURL.setInternalReferenceURL(ctx.url.url());
1980 d->m_referenceURLMap[ctx.url.url()] = url.path();
1981 }
1982 d->openURLContext.remove(jobIt);
1983 d->complete = d->jobData.isEmpty() && d->openURLContext.isEmpty();
1984 s_pCache->listDir( this, realURL, ctx.keep, ctx.reload );
1985}
1986
1987void KDirLister::slotLocalURLKIODestroyed() {
1988 TDEIO::Job* terminatedJob = const_cast<TDEIO::Job*>(static_cast<const TDEIO::Job*>(sender()));
1989 auto jobIt = d->openURLContext.find(terminatedJob);
1990
1991 if (jobIt != d->openURLContext.end()) {
1992 auto ctx = jobIt.data();
1993 d->openURLContext.remove(jobIt);
1994 d->complete = d->jobData.isEmpty() && d->openURLContext.isEmpty();
1995 s_pCache->listDir( this, ctx.url, ctx.keep, ctx.reload );
1996 }
1997}
1998
1999void KDirLister::stop()
2000{
2001 kdDebug(7003) << k_funcinfo << endl;
2002 s_pCache->stop( this );
2003 for( auto it = d->openURLContext.begin(); it != d->openURLContext.end(); ++it ) {
2004 it.key()->disconnect( this );
2005 it.key()->kill();
2006 }
2007 d->openURLContext.clear();
2008 d->m_referenceURLMap.clear();
2009}
2010
2011void KDirLister::stop( const KURL& _url )
2012{
2013 kdDebug(7003) << k_funcinfo << _url.prettyURL() << endl;
2014 s_pCache->stop( this, _url );
2015 TQPtrList<TDEIO::Job> toRemove;
2016 for( auto it = d->openURLContext.begin(); it != d->openURLContext.end(); ++it ) {
2017 if( it.data().url ==_url ) {
2018 it.key()->disconnect( this );
2019 it.key()->kill();
2020 toRemove.append(it.key());
2021 }
2022 }
2023 for(const auto &job: toRemove) {
2024 d->openURLContext.remove(job);
2025 }
2026 d->m_referenceURLMap.remove(_url.url());
2027}
2028
2029bool KDirLister::autoUpdate() const
2030{
2031 return d->autoUpdate;
2032}
2033
2034void KDirLister::setAutoUpdate( bool _enable )
2035{
2036 if ( d->autoUpdate == _enable )
2037 return;
2038
2039 d->autoUpdate = _enable;
2040 s_pCache->setAutoUpdate( this, _enable );
2041}
2042
2043bool KDirLister::showingDotFiles() const
2044{
2045 return d->isShowingDotFiles;
2046}
2047
2048void KDirLister::setShowingDotFiles( bool _showDotFiles )
2049{
2050 if ( d->isShowingDotFiles == _showDotFiles )
2051 return;
2052
2053 d->isShowingDotFiles = _showDotFiles;
2054 d->changes ^= DOT_FILES;
2055}
2056
2057bool KDirLister::dirOnlyMode() const
2058{
2059 return d->dirOnlyMode;
2060}
2061
2062void KDirLister::setDirOnlyMode( bool _dirsOnly )
2063{
2064 if ( d->dirOnlyMode == _dirsOnly )
2065 return;
2066
2067 d->dirOnlyMode = _dirsOnly;
2068 d->changes ^= DIR_ONLY_MODE;
2069}
2070
2071bool KDirLister::autoErrorHandlingEnabled() const
2072{
2073 return d->autoErrorHandling;
2074}
2075
2076void KDirLister::setAutoErrorHandlingEnabled( bool enable, TQWidget* parent )
2077{
2078 d->autoErrorHandling = enable;
2079 d->errorParent = parent;
2080}
2081
2082const KURL& KDirLister::url() const
2083{
2084 return d->url;
2085}
2086
2087const KURL::List& KDirLister::directories() const
2088{
2089 return d->lstDirs;
2090}
2091
2092void KDirLister::emitChanges()
2093{
2094 if ( d->changes == NONE )
2095 return;
2096
2097 static const TQString& dot = TDEGlobal::staticQString(".");
2098 static const TQString& dotdot = TDEGlobal::staticQString("..");
2099
2100 for ( KURL::List::Iterator it = d->lstDirs.begin();
2101 it != d->lstDirs.end(); ++it )
2102 {
2103 KFileItemListIterator kit( *s_pCache->itemsForDir( *it ) );
2104 for ( ; kit.current(); ++kit )
2105 {
2106 if ( (*kit)->text() == dot || (*kit)->text() == dotdot )
2107 continue;
2108
2109 bool oldMime = true, newMime = true;
2110
2111 if ( d->changes & MIME_FILTER )
2112 {
2113 oldMime = doMimeFilter( (*kit)->mimetype(), d->oldMimeFilter )
2114 && doMimeExcludeFilter( (*kit)->mimetype(), d->oldMimeExcludeFilter );
2115 newMime = doMimeFilter( (*kit)->mimetype(), d->mimeFilter )
2116 && doMimeExcludeFilter( (*kit)->mimetype(), d->mimeExcludeFilter );
2117
2118 if ( oldMime && !newMime )
2119 {
2120 emit deleteItem( *kit );
2121 continue;
2122 }
2123 }
2124
2125 if ( d->changes & DIR_ONLY_MODE )
2126 {
2127 // the lister switched to dirOnlyMode
2128 if ( d->dirOnlyMode )
2129 {
2130 if ( !(*kit)->isDir() )
2131 emit deleteItem( *kit );
2132 }
2133 else if ( !(*kit)->isDir() ) {
2134 addNewItem( *kit );
2135 }
2136
2137 continue;
2138 }
2139
2140 if ( (*kit)->isHidden() )
2141 {
2142 if ( d->changes & DOT_FILES )
2143 {
2144 // the lister switched to dot files mode
2145 if ( d->isShowingDotFiles ) {
2146 addNewItem( *kit );
2147 }
2148 else {
2149 emit deleteItem( *kit );
2150 }
2151
2152 continue;
2153 }
2154 }
2155 else if ( d->changes & NAME_FILTER )
2156 {
2157 bool oldName = (*kit)->isDir() ||
2158 d->oldFilters.isEmpty() ||
2159 doNameFilter( (*kit)->text(), d->oldFilters );
2160
2161 bool newName = (*kit)->isDir() ||
2162 d->lstFilters.isEmpty() ||
2163 doNameFilter( (*kit)->text(), d->lstFilters );
2164
2165 if ( oldName && !newName )
2166 {
2167 emit deleteItem( *kit );
2168 continue;
2169 }
2170 else if ( !oldName && newName ) {
2171 addNewItem( *kit );
2172 }
2173 }
2174
2175 if ( (d->changes & MIME_FILTER) && !oldMime && newMime ) {
2176 addNewItem( *kit );
2177 }
2178 }
2179
2180 emitItems();
2181 }
2182
2183 d->changes = NONE;
2184}
2185
2186void KDirLister::updateDirectory( const KURL& _u )
2187{
2188 s_pCache->updateDirectory( _u );
2189}
2190
2191bool KDirLister::isFinished() const
2192{
2193 return d->complete;
2194}
2195
2196KFileItem *KDirLister::rootItem() const
2197{
2198 return d->rootFileItem;
2199}
2200
2201KFileItem *KDirLister::findByURL( const KURL& _url ) const
2202{
2203 return s_pCache->findByURL( this, _url );
2204}
2205
2206KFileItem *KDirLister::findByName( const TQString& _name ) const
2207{
2208 return s_pCache->findByName( this, _name );
2209}
2210
2211#ifndef KDE_NO_COMPAT
2212KFileItem *KDirLister::find( const KURL& _url ) const
2213{
2214 return findByURL( _url );
2215}
2216#endif
2217
2218
2219// ================ public filter methods ================ //
2220
2221void KDirLister::setNameFilter( const TQString& nameFilter )
2222{
2223 if ( !(d->changes & NAME_FILTER) )
2224 {
2225 d->oldFilters = d->lstFilters;
2226 d->lstFilters.setAutoDelete( false );
2227 }
2228
2229 d->lstFilters.clear();
2230 d->lstFilters.setAutoDelete( true );
2231
2232 d->nameFilter = nameFilter;
2233
2234 // Split on white space
2235 TQStringList list = TQStringList::split( ' ', nameFilter );
2236 for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
2237 d->lstFilters.append( new TQRegExp(*it, false, true ) );
2238
2239 d->changes |= NAME_FILTER;
2240}
2241
2242const TQString& KDirLister::nameFilter() const
2243{
2244 return d->nameFilter;
2245}
2246
2247void KDirLister::setMimeFilter( const TQStringList& mimeFilter )
2248{
2249 if ( !(d->changes & MIME_FILTER) )
2250 d->oldMimeFilter = d->mimeFilter;
2251
2252 if ( mimeFilter.find("all/allfiles") != mimeFilter.end() ||
2253 mimeFilter.find("all/all") != mimeFilter.end() )
2254 d->mimeFilter.clear();
2255 else
2256 d->mimeFilter = mimeFilter;
2257
2258 d->changes |= MIME_FILTER;
2259}
2260
2261void KDirLister::setMimeExcludeFilter( const TQStringList& mimeExcludeFilter )
2262{
2263 if ( !(d->changes & MIME_FILTER) )
2264 d->oldMimeExcludeFilter = d->mimeExcludeFilter;
2265
2266 d->mimeExcludeFilter = mimeExcludeFilter;
2267 d->changes |= MIME_FILTER;
2268}
2269
2270
2271void KDirLister::clearMimeFilter()
2272{
2273 if ( !(d->changes & MIME_FILTER) )
2274 {
2275 d->oldMimeFilter = d->mimeFilter;
2276 d->oldMimeExcludeFilter = d->mimeExcludeFilter;
2277 }
2278 d->mimeFilter.clear();
2279 d->mimeExcludeFilter.clear();
2280 d->changes |= MIME_FILTER;
2281}
2282
2283const TQStringList& KDirLister::mimeFilters() const
2284{
2285 return d->mimeFilter;
2286}
2287
2288bool KDirLister::matchesFilter( const TQString& name ) const
2289{
2290 return doNameFilter( name, d->lstFilters );
2291}
2292
2293bool KDirLister::matchesMimeFilter( const TQString& mime ) const
2294{
2295 return doMimeFilter( mime, d->mimeFilter ) && doMimeExcludeFilter(mime,d->mimeExcludeFilter);
2296}
2297
2298// ================ protected methods ================ //
2299
2300bool KDirLister::matchesFilter( const KFileItem *item ) const
2301{
2302 Q_ASSERT( item );
2303 static const TQString& dotdot = TDEGlobal::staticQString("..");
2304
2305 if ( item->text() == dotdot )
2306 return false;
2307
2308 if ( !d->isShowingDotFiles && item->isHidden() )
2309 return false;
2310
2311 if ( item->isDir() || d->lstFilters.isEmpty() )
2312 return true;
2313
2314 return matchesFilter( item->text() );
2315}
2316
2317bool KDirLister::matchesMimeFilter( const KFileItem *item ) const
2318{
2319 Q_ASSERT( item );
2320 // Don't lose time determining the mimetype if there is no filter
2321 if ( d->mimeFilter.isEmpty() && d->mimeExcludeFilter.isEmpty() )
2322 return true;
2323 return matchesMimeFilter( item->mimetype() );
2324}
2325
2326bool KDirLister::doNameFilter( const TQString& name, const TQPtrList<TQRegExp>& filters ) const
2327{
2328 for ( TQPtrListIterator<TQRegExp> it( filters ); it.current(); ++it )
2329 if ( it.current()->exactMatch( name ) )
2330 return true;
2331
2332 return false;
2333}
2334
2335bool KDirLister::doMimeFilter( const TQString& mime, const TQStringList& filters ) const
2336{
2337 if ( filters.isEmpty() )
2338 return true;
2339
2340 KMimeType::Ptr mimeptr = KMimeType::mimeType(mime);
2341 //kdDebug(7004) << "doMimeFilter: investigating: "<<mimeptr->name()<<endl;
2342 TQStringList::ConstIterator it = filters.begin();
2343 for ( ; it != filters.end(); ++it )
2344 if ( mimeptr->is(*it) )
2345 return true;
2346 //else kdDebug(7004) << "doMimeFilter: compared without result to "<<*it<<endl;
2347
2348
2349 return false;
2350}
2351
2352bool KDirLister::doMimeExcludeFilter( const TQString& mime, const TQStringList& filters ) const
2353{
2354 if ( filters.isEmpty() )
2355 return true;
2356
2357 TQStringList::ConstIterator it = filters.begin();
2358 for ( ; it != filters.end(); ++it )
2359 if ( (*it) == mime )
2360 return false;
2361
2362 return true;
2363}
2364
2365
2366bool KDirLister::validURL( const KURL& _url ) const
2367{
2368 return s_pCache->validURL( this, _url );
2369}
2370
2371void KDirLister::handleError( TDEIO::Job *job )
2372{
2373 if ( d->autoErrorHandling ) {
2374 job->showErrorDialog( d->errorParent );
2375 }
2376}
2377
2378
2379// ================= private methods ================= //
2380
2381void KDirLister::addNewItem( const KFileItem *item )
2382{
2383 TQString refURL = item->url().internalReferenceURL();
2384 if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2385 item->url().path().startsWith(d->m_referenceURLMap[refURL]))
2386 {
2387 // Likely a media:/ tdeioslave URL or similar
2388 // Rewrite the URL to ensure that the user remains within the media:/ tree!
2389 if (!refURL.endsWith("/"))
2390 {
2391 refURL.append("/");
2392 }
2393 KURL newItemURL(refURL);
2394 newItemURL.addPath(item->url().fileName());
2395 const_cast<KFileItem*>(item)->setListerURL(newItemURL);
2396 const_cast<KFileItem*>(item)->setURL(newItemURL);
2397 }
2398
2399 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) ) {
2400 return; // No reason to continue... bailing out here prevents a mimetype scan.
2401 }
2402
2403 if ( matchesMimeFilter( item ) )
2404 {
2405 if ( !d->lstNewItems ) {
2406 d->lstNewItems = new KFileItemList;
2407 }
2408
2409 d->lstNewItems->append( item ); // items not filtered
2410 }
2411 else
2412 {
2413 if ( !d->lstMimeFilteredItems ) {
2414 d->lstMimeFilteredItems = new KFileItemList;
2415 }
2416
2417 d->lstMimeFilteredItems->append( item ); // only filtered by mime
2418 }
2419}
2420
2421void KDirLister::addNewItems( const KFileItemList& items )
2422{
2423 // TODO: make this faster - test if we have a filter at all first
2424 // DF: was this profiled? The matchesFoo() functions should be fast, w/o filters...
2425 // Of course if there is no filter and we can do a range-insertion instead of a loop, that might be good.
2426 for ( KFileItemListIterator kit( items ); kit.current(); ++kit ) {
2427 addNewItem( *kit );
2428 }
2429}
2430
2431void KDirLister::aboutToRefreshItem( const KFileItem *item )
2432{
2433 // The code here follows the logic in addNewItem
2434 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) )
2435 d->refreshItemWasFiltered = true;
2436 else if ( !matchesMimeFilter( item ) )
2437 d->refreshItemWasFiltered = true;
2438 else
2439 d->refreshItemWasFiltered = false;
2440}
2441
2442void KDirLister::addRefreshItem( const KFileItem *item )
2443{
2444 bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
2445
2446 TQString refURL = item->url().internalReferenceURL();
2447 if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2448 item->url().path().startsWith(d->m_referenceURLMap[refURL]))
2449 {
2450 // Likely a media:/ tdeioslave URL or similar
2451 // Rewrite the URL to ensure that the user remains within the media:/ tree!
2452 if (!refURL.endsWith("/"))
2453 {
2454 refURL.append("/");
2455 }
2456 KURL newItemURL(refURL);
2457 newItemURL.addPath(item->url().fileName());
2458 const_cast<KFileItem*>(item)->setListerURL(newItemURL);
2459 const_cast<KFileItem*>(item)->setURL(newItemURL);
2460 }
2461
2462 if ( !isExcluded && matchesMimeFilter( item ) )
2463 {
2464 if ( d->refreshItemWasFiltered )
2465 {
2466 if ( !d->lstNewItems ) {
2467 d->lstNewItems = new KFileItemList;
2468 }
2469
2470 d->lstNewItems->append( item );
2471 }
2472 else
2473 {
2474 if ( !d->lstRefreshItems ) {
2475 d->lstRefreshItems = new KFileItemList;
2476 }
2477
2478 d->lstRefreshItems->append( item );
2479 }
2480 }
2481 else if ( !d->refreshItemWasFiltered )
2482 {
2483 if ( !d->lstRemoveItems ) {
2484 d->lstRemoveItems = new KFileItemList;
2485 }
2486
2487 // notify the user that the mimetype of a file changed that doesn't match
2488 // a filter or does match an exclude filter
2489 d->lstRemoveItems->append( item );
2490 }
2491}
2492
2493void KDirLister::emitItems()
2494{
2495 KFileItemList *tmpNew = d->lstNewItems;
2496 d->lstNewItems = 0;
2497
2498 KFileItemList *tmpMime = d->lstMimeFilteredItems;
2499 d->lstMimeFilteredItems = 0;
2500
2501 KFileItemList *tmpRefresh = d->lstRefreshItems;
2502 d->lstRefreshItems = 0;
2503
2504 KFileItemList *tmpRemove = d->lstRemoveItems;
2505 d->lstRemoveItems = 0;
2506
2507 if ( tmpNew )
2508 {
2509 // For historical reasons, items with different protocols and/or prefixes must be emitted separately
2510 TQString protocol;
2511 TQString prefix;
2512 TQString prevProtocol;
2513 TQString prevPrefix;
2514 KFileItemList emitList;
2515 for ( KFileItemListIterator kit( *tmpNew ); kit.current(); ++kit )
2516 {
2517 KFileItem *item = *kit;
2518 protocol = item->url().protocol();
2519 prefix = TQStringList::split("/", item->url().path())[0];
2520 if ((protocol != prevProtocol) || (prefix != prevPrefix)) {
2521 if (emitList.count() > 0) {
2522 emit newItems( emitList );
2523 emitList.clear();
2524 }
2525 }
2526 emitList.append(item);
2527 prevProtocol = protocol;
2528 prevPrefix = prefix;
2529 }
2530
2531 if (emitList.count() > 0) {
2532 emit newItems( emitList );
2533 }
2534 delete tmpNew;
2535 }
2536
2537 if ( tmpMime )
2538 {
2539 emit itemsFilteredByMime( *tmpMime );
2540 delete tmpMime;
2541 }
2542
2543 if ( tmpRefresh )
2544 {
2545 emit refreshItems( *tmpRefresh );
2546 delete tmpRefresh;
2547 }
2548
2549 if ( tmpRemove )
2550 {
2551 for ( KFileItem *tmp = tmpRemove->first(); tmp; tmp = tmpRemove->next() ) {
2552 emit deleteItem( tmp );
2553 }
2554 delete tmpRemove;
2555 }
2556}
2557
2558void KDirLister::emitDeleteItem( KFileItem *item )
2559{
2560 if ( ( d->dirOnlyMode && !item->isDir() ) || !matchesFilter( item ) ) {
2561 return; // No reason to continue... bailing out here prevents a mimetype scan.
2562 }
2563
2564 if ( matchesMimeFilter( item ) ) {
2565 emit deleteItem( item );
2566 }
2567}
2568
2569
2570// ================ private slots ================ //
2571
2572void KDirLister::slotInfoMessage( TDEIO::Job *, const TQString& message )
2573{
2574 emit infoMessage( message );
2575}
2576
2577void KDirLister::slotPercent( TDEIO::Job *job, unsigned long pcnt )
2578{
2579 d->jobData[static_cast<TDEIO::ListJob *>(job)].percent = pcnt;
2580
2581 int result = 0;
2582
2583 TDEIO::filesize_t size = 0;
2584
2585 TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2586 while ( dataIt != d->jobData.end() )
2587 {
2588 result += (*dataIt).percent * (*dataIt).totalSize;
2589 size += (*dataIt).totalSize;
2590 ++dataIt;
2591 }
2592
2593 if ( size != 0 )
2594 result /= size;
2595 else
2596 result = 100;
2597 emit percent( result );
2598}
2599
2600void KDirLister::slotTotalSize( TDEIO::Job *job, TDEIO::filesize_t size )
2601{
2602 d->jobData[static_cast<TDEIO::ListJob *>(job)].totalSize = size;
2603
2604 TDEIO::filesize_t result = 0;
2605 TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2606 while ( dataIt != d->jobData.end() )
2607 {
2608 result += (*dataIt).totalSize;
2609 ++dataIt;
2610 }
2611
2612 emit totalSize( result );
2613}
2614
2615void KDirLister::slotProcessedSize( TDEIO::Job *job, TDEIO::filesize_t size )
2616{
2617 d->jobData[static_cast<TDEIO::ListJob *>(job)].processedSize = size;
2618
2619 TDEIO::filesize_t result = 0;
2620 TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2621 while ( dataIt != d->jobData.end() )
2622 {
2623 result += (*dataIt).processedSize;
2624 ++dataIt;
2625 }
2626
2627 emit processedSize( result );
2628}
2629
2630void KDirLister::slotSpeed( TDEIO::Job *job, unsigned long spd )
2631{
2632 d->jobData[static_cast<TDEIO::ListJob *>(job)].speed = spd;
2633
2634 int result = 0;
2635 TQMap< TDEIO::ListJob *, KDirListerPrivate::JobData >::Iterator dataIt = d->jobData.begin();
2636 while ( dataIt != d->jobData.end() )
2637 {
2638 result += (*dataIt).speed;
2639 ++dataIt;
2640 }
2641
2642 emit speed( result );
2643}
2644
2645uint KDirLister::numJobs()
2646{
2647 return d->jobData.count();
2648}
2649
2650void KDirLister::jobDone( TDEIO::ListJob *job )
2651{
2652 d->jobData.remove( job );
2653}
2654
2655void KDirLister::jobStarted( TDEIO::ListJob *job )
2656{
2657 KDirListerPrivate::JobData jobData;
2658 jobData.speed = 0;
2659 jobData.percent = 0;
2660 jobData.processedSize = 0;
2661 jobData.totalSize = 0;
2662
2663 d->jobData.insert( job, jobData );
2664 d->complete = false;
2665}
2666
2667void KDirLister::connectJob( TDEIO::ListJob *job )
2668{
2669 connect( job, TQ_SIGNAL(infoMessage( TDEIO::Job *, const TQString& )),
2670 this, TQ_SLOT(slotInfoMessage( TDEIO::Job *, const TQString& )) );
2671 connect( job, TQ_SIGNAL(percent( TDEIO::Job *, unsigned long )),
2672 this, TQ_SLOT(slotPercent( TDEIO::Job *, unsigned long )) );
2673 connect( job, TQ_SIGNAL(totalSize( TDEIO::Job *, TDEIO::filesize_t )),
2674 this, TQ_SLOT(slotTotalSize( TDEIO::Job *, TDEIO::filesize_t )) );
2675 connect( job, TQ_SIGNAL(processedSize( TDEIO::Job *, TDEIO::filesize_t )),
2676 this, TQ_SLOT(slotProcessedSize( TDEIO::Job *, TDEIO::filesize_t )) );
2677 connect( job, TQ_SIGNAL(speed( TDEIO::Job *, unsigned long )),
2678 this, TQ_SLOT(slotSpeed( TDEIO::Job *, unsigned long )) );
2679}
2680
2681void KDirLister::emitCompleted( const KURL& _url )
2682{
2683 TQString refURL = _url.internalReferenceURL();
2684 if (!refURL.isEmpty() && d->m_referenceURLMap.contains(refURL) &&
2685 _url.path().startsWith(d->m_referenceURLMap[refURL]))
2686 {
2687 // Likely a media:/ tdeioslave URL or similar
2688 // Rewrite the URL to ensure that the user remains within the media:/ tree!
2689 if (!refURL.endsWith("/"))
2690 {
2691 refURL.append("/");
2692 }
2693 KURL newItemURL(refURL);
2694 newItemURL.addPath(_url.fileName());
2695 emit completed(newItemURL);
2696 }
2697 else
2698 {
2699 emit completed(_url);
2700 }
2701}
2702
2703void KDirLister::setMainWindow( TQWidget *window )
2704{
2705 d->window = window;
2706}
2707
2708TQWidget *KDirLister::mainWindow()
2709{
2710 return d->window;
2711}
2712
2713KFileItemList KDirLister::items( WhichItems which ) const
2714{
2715 return itemsForDir( url(), which );
2716}
2717
2718KFileItemList KDirLister::itemsForDir( const KURL& dir, WhichItems which ) const
2719{
2720 KFileItemList result;
2721 KFileItemList *allItems = s_pCache->itemsForDir( dir );
2722 if ( !allItems ) {
2723 return result;
2724 }
2725
2726 if ( which == AllItems ) {
2727 result = *allItems; // shallow copy
2728 }
2729 else // only items passing the filters
2730 {
2731 for ( KFileItemListIterator kit( *allItems ); kit.current(); ++kit )
2732 {
2733 KFileItem *item = *kit;
2734 bool isExcluded = (d->dirOnlyMode && !item->isDir()) || !matchesFilter( item );
2735 if ( !isExcluded && matchesMimeFilter( item ) ) {
2736 result.append( item );
2737 }
2738 }
2739 }
2740
2741 return result;
2742}
2743
2744// to keep BC changes
2745
2746void KDirLister::virtual_hook( int, void * )
2747{ /*BASE::virtual_hook( id, data );*/ }
2748
2749#include "kdirlister.moc"
2750#include "kdirlister_p.moc"
KDirLister
The dir lister deals with the tdeiojob used to list and update a directory and has signals for the us...
Definition kdirlister.h:56
KDirLister::autoUpdate
bool autoUpdate() const
Checks whether KDirWatch will automatically update directories.
Definition kdirlister.cpp:2029
KDirLister::openURL
virtual bool openURL(const KURL &_url, bool _keep=false, bool _reload=false)
Run the directory lister on the given url.
Definition kdirlister.cpp:1937
KDirLister::newItems
void newItems(const KFileItemList &items)
Signal new items.
KDirLister::speed
void speed(int bytes_per_second)
Emitted to display information about the speed of the jobs.
KDirLister::doNameFilter
virtual bool doNameFilter(const TQString &name, const TQPtrList< TQRegExp > &filters) const
Called by the public matchesFilter() to do the actual filtering.
Definition kdirlister.cpp:2326
KDirLister::doMimeFilter
virtual bool doMimeFilter(const TQString &mime, const TQStringList &filters) const
Called by the public matchesMimeFilter() to do the actual filtering.
Definition kdirlister.cpp:2335
KDirLister::autoErrorHandlingEnabled
bool autoErrorHandlingEnabled() const
Check whether auto error handling is enabled.
Definition kdirlister.cpp:2071
KDirLister::matchesFilter
bool matchesFilter(const TQString &name) const
Checks whether name matches a filter in the list of name filters.
Definition kdirlister.cpp:2288
KDirLister::isFinished
bool isFinished() const
Returns true if no io operation is currently in progress.
Definition kdirlister.cpp:2191
KDirLister::findByURL
virtual KFileItem * findByURL(const KURL &_url) const
Find an item by its URL.
Definition kdirlister.cpp:2201
KDirLister::mimeFilters
const TQStringList & mimeFilters() const
Returns the list of mime based filters, as set via setMimeFilter().
Definition kdirlister.cpp:2283
KDirLister::rootItem
KFileItem * rootItem() const
Returns the file item of the URL.
Definition kdirlister.cpp:2196
KDirLister::setMainWindow
void setMainWindow(TQWidget *window)
Pass the main window this object is associated with this is used for caching authentication data.
Definition kdirlister.cpp:2703
KDirLister::setMimeFilter
virtual void setMimeFilter(const TQStringList &mimeList)
Set mime-based filter to only list items matching the given mimetypes.
Definition kdirlister.cpp:2247
KDirLister::setNameFilter
virtual void setNameFilter(const TQString &filter)
Set a name filter to only list items matching this name, e.g.
Definition kdirlister.cpp:2221
KDirLister::dirOnlyMode
bool dirOnlyMode() const
Checks whether the KDirLister only lists directories or all files.
Definition kdirlister.cpp:2057
KDirLister::findByName
virtual KFileItem * findByName(const TQString &name) const
Find an item by its name.
Definition kdirlister.cpp:2206
KDirLister::items
KFileItemList items(WhichItems which=FilteredItems) const
Returns the items listed for the current url().
Definition kdirlister.cpp:2713
KDirLister::clearMimeFilter
virtual void clearMimeFilter()
Clears the mime based filter.
Definition kdirlister.cpp:2271
KDirLister::setMimeExcludeFilter
void setMimeExcludeFilter(const TQStringList &mimeList)
Filtering should be done with KFileFilter.
Definition kdirlister.cpp:2261
KDirLister::emitChanges
virtual void emitChanges()
Actually emit the changes made with setShowingDotFiles, setDirOnlyMode, setNameFilter and setMimeFilt...
Definition kdirlister.cpp:2092
KDirLister::canceled
void canceled()
Tell the view that the user canceled the listing.
KDirLister::setDirOnlyMode
virtual void setDirOnlyMode(bool dirsOnly)
Call this to list only directories.
Definition kdirlister.cpp:2062
KDirLister::showingDotFiles
bool showingDotFiles() const
Checks whether hidden files (files beginning with a dot) will be shown.
Definition kdirlister.cpp:2043
KDirLister::completed
void completed()
Tell the view that listing is finished.
KDirLister::deleteItem
void deleteItem(KFileItem *_fileItem)
Signal an item to remove.
KDirLister::validURL
virtual bool validURL(const KURL &) const
Checks if an url is malformed or not and displays an error message if it is and autoErrorHandling is ...
Definition kdirlister.cpp:2366
KDirLister::KDirLister
KDirLister(bool _delayedMimeTypes=false)
Create a directory lister.
Definition kdirlister.cpp:1907
KDirLister::processedSize
void processedSize(TDEIO::filesize_t size)
Regularly emitted to show the progress of this KDirLister.
KDirLister::refreshItems
void refreshItems(const KFileItemList &items)
Signal an item to refresh (its mimetype/icon/name has changed).
KDirLister::stop
virtual void stop()
Stop listing all directories currently being listed.
Definition kdirlister.cpp:1999
KDirLister::~KDirLister
virtual ~KDirLister()
Destroy the directory lister.
Definition kdirlister.cpp:1923
KDirLister::clear
void clear()
Signal to clear all items.
KDirLister::nameFilter
const TQString & nameFilter() const
Returns the current name filter, as set via setNameFilter()
Definition kdirlister.cpp:2242
KDirLister::handleError
virtual void handleError(TDEIO::Job *)
Reimplement to customize error handling.
Definition kdirlister.cpp:2371
KDirLister::updateDirectory
virtual void updateDirectory(const KURL &_dir)
Update the directory _dir.
Definition kdirlister.cpp:2186
KDirLister::directories
const KURL::List & directories() const
Returns all URLs that are listed by this KDirLister.
Definition kdirlister.cpp:2087
KDirLister::url
const KURL & url() const
Returns the top level URL that is listed by this KDirLister.
Definition kdirlister.cpp:2082
KDirLister::started
void started(const KURL &_url)
Tell the view that we started to list _url.
KDirLister::setShowingDotFiles
virtual void setShowingDotFiles(bool _showDotFiles)
Changes the "is viewing dot files" setting.
Definition kdirlister.cpp:2048
KDirLister::totalSize
void totalSize(TDEIO::filesize_t size)
Emitted when we know the size of the jobs.
KDirLister::matchesMimeFilter
bool matchesMimeFilter(const TQString &mime) const
Checks whether mime matches a filter in the list of mime types.
Definition kdirlister.cpp:2293
KDirLister::setAutoUpdate
virtual void setAutoUpdate(bool enable)
Enable/disable automatic directory updating, when a directory changes (using KDirWatch).
Definition kdirlister.cpp:2034
KDirLister::itemsFilteredByMime
void itemsFilteredByMime(const KFileItemList &items)
Send a list of items filtered-out by mime-type.
KDirLister::mainWindow
TQWidget * mainWindow()
Returns the main window associated with this object.
Definition kdirlister.cpp:2708
KDirLister::itemsForDir
KFileItemList itemsForDir(const KURL &dir, WhichItems which=FilteredItems) const
Returns the items listed for the given dir.
Definition kdirlister.cpp:2718
KDirLister::WhichItems
WhichItems
Used by items() and itemsForDir() to specify whether you want all items for a directory or just the f...
Definition kdirlister.h:364
KDirLister::setAutoErrorHandlingEnabled
void setAutoErrorHandlingEnabled(bool enable, TQWidget *parent)
Enable or disable auto error handling is enabled.
Definition kdirlister.cpp:2076
KDirLister::percent
void percent(int percent)
Progress signal showing the overall progress of the KDirLister.
KDirLister::infoMessage
void infoMessage(const TQString &msg)
Emitted to display information about running jobs.
KDirLister::redirection
void redirection(const KURL &_url)
Signal a redirection.
KDirWatch::exists
static bool exists()
Returns true if there is an instance of KDirWatch.
Definition kdirwatch.cpp:1643
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition tdefileitem.h:42
KFileItem::isMarked
bool isMarked() const
Used when updating a directory.
Definition tdefileitem.h:435
KFileItem::mimetype
TQString mimetype() const
Returns the mimetype of the file item.
Definition tdefileitem.cpp:551
KFileItem::isLocalFile
bool isLocalFile() const
Returns true if the file is a local file.
Definition tdefileitem.h:296
KFileItem::mark
void mark()
Marks the item.
Definition tdefileitem.h:440
KFileItem::setURL
void setURL(const KURL &url)
Sets the item's URL.
Definition tdefileitem.cpp:314
KFileItem::setUDSEntry
void setUDSEntry(const TDEIO::UDSEntry &entry, const KURL &url, bool determineMimeTypeOnDemand=false, bool urlIsDirectory=false)
Reinitialize KFileItem with a new UDSEntry.
Definition tdefileitem.cpp:1090
KFileItem::url
const KURL & url() const
Returns the url of the file.
Definition tdefileitem.h:113
KFileItem::localPath
TQString localPath() const
Returns the local path if isLocalFile() == true or the TDEIO item has a UDS_LOCAL_PATH atom.
Definition tdefileitem.cpp:355
KFileItem::refreshMimeType
void refreshMimeType()
Re-reads mimetype information.
Definition tdefileitem.cpp:303
KFileItem::isDir
bool isDir() const
Returns true if this item represents a directory.
Definition tdefileitem.cpp:844
KFileItem::name
const TQString & name(bool lowerCase=false) const
Return the name of the file item (without a path).
Definition tdefileitem.h:312
KFileItem::isHidden
bool isHidden() const
Checks whether the file is hidden.
Definition tdefileitem.cpp:833
KFileItem::text
const TQString & text() const
Returns the text of the file item.
Definition tdefileitem.h:303
KFileItem::refresh
void refresh()
Throw away and re-read (for local files) all information about the file.
Definition tdefileitem.cpp:285
KMimeType::mimeType
static Ptr mimeType(const TQString &_name)
Retrieve a pointer to the mime type _name or a pointer to the default mime type "application/octet-st...
Definition kmimetype.cpp:141
KProtocolInfo::supportsListing
static bool supportsListing(const KURL &url)
Returns whether the protocol can list files/objects.
Definition kprotocolinfo.cpp:121
TDEIO::Job
The base class for all jobs.
Definition jobclasses.h:67
TDEIO::Job::showErrorDialog
void showErrorDialog(TQWidget *parent=0L)
Display a dialog box to inform the user of the error given by this job.
Definition job.cpp:315
TDEIO::Job::error
int error() const
Returns the error code, if there has been an error.
Definition jobclasses.h:94
TDEIO::Job::setWindow
void setWindow(TQWidget *window)
Definition job.cpp:381
TDEIO::Job::window
TQWidget * window() const
Definition job.cpp:387
TDEIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition jobclasses.h:1391
TDEIO::ListJob::redirectionURL
const KURL & redirectionURL() const
Returns the ListJob's redirection URL.
Definition jobclasses.h:1423
TDEIO::LocalURLJob
A TDEIO job that finds a local URL.
Definition jobclasses.h:1865
TDEIO::SimpleJob::url
const KURL & url() const
Returns the SimpleJob's URL.
Definition jobclasses.h:548
TDEIO::SimpleJob::kill
virtual void kill(bool quietly=true)
Abort job.
Definition job.cpp:486
TDEIO::localURL
TDEIO_EXPORT LocalURLJob * localURL(const KURL &remoteUrl)
Retrieve local URL if available.
Definition job.cpp:870
TDEIO::UDS_NAME
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition global.h:335
TDEIO::manually_mounted
TDEIO_EXPORT bool manually_mounted(const TQString &filename)
Checks if the path belongs to a filesystem that is manually mounted.
Definition global.cpp:1959
TDEIO::listDir
TDEIO_EXPORT ListJob * listDir(const KURL &url, bool showProgressInfo=true, bool includeHidden=true)
List the contents of url, which is assumed to be a directory.
Definition job.cpp:2216
TDEIO::filesize_t
TQ_ULLONG filesize_t
64-bit file size
Definition global.h:39

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.9.8
This website is maintained by Timothy Pearson.