File indexing completed on 2024-12-08 06:40:29
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 /** 0098 * Return the index for a given kfileitem. This can be slow. 0099 */ 0100 Q_INVOKABLE QModelIndex indexForItem(const KFileItem &) const; 0101 0102 /** 0103 * Return the index for a given url. This can be slow. 0104 */ 0105 Q_INVOKABLE QModelIndex indexForUrl(const QUrl &url) const; 0106 0107 /** 0108 * @short Lists subdirectories using fetchMore() as needed until the given @p url exists in the model. 0109 * 0110 * When the model is used by a treeview, call KDirLister::openUrl with the base url of the tree, 0111 * then the treeview will take care of calling fetchMore() when the user opens directories. 0112 * However if you want the tree to show a given URL (i.e. open the tree recursively until that URL), 0113 * call expandToUrl(). 0114 * Note that this is asynchronous; the necessary listing of subdirectories will take time so 0115 * the model will not immediately have this url available. 0116 * The model emits the signal expand() when an index has become available; this can be connected 0117 * to the treeview in order to let it open that index. 0118 * @param url the url of a subdirectory of the directory model (or a file in a subdirectory) 0119 */ 0120 Q_INVOKABLE void expandToUrl(const QUrl &url); 0121 0122 /** 0123 * Notify the model that the item at this index has changed. 0124 * For instance because KMimeTypeResolver called determineMimeType on it. 0125 * This makes the model emit its dataChanged signal at this index, so that views repaint. 0126 * Note that for most things (renaming, changing size etc.), KDirLister's signals tell the model already. 0127 */ 0128 Q_INVOKABLE void itemChanged(const QModelIndex &index); 0129 0130 /** 0131 * Forget all previews (optimization for turning previews off). 0132 * The items will again have their default appearance (not controlled by the model). 0133 * @since 5.28 0134 */ 0135 Q_INVOKABLE void clearAllPreviews(); 0136 0137 /** 0138 * Useful "default" columns. Views can use a proxy to have more control over this. 0139 */ 0140 enum ModelColumns { 0141 Name = 0, 0142 Size, 0143 ModifiedTime, 0144 Permissions, 0145 Owner, 0146 Group, 0147 Type, 0148 ColumnCount, 0149 }; 0150 0151 /// Possible return value for data(ChildCountRole), meaning the item isn't a directory, 0152 /// or we haven't calculated its child count yet 0153 enum { ChildCountUnknown = -1 }; 0154 0155 enum AdditionalRoles { 0156 // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM)) 0157 // to define additional roles. 0158 FileItemRole = 0x07A263FF, ///< returns the KFileItem for a given index. roleName is "fileItem". 0159 ChildCountRole = 0x2C4D0A40, ///< returns the number of items in a directory, or ChildCountUnknown. roleName is "childCount". 0160 HasJobRole = 0x01E555A5, ///< returns whether or not there is a job on an item (file/directory). roleName is "hasJob". 0161 }; 0162 0163 /** 0164 * @see DropsAllowed 0165 */ 0166 enum DropsAllowedFlag { 0167 NoDrops = 0, 0168 DropOnDirectory = 1, ///< allow drops on any directory 0169 DropOnAnyFile = 2, ///< allow drops on any file 0170 DropOnLocalExecutable = 4, ///< allow drops on local executables, shell scripts and desktop files. Can be used with DropOnDirectory. 0171 }; 0172 /** 0173 * Stores a combination of #DropsAllowedFlag values. 0174 */ 0175 Q_DECLARE_FLAGS(DropsAllowed, DropsAllowedFlag) 0176 Q_FLAG(DropsAllowed) 0177 0178 /// Set whether dropping onto items should be allowed, and for which kind of item 0179 /// Drops are disabled by default. 0180 Q_INVOKABLE void setDropsAllowed(DropsAllowed dropsAllowed); 0181 0182 /// Reimplemented from QAbstractItemModel. Returns true for empty directories. 0183 bool canFetchMore(const QModelIndex &parent) const override; 0184 /// Reimplemented from QAbstractItemModel. Returns ColumnCount. 0185 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 0186 /// Reimplemented from QAbstractItemModel. 0187 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0188 /// Reimplemented from QAbstractItemModel. Not implemented yet. 0189 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; 0190 /// Reimplemented from QAbstractItemModel. Lists the subdirectory. 0191 void fetchMore(const QModelIndex &parent) override; 0192 /// Reimplemented from QAbstractItemModel. 0193 Qt::ItemFlags flags(const QModelIndex &index) const override; 0194 /// Reimplemented from QAbstractItemModel. Returns true for directories. 0195 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; 0196 /// Reimplemented from QAbstractItemModel. Returns the column titles. 0197 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 0198 /// Reimplemented from QAbstractItemModel. O(1) 0199 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 0200 /// Reimplemented from QAbstractItemModel. 0201 QMimeData *mimeData(const QModelIndexList &indexes) const override; 0202 /// Reimplemented from QAbstractItemModel. 0203 QStringList mimeTypes() const override; 0204 /// Reimplemented from QAbstractItemModel. 0205 QModelIndex parent(const QModelIndex &index) const override; 0206 /// Reimplemented from QAbstractItemModel. 0207 QModelIndex sibling(int row, int column, const QModelIndex &index) const override; 0208 /// Reimplemented from QAbstractItemModel. 0209 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0210 /// Reimplemented from QAbstractItemModel. 0211 /// Call this to set a new icon, e.g. a preview 0212 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 0213 /// Reimplemented from QAbstractItemModel. Not implemented. @see KDirSortFilterProxyModel 0214 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; 0215 /// Reimplemented from QAbstractItemModel. 0216 /// @see AdditionalRoles 0217 QHash<int, QByteArray> roleNames() const override; 0218 0219 /** 0220 * Remove urls from the list if an ancestor is present on the list. This can 0221 * be used to delete only the ancestor url and skip a potential error of a non-existent url. 0222 * 0223 * 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", 0224 * "home/foo/b/b.txt", this method will return the list "/home/foo/a", "/home/foo/b/b.txt". 0225 * 0226 * @return the list @p urls without parented urls inside. 0227 */ 0228 static QList<QUrl> simplifiedUrlList(const QList<QUrl> &urls); 0229 0230 /** 0231 * This emits the needSequenceIcon signal, requesting another sequence icon 0232 * 0233 * If there is a KFilePreviewGenerator attached to this model, that generator will care 0234 * about creating another preview. 0235 * 0236 * @param index Index of the item that should get another icon 0237 * @param sequenceIndex Index in the sequence. If it is zero, the standard icon will be assigned. 0238 * For higher indices, arbitrary different meaningful icons will be generated. 0239 */ 0240 void requestSequenceIcon(const QModelIndex &index, int sequenceIndex); 0241 0242 /** 0243 * Enable/Disable the displaying of an animated overlay that is shown for any destination 0244 * urls (in the view). When enabled, the animations (if any) will be drawn automatically. 0245 * 0246 * Only the files/folders that are visible and have jobs associated with them 0247 * will display the animation. 0248 * You would likely not want this enabled if you perform some kind of custom painting 0249 * that takes up a whole item, and will just make this(and what you paint) look funky. 0250 * 0251 * Default is disabled. 0252 * 0253 * Note: KFileItemDelegate needs to have it's method called with the same 0254 * value, when you make the call to this method. 0255 */ 0256 void setJobTransfersVisible(bool show); 0257 0258 /** 0259 * Returns whether or not displaying job transfers has been enabled. 0260 */ 0261 bool jobTransfersVisible() const; 0262 0263 Qt::DropActions supportedDropActions() const override; 0264 0265 Q_SIGNALS: 0266 /** 0267 * Emitted for each subdirectory that is a parent of a url passed to expandToUrl 0268 * This allows to asynchronously open a tree view down to a given directory. 0269 * Also emitted for the final file, if expandToUrl is called with a file 0270 * (for instance so that it can be selected). 0271 */ 0272 void expand(const QModelIndex &index); 0273 /** 0274 * Emitted when another icon sequence index is requested 0275 * @param index Index of the item that should get another icon 0276 * @param sequenceIndex Index in the sequence. If it is zero, the standard icon should be assigned. 0277 * For higher indices, arbitrary different meaningful icons should be generated. 0278 * This is usually slowly counted up while the user hovers the icon. 0279 * If no meaningful alternative icons can be generated, this should be ignored. 0280 */ 0281 void needSequenceIcon(const QModelIndex &index, int sequenceIndex); 0282 0283 private: 0284 // Make those private, they shouldn't be called by applications 0285 bool insertRows(int, int, const QModelIndex & = QModelIndex()) override; 0286 bool insertColumns(int, int, const QModelIndex & = QModelIndex()) override; 0287 bool removeRows(int, int, const QModelIndex & = QModelIndex()) override; 0288 bool removeColumns(int, int, const QModelIndex & = QModelIndex()) override; 0289 0290 private: 0291 friend class KDirModelPrivate; 0292 std::unique_ptr<KDirModelPrivate> const d; 0293 }; 0294 0295 Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::DropsAllowed) 0296 Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::OpenUrlFlags) 0297 0298 #endif /* KDIRMODEL_H */