diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/kernel/qmimedata.cpp | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/kernel/qmimedata.cpp')
-rw-r--r-- | src/corelib/kernel/qmimedata.cpp | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp new file mode 100644 index 0000000..f1c8e53 --- /dev/null +++ b/src/corelib/kernel/qmimedata.cpp @@ -0,0 +1,627 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmimedata.h" + +#include "private/qobject_p.h" +#include "qurl.h" +#include "qstringlist.h" +#include "qtextcodec.h" + +QT_BEGIN_NAMESPACE + +struct QMimeDataStruct +{ + QString format; + QVariant data; +}; + +class QMimeDataPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QMimeData) +public: + void removeData(const QString &format); + void setData(const QString &format, const QVariant &data); + QVariant getData(const QString &format) const; + + QVariant retrieveTypedData(const QString &format, QVariant::Type type) const; + + QList<QMimeDataStruct> dataList; +}; + +void QMimeDataPrivate::removeData(const QString &format) +{ + for (int i=0; i<dataList.size(); i++) { + if (dataList.at(i).format == format) { + dataList.removeAt(i); + return; + } + } +} + +void QMimeDataPrivate::setData(const QString &format, const QVariant &data) +{ + // remove it first if the format is already here. + removeData(format); + QMimeDataStruct mimeData; + mimeData.format = format; + mimeData.data = data; + dataList += mimeData; +} + + +QVariant QMimeDataPrivate::getData(const QString &format) const +{ + QVariant data; + for (int i=0; i<dataList.size(); i++) { + if (dataList.at(i).format == format) { + data = dataList.at(i).data; + break; + } + } + return data; +} + +QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Type type) const +{ + Q_Q(const QMimeData); + + QVariant data = q->retrieveData(format, type); + if (data.type() == type || data.type() == QVariant::Invalid) + return data; + + // provide more conversion possiblities than just what QVariant provides + + // URLs can be lists as well... + if ((type == QVariant::Url && data.type() == QVariant::List) + || (type == QVariant::List && data.type() == QVariant::Url)) + return data; + + // images and pixmaps are interchangeable + if ((type == QVariant::Pixmap && data.type() == QVariant::Image) + || (type == QVariant::Image && data.type() == QVariant::Pixmap)) + return data; + + if (data.type() == QVariant::ByteArray) { + // see if we can convert to the requested type + switch(type) { +#ifndef QT_NO_TEXTCODEC + case QVariant::String: { + const QByteArray ba = data.toByteArray(); + QTextCodec *codec = QTextCodec::codecForName("utf-8"); + if (format == QLatin1String("text/html")) + codec = QTextCodec::codecForHtml(ba, codec); + return codec->toUnicode(ba); + } +#endif // QT_NO_TEXTCODEC + case QVariant::Color: { + QVariant newData = data; + newData.convert(QVariant::Color); + return newData; + } + case QVariant::List: { + if (format != QLatin1String("text/uri-list")) + break; + // fall through + } + case QVariant::Url: { + QByteArray ba = data.toByteArray(); + // Qt 3.x will send text/uri-list with a trailing + // null-terminator (that is *not* sent for any other + // text/* mime-type), so chop it off + if (ba.endsWith('\0')) + ba.chop(1); + + QList<QByteArray> urls = ba.split('\n'); + QList<QVariant> list; + for (int i = 0; i < urls.size(); ++i) { + QByteArray ba = urls.at(i).trimmed(); + if (!ba.isEmpty()) + list.append(QUrl::fromEncoded(ba)); + } + return list; + } + default: + break; + } + + } else if (type == QVariant::ByteArray) { + + // try to convert to bytearray + switch(data.type()) { + case QVariant::ByteArray: + case QVariant::Color: + return data.toByteArray(); + break; + case QVariant::String: + return data.toString().toUtf8(); + break; + case QVariant::Url: + return data.toUrl().toEncoded(); + break; + case QVariant::List: { + // has to be list of URLs + QByteArray result; + QList<QVariant> list = data.toList(); + for (int i = 0; i < list.size(); ++i) { + if (list.at(i).type() == QVariant::Url) { + result += list.at(i).toUrl().toEncoded(); + result += "\r\n"; + } + } + if (!result.isEmpty()) + return result; + break; + } + default: + break; + } + } + return data; +} + +/*! + \class QMimeData + \brief The QMimeData class provides a container for data that records information + about its MIME type. + + QMimeData is used to describe information that can be stored in + the \l{QClipboard}{clipboard}, and transferred via the \l{drag + and drop} mechanism. QMimeData objects associate the data that + they hold with the corresponding MIME types to ensure that + information can be safely transferred between applications, and + copied around within the same application. + + QMimeData objects are usually created using \c new and supplied + to QDrag or QClipboard objects. This is to enable Qt to manage + the memory that they use. + + A single QMimeData object can store the same data using several + different formats at the same time. The formats() function + returns a list of the available formats in order of preference. + The data() function returns the raw data associated with a MIME + type, and setData() allows you to set the data for a MIME type. + + For the most common MIME types, QMimeData provides convenience + functions to access the data: + + \table + \header \o Tester \o Getter \o Setter \o MIME Types + \row \o hasText() \o text() \o setText() \o \c text/plain + \row \o hasHtml() \o html() \o setHtml() \o \c text/html + \row \o hasUrls() \o urls() \o setUrls() \o \c text/uri-list + \row \o hasImage() \o imageData() \o setImageData() \o \c image/ * + \row \o hasColor() \o colorData() \o setColorData() \o \c application/x-color + \endtable + + For example, if your write a widget that accepts URL drags, you + would end up writing code like this: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 0 + + There are three approaches for storing custom data in a QMimeData + object: + + \list 1 + \o Custom data can be stored directly in a QMimeData object as a + QByteArray using setData(). For example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1 + + \o We can subclass QMimeData and reimplement hasFormat(), + formats(), and retrieveData(). + + \o If the drag and drop operation occurs withing a single + application, we can subclass QMimeData and add extra data in + it, and use a qobject_cast() in the receiver's drop event + handler. For example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 2 + \endlist + + \section1 Platform-Specific MIME Types + + On Windows, formats() will also return custom formats available + in the MIME data, using the \c{x-qt-windows-mime} subtype to + indicate that they represent data in non-standard formats. + The formats will take the following form: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 3 + + The following are examples of custom MIME types: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 4 + + The \c value declaration of each format describes the way in which the + data is encoded. + + On Windows, the MIME format does not always map directly to the + clipboard formats. Qt provides QWindowsMime to map clipboard + formats to open-standard MIME formats. Similarly, the + QMacPasteboardMime maps MIME to Mac flavors. + + \sa QClipboard, QDragEnterEvent, QDragMoveEvent, QDropEvent, QDrag, + QWindowsMime, QMacPasteboardMime, {Drag and Drop} +*/ + +/*! + Constructs a new MIME data object with no data in it. +*/ +QMimeData::QMimeData() + : QObject(*new QMimeDataPrivate, 0) +{ +} + +/*! + Destroys the MIME data object. +*/ +QMimeData::~QMimeData() +{ +} + +/*! + Returns a list of URLs contained within the MIME data object. + + URLs correspond to the MIME type \c text/uri-list. + + \sa hasUrls(), data() +*/ +QList<QUrl> QMimeData::urls() const +{ + Q_D(const QMimeData); + QVariant data = d->retrieveTypedData(QLatin1String("text/uri-list"), QVariant::List); + QList<QUrl> urls; + if (data.type() == QVariant::Url) + urls.append(data.toUrl()); + else if (data.type() == QVariant::List) { + QList<QVariant> list = data.toList(); + for (int i = 0; i < list.size(); ++i) { + if (list.at(i).type() == QVariant::Url) + urls.append(list.at(i).toUrl()); + } + } + return urls; +} + +/*! + Sets the URLs stored in the MIME data object to those specified by \a urls. + + URLs correspond to the MIME type \c text/uri-list. + + \sa hasUrls(), setData() +*/ +void QMimeData::setUrls(const QList<QUrl> &urls) +{ + Q_D(QMimeData); + QList<QVariant> list; + for (int i = 0; i < urls.size(); ++i) + list.append(urls.at(i)); + + d->setData(QLatin1String("text/uri-list"), list); +} + +/*! + Returns true if the object can return a list of urls; otherwise + returns false. + + URLs correspond to the MIME type \c text/uri-list. + + \sa setUrls(), urls(), hasFormat() +*/ +bool QMimeData::hasUrls() const +{ + return hasFormat(QLatin1String("text/uri-list")); +} + + +/*! + Returns a plain text (MIME type \c text/plain) representation of + the data. + + \sa hasText(), html(), data() +*/ +QString QMimeData::text() const +{ + Q_D(const QMimeData); + QVariant data = d->retrieveTypedData(QLatin1String("text/plain"), QVariant::String); + return data.toString(); +} + +/*! + Sets \a text as the plain text (MIME type \c text/plain) used to + represent the data. + + \sa hasText(), setHtml(), setData() +*/ +void QMimeData::setText(const QString &text) +{ + Q_D(QMimeData); + d->setData(QLatin1String("text/plain"), text); +} + +/*! + Returns true if the object can return plain text (MIME type \c + text/plain); otherwise returns false. + + \sa setText(), text(), hasHtml(), hasFormat() +*/ +bool QMimeData::hasText() const +{ + return hasFormat(QLatin1String("text/plain")); +} + +/*! + Returns a string if the data stored in the object is HTML (MIME + type \c text/html); otherwise returns an empty string. + + \sa hasHtml(), setData() +*/ +QString QMimeData::html() const +{ + Q_D(const QMimeData); + QVariant data = d->retrieveTypedData(QLatin1String("text/html"), QVariant::String); + return data.toString(); +} + +/*! + Sets \a html as the HTML (MIME type \c text/html) used to + represent the data. + + \sa hasHtml(), setText(), setData() +*/ +void QMimeData::setHtml(const QString &html) +{ + Q_D(QMimeData); + d->setData(QLatin1String("text/html"), html); +} + +/*! + Returns true if the object can return HTML (MIME type \c + text/html); otherwise returns false. + + \sa setHtml(), html(), hasFormat() +*/ +bool QMimeData::hasHtml() const +{ + return hasFormat(QLatin1String("text/html")); +} + +/*! + Returns a QVariant storing a QImage if the object can return an + image; otherwise returns a null variant. + + A QVariant is used because QMimeData belongs to the \l QtCore + library, whereas QImage belongs to \l QtGui. To convert the + QVariant to a QImage, simply use qvariant_cast(). For example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 5 + + \sa hasImage() +*/ +QVariant QMimeData::imageData() const +{ + Q_D(const QMimeData); + return d->retrieveTypedData(QLatin1String("application/x-qt-image"), QVariant::Image); +} + +/*! + Sets the data in the object to the given \a image. + + A QVariant is used because QMimeData belongs to the \l QtCore + library, whereas QImage belongs to \l QtGui. The conversion + from QImage to QVariant is implicit. For example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 6 + + \sa hasImage(), setData() +*/ +void QMimeData::setImageData(const QVariant &image) +{ + Q_D(QMimeData); + d->setData(QLatin1String("application/x-qt-image"), image); +} + +/*! + Returns true if the object can return an image; otherwise returns + false. + + \sa setImageData(), imageData(), hasFormat() +*/ +bool QMimeData::hasImage() const +{ + return hasFormat(QLatin1String("application/x-qt-image")); +} + +/*! + Returns a color if the data stored in the object represents a + color (MIME type \c application/x-color); otherwise returns a + null variant. + + A QVariant is used because QMimeData belongs to the \l QtCore + library, whereas QColor belongs to \l QtGui. To convert the + QVariant to a QColor, simply use qvariant_cast(). For example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 7 + + \sa hasColor(), setColorData(), data() +*/ +QVariant QMimeData::colorData() const +{ + Q_D(const QMimeData); + return d->retrieveTypedData(QLatin1String("application/x-color"), QVariant::Color); +} + +/*! + Sets the color data in the object to the given \a color. + + Colors correspond to the MIME type \c application/x-color. + + \sa hasColor(), setData() +*/ +void QMimeData::setColorData(const QVariant &color) +{ + Q_D(QMimeData); + d->setData(QLatin1String("application/x-color"), color); +} + + +/*! + Returns true if the object can return a color (MIME type \c + application/x-color); otherwise returns false. + + \sa setColorData(), colorData(), hasFormat() +*/ +bool QMimeData::hasColor() const +{ + return hasFormat(QLatin1String("application/x-color")); +} + +/*! + Returns the data stored in the object in the format described by + the MIME type specified by \a mimeType. +*/ +QByteArray QMimeData::data(const QString &mimeType) const +{ + Q_D(const QMimeData); + QVariant data = d->retrieveTypedData(mimeType, QVariant::ByteArray); + return data.toByteArray(); +} + +/*! + Sets the data associated with the MIME type given by \a mimeType + to the specified \a data. + + For the most common types of data, you can call the higher-level + functions setText(), setHtml(), setUrls(), setImageData(), and + setColorData() instead. + + Note that if you want to use a custom data type in an item view drag and drop + operation, you must register it as a Qt \l{QMetaType}{meta type}, using the + Q_DECLARE_METATYPE() macro, and implement stream operators for it. The stream + operators must then be registered with the qRegisterMetaTypeStreamOperators() + function. + + \sa hasFormat(), QMetaType, qRegisterMetaTypeStreamOperators() +*/ +void QMimeData::setData(const QString &mimeType, const QByteArray &data) +{ + Q_D(QMimeData); + d->setData(mimeType, QVariant(data)); +} + +/*! + Returns true if the object can return data for the MIME type + specified by \a mimeType; otherwise returns false. + + For the most common types of data, you can call the higher-level + functions hasText(), hasHtml(), hasUrls(), hasImage(), and + hasColor() instead. + + \sa formats(), setData(), data() +*/ +bool QMimeData::hasFormat(const QString &mimeType) const +{ + return formats().contains(mimeType); +} + +/*! + Returns a list of formats supported by the object. This is a list + of MIME types for which the object can return suitable data. The + formats in the list are in a priority order. + + For the most common types of data, you can call the higher-level + functions hasText(), hasHtml(), hasUrls(), hasImage(), and + hasColor() instead. + + \sa hasFormat(), setData(), data() +*/ +QStringList QMimeData::formats() const +{ + Q_D(const QMimeData); + QStringList list; + for (int i=0; i<d->dataList.size(); i++) + list += d->dataList.at(i).format; + return list; +} + +/*! + Returns a variant with the given \a type containing data for the + MIME type specified by \a mimeType. If the object does not + support the MIME type or variant type given, a null variant is + returned instead. + + This function is called by the general data() getter and by the + convenience getters (text(), html(), urls(), imageData(), and + colorData()). You can reimplement it if you want to store your + data using a custom data structure (instead of a QByteArray, + which is what setData() provides). You would then also need + to reimplement hasFormat() and formats(). + + \sa data() +*/ +QVariant QMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const +{ + Q_UNUSED(type); + Q_D(const QMimeData); + return d->getData(mimeType); +} + +/*! + Removes all the MIME type and data entries in the object. +*/ +void QMimeData::clear() +{ + Q_D(QMimeData); + d->dataList.clear(); +} + +/*! + \since 4.4 + + Removes the data entry for \a mimeType in the object. +*/ +void QMimeData::removeFormat(const QString &mimeType) +{ + Q_D(QMimeData); + d->removeData(mimeType); +} + +QT_END_NAMESPACE |