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 // QTBUG-96693: Because the same form can be instantiated on multiple
178 // widgets, when for example using a form for custom widgets, there can
179 // exist multiple widgets with the same buddy name in the window. Since
180 // the buddy closest to the label is the correct one to use, we search
181 // for the buddy bottom-up rather than top-down.
182 QWidgetList widgets;
183 QWidget *parent = label->parentWidget();
184 while (parent && widgets.isEmpty()) {
185 widgets = parent->findChildren<QWidget*>(buddyName);
186 parent = parent->parentWidget();
187 }
188
189 if (widgets.isEmpty()) {
190 label->setBuddy(nullptr);
191 return false;
192 }
193
194 for (auto *w : widgets) {
195 if (applyMode == BuddyApplyAll || !w->isHidden()) {
196 label->setBuddy(w);
197 return true;
198 }
199 }
200
201 label->setBuddy(nullptr);
202 return false;
203}
204
205const QPointer<QWidget> &QFormBuilderExtra::parentWidget() const
206{
207 return m_parentWidget;
208}
209
210bool QFormBuilderExtra::parentWidgetIsSet() const
211{
212 return m_parentWidgetIsSet;
213}
214
215void QFormBuilderExtra::setParentWidget(const QPointer<QWidget> &w)
216{
217 // Parent widget requires special handling of the geometry property.
218 m_parentWidget = w;
219 m_parentWidgetIsSet = true;
220}
221
222void QFormBuilderExtra::storeCustomWidgetData(const QString &className, const DomCustomWidget *d)
223{
224 if (d)
225 m_customWidgetDataHash.insert(className, CustomWidgetData(d));
226}
227
228QString QFormBuilderExtra::customWidgetBaseClass(const QString &className) const
229{
230 const auto it = m_customWidgetDataHash.constFind(className);
231 if (it != m_customWidgetDataHash.constEnd())
232 return it.value().baseClass;
233 return QString();
234}
235
236QString QFormBuilderExtra::customWidgetAddPageMethod(const QString &className) const
237{
238 const auto it = m_customWidgetDataHash.constFind(className);
239 if (it != m_customWidgetDataHash.constEnd())
240 return it.value().addPageMethod;
241 return QString();
242}
243
244bool QFormBuilderExtra::isCustomWidgetContainer(const QString &className) const
245{
246 const auto it = m_customWidgetDataHash.constFind(className);
247 if (it != m_customWidgetDataHash.constEnd())
248 return it.value().isContainer;
249 return false;
250}
251
252void QFormBuilderExtra::setProcessingLayoutWidget(bool processing)
253{
254 m_layoutWidget = processing;
255}
256
257 bool QFormBuilderExtra::processingLayoutWidget() const
258{
259 return m_layoutWidget;
260}
261void QFormBuilderExtra::setResourceBuilder(QResourceBuilder *builder)
262{
263 if (m_resourceBuilder == builder)
264 return;
265 clearResourceBuilder();
266 m_resourceBuilder = builder;
267}
268
269QResourceBuilder *QFormBuilderExtra::resourceBuilder() const
270{
271 return m_resourceBuilder;
272}
273
274void QFormBuilderExtra::clearResourceBuilder()
275{
276 if (m_resourceBuilder) {
277 delete m_resourceBuilder;
278 m_resourceBuilder = nullptr;
279 }
280}
281
282void QFormBuilderExtra::setTextBuilder(QTextBuilder *builder)
283{
284 if (m_textBuilder == builder)
285 return;
286 clearTextBuilder();
287 m_textBuilder = builder;
288}
289
290QTextBuilder *QFormBuilderExtra::textBuilder() const
291{
292 return m_textBuilder;
293}
294
295void QFormBuilderExtra::clearTextBuilder()
296{
297 if (m_textBuilder) {
298 delete m_textBuilder;
299 m_textBuilder = nullptr;
300 }
301}
302
303void QFormBuilderExtra::registerButtonGroups(const DomButtonGroups *domGroups)
304{
305 const auto &domGroupList = domGroups->elementButtonGroup();
306 for (DomButtonGroup *domGroup : domGroupList)
307 m_buttonGroups.insert(domGroup->attributeName(), ButtonGroupEntry(domGroup, nullptr));
308}
309
310// Utilities for parsing per-cell integer properties that have setters and
311// getters of the form 'setX(int idx, int value)' and 'x(int index)'
312// (converting them to comma-separated string lists and back).
313// Used for layout stretch and grid per-row/column properties.
314
315// Format a list of cell-properties of one dimension as a ','-separated list
316template <class Layout>
317inline QString perCellPropertyToString(const Layout *l, int count, int (Layout::*getter)(int) const)
318{
319 if (count == 0)
320 return QString();
321 QString rc;
322 {
323 QTextStream str(&rc);
324 for (int i = 0; i < count; i++) {
325 if (i)
326 str << ',';
327 str << (l->*getter)(i);
328 }
329 }
330 return rc;
331}
332
333// Clear the property, set all cells to 0
334
335template <class Layout>
336inline void clearPerCellValue(Layout *l, int count, void (Layout::*setter)(int,int), int value = 0)
337{
338 for (int i = 0; i < count; i++)
339 (l->*setter)(i, value);
340}
341
342// Parse and set the property from a comma-separated list
343
344template <class Layout>
345inline bool parsePerCellProperty(Layout *l, int count, void (Layout::*setter)(int,int), const QString &s, int defaultValue = 0)
346{
347 if (s.isEmpty()) {
348 clearPerCellValue(l, count, setter, defaultValue);
349 return true;
350 }
351 const auto list = QStringView{s}.split(u',');
352 if (list.isEmpty()) {
353 clearPerCellValue(l, count, setter, defaultValue);
354 return true;
355 }
356 // Apply all values contained in list
357 const int ac = qMin(count, list.size());
358 bool ok;
359 int i = 0;
360 for ( ; i < ac; i++) {
361 const int value = list.at(i).toInt(&ok);
362 if (!ok || value < 0)
363 return false;
364 (l->*setter)(i, value);
365 }
366 // Clear rest
367 for ( ; i < count; i++)
368 (l->*setter)(i, defaultValue);
369 return true;
370}
371
372// Read and write stretch
373static QString msgInvalidStretch(const QString &objectName, const QString &stretch)
374{
375 //: Parsing layout stretch values
376 return QCoreApplication::translate("FormBuilder", "Invalid stretch value for '%1': '%2'").arg(objectName, stretch);
377}
378
379void QFormBuilderExtra::getLayoutMargins(const QList<DomProperty*> &properties,
380 int *left, int *top, int *right, int *bottom)
381{
382 if (const auto *p = propertyByName(properties, "leftMargin"))
383 *left = p->elementNumber();
384 if (const auto *p = propertyByName(properties, "topMargin"))
385 *top = p->elementNumber();
386 if (const auto *p = propertyByName(properties, "rightMargin"))
387 *right = p->elementNumber();
388 if (const auto *p = propertyByName(properties, "bottomMargin"))
389 *bottom = p->elementNumber();
390}
391
392bool QFormBuilderExtra::isQFontComboBox(const QWidget *w)
393{
394#if QT_CONFIG(fontcombobox)
395 return qobject_cast<const QFontComboBox*>(w) != nullptr;
396#else
397 Q_UNUSED(w);
398 return false;
399#endif
400}
401
402QString QFormBuilderExtra::boxLayoutStretch(const QBoxLayout *box)
403{
404 return perCellPropertyToString(box, box->count(), &QBoxLayout::stretch);
405}
406
407bool QFormBuilderExtra::setBoxLayoutStretch(const QString &s, QBoxLayout *box)
408{
409 const bool rc = parsePerCellProperty(box, box->count(), &QBoxLayout::setStretch, s);
410 if (!rc)
411 uiLibWarning(msgInvalidStretch(box->objectName(), s));
412 return rc;
413}
414
415void QFormBuilderExtra::clearBoxLayoutStretch(QBoxLayout *box)
416{
417 clearPerCellValue(box, box->count(), &QBoxLayout::setStretch);
418}
419
420QString QFormBuilderExtra::gridLayoutRowStretch(const QGridLayout *grid)
421{
422 return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowStretch);
423}
424
425bool QFormBuilderExtra::setGridLayoutRowStretch(const QString &s, QGridLayout *grid)
426{
427 const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowStretch, s);
428 if (!rc)
429 uiLibWarning(msgInvalidStretch(grid->objectName(), s));
430 return rc;
431}
432
433void QFormBuilderExtra::clearGridLayoutRowStretch(QGridLayout *grid)
434{
435 clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowStretch);
436}
437
438QString QFormBuilderExtra::gridLayoutColumnStretch(const QGridLayout *grid)
439{
440 return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnStretch);
441}
442
443bool QFormBuilderExtra::setGridLayoutColumnStretch(const QString &s, QGridLayout *grid)
444{
445 const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnStretch, s);
446 if (!rc)
447 uiLibWarning(msgInvalidStretch(grid->objectName(), s));
448 return rc;
449}
450
451void QFormBuilderExtra::clearGridLayoutColumnStretch(QGridLayout *grid)
452{
453 clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnStretch);
454}
455
456// Read and write grid layout row/column size limits
457
458static QString msgInvalidMinimumSize(const QString &objectName, const QString &ms)
459{
460 //: Parsing grid layout minimum size values
461 return QCoreApplication::translate("FormBuilder", "Invalid minimum size for '%1': '%2'").arg(objectName, ms);
462}
463
464QString QFormBuilderExtra::gridLayoutRowMinimumHeight(const QGridLayout *grid)
465{
466 return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowMinimumHeight);
467}
468
469bool QFormBuilderExtra::setGridLayoutRowMinimumHeight(const QString &s, QGridLayout *grid)
470{
471 const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight, s);
472 if (!rc)
473 uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
474 return rc;
475}
476
477void QFormBuilderExtra::clearGridLayoutRowMinimumHeight(QGridLayout *grid)
478{
479 clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight);
480}
481
482QString QFormBuilderExtra::gridLayoutColumnMinimumWidth(const QGridLayout *grid)
483{
484 return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnMinimumWidth);
485}
486
487bool QFormBuilderExtra::setGridLayoutColumnMinimumWidth(const QString &s, QGridLayout *grid)
488{
489 const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth, s);
490 if (!rc)
491 uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
492 return rc;
493}
494
495void QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(QGridLayout *grid)
496{
497 clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth);
498}
499
500void QFormBuilderExtra::setPixmapProperty(DomProperty *p, const std::pair<QString, QString> &ip)
501{
502 DomResourcePixmap *pix = new DomResourcePixmap;
503 if (!ip.second.isEmpty())
504 pix->setAttributeResource(ip.second);
505
506 pix->setText(ip.first);
507
508 p->setAttributeName("pixmap"_L1);
509 p->setElementPixmap(pix);
510}
511
512void QFormBuilderExtra::setupColorGroup(QPalette *palette, QPalette::ColorGroup colorGroup,
513 const DomColorGroup *group)
514{
515 // old format
516 const auto &colors = group->elementColor();
517 for (int role = 0; role < colors.size(); ++role) {
518 const DomColor *color = colors.at(role);
519 const QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
520 palette->setColor(colorGroup, QPalette::ColorRole(role), c);
521 }
522
523 // new format
524 const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
525
526 const auto colorRoles = group->elementColorRole();
527 for (const DomColorRole *colorRole : colorRoles) {
528 if (colorRole->hasAttributeRole()) {
529 const int r = colorRole_enum.keyToValue(colorRole->attributeRole().toLatin1());
530 if (r != -1) {
531 const QBrush br = setupBrush(colorRole->elementBrush());
532 palette->setBrush(colorGroup, static_cast<QPalette::ColorRole>(r), br);
533 }
534 }
535 }
536}
537
538DomColorGroup *QFormBuilderExtra::saveColorGroup(const QPalette &palette,
539 QPalette::ColorGroup colorGroup)
540{
541
542 const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
543
544 DomColorGroup *group = new DomColorGroup();
545 QList<DomColorRole *> colorRoles;
546
547 for (int r = QPalette::WindowText; r < QPalette::NColorRoles; ++r) {
548 const auto role = static_cast<QPalette::ColorRole>(r);
549 if (palette.isBrushSet(colorGroup, role)) {
550 const QBrush &br = palette.brush(colorGroup, role);
551 DomColorRole *colorRole = new DomColorRole();
552 colorRole->setElementBrush(saveBrush(br));
553 colorRole->setAttributeRole(QLatin1StringView(colorRole_enum.valueToKey(role)));
554 colorRoles.append(colorRole);
555 }
556 }
557
558 group->setElementColorRole(colorRoles);
559 return group;
560}
561
562DomPalette *QFormBuilderExtra::savePalette(const QPalette &palette)
563{
564 DomPalette *dom = new DomPalette();
565 dom->setElementActive(QFormBuilderExtra::saveColorGroup(palette, QPalette::Active));
566 dom->setElementInactive(QFormBuilderExtra::saveColorGroup(palette, QPalette::Inactive));
567 dom->setElementDisabled(QFormBuilderExtra::saveColorGroup(palette, QPalette::Disabled));
568
569 return dom;
570}
571
572QPalette QFormBuilderExtra::loadPalette(const DomPalette *dom)
573{
574 QPalette palette;
575
576 if (dom->elementActive())
577 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Active, dom->elementActive());
578
579 if (dom->elementInactive())
580 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Inactive, dom->elementInactive());
581
582 if (dom->elementDisabled())
583 QFormBuilderExtra::setupColorGroup(&palette, QPalette::Disabled, dom->elementDisabled());
584
585 palette.setCurrentColorGroup(QPalette::Active);
586 return palette;
587}
588
589QBrush QFormBuilderExtra::setupBrush(const DomBrush *brush)
590{
591 QBrush br;
592 if (!brush->hasAttributeBrushStyle())
593 return br;
594
595 const Qt::BrushStyle style = enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::BrushStyle>("brushStyle",
596 brush->attributeBrushStyle().toLatin1().constData());
597
598 if (style == Qt::LinearGradientPattern ||
599 style == Qt::RadialGradientPattern ||
600 style == Qt::ConicalGradientPattern) {
601 const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
602 const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
603 const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
604
605 const DomGradient *gradient = brush->elementGradient();
606 const QGradient::Type type = enumKeyToValue<QGradient::Type>(gradientType_enum, gradient->attributeType().toLatin1());
607
608
609 QGradient *gr = nullptr;
610
611 if (type == QGradient::LinearGradient) {
612 gr = new QLinearGradient(QPointF(gradient->attributeStartX(), gradient->attributeStartY()),
613 QPointF(gradient->attributeEndX(), gradient->attributeEndY()));
614 } else if (type == QGradient::RadialGradient) {
615 gr = new QRadialGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
616 gradient->attributeRadius(),
617 QPointF(gradient->attributeFocalX(), gradient->attributeFocalY()));
618 } else if (type == QGradient::ConicalGradient) {
619 gr = new QConicalGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
620 gradient->attributeAngle());
621 }
622 if (!gr)
623 return br;
624
625 const QGradient::Spread spread = enumKeyToValue<QGradient::Spread>(gradientSpread_enum, gradient->attributeSpread().toLatin1());
626 gr->setSpread(spread);
627
628 const QGradient::CoordinateMode coord = enumKeyToValue<QGradient::CoordinateMode>(gradientCoordinate_enum, gradient->attributeCoordinateMode().toLatin1());
629 gr->setCoordinateMode(coord);
630
631 const auto &stops = gradient->elementGradientStop();
632 for (const DomGradientStop *stop : stops) {
633 const DomColor *color = stop->elementColor();
634 gr->setColorAt(stop->attributePosition(), QColor::fromRgb(color->elementRed(),
635 color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
636 }
637 br = QBrush(*gr);
638 delete gr;
639 } else if (style == Qt::TexturePattern) {
640 const DomProperty *texture = brush->elementTexture();
641 if (texture && texture->kind() == DomProperty::Pixmap) {
642 br.setTexture({});
643 }
644 } else {
645 const DomColor *color = brush->elementColor();
646 br.setColor(QColor::fromRgb(color->elementRed(),
647 color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
648 br.setStyle((Qt::BrushStyle)style);
649 }
650 return br;
651}
652
653DomBrush *QFormBuilderExtra::saveBrush(const QBrush &br)
654{
655 const QMetaEnum brushStyle_enum = metaEnum<QAbstractFormBuilderGadget>("brushStyle");
656
657 DomBrush *brush = new DomBrush();
658 const Qt::BrushStyle style = br.style();
659 brush->setAttributeBrushStyle(QLatin1StringView(brushStyle_enum.valueToKey(style)));
660 if (style == Qt::LinearGradientPattern ||
661 style == Qt::RadialGradientPattern ||
662 style == Qt::ConicalGradientPattern) {
663 const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
664 const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
665 const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
666
667 DomGradient *gradient = new DomGradient();
668 const QGradient *gr = br.gradient();
669 const QGradient::Type type = gr->type();
670 gradient->setAttributeType(QLatin1StringView(gradientType_enum.valueToKey(type)));
671 gradient->setAttributeSpread(QLatin1StringView(gradientSpread_enum.valueToKey(gr->spread())));
672 gradient->setAttributeCoordinateMode(QLatin1StringView(gradientCoordinate_enum.valueToKey(gr->coordinateMode())));
673 QList<DomGradientStop *> stops;
674 const QGradientStops st = gr->stops();
675 for (const QGradientStop &pair : st) {
676 DomGradientStop *stop = new DomGradientStop();
677 stop->setAttributePosition(pair.first);
678 DomColor *color = new DomColor();
679 color->setElementRed(pair.second.red());
680 color->setElementGreen(pair.second.green());
681 color->setElementBlue(pair.second.blue());
682 color->setAttributeAlpha(pair.second.alpha());
683 stop->setElementColor(color);
684 stops.append(stop);
685 }
686 gradient->setElementGradientStop(stops);
687 if (type == QGradient::LinearGradient) {
688 auto lgr = static_cast<const QLinearGradient *>(gr);
689 gradient->setAttributeStartX(lgr->start().x());
690 gradient->setAttributeStartY(lgr->start().y());
691 gradient->setAttributeEndX(lgr->finalStop().x());
692 gradient->setAttributeEndY(lgr->finalStop().y());
693 } else if (type == QGradient::RadialGradient) {
694 auto rgr = static_cast<const QRadialGradient *>(gr);
695 gradient->setAttributeCentralX(rgr->center().x());
696 gradient->setAttributeCentralY(rgr->center().y());
697 gradient->setAttributeFocalX(rgr->focalPoint().x());
698 gradient->setAttributeFocalY(rgr->focalPoint().y());
699 gradient->setAttributeRadius(rgr->radius());
700 } else if (type == QGradient::ConicalGradient) {
701 auto cgr = static_cast<const QConicalGradient *>(gr);
702 gradient->setAttributeCentralX(cgr->center().x());
703 gradient->setAttributeCentralY(cgr->center().y());
704 gradient->setAttributeAngle(cgr->angle());
705 }
706
707 brush->setElementGradient(gradient);
708 } else if (style == Qt::TexturePattern) {
709 const QPixmap pixmap = br.texture();
710 if (!pixmap.isNull()) {
711 DomProperty *p = new DomProperty;
712 QFormBuilderExtra::setPixmapProperty(p, {});
713 brush->setElementTexture(p);
714 }
715 } else {
716 const QColor &c = br.color();
717 DomColor *color = new DomColor();
718 color->setElementRed(c.red());
719 color->setElementGreen(c.green());
720 color->setElementBlue(c.blue());
721 color->setAttributeAlpha(c.alpha());
722 brush->setElementColor(color);
723 }
724 return brush;
725}
726
727DomProperty *QFormBuilderExtra::propertyByName(const QList<DomProperty*> &properties,
728 QAnyStringView needle)
729{
730 auto it = std::find_if(properties.cbegin(), properties.cend(),
731 [needle](const DomProperty *p) {
732 return p->attributeName() == needle; });
733 return it != properties.cend() ? *it : nullptr;
734}
735
736// ------------ QFormBuilderStrings
737
738QFormBuilderStrings::QFormBuilderStrings() :
739 itemRoles {
740 {Qt::FontRole, "font"_L1},
741 {Qt::TextAlignmentRole, "textAlignment"_L1},
742 {Qt::BackgroundRole, "background"_L1},
743 {Qt::ForegroundRole, "foreground"_L1},
744 {Qt::CheckStateRole, "checkState"_L1}
745 },
746 itemTextRoles { // This must be first for the loop below
747 { {Qt::EditRole, Qt::DisplayPropertyRole}, textAttribute},
748 { {Qt::ToolTipRole, Qt::ToolTipPropertyRole}, toolTipAttribute},
749 { {Qt::StatusTipRole, Qt::StatusTipPropertyRole}, "statusTip"_L1},
750 { {Qt::WhatsThisRole, Qt::WhatsThisPropertyRole}, whatsThisAttribute}
751 }
752{
753 for (const RoleNName &it : std::as_const(itemRoles))
754 treeItemRoleHash.insert(it.second, it.first);
755
756 // Note: this skips the first item!
757 auto it = itemTextRoles.constBegin();
758 const auto end = itemTextRoles.constEnd();
759 while (++it != end)
760 treeItemTextRoleHash.insert(it->second, it->first);
761}
762
763const QFormBuilderStrings &QFormBuilderStrings::instance()
764{
765 static const QFormBuilderStrings rc;
766 return rc;
767}
768
769#ifdef QFORMINTERNAL_NAMESPACE
770} // namespace QFormInternal
771#endif
772
773QT_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)
const QString & asString(const QString &s)
Definition qstring.h:1680
#define qPrintable(string)
Definition qstring.h:1685