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
formbuilderextra.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
6#include "properties_p.h"
9#include "ui4_p.h"
10
11#include <QtWidgets/qlabel.h>
12#include <QtWidgets/qboxlayout.h>
13#include <QtWidgets/qgridlayout.h>
14#if QT_CONFIG(fontcombobox)
15# include <QtWidgets/qfontcombobox.h>
16#endif
17
18#include <QtCore/qvariant.h>
19#include <QtCore/qdebug.h>
20#include <QtCore/qtextstream.h>
21#include <QtCore/qstringlist.h>
22#include <QtCore/qcoreapplication.h>
23#include <QtCore/qversionnumber.h>
24
25#include <limits.h>
26
28
29using namespace Qt::StringLiterals;
30
31#ifdef QFORMINTERNAL_NAMESPACE
32namespace QFormInternal {
33#endif
34
35void uiLibWarning(const QString &message) {
36 qWarning("Designer: %s", qPrintable(message));
37}
38
39QFormBuilderExtra::CustomWidgetData::CustomWidgetData() = default;
40
41QFormBuilderExtra::CustomWidgetData::CustomWidgetData(const DomCustomWidget *dcw) :
42 addPageMethod(dcw->elementAddPageMethod()),
43 baseClass(dcw->elementExtends()),
44 isContainer(dcw->hasElementContainer() && dcw->elementContainer() != 0)
45{
46}
47
48QFormBuilderExtra::QFormBuilderExtra() :
49 m_defaultMargin(INT_MIN),
50 m_defaultSpacing(INT_MIN),
51 m_language(u"c++"_s)
52{
53}
54
55QFormBuilderExtra::~QFormBuilderExtra()
56{
57 clearResourceBuilder();
58 clearTextBuilder();
59}
60
61void QFormBuilderExtra::clear()
62{
63 m_buddies.clear();
64 m_parentWidget = nullptr;
65 m_parentWidgetIsSet = false;
66 m_customWidgetDataHash.clear();
67 m_buttonGroups.clear();
68}
69
70static inline QString msgXmlError(const QXmlStreamReader &reader)
71{
72 return QCoreApplication::translate("QAbstractFormBuilder",
73 "An error has occurred while reading the UI file at line %1, column %2: %3")
74 .arg(reader.lineNumber()).arg(reader.columnNumber())
75 .arg(reader.errorString());
76}
77
78// Read and check the version and the (optional) language attribute
79// of an <ui> element and leave reader positioned at <ui>.
80static bool inline readUiAttributes(QXmlStreamReader &reader, const QString &language,
81 QString *errorMessage)
82{
83 // Read up to first element
84 while (!reader.atEnd()) {
85 switch (reader.readNext()) {
86 case QXmlStreamReader::Invalid:
87 *errorMessage = msgXmlError(reader);
88 return false;
89 case QXmlStreamReader::StartElement:
90 if (reader.name().compare("ui"_L1, Qt::CaseInsensitive) == 0) {
91 const QString versionAttribute = u"version"_s;
92 const QString languageAttribute = u"language"_s;
93 const QXmlStreamAttributes attributes = reader.attributes();
94 if (attributes.hasAttribute(versionAttribute)) {
95 const QVersionNumber version =
96 QVersionNumber::fromString(attributes.value(versionAttribute));
97 if (version < QVersionNumber(4)) {
98 *errorMessage =
99 QCoreApplication::translate("QAbstractFormBuilder",
100 "This file was created using Designer from Qt-%1 and cannot be read.")
101 .arg(attributes.value(versionAttribute));
102 return false;
103 } // version error
104 } // has version
105 if (attributes.hasAttribute(languageAttribute)) {
106 // Check on optional language (Jambi)
107 const QString formLanguage = attributes.value(languageAttribute).toString();
108 if (!formLanguage.isEmpty() && formLanguage.compare(language, Qt::CaseInsensitive)) {
109 *errorMessage =
110 QCoreApplication::translate("QAbstractFormBuilder",
111 "This file cannot be read because it was created using %1.")
112 .arg(formLanguage);
113 return false;
114 } // language error
115 } // has language
116 return true;
117 } // <ui> matched
118 break;
119 default:
120 break;
121 }
122 }
123 // No <ui> found.
124 *errorMessage = QCoreApplication::translate("QAbstractFormBuilder",
125 "Invalid UI file: The root element <ui> is missing.");
126 return false;
127}
128
129DomUI *QFormBuilderExtra::readUi(QIODevice *dev)
130{
131 QXmlStreamReader reader(dev);
132 m_errorString.clear();
133 if (!readUiAttributes(reader, m_language, &m_errorString)) {
134 uiLibWarning(m_errorString);
135 return nullptr;
136 }
137 DomUI *ui = new DomUI;
138 ui->read(reader);
139 if (reader.hasError()) {
140 m_errorString = msgXmlError(reader);
141 uiLibWarning(m_errorString);
142 delete ui;
143 return nullptr;
144 }
145 return ui;
146}
147
148QString QFormBuilderExtra::msgInvalidUiFile()
149{
150 return QCoreApplication::translate("QAbstractFormBuilder", "Invalid UI file");
151}
152
153bool QFormBuilderExtra::applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value)
154{
155 // Store buddies and apply them later on as the widgets might not exist yet.
156 QLabel *label = qobject_cast<QLabel*>(o);
157 if (label == nullptr || propertyName != "buddy"_L1)
158 return false;
159
160 m_buddies.insert(label, value.toString());
161 return true;
162}
163
164void QFormBuilderExtra::applyInternalProperties() const
165{
166 for (auto it = m_buddies.cbegin(), cend = m_buddies.cend(); it != cend; ++it )
167 applyBuddy(it.value(), BuddyApplyAll, it.key());
168}
169
170bool QFormBuilderExtra::applyBuddy(const QString &buddyName, BuddyMode applyMode, QLabel *label)
171{
172 if (buddyName.isEmpty()) {
173 label->setBuddy(nullptr);
174 return false;
175 }
176
177 const QWidgetList widgets = label->topLevelWidget()->findChildren<QWidget*>(buddyName);
178 if (widgets.isEmpty()) {
179 label->setBuddy(nullptr);
180 return false;
181 }
182
183 for (auto *w : widgets) {
184 if (applyMode == BuddyApplyAll || !w->isHidden()) {
185 label->setBuddy(w);
186 return true;
187 }
188 }
189
190 label->setBuddy(nullptr);
191 return false;
192}
193
194const QPointer<QWidget> &QFormBuilderExtra::parentWidget() const
195{
196 return m_parentWidget;
197}
198
199bool QFormBuilderExtra::parentWidgetIsSet() const
200{
201 return m_parentWidgetIsSet;
202}
203
204void QFormBuilderExtra::setParentWidget(const QPointer<QWidget> &w)
205{
206 // Parent widget requires special handling of the geometry property.
207 m_parentWidget = w;
208 m_parentWidgetIsSet = true;
209}
210
211void QFormBuilderExtra::storeCustomWidgetData(const QString &className, const DomCustomWidget *d)
212{
213 if (d)
214 m_customWidgetDataHash.insert(className, CustomWidgetData(d));
215}
216
217QString QFormBuilderExtra::customWidgetBaseClass(const QString &className) const
218{
219 const auto it = m_customWidgetDataHash.constFind(className);
220 if (it != m_customWidgetDataHash.constEnd())
221 return it.value().baseClass;
222 return QString();
223}
224
225QString QFormBuilderExtra::customWidgetAddPageMethod(const QString &className) const
226{
227 const auto it = m_customWidgetDataHash.constFind(className);
228 if (it != m_customWidgetDataHash.constEnd())
229 return it.value().addPageMethod;
230 return QString();
231}
232
233bool QFormBuilderExtra::isCustomWidgetContainer(const QString &className) const
234{
235 const auto it = m_customWidgetDataHash.constFind(className);
236 if (it != m_customWidgetDataHash.constEnd())
237 return it.value().isContainer;
238 return false;
239}
240
241void QFormBuilderExtra::setProcessingLayoutWidget(bool processing)
242{
243 m_layoutWidget = processing;
244}
245
246 bool QFormBuilderExtra::processingLayoutWidget() const
247{
248 return m_layoutWidget;
249}
250void QFormBuilderExtra::setResourceBuilder(QResourceBuilder *builder)
251{
252 if (m_resourceBuilder == builder)
253 return;
254 clearResourceBuilder();
255 m_resourceBuilder = builder;
256}
257
258QResourceBuilder *QFormBuilderExtra::resourceBuilder() const
259{
260 return m_resourceBuilder;
261}
262
263void QFormBuilderExtra::clearResourceBuilder()
264{
265 if (m_resourceBuilder) {
266 delete m_resourceBuilder;
267 m_resourceBuilder = nullptr;
268 }
269}
270
271void QFormBuilderExtra::setTextBuilder(QTextBuilder *builder)
272{
273 if (m_textBuilder == builder)
274 return;
275 clearTextBuilder();
276 m_textBuilder = builder;
277}
278
279QTextBuilder *QFormBuilderExtra::textBuilder() const
280{
281 return m_textBuilder;
282}
283
284void QFormBuilderExtra::clearTextBuilder()
285{
286 if (m_textBuilder) {
287 delete m_textBuilder;
288 m_textBuilder = nullptr;
289 }
290}
291
292void QFormBuilderExtra::registerButtonGroups(const DomButtonGroups *domGroups)
293{
294 const auto &domGroupList = domGroups->elementButtonGroup();
295 for (DomButtonGroup *domGroup : domGroupList)
296 m_buttonGroups.insert(domGroup->attributeName(), ButtonGroupEntry(domGroup, nullptr));
297}
298
299// Utilities for parsing per-cell integer properties that have setters and
300// getters of the form 'setX(int idx, int value)' and 'x(int index)'
301// (converting them to comma-separated string lists and back).
302// Used for layout stretch and grid per-row/column properties.
303
304// Format a list of cell-properties of one dimension as a ','-separated list
305template <class Layout>
306inline QString perCellPropertyToString(const Layout *l, int count, int (Layout::*getter)(int) const)
307{
308 if (count == 0)
309 return QString();
310 QString rc;
311 {
312 QTextStream str(&rc);
313 for (int i = 0; i < count; i++) {
314 if (i)
315 str << ',';
316 str << (l->*getter)(i);
317 }
318 }
319 return rc;
320}
321
322// Clear the property, set all cells to 0
323
324template <class Layout>
325inline void clearPerCellValue(Layout *l, int count, void (Layout::*setter)(int,int), int value = 0)
326{
327 for (int i = 0; i < count; i++)
328 (l->*setter)(i, value);
329}
330
331// Parse and set the property from a comma-separated list
332
333template <class Layout>
334inline bool parsePerCellProperty(Layout *l, int count, void (Layout::*setter)(int,int), const QString &s, int defaultValue = 0)
335{
336 if (s.isEmpty()) {
337 clearPerCellValue(l, count, setter, defaultValue);
338 return true;
339 }
340 const auto list = QStringView{s}.split(u',');
341 if (list.isEmpty()) {
342 clearPerCellValue(l, count, setter, defaultValue);
343 return true;
344 }
345 // Apply all values contained in list
346 const int ac = qMin(count, list.size());
347 bool ok;
348 int i = 0;
349 for ( ; i < ac; i++) {
350 const int value = list.at(i).toInt(&ok);
351 if (!ok || value < 0)
352 return false;
353 (l->*setter)(i, value);
354 }
355 // Clear rest
356 for ( ; i < count; i++)
357 (l->*setter)(i, defaultValue);
358 return true;
359}
360
361// Read and write stretch
362static QString msgInvalidStretch(const QString &objectName, const QString &stretch)
363{
364 //: Parsing layout stretch values
365 return QCoreApplication::translate("FormBuilder", "Invalid stretch value for '%1': '%2'").arg(objectName, stretch);
366}
367
368void QFormBuilderExtra::getLayoutMargins(const QList<DomProperty*> &properties,
369 int *left, int *top, int *right, int *bottom)
370{
371 if (const auto *p = propertyByName(properties, "leftMargin"))
372 *left = p->elementNumber();
373 if (const auto *p = propertyByName(properties, "topMargin"))
374 *top = p->elementNumber();
375 if (const auto *p = propertyByName(properties, "rightMargin"))
376 *right = p->elementNumber();
377 if (const auto *p = propertyByName(properties, "bottomMargin"))
378 *bottom = p->elementNumber();
379}
380
381bool QFormBuilderExtra::isQFontComboBox(const QWidget *w)
382{
383#if QT_CONFIG(fontcombobox)
384 return qobject_cast<const QFontComboBox*>(w) != nullptr;
385#else
386 Q_UNUSED(w);
387 return false;
388#endif
389}
390
391QString QFormBuilderExtra::boxLayoutStretch(const QBoxLayout *box)
392{
393 return perCellPropertyToString(box, box->count(), &QBoxLayout::stretch);
394}
395
396bool QFormBuilderExtra::setBoxLayoutStretch(const QString &s, QBoxLayout *box)
397{
398 const bool rc = parsePerCellProperty(box, box->count(), &QBoxLayout::setStretch, s);
399 if (!rc)
400 uiLibWarning(msgInvalidStretch(box->objectName(), s));
401 return rc;
402}
403
404void QFormBuilderExtra::clearBoxLayoutStretch(QBoxLayout *box)
405{
406 clearPerCellValue(box, box->count(), &QBoxLayout::setStretch);
407}
408
409QString QFormBuilderExtra::gridLayoutRowStretch(const QGridLayout *grid)
410{
411 return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowStretch);
412}
413
414bool QFormBuilderExtra::setGridLayoutRowStretch(const QString &s, QGridLayout *grid)
415{
416 const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowStretch, s);
417 if (!rc)
418 uiLibWarning(msgInvalidStretch(grid->objectName(), s));
419 return rc;
420}
421
422void QFormBuilderExtra::clearGridLayoutRowStretch(QGridLayout *grid)
423{
424 clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowStretch);
425}
426
427QString QFormBuilderExtra::gridLayoutColumnStretch(const QGridLayout *grid)
428{
429 return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnStretch);
430}
431
432bool QFormBuilderExtra::setGridLayoutColumnStretch(const QString &s, QGridLayout *grid)
433{
434 const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnStretch, s);
435 if (!rc)
436 uiLibWarning(msgInvalidStretch(grid->objectName(), s));
437 return rc;
438}
439
440void QFormBuilderExtra::clearGridLayoutColumnStretch(QGridLayout *grid)
441{
442 clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnStretch);
443}
444
445// Read and write grid layout row/column size limits
446
447static QString msgInvalidMinimumSize(const QString &objectName, const QString &ms)
448{
449 //: Parsing grid layout minimum size values
450 return QCoreApplication::translate("FormBuilder", "Invalid minimum size for '%1': '%2'").arg(objectName, ms);
451}
452
453QString QFormBuilderExtra::gridLayoutRowMinimumHeight(const QGridLayout *grid)
454{
455 return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowMinimumHeight);
456}
457
458bool QFormBuilderExtra::setGridLayoutRowMinimumHeight(const QString &s, QGridLayout *grid)
459{
460 const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight, s);
461 if (!rc)
462 uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
463 return rc;
464}
465
466void QFormBuilderExtra::clearGridLayoutRowMinimumHeight(QGridLayout *grid)
467{
468 clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight);
469}
470
471QString QFormBuilderExtra::gridLayoutColumnMinimumWidth(const QGridLayout *grid)
472{
473 return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnMinimumWidth);
474}
475
476bool QFormBuilderExtra::setGridLayoutColumnMinimumWidth(const QString &s, QGridLayout *grid)
477{
478 const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth, s);
479 if (!rc)
480 uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
481 return rc;
482}
483
484void QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(QGridLayout *grid)
485{
486 clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth);
487}
488
489void QFormBuilderExtra::setPixmapProperty(DomProperty *p, const std::pair<QString, QString> &ip)
490{
491 DomResourcePixmap *pix = new DomResourcePixmap;
492 if (!ip.second.isEmpty())
493 pix->setAttributeResource(ip.second);
494
495 pix->setText(ip.first);
496
497 p->setAttributeName("pixmap"_L1);
498 p->setElementPixmap(pix);
499}
500
501void QFormBuilderExtra::setupColorGroup(QPalette *palette, QPalette::ColorGroup colorGroup,
502 const DomColorGroup *group)
503{
504 // old format
505 const auto &colors = group->elementColor();
506 for (int role = 0; role < colors.size(); ++role) {
507 const DomColor *color = colors.at(role);
508 const QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
509 palette->setColor(colorGroup, QPalette::ColorRole(role), c);
510 }
511
512 // new format
513 const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
514
515 const auto colorRoles = group->elementColorRole();
516 for (const DomColorRole *colorRole : colorRoles) {
517 if (colorRole->hasAttributeRole()) {
518 const int r = colorRole_enum.keyToValue(colorRole->attributeRole().toLatin1());
519 if (r != -1) {
520 const QBrush br = setupBrush(colorRole->elementBrush());
521 palette->setBrush(colorGroup, static_cast<QPalette::ColorRole>(r), br);
522 }
523 }
524 }
525}
526
527DomColorGroup *QFormBuilderExtra::saveColorGroup(const QPalette &palette,
528 QPalette::ColorGroup colorGroup)
529{
530
531 const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
532
533 DomColorGroup *group = new DomColorGroup();
534 QList<DomColorRole *> colorRoles;
535
536 for (int r = QPalette::WindowText; r < QPalette::NColorRoles; ++r) {
537 const auto role = static_cast<QPalette::ColorRole>(r);
538 if (palette.isBrushSet(colorGroup, role)) {
539 const QBrush &br = palette.brush(colorGroup, role);
540 DomColorRole *colorRole = new DomColorRole();
541 colorRole->setElementBrush(saveBrush(br));
542 colorRole->setAttributeRole(QLatin1StringView(colorRole_enum.valueToKey(role)));
543 colorRoles.append(colorRole);
544 }
545 }
546
547 group->setElementColorRole(colorRoles);
548 return group;
549}
550
551DomPalette *QFormBuilderExtra::savePalette(const QPalette &palette)
552{
553 DomPalette *dom = new DomPalette();
554 dom->setElementActive(QFormBuilderExtra::saveColorGroup(palette, QPalette::Active));
555 dom->setElementInactive(QFormBuilderExtra::saveColorGroup(palette, QPalette::Inactive));
556 dom->setElementDisabled(QFormBuilderExtra::saveColorGroup(palette, QPalette::Disabled));
557
558 return dom;
559}
560
561QPalette QFormBuilderExtra::loadPalette(const DomPalette *dom)
562{
563 QPalette palette;
564
565 if (dom->elementActive())
566 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Active, dom->elementActive());
567
568 if (dom->elementInactive())
569 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Inactive, dom->elementInactive());
570
571 if (dom->elementDisabled())
572 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Disabled, dom->elementDisabled());
573
574 palette.setCurrentColorGroup(QPalette::Active);
575 return palette;
576}
577
578QBrush QFormBuilderExtra::setupBrush(const DomBrush *brush)
579{
580 QBrush br;
581 if (!brush->hasAttributeBrushStyle())
582 return br;
583
584 const Qt::BrushStyle style = enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::BrushStyle>("brushStyle",
585 brush->attributeBrushStyle().toLatin1().constData());
586
587 if (style == Qt::LinearGradientPattern ||
588 style == Qt::RadialGradientPattern ||
589 style == Qt::ConicalGradientPattern) {
590 const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
591 const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
592 const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
593
594 const DomGradient *gradient = brush->elementGradient();
595 const QGradient::Type type = enumKeyToValue<QGradient::Type>(gradientType_enum, gradient->attributeType().toLatin1());
596
597
598 QGradient *gr = nullptr;
599
600 if (type == QGradient::LinearGradient) {
601 gr = new QLinearGradient(QPointF(gradient->attributeStartX(), gradient->attributeStartY()),
602 QPointF(gradient->attributeEndX(), gradient->attributeEndY()));
603 } else if (type == QGradient::RadialGradient) {
604 gr = new QRadialGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
605 gradient->attributeRadius(),
606 QPointF(gradient->attributeFocalX(), gradient->attributeFocalY()));
607 } else if (type == QGradient::ConicalGradient) {
608 gr = new QConicalGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
609 gradient->attributeAngle());
610 }
611 if (!gr)
612 return br;
613
614 const QGradient::Spread spread = enumKeyToValue<QGradient::Spread>(gradientSpread_enum, gradient->attributeSpread().toLatin1());
615 gr->setSpread(spread);
616
617 const QGradient::CoordinateMode coord = enumKeyToValue<QGradient::CoordinateMode>(gradientCoordinate_enum, gradient->attributeCoordinateMode().toLatin1());
618 gr->setCoordinateMode(coord);
619
620 const auto &stops = gradient->elementGradientStop();
621 for (const DomGradientStop *stop : stops) {
622 const DomColor *color = stop->elementColor();
623 gr->setColorAt(stop->attributePosition(), QColor::fromRgb(color->elementRed(),
624 color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
625 }
626 br = QBrush(*gr);
627 delete gr;
628 } else if (style == Qt::TexturePattern) {
629 const DomProperty *texture = brush->elementTexture();
630 if (texture && texture->kind() == DomProperty::Pixmap) {
631 br.setTexture({});
632 }
633 } else {
634 const DomColor *color = brush->elementColor();
635 br.setColor(QColor::fromRgb(color->elementRed(),
636 color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
637 br.setStyle((Qt::BrushStyle)style);
638 }
639 return br;
640}
641
642DomBrush *QFormBuilderExtra::saveBrush(const QBrush &br)
643{
644 const QMetaEnum brushStyle_enum = metaEnum<QAbstractFormBuilderGadget>("brushStyle");
645
646 DomBrush *brush = new DomBrush();
647 const Qt::BrushStyle style = br.style();
648 brush->setAttributeBrushStyle(QLatin1StringView(brushStyle_enum.valueToKey(style)));
649 if (style == Qt::LinearGradientPattern ||
650 style == Qt::RadialGradientPattern ||
651 style == Qt::ConicalGradientPattern) {
652 const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
653 const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
654 const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
655
656 DomGradient *gradient = new DomGradient();
657 const QGradient *gr = br.gradient();
658 const QGradient::Type type = gr->type();
659 gradient->setAttributeType(QLatin1StringView(gradientType_enum.valueToKey(type)));
660 gradient->setAttributeSpread(QLatin1StringView(gradientSpread_enum.valueToKey(gr->spread())));
661 gradient->setAttributeCoordinateMode(QLatin1StringView(gradientCoordinate_enum.valueToKey(gr->coordinateMode())));
662 QList<DomGradientStop *> stops;
663 const QGradientStops st = gr->stops();
664 for (const QGradientStop &pair : st) {
665 DomGradientStop *stop = new DomGradientStop();
666 stop->setAttributePosition(pair.first);
667 DomColor *color = new DomColor();
668 color->setElementRed(pair.second.red());
669 color->setElementGreen(pair.second.green());
670 color->setElementBlue(pair.second.blue());
671 color->setAttributeAlpha(pair.second.alpha());
672 stop->setElementColor(color);
673 stops.append(stop);
674 }
675 gradient->setElementGradientStop(stops);
676 if (type == QGradient::LinearGradient) {
677 auto lgr = static_cast<const QLinearGradient *>(gr);
678 gradient->setAttributeStartX(lgr->start().x());
679 gradient->setAttributeStartY(lgr->start().y());
680 gradient->setAttributeEndX(lgr->finalStop().x());
681 gradient->setAttributeEndY(lgr->finalStop().y());
682 } else if (type == QGradient::RadialGradient) {
683 auto rgr = static_cast<const QRadialGradient *>(gr);
684 gradient->setAttributeCentralX(rgr->center().x());
685 gradient->setAttributeCentralY(rgr->center().y());
686 gradient->setAttributeFocalX(rgr->focalPoint().x());
687 gradient->setAttributeFocalY(rgr->focalPoint().y());
688 gradient->setAttributeRadius(rgr->radius());
689 } else if (type == QGradient::ConicalGradient) {
690 auto cgr = static_cast<const QConicalGradient *>(gr);
691 gradient->setAttributeCentralX(cgr->center().x());
692 gradient->setAttributeCentralY(cgr->center().y());
693 gradient->setAttributeAngle(cgr->angle());
694 }
695
696 brush->setElementGradient(gradient);
697 } else if (style == Qt::TexturePattern) {
698 const QPixmap pixmap = br.texture();
699 if (!pixmap.isNull()) {
700 DomProperty *p = new DomProperty;
701 QFormBuilderExtra::setPixmapProperty(p, {});
702 brush->setElementTexture(p);
703 }
704 } else {
705 const QColor &c = br.color();
706 DomColor *color = new DomColor();
707 color->setElementRed(c.red());
708 color->setElementGreen(c.green());
709 color->setElementBlue(c.blue());
710 color->setAttributeAlpha(c.alpha());
711 brush->setElementColor(color);
712 }
713 return brush;
714}
715
716DomProperty *QFormBuilderExtra::propertyByName(const QList<DomProperty*> &properties,
717 QAnyStringView needle)
718{
719 auto it = std::find_if(properties.cbegin(), properties.cend(),
720 [needle](const DomProperty *p) {
721 return p->attributeName() == needle; });
722 return it != properties.cend() ? *it : nullptr;
723}
724
725// ------------ QFormBuilderStrings
726
727QFormBuilderStrings::QFormBuilderStrings() :
728 itemRoles {
729 {Qt::FontRole, "font"_L1},
730 {Qt::TextAlignmentRole, "textAlignment"_L1},
731 {Qt::BackgroundRole, "background"_L1},
732 {Qt::ForegroundRole, "foreground"_L1},
733 {Qt::CheckStateRole, "checkState"_L1}
734 },
735 itemTextRoles { // This must be first for the loop below
736 { {Qt::EditRole, Qt::DisplayPropertyRole}, textAttribute},
737 { {Qt::ToolTipRole, Qt::ToolTipPropertyRole}, toolTipAttribute},
738 { {Qt::StatusTipRole, Qt::StatusTipPropertyRole}, "statusTip"_L1},
739 { {Qt::WhatsThisRole, Qt::WhatsThisPropertyRole}, whatsThisAttribute}
740 }
741{
742 for (const RoleNName &it : std::as_const(itemRoles))
743 treeItemRoleHash.insert(it.second, it.first);
744
745 // Note: this skips the first item!
746 auto it = itemTextRoles.constBegin();
747 const auto end = itemTextRoles.constEnd();
748 while (++it != end)
749 treeItemTextRoleHash.insert(it->second, it->first);
750}
751
752const QFormBuilderStrings &QFormBuilderStrings::instance()
753{
754 static const QFormBuilderStrings rc;
755 return rc;
756}
757
758#ifdef QFORMINTERNAL_NAMESPACE
759} // namespace QFormInternal
760#endif
761
762QT_END_NAMESPACE
static QString msgInvalidMinimumSize(const QString &objectName, const QString &ms)
void clearPerCellValue(Layout *l, int count, void(Layout::*setter)(int, int), int value=0)
bool parsePerCellProperty(Layout *l, int count, void(Layout::*setter)(int, int), const QString &s, int defaultValue=0)
static QString msgInvalidStretch(const QString &objectName, const QString &stretch)
QString perCellPropertyToString(const Layout *l, int count, int(Layout::*getter)(int) const)
static bool readUiAttributes(QXmlStreamReader &reader, const QString &language, QString *errorMessage)
void uiLibWarning(const QString &message)
static QString msgXmlError(const QXmlStreamReader &reader)
Combined button and popup list for selecting options.
const QString & asString(const QString &s)
Definition qstring.h:1661
#define qPrintable(string)
Definition qstring.h:1666