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 | |
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>(logic&: constructor, type, data: nullptr); |
107 | } |
108 | |
109 | static 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 |
116 | template<class Filter> |
117 | class QGuiVariantIsNull : public QVariantIsNull<Filter> { |
118 | typedef QVariantIsNull<Filter> Base; |
119 | public: |
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 | }; |
129 | static 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 |
136 | template<class Filter> |
137 | class QGuiVariantComparator : public QVariantComparator<Filter> { |
138 | typedef QVariantComparator<Filter> Base; |
139 | public: |
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 | |
171 | static 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 | |
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(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) |
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>(logic&: stream, type: d->type, data: nullptr); |
315 | } |
316 | #endif |
317 | |
318 | const 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 | |
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 | |
348 | void qRegisterGuiVariant() |
349 | { |
350 | QVariantPrivate::registerHandler(name: QModulesPrivate::Gui, handler: &qt_gui_variant_handler); |
351 | qMetaTypeGuiHelper = qVariantGuiHelper; |
352 | } |
353 | Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant) |
354 | |
355 | QT_END_NAMESPACE |
356 | |