1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QFILEINFOGATHERER_H
41#define QFILEINFOGATHERER_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtGui/private/qtguiglobal_p.h>
55
56#include <qthread.h>
57#include <qmutex.h>
58#include <qwaitcondition.h>
59#if QT_CONFIG(filesystemwatcher)
60#include <qfilesystemwatcher.h>
61#endif
62#include <qabstractfileiconprovider.h>
63#include <qpair.h>
64#include <qstack.h>
65#include <qdatetime.h>
66#include <qdir.h>
67#include <qelapsedtimer.h>
68
69#include <private/qfilesystemengine_p.h>
70
71QT_REQUIRE_CONFIG(filesystemmodel);
72
73QT_BEGIN_NAMESPACE
74
75class QExtendedInformation {
76public:
77 enum Type { Dir, File, System };
78
79 QExtendedInformation() {}
80 QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {}
81
82 inline bool isDir() { return type() == Dir; }
83 inline bool isFile() { return type() == File; }
84 inline bool isSystem() { return type() == System; }
85
86 bool operator ==(const QExtendedInformation &fileInfo) const {
87 return mFileInfo == fileInfo.mFileInfo
88 && displayType == fileInfo.displayType
89 && permissions() == fileInfo.permissions()
90 && lastModified() == fileInfo.lastModified();
91 }
92
93#ifndef QT_NO_FSFILEENGINE
94 bool isCaseSensitive() const {
95 return QFileSystemEngine::isCaseSensitive();
96 }
97#endif
98
99 QFile::Permissions permissions() const {
100 return mFileInfo.permissions();
101 }
102
103 Type type() const {
104 if (mFileInfo.isDir()) {
105 return QExtendedInformation::Dir;
106 }
107 if (mFileInfo.isFile()) {
108 return QExtendedInformation::File;
109 }
110 if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
111 return QExtendedInformation::System;
112 }
113 return QExtendedInformation::System;
114 }
115
116 bool isSymLink(bool ignoreNtfsSymLinks = false) const
117 {
118 if (ignoreNtfsSymLinks) {
119#ifdef Q_OS_WIN
120 return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
121#endif
122 }
123 return mFileInfo.isSymLink();
124 }
125
126 bool isHidden() const {
127 return mFileInfo.isHidden();
128 }
129
130 QFileInfo fileInfo() const {
131 return mFileInfo;
132 }
133
134 QDateTime lastModified() const {
135 return mFileInfo.lastModified();
136 }
137
138 qint64 size() const {
139 qint64 size = -1;
140 if (type() == QExtendedInformation::Dir)
141 size = 0;
142 if (type() == QExtendedInformation::File)
143 size = mFileInfo.size();
144 if (!mFileInfo.exists() && !mFileInfo.isSymLink())
145 size = -1;
146 return size;
147 }
148
149 QString displayType;
150 QIcon icon;
151
152private :
153 QFileInfo mFileInfo;
154};
155
156class QFileIconProvider;
157
158class Q_GUI_EXPORT QFileInfoGatherer : public QThread
159{
160Q_OBJECT
161
162Q_SIGNALS:
163 void updates(const QString &directory, const QList<QPair<QString, QFileInfo>> &updates);
164 void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
165 void nameResolved(const QString &fileName, const QString &resolvedName) const;
166 void directoryLoaded(const QString &path);
167
168public:
169 explicit QFileInfoGatherer(QObject *parent = nullptr);
170 ~QFileInfoGatherer();
171
172 QStringList watchedFiles() const;
173 QStringList watchedDirectories() const;
174 void watchPaths(const QStringList &paths);
175 void unwatchPaths(const QStringList &paths);
176
177 bool isWatching() const;
178 void setWatching(bool v);
179
180 // only callable from this->thread():
181 void clear();
182 void removePath(const QString &path);
183 QExtendedInformation getInfo(const QFileInfo &info) const;
184 QAbstractFileIconProvider *iconProvider() const;
185 bool resolveSymlinks() const;
186
187public Q_SLOTS:
188 void list(const QString &directoryPath);
189 void fetchExtendedInformation(const QString &path, const QStringList &files);
190 void updateFile(const QString &path);
191 void setResolveSymlinks(bool enable);
192 void setIconProvider(QAbstractFileIconProvider *provider);
193
194private Q_SLOTS:
195 void driveAdded();
196 void driveRemoved();
197
198private:
199 void run() override;
200 // called by run():
201 void getFileInfos(const QString &path, const QStringList &files);
202 void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime,
203 QList<QPair<QString, QFileInfo>> &updatedFiles, const QString &path);
204
205private:
206 void createWatcher();
207
208 mutable QMutex mutex;
209 // begin protected by mutex
210 QWaitCondition condition;
211 QStack<QString> path;
212 QStack<QStringList> files;
213 // end protected by mutex
214 QAtomicInt abort;
215
216#if QT_CONFIG(filesystemwatcher)
217 QFileSystemWatcher *m_watcher = nullptr;
218#endif
219 QAbstractFileIconProvider *m_iconProvider; // not accessed by run()
220 QAbstractFileIconProvider defaultProvider;
221#ifdef Q_OS_WIN
222 bool m_resolveSymlinks = true; // not accessed by run()
223#endif
224#if QT_CONFIG(filesystemwatcher)
225 bool m_watching = true;
226#endif
227};
228
229QT_END_NAMESPACE
230#endif // QFILEINFOGATHERER_H
231