Add PLUGIN_CLASS_NAME to qtbase plugins
[profile/ivi/qtbase.git] / src / plugins / platforms / xcb / qxcbmime.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qxcbmime.h"
43
44 #include <QtCore/QTextCodec>
45 #include <QtGui/QImageWriter>
46 #include <QtCore/QBuffer>
47 #include <qdebug.h>
48
49 #include <X11/Xutil.h>
50
51 #undef XCB_ATOM_STRING
52 #undef XCB_ATOM_PIXMAP
53 #undef XCB_ATOM_BITMAP
54
55 QT_BEGIN_NAMESPACE
56
57 #if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
58
59 QXcbMime::QXcbMime()
60     : QInternalMimeData()
61 { }
62
63 QXcbMime::~QXcbMime()
64 {}
65
66
67
68 QString QXcbMime::mimeAtomToString(QXcbConnection *connection, xcb_atom_t a)
69 {
70     if (a == XCB_NONE)
71         return QString();
72
73     // special cases for string type
74     if (a == XCB_ATOM_STRING
75         || a == connection->atom(QXcbAtom::UTF8_STRING)
76         || a == connection->atom(QXcbAtom::TEXT))
77         return QLatin1String("text/plain");
78
79     // special case for images
80     if (a == XCB_ATOM_PIXMAP)
81         return QLatin1String("image/ppm");
82
83     QByteArray atomName = connection->atomName(a);
84
85     // special cases for uris
86     if (atomName == "text/x-moz-url")
87         atomName = "text/uri-list";
88
89     return QString::fromLatin1(atomName.constData());
90 }
91
92 bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
93                                xcb_atom_t *atomFormat, int *dataFormat)
94 {
95     if (!data)
96         return false;
97
98     bool ret = false;
99     *atomFormat = a;
100     *dataFormat = 8;
101
102     if ((a == connection->atom(QXcbAtom::UTF8_STRING)
103          || a == XCB_ATOM_STRING
104          || a == connection->atom(QXcbAtom::TEXT))
105         && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) {
106         if (a == connection->atom(QXcbAtom::UTF8_STRING)) {
107             *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData);
108             ret = true;
109         } else if (a == XCB_ATOM_STRING ||
110                    a == connection->atom(QXcbAtom::TEXT)) {
111             // ICCCM says STRING is latin1
112             *data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
113                         QLatin1String("text/plain"), mimeData)).toLatin1();
114             ret = true;
115         }
116         return ret;
117     }
118
119     QString atomName = mimeAtomToString(connection, a);
120     if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) {
121         *data = QInternalMimeData::renderDataHelper(atomName, mimeData);
122         if (atomName == QLatin1String("application/x-color"))
123             *dataFormat = 16;
124         ret = true;
125     } else if (atomName == QLatin1String("text/x-moz-url") &&
126                QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) {
127         QByteArray uri = QInternalMimeData::renderDataHelper(
128                          QLatin1String("text/uri-list"), mimeData).split('\n').first();
129         QString mozUri = QString::fromLatin1(uri, uri.size());
130         mozUri += QLatin1Char('\n');
131         *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2);
132         ret = true;
133     } else if ((a == XCB_ATOM_PIXMAP || a == XCB_ATOM_BITMAP) && mimeData->hasImage()) {
134         ret = true;
135     }
136     return ret;
137 }
138
139 QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
140 {
141     QList<xcb_atom_t> atoms;
142     atoms.append(connection->internAtom(format.toLatin1()));
143
144     // special cases for strings
145     if (format == QLatin1String("text/plain")) {
146         atoms.append(connection->atom(QXcbAtom::UTF8_STRING));
147         atoms.append(XCB_ATOM_STRING);
148         atoms.append(connection->atom(QXcbAtom::TEXT));
149     }
150
151     // special cases for uris
152     if (format == QLatin1String("text/uri-list"))
153         atoms.append(connection->internAtom("text/x-moz-url"));
154
155     //special cases for images
156     if (format == QLatin1String("image/ppm"))
157         atoms.append(XCB_ATOM_PIXMAP);
158     if (format == QLatin1String("image/pbm"))
159         atoms.append(XCB_ATOM_BITMAP);
160
161     return atoms;
162 }
163
164 QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
165                                        QVariant::Type requestedType, const QByteArray &encoding)
166 {
167     QString atomName = mimeAtomToString(connection, a);
168 //    qDebug() << "mimeConvertDataToFormat" << format << atomName << data;
169
170     if (!encoding.isEmpty()
171         && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) {
172
173         if (requestedType == QVariant::String) {
174             QTextCodec *codec = QTextCodec::codecForName(encoding);
175             if (codec)
176                 return codec->toUnicode(data);
177         }
178
179         return data;
180     }
181
182     // special cases for string types
183     if (format == QLatin1String("text/plain")) {
184         if (a == connection->atom(QXcbAtom::UTF8_STRING))
185             return QString::fromUtf8(data);
186         if (a == XCB_ATOM_STRING ||
187             a == connection->atom(QXcbAtom::TEXT))
188             return QString::fromLatin1(data);
189     }
190
191     // special case for uri types
192     if (format == QLatin1String("text/uri-list")) {
193         if (atomName == QLatin1String("text/x-moz-url")) {
194             // we expect this as utf16 <url><space><title>
195             // the first part is a url that should only contain ascci char
196             // so it should be safe to check that the second char is 0
197             // to verify that it is utf16
198             if (data.size() > 1 && data.at(1) == 0)
199                 return QString::fromRawData((const QChar *)data.constData(),
200                                 data.size() / 2).split(QLatin1Char('\n')).first().toLatin1();
201         }
202     }
203
204     if (atomName == format)
205         return data;
206
207 #if 0 // ###
208     // special case for images
209     if (format == QLatin1String("image/ppm")) {
210         if (a == XCB_ATOM_PIXMAP && data.size() == sizeof(Pixmap)) {
211             Pixmap xpm = *((Pixmap*)data.data());
212             if (!xpm)
213                 return QByteArray();
214             Window root;
215             int x;
216             int y;
217             uint width;
218             uint height;
219             uint border_width;
220             uint depth;
221
222             XGetGeometry(display, xpm, &root, &x, &y, &width, &height, &border_width, &depth);
223             XImage *ximg = XGetImage(display,xpm,x,y,width,height,AllPlanes,depth==1 ? XYPixmap : ZPixmap);
224             QImage qimg = QXlibStatic::qimageFromXImage(ximg);
225             XDestroyImage(ximg);
226
227             QImageWriter imageWriter;
228             imageWriter.setFormat("PPMRAW");
229             QBuffer buf;
230             buf.open(QIODevice::WriteOnly);
231             imageWriter.setDevice(&buf);
232             imageWriter.write(qimg);
233             return buf.buffer();
234         }
235     }
236 #endif
237     return QVariant();
238 }
239
240 xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
241                                  const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
242 {
243     requestedEncoding->clear();
244
245     // find matches for string types
246     if (format == QLatin1String("text/plain")) {
247         if (atoms.contains(connection->atom(QXcbAtom::UTF8_STRING)))
248             return connection->atom(QXcbAtom::UTF8_STRING);
249         if (atoms.contains(XCB_ATOM_STRING))
250             return XCB_ATOM_STRING;
251         if (atoms.contains(connection->atom(QXcbAtom::TEXT)))
252             return connection->atom(QXcbAtom::TEXT);
253     }
254
255     // find matches for uri types
256     if (format == QLatin1String("text/uri-list")) {
257         xcb_atom_t a = connection->internAtom(format.toLatin1());
258         if (a && atoms.contains(a))
259             return a;
260         a = connection->internAtom("text/x-moz-url");
261         if (a && atoms.contains(a))
262             return a;
263     }
264
265     // find match for image
266     if (format == QLatin1String("image/ppm")) {
267         if (atoms.contains(XCB_ATOM_PIXMAP))
268             return XCB_ATOM_PIXMAP;
269     }
270
271     // for string/text requests try to use a format with a well-defined charset
272     // first to avoid encoding problems
273     if (requestedType == QVariant::String
274         && format.startsWith(QLatin1String("text/"))
275         && !format.contains(QLatin1String("charset="))) {
276
277         QString formatWithCharset = format;
278         formatWithCharset.append(QLatin1String(";charset=utf-8"));
279
280         xcb_atom_t a = connection->internAtom(formatWithCharset.toLatin1());
281         if (a && atoms.contains(a)) {
282             *requestedEncoding = "utf-8";
283             return a;
284         }
285     }
286
287     xcb_atom_t a = connection->internAtom(format.toLatin1());
288     if (a && atoms.contains(a))
289         return a;
290
291     return 0;
292 }
293
294 #endif // !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
295
296 QT_END_NAMESPACE