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 <QtWidgets/private/qtwidgetsglobal_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 <qfileiconprovider.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 71 QT_REQUIRE_CONFIG(filesystemmodel); 72 73 QT_BEGIN_NAMESPACE 74 75 class QExtendedInformation { 76 public: 77 enum Type { Dir, File, System }; 78 QExtendedInformation()79 QExtendedInformation() {} QExtendedInformation(const QFileInfo & info)80 QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {} 81 isDir()82 inline bool isDir() { return type() == Dir; } isFile()83 inline bool isFile() { return type() == File; } isSystem()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 isCaseSensitive()94 bool isCaseSensitive() const { 95 return QFileSystemEngine::isCaseSensitive(); 96 } 97 #endif 98 permissions()99 QFile::Permissions permissions() const { 100 return mFileInfo.permissions(); 101 } 102 type()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 isHidden()126 bool isHidden() const { 127 return mFileInfo.isHidden(); 128 } 129 fileInfo()130 QFileInfo fileInfo() const { 131 return mFileInfo; 132 } 133 lastModified()134 QDateTime lastModified() const { 135 return mFileInfo.lastModified(); 136 } 137 size()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 152 private : 153 QFileInfo mFileInfo; 154 }; 155 156 class QFileIconProvider; 157 158 class Q_AUTOTEST_EXPORT QFileInfoGatherer : public QThread 159 { 160 Q_OBJECT 161 162 Q_SIGNALS: 163 void updates(const QString &directory, const QVector<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 168 public: 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 QFileIconProvider *iconProvider() const; 185 bool resolveSymlinks() const; 186 187 public 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(QFileIconProvider *provider); 193 194 private Q_SLOTS: 195 void driveAdded(); 196 void driveRemoved(); 197 198 private: 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, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path); 203 204 private: 205 void createWatcher(); 206 207 mutable QMutex mutex; 208 // begin protected by mutex 209 QWaitCondition condition; 210 QStack<QString> path; 211 QStack<QStringList> files; 212 // end protected by mutex 213 QAtomicInt abort; 214 215 #if QT_CONFIG(filesystemwatcher) 216 QFileSystemWatcher *m_watcher = nullptr; 217 #endif 218 QFileIconProvider *m_iconProvider; // not accessed by run() 219 QFileIconProvider defaultProvider; 220 #ifdef Q_OS_WIN 221 bool m_resolveSymlinks = true; // not accessed by run() 222 #endif 223 #if QT_CONFIG(filesystemwatcher) 224 bool m_watching = true; 225 #endif 226 }; 227 228 QT_END_NAMESPACE 229 #endif // QFILEINFOGATHERER_H 230