1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#ifndef KDIRMODEL_H
9#define KDIRMODEL_H
10
11#include "kiowidgets_export.h"
12#include <QAbstractItemModel>
13#include <kfileitem.h>
14
15#include <memory>
16
17class KDirLister;
18class KDirModelPrivate;
19class JobUrlCache;
20
21/*!
22 * \class KDirModel
23 * \inmodule KIOWidgets
24 *
25 * \brief A model for a KIO-based directory tree.
26 *
27 * KDirModel implements the QAbstractItemModel interface (for use with Qt's model/view widgets)
28 * around the directory listing for one directory or a tree of directories.
29 *
30 * Note that there are some cases when using QPersistentModelIndexes from this model will not give
31 * expected results. QPersistentIndexes will remain valid and updated if its siblings are added or
32 * removed. However, if the QPersistentIndex or one of its ancestors is moved, the QPersistentIndex will become
33 * invalid. For example, if a file or directory is renamed after storing a QPersistentModelIndex for it,
34 * the index (along with any stored children) will become invalid even though it is still in the model. The reason
35 * for this is that moves of files and directories are treated as separate insert and remove actions.
36 *
37 * \sa KDirSortFilterProxyModel
38 *
39 */
40class KIOWIDGETS_EXPORT KDirModel : public QAbstractItemModel
41{
42 Q_OBJECT
43
44public:
45 /*!
46 * \a parent parent qobject
47 */
48 explicit KDirModel(QObject *parent = nullptr);
49 ~KDirModel() override;
50
51 /*!
52 * Flags for the openUrl() method
53 *
54 * \value NoFlags No additional flags specified.
55 * \value Reload Indicates whether to use the cache or to reread the directory from the disk. Use only when opening a dir not yet listed by our dirLister()
56 * without using the cache. Otherwise use dirLister()->updateDirectory().
57 * \value ShowRoot Display a root node for the URL being opened.
58 * \since 5.69
59 */
60 enum OpenUrlFlag {
61 NoFlags = 0x0,
62 Reload = 0x1,
63 ShowRoot = 0x2,
64 };
65 Q_DECLARE_FLAGS(OpenUrlFlags, OpenUrlFlag)
66 Q_FLAG(OpenUrlFlags)
67
68 /*!
69 * Display the contents of \a url in the model.
70 *
71 * Apart from the support for the ShowRoot flag, this is equivalent to dirLister()->openUrl(url, flags)
72 *
73 * \a url the URL of the directory whose contents should be listed. Unless ShowRoot is set, the item for this directory will NOT be shown, the model starts
74 * at its children.
75 *
76 * \a flags see OpenUrlFlag
77 *
78 * \since 5.69
79 */
80 Q_INVOKABLE void openUrl(const QUrl &url, OpenUrlFlags flags = NoFlags);
81
82 /*!
83 * Set the directory lister to use by this model, instead of the default KDirLister created internally.
84 * The model takes ownership.
85 */
86 void setDirLister(KDirLister *dirLister);
87
88 /*!
89 * Return the directory lister used by this model.
90 */
91 KDirLister *dirLister() const;
92
93 /*!
94 * Return the fileitem for a given index. This is O(1), i.e. fast.
95 */
96 KFileItem itemForIndex(const QModelIndex &index) const;
97
98 /*!
99 * Return the index for a given kfileitem. This can be slow.
100 */
101 Q_INVOKABLE QModelIndex indexForItem(const KFileItem &) const;
102
103 /*!
104 * Return the index for a given url. This can be slow.
105 */
106 Q_INVOKABLE QModelIndex indexForUrl(const QUrl &url) const;
107
108 /*!
109 * Lists subdirectories using fetchMore() as needed until the given url exists in the model.
110 *
111 * When the model is used by a treeview, call KDirLister::openUrl with the base url of the tree,
112 * then the treeview will take care of calling fetchMore() when the user opens directories.
113 * However if you want the tree to show a given URL (i.e. open the tree recursively until that URL),
114 * call expandToUrl().
115 * Note that this is asynchronous; the necessary listing of subdirectories will take time so
116 * the model will not immediately have this url available.
117 * The model emits the signal expand() when an index has become available; this can be connected
118 * to the treeview in order to let it open that index.
119 *
120 * \a url the url of a subdirectory of the directory model (or a file in a subdirectory)
121 */
122 Q_INVOKABLE void expandToUrl(const QUrl &url);
123
124 /*!
125 * Notify the model that the item at this index has changed.
126 * For instance because its mimetype was resolved.
127 * This makes the model emit its dataChanged signal at this index, so that views repaint.
128 * Note that for most things (renaming, changing size etc.), KDirLister's signals tell the model already.
129 */
130 Q_INVOKABLE void itemChanged(const QModelIndex &index);
131
132 /*!
133 * Forget all previews (optimization for turning previews off).
134 * The items will again have their default appearance (not controlled by the model).
135 * \since 5.28
136 */
137 Q_INVOKABLE void clearAllPreviews();
138
139 /*!
140 * Useful "default" columns. Views can use a proxy to have more control over this.
141 *
142 * \value Name
143 * \value Size
144 * \value ModifiedTime
145 * \value Permissions
146 * \value Owner
147 * \value Group
148 * \value Type
149 * \value ColumnCount
150 */
151 enum ModelColumns {
152 Name = 0,
153 Size,
154 ModifiedTime,
155 Permissions,
156 Owner,
157 Group,
158 Type,
159 ColumnCount,
160 };
161
162 /*!
163 * Possible return value for data(ChildCountRole), meaning the item isn't a directory,
164 * or we haven't calculated its child count yet
165 *
166 * \value ChildCountUnknown
167 */
168 enum {
169 ChildCountUnknown = -1
170 };
171
172 /*!
173 * \value FileItemRole Returns the KFileItem for a given index. roleName is "fileItem".
174 * \value ChildCountRole Returns the number of items in a directory, or ChildCountUnknown. roleName is "childCount".
175 * \value HasJobRole Returns whether or not there is a job on an item (file/directory). roleName is "hasJob".
176 * \value HandleSequencesRole
177 */
178 enum AdditionalRoles {
179 // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
180 // to define additional roles.
181 FileItemRole = 0x07A263FF,
182 ChildCountRole = 0x2C4D0A40,
183 HasJobRole = 0x01E555A5,
184 HandleSequencesRole = 0x1E642272,
185 };
186
187 /*!
188 * \value NoDrops
189 * \value DropOnDirectory Allow drops on any directory
190 * \value DropOnAnyFile Allow drops on any file
191 * \value DropOnLocalExecutable Allow drops on local executables, shell scripts and desktop files. Can be used with DropOnDirectory.
192 */
193 enum DropsAllowedFlag {
194 NoDrops = 0,
195 DropOnDirectory = 1,
196 DropOnAnyFile = 2,
197 DropOnLocalExecutable = 4,
198 };
199 Q_DECLARE_FLAGS(DropsAllowed, DropsAllowedFlag)
200 Q_FLAG(DropsAllowed)
201
202 /*!
203 * Set whether dropping onto items should be allowed, and for which kind of item
204 * Drops are disabled by default.
205 */
206 Q_INVOKABLE void setDropsAllowed(DropsAllowed dropsAllowed);
207
208 /*!
209 * \reimp
210 * Returns \c true for empty directories.
211 */
212 bool canFetchMore(const QModelIndex &parent) const override;
213
214 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
215
216 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
217
218 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
219
220 /*!
221 * \reimp Lists the subdirectory.
222 */
223 void fetchMore(const QModelIndex &parent) override;
224
225 Qt::ItemFlags flags(const QModelIndex &index) const override;
226
227 /*!
228 * \reimp
229 * Returns \c true for directories
230 */
231 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
232
233 /*!
234 * \reimp
235 * Returns the column titles.
236 */
237 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
238
239 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
240
241 QMimeData *mimeData(const QModelIndexList &indexes) const override;
242
243 QStringList mimeTypes() const override;
244
245 QModelIndex parent(const QModelIndex &index) const override;
246
247 QModelIndex sibling(int row, int column, const QModelIndex &index) const override;
248
249 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
250
251 /*!
252 * \reimp
253 * Call this to set a new icon, e.g. a preview
254 */
255 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
256
257 /*!
258 * \reimp
259 * Not implemented.
260 * \sa KDirSortFilterProxyModel
261 */
262 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
263
264 QHash<int, QByteArray> roleNames() const override;
265
266 /*!
267 * Remove urls from the list if an ancestor is present on the list. This can
268 * be used to delete only the ancestor url and skip a potential error of a non-existent url.
269 *
270 * 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",
271 * "home/foo/b/b.txt", this method will return the list "/home/foo/a", "/home/foo/b/b.txt".
272 *
273 * Returns the list \a urls without parented urls inside.
274 */
275 static QList<QUrl> simplifiedUrlList(const QList<QUrl> &urls);
276
277 /*!
278 * This emits the needSequenceIcon signal, requesting another sequence icon
279 *
280 * If there is a KFilePreviewGenerator attached to this model, that generator will care
281 * about creating another preview.
282 *
283 * \a index Index of the item that should get another icon
284 *
285 * \a sequenceIndex Index in the sequence. If it is zero, the standard icon will be assigned.
286 * For higher indices, arbitrary different meaningful icons will be generated.
287 */
288 void requestSequenceIcon(const QModelIndex &index, int sequenceIndex);
289
290 /*!
291 * Enable/Disable the displaying of an animated overlay that is shown for any destination
292 * urls (in the view). When enabled, the animations (if any) will be drawn automatically.
293 *
294 * Only the files/folders that are visible and have jobs associated with them
295 * will display the animation.
296 * You would likely not want this enabled if you perform some kind of custom painting
297 * that takes up a whole item, and will just make this(and what you paint) look funky.
298 *
299 * Default is disabled.
300 *
301 * Note: KFileItemDelegate needs to have it's method called with the same
302 * value, when you make the call to this method.
303 */
304 void setJobTransfersVisible(bool show);
305
306 /*!
307 * Returns whether or not displaying job transfers has been enabled.
308 */
309 bool jobTransfersVisible() const;
310
311 Qt::DropActions supportedDropActions() const override;
312
313Q_SIGNALS:
314 /*!
315 * Emitted for each subdirectory that is a parent of a url passed to expandToUrl
316 * This allows to asynchronously open a tree view down to a given directory.
317 * Also emitted for the final file, if expandToUrl is called with a file
318 * (for instance so that it can be selected).
319 */
320 void expand(const QModelIndex &index);
321 /*!
322 * Emitted when another icon sequence index is requested
323 *
324 * \a index Index of the item that should get another icon
325 *
326 * \a sequenceIndex Index in the sequence. If it is zero, the standard icon should be assigned.
327 * For higher indices, arbitrary different meaningful icons should be generated.
328 * This is usually slowly counted up while the user hovers the icon.
329 * If no meaningful alternative icons can be generated, this should be ignored.
330 */
331 void needSequenceIcon(const QModelIndex &index, int sequenceIndex);
332
333private:
334 // Make those private, they shouldn't be called by applications
335 bool insertRows(int, int, const QModelIndex & = QModelIndex()) override;
336 bool insertColumns(int, int, const QModelIndex & = QModelIndex()) override;
337 bool removeRows(int, int, const QModelIndex & = QModelIndex()) override;
338 bool removeColumns(int, int, const QModelIndex & = QModelIndex()) override;
339
340private:
341 friend class KDirModelPrivate;
342 std::unique_ptr<KDirModelPrivate> const d;
343};
344
345Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::DropsAllowed)
346Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::OpenUrlFlags)
347
348#endif /* KDIRMODEL_H */
349

source code of kio/src/widgets/kdirmodel.h