File indexing completed on 2024-04-21 03:55:06

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
0004     SPDX-FileCopyrightText: 2001, 2002, 2004-2006 Michael Brade <brade@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KCOREDIRLISTER_H
0010 #define KCOREDIRLISTER_H
0011 
0012 #include "kfileitem.h"
0013 
0014 #include <QString>
0015 #include <QStringList>
0016 #include <QUrl>
0017 
0018 #include <memory>
0019 
0020 class KJob;
0021 namespace KIO
0022 {
0023 class Job;
0024 class ListJob;
0025 }
0026 
0027 class KCoreDirListerPrivate;
0028 
0029 /**
0030  * @class KCoreDirLister kcoredirlister.h <KCoreDirLister>
0031  *
0032  * @short Helper class for the kiojob used to list and update a directory.
0033  *
0034  * The dir lister deals with the kiojob used to list and update a directory
0035  * and has signals for the user of this class (e.g. konqueror view or
0036  * kdesktop) to create/destroy its items when asked.
0037  *
0038  * This class is independent from the graphical representation of the dir
0039  * (icon container, tree view, ...) and it stores the items (as KFileItems).
0040  *
0041  * Typical usage :
0042  * @li Create an instance.
0043  * @li Connect to at least update, clear, itemsAdded, and itemsDeleted.
0044  * @li Call openUrl - the signals will be called.
0045  * @li Reuse the instance when opening a new url (openUrl).
0046  * @li Destroy the instance when not needed anymore (usually destructor).
0047  *
0048  * Advanced usage : call openUrl with OpenUrlFlag::Keep to list directories
0049  * without forgetting the ones previously read (e.g. for a tree view)
0050  *
0051  * @author Michael Brade <brade@kde.org>
0052  */
0053 class KIOCORE_EXPORT KCoreDirLister : public QObject
0054 {
0055     friend class KCoreDirListerCache;
0056     friend struct KCoreDirListerCacheDirectoryData;
0057 
0058     Q_OBJECT
0059     Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate)
0060     Q_PROPERTY(bool showHiddenFiles READ showHiddenFiles WRITE setShowHiddenFiles)
0061     Q_PROPERTY(bool dirOnlyMode READ dirOnlyMode WRITE setDirOnlyMode)
0062     Q_PROPERTY(bool delayedMimeTypes READ delayedMimeTypes WRITE setDelayedMimeTypes)
0063     Q_PROPERTY(bool requestMimeTypeWhileListing READ requestMimeTypeWhileListing WRITE setRequestMimeTypeWhileListing)
0064     Q_PROPERTY(QString nameFilter READ nameFilter WRITE setNameFilter)
0065     Q_PROPERTY(QStringList mimeFilter READ mimeFilters WRITE setMimeFilter RESET clearMimeFilter)
0066     Q_PROPERTY(bool autoErrorHandlingEnabled READ autoErrorHandlingEnabled WRITE setAutoErrorHandlingEnabled)
0067 
0068 public:
0069     /**
0070      * @see OpenUrlFlags
0071      */
0072     enum OpenUrlFlag {
0073         NoFlags = 0x0, ///< No additional flags specified.
0074 
0075         Keep = 0x1, ///< Previous directories aren't forgotten
0076         ///< (they are still watched by kdirwatch and their items
0077         ///< are kept for this KCoreDirLister). This is useful for e.g.
0078         ///< a treeview.
0079 
0080         Reload = 0x2, ///< Indicates whether to use the cache or to reread
0081                       ///< the directory from the disk.
0082                       ///< Use only when opening a dir not yet listed by this lister
0083                       ///< without using the cache. Otherwise use updateDirectory.
0084     };
0085 
0086     /**
0087      * Stores a combination of #OpenUrlFlag values.
0088      */
0089     Q_DECLARE_FLAGS(OpenUrlFlags, OpenUrlFlag)
0090 
0091     /**
0092      * Create a directory lister.
0093      */
0094     KCoreDirLister(QObject *parent = nullptr);
0095 
0096     /**
0097      * Destroy the directory lister.
0098      */
0099     ~KCoreDirLister() override;
0100 
0101     /**
0102      * Run the directory lister on the given url.
0103      *
0104      * This method causes KCoreDirLister to emit @em all the items of @p dirUrl, in any case.
0105      * Depending on @p flags, either clear() or clearDir(const QUrl &) will be emitted first.
0106      *
0107      * The newItems() signal may be emitted more than once to supply you with KFileItems, up
0108      * until the signal completed() is emitted (and isFinished() returns @c true).
0109      *
0110      * @param dirUrl the directory URL.
0111      * @param flags whether to keep previous directories, and whether to reload, see OpenUrlFlags
0112      * @return @c true if successful, @c false otherwise (e.g. if @p dirUrl is invalid)
0113      */
0114     bool openUrl(const QUrl &dirUrl, OpenUrlFlags flags = NoFlags); // TODO KF6: change bool to void
0115 
0116     /**
0117      * Stop listing all directories currently being listed.
0118      *
0119      * Emits canceled() if there was at least one job running.
0120      * Emits listingDirCanceled(const QUrl &) for each stopped job if there is more than one
0121      * directory being watched by this KCoreDirLister.
0122      */
0123     void stop();
0124 
0125     /**
0126      * Stop listing the given directory.
0127      *
0128      * Emits canceled() if the killed job was the last running one.
0129      * Emits listingDirCanceled(const QUrl &) for the killed job if there is more than one
0130      * directory being watched by this KCoreDirLister.
0131      *
0132      * No signal is emitted if there was no job running for @p dirUrl.
0133      *
0134      * @param dirUrl the directory URL
0135      */
0136     void stop(const QUrl &dirUrl);
0137 
0138     /**
0139      * Stop listening for further changes in the given directory.
0140      * When a new directory is opened with OpenUrlFlag::Keep the caller will keep being notified of file changes for all directories that were kept open.
0141      * This call selectively removes a directory from sending future notifications to this KCoreDirLister.
0142      *
0143      * @param dirUrl the directory URL.
0144      * @since 5.91
0145      */
0146     void forgetDirs(const QUrl &dirUrl);
0147 
0148     /**
0149      * @return @c true if the "delayed MIME types" feature was enabled
0150      * @see setDelayedMimeTypes
0151      */
0152     bool delayedMimeTypes() const;
0153 
0154     /**
0155      * Delayed MIME types feature:
0156      * If enabled, MIME types will be fetched on demand, which leads to a
0157      * faster initial directory listing, where icons get progressively replaced
0158      * with the correct one while KMimeTypeResolver is going through the items
0159      * with unknown or imprecise MIME type (e.g. files with no extension or an
0160      * unknown extension).
0161      */
0162     void setDelayedMimeTypes(bool delayedMimeTypes);
0163 
0164     /**
0165      * Checks whether KDirWatch will automatically update directories. This is
0166      * enabled by default.
0167      *
0168      * @return @c true if KDirWatch is used to automatically update directories
0169      */
0170     bool autoUpdate() const;
0171 
0172     /**
0173      * Toggle automatic directory updating, when a directory changes (using KDirWatch).
0174      *
0175      * @param enable set to @c true to enable or @c false to disable
0176      */
0177     void setAutoUpdate(bool enable);
0178 
0179     /**
0180      * Checks whether hidden files (e.g. files whose name start with '.' on Unix) will be shown.
0181      * By default this option is disabled (hidden files are not shown).
0182      *
0183      * @return @c true if hidden files are shown, @c false otherwise
0184      *
0185      * @see setShowHiddenFiles()
0186      * @since 5.100
0187      */
0188     bool showHiddenFiles() const;
0189 
0190     /**
0191      * Toggles whether hidden files (e.g. files whose name start with '.' on Unix) are shown/
0192      * By default hidden files are not shown.
0193      *
0194      * You need to call emitChanges() afterwards.
0195      *
0196      * @param showHiddenFiles set to @c true/false to show/hide hidden files respectively
0197      *
0198      * @see showHiddenFiles()
0199      * @since 5.100
0200      */
0201     void setShowHiddenFiles(bool showHiddenFiles);
0202 
0203     /**
0204      * Checks whether this KCoreDirLister only lists directories or all items (directories and
0205      * files), by default all items are listed.
0206      *
0207      * @return @c true if only directories are listed, @c false otherwise
0208      *
0209      * @see setDirOnlyMode(bool)
0210      */
0211     bool dirOnlyMode() const;
0212 
0213     /**
0214      * Call this to list only directories (by default all items (directories and files)
0215      * are listed).
0216      *
0217      * You need to call emitChanges() afterwards.
0218      *
0219      * @param dirsOnly set to @c true to list only directories
0220      */
0221     void setDirOnlyMode(bool dirsOnly);
0222 
0223     /**
0224      * Checks whether this KCoreDirLister requests the MIME type of files from the worker.
0225      *
0226      * Enabling this will tell the worker used for listing that it should try to
0227      * determine the mime type of entries while listing them. This potentially
0228      * reduces the speed at which entries are listed but ensures mime types are
0229      * immediately available when an entry is added, greatly speeding up things
0230      * like mime type filtering.
0231      *
0232      * By default this is disabled.
0233      *
0234      * @return @c true if the worker is asked for MIME types, @c false otherwise.
0235      *
0236      * @see setRequestMimeTypeWhileListing(bool)
0237      *
0238      * @since 5.82
0239      */
0240     bool requestMimeTypeWhileListing() const;
0241 
0242     /**
0243      * Toggles whether to request MIME types from the worker or in-process.
0244      *
0245      * @param request set to @c true to request MIME types from the worker.
0246      *
0247      * @note If this is changed while the lister is already listing a directory,
0248      * it will only have an effect the next time openUrl() is called.
0249      *
0250      * @see requestMimeTypeWhileListing()
0251      *
0252      * @since 5.82
0253      */
0254     void setRequestMimeTypeWhileListing(bool request);
0255 
0256     /**
0257      * Returns the top level URL that is listed by this KCoreDirLister.
0258      *
0259      * It might be different from the one given with openUrl() if there was a
0260      * redirection. If you called openUrl() with OpenUrlFlag::Keep this is the
0261      * first url opened (e.g. in a treeview this is the root).
0262      *
0263      * @return the url used by this instance to list the files
0264      */
0265     QUrl url() const;
0266 
0267     /**
0268      * Returns all URLs that are listed by this KCoreDirLister. This is only
0269      * useful if you called openUrl() with OpenUrlFlag::Keep, as it happens in a
0270      * treeview, for example. (Note that the base url is included in the list
0271      * as well, of course.)
0272      *
0273      * @return a list of all listed URLs
0274      */
0275     QList<QUrl> directories() const;
0276 
0277     /**
0278      * Actually emit the changes made with setShowHiddenFiles, setDirOnlyMode,
0279      * setNameFilter and setMimeFilter.
0280      */
0281     void emitChanges();
0282 
0283     /**
0284      * Update the directory @p dirUrl. This method causes KCoreDirLister to @em only emit
0285      * the items of @p dirUrl that actually changed compared to the current state in the
0286      * cache, and updates the cache.
0287      *
0288      * The current implementation calls updateDirectory automatically for local files, using
0289      * KDirWatch (if autoUpdate() is @c true), but it might be useful to force an update manually.
0290      *
0291      * @param dirUrl the directory URL
0292      */
0293     void updateDirectory(const QUrl &dirUrl);
0294 
0295     /**
0296      * Returns @c true if no I/O operation is currently in progress.
0297      *
0298      * @return @c true if finished, @c false otherwise
0299      */
0300     bool isFinished() const;
0301 
0302     /**
0303      * Returns the file item of the URL.
0304      *
0305      * Can return an empty KFileItem.
0306      * @return the file item for url() itself (".")
0307      */
0308     KFileItem rootItem() const;
0309 
0310     /**
0311      * Find an item by its URL.
0312      * @param url the item URL
0313      * @return the KFileItem
0314      */
0315     KFileItem findByUrl(const QUrl &url) const;
0316 
0317     /**
0318      * Find an item by its name.
0319      * @param name the item name
0320      * @return the KFileItem
0321      */
0322     KFileItem findByName(const QString &name) const;
0323 
0324     /**
0325      * Set a name filter to only list items matching this name, e.g.\ "*.cpp".
0326      *
0327      * You can set more than one filter by separating them with whitespace, e.g
0328      * "*.cpp *.h".
0329      * Note: the directory is not automatically reloaded.
0330      * You need to call emitChanges() afterwards.
0331      *
0332      * @param filter the new filter, QString() to disable filtering
0333      * @see matchesFilter
0334      */
0335     void setNameFilter(const QString &filter);
0336 
0337     /**
0338      * Returns the current name filter, as set via setNameFilter()
0339      * @return the current name filter, can be QString() if filtering
0340      *         is turned off
0341      */
0342     QString nameFilter() const;
0343 
0344     /**
0345      * Set MIME type based filter to only list items matching the given MIME types.
0346      *
0347      * NOTE: setting the filter does not automatically reload directory.
0348      * Also calling this function will not affect any named filter already set.
0349      *
0350      * You need to call emitChanges() afterwards.
0351      *
0352      * @param mimeList a list of MIME types
0353      *
0354      * @see clearMimeFilter
0355      * @see matchesMimeFilter
0356      */
0357     void setMimeFilter(const QStringList &mimeList);
0358 
0359     /**
0360      * Filtering should be done with KFileFilter. This will be implemented in a later
0361      * revision of KCoreDirLister. This method may be removed then.
0362      *
0363      * Set MIME type based exclude filter to only list items not matching the given MIME types
0364      *
0365      * NOTE: setting the filter does not automatically reload directory.
0366      * Also calling this function will not affect any named filter already set.
0367      *
0368      * @param mimeList a list of MIME types
0369      * @see clearMimeFilter
0370      * @see matchesMimeFilter
0371      */
0372     void setMimeExcludeFilter(const QStringList &mimeList);
0373 
0374     /**
0375      * Clears the MIME type based filter.
0376      *
0377      * You need to call emitChanges() afterwards.
0378      *
0379      * @see setMimeFilter
0380      */
0381     void clearMimeFilter();
0382 
0383     /**
0384      * Returns the list of MIME type based filters, as set via setMimeFilter().
0385      * @return the list of MIME type based filters. Empty, when no MIME type filter is set.
0386      */
0387     QStringList mimeFilters() const;
0388 
0389     /**
0390      * Used by items() and itemsForDir() to specify whether you want
0391      * all items for a directory or just the filtered ones.
0392      */
0393     enum WhichItems {
0394         AllItems = 0,
0395         FilteredItems = 1,
0396     };
0397 
0398     /**
0399      * Returns the items listed for the current url().
0400      *
0401      * This method will @em not start listing a directory, you should only call
0402      * this in a slot connected to the finished() signal.
0403      *
0404      * The items in the KFileItemList are copies of the items used by KCoreDirLister.
0405      *
0406      * @param which specifies whether the returned list will contain all entries
0407      *              or only the ones that passed the nameFilter(), mimeFilter(),
0408      *              etc. Note that the latter causes iteration over all the
0409      *              items, filtering them. If this is too slow for you, use the
0410      *              newItems() signal, sending out filtered items in chunks
0411      * @return the items listed for the current url()
0412      */
0413     KFileItemList items(WhichItems which = FilteredItems) const;
0414 
0415     /**
0416      * Returns the items listed for the given @p dirUrl.
0417      * This method will @em not start listing @p dirUrl, you should only call
0418      * this in a slot connected to the finished() signal.
0419      *
0420      * The items in the KFileItemList are copies of the items used by KCoreDirLister.
0421      *
0422      * @param dirUrl specifies the url for which the items should be returned. This
0423      *            is only useful if you use KCoreDirLister with multiple URLs
0424      *            i.e. using bool OpenUrlFlag::Keep in openUrl()
0425      * @param which specifies whether the returned list will contain all entries
0426      *              or only the ones that passed the nameFilter, mimeFilter, etc.
0427      *              Note that the latter causes iteration over all the items,
0428      *              filtering them. If this is too slow for you, use the
0429      * newItems() signal, sending out filtered items in chunks
0430      *
0431      * @return the items listed for @p dirUrl
0432      */
0433     KFileItemList itemsForDir(const QUrl &dirUrl, WhichItems which = FilteredItems) const;
0434 
0435     /**
0436      * Return the KFileItem for the given URL, if it was listed recently and it's
0437      * still in the cache, which is always the case if a directory view is currently
0438      * showing this item. If not, then it might be in the cache; if not in the cache a
0439      * a null KFileItem will be returned.
0440      *
0441      * If you really need a KFileItem for this URL in all cases, then use KIO::stat() instead.
0442      *
0443      */
0444     static KFileItem cachedItemForUrl(const QUrl &url);
0445 
0446     /**
0447      * Checks whether auto error handling is enabled.
0448      * If enabled, it will show an error dialog to the user when an
0449      * error occurs (assuming the application links to KIOWidgets).
0450      * It is turned on by default.
0451      * @return @c true if auto error handling is enabled, @c false otherwise
0452      * @see setAutoErrorHandlingEnabled()
0453      * @since 5.82
0454      */
0455     bool autoErrorHandlingEnabled() const;
0456 
0457     /**
0458      * Enable or disable auto error handling.
0459      * If enabled, it will show an error dialog to the user when an
0460      * error occurs. It is turned on by default.
0461      * @param enable true to enable auto error handling, false to disable
0462      * @param parent the parent widget for the error dialogs, can be @c nullptr for
0463      *               top-level
0464      * @see autoErrorHandlingEnabled()
0465      * @since 5.82
0466      */
0467     void setAutoErrorHandlingEnabled(bool enable);
0468 
0469 Q_SIGNALS:
0470     /**
0471      * Tell the view that this KCoreDirLister has started to list @p dirUrl. Note that this
0472      * does @em not imply that there is really a job running! I.e. KCoreDirLister::jobs()
0473      * may return an empty list, in which case the items are taken from the cache.
0474      *
0475      * The view knows that openUrl should start it, so this might seem useless, but the view
0476      * also needs to know when an automatic update happens.
0477      * @param dirUrl the URL to list
0478      */
0479     void started(const QUrl &dirUrl);
0480 
0481     /**
0482      * Tell the view that listing is finished. There are no jobs running anymore.
0483      */
0484     void completed();
0485 
0486     /**
0487      * Tell the view that the listing of the directory @p dirUrl is finished.
0488      * There might be other running jobs left.
0489      *
0490      * @param dirUrl the directory URL
0491      *
0492      * @since 5.79
0493      */
0494     void listingDirCompleted(const QUrl &dirUrl);
0495 
0496     /**
0497      * Tell the view that the user canceled the listing. No running jobs are left.
0498      */
0499     void canceled();
0500 
0501     /**
0502      * Tell the view that the listing of the directory @p dirUrl was canceled.
0503      * There might be other running jobs left.
0504      *
0505      * @param dirUrl the directory URL
0506      *
0507      * @since 5.79
0508      */
0509     void listingDirCanceled(const QUrl &dirUrl);
0510 
0511     /**
0512      * Signals a redirection.
0513      *
0514      * @param oldUrl the original URL
0515      * @param newUrl the new URL
0516      */
0517     void redirection(const QUrl &oldUrl, const QUrl &newUrl);
0518 
0519     /**
0520      * Signals to the view to remove all items (when e.g.\ going from dirA to dirB).
0521      * Make sure to connect to this signal to avoid having duplicate items in the view.
0522      */
0523     void clear();
0524 
0525     /**
0526      * Signals to the view to clear all items from directory @p dirUrl.
0527      *
0528      * This is only emitted if the lister is holding more than one directory.
0529      *
0530      * @param dirUrl the directory that the view should clear all items from
0531      *
0532      * @since 5.79
0533      */
0534     void clearDir(const QUrl &dirUrl);
0535 
0536     /**
0537      * Signal new items.
0538      *
0539      * @param items a list of new items
0540      */
0541     void newItems(const KFileItemList &items);
0542 
0543     /**
0544      * Signal that new items were found during directory listing.
0545      * Alternative signal emitted at the same time as newItems(),
0546      * but itemsAdded also passes the url of the parent directory.
0547      *
0548      * @param items a list of new items
0549      */
0550     void itemsAdded(const QUrl &directoryUrl, const KFileItemList &items);
0551 
0552     /**
0553      * Send a list of items filtered-out by MIME type.
0554      * @param items the list of filtered items
0555      *
0556      */
0557     void itemsFilteredByMime(const KFileItemList &items);
0558 
0559     /**
0560      * Signal that items have been deleted
0561      *
0562      * @since 4.1.2
0563      * @param items the list of deleted items
0564      */
0565     void itemsDeleted(const KFileItemList &items);
0566 
0567     /**
0568      * Signal an item to refresh (its MIME-type/icon/name has changed).
0569      * Note: KFileItem::refresh has already been called on those items.
0570      * @param items the items to refresh. This is a list of pairs, where
0571      * the first item in the pair is the OLD item, and the second item is the
0572      * NEW item. This allows to track which item has changed, especially after
0573      * a renaming.
0574      */
0575     void refreshItems(const QList<QPair<KFileItem, KFileItem>> &items);
0576 
0577     /**
0578      * Emitted to display information about running jobs.
0579      * Examples of message are "Resolving host", "Connecting to host...", etc.
0580      * @param msg the info message
0581      */
0582     void infoMessage(const QString &msg);
0583 
0584     /**
0585      * Progress signal showing the overall progress of the KCoreDirLister.
0586      * This allows using a progress bar very easily. (see QProgressBar)
0587      * @param percent the progress in percent
0588      */
0589     void percent(int percent);
0590 
0591     /**
0592      * Emitted when we know the size of the jobs.
0593      * @param size the total size in bytes
0594      */
0595     void totalSize(KIO::filesize_t size);
0596 
0597     /**
0598      * Regularly emitted to show the progress of this KCoreDirLister.
0599      * @param size the processed size in bytes
0600      */
0601     void processedSize(KIO::filesize_t size);
0602 
0603     /**
0604      * Emitted to display information about the speed of the jobs.
0605      * @param bytes_per_second the speed in bytes/s
0606      */
0607     void speed(int bytes_per_second);
0608 
0609     /**
0610      * Emitted if listing a directory fails with an error.
0611      * A typical implementation in a widgets-based application
0612      * would show a message box by calling this in a slot connected to this signal:
0613      * <tt>job->uiDelegate()->showErrorMessage()</tt>
0614      * Many applications might prefer to embed the error message though
0615      * (e.g. by using the KMessageWidget class, from the KWidgetsAddons Framework).
0616      * @param the job with an error
0617      * @since 5.82
0618      */
0619     void jobError(KIO::Job *job);
0620 
0621 protected:
0622     /**
0623      * Reimplemented by KDirLister to associate windows with jobs
0624      * @since 5.0
0625      */
0626     virtual void jobStarted(KIO::ListJob *);
0627 
0628 private:
0629     friend class KCoreDirListerPrivate;
0630     std::unique_ptr<KCoreDirListerPrivate> d;
0631 };
0632 
0633 Q_DECLARE_OPERATORS_FOR_FLAGS(KCoreDirLister::OpenUrlFlags)
0634 
0635 #endif