1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILESYSTEMWATCHER_FSEVENTS_P_H
#define QFILESYSTEMWATCHER_FSEVENTS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qfilesystemwatcher_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qhash.h>
#include <QtCore/qthread.h>
#include <QtCore/qvector.h>
#include <QtCore/qsocketnotifier.h>
#include <dispatch/dispatch.h>
#include <CoreServices/CoreServices.h>
QT_REQUIRE_CONFIG(filesystemwatcher);
QT_BEGIN_NAMESPACE
class QFseventsFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
public:
~QFseventsFileSystemWatcherEngine();
static QFseventsFileSystemWatcherEngine *create(QObject *parent);
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
void processEvent(ConstFSEventStreamRef streamRef, size_t numEvents, char **eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
Q_SIGNALS:
void emitFileChanged(const QString &path, bool removed);
void emitDirectoryChanged(const QString &path, bool removed);
void scheduleStreamRestart();
private slots:
void doEmitFileChanged(const QString &path, bool removed);
void doEmitDirectoryChanged(const QString &path, bool removed);
bool restartStream();
private:
struct Info {
QString origPath;
timespec ctime;
mode_t mode;
QString watchedPath;
Info(): mode(0)
{
ctime.tv_sec = 0;
ctime.tv_nsec = 0;
}
Info(const QString &origPath, const timespec &ctime, mode_t mode, const QString &watchedPath)
: origPath(origPath)
, ctime(ctime)
, mode(mode)
, watchedPath(watchedPath)
{}
};
typedef QHash<QString, Info> InfoByName;
typedef QHash<QString, InfoByName> FilesByPath;
struct DirInfo {
Info dirInfo;
InfoByName entries;
};
typedef QHash<QString, DirInfo> DirsByName;
typedef QHash<QString, qint64> PathRefCounts;
struct WatchingState {
// These fields go hand-in-hand. FSEvents watches paths, and there is no use in watching
// the same path multiple times. So, the "refcount" on a path is the number of watched
// files that have the same path, plus the number of directories that have the same path.
//
// If the stream fails to start after adding files/directories, the watcher will try to
// keep watching files/directories that it was already watching. It does that by restoring
// the previous WatchingState and restarting the stream.
FilesByPath watchedFiles;
DirsByName watchedDirectories;
PathRefCounts watchedPaths;
};
QFseventsFileSystemWatcherEngine(QObject *parent);
bool startStream();
void stopStream(bool isStopped = false);
InfoByName scanForDirEntries(const QString &path);
bool derefPath(const QString &watchedPath);
bool checkDir(DirsByName::iterator &it);
bool rescanDirs(const QString &path);
bool rescanFiles(InfoByName &filesInPath);
bool rescanFiles(const QString &path);
QMutex lock;
dispatch_queue_t queue;
FSEventStreamRef stream;
FSEventStreamEventId lastReceivedEvent;
WatchingState watchingState;
};
QT_END_NAMESPACE
#endif // QFILESYSTEMWATCHER_FSEVENTS_P_H
|