File indexing completed on 2024-07-14 14:33:59

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KDIRMODEL_H
0009 #define KDIRMODEL_H
0010 
0011 #include "kiowidgets_export.h"
0012 #include <QAbstractItemModel>
0013 #include <kfileitem.h>
0014 
0015 #include <memory>
0016 
0017 class KDirLister;
0018 class KDirModelPrivate;
0019 class JobUrlCache;
0020 
0021 /**
0022  * @class KDirModel kdirmodel.h <KDirModel>
0023  *
0024  * @short A model for a KIO-based directory tree.
0025  *
0026  * KDirModel implements the QAbstractItemModel interface (for use with Qt's model/view widgets)
0027  * around the directory listing for one directory or a tree of directories.
0028  *
0029  * Note that there are some cases when using QPersistentModelIndexes from this model will not give
0030  * expected results. QPersistentIndexes will remain valid and updated if its siblings are added or
0031  * removed. However, if the QPersistentIndex or one of its ancestors is moved, the QPersistentIndex will become
0032  * invalid. For example, if a file or directory is renamed after storing a QPersistentModelIndex for it,
0033  * the index (along with any stored children) will become invalid even though it is still in the model. The reason
0034  * for this is that moves of files and directories are treated as separate insert and remove actions.
0035  *
0036  * @see KDirSortFilterProxyModel
0037  *
0038  * @author David Faure
0039  * Based on work by Hamish Rodda and Pascal Letourneau
0040  */
0041 class KIOWIDGETS_EXPORT KDirModel : public QAbstractItemModel
0042 {
0043     Q_OBJECT
0044 
0045 public:
0046     /**
0047      * @param parent parent qobject
0048      */
0049     explicit KDirModel(QObject *parent = nullptr);
0050     ~KDirModel() override;
0051 
0052     /**
0053      * Flags for the openUrl() method
0054      * @see OpenUrlFlags
0055      * @since 5.69
0056      */
0057     enum OpenUrlFlag {
0058         NoFlags = 0x0, ///< No additional flags specified.
0059         Reload = 0x1, ///< Indicates whether to use the cache or to reread
0060                       ///< the directory from the disk.
0061                       ///< Use only when opening a dir not yet listed by our dirLister()
0062                       ///< without using the cache. Otherwise use dirLister()->updateDirectory().
0063         ShowRoot = 0x2, ///< Display a root node for the URL being opened.
0064     };
0065     /**
0066      * Stores a combination of #OpenUrlFlag values.
0067      */
0068     Q_DECLARE_FLAGS(OpenUrlFlags, OpenUrlFlag)
0069     Q_FLAG(OpenUrlFlags)
0070 
0071     /**
0072      * Display the contents of @p url in the model.
0073      * Apart from the support for the ShowRoot flag, this is equivalent to dirLister()->openUrl(url, flags)
0074      * @param url   the URL of the directory whose contents should be listed.
0075      *              Unless ShowRoot is set, the item for this directory will NOT be shown, the model starts at its children.
0076      * @param flags see OpenUrlFlag
0077      * @since 5.69
0078      */
0079     Q_INVOKABLE void openUrl(const QUrl &url, OpenUrlFlags flags = NoFlags);
0080 
0081     /**
0082      * Set the directory lister to use by this model, instead of the default KDirLister created internally.
0083      * The model takes ownership.
0084      */
0085     void setDirLister(KDirLister *dirLister);
0086 
0087     /**
0088      * Return the directory lister used by this model.
0089      */
0090     KDirLister *dirLister() const;
0091 
0092     /**
0093      * Return the fileitem for a given index. This is O(1), i.e. fast.
0094      */
0095     KFileItem itemForIndex(const QModelIndex &index) const;
0096 
0097 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(4, 0)
0098     /**
0099      * Return the index for a given kfileitem. This can be slow.
0100      * @deprecated Since 4.0, use the method that takes a KFileItem by value
0101      */
0102     KIOWIDGETS_DEPRECATED_VERSION(4, 0, "Use KDirModel::indexForItem(const KFileItem &)")
0103     QModelIndex indexForItem(const KFileItem *) const;
0104 #endif
0105 
0106     /**
0107      * Return the index for a given kfileitem. This can be slow.
0108      */
0109     Q_INVOKABLE QModelIndex indexForItem(const KFileItem &) const;
0110 
0111     /**
0112      * Return the index for a given url. This can be slow.
0113      */
0114     Q_INVOKABLE QModelIndex indexForUrl(const QUrl &url) const;
0115 
0116     /**
0117      * @short Lists subdirectories using fetchMore() as needed until the given @p url exists in the model.
0118      *
0119      * When the model is used by a treeview, call KDirLister::openUrl with the base url of the tree,
0120      * then the treeview will take care of calling fetchMore() when the user opens directories.
0121      * However if you want the tree to show a given URL (i.e. open the tree recursively until that URL),
0122      * call expandToUrl().
0123      * Note that this is asynchronous; the necessary listing of subdirectories will take time so
0124      * the model will not immediately have this url available.
0125      * The model emits the signal expand() when an index has become available; this can be connected
0126      * to the treeview in order to let it open that index.
0127      * @param url the url of a subdirectory of the directory model (or a file in a subdirectory)
0128      */
0129     Q_INVOKABLE void expandToUrl(const QUrl &url);
0130 
0131     /**
0132      * Notify the model that the item at this index has changed.
0133      * For instance because KMimeTypeResolver called determineMimeType on it.
0134      * This makes the model emit its dataChanged signal at this index, so that views repaint.
0135      * Note that for most things (renaming, changing size etc.), KDirLister's signals tell the model already.
0136      */
0137     Q_INVOKABLE void itemChanged(const QModelIndex &index);
0138 
0139     /**
0140      * Forget all previews (optimization for turning previews off).
0141      * The items will again have their default appearance (not controlled by the model).
0142      * @since 5.28
0143      */
0144     Q_INVOKABLE void clearAllPreviews();
0145 
0146     /**
0147      * Useful "default" columns. Views can use a proxy to have more control over this.
0148      */
0149     enum ModelColumns {
0150         Name = 0,
0151         Size,
0152         ModifiedTime,
0153         Permissions,
0154         Owner,
0155         Group,
0156         Type,
0157         ColumnCount,
0158     };
0159 
0160     /// Possible return value for data(ChildCountRole), meaning the item isn't a directory,
0161     /// or we haven't calculated its child count yet
0162     enum { ChildCountUnknown = -1 };
0163 
0164     enum AdditionalRoles {
0165         // Note: use   printf "0x%08X\n" $(($RANDOM*$RANDOM))
0166         // to define additional roles.
0167         FileItemRole = 0x07A263FF, ///< returns the KFileItem for a given index. roleName is "fileItem".
0168         ChildCountRole = 0x2C4D0A40, ///< returns the number of items in a directory, or ChildCountUnknown. roleName is "childCount".
0169         HasJobRole = 0x01E555A5, ///< returns whether or not there is a job on an item (file/directory). roleName is "hasJob".
0170     };
0171 
0172     /**
0173      * @see DropsAllowed
0174      */
0175     enum DropsAllowedFlag {
0176         NoDrops = 0,
0177         DropOnDirectory = 1, ///< allow drops on any directory
0178         DropOnAnyFile = 2, ///< allow drops on any file
0179         DropOnLocalExecutable = 4, ///< allow drops on local executables, shell scripts and desktop files. Can be used with DropOnDirectory.
0180     };
0181     /**
0182      * Stores a combination of #DropsAllowedFlag values.
0183      */
0184     Q_DECLARE_FLAGS(DropsAllowed, DropsAllowedFlag)
0185     Q_FLAG(DropsAllowed)
0186 
0187     /// Set whether dropping onto items should be allowed, and for which kind of item
0188     /// Drops are disabled by default.
0189     Q_INVOKABLE void setDropsAllowed(DropsAllowed dropsAllowed);
0190 
0191     /// Reimplemented from QAbstractItemModel. Returns true for empty directories.
0192     bool canFetchMore(const QModelIndex &parent) const override;
0193     /// Reimplemented from QAbstractItemModel. Returns ColumnCount.
0194     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0195     /// Reimplemented from QAbstractItemModel.
0196     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0197     /// Reimplemented from QAbstractItemModel. Not implemented yet.
0198     bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
0199     /// Reimplemented from QAbstractItemModel. Lists the subdirectory.
0200     void fetchMore(const QModelIndex &parent) override;
0201     /// Reimplemented from QAbstractItemModel.
0202     Qt::ItemFlags flags(const QModelIndex &index) const override;
0203     /// Reimplemented from QAbstractItemModel. Returns true for directories.
0204     bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
0205     /// Reimplemented from QAbstractItemModel. Returns the column titles.
0206     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
0207     /// Reimplemented from QAbstractItemModel. O(1)
0208     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
0209     /// Reimplemented from QAbstractItemModel.
0210     QMimeData *mimeData(const QModelIndexList &indexes) const override;
0211     /// Reimplemented from QAbstractItemModel.
0212     QStringList mimeTypes() const override;
0213     /// Reimplemented from QAbstractItemModel.
0214     QModelIndex parent(const QModelIndex &index) const override;
0215     /// Reimplemented from QAbstractItemModel.
0216     QModelIndex sibling(int row, int column, const QModelIndex &index) const override;
0217     /// Reimplemented from QAbstractItemModel.
0218     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0219     /// Reimplemented from QAbstractItemModel.
0220     /// Call this to set a new icon, e.g. a preview
0221     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
0222     /// Reimplemented from QAbstractItemModel. Not implemented. @see KDirSortFilterProxyModel
0223     void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
0224     /// Reimplemented from QAbstractItemModel.
0225     /// @see AdditionalRoles
0226     QHash<int, QByteArray> roleNames() const override;
0227 
0228     /**
0229      * Remove urls from the list if an ancestor is present on the list. This can
0230      * be used to delete only the ancestor url and skip a potential error of a non-existent url.
0231      *
0232      * For example, for a list of "/home/foo/a", "/home/foo/a/a.txt", "/home/foo/a/a/a.txt", "/home/foo/a/b/b.txt",
0233      * "home/foo/b/b.txt", this method will return the list "/home/foo/a", "/home/foo/b/b.txt".
0234      *
0235      * @return the list @p urls without parented urls inside.
0236      * @since 4.2
0237      */
0238     static QList<QUrl> simplifiedUrlList(const QList<QUrl> &urls);
0239 
0240     /**
0241      * This emits the needSequenceIcon signal, requesting another sequence icon
0242      *
0243      * If there is a KFilePreviewGenerator attached to this model, that generator will care
0244      * about creating another preview.
0245      *
0246      * @param index Index of the item that should get another icon
0247      * @param sequenceIndex Index in the sequence. If it is zero, the standard icon will be assigned.
0248      *                                        For higher indices, arbitrary different meaningful icons will be generated.
0249      * @since 4.3
0250      */
0251     void requestSequenceIcon(const QModelIndex &index, int sequenceIndex);
0252 
0253     /**
0254      * Enable/Disable the displaying of an animated overlay that is shown for any destination
0255      * urls (in the view). When enabled, the animations (if any) will be drawn automatically.
0256      *
0257      * Only the files/folders that are visible and have jobs associated with them
0258      * will display the animation.
0259      * You would likely not want this enabled if you perform some kind of custom painting
0260      * that takes up a whole item, and will just make this(and what you paint) look funky.
0261      *
0262      * Default is disabled.
0263      *
0264      * Note: KFileItemDelegate needs to have it's method called with the same
0265      * value, when you make the call to this method.
0266      *
0267      * @since 4.5
0268      */
0269     void setJobTransfersVisible(bool show);
0270 
0271     /**
0272      * Returns whether or not displaying job transfers has been enabled.
0273      * @since 4.5
0274      */
0275     bool jobTransfersVisible() const;
0276 
0277     Qt::DropActions supportedDropActions() const override;
0278 
0279 Q_SIGNALS:
0280     /**
0281      * Emitted for each subdirectory that is a parent of a url passed to expandToUrl
0282      * This allows to asynchronously open a tree view down to a given directory.
0283      * Also emitted for the final file, if expandToUrl is called with a file
0284      * (for instance so that it can be selected).
0285      */
0286     void expand(const QModelIndex &index);
0287     /**
0288      * Emitted when another icon sequence index is requested
0289      * @param index Index of the item that should get another icon
0290      * @param sequenceIndex Index in the sequence. If it is zero, the standard icon should be assigned.
0291      *                                        For higher indices, arbitrary different meaningful icons should be generated.
0292      *                                        This is usually slowly counted up while the user hovers the icon.
0293      *                                        If no meaningful alternative icons can be generated, this should be ignored.
0294      * @since 4.3
0295      */
0296     void needSequenceIcon(const QModelIndex &index, int sequenceIndex);
0297 
0298 private:
0299     // Make those private, they shouldn't be called by applications
0300     bool insertRows(int, int, const QModelIndex & = QModelIndex()) override;
0301     bool insertColumns(int, int, const QModelIndex & = QModelIndex()) override;
0302     bool removeRows(int, int, const QModelIndex & = QModelIndex()) override;
0303     bool removeColumns(int, int, const QModelIndex & = QModelIndex()) override;
0304 
0305 private:
0306     friend class KDirModelPrivate;
0307     std::unique_ptr<KDirModelPrivate> const d;
0308 };
0309 
0310 Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::DropsAllowed)
0311 Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::OpenUrlFlags)
0312 
0313 #endif /* KDIRMODEL_H */