diff options
Diffstat (limited to 'src/corelib/io/qfilesystemwatcher_win.cpp')
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_win.cpp | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index c385a82fc5..ff0d45935c 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -71,6 +71,19 @@ QT_BEGIN_NAMESPACE # define DEBUG if (false) qDebug #endif +static Qt::HANDLE createChangeNotification(const QString &path, uint flags) +{ + // Volume and folder paths need a trailing slash for proper notification + // (e.g. "c:" -> "c:/"). + QString nativePath = QDir::toNativeSeparators(path); + if ((flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) == 0 && !nativePath.endsWith(QLatin1Char('\\'))) + nativePath.append(QLatin1Char('\\')); + const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()), + FALSE, flags); + DEBUG() << __FUNCTION__ << nativePath << hex <<showbase << flags << "returns" << result; + return result; +} + #ifndef Q_OS_WINRT /////////// // QWindowsRemovableDriveListener @@ -404,8 +417,29 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, thread = *jt; QMutexLocker locker(&(thread->mutex)); - handle = thread->handleForDir.value(QFileSystemWatcherPathKey(absolutePath)); - if (handle.handle != INVALID_HANDLE_VALUE && handle.flags == flags) { + const auto hit = thread->handleForDir.find(QFileSystemWatcherPathKey(absolutePath)); + if (hit != thread->handleForDir.end() && hit.value().flags < flags) { + // Requesting to add a file whose directory has been added previously. + // Recreate the notification handle to add the missing notification attributes + // for files (FILE_NOTIFY_CHANGE_ATTRIBUTES...) + DEBUG() << "recreating" << absolutePath << hex << showbase << hit.value().flags + << "->" << flags; + const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags); + if (fileHandle != INVALID_HANDLE_VALUE) { + const int index = thread->handles.indexOf(hit.value().handle); + const auto pit = thread->pathInfoForHandle.find(hit.value().handle); + Q_ASSERT(index != -1); + Q_ASSERT(pit != thread->pathInfoForHandle.end()); + FindCloseChangeNotification(hit.value().handle); + thread->handles[index] = hit.value().handle = fileHandle; + hit.value().flags = flags; + thread->pathInfoForHandle.insert(fileHandle, pit.value()); + thread->pathInfoForHandle.erase(pit); + } + } + // In addition, check on flags for sufficient notification attributes + if (hit != thread->handleForDir.end() && hit.value().flags >= flags) { + handle = hit.value(); // found a thread now insert... DEBUG() << "Found a thread" << thread; @@ -426,14 +460,9 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, } // no thread found, first create a handle - if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) { + if (handle.handle == INVALID_HANDLE_VALUE) { DEBUG() << "No thread found"; - // Volume and folder paths need a trailing slash for proper notification - // (e.g. "c:" -> "c:/"). - const QString effectiveAbsolutePath = - isDir ? (absolutePath + QLatin1Char('/')) : absolutePath; - - handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags); + handle.handle = createChangeNotification(absolutePath, flags); handle.flags = flags; if (handle.handle == INVALID_HANDLE_VALUE) continue; |