1 | /* |
2 | This file is part of the KDE project |
3 | SPDX-FileCopyrightText: 2002-2006 Michael Brade <brade@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #ifndef KCOREDIRLISTER_P_H |
9 | #define KCOREDIRLISTER_P_H |
10 | |
11 | #include "kfileitem.h" |
12 | |
13 | #ifndef KIO_ANDROID_STUB |
14 | #include "kdirnotify.h" |
15 | #endif |
16 | |
17 | #include <QCache> |
18 | #include <QCoreApplication> |
19 | #include <QFileInfo> |
20 | #include <QHash> |
21 | #include <QList> |
22 | #include <QMap> |
23 | #include <QTimer> |
24 | #include <QUrl> |
25 | |
26 | #include <KDirWatch> |
27 | #include <kio/global.h> |
28 | |
29 | #include <set> |
30 | |
31 | class QRegularExpression; |
32 | class KCoreDirLister; |
33 | namespace KIO |
34 | { |
35 | class Job; |
36 | class ListJob; |
37 | } |
38 | class OrgKdeKDirNotifyInterface; |
39 | struct KCoreDirListerCacheDirectoryData; |
40 | |
41 | class KCoreDirListerPrivate |
42 | { |
43 | public: |
44 | explicit KCoreDirListerPrivate(KCoreDirLister *qq); |
45 | |
46 | void emitCachedItems(const QUrl &, bool, bool); |
47 | void slotInfoMessage(KJob *, const QString &); |
48 | void slotPercent(KJob *, unsigned long); |
49 | void slotTotalSize(KJob *, qulonglong); |
50 | void slotProcessedSize(KJob *, qulonglong); |
51 | void slotSpeed(KJob *, unsigned long); |
52 | |
53 | /* |
54 | * Called by the public matchesMimeFilter() to do the |
55 | * actual filtering. Those methods may be reimplemented to customize |
56 | * filtering. |
57 | * @param mimeType the MIME type to filter |
58 | * @param filters the list of MIME types to filter |
59 | */ |
60 | bool doMimeFilter(const QString &mimeType, const QStringList &filters) const; |
61 | bool doMimeExcludeFilter(const QString &mimeExclude, const QStringList &filters) const; |
62 | void connectJob(KIO::ListJob *); |
63 | void jobDone(KIO::ListJob *); |
64 | uint numJobs(); |
65 | void addNewItem(const QUrl &directoryUrl, const KFileItem &item); |
66 | void addNewItems(const QUrl &directoryUrl, const QList<KFileItem> &items); |
67 | void addRefreshItem(const QUrl &directoryUrl, const KFileItem &oldItem, const KFileItem &item); |
68 | void emitItems(); |
69 | void emitItemsDeleted(const KFileItemList &items); |
70 | |
71 | /* |
72 | * Called for every new item before emitting newItems(). |
73 | * You may reimplement this method in a subclass to implement your own |
74 | * filtering. |
75 | * The default implementation filters out ".." and everything not matching |
76 | * the name filter(s) |
77 | * @return @c true if the item is "ok". |
78 | * @c false if the item shall not be shown in a view, e.g. |
79 | * files not matching a pattern *.cpp ( KFileItem::isHidden()) |
80 | * @see matchesFilter |
81 | * @see setNameFilter |
82 | */ |
83 | bool matchesFilter(const KFileItem &) const; |
84 | |
85 | /* |
86 | * Called for every new item before emitting newItems(). |
87 | * You may reimplement this method in a subclass to implement your own |
88 | * filtering. |
89 | * The default implementation filters out everything not matching |
90 | * the mime filter(s) |
91 | * @return @c true if the item is "ok". |
92 | * @c false if the item shall not be shown in a view, e.g. |
93 | * files not matching the mime filter |
94 | * @see matchesMimeFilter |
95 | * @see setMimeFilter |
96 | */ |
97 | bool matchesMimeFilter(const KFileItem &) const; |
98 | |
99 | /** |
100 | * Redirect this dirlister from oldUrl to newUrl. |
101 | * @param keepItems if true, keep the fileitems (e.g. when renaming an existing dir); |
102 | * if false, clear out everything (e.g. when redirecting during listing). |
103 | */ |
104 | void redirect(const QUrl &oldUrl, const QUrl &newUrl, bool keepItems); |
105 | |
106 | /** |
107 | * Should this item be visible according to the current filter settings? |
108 | */ |
109 | bool isItemVisible(const KFileItem &item) const; |
110 | |
111 | void prepareForSettingsChange() |
112 | { |
113 | if (!hasPendingChanges) { |
114 | hasPendingChanges = true; |
115 | oldSettings = settings; |
116 | } |
117 | } |
118 | |
119 | void emitChanges(); |
120 | |
121 | class CachedItemsJob; |
122 | CachedItemsJob *cachedItemsJobForUrl(const QUrl &url) const; |
123 | |
124 | KCoreDirLister *const q; |
125 | |
126 | /** |
127 | * List of dirs handled by this dirlister. The first entry is the base URL. |
128 | * For a tree view, it contains all the dirs shown. |
129 | */ |
130 | QList<QUrl> lstDirs; |
131 | |
132 | // toplevel URL |
133 | QUrl url; |
134 | |
135 | bool complete = false; |
136 | bool autoUpdate = false; |
137 | bool delayedMimeTypes = false; |
138 | bool hasPendingChanges = false; // i.e. settings != oldSettings |
139 | bool m_autoErrorHandling = true; |
140 | bool requestMimeTypeWhileListing = false; |
141 | |
142 | struct JobData { |
143 | long unsigned int percent, speed; |
144 | KIO::filesize_t processedSize, totalSize; |
145 | }; |
146 | |
147 | QMap<KIO::ListJob *, JobData> jobData; |
148 | |
149 | // file item for the root itself (".") |
150 | KFileItem rootFileItem; |
151 | |
152 | typedef QHash<QUrl, KFileItemList> NewItemsHash; |
153 | NewItemsHash lstNewItems; |
154 | QList<QPair<KFileItem, KFileItem>> lstRefreshItems; |
155 | KFileItemList lstMimeFilteredItems, lstRemoveItems; |
156 | |
157 | QList<CachedItemsJob *> m_cachedItemsJobs; |
158 | |
159 | QString nameFilter; // parsed into lstFilters |
160 | |
161 | struct FilterSettings { |
162 | FilterSettings() |
163 | : isShowingDotFiles(false) |
164 | , dirOnlyMode(false) |
165 | { |
166 | } |
167 | bool isShowingDotFiles; |
168 | bool dirOnlyMode; |
169 | QList<QRegularExpression> lstFilters; |
170 | QStringList mimeFilter; |
171 | QStringList mimeExcludeFilter; |
172 | }; |
173 | FilterSettings settings; |
174 | FilterSettings oldSettings; |
175 | |
176 | friend class KCoreDirListerCache; |
177 | }; |
178 | |
179 | /** |
180 | * Design of the cache: |
181 | * There is a single KCoreDirListerCache for the whole process. |
182 | * It holds all the items used by the dir listers (itemsInUse) |
183 | * as well as a cache of the recently used items (itemsCached). |
184 | * Those items are grouped by directory (a DirItem represents a whole directory). |
185 | * |
186 | * KCoreDirListerCache also runs all the jobs for listing directories, whether they are for |
187 | * normal listing or for updates. |
188 | * For faster lookups, it also stores a hash table, which gives for a directory URL: |
189 | * - the dirlisters holding that URL (listersCurrentlyHolding) |
190 | * - the dirlisters currently listing that URL (listersCurrentlyListing) |
191 | */ |
192 | class KCoreDirListerCache : public QObject |
193 | { |
194 | Q_OBJECT |
195 | public: |
196 | KCoreDirListerCache(); // only called by QThreadStorage internally |
197 | ~KCoreDirListerCache() override; |
198 | |
199 | void updateDirectory(const QUrl &dir); |
200 | |
201 | KFileItem itemForUrl(const QUrl &url) const; |
202 | QList<KFileItem> *itemsForDir(const QUrl &dir) const; |
203 | |
204 | bool listDir(KCoreDirLister *lister, const QUrl &_url, bool _keep, bool _reload); |
205 | |
206 | // stop all running jobs for lister |
207 | void stop(KCoreDirLister *lister, bool silent = false); |
208 | // stop just the job listing url for lister |
209 | void stopListingUrl(KCoreDirLister *lister, const QUrl &_url, bool silent = false); |
210 | |
211 | void setAutoUpdate(KCoreDirLister *lister, bool enable); |
212 | |
213 | void forgetDirs(KCoreDirLister *lister); |
214 | void forgetDirs(KCoreDirLister *lister, const QUrl &_url, bool notify); |
215 | |
216 | KFileItem findByName(const KCoreDirLister *lister, const QString &_name) const; |
217 | // findByUrl returns a pointer so that it's possible to modify the item. |
218 | // See itemForUrl for the version that returns a readonly kfileitem. |
219 | // @param lister can be 0. If set, it is checked that the url is held by the lister |
220 | KFileItem findByUrl(const KCoreDirLister *lister, const QUrl &url) const; |
221 | |
222 | // Called by CachedItemsJob: |
223 | // Emits the cached items, for this lister and this url |
224 | void emitItemsFromCache(KCoreDirListerPrivate::CachedItemsJob *job, KCoreDirLister *lister, const QUrl &_url, bool _reload, bool _emitCompleted); |
225 | // Called by CachedItemsJob: |
226 | void forgetCachedItemsJob(KCoreDirListerPrivate::CachedItemsJob *job, KCoreDirLister *lister, const QUrl &url); |
227 | |
228 | public Q_SLOTS: |
229 | /** |
230 | * Notify that files have been added in @p directory |
231 | * The receiver will list that directory again to find |
232 | * the new items (since it needs more than just the names anyway). |
233 | * Connected to the DBus signal from the KDirNotify interface. |
234 | */ |
235 | void slotFilesAdded(const QString &urlDirectory); |
236 | |
237 | /** |
238 | * Notify that files have been deleted. |
239 | * This call passes the exact urls of the deleted files |
240 | * so that any view showing them can simply remove them |
241 | * or be closed (if its current dir was deleted) |
242 | * Connected to the DBus signal from the KDirNotify interface. |
243 | */ |
244 | void slotFilesRemoved(const QStringList &fileList); |
245 | |
246 | /** |
247 | * Notify that files have been changed. |
248 | * At the moment, this is only used for new icon, but it could be |
249 | * used for size etc. as well. |
250 | * Connected to the DBus signal from the KDirNotify interface. |
251 | */ |
252 | void slotFilesChanged(const QStringList &fileList); |
253 | void slotFileRenamed(const QString &srcUrl, const QString &dstUrl, const QString &dstPath); |
254 | |
255 | private Q_SLOTS: |
256 | void slotFileDirty(const QString &_file); |
257 | void slotFileCreated(const QString &_file); |
258 | void slotFileDeleted(const QString &_file); |
259 | |
260 | void slotEntries(KIO::Job *job, const KIO::UDSEntryList &entries); |
261 | void slotResult(KJob *j); |
262 | void slotRedirection(KIO::Job *job, const QUrl &url); |
263 | |
264 | void slotUpdateEntries(KIO::Job *job, const KIO::UDSEntryList &entries); |
265 | void slotUpdateResult(KJob *job); |
266 | void processPendingUpdates(); |
267 | |
268 | private: |
269 | void itemsAddedInDirectory(const QUrl &url); |
270 | |
271 | class DirItem; |
272 | DirItem *dirItemForUrl(const QUrl &dir) const; |
273 | |
274 | void stopListJob(const QUrl &url, bool silent); |
275 | |
276 | KIO::ListJob *jobForUrl(const QUrl &url, KIO::ListJob *not_job = nullptr); |
277 | const QUrl &joburl(KIO::ListJob *job); |
278 | |
279 | void killJob(KIO::ListJob *job); |
280 | |
281 | // Called when something tells us that the directory @p url has changed. |
282 | // Returns true if @p url is held by some lister (meaning: do the update now) |
283 | // otherwise mark the cached item as not-up-to-date for later and return false |
284 | bool checkUpdate(const QUrl &url); |
285 | |
286 | // Helper method for slotFileDirty |
287 | void handleFileDirty(const QUrl &url); |
288 | void handleDirDirty(const QUrl &url); |
289 | |
290 | // when there were items deleted from the filesystem all the listers holding |
291 | // the parent directory need to be notified, the items have to be deleted |
292 | // and removed from the cache including all the children. |
293 | void deleteUnmarkedItems(const QList<KCoreDirLister *> &, QList<KFileItem> &lstItems, const QHash<QString, KFileItem> &itemsToDelete); |
294 | |
295 | // Helper method called when we know that a list of items was deleted |
296 | void itemsDeleted(const QList<KCoreDirLister *> &listers, const KFileItemList &deletedItems); |
297 | void slotFilesRemoved(const QList<QUrl> &urls); |
298 | // common for slotRedirection and slotFileRenamed |
299 | void renameDir(const QUrl &oldUrl, const QUrl &url); |
300 | // common for deleteUnmarkedItems and slotFilesRemoved |
301 | void deleteDir(const QUrl &dirUrl); |
302 | // remove directory from cache (itemsCached), including all child dirs |
303 | void removeDirFromCache(const QUrl &dir); |
304 | // helper for renameDir |
305 | void emitRedirections(const QUrl &oldUrl, const QUrl &url); |
306 | |
307 | /** |
308 | * Emits refreshItem() in the directories that cared for oldItem. |
309 | * The caller has to remember to call emitItems in the set of dirlisters returned |
310 | * (but this allows to buffer change notifications) |
311 | */ |
312 | std::set<KCoreDirLister *> emitRefreshItem(const KFileItem &oldItem, const KFileItem &fileitem); |
313 | |
314 | /** |
315 | * Remove the item from the sorted by url list matching @p oldUrl, |
316 | * that is in the wrong place (because its url has changed) and insert @p item in the right place. |
317 | * @param oldUrl the previous url of the @p item |
318 | * @param item the modified item to be inserted |
319 | */ |
320 | void reinsert(const KFileItem &item, const QUrl &oldUrl) |
321 | { |
322 | const QUrl parentDir = oldUrl.adjusted(options: QUrl::RemoveFilename | QUrl::StripTrailingSlash); |
323 | DirItem *dirItem = dirItemForUrl(dir: parentDir); |
324 | if (dirItem) { |
325 | auto it = std::lower_bound(first: dirItem->lstItems.begin(), last: dirItem->lstItems.end(), val: oldUrl); |
326 | Q_ASSERT(it != dirItem->lstItems.end()); |
327 | dirItem->lstItems.erase(pos: it); |
328 | dirItem->insert(item); |
329 | } |
330 | } |
331 | |
332 | void remove(const QUrl &oldUrl) |
333 | { |
334 | const QUrl parentDir = oldUrl.adjusted(options: QUrl::RemoveFilename | QUrl::StripTrailingSlash); |
335 | DirItem *dirItem = dirItemForUrl(dir: parentDir); |
336 | if (dirItem) { |
337 | auto it = std::lower_bound(first: dirItem->lstItems.begin(), last: dirItem->lstItems.end(), val: oldUrl); |
338 | Q_ASSERT(it != dirItem->lstItems.end()); |
339 | dirItem->lstItems.erase(pos: it); |
340 | } |
341 | } |
342 | |
343 | /** |
344 | * When KDirWatch tells us that something changed in "dir", we need to |
345 | * also notify the dirlisters that are listing a symlink to "dir" (#213799) |
346 | */ |
347 | QList<QUrl> directoriesForCanonicalPath(const QUrl &dir) const; |
348 | |
349 | // Definition of the cache of ".hidden" files |
350 | struct CacheHiddenFile { |
351 | CacheHiddenFile(const QDateTime &mtime, std::set<QString> &&listedFilesParam) |
352 | : mtime(mtime) |
353 | , listedFiles(std::move(listedFilesParam)) |
354 | { |
355 | } |
356 | QDateTime mtime; |
357 | std::set<QString> listedFiles; |
358 | }; |
359 | |
360 | /** |
361 | * Returns the names listed in dir's ".hidden" file, if it exists. |
362 | * If a file named ".hidden" exists in the @p dir directory, this method |
363 | * returns all the file names listed in that file. If it doesn't exist, an |
364 | * empty set is returned. |
365 | * @param dir path to the target directory. |
366 | * @return names listed in the directory's ".hidden" file (empty if it doesn't exist). |
367 | */ |
368 | CacheHiddenFile *cachedDotHiddenForDir(const QString &dir); |
369 | |
370 | #ifndef NDEBUG |
371 | void printDebug(); |
372 | #endif |
373 | |
374 | class DirItem |
375 | { |
376 | public: |
377 | DirItem(const QUrl &dir, const QString &canonicalPath) |
378 | : url(dir) |
379 | , m_canonicalPath(canonicalPath) |
380 | { |
381 | autoUpdates = 0; |
382 | complete = false; |
383 | watchedWhileInCache = false; |
384 | } |
385 | |
386 | ~DirItem() |
387 | { |
388 | if (autoUpdates) { |
389 | if (KDirWatch::exists() && url.isLocalFile()) { |
390 | KDirWatch::self()->removeDir(path: m_canonicalPath); |
391 | } |
392 | // Since sendSignal goes through D-Bus, QCoreApplication has to be available |
393 | // which might not be the case anymore from a global static dtor like the |
394 | // lister cache |
395 | if (QCoreApplication::instance()) { |
396 | sendSignal(entering: false, url); |
397 | } |
398 | } |
399 | lstItems.clear(); |
400 | } |
401 | |
402 | DirItem(const DirItem &) = delete; |
403 | DirItem &operator=(const DirItem &) = delete; |
404 | |
405 | void sendSignal(bool entering, const QUrl &url) |
406 | { |
407 | // Note that "entering" means "start watching", and "leaving" means "stop watching" |
408 | // (i.e. it's not when the user leaves the directory, it's when the directory is removed from the cache) |
409 | #ifndef KIO_ANDROID_STUB |
410 | if (entering) { |
411 | org::kde::KDirNotify::emitEnteredDirectory(url); |
412 | } else { |
413 | org::kde::KDirNotify::emitLeftDirectory(url); |
414 | } |
415 | #endif |
416 | } |
417 | |
418 | void redirect(const QUrl &newUrl) |
419 | { |
420 | if (autoUpdates) { |
421 | if (url.isLocalFile()) { |
422 | KDirWatch::self()->removeDir(path: m_canonicalPath); |
423 | } |
424 | sendSignal(entering: false, url); |
425 | |
426 | if (newUrl.isLocalFile()) { |
427 | m_canonicalPath = QFileInfo(newUrl.toLocalFile()).canonicalFilePath(); |
428 | KDirWatch::self()->addDir(path: m_canonicalPath); |
429 | } |
430 | sendSignal(entering: true, url: newUrl); |
431 | } |
432 | |
433 | url = newUrl; |
434 | |
435 | if (!rootItem.isNull()) { |
436 | rootItem.setUrl(newUrl); |
437 | } |
438 | } |
439 | |
440 | void incAutoUpdate() |
441 | { |
442 | if (autoUpdates++ == 0) { |
443 | if (url.isLocalFile()) { |
444 | KDirWatch::self()->addDir(path: m_canonicalPath); |
445 | } |
446 | sendSignal(entering: true, url); |
447 | } |
448 | } |
449 | |
450 | void decAutoUpdate() |
451 | { |
452 | if (--autoUpdates == 0) { |
453 | if (url.isLocalFile()) { |
454 | KDirWatch::self()->removeDir(path: m_canonicalPath); |
455 | } |
456 | sendSignal(entering: false, url); |
457 | } |
458 | |
459 | else if (autoUpdates < 0) { |
460 | autoUpdates = 0; |
461 | } |
462 | } |
463 | |
464 | // Insert the item in the sorted list |
465 | void insert(const KFileItem &item) |
466 | { |
467 | auto it = std::lower_bound(first: lstItems.begin(), last: lstItems.end(), val: item.url()); |
468 | lstItems.insert(before: it, t: item); |
469 | } |
470 | |
471 | // Insert the already sorted items in the sorted list |
472 | void insertSortedItems(const KFileItemList &items) |
473 | { |
474 | if (items.isEmpty()) { |
475 | return; |
476 | } |
477 | lstItems.reserve(asize: lstItems.size() + items.size()); |
478 | auto it = lstItems.begin(); |
479 | for (const auto &item : items) { |
480 | it = std::lower_bound(first: it, last: lstItems.end(), val: item.url()); |
481 | it = lstItems.insert(before: it, t: item); |
482 | } |
483 | } |
484 | |
485 | // number of KCoreDirListers using autoUpdate for this dir |
486 | short autoUpdates; |
487 | |
488 | // this directory is up-to-date |
489 | bool complete; |
490 | |
491 | // the directory is watched while being in the cache (useful for proper incAutoUpdate/decAutoUpdate count) |
492 | bool watchedWhileInCache; |
493 | |
494 | // the complete url of this directory |
495 | QUrl url; |
496 | |
497 | // the local path, with symlinks resolved, so that KDirWatch works |
498 | QString m_canonicalPath; |
499 | |
500 | // KFileItem representing the root of this directory. |
501 | // Remember that this is optional. FTP sites don't return '.' in |
502 | // the list, so they give no root item |
503 | KFileItem rootItem; |
504 | QList<KFileItem> lstItems; |
505 | }; |
506 | |
507 | QMap<KIO::ListJob *, KIO::UDSEntryList> runningListJobs; |
508 | |
509 | // an item is a complete directory |
510 | QHash<QUrl, DirItem *> itemsInUse; |
511 | QCache<QUrl, DirItem> itemsCached; |
512 | |
513 | // cache of ".hidden" files |
514 | QCache<QString /*dot hidden file*/, CacheHiddenFile> m_cacheHiddenFiles; |
515 | |
516 | typedef QHash<QUrl, KCoreDirListerCacheDirectoryData> DirectoryDataHash; |
517 | DirectoryDataHash directoryData; |
518 | |
519 | // Symlink-to-directories are registered here so that we can |
520 | // find the url that changed, when kdirwatch tells us about |
521 | // changes in the canonical url. (#213799) |
522 | QHash<QUrl /*canonical path*/, QList<QUrl> /*dirlister urls*/> canonicalUrls; |
523 | |
524 | // Set of local files that we have changed recently (according to KDirWatch) |
525 | // We temporize the notifications by keeping them 500ms in this list. |
526 | std::set<QString /*path*/> pendingUpdates; |
527 | std::set<QString /*path*/> pendingDirectoryUpdates; |
528 | // The timer for doing the delayed updates |
529 | QTimer pendingUpdateTimer; |
530 | |
531 | // Set of remote files that have changed recently -- but we can't emit those |
532 | // changes yet, we need to wait for the "update" directory listing. |
533 | // The cmp() call can't differ MIME types since they are determined on demand, |
534 | // this is why we need to remember those files here. |
535 | std::set<KFileItem> pendingRemoteUpdates; |
536 | |
537 | // the KDirNotify signals |
538 | OrgKdeKDirNotifyInterface *kdirnotify; |
539 | |
540 | struct ItemInUseChange; |
541 | }; |
542 | |
543 | // Data associated with a directory url |
544 | // This could be in DirItem but only in the itemsInUse dict... |
545 | struct KCoreDirListerCacheDirectoryData { |
546 | // A lister can be EITHER in listersCurrentlyListing OR listersCurrentlyHolding |
547 | // but NOT in both at the same time. |
548 | // But both lists can have different listers at the same time; this |
549 | // happens if more listers are requesting url at the same time and |
550 | // one lister was stopped during the listing of files. |
551 | |
552 | // Listers that are currently listing this url |
553 | QList<KCoreDirLister *> listersCurrentlyListing; |
554 | // Listers that are currently holding this url |
555 | QList<KCoreDirLister *> listersCurrentlyHolding; |
556 | |
557 | void moveListersWithoutCachedItemsJob(const QUrl &url); |
558 | }; |
559 | |
560 | // This job tells KCoreDirListerCache to emit cached items asynchronously from listDir() |
561 | // to give the KCoreDirLister user enough time for connecting to its signals, and so |
562 | // that KCoreDirListerCache behaves just like when a real KIO::Job is used: nothing |
563 | // is emitted during the openUrl call itself. |
564 | class KCoreDirListerPrivate::CachedItemsJob : public KJob |
565 | { |
566 | Q_OBJECT |
567 | public: |
568 | CachedItemsJob(KCoreDirLister *lister, const QUrl &url, bool reload); |
569 | |
570 | /*reimp*/ void start() override |
571 | { |
572 | QMetaObject::invokeMethod(object: this, function: &KCoreDirListerPrivate::CachedItemsJob::done, type: Qt::QueuedConnection); |
573 | } |
574 | |
575 | // For updateDirectory() to cancel m_emitCompleted; |
576 | void setEmitCompleted(bool b) |
577 | { |
578 | m_emitCompleted = b; |
579 | } |
580 | |
581 | QUrl url() const |
582 | { |
583 | return m_url; |
584 | } |
585 | |
586 | protected: |
587 | bool doKill() override; |
588 | |
589 | public Q_SLOTS: |
590 | void done(); |
591 | |
592 | private: |
593 | KCoreDirLister *m_lister; |
594 | QUrl m_url; |
595 | bool m_reload; |
596 | bool m_emitCompleted; |
597 | }; |
598 | |
599 | #endif |
600 | |