1 /*
2     This file is part of the KDE project
3     SPDX-FileCopyrightText: 1999-2006 David Faure <faure@kde.org>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef KFILEITEM_H
9 #define KFILEITEM_H
10 
11 #include "kiocore_export.h"
12 #include <QDateTime>
13 #include <QFile>
14 #include <QUrl>
15 #include <kacl.h>
16 #include <kio/global.h>
17 #include <kio/udsentry.h>
18 
19 #include <QList>
20 #include <QMimeType>
21 #include <qplatformdefs.h>
22 
23 class KFileItemPrivate;
24 
25 /**
26  * @class KFileItem kfileitem.h <KFileItem>
27  *
28  * A KFileItem is a generic class to handle a file, local or remote.
29  * In particular, it makes it easier to handle the result of KIO::listDir
30  * (UDSEntry isn't very friendly to use).
31  * It includes many file attributes such as MIME type, icon, text, mode, link...
32  *
33  * KFileItem is implicitly shared, i.e. it can be used as a value and copied around at almost no cost.
34  */
35 class KIOCORE_EXPORT KFileItem
36 {
37 public:
38     enum { Unknown = static_cast<mode_t>(-1) };
39 
40     /**
41      * The timestamps associated with a file.
42      * - ModificationTime: the time the file's contents were last modified
43      * - AccessTime: the time the file was last accessed (last read or written to)
44      * - CreationTime: the time the file was created
45      */
46     enum FileTimes {
47         // warning: don't change without looking at the Private class
48         ModificationTime = 0,
49         AccessTime = 1,
50         CreationTime = 2,
51         // ChangeTime
52     };
53 
54     enum MimeTypeDetermination {
55         NormalMimeTypeDetermination = 0,
56         SkipMimeTypeFromContent,
57     };
58 
59     /**
60      * Null KFileItem. Doesn't represent any file, only exists for convenience.
61      */
62     KFileItem();
63 
64     /**
65      * Creates an item representing a file, from a UDSEntry.
66      * This is the preferred constructor when using KIO::listDir().
67      *
68      * @param entry the KIO entry used to get the file, contains info about it
69      * @param itemOrDirUrl the URL of the item or of the directory containing this item (see urlIsDirectory).
70      * @param delayedMimeTypes specifies if the MIME type of the given
71      *       URL should be determined immediately or on demand.
72      *       See the bool delayedMimeTypes in the KDirLister constructor.
73      * @param urlIsDirectory specifies if the url is just the directory of the
74      *       fileitem and the filename from the UDSEntry should be used.
75      *
76      * When creating KFileItems out of the UDSEntry emitted by a KIO list job,
77      * use KFileItem(entry, listjob->url(), delayedMimeTypes, true);
78      */
79     KFileItem(const KIO::UDSEntry &entry, const QUrl &itemOrDirUrl, bool delayedMimeTypes = false, bool urlIsDirectory = false);
80 
81 #if KIOCORE_ENABLE_DEPRECATED_SINCE(5, 0)
82     /**
83      * Creates an item representing a file, from all the necessary info for it.
84      * @param mode the file mode (according to stat() (e.g. S_IFDIR...)
85      * Set to KFileItem::Unknown if unknown. For local files, KFileItem will use stat().
86      * @param permissions the access permissions
87      * If you set both the mode and the permissions, you save a ::stat() for
88      * local files.
89      * Set to KFileItem::Unknown if you don't know the mode or the permission.
90      * @param url the file url
91      *
92      * @param delayedMimeTypes specify if the MIME type of the given URL
93      *       should be determined immediately or on demand
94      * @deprecated since 5.0. Most callers gave Unknown for mode and permissions,
95      * so just port to KFileItem(url) and setDelayedMimeTypes(true) if necessary.
96      */
97     KIOCORE_DEPRECATED_VERSION(5, 0, "See API docs")
98     KFileItem(mode_t mode, mode_t permissions, const QUrl &url, bool delayedMimeTypes = false);
99 #endif
100 
101     /**
102      * Creates an item representing a file, for which the MIME type is already known.
103      * @param url the file url
104      * @param mimeType the name of the file's MIME type
105      * @param mode the mode (S_IFDIR...)
106      */
107     KFileItem(const QUrl &url, const QString &mimeType = QString(), mode_t mode = KFileItem::Unknown); // KF6 TODO: explicit!
108 
109     /**
110      * Creates an item representing a file, with the option of skipping MIME type determination.
111      * @param url the file url
112      * @param mimeTypeDetermination the mode of determining the MIME type:
113      *       NormalMimeTypeDetermination by content if local file, i.e. access the file,
114      *                                   open and read part of it;
115      *                                   by QMimeDatabase::MatchMode::MatchExtension if not local.
116      *       SkipMimeTypeFromContent     always by QMimeDatabase::MatchMode::MatchExtension,
117      *                                   i.e. won't access the file by stat() or opening it;
118      *                                   only suitable for files, directories won't be recognized.
119      * @since 5.57
120      */
121     KFileItem(const QUrl &url, KFileItem::MimeTypeDetermination mimeTypeDetermination);
122 
123     /**
124      * Copy constructor
125      */
126     KFileItem(const KFileItem &);
127 
128     /**
129      * Destructor
130      */
131     ~KFileItem();
132 
133     /**
134      * Move constructor
135      * @since 5.43
136      */
137     KFileItem(KFileItem &&);
138 
139     /**
140      * Copy assignment
141      */
142     KFileItem &operator=(const KFileItem &);
143 
144     /**
145      * Move assignment
146      * @since 5.43
147      */
148     KFileItem &operator=(KFileItem &&);
149 
150     /**
151      * Throw away and re-read (for local files) all information about the file.
152      * This is called when the _file_ changes.
153      */
154     void refresh();
155 
156     /**
157      * Re-reads MIME type information.
158      * This is called when the MIME type database changes.
159      */
160     void refreshMimeType();
161 
162     /**
163      * Sets MIME type determination to be immediate or on demand.
164      * Call this after the constructor, and before using any MIME-type-related method.
165      * @since 5.0
166      */
167     void setDelayedMimeTypes(bool b);
168 
169     /**
170      * Returns the url of the file.
171      * @return the url of the file
172      */
173     QUrl url() const;
174 
175     /**
176      * Sets the item's URL. Do not call unless you know what you are doing!
177      * (used for example when an item got renamed).
178      * @param url the item's URL
179      */
180     void setUrl(const QUrl &url);
181 
182     /**
183      * Sets the item's local path (UDS_LOCAL_PATH). Do not call unless you know what you are doing!
184      * This won't change the item's name or URL.
185      * (used for example when an item got renamed).
186      * @param path the item's local path
187      * @since 5.20
188      */
189     void setLocalPath(const QString &path);
190 
191     /**
192      * Sets the item's name (i.e. the filename).
193      * This is automatically done by setUrl, to set the name from the URL's fileName().
194      * This method is provided for some special cases like relative paths as names (KFindPart)
195      * @param name the item's name
196      */
197     void setName(const QString &name);
198 
199     /**
200      * Returns the permissions of the file (stat.st_mode containing only permissions).
201      * @return the permissions of the file
202      */
203     mode_t permissions() const;
204 
205     /**
206      * Returns the access permissions for the file as a string.
207      * @return the access permission as string
208      */
209     QString permissionsString() const;
210 
211     /**
212      * Tells if the file has extended access level information ( Posix ACL )
213      * @return true if the file has extend ACL information or false if it hasn't
214      */
215     bool hasExtendedACL() const;
216 
217     /**
218      * Returns the access control list for the file.
219      * @return the access control list as a KACL
220      */
221     KACL ACL() const;
222 
223     /**
224      * Returns the default access control list for the directory.
225      * @return the default access control list as a KACL
226      */
227     KACL defaultACL() const;
228 
229     /**
230      * Returns the file type (stat.st_mode containing only S_IFDIR, S_IFLNK, ...).
231      * @return the file type
232      */
233     mode_t mode() const;
234 
235     /**
236      * Returns the owner of the file.
237      * @return the file's owner
238      */
239     QString user() const;
240 
241     /**
242      * Returns the group of the file.
243      * @return the file's group
244      */
245     QString group() const;
246 
247     /**
248      * Returns true if this item represents a link in the UNIX sense of
249      * a link.
250      * @return true if the file is a link
251      */
252     bool isLink() const;
253 
254     /**
255      * Returns true if this item represents a directory.
256      * @return true if the item is a directory
257      */
258     bool isDir() const;
259 
260     /**
261      * Returns true if this item represents a file (and not a directory)
262      * @return true if the item is a file
263      */
264     bool isFile() const;
265 
266     /**
267      * Checks whether the file or directory is readable. In some cases
268      * (remote files), we may return true even though it can't be read.
269      * @return true if the file can be read - more precisely,
270      *         false if we know for sure it can't
271      */
272     bool isReadable() const;
273 
274     /**
275      * Checks whether the file or directory is writable. In some cases
276      * (remote files), we may return true even though it can't be written to.
277      * @return true if the file or directory can be written to - more precisely,
278      *         false if we know for sure it can't
279      */
280     bool isWritable() const;
281 
282     /**
283      * Checks whether the file is hidden.
284      * @return true if the file is hidden.
285      */
286     bool isHidden() const;
287 
288     /**
289      * @return true if the file is a remote URL, or a local file on a network mount.
290      * It will return false only for really-local file systems.
291      * @since 4.7.4
292      */
293     bool isSlow() const;
294 
295     /**
296      * Checks whether the file is a readable local .desktop file,
297      * i.e. a file whose path can be given to KDesktopFile
298      * @return true if the file is a desktop file.
299      * @since 4.1
300      */
301     bool isDesktopFile() const;
302 
303     /**
304      * Returns the link destination if isLink() == true.
305      * @return the link destination. QString() if the item is not a link
306      */
307     QString linkDest() const;
308 
309     /**
310      * Returns the target url of the file, which is the same as url()
311      * in cases where the slave doesn't specify UDS_TARGET_URL
312      * @return the target url.
313      * @since 4.1
314      */
315     QUrl targetUrl() const;
316 
317     /**
318      * Returns the local path if isLocalFile() == true or the KIO item has
319      * a UDS_LOCAL_PATH atom.
320      * @return the item local path, or QString() if not known
321      */
322     QString localPath() const;
323 
324     /**
325      * Returns the size of the file, if known.
326      * @return the file size, or 0 if not known
327      */
328     KIO::filesize_t size() const;
329 
330     /**
331      * @brief For folders, its recursive size:
332      * the size of its files plus the recursiveSize of its folder
333      *
334      * Initially only implemented for trash:/
335      *
336      * @since 5.70
337      * @return The recursive size
338      */
339     KIO::filesize_t recursiveSize() const;
340 
341     /**
342      * Requests the modification, access or creation time, depending on @p which.
343      * @param which the timestamp
344      * @return the time asked for, QDateTime() if not available
345      * @see timeString()
346      */
347     QDateTime time(FileTimes which) const;
348 
349     /**
350      * Requests the modification, access or creation time as a string, depending
351      * on @p which.
352      * @param which the timestamp
353      * @returns a formatted string of the requested time.
354      * @see time
355      */
356     QString timeString(FileTimes which = ModificationTime) const;
357 
358 #if KIOCORE_ENABLE_DEPRECATED_SINCE(4, 0)
359     KIOCORE_DEPRECATED_VERSION(4, 0, "Use KFileItem::timeString(FileTimes)")
360     QString timeString(unsigned int which) const;
361 #endif
362 
363     /**
364      * Returns true if the file is a local file.
365      * @return true if the file is local, false otherwise
366      */
367     bool isLocalFile() const;
368 
369     /**
370      * Returns the text of the file item.
371      * It's not exactly the filename since some decoding happens ('%2F'->'/').
372      * @return the text of the file item
373      */
374     QString text() const;
375 
376     /**
377      * Return the name of the file item (without a path).
378      * Similar to text(), but unencoded, i.e. the original name.
379      * @param lowerCase if true, the name will be returned in lower case,
380      * which is useful to speed up sorting by name, case insensitively.
381      * @return the file's name
382      */
383     QString name(bool lowerCase = false) const;
384 
385     /**
386      * Returns the MIME type of the file item.
387      * If @p delayedMimeTypes was used in the constructor, this will determine
388      * the MIME type first. Equivalent to determineMimeType()->name()
389      * @return the MIME type of the file
390      */
391     QString mimetype() const;
392 
393     /**
394      * Returns the MIME type of the file item.
395      * If delayedMimeTypes was used in the constructor, this will determine
396      * the MIME type first.
397      * @return the MIME type
398      */
399     QMimeType determineMimeType() const;
400 
401     /**
402      * Returns the currently known MIME type of the file item.
403      * This will not try to determine the MIME type if unknown.
404      * @return the known MIME type
405      */
406     QMimeType currentMimeType() const;
407 
408     /**
409      * @return true if we have determined the final icon of this file already.
410      * @since 4.10.2
411      */
412     bool isFinalIconKnown() const;
413 
414     /**
415      * @return true if we have determined the MIME type of this file already,
416      * i.e. if determineMimeType() will be fast. Otherwise it will have to
417      * find what the MIME type is, which is a possibly slow operation; usually
418      * this is delayed until necessary.
419      */
420     bool isMimeTypeKnown() const;
421 
422     /**
423      * Returns the user-readable string representing the type of this file,
424      * like "OpenDocument Text File".
425      * @return the type of this KFileItem
426      */
427     QString mimeComment() const;
428 
429     /**
430      * Returns the full path name to the icon that represents
431      * this MIME type.
432      * @return iconName the name of the file's icon
433      */
434     QString iconName() const;
435 
436     /**
437      * Returns the overlays (bitfield of KIconLoader::*Overlay flags) that are used
438      * for this item's pixmap. Overlays are used to show for example, whether
439      * a file can be modified.
440      * @return the overlays of the pixmap
441      */
442     QStringList overlays() const;
443 
444     /**
445      * A comment which can contain anything - even rich text. It will
446      * simply be displayed to the user as is.
447      *
448      * @since 4.6
449      */
450     QString comment() const;
451 
452     /**
453      * Returns the string to be displayed in the statusbar,
454      * e.g. when the mouse is over this item
455      * @return the status bar information
456      */
457     QString getStatusBarInfo() const;
458 
459 #if KIOCORE_ENABLE_DEPRECATED_SINCE(4, 0)
460     /**
461      * Returns true if files can be dropped over this item.
462      * Contrary to popular belief, not only dirs will return true :)
463      * Executables, .desktop files, will do so as well.
464      * @return true if you can drop files over the item
465      *
466      * @deprecated Since 4.0. This logic is application-dependent, the behavior described above
467      * mostly makes sense for file managers only.
468      * KDirModel has setDropsAllowed for similar (but configurable) logic.
469      */
470     KIOCORE_DEPRECATED_VERSION(4, 0, "See API docs")
471     bool acceptsDrops() const;
472 #endif
473 
474     /**
475      * Returns the UDS entry. Used by the tree view to access all details
476      * by position.
477      * @return the UDS entry
478      */
479     KIO::UDSEntry entry() const;
480 
481     /**
482      * Return true if this item is a regular file,
483      * false otherwise (directory, link, character/block device, fifo, socket)
484      * @since 4.3
485      */
486     bool isRegularFile() const;
487 
488     /**
489      * Somewhat like a comparison operator, but more explicit,
490      * and it can detect that two fileitems differ if any property of the file item
491      * has changed (file size, modification date, etc.). Two items are equal if
492      * all properties are equal. In contrast, operator== only compares URLs.
493      * @param item the item to compare
494      * @return true if all values are equal
495      */
496     bool cmp(const KFileItem &item) const;
497 
498     /**
499      * Returns true if both items share the same URL.
500      */
501     bool operator==(const KFileItem &other) const;
502 
503     /**
504      * Returns true if both items do not share the same URL.
505      */
506     bool operator!=(const KFileItem &other) const;
507 
508     /**
509      * Returns true if this item's URL is lexically less than other's URL; otherwise returns false
510      * @since 5.48
511      */
512     bool operator<(const KFileItem &other) const;
513 
514     /**
515      * Returns true if this item's URL is lexically less than url other; otherwise returns false
516      * @since 5.48
517      */
518     bool operator<(const QUrl &other) const;
519 
520     /**
521      * Converts this KFileItem to a QVariant, this allows to use KFileItem
522      * in QVariant() constructor
523      */
524     operator QVariant() const;
525 
526 #if KIOCORE_ENABLE_DEPRECATED_SINCE(4, 0)
527     /**
528      * @deprecated Since 4.0, simply use '='
529      */
530     KIOCORE_DEPRECATED_VERSION(4, 0, "Use KFileItem::operator=(const KFileItem&)")
531     void assign(const KFileItem &item);
532 #endif
533 
534     /**
535      * Tries to give a local URL for this file item if possible.
536      * The given boolean indicates if the returned url is local or not.
537      * \since 4.6
538      */
539     QUrl mostLocalUrl(bool *local = nullptr) const;
540 
541     struct MostLocalUrlResult {
542         QUrl url;
543         bool local;
544     };
545 
546     /**
547      * Returns a MostLocalUrlResult, with the local Url for this item if possible
548      * (otherwise an empty Url), and a bool that is set to @c true if this Url
549      * does represent a local file otherwise @c false.
550      *
551      * @since 5.84
552      */
553     MostLocalUrlResult isMostLocalUrl() const;
554 
555 #if KIOCORE_ENABLE_DEPRECATED_SINCE(5, 0)
556     /**
557      * @deprecated since 5.0 add '&' in front of your boolean argument
558      */
559     KIOCORE_DEPRECATED_VERSION(5, 0, "Use KFileItem::mostLocalUrl(bool *)")
mostLocalUrl(bool & local)560     QUrl mostLocalUrl(bool &local) const
561     {
562         return mostLocalUrl(&local);
563     }
564 #endif
565 
566     /**
567      * Return true if default-constructed
568      */
569     bool isNull() const;
570 
571 private:
572     QSharedDataPointer<KFileItemPrivate> d;
573 
574     /**
575      * Hides the file.
576      */
577     void setHidden();
578 
579 private:
580     KIOCORE_EXPORT friend QDataStream &operator<<(QDataStream &s, const KFileItem &a);
581     KIOCORE_EXPORT friend QDataStream &operator>>(QDataStream &s, KFileItem &a);
582 
583     friend class KFileItemTest;
584     friend class KCoreDirListerCache;
585 };
586 
587 Q_DECLARE_METATYPE(KFileItem)
588 Q_DECLARE_TYPEINFO(KFileItem, Q_MOVABLE_TYPE);
589 
qHash(const KFileItem & item)590 inline uint qHash(const KFileItem &item)
591 {
592     return qHash(item.url());
593 }
594 
595 /**
596  * @class KFileItemList kfileitem.h <KFileItem>
597  *
598  * List of KFileItems, which adds a few helper
599  * methods to QList<KFileItem>.
600  */
601 class KIOCORE_EXPORT KFileItemList : public QList<KFileItem>
602 {
603 public:
604     /// Creates an empty list of file items.
605     KFileItemList();
606 
607     /// Creates a new KFileItemList from a QList of file @p items.
608     KFileItemList(const QList<KFileItem> &items);
609 
610     /// Creates a new KFileItemList from an initializer_list of file @p items.
611     /// @since 5.76
612     KFileItemList(std::initializer_list<KFileItem> items);
613 
614     /**
615      * Find a KFileItem by name and return it.
616      * @return the item with the given name, or a null-item if none was found
617      *         (see KFileItem::isNull())
618      */
619     KFileItem findByName(const QString &fileName) const;
620 
621     /**
622      * Find a KFileItem by URL and return it.
623      * @return the item with the given URL, or a null-item if none was found
624      *         (see KFileItem::isNull())
625      */
626     KFileItem findByUrl(const QUrl &url) const;
627 
628     /// @return the list of URLs that those items represent
629     QList<QUrl> urlList() const;
630 
631     /// @return the list of target URLs that those items represent
632     /// @since 4.2
633     QList<QUrl> targetUrlList() const;
634 
635     // TODO KDE-5 add d pointer here so that we can merge KFileItemListProperties into KFileItemList
636 };
637 
638 KIOCORE_EXPORT QDataStream &operator<<(QDataStream &s, const KFileItem &a);
639 KIOCORE_EXPORT QDataStream &operator>>(QDataStream &s, KFileItem &a);
640 
641 /**
642  * Support for qDebug() << aFileItem
643  * \since 4.4
644  */
645 KIOCORE_EXPORT QDebug operator<<(QDebug stream, const KFileItem &item);
646 
647 #endif
648