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 QtQml 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#include "qqmlstringconverters_p.h"
41#include <private/qqmlglobal_p.h>
42
43#include <QtCore/qpoint.h>
44#include <QtCore/qrect.h>
45#include <QtCore/qsize.h>
46#include <QtCore/qvariant.h>
47#include <QtCore/qdatetime.h>
48
49QT_BEGIN_NAMESPACE
50
51QVariant QQmlStringConverters::variantFromString(const QString &s)
52{
53 if (s.isEmpty())
54 return QVariant(s);
55
56 bool ok = false;
57 QRectF r = rectFFromString(s, &ok);
58 if (ok) return QVariant(r);
59 QPointF p = pointFFromString(s, &ok);
60 if (ok) return QVariant(p);
61 QSizeF sz = sizeFFromString(s, &ok);
62 if (ok) return QVariant(sz);
63
64 return QQml_valueTypeProvider()->createVariantFromString(s);
65}
66
67QVariant QQmlStringConverters::variantFromString(const QString &s, int preferredType, bool *ok)
68{
69 switch (preferredType) {
70 case QMetaType::Int:
71 return QVariant(int(qRound(s.toDouble(ok))));
72 case QMetaType::UInt:
73 return QVariant(uint(qRound(s.toDouble(ok))));
74#if QT_CONFIG(datestring)
75 case QMetaType::QDate:
76 return QVariant::fromValue(dateFromString(s, ok));
77 case QMetaType::QTime:
78 return QVariant::fromValue(timeFromString(s, ok));
79 case QMetaType::QDateTime:
80 return QVariant::fromValue(dateTimeFromString(s, ok));
81#endif // datestring
82 case QMetaType::QPointF:
83 return QVariant::fromValue(pointFFromString(s, ok));
84 case QMetaType::QPoint:
85 return QVariant::fromValue(pointFFromString(s, ok).toPoint());
86 case QMetaType::QSizeF:
87 return QVariant::fromValue(sizeFFromString(s, ok));
88 case QMetaType::QSize:
89 return QVariant::fromValue(sizeFFromString(s, ok).toSize());
90 case QMetaType::QRectF:
91 return QVariant::fromValue(rectFFromString(s, ok));
92 case QMetaType::QRect:
93 return QVariant::fromValue(rectFFromString(s, ok).toRect());
94 default:
95 return QQml_valueTypeProvider()->createVariantFromString(preferredType, s, ok);
96 }
97}
98
99QVariant QQmlStringConverters::colorFromString(const QString &s, bool *ok)
100{
101 return QQml_colorProvider()->colorFromString(s, ok);
102}
103
104unsigned QQmlStringConverters::rgbaFromString(const QString &s, bool *ok)
105{
106 return QQml_colorProvider()->rgbaFromString(s, ok);
107}
108
109#if QT_CONFIG(datestring)
110QDate QQmlStringConverters::dateFromString(const QString &s, bool *ok)
111{
112 QDate d = QDate::fromString(s, Qt::ISODate);
113 if (ok) *ok = d.isValid();
114 return d;
115}
116
117QTime QQmlStringConverters::timeFromString(const QString &s, bool *ok)
118{
119 QTime t = QTime::fromString(s, Qt::ISODate);
120 if (ok) *ok = t.isValid();
121 return t;
122}
123
124QDateTime QQmlStringConverters::dateTimeFromString(const QString &s, bool *ok)
125{
126 QDateTime d = QDateTime::fromString(s, Qt::ISODate);
127 if (ok) *ok = d.isValid();
128 // V8 never parses a date string as local time. For consistency do the same here.
129 if (d.timeSpec() == Qt::LocalTime)
130 d.setTimeSpec(Qt::UTC);
131 return d;
132}
133#endif // datestring
134
135//expects input of "x,y"
136QPointF QQmlStringConverters::pointFFromString(const QString &s, bool *ok)
137{
138 if (s.count(QLatin1Char(',')) != 1) {
139 if (ok)
140 *ok = false;
141 return QPointF();
142 }
143
144 bool xGood, yGood;
145 int index = s.indexOf(QLatin1Char(','));
146 qreal xCoord = s.leftRef(index).toDouble(&xGood);
147 qreal yCoord = s.midRef(index+1).toDouble(&yGood);
148 if (!xGood || !yGood) {
149 if (ok)
150 *ok = false;
151 return QPointF();
152 }
153
154 if (ok)
155 *ok = true;
156 return QPointF(xCoord, yCoord);
157}
158
159//expects input of "widthxheight"
160QSizeF QQmlStringConverters::sizeFFromString(const QString &s, bool *ok)
161{
162 if (s.count(QLatin1Char('x')) != 1) {
163 if (ok)
164 *ok = false;
165 return QSizeF();
166 }
167
168 bool wGood, hGood;
169 int index = s.indexOf(QLatin1Char('x'));
170 qreal width = s.leftRef(index).toDouble(&wGood);
171 qreal height = s.midRef(index+1).toDouble(&hGood);
172 if (!wGood || !hGood) {
173 if (ok)
174 *ok = false;
175 return QSizeF();
176 }
177
178 if (ok)
179 *ok = true;
180 return QSizeF(width, height);
181}
182
183//expects input of "x,y,widthxheight" //### use space instead of second comma?
184QRectF QQmlStringConverters::rectFFromString(const QString &s, bool *ok)
185{
186 if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
187 if (ok)
188 *ok = false;
189 return QRectF();
190 }
191
192 bool xGood, yGood, wGood, hGood;
193 int index = s.indexOf(QLatin1Char(','));
194 qreal x = s.leftRef(index).toDouble(&xGood);
195 int index2 = s.indexOf(QLatin1Char(','), index+1);
196 qreal y = s.midRef(index+1, index2-index-1).toDouble(&yGood);
197 index = s.indexOf(QLatin1Char('x'), index2+1);
198 qreal width = s.midRef(index2+1, index-index2-1).toDouble(&wGood);
199 qreal height = s.midRef(index+1).toDouble(&hGood);
200 if (!xGood || !yGood || !wGood || !hGood) {
201 if (ok)
202 *ok = false;
203 return QRectF();
204 }
205
206 if (ok)
207 *ok = true;
208 return QRectF(x, y, width, height);
209}
210
211bool QQmlStringConverters::createFromString(int type, const QString &s, void *data, size_t n)
212{
213 Q_ASSERT(data);
214
215 bool ok = false;
216
217 switch (type) {
218 case QMetaType::Int:
219 {
220 Q_ASSERT(n >= sizeof(int));
221 int *p = reinterpret_cast<int *>(data);
222 *p = int(qRound(s.toDouble(&ok)));
223 return ok;
224 }
225 case QMetaType::UInt:
226 {
227 Q_ASSERT(n >= sizeof(uint));
228 uint *p = reinterpret_cast<uint *>(data);
229 *p = uint(qRound(s.toDouble(&ok)));
230 return ok;
231 }
232#if QT_CONFIG(datestring)
233 case QMetaType::QDate:
234 {
235 Q_ASSERT(n >= sizeof(QDate));
236 QDate *p = reinterpret_cast<QDate *>(data);
237 *p = dateFromString(s, &ok);
238 return ok;
239 }
240 case QMetaType::QTime:
241 {
242 Q_ASSERT(n >= sizeof(QTime));
243 QTime *p = reinterpret_cast<QTime *>(data);
244 *p = timeFromString(s, &ok);
245 return ok;
246 }
247 case QMetaType::QDateTime:
248 {
249 Q_ASSERT(n >= sizeof(QDateTime));
250 QDateTime *p = reinterpret_cast<QDateTime *>(data);
251 *p = dateTimeFromString(s, &ok);
252 return ok;
253 }
254#endif // datestring
255 case QMetaType::QPointF:
256 {
257 Q_ASSERT(n >= sizeof(QPointF));
258 QPointF *p = reinterpret_cast<QPointF *>(data);
259 *p = pointFFromString(s, &ok);
260 return ok;
261 }
262 case QMetaType::QPoint:
263 {
264 Q_ASSERT(n >= sizeof(QPoint));
265 QPoint *p = reinterpret_cast<QPoint *>(data);
266 *p = pointFFromString(s, &ok).toPoint();
267 return ok;
268 }
269 case QMetaType::QSizeF:
270 {
271 Q_ASSERT(n >= sizeof(QSizeF));
272 QSizeF *p = reinterpret_cast<QSizeF *>(data);
273 *p = sizeFFromString(s, &ok);
274 return ok;
275 }
276 case QMetaType::QSize:
277 {
278 Q_ASSERT(n >= sizeof(QSize));
279 QSize *p = reinterpret_cast<QSize *>(data);
280 *p = sizeFFromString(s, &ok).toSize();
281 return ok;
282 }
283 case QMetaType::QRectF:
284 {
285 Q_ASSERT(n >= sizeof(QRectF));
286 QRectF *p = reinterpret_cast<QRectF *>(data);
287 *p = rectFFromString(s, &ok);
288 return ok;
289 }
290 case QMetaType::QRect:
291 {
292 Q_ASSERT(n >= sizeof(QRect));
293 QRect *p = reinterpret_cast<QRect *>(data);
294 *p = rectFFromString(s, &ok).toRect();
295 return ok;
296 }
297 default:
298 return QQml_valueTypeProvider()->createValueFromString(type, s, data, n);
299 }
300}
301
302QT_END_NAMESPACE
303