e5fcad3 by Lars Knoll at 2009-03-23 1
/****************************************************************************
2
**
89c08c0 by Jason McDonald at 2012-01-11 3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
04e3b30 by Jason McDonald at 2009-09-09 4
** All rights reserved.
858c70f by Jason McDonald at 2009-06-16 5
** Contact: Nokia Corporation (qt-info@nokia.com)
e5fcad3 by Lars Knoll at 2009-03-23 6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
1eea52e by Jyri Tahtela at 2011-05-13 11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
e5fcad3 by Lars Knoll at 2009-03-23 17
**
04e3b30 by Jason McDonald at 2009-09-09 18
** In addition, as a special exception, Nokia gives you certain additional
1eea52e by Jyri Tahtela at 2011-05-13 19
** rights. These rights are described in the Nokia Qt LGPL Exception
04e3b30 by Jason McDonald at 2009-09-09 20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
e5fcad3 by Lars Knoll at 2009-03-23 21
**
1eea52e by Jyri Tahtela at 2011-05-13 22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
309db73 by Jason McDonald at 2009-08-31 29
**
1eea52e by Jyri Tahtela at 2011-05-13 30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
309db73 by Jason McDonald at 2009-08-31 33
**
34
**
35
**
36
**
e5fcad3 by Lars Knoll at 2009-03-23 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);
32182d1 by Thierry Bastian at 2009-07-13 108
    if (data.type() == type || !data.isValid())
e5fcad3 by Lars Knoll at 2009-03-23 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
0d5e900 by Jason McDonald at 2010-11-01 252
    \o  If the drag and drop operation occurs within a single
e5fcad3 by Lars Knoll at 2009-03-23 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