File indexing completed on 2024-05-19 04:56:02

0001 /**
0002  * \file fileinfogatherer_p.h
0003  * \cond
0004  * Taken from Qt Git, revision e73bd4a
0005  * qtbase/src/widgets/dialogs/qfileinfogatherer_p.h
0006  * Adapted for Kid3 with the following changes:
0007  * - Remove Q prefix from class names
0008  * - Remove QT_..._CONFIG, QT_..._NAMESPACE, Q_..._EXPORT...
0009  * - Allow compilation without Qt private headers (USE_QT_PRIVATE_HEADERS)
0010  * - Replace include guards by #pragma once
0011  * - Remove dependencies to Qt5::Widgets
0012  */
0013 /****************************************************************************
0014 **
0015 ** Copyright (C) 2016 The Qt Company Ltd.
0016 ** Contact: https://www.qt.io/licensing/
0017 **
0018 ** This file is part of the QtWidgets module of the Qt Toolkit.
0019 **
0020 ** $QT_BEGIN_LICENSE:LGPL$
0021 ** Commercial License Usage
0022 ** Licensees holding valid commercial Qt licenses may use this file in
0023 ** accordance with the commercial license agreement provided with the
0024 ** Software or, alternatively, in accordance with the terms contained in
0025 ** a written agreement between you and The Qt Company. For licensing terms
0026 ** and conditions see https://www.qt.io/terms-conditions. For further
0027 ** information use the contact form at https://www.qt.io/contact-us.
0028 **
0029 ** GNU Lesser General Public License Usage
0030 ** Alternatively, this file may be used under the terms of the GNU Lesser
0031 ** General Public License version 3 as published by the Free Software
0032 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
0033 ** packaging of this file. Please review the following information to
0034 ** ensure the GNU Lesser General Public License version 3 requirements
0035 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
0036 **
0037 ** GNU General Public License Usage
0038 ** Alternatively, this file may be used under the terms of the GNU
0039 ** General Public License version 2.0 or (at your option) the GNU General
0040 ** Public license version 3 or any later version approved by the KDE Free
0041 ** Qt Foundation. The licenses are as published by the Free Software
0042 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
0043 ** included in the packaging of this file. Please review the following
0044 ** information to ensure the GNU General Public License requirements will
0045 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
0046 ** https://www.gnu.org/licenses/gpl-3.0.html.
0047 **
0048 ** $QT_END_LICENSE$
0049 **
0050 ****************************************************************************/
0051 
0052 #pragma once
0053 
0054 //
0055 //  W A R N I N G
0056 //  -------------
0057 //
0058 // This file is not part of the Qt API.  It exists purely as an
0059 // implementation detail.  This header file may change from version to
0060 // version without notice, or even be removed.
0061 //
0062 // We mean it.
0063 //
0064 
0065 #include <qthread.h>
0066 #include <qmutex.h>
0067 #include <qwaitcondition.h>
0068 #include <qfilesystemwatcher.h>
0069 #include <qvariant.h>
0070 #include <qpair.h>
0071 #include <qstack.h>
0072 #include <qdatetime.h>
0073 #include <qdir.h>
0074 #include <qelapsedtimer.h>
0075 
0076 #ifdef USE_QT_PRIVATE_HEADERS
0077 #include <private/qfilesystemengine_p.h>
0078 #endif
0079 
0080 class ExtendedInformation {
0081 public:
0082     enum Type { Dir, File, System };
0083 
0084     ExtendedInformation() {}
0085     explicit ExtendedInformation(const QFileInfo &info) : mFileInfo(info) {}
0086 
0087     inline bool isDir() { return type() == Dir; }
0088     inline bool isFile() { return type() == File; }
0089     inline bool isSystem() { return type() == System; }
0090 
0091     bool operator ==(const ExtendedInformation &fileInfo) const {
0092        return mFileInfo == fileInfo.mFileInfo
0093        && displayType == fileInfo.displayType
0094        && permissions() == fileInfo.permissions()
0095        && lastModified() == fileInfo.lastModified();
0096     }
0097 
0098 #ifndef QT_NO_FSFILEENGINE
0099     bool isCaseSensitive() const {
0100 #ifdef USE_QT_PRIVATE_HEADERS
0101         return QFileSystemEngine::isCaseSensitive();
0102 #else
0103         return false;
0104 #endif
0105     }
0106 #endif
0107 
0108     QFile::Permissions permissions() const {
0109 #ifdef Q_OS_WIN
0110         if (isInvalidDrive(mFileInfo.filePath())) {
0111             return {};
0112         }
0113 #endif
0114         return mFileInfo.permissions();
0115     }
0116 
0117     Type type() const {
0118         if (mFileInfo.isDir()) {
0119             return ExtendedInformation::Dir;
0120         }
0121         if (mFileInfo.isFile()) {
0122             return ExtendedInformation::File;
0123         }
0124         if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
0125             return ExtendedInformation::System;
0126         }
0127         return ExtendedInformation::System;
0128     }
0129 
0130     bool isSymLink(bool ignoreNtfsSymLinks = false) const
0131     {
0132         if (ignoreNtfsSymLinks) {
0133 #ifdef Q_OS_WIN
0134             return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
0135 #endif
0136         }
0137         return mFileInfo.isSymLink();
0138     }
0139 
0140     bool isHidden() const {
0141         return mFileInfo.isHidden();
0142     }
0143 
0144     QFileInfo fileInfo() const {
0145         return mFileInfo;
0146     }
0147 
0148     QDateTime lastModified() const {
0149         return mFileInfo.lastModified();
0150     }
0151 
0152     qint64 size() const {
0153         qint64 size = -1;
0154         if (type() == ExtendedInformation::Dir)
0155             size = 0;
0156         if (type() == ExtendedInformation::File)
0157             size = mFileInfo.size();
0158         if (!mFileInfo.exists() && !mFileInfo.isSymLink())
0159             size = -1;
0160         return size;
0161     }
0162 
0163     QString displayType;
0164     QVariant icon;
0165 
0166 private :
0167 #ifdef Q_OS_WIN
0168     static bool isInvalidDrive(const QString &path);
0169 #endif
0170     QFileInfo mFileInfo;
0171 };
0172 
0173 class AbstractFileDecorationProvider;
0174 
0175 class FileInfoGatherer : public QThread
0176 {
0177 Q_OBJECT
0178 
0179 Q_SIGNALS:
0180     void updates(const QString &directory, const QVector<QPair<QString, QFileInfo> > &updates);
0181     void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
0182     void nameResolved(const QString &fileName, const QString &resolvedName) const;
0183     void directoryLoaded(const QString &path);
0184 
0185 public:
0186     explicit FileInfoGatherer(QObject *parent = 0);
0187     ~FileInfoGatherer();
0188 
0189     // only callable from this->thread():
0190     void clear();
0191     void addPath(const QString &path);
0192     void removePath(const QString &path);
0193     ExtendedInformation getInfo(const QFileInfo &fileInfo) const;
0194     AbstractFileDecorationProvider *decorationProvider() const;
0195     bool resolveSymlinks() const;
0196 
0197 public Q_SLOTS:
0198     void list(const QString &directoryPath);
0199     void fetchExtendedInformation(const QString &path, const QStringList &files);
0200     void updateFile(const QString &filePath);
0201     void setResolveSymlinks(bool enable);
0202     void setDecorationProvider(AbstractFileDecorationProvider *provider);
0203 
0204 private Q_SLOTS:
0205     void driveAdded();
0206     void driveRemoved();
0207 
0208 private:
0209     void run() Q_DECL_OVERRIDE;
0210     // called by run():
0211     void getFileInfos(const QString &path, const QStringList &files);
0212     void fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
0213 
0214 private:
0215     mutable QMutex mutex;
0216     // begin protected by mutex
0217     QWaitCondition condition;
0218     QStack<QString> path;
0219     QStack<QStringList> files;
0220     // end protected by mutex
0221     QAtomicInt abort;
0222 
0223 #ifndef QT_NO_FILESYSTEMWATCHER
0224     QFileSystemWatcher *watcher;
0225 #endif
0226 #ifdef Q_OS_WIN
0227     bool m_resolveSymlinks; // not accessed by run()
0228 #endif
0229     AbstractFileDecorationProvider *m_decorationProvider;
0230 };
0231 /** \endcond */