src/corelib/kernel/qmimedata.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 QtCore 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 "qmimedata.h"
       
    43 
       
    44 #include "private/qobject_p.h"
       
    45 #include "qurl.h"
       
    46 #include "qstringlist.h"
       
    47 #include "qtextcodec.h"
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 struct QMimeDataStruct
       
    52 {
       
    53     QString format;
       
    54     QVariant data;
       
    55 };
       
    56 
       
    57 class QMimeDataPrivate : public QObjectPrivate
       
    58 {
       
    59     Q_DECLARE_PUBLIC(QMimeData)
       
    60 public:
       
    61     void removeData(const QString &format);
       
    62     void setData(const QString &format, const QVariant &data);
       
    63     QVariant getData(const QString &format) const;
       
    64 
       
    65     QVariant retrieveTypedData(const QString &format, QVariant::Type type) const;
       
    66 
       
    67     QList<QMimeDataStruct> dataList;
       
    68 };
       
    69 
       
    70 void QMimeDataPrivate::removeData(const QString &format)
       
    71 {
       
    72     for (int i=0; i<dataList.size(); i++) {
       
    73         if (dataList.at(i).format == format) {
       
    74             dataList.removeAt(i);
       
    75             return;
       
    76         }
       
    77     }
       
    78 }
       
    79 
       
    80 void QMimeDataPrivate::setData(const QString &format, const QVariant &data)
       
    81 {
       
    82     // remove it first if the format is already here.
       
    83     removeData(format);
       
    84     QMimeDataStruct mimeData;
       
    85     mimeData.format = format;
       
    86     mimeData.data = data;
       
    87     dataList += mimeData;
       
    88 }
       
    89 
       
    90 
       
    91 QVariant QMimeDataPrivate::getData(const QString &format) const
       
    92 {
       
    93     QVariant data;
       
    94     for (int i=0; i<dataList.size(); i++) {
       
    95         if (dataList.at(i).format == format) {
       
    96             data = dataList.at(i).data;
       
    97             break;
       
    98         }
       
    99     }
       
   100     return data;
       
   101 }
       
   102 
       
   103 QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Type type) const
       
   104 {
       
   105     Q_Q(const QMimeData);
       
   106 
       
   107     QVariant data = q->retrieveData(format, type);
       
   108     if (data.type() == type || !data.isValid())
       
   109         return data;
       
   110 
       
   111     // provide more conversion possiblities than just what QVariant provides
       
   112 
       
   113     // URLs can be lists as well...
       
   114     if ((type == QVariant::Url && data.type() == QVariant::List)
       
   115         || (type == QVariant::List && data.type() == QVariant::Url))
       
   116         return data;
       
   117 
       
   118     // images and pixmaps are interchangeable
       
   119     if ((type == QVariant::Pixmap && data.type() == QVariant::Image)
       
   120         || (type == QVariant::Image && data.type() == QVariant::Pixmap))
       
   121         return data;
       
   122 
       
   123     if (data.type() == QVariant::ByteArray) {
       
   124         // see if we can convert to the requested type
       
   125         switch(type) {
       
   126 #ifndef QT_NO_TEXTCODEC
       
   127         case QVariant::String: {
       
   128             const QByteArray ba = data.toByteArray();
       
   129             QTextCodec *codec = QTextCodec::codecForName("utf-8");
       
   130             if (format == QLatin1String("text/html"))
       
   131                 codec = QTextCodec::codecForHtml(ba, codec);
       
   132             return codec->toUnicode(ba);
       
   133         }
       
   134 #endif // QT_NO_TEXTCODEC
       
   135         case QVariant::Color: {
       
   136             QVariant newData = data;
       
   137             newData.convert(QVariant::Color);
       
   138             return newData;
       
   139         }
       
   140         case QVariant::List: {
       
   141             if (format != QLatin1String("text/uri-list"))
       
   142                 break;
       
   143             // fall through
       
   144         }
       
   145         case QVariant::Url: {
       
   146             QByteArray ba = data.toByteArray();
       
   147             // Qt 3.x will send text/uri-list with a trailing
       
   148             // null-terminator (that is *not* sent for any other
       
   149             // text/* mime-type), so chop it off
       
   150             if (ba.endsWith('\0'))
       
   151                 ba.chop(1);
       
   152 
       
   153             QList<QByteArray> urls = ba.split('\n');
       
   154             QList<QVariant> list;
       
   155             for (int i = 0; i < urls.size(); ++i) {
       
   156                 QByteArray ba = urls.at(i).trimmed();
       
   157                 if (!ba.isEmpty())
       
   158                     list.append(QUrl::fromEncoded(ba));
       
   159             }
       
   160             return list;
       
   161         }
       
   162         default:
       
   163             break;
       
   164         }
       
   165 
       
   166     } else if (type == QVariant::ByteArray) {
       
   167 
       
   168         // try to convert to bytearray
       
   169         switch(data.type()) {
       
   170         case QVariant::ByteArray:
       
   171         case QVariant::Color:
       
   172             return data.toByteArray();
       
   173             break;
       
   174         case QVariant::String:
       
   175             return data.toString().toUtf8();
       
   176             break;
       
   177         case QVariant::Url:
       
   178             return data.toUrl().toEncoded();
       
   179             break;
       
   180         case QVariant::List: {
       
   181             // has to be list of URLs
       
   182             QByteArray result;
       
   183             QList<QVariant> list = data.toList();
       
   184             for (int i = 0; i < list.size(); ++i) {
       
   185                 if (list.at(i).type() == QVariant::Url) {
       
   186                     result += list.at(i).toUrl().toEncoded();
       
   187                     result += "\r\n";
       
   188                 }
       
   189             }
       
   190             if (!result.isEmpty())
       
   191                 return result;
       
   192             break;
       
   193         }
       
   194         default:
       
   195             break;
       
   196         }
       
   197     }
       
   198     return data;
       
   199 }
       
   200 
       
   201 /*!
       
   202     \class QMimeData
       
   203     \brief The QMimeData class provides a container for data that records information
       
   204     about its MIME type.
       
   205 
       
   206     QMimeData is used to describe information that can be stored in
       
   207     the \l{QClipboard}{clipboard}, and transferred via the \l{drag
       
   208     and drop} mechanism. QMimeData objects associate the data that
       
   209     they hold with the corresponding MIME types to ensure that
       
   210     information can be safely transferred between applications, and
       
   211     copied around within the same application.
       
   212 
       
   213     QMimeData objects are usually created using \c new and supplied
       
   214     to QDrag or QClipboard objects. This is to enable Qt to manage
       
   215     the memory that they use.
       
   216 
       
   217     A single QMimeData object can store the same data using several
       
   218     different formats at the same time. The formats() function
       
   219     returns a list of the available formats in order of preference.
       
   220     The data() function returns the raw data associated with a MIME
       
   221     type, and setData() allows you to set the data for a MIME type.
       
   222 
       
   223     For the most common MIME types, QMimeData provides convenience
       
   224     functions to access the data:
       
   225 
       
   226     \table
       
   227     \header \o Tester       \o Getter       \o Setter           \o MIME Types
       
   228     \row    \o hasText()    \o text()       \o setText()        \o \c text/plain
       
   229     \row    \o hasHtml()    \o html()       \o setHtml()        \o \c text/html
       
   230     \row    \o hasUrls()    \o urls()       \o setUrls()        \o \c text/uri-list
       
   231     \row    \o hasImage()   \o imageData()  \o setImageData()   \o \c image/ *
       
   232     \row    \o hasColor()   \o colorData()  \o setColorData()   \o \c application/x-color
       
   233     \endtable
       
   234 
       
   235     For example, if your write a widget that accepts URL drags, you
       
   236     would end up writing code like this:
       
   237 
       
   238     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 0
       
   239 
       
   240     There are three approaches for storing custom data in a QMimeData
       
   241     object:
       
   242 
       
   243     \list 1
       
   244     \o  Custom data can be stored directly in a QMimeData object as a
       
   245         QByteArray using setData(). For example:
       
   246 
       
   247         \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1
       
   248 
       
   249     \o  We can subclass QMimeData and reimplement hasFormat(),
       
   250         formats(), and retrieveData().
       
   251 
       
   252     \o  If the drag and drop operation occurs withing a single
       
   253         application, we can subclass QMimeData and add extra data in
       
   254         it, and use a qobject_cast() in the receiver's drop event
       
   255         handler. For example:
       
   256 
       
   257         \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 2
       
   258     \endlist
       
   259 
       
   260     \section1 Platform-Specific MIME Types
       
   261 
       
   262     On Windows, formats() will also return custom formats available
       
   263     in the MIME data, using the \c{x-qt-windows-mime} subtype to
       
   264     indicate that they represent data in non-standard formats.
       
   265     The formats will take the following form:
       
   266 
       
   267     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 3
       
   268 
       
   269     The following are examples of custom MIME types:
       
   270 
       
   271     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 4
       
   272 
       
   273     The \c value declaration of each format describes the way in which the
       
   274     data is encoded.
       
   275 
       
   276     On Windows, the MIME format does not always map directly to the
       
   277     clipboard formats. Qt provides QWindowsMime to map clipboard
       
   278     formats to open-standard MIME formats. Similarly, the
       
   279     QMacPasteboardMime maps MIME to Mac flavors.
       
   280 
       
   281     \sa QClipboard, QDragEnterEvent, QDragMoveEvent, QDropEvent, QDrag,
       
   282         QWindowsMime, QMacPasteboardMime, {Drag and Drop}
       
   283 */
       
   284 
       
   285 /*!
       
   286     Constructs a new MIME data object with no data in it.
       
   287 */
       
   288 QMimeData::QMimeData()
       
   289     : QObject(*new QMimeDataPrivate, 0)
       
   290 {
       
   291 }
       
   292 
       
   293 /*!
       
   294     Destroys the MIME data object.
       
   295 */
       
   296 QMimeData::~QMimeData()
       
   297 {
       
   298 }
       
   299 
       
   300 /*!
       
   301     Returns a list of URLs contained within the MIME data object.
       
   302 
       
   303     URLs correspond to the MIME type \c text/uri-list.
       
   304 
       
   305     \sa hasUrls(), data()
       
   306 */
       
   307 QList<QUrl> QMimeData::urls() const
       
   308 {
       
   309     Q_D(const QMimeData);
       
   310     QVariant data = d->retrieveTypedData(QLatin1String("text/uri-list"), QVariant::List);
       
   311     QList<QUrl> urls;
       
   312     if (data.type() == QVariant::Url)
       
   313         urls.append(data.toUrl());
       
   314     else if (data.type() == QVariant::List) {
       
   315         QList<QVariant> list = data.toList();
       
   316         for (int i = 0; i < list.size(); ++i) {
       
   317             if (list.at(i).type() == QVariant::Url)
       
   318                 urls.append(list.at(i).toUrl());
       
   319         }
       
   320     }
       
   321     return urls;
       
   322 }
       
   323 
       
   324 /*!
       
   325     Sets the URLs stored in the MIME data object to those specified by \a urls.
       
   326 
       
   327     URLs correspond to the MIME type \c text/uri-list.
       
   328 
       
   329     \sa hasUrls(), setData()
       
   330 */
       
   331 void QMimeData::setUrls(const QList<QUrl> &urls)
       
   332 {
       
   333     Q_D(QMimeData);
       
   334     QList<QVariant> list;
       
   335     for (int i = 0; i < urls.size(); ++i)
       
   336         list.append(urls.at(i));
       
   337 
       
   338     d->setData(QLatin1String("text/uri-list"), list);
       
   339 }
       
   340 
       
   341 /*!
       
   342     Returns true if the object can return a list of urls; otherwise
       
   343     returns false.
       
   344 
       
   345     URLs correspond to the MIME type \c text/uri-list.
       
   346 
       
   347     \sa setUrls(), urls(), hasFormat()
       
   348 */
       
   349 bool QMimeData::hasUrls() const
       
   350 {
       
   351     return hasFormat(QLatin1String("text/uri-list"));
       
   352 }
       
   353 
       
   354 
       
   355 /*!
       
   356     Returns a plain text (MIME type \c text/plain) representation of
       
   357     the data.
       
   358 
       
   359     \sa hasText(), html(), data()
       
   360 */
       
   361 QString QMimeData::text() const
       
   362 {
       
   363     Q_D(const QMimeData);
       
   364     QVariant data = d->retrieveTypedData(QLatin1String("text/plain"), QVariant::String);
       
   365     return data.toString();
       
   366 }
       
   367 
       
   368 /*!
       
   369     Sets \a text as the plain text (MIME type \c text/plain) used to
       
   370     represent the data.
       
   371 
       
   372     \sa hasText(), setHtml(), setData()
       
   373 */
       
   374 void QMimeData::setText(const QString &text)
       
   375 {
       
   376     Q_D(QMimeData);
       
   377     d->setData(QLatin1String("text/plain"), text);
       
   378 }
       
   379 
       
   380 /*!
       
   381     Returns true if the object can return plain text (MIME type \c
       
   382     text/plain); otherwise returns false.
       
   383 
       
   384     \sa setText(), text(), hasHtml(), hasFormat()
       
   385 */
       
   386 bool QMimeData::hasText() const
       
   387 {
       
   388     return hasFormat(QLatin1String("text/plain"));
       
   389 }
       
   390 
       
   391 /*!
       
   392     Returns a string if the data stored in the object is HTML (MIME
       
   393     type \c text/html); otherwise returns an empty string.
       
   394 
       
   395     \sa hasHtml(), setData()
       
   396 */
       
   397 QString QMimeData::html() const
       
   398 {
       
   399     Q_D(const QMimeData);
       
   400     QVariant data = d->retrieveTypedData(QLatin1String("text/html"), QVariant::String);
       
   401     return data.toString();
       
   402 }
       
   403 
       
   404 /*!
       
   405     Sets \a html as the HTML (MIME type \c text/html) used to
       
   406     represent the data.
       
   407 
       
   408     \sa hasHtml(), setText(), setData()
       
   409 */
       
   410 void QMimeData::setHtml(const QString &html)
       
   411 {
       
   412     Q_D(QMimeData);
       
   413     d->setData(QLatin1String("text/html"), html);
       
   414 }
       
   415 
       
   416 /*!
       
   417     Returns true if the object can return HTML (MIME type \c
       
   418     text/html); otherwise returns false.
       
   419 
       
   420     \sa setHtml(), html(), hasFormat()
       
   421 */
       
   422 bool QMimeData::hasHtml() const
       
   423 {
       
   424     return hasFormat(QLatin1String("text/html"));
       
   425 }
       
   426 
       
   427 /*!
       
   428     Returns a QVariant storing a QImage if the object can return an
       
   429     image; otherwise returns a null variant.
       
   430 
       
   431     A QVariant is used because QMimeData belongs to the \l QtCore
       
   432     library, whereas QImage belongs to \l QtGui. To convert the
       
   433     QVariant to a QImage, simply use qvariant_cast(). For example:
       
   434 
       
   435     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 5
       
   436 
       
   437     \sa hasImage()
       
   438 */
       
   439 QVariant QMimeData::imageData() const
       
   440 {
       
   441     Q_D(const QMimeData);
       
   442     return d->retrieveTypedData(QLatin1String("application/x-qt-image"), QVariant::Image);
       
   443 }
       
   444 
       
   445 /*!
       
   446     Sets the data in the object to the given \a image.
       
   447 
       
   448     A QVariant is used because QMimeData belongs to the \l QtCore
       
   449     library, whereas QImage belongs to \l QtGui. The conversion
       
   450     from QImage to QVariant is implicit. For example:
       
   451 
       
   452     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 6
       
   453 
       
   454     \sa hasImage(), setData()
       
   455 */
       
   456 void QMimeData::setImageData(const QVariant &image)
       
   457 {
       
   458     Q_D(QMimeData);
       
   459     d->setData(QLatin1String("application/x-qt-image"), image);
       
   460 }
       
   461 
       
   462 /*!
       
   463     Returns true if the object can return an image; otherwise returns
       
   464     false.
       
   465 
       
   466     \sa setImageData(), imageData(), hasFormat()
       
   467 */
       
   468 bool QMimeData::hasImage() const
       
   469 {
       
   470     return hasFormat(QLatin1String("application/x-qt-image"));
       
   471 }
       
   472 
       
   473 /*!
       
   474     Returns a color if the data stored in the object represents a
       
   475     color (MIME type \c application/x-color); otherwise returns a
       
   476     null variant.
       
   477 
       
   478     A QVariant is used because QMimeData belongs to the \l QtCore
       
   479     library, whereas QColor belongs to \l QtGui. To convert the
       
   480     QVariant to a QColor, simply use qvariant_cast(). For example:
       
   481 
       
   482     \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 7
       
   483 
       
   484     \sa hasColor(), setColorData(), data()
       
   485 */
       
   486 QVariant QMimeData::colorData() const
       
   487 {
       
   488     Q_D(const QMimeData);
       
   489     return d->retrieveTypedData(QLatin1String("application/x-color"), QVariant::Color);
       
   490 }
       
   491 
       
   492 /*!
       
   493     Sets the color data in the object to the given \a color.
       
   494 
       
   495     Colors correspond to the MIME type \c application/x-color.
       
   496 
       
   497     \sa hasColor(), setData()
       
   498 */
       
   499 void QMimeData::setColorData(const QVariant &color)
       
   500 {
       
   501     Q_D(QMimeData);
       
   502     d->setData(QLatin1String("application/x-color"), color);
       
   503 }
       
   504 
       
   505 
       
   506 /*!
       
   507     Returns true if the object can return a color (MIME type \c
       
   508     application/x-color); otherwise returns false.
       
   509 
       
   510     \sa setColorData(), colorData(), hasFormat()
       
   511 */
       
   512 bool QMimeData::hasColor() const
       
   513 {
       
   514     return hasFormat(QLatin1String("application/x-color"));
       
   515 }
       
   516 
       
   517 /*!
       
   518     Returns the data stored in the object in the format described by
       
   519     the MIME type specified by \a mimeType.
       
   520 */
       
   521 QByteArray QMimeData::data(const QString &mimeType) const
       
   522 {
       
   523     Q_D(const QMimeData);
       
   524     QVariant data = d->retrieveTypedData(mimeType, QVariant::ByteArray);
       
   525     return data.toByteArray();
       
   526 }
       
   527 
       
   528 /*!
       
   529     Sets the data associated with the MIME type given by \a mimeType
       
   530     to the specified \a data.
       
   531 
       
   532     For the most common types of data, you can call the higher-level
       
   533     functions setText(), setHtml(), setUrls(), setImageData(), and
       
   534     setColorData() instead.
       
   535 
       
   536     Note that if you want to use a custom data type in an item view drag and drop
       
   537     operation, you must register it as a Qt \l{QMetaType}{meta type}, using the
       
   538     Q_DECLARE_METATYPE() macro, and implement stream operators for it. The stream
       
   539     operators must then be registered with the qRegisterMetaTypeStreamOperators()
       
   540     function.
       
   541 
       
   542     \sa hasFormat(), QMetaType, qRegisterMetaTypeStreamOperators()
       
   543 */
       
   544 void QMimeData::setData(const QString &mimeType, const QByteArray &data)
       
   545 {
       
   546     Q_D(QMimeData);
       
   547     d->setData(mimeType, QVariant(data));
       
   548 }
       
   549 
       
   550 /*!
       
   551     Returns true if the object can return data for the MIME type
       
   552     specified by \a mimeType; otherwise returns false.
       
   553 
       
   554     For the most common types of data, you can call the higher-level
       
   555     functions hasText(), hasHtml(), hasUrls(), hasImage(), and
       
   556     hasColor() instead.
       
   557 
       
   558     \sa formats(), setData(), data()
       
   559 */
       
   560 bool QMimeData::hasFormat(const QString &mimeType) const
       
   561 {
       
   562     return formats().contains(mimeType);
       
   563 }
       
   564 
       
   565 /*!
       
   566     Returns a list of formats supported by the object. This is a list
       
   567     of MIME types for which the object can return suitable data. The
       
   568     formats in the list are in a priority order.
       
   569 
       
   570     For the most common types of data, you can call the higher-level
       
   571     functions hasText(), hasHtml(), hasUrls(), hasImage(), and
       
   572     hasColor() instead.
       
   573 
       
   574     \sa hasFormat(), setData(), data()
       
   575 */
       
   576 QStringList QMimeData::formats() const
       
   577 {
       
   578     Q_D(const QMimeData);
       
   579     QStringList list;
       
   580     for (int i=0; i<d->dataList.size(); i++)
       
   581         list += d->dataList.at(i).format;
       
   582     return list;
       
   583 }
       
   584 
       
   585 /*!
       
   586     Returns a variant with the given \a type containing data for the
       
   587     MIME type specified by \a mimeType. If the object does not
       
   588     support the MIME type or variant type given, a null variant is
       
   589     returned instead.
       
   590 
       
   591     This function is called by the general data() getter and by the
       
   592     convenience getters (text(), html(), urls(), imageData(), and
       
   593     colorData()). You can reimplement it if you want to store your
       
   594     data using a custom data structure (instead of a QByteArray,
       
   595     which is what setData() provides). You would then also need
       
   596     to reimplement hasFormat() and formats().
       
   597 
       
   598     \sa data()
       
   599 */
       
   600 QVariant QMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
       
   601 {
       
   602     Q_UNUSED(type);
       
   603     Q_D(const QMimeData);
       
   604     return d->getData(mimeType);
       
   605 }
       
   606 
       
   607 /*!
       
   608     Removes all the MIME type and data entries in the object.
       
   609 */
       
   610 void QMimeData::clear()
       
   611 {
       
   612     Q_D(QMimeData);
       
   613     d->dataList.clear();
       
   614 }
       
   615 
       
   616 /*!
       
   617     \since 4.4
       
   618 
       
   619     Removes the data entry for \a mimeType in the object.
       
   620 */
       
   621 void QMimeData::removeFormat(const QString &mimeType)
       
   622 {
       
   623     Q_D(QMimeData);
       
   624     d->removeData(mimeType);
       
   625 }
       
   626 
       
   627 QT_END_NAMESPACE