Leuven, E. wrote:
> Yes, that's a good idea. Can you have a look at the clipboard
> copy-pasting of metafile data?
was already looking at that (thus my installer request ;-), the attached
is what i have. the getdata call seems to be unsuccessful so i am doing
something wrong.
am a bit stuck here i must admit...
The Qt stuff would have been the difficult part for me :) To obtain the
metafile data you just need a few API calls. The attached patch works
fine for me.
This is really a great feature. I can now copy graphics from any Windows
application!
Joost
Index: src/frontends/Clipboard.h
===================================================================
--- src/frontends/Clipboard.h (revision 24136)
+++ src/frontends/Clipboard.h (working copy)
@@ -37,6 +37,8 @@
PngGraphicsType,
JpegGraphicsType,
LinkBackGraphicsType,
+ EmfGraphicsType,
+ WmfGraphicsType,
AnyGraphicsType,
};
Index: src/frontends/qt4/GuiClipboard.cpp
===================================================================
--- src/frontends/qt4/GuiClipboard.cpp (revision 24136)
+++ src/frontends/qt4/GuiClipboard.cpp (working copy)
@@ -41,6 +41,11 @@
#include <QString>
#include <QStringList>
+#ifdef Q_WS_WIN
+#include <QWindowsMime>
+#include <objidl.h>
+#endif // Q_WS_WIN
+
#include "boost/assert.hpp"
#include <map>
@@ -54,11 +59,133 @@
static char const * const lyx_mime_type = "application/x-lyx";
static char const * const pdf_mime_type = "application/pdf";
+static char const * const emf_mime_type = "image/x-emf";
+static char const * const wmf_mime_type = "image/x-wmf";
namespace lyx {
namespace frontend {
+#ifdef Q_WS_WIN
+
+static FORMATETC setCf(int cf)
+{
+ FORMATETC formatetc;
+ formatetc.cfFormat = cf;
+ formatetc.ptd = NULL;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ if (cf == CF_ENHMETAFILE) formatetc.tymed = TYMED_ENHMF;
+ if (cf == CF_METAFILEPICT) formatetc.tymed = TYMED_MFPICT;
+ return formatetc;
+}
+
+
+static bool canGetData(int cf, IDataObject * pDataObj)
+{
+ FORMATETC formatetc = setCf(cf);
+ return pDataObj->QueryGetData(&formatetc) == S_OK;
+}
+
+
+class QWindowsMimeMetafile : public QWindowsMime {
+public:
+ QWindowsMimeMetafile()
+ : QWindowsMime()
+ {}
+ ~QWindowsMimeMetafile() {}
+ bool canConvertFromMime(const FORMATETC & formatetc, const QMimeData *
mimeData) const;
+ bool canConvertToMime(const QString & mimeType, IDataObject * pDataObj)
const;
+ bool convertFromMime(const FORMATETC & formatetc, const QMimeData *
mimeData, STGMEDIUM * pmedium) const;
+ QVariant convertToMime(const QString & mimeType, IDataObject *
pDataObj, QVariant::Type preferredType) const;
+ QVector<FORMATETC> formatsForMime(const QString & mimeType, const
QMimeData * mimeData) const;
+ QString mimeForFormat(const FORMATETC &) const;
+};
+
+
+QString QWindowsMimeMetafile::mimeForFormat(const FORMATETC & formatetc) const
+{
+ QString f;
+ if (formatetc.cfFormat == CF_ENHMETAFILE)
+ f = emf_mime_type;
+ else if (formatetc.cfFormat == CF_METAFILEPICT)
+ f = wmf_mime_type;
+ return f;
+}
+
+bool QWindowsMimeMetafile::canConvertFromMime(
+ const FORMATETC & formatetc, const QMimeData * mimeData) const
+{
+ return false;
+}
+
+
+bool QWindowsMimeMetafile::canConvertToMime(
+ const QString & mimeType, IDataObject * pDataObj) const
+{
+ return (mimeType == "image/x-emf" && canGetData(CF_ENHMETAFILE, pDataObj))
+ || (mimeType == "image/x-wmf" && canGetData(CF_METAFILEPICT,
pDataObj));
+}
+
+
+bool QWindowsMimeMetafile::convertFromMime(
+ const FORMATETC & formatetc, const QMimeData * mimeData,
+ STGMEDIUM * pmedium) const
+{
+ return false;
+}
+
+
+QVariant QWindowsMimeMetafile::convertToMime(
+ const QString & mimeType, IDataObject * pDataObj,
+ QVariant::Type preferredType) const
+{
+ QVariant ret;
+
+ if (canConvertToMime(mimeType, pDataObj)) {
+ FORMATETC formatetc;
+ if (mimeType == "image/x-emf")
+ formatetc = setCf(CF_ENHMETAFILE);
+ if (mimeType == "image/x-wmf")
+ formatetc = setCf(CF_METAFILEPICT);
+ STGMEDIUM s;
+ QByteArray data;
+ int dataSize;
+
+ if (pDataObj->GetData(&formatetc, &s) == S_OK) {
+ if (s.tymed == TYMED_ENHMF) {
+ dataSize = GetEnhMetaFileBits(s.hEnhMetaFile,
NULL, NULL);
+ data.resize(dataSize);
+ dataSize = GetEnhMetaFileBits(s.hEnhMetaFile,
dataSize, (LPBYTE)data.data());
+ } else if (s.tymed == TYMED_MFPICT) {
+ dataSize =
GetMetaFileBitsEx((HMETAFILE)s.hMetaFilePict, NULL, NULL);
+ data.resize(dataSize);
+ dataSize =
GetMetaFileBitsEx((HMETAFILE)s.hMetaFilePict, dataSize, (LPBYTE)data.data());
+ }
+ data.detach();
+ ReleaseStgMedium(&s);
+ }
+ ret = data;
+ }
+ return ret;
+}
+
+
+QVector<FORMATETC> QWindowsMimeMetafile::formatsForMime(
+ const QString & mimeType, const QMimeData * mimeData) const
+{
+ QVector<FORMATETC> formats;
+ if (mimeType == "image/x-emf")
+ formats += setCf(CF_ENHMETAFILE);
+ if (mimeType == "image/x-wmf")
+ formats += setCf(CF_METAFILEPICT);
+ return formats;
+}
+
+static QWindowsMimeMetafile * metafileWindowsMime;
+
+#endif // Q_WS_WIN
+
#ifdef Q_WS_MACX
class QMacPasteboardMimeGraphics : public QMacPasteboardMime {
@@ -137,6 +264,11 @@
if (!graphicsPasteboardMime)
graphicsPasteboardMime = new QMacPasteboardMimeGraphics();
#endif // Q_WS_MACX
+
+#ifdef Q_WS_WIN
+ if (!metafileWindowsMime)
+ metafileWindowsMime = new QWindowsMimeMetafile();
+#endif // Q_WS_WIN
}
@@ -177,6 +309,10 @@
{
// create file dialog filter according to the existing types in the
clipboard
vector<Clipboard::GraphicsType> types;
+ if (hasGraphicsContents(Clipboard::EmfGraphicsType))
+ types.push_back(Clipboard::EmfGraphicsType);
+ if (hasGraphicsContents(Clipboard::WmfGraphicsType))
+ types.push_back(Clipboard::WmfGraphicsType);
if (hasGraphicsContents(Clipboard::LinkBackGraphicsType))
types.push_back(Clipboard::LinkBackGraphicsType);
if (hasGraphicsContents(Clipboard::PdfGraphicsType))
@@ -196,11 +332,15 @@
map<Clipboard::GraphicsType, string> extensions;
map<Clipboard::GraphicsType, docstring> typeNames;
+ extensions[Clipboard::EmfGraphicsType] = "emf";
+ extensions[Clipboard::WmfGraphicsType] = "wmf";
extensions[Clipboard::LinkBackGraphicsType] = "linkback";
extensions[Clipboard::PdfGraphicsType] = "pdf";
extensions[Clipboard::PngGraphicsType] = "png";
extensions[Clipboard::JpegGraphicsType] = "jpeg";
+ typeNames[Clipboard::EmfGraphicsType] = _("Enhanced Metafile");
+ typeNames[Clipboard::WmfGraphicsType] = _("Windows Metafile");
typeNames[Clipboard::LinkBackGraphicsType] = _("LinkBack PDF");
typeNames[Clipboard::PdfGraphicsType] = _("PDF");
typeNames[Clipboard::PngGraphicsType] = _("PNG");
@@ -329,6 +469,8 @@
switch (type) {
case PdfGraphicsType: mime = pdf_mime_type; break;
case LinkBackGraphicsType: mime = pdf_mime_type; break;
+ case EmfGraphicsType: mime = emf_mime_type; break;
+ case WmfGraphicsType: mime = wmf_mime_type; break;
default: BOOST_ASSERT(false);
}
@@ -415,12 +557,14 @@
return hasGraphicsContents(PdfGraphicsType)
|| hasGraphicsContents(PngGraphicsType)
|| hasGraphicsContents(JpegGraphicsType)
+ || hasGraphicsContents(EmfGraphicsType)
+ || hasGraphicsContents(WmfGraphicsType)
|| hasGraphicsContents(LinkBackGraphicsType);
}
QMimeData const * const source =
qApp->clipboard()->mimeData(QClipboard::Clipboard);
-
+
// handle image cases first
if (type == PngGraphicsType || type == JpegGraphicsType)
return source->hasImage();
@@ -444,6 +588,8 @@
// compute mime for type
QString mime;
switch (type) {
+ case EmfGraphicsType: mime = emf_mime_type; break;
+ case WmfGraphicsType: mime = wmf_mime_type; break;
case PdfGraphicsType: mime = pdf_mime_type; break;
default: BOOST_ASSERT(false);
}