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