1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFILEINFOGATHERER_H
5#define QFILEINFOGATHERER_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19
20#include <qthread.h>
21#include <qmutex.h>
22#include <qwaitcondition.h>
23#if QT_CONFIG(filesystemwatcher)
24#include <qfilesystemwatcher.h>
25#endif
26#include <qabstractfileiconprovider.h>
27#include <qpair.h>
28#include <qstack.h>
29#include <qdatetime.h>
30#include <qdir.h>
31#include <qelapsedtimer.h>
32
33#include <private/qfilesystemengine_p.h>
34
35QT_REQUIRE_CONFIG(filesystemmodel);
36
37QT_BEGIN_NAMESPACE
38
39class QExtendedInformation {
40public:
41 enum Type { Dir, File, System };
42
43 QExtendedInformation() {}
44 QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {}
45
46 inline bool isDir() { return type() == Dir; }
47 inline bool isFile() { return type() == File; }
48 inline bool isSystem() { return type() == System; }
49
50 bool operator ==(const QExtendedInformation &fileInfo) const {
51 return mFileInfo == fileInfo.mFileInfo
52 && displayType == fileInfo.displayType
53 && permissions() == fileInfo.permissions()
54 && lastModified(tz: QTimeZone::UTC) == fileInfo.lastModified(tz: QTimeZone::UTC);
55 }
56
57#ifndef QT_NO_FSFILEENGINE
58 bool isCaseSensitive() const {
59 return QFileSystemEngine::isCaseSensitive();
60 }
61#endif
62
63 QFile::Permissions permissions() const {
64 return mFileInfo.permissions();
65 }
66
67 Type type() const {
68 if (mFileInfo.isDir()) {
69 return QExtendedInformation::Dir;
70 }
71 if (mFileInfo.isFile()) {
72 return QExtendedInformation::File;
73 }
74 if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
75 return QExtendedInformation::System;
76 }
77 return QExtendedInformation::System;
78 }
79
80 bool isSymLink(bool ignoreNtfsSymLinks = false) const
81 {
82 if (ignoreNtfsSymLinks) {
83#ifdef Q_OS_WIN
84 return !mFileInfo.suffix().compare(QLatin1StringView("lnk"), Qt::CaseInsensitive);
85#endif
86 }
87 return mFileInfo.isSymLink();
88 }
89
90 bool isHidden() const {
91 return mFileInfo.isHidden();
92 }
93
94 QFileInfo fileInfo() const {
95 return mFileInfo;
96 }
97
98 QDateTime lastModified(const QTimeZone &tz) const {
99 return mFileInfo.lastModified(tz);
100 }
101
102 qint64 size() const {
103 qint64 size = -1;
104 if (type() == QExtendedInformation::Dir)
105 size = 0;
106 if (type() == QExtendedInformation::File)
107 size = mFileInfo.size();
108 if (!mFileInfo.exists() && !mFileInfo.isSymLink())
109 size = -1;
110 return size;
111 }
112
113 QString displayType;
114 QIcon icon;
115
116private :
117 QFileInfo mFileInfo;
118};
119
120class QFileIconProvider;
121
122class Q_GUI_EXPORT QFileInfoGatherer : public QThread
123{
124Q_OBJECT
125
126Q_SIGNALS:
127 void updates(const QString &directory, const QList<QPair<QString, QFileInfo>> &updates);
128 void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
129 void nameResolved(const QString &fileName, const QString &resolvedName) const;
130 void directoryLoaded(const QString &path);
131
132public:
133 explicit QFileInfoGatherer(QObject *parent = nullptr);
134 ~QFileInfoGatherer();
135
136 QStringList watchedFiles() const;
137 QStringList watchedDirectories() const;
138 void watchPaths(const QStringList &paths);
139 void unwatchPaths(const QStringList &paths);
140
141 bool isWatching() const;
142 void setWatching(bool v);
143
144 // only callable from this->thread():
145 void clear();
146 void removePath(const QString &path);
147 QExtendedInformation getInfo(const QFileInfo &info) const;
148 QAbstractFileIconProvider *iconProvider() const;
149 bool resolveSymlinks() const;
150
151public Q_SLOTS:
152 void list(const QString &directoryPath);
153 void fetchExtendedInformation(const QString &path, const QStringList &files);
154 void updateFile(const QString &path);
155 void setResolveSymlinks(bool enable);
156 void setIconProvider(QAbstractFileIconProvider *provider);
157
158private Q_SLOTS:
159 void driveAdded();
160 void driveRemoved();
161
162private:
163 void run() override;
164 // called by run():
165 void getFileInfos(const QString &path, const QStringList &files);
166 void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime,
167 QList<QPair<QString, QFileInfo>> &updatedFiles, const QString &path);
168
169private:
170 void createWatcher();
171
172 mutable QMutex mutex;
173 // begin protected by mutex
174 QWaitCondition condition;
175 QStack<QString> path;
176 QStack<QStringList> files;
177 // end protected by mutex
178 QAtomicInt abort;
179
180#if QT_CONFIG(filesystemwatcher)
181 QFileSystemWatcher *m_watcher = nullptr;
182#endif
183 QAbstractFileIconProvider *m_iconProvider; // not accessed by run()
184 QAbstractFileIconProvider defaultProvider;
185#ifdef Q_OS_WIN
186 bool m_resolveSymlinks = true; // not accessed by run()
187#endif
188#if QT_CONFIG(filesystemwatcher)
189 bool m_watching = true;
190#endif
191};
192
193QT_END_NAMESPACE
194#endif // QFILEINFOGATHERER_H
195

source code of qtbase/src/gui/itemmodels/qfileinfogatherer_p.h