1/* This file is part of the KDE project
2 Copyright (C) 2006 David Faure <faure@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19#ifndef KDIRMODEL_H
20#define KDIRMODEL_H
21
22#include <QtCore/QAbstractItemModel>
23#include <kio/kio_export.h>
24#include <kfileitem.h>
25
26class KDirLister;
27class KDirModelPrivate;
28class JobUrlCache;
29
30/**
31 * @short A model for a KIO-based directory tree.
32 *
33 * KDirModel implements the QAbstractItemModel interface (for use with Qt's model/view widgets)
34 * around the directory listing for one directory or a tree of directories.
35 *
36 * Note that there are some cases when using QPersistentModelIndexes from this model will not give
37 * expected results. QPersistentIndexes will remain valid and updated if its siblings are added or
38 * removed. However, if the QPersistentIndex or one of its ancestors is moved, the QPersistentIndex will become
39 * invalid. For example, if a file or directory is renamed after storing a QPersistentModelIndex for it,
40 * the index (along with any stored children) will become invalid even though it is still in the model. The reason
41 * for this is that moves of files and directories are treated as separate insert and remove actions.
42 *
43 * @see KDirSortFilterProxyModel
44 *
45 * @author David Faure
46 * Based on work by Hamish Rodda and Pascal Letourneau
47 */
48class KIO_EXPORT KDirModel : public QAbstractItemModel
49{
50 Q_OBJECT
51
52public:
53 /**
54 * @param parent parent qobject
55 */
56 explicit KDirModel( QObject* parent = 0 );
57 ~KDirModel();
58
59 /**
60 * Set the directory lister to use by this model, instead of the default KDirLister created internally.
61 * The model takes ownership.
62 */
63 void setDirLister( KDirLister* dirLister );
64
65 /**
66 * Return the directory lister used by this model.
67 */
68 KDirLister* dirLister() const;
69
70 /**
71 * Return the fileitem for a given index. This is O(1), i.e. fast.
72 */
73 KFileItem itemForIndex( const QModelIndex& index ) const;
74
75 /**
76 * Return the index for a given kfileitem. This can be slow.
77 * @deprecated use the method that takes a KFileItem by value
78 */
79#ifndef KDE_NO_DEPRECATED
80 KDE_DEPRECATED QModelIndex indexForItem( const KFileItem* ) const;
81#endif
82
83 /**
84 * Return the index for a given kfileitem. This can be slow.
85 */
86 QModelIndex indexForItem( const KFileItem& ) const;
87
88 /**
89 * Return the index for a given url. This can be slow.
90 */
91 QModelIndex indexForUrl(const KUrl& url) const;
92
93 /**
94 * @short Lists subdirectories using fetchMore() as needed until the given @p url exists in the model.
95 *
96 * When the model is used by a treeview, call KDirLister::openUrl with the base url of the tree,
97 * then the treeview will take care of calling fetchMore() when the user opens directories.
98 * However if you want the tree to show a given URL (i.e. open the tree recursively until that URL),
99 * call expandToUrl().
100 * Note that this is asynchronous; the necessary listing of subdirectories will take time so
101 * the model will not immediately have this url available.
102 * The model emits the signal expand() when an index has become available; this can be connected
103 * to the treeview in order to let it open that index.
104 * @param url the url of a subdirectory of the directory model (or a file in a subdirectory)
105 */
106 void expandToUrl(const KUrl& url);
107
108 /**
109 * Notify the model that the item at this index has changed.
110 * For instance because KMimeTypeResolver called determineMimeType on it.
111 * This makes the model emit its dataChanged signal at this index, so that views repaint.
112 * Note that for most things (renaming, changing size etc.), KDirLister's signals tell the model already.
113 */
114 void itemChanged( const QModelIndex& index );
115
116 /***
117 * Useful "default" columns. Views can use a proxy to have more control over this.
118 */
119 enum ModelColumns {
120 Name = 0,
121 Size,
122 ModifiedTime,
123 Permissions,
124 Owner,
125 Group,
126 Type,
127 ColumnCount
128 };
129
130 /// Possible return value for data(ChildCountRole), meaning the item isn't a directory,
131 /// or we haven't calculated its child count yet
132 enum { ChildCountUnknown = -1 };
133
134 enum AdditionalRoles {
135 // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
136 // to define additional roles.
137 FileItemRole = 0x07A263FF, ///< returns the KFileItem for a given index
138 ChildCountRole = 0x2C4D0A40, ///< returns the number of items in a directory, or ChildCountUnknown
139 HasJobRole = 0x01E555A5 ///< returns whether or not there is a job on an item (file/directory)
140 };
141
142 enum DropsAllowedFlag {
143 NoDrops = 0,
144 DropOnDirectory = 1, ///< allow drops on any directory
145 DropOnAnyFile = 2, ///< allow drops on any file
146 DropOnLocalExecutable = 4 ///< allow drops on local executables, shell scripts and desktop files. Can be used with DropOnDirectory.
147 };
148 Q_DECLARE_FLAGS(DropsAllowed, DropsAllowedFlag)
149
150 /// Set whether dropping onto items should be allowed, and for which kind of item
151 /// Drops are disabled by default.
152 void setDropsAllowed(DropsAllowed dropsAllowed);
153
154 /// Reimplemented from QAbstractItemModel. Returns true for empty directories.
155 virtual bool canFetchMore ( const QModelIndex & parent ) const;
156 /// Reimplemented from QAbstractItemModel. Returns ColumnCount.
157 virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
158 /// Reimplemented from QAbstractItemModel.
159 virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
160 /// Reimplemented from QAbstractItemModel. Not implemented yet.
161 virtual bool dropMimeData ( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent );
162 /// Reimplemented from QAbstractItemModel. Lists the subdirectory.
163 virtual void fetchMore ( const QModelIndex & parent );
164 /// Reimplemented from QAbstractItemModel.
165 virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
166 /// Reimplemented from QAbstractItemModel. Returns true for directories.
167 virtual bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const;
168 /// Reimplemented from QAbstractItemModel. Returns the column titles.
169 virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
170 /// Reimplemented from QAbstractItemModel. O(1)
171 virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
172 /// Reimplemented from QAbstractItemModel.
173 virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const;
174 /// Reimplemented from QAbstractItemModel.
175 virtual QStringList mimeTypes () const;
176 /// Reimplemented from QAbstractItemModel.
177 virtual QModelIndex parent ( const QModelIndex & index ) const;
178 /// Reimplemented from QAbstractItemModel.
179 virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
180 /// Reimplemented from QAbstractItemModel.
181 /// Call this to set a new icon, e.g. a preview
182 virtual bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );
183 /// Reimplemented from QAbstractItemModel. Not implemented. @see KDirSortFilterProxyModel
184 virtual void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder );
185
186
187 /**
188 * Remove urls from the list if an ancestor is present on the list. This can
189 * be used to delete only the ancestor url and skip a potential error of a non-existent url.
190 *
191 * 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",
192 * "home/foo/b/b.txt", this method will return the list "/home/foo/a", "/home/foo/b/b.txt".
193 *
194 * @return the list @p urls without parented urls inside.
195 * @since 4.2
196 */
197 static KUrl::List simplifiedUrlList( const KUrl::List & urls );
198
199 /**
200 * This emits the needSequenceIcon signal, requesting another sequence icon
201 *
202 * If there is a KFilePreviewGenerator attached to this model, that generator will care
203 * about creating another preview.
204 *
205 * @param index Index of the item that should get another icon
206 * @param sequenceIndex Index in the sequence. If it is zero, the standard icon will be assigned.
207 * For higher indices, arbitrary different meaningful icons will be generated.
208 * @since 4.3
209 */
210 void requestSequenceIcon(const QModelIndex& index, int sequenceIndex);
211
212 /**
213 * Enable/Disable the displaying of an animated overlay that is shown for any destination
214 * urls (in the view). When enabled, the animations (if any) will be drawn automatically.
215 *
216 * Only the files/folders that are visible and have jobs associated with them
217 * will display the animation.
218 * You would likely not want this enabled if you perform some kind of custom painting
219 * that takes up a whole item, and will just make this(and what you paint) look funky.
220 *
221 * Default is disabled.
222 *
223 * Note: KFileItemDelegate needs to have it's method called with the same
224 * value, when you make the call to this method.
225 *
226 * @since 4.5
227 */
228 void setJobTransfersVisible(bool value);
229
230 /**
231 * Returns whether or not displaying job transfers has been enabled.
232 * @since 4.5
233 */
234 bool jobTransfersVisible() const;
235
236Q_SIGNALS:
237 /**
238 * Emitted for each subdirectory that is a parent of a url passed to expandToUrl
239 * This allows to asynchronously open a tree view down to a given directory.
240 * Also emitted for the final file, if expandToUrl is called with a file
241 * (for instance so that it can be selected).
242 */
243 void expand(const QModelIndex& index);
244 /**
245 * Emitted when another icon sequence index is requested
246 * @param index Index of the item that should get another icon
247 * @param sequenceIndex Index in the sequence. If it is zero, the standard icon should be assigned.
248 * For higher indices, arbitrary different meaningful icons should be generated.
249 * This is usually slowly counted up while the user hovers the icon.
250 * If no meaningful alternative icons can be generated, this should be ignored.
251 * @since 4.3
252 */
253 void needSequenceIcon(const QModelIndex& index, int sequenceIndex);
254
255private:
256 // Make those private, they shouldn't be called by applications
257 virtual bool insertRows(int , int, const QModelIndex & = QModelIndex());
258 virtual bool insertColumns(int, int, const QModelIndex & = QModelIndex());
259 virtual bool removeRows(int, int, const QModelIndex & = QModelIndex());
260 virtual bool removeColumns(int, int, const QModelIndex & = QModelIndex());
261
262private:
263 friend class KDirModelPrivate;
264 KDirModelPrivate *const d;
265
266 Q_PRIVATE_SLOT( d, void _k_slotNewItems(const KUrl&, const KFileItemList&) )
267 Q_PRIVATE_SLOT( d, void _k_slotDeleteItems(const KFileItemList&) )
268 Q_PRIVATE_SLOT( d, void _k_slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&) )
269 Q_PRIVATE_SLOT( d, void _k_slotClear() )
270 Q_PRIVATE_SLOT( d, void _k_slotRedirection(const KUrl&, const KUrl&) )
271 Q_PRIVATE_SLOT( d, void _k_slotJobUrlsChanged(const QStringList&))
272};
273
274Q_DECLARE_OPERATORS_FOR_FLAGS(KDirModel::DropsAllowed)
275
276#endif /* KDIRMODEL_H */
277