source: trunk/src/corelib/kernel/qmimedata.cpp@ 947

Last change on this file since 947 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 18.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
49QT_BEGIN_NAMESPACE
50
51struct QMimeDataStruct
52{
53 QString format;
54 QVariant data;
55};
56
57class QMimeDataPrivate : public QObjectPrivate
58{
59 Q_DECLARE_PUBLIC(QMimeData)
60public:
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
70void 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
80void 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
91QVariant 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
103QVariant 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