From fe1075332cf0066d47432a98e3a4b68386d6523a Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 1 Nov 2022 16:07:18 +0100 Subject: Windows: simplify registration of QWindowsMime implementations Register the QWindowsMime implementation instance in the QWindowsMime constructor, and remove it again in the destructor. Provide a convenience static method to register a mime type. This makes it a lot easier to use the type, without having to use native interfaces. Since this requires adding a qwindowsmime.cpp file, move the (so far internal) documentation there. Task-number: QTBUG-93632 Change-Id: I3b5e45be6255bd11a576127304c4aec9d7364e69 Reviewed-by: Timur Pocheptsov --- src/gui/CMakeLists.txt | 2 +- src/gui/platform/windows/qwindowsmime.cpp | 153 +++++++++++++++++++++ src/gui/platform/windows/qwindowsmime_p.h | 5 +- .../platforms/windows/qwindowsmimeregistry.cpp | 130 +++-------------- 4 files changed, 175 insertions(+), 115 deletions(-) create mode 100644 src/gui/platform/windows/qwindowsmime.cpp diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 85c14f39ab..6278ea45f9 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -413,7 +413,7 @@ qt_internal_extend_target(Gui CONDITION WIN32 image/qpixmap_win.cpp kernel/qwindowdefs_win.h platform/windows/qwindowsguieventdispatcher.cpp platform/windows/qwindowsguieventdispatcher_p.h - platform/windows/qwindowsmime_p.h + platform/windows/qwindowsmime_p.h platform/windows/qwindowsmime.cpp platform/windows/qwindowsnativeinterface.cpp rhi/cs_tdr_p.h rhi/qrhid3d11.cpp rhi/qrhid3d11_p.h diff --git a/src/gui/platform/windows/qwindowsmime.cpp b/src/gui/platform/windows/qwindowsmime.cpp new file mode 100644 index 0000000000..a60e72dda7 --- /dev/null +++ b/src/gui/platform/windows/qwindowsmime.cpp @@ -0,0 +1,153 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwindowsmime_p.h" + +#include +#include + +using namespace QNativeInterface::Private; + +/*! + \class QWindowsMime + \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. + \internal + + Qt's drag-and-drop and clipboard facilities use the MIME standard. + On X11, this maps trivially to the Xdnd protocol, but on Windows + although some applications use MIME types to describe clipboard + formats, others use arbitrary non-standardized naming conventions, + or unnamed built-in formats of Windows. + + By instantiating subclasses of QWindowsMime that provide conversions + between Windows Clipboard and MIME formats, you can convert + proprietary clipboard formats to MIME formats. + + Qt has predefined support for the following Windows Clipboard formats: + + \table + \header \li Windows Format \li Equivalent MIME type + \row \li \c CF_UNICODETEXT \li \c text/plain + \row \li \c CF_TEXT \li \c text/plain + \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is + a \l{QImageWriter::supportedImageFormats()}{Qt image format} + \row \li \c CF_HDROP \li \c text/uri-list + \row \li \c CF_INETURL \li \c text/uri-list + \row \li \c CF_HTML \li \c text/html + \endtable + + An example use of this class would be to map the Windows Metafile + clipboard format (\c CF_METAFILEPICT) to and from the MIME type + \c{image/x-wmf}. This conversion might simply be adding or removing + a header, or even just passing on the data. See \l{Drag and Drop} + for more information on choosing and definition MIME types. + + You can check if a MIME type is convertible using canConvertFromMime() and + can perform conversions with convertToMime() and convertFromMime(). + + \sa QWindowsMimeRegistry +*/ + + +/*! + \fn bool QWindowsMime::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const + \internal + + Returns \c true if the converter can convert from the \a mimeData to + the format specified in \a formatetc. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn bool QWindowsMime::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const + \internal + + Returns \c true if the converter can convert to the \a mimeType from + the available formats in \a pDataObj. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QString QWindowsMime::mimeForFormat(const FORMATETC &formatetc) const + \internal + + Returns the mime type that will be created form the format specified + in \a formatetc, or an empty string if this converter does not support + \a formatetc. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QList QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const + \internal + + Returns a QList of FORMATETC structures representing the different windows clipboard + formats that can be provided for the \a mimeType from the \a mimeData. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QVariant QWindowsMime::convertToMime(const QString &mimeType, IDataObject *pDataObj, + QMetaType preferredType) const + \internal + + Returns a QVariant containing the converted data for \a mimeType from \a pDataObj. + If possible the QVariant should be of the \a preferredType to avoid needless conversions. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn bool QWindowsMime::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const + \internal + + Convert the \a mimeData to the format specified in \a formatetc. + The converted data should then be placed in \a pmedium structure. + + Return true if the conversion was successful. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + Constructs a QWindowsMime instance. + + The instance is automatically registered, and will be called to convert data during + clipboard or drag'n'drop operations. +*/ +QWindowsMime::QWindowsMime() +{ + auto nativeWindowsApp = dynamic_cast(QGuiApplicationPrivate::platformIntegration()); + Q_ASSERT(nativeWindowsApp); + nativeWindowsApp->registerMime(this); +} + +/*! + Constructs a QWindowsMime instance. + + The instance is automatically unregistered. +*/ +QWindowsMime::~QWindowsMime() +{ + auto nativeWindowsApp = dynamic_cast(QGuiApplicationPrivate::platformIntegration()); + Q_ASSERT(nativeWindowsApp); + nativeWindowsApp->unregisterMime(this); +} + +/*! + Registers the MIME type \a mime, and returns an ID number + identifying the format on Windows. + + A mime type \c {application/x-qt-windows-mime;value="WindowsType"} will be + registered as the clipboard format for \c WindowsType. +*/ +int QWindowsMime::registerMimeType(const QString &mimeType) +{ + auto nativeWindowsApp = dynamic_cast(QGuiApplicationPrivate::platformIntegration()); + Q_ASSERT(nativeWindowsApp); + return nativeWindowsApp->registerMimeType(mimeType); +} diff --git a/src/gui/platform/windows/qwindowsmime_p.h b/src/gui/platform/windows/qwindowsmime_p.h index a2fbd38119..f097a618ef 100644 --- a/src/gui/platform/windows/qwindowsmime_p.h +++ b/src/gui/platform/windows/qwindowsmime_p.h @@ -30,7 +30,10 @@ namespace QNativeInterface::Private { class Q_GUI_EXPORT QWindowsMime { public: - virtual ~QWindowsMime() = default; + QWindowsMime(); + virtual ~QWindowsMime(); + + static int registerMimeType(const QString &mimeType); // for converting from Qt virtual bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const = 0; diff --git a/src/plugins/platforms/windows/qwindowsmimeregistry.cpp b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp index 55d0266bb2..0524cff5f7 100644 --- a/src/plugins/platforms/windows/qwindowsmimeregistry.cpp +++ b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp @@ -333,105 +333,6 @@ QDebug operator<<(QDebug d, IDataObject *dataObj) } #endif // !QT_NO_DEBUG_STREAM -/*! - \class QWindowsMime - \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. - \internal - - Qt's drag-and-drop and clipboard facilities use the MIME standard. - On X11, this maps trivially to the Xdnd protocol, but on Windows - although some applications use MIME types to describe clipboard - formats, others use arbitrary non-standardized naming conventions, - or unnamed built-in formats of Windows. - - By instantiating subclasses of QWindowsMime that provide conversions - between Windows Clipboard and MIME formats, you can convert - proprietary clipboard formats to MIME formats. - - Qt has predefined support for the following Windows Clipboard formats: - - \table - \header \li Windows Format \li Equivalent MIME type - \row \li \c CF_UNICODETEXT \li \c text/plain - \row \li \c CF_TEXT \li \c text/plain - \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is - a \l{QImageWriter::supportedImageFormats()}{Qt image format} - \row \li \c CF_HDROP \li \c text/uri-list - \row \li \c CF_INETURL \li \c text/uri-list - \row \li \c CF_HTML \li \c text/html - \endtable - - An example use of this class would be to map the Windows Metafile - clipboard format (\c CF_METAFILEPICT) to and from the MIME type - \c{image/x-wmf}. This conversion might simply be adding or removing - a header, or even just passing on the data. See \l{Drag and Drop} - for more information on choosing and definition MIME types. - - You can check if a MIME type is convertible using canConvertFromMime() and - can perform conversions with convertToMime() and convertFromMime(). - - \sa QWindowsMimeRegistry -*/ - - -/*! -\fn bool QWindowsMime::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const - - Returns \c true if the converter can convert from the \a mimeData to - the format specified in \a formatetc. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn bool QWindowsMime::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const - - Returns \c true if the converter can convert to the \a mimeType from - the available formats in \a pDataObj. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn QString QWindowsMime::mimeForFormat(const FORMATETC &formatetc) const - - Returns the mime type that will be created form the format specified - in \a formatetc, or an empty string if this converter does not support - \a formatetc. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn QList QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const - - Returns a QList of FORMATETC structures representing the different windows clipboard - formats that can be provided for the \a mimeType from the \a mimeData. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QVariant QWindowsMime::convertToMime(const QString &mimeType, IDataObject *pDataObj, - QMetaType preferredType) const - - Returns a QVariant containing the converted data for \a mimeType from \a pDataObj. - If possible the QVariant should be of the \a preferredType to avoid needless conversions. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn bool QWindowsMime::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const - - Convert the \a mimeData to the format specified in \a formatetc. - The converted data should then be placed in \a pmedium structure. - - Return true if the conversion was successful. - - All subclasses must reimplement this pure virtual function. -*/ - class QWindowsMimeText : public QNativeInterface::Private::QWindowsMime { public: @@ -605,8 +506,8 @@ private: QWindowsMimeURI::QWindowsMimeURI() { - CF_INETURL_W = QWindowsMimeRegistry::registerMimeType(QStringLiteral("UniformResourceLocatorW")); - CF_INETURL = QWindowsMimeRegistry::registerMimeType(QStringLiteral("UniformResourceLocator")); + CF_INETURL_W = registerMimeType(QStringLiteral("UniformResourceLocatorW")); + CF_INETURL = registerMimeType(QStringLiteral("UniformResourceLocator")); } bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const @@ -775,7 +676,7 @@ private: QWindowsMimeHtml::QWindowsMimeHtml() { - CF_HTML = QWindowsMimeRegistry::registerMimeType(QStringLiteral("HTML Format")); + CF_HTML = registerMimeType(QStringLiteral("HTML Format")); } QList QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const @@ -1075,8 +976,8 @@ private: QBuiltInMimes::QBuiltInMimes() : QWindowsMime() { - outFormats.insert(QWindowsMimeRegistry::registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color")); - inFormats.insert(QWindowsMimeRegistry::registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color")); + outFormats.insert(registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color")); + inFormats.insert(registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color")); } bool QBuiltInMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const @@ -1257,7 +1158,7 @@ QList QLastResortMimes::formatsForMime(const QString &mimeType, const auto mit = std::find(formats.begin(), formats.end(), mimeType); // register any other available formats if (mit == formats.end() && !excludeList.contains(mimeType, Qt::CaseInsensitive)) - mit = formats.insert(QWindowsMimeRegistry::registerMimeType(mimeType), mimeType); + mit = formats.insert(registerMimeType(mimeType), mimeType); if (mit != formats.end()) formatetcs += setCf(mit.key()); @@ -1301,7 +1202,7 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD } // if it is not in there then register it and see if we can get it const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType); - const int cf = mit != formats.cend() ? mit.key() : QWindowsMimeRegistry::registerMimeType(mimeType); + const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType); return canGetData(cf, pDataObj); } @@ -1318,7 +1219,7 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p data = getData(int(cf), pDataObj, lindex); } else { const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType); - const int cf = mit != formats.cend() ? mit.key() : QWindowsMimeRegistry::registerMimeType(mimeType); + const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType); data = getData(cf, pDataObj); } if (!data.isEmpty()) @@ -1445,15 +1346,18 @@ QList QWindowsMimeRegistry::allFormatsForMime(const QMimeData *mimeDa void QWindowsMimeRegistry::ensureInitialized() const { - if (m_mimes.isEmpty()) { - m_mimes + if (m_internalMimeCount == 0) { + m_internalMimeCount = -1; // prevent reentrancy when types register themselves #ifndef QT_NO_IMAGEFORMAT_BMP - << new QWindowsMimeImage + (void)new QWindowsMimeImage; #endif //QT_NO_IMAGEFORMAT_BMP - << new QLastResortMimes - << new QWindowsMimeText << new QWindowsMimeURI - << new QWindowsMimeHtml << new QBuiltInMimes; + (void)new QLastResortMimes; + (void)new QWindowsMimeText; + (void)new QWindowsMimeURI; + (void)new QWindowsMimeHtml; + (void)new QBuiltInMimes; m_internalMimeCount = m_mimes.size(); + Q_ASSERT(m_internalMimeCount > 0); } } -- cgit v1.2.3