5#include <ImageIO/ImageIO.h>
6#include <CoreFoundation/CoreFoundation.h>
7#include <UniformTypeIdentifiers/UTCoreTypes.h>
9#include <QtCore/qsystemdetection.h>
10#include <QtCore/qurl.h>
11#include <QtGui/qimage.h>
12#include <QtCore/qmimedata.h>
13#include <QtCore/qstringconverter.h>
15#if defined(Q_OS_MACOS)
16#import <AppKit/AppKit.h>
18#include <MobileCoreServices/MobileCoreServices.h>
21#if defined(QT_PLATFORM_UIKIT)
22#import <UIKit/UIKit.h>
28#include "private/qcore_mac_p.h"
32using namespace Qt::StringLiterals;
35
36
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
92
95
96
97
100
101
102
103
104QUtiMimeConverter::QUtiMimeConverter(HandlerScope scope)
107 QMacMimeRegistry::registerMimeConverter(
this);
111
112
113
114
115
116QUtiMimeConverter::QUtiMimeConverter()
117 : QUtiMimeConverter(HandlerScopeFlag::All)
122
123
124
125QUtiMimeConverter::~QUtiMimeConverter()
127 QMacMimeRegistry::unregisterMimeConverter(
this);
131
132
133int QUtiMimeConverter::count(
const QMimeData *mimeData)
const
140
141
142
143
144
147
148
149
150
151
152
153
156
157
158
159
160
161
162
165
166
167
168
169
170
171
172
173
174
177
178
179
180
181
182
183
184
185
186
196 const QString &uti)
const override;
198 const QString &uti)
const override;
204 if (mime ==
"application/x-qt-mime-type-name"_L1)
206 QString ret =
"com.trolltech.anymime."_L1 + mime;
207 return ret.replace(u'/',
"--"_L1);
212 const QString any_prefix =
"com.trolltech.anymime."_L1;
213 if (uti.size() > any_prefix.length() && uti.startsWith(any_prefix))
214 return uti.mid(any_prefix.length()).replace(
"--"_L1,
"/"_L1);
219 const QString &)
const
221 if (data.count() > 1)
222 qWarning(
"QMacMimeAny: Cannot handle multiple member data");
224 if (mime ==
"text/plain"_L1)
225 ret = QString::fromUtf8(data.first());
232 const QString &)
const
234 QList<QByteArray> ret;
235 if (mime ==
"text/plain"_L1)
236 ret.append(data.toString().toUtf8());
238 ret.append(data.toByteArray());
250 QVariant
convertToMime(
const QString &mime,
const QList<QByteArray> &data,
const QString &uti)
const override;
256 if (mime ==
"application/x-qt-mime-type-name"_L1)
257 return u"com.trolltech.qt.MimeTypeName"_s;
274 QList<QByteArray> ret;
275 ret.append(QString(
"x-qt-mime-type-name"_L1).toUtf8());
285 const QString &uti)
const override;
287 const QString &uti)
const override;
292 if (mime ==
"text/plain"_L1)
293 return "public.text"_L1;
299 if (uti ==
"public.text"_L1)
300 return "text/plain"_L1;
306 const QList<QByteArray> &data,
const QString &uti)
const
308 if (data.count() > 1)
309 qWarning(
"QMacMimePlainTextFallback: Cannot handle multiple member data");
311 if (uti ==
"public.text"_L1) {
315 return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault,
316 reinterpret_cast<
const UInt8 *>(firstData.constData()),
317 firstData.size(), kCFStringEncodingUTF8,
false)));
319 qWarning(
"QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
326 const QString &uti)
const
328 QList<QByteArray> ret;
329 QString string = data.toString();
330 if (uti ==
"public.text"_L1)
331 ret.append(string.toUtf8());
341 const QString &uti)
const override;
343 const QString &uti)
const override;
348 if (mime ==
"text/plain"_L1)
349 return "public.utf16-plain-text"_L1;
350 if (qsizetype i = mime.indexOf(
"charset="_L1); i >= 0) {
351 QString cs(mime.mid(i + 8).toLower());
352 i = cs.indexOf(u';');
355 if (cs ==
"system"_L1)
356 return "public.utf8-plain-text"_L1;
357 else if (cs ==
"iso-10646-ucs-2"_L1 || cs ==
"utf16"_L1)
358 return "public.utf16-plain-text"_L1;
365 if (uti ==
"public.utf16-plain-text"_L1 || uti ==
"public.utf8-plain-text"_L1)
366 return "text/plain"_L1;
372 const QList<QByteArray> &data,
const QString &uti)
const
374 if (data.count() > 1)
375 qWarning(
"QMacMimeUnicodeText: Cannot handle multiple member data");
379 if (uti ==
"public.utf8-plain-text"_L1) {
380 ret = QString::fromUtf8(firstData);
381 }
else if (uti ==
"public.utf16-plain-text"_L1) {
382 QString str = QStringDecoder(QStringDecoder::Utf16)(firstData);
385 qWarning(
"QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
392 const QString &uti)
const
394 QList<QByteArray> ret;
395 QString string = data.toString();
396 if (uti ==
"public.utf8-plain-text"_L1)
397 ret.append(string.toUtf8());
398 else if (uti ==
"public.utf16-plain-text"_L1) {
399 QStringEncoder::Flags f;
400#if defined(Q_OS_MACOS)
404 f = QStringEncoder::Flag::Default;
410 f = QStringEncoder::Flag::WriteBom;
412 QStringEncoder encoder(QStringEncoder::Utf16, f);
413 ret.append(encoder(string));
424 const QString &uti)
const override;
426 const QString &uti)
const override;
431 if (mime ==
"text/html"_L1)
432 return "public.html"_L1;
438 if (uti ==
"public.html"_L1)
439 return "text/html"_L1;
445 const QList<QByteArray> &data,
const QString &uti)
const
449 if (data.count() > 1)
450 qWarning(
"QMacMimeHTMLText: Cannot handle multiple member data");
456 const QVariant &data,
const QString &uti)
const
458 QList<QByteArray> ret;
461 ret.append(data.toByteArray());
471 const QString &uti)
const override;
473 const QString &uti)
const override;
478 if (mime ==
"text/html"_L1)
479 return "public.rtf"_L1;
485 if (uti ==
"public.rtf"_L1)
486 return "text/html"_L1;
492 const QList<QByteArray> &data,
const QString &uti)
const
496 if (data.count() > 1)
497 qWarning(
"QMacMimeHTMLText: Cannot handle multiple member data");
500 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
501 options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
502 documentAttributes:nil
506 NSRange range = NSMakeRange(0, [string length]);
507 NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
508 NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
514 return QByteArray::fromNSData(htmlData).trimmed();
519 const QVariant &data,
const QString &uti)
const
521 QList<QByteArray> ret;
525 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
526 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
527 documentAttributes:nil
531 NSRange range = NSMakeRange(0, [string length]);
532 NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
533 NSData *rtfData = [string dataFromRange:range documentAttributes:dict error:&error];
534 ret << QByteArray::fromNSData(rtfData);
544 const QString &uti)
const override;
546 const QString &uti)
const override;
552 if (mime ==
"text/uri-list"_L1)
553 return "public.file-url"_L1;
559 if (uti ==
"public.file-url"_L1)
560 return "text/uri-list"_L1;
566 const QList<QByteArray> &data,
const QString &uti)
const
571 for (
int i = 0; i < data.size(); ++i) {
573 NSString *urlString = [[[NSString alloc] initWithBytesNoCopy:(
void *)a.data() length:a.size()
574 encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
575 NSURL *nsurl = [NSURL URLWithString:urlString];
578 if ([nsurl isFileReferenceURL]) {
579 url = QUrl::fromNSURL([nsurl filePathURL]);
581 url = QUrl::fromNSURL(nsurl);
584 if (url.host().toLower() ==
"localhost"_L1)
585 url.setHost(QString());
587 url.setPath(url.path().normalized(QString::NormalizationForm_C));
590 return QVariant(ret);
595 const QVariant &data,
const QString &uti)
const
597 QList<QByteArray> ret;
600 QList<QVariant> urls = data.toList();
601 for (
int i = 0; i < urls.size(); ++i) {
602 QUrl url = urls.at(i).toUrl();
603 if (url.scheme().isEmpty())
604 url.setScheme(
"file"_L1);
605 if (url.scheme() ==
"file"_L1) {
606 if (url.host().isEmpty())
607 url.setHost(
"localhost"_L1);
608 url.setPath(url.path().normalized(QString::NormalizationForm_D));
610 if (url.isLocalFile())
611 ret.append(url.toEncoded());
618 return mimeData->urls().count();
627 const QString &uti)
const override;
629 const QString &uti)
const override;
634 if (mime.startsWith(
"text/uri-list"_L1))
635 return "public.url"_L1;
641 if (uti ==
"public.url"_L1)
642 return "text/uri-list"_L1;
647 const QList<QByteArray> &data,
const QString &uti)
const
653 for (
int i=0; i<data.size(); ++i) {
654 QUrl url = QUrl::fromEncoded(data.at(i));
655 if (url.host().toLower() ==
"localhost"_L1)
656 url.setHost(QString());
657 url.setPath(url.path().normalized(QString::NormalizationForm_C));
660 return QVariant(ret);
664 const QVariant &data,
const QString &uti)
const
666 QList<QByteArray> ret;
670 QList<QVariant> urls = data.toList();
671 for (
int i=0; i<urls.size(); ++i) {
672 QUrl url = urls.at(i).toUrl();
673 if (url.scheme().isEmpty())
674 url.setScheme(
"file"_L1);
675 if (url.scheme() ==
"file"_L1) {
676 if (url.host().isEmpty())
677 url.setHost(
"localhost"_L1);
678 url.setPath(url.path().normalized(QString::NormalizationForm_D));
680 ret.append(url.toEncoded());
691 const QString &uti)
const override;
693 const QString &uti)
const override;
698 if (mime.startsWith(
"text/vcard"_L1))
699 return "public.vcard"_L1;
705 if (uti ==
"public.vcard"_L1)
706 return "text/vcard"_L1;
711 const QList<QByteArray> &data,
const QString &uti)
const
716 if (uti ==
"public.vcard"_L1) {
717 for (
int i=0; i<data.size(); ++i)
720 return QVariant(cards);
724 const QVariant &data,
const QString &uti)
const
726 QList<QByteArray> ret;
730 if (mime ==
"text/vcard"_L1)
731 ret.append(data.toString().toUtf8());
744 const QString &uti)
const override;
746 const QString &uti)
const override;
751 if (mime.startsWith(
"application/x-qt-image"_L1))
752 return "public.tiff"_L1;
758 if (uti ==
"public.tiff"_L1)
759 return "application/x-qt-image"_L1;
764 const QList<QByteArray> &data,
const QString &uti)
const
766 if (data.count() > 1)
767 qWarning(
"QMacMimeTiff: Cannot handle multiple member data");
772 QCFType<CFDataRef> tiffData = data.first().toRawCFData();
773 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
775 if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
776 return QVariant(qt_mac_toQImage(image));
782 const QVariant &variant,
const QString &uti)
const
787 QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
788 QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data,
789 (CFStringRef)UTTypeTIFF.identifier, 1, 0);
791 if (!imageDestination)
794 QImage img = qvariant_cast<QImage>(variant);
795 NSDictionary *props = @{
796 static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
797 static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
800 CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img),
801 static_cast<CFDictionaryRef>(props));
802 CGImageDestinationFinalize(imageDestination);
804 return QList<QByteArray>() << QByteArray::fromCFData(data);
809void 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.
Combined button and popup list for selecting options.
QImage qt_mac_toQImage(CGImageRef cgImage)
CGImageRef qt_mac_toCGImage(const QImage &inImage)