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