• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

kdirlister_p.h

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2002-2006 Michael Brade <brade@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #ifndef kdirlister_p_h
00021 #define kdirlister_p_h
00022 
00023 #include "kfileitem.h"
00024 
00025 #include <QtCore/QMap>
00026 #include <QtCore/QHash>
00027 #include <QtCore/QCache>
00028 #include <QtCore/QSet>
00029 #include <QtCore/QTimer>
00030 #include <QtGui/QWidget>
00031 
00032 #include <kurl.h>
00033 #include <kdebug.h>
00034 #include <kio/global.h>
00035 #include <kdirwatch.h>
00036 
00037 class KDirLister;
00038 namespace KIO { class Job; class ListJob; }
00039 class OrgKdeKDirNotifyInterface;
00040 struct KDirListerCacheDirectoryData;
00041 
00042 class KDirLister::Private
00043 {
00044 public:
00045   Private(KDirLister *parent)
00046       : m_parent(parent)
00047   {
00048     complete = false;
00049 
00050     autoUpdate = false;
00051 
00052     autoErrorHandling = false;
00053     errorParent = 0;
00054 
00055     delayedMimeTypes = false;
00056 
00057     rootFileItem = KFileItem();
00058 
00059     lstNewItems = 0;
00060     lstRefreshItems = 0;
00061     lstMimeFilteredItems = 0;
00062     lstRemoveItems = 0;
00063 
00064     hasPendingChanges = false;
00065 
00066     window = 0;
00067     m_cachedItemsJob = 0;
00068   }
00069 
00070     void _k_emitCachedItems(const KUrl&, bool, bool);
00071   void _k_slotInfoMessage( KJob*, const QString& );
00072   void _k_slotPercent( KJob*, unsigned long );
00073   void _k_slotTotalSize( KJob*, qulonglong );
00074   void _k_slotProcessedSize( KJob*, qulonglong );
00075   void _k_slotSpeed( KJob*, unsigned long );
00076 
00077   bool doMimeExcludeFilter( const QString& mimeExclude, const QStringList& filters ) const;
00078   void jobStarted( KIO::ListJob * );
00079   void connectJob( KIO::ListJob * );
00080   void jobDone( KIO::ListJob * );
00081   uint numJobs();
00082     void addNewItem(const KUrl& directoryUrl, const KFileItem& item);
00083     void addNewItems(const KUrl& directoryUrl, const KFileItemList& items);
00084     void addRefreshItem(const KUrl& directoryUrl, const KFileItem& oldItem, const KFileItem& item);
00085   void emitItems();
00086   void emitItemsDeleted(const KFileItemList &items);
00087 
00093     void redirect(const KUrl& oldUrl, const KUrl& newUrl, bool keepItems);
00094 
00098     bool isItemVisible(const KFileItem& item) const;
00099 
00100     void prepareForSettingsChange() {
00101         if (!hasPendingChanges) {
00102             hasPendingChanges = true;
00103             oldSettings = settings;
00104         }
00105     }
00106 
00107     void emitChanges();
00108 
00109 
00110   KDirLister *m_parent;
00111 
00116   KUrl::List lstDirs;
00117 
00118   // toplevel URL
00119   KUrl url;
00120 
00121   bool complete:1;
00122 
00123   bool autoUpdate:1;
00124 
00125   bool delayedMimeTypes:1;
00126 
00127     bool hasPendingChanges:1; // i.e. settings != oldSettings
00128 
00129   bool autoErrorHandling:2;
00130   QWidget *errorParent;
00131 
00132   struct JobData {
00133     long unsigned int percent, speed;
00134     KIO::filesize_t processedSize, totalSize;
00135   };
00136 
00137   QMap<KIO::ListJob *, JobData> jobData;
00138 
00139   // file item for the root itself (".")
00140   KFileItem rootFileItem;
00141 
00142     typedef QHash<KUrl, KFileItemList> NewItemsHash;
00143     NewItemsHash *lstNewItems;
00144   QList<QPair<KFileItem,KFileItem> > *lstRefreshItems;
00145   KFileItemList *lstMimeFilteredItems, *lstRemoveItems;
00146 
00147     QWidget *window; // Main window this lister is associated with
00148     class CachedItemsJob;
00149     CachedItemsJob* m_cachedItemsJob;
00150 
00151     QString nameFilter; // parsed into lstFilters
00152 
00153     struct FilterSettings {
00154         FilterSettings() : isShowingDotFiles(false), dirOnlyMode(false) {}
00155         bool isShowingDotFiles;
00156         bool dirOnlyMode;
00157         QList<QRegExp> lstFilters;
00158         QStringList mimeFilter;
00159         QStringList mimeExcludeFilter;
00160     };
00161     FilterSettings settings;
00162     FilterSettings oldSettings;
00163 
00164     friend class KDirListerCache;
00165 };
00166 
00180 class KDirListerCache : public QObject
00181 {
00182     Q_OBJECT
00183 public:
00184     KDirListerCache(); // only called by K_GLOBAL_STATIC
00185     ~KDirListerCache();
00186 
00187     void updateDirectory( const KUrl& dir );
00188 
00189     KFileItem itemForUrl( const KUrl& url ) const;
00190     KFileItemList *itemsForDir(const KUrl& dir) const;
00191 
00192     bool listDir( KDirLister *lister, const KUrl& _url, bool _keep, bool _reload );
00193 
00194     // stop all running jobs for lister
00195     void stop( KDirLister *lister, bool silent = false );
00196     // stop just the job listing url for lister
00197     void stop( KDirLister *lister, const KUrl &_url, bool silent = false );
00198 
00199   void setAutoUpdate( KDirLister *lister, bool enable );
00200 
00201   void forgetDirs( KDirLister *lister );
00202   void forgetDirs( KDirLister *lister, const KUrl &_url, bool notify );
00203 
00204     KFileItem findByName( const KDirLister *lister, const QString &_name ) const;
00205     // findByUrl returns a pointer so that it's possible to modify the item.
00206     // See itemForUrl for the version that returns a readonly kfileitem.
00207     // @param lister can be 0. If set, it is checked that the url is held by the lister
00208     KFileItem *findByUrl(const KDirLister *lister, const KUrl &url) const;
00209 
00210     // Called by CachedItemsJob:
00211     // Emits those items, for this lister and this url
00212     void emitItemsFromCache(KDirLister* lister, const KFileItemList& lst, const KFileItem& rootItem,
00213                             const KUrl& _url, bool _reload, bool _emitCompleted);
00214 
00215 public Q_SLOTS:
00222   void slotFilesAdded( const QString& urlDirectory );
00223 
00231   void slotFilesRemoved( const QStringList& fileList );
00232 
00239   void slotFilesChanged( const QStringList& fileList );
00240   void slotFileRenamed( const QString& srcUrl, const QString& dstUrl );
00241 
00242 private Q_SLOTS:
00243   void slotFileDirty( const QString &_file );
00244   void slotFileCreated( const QString &_file );
00245   void slotFileDeleted( const QString &_file );
00246 
00247   void slotEntries( KIO::Job *job, const KIO::UDSEntryList &entries );
00248   void slotResult( KJob *j );
00249   void slotRedirection( KIO::Job *job, const KUrl &url );
00250 
00251   void slotUpdateEntries( KIO::Job *job, const KIO::UDSEntryList &entries );
00252   void slotUpdateResult( KJob *job );
00253   void processPendingUpdates();
00254 
00255 private:
00256     class DirItem;
00257     DirItem* dirItemForUrl(const KUrl& dir) const;
00258 
00259     bool validUrl( const KDirLister *lister, const KUrl& _url ) const;
00260 
00261     // helper for both stop methods
00262     void stopLister(KDirLister* lister, const QString& url, KDirListerCacheDirectoryData& dirData, bool silent);
00263 
00264     KIO::ListJob *jobForUrl( const QString& url, KIO::ListJob *not_job = 0 );
00265     const KUrl& joburl( KIO::ListJob *job );
00266 
00267     void killJob( KIO::ListJob *job );
00268 
00269     // Called when something tells us that the directory @p url has changed.
00270     // Returns true if @p url is held by some lister (meaning: do the update now)
00271     // otherwise mark the cached item as not-up-to-date for later and return false
00272     bool checkUpdate( const QString& url );
00273 
00274     // Helper method for slotFileDirty
00275     void handleFileDirty(const KUrl& url);
00276     void handleDirDirty(const KUrl& url);
00277 
00278   // when there were items deleted from the filesystem all the listers holding
00279   // the parent directory need to be notified, the unmarked items have to be deleted
00280   // and removed from the cache including all the children.
00281   void deleteUnmarkedItems( const QList<KDirLister *>&, KFileItemList & );
00282     // Helper method called when we know that a list of items was deleted
00283     void itemsDeleted(const QList<KDirLister *>& listers, const KFileItemList& deletedItems);
00284     void slotFilesRemoved(const KUrl::List& urls);
00285     // common for slotRedirection and slotFileRenamed
00286   void renameDir( const KUrl &oldUrl, const KUrl &url );
00287   // common for deleteUnmarkedItems and slotFilesRemoved
00288   void deleteDir( const KUrl& dirUrl );
00289   // remove directory from cache (itemsCached), including all child dirs
00290   void removeDirFromCache( const KUrl& dir );
00291   // helper for renameDir
00292   void emitRedirections( const KUrl &oldUrl, const KUrl &url );
00293 
00299     QSet<KDirLister *> emitRefreshItem(const KFileItem& oldItem, const KFileItem& fileitem);
00300 
00305     QStringList directoriesForCanonicalPath(const QString& dir) const;
00306 
00307 #ifndef NDEBUG
00308   void printDebug();
00309 #endif
00310 
00311   class DirItem
00312   {
00313   public:
00314     DirItem(const KUrl &dir, const QString& canonicalPath)
00315       : url(dir), m_canonicalPath(canonicalPath)
00316     {
00317       autoUpdates = 0;
00318       complete = false;
00319     }
00320 
00321     ~DirItem()
00322     {
00323       if ( autoUpdates )
00324       {
00325         if ( KDirWatch::exists() && url.isLocalFile() )
00326             KDirWatch::self()->removeDir(m_canonicalPath);
00327         sendSignal( false, url );
00328       }
00329       lstItems.clear();
00330     }
00331 
00332     void sendSignal( bool entering, const KUrl& url )
00333     {
00334         // Note that "entering" means "start watching", and "leaving" means "stop watching"
00335         // (i.e. it's not when the user leaves the directory, it's when the directory is removed from the cache)
00336         if (entering)
00337             org::kde::KDirNotify::emitEnteredDirectory( url.url() );
00338         else
00339             org::kde::KDirNotify::emitLeftDirectory( url.url() );
00340     }
00341 
00342     void redirect( const KUrl& newUrl )
00343     {
00344       if ( autoUpdates )
00345       {
00346         if ( url.isLocalFile() )
00347             KDirWatch::self()->removeDir(m_canonicalPath);
00348         sendSignal( false, url );
00349 
00350         if (newUrl.isLocalFile()) {
00351             m_canonicalPath = QFileInfo(newUrl.toLocalFile()).canonicalFilePath();
00352             KDirWatch::self()->addDir(m_canonicalPath);
00353         }
00354         sendSignal( true, newUrl );
00355       }
00356 
00357       url = newUrl;
00358 
00359       if ( !rootItem.isNull() )
00360         rootItem.setUrl( newUrl );
00361     }
00362 
00363     void incAutoUpdate()
00364     {
00365       if ( autoUpdates++ == 0 )
00366       {
00367         if ( url.isLocalFile() )
00368           KDirWatch::self()->addDir(m_canonicalPath);
00369         sendSignal( true, url );
00370       }
00371     }
00372 
00373     void decAutoUpdate()
00374     {
00375       if ( --autoUpdates == 0 )
00376       {
00377         if ( url.isLocalFile() )
00378           KDirWatch::self()->removeDir(m_canonicalPath);
00379         sendSignal( false, url );
00380       }
00381 
00382       else if ( autoUpdates < 0 )
00383         autoUpdates = 0;
00384     }
00385 
00386     // number of KDirListers using autoUpdate for this dir
00387     short autoUpdates;
00388 
00389     // this directory is up-to-date
00390     bool complete;
00391 
00392     // the complete url of this directory
00393     KUrl url;
00394 
00395     // the local path, with symlinks resolved, so that KDirWatch works
00396     QString m_canonicalPath;
00397 
00398     // KFileItem representing the root of this directory.
00399     // Remember that this is optional. FTP sites don't return '.' in
00400     // the list, so they give no root item
00401     KFileItem rootItem;
00402     KFileItemList lstItems;
00403   };
00404 
00405     //static const unsigned short MAX_JOBS_PER_LISTER;
00406 
00407     QMap<KIO::ListJob *, KIO::UDSEntryList> runningListJobs;
00408 
00409     // an item is a complete directory
00410     QHash<QString /*url*/, DirItem*> itemsInUse;
00411     QCache<QString /*url*/, DirItem> itemsCached;
00412 
00413     typedef QHash<QString /*url*/, KDirListerCacheDirectoryData> DirectoryDataHash;
00414     DirectoryDataHash directoryData;
00415 
00416     // Symlink-to-directories are registered here so that we can
00417     // find the url that changed, when kdirwatch tells us about
00418     // changes in the canonical url. (#213799)
00419     QHash<QString /*canonical path*/, QStringList /*dirlister urls*/> canonicalUrls;
00420 
00421     // Set of local files that we have changed recently (according to KDirWatch)
00422     // We temporize the notifications by keeping them 500ms in this list.
00423     QSet<QString /*path*/> pendingUpdates;
00424     // The timer for doing the delayed updates
00425     QTimer pendingUpdateTimer;
00426 
00427     // Set of remote files that have changed recently -- but we can't emit those
00428     // changes yet, we need to wait for the "update" directory listing.
00429     // The cmp() call can't differ mimetypes since they are determined on demand,
00430     // this is why we need to remember those files here.
00431     QSet<KFileItem*> pendingRemoteUpdates;
00432 
00433     // the KDirNotify signals
00434     OrgKdeKDirNotifyInterface *kdirnotify;
00435 
00436     struct ItemInUseChange;
00437 };
00438 
00439 // Data associated with a directory url
00440 // This could be in DirItem but only in the itemsInUse dict...
00441 struct KDirListerCacheDirectoryData
00442 {
00443     // A lister can be EITHER in listersCurrentlyListing OR listersCurrentlyHolding
00444     // but NOT in both at the same time.
00445     // But both lists can have different listers at the same time; this
00446     // happens if more listers are requesting url at the same time and
00447     // one lister was stopped during the listing of files.
00448 
00449     // Listers that are currently listing this url
00450     QList<KDirLister *> listersCurrentlyListing;
00451     // Listers that are currently holding this url
00452     QList<KDirLister *> listersCurrentlyHolding;
00453 
00454     void moveListersWithoutCachedItemsJob(const KUrl& url);
00455 };
00456 
00457 //const unsigned short KDirListerCache::MAX_JOBS_PER_LISTER = 5;
00458 
00459 // This job tells KDirListerCache to emit cached items asynchronously from listDir()
00460 // to give the KDirLister user enough time for connecting to its signals, and so
00461 // that KDirListerCache behaves just like when a real KIO::Job is used: nothing
00462 // is emitted during the openUrl call itself.
00463 class KDirLister::Private::CachedItemsJob : public KJob {
00464     Q_OBJECT
00465 public:
00466     CachedItemsJob(KDirLister* lister, const KFileItemList& items, const KFileItem& rootItem,
00467                    const KUrl& url, bool reload)
00468         : KJob(lister),
00469           m_lister(lister), m_url(url),
00470           m_items(items), m_rootItem(rootItem),
00471           m_reload(reload), m_emitCompleted(true) {
00472         Q_ASSERT(lister->d->m_cachedItemsJob == 0);
00473         lister->d->m_cachedItemsJob = this;
00474         setAutoDelete(true);
00475         start();
00476     }
00477 
00478     /*reimp*/ void start() { QMetaObject::invokeMethod(this, "done", Qt::QueuedConnection); }
00479 
00480     // For updateDirectory() to cancel m_emitCompleted;
00481     void setEmitCompleted(bool b) { m_emitCompleted = b; }
00482 
00483     KUrl url() const { return m_url; }
00484 
00485 public Q_SLOTS:
00486     void done();
00487 
00488 private:
00489     KDirLister* m_lister;
00490     KUrl m_url;
00491     KFileItemList m_items;
00492     KFileItem m_rootItem;
00493     bool m_reload;
00494     bool m_emitCompleted;
00495 };
00496 
00497 #endif

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal