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