Cleanup usage of QVariant::Type.
[profile/ivi/qtbase.git] / src / gui / kernel / qguivariant.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qvariant.h"
43
44 // Gui types
45 #include "qbitmap.h"
46 #include "qbrush.h"
47 #include "qcolor.h"
48 #include "qcursor.h"
49 #include "qdatastream.h"
50 #include "qdebug.h"
51 #include "qfont.h"
52 #include "qimage.h"
53 #include "qkeysequence.h"
54 #include "qtransform.h"
55 #include "qmatrix.h"
56 #include "qpalette.h"
57 #include "qpen.h"
58 #include "qpixmap.h"
59 #include "qpolygon.h"
60 #include "qregion.h"
61 #include "qtextformat.h"
62 #include "qmatrix4x4.h"
63 #include "qvector2d.h"
64 #include "qvector3d.h"
65 #include "qvector4d.h"
66 #include "qquaternion.h"
67
68 // Core types
69 #include "qvariant.h"
70 #include "qbitarray.h"
71 #include "qbytearray.h"
72 #include "qdatastream.h"
73 #include "qdebug.h"
74 #include "qmap.h"
75 #include "qdatetime.h"
76 #include "qeasingcurve.h"
77 #include "qlist.h"
78 #include "qstring.h"
79 #include "qstringlist.h"
80 #include "qurl.h"
81 #include "qlocale.h"
82 #include "quuid.h"
83
84 #ifndef QT_NO_GEOM_VARIANT
85 #include "qsize.h"
86 #include "qpoint.h"
87 #include "qrect.h"
88 #include "qline.h"
89 #endif
90
91 #include <float.h>
92
93 #include "private/qvariant_p.h"
94 #include <private/qmetatype_p.h>
95
96 QT_BEGIN_NAMESPACE
97
98 Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
99
100 namespace {
101 template<typename T>
102 struct TypeDefinition {
103     static const bool IsAvailable = true;
104 };
105 // Ignore these types, as incomplete
106 #ifdef QT_NO_GEOM_VARIANT
107 template<> struct TypeDefinition<QRect> { static const bool IsAvailable = false; };
108 template<> struct TypeDefinition<QRectF> { static const bool IsAvailable = false; };
109 template<> struct TypeDefinition<QSize> { static const bool IsAvailable = false; };
110 template<> struct TypeDefinition<QSizeF> { static const bool IsAvailable = false; };
111 template<> struct TypeDefinition<QLine> { static const bool IsAvailable = false; };
112 template<> struct TypeDefinition<QLineF> { static const bool IsAvailable = false; };
113 template<> struct TypeDefinition<QPoint> { static const bool IsAvailable = false; };
114 template<> struct TypeDefinition<QPointF> { static const bool IsAvailable = false; };
115 #endif
116 #ifdef QT_NO_SHORTCUT
117 template<> struct TypeDefinition<QKeySequence> { static const bool IsAvailable = false; };
118 #endif
119 #ifdef QT_NO_CURSOR
120 template<> struct TypeDefinition<QCursor> { static const bool IsAvailable = false; };
121 #endif
122 #ifdef QT_NO_MATRIX4X4
123 template<> struct TypeDefinition<QMatrix4x4> { static const bool IsAvailable = false; };
124 #endif
125 #ifdef QT_NO_VECTOR2D
126 template<> struct TypeDefinition<QVector2D> { static const bool IsAvailable = false; };
127 #endif
128 #ifdef QT_NO_VECTOR3D
129 template<> struct TypeDefinition<QVector3D> { static const bool IsAvailable = false; };
130 #endif
131 #ifdef QT_NO_VECTOR4D
132 template<> struct TypeDefinition<QVector4D> { static const bool IsAvailable = false; };
133 #endif
134 #ifdef QT_NO_QUATERNION
135 template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable = false; };
136 #endif
137
138 struct GuiTypesFilter {
139     template<typename T>
140     struct Acceptor {
141         static const bool IsAccepted = QTypeModuleInfo<T>::IsGui && TypeDefinition<T>::IsAvailable;
142     };
143 };
144 } // namespace used to hide TypeDefinition
145
146 namespace {
147 static void construct(QVariant::Private *x, const void *copy)
148 {
149     const int type = x->type;
150     if (Q_UNLIKELY(type == 62)) {
151         // small 'trick' to let a QVariant(Qt::blue) create a variant
152         // of type QColor
153         // TODO Get rid of this hack.
154         x->type = QVariant::Color;
155         QColor color(*reinterpret_cast<const Qt::GlobalColor *>(copy));
156         v_construct<QColor>(x, &color);
157         return;
158     }
159     QVariantConstructor<GuiTypesFilter> constructor(x, copy);
160     QMetaTypeSwitcher::switcher<void>(constructor, type, 0);
161 }
162
163 static void clear(QVariant::Private *d)
164 {
165     QVariantDestructor<GuiTypesFilter> destructor(d);
166     QMetaTypeSwitcher::switcher<void>(destructor, d->type, 0);
167 }
168
169 // This class is a hack that customizes access to QPolygon
170 template<class Filter>
171 class QGuiVariantIsNull : public QVariantIsNull<Filter> {
172     typedef QVariantIsNull<Filter> Base;
173 public:
174     QGuiVariantIsNull(const QVariant::Private *d)
175         : QVariantIsNull<Filter>(d)
176     {}
177     template<typename T>
178     bool delegate(const T *p) { return Base::delegate(p); }
179     bool delegate(const QPolygon*) { return v_cast<QPolygon>(Base::m_d)->isEmpty(); }
180     bool delegate(const void *p) { return Base::delegate(p); }
181 };
182 static bool isNull(const QVariant::Private *d)
183 {
184     QGuiVariantIsNull<GuiTypesFilter> isNull(d);
185     return QMetaTypeSwitcher::switcher<bool>(isNull, d->type, 0);
186 }
187
188 // This class is a hack that customizes access to QPixmap, QBitmap and QCursor
189 template<class Filter>
190 class QGuiVariantComparator : public QVariantComparator<Filter> {
191     typedef QVariantComparator<Filter> Base;
192 public:
193     QGuiVariantComparator(const QVariant::Private *a, const QVariant::Private *b)
194         : QVariantComparator<Filter>(a, b)
195     {}
196     template<typename T>
197     bool delegate(const T *p)
198     {
199         return Base::delegate(p);
200     }
201     bool delegate(const QPixmap*)
202     {
203         return v_cast<QPixmap>(Base::m_a)->cacheKey() == v_cast<QPixmap>(Base::m_b)->cacheKey();
204     }
205     bool delegate(const QBitmap*)
206     {
207         return v_cast<QBitmap>(Base::m_a)->cacheKey() == v_cast<QBitmap>(Base::m_b)->cacheKey();
208     }
209 #ifndef QT_NO_CURSOR
210     bool delegate(const QCursor*)
211     {
212         return v_cast<QCursor>(Base::m_a)->shape() == v_cast<QCursor>(Base::m_b)->shape();
213     }
214 #endif
215     bool delegate(const void *p) { return Base::delegate(p); }
216 };
217
218 static bool compare(const QVariant::Private *a, const QVariant::Private *b)
219 {
220     QGuiVariantComparator<GuiTypesFilter> comparator(a, b);
221     return QMetaTypeSwitcher::switcher<bool>(comparator, a->type, 0);
222 }
223
224 static bool convert(const QVariant::Private *d, int t,
225                  void *result, bool *ok)
226 {
227     switch (t) {
228     case QVariant::ByteArray:
229         if (d->type == QVariant::Color) {
230             *static_cast<QByteArray *>(result) = v_cast<QColor>(d)->name().toLatin1();
231             return true;
232         }
233         break;
234     case QVariant::String: {
235         QString *str = static_cast<QString *>(result);
236         switch (d->type) {
237 #ifndef QT_NO_SHORTCUT
238         case QVariant::KeySequence:
239             *str = QString(*v_cast<QKeySequence>(d));
240             return true;
241 #endif
242         case QVariant::Font:
243             *str = v_cast<QFont>(d)->toString();
244             return true;
245         case QVariant::Color:
246             *str = v_cast<QColor>(d)->name();
247             return true;
248         default:
249             break;
250         }
251         break;
252     }
253     case QVariant::Pixmap:
254         if (d->type == QVariant::Image) {
255             *static_cast<QPixmap *>(result) = QPixmap::fromImage(*v_cast<QImage>(d));
256             return true;
257         } else if (d->type == QVariant::Bitmap) {
258             *static_cast<QPixmap *>(result) = *v_cast<QBitmap>(d);
259             return true;
260         } else if (d->type == QVariant::Brush) {
261             if (v_cast<QBrush>(d)->style() == Qt::TexturePattern) {
262                 *static_cast<QPixmap *>(result) = v_cast<QBrush>(d)->texture();
263                 return true;
264             }
265         }
266         break;
267     case QVariant::Image:
268         if (d->type == QVariant::Pixmap) {
269             *static_cast<QImage *>(result) = v_cast<QPixmap>(d)->toImage();
270             return true;
271         } else if (d->type == QVariant::Bitmap) {
272             *static_cast<QImage *>(result) = v_cast<QBitmap>(d)->toImage();
273             return true;
274         }
275         break;
276     case QVariant::Bitmap:
277         if (d->type == QVariant::Pixmap) {
278             *static_cast<QBitmap *>(result) = *v_cast<QPixmap>(d);
279             return true;
280         } else if (d->type == QVariant::Image) {
281             *static_cast<QBitmap *>(result) = QBitmap::fromImage(*v_cast<QImage>(d));
282             return true;
283         }
284         break;
285 #ifndef QT_NO_SHORTCUT
286     case QVariant::Int:
287         if (d->type == QVariant::KeySequence) {
288             *static_cast<int *>(result) = (int)(*(v_cast<QKeySequence>(d)));
289             return true;
290         }
291         break;
292 #endif
293     case QVariant::Font:
294         if (d->type == QVariant::String) {
295             QFont *f = static_cast<QFont *>(result);
296             f->fromString(*v_cast<QString>(d));
297             return true;
298         }
299         break;
300     case QVariant::Color:
301         if (d->type == QVariant::String) {
302             static_cast<QColor *>(result)->setNamedColor(*v_cast<QString>(d));
303             return static_cast<QColor *>(result)->isValid();
304         } else if (d->type == QVariant::ByteArray) {
305             static_cast<QColor *>(result)->setNamedColor(QString::fromLatin1(
306                                 *v_cast<QByteArray>(d)));
307             return true;
308         } else if (d->type == QVariant::Brush) {
309             if (v_cast<QBrush>(d)->style() == Qt::SolidPattern) {
310                 *static_cast<QColor *>(result) = v_cast<QBrush>(d)->color();
311                 return true;
312             }
313         }
314         break;
315     case QVariant::Brush:
316         if (d->type == QVariant::Color) {
317             *static_cast<QBrush *>(result) = QBrush(*v_cast<QColor>(d));
318             return true;
319         } else if (d->type == QVariant::Pixmap) {
320             *static_cast<QBrush *>(result) = QBrush(*v_cast<QPixmap>(d));
321             return true;
322         }
323         break;
324 #ifndef QT_NO_SHORTCUT
325     case QVariant::KeySequence: {
326         QKeySequence *seq = static_cast<QKeySequence *>(result);
327         switch (d->type) {
328         case QVariant::String:
329             *seq = QKeySequence(*v_cast<QString>(d));
330             return true;
331         case QVariant::Int:
332             *seq = QKeySequence(d->data.i);
333             return true;
334         default:
335             break;
336         }
337     }
338 #endif
339     default:
340         break;
341     }
342     return qcoreVariantHandler()->convert(d, t, result, ok);
343 }
344
345 #if !defined(QT_NO_DEBUG_STREAM)
346 static void streamDebug(QDebug dbg, const QVariant &v)
347 {
348     QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
349     QVariantDebugStream<GuiTypesFilter> stream(dbg, d);
350     QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
351 }
352 #endif
353
354 const QVariant::Handler qt_gui_variant_handler = {
355     construct,
356     clear,
357     isNull,
358 #ifndef QT_NO_DATASTREAM
359     0,
360     0,
361 #endif
362     compare,
363     convert,
364     0,
365 #if !defined(QT_NO_DEBUG_STREAM)
366     streamDebug
367 #else
368     0
369 #endif
370 };
371
372 #define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \
373     QT_METATYPE_INTERFACE_INIT(RealName),
374
375 static const QMetaTypeInterface qVariantGuiHelper[] = {
376     QT_FOR_EACH_STATIC_GUI_CLASS(QT_IMPL_METATYPEINTERFACE_GUI_TYPES)
377 };
378
379 #undef QT_IMPL_METATYPEINTERFACE_GUI_TYPES
380 } // namespace used to hide QVariant handler
381
382 extern Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper;
383
384 void qRegisterGuiVariant()
385 {
386     QVariantPrivate::registerHandler(QModulesPrivate::Gui, &qt_gui_variant_handler);
387     qMetaTypeGuiHelper = qVariantGuiHelper;
388 }
389 Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant)
390
391 void qUnregisterGuiVariant()
392 {
393     QVariantPrivate::unregisterHandler(QModulesPrivate::Gui);
394     qMetaTypeGuiHelper = 0;
395 }
396 Q_DESTRUCTOR_FUNCTION(qUnregisterGuiVariant)
397
398
399 QT_END_NAMESPACE