1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
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 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 **   * Redistributions of source code must retain the above copyright
25 **     notice, this list of conditions and the following disclaimer.
26 **   * Redistributions in binary form must reproduce the above copyright
27 **     notice, this list of conditions and the following disclaimer in
28 **     the documentation and/or other materials provided with the
29 **     distribution.
30 **   * Neither the name of The Qt Company Ltd nor the names of its
31 **     contributors may be used to endorse or promote products derived
32 **     from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
51 #include "properties_p.h"
52 #include "ui4_p.h"
53 #include "abstractformbuilder.h"
54 #include "formbuilderextra_p.h"
55 #include "resourcebuilder_p.h"
56 
57 #include <QtCore/qdatetime.h>
58 #include <QtCore/qurl.h>
59 #include <QtCore/qdebug.h>
60 
61 #include <QtGui/qicon.h>
62 #include <QtGui/qpixmap.h>
63 #include <QtGui/qfont.h>
64 #include <QtWidgets/qframe.h>
65 #include <QtWidgets/qabstractscrollarea.h>
66 
67 QT_BEGIN_NAMESPACE
68 
69 #ifdef QFORMINTERNAL_NAMESPACE
70 namespace QFormInternal
71 {
72 #endif
73 
fixEnum(QString & s)74 static inline void fixEnum(QString &s)
75 {
76     int qualifierIndex = s.lastIndexOf(QLatin1Char(':'));
77     if (qualifierIndex == -1)
78         qualifierIndex = s.lastIndexOf(QLatin1Char('.'));
79     if (qualifierIndex != -1)
80         s.remove(0, qualifierIndex + 1);
81 }
82 // Convert complex DOM types with the help of  QAbstractFormBuilder
domPropertyToVariant(QAbstractFormBuilder * afb,const QMetaObject * meta,const DomProperty * p)83 QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta,const  DomProperty *p)
84 {
85     // Complex types that need functions from QAbstractFormBuilder
86     switch(p->kind()) {
87     case DomProperty::String: {
88         const int index = meta->indexOfProperty(p->attributeName().toUtf8());
89         if (index != -1 && meta->property(index).type() == QVariant::KeySequence)
90             return QVariant::fromValue(QKeySequence(p->elementString()->text()));
91     }
92         break;
93 
94     case DomProperty::Palette: {
95         const DomPalette *dom = p->elementPalette();
96         QPalette palette;
97 
98         if (dom->elementActive())
99             afb->setupColorGroup(palette, QPalette::Active, dom->elementActive());
100 
101         if (dom->elementInactive())
102             afb->setupColorGroup(palette, QPalette::Inactive, dom->elementInactive());
103 
104         if (dom->elementDisabled())
105             afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled());
106 
107         palette.setCurrentColorGroup(QPalette::Active);
108         return QVariant::fromValue(palette);
109     }
110 
111     case DomProperty::Set: {
112         const QByteArray pname = p->attributeName().toUtf8();
113         const int index = meta->indexOfProperty(pname);
114         if (index == -1) {
115             uiLibWarning(QCoreApplication::translate("QFormBuilder", "The set-type property %1 could not be read.").arg(p->attributeName()));
116             return QVariant();
117         }
118 
119         const QMetaEnum e = meta->property(index).enumerator();
120         Q_ASSERT(e.isFlag() == true);
121         return QVariant(e.keysToValue(p->elementSet().toUtf8()));
122     }
123 
124     case DomProperty::Enum: {
125         const QByteArray pname = p->attributeName().toUtf8();
126         const int index = meta->indexOfProperty(pname);
127         QString enumValue = p->elementEnum();
128         // Triggers in case of objects in Designer like Spacer/Line for which properties
129         // are serialized using language introspection. On preview, however, these objects are
130         // emulated by hacks in the formbuilder (size policy/orientation)
131         fixEnum(enumValue);
132         if (index == -1) {
133             // ### special-casing for Line (QFrame) -- fix for 4.2. Jambi hack for enumerations
134             if (!qstrcmp(meta->className(), "QFrame")
135                 && (pname == QByteArray("orientation"))) {
136                 return QVariant(enumValue == QFormBuilderStrings::instance().horizontalPostFix ? QFrame::HLine : QFrame::VLine);
137             }
138             uiLibWarning(QCoreApplication::translate("QFormBuilder", "The enumeration-type property %1 could not be read.").arg(p->attributeName()));
139             return QVariant();
140         }
141 
142         const QMetaEnum e = meta->property(index).enumerator();
143         return QVariant(e.keyToValue(enumValue.toUtf8()));
144     }
145     case DomProperty::Brush:
146         return QVariant::fromValue(afb->setupBrush(p->elementBrush()));
147     default:
148         if (afb->resourceBuilder()->isResourceProperty(p)) {
149             return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p);
150             }
151 
152         break;
153     }
154 
155     // simple type
156     return domPropertyToVariant(p);
157 }
158 
159 // Convert simple DOM types
domPropertyToVariant(const DomProperty * p)160 QVariant domPropertyToVariant(const DomProperty *p)
161 {
162     // requires non-const virtual nameToIcon, etc.
163     switch(p->kind()) {
164     case DomProperty::Bool:
165         return QVariant(p->elementBool() == QFormBuilderStrings::instance().trueValue);
166 
167     case DomProperty::Cstring:
168         return QVariant(p->elementCstring().toUtf8());
169 
170     case DomProperty::Point: {
171         const DomPoint *point = p->elementPoint();
172         return QVariant(QPoint(point->elementX(), point->elementY()));
173     }
174 
175     case DomProperty::PointF: {
176         const DomPointF *pointf = p->elementPointF();
177         return QVariant(QPointF(pointf->elementX(), pointf->elementY()));
178     }
179 
180     case DomProperty::Size: {
181         const DomSize *size = p->elementSize();
182         return QVariant(QSize(size->elementWidth(), size->elementHeight()));
183     }
184 
185     case DomProperty::SizeF: {
186         const DomSizeF *sizef = p->elementSizeF();
187         return QVariant(QSizeF(sizef->elementWidth(), sizef->elementHeight()));
188     }
189 
190     case DomProperty::Rect: {
191         const DomRect *rc = p->elementRect();
192         const QRect g(rc->elementX(), rc->elementY(), rc->elementWidth(), rc->elementHeight());
193         return QVariant(g);
194     }
195 
196     case DomProperty::RectF: {
197         const DomRectF *rcf = p->elementRectF();
198         const QRectF g(rcf->elementX(), rcf->elementY(), rcf->elementWidth(), rcf->elementHeight());
199         return QVariant(g);
200     }
201 
202     case DomProperty::String:
203         return QVariant(p->elementString()->text());
204 
205     case DomProperty::Number:
206         return QVariant(p->elementNumber());
207 
208     case DomProperty::UInt:
209         return QVariant(p->elementUInt());
210 
211     case DomProperty::LongLong:
212         return QVariant(p->elementLongLong());
213 
214     case DomProperty::ULongLong:
215         return QVariant(p->elementULongLong());
216 
217     case DomProperty::Double:
218         return QVariant(p->elementDouble());
219 
220     case DomProperty::Char: {
221         const DomChar *character = p->elementChar();
222         const QChar c(character->elementUnicode());
223         return QVariant::fromValue(c);
224     }
225 
226     case DomProperty::Color: {
227         const DomColor *color = p->elementColor();
228         QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
229         if (color->hasAttributeAlpha())
230             c.setAlpha(color->attributeAlpha());
231         return QVariant::fromValue(c);
232     }
233 
234     case DomProperty::Font: {
235         const DomFont *font = p->elementFont();
236 
237         QFont f;
238         if (font->hasElementFamily() && !font->elementFamily().isEmpty())
239             f.setFamily(font->elementFamily());
240         if (font->hasElementPointSize() && font->elementPointSize() > 0)
241             f.setPointSize(font->elementPointSize());
242         if (font->hasElementWeight() && font->elementWeight() > 0)
243             f.setWeight(font->elementWeight());
244         if (font->hasElementItalic())
245             f.setItalic(font->elementItalic());
246         if (font->hasElementBold())
247             f.setBold(font->elementBold());
248         if (font->hasElementUnderline())
249             f.setUnderline(font->elementUnderline());
250         if (font->hasElementStrikeOut())
251             f.setStrikeOut(font->elementStrikeOut());
252         if (font->hasElementKerning())
253             f.setKerning(font->elementKerning());
254         if (font->hasElementAntialiasing())
255             f.setStyleStrategy(font->elementAntialiasing() ? QFont::PreferDefault : QFont::NoAntialias);
256         if (font->hasElementStyleStrategy()) {
257             f.setStyleStrategy(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::StyleStrategy>("styleStrategy",
258                                                                                                         font->elementStyleStrategy().toLatin1().constData()));
259         }
260         return QVariant::fromValue(f);
261     }
262 
263     case DomProperty::Date: {
264         const DomDate *date = p->elementDate();
265         return QVariant(QDate(date->elementYear(), date->elementMonth(), date->elementDay()));
266     }
267 
268     case DomProperty::Time: {
269         const DomTime *t = p->elementTime();
270         return QVariant(QTime(t->elementHour(), t->elementMinute(), t->elementSecond()));
271     }
272 
273     case DomProperty::DateTime: {
274         const DomDateTime *dateTime = p->elementDateTime();
275         const QDate d(dateTime->elementYear(), dateTime->elementMonth(), dateTime->elementDay());
276         const QTime tm(dateTime->elementHour(), dateTime->elementMinute(), dateTime->elementSecond());
277         return QVariant(QDateTime(d, tm));
278     }
279 
280     case DomProperty::Url: {
281         const DomUrl *url = p->elementUrl();
282         return QVariant(QUrl(url->elementString()->text()));
283     }
284 
285 #if QT_CONFIG(cursor)
286     case DomProperty::Cursor:
287         return QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor())));
288 
289     case DomProperty::CursorShape:
290         return QVariant::fromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape",
291                                                                                                                p->elementCursorShape().toLatin1().constData())));
292 #endif
293 
294     case DomProperty::Locale: {
295         const DomLocale *locale = p->elementLocale();
296         return QVariant::fromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language",
297                                                                                                                  locale->attributeLanguage().toLatin1().constData()),
298                     enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Country>("country",
299                                                                                          locale->attributeCountry().toLatin1().constData())));
300     }
301     case DomProperty::SizePolicy: {
302         const DomSizePolicy *sizep = p->elementSizePolicy();
303 
304         QSizePolicy sizePolicy;
305         sizePolicy.setHorizontalStretch(sizep->elementHorStretch());
306         sizePolicy.setVerticalStretch(sizep->elementVerStretch());
307 
308         const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
309 
310         if (sizep->hasElementHSizeType()) {
311             sizePolicy.setHorizontalPolicy((QSizePolicy::Policy) sizep->elementHSizeType());
312         } else if (sizep->hasAttributeHSizeType()) {
313             const QSizePolicy::Policy sp = enumKeyToValue<QSizePolicy::Policy>(sizeType_enum, sizep->attributeHSizeType().toLatin1());
314             sizePolicy.setHorizontalPolicy(sp);
315         }
316 
317         if (sizep->hasElementVSizeType()) {
318             sizePolicy.setVerticalPolicy((QSizePolicy::Policy) sizep->elementVSizeType());
319         } else if (sizep->hasAttributeVSizeType()) {
320             const  QSizePolicy::Policy sp = enumKeyToValue<QSizePolicy::Policy>(sizeType_enum, sizep->attributeVSizeType().toLatin1());
321             sizePolicy.setVerticalPolicy(sp);
322         }
323 
324         return QVariant::fromValue(sizePolicy);
325     }
326 
327     case DomProperty::StringList:
328         return QVariant(p->elementStringList()->elementString());
329 
330     default:
331         uiLibWarning(QCoreApplication::translate("QFormBuilder", "Reading properties of the type %1 is not supported yet.").arg(p->kind()));
332         break;
333     }
334 
335     return QVariant();
336 }
337 
338 // Apply a simple variant type to a DOM property
applySimpleProperty(const QVariant & v,bool translateString,DomProperty * dom_prop)339 static bool applySimpleProperty(const QVariant &v, bool translateString, DomProperty *dom_prop)
340 {
341     switch (v.type()) {
342     case QVariant::String: {
343         DomString *str = new DomString();
344         str->setText(v.toString());
345         if (!translateString)
346             str->setAttributeNotr(QStringLiteral("true"));
347         dom_prop->setElementString(str);
348     }
349         return true;
350 
351     case QVariant::ByteArray:
352         dom_prop->setElementCstring(QString::fromUtf8(v.toByteArray()));
353         return true;
354 
355     case QVariant::Int:
356         dom_prop->setElementNumber(v.toInt());
357         return true;
358 
359     case QVariant::UInt:
360         dom_prop->setElementUInt(v.toUInt());
361         return true;
362 
363     case QVariant::LongLong:
364         dom_prop->setElementLongLong(v.toLongLong());
365         return true;
366 
367     case QVariant::ULongLong:
368         dom_prop->setElementULongLong(v.toULongLong());
369         return true;
370 
371     case QVariant::Double:
372         dom_prop->setElementDouble(v.toDouble());
373         return true;
374 
375     case QVariant::Bool:
376         dom_prop->setElementBool(v.toBool() ? QFormBuilderStrings::instance().trueValue : QFormBuilderStrings::instance().falseValue);
377         return true;
378 
379     case QVariant::Char: {
380         DomChar *ch = new DomChar();
381         const QChar character = v.toChar();
382         ch->setElementUnicode(character.unicode());
383         dom_prop->setElementChar(ch);
384     }
385         return true;
386 
387     case QVariant::Point: {
388         DomPoint *pt = new DomPoint();
389         const QPoint point = v.toPoint();
390         pt->setElementX(point.x());
391         pt->setElementY(point.y());
392         dom_prop->setElementPoint(pt);
393     }
394         return true;
395 
396     case QVariant::PointF: {
397         DomPointF *ptf = new DomPointF();
398         const QPointF pointf = v.toPointF();
399         ptf->setElementX(pointf.x());
400         ptf->setElementY(pointf.y());
401         dom_prop->setElementPointF(ptf);
402     }
403         return true;
404 
405     case QVariant::Color: {
406         DomColor *clr = new DomColor();
407         const QColor color = qvariant_cast<QColor>(v);
408         clr->setElementRed(color.red());
409         clr->setElementGreen(color.green());
410         clr->setElementBlue(color.blue());
411         const int alphaChannel = color.alpha();
412         if (alphaChannel != 255)
413             clr->setAttributeAlpha(alphaChannel);
414         dom_prop->setElementColor(clr);
415     }
416         return true;
417 
418     case QVariant::Size: {
419         DomSize *sz = new DomSize();
420         const QSize size = v.toSize();
421         sz->setElementWidth(size.width());
422         sz->setElementHeight(size.height());
423         dom_prop->setElementSize(sz);
424     }
425         return true;
426 
427     case QVariant::SizeF: {
428         DomSizeF *szf = new DomSizeF();
429         const QSizeF sizef = v.toSizeF();
430         szf->setElementWidth(sizef.width());
431         szf->setElementHeight(sizef.height());
432         dom_prop->setElementSizeF(szf);
433     }
434         return true;
435 
436     case QVariant::Rect: {
437         DomRect *rc = new DomRect();
438         const QRect rect = v.toRect();
439         rc->setElementX(rect.x());
440         rc->setElementY(rect.y());
441         rc->setElementWidth(rect.width());
442         rc->setElementHeight(rect.height());
443         dom_prop->setElementRect(rc);
444     }
445         return true;
446 
447     case QVariant::RectF: {
448         DomRectF *rcf = new DomRectF();
449         const QRectF rectf = v.toRectF();
450         rcf->setElementX(rectf.x());
451         rcf->setElementY(rectf.y());
452         rcf->setElementWidth(rectf.width());
453         rcf->setElementHeight(rectf.height());
454         dom_prop->setElementRectF(rcf);
455     }
456         return true;
457 
458     case QVariant::Font: {
459         DomFont *fnt = new DomFont();
460         const QFont font = qvariant_cast<QFont>(v);
461         const uint mask = font.resolve();
462         if (mask & QFont::WeightResolved) {
463             fnt->setElementBold(font.bold());
464             fnt->setElementWeight(font.weight());
465         }
466         if (mask & QFont::FamilyResolved)
467             fnt->setElementFamily(font.family());
468         if (mask & QFont::StyleResolved)
469             fnt->setElementItalic(font.italic());
470         if (mask & QFont::SizeResolved)
471             fnt->setElementPointSize(font.pointSize());
472         if (mask & QFont::StrikeOutResolved)
473             fnt->setElementStrikeOut(font.strikeOut());
474         if (mask & QFont::UnderlineResolved)
475             fnt->setElementUnderline(font.underline());
476         if (mask & QFont::KerningResolved)
477             fnt->setElementKerning(font.kerning());
478         if (mask & QFont::StyleStrategyResolved) {
479             const QMetaEnum styleStrategy_enum = metaEnum<QAbstractFormBuilderGadget>("styleStrategy");
480             fnt->setElementStyleStrategy(QLatin1String(styleStrategy_enum.valueToKey(font.styleStrategy())));
481         }
482         dom_prop->setElementFont(fnt);
483     }
484         return true;
485 
486 #if QT_CONFIG(cursor)
487     case QVariant::Cursor: {
488         const QMetaEnum cursorShape_enum = metaEnum<QAbstractFormBuilderGadget>("cursorShape");
489         dom_prop->setElementCursorShape(QLatin1String(cursorShape_enum.valueToKey(qvariant_cast<QCursor>(v).shape())));
490         }
491         return true;
492 #endif
493 
494     case QVariant::KeySequence: {
495         DomString *s = new DomString();
496         s->setText(qvariant_cast<QKeySequence>(v).toString(QKeySequence::PortableText));
497         dom_prop->setElementString(s);
498         }
499         return true;
500 
501     case QVariant::Locale: {
502         DomLocale *dom = new DomLocale();
503         const QLocale locale = qvariant_cast<QLocale>(v);
504 
505         const QMetaEnum language_enum = metaEnum<QAbstractFormBuilderGadget>("language");
506         const QMetaEnum country_enum = metaEnum<QAbstractFormBuilderGadget>("country");
507 
508         dom->setAttributeLanguage(QLatin1String(language_enum.valueToKey(locale.language())));
509         dom->setAttributeCountry(QLatin1String(country_enum.valueToKey(locale.country())));
510 
511         dom_prop->setElementLocale(dom);
512         }
513         return true;
514 
515     case QVariant::SizePolicy: {
516         DomSizePolicy *dom = new DomSizePolicy();
517         const QSizePolicy sizePolicy = qvariant_cast<QSizePolicy>(v);
518 
519         dom->setElementHorStretch(sizePolicy.horizontalStretch());
520         dom->setElementVerStretch(sizePolicy.verticalStretch());
521 
522         const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
523 
524         dom->setAttributeHSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.horizontalPolicy())));
525         dom->setAttributeVSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.verticalPolicy())));
526 
527         dom_prop->setElementSizePolicy(dom);
528     }
529         return true;
530 
531     case QVariant::Date: {
532         DomDate *dom = new DomDate();
533         const QDate date = qvariant_cast<QDate>(v);
534 
535         dom->setElementYear(date.year());
536         dom->setElementMonth(date.month());
537         dom->setElementDay(date.day());
538 
539         dom_prop->setElementDate(dom);
540         }
541         return true;
542 
543     case QVariant::Time: {
544         DomTime *dom = new DomTime();
545         const QTime time = qvariant_cast<QTime>(v);
546 
547         dom->setElementHour(time.hour());
548         dom->setElementMinute(time.minute());
549         dom->setElementSecond(time.second());
550 
551         dom_prop->setElementTime(dom);
552         }
553         return true;
554 
555     case QVariant::DateTime: {
556         DomDateTime *dom = new DomDateTime();
557         const QDateTime dateTime = qvariant_cast<QDateTime>(v);
558 
559         dom->setElementHour(dateTime.time().hour());
560         dom->setElementMinute(dateTime.time().minute());
561         dom->setElementSecond(dateTime.time().second());
562         dom->setElementYear(dateTime.date().year());
563         dom->setElementMonth(dateTime.date().month());
564         dom->setElementDay(dateTime.date().day());
565 
566         dom_prop->setElementDateTime(dom);
567     }
568         return true;
569 
570     case QVariant::Url: {
571         DomUrl *dom = new DomUrl();
572         const QUrl url = v.toUrl();
573 
574         DomString *str = new DomString();
575         str->setText(url.toString());
576         dom->setElementString(str);
577 
578         dom_prop->setElementUrl(dom);
579     }
580         return true;
581 
582     case QVariant::StringList: {
583         DomStringList *sl = new DomStringList;
584         sl->setElementString(qvariant_cast<QStringList>(v));
585         dom_prop->setElementStringList(sl);
586     }
587         return true;
588 
589     default:
590         break;
591     }
592 
593     return false;
594 }
msgCannotWriteProperty(const QString & pname,const QVariant & v)595 static QString msgCannotWriteProperty(const QString &pname, const QVariant &v)
596 {
597     return QCoreApplication::translate("QFormBuilder", "The property %1 could not be written. The type %2 is not supported yet.").
598                        arg(pname).arg(QLatin1String(v.typeName()));
599 
600 }
601 
isOfType(const QMetaObject * what,const QMetaObject * type)602 static bool isOfType(const QMetaObject *what, const QMetaObject *type)
603 {
604     do {
605         if (what == type)
606             return true;
607     } while ((what = what->superClass()));
608     return false;
609 }
610 
isTranslatable(const QString & pname,const QVariant & v,const QMetaObject * meta)611 static bool isTranslatable(const QString &pname, const QVariant &v, const QMetaObject *meta)
612 {
613     const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
614     if (pname == strings.objectNameProperty)
615         return false;
616     if (pname == strings.styleSheetProperty && v.type() == QVariant::String && isOfType(meta, &QWidget::staticMetaObject))
617         return false;
618     return true;
619 }
620 
621 // Convert complex variant types to DOM properties with the help of  QAbstractFormBuilder
622 // Does not perform a check using  QAbstractFormBuilder::checkProperty().
variantToDomProperty(QAbstractFormBuilder * afb,const QMetaObject * meta,const QString & pname,const QVariant & v)623 DomProperty *variantToDomProperty(QAbstractFormBuilder *afb, const QMetaObject *meta,
624                                   const QString &pname, const QVariant &v)
625 {
626     const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
627 
628     DomProperty *dom_prop = new DomProperty();
629     dom_prop->setAttributeName(pname);
630 
631     const int pindex = meta->indexOfProperty(pname.toLatin1());
632     if (pindex != -1) {
633         QMetaProperty meta_property = meta->property(pindex);
634         if ((v.type() == QVariant::Int || v.type() == QVariant::UInt) && meta_property.isEnumType()) {
635             const QMetaEnum e = meta_property.enumerator();
636             if (e.isFlag())
637                 dom_prop->setElementSet(QString::fromLatin1(e.valueToKeys(v.toInt())));
638             else
639                 dom_prop->setElementEnum(QString::fromLatin1(e.valueToKey(v.toInt())));
640             return dom_prop;
641         }
642         if (!meta_property.hasStdCppSet() || (isOfType(meta, &QAbstractScrollArea::staticMetaObject) && pname == strings.cursorProperty))
643             dom_prop->setAttributeStdset(0);
644     }
645 
646     // Try simple properties
647     if (applySimpleProperty(v, isTranslatable(pname, v, meta), dom_prop))
648         return dom_prop;
649 
650     // Complex properties
651     switch (v.type()) {
652     case QVariant::Palette: {
653         DomPalette *dom = new DomPalette();
654         QPalette palette = qvariant_cast<QPalette>(v);
655 
656         palette.setCurrentColorGroup(QPalette::Active);
657         dom->setElementActive(afb->saveColorGroup(palette));
658 
659         palette.setCurrentColorGroup(QPalette::Inactive);
660         dom->setElementInactive(afb->saveColorGroup(palette));
661 
662         palette.setCurrentColorGroup(QPalette::Disabled);
663         dom->setElementDisabled(afb->saveColorGroup(palette));
664 
665         dom_prop->setElementPalette(dom);
666     } break;
667     case QVariant::Brush:
668         dom_prop->setElementBrush(afb->saveBrush(qvariant_cast<QBrush>(v)));
669         break;
670     default: {
671         const bool hadAttributeStdset = dom_prop->hasAttributeStdset();
672         const bool attributeStdset = dom_prop->attributeStdset();
673         delete dom_prop;
674         if (afb->resourceBuilder()->isResourceType(v)) {
675             dom_prop = afb->resourceBuilder()->saveResource(afb->workingDirectory(), v);
676             if (dom_prop) {
677                 dom_prop->setAttributeName(pname);
678                 if (hadAttributeStdset)
679                     dom_prop->setAttributeStdset(attributeStdset);
680             }
681             break;
682         }
683         uiLibWarning(msgCannotWriteProperty(pname, v));
684     } return nullptr;
685     }
686     return dom_prop;
687 }
688 
689 #ifdef QFORMINTERNAL_NAMESPACE
690 }
691 #endif
692 
693 QT_END_NAMESPACE
694