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 | |
71 | QT_BEGIN_NAMESPACE |
72 | |
73 | #ifdef QFORMINTERNAL_NAMESPACE |
74 | namespace QFormInternal { |
75 | #endif |
76 | |
77 | void uiLibWarning(const QString &message) { |
78 | qWarning(msg: "Designer: %s" , qPrintable(message)); |
79 | } |
80 | |
81 | |
82 | QFormBuilderExtra::CustomWidgetData::() = default; |
83 | |
84 | QFormBuilderExtra::CustomWidgetData::(const DomCustomWidget *dcw) : |
85 | addPageMethod(dcw->elementAddPageMethod()), |
86 | baseClass(dcw->elementExtends()), |
87 | isContainer(dcw->hasElementContainer() && dcw->elementContainer() != 0) |
88 | { |
89 | } |
90 | |
91 | QFormBuilderExtra::() : |
92 | m_defaultMargin(INT_MIN), |
93 | m_defaultSpacing(INT_MIN), |
94 | m_language(QStringLiteral("c++" )) |
95 | { |
96 | } |
97 | |
98 | QFormBuilderExtra::() |
99 | { |
100 | clearResourceBuilder(); |
101 | clearTextBuilder(); |
102 | } |
103 | |
104 | void QFormBuilderExtra::() |
105 | { |
106 | m_buddies.clear(); |
107 | m_parentWidget = nullptr; |
108 | m_parentWidgetIsSet = false; |
109 | m_customWidgetDataHash.clear(); |
110 | m_buttonGroups.clear(); |
111 | } |
112 | |
113 | static 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>. |
123 | static 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 | |
173 | DomUI *QFormBuilderExtra::(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 | |
192 | QString QFormBuilderExtra::() |
193 | { |
194 | return QCoreApplication::translate(context: "QAbstractFormBuilder" , key: "Invalid UI file" ); |
195 | } |
196 | |
197 | bool QFormBuilderExtra::(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 | |
208 | void QFormBuilderExtra::() 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 | |
218 | bool QFormBuilderExtra::(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 | |
243 | const QPointer<QWidget> &QFormBuilderExtra::() const |
244 | { |
245 | return m_parentWidget; |
246 | } |
247 | |
248 | bool QFormBuilderExtra::() const |
249 | { |
250 | return m_parentWidgetIsSet; |
251 | } |
252 | |
253 | void QFormBuilderExtra::(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 | |
260 | void QFormBuilderExtra::(const QString &className, const DomCustomWidget *d) |
261 | { |
262 | if (d) |
263 | m_customWidgetDataHash.insert(akey: className, avalue: CustomWidgetData(d)); |
264 | } |
265 | |
266 | QString QFormBuilderExtra::(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 | |
274 | QString QFormBuilderExtra::(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 | |
282 | bool QFormBuilderExtra::(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 | |
290 | void QFormBuilderExtra::(bool processing) |
291 | { |
292 | m_layoutWidget = processing; |
293 | } |
294 | |
295 | bool QFormBuilderExtra::() const |
296 | { |
297 | return m_layoutWidget; |
298 | } |
299 | void QFormBuilderExtra::(QResourceBuilder *builder) |
300 | { |
301 | if (m_resourceBuilder == builder) |
302 | return; |
303 | clearResourceBuilder(); |
304 | m_resourceBuilder = builder; |
305 | } |
306 | |
307 | QResourceBuilder *QFormBuilderExtra::() const |
308 | { |
309 | return m_resourceBuilder; |
310 | } |
311 | |
312 | void QFormBuilderExtra::() |
313 | { |
314 | if (m_resourceBuilder) { |
315 | delete m_resourceBuilder; |
316 | m_resourceBuilder = nullptr; |
317 | } |
318 | } |
319 | |
320 | void QFormBuilderExtra::(QTextBuilder *builder) |
321 | { |
322 | if (m_textBuilder == builder) |
323 | return; |
324 | clearTextBuilder(); |
325 | m_textBuilder = builder; |
326 | } |
327 | |
328 | QTextBuilder *QFormBuilderExtra::() const |
329 | { |
330 | return m_textBuilder; |
331 | } |
332 | |
333 | void QFormBuilderExtra::() |
334 | { |
335 | if (m_textBuilder) { |
336 | delete m_textBuilder; |
337 | m_textBuilder = nullptr; |
338 | } |
339 | } |
340 | |
341 | void QFormBuilderExtra::(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 |
354 | template <class Layout> |
355 | inline 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 | |
373 | template <class Layout> |
374 | inline 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 | |
382 | template <class Layout> |
383 | inline 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 |
411 | static 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 | |
417 | QString QFormBuilderExtra::(const QBoxLayout *box) |
418 | { |
419 | return perCellPropertyToString(l: box, count: box->count(), getter: &QBoxLayout::stretch); |
420 | } |
421 | |
422 | bool QFormBuilderExtra::(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 | |
430 | void QFormBuilderExtra::(QBoxLayout *box) |
431 | { |
432 | clearPerCellValue(l: box, count: box->count(), setter: &QBoxLayout::setStretch); |
433 | } |
434 | |
435 | QString QFormBuilderExtra::(const QGridLayout *grid) |
436 | { |
437 | return perCellPropertyToString(l: grid, count: grid->rowCount(), getter: &QGridLayout::rowStretch); |
438 | } |
439 | |
440 | bool QFormBuilderExtra::(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 | |
448 | void QFormBuilderExtra::(QGridLayout *grid) |
449 | { |
450 | clearPerCellValue(l: grid, count: grid->rowCount(), setter: &QGridLayout::setRowStretch); |
451 | } |
452 | |
453 | QString QFormBuilderExtra::gridLayoutColumnStretch(const QGridLayout *grid) |
454 | { |
455 | return perCellPropertyToString(l: grid, count: grid->columnCount(), getter: &QGridLayout::columnStretch); |
456 | } |
457 | |
458 | bool 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 | |
466 | void 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 | |
473 | static 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 | |
479 | QString QFormBuilderExtra::(const QGridLayout *grid) |
480 | { |
481 | return perCellPropertyToString(l: grid, count: grid->rowCount(), getter: &QGridLayout::rowMinimumHeight); |
482 | } |
483 | |
484 | bool QFormBuilderExtra::(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 | |
492 | void QFormBuilderExtra::(QGridLayout *grid) |
493 | { |
494 | clearPerCellValue(l: grid, count: grid->rowCount(), setter: &QGridLayout::setRowMinimumHeight); |
495 | } |
496 | |
497 | QString QFormBuilderExtra::gridLayoutColumnMinimumWidth(const QGridLayout *grid) |
498 | { |
499 | return perCellPropertyToString(l: grid, count: grid->columnCount(), getter: &QGridLayout::columnMinimumWidth); |
500 | } |
501 | |
502 | bool 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 | |
510 | void QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(QGridLayout *grid) |
511 | { |
512 | clearPerCellValue(l: grid, count: grid->columnCount(), setter: &QGridLayout::setColumnMinimumWidth); |
513 | } |
514 | |
515 | void QFormBuilderExtra::(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 | |
527 | void QFormBuilderExtra::(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 | |
553 | DomColorGroup *QFormBuilderExtra::(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 | |
578 | DomPalette *QFormBuilderExtra::(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 | |
588 | QPalette QFormBuilderExtra::(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 | |
605 | QBrush QFormBuilderExtra::(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 | |
669 | DomBrush *QFormBuilderExtra::(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 | |
745 | QFormBuilderStrings::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 | |
813 | const QFormBuilderStrings &QFormBuilderStrings::instance() |
814 | { |
815 | static const QFormBuilderStrings rc; |
816 | return rc; |
817 | } |
818 | |
819 | #ifdef QFORMINTERNAL_NAMESPACE |
820 | } // namespace QFormInternal |
821 | #endif |
822 | |
823 | QT_END_NAMESPACE |
824 | |