Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qutimimeconverter.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <ImageIO/ImageIO.h>
5#include <CoreFoundation/CoreFoundation.h>
6#include <UniformTypeIdentifiers/UTCoreTypes.h>
7
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>
13
14#if defined(Q_OS_MACOS)
15#import <AppKit/AppKit.h>
16#else
17#include <MobileCoreServices/MobileCoreServices.h>
18#endif
19
20#if defined(QT_PLATFORM_UIKIT)
21#import <UIKit/UIKit.h>
22#endif
23
27#include "private/qcore_mac_p.h"
28
30
31using namespace Qt::StringLiterals;
32
33/*****************************************************************************
34 QDnD debug facilities
35 *****************************************************************************/
36//#define DEBUG_MIME_MAPS
37
38/*!
39 \class QUtiMimeConverter
40 \brief The QUtiMimeConverter class converts between a MIME type and a
41 \l{https://developer.apple.com/documentation/uniformtypeidentifiers}
42 {Uniform Type Identifier (UTI)} format.
43 \since 6.5
44
45 \ingroup draganddrop
46 \inmodule QtGui
47
48 Qt's drag and drop and clipboard facilities use the MIME
49 standard. On X11, this maps trivially to the Xdnd protocol. On
50 Mac, although some applications use MIME to describe clipboard
51 contents, it is more common to use Apple's UTI format.
52
53 QUtiMimeConverter's role is to bridge the gap between MIME and UTI;
54 By subclasses this class, one can extend Qt's drag and drop
55 and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
56
57 Construct an instance of your converter implementation after instantiating
58 QGuiApplication:
59
60 \code
61 int main(int argc, char **argv)
62 {
63 QGuiApplication app(argc, argv);
64 JsonMimeConverter jsonConverter;
65 }
66 \endcode
67
68 Destroying the instance will unregister the converter and remove support
69 for the conversion. It is also valid to heap-allocate the converter
70 instance; Qt takes ownership and will delete the converter object during
71 QGuiApplication shut-down.
72
73 Qt has predefined support for the following UTIs:
74 \list
75 \li public.utf8-plain-text - converts to "text/plain"
76 \li public.utf16-plain-text - converts to "text/plain"
77 \li public.text - converts to "text/plain"
78 \li public.html - converts to "text/html"
79 \li public.url - converts to "text/uri-list"
80 \li public.file-url - converts to "text/uri-list"
81 \li public.tiff - converts to "application/x-qt-image"
82 \li public.vcard - converts to "text/plain"
83 \li com.apple.traditional-mac-plain-text - converts to "text/plain"
84 \li com.apple.pict - converts to "application/x-qt-image"
85 \endlist
86
87 When working with MIME data, Qt will iterate through all instances of QUtiMimeConverter to find
88 find an instance that can convert to, or from, a specific MIME type. It will do this by calling
89 mimeForUti() or utiForMime() on each instance, starting with (and choosing) the last created
90 instance first. The actual conversions will be done by using convertToMime() and convertFromMime().
91*/
92
93/*!
94 \enum QUtiMimeConverter::HandlerScope
95 \internal
96*/
97
98/*!
99 \internal
100 Constructs a new conversion object of type \a scope, adding it to the
101 globally accessed list of available converters.
102*/
103QUtiMimeConverter::QUtiMimeConverter(HandlerScope scope)
104 : m_scope(scope)
105{
106 QMacMimeRegistry::registerMimeConverter(this);
107}
108
109/*!
110 Constructs a new conversion object and adds it to the
111 globally accessed list of available converters.
112
113 Call this constructor after QGuiApplication has been created.
114*/
115QUtiMimeConverter::QUtiMimeConverter()
116 : QUtiMimeConverter(HandlerScopeFlag::All)
117{
118}
119
120/*!
121 Destroys a conversion object, removing it from the global
122 list of available converters.
123*/
124QUtiMimeConverter::~QUtiMimeConverter()
125{
126 QMacMimeRegistry::unregisterMimeConverter(this);
127}
128
129/*!
130 Returns the item count for the given \a mimeData
131*/
132int QUtiMimeConverter::count(const QMimeData *mimeData) const
133{
134 Q_UNUSED(mimeData);
135 return 1;
136}
137
138/*!
139 \fn bool QUtiMimeConverter::canConvert(const QString &mime, const QString &uti) const
140
141 Returns \c true if the converter can convert (both ways) between
142 \a mime and \a uti; otherwise returns \c false.
143*/
144
145/*!
146 \fn QString QUtiMimeConverter::mimeForUti(const QString &uti) const
147
148 Returns the MIME type used for Mac UTI \a uti, or an empty string if
149 this converter does not support converting from \a uti.
150
151 All subclasses must reimplement this pure virtual function.
152*/
153
154/*!
155 \fn QString QUtiMimeConverter::utiForMime(const QString &mime) const
156
157 Returns the Mac UTI used for MIME type \a mime, or an empty string if
158 this converter does not support converting from \a mime.
159
160 All subclasses must reimplement this pure virtual function.
161*/
162
163/*!
164 \fn QVariant QUtiMimeConverter::convertToMime(const QString &mime,
165 const QList<QByteArray> &data, const QString &uti) const
166
167 Returns \a data converted from Mac UTI \a uti to MIME type \a mime.
168
169 Note that Mac UTIs must all be self-terminating. The input \a data
170 may contain trailing data.
171
172 All subclasses must reimplement this pure virtual function.
173*/
174
175/*!
176 \fn QList<QByteArray> QUtiMimeConverter::convertFromMime(const QString &mime,
177 const QVariant &data, const QString & uti) const
178
179 Returns \a data converted from MIME type \a mime to Mac UTI \a uti.
180
181 Note that Mac UTIs must all be self-terminating. The return
182 value may contain trailing data.
183
184 All subclasses must reimplement this pure virtual function.
185*/
186
187
189public:
191
192 QString utiForMime(const QString &mime) const override;
193 QString mimeForUti(const QString &uti) const override;
194 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
195 const QString &uti) const override;
196 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
197 const QString &uti) const override;
198};
199
200QString QMacMimeAny::utiForMime(const QString &mime) const
201{
202 // do not handle the mime type name in the drag pasteboard
203 if (mime == "application/x-qt-mime-type-name"_L1)
204 return QString();
205 QString ret = "com.trolltech.anymime."_L1 + mime;
206 return ret.replace(u'/', "--"_L1);
207}
208
209QString QMacMimeAny::mimeForUti(const QString &uti) const
210{
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);
214 return QString();
215}
216
217QVariant QMacMimeAny::convertToMime(const QString &mime, const QList<QByteArray> &data,
218 const QString &) const
219{
220 if (data.count() > 1)
221 qWarning("QMacMimeAny: Cannot handle multiple member data");
222 QVariant ret;
223 if (mime == "text/plain"_L1)
224 ret = QString::fromUtf8(data.first());
225 else
226 ret = data.first();
227 return ret;
228}
229
230QList<QByteArray> QMacMimeAny::convertFromMime(const QString &mime, const QVariant &data,
231 const QString &) const
232{
233 QList<QByteArray> ret;
234 if (mime == "text/plain"_L1)
235 ret.append(data.toString().toUtf8());
236 else
237 ret.append(data.toByteArray());
238 return ret;
239}
240
242private:
243
244public:
246
247 QString utiForMime(const QString &mime) const override;
248 QString mimeForUti(const QString &uti) const override;
249 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data, const QString &uti) const override;
250 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override;
251};
252
253QString QMacMimeTypeName::utiForMime(const QString &mime) const
254{
255 if (mime == "application/x-qt-mime-type-name"_L1)
256 return u"com.trolltech.qt.MimeTypeName"_s;
257 return QString();
258}
259
260QString QMacMimeTypeName::mimeForUti(const QString &) const
261{
262 return QString();
263}
264
265QVariant QMacMimeTypeName::convertToMime(const QString &, const QList<QByteArray> &, const QString &) const
266{
267 QVariant ret;
268 return ret;
269}
270
271QList<QByteArray> QMacMimeTypeName::convertFromMime(const QString &, const QVariant &, const QString &) const
272{
273 QList<QByteArray> ret;
274 ret.append(QString("x-qt-mime-type-name"_L1).toUtf8());
275 return ret;
276}
277
279{
280public:
281 QString utiForMime(const QString &mime) const override;
282 QString mimeForUti(const QString &uti) const override;
283 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
284 const QString &uti) const override;
285 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
286 const QString &uti) const override;
287};
288
289QString QMacMimePlainTextFallback::utiForMime(const QString &mime) const
290{
291 if (mime == "text/plain"_L1)
292 return "public.text"_L1;
293 return QString();
294}
295
296QString QMacMimePlainTextFallback::mimeForUti(const QString &uti) const
297{
298 if (uti == "public.text"_L1)
299 return "text/plain"_L1;
300 return QString();
301}
302
303QVariant
305 const QList<QByteArray> &data, const QString &uti) const
306{
307 if (data.count() > 1)
308 qWarning("QMacMimePlainTextFallback: Cannot handle multiple member data");
309
310 if (uti == "public.text"_L1) {
311 // Note that public.text is documented by Apple to have an undefined encoding. From
312 // testing it seems that utf8 is normally used, at least by Safari on iOS.
313 const QByteArray &firstData = data.first();
314 return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault,
315 reinterpret_cast<const UInt8 *>(firstData.constData()),
316 firstData.size(), kCFStringEncodingUTF8, false)));
317 } else {
318 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
319 }
320 return QVariant();
321}
322
324QMacMimePlainTextFallback::convertFromMime(const QString &, const QVariant &data,
325 const QString &uti) const
326{
327 QList<QByteArray> ret;
328 QString string = data.toString();
329 if (uti == "public.text"_L1)
330 ret.append(string.toUtf8());
331 return ret;
332}
333
335{
336public:
337 QString utiForMime(const QString &mime) const override;
338 QString mimeForUti(const QString &uti) const override;
339 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
340 const QString &uti) const override;
341 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
342 const QString &uti) const override;
343};
344
345QString QMacMimeUnicodeText::utiForMime(const QString &mime) const
346{
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';');
352 if (i >= 0)
353 cs = cs.left(i);
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;
358 }
359 return QString();
360}
361
362QString QMacMimeUnicodeText::mimeForUti(const QString &uti) const
363{
364 if (uti == "public.utf16-plain-text"_L1 || uti == "public.utf8-plain-text"_L1)
365 return "text/plain"_L1;
366 return QString();
367}
368
369QVariant
370QMacMimeUnicodeText::convertToMime(const QString &mimetype,
371 const QList<QByteArray> &data, const QString &uti) const
372{
373 if (data.count() > 1)
374 qWarning("QMacMimeUnicodeText: Cannot handle multiple member data");
375 const QByteArray &firstData = data.first();
376 // I can only handle two types (system and unicode) so deal with them that way
377 QVariant ret;
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);
382 ret = str;
383 } else {
384 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
385 }
386 return ret;
387}
388
390QMacMimeUnicodeText::convertFromMime(const QString &, const QVariant &data,
391 const QString &uti) const
392{
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)
400 // Some applications such as Microsoft Excel, don't deal well with
401 // a BOM present, so we follow the traditional approach of Qt on
402 // macOS to not generate public.utf16-plain-text with a BOM.
403 f = QStringEncoder::Flag::Default;
404#else
405 // Whereas iOS applications will fail to paste if we do _not_
406 // include a BOM in the public.utf16-plain-text content, most
407 // likely due to converting the data using NSUTF16StringEncoding
408 // which assumes big-endian byte order if there is no BOM.
409 f = QStringEncoder::Flag::WriteBom;
410#endif
411 QStringEncoder encoder(QStringEncoder::Utf16, f);
412 ret.append(encoder(string));
413 }
414 return ret;
415}
416
418{
419public:
420 QString utiForMime(const QString &mime) const override;
421 QString mimeForUti(const QString &uti) const override;
422 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
423 const QString &uti) const override;
424 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
425 const QString &uti) const override;
426};
427
428QString QMacMimeHTMLText::utiForMime(const QString &mime) const
429{
430 if (mime == "text/html"_L1)
431 return "public.html"_L1;
432 return QString();
433}
434
435QString QMacMimeHTMLText::mimeForUti(const QString &uti) const
436{
437 if (uti == "public.html"_L1)
438 return "text/html"_L1;
439 return QString();
440}
441
442QVariant
443QMacMimeHTMLText::convertToMime(const QString &mimeType,
444 const QList<QByteArray> &data, const QString &uti) const
445{
446 if (!canConvert(mimeType, uti))
447 return QVariant();
448 if (data.count() > 1)
449 qWarning("QMacMimeHTMLText: Cannot handle multiple member data");
450 return data.first();
451}
452
455 const QVariant &data, const QString &uti) const
456{
457 QList<QByteArray> ret;
458 if (!canConvert(mime, uti))
459 return ret;
460 ret.append(data.toByteArray());
461 return ret;
462}
463
465{
466public:
467 QString utiForMime(const QString &mime) const override;
468 QString mimeForUti(const QString &uti) const override;
469 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
470 const QString &uti) const override;
471 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
472 const QString &uti) const override;
473};
474
475QString QMacMimeRtfText::utiForMime(const QString &mime) const
476{
477 if (mime == "text/html"_L1)
478 return "public.rtf"_L1;
479 return QString();
480}
481
482QString QMacMimeRtfText::mimeForUti(const QString &uti) const
483{
484 if (uti == "public.rtf"_L1)
485 return "text/html"_L1;
486 return QString();
487}
488
489QVariant
490QMacMimeRtfText::convertToMime(const QString &mimeType,
491 const QList<QByteArray> &data, const QString &uti) const
492{
493 if (!canConvert(mimeType, uti))
494 return QVariant();
495 if (data.count() > 1)
496 qWarning("QMacMimeHTMLText: Cannot handle multiple member data");
497
498 // Read RTF into to NSAttributedString, then convert the string to HTML
499 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
500 options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
501 documentAttributes:nil
502 error:nil];
503
504 NSError *error;
505 NSRange range = NSMakeRange(0, [string length]);
506 NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
507 NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
508
509 // Note: We trim the data here, as NSAttributedString wrongly inserts a newline at the
510 // end when generating HTML, which HTML parsers (including our own QTextHtmlParser)
511 // correctly treat as an additional white space in the body of the HTML document
512 // (see HTML5 § 13.2.6.4.22 - The "after after body" insertion mode).
513 return QByteArray::fromNSData(htmlData).trimmed();
514}
515
517QMacMimeRtfText::convertFromMime(const QString &mime,
518 const QVariant &data, const QString &uti) const
519{
520 QList<QByteArray> ret;
521 if (!canConvert(mime, uti))
522 return ret;
523
524 NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
525 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
526 documentAttributes:nil
527 error:nil];
528
529 NSError *error;
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);
534 return ret;
535}
536
538{
539public:
540 QString utiForMime(const QString &mime) const override;
541 QString mimeForUti(const QString &uti) const override;
542 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
543 const QString &uti) const override;
544 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
545 const QString &uti) const override;
546 int count(const QMimeData *mimeData) const override;
547};
548
549QString QMacMimeFileUri::utiForMime(const QString &mime) const
550{
551 if (mime == "text/uri-list"_L1)
552 return "public.file-url"_L1;
553 return QString();
554}
555
556QString QMacMimeFileUri::mimeForUti(const QString &uti) const
557{
558 if (uti == "public.file-url"_L1)
559 return "text/uri-list"_L1;
560 return QString();
561}
562
563QVariant
564QMacMimeFileUri::convertToMime(const QString &mime,
565 const QList<QByteArray> &data, const QString &uti) const
566{
567 if (!canConvert(mime, uti))
568 return QVariant();
569 QList<QVariant> ret;
570 for (int i = 0; i < data.size(); ++i) {
571 const QByteArray &a = data.at(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];
575 QUrl url;
576 // OS X 10.10 sends file references instead of file paths
577 if ([nsurl isFileReferenceURL]) {
578 url = QUrl::fromNSURL([nsurl filePathURL]);
579 } else {
580 url = QUrl::fromNSURL(nsurl);
581 }
582
583 if (url.host().toLower() == "localhost"_L1)
584 url.setHost(QString());
585
586 url.setPath(url.path().normalized(QString::NormalizationForm_C));
587 ret.append(url);
588 }
589 return QVariant(ret);
590}
591
593QMacMimeFileUri::convertFromMime(const QString &mime,
594 const QVariant &data, const QString &uti) const
595{
596 QList<QByteArray> ret;
597 if (!canConvert(mime, uti))
598 return 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));
608 }
609 if (url.isLocalFile())
610 ret.append(url.toEncoded());
611 }
612 return ret;
613}
614
615int QMacMimeFileUri::count(const QMimeData *mimeData) const
616{
617 return mimeData->urls().count();
618}
619
621{
622public:
623 QString utiForMime(const QString &mime) const override;
624 QString mimeForUti(const QString &uti) const override;
625 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
626 const QString &uti) const override;
627 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
628 const QString &uti) const override;
629};
630
631QString QMacMimeUrl::utiForMime(const QString &mime) const
632{
633 if (mime.startsWith("text/uri-list"_L1))
634 return "public.url"_L1;
635 return QString();
636}
637
638QString QMacMimeUrl::mimeForUti(const QString &uti) const
639{
640 if (uti == "public.url"_L1)
641 return "text/uri-list"_L1;
642 return QString();
643}
644
645QVariant QMacMimeUrl::convertToMime(const QString &mime,
646 const QList<QByteArray> &data, const QString &uti) const
647{
648 if (!canConvert(mime, uti))
649 return QVariant();
650
651 QList<QVariant> ret;
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));
657 ret.append(url);
658 }
659 return QVariant(ret);
660}
661
663 const QVariant &data, const QString &uti) const
664{
665 QList<QByteArray> ret;
666 if (!canConvert(mime, uti))
667 return ret;
668
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));
678 }
679 ret.append(url.toEncoded());
680 }
681 return ret;
682}
683
685{
686public:
687 QString utiForMime(const QString &mime) const override;
688 QString mimeForUti(const QString &uti) const override;
689 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
690 const QString &uti) const override;
691 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
692 const QString &uti) const override;
693};
694
695QString QMacMimeVCard::utiForMime(const QString &mime) const
696{
697 if (mime.startsWith("text/vcard"_L1))
698 return "public.vcard"_L1;
699 return QString();
700}
701
702QString QMacMimeVCard::mimeForUti(const QString &uti) const
703{
704 if (uti == "public.vcard"_L1)
705 return "text/vcard"_L1;
706 return QString();
707}
708
709QVariant QMacMimeVCard::convertToMime(const QString &mime,
710 const QList<QByteArray> &data, const QString &uti) const
711{
712 if (!canConvert(mime, uti))
713 return QVariant();
714 QByteArray cards;
715 if (uti == "public.vcard"_L1) {
716 for (int i=0; i<data.size(); ++i)
717 cards += data[i];
718 }
719 return QVariant(cards);
720}
721
723 const QVariant &data, const QString &uti) const
724{
725 QList<QByteArray> ret;
726 if (!canConvert(mime, uti))
727 return ret;
728
729 if (mime == "text/vcard"_L1)
730 ret.append(data.toString().toUtf8());
731 return ret;
732}
733
734extern QImage qt_mac_toQImage(CGImageRef image);
735extern CGImageRef qt_mac_toCGImage(const QImage &qImage);
736
738{
739public:
740 QString utiForMime(const QString &mime) const override;
741 QString mimeForUti(const QString &uti) const override;
742 QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
743 const QString &uti) const override;
744 QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
745 const QString &uti) const override;
746};
747
748QString QMacMimeTiff::utiForMime(const QString &mime) const
749{
750 if (mime.startsWith("application/x-qt-image"_L1))
751 return "public.tiff"_L1;
752 return QString();
753}
754
755QString QMacMimeTiff::mimeForUti(const QString &uti) const
756{
757 if (uti == "public.tiff"_L1)
758 return "application/x-qt-image"_L1;
759 return QString();
760}
761
762QVariant QMacMimeTiff::convertToMime(const QString &mime,
763 const QList<QByteArray> &data, const QString &uti) const
764{
765 if (data.count() > 1)
766 qWarning("QMacMimeTiff: Cannot handle multiple member data");
767
768 if (!canConvert(mime, uti))
769 return QVariant();
770
771 QCFType<CFDataRef> tiffData = data.first().toRawCFData();
772 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
773
774 if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
775 return QVariant(qt_mac_toQImage(image));
776
777 return QVariant();
778}
779
781 const QVariant &variant, const QString &uti) const
782{
783 if (!canConvert(mime, uti))
784 return QList<QByteArray>();
785
786 QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
787 QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data,
788 (CFStringRef)UTTypeTIFF.identifier, 1, 0);
789
790 if (!imageDestination)
791 return QList<QByteArray>();
792
793 QImage img = qvariant_cast<QImage>(variant);
794 NSDictionary *props = @{
795 static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
796 static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
797 };
798
799 CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img),
800 static_cast<CFDictionaryRef>(props));
801 CGImageDestinationFinalize(imageDestination);
802
803 return QList<QByteArray>() << QByteArray::fromCFData(data);
804}
805
806namespace QMacMimeRegistry {
807
808void registerBuiltInTypes()
809{
810 // Create QMacMimeAny first to put it at the end of globalMimeList
811 // with lowest priority. (the constructor prepends to the list)
812 new QMacMimeAny;
813
814 //standard types that we wrap
815 new QMacMimeTiff;
818 new QMacMimeRtfText;
820 new QMacMimeFileUri;
821 new QMacMimeUrl;
823 new QMacMimeVCard;
824}
825
826}
827
828QT_END_NAMESPACE
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)