43 #include <qplatformdefs.h> 48 #ifndef QT_NO_FILESYSTEMWATCHER 56 #include <mach/mach.h> 57 #include <sys/types.h> 58 #include <CoreFoundation/CFRunLoop.h> 59 #include <CoreFoundation/CFUUID.h> 60 #if !defined(Q_OS_IOS) 61 #include <CoreServices/CoreServices.h> 63 #include <AvailabilityMacros.h> 64 #include <private/qcore_mac_p.h> 68 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 73 return left.tv_sec == right.tv_sec
74 && left.tv_nsec == right.tv_nsec;
79 return left.st_dev == right.st_dev
80 && left.st_mode == right.st_mode
81 && left.st_size == right.st_size
82 && left.st_ino == right.st_ino
83 && left.st_uid == right.st_uid
84 && left.st_gid == right.st_gid
85 && left.st_mtimespec == right.st_mtimespec
86 && left.st_ctimespec == right.st_ctimespec
87 && left.st_flags == right.st_flags;
99 PathInfoList &list = pathHash[
key];
100 list.push_back(PathInfo(path,
102 pathHash.
insert(key, list);
107 PathInfoList &list = pathHash[
key];
109 PathInfoList::iterator
End = list.end();
110 PathInfoList::iterator
it = list.begin();
112 if (it->originalPath == path) {
125 FSEventStreamStop(stream);
126 FSEventStreamInvalidate(stream);
134 string.
reserve(
string.size() + 1);
142 FSEventStreamRelease(stream);
145 const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer );
147 const CFTimeInterval Latency = 0.033;
151 : fsStream(0), pathsToWatch(0), threadsRunLoop(0)
157 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 176 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 184 idToCheck = FSEventStreamGetLatestEventId(
fsStream);
187 idToCheck = kFSEventStreamEventIdSinceNow;
198 for (
int i = 0; i < paths.
size(); ++i) {
207 if (fileInfo.
isDir()) {
212 directories->
append(path);
215 addPathToHash(dirPathInfoHash, cfpath, fileInfo, path);
216 CFArrayAppendValue(tmpArray, cfpath);
226 addPathToHash(filePathInfoHash, cfpath, fileInfo, path);
227 CFArrayAppendValue(tmpArray, cfpath);
236 if (CFArrayGetCount(tmpArray) > 0) {
241 pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
244 FSEventStreamContext context = { 0,
this, 0, 0, 0 };
245 fsStream = FSEventStreamCreate(kCFAllocatorDefault,
248 idToCheck, Latency, QtFSEventFlags);
262 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 274 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 285 idToCheck = FSEventStreamGetLatestEventId(
fsStream);
289 idToCheck = kFSEventStreamEventIdSinceNow;
297 for (
int i = 0; i < paths.
size(); ++i) {
299 itemCount = CFArrayGetCount(tmpArray);
304 CFIndex
index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath);
306 CFArrayRemoveValueAtIndex(tmpArray, index);
308 removePathFromHash(filePathInfoHash, cfpath, path);
312 index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath);
314 CFArrayRemoveValueAtIndex(tmpArray, index);
316 removePathFromHash(dirPathInfoHash, cfpath, path);
318 failedToRemove.
append(path);
322 itemCount = CFArrayGetCount(tmpArray);
323 if (itemCount != 0) {
324 pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
326 FSEventStreamContext context = { 0,
this, 0, 0, 0 };
327 fsStream = FSEventStreamCreate(kCFAllocatorDefault,
329 &context,
pathsToWatch, idToCheck, Latency, QtFSEventFlags);
332 return failedToRemove;
341 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 342 void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list,
bool directory,
bool emitSignals)
344 PathInfoList::iterator End = list.end();
345 PathInfoList::iterator it = list.begin();
347 struct ::stat64 newInfo;
348 if (::stat64(it->absolutePath, &newInfo) == 0) {
350 if (newInfo != it->savedInfo) {
351 it->savedInfo = newInfo;
358 it->savedInfo = newInfo;
361 if (
errno == ENOENT) {
371 qWarning(
"%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s",
380 void QFSEventsFileSystemWatcherEngine::updateHash(
PathHash &pathHash)
384 const bool IsDirectory = (&pathHash == &dirPathInfoHash);
385 while (it != HashEnd) {
386 updateList(it.value(), IsDirectory,
false);
387 if (it.value().isEmpty())
388 it = pathHash.
erase(it);
396 void *clientCallBackInfo,
size_t numEvents,
401 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 405 for (
size_t i = 0; i < numEvents; ++i) {
407 static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i)));
420 if (watcher->filePathInfoHash.contains(path))
421 watcher->updateList(watcher->filePathInfoHash[path],
false,
true);
423 if (watcher->dirPathInfoHash.contains(path))
424 watcher->updateList(watcher->dirPathInfoHash[path],
true,
true);
436 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 448 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 450 updateHash(filePathInfoHash);
451 updateHash(dirPathInfoHash);
452 if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) {
454 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 472 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(Q_OS_IOS) 475 bool startedOK = FSEventStreamStart(
fsStream);
494 #endif //QT_NO_FILESYSTEMWATCHER void fileChanged(const QString &path, bool removed)
#define QT_END_NAMESPACE
This macro expands to.
int remove(const Key &key)
Removes all the items that have the key from the hash.
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories)
#define it(className, varName)
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
static QFSEventsFileSystemWatcherEngine * create()
const struct __FSEventStream * ConstFSEventStreamRef
static QString toQString(CFStringRef cfstr)
bool exists() const
Returns true if the file exists; otherwise returns false.
UInt32 FSEventStreamEventFlags
The QString class provides a Unicode character string.
QString normalized(NormalizationForm mode) const Q_REQUIRED_RESULT
Returns the string in the given Unicode normalization mode.
struct __FSEventStream * FSEventStreamRef
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
void reserve(int size)
Attempts to allocate memory for at least size characters.
FSEventStreamRef fsStream
void append(const T &t)
Inserts value at the end of the list.
QTextStream & right(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight) on stream and returns stream...
#define QT_BEGIN_NAMESPACE
This macro expands to.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory; otherwise ret...
QFSEventsFileSystemWatcherEngine()
CFRunLoopRef threadsRunLoop
const T & at(int i) const
Returns the item at index position i in the list.
The QStringList class provides a list of strings.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
Q_CORE_EXPORT void qWarning(const char *,...)
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[])
void directoryChanged(const QString &path, bool removed)
QString canonicalPath() const
Returns the file's path canonical path (excluding the file name), i.e.
bool wait(QMutex *mutex, unsigned long time=ULONG_MAX)
bool operator!=(const T *o, const QPointer< T > &p)
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
int size() const
Returns the number of items in the list.
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
bool operator==(const T *o, const QPointer< T > &p)
QWaitCondition waitCondition
uint64_t FSEventStreamEventId
The QFileInfo class provides system-independent file information.
const struct __CFArray * CFArrayRef
#define qPrintable(string)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories)
virtual IFMETHOD End(void)=0
iterator erase(iterator it)
Removes the (key, value) pair associated with the iterator pos from the hash, and returns an iterator...
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
~QFSEventsFileSystemWatcherEngine()
void run()
The starting point for the thread.
int removeAll(const T &t)
Removes all occurrences of value in the list and returns the number of entries removed.
QTextStream & left(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft) on stream and returns stream...
QWaitCondition waitForStop