1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module 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 The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 // Gui types
41 #include "qbitmap.h"
42 #include "qbrush.h"
43 #include "qcolor.h"
44 #include "qcolorspace.h"
45 #include "qcursor.h"
46 #include "qfont.h"
47 #include "qimage.h"
48 #include "qkeysequence.h"
49 #include "qtransform.h"
50 #include "qpalette.h"
51 #include "qpen.h"
52 #include "qpixmap.h"
53 #include "qpolygon.h"
54 #include "qregion.h"
55 #include "qtextformat.h"
56 #include "qmatrix4x4.h"
57 #include "qvector2d.h"
58 #include "qvector3d.h"
59 #include "qvector4d.h"
60 #include "qquaternion.h"
61 #include "qicon.h"
62 
63 // Core types
64 #include "qvariant.h"
65 #include "qbitarray.h"
66 #include "qbytearray.h"
67 #include "qdatastream.h"
68 #include "qdebug.h"
69 #include "qmap.h"
70 #include "qdatetime.h"
71 #include "qlist.h"
72 #include "qstring.h"
73 #include "qstringlist.h"
74 #include "qurl.h"
75 #include "qlocale.h"
76 #include "quuid.h"
77 
78 #ifndef QT_NO_GEOM_VARIANT
79 #include "qsize.h"
80 #include "qpoint.h"
81 #include "qrect.h"
82 #include "qline.h"
83 #endif
84 
85 #include <float.h>
86 
87 #include "private/qvariant_p.h"
88 #include <private/qmetatype_p.h>
89 
90 QT_BEGIN_NAMESPACE
91 
92 Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
93 
94 namespace {
95 struct GuiTypesFilter {
96     template<typename T>
97     struct Acceptor {
98         static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsGui && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
99     };
100 };
101 
construct(QVariant::Private * x,const void * copy)102 static void construct(QVariant::Private *x, const void *copy)
103 {
104     const int type = x->type;
105     QVariantConstructor<GuiTypesFilter> constructor(x, copy);
106     QMetaTypeSwitcher::switcher<void>(constructor, type, nullptr);
107 }
108 
clear(QVariant::Private * d)109 static void clear(QVariant::Private *d)
110 {
111     QVariantDestructor<GuiTypesFilter> destructor(d);
112     QMetaTypeSwitcher::switcher<void>(destructor, d->type, nullptr);
113 }
114 
115 // This class is a hack that customizes access to QPolygon and QPolygonF
116 template<class Filter>
117 class QGuiVariantIsNull : public QVariantIsNull<Filter> {
118     typedef QVariantIsNull<Filter> Base;
119 public:
QGuiVariantIsNull(const QVariant::Private * d)120     QGuiVariantIsNull(const QVariant::Private *d)
121         : QVariantIsNull<Filter>(d)
122     {}
123     template<typename T>
delegate(const T * p)124     bool delegate(const T *p) { return Base::delegate(p); }
delegate(const QPolygon *)125     bool delegate(const QPolygon*) { return v_cast<QPolygon>(Base::m_d)->isEmpty(); }
delegate(const QPolygonF *)126     bool delegate(const QPolygonF*) { return v_cast<QPolygonF>(Base::m_d)->isEmpty(); }
delegate(const void * p)127     bool delegate(const void *p) { return Base::delegate(p); }
128 };
isNull(const QVariant::Private * d)129 static bool isNull(const QVariant::Private *d)
130 {
131     QGuiVariantIsNull<GuiTypesFilter> isNull(d);
132     return QMetaTypeSwitcher::switcher<bool>(isNull, d->type, nullptr);
133 }
134 
135 // This class is a hack that customizes access to QPixmap, QBitmap, QCursor and QIcon
136 template<class Filter>
137 class QGuiVariantComparator : public QVariantComparator<Filter> {
138     typedef QVariantComparator<Filter> Base;
139 public:
QGuiVariantComparator(const QVariant::Private * a,const QVariant::Private * b)140     QGuiVariantComparator(const QVariant::Private *a, const QVariant::Private *b)
141         : QVariantComparator<Filter>(a, b)
142     {}
143     template<typename T>
delegate(const T * p)144     bool delegate(const T *p)
145     {
146         return Base::delegate(p);
147     }
delegate(const QPixmap *)148     bool delegate(const QPixmap*)
149     {
150         return v_cast<QPixmap>(Base::m_a)->cacheKey() == v_cast<QPixmap>(Base::m_b)->cacheKey();
151     }
delegate(const QBitmap *)152     bool delegate(const QBitmap*)
153     {
154         return v_cast<QBitmap>(Base::m_a)->cacheKey() == v_cast<QBitmap>(Base::m_b)->cacheKey();
155     }
156 #ifndef QT_NO_CURSOR
delegate(const QCursor *)157     bool delegate(const QCursor*)
158     {
159         return v_cast<QCursor>(Base::m_a)->shape() == v_cast<QCursor>(Base::m_b)->shape();
160     }
161 #endif
162 #ifndef QT_NO_ICON
delegate(const QIcon *)163     bool delegate(const QIcon *)
164     {
165         return v_cast<QIcon>(Base::m_a)->cacheKey() == v_cast<QIcon>(Base::m_b)->cacheKey();
166     }
167 #endif
delegate(const void * p)168     bool delegate(const void *p) { return Base::delegate(p); }
169 };
170 
compare(const QVariant::Private * a,const QVariant::Private * b)171 static bool compare(const QVariant::Private *a, const QVariant::Private *b)
172 {
173     QGuiVariantComparator<GuiTypesFilter> comparator(a, b);
174     return QMetaTypeSwitcher::switcher<bool>(comparator, a->type, nullptr);
175 }
176 
convert(const QVariant::Private * d,int t,void * result,bool * ok)177 static bool convert(const QVariant::Private *d, int t,
178                  void *result, bool *ok)
179 {
180     switch (t) {
181     case QMetaType::QByteArray:
182         if (d->type == QMetaType::QColor) {
183             const QColor *c = v_cast<QColor>(d);
184             *static_cast<QByteArray *>(result) = c->name(c->alpha() != 255 ? QColor::HexArgb : QColor::HexRgb).toLatin1();
185             return true;
186         }
187         break;
188     case QMetaType::QString: {
189         QString *str = static_cast<QString *>(result);
190         switch (d->type) {
191 #ifndef QT_NO_SHORTCUT
192         case QMetaType::QKeySequence:
193             *str = (*v_cast<QKeySequence>(d)).toString(QKeySequence::NativeText);
194             return true;
195 #endif
196         case QMetaType::QFont:
197             *str = v_cast<QFont>(d)->toString();
198             return true;
199         case QMetaType::QColor: {
200             const QColor *c = v_cast<QColor>(d);
201             *str = c->name(c->alpha() != 255 ? QColor::HexArgb : QColor::HexRgb);
202             return true;
203         }
204         default:
205             break;
206         }
207         break;
208     }
209     case QMetaType::QPixmap:
210         if (d->type == QMetaType::QImage) {
211             *static_cast<QPixmap *>(result) = QPixmap::fromImage(*v_cast<QImage>(d));
212             return true;
213         } else if (d->type == QMetaType::QBitmap) {
214             *static_cast<QPixmap *>(result) = *v_cast<QBitmap>(d);
215             return true;
216         } else if (d->type == QMetaType::QBrush) {
217             if (v_cast<QBrush>(d)->style() == Qt::TexturePattern) {
218                 *static_cast<QPixmap *>(result) = v_cast<QBrush>(d)->texture();
219                 return true;
220             }
221         }
222         break;
223     case QMetaType::QImage:
224         if (d->type == QMetaType::QPixmap) {
225             *static_cast<QImage *>(result) = v_cast<QPixmap>(d)->toImage();
226             return true;
227         } else if (d->type == QMetaType::QBitmap) {
228             *static_cast<QImage *>(result) = v_cast<QBitmap>(d)->toImage();
229             return true;
230         }
231         break;
232     case QMetaType::QBitmap:
233         if (d->type == QMetaType::QPixmap) {
234             *static_cast<QBitmap *>(result) = *v_cast<QPixmap>(d);
235             return true;
236         } else if (d->type == QMetaType::QImage) {
237             *static_cast<QBitmap *>(result) = QBitmap::fromImage(*v_cast<QImage>(d));
238             return true;
239         }
240         break;
241 #ifndef QT_NO_SHORTCUT
242     case QMetaType::Int:
243         if (d->type == QMetaType::QKeySequence) {
244             const QKeySequence &seq = *v_cast<QKeySequence>(d);
245             *static_cast<int *>(result) = seq.isEmpty() ? 0 : seq[0];
246             return true;
247         }
248         break;
249 #endif
250     case QMetaType::QFont:
251         if (d->type == QMetaType::QString) {
252             QFont *f = static_cast<QFont *>(result);
253             f->fromString(*v_cast<QString>(d));
254             return true;
255         }
256         break;
257     case QMetaType::QColor:
258         if (d->type == QMetaType::QString) {
259             static_cast<QColor *>(result)->setNamedColor(*v_cast<QString>(d));
260             return static_cast<QColor *>(result)->isValid();
261         } else if (d->type == QMetaType::QByteArray) {
262             static_cast<QColor *>(result)->setNamedColor(QLatin1String(*v_cast<QByteArray>(d)));
263             return true;
264         } else if (d->type == QMetaType::QBrush) {
265             if (v_cast<QBrush>(d)->style() == Qt::SolidPattern) {
266                 *static_cast<QColor *>(result) = v_cast<QBrush>(d)->color();
267                 return true;
268             }
269         }
270         break;
271     case QMetaType::QBrush:
272         if (d->type == QMetaType::QColor) {
273             *static_cast<QBrush *>(result) = QBrush(*v_cast<QColor>(d));
274             return true;
275         } else if (d->type == QMetaType::QPixmap) {
276             *static_cast<QBrush *>(result) = QBrush(*v_cast<QPixmap>(d));
277             return true;
278         }
279         break;
280 #ifndef QT_NO_SHORTCUT
281     case QMetaType::QKeySequence: {
282         QKeySequence *seq = static_cast<QKeySequence *>(result);
283         switch (d->type) {
284         case QMetaType::QString:
285             *seq = QKeySequence(*v_cast<QString>(d));
286             return true;
287         case QMetaType::Int:
288             *seq = QKeySequence(d->data.i);
289             return true;
290         default:
291             break;
292         }
293         break;
294     }
295 #endif
296 #ifndef QT_NO_ICON
297     case QMetaType::QIcon: {
298         if (ok)
299             *ok = false;
300         return false;
301     }
302 #endif
303     default:
304         break;
305     }
306     return qcoreVariantHandler()->convert(d, t, result, ok);
307 }
308 
309 #if !defined(QT_NO_DEBUG_STREAM)
streamDebug(QDebug dbg,const QVariant & v)310 static void streamDebug(QDebug dbg, const QVariant &v)
311 {
312     QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
313     QVariantDebugStream<GuiTypesFilter> stream(dbg, d);
314     QMetaTypeSwitcher::switcher<void>(stream, d->type, nullptr);
315 }
316 #endif
317 
318 const QVariant::Handler qt_gui_variant_handler = {
319     construct,
320     clear,
321     isNull,
322 #ifndef QT_NO_DATASTREAM
323     nullptr,
324     nullptr,
325 #endif
326     compare,
327     convert,
328     nullptr,
329 #if !defined(QT_NO_DEBUG_STREAM)
330     streamDebug
331 #else
332     0
333 #endif
334 };
335 
336 #define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \
337     QT_METATYPE_INTERFACE_INIT(RealName),
338 
339 static const QMetaTypeInterface qVariantGuiHelper[] = {
340     QT_FOR_EACH_STATIC_GUI_CLASS(QT_IMPL_METATYPEINTERFACE_GUI_TYPES)
341 };
342 
343 #undef QT_IMPL_METATYPEINTERFACE_GUI_TYPES
344 } // namespace used to hide QVariant handler
345 
346 extern Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper;
347 
qRegisterGuiVariant()348 void qRegisterGuiVariant()
349 {
350     QVariantPrivate::registerHandler(QModulesPrivate::Gui, &qt_gui_variant_handler);
351     qMetaTypeGuiHelper = qVariantGuiHelper;
352 }
353 Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant)
354 
355 QT_END_NAMESPACE
356