Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
properties.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "properties_p.h"
6#include "ui4_p.h"
10
11#include <QtCore/qdatetime.h>
12#include <QtCore/qurl.h>
13#include <QtCore/qdebug.h>
14
15#include <QtGui/qicon.h>
16#include <QtGui/qpixmap.h>
17#include <QtGui/qfont.h>
18#include <QtWidgets/qframe.h>
19#include <QtWidgets/qabstractscrollarea.h>
20
21#include <limits>
22#include <memory>
23
24QT_BEGIN_NAMESPACE
25
26using namespace Qt::StringLiterals;
27
28#ifdef QFORMINTERNAL_NAMESPACE
29namespace QFormInternal
30{
31#endif
32
33// Convert complex DOM types with the help of QAbstractFormBuilder
34QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta,const DomProperty *p)
35{
36 // Complex types that need functions from QAbstractFormBuilder
37 switch(p->kind()) {
38 case DomProperty::String: {
39 const int index = meta->indexOfProperty(p->attributeName().toUtf8().constData());
40 if (index != -1 && meta->property(index).metaType().id() == QMetaType::QKeySequence)
41 return QVariant::fromValue(QKeySequence(p->elementString()->text()));
42 }
43 break;
44
45 case DomProperty::Palette: {
46 const DomPalette *dom = p->elementPalette();
47 QPalette palette;
48
49 if (dom->elementActive())
50 afb->setupColorGroup(palette, QPalette::Active, dom->elementActive());
51
52 if (dom->elementInactive())
53 afb->setupColorGroup(palette, QPalette::Inactive, dom->elementInactive());
54
55 if (dom->elementDisabled())
56 afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled());
57
58 palette.setCurrentColorGroup(QPalette::Active);
59 return QVariant::fromValue(palette);
60 }
61
62 case DomProperty::Set: {
63 const QByteArray pname = p->attributeName().toUtf8();
64 const int index = meta->indexOfProperty(pname.constData());
65 if (index == -1) {
66 uiLibWarning(QCoreApplication::translate("QFormBuilder", "The set-type property %1 could not be read.").arg(p->attributeName()));
67 return QVariant();
68 }
69
70 const QMetaEnum e = meta->property(index).enumerator();
71 Q_ASSERT(e.isFlag() == true);
72 bool ok{};
73 QVariant result(e.keysToValue(p->elementSet().toUtf8().constData(), &ok));
74 if (!ok) {
75 uiLibWarning(QCoreApplication::translate("QFormBuilder",
76 "The value \"%1\" of the set-type property %2 could not be read.").
77 arg(p->elementSet(), p->attributeName()));
78 return {};
79 }
80 return result;
81 }
82
83 case DomProperty::Enum: {
84 const QByteArray pname = p->attributeName().toUtf8().constData();
85 const int index = meta->indexOfProperty(pname.constData());
86 const auto &enumValue = p->elementEnum();
87 // Triggers in case of objects in Designer like Spacer/Line for which properties
88 // are serialized using language introspection. On preview, however, these objects are
89 // emulated by hacks in the formbuilder (size policy/orientation)
90 if (index == -1) {
91 // ### special-casing for Line (QFrame) -- fix for 4.2. Jambi hack for enumerations
92 if (!qstrcmp(meta->className(), "QFrame")
93 && (pname == QByteArray("orientation"))) {
94 return QVariant(enumValue.endsWith("Horizontal"_L1) ? QFrame::HLine : QFrame::VLine);
95 }
96 uiLibWarning(QCoreApplication::translate("QFormBuilder", "The enumeration-type property %1 could not be read.").arg(p->attributeName()));
97 return QVariant();
98 }
99
100 const QMetaEnum e = meta->property(index).enumerator();
101 bool ok{};
102 QVariant result(e.keyToValue(enumValue.toUtf8().constData(), &ok));
103 if (!ok) {
104 uiLibWarning(QCoreApplication::translate("QFormBuilder",
105 "The value \"%1\" of the enum-type property %2 could not be read.").
106 arg(enumValue, p->attributeName()));
107 return {};
108 }
109 return result;
110 }
111 case DomProperty::Brush:
112 return QVariant::fromValue(afb->setupBrush(p->elementBrush()));
113 default:
114 if (afb->resourceBuilder()->isResourceProperty(p)) {
115 return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p);
116 }
117
118 break;
119 }
120
121 // simple type
122 return domPropertyToVariant(p);
123}
124
125// Convert a legacy Qt 4 integer font weight to the closes enumeration value
126
128{
129 const QMetaEnum result = metaEnum<QAbstractFormBuilderGadget>("fontWeight");
130 Q_ASSERT(result.isValid());
131 return result;
132}
133
134// Convert simple DOM types
135QVariant domPropertyToVariant(const DomProperty *p)
136{
137 // requires non-const virtual nameToIcon, etc.
138 switch(p->kind()) {
139 case DomProperty::Bool:
140 return QVariant(p->elementBool() == "true"_L1);
141
142 case DomProperty::Cstring:
143 return QVariant(p->elementCstring().toUtf8());
144
145 case DomProperty::Point: {
146 const DomPoint *point = p->elementPoint();
147 return QVariant(QPoint(point->elementX(), point->elementY()));
148 }
149
150 case DomProperty::PointF: {
151 const DomPointF *pointf = p->elementPointF();
152 return QVariant(QPointF(pointf->elementX(), pointf->elementY()));
153 }
154
155 case DomProperty::Size: {
156 const DomSize *size = p->elementSize();
157 return QVariant(QSize(size->elementWidth(), size->elementHeight()));
158 }
159
160 case DomProperty::SizeF: {
161 const DomSizeF *sizef = p->elementSizeF();
162 return QVariant(QSizeF(sizef->elementWidth(), sizef->elementHeight()));
163 }
164
165 case DomProperty::Rect: {
166 const DomRect *rc = p->elementRect();
167 const QRect g(rc->elementX(), rc->elementY(), rc->elementWidth(), rc->elementHeight());
168 return QVariant(g);
169 }
170
171 case DomProperty::RectF: {
172 const DomRectF *rcf = p->elementRectF();
173 const QRectF g(rcf->elementX(), rcf->elementY(), rcf->elementWidth(), rcf->elementHeight());
174 return QVariant(g);
175 }
176
177 case DomProperty::String:
178 return QVariant(p->elementString()->text());
179
180 case DomProperty::Number:
181 return QVariant(p->elementNumber());
182
183 case DomProperty::UInt:
184 return QVariant(p->elementUInt());
185
186 case DomProperty::LongLong:
187 return QVariant(p->elementLongLong());
188
189 case DomProperty::ULongLong:
190 return QVariant(p->elementULongLong());
191
192 case DomProperty::Double:
193 return QVariant(p->elementDouble());
194
195 case DomProperty::Char: {
196 const DomChar *character = p->elementChar();
197 const QChar c(character->elementUnicode());
198 return QVariant::fromValue(c);
199 }
200
201 case DomProperty::Color: {
202 const DomColor *color = p->elementColor();
203 QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
204 if (color->hasAttributeAlpha())
205 c.setAlpha(color->attributeAlpha());
206 return QVariant::fromValue(c);
207 }
208
209 case DomProperty::Font: {
210 const DomFont *font = p->elementFont();
211
212 QFont f;
213 if (font->hasElementFamily() && !font->elementFamily().isEmpty())
214 f.setFamily(font->elementFamily());
215 if (font->hasElementPointSize() && font->elementPointSize() > 0)
216 f.setPointSize(font->elementPointSize());
217 if (font->hasElementItalic())
218 f.setItalic(font->elementItalic());
219 if (font->hasElementUnderline())
220 f.setUnderline(font->elementUnderline());
221 if (font->hasElementStrikeOut())
222 f.setStrikeOut(font->elementStrikeOut());
223 if (font->hasElementKerning())
224 f.setKerning(font->elementKerning());
225 if (font->hasElementAntialiasing())
226 f.setStyleStrategy(font->elementAntialiasing() ? QFont::PreferDefault : QFont::NoAntialias);
227 if (font->hasElementStyleStrategy()) {
228 f.setStyleStrategy(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::StyleStrategy>("styleStrategy",
229 font->elementStyleStrategy().toLatin1().constData()));
230 }
231 if (font->hasElementHintingPreference()) {
232 f.setHintingPreference(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::HintingPreference>("hintingPreference",
233 font->elementHintingPreference().toLatin1().constData()));
234 }
235
236 if (font->hasElementFontWeight()) {
237 f.setWeight(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::Weight>(
238 "fontWeight",
239 font->elementFontWeight().toLatin1().constData()));
240 } else if (font->hasElementBold()) {
241 f.setBold(font->elementBold());
242 }
243
244 return QVariant::fromValue(f);
245 }
246
247 case DomProperty::Date: {
248 const DomDate *date = p->elementDate();
249 return QVariant(QDate(date->elementYear(), date->elementMonth(), date->elementDay()));
250 }
251
252 case DomProperty::Time: {
253 const DomTime *t = p->elementTime();
254 return QVariant(QTime(t->elementHour(), t->elementMinute(), t->elementSecond()));
255 }
256
257 case DomProperty::DateTime: {
258 const DomDateTime *dateTime = p->elementDateTime();
259 const QDate d(dateTime->elementYear(), dateTime->elementMonth(), dateTime->elementDay());
260 const QTime tm(dateTime->elementHour(), dateTime->elementMinute(), dateTime->elementSecond());
261 return QVariant(QDateTime(d, tm));
262 }
263
264 case DomProperty::Url: {
265 const DomUrl *url = p->elementUrl();
266 return QVariant(QUrl(url->elementString()->text()));
267 }
268
269#if QT_CONFIG(cursor)
270 case DomProperty::Cursor:
271 return QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor())));
272
273 case DomProperty::CursorShape:
274 return QVariant::fromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape",
275 p->elementCursorShape().toLatin1().constData())));
276#endif
277
278 case DomProperty::Locale: {
279 const DomLocale *locale = p->elementLocale();
280 return QVariant::fromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language",
281 locale->attributeLanguage().toLatin1().constData()),
282 enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Territory>("country",
283 locale->attributeCountry().toLatin1().constData())));
284 }
285 case DomProperty::SizePolicy: {
286 const DomSizePolicy *sizep = p->elementSizePolicy();
287
288 QSizePolicy sizePolicy;
289 sizePolicy.setHorizontalStretch(sizep->elementHorStretch());
290 sizePolicy.setVerticalStretch(sizep->elementVerStretch());
291
292 const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
293
294 if (sizep->hasElementHSizeType()) {
295 sizePolicy.setHorizontalPolicy((QSizePolicy::Policy) sizep->elementHSizeType());
296 } else if (sizep->hasAttributeHSizeType()) {
297 const auto sp = enumKeyToValue<QSizePolicy::Policy>(
298 sizeType_enum, sizep->attributeHSizeType().toLatin1().constData());
299 sizePolicy.setHorizontalPolicy(sp);
300 }
301
302 if (sizep->hasElementVSizeType()) {
303 sizePolicy.setVerticalPolicy((QSizePolicy::Policy) sizep->elementVSizeType());
304 } else if (sizep->hasAttributeVSizeType()) {
305 const auto sp = enumKeyToValue<QSizePolicy::Policy>(
306 sizeType_enum, sizep->attributeVSizeType().toLatin1().constData());
307 sizePolicy.setVerticalPolicy(sp);
308 }
309
310 return QVariant::fromValue(sizePolicy);
311 }
312
313 case DomProperty::StringList:
314 return QVariant(p->elementStringList()->elementString());
315
316 default:
317 uiLibWarning(QCoreApplication::translate("QFormBuilder", "Reading properties of the type %1 is not supported yet.").arg(p->kind()));
318 break;
319 }
320
321 return QVariant();
322}
323
324// Apply a simple variant type to a DOM property
325static bool applySimpleProperty(const QVariant &v, bool translateString, DomProperty *dom_prop)
326{
327 switch (v.metaType().id()) {
328 case QMetaType::QString: {
329 auto *str = new DomString();
330 str->setText(v.toString());
331 if (!translateString)
332 str->setAttributeNotr(u"true"_s);
333 dom_prop->setElementString(str);
334 }
335 return true;
336
337 case QMetaType::QByteArray:
338 dom_prop->setElementCstring(QString::fromUtf8(v.toByteArray()));
339 return true;
340
341 case QMetaType::Int:
342 dom_prop->setElementNumber(v.toInt());
343 return true;
344
345 case QMetaType::UInt:
346 dom_prop->setElementUInt(v.toUInt());
347 return true;
348
349 case QMetaType::LongLong:
350 dom_prop->setElementLongLong(v.toLongLong());
351 return true;
352
353 case QMetaType::ULongLong:
354 dom_prop->setElementULongLong(v.toULongLong());
355 return true;
356
357 case QMetaType::Double:
358 dom_prop->setElementDouble(v.toDouble());
359 return true;
360
361 case QMetaType::Bool:
362 dom_prop->setElementBool(v.toBool() ? "true"_L1 : "false"_L1);
363 return true;
364
365 case QMetaType::QChar: {
366 auto *ch = new DomChar();
367 const QChar character = v.toChar();
368 ch->setElementUnicode(character.unicode());
369 dom_prop->setElementChar(ch);
370 }
371 return true;
372
373 case QMetaType::QPoint: {
374 auto *pt = new DomPoint();
375 const QPoint point = v.toPoint();
376 pt->setElementX(point.x());
377 pt->setElementY(point.y());
378 dom_prop->setElementPoint(pt);
379 }
380 return true;
381
382 case QMetaType::QPointF: {
383 auto *ptf = new DomPointF();
384 const QPointF pointf = v.toPointF();
385 ptf->setElementX(pointf.x());
386 ptf->setElementY(pointf.y());
387 dom_prop->setElementPointF(ptf);
388 }
389 return true;
390
391 case QMetaType::QColor: {
392 auto *clr = new DomColor();
393 const auto color = qvariant_cast<QColor>(v);
394 clr->setElementRed(color.red());
395 clr->setElementGreen(color.green());
396 clr->setElementBlue(color.blue());
397 const int alphaChannel = color.alpha();
398 if (alphaChannel != 255)
399 clr->setAttributeAlpha(alphaChannel);
400 dom_prop->setElementColor(clr);
401 }
402 return true;
403
404 case QMetaType::QSize: {
405 auto *sz = new DomSize();
406 const QSize size = v.toSize();
407 sz->setElementWidth(size.width());
408 sz->setElementHeight(size.height());
409 dom_prop->setElementSize(sz);
410 }
411 return true;
412
413 case QMetaType::QSizeF: {
414 auto *szf = new DomSizeF();
415 const QSizeF sizef = v.toSizeF();
416 szf->setElementWidth(sizef.width());
417 szf->setElementHeight(sizef.height());
418 dom_prop->setElementSizeF(szf);
419 }
420 return true;
421
422 case QMetaType::QRect: {
423 auto *rc = new DomRect();
424 const QRect rect = v.toRect();
425 rc->setElementX(rect.x());
426 rc->setElementY(rect.y());
427 rc->setElementWidth(rect.width());
428 rc->setElementHeight(rect.height());
429 dom_prop->setElementRect(rc);
430 }
431 return true;
432
433 case QMetaType::QRectF: {
434 auto *rcf = new DomRectF();
435 const QRectF rectf = v.toRectF();
436 rcf->setElementX(rectf.x());
437 rcf->setElementY(rectf.y());
438 rcf->setElementWidth(rectf.width());
439 rcf->setElementHeight(rectf.height());
440 dom_prop->setElementRectF(rcf);
441 }
442 return true;
443
444 case QMetaType::QFont: {
445 auto *fnt = new DomFont();
446 const auto font = qvariant_cast<QFont>(v);
447 const uint mask = font.resolveMask();
448 if (mask & QFont::WeightResolved) {
449 switch (font.weight()) {
450 case QFont::Normal:
451 fnt->setElementBold(false);
452 break;
453 case QFont::Bold:
454 fnt->setElementBold(true);
455 break;
456 default: {
457 const QMetaEnum me = fontWeightMetaEnum();
458 const QString ws = QLatin1StringView(me.valueToKey(font.weight()));
459 fnt->setElementFontWeight(ws);
460 }
461 break;
462 }
463 }
464 if ((mask & (QFont::FamilyResolved | QFont::FamiliesResolved)) != 0)
465 fnt->setElementFamily(font.family());
466 if (mask & QFont::StyleResolved)
467 fnt->setElementItalic(font.italic());
468 if (mask & QFont::SizeResolved)
469 fnt->setElementPointSize(font.pointSize());
470 if (mask & QFont::StrikeOutResolved)
471 fnt->setElementStrikeOut(font.strikeOut());
472 if (mask & QFont::UnderlineResolved)
473 fnt->setElementUnderline(font.underline());
474 if (mask & QFont::KerningResolved)
475 fnt->setElementKerning(font.kerning());
476 if (mask & QFont::StyleStrategyResolved) {
477 const QMetaEnum styleStrategy_enum = metaEnum<QAbstractFormBuilderGadget>("styleStrategy");
478 fnt->setElementStyleStrategy(QLatin1StringView(styleStrategy_enum.valueToKey(font.styleStrategy())));
479 }
480 if (mask & QFont::HintingPreferenceResolved) {
481 const QMetaEnum hintingPreference_enum = metaEnum<QAbstractFormBuilderGadget>("hintingPreference");
482 fnt->setElementHintingPreference(QLatin1StringView(hintingPreference_enum.valueToKey(font.hintingPreference())));
483 }
484
485 dom_prop->setElementFont(fnt);
486 }
487 return true;
488
489#if QT_CONFIG(cursor)
490 case QMetaType::QCursor: {
491 const QMetaEnum cursorShape_enum = metaEnum<QAbstractFormBuilderGadget>("cursorShape");
492 dom_prop->setElementCursorShape(QLatin1StringView(cursorShape_enum.valueToKey(qvariant_cast<QCursor>(v).shape())));
493 }
494 return true;
495#endif
496
497 case QMetaType::QKeySequence: {
498 auto *s = new DomString();
499 s->setText(qvariant_cast<QKeySequence>(v).toString(QKeySequence::PortableText));
500 dom_prop->setElementString(s);
501 }
502 return true;
503
504 case QMetaType::QLocale: {
505 auto *dom = new DomLocale();
506 const auto locale = qvariant_cast<QLocale>(v);
507
508 const QMetaEnum language_enum = metaEnum<QAbstractFormBuilderGadget>("language");
509 const QMetaEnum territory_enum = metaEnum<QAbstractFormBuilderGadget>("country");
510
511 dom->setAttributeLanguage(QLatin1StringView(language_enum.valueToKey(locale.language())));
512 dom->setAttributeCountry(QLatin1StringView(territory_enum.valueToKey(locale.territory())));
513
514 dom_prop->setElementLocale(dom);
515 }
516 return true;
517
518 case QMetaType::QSizePolicy: {
519 auto *dom = new DomSizePolicy();
520 const auto sizePolicy = qvariant_cast<QSizePolicy>(v);
521
522 dom->setElementHorStretch(sizePolicy.horizontalStretch());
523 dom->setElementVerStretch(sizePolicy.verticalStretch());
524
525 const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
526
527 dom->setAttributeHSizeType(QLatin1StringView(sizeType_enum.valueToKey(sizePolicy.horizontalPolicy())));
528 dom->setAttributeVSizeType(QLatin1StringView(sizeType_enum.valueToKey(sizePolicy.verticalPolicy())));
529
530 dom_prop->setElementSizePolicy(dom);
531 }
532 return true;
533
534 case QMetaType::QDate: {
535 auto *dom = new DomDate();
536 const auto date = qvariant_cast<QDate>(v);
537
538 dom->setElementYear(date.year());
539 dom->setElementMonth(date.month());
540 dom->setElementDay(date.day());
541
542 dom_prop->setElementDate(dom);
543 }
544 return true;
545
546 case QMetaType::QTime: {
547 auto *dom = new DomTime();
548 const auto time = qvariant_cast<QTime>(v);
549
550 dom->setElementHour(time.hour());
551 dom->setElementMinute(time.minute());
552 dom->setElementSecond(time.second());
553
554 dom_prop->setElementTime(dom);
555 }
556 return true;
557
558 case QMetaType::QDateTime: {
559 auto *dom = new DomDateTime();
560 const auto dateTime = qvariant_cast<QDateTime>(v);
561
562 dom->setElementHour(dateTime.time().hour());
563 dom->setElementMinute(dateTime.time().minute());
564 dom->setElementSecond(dateTime.time().second());
565 dom->setElementYear(dateTime.date().year());
566 dom->setElementMonth(dateTime.date().month());
567 dom->setElementDay(dateTime.date().day());
568
569 dom_prop->setElementDateTime(dom);
570 }
571 return true;
572
573 case QMetaType::QUrl: {
574 auto *dom = new DomUrl();
575 const QUrl url = v.toUrl();
576
577 auto *str = new DomString();
578 str->setText(url.toString());
579 dom->setElementString(str);
580
581 dom_prop->setElementUrl(dom);
582 }
583 return true;
584
585 case QMetaType::QStringList: {
586 auto *sl = new DomStringList;
587 sl->setElementString(qvariant_cast<QStringList>(v));
588 dom_prop->setElementStringList(sl);
589 }
590 return true;
591
592 default:
593 break;
594 }
595
596 return false;
597}
598static QString msgCannotWriteProperty(const QString &pname, const QVariant &v)
599{
600 return QCoreApplication::translate("QFormBuilder", "The property %1 could not be written. The type %2 is not supported yet.").
601 arg(pname).arg(QLatin1StringView(v.typeName()));
602
603}
604
605static bool isOfType(const QMetaObject *what, const QMetaObject *type)
606{
607 do {
608 if (what == type)
609 return true;
610 } while ((what = what->superClass()));
611 return false;
612}
613
614static bool isTranslatable(const QString &pname, const QVariant &v, const QMetaObject *meta)
615{
616 if (pname == "objectName"_L1)
617 return false;
618 if (pname == "styleSheet"_L1 && v.metaType().id() == QMetaType::QString
619 && isOfType(meta, &QWidget::staticMetaObject)) {
620 return false;
621 }
622 return true;
623}
624
625// PYSIDE-3278 (since 7.0) Write fully qualified enums for Python. This code
626// path is used by QFormBuilder or Qt Widgets Designer when writing item view
627// content properties such as alignment (oversight from PYSIDE-2492, see also
628// qdesigner_resource.cpp).
629static bool supportsQualifiedEnums(const QVersionNumber &qtVersion)
630{
631 return qtVersion >= QVersionNumber{ 7, 0, 0 };
632}
633
634static QString enumPrefix(QMetaEnum metaEnum)
635{
636 QString result;
637 if (const auto *scope = metaEnum.scope())
638 result += QLatin1StringView(scope) + "::"_L1;
639 if (const auto *name = metaEnum.enumName()) // Anonymous?
640 result += QLatin1StringView(name) + "::"_L1;
641 return result;
642}
643
644static QString enumValue(QMetaEnum metaEnum, int v, const QVersionNumber &qtVersion)
645{
646 auto value = QLatin1StringView(metaEnum.valueToKey(v));
647 return supportsQualifiedEnums(qtVersion) ? enumPrefix(metaEnum) + value : QString{ value };
648}
649
650static QString flagsValue(QMetaEnum metaEnum, int v, const QVersionNumber &qtVersion)
651{
652 QString result = QLatin1StringView(metaEnum.valueToKeys(v));
653 if (supportsQualifiedEnums(qtVersion) && !result.isEmpty()) {
654 const QString prefix = enumPrefix(metaEnum);
655 result.replace(u'|', u'|' + prefix);
656 result.prepend(prefix);
657 }
658 return result;
659}
660
661// Convert complex variant types to DOM properties with the help of QAbstractFormBuilder
662// Does not perform a check using QAbstractFormBuilder::checkProperty().
663DomProperty *variantToDomProperty(QAbstractFormBuilder *afb, const QMetaObject *meta,
664 const QString &pname, const QVariant &v)
665{
666 auto dom_prop = std::make_unique<DomProperty>();
667 dom_prop->setAttributeName(pname);
668
669 const int pindex = meta->indexOfProperty(pname.toLatin1().constData());
670 if (pindex != -1) {
671 QMetaProperty meta_property = meta->property(pindex);
672 if (v.canConvert<int>() && meta_property.isEnumType()) {
673 const QMetaEnum e = meta_property.enumerator();
674 if (e.isFlag()) {
675 const QString sv = flagsValue(e, v.toInt(), afb->d->m_saveVersion);
676 if (sv.isEmpty()) // QTBUG-136164: Suppress empty strings for option-type flags.
677 return nullptr;
678 dom_prop->setElementSet(sv);
679 } else {
680 dom_prop->setElementEnum(enumValue(e, v.toInt(), afb->d->m_saveVersion));
681 }
682 return dom_prop.release();
683 }
684 if (!meta_property.hasStdCppSet()
685 || (isOfType(meta, &QAbstractScrollArea::staticMetaObject)
686 && pname == "cursor"_L1)) {
687 dom_prop->setAttributeStdset(0);
688 }
689 }
690
691 // Try simple properties
692 if (applySimpleProperty(v, isTranslatable(pname, v, meta), dom_prop.get()))
693 return dom_prop.release();
694
695 // Complex properties
696 switch (v.metaType().id()) {
697 case QMetaType::QPalette: {
698 auto *dom = new DomPalette();
699 auto palette = qvariant_cast<QPalette>(v);
700
701 palette.setCurrentColorGroup(QPalette::Active);
702 dom->setElementActive(afb->saveColorGroup(palette));
703
704 palette.setCurrentColorGroup(QPalette::Inactive);
705 dom->setElementInactive(afb->saveColorGroup(palette));
706
707 palette.setCurrentColorGroup(QPalette::Disabled);
708 dom->setElementDisabled(afb->saveColorGroup(palette));
709
710 dom_prop->setElementPalette(dom);
711 } break;
712 case QMetaType::QBrush:
713 dom_prop->setElementBrush(afb->saveBrush(qvariant_cast<QBrush>(v)));
714 break;
715 default: {
716 const bool hadAttributeStdset = dom_prop->hasAttributeStdset();
717 const bool attributeStdset = dom_prop->attributeStdset();
718 if (afb->resourceBuilder()->isResourceType(v)) {
719 dom_prop.reset(afb->resourceBuilder()->saveResource(afb->workingDirectory(), v));
720 if (dom_prop) {
721 dom_prop->setAttributeName(pname);
722 if (hadAttributeStdset)
723 dom_prop->setAttributeStdset(attributeStdset);
724 }
725 break;
726 }
727 uiLibWarning(msgCannotWriteProperty(pname, v));
728 } return nullptr;
729 }
730 return dom_prop.release();
731}
732
733#ifdef QFORMINTERNAL_NAMESPACE
734}
735#endif
736
737QT_END_NAMESPACE
static bool isOfType(const QMetaObject *what, const QMetaObject *type)
static bool applySimpleProperty(const QVariant &v, bool translateString, DomProperty *dom_prop)
static QMetaEnum fontWeightMetaEnum()
DomProperty * variantToDomProperty(QAbstractFormBuilder *afb, const QMetaObject *meta, const QString &pname, const QVariant &v)
static QString flagsValue(QMetaEnum metaEnum, int v, const QVersionNumber &qtVersion)
static QString msgCannotWriteProperty(const QString &pname, const QVariant &v)
static bool isTranslatable(const QString &pname, const QVariant &v, const QMetaObject *meta)
static QString enumPrefix(QMetaEnum metaEnum)
static bool supportsQualifiedEnums(const QVersionNumber &qtVersion)
QVariant domPropertyToVariant(QAbstractFormBuilder *afb, const QMetaObject *meta, const DomProperty *p)
QVariant domPropertyToVariant(const DomProperty *p)
static QString enumValue(QMetaEnum metaEnum, int v, const QVersionNumber &qtVersion)