1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 //#define USE_INTERNET_CONFIG
46 #ifndef USE_INTERNET_CONFIG
48 # include "qfileinfo.h"
49 # include "qtextstream.h"
52 # include <sys/types.h>
53 # include <sys/stat.h>
54 # include <sys/fcntl.h>
59 #include "qimagewriter.h"
60 #include "qimagereader.h"
61 #include "qdatastream.h"
63 #include "qdatetime.h"
64 #include "qapplication_p.h"
65 #include "qtextcodec.h"
69 #include <private/qt_mac_p.h>
73 #include <QuickTime/QuickTime.h>
79 extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp
81 typedef QList<QMacPasteboardMime*> MimeList;
82 Q_GLOBAL_STATIC(MimeList, globalMimeList)
84 static void cleanup_mimes()
86 MimeList *mimes = globalMimeList();
87 while (!mimes->isEmpty())
88 delete mimes->takeFirst();
91 Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
94 \fn void qRegisterDraggedTypes(const QStringList &types)
95 \relates QMacPasteboardMime
97 Registers the given \a types as custom pasteboard types.
99 This function should be called to enable the Drag and Drop events
100 for custom pasteboard types on Cocoa implementations. This is required
101 in addition to a QMacPasteboardMime subclass implementation. By default
102 drag and drop is enabled for all standard pasteboard types.
104 \sa QMacPasteboardMime
106 Q_WIDGETS_EXPORT void qRegisterDraggedTypes(const QStringList &types)
108 (*globalDraggedTypesList()) += types;
111 const QStringList& qEnabledDraggedTypes()
113 return (*globalDraggedTypesList());
117 /*****************************************************************************
118 QDnD debug facilities
119 *****************************************************************************/
120 //#define DEBUG_MIME_MAPS
123 extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
124 extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp
126 ScrapFlavorType qt_mac_mime_type = 'CUTE';
127 CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
130 \class QMacPasteboardMime
131 \brief The QMacPasteboardMime class converts between a MIME type and a
132 \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
133 Type Identifier (UTI)} format.
139 Qt's drag and drop and clipboard facilities use the MIME
140 standard. On X11, this maps trivially to the Xdnd protocol. On
141 Mac, although some applications use MIME to describe clipboard
142 contents, it is more common to use Apple's UTI format.
144 QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
145 By subclasses this class, one can extend Qt's drag and drop
146 and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
148 A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
150 Qt has predefined support for the following UTIs:
152 \i public.utf8-plain-text - converts to "text/plain"
153 \i public.utf16-plain-text - converts to "text/plain"
154 \i public.html - converts to "text/html"
155 \i public.url - converts to "text/uri-list"
156 \i public.file-url - converts to "text/uri-list"
157 \i public.tiff - converts to "application/x-qt-image"
158 \i public.vcard - converts to "text/plain"
159 \i com.apple.traditional-mac-plain-text - converts to "text/plain"
160 \i com.apple.pict - converts to "application/x-qt-image"
163 When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
164 find an instance that can convert to, or from, a specific MIME type. It will do this by calling
165 canConvert() on each instance, starting with (and choosing) the last created instance first.
166 The actual conversions will be done by using convertToMime() and convertFromMime().
168 \note The API uses the term "flavor" in some cases. This is for backwards
169 compatibility reasons, and should now be understood as UTIs.
172 /*! \enum QMacPasteboardMime::QMacPasteboardMimeType
177 Constructs a new conversion object of type \a t, adding it to the
178 globally accessed list of available convertors.
180 QMacPasteboardMime::QMacPasteboardMime(char t) : type(t)
182 globalMimeList()->append(this);
186 Destroys a conversion object, removing it from the global
187 list of available convertors.
189 QMacPasteboardMime::~QMacPasteboardMime()
191 if(!QApplication::closingDown())
192 globalMimeList()->removeAll(this);
195 class QMacPasteboardMimeAny : public QMacPasteboardMime {
199 QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
201 ~QMacPasteboardMimeAny() {
203 QString convertorName();
205 QString flavorFor(const QString &mime);
206 QString mimeFor(QString flav);
207 bool canConvert(const QString &mime, QString flav);
208 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
209 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
212 QString QMacPasteboardMimeAny::convertorName()
214 return QLatin1String("Any-Mime");
217 QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
219 // do not handle the mime type name in the drag pasteboard
220 if(mime == QLatin1String("application/x-qt-mime-type-name"))
222 QString ret = QLatin1String("com.trolltech.anymime.") + mime;
223 return ret.replace(QLatin1Char('/'), QLatin1String("--"));
226 QString QMacPasteboardMimeAny::mimeFor(QString flav)
228 const QString any_prefix = QLatin1String("com.trolltech.anymime.");
229 if(flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
230 return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
234 bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
236 return mimeFor(flav) == mime;
239 QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
242 qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
244 if (mime == QLatin1String("text/plain"))
245 ret = QString::fromUtf8(data.first());
251 QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
253 QList<QByteArray> ret;
254 if (mime == QLatin1String("text/plain"))
255 ret.append(data.toString().toUtf8());
257 ret.append(data.toByteArray());
261 class QMacPasteboardMimeTypeName : public QMacPasteboardMime {
265 QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
267 ~QMacPasteboardMimeTypeName() {
269 QString convertorName();
271 QString flavorFor(const QString &mime);
272 QString mimeFor(QString flav);
273 bool canConvert(const QString &mime, QString flav);
274 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
275 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
278 QString QMacPasteboardMimeTypeName::convertorName()
280 return QLatin1String("Qt-Mime-Type");
283 QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
285 if(mime == QLatin1String("application/x-qt-mime-type-name"))
286 return QLatin1String("com.trolltech.qt.MimeTypeName");
290 QString QMacPasteboardMimeTypeName::mimeFor(QString)
295 bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
300 QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
306 QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
308 QList<QByteArray> ret;
309 ret.append(QString("x-qt-mime-type-name").toUtf8());
313 class QMacPasteboardMimePlainText : public QMacPasteboardMime {
315 QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { }
316 QString convertorName();
318 QString flavorFor(const QString &mime);
319 QString mimeFor(QString flav);
320 bool canConvert(const QString &mime, QString flav);
321 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
322 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
325 QString QMacPasteboardMimePlainText::convertorName()
327 return QLatin1String("PlainText");
330 QString QMacPasteboardMimePlainText::flavorFor(const QString &mime)
332 if (mime == QLatin1String("text/plain"))
333 return QLatin1String("com.apple.traditional-mac-plain-text");
337 QString QMacPasteboardMimePlainText::mimeFor(QString flav)
339 if (flav == QLatin1String("com.apple.traditional-mac-plain-text"))
340 return QLatin1String("text/plain");
344 bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav)
346 return flavorFor(mime) == flav;
349 QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
352 qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data");
353 const QByteArray &firstData = data.first();
355 if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) {
356 QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
357 reinterpret_cast<const UInt8 *>(firstData.constData()),
358 firstData.size(), CFStringGetSystemEncoding(), false));
361 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
366 QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor)
368 QList<QByteArray> ret;
369 QString string = data.toString();
370 if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text")))
371 ret.append(string.toLatin1());
375 class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime {
377 QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { }
378 QString convertorName();
380 QString flavorFor(const QString &mime);
381 QString mimeFor(QString flav);
382 bool canConvert(const QString &mime, QString flav);
383 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
384 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
387 QString QMacPasteboardMimeUnicodeText::convertorName()
389 return QLatin1String("UnicodeText");
392 QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
394 if (mime == QLatin1String("text/plain"))
395 return QLatin1String("public.utf16-plain-text");
396 int i = mime.indexOf(QLatin1String("charset="));
398 QString cs(mime.mid(i+8).toLower());
399 i = cs.indexOf(QLatin1Char(';'));
402 if (cs == QLatin1String("system"))
403 return QLatin1String("public.utf8-plain-text");
404 else if (cs == QLatin1String("iso-10646-ucs-2")
405 || cs == QLatin1String("utf16"))
406 return QLatin1String("public.utf16-plain-text");
411 QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
413 if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
414 return QLatin1String("text/plain");
418 bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
420 return flavorFor(mime) == flav;
423 QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
426 qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
427 const QByteArray &firstData = data.first();
428 // I can only handle two types (system and unicode) so deal with them that way
430 if(flavor == QLatin1String("public.utf8-plain-text")) {
431 QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
432 reinterpret_cast<const UInt8 *>(firstData.constData()),
433 firstData.size(), CFStringGetSystemEncoding(), false));
435 } else if (flavor == QLatin1String("public.utf16-plain-text")) {
436 ret = QString(reinterpret_cast<const QChar *>(firstData.constData()),
437 firstData.size() / sizeof(QChar));
439 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
444 QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
446 QList<QByteArray> ret;
447 QString string = data.toString();
448 if(flavor == QLatin1String("public.utf8-plain-text"))
449 ret.append(string.toUtf8());
450 else if (flavor == QLatin1String("public.utf16-plain-text"))
451 ret.append(QByteArray((char*)string.utf16(), string.length()*2));
455 class QMacPasteboardMimeHTMLText : public QMacPasteboardMime {
457 QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { }
458 QString convertorName();
460 QString flavorFor(const QString &mime);
461 QString mimeFor(QString flav);
462 bool canConvert(const QString &mime, QString flav);
463 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
464 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
467 QString QMacPasteboardMimeHTMLText::convertorName()
469 return QLatin1String("HTML");
472 QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
474 if (mime == QLatin1String("text/html"))
475 return QLatin1String("public.html");
479 QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
481 if (flav == QLatin1String("public.html"))
482 return QLatin1String("text/html");
486 bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
488 return flavorFor(mime) == flav;
491 QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
493 if (!canConvert(mimeType, flavor))
495 if (data.count() > 1)
496 qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
500 QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
502 QList<QByteArray> ret;
503 if (!canConvert(mime, flavor))
505 ret.append(data.toByteArray());
512 // This can be removed once 10.6 is the minimum (or we have to require 64-bit) whichever comes first.
514 typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle);
515 typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32);
516 typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef);
517 typedef ComponentResult (*PtrGraphicsExportSetOutputHandle)(GraphicsExportComponent, Handle);
518 typedef ComponentResult (*PtrGraphicsExportDoExport)(GraphicsExportComponent, unsigned long *);
520 static PtrGraphicsImportSetDataHandle ptrGraphicsImportSetDataHandle = 0;
521 static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0;
522 static PtrGraphicsExportSetInputCGImage ptrGraphicsExportSetInputCGImage = 0;
523 static PtrGraphicsExportSetOutputHandle ptrGraphicsExportSetOutputHandle = 0;
524 static PtrGraphicsExportDoExport ptrGraphicsExportDoExport = 0;
526 static bool resolveMimeQuickTimeSymbols()
528 if (ptrGraphicsImportSetDataHandle == 0) {
529 QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime"));
530 ptrGraphicsImportSetDataHandle = reinterpret_cast<PtrGraphicsImportSetDataHandle>(library.resolve("GraphicsImportSetDataHandle"));
531 ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage"));
532 ptrGraphicsExportSetInputCGImage = reinterpret_cast<PtrGraphicsExportSetInputCGImage>(library.resolve("GraphicsExportSetInputCGImage"));
533 ptrGraphicsExportSetOutputHandle = reinterpret_cast<PtrGraphicsExportSetOutputHandle>(library.resolve("GraphicsExportSetOutputHandle"));
534 ptrGraphicsExportDoExport = reinterpret_cast<PtrGraphicsExportDoExport>(library.resolve("GraphicsExportDoExport"));
537 return ptrGraphicsImportSetDataHandle != 0
538 && ptrGraphicsImportCreateCGImage != 0 && ptrGraphicsExportSetInputCGImage != 0
539 && ptrGraphicsExportSetOutputHandle != 0 && ptrGraphicsExportDoExport != 0;
542 class QMacPasteboardMimePict : public QMacPasteboardMime {
544 QMacPasteboardMimePict() : QMacPasteboardMime(MIME_ALL) { }
545 QString convertorName();
547 QString flavorFor(const QString &mime);
548 QString mimeFor(QString flav);
549 bool canConvert(const QString &mime, QString flav);
550 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
551 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
554 QString QMacPasteboardMimePict::convertorName()
556 return QLatin1String("Pict");
559 QString QMacPasteboardMimePict::flavorFor(const QString &mime)
561 if(mime.startsWith(QLatin1String("application/x-qt-image")))
562 return QLatin1String("com.apple.pict");
566 QString QMacPasteboardMimePict::mimeFor(QString flav)
568 if(flav == QLatin1String("com.apple.pict"))
569 return QLatin1String("application/x-qt-image");
573 bool QMacPasteboardMimePict::canConvert(const QString &mime, QString flav)
575 return flav == QLatin1String("com.apple.pict")
576 && mime == QLatin1String("application/x-qt-image");
580 QVariant QMacPasteboardMimePict::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
583 qWarning("QMacPasteboardMimePict: Cannot handle multiple member data");
585 if (!resolveMimeQuickTimeSymbols())
588 if(!canConvert(mime, flav))
590 const QByteArray &a = data.first();
592 // This function expects the 512 header (just to skip it, so create the extra space for it).
593 Handle pic = NewHandle(a.size() + 512);
594 memcpy(*pic + 512, a.constData(), a.size());
596 GraphicsImportComponent graphicsImporter;
597 ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType,
598 kQTFileTypePicture, &graphicsImporter);
599 QCFType<CGImageRef> cgImage;
601 result = ptrGraphicsImportSetDataHandle(graphicsImporter, pic);
603 result = ptrGraphicsImportCreateCGImage(graphicsImporter, &cgImage,
604 kGraphicsImportCreateCGImageUsingCurrentSettings);
606 ret = QVariant(QPixmap::fromMacCGImageRef(cgImage).toImage());
607 CloseComponent(graphicsImporter);
612 QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, QVariant variant,
615 QList<QByteArray> ret;
616 if (!resolveMimeQuickTimeSymbols())
619 if (!canConvert(mime, flav))
621 QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(qvariant_cast<QImage>(variant));
622 Handle pic = NewHandle(0);
623 GraphicsExportComponent graphicsExporter;
624 ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
625 kQTFileTypePicture, &graphicsExporter);
627 unsigned long sizeWritten;
628 result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
630 result = ptrGraphicsExportSetOutputHandle(graphicsExporter, pic);
632 result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
634 CloseComponent(graphicsExporter);
637 int size = GetHandleSize((Handle)pic);
638 // Skip the Picture File header (512 bytes) and feed the raw data
639 QByteArray ar(reinterpret_cast<char *>(*pic + 512), size - 512);
648 class QMacPasteboardMimeTiff : public QMacPasteboardMime {
650 QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { }
651 QString convertorName();
653 QString flavorFor(const QString &mime);
654 QString mimeFor(QString flav);
655 bool canConvert(const QString &mime, QString flav);
656 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
657 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
660 QString QMacPasteboardMimeTiff::convertorName()
662 return QLatin1String("Tiff");
665 QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
667 if(mime.startsWith(QLatin1String("application/x-qt-image")))
668 return QLatin1String("public.tiff");
672 QString QMacPasteboardMimeTiff::mimeFor(QString flav)
674 if(flav == QLatin1String("public.tiff"))
675 return QLatin1String("application/x-qt-image");
679 bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
681 return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
684 QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
687 qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
689 if (!canConvert(mime, flav))
691 const QByteArray &a = data.first();
692 QCFType<CGImageRef> image;
693 QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
694 reinterpret_cast<const UInt8 *>(a.constData()),
695 a.size(), kCFAllocatorNull);
696 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
697 image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
700 ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
704 QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
706 QList<QByteArray> ret;
707 if (!canConvert(mime, flav))
710 QImage img = qvariant_cast<QImage>(variant);
711 QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img);
712 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
713 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
714 QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
715 QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
716 if (imageDestination != 0) {
718 QCFType<CFTypeRef> values[2];
719 QCFType<CFDictionaryRef> options;
720 keys[0] = kCGImagePropertyPixelWidth;
721 keys[1] = kCGImagePropertyPixelHeight;
722 int width = img.width();
723 int height = img.height();
724 values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
725 values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
726 options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
727 reinterpret_cast<const void **>(values), 2,
728 &kCFTypeDictionaryKeyCallBacks,
729 &kCFTypeDictionaryValueCallBacks);
730 CGImageDestinationAddImage(imageDestination, cgimage, options);
731 CGImageDestinationFinalize(imageDestination);
733 QByteArray ar(CFDataGetLength(data), 0);
735 CFRangeMake(0, ar.size()),
736 reinterpret_cast<UInt8 *>(ar.data()));
742 Handle tiff = NewHandle(0);
743 if (resolveMimeQuickTimeSymbols()) {
744 GraphicsExportComponent graphicsExporter;
745 ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
746 kQTFileTypeTIFF, &graphicsExporter);
748 unsigned long sizeWritten;
749 result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
751 result = ptrGraphicsExportSetOutputHandle(graphicsExporter, tiff);
753 result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
755 CloseComponent(graphicsExporter);
758 int size = GetHandleSize((Handle)tiff);
759 QByteArray ar(reinterpret_cast<char *>(*tiff), size);
768 class QMacPasteboardMimeFileUri : public QMacPasteboardMime {
770 QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { }
771 QString convertorName();
773 QString flavorFor(const QString &mime);
774 QString mimeFor(QString flav);
775 bool canConvert(const QString &mime, QString flav);
776 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
777 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
780 QString QMacPasteboardMimeFileUri::convertorName()
782 return QLatin1String("FileURL");
785 QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
787 if (mime == QLatin1String("text/uri-list"))
788 return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
792 QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
794 if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)))
795 return QLatin1String("text/uri-list");
799 bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
801 return mime == QLatin1String("text/uri-list")
802 && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
805 QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
807 if(!canConvert(mime, flav))
810 for(int i = 0; i < data.size(); ++i) {
811 QUrl url = QUrl::fromEncoded(data.at(i));
812 if (url.host().toLower() == QLatin1String("localhost"))
813 url.setHost(QString());
814 url.setPath(url.path().normalized(QString::NormalizationForm_C));
817 return QVariant(ret);
820 QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
822 QList<QByteArray> ret;
823 if (!canConvert(mime, flav))
825 QList<QVariant> urls = data.toList();
826 for(int i = 0; i < urls.size(); ++i) {
827 QUrl url = urls.at(i).toUrl();
828 if (url.scheme().isEmpty())
829 url.setScheme(QLatin1String("file"));
830 if (url.scheme().toLower() == QLatin1String("file")) {
831 if (url.host().isEmpty())
832 url.setHost(QLatin1String("localhost"));
833 url.setPath(url.path().normalized(QString::NormalizationForm_D));
835 ret.append(url.toEncoded());
840 class QMacPasteboardMimeUrl : public QMacPasteboardMime {
842 QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
843 QString convertorName();
845 QString flavorFor(const QString &mime);
846 QString mimeFor(QString flav);
847 bool canConvert(const QString &mime, QString flav);
848 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
849 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
852 QString QMacPasteboardMimeUrl::convertorName()
854 return QLatin1String("URL");
857 QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
859 if(mime.startsWith(QLatin1String("text/uri-list")))
860 return QLatin1String("public.url");
864 QString QMacPasteboardMimeUrl::mimeFor(QString flav)
866 if(flav == QLatin1String("public.url"))
867 return QLatin1String("text/uri-list");
871 bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
873 return flav == QLatin1String("public.url")
874 && mime == QLatin1String("text/uri-list");
877 QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
879 if(!canConvert(mime, flav))
883 for (int i=0; i<data.size(); ++i) {
884 QUrl url = QUrl::fromEncoded(data.at(i));
885 if (url.host().toLower() == QLatin1String("localhost"))
886 url.setHost(QString());
887 url.setPath(url.path().normalized(QString::NormalizationForm_C));
890 return QVariant(ret);
893 QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
895 QList<QByteArray> ret;
896 if (!canConvert(mime, flav))
899 QList<QVariant> urls = data.toList();
900 for(int i=0; i<urls.size(); ++i) {
901 QUrl url = urls.at(i).toUrl();
902 if (url.scheme().isEmpty())
903 url.setScheme(QLatin1String("file"));
904 if (url.scheme().toLower() == QLatin1String("file")) {
905 if (url.host().isEmpty())
906 url.setHost(QLatin1String("localhost"));
907 url.setPath(url.path().normalized(QString::NormalizationForm_D));
909 ret.append(url.toEncoded());
914 class QMacPasteboardMimeVCard : public QMacPasteboardMime
917 QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ }
918 QString convertorName();
920 QString flavorFor(const QString &mime);
921 QString mimeFor(QString flav);
922 bool canConvert(const QString &mime, QString flav);
923 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
924 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
927 QString QMacPasteboardMimeVCard::convertorName()
929 return QString("VCard");
932 bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
934 return mimeFor(flav) == mime;
937 QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
939 if(mime.startsWith(QLatin1String("text/plain")))
940 return QLatin1String("public.vcard");
944 QString QMacPasteboardMimeVCard::mimeFor(QString flav)
946 if (flav == QLatin1String("public.vcard"))
947 return QLatin1String("text/plain");
951 QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
954 if (mime == QLatin1String("text/plain")) {
955 for (int i=0; i<data.size(); ++i)
958 return QVariant(cards);
961 QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
963 QList<QByteArray> ret;
964 if (mime == QLatin1String("text/plain"))
965 ret.append(data.toString().toUtf8());
973 This is an internal function.
975 void QMacPasteboardMime::initialize()
977 if(globalMimeList()->isEmpty()) {
978 qAddPostRoutine(cleanup_mimes);
980 //standard types that we wrap
981 new QMacPasteboardMimeTiff;
983 // 10.6 does automatic synthesis to and from PICT to standard image types (like TIFF),
984 // so don't bother doing it ourselves, especially since it's not available in 64-bit.
985 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
986 new QMacPasteboardMimePict;
988 new QMacPasteboardMimeUnicodeText;
989 new QMacPasteboardMimePlainText;
990 new QMacPasteboardMimeHTMLText;
991 new QMacPasteboardMimeFileUri;
992 new QMacPasteboardMimeUrl;
993 new QMacPasteboardMimeTypeName;
994 new QMacPasteboardMimeVCard;
995 //make sure our "non-standard" types are always last! --Sam
996 new QMacPasteboardMimeAny;
1001 Returns the most-recently created QMacPasteboardMime of type \a t that can convert
1002 between the \a mime and \a flav formats. Returns 0 if no such convertor
1006 QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
1008 MimeList *mimes = globalMimeList();
1009 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1010 #ifdef DEBUG_MIME_MAPS
1011 qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
1012 (*it)->convertorName().toLatin1().constData(),
1013 (*it)->type & t, mime.toLatin1().constData(),
1014 flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
1015 (*it)->canConvert(mime,flav));
1016 for(int i = 0; i < (*it)->countFlavors(); ++i) {
1017 int f = (*it)->flavor(i);
1018 qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
1019 (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
1020 (*it)->convertorName().toLatin1().constData());
1023 if(((*it)->type & t) && (*it)->canConvert(mime, flav))
1029 Returns a MIME type of type \a t for \a flav, or 0 if none exists.
1031 QString QMacPasteboardMime::flavorToMime(uchar t, QString flav)
1033 MimeList *mimes = globalMimeList();
1034 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1035 #ifdef DEBUG_MIME_MAPS
1036 qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
1037 (*it)->convertorName().toLatin1().constData(),
1038 (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
1039 (*it)->mimeFor(flav).toLatin1().constData());
1042 if((*it)->type & t) {
1043 QString mimeType = (*it)->mimeFor(flav);
1044 if(!mimeType.isNull())
1052 Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
1054 QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t)
1057 MimeList *mimes = globalMimeList();
1058 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1067 \fn QString QMacPasteboardMime::convertorName()
1069 Returns a name for the convertor.
1071 All subclasses must reimplement this pure virtual function.
1075 \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
1077 Returns true if the convertor can convert (both ways) between
1078 \a mime and \a flav; otherwise returns false.
1080 All subclasses must reimplement this pure virtual function.
1084 \fn QString QMacPasteboardMime::mimeFor(QString flav)
1086 Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
1087 convertor does not support \a flav.
1089 All subclasses must reimplement this pure virtual function.
1093 \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
1095 Returns the Mac UTI used for MIME type \a mime, or 0 if this
1096 convertor does not support \a mime.
1098 All subclasses must reimplement this pure virtual function.
1102 \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
1104 Returns \a data converted from Mac UTI \a flav to MIME type \a
1107 Note that Mac flavors must all be self-terminating. The input \a
1108 data may contain trailing data.
1110 All subclasses must reimplement this pure virtual function.
1114 \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
1116 Returns \a data converted from MIME type \a mime
1119 Note that Mac flavors must all be self-terminating. The return
1120 value may contain trailing data.
1122 All subclasses must reimplement this pure virtual function.