summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemwatcher.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2016-05-24 11:15:16 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2016-10-18 07:52:22 +0000
commit45580aa92557caa4f3f5be783573ddb80602e494 (patch)
tree31abaac0c77ae0588e65b56ea7f2c401492bb4d4 /src/corelib/io/qfilesystemwatcher.cpp
parentae6681673eb5c7768070cad61f483d2a5405dc9e (diff)
QFileSystemWatcher/Win32: Listen for WM_DEVICECHANGE
Add a class QWindowsRemovableDriveListener to QWindowsFileSystemWatcherEngine listening to the WM_DEVICECHANGE messages sent to the top level windows to detect insertion and removal of USB drives. In addition, hook into QWindowsFileSystemWatcherEngine::addPaths() when watching on removable drives, registering a notification for a volume-lock-for-removal message on the internal window handle obtained from QEventDispatcherWin32. When a request to lock the volume for removal is received, remove the paths from the watcher, enabling removal. The class instance is set as a dynamic property on the QFileSystemWatcher where it can be retrieved from clients. This is primarily intended for use by QFileInfoGatherer/QFileSystemModel. Task-number: QTBUG-14290 Task-number: QTBUG-18729 Task-number: QTBUG-55459 Change-Id: Ic95b9d9291b1ec6f426c0702bad896bb064b9346 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/io/qfilesystemwatcher.cpp')
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index a1d90c76f4..612b3fa57c 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -64,6 +64,9 @@
# include "qfilesystemwatcher_fsevents_p.h"
#endif
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject *parent)
@@ -102,6 +105,17 @@ void QFileSystemWatcherPrivate::init()
SIGNAL(directoryChanged(QString,bool)),
q,
SLOT(_q_directoryChanged(QString,bool)));
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveLockForRemoval,
+ q, [this] (const QString &p) { _q_winDriveLockForRemoval(p); });
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveLockForRemovalFailed,
+ q, [this] (const QString &p) { _q_winDriveLockForRemovalFailed(p); });
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveRemoved,
+ q, [this] (const QString &p) { _q_winDriveRemoved(p); });
+#endif // !Q_OS_WINRT
}
}
@@ -146,7 +160,46 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re
emit q->directoryChanged(path, QFileSystemWatcher::QPrivateSignal());
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+void QFileSystemWatcherPrivate::_q_winDriveLockForRemoval(const QString &path)
+{
+ // Windows: Request to lock a (removable/USB) drive for removal, release
+ // its paths under watch, temporarily storing them should the lock fail.
+ Q_Q(QFileSystemWatcher);
+ QStringList pathsToBeRemoved;
+ auto pred = [&path] (const QString &f) { return !f.startsWith(path, Qt::CaseInsensitive); };
+ std::remove_copy_if(files.cbegin(), files.cend(),
+ std::back_inserter(pathsToBeRemoved), pred);
+ std::remove_copy_if(directories.cbegin(), directories.cend(),
+ std::back_inserter(pathsToBeRemoved), pred);
+ if (!pathsToBeRemoved.isEmpty()) {
+ q->removePaths(pathsToBeRemoved);
+ temporarilyRemovedPaths.insert(path.at(0), pathsToBeRemoved);
+ }
+}
+
+void QFileSystemWatcherPrivate::_q_winDriveLockForRemovalFailed(const QString &path)
+{
+ // Windows: Request to lock a (removable/USB) drive failed (blocked by other
+ // application), restore the watched paths.
+ Q_Q(QFileSystemWatcher);
+ if (!path.isEmpty()) {
+ const auto it = temporarilyRemovedPaths.find(path.at(0));
+ if (it != temporarilyRemovedPaths.end()) {
+ q->addPaths(it.value());
+ temporarilyRemovedPaths.erase(it);
+ }
+ }
+}
+void QFileSystemWatcherPrivate::_q_winDriveRemoved(const QString &path)
+{
+ // Windows: Drive finally removed, clear out paths stored in lock request.
+ if (!path.isEmpty())
+ temporarilyRemovedPaths.remove(path.at(0));
+}
+#endif // Q_OS_WIN && !Q_OS_WINRT
/*!
\class QFileSystemWatcher