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