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 } 00068 00069 void _k_emitCachedItems(const KUrl&, bool, bool); 00070 void _k_slotInfoMessage( KJob*, const QString& ); 00071 void _k_slotPercent( KJob*, unsigned long ); 00072 void _k_slotTotalSize( KJob*, qulonglong ); 00073 void _k_slotProcessedSize( KJob*, qulonglong ); 00074 void _k_slotSpeed( KJob*, unsigned long ); 00075 00076 bool doMimeExcludeFilter( const QString& mimeExclude, const QStringList& filters ) const; 00077 void jobStarted( KIO::ListJob * ); 00078 void connectJob( KIO::ListJob * ); 00079 void jobDone( KIO::ListJob * ); 00080 uint numJobs(); 00081 void addNewItem(const KUrl& directoryUrl, const KFileItem& item); 00082 void addNewItems(const KUrl& directoryUrl, const KFileItemList& items); 00083 void addRefreshItem(const KUrl& directoryUrl, const KFileItem& oldItem, const KFileItem& item); 00084 void emitItems(); 00085 void emitItemsDeleted(const KFileItemList &items); 00086 00092 void redirect(const KUrl& oldUrl, const KUrl& newUrl, bool keepItems); 00093 00097 bool isItemVisible(const KFileItem& item) const; 00098 00099 void prepareForSettingsChange() { 00100 if (!hasPendingChanges) { 00101 hasPendingChanges = true; 00102 oldSettings = settings; 00103 } 00104 } 00105 00106 void emitChanges(); 00107 00108 class CachedItemsJob; 00109 CachedItemsJob* cachedItemsJobForUrl(const KUrl& url) const; 00110 00111 00112 KDirLister *m_parent; 00113 00118 KUrl::List lstDirs; 00119 00120 // toplevel URL 00121 KUrl url; 00122 00123 bool complete:1; 00124 00125 bool autoUpdate:1; 00126 00127 bool delayedMimeTypes:1; 00128 00129 bool hasPendingChanges:1; // i.e. settings != oldSettings 00130 00131 bool autoErrorHandling:2; 00132 QWidget *errorParent; 00133 00134 struct JobData { 00135 long unsigned int percent, speed; 00136 KIO::filesize_t processedSize, totalSize; 00137 }; 00138 00139 QMap<KIO::ListJob *, JobData> jobData; 00140 00141 // file item for the root itself (".") 00142 KFileItem rootFileItem; 00143 00144 typedef QHash<KUrl, KFileItemList> NewItemsHash; 00145 NewItemsHash *lstNewItems; 00146 QList<QPair<KFileItem,KFileItem> > *lstRefreshItems; 00147 KFileItemList *lstMimeFilteredItems, *lstRemoveItems; 00148 00149 QWidget *window; // Main window this lister is associated with 00150 QList<CachedItemsJob*> m_cachedItemsJobs; 00151 00152 QString nameFilter; // parsed into lstFilters 00153 00154 struct FilterSettings { 00155 FilterSettings() : isShowingDotFiles(false), dirOnlyMode(false) {} 00156 bool isShowingDotFiles; 00157 bool dirOnlyMode; 00158 QList<QRegExp> lstFilters; 00159 QStringList mimeFilter; 00160 QStringList mimeExcludeFilter; 00161 }; 00162 FilterSettings settings; 00163 FilterSettings oldSettings; 00164 00165 friend class KDirListerCache; 00166 }; 00167 00181 class KDirListerCache : public QObject 00182 { 00183 Q_OBJECT 00184 public: 00185 KDirListerCache(); // only called by K_GLOBAL_STATIC 00186 ~KDirListerCache(); 00187 00188 void updateDirectory( const KUrl& dir ); 00189 00190 KFileItem itemForUrl( const KUrl& url ) const; 00191 KFileItemList *itemsForDir(const KUrl& dir) const; 00192 00193 bool listDir( KDirLister *lister, const KUrl& _url, bool _keep, bool _reload ); 00194 00195 // stop all running jobs for lister 00196 void stop( KDirLister *lister, bool silent = false ); 00197 // stop just the job listing url for lister 00198 void stopListingUrl( KDirLister *lister, const KUrl &_url, bool silent = false ); 00199 00200 void setAutoUpdate( KDirLister *lister, bool enable ); 00201 00202 void forgetDirs( KDirLister *lister ); 00203 void forgetDirs( KDirLister *lister, const KUrl &_url, bool notify ); 00204 00205 KFileItem findByName( const KDirLister *lister, const QString &_name ) const; 00206 // findByUrl returns a pointer so that it's possible to modify the item. 00207 // See itemForUrl for the version that returns a readonly kfileitem. 00208 // @param lister can be 0. If set, it is checked that the url is held by the lister 00209 KFileItem *findByUrl(const KDirLister *lister, const KUrl &url) const; 00210 00211 // Called by CachedItemsJob: 00212 // Emits the cached items, for this lister and this url 00213 void emitItemsFromCache(KDirLister::Private::CachedItemsJob* job, KDirLister* lister, 00214 const KUrl& _url, bool _reload, bool _emitCompleted); 00215 // Called by CachedItemsJob: 00216 void forgetCachedItemsJob(KDirLister::Private::CachedItemsJob* job, KDirLister* lister, 00217 const KUrl& url); 00218 00219 public Q_SLOTS: 00226 void slotFilesAdded( const QString& urlDirectory ); 00227 00235 void slotFilesRemoved( const QStringList& fileList ); 00236 00243 void slotFilesChanged( const QStringList& fileList ); 00244 void slotFileRenamed( const QString& srcUrl, const QString& dstUrl ); 00245 00246 private Q_SLOTS: 00247 void slotFileDirty( const QString &_file ); 00248 void slotFileCreated( const QString &_file ); 00249 void slotFileDeleted( const QString &_file ); 00250 00251 void slotEntries( KIO::Job *job, const KIO::UDSEntryList &entries ); 00252 void slotResult( KJob *j ); 00253 void slotRedirection( KIO::Job *job, const KUrl &url ); 00254 00255 void slotUpdateEntries( KIO::Job *job, const KIO::UDSEntryList &entries ); 00256 void slotUpdateResult( KJob *job ); 00257 void processPendingUpdates(); 00258 00259 private: 00260 class DirItem; 00261 DirItem* dirItemForUrl(const KUrl& dir) const; 00262 00263 bool validUrl( const KDirLister *lister, const KUrl& _url ) const; 00264 00265 void stopListJob(const QString& url, bool silent); 00266 00267 KIO::ListJob *jobForUrl( const QString& url, KIO::ListJob *not_job = 0 ); 00268 const KUrl& joburl( KIO::ListJob *job ); 00269 00270 void killJob( KIO::ListJob *job ); 00271 00272 // Called when something tells us that the directory @p url has changed. 00273 // Returns true if @p url is held by some lister (meaning: do the update now) 00274 // otherwise mark the cached item as not-up-to-date for later and return false 00275 bool checkUpdate( const QString& url ); 00276 00277 // Helper method for slotFileDirty 00278 void handleFileDirty(const KUrl& url); 00279 void handleDirDirty(const KUrl& url); 00280 00281 // when there were items deleted from the filesystem all the listers holding 00282 // the parent directory need to be notified, the unmarked items have to be deleted 00283 // and removed from the cache including all the children. 00284 void deleteUnmarkedItems( const QList<KDirLister *>&, KFileItemList & ); 00285 // Helper method called when we know that a list of items was deleted 00286 void itemsDeleted(const QList<KDirLister *>& listers, const KFileItemList& deletedItems); 00287 void slotFilesRemoved(const KUrl::List& urls); 00288 // common for slotRedirection and slotFileRenamed 00289 void renameDir( const KUrl &oldUrl, const KUrl &url ); 00290 // common for deleteUnmarkedItems and slotFilesRemoved 00291 void deleteDir( const KUrl& dirUrl ); 00292 // remove directory from cache (itemsCached), including all child dirs 00293 void removeDirFromCache( const KUrl& dir ); 00294 // helper for renameDir 00295 void emitRedirections( const KUrl &oldUrl, const KUrl &url ); 00296 00302 QSet<KDirLister *> emitRefreshItem(const KFileItem& oldItem, const KFileItem& fileitem); 00303 00308 QStringList directoriesForCanonicalPath(const QString& dir) const; 00309 00310 #ifndef NDEBUG 00311 void printDebug(); 00312 #endif 00313 00314 class DirItem 00315 { 00316 public: 00317 DirItem(const KUrl &dir, const QString& canonicalPath) 00318 : url(dir), m_canonicalPath(canonicalPath) 00319 { 00320 autoUpdates = 0; 00321 complete = false; 00322 watchedWhileInCache = false; 00323 } 00324 00325 ~DirItem() 00326 { 00327 if ( autoUpdates ) 00328 { 00329 if ( KDirWatch::exists() && url.isLocalFile() ) 00330 KDirWatch::self()->removeDir(m_canonicalPath); 00331 sendSignal( false, url ); 00332 } 00333 lstItems.clear(); 00334 } 00335 00336 void sendSignal( bool entering, const KUrl& url ) 00337 { 00338 // Note that "entering" means "start watching", and "leaving" means "stop watching" 00339 // (i.e. it's not when the user leaves the directory, it's when the directory is removed from the cache) 00340 if (entering) 00341 org::kde::KDirNotify::emitEnteredDirectory( url.url() ); 00342 else 00343 org::kde::KDirNotify::emitLeftDirectory( url.url() ); 00344 } 00345 00346 void redirect( const KUrl& newUrl ) 00347 { 00348 if ( autoUpdates ) 00349 { 00350 if ( url.isLocalFile() ) 00351 KDirWatch::self()->removeDir(m_canonicalPath); 00352 sendSignal( false, url ); 00353 00354 if (newUrl.isLocalFile()) { 00355 m_canonicalPath = QFileInfo(newUrl.toLocalFile()).canonicalFilePath(); 00356 KDirWatch::self()->addDir(m_canonicalPath); 00357 } 00358 sendSignal( true, newUrl ); 00359 } 00360 00361 url = newUrl; 00362 00363 if ( !rootItem.isNull() ) 00364 rootItem.setUrl( newUrl ); 00365 } 00366 00367 void incAutoUpdate() 00368 { 00369 if ( autoUpdates++ == 0 ) 00370 { 00371 if ( url.isLocalFile() ) 00372 KDirWatch::self()->addDir(m_canonicalPath); 00373 sendSignal( true, url ); 00374 } 00375 } 00376 00377 void decAutoUpdate() 00378 { 00379 if ( --autoUpdates == 0 ) 00380 { 00381 if ( url.isLocalFile() ) 00382 KDirWatch::self()->removeDir(m_canonicalPath); 00383 sendSignal( false, url ); 00384 } 00385 00386 else if ( autoUpdates < 0 ) 00387 autoUpdates = 0; 00388 } 00389 00390 // number of KDirListers using autoUpdate for this dir 00391 short autoUpdates; 00392 00393 // this directory is up-to-date 00394 bool complete; 00395 00396 // the directory is watched while being in the cache (useful for proper incAutoUpdate/decAutoUpdate count) 00397 bool watchedWhileInCache; 00398 00399 // the complete url of this directory 00400 KUrl url; 00401 00402 // the local path, with symlinks resolved, so that KDirWatch works 00403 QString m_canonicalPath; 00404 00405 // KFileItem representing the root of this directory. 00406 // Remember that this is optional. FTP sites don't return '.' in 00407 // the list, so they give no root item 00408 KFileItem rootItem; 00409 KFileItemList lstItems; 00410 }; 00411 00412 //static const unsigned short MAX_JOBS_PER_LISTER; 00413 00414 QMap<KIO::ListJob *, KIO::UDSEntryList> runningListJobs; 00415 00416 // an item is a complete directory 00417 QHash<QString /*url*/, DirItem*> itemsInUse; 00418 QCache<QString /*url*/, DirItem> itemsCached; 00419 00420 typedef QHash<QString /*url*/, KDirListerCacheDirectoryData> DirectoryDataHash; 00421 DirectoryDataHash directoryData; 00422 00423 // Symlink-to-directories are registered here so that we can 00424 // find the url that changed, when kdirwatch tells us about 00425 // changes in the canonical url. (#213799) 00426 QHash<QString /*canonical path*/, QStringList /*dirlister urls*/> canonicalUrls; 00427 00428 // Set of local files that we have changed recently (according to KDirWatch) 00429 // We temporize the notifications by keeping them 500ms in this list. 00430 QSet<QString /*path*/> pendingUpdates; 00431 // The timer for doing the delayed updates 00432 QTimer pendingUpdateTimer; 00433 00434 // Set of remote files that have changed recently -- but we can't emit those 00435 // changes yet, we need to wait for the "update" directory listing. 00436 // The cmp() call can't differ mimetypes since they are determined on demand, 00437 // this is why we need to remember those files here. 00438 QSet<KFileItem*> pendingRemoteUpdates; 00439 00440 // the KDirNotify signals 00441 OrgKdeKDirNotifyInterface *kdirnotify; 00442 00443 struct ItemInUseChange; 00444 }; 00445 00446 // Data associated with a directory url 00447 // This could be in DirItem but only in the itemsInUse dict... 00448 struct KDirListerCacheDirectoryData 00449 { 00450 // A lister can be EITHER in listersCurrentlyListing OR listersCurrentlyHolding 00451 // but NOT in both at the same time. 00452 // But both lists can have different listers at the same time; this 00453 // happens if more listers are requesting url at the same time and 00454 // one lister was stopped during the listing of files. 00455 00456 // Listers that are currently listing this url 00457 QList<KDirLister *> listersCurrentlyListing; 00458 // Listers that are currently holding this url 00459 QList<KDirLister *> listersCurrentlyHolding; 00460 00461 void moveListersWithoutCachedItemsJob(const KUrl& url); 00462 }; 00463 00464 //const unsigned short KDirListerCache::MAX_JOBS_PER_LISTER = 5; 00465 00466 // This job tells KDirListerCache to emit cached items asynchronously from listDir() 00467 // to give the KDirLister user enough time for connecting to its signals, and so 00468 // that KDirListerCache behaves just like when a real KIO::Job is used: nothing 00469 // is emitted during the openUrl call itself. 00470 class KDirLister::Private::CachedItemsJob : public KJob { 00471 Q_OBJECT 00472 public: 00473 CachedItemsJob(KDirLister* lister, const KUrl& url, bool reload); 00474 00475 /*reimp*/ void start() { QMetaObject::invokeMethod(this, "done", Qt::QueuedConnection); } 00476 00477 // For updateDirectory() to cancel m_emitCompleted; 00478 void setEmitCompleted(bool b) { m_emitCompleted = b; } 00479 00480 KUrl url() const { return m_url; } 00481 00482 protected: 00483 virtual bool doKill(); 00484 00485 public Q_SLOTS: 00486 void done(); 00487 00488 private: 00489 KDirLister* m_lister; 00490 KUrl m_url; 00491 bool m_reload; 00492 bool m_emitCompleted; 00493 }; 00494 00495 #endif
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:34:59 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:34:59 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.