From 035c78be3c28cceda7c8a811f312f92c571049f5 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 18 Sep 2018 11:09:37 +1000 Subject: [PATCH] Add native platform interface for usb storage events Allows native interfaces to send a signal when a USB storage device is inserted/removed Refs #14481 --- src/app/qgisapp.cpp | 7 +++++-- src/native/CMakeLists.txt | 12 +++++++++++- src/native/qgsnative.h | 20 +++++++++++++++++++- src/native/win/qgswinnative.cpp | 30 ++++++++++++++++++++++++++++++ src/native/win/qgswinnative.h | 22 ++++++++++++++++++++-- 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 959703cd76c..974630a90e3 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -1321,8 +1321,11 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh QgsGui::instance()->nativePlatformInterface()->initializeMainWindow( windowHandle(), QgsApplication::applicationName(), QgsApplication::organizationName(), - Qgis::QGIS_VERSION - ); + Qgis::QGIS_VERSION ); + connect( QgsGui::instance()->nativePlatformInterface(), &QgsNative::usbStorageNotification, this, [ = ]( const QString & path, bool inserted ) + { + QgsDebugMsg( QStringLiteral( "USB STORAGE NOTIFICATION! %1 %2" ).arg( path ).arg( inserted ? QStringLiteral( "inserted" ) : QStringLiteral( "removed" ) ) ); + } ); // setup application progress reports from task manager connect( QgsApplication::taskManager(), &QgsTaskManager::taskAdded, this, [] diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index 6df2b6ab080..e38ea09c7af 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -36,6 +36,10 @@ SET(QGIS_NATIVE_SRCS qgsnative.cpp ) +SET (QGIS_NATIVE_MOC_HDRS + qgsnative.h +) + IF(APPLE) SET(QGIS_APP_OBJC_SRCS mac/cocoainitializer.mm @@ -54,6 +58,10 @@ IF(WIN32) ../../external/wintoast/src/wintoastlib.cpp win/qgswinnative.cpp ) + SET (QGIS_NATIVE_MOC_HDRS + ${QGIS_NATIVE_MOC_HDRS} + win/qgswinnative.h + ) SET(QGIS_NATIVE_SRCS ${QGIS_NATIVE_SRCS} ${QGIS_APP_WIN32_SRCS} ) @@ -72,6 +80,8 @@ SET(QGIS_NATIVE_HDRS qgsnative.h ) +QT5_WRAP_CPP(QGIS_NATIVE_MOC_SRCS ${QGIS_NATIVE_MOC_HDRS}) + # install headers IF(APPLE) @@ -107,7 +117,7 @@ ENDIF(WIN32) ############################################################# # qgis_native library -ADD_LIBRARY(qgis_native SHARED ${QGIS_NATIVE_SRCS} ${QGIS_NATIVE_HDRS}) +ADD_LIBRARY(qgis_native SHARED ${QGIS_NATIVE_SRCS} ${QGIS_NATIVE_MOC_SRCS} ${QGIS_NATIVE_HDRS} ${QGIS_NATIVE_MOC_HDRS}) SET_PROPERTY(TARGET qgis_native PROPERTY POSITION_INDEPENDENT_CODE ON) GENERATE_EXPORT_HEADER( diff --git a/src/native/qgsnative.h b/src/native/qgsnative.h index 21b64ad0742..75c4d70d03a 100644 --- a/src/native/qgsnative.h +++ b/src/native/qgsnative.h @@ -22,6 +22,7 @@ #include #include #include +#include class QString; class QWindow; @@ -33,8 +34,10 @@ class QWindow; * are implemented in subclasses to provide platform abstraction. * \since QGIS 3.0 */ -class NATIVE_EXPORT QgsNative +class NATIVE_EXPORT QgsNative : public QObject { + Q_OBJECT + public: //! Native interface capabilities @@ -215,6 +218,21 @@ class NATIVE_EXPORT QgsNative * \since QGIS 3.4 */ virtual void onRecentProjectsChanged( const std::vector< RecentProjectProperties > &recentProjects ); + + signals: + + /** + * Emitted whenever a USB storage device has been inserted or removed. + * + * The \a path argument gives the file path to the device (if available). + * + * If \a inserted is true then the device was inserted. If \a inserted is false then + * the device was removed. + * + * \since QGIS 3.4 + */ + void usbStorageNotification( const QString &path, bool inserted ); + }; Q_DECLARE_OPERATORS_FOR_FLAGS( QgsNative::Capabilities ) diff --git a/src/native/win/qgswinnative.cpp b/src/native/win/qgswinnative.cpp index fa3eb6e0002..35af872d2c5 100644 --- a/src/native/win/qgswinnative.cpp +++ b/src/native/win/qgswinnative.cpp @@ -21,12 +21,14 @@ #include #include #include +#include #include #include #include #include #include #include "wintoastlib.h" +#include QgsNative::Capabilities QgsWinNative::capabilities() const { @@ -57,6 +59,10 @@ void QgsWinNative::initializeMainWindow( QWindow *window, mWinToastInitialized = true; mCapabilities = mCapabilities | NativeDesktopNotifications; } + + mNativeEventFilter = new QgsWinNativeEventFilter(); + QAbstractEventDispatcher::instance()->installNativeEventFilter( mNativeEventFilter ); + connect( mNativeEventFilter, &QgsWinNativeEventFilter::usbStorageNotification, this, &QgsNative::usbStorageNotification ); } void QgsWinNative::cleanup() @@ -156,3 +162,27 @@ QgsNative::NotificationResult QgsWinNative::showDesktopNotification( const QStri return result; } + +bool QgsWinNativeEventFilter::nativeEventFilter( const QByteArray &, void *message, long * ) +{ + MSG *pWindowsMessage = static_cast( message ); + unsigned int wParam = pWindowsMessage->wParam; + if ( wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE ) + { + long lParam = pWindowsMessage->lParam; + unsigned long deviceType = reinterpret_cast( lParam )->dbch_devicetype; + if ( deviceType == DBT_DEVTYP_VOLUME ) + { + unsigned long unitmask = reinterpret_cast( lParam )->dbcv_unitmask; + for ( int i = 0; i < 32; ++i ) + { + if ( ( unitmask & ( 1 << i ) ) != 0 ) + { + const QChar drive( 65 + i ); + emit usbStorageNotification( QStringLiteral( "%1:/" ).arg( drive ), wParam == DBT_DEVICEARRIVAL ); + } + } + } + } + return false; +} diff --git a/src/native/win/qgswinnative.h b/src/native/win/qgswinnative.h index 140f209c0cc..d6a3336e53b 100644 --- a/src/native/win/qgswinnative.h +++ b/src/native/win/qgswinnative.h @@ -19,14 +19,30 @@ #define QGSMACNATIVE_H #include "qgsnative.h" -#include -#include +#include + +#include +#include #pragma comment(lib,"Shell32.lib") class QWinTaskbarButton; class QWinTaskbarProgress; class QWindow; + +class QgsWinNativeEventFilter : public QObject, public QAbstractNativeEventFilter +{ + Q_OBJECT + public: + + bool nativeEventFilter( const QByteArray &eventType, void *message, long * ) override; + + signals: + + void usbStorageNotification( const QString &path, bool inserted ); +}; + + class NATIVE_EXPORT QgsWinNative : public QgsNative { public: @@ -49,6 +65,8 @@ class NATIVE_EXPORT QgsWinNative : public QgsNative bool mWinToastInitialized = false; QWinTaskbarButton *mTaskButton = nullptr; QWinTaskbarProgress *mTaskProgress = nullptr; + QgsWinNativeEventFilter *mNativeEventFilter = nullptr; + }; #endif // QGSMACNATIVE_H