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

source code of qttools/src/designer/src/lib/uilib/formbuilderextra.cpp