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
90QT_BEGIN_NAMESPACE
91
92Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
93
94namespace {
95struct GuiTypesFilter {
96 template<typename T>
97 struct Acceptor {
98 static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsGui && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
99 };
100};
101
102static 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>(logic&: constructor, type, data: nullptr);
107}
108
109static void clear(QVariant::Private *d)
110{
111 QVariantDestructor<GuiTypesFilter> destructor(d);
112 QMetaTypeSwitcher::switcher<void>(logic&: destructor, type: d->type, data: nullptr);
113}
114
115// This class is a hack that customizes access to QPolygon and QPolygonF
116template<class Filter>
117class QGuiVariantIsNull : public QVariantIsNull<Filter> {
118 typedef QVariantIsNull<Filter> Base;
119public:
120 QGuiVariantIsNull(const QVariant::Private *d)
121 : QVariantIsNull<Filter>(d)
122 {}
123 template<typename T>
124 bool delegate(const T *p) { return Base::delegate(p); }
125 bool delegate(const QPolygon*) { return v_cast<QPolygon>(Base::m_d)->isEmpty(); }
126 bool delegate(const QPolygonF*) { return v_cast<QPolygonF>(Base::m_d)->isEmpty(); }
127 bool delegate(const void *p) { return Base::delegate(p); }
128};
129static bool isNull(const QVariant::Private *d)
130{
131 QGuiVariantIsNull<GuiTypesFilter> isNull(d);
132 return QMetaTypeSwitcher::switcher<bool>(logic&: isNull, type: d->type, data: nullptr);
133}
134
135// This class is a hack that customizes access to QPixmap, QBitmap, QCursor and QIcon
136template<class Filter>
137class QGuiVariantComparator : public QVariantComparator<Filter> {
138 typedef QVariantComparator<Filter> Base;
139public:
140 QGuiVariantComparator(const QVariant::Private *a, const QVariant::Private *b)
141 : QVariantComparator<Filter>(a, b)
142 {}
143 template<typename T>
144 bool delegate(const T *p)
145 {
146 return Base::delegate(p);
147 }
148 bool delegate(const QPixmap*)
149 {
150 return v_cast<QPixmap>(Base::m_a)->cacheKey() == v_cast<QPixmap>(Base::m_b)->cacheKey();
151 }
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
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
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
168 bool delegate(const void *p) { return Base::delegate(p); }
169};
170
171static bool compare(const QVariant::Private *a, const QVariant::Private *b)
172{
173 QGuiVariantComparator<GuiTypesFilter> comparator(a, b);
174 return QMetaTypeSwitcher::switcher<bool>(logic&: comparator, type: a->type, data: nullptr);
175}
176
177static 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(format: 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(format: 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(format: 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(image: *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(image: *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)
310static 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>(logic&: stream, type: d->type, data: nullptr);
315}
316#endif
317
318const QVariant::Handler qt_gui_variant_handler = {
319 .construct: construct,
320 .clear: clear,
321 .isNull: isNull,
322#ifndef QT_NO_DATASTREAM
323 .load: nullptr,
324 .save: nullptr,
325#endif
326 .compare: compare,
327 .convert: convert,
328 .canConvert: nullptr,
329#if !defined(QT_NO_DEBUG_STREAM)
330 .debugStream: 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
339static 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
346extern Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper;
347
348void qRegisterGuiVariant()
349{
350 QVariantPrivate::registerHandler(name: QModulesPrivate::Gui, handler: &qt_gui_variant_handler);
351 qMetaTypeGuiHelper = qVariantGuiHelper;
352}
353Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant)
354
355QT_END_NAMESPACE
356

source code of qtbase/src/gui/kernel/qguivariant.cpp