4#include <ImageIO/ImageIO.h>
5#include <CoreFoundation/CoreFoundation.h>
6#include <UniformTypeIdentifiers/UTCoreTypes.h>
8#include <QtCore/qsystemdetection.h>
9#include <QtCore/qurl.h>
10#include <QtGui/qimage.h>
11#include <QtCore/qmimedata.h>
12#include <QtCore/qstringconverter.h>
14#if defined(Q_OS_MACOS)
15#import <AppKit/AppKit.h>
17#include <MobileCoreServices/MobileCoreServices.h>
20#if defined(QT_PLATFORM_UIKIT)
21#import <UIKit/UIKit.h>
27#include "private/qcore_mac_p.h"
31using namespace Qt::StringLiterals;
34
35
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
94
95
96
99
100
101
102
103QUtiMimeConverter::QUtiMimeConverter(HandlerScope scope)
106 QMacMimeRegistry::registerMimeConverter(
this);
110
111
112
113
114
115QUtiMimeConverter::QUtiMimeConverter()
116 : QUtiMimeConverter(HandlerScopeFlag::All)
121
122
123
124QUtiMimeConverter::~QUtiMimeConverter()
126 QMacMimeRegistry::unregisterMimeConverter(
this);
130
131
132int QUtiMimeConverter::count(
const QMimeData *mimeData)
const
139
140
141
142
143
146
147
148
149
150
151
152
155
156
157
158
159
160
161
164
165
166
167
168
169
170
171
172
173
176
177
178
179
180
181
182
183
184
185
195 const QString &uti)
const override;
197 const QString &uti)
const override;
203 if (mime ==
"application/x-qt-mime-type-name"_L1)
205 QString ret =
"com.trolltech.anymime."_L1 + mime;
206 return ret.replace(u'/',
"--"_L1);
211 const QString any_prefix =
"com.trolltech.anymime."_L1;
212 if (uti.size() > any_prefix.length() && uti.startsWith(any_prefix))
213 return uti.mid(any_prefix.length()).replace(
"--"_L1,
"/"_L1);
218 const QString &)
const
220 if (data.count() > 1)
221 qWarning(
"QMacMimeAny: Cannot handle multiple member data");
223 if (mime ==
"text/plain"_L1)
224 ret = QString::fromUtf8(data.first());
231 const QString &)
const
233 QList<QByteArray> ret;
234 if (mime ==
"text/plain"_L1)
235 ret.append(data.toString().toUtf8());
237 ret.append(data.toByteArray());
249 QVariant
convertToMime(
const QString &mime,
const QList<QByteArray> &data,
const QString &uti)
const override;
255 if (mime ==
"application/x-qt-mime-type-name"_L1)
256 return u"com.trolltech.qt.MimeTypeName"_s;
273 QList<QByteArray> ret;
274 ret.append(QString(
"x-qt-mime-type-name"_L1).toUtf8());
284 const QString &uti)
const override;
286 const QString &uti)
const override;
291 if (mime ==
"text/plain"_L1)
292 return "public.text"_L1;
298 if (uti ==
"public.text"_L1)
299 return "text/plain"_L1;
305 const QList<QByteArray> &data,
const QString &uti)
const
307 if (data.count() > 1)
308 qWarning(
"QMacMimePlainTextFallback: Cannot handle multiple member data");
310 if (uti ==
"public.text"_L1) {
314 return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault,
315 reinterpret_cast<
const UInt8 *>(firstData.constData()),
316 firstData.size(), kCFStringEncodingUTF8,
false)));
318 qWarning(
"QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
325 const QString &uti)
const
327 QList<QByteArray> ret;
328 QString string = data.toString();
329 if (uti ==
"public.text"_L1)
330 ret.append(string.toUtf8());
340 const QString &uti)
const override;
342 const QString &uti)
const override;
347 if (mime ==
"text/plain"_L1)
348 return "public.utf16-plain-text"_L1;
349 if (qsizetype i = mime.indexOf(
"charset="_L1); i >= 0) {
350 QString cs(mime.mid(i + 8).toLower());
351 i = cs.indexOf(u';');
354 if (cs ==
"system"_L1)
355 return "public.utf8-plain-text"_L1;
356 else if (cs ==
"iso-10646-ucs-2"_L1 || cs ==
"utf16"_L1)
357 return "public.utf16-plain-text"_L1;
364 if (uti ==
"public.utf16-plain-text"_L1 || uti ==
"public.utf8-plain-text"_L1)
365 return "text/plain"_L1;
371 const QList<QByteArray> &data,
const QString &uti)
const
373 if (data.count() > 1)
374 qWarning(
"QMacMimeUnicodeText: Cannot handle multiple member data");
378 if (uti ==
"public.utf8-plain-text"_L1) {
379 ret = QString::fromUtf8(firstData);
380 }
else if (uti ==
"public.utf16-plain-text"_L1) {
381 QString str = QStringDecoder(QStringDecoder::Utf16)(firstData);
384 qWarning(
"QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
391 const QString &uti)
const
393 QList<QByteArray> ret;
394 QString string = data.toString();
395 if (uti ==
"public.utf8-plain-text"_L1)
396 ret.append(string.toUtf8());
397 else if (uti ==
"public.utf16-plain-text"_L1) {
398 QStringEncoder::Flags f;
399#if defined(Q_OS_MACOS)
403 f = QStringEncoder::Flag::Default;
409 f = QStringEncoder::Flag::WriteBom;
411 QStringEncoder encoder(QStringEncoder::Utf16, f);
412 ret.append(encoder(string));
423 const QString &uti)
const override;
425 const QString &uti)
const override;
430 if (mime ==
"text/html"_L1)
431 return "public.html"_L1;
437 if (uti ==
"public.html"_L1)
438 return "text/html"_L1;
444 const QList<QByteArray> &data,
const QString &uti)
const
448 if (data.count() > 1)
449 qWarning(
"QMacMimeHTMLText: Cannot handle multiple member data");
455 const QVariant &data,
const QString &uti)
const
457 QList<QByteArray> ret;
460 ret.append(data.toByteArray());
470 const QString &uti)
const override;
472 const QString &uti)
const override;
477 if (mime ==
"text/html"_L1)
478 return "public.rtf"_L1;
484 if (uti ==
"public.rtf"_L1)
485 return "text/html"_L1;
491 const QList<QByteArray> &data,
const QString &uti)
const
495 if (data.count() > 1)
496 qWarning(
"QMacMimeHTMLText: Cannot handle multiple member data");
499 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
500 options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
501 documentAttributes:nil
505 NSRange range = NSMakeRange(0, [string length]);
506 NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
507 NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
513 return QByteArray::fromNSData(htmlData).trimmed();
518 const QVariant &data,
const QString &uti)
const
520 QList<QByteArray> ret;
524 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
525 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
526 documentAttributes:nil
530 NSRange range = NSMakeRange(0, [string length]);
531 NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
532 NSData *rtfData = [string dataFromRange:range documentAttributes:dict error:&error];
533 ret << QByteArray::fromNSData(rtfData);
543 const QString &uti)
const override;
545 const QString &uti)
const override;
551 if (mime ==
"text/uri-list"_L1)
552 return "public.file-url"_L1;
558 if (uti ==
"public.file-url"_L1)
559 return "text/uri-list"_L1;
565 const QList<QByteArray> &data,
const QString &uti)
const
570 for (
int i = 0; i < data.size(); ++i) {
572 NSString *urlString = [[[NSString alloc] initWithBytesNoCopy:(
void *)a.data() length:a.size()
573 encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
574 NSURL *nsurl = [NSURL URLWithString:urlString];
577 if ([nsurl isFileReferenceURL]) {
578 url = QUrl::fromNSURL([nsurl filePathURL]);
580 url = QUrl::fromNSURL(nsurl);
583 if (url.host().toLower() ==
"localhost"_L1)
584 url.setHost(QString());
586 url.setPath(url.path().normalized(QString::NormalizationForm_C));
589 return QVariant(ret);
594 const QVariant &data,
const QString &uti)
const
596 QList<QByteArray> ret;
599 QList<QVariant> urls = data.toList();
600 for (
int i = 0; i < urls.size(); ++i) {
601 QUrl url = urls.at(i).toUrl();
602 if (url.scheme().isEmpty())
603 url.setScheme(
"file"_L1);
604 if (url.scheme() ==
"file"_L1) {
605 if (url.host().isEmpty())
606 url.setHost(
"localhost"_L1);
607 url.setPath(url.path().normalized(QString::NormalizationForm_D));
609 if (url.isLocalFile())
610 ret.append(url.toEncoded());
617 return mimeData->urls().count();
626 const QString &uti)
const override;
628 const QString &uti)
const override;
633 if (mime.startsWith(
"text/uri-list"_L1))
634 return "public.url"_L1;
640 if (uti ==
"public.url"_L1)
641 return "text/uri-list"_L1;
646 const QList<QByteArray> &data,
const QString &uti)
const
652 for (
int i=0; i<data.size(); ++i) {
653 QUrl url = QUrl::fromEncoded(data.at(i));
654 if (url.host().toLower() ==
"localhost"_L1)
655 url.setHost(QString());
656 url.setPath(url.path().normalized(QString::NormalizationForm_C));
659 return QVariant(ret);
663 const QVariant &data,
const QString &uti)
const
665 QList<QByteArray> ret;
669 QList<QVariant> urls = data.toList();
670 for (
int i=0; i<urls.size(); ++i) {
671 QUrl url = urls.at(i).toUrl();
672 if (url.scheme().isEmpty())
673 url.setScheme(
"file"_L1);
674 if (url.scheme() ==
"file"_L1) {
675 if (url.host().isEmpty())
676 url.setHost(
"localhost"_L1);
677 url.setPath(url.path().normalized(QString::NormalizationForm_D));
679 ret.append(url.toEncoded());
690 const QString &uti)
const override;
692 const QString &uti)
const override;
697 if (mime.startsWith(
"text/vcard"_L1))
698 return "public.vcard"_L1;
704 if (uti ==
"public.vcard"_L1)
705 return "text/vcard"_L1;
710 const QList<QByteArray> &data,
const QString &uti)
const
715 if (uti ==
"public.vcard"_L1) {
716 for (
int i=0; i<data.size(); ++i)
719 return QVariant(cards);
723 const QVariant &data,
const QString &uti)
const
725 QList<QByteArray> ret;
729 if (mime ==
"text/vcard"_L1)
730 ret.append(data.toString().toUtf8());
743 const QString &uti)
const override;
745 const QString &uti)
const override;
750 if (mime.startsWith(
"application/x-qt-image"_L1))
751 return "public.tiff"_L1;
757 if (uti ==
"public.tiff"_L1)
758 return "application/x-qt-image"_L1;
763 const QList<QByteArray> &data,
const QString &uti)
const
765 if (data.count() > 1)
766 qWarning(
"QMacMimeTiff: Cannot handle multiple member data");
771 QCFType<CFDataRef> tiffData = data.first().toRawCFData();
772 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
774 if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
775 return QVariant(qt_mac_toQImage(image));
781 const QVariant &variant,
const QString &uti)
const
786 QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
787 QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data,
788 (CFStringRef)UTTypeTIFF.identifier, 1, 0);
790 if (!imageDestination)
793 QImage img = qvariant_cast<QImage>(variant);
794 NSDictionary *props = @{
795 static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
796 static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
799 CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img),
800 static_cast<CFDictionaryRef>(props));
801 CGImageDestinationFinalize(imageDestination);
803 return QList<QByteArray>() << QByteArray::fromCFData(data);
808void registerBuiltInTypes()
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
int count(const QMimeData *mimeData) const override
Returns the item count for the given mimeData.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QVariant convertToMime(const QString &mime, const QList< QByteArray > &data, const QString &uti) const override
Returns data converted from Mac UTI uti to MIME type mime.
QString utiForMime(const QString &mime) const override
Returns the Mac UTI used for MIME type mime, or an empty string if this converter does not support co...
QString mimeForUti(const QString &uti) const override
Returns the MIME type used for Mac UTI uti, or an empty string if this converter does not support con...
QList< QByteArray > convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override
Returns data converted from MIME type mime to Mac UTI uti.
bool canConvert(const QString &mime, const QString &uti) const
Returns true if the converter can convert (both ways) between mime and uti; otherwise returns false.
QImage qt_mac_toQImage(CGImageRef cgImage)
CGImageRef qt_mac_toCGImage(const QImage &inImage)