diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-05-24 11:15:16 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-10-18 07:52:22 +0000 |
commit | 45580aa92557caa4f3f5be783573ddb80602e494 (patch) | |
tree | 31abaac0c77ae0588e65b56ea7f2c401492bb4d4 /src/corelib/io/qfilesystemwatcher.cpp | |
parent | ae6681673eb5c7768070cad61f483d2a5405dc9e (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.cpp | 53 |
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 |