Cutelee 6.2.0
stringfilters.cpp
1/*
2 This file is part of the Cutelee template system.
3
4 Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either version
9 2.1 of the Licence, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#include "stringfilters.h"
22
23#include "util.h"
24
25#include <QtCore/QRegularExpression>
26#include <QtCore/QVariant>
27#include <QtCore/QJsonArray>
28#include <QtCore/QJsonObject>
29#include <QtCore/QJsonDocument>
30
32 const QVariant &argument,
33 bool autoescape) const
34{
35 Q_UNUSED(argument)
36 Q_UNUSED(autoescape)
37 auto safeString = getSafeString(input);
38 safeString.get()
39 .replace(QLatin1Char('\\'), QStringLiteral("\\\\"))
40 .get()
41 .replace(QLatin1Char('\"'), QStringLiteral("\\\""))
42 .get()
43 .replace(QLatin1Char('\''), QStringLiteral("\\\'"));
44 return safeString;
45}
46
48 const QVariant &argument,
49 bool autoescape) const
50{
51 Q_UNUSED(argument)
52 Q_UNUSED(autoescape)
53 auto safeString = getSafeString(input);
54 if (safeString.get().isEmpty())
55 return QString();
56
57 return QVariant(safeString.get().at(0).toUpper()
58 + static_cast<QString>(
59 safeString.get().right(safeString.get().size() - 1)));
60}
61
62EscapeJsFilter::EscapeJsFilter() {}
63
64static QList<std::pair<QString, QString>> getJsEscapes()
65{
67 jsEscapes << std::pair<QString, QString>(QChar::fromLatin1('\\'),
68 QStringLiteral("\\u005C"))
69 << std::pair<QString, QString>(QChar::fromLatin1('\''),
70 QStringLiteral("\\u0027"))
71 << std::pair<QString, QString>(QChar::fromLatin1('\"'),
72 QStringLiteral("\\u0022"))
73 << std::pair<QString, QString>(QChar::fromLatin1('>'),
74 QStringLiteral("\\u003E"))
75 << std::pair<QString, QString>(QChar::fromLatin1('<'),
76 QStringLiteral("\\u003C"))
77 << std::pair<QString, QString>(QChar::fromLatin1('&'),
78 QStringLiteral("\\u0026"))
79 << std::pair<QString, QString>(QChar::fromLatin1('='),
80 QStringLiteral("\\u003D"))
81 << std::pair<QString, QString>(QChar::fromLatin1('-'),
82 QStringLiteral("\\u002D"))
83 << std::pair<QString, QString>(QChar::fromLatin1(';'),
84 QStringLiteral("\\u003B"))
85 << std::pair<QString, QString>(QChar(0x2028), QStringLiteral("\\u2028"))
86 << std::pair<QString, QString>(QChar(0x2029),
87 QStringLiteral("\\u2029"));
88
89 for (auto i = 0; i < 32; ++i) {
90 jsEscapes << std::pair<QString, QString>(
91 QChar(i),
92 QStringLiteral("\\u00")
93 + QStringLiteral("%1").arg(i, 2, 16, QLatin1Char('0')).toUpper());
94 }
95 return jsEscapes;
96}
97
99 const QVariant &argument,
100 bool autoescape) const
101{
102 Q_UNUSED(argument)
103 Q_UNUSED(autoescape)
104 QString retString = getSafeString(input);
105
106 static const auto jsEscapes = getJsEscapes();
107
108 for (auto &escape : jsEscapes) {
109 retString = retString.replace(escape.first, escape.second);
110 }
111 return retString;
112}
113
115 const QVariant &argument,
116 bool autoescape) const
117{
118 Q_UNUSED(argument)
119 Q_UNUSED(autoescape)
120 auto safeString = getSafeString(input);
121
122 const QRegularExpression fixAmpersandsRegexp(
123 QStringLiteral("&(?!(\\w+|#\\d+);)"));
124
125 safeString.get().replace(fixAmpersandsRegexp, QStringLiteral("&amp;"));
126
127 return safeString;
128}
129
130QVariant CutFilter::doFilter(const QVariant &input, const QVariant &argument,
131 bool autoescape) const
132{
133 Q_UNUSED(autoescape)
134 auto retString = getSafeString(input);
135 auto argString = getSafeString(argument);
136
137 auto inputSafe = retString.isSafe();
138
139 retString.get().remove(argString);
140
141 if (inputSafe && argString.get() != QChar::fromLatin1(';'))
142 return SafeString(retString, true);
143 else
144 return retString;
145}
146
147QVariant SafeFilter::doFilter(const QVariant &input, const QVariant &argument,
148 bool autoescape) const
149{
150 Q_UNUSED(argument)
151 Q_UNUSED(autoescape)
152 return markSafe(getSafeString(input));
153}
154
156 const QVariant &argument,
157 bool autoescape) const
158{
159 Q_UNUSED(argument)
160 auto safeString = getSafeString(input);
161 auto lines = safeString.get().split(QLatin1Char('\n'));
162 auto width = QString::number(lines.size()).size();
163
164 const auto shouldEscape = (autoescape && !safeString.isSafe());
165 for (auto i = 0; i < lines.size(); ++i) {
166 lines[i]
167 = QStringLiteral("%1. %2")
168 .arg(i + 1, width)
169 .arg(shouldEscape ? QString(escape(lines.at(i))) : lines.at(i));
170 }
171
172 return SafeString(lines.join(QChar::fromLatin1('\n')), true);
173}
174
175QVariant LowerFilter::doFilter(const QVariant &input, const QVariant &argument,
176 bool autoescape) const
177{
178 Q_UNUSED(argument)
179 Q_UNUSED(autoescape)
180 return getSafeString(input).get().toLower();
181}
182
184 const QVariant &argument,
185 bool autoescape) const
186{
187 Q_UNUSED(autoescape)
188 SafeString a;
189 if (isSafeString(input))
190 a = getSafeString(input);
191 else if (input.userType() == qMetaTypeId<QVariantList>()) {
192 a = toString(input.value<QVariantList>());
193 }
194
195 return SafeString(getSafeString(argument).get().arg(a),
196 getSafeString(input).isSafe());
197}
198
199QVariant TitleFilter::doFilter(const QVariant &input, const QVariant &argument,
200 bool autoescape) const
201{
202 Q_UNUSED(argument)
203 Q_UNUSED(autoescape)
204
205 QString str = getSafeString(input);
206
207 auto it = str.begin();
208 const auto end = str.end();
209
210 auto toUpper = true;
211 for (; it != end; ++it) {
212 if (toUpper)
213 *it = it->toUpper();
214 else
215 *it = it->toLower();
216 toUpper = it->isSpace();
217 }
218
219 return str;
220}
221
223 const QVariant &argument,
224 bool autoescape) const
225{
226 Q_UNUSED(autoescape)
227 auto s = getSafeString(argument);
228
229 bool ok;
230 auto numWords = s.get().toInt(&ok);
231
232 if (!ok) {
233 return input.toString();
234 }
235
236 QString inputString = getSafeString(input);
237 auto words = inputString.split(QLatin1Char(' '), Qt::SkipEmptyParts);
238
239 if (words.size() > numWords) {
240 words = words.mid(0, numWords);
241 if (!words.at(words.size() - 1).endsWith(QStringLiteral("..."))) {
242 words << QStringLiteral("...");
243 }
244 }
245 return words.join(QChar::fromLatin1(' '));
246}
247
248QVariant UpperFilter::doFilter(const QVariant &input, const QVariant &argument,
249 bool autoescape) const
250{
251 Q_UNUSED(argument)
252 Q_UNUSED(autoescape)
253 return getSafeString(input).get().toUpper();
254}
255
257 const QVariant &argument,
258 bool autoescape) const
259{
260 Q_UNUSED(argument)
261 Q_UNUSED(autoescape)
262 return QString::number(
263 getSafeString(input).get().split(QLatin1Char(' ')).size());
264}
265
266QVariant LJustFilter::doFilter(const QVariant &input, const QVariant &argument,
267 bool autoescape) const
268{
269 Q_UNUSED(autoescape)
270 return getSafeString(input).get().leftJustified(
271 getSafeString(argument).get().toInt());
272}
273
274QVariant RJustFilter::doFilter(const QVariant &input, const QVariant &argument,
275 bool autoescape) const
276{
277 Q_UNUSED(autoescape)
278 return getSafeString(input).get().rightJustified(
279 getSafeString(argument).get().toInt());
280}
281
282QVariant CenterFilter::doFilter(const QVariant &input, const QVariant &argument,
283 bool autoescape) const
284{
285 Q_UNUSED(autoescape)
286 QString value = getSafeString(input);
287 const auto valueWidth = value.size();
288 const auto width = getSafeString(argument).get().toInt();
289 const auto totalPadding = width - valueWidth;
290 const auto rightPadding = totalPadding >> 1;
291
292 return value.leftJustified(valueWidth + rightPadding).rightJustified(width);
293}
294
295QVariant EscapeFilter::doFilter(const QVariant &input, const QVariant &argument,
296 bool autoescape) const
297{
298 Q_UNUSED(argument)
299 Q_UNUSED(autoescape)
300 return markForEscaping(getSafeString(input));
301}
302
304 const QVariant &argument,
305 bool autoescape) const
306{
307 Q_UNUSED(argument)
308 Q_UNUSED(autoescape)
309 return markSafe(escape(getSafeString(input)));
310}
311
313 const QVariant &argument,
314 bool autoescape) const
315{
316 Q_UNUSED(autoescape)
317 const auto tags = getSafeString(argument).get().split(QLatin1Char(' '));
318 const auto tagRe
319 = QStringLiteral("(%1)").arg(tags.join(QChar::fromLatin1('|')));
320 const QRegularExpression startTag(
321 QStringLiteral("<%1(/?>|(\\s+[^>]*>))").arg(tagRe));
322 const QRegularExpression endTag(QStringLiteral("</%1>").arg(tagRe));
323
324 auto value = getSafeString(input);
325 const auto safeInput = value.isSafe();
326 value.get().remove(startTag);
327 value.get().remove(endTag);
328 if (safeInput)
329 return markSafe(value);
330 return value;
331}
332
334 const QVariant &argument,
335 bool autoescape) const
336{
337 Q_UNUSED(argument)
338 Q_UNUSED(autoescape)
339 static QRegularExpression tagRe(QStringLiteral("<[^>]*>"),
341
342 QString value = getSafeString(input);
343 value.remove(tagRe);
344 return value;
345}
346
348 const QVariant &argument,
349 bool autoescape) const
350{
351 Q_UNUSED(autoescape)
352 QString _input = getSafeString(input);
353 auto width = argument.value<int>();
354 auto partList = _input.split(QLatin1Char(' '), Qt::SkipEmptyParts);
355 if (partList.isEmpty())
356 return QVariant();
357 auto output = partList.takeFirst();
358 auto pos = output.size() - output.lastIndexOf(QLatin1Char('\n')) - 1;
359 Q_FOREACH (const QString &part, partList) {
360 QStringList lines;
361 if (part.contains(QLatin1Char('\n'))) {
362 lines = part.split(QLatin1Char('\n'));
363 } else {
364 lines.append(part);
365 }
366 pos += lines.first().size() + 1;
367 if (pos > width) {
368 output.append(QLatin1Char('\n'));
369 pos += lines.last().size();
370 } else {
371 output.append(QLatin1Char(' '));
372 if (lines.size() > 1)
373 pos += lines.last().size();
374 }
375 output.append(part);
376 }
377 return output;
378}
379
381 const QVariant &argument,
382 bool autoescape) const
383{
384 Q_UNUSED(autoescape)
385 double inputDouble;
386 switch (input.userType()) {
387 case QMetaType::Int:
388 case QMetaType::UInt:
392 inputDouble = input.toDouble();
393 break;
394 default:
395 inputDouble = getSafeString(input).get().toDouble();
396 }
397
398 int precision;
399 if (argument.isValid())
400 precision = getSafeString(argument).get().toInt();
401 else
402 precision = 1;
403
404 return QString::number(inputDouble, 'f', precision);
405}
406
408 const QVariant &argument,
409 bool autoescape) const
410{
411 Q_UNUSED(argument)
412 Q_UNUSED(autoescape)
413 QVariantList list;
414 if (input.userType() == qMetaTypeId<QVariantList>()) {
415 const auto inputList = input.value<QVariantList>();
416 for (const auto &item : inputList) {
417 list << markSafe(getSafeString(item));
418 }
419 }
420 return list;
421}
422
424 const QVariant &argument,
425 bool autoescape) const
426{
427 Q_UNUSED(argument)
428 auto inputString = getSafeString(input);
429 static const QRegularExpression re(QStringLiteral("\n{2,}"));
430 QStringList output;
431
432 Q_FOREACH (const QString &bit, inputString.get().split(re)) {
433 auto _bit = SafeString(bit, inputString.isSafe());
434 if (autoescape)
435 _bit = conditionalEscape(_bit);
436 _bit.get().replace(QLatin1Char('\n'), QStringLiteral("<br />"));
437 output.append(QStringLiteral("<p>%1</p>").arg(_bit));
438 }
439 return markSafe(output.join(QStringLiteral("\n\n")));
440}
441
443 const QVariant &argument,
444 bool autoescape) const
445{
446 Q_UNUSED(argument)
447 auto inputString = getSafeString(input);
448 if (autoescape && isSafeString(input)) {
449 inputString = conditionalEscape(inputString);
450 }
451 return markSafe(
452 inputString.get().replace(QLatin1Char('\n'), QStringLiteral("<br />")));
453}
454
455static QString nofailStringToAscii(const QString &input)
456{
457 QString output;
458 output.reserve(input.size());
459
460 auto it = input.constBegin();
461 const auto end = input.constEnd();
462 static const QChar asciiEndPoint(128);
463 for (; it != end; ++it)
464 if (*it < asciiEndPoint)
465 output.append(*it);
466
467 return output;
468}
469
471 const QVariant &argument,
472 bool autoescape) const
473{
474 Q_UNUSED(argument)
475 Q_UNUSED(autoescape)
476 QString inputString = getSafeString(input);
477 inputString = inputString.normalized(QString::NormalizationForm_KD);
478 inputString = nofailStringToAscii(inputString);
479 inputString = inputString.trimmed()
480 .toLower()
481 .remove(QRegularExpression(QStringLiteral("[^\\w\\s-]")))
482 .replace(QRegularExpression(QStringLiteral("[-\\s]+")), QStringLiteral("-"));
483 return SafeString(inputString, true);
484}
485
487 const QVariant &argument,
488 bool autoescape) const
489{
490 QVariant ret;
491
492 Q_UNUSED(autoescape)
493 const auto arg = getSafeString(argument);
494 bool numberConvert = true;
495
496 qreal size = 0.0f;
497 if (input.canConvert<qreal>()) {
498 size = input.toReal(&numberConvert);
499 if (!numberConvert) {
500 qWarning("%s", "Failed to convert input file size into floating point value.");
501 }
502 } else {
503 size = getSafeString(input).get().toDouble(&numberConvert);
504 if (!numberConvert) {
505 qWarning("%s", "Failed to convert input file size into floating point value.");
506 }
507 }
508
509 int unitSystem = 10;
510 int precision = 2;
511 qreal multiplier = 1.0f;
512
513 if (!arg.get().isEmpty()) {
514 const auto argList = arg.get().split(QLatin1Char(','), Qt::SkipEmptyParts);
515 const auto numArgs = argList.size();
516 if (numArgs > 0) {
517 unitSystem = argList.at(0).toInt(&numberConvert);
518 if (!numberConvert) {
519 qWarning("%s", "Failed to convert filse size format unit system into integer. Falling back to default 10.");
520 unitSystem = 10;
521 }
522 }
523
524 if (numArgs > 1) {
525 precision = argList.at(1).toInt(&numberConvert);
526 if (!numberConvert) {
527 qWarning("%s", "Failed to convert file size format decimal precision into integer. Falling back to default 2.");
528 precision = 2;
529 }
530 }
531
532 if (numArgs > 2) {
533 multiplier = argList.at(2).toDouble(&numberConvert);
534 if (!numberConvert) {
535 qWarning("%s", "Failed to convert file size format multiplier into double value. Falling back to default 1.0");
536 multiplier = 1.0f;
537 } else {
538 if (multiplier == 0.0f) {
539 qWarning("%s", "It makes no sense to multiply the file size by zero. Using default value 1.0.");
540 multiplier = 1.0f;
541 }
542 }
543 }
544 }
545
546 const double sizeMult = size * multiplier;
547
548 if (unitSystem == 10) {
549 if ((sizeMult > -1000) && (sizeMult < 1000)) {
550 precision = 0;
551 }
552 } else if (unitSystem == 2) {
553 if ((sizeMult > - 1024) && (sizeMult < 1024)) {
554 precision = 0;
555 }
556 }
557
558 const std::pair<qreal,QString> sizePair = calcFileSize(size, unitSystem, multiplier);
559
560 const QString retString = QString::number(sizePair.first, 'f', precision) + QLatin1Char(' ') + sizePair.second;
561
562 ret.setValue(retString);
563
564 return ret;
565}
566
567QVariant TruncateCharsFilter::doFilter(const QVariant &input, const QVariant &argument, bool autoescape) const
568{
569 Q_UNUSED(autoescape)
570 QString retString = getSafeString(input);
571 int count = getSafeString(argument).get().toInt();
572
573 if(retString.length() < count) return retString;
574 retString.truncate(count);
575 retString.append(QStringLiteral("..."));
576 return retString;
577}
578
579static QString escapeJson(const QString &input)
580{
581 QString esc;
582 const int len = input.length();
583 esc.reserve(static_cast<int>(len * 1.2));
584 for (int i = 0; i < len; ++i) {
585 const QChar ch = input.at(i);
586 if (ch == QLatin1Char('>')) {
587 esc += QStringLiteral("\\\\u003E");
588 } else if (ch == QLatin1Char('<')) {
589 esc += QStringLiteral("\\\\u003C");
590 } else if (ch == QLatin1Char('&')) {
591 esc += QStringLiteral("\\\\u0026");
592 } else {
593 esc += ch;
594 }
595 }
596 esc.squeeze();
597 return esc;
598}
599
600QVariant JsonScriptFilter::doFilter(const QVariant &input, const QVariant &argument, bool autoescape) const
601{
602 Q_UNUSED(autoescape)
603 if (input.isNull() || !input.isValid()) {
604 return QVariant();
605 }
606
607 const QString arg = escape(getSafeString(argument));
608
609 QJsonDocument json;
610 if (input.canConvert<QJsonDocument>()) {
611 json = input.toJsonDocument();
612 } else if (input.canConvert<QJsonObject>()) {
613 json.setObject(input.toJsonObject());
614 } else if (input.canConvert<QJsonArray>()) {
615 json.setArray(input.toJsonArray());
616 } else {
617 qWarning("%s", "Can not convert input data into QJsonObject or QJSonArray.");
618 return QVariant();
619 }
620
622 jsonString = escapeJson(jsonString);
623
624 const QString scriptString = u"<script id=\"" + arg + u"\" type=\"application/json\">" + jsonString + u"</script>";
625
626 return SafeString(scriptString, true);
627}
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
SafeString escape(const QString &input) const
Definition filter.cpp:10
SafeString conditionalEscape(const SafeString &input) const
Definition filter.cpp:22
A QString wrapper class for containing whether a string is safe or needs to be escaped.
Definition safestring.h:92
const NestedString & get() const
Definition safestring.h:325
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument=QVariant(), bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument=QVariant(), bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
bool isSafe() const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument=QVariant(), bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
QVariant doFilter(const QVariant &input, const QVariant &argument={}, bool autoescape={}) const override
std::pair< qreal, QString > calcFileSize(qreal size, int unitSystem=10, qreal multiplier=1.0)
Definition util.cpp:196
bool isSafeString(const QVariant &input)
Definition util.cpp:120
Cutelee::SafeString getSafeString(const QVariant &input)
Definition util.cpp:111
Cutelee::SafeString markSafe(const Cutelee::SafeString &input)
Definition util.cpp:93
Cutelee::SafeString markForEscaping(const Cutelee::SafeString &input)
Definition util.cpp:101
QChar fromLatin1(char c)
void setArray(const QJsonArray &array)
void setObject(const QJsonObject &object)
QByteArray toJson(QJsonDocument::JsonFormat format) const const
void append(QList< T > &&value)
T & first()
T & last()
qsizetype size() const const
NormalizationForm_KD
QString & append(QChar ch)
const QChar at(qsizetype position) const const
QString::iterator begin()
QString::const_iterator constBegin() const const
QString::const_iterator constEnd() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString::iterator end()
QString fromUtf8(QByteArrayView str)
QString leftJustified(qsizetype width, QChar fill, bool truncate) const const
qsizetype length() const const
QString normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
void reserve(qsizetype size)
QString rightJustified(qsizetype width, QChar fill, bool truncate) const const
qsizetype size() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
void squeeze()
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QString toLower() const const
QString toUpper() const const
QString trimmed() const const
void truncate(qsizetype position)
QString join(QChar separator) const const
SkipEmptyParts
bool canConvert() const const
bool isNull() const const
bool isValid() const const
void setValue(QVariant &&value)
double toDouble(bool *ok) const const
QJsonArray toJsonArray() const const
QJsonDocument toJsonDocument() const const
QJsonObject toJsonObject() const const
qreal toReal(bool *ok) const const
QString toString() const const
int userType() const const
T value() const &const
Utility functions used throughout Cutelee.