1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qmime.h"
43
44 //#define USE_INTERNET_CONFIG
45
46 #ifndef USE_INTERNET_CONFIG
47 # include "qfile.h"
48 # include "qfileinfo.h"
49 # include "qtextstream.h"
50 # include "qdir.h"
51 # include <unistd.h>
52 # include <sys/types.h>
53 # include <sys/stat.h>
54 # include <sys/fcntl.h>
55 #endif
56
57 #include "qdebug.h"
58 #include "qpixmap.h"
59 #include "qimagewriter.h"
60 #include "qimagereader.h"
61 #include "qdatastream.h"
62 #include "qbuffer.h"
63 #include "qdatetime.h"
64 #include "qapplication_p.h"
65 #include "qtextcodec.h"
66 #include "qregexp.h"
67 #include "qurl.h"
68 #include "qmap.h"
69 #include <private/qt_mac_p.h>
70
71
72 #ifdef Q_WS_MAC32
73 #include <QuickTime/QuickTime.h>
74 #include <qlibrary.h>
75 #endif
76
77 QT_BEGIN_NAMESPACE
78
79 extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp
80
81 typedef QList<QMacPasteboardMime*> MimeList;
Q_GLOBAL_STATIC(MimeList,globalMimeList)82 Q_GLOBAL_STATIC(MimeList, globalMimeList)
83
84 static void cleanup_mimes()
85 {
86 MimeList *mimes = globalMimeList();
87 while (!mimes->isEmpty())
88 delete mimes->takeFirst();
89 }
90
Q_GLOBAL_STATIC(QStringList,globalDraggedTypesList)91 Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
92
93 /*!
94 \fn void qRegisterDraggedTypes(const QStringList &types)
95 \relates QMacPasteboardMime
96
97 Registers the given \a types as custom pasteboard types.
98
99 This function should be called to enable the Drag and Drop events
100 for custom pasteboard types on Cocoa implementations. This is required
101 in addition to a QMacPasteboardMime subclass implementation. By default
102 drag and drop is enabled for all standard pasteboard types.
103
104 \sa QMacPasteboardMime
105 */
106 Q_GUI_EXPORT void qRegisterDraggedTypes(const QStringList &types)
107 {
108 (*globalDraggedTypesList()) += types;
109 }
110
qEnabledDraggedTypes()111 const QStringList& qEnabledDraggedTypes()
112 {
113 return (*globalDraggedTypesList());
114 }
115
116
117 /*****************************************************************************
118 QDnD debug facilities
119 *****************************************************************************/
120 //#define DEBUG_MIME_MAPS
121
122 ScrapFlavorType qt_mac_mime_type = 'CUTE';
123 CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
124
125 /*!
126 \class QMacPasteboardMime
127 \brief The QMacPasteboardMime class converts between a MIME type and a
128 \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
129 Type Identifier (UTI)} format.
130 \since 4.2
131
132 \ingroup draganddrop
133
134 Qt's drag and drop and clipboard facilities use the MIME
135 standard. On X11, this maps trivially to the Xdnd protocol. On
136 Mac, although some applications use MIME to describe clipboard
137 contents, it is more common to use Apple's UTI format.
138
139 QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
140 By subclasses this class, one can extend Qt's drag and drop
141 and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
142
143 A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
144
145 Qt has predefined support for the following UTIs:
146 \list
147 \i public.utf8-plain-text - converts to "text/plain"
148 \i public.utf16-plain-text - converts to "text/plain"
149 \i public.html - converts to "text/html"
150 \i public.url - converts to "text/uri-list"
151 \i public.file-url - converts to "text/uri-list"
152 \i public.tiff - converts to "application/x-qt-image"
153 \i public.vcard - converts to "text/plain"
154 \i com.apple.traditional-mac-plain-text - converts to "text/plain"
155 \i com.apple.pict - converts to "application/x-qt-image"
156 \endlist
157
158 When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
159 find an instance that can convert to, or from, a specific MIME type. It will do this by calling
160 canConvert() on each instance, starting with (and choosing) the last created instance first.
161 The actual conversions will be done by using convertToMime() and convertFromMime().
162
163 \note The API uses the term "flavor" in some cases. This is for backwards
164 compatibility reasons, and should now be understood as UTIs.
165 */
166
167 /*! \enum QMacPasteboardMime::QMacPasteboardMimeType
168 \internal
169 */
170
171 /*!
172 Constructs a new conversion object of type \a t, adding it to the
173 globally accessed list of available convertors.
174 */
QMacPasteboardMime(char t)175 QMacPasteboardMime::QMacPasteboardMime(char t) : type(t)
176 {
177 globalMimeList()->append(this);
178 }
179
180 /*!
181 Destroys a conversion object, removing it from the global
182 list of available convertors.
183 */
~QMacPasteboardMime()184 QMacPasteboardMime::~QMacPasteboardMime()
185 {
186 if(!QApplication::closingDown())
187 globalMimeList()->removeAll(this);
188 }
189
190 class QMacPasteboardMimeAny : public QMacPasteboardMime {
191 private:
192
193 public:
QMacPasteboardMimeAny()194 QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
195 }
~QMacPasteboardMimeAny()196 ~QMacPasteboardMimeAny() {
197 }
198 QString convertorName();
199
200 QString flavorFor(const QString &mime);
201 QString mimeFor(QString flav);
202 bool canConvert(const QString &mime, QString flav);
203 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
204 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
205 };
206
convertorName()207 QString QMacPasteboardMimeAny::convertorName()
208 {
209 return QLatin1String("Any-Mime");
210 }
211
flavorFor(const QString & mime)212 QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
213 {
214 // do not handle the mime type name in the drag pasteboard
215 if(mime == QLatin1String("application/x-qt-mime-type-name"))
216 return QString();
217 QString ret = QLatin1String("com.trolltech.anymime.") + mime;
218 return ret.replace(QLatin1Char('/'), QLatin1String("--"));
219 }
220
mimeFor(QString flav)221 QString QMacPasteboardMimeAny::mimeFor(QString flav)
222 {
223 const QString any_prefix = QLatin1String("com.trolltech.anymime.");
224 if(flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
225 return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
226 return QString();
227 }
228
canConvert(const QString & mime,QString flav)229 bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
230 {
231 return mimeFor(flav) == mime;
232 }
233
convertToMime(const QString & mime,QList<QByteArray> data,QString)234 QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
235 {
236 if(data.count() > 1)
237 qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
238 QVariant ret;
239 if (mime == QLatin1String("text/plain"))
240 ret = QString::fromUtf8(data.first());
241 else
242 ret = data.first();
243 return ret;
244 }
245
convertFromMime(const QString & mime,QVariant data,QString)246 QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
247 {
248 QList<QByteArray> ret;
249 if (mime == QLatin1String("text/plain"))
250 ret.append(data.toString().toUtf8());
251 else
252 ret.append(data.toByteArray());
253 return ret;
254 }
255
256 class QMacPasteboardMimeTypeName : public QMacPasteboardMime {
257 private:
258
259 public:
QMacPasteboardMimeTypeName()260 QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
261 }
~QMacPasteboardMimeTypeName()262 ~QMacPasteboardMimeTypeName() {
263 }
264 QString convertorName();
265
266 QString flavorFor(const QString &mime);
267 QString mimeFor(QString flav);
268 bool canConvert(const QString &mime, QString flav);
269 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
270 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
271 };
272
convertorName()273 QString QMacPasteboardMimeTypeName::convertorName()
274 {
275 return QLatin1String("Qt-Mime-Type");
276 }
277
flavorFor(const QString & mime)278 QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
279 {
280 if(mime == QLatin1String("application/x-qt-mime-type-name"))
281 return QLatin1String("com.trolltech.qt.MimeTypeName");
282 return QString();
283 }
284
mimeFor(QString)285 QString QMacPasteboardMimeTypeName::mimeFor(QString)
286 {
287 return QString();
288 }
289
canConvert(const QString &,QString)290 bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
291 {
292 return false;
293 }
294
convertToMime(const QString &,QList<QByteArray>,QString)295 QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
296 {
297 QVariant ret;
298 return ret;
299 }
300
convertFromMime(const QString &,QVariant,QString)301 QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
302 {
303 QList<QByteArray> ret;
304 ret.append(QString("x-qt-mime-type-name").toUtf8());
305 return ret;
306 }
307
308 class QMacPasteboardMimePlainText : public QMacPasteboardMime {
309 public:
QMacPasteboardMimePlainText()310 QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { }
311 QString convertorName();
312
313 QString flavorFor(const QString &mime);
314 QString mimeFor(QString flav);
315 bool canConvert(const QString &mime, QString flav);
316 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
317 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
318 };
319
convertorName()320 QString QMacPasteboardMimePlainText::convertorName()
321 {
322 return QLatin1String("PlainText");
323 }
324
flavorFor(const QString & mime)325 QString QMacPasteboardMimePlainText::flavorFor(const QString &mime)
326 {
327 if (mime == QLatin1String("text/plain"))
328 return QLatin1String("com.apple.traditional-mac-plain-text");
329 return QString();
330 }
331
mimeFor(QString flav)332 QString QMacPasteboardMimePlainText::mimeFor(QString flav)
333 {
334 if (flav == QLatin1String("com.apple.traditional-mac-plain-text"))
335 return QLatin1String("text/plain");
336 return QString();
337 }
338
canConvert(const QString & mime,QString flav)339 bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav)
340 {
341 return flavorFor(mime) == flav;
342 }
343
convertToMime(const QString & mimetype,QList<QByteArray> data,QString flavor)344 QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
345 {
346 if(data.count() > 1)
347 qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data");
348 const QByteArray &firstData = data.first();
349 QVariant ret;
350 if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) {
351 QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
352 reinterpret_cast<const UInt8 *>(firstData.constData()),
353 firstData.size(), CFStringGetSystemEncoding(), false));
354 ret = QString(str);
355 } else {
356 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
357 }
358 return ret;
359 }
360
convertFromMime(const QString &,QVariant data,QString flavor)361 QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor)
362 {
363 QList<QByteArray> ret;
364 QString string = data.toString();
365 if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text")))
366 ret.append(string.toLatin1());
367 return ret;
368 }
369
370 class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime {
371 public:
QMacPasteboardMimeUnicodeText()372 QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { }
373 QString convertorName();
374
375 QString flavorFor(const QString &mime);
376 QString mimeFor(QString flav);
377 bool canConvert(const QString &mime, QString flav);
378 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
379 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
380 };
381
convertorName()382 QString QMacPasteboardMimeUnicodeText::convertorName()
383 {
384 return QLatin1String("UnicodeText");
385 }
386
flavorFor(const QString & mime)387 QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
388 {
389 if (mime == QLatin1String("text/plain"))
390 return QLatin1String("public.utf16-plain-text");
391 int i = mime.indexOf(QLatin1String("charset="));
392 if (i >= 0) {
393 QString cs(mime.mid(i+8).toLower());
394 i = cs.indexOf(QLatin1Char(';'));
395 if (i>=0)
396 cs = cs.left(i);
397 if (cs == QLatin1String("system"))
398 return QLatin1String("public.utf8-plain-text");
399 else if (cs == QLatin1String("iso-10646-ucs-2")
400 || cs == QLatin1String("utf16"))
401 return QLatin1String("public.utf16-plain-text");
402 }
403 return QString();
404 }
405
mimeFor(QString flav)406 QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
407 {
408 if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
409 return QLatin1String("text/plain");
410 return QString();
411 }
412
canConvert(const QString & mime,QString flav)413 bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
414 {
415 return flavorFor(mime) == flav;
416 }
417
convertToMime(const QString & mimetype,QList<QByteArray> data,QString flavor)418 QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
419 {
420 if(data.count() > 1)
421 qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
422 const QByteArray &firstData = data.first();
423 // I can only handle two types (system and unicode) so deal with them that way
424 QVariant ret;
425 if(flavor == QLatin1String("public.utf8-plain-text")) {
426 QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
427 reinterpret_cast<const UInt8 *>(firstData.constData()),
428 firstData.size(), CFStringGetSystemEncoding(), false));
429 ret = QString(str);
430 } else if (flavor == QLatin1String("public.utf16-plain-text")) {
431 ret = QString(reinterpret_cast<const QChar *>(firstData.constData()),
432 firstData.size() / sizeof(QChar));
433 } else {
434 qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
435 }
436 return ret;
437 }
438
convertFromMime(const QString &,QVariant data,QString flavor)439 QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
440 {
441 QList<QByteArray> ret;
442 QString string = data.toString();
443 if(flavor == QLatin1String("public.utf8-plain-text"))
444 ret.append(string.toUtf8());
445 else if (flavor == QLatin1String("public.utf16-plain-text"))
446 ret.append(QByteArray((char*)string.utf16(), string.length()*2));
447 return ret;
448 }
449
450 class QMacPasteboardMimeHTMLText : public QMacPasteboardMime {
451 public:
QMacPasteboardMimeHTMLText()452 QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { }
453 QString convertorName();
454
455 QString flavorFor(const QString &mime);
456 QString mimeFor(QString flav);
457 bool canConvert(const QString &mime, QString flav);
458 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
459 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
460 };
461
convertorName()462 QString QMacPasteboardMimeHTMLText::convertorName()
463 {
464 return QLatin1String("HTML");
465 }
466
flavorFor(const QString & mime)467 QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
468 {
469 if (mime == QLatin1String("text/html"))
470 return QLatin1String("public.html");
471 return QString();
472 }
473
mimeFor(QString flav)474 QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
475 {
476 if (flav == QLatin1String("public.html"))
477 return QLatin1String("text/html");
478 return QString();
479 }
480
canConvert(const QString & mime,QString flav)481 bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
482 {
483 return flavorFor(mime) == flav;
484 }
485
convertToMime(const QString & mimeType,QList<QByteArray> data,QString flavor)486 QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
487 {
488 if (!canConvert(mimeType, flavor))
489 return QVariant();
490 if (data.count() > 1)
491 qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
492 return data.first();
493 }
494
convertFromMime(const QString & mime,QVariant data,QString flavor)495 QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
496 {
497 QList<QByteArray> ret;
498 if (!canConvert(mime, flavor))
499 return ret;
500 ret.append(data.toByteArray());
501 return ret;
502 }
503
504
505 #ifdef Q_WS_MAC32
506
507 // This can be removed once 10.6 is the minimum (or we have to require 64-bit) whichever comes first.
508
509 typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle);
510 typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32);
511 typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef);
512 typedef ComponentResult (*PtrGraphicsExportSetOutputHandle)(GraphicsExportComponent, Handle);
513 typedef ComponentResult (*PtrGraphicsExportDoExport)(GraphicsExportComponent, unsigned long *);
514
515 static PtrGraphicsImportSetDataHandle ptrGraphicsImportSetDataHandle = 0;
516 static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0;
517 static PtrGraphicsExportSetInputCGImage ptrGraphicsExportSetInputCGImage = 0;
518 static PtrGraphicsExportSetOutputHandle ptrGraphicsExportSetOutputHandle = 0;
519 static PtrGraphicsExportDoExport ptrGraphicsExportDoExport = 0;
520
resolveMimeQuickTimeSymbols()521 static bool resolveMimeQuickTimeSymbols()
522 {
523 static bool triedResolve = false;
524 if (!triedResolve) {
525 QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime"));
526 ptrGraphicsImportSetDataHandle = reinterpret_cast<PtrGraphicsImportSetDataHandle>(library.resolve("GraphicsImportSetDataHandle"));
527 ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage"));
528 ptrGraphicsExportSetInputCGImage = reinterpret_cast<PtrGraphicsExportSetInputCGImage>(library.resolve("GraphicsExportSetInputCGImage"));
529 ptrGraphicsExportSetOutputHandle = reinterpret_cast<PtrGraphicsExportSetOutputHandle>(library.resolve("GraphicsExportSetOutputHandle"));
530 ptrGraphicsExportDoExport = reinterpret_cast<PtrGraphicsExportDoExport>(library.resolve("GraphicsExportDoExport"));
531 triedResolve = true;
532 }
533
534 return ptrGraphicsImportSetDataHandle != 0
535 && ptrGraphicsImportCreateCGImage != 0 && ptrGraphicsExportSetInputCGImage != 0
536 && ptrGraphicsExportSetOutputHandle != 0 && ptrGraphicsExportDoExport != 0;
537 }
538
539 class QMacPasteboardMimePict : public QMacPasteboardMime {
540 public:
QMacPasteboardMimePict()541 QMacPasteboardMimePict() : QMacPasteboardMime(MIME_ALL) { }
542 QString convertorName();
543
544 QString flavorFor(const QString &mime);
545 QString mimeFor(QString flav);
546 bool canConvert(const QString &mime, QString flav);
547 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
548 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
549 };
550
convertorName()551 QString QMacPasteboardMimePict::convertorName()
552 {
553 return QLatin1String("Pict");
554 }
555
flavorFor(const QString & mime)556 QString QMacPasteboardMimePict::flavorFor(const QString &mime)
557 {
558 if(mime.startsWith(QLatin1String("application/x-qt-image")))
559 return QLatin1String("com.apple.pict");
560 return QString();
561 }
562
mimeFor(QString flav)563 QString QMacPasteboardMimePict::mimeFor(QString flav)
564 {
565 if(flav == QLatin1String("com.apple.pict"))
566 return QLatin1String("application/x-qt-image");
567 return QString();
568 }
569
canConvert(const QString & mime,QString flav)570 bool QMacPasteboardMimePict::canConvert(const QString &mime, QString flav)
571 {
572 return flav == QLatin1String("com.apple.pict")
573 && mime == QLatin1String("application/x-qt-image");
574 }
575
576
convertToMime(const QString & mime,QList<QByteArray> data,QString flav)577 QVariant QMacPasteboardMimePict::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
578 {
579 if(data.count() > 1)
580 qWarning("QMacPasteboardMimePict: Cannot handle multiple member data");
581 QVariant ret;
582 if (!resolveMimeQuickTimeSymbols())
583 return ret;
584
585 if(!canConvert(mime, flav))
586 return ret;
587 const QByteArray &a = data.first();
588
589 // This function expects the 512 header (just to skip it, so create the extra space for it).
590 Handle pic = NewHandle(a.size() + 512);
591 memcpy(*pic + 512, a.constData(), a.size());
592
593 GraphicsImportComponent graphicsImporter;
594 ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType,
595 kQTFileTypePicture, &graphicsImporter);
596 QCFType<CGImageRef> cgImage;
597 if (!result)
598 result = ptrGraphicsImportSetDataHandle(graphicsImporter, pic);
599 if (!result)
600 result = ptrGraphicsImportCreateCGImage(graphicsImporter, &cgImage,
601 kGraphicsImportCreateCGImageUsingCurrentSettings);
602 if (!result)
603 ret = QVariant(QPixmap::fromMacCGImageRef(cgImage).toImage());
604 CloseComponent(graphicsImporter);
605 DisposeHandle(pic);
606 return ret;
607 }
608
convertFromMime(const QString & mime,QVariant variant,QString flav)609 QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, QVariant variant,
610 QString flav)
611 {
612 QList<QByteArray> ret;
613 if (!resolveMimeQuickTimeSymbols())
614 return ret;
615
616 if (!canConvert(mime, flav))
617 return ret;
618 QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(qvariant_cast<QImage>(variant));
619 Handle pic = NewHandle(0);
620 GraphicsExportComponent graphicsExporter;
621 ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
622 kQTFileTypePicture, &graphicsExporter);
623 if (!result) {
624 unsigned long sizeWritten;
625 result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
626 if (!result)
627 result = ptrGraphicsExportSetOutputHandle(graphicsExporter, pic);
628 if (!result)
629 result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
630
631 CloseComponent(graphicsExporter);
632 }
633
634 int size = GetHandleSize((Handle)pic);
635 // Skip the Picture File header (512 bytes) and feed the raw data
636 QByteArray ar(reinterpret_cast<char *>(*pic + 512), size - 512);
637 ret.append(ar);
638 DisposeHandle(pic);
639 return ret;
640 }
641
642
643 #endif //Q_WS_MAC32
644
645 class QMacPasteboardMimeTiff : public QMacPasteboardMime {
646 public:
QMacPasteboardMimeTiff()647 QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { }
648 QString convertorName();
649
650 QString flavorFor(const QString &mime);
651 QString mimeFor(QString flav);
652 bool canConvert(const QString &mime, QString flav);
653 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
654 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
655 };
656
convertorName()657 QString QMacPasteboardMimeTiff::convertorName()
658 {
659 return QLatin1String("Tiff");
660 }
661
flavorFor(const QString & mime)662 QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
663 {
664 if(mime.startsWith(QLatin1String("application/x-qt-image")))
665 return QLatin1String("public.tiff");
666 return QString();
667 }
668
mimeFor(QString flav)669 QString QMacPasteboardMimeTiff::mimeFor(QString flav)
670 {
671 if(flav == QLatin1String("public.tiff"))
672 return QLatin1String("application/x-qt-image");
673 return QString();
674 }
675
canConvert(const QString & mime,QString flav)676 bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
677 {
678 return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
679 }
680
convertToMime(const QString & mime,QList<QByteArray> data,QString flav)681 QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
682 {
683 if(data.count() > 1)
684 qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
685 QVariant ret;
686 if (!canConvert(mime, flav))
687 return ret;
688 const QByteArray &a = data.first();
689 QCFType<CGImageRef> image;
690 QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
691 reinterpret_cast<const UInt8 *>(a.constData()),
692 a.size(), kCFAllocatorNull);
693 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
694 image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
695
696 if (image != 0)
697 ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
698 return ret;
699 }
700
convertFromMime(const QString & mime,QVariant variant,QString flav)701 QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
702 {
703 QList<QByteArray> ret;
704 if (!canConvert(mime, flav))
705 return ret;
706
707 QImage img = qvariant_cast<QImage>(variant);
708 QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img);
709 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
710 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
711 QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
712 QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
713 if (imageDestination != 0) {
714 CFTypeRef keys[2];
715 QCFType<CFTypeRef> values[2];
716 QCFType<CFDictionaryRef> options;
717 keys[0] = kCGImagePropertyPixelWidth;
718 keys[1] = kCGImagePropertyPixelHeight;
719 int width = img.width();
720 int height = img.height();
721 values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
722 values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
723 options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
724 reinterpret_cast<const void **>(values), 2,
725 &kCFTypeDictionaryKeyCallBacks,
726 &kCFTypeDictionaryValueCallBacks);
727 CGImageDestinationAddImage(imageDestination, cgimage, options);
728 CGImageDestinationFinalize(imageDestination);
729 }
730 QByteArray ar(CFDataGetLength(data), 0);
731 CFDataGetBytes(data,
732 CFRangeMake(0, ar.size()),
733 reinterpret_cast<UInt8 *>(ar.data()));
734 ret.append(ar);
735 } else
736 #endif
737 {
738 #ifdef Q_WS_MAC32
739 Handle tiff = NewHandle(0);
740 if (resolveMimeQuickTimeSymbols()) {
741 GraphicsExportComponent graphicsExporter;
742 ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
743 kQTFileTypeTIFF, &graphicsExporter);
744 if (!result) {
745 unsigned long sizeWritten;
746 result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
747 if (!result)
748 result = ptrGraphicsExportSetOutputHandle(graphicsExporter, tiff);
749 if (!result)
750 result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
751
752 CloseComponent(graphicsExporter);
753 }
754 }
755 int size = GetHandleSize((Handle)tiff);
756 QByteArray ar(reinterpret_cast<char *>(*tiff), size);
757 ret.append(ar);
758 DisposeHandle(tiff);
759 #endif
760 }
761 return ret;
762 }
763
764
765 class QMacPasteboardMimeFileUri : public QMacPasteboardMime {
766 public:
QMacPasteboardMimeFileUri()767 QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { }
768 QString convertorName();
769
770 QString flavorFor(const QString &mime);
771 QString mimeFor(QString flav);
772 bool canConvert(const QString &mime, QString flav);
773 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
774 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
775 };
776
convertorName()777 QString QMacPasteboardMimeFileUri::convertorName()
778 {
779 return QLatin1String("FileURL");
780 }
781
flavorFor(const QString & mime)782 QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
783 {
784 if (mime == QLatin1String("text/uri-list"))
785 return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
786 return QString();
787 }
788
mimeFor(QString flav)789 QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
790 {
791 if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)))
792 return QLatin1String("text/uri-list");
793 return QString();
794 }
795
canConvert(const QString & mime,QString flav)796 bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
797 {
798 return mime == QLatin1String("text/uri-list")
799 && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
800 }
801
convertToMime(const QString & mime,QList<QByteArray> data,QString flav)802 QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
803 {
804 if(!canConvert(mime, flav))
805 return QVariant();
806 QList<QVariant> ret;
807 for(int i = 0; i < data.size(); ++i) {
808 QUrl url = QUrl::fromEncoded(data.at(i));
809 if (url.host().toLower() == QLatin1String("localhost"))
810 url.setHost(QString());
811 url.setPath(url.path().normalized(QString::NormalizationForm_C));
812 ret.append(url);
813 }
814 return QVariant(ret);
815 }
816
convertFromMime(const QString & mime,QVariant data,QString flav)817 QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
818 {
819 QList<QByteArray> ret;
820 if (!canConvert(mime, flav))
821 return ret;
822 QList<QVariant> urls = data.toList();
823 for(int i = 0; i < urls.size(); ++i) {
824 QUrl url = urls.at(i).toUrl();
825 if (url.scheme().isEmpty())
826 url.setScheme(QLatin1String("file"));
827 if (url.scheme().toLower() == QLatin1String("file")) {
828 if (url.host().isEmpty())
829 url.setHost(QLatin1String("localhost"));
830 url.setPath(url.path().normalized(QString::NormalizationForm_D));
831 }
832 ret.append(url.toEncoded());
833 }
834 return ret;
835 }
836
837 class QMacPasteboardMimeUrl : public QMacPasteboardMime {
838 public:
QMacPasteboardMimeUrl()839 QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
840 QString convertorName();
841
842 QString flavorFor(const QString &mime);
843 QString mimeFor(QString flav);
844 bool canConvert(const QString &mime, QString flav);
845 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
846 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
847 };
848
convertorName()849 QString QMacPasteboardMimeUrl::convertorName()
850 {
851 return QLatin1String("URL");
852 }
853
flavorFor(const QString & mime)854 QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
855 {
856 if(mime.startsWith(QLatin1String("text/uri-list")))
857 return QLatin1String("public.url");
858 return QString();
859 }
860
mimeFor(QString flav)861 QString QMacPasteboardMimeUrl::mimeFor(QString flav)
862 {
863 if(flav == QLatin1String("public.url"))
864 return QLatin1String("text/uri-list");
865 return QString();
866 }
867
canConvert(const QString & mime,QString flav)868 bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
869 {
870 return flav == QLatin1String("public.url")
871 && mime == QLatin1String("text/uri-list");
872 }
873
convertToMime(const QString & mime,QList<QByteArray> data,QString flav)874 QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
875 {
876 if(!canConvert(mime, flav))
877 return QVariant();
878
879 QList<QVariant> ret;
880 for (int i=0; i<data.size(); ++i) {
881 QUrl url = QUrl::fromEncoded(data.at(i));
882 if (url.host().toLower() == QLatin1String("localhost"))
883 url.setHost(QString());
884 url.setPath(url.path().normalized(QString::NormalizationForm_C));
885 ret.append(url);
886 }
887 return QVariant(ret);
888 }
889
convertFromMime(const QString & mime,QVariant data,QString flav)890 QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
891 {
892 QList<QByteArray> ret;
893 if (!canConvert(mime, flav))
894 return ret;
895
896 QList<QVariant> urls = data.toList();
897 for(int i=0; i<urls.size(); ++i) {
898 QUrl url = urls.at(i).toUrl();
899 if (url.scheme().isEmpty())
900 url.setScheme(QLatin1String("file"));
901 if (url.scheme().toLower() == QLatin1String("file")) {
902 if (url.host().isEmpty())
903 url.setHost(QLatin1String("localhost"));
904 url.setPath(url.path().normalized(QString::NormalizationForm_D));
905 }
906 ret.append(url.toEncoded());
907 }
908 return ret;
909 }
910
911 class QMacPasteboardMimeVCard : public QMacPasteboardMime
912 {
913 public:
QMacPasteboardMimeVCard()914 QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ }
915 QString convertorName();
916
917 QString flavorFor(const QString &mime);
918 QString mimeFor(QString flav);
919 bool canConvert(const QString &mime, QString flav);
920 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
921 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
922 };
923
convertorName()924 QString QMacPasteboardMimeVCard::convertorName()
925 {
926 return QString("VCard");
927 }
928
canConvert(const QString & mime,QString flav)929 bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
930 {
931 return mimeFor(flav) == mime;
932 }
933
flavorFor(const QString & mime)934 QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
935 {
936 if(mime.startsWith(QLatin1String("text/plain")))
937 return QLatin1String("public.vcard");
938 return QString();
939 }
940
mimeFor(QString flav)941 QString QMacPasteboardMimeVCard::mimeFor(QString flav)
942 {
943 if (flav == QLatin1String("public.vcard"))
944 return QLatin1String("text/plain");
945 return QString();
946 }
947
convertToMime(const QString & mime,QList<QByteArray> data,QString)948 QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
949 {
950 QByteArray cards;
951 if (mime == QLatin1String("text/plain")) {
952 for (int i=0; i<data.size(); ++i)
953 cards += data[i];
954 }
955 return QVariant(cards);
956 }
957
convertFromMime(const QString & mime,QVariant data,QString)958 QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
959 {
960 QList<QByteArray> ret;
961 if (mime == QLatin1String("text/plain"))
962 ret.append(data.toString().toUtf8());
963 return ret;
964 }
965
966 #ifdef QT3_SUPPORT
967 class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
968 private:
969 int current_max;
970 QFile library_file;
971 QDateTime mime_registry_loaded;
972 QMap<QString, int> mime_registry;
973 int registerMimeType(const QString &mime);
974 bool loadMimeRegistry();
975
976 public:
QMacPasteboardMimeQt3Any()977 QMacPasteboardMimeQt3Any() : QMacPasteboardMime(MIME_QT3_CONVERTOR) {
978 current_max = 'QT00';
979 }
~QMacPasteboardMimeQt3Any()980 ~QMacPasteboardMimeQt3Any() {
981 }
982 QString convertorName();
983
984 QString flavorFor(const QString &mime);
985 QString mimeFor(QString flav);
986 bool canConvert(const QString &mime, QString flav);
987 QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
988 QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
989 };
990
qt_mac_openMimeRegistry(bool global,QIODevice::OpenMode mode,QFile & file)991 static bool qt_mac_openMimeRegistry(bool global, QIODevice::OpenMode mode, QFile &file)
992 {
993 QString dir = QLatin1String("/Library/Qt");
994 if(!global)
995 dir.prepend(QDir::homePath());
996 file.setFileName(dir + QLatin1String("/.mime_types"));
997 if(mode != QIODevice::ReadOnly) {
998 if(!QFile::exists(dir)) {
999 // Do it with a system call as I don't see much worth in
1000 // doing it with QDir since we have to chmod anyway.
1001 bool success = ::mkdir(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR) == 0;
1002 if (success)
1003 success = ::chmod(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR
1004 | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH) == 0;
1005 if (!success)
1006 return false;
1007 }
1008 if (!file.exists()) {
1009 // Create the file and chmod it so that everyone can write to it.
1010 int fd = ::open(file.fileName().toLocal8Bit().constData(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
1011 bool success = fd != -1;
1012 if (success)
1013 success = ::fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0;
1014 if (fd != -1)
1015 ::close(fd);
1016 if(!success)
1017 return false;
1018 }
1019 }
1020 return file.open(mode);
1021 }
1022
qt_mac_loadMimeRegistry(QFile & file,QMap<QString,int> & registry,int & max)1023 static void qt_mac_loadMimeRegistry(QFile &file, QMap<QString, int> ®istry, int &max)
1024 {
1025 file.reset();
1026 QTextStream stream(&file);
1027 while(!stream.atEnd()) {
1028 QString mime = stream.readLine();
1029 int mactype = stream.readLine().toInt();
1030 if(mactype > max)
1031 max = mactype;
1032 registry.insert(mime, mactype);
1033 }
1034 }
1035
loadMimeRegistry()1036 bool QMacPasteboardMimeQt3Any::loadMimeRegistry()
1037 {
1038 if(!library_file.isOpen()) {
1039 if(!qt_mac_openMimeRegistry(true, QIODevice::ReadWrite, library_file)) {
1040 QFile global;
1041 if(qt_mac_openMimeRegistry(true, QIODevice::ReadOnly, global)) {
1042 qt_mac_loadMimeRegistry(global, mime_registry, current_max);
1043 global.close();
1044 }
1045 if(!qt_mac_openMimeRegistry(false, QIODevice::ReadWrite, library_file)) {
1046 qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open mime resources %s -- %s", library_file.fileName().toLatin1().constData(),
1047 library_file.errorString().toLatin1().constData());
1048 return false;
1049 }
1050 }
1051 }
1052
1053 QFileInfo fi(library_file);
1054 if(!mime_registry_loaded.isNull() && mime_registry_loaded == fi.lastModified())
1055 return true;
1056 mime_registry_loaded = fi.lastModified();
1057 qt_mac_loadMimeRegistry(library_file, mime_registry, current_max);
1058 return true;
1059 }
1060
registerMimeType(const QString & mime)1061 int QMacPasteboardMimeQt3Any::registerMimeType(const QString &mime)
1062 {
1063 if(!mime_registry.contains(mime)) {
1064 if(!loadMimeRegistry()) {
1065 qWarning("QMacPasteboardMimeAnyQt3Mime: Internal error");
1066 return 0;
1067 }
1068 if(!mime_registry.contains(mime)) {
1069 if(!library_file.isOpen()) {
1070 if(!library_file.open(QIODevice::WriteOnly)) {
1071 qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open %s -- %s", library_file.fileName().toLatin1().constData(),
1072 library_file.errorString().toLatin1().constData());
1073 return false;
1074 }
1075 }
1076 int ret = ++current_max;
1077 mime_registry_loaded = QFileInfo(library_file).lastModified();
1078 QTextStream stream(&library_file);
1079 stream << mime << endl;
1080 stream << ret << endl;
1081 mime_registry.insert(mime, ret);
1082 library_file.flush(); //flush and set mtime
1083 return ret;
1084 }
1085 }
1086 return mime_registry[mime];
1087 }
1088
convertorName()1089 QString QMacPasteboardMimeQt3Any::convertorName()
1090 {
1091 return QLatin1String("Qt3-Any-Mime");
1092 }
1093
flavorFor(const QString & mime)1094 QString QMacPasteboardMimeQt3Any::flavorFor(const QString &mime)
1095 {
1096 const int os_flav = registerMimeType(mime);
1097 QCFType<CFArrayRef> ids = UTTypeCreateAllIdentifiersForTag(0, kUTTagClassOSType,
1098 QCFString(UTCreateStringForOSType(os_flav)));
1099 if(ids) {
1100 const int type_count = CFArrayGetCount(ids);
1101 if(type_count) {
1102 if(type_count > 1)
1103 qDebug("Can't happen!");
1104 return QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(ids, 0));
1105 }
1106 }
1107 return QString();
1108 }
1109
mimeFor(QString flav)1110 QString QMacPasteboardMimeQt3Any::mimeFor(QString flav)
1111 {
1112 loadMimeRegistry();
1113 const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType));
1114 for(QMap<QString, int>::const_iterator it = mime_registry.constBegin();
1115 it != mime_registry.constEnd(); ++it) {
1116 if(it.value() == os_flav)
1117 return QString::fromLatin1(it.key().toLatin1());
1118 }
1119 return QString();
1120 }
1121
canConvert(const QString & mime,QString flav)1122 bool QMacPasteboardMimeQt3Any::canConvert(const QString &mime, QString flav)
1123 {
1124 loadMimeRegistry();
1125 const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType));
1126 if(mime_registry.contains(mime) && mime_registry[mime] == os_flav)
1127 return true;
1128 return false;
1129 }
1130
convertToMime(const QString &,QList<QByteArray>,QString)1131 QVariant QMacPasteboardMimeQt3Any::convertToMime(const QString &, QList<QByteArray>, QString)
1132 {
1133 qWarning("QMacPasteboardMimeAnyQt3Mime: Cannot write anything!");
1134 return QVariant();
1135 }
1136
convertFromMime(const QString & mime,QVariant data,QString)1137 QList<QByteArray> QMacPasteboardMimeQt3Any::convertFromMime(const QString &mime, QVariant data, QString)
1138 {
1139 QList<QByteArray> ret;
1140 if (mime == QLatin1String("text/plain")) {
1141 ret.append(data.toString().toUtf8());
1142 } else {
1143 ret.append(data.toByteArray());
1144 }
1145 return ret;
1146 }
1147 #endif
1148
1149 /*!
1150 \internal
1151
1152 This is an internal function.
1153 */
initialize()1154 void QMacPasteboardMime::initialize()
1155 {
1156 if(globalMimeList()->isEmpty()) {
1157 qAddPostRoutine(cleanup_mimes);
1158
1159 //standard types that we wrap
1160 new QMacPasteboardMimeTiff;
1161 #ifdef Q_WS_MAC32
1162 // 10.6 does automatic synthesis to and from PICT to standard image types (like TIFF),
1163 // so don't bother doing it ourselves, especially since it's not available in 64-bit.
1164 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
1165 new QMacPasteboardMimePict;
1166 #endif
1167 new QMacPasteboardMimeUnicodeText;
1168 new QMacPasteboardMimePlainText;
1169 new QMacPasteboardMimeHTMLText;
1170 new QMacPasteboardMimeFileUri;
1171 new QMacPasteboardMimeUrl;
1172 new QMacPasteboardMimeTypeName;
1173 new QMacPasteboardMimeVCard;
1174 //make sure our "non-standard" types are always last! --Sam
1175 new QMacPasteboardMimeAny;
1176 #ifdef QT3_SUPPORT
1177 new QMacPasteboardMimeQt3Any;
1178 #endif
1179 }
1180 }
1181
1182 /*!
1183 Returns the most-recently created QMacPasteboardMime of type \a t that can convert
1184 between the \a mime and \a flav formats. Returns 0 if no such convertor
1185 exists.
1186 */
1187 QMacPasteboardMime*
convertor(uchar t,const QString & mime,QString flav)1188 QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
1189 {
1190 MimeList *mimes = globalMimeList();
1191 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1192 #ifdef DEBUG_MIME_MAPS
1193 qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
1194 (*it)->convertorName().toLatin1().constData(),
1195 (*it)->type & t, mime.toLatin1().constData(),
1196 flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
1197 (*it)->canConvert(mime,flav));
1198 for(int i = 0; i < (*it)->countFlavors(); ++i) {
1199 int f = (*it)->flavor(i);
1200 qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
1201 (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
1202 (*it)->convertorName().toLatin1().constData());
1203 }
1204 #endif
1205 if(((*it)->type & t) && (*it)->canConvert(mime, flav))
1206 return (*it);
1207 }
1208 return 0;
1209 }
1210 /*!
1211 Returns a MIME type of type \a t for \a flav, or 0 if none exists.
1212 */
flavorToMime(uchar t,QString flav)1213 QString QMacPasteboardMime::flavorToMime(uchar t, QString flav)
1214 {
1215 MimeList *mimes = globalMimeList();
1216 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1217 #ifdef DEBUG_MIME_MAPS
1218 qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
1219 (*it)->convertorName().toLatin1().constData(),
1220 (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
1221 (*it)->mimeFor(flav).toLatin1().constData());
1222
1223 #endif
1224 if((*it)->type & t) {
1225 QString mimeType = (*it)->mimeFor(flav);
1226 if(!mimeType.isNull())
1227 return mimeType;
1228 }
1229 }
1230 return QString();
1231 }
1232
1233 /*!
1234 Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
1235 */
all(uchar t)1236 QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t)
1237 {
1238 MimeList ret;
1239 MimeList *mimes = globalMimeList();
1240 for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
1241 if((*it)->type & t)
1242 ret.append((*it));
1243 }
1244 return ret;
1245 }
1246
1247
1248 /*!
1249 \fn QString QMacPasteboardMime::convertorName()
1250
1251 Returns a name for the convertor.
1252
1253 All subclasses must reimplement this pure virtual function.
1254 */
1255
1256 /*!
1257 \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
1258
1259 Returns true if the convertor can convert (both ways) between
1260 \a mime and \a flav; otherwise returns false.
1261
1262 All subclasses must reimplement this pure virtual function.
1263 */
1264
1265 /*!
1266 \fn QString QMacPasteboardMime::mimeFor(QString flav)
1267
1268 Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
1269 convertor does not support \a flav.
1270
1271 All subclasses must reimplement this pure virtual function.
1272 */
1273
1274 /*!
1275 \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
1276
1277 Returns the Mac UTI used for MIME type \a mime, or 0 if this
1278 convertor does not support \a mime.
1279
1280 All subclasses must reimplement this pure virtual function.
1281 */
1282
1283 /*!
1284 \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
1285
1286 Returns \a data converted from Mac UTI \a flav to MIME type \a
1287 mime.
1288
1289 Note that Mac flavors must all be self-terminating. The input \a
1290 data may contain trailing data.
1291
1292 All subclasses must reimplement this pure virtual function.
1293 */
1294
1295 /*!
1296 \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
1297
1298 Returns \a data converted from MIME type \a mime
1299 to Mac UTI \a flav.
1300
1301 Note that Mac flavors must all be self-terminating. The return
1302 value may contain trailing data.
1303
1304 All subclasses must reimplement this pure virtual function.
1305 */
1306
1307
1308 QT_END_NAMESPACE
1309