From efbc53858725ec8563bb97423d9bf789c41cf79f Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 5 Nov 2014 16:53:46 +0100 Subject: qwindowsmime.cpp: support dropping multiple mail attachments Only the data for the first file could be reached with the mimetype application/x-qt-windows-mime;value="FileContents" To get the data for the other files, setting the lindex field of the FORMATETC struct is necessary. Provide support for that by appending ;index=N to the mimetype string. The Windows API provides no generic way to find out how many of these are available (the app has to find out by looking into the FILEGROUPDESCRIPTORW structure, for this particular use case), so these additional mimetypes are not listed in QMimeData::formats(). However this patch extends the documentation to mention the feature. [ChangeLog][Platform Specific Changes][Windows][QMimeData] Add support for handling dropping of multiple mail attachments, adding ;index=N to the mimetype string application/x-qt-windows-mime;value="FileContents" Task-number: QTBUG-17373 Change-Id: I031e477d2357b4e5135d2dcd3e3cf991025715a5 Reviewed-by: Andy Shaw Reviewed-by: Friedemann Kleint --- .../snippets/code/src_corelib_kernel_qmimedata.cpp | 6 +++++ src/corelib/kernel/qmimedata.cpp | 5 ++++ src/plugins/platforms/windows/qwindowsmime.cpp | 27 +++++++++++++++++----- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp index 7f42cd8def..278a00fdfd 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmimedata.cpp @@ -106,3 +106,9 @@ if (event->mimeData()->hasColor()) { ... } //! [7] + + +//! [8] +application/x-qt-windows-mime;value="FileContents";index=0 +application/x-qt-windows-mime;value="FileContents";index=1 +//! [8] diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index 15fdf57747..45aec88429 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -286,6 +286,11 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty The \c value declaration of each format describes the way in which the data is encoded. + In some cases (e.g. dropping multiple email attachments), multiple data + values are available. They can be accessed by adding an \c index value: + + \snippet code/src_corelib_kernel_qmimedata.cpp 8 + On Windows, the MIME format does not always map directly to the clipboard formats. Qt provides QWinMime to map clipboard formats to open-standard MIME formats. Similarly, the diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 2de1477f29..42f4e66d6c 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -343,10 +343,11 @@ static bool setData(const QByteArray &data, STGMEDIUM *pmedium) return true; } -static QByteArray getData(int cf, IDataObject *pDataObj) +static QByteArray getData(int cf, IDataObject *pDataObj, int lindex = -1) { QByteArray data; FORMATETC formatetc = setCf(cf); + formatetc.lindex = lindex; STGMEDIUM s; if (pDataObj->GetData(&formatetc, &s) == S_OK) { DWORD * val = (DWORD*)GlobalLock(s.hGlobal); @@ -1339,16 +1340,29 @@ static bool isCustomMimeType(const QString &mimeType) return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive); } -static QString customMimeType(const QString &mimeType) +static QString customMimeType(const QString &mimeType, int *lindex = 0) { int len = sizeof(x_qt_windows_mime) - 1; - int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len; - return mimeType.mid(len, n); + int n = mimeType.lastIndexOf(QLatin1Char('\"')) - len; + QString ret = mimeType.mid(len, n); + + const int beginPos = mimeType.indexOf(QLatin1String(";index=")); + if (beginPos > -1) { + const int endPos = mimeType.indexOf(QLatin1Char(';'), beginPos + 1); + const int indexStartPos = beginPos + 7; + if (lindex) + *lindex = mimeType.midRef(indexStartPos, endPos == -1 ? endPos : endPos - indexStartPos).toInt(); + } else { + if (lindex) + *lindex = -1; + } + return ret; } bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { if (isCustomMimeType(mimeType)) { + // MSDN documentation for QueryGetData says only -1 is supported, so ignore lindex here. QString clipFormat = customMimeType(mimeType); int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); return canGetData(cf, pDataObj); @@ -1369,9 +1383,10 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p if (canConvertToMime(mimeType, pDataObj)) { QByteArray data; if (isCustomMimeType(mimeType)) { - QString clipFormat = customMimeType(mimeType); + int lindex; + QString clipFormat = customMimeType(mimeType, &lindex); int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); - data = getData(cf, pDataObj); + data = getData(cf, pDataObj, lindex); } else if (formats.keys(mimeType).isEmpty()) { int cf = QWindowsMime::registerMimeType(mimeType); data = getData(cf, pDataObj); -- cgit v1.2.3