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
abstractformbuilder.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
8#include "ui4_p.h"
9#include "properties_p.h"
10
11#include <QtWidgets/qmainwindow.h>
12#include <QtWidgets/qmenu.h>
13#include <QtWidgets/qmenubar.h>
14#include <QtWidgets/qstatusbar.h>
15#include <QtWidgets/qtoolbar.h>
16#include <QtWidgets/qmdiarea.h>
17#include <QtWidgets/qdockwidget.h>
18#include <QtWidgets/qwizard.h>
19#include <QtWidgets/qstackedwidget.h>
20#include <QtWidgets/qtoolbox.h>
21#include <QtWidgets/qtabwidget.h>
22#include <QtWidgets/qsplitter.h>
23#include <QtWidgets/qbuttongroup.h>
24#include <QtWidgets/qboxlayout.h>
25#include <QtWidgets/qformlayout.h>
26#include <QtWidgets/qgridlayout.h>
27#include <QtWidgets/qscrollarea.h>
28#include <QtWidgets/qtreewidget.h>
29#include <QtWidgets/qlistwidget.h>
30#include <QtWidgets/qheaderview.h>
31#include <QtWidgets/qtablewidget.h>
32#include <QtWidgets/qfontcombobox.h>
33#include <QtWidgets/qpushbutton.h>
34#ifndef QFORMINTERNAL_NAMESPACE
35# include <private/qlayout_p.h> // Compiling within Designer
36#endif
37
38#include <QtGui/qaction.h>
39#include <QtGui/qactiongroup.h>
40
41#include <QtCore/qcoreapplication.h>
42#include <QtCore/qdebug.h>
43#include <QtCore/qdir.h>
44#include <QtCore/qfileinfo.h>
45#include <QtCore/qhash.h>
46#include <QtCore/qmetaobject.h>
47#include <QtCore/qpair.h>
48#include <QtCore/qqueue.h>
49#include <QtCore/qvariant.h>
50#include <QtCore/qxmlstream.h>
51
52#include <limits.h>
53
54#include <algorithm>
55#include <iterator>
56
57Q_DECLARE_METATYPE(QWidgetList)
58
59QT_BEGIN_NAMESPACE
60
61using namespace Qt::StringLiterals;
62
63static constexpr auto buttonGroupPropertyC = "buttonGroup"_L1;
64
65#ifdef QFORMINTERNAL_NAMESPACE
66using namespace QFormInternal;
67#endif
68
69using QFBE = QFormBuilderExtra;
70
71static inline DomProperty *currentIndexProperty(const QList<DomProperty*> &properties)
72{
73 return QFBE::propertyByName(properties, "currentIndex");
74}
75
77{
78public:
79 inline QFriendlyLayout() { Q_ASSERT(0); }
80
81#ifdef QFORMINTERNAL_NAMESPACE
83#else
84 friend class QAbstractFormBuilder;
85#endif
86};
87
88/*!
89 \class QAbstractFormBuilder
90
91 \brief The QAbstractFormBuilder class provides a default
92 implementation for classes that create user interfaces at
93 run-time.
94
95 \inmodule QtDesigner
96
97 QAbstractFormBuilder provides a standard interface and a default
98 implementation for constructing forms from user interface
99 files. It is not intended to be instantiated directly. Use the
100 QFormBuilder class to create user interfaces from UI files at
101 run-time. For example:
102
103 \snippet lib/tools_designer_src_lib_uilib_formbuilder.cpp 0
104
105 To override certain aspects of the form builder's behavior,
106 subclass QAbstractFormBuilder and reimplement the relevant virtual
107 functions:
108
109 \list
110 \li load() handles reading of UI format files from arbitrary
111 QIODevices, and construction of widgets from the XML data
112 that they contain.
113 \li save() handles saving of widget details in UI format to
114 arbitrary QIODevices.
115 \li workingDirectory() and setWorkingDirectory() control the
116 directory in which forms are held. The form builder looks for
117 other resources on paths relative to this directory.
118 \endlist
119
120 The QFormBuilder class is typically used by custom components and
121 applications that embed \QD. Standalone applications that need to
122 dynamically generate user interfaces at run-time use the
123 QUiLoader, found in the \l{Qt UI Tools} module.
124
125 \sa {Qt UI Tools}
126*/
127
128/*!
129 Constructs a new form builder.*/
130QAbstractFormBuilder::QAbstractFormBuilder() : d(new QFormBuilderExtra)
131{
132 setResourceBuilder(new QResourceBuilder());
133 setTextBuilder(new QTextBuilder());
134}
135
136/*!
137 Destroys the form builder.*/
138QAbstractFormBuilder::~QAbstractFormBuilder() = default;
139
140/*!
141 \fn QWidget *QAbstractFormBuilder::load(QIODevice *device, QWidget *parent)
142
143 Loads an XML representation of a widget from the given \a device,
144 and constructs a new widget with the specified \a parent.
145
146 \sa save(), errorString()
147*/
148QWidget *QAbstractFormBuilder::load(QIODevice *dev, QWidget *parentWidget)
149{
150 QScopedPointer<DomUI> ui(d->readUi(dev));
151 if (ui.isNull())
152 return nullptr;
153 QWidget *widget = create(ui.data(), parentWidget);
154 if (!widget && d->m_errorString.isEmpty())
155 d->m_errorString = QFormBuilderExtra::msgInvalidUiFile();
156 return widget;
157}
158
159/*!
160 \internal
161*/
162QWidget *QAbstractFormBuilder::create(DomUI *ui, QWidget *parentWidget)
163{
164 d->clear();
165 if (const DomLayoutDefault *def = ui->elementLayoutDefault()) {
166 d->m_defaultMargin = def->hasAttributeMargin() ? def->attributeMargin() : INT_MIN;
167 d->m_defaultSpacing = def->hasAttributeSpacing() ? def->attributeSpacing() : INT_MIN;
169
170 DomWidget *ui_widget = ui->elementWidget();
171 if (!ui_widget)
172 return nullptr;
173
174 initialize(ui);
175
176 if (const DomButtonGroups *domButtonGroups = ui->elementButtonGroups())
177 d->registerButtonGroups(domButtonGroups);
178
179 if (QWidget *widget = create(ui_widget, parentWidget)) {
180 // Reparent button groups that were actually created to main container for them to be found in the signal/slot part
181 for (const auto &bg : std::as_const(d->buttonGroups())) {
182 if (bg.second)
183 bg.second->setParent(widget);
184 }
185 createConnections(ui->elementConnections(), widget);
186 createResources(ui->elementResources()); // maybe this should go first, before create()...
187 applyTabStops(widget, ui->elementTabStops());
188 d->applyInternalProperties();
189 reset();
190 d->clear();
191 return widget;
192 }
193 d->clear();
194 return nullptr;
195}
196
197/*!
198 \internal
199 Retrieve relevant information from the custom widgets section.
200 Called by create(DomUI *, QWidget *); call manually if you
201 just use create(DomWidget *, QWidget *) on some child widget of DomUI.
202 */
203
204void QAbstractFormBuilder::initialize(const DomUI *ui)
205{
206 DomCustomWidgets *domCustomWidgets = ui->elementCustomWidgets();
207 createCustomWidgets(domCustomWidgets);
208
209 if (domCustomWidgets) {
210 const auto &customWidgets = domCustomWidgets->elementCustomWidget();
211 for (const DomCustomWidget *w : customWidgets)
212 d->storeCustomWidgetData(w->elementClass(), w);
213 }
214}
215
216/*!
217 \internal
218*/
219QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidget)
220{
221 QWidget *w = createWidget(ui_widget->attributeClass(), parentWidget, ui_widget->attributeName());
222 if (!w)
223 return nullptr;
224
225 applyProperties(w, ui_widget->elementProperty());
226
227 const auto &elementAction = ui_widget->elementAction();
228 for (DomAction *ui_action : elementAction) {
229 QAction *child_action = create(ui_action, w);
230 Q_UNUSED( child_action );
231 }
232
233 const auto &elementActionGroup = ui_widget->elementActionGroup();
234 for (DomActionGroup *ui_action_group : elementActionGroup) {
235 QActionGroup *child_action_group = create(ui_action_group, w);
236 Q_UNUSED( child_action_group );
237 }
238
239 QWidgetList children;
240 const auto &elementWidget = ui_widget->elementWidget();
241 for (DomWidget *ui_child : elementWidget) {
242 if (QWidget *child = create(ui_child, w)) {
243 children += child;
244 } else {
245 const QString className = ui_child->elementClass().value(0);
246 uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "The creation of a widget of the class '%1' failed.").arg(className));
247 }
248 }
249
250 const auto &elementLayout = ui_widget->elementLayout();
251 for (DomLayout *ui_lay : elementLayout) {
252 QLayout *child_lay = create(ui_lay, nullptr, w);
253 Q_UNUSED( child_lay );
254 }
255
256 const auto &addActions = ui_widget->elementAddAction();
257 if (!addActions.isEmpty()) {
258 for (DomActionRef *ui_action_ref : addActions) {
259 const QString name = ui_action_ref->attributeName();
260 if (name == "separator"_L1) {
261 QAction *sep = new QAction(w);
262 sep->setSeparator(true);
263 w->addAction(sep);
264 addMenuAction(sep);
265 } else if (QAction *a = d->m_actions.value(name)) {
266 w->addAction(a);
267 } else if (QActionGroup *g = d->m_actionGroups.value(name)) {
268 w->addActions(g->actions());
269 } else if (QMenu *menu = w->findChild<QMenu*>(name)) {
270 w->addAction(menu->menuAction());
271 addMenuAction(menu->menuAction());
272 }
273 }
274 }
275
276 loadExtraInfo(ui_widget, w, parentWidget);
277 addItem(ui_widget, w, parentWidget);
278
279 if (qobject_cast<QDialog *>(w) && parentWidget)
280 w->setAttribute(Qt::WA_Moved, false); // So that QDialog::setVisible(true) will center it
281
282 const QStringList zOrderNames = ui_widget->elementZOrder();
283 if (!zOrderNames.isEmpty()) {
284 QWidgetList zOrder = qvariant_cast<QWidgetList>(w->property("_q_zOrder"));
285 for (const QString &widgetName : zOrderNames) {
286 if (QWidget *child = w->findChild<QWidget*>(widgetName)) {
287 if (child->parentWidget() == w) {
288 zOrder.removeAll(child);
289 zOrder.append(child);
290 child->raise();
291 }
292 }
293 }
294 w->setProperty("_q_zOrder", QVariant::fromValue(zOrder));
295 }
296
297 return w;
298}
299
300/*!
301 \internal
302*/
303QAction *QAbstractFormBuilder::create(DomAction *ui_action, QObject *parent)
304{
305 QAction *a = createAction(parent, ui_action->attributeName());
306 if (!a)
307 return nullptr;
308
309 d->m_actions.insert(ui_action->attributeName(), a);
310 applyProperties(a, ui_action->elementProperty());
311 return a;
312}
313
314/*!
315 \internal
316*/
317QActionGroup *QAbstractFormBuilder::create(DomActionGroup *ui_action_group, QObject *parent)
318{
319 QActionGroup *a = createActionGroup(parent, ui_action_group->attributeName());
320 if (!a)
321 return nullptr;
322 d->m_actionGroups.insert(ui_action_group->attributeName(), a);
323 applyProperties(a, ui_action_group->elementProperty());
324
325 const auto &elementAction = ui_action_group->elementAction();
326 for (DomAction *ui_action : elementAction) {
327 QAction *child_action = create(ui_action, a);
328 Q_UNUSED( child_action );
329 }
330
331 const auto &elementActionGroup = ui_action_group->elementActionGroup();
332 for (DomActionGroup *g : elementActionGroup) {
333 QActionGroup *child_action_group = create(g, parent);
334 Q_UNUSED( child_action_group );
335 }
336
337 return a;
338}
339
340// figure out the toolbar area of a DOM attrib list.
341// By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value.
342Qt::ToolBarArea QAbstractFormBuilder::toolbarAreaFromDOMAttributes(const DomPropertyHash &attributes)
343{
344 const DomProperty *attr = attributes.value("toolBarArea"_L1);
345 if (!attr)
346 return Qt::TopToolBarArea;
347 switch(attr->kind()) {
348 case DomProperty::Number:
349 return static_cast<Qt::ToolBarArea>(attr->elementNumber());
350 case DomProperty::Enum:
351 return enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::ToolBarArea>("toolBarArea",
352 attr->elementEnum().toLatin1().constData());
353 default:
354 break;
355 }
356 return Qt::TopToolBarArea;
357}
358
359/*!
360 \internal
361*/
362bool QAbstractFormBuilder::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
363{
364 const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
365
366 if (parentWidget == nullptr)
367 return true;
368 // Check special cases. First: Custom container
369 const QString className = QLatin1StringView(parentWidget->metaObject()->className());
370 const QString addPageMethod = d->customWidgetAddPageMethod(className);
371 if (!addPageMethod.isEmpty()) {
372 // If this fails ( non-existent or non-slot), use ContainerExtension in Designer, else it can't be helped
373 return QMetaObject::invokeMethod(parentWidget, addPageMethod.toUtf8().constData(), Qt::DirectConnection, Q_ARG(QWidget*, widget));
374 }
375
376 if (QMainWindow *mw = qobject_cast<QMainWindow*>(parentWidget)) {
377
378#if QT_CONFIG(menubar)
379 // the menubar
380 if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) {
381 mw->setMenuBar(menuBar);
382 return true;
383 }
384#endif
385
386#if QT_CONFIG(toolbar)
387 // apply the toolbar's attributes
388 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
389 mw->addToolBar(toolbarAreaFromDOMAttributes(attributes), toolBar);
390 // check break
391 if (const DomProperty *attr = attributes.value("toolBarBreak"_L1))
392 if (attr->elementBool() == "true"_L1)
393 mw->insertToolBarBreak (toolBar);
394
395 return true;
396 }
397#endif
398
399#if QT_CONFIG(statusbar)
400 // statusBar
401 if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) {
402 mw->setStatusBar(statusBar);
403 return true;
404 }
405#endif
406
407#if QT_CONFIG(dockwidget)
408 // apply the dockwidget's attributes
409 if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) {
410 if (const DomProperty *attr = attributes.value("dockWidgetArea"_L1)) {
411 Qt::DockWidgetArea area = static_cast<Qt::DockWidgetArea>(attr->elementNumber());
412 if (!dockWidget->isAreaAllowed(area)) {
413 if (dockWidget->isAreaAllowed(Qt::LeftDockWidgetArea))
414 area = Qt::LeftDockWidgetArea;
415 else if (dockWidget->isAreaAllowed(Qt::RightDockWidgetArea))
416 area = Qt::RightDockWidgetArea;
417 else if (dockWidget->isAreaAllowed(Qt::TopDockWidgetArea))
418 area = Qt::TopDockWidgetArea;
419 else if (dockWidget->isAreaAllowed(Qt::BottomDockWidgetArea))
420 area = Qt::BottomDockWidgetArea;
421 }
422 mw->addDockWidget(area, dockWidget);
423 } else {
424 mw->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
425 }
426 return true;
427 }
428#endif
429
430 if (!mw->centralWidget()) {
431 mw->setCentralWidget(widget);
432 return true;
433 }
434 }
435
436#if QT_CONFIG(tabwidget)
437 else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) {
438 widget->setParent(nullptr);
439
440 const int tabIndex = tabWidget->count();
441 if (auto *titleP = attributes.value(QFormBuilderStrings::titleAttribute))
442 tabWidget->addTab(widget, toString(titleP->elementString()));
443 else
444 tabWidget->addTab(widget, "Page"_L1);
445
446 if (const auto *picon = attributes.value(QFormBuilderStrings::iconAttribute)) {
447 QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
448 QVariant nativeValue = resourceBuilder()->toNativeValue(v);
449 tabWidget->setTabIcon(tabIndex, qvariant_cast<QIcon>(nativeValue));
450 }
451
452#if QT_CONFIG(tooltip)
453 if (const auto *ptoolTip = attributes.value(QFormBuilderStrings::toolTipAttribute)) {
454 tabWidget->setTabToolTip(tabIndex, toString(ptoolTip->elementString()));
455 }
456#endif
457
458#if QT_CONFIG(whatsthis)
459 if (const auto *pwhatsThis = attributes.value(QFormBuilderStrings::whatsThisAttribute)) {
460 tabWidget->setTabWhatsThis(tabIndex, toString(pwhatsThis->elementString()));
461 }
462#endif
463
464 return true;
465 }
466#endif
467
468#if QT_CONFIG(toolbox)
469 else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) {
470 const int tabIndex = toolBox->count();
471 if (const auto *labelP = attributes.value(QFormBuilderStrings::labelAttribute))
472 toolBox->addItem(widget, toString(labelP->elementString()));
473 else
474 toolBox->addItem(widget, "Page"_L1);
475
476 if (const auto *picon = attributes.value(QFormBuilderStrings::iconAttribute)) {
477 QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
478 QVariant nativeValue = resourceBuilder()->toNativeValue(v);
479 toolBox->setItemIcon(tabIndex, qvariant_cast<QIcon>(nativeValue));
480 }
481
482#if QT_CONFIG(tooltip)
483 if (const auto *ptoolTip = attributes.value(QFormBuilderStrings::toolTipAttribute)) {
484 toolBox->setItemToolTip(tabIndex, toString(ptoolTip->elementString()));
485 }
486#endif
487
488 return true;
489 }
490#endif
491
492#if QT_CONFIG(stackedwidget)
493 else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(parentWidget)) {
494 stackedWidget->addWidget(widget);
495 return true;
496 }
497#endif
498
499#if QT_CONFIG(splitter)
500 else if (QSplitter *splitter = qobject_cast<QSplitter*>(parentWidget)) {
501 splitter->addWidget(widget);
502 return true;
503 }
504#endif
505
506#if QT_CONFIG(mdiarea)
507 else if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(parentWidget)) {
508 mdiArea->addSubWindow(widget);
509 return true;
510 }
511#endif
512
513#if QT_CONFIG(dockwidget)
514 else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(parentWidget)) {
515 dockWidget->setWidget(widget);
516 return true;
517 }
518#endif
519
520#if QT_CONFIG(scrollarea)
521 else if (QScrollArea *scrollArea = qobject_cast<QScrollArea*>(parentWidget)) {
522 scrollArea->setWidget(widget);
523 return true;
524 }
525#endif
526
527#if QT_CONFIG(wizard)
528 else if (QWizard *wizard = qobject_cast<QWizard *>(parentWidget)) {
529 QWizardPage *page = qobject_cast<QWizardPage*>(widget);
530 if (!page) {
531 uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Attempt to add child that is not of class QWizardPage to QWizard."));
532 return false;
533 }
534 wizard->addPage(page);
535 return true;
536 }
537#endif
538 return false;
539}
540
541/*!
542 \internal
543*/
544void QAbstractFormBuilder::layoutInfo(DomLayout *ui_layout, QObject *parent, int *margin, int *spacing)
545{
546 Q_UNUSED(parent);
547 auto properties = ui_layout->elementProperty();
548
549 int mar = INT_MIN;
550 int spac = INT_MIN;
551 if (const DomProperty *p = QFBE::propertyByName(properties, "margin"))
552 mar = p->elementNumber();
553 if (const DomProperty *p = QFBE::propertyByName(properties, "spacing"))
554 spac = p->elementNumber();
555
556#ifdef Q_OS_MACOS
557 // here we recognize UI file < 4.3 (no we don't store margin property)
558 if (mar != INT_MIN) {
559 const int defaultMargin = parent->inherits("QLayoutWidget") ? 0 : 9;
560 if (mar == defaultMargin)
561 mar = INT_MIN;
562 if (spac == 6)
563 spac = INT_MIN;
564
565 if (mar == INT_MIN || spac == INT_MIN) {
566 for (auto it = properties.begin(); it != properties.end(); ) {
567 DomProperty *prop = *it;
568 if ((mar == INT_MIN && prop->attributeName() == "margin"_L1)
569 || (spac == INT_MIN && prop->attributeName() == "spacing"_L1)) {
570 delete prop;
571 it = properties.erase(it);
572 } else {
573 ++it;
574 }
575 }
576 ui_layout->setElementProperty(properties);
577 }
578 }
579#endif
580 if (margin)
581 *margin = mar;
582 if (spacing)
583 *spacing = spac;
584}
585
586/*!
587 \internal
588*/
589QLayout *QAbstractFormBuilder::create(DomLayout *ui_layout, QLayout *parentLayout, QWidget *parentWidget)
590{
591 QObject *p = parentLayout;
592
593 if (p == nullptr)
594 p = parentWidget;
595
596 Q_ASSERT(p != nullptr);
597
598 bool tracking = false;
599
600 if (p == parentWidget && parentWidget->layout()) {
601 tracking = true;
602 p = parentWidget->layout();
603 }
604
605 QLayout *layout = createLayout(ui_layout->attributeClass(), p, ui_layout->hasAttributeName() ? ui_layout->attributeName() : QString());
606
607 if (layout == nullptr)
608 return 0;
609
610 if (tracking && layout->parent() == nullptr) {
611 QBoxLayout *box = qobject_cast<QBoxLayout*>(parentWidget->layout());
612 if (!box) { // only QBoxLayout is supported
613 const QString widgetClass = QString::fromUtf8(parentWidget->metaObject()->className());
614 const QString layoutClass = QString::fromUtf8(parentWidget->layout()->metaObject()->className());
615 const QString msg = QCoreApplication::translate("QAbstractFormBuilder", "Attempt to add a layout to a widget '%1' (%2) which already has a layout of non-box type %3.\n"
616 "This indicates an inconsistency in the ui-file.").
617 arg(parentWidget->objectName(), widgetClass, layoutClass);
618 uiLibWarning(msg);
619 return nullptr;
620 }
621 box->addLayout(layout);
622 }
623
624 int margin = INT_MIN, spacing = INT_MIN;
625 layoutInfo(ui_layout, p, &margin, &spacing);
626
627 if (margin != INT_MIN) {
628 layout->setContentsMargins(margin, margin, margin, margin);
629 } else {
630 int left = -1, top = -1, right = -1, bottom = -1;
631 layout->getContentsMargins(&left, &top, &right, &bottom);
632 QFormBuilderExtra::getLayoutMargins(ui_layout->elementProperty(),
633 &left, &top, &right, &bottom);
634 layout->setContentsMargins(left, top, right, bottom);
635 }
636
637 if (spacing != INT_MIN) {
638 layout->setSpacing(spacing);
639 } else {
640 QGridLayout *grid = qobject_cast<QGridLayout *>(layout);
641 if (grid) {
642 const auto &properties = ui_layout->elementProperty();
643 if (const auto *p = QFBE::propertyByName(properties, "horizontalSpacing"))
644 grid->setHorizontalSpacing(p->elementNumber());
645 if (const auto *p = QFBE::propertyByName(properties, "verticalSpacing"))
646 grid->setVerticalSpacing(p->elementNumber());
647 }
648 }
649
650 applyProperties(layout, ui_layout->elementProperty());
651
652 const auto &elementItem = ui_layout->elementItem();
653 for (DomLayoutItem *ui_item : elementItem) {
654 if (QLayoutItem *item = create(ui_item, layout, parentWidget)) {
655 addItem(ui_item, item, layout);
656 }
657 }
658 // Check the box stretch attributes
659 if (QBoxLayout *box = qobject_cast<QBoxLayout*>(layout)) {
660 const QString boxStretch = ui_layout->attributeStretch();
661 if (!boxStretch.isEmpty())
662 QFormBuilderExtra::setBoxLayoutStretch(boxStretch, box);
663 }
664 // Check the grid stretch/minimum size attributes
665 if (QGridLayout *grid = qobject_cast<QGridLayout*>(layout)) {
666 // Stretch
667 const QString gridRowStretch = ui_layout->attributeRowStretch();
668 if (!gridRowStretch.isEmpty())
669 QFormBuilderExtra::setGridLayoutRowStretch(gridRowStretch, grid);
670 const QString gridColumnStretch = ui_layout->attributeColumnStretch();
671 if (!gridColumnStretch.isEmpty())
672 QFormBuilderExtra::setGridLayoutColumnStretch(gridColumnStretch, grid);
673 // Minimum size
674 const QString gridColumnMinimumWidth = ui_layout->attributeColumnMinimumWidth();
675 if (!gridColumnMinimumWidth.isEmpty())
676 QFormBuilderExtra::setGridLayoutColumnMinimumWidth(gridColumnMinimumWidth, grid);
677 const QString gridRowMinimumHeight = ui_layout->attributeRowMinimumHeight();
678 if (!gridRowMinimumHeight.isEmpty())
679 QFormBuilderExtra::setGridLayoutRowMinimumHeight(gridRowMinimumHeight, grid);
680 }
681 return layout;
682}
683
684#if QT_CONFIG(formlayout)
685static inline QFormLayout::ItemRole formLayoutRole(int column, int colspan)
686{
687 if (colspan > 1)
688 return QFormLayout::SpanningRole;
689 return column == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
690}
691#endif
692
693static inline QString alignmentPrefix(bool fullyQualifiedEnums)
694{
695 return fullyQualifiedEnums ? "Qt::AlignmentFlag::"_L1 : "Qt::"_L1;
696}
697
698static inline QString alignmentValue(Qt::Alignment a, bool fullyQualifiedEnums)
699{
700 QLatin1StringView h;
701 QLatin1StringView v;
702 switch (a & Qt::AlignHorizontal_Mask) {
703 case Qt::AlignLeft:
704 h = "AlignLeft"_L1;
705 break;
706 case Qt::AlignRight:
707 h = "AlignRight"_L1;
708 break;
709 case Qt::AlignHCenter:
710 h = "AlignHCenter"_L1;
711 break;
712 case Qt::AlignJustify:
713 h = "AlignJustify"_L1;
714 break;
715 }
716 switch (a & Qt::AlignVertical_Mask) {
717 case Qt::AlignTop:
718 v = "AlignTop"_L1;
719 break;
720 case Qt::AlignBottom:
721 v = "AlignBottom"_L1;
722 break;
723 case Qt::AlignVCenter:
724 v = "AlignVCenter"_L1;
725 break;
726 }
727 QString result;
728 if (h.isEmpty())
729 result += alignmentPrefix(fullyQualifiedEnums) + h;
730 if (!h.isEmpty() && !v.isEmpty())
731 result += u'|';
732 if (!v.isEmpty())
733 result += alignmentPrefix(fullyQualifiedEnums) + v;
734 return result;
735}
736
737static inline Qt::Alignment alignmentFromDom(const QString &in)
738{
739 Qt::Alignment rc;
740 if (!in.isEmpty()) {
741 for (const auto &f : qTokenize(in, u'|')) {
742 if (f.endsWith("::AlignLeft"_L1)) {
743 rc |= Qt::AlignLeft;
744 } else if (f.endsWith("::AlignRight"_L1)) {
745 rc |= Qt::AlignRight;
746 } else if (f.endsWith("::AlignHCenter"_L1)) {
747 rc |= Qt::AlignHCenter;
748 } else if (f.endsWith("::AlignJustify"_L1)) {
749 rc |= Qt::AlignJustify;
750 } else if (f.endsWith("::AlignTop"_L1)) {
751 rc |= Qt::AlignTop;
752 } else if (f.endsWith("::AlignBottom"_L1)) {
753 rc |= Qt::AlignBottom;
754 } else if (f.endsWith("::AlignVCenter"_L1)) {
755 rc |= Qt::AlignVCenter;
756 }
757 }
758 }
759 return rc;
760}
761
762/*!
763 \internal
764*/
765bool QAbstractFormBuilder::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout)
766{
767 // Calling addChildWidget(), etc. is required to maintain consistency of the layouts,
768 // see documentation of addItem(), which should ideally not be used.
769 if (item->widget()) {
770 static_cast<QFriendlyLayout*>(layout)->addChildWidget(item->widget());
771 } else if (item->layout()) {
772 static_cast<QFriendlyLayout*>(layout)->addChildLayout(item->layout());
773 } else if (item->spacerItem()) {
774 // nothing to do
775 } else {
776 return false;
777 }
778
779 if (QGridLayout *grid = qobject_cast<QGridLayout*>(layout)) {
780 const int rowSpan = ui_item->hasAttributeRowSpan() ? ui_item->attributeRowSpan() : 1;
781 const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1;
782 grid->addItem(item, ui_item->attributeRow(), ui_item->attributeColumn(),
783 rowSpan, colSpan, item->alignment());
784 return true;
785 }
786#if QT_CONFIG(formlayout)
787 if (QFormLayout *form = qobject_cast<QFormLayout *>(layout)) {
788 const int row = ui_item->attributeRow();
789 const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1;
790 form->setItem(row, formLayoutRole(ui_item->attributeColumn(), colSpan), item);
791 return true;
792 }
793
794#endif
795 layout->addItem(item);
796 return true;
797}
798
799/*!
800 \internal
801*/
802QLayoutItem *QAbstractFormBuilder::create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget)
803{
804 switch (ui_layoutItem->kind()) {
805 case DomLayoutItem::Widget: {
806 if (QWidget *w = create(ui_layoutItem->elementWidget(), parentWidget)) {
807#ifdef QFORMINTERNAL_NAMESPACE // uilib
808 QWidgetItem *item = new QWidgetItemV2(w);
809#else // Within Designer: Use factory method that returns special items that refuse to shrink to 0,0
810 QWidgetItem *item = QLayoutPrivate::createWidgetItem(layout, w);
811#endif
812 item->setAlignment(alignmentFromDom(ui_layoutItem->attributeAlignment()));
813 return item;
814 }
815 qWarning() << QCoreApplication::translate("QAbstractFormBuilder", "Empty widget item in %1 '%2'.").arg(QString::fromUtf8(layout->metaObject()->className()), layout->objectName());
816 return nullptr;
817 }
818 case DomLayoutItem::Spacer: {
819 QSize size(0, 0);
820 QSizePolicy::Policy sizeType = QSizePolicy::Expanding;
821 bool isVspacer = false;
822
823 const DomSpacer *ui_spacer = ui_layoutItem->elementSpacer();
824 const auto &spacerProperties = ui_spacer->elementProperty();
825 if (!spacerProperties.isEmpty()) {
826 for (DomProperty *p : spacerProperties) {
827 const QVariant v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p); // ### remove me
828 if (v.isNull())
829 continue;
830 if (p->attributeName() == "sizeHint"_L1 && p->kind() == DomProperty::Size) {
831 size = v.toSize(); // ### remove me
832 } else if (p->attributeName() == "sizeType"_L1 && p->kind() == DomProperty::Enum) {
833 sizeType = static_cast<QSizePolicy::Policy>(v.toInt());
834 } else if (p->attributeName() == "orientation"_L1 && p->kind() == DomProperty::Enum) {
835 const Qt::Orientation o = static_cast<Qt::Orientation>(v.toInt());
836 isVspacer = (o == Qt::Vertical);
837 }
838 }
839 }
840
841 QSpacerItem *spacer = nullptr;
842 if (isVspacer)
843 spacer = new QSpacerItem(size.width(), size.height(), QSizePolicy::Minimum, sizeType);
844 else
845 spacer = new QSpacerItem(size.width(), size.height(), sizeType, QSizePolicy::Minimum);
846 return spacer; }
847
848 case DomLayoutItem::Layout:
849 return create(ui_layoutItem->elementLayout(), layout, parentWidget);
850
851 default:
852 break;
853 }
854
855 return nullptr;
856}
857
858/*!
859 \internal
860*/
861void QAbstractFormBuilder::applyProperties(QObject *o, const QList<DomProperty*> &properties)
862{
863 for (DomProperty *p : properties) {
864 const QVariant v = toVariant(o->metaObject(), p);
865 if (!v.isNull()) {
866 QString attributeName = p->attributeName();
867 if (attributeName == "numDigits"_L1 && o->inherits("QLCDNumber")) // Deprecated in Qt 4, removed in Qt 5.
868 attributeName = u"digitCount"_s;
869 if (!d->applyPropertyInternally(o, attributeName, v))
870 o->setProperty(attributeName.toUtf8(), v);
871 }
872 }
873}
874
875
876/*!
877 \internal
878 Check whether a property is applied internally by QAbstractFormBuilder. Call this
879 from overwritten applyProperties().
880*/
881
882bool QAbstractFormBuilder::applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value)
883{
884 return d->applyPropertyInternally(o,propertyName, value);
885}
886
887/*!
888 \internal
889*/
890
891QVariant QAbstractFormBuilder::toVariant(const QMetaObject *meta, DomProperty *p)
892{
893 return domPropertyToVariant(this, meta, p);
894}
895
896/*!
897 \internal
898*/
899void QAbstractFormBuilder::setupColorGroup(QPalette &palette, QPalette::ColorGroup colorGroup,
900 DomColorGroup *group)
901{
902 QFormBuilderExtra::setupColorGroup(&palette, colorGroup, group);
903}
904
905/*!
906 \internal
907*/
908DomColorGroup *QAbstractFormBuilder::saveColorGroup(const QPalette &palette)
909{
910 return QFormBuilderExtra::saveColorGroup(palette,
911 palette.currentColorGroup());
912}
913
914/*!
915 \internal
916*/
917QBrush QAbstractFormBuilder::setupBrush(DomBrush *brush)
918{
919 return QFormBuilderExtra::setupBrush(brush);
920}
921
922DomBrush *QAbstractFormBuilder::saveBrush(const QBrush &br)
923{
924 return QFormBuilderExtra::saveBrush(br);
925}
926
927/*!
928 \internal
929*/
930QWidget *QAbstractFormBuilder::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
931{
932 Q_UNUSED(widgetName);
933 Q_UNUSED(parentWidget);
934 Q_UNUSED(name);
935 return nullptr;
936}
937
938/*!
939 \internal
940*/
941QLayout *QAbstractFormBuilder::createLayout(const QString &layoutName, QObject *parent, const QString &name)
942{
943 Q_UNUSED(layoutName);
944 Q_UNUSED(parent);
945 Q_UNUSED(name);
946 return nullptr;
947}
948
949/*!
950 \internal
951*/
952QAction *QAbstractFormBuilder::createAction(QObject *parent, const QString &name)
953{
954 QAction *action = new QAction(parent);
955 action->setObjectName(name);
956 return action;
957}
958
959/*!
960 \internal
961*/
962QActionGroup *QAbstractFormBuilder::createActionGroup(QObject *parent, const QString &name)
963{
964 QActionGroup *g = new QActionGroup(parent);
965 g->setObjectName(name);
966 return g;
967}
968
969/*!
970 \fn void QAbstractFormBuilder::save(QIODevice *device, QWidget *widget)
971
972 Saves an XML representation of the given \a widget to the
973 specified \a device in the standard UI file format.
974
975 \note Unlike when saving a form in \QD, all property values are
976 written. This is because, the state of whether a property value was
977 modified or not isn't stored in the Qt property system. The widget that
978 is being saved, could have been created dynamically, not loaded via
979 \l load(), so in this case the form builder isn't aware of the list of
980 changed properties. Also, there's no generic way to do this for widgets
981 that were created dynamically.
982
983 Therefore, you should remove properties that are not required from your
984 resulting XML files, before loading them. Alternatively, if you already
985 know which properties you want to save when you call this method,
986 you can overload \c computeProperties() and return a filtered list of
987 required properties. Otherwise, unexpected behavior may occur as some
988 of these properties may depend on each other.
989
990 \sa load()
991*/
992void QAbstractFormBuilder::save(QIODevice *dev, QWidget *widget)
993{
994 DomWidget *ui_widget = createDom(widget, nullptr);
995 Q_ASSERT( ui_widget != nullptr );
996
997 DomUI *ui = new DomUI();
998 ui->setAttributeVersion(u"4.0"_s);
999 ui->setElementWidget(ui_widget);
1000
1001 saveDom(ui, widget);
1002
1003 QXmlStreamWriter writer(dev);
1004 writer.setAutoFormatting(true);
1005 writer.setAutoFormattingIndent(1);
1006 writer.writeStartDocument();
1007 ui->write(writer);
1008 writer.writeEndDocument();
1009
1010 d->m_laidout.clear();
1011
1012 delete ui;
1013}
1014
1015/*!
1016 \internal
1017*/
1018void QAbstractFormBuilder::saveDom(DomUI *ui, QWidget *widget)
1019{
1020 ui->setElementClass(widget->objectName());
1021
1022 if (DomConnections *ui_connections = saveConnections()) {
1023 ui->setElementConnections(ui_connections);
1024 }
1025
1026 if (DomCustomWidgets *ui_customWidgets = saveCustomWidgets()) {
1027 ui->setElementCustomWidgets(ui_customWidgets);
1028 }
1029
1030 if (DomTabStops *ui_tabStops = saveTabStops()) {
1031 ui->setElementTabStops(ui_tabStops);
1032 }
1033
1034 if (DomResources *ui_resources = saveResources()) {
1035 ui->setElementResources(ui_resources);
1036 }
1037 if (DomButtonGroups *ui_buttonGroups = saveButtonGroups(widget))
1038 ui->setElementButtonGroups(ui_buttonGroups);
1039}
1040
1041/*!
1042 \internal
1043*/
1044DomConnections *QAbstractFormBuilder::saveConnections()
1045{
1046 return new DomConnections;
1047}
1048
1049/*!
1050 \internal
1051*/
1052
1053DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive)
1054{
1055 DomWidget *ui_widget = new DomWidget();
1056 ui_widget->setAttributeClass(QLatin1StringView(widget->metaObject()->className()));
1057 ui_widget->setAttributeName(widget->objectName());
1058
1059 ui_widget->setElementProperty(computeProperties(widget));
1060
1061 if (recursive) {
1062 if (QLayout *layout = widget->layout()) {
1063 if (DomLayout *ui_layout = createDom(layout, nullptr, ui_parentWidget)) {
1064 QList<DomLayout *> ui_layouts;
1065 ui_layouts.append(ui_layout);
1066
1067 ui_widget->setElementLayout(ui_layouts);
1068 }
1069 }
1070 }
1071
1072 // widgets, actions and action groups
1073 QList<DomWidget *> ui_widgets;
1074 QList<DomAction *> ui_actions;
1075 QList<DomActionGroup *> ui_action_groups;
1076
1077 QObjectList children;
1078
1079 // splitters need to store their children in the order specified by child indexes,
1080 // not the order of the child list.
1081#if QT_CONFIG(splitter)
1082 if (const QSplitter *splitter = qobject_cast<const QSplitter*>(widget)) {
1083 const int count = splitter->count();
1084 for (int i = 0; i < count; ++i)
1085 children.append(splitter->widget(i));
1086 } else
1087#endif
1088 {
1089 QObjectList childObjects = widget->children();
1090
1091 const QWidgetList list = qvariant_cast<QWidgetList>(widget->property("_q_widgetOrder"));
1092 for (QWidget *w : list) {
1093 if (childObjects.contains(w)) {
1094 children.append(w);
1095 childObjects.removeAll(w);
1096 }
1097 }
1098 children += childObjects;
1099
1100 const QWidgetList zOrder = qvariant_cast<QWidgetList>(widget->property("_q_zOrder"));
1101 if (list != zOrder) {
1102 QStringList zOrderList;
1103 zOrderList.reserve(zOrder.size());
1104 std::transform(zOrder.cbegin(), zOrder.cend(),
1105 std::back_inserter(zOrderList),
1106 [] (const QWidget *w) { return w->objectName(); });
1107 ui_widget->setElementZOrder(zOrderList);
1108 }
1109 }
1110
1111 for (QObject *obj : std::as_const(children)) {
1112 if (QWidget *childWidget = qobject_cast<QWidget*>(obj)) {
1113 if (d->m_laidout.contains(childWidget) || !recursive)
1114 continue;
1115
1116 if (QMenu *menu = qobject_cast<QMenu *>(childWidget)) {
1117 const auto actions = menu->parentWidget()->actions();
1118 const bool found =
1119 std::any_of(actions.cbegin(), actions.cend(),
1120 [menu] (const QAction *a) { return a->menu() == menu; });
1121 if (!found)
1122 continue;
1123 }
1124
1125 if (DomWidget *ui_child = createDom(childWidget, ui_widget)) {
1126 ui_widgets.append(ui_child);
1127 }
1128 } else if (QAction *childAction = qobject_cast<QAction*>(obj)) {
1129 if (childAction->actionGroup() != nullptr) {
1130 // it will be added later.
1131 continue;
1132 }
1133
1134 if (DomAction *ui_action = createDom(childAction)) {
1135 ui_actions.append(ui_action);
1136 }
1137 } else if (QActionGroup *childActionGroup = qobject_cast<QActionGroup*>(obj)) {
1138 if (DomActionGroup *ui_action_group = createDom(childActionGroup)) {
1139 ui_action_groups.append(ui_action_group);
1140 }
1141 }
1142 }
1143
1144 // add-action
1145 QList<DomActionRef *> ui_action_refs;
1146 const auto &actions = widget->actions();
1147 ui_action_refs.reserve(actions.size());
1148 for (QAction *action : actions) {
1149 if (DomActionRef *ui_action_ref = createActionRefDom(action)) {
1150 ui_action_refs.append(ui_action_ref);
1151 }
1152 }
1153
1154 if (recursive)
1155 ui_widget->setElementWidget(ui_widgets);
1156
1157 ui_widget->setElementAction(ui_actions);
1158 ui_widget->setElementActionGroup(ui_action_groups);
1159 ui_widget->setElementAddAction(ui_action_refs);
1160
1161 saveExtraInfo(widget, ui_widget, ui_parentWidget);
1162
1163 return ui_widget;
1164}
1165
1166/*!
1167 \internal
1168*/
1169DomActionRef *QAbstractFormBuilder::createActionRefDom(QAction *action)
1170{
1171 DomActionRef *ui_action_ref = new DomActionRef();
1172 if (action->isSeparator()) {
1173 ui_action_ref->setAttributeName("separator"_L1);
1174 } else {
1175 ui_action_ref->setAttributeName(action->menu() != nullptr
1176 ? action->menu()->objectName()
1177 : action->objectName());
1178 }
1179
1180 return ui_action_ref;
1181}
1182
1183// Struct to store layout item parameters for saving layout items
1185 explicit FormBuilderSaveLayoutEntry(QLayoutItem *li = nullptr) :
1186 item(li) {}
1187
1188 void setAlignment(Qt::Alignment al);
1189
1190 QLayoutItem *item;
1191 int row = -1;
1192 int column = -1;
1193 int rowSpan = 0;
1194 int columnSpan = 0;
1196};
1197
1198// filter out the case of "Spacer" and "QLayoutWidget" widgets
1200{
1201 if (const QWidget *widget = item->widget()) {
1202 const char *className = widget->metaObject()->className();
1203 if (qstrcmp(className, "Spacer") && qstrcmp(className, "QLayoutWidget"))
1204 alignment = al;
1205 }
1206}
1207
1208// Create list from standard box layout
1210{
1212 if (const int count = layout->count()) {
1213 rc.reserve(count);
1214 for (int idx = 0; idx < count; ++idx) {
1215 QLayoutItem *item = layout->itemAt(idx);
1217 entry.setAlignment(item->alignment());
1218 rc.append(entry);
1219 }
1220 }
1221 return rc;
1222}
1223
1224// Create list from grid layout
1226{
1228 if (const int count = gridLayout->count()) {
1229 rc.reserve(count);
1230 for (int idx = 0; idx < count; ++idx) {
1231 QLayoutItem *item = gridLayout->itemAt(idx);
1233 gridLayout->getItemPosition(idx, &entry.row, &entry.column, &entry.rowSpan,&entry.columnSpan);
1234 entry.setAlignment(item->alignment());
1235 rc.append(entry);
1236 }
1237 }
1238 return rc;
1239}
1240
1241#if QT_CONFIG(formlayout)
1242// Create list from form layout
1243static QList<FormBuilderSaveLayoutEntry> saveFormLayoutEntries(const QFormLayout *formLayout)
1244{
1245 QList<FormBuilderSaveLayoutEntry> rc;
1246 if (const int count = formLayout->count()) {
1247 rc.reserve(count);
1248 for (int idx = 0; idx < count; ++idx) {
1249 QLayoutItem *item = formLayout->itemAt(idx);
1250 QFormLayout::ItemRole role = QFormLayout::LabelRole;
1251 FormBuilderSaveLayoutEntry entry(item);
1252 formLayout->getItemPosition(idx, &entry.row, &role);
1253 switch (role ) {
1254 case QFormLayout::LabelRole:
1255 entry.column = 0;
1256 break;
1257 case QFormLayout::FieldRole:
1258 entry.column = 1;
1259 break;
1260 case QFormLayout::SpanningRole:
1261 entry.column = 0;
1262 entry.columnSpan = 2;
1263 break;
1264 }
1265 rc.push_back(entry);
1266 }
1267 }
1268 return rc;
1269}
1270#endif
1271
1272/*!
1273 \internal
1274*/
1275
1276DomLayout *QAbstractFormBuilder::createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget)
1277{
1278 Q_UNUSED(ui_layout);
1279 DomLayout *lay = new DomLayout();
1280 lay->setAttributeClass(QLatin1StringView(layout->metaObject()->className()));
1281 const QString objectName = layout->objectName();
1282 if (!objectName.isEmpty())
1283 lay->setAttributeName(objectName);
1284 lay->setElementProperty(computeProperties(layout));
1285
1286 QList<FormBuilderSaveLayoutEntry> newList;
1287 if (QGridLayout *gridLayout = qobject_cast<QGridLayout *>(layout)) {
1288 newList = saveGridLayoutEntries(gridLayout);
1289#if QT_CONFIG(formlayout)
1290 } else if (const QFormLayout *formLayout = qobject_cast<const QFormLayout *>(layout)) {
1291 newList = saveFormLayoutEntries(formLayout);
1292#endif
1293 } else {
1294 newList = saveLayoutEntries(layout);
1295 }
1296
1297 QList<DomLayoutItem *> ui_items;
1298 ui_items.reserve(newList.size());
1299 for (const FormBuilderSaveLayoutEntry &item : std::as_const(newList)) {
1300 if (DomLayoutItem *ui_item = createDom(item.item, lay, ui_parentWidget)) {
1301 if (item.row >= 0)
1302 ui_item->setAttributeRow(item.row);
1303 if (item.column >= 0)
1304 ui_item->setAttributeColumn(item.column);
1305 if (item.rowSpan > 1)
1306 ui_item->setAttributeRowSpan(item.rowSpan);
1307 if (item.columnSpan > 1)
1308 ui_item->setAttributeColSpan(item.columnSpan);
1309 if (item.alignment)
1310 ui_item->setAttributeAlignment(alignmentValue(item.alignment,
1311 d->m_fullyQualifiedEnums));
1312 ui_items.append(ui_item);
1313 }
1314 }
1315
1316 lay->setElementItem(ui_items);
1317
1318 return lay;
1319}
1320
1321/*!
1322 \internal
1323*/
1324DomLayoutItem *QAbstractFormBuilder::createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget)
1325{
1326 DomLayoutItem *ui_item = new DomLayoutItem();
1327
1328 if (item->widget()) {
1329 ui_item->setElementWidget(createDom(item->widget(), ui_parentWidget));
1330 d->m_laidout.insert(item->widget(), true);
1331 } else if (item->layout()) {
1332 ui_item->setElementLayout(createDom(item->layout(), ui_layout, ui_parentWidget));
1333 } else if (item->spacerItem()) {
1334 ui_item->setElementSpacer(createDom(item->spacerItem(), ui_layout, ui_parentWidget));
1335 }
1336
1337 return ui_item;
1338}
1339
1340/*!
1341 \internal
1342*/
1343DomSpacer *QAbstractFormBuilder::createDom(QSpacerItem *spacer, DomLayout *ui_layout, DomWidget *ui_parentWidget)
1344{
1345 Q_UNUSED(ui_layout);
1346 Q_UNUSED(ui_parentWidget);
1347
1348 DomSpacer *ui_spacer = new DomSpacer();
1349 QList<DomProperty*> properties;
1350
1351 DomProperty *prop = nullptr;
1352 // sizeHint property
1353 prop = new DomProperty();
1354 prop->setAttributeName("sizeHint"_L1);
1355 prop->setElementSize(new DomSize());
1356 prop->elementSize()->setElementWidth(spacer->sizeHint().width());
1357 prop->elementSize()->setElementHeight(spacer->sizeHint().height());
1358 properties.append(prop);
1359
1360 // orientation property
1361 prop = new DomProperty(); // ### we don't implemented the case where expandingDirections() is both Vertical and Horizontal
1362 prop->setAttributeName("orientation"_L1);
1363 QString value = d->m_fullyQualifiedEnums ? "Qt::Orientation::"_L1 : "Qt::"_L1;
1364 value += spacer->expandingDirections().testFlag(Qt::Horizontal)
1365 ? "Horizontal"_L1 : "Vertical"_L1;
1366 prop->setElementEnum(value);
1367 properties.append(prop);
1368
1369 ui_spacer->setElementProperty(properties);
1370 return ui_spacer;
1371}
1372
1373/*!
1374 \internal
1375*/
1376DomProperty *QAbstractFormBuilder::createProperty(QObject *obj, const QString &pname, const QVariant &v)
1377{
1378 if (!checkProperty(obj, pname)) {
1379 return nullptr;
1380 }
1381 return variantToDomProperty(this, obj->metaObject(), pname, v);
1382}
1383
1384/*!
1385 \internal
1386*/
1387QList<DomProperty*> QAbstractFormBuilder::computeProperties(QObject *obj)
1388{
1389 QList<DomProperty*> lst;
1390
1391 const QMetaObject *meta = obj->metaObject();
1392
1393 QHash<QByteArray, bool> properties;
1394 const int propertyCount = meta->propertyCount();
1395 for(int i=0; i < propertyCount; ++i)
1396 properties.insert(meta->property(i).name(), true);
1397
1398 const auto propertyNames = properties.keys();
1399
1400 const int propertyNamesCount = propertyNames.size();
1401 for(int i=0; i<propertyNamesCount ; ++i) {
1402 const QString pname = QString::fromUtf8(propertyNames.at(i));
1403 const QMetaProperty prop = meta->property(meta->indexOfProperty(pname.toUtf8()));
1404
1405 if (!prop.isWritable() || !checkProperty(obj, QLatin1StringView(prop.name())))
1406 continue;
1407
1408 const QVariant v = prop.read(obj);
1409
1410 DomProperty *dom_prop = nullptr;
1411 if (v.metaType().id() == QMetaType::Int) {
1412 dom_prop = new DomProperty();
1413
1414 if (prop.isFlagType())
1415 uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Flags property are not supported yet."));
1416
1417 if (prop.isEnumType()) {
1418 QString scope = QString::fromUtf8(prop.enumerator().scope());
1419 if (scope.size())
1420 scope += "::"_L1;
1421 const QString e = QString::fromUtf8(prop.enumerator().valueToKey(v.toInt()));
1422 if (e.size())
1423 dom_prop->setElementEnum(scope + e);
1424 } else
1425 dom_prop->setElementNumber(v.toInt());
1426 dom_prop->setAttributeName(pname);
1427 } else {
1428 dom_prop = createProperty(obj, pname, v);
1429 }
1430
1431 if (!dom_prop || dom_prop->kind() == DomProperty::Unknown)
1432 delete dom_prop;
1433 else
1434 lst.append(dom_prop);
1435 }
1436
1437 return lst;
1438}
1439
1440
1441/*!
1442 \internal
1443 \typedef QAbstractFormBuilder::DomPropertyHash
1444 \typedef QAbstractFormBuilder::IconPaths
1445*/
1446
1447
1448/*!
1449 \internal
1450*/
1451QAbstractFormBuilder::DomPropertyHash QAbstractFormBuilder::propertyMap(const QList<DomProperty*> &properties)
1452{
1453 DomPropertyHash map;
1454
1455 for (DomProperty *p : properties)
1456 map.insert(p->attributeName(), p);
1457
1458 return map;
1459}
1460
1461/*!
1462 \internal
1463*/
1464bool QAbstractFormBuilder::checkProperty(QObject *obj, const QString &prop) const
1465{
1466 Q_UNUSED(obj);
1467 Q_UNUSED(prop);
1468
1469 return true;
1470}
1471
1472/*!
1473 \internal
1474*/
1475QString QAbstractFormBuilder::toString(const DomString *str)
1476{
1477 return str ? str->text() : QString();
1478}
1479
1480/*!
1481 \internal
1482*/
1483void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops)
1484{
1485 if (!tabStops)
1486 return;
1487
1488 const QStringList &names = tabStops->elementTabStop();
1489 QWidgetList widgets;
1490 widgets.reserve(names.size());
1491 for (const QString &name : names) {
1492 if (QWidget *child = widget->findChild<QWidget*>(name)) {
1493 widgets.append(child);
1494 } else {
1495 uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder",
1496 "While applying tab stops: The widget '%1' could not be found.")
1497 .arg(name));
1498 }
1499 }
1500
1501 for (int i = 1, count = widgets.size(); i < count; ++i)
1502 QWidget::setTabOrder(widgets.at(i - 1), widgets.at(i));
1503}
1504
1505/*!
1506 \internal
1507*/
1508DomCustomWidgets *QAbstractFormBuilder::saveCustomWidgets()
1509{
1510 return nullptr;
1511}
1512
1513/*!
1514 \internal
1515*/
1516DomTabStops *QAbstractFormBuilder::saveTabStops()
1517{
1518 return nullptr;
1519}
1520
1521/*!
1522 \internal
1523*/
1524DomResources *QAbstractFormBuilder::saveResources()
1525{
1526 return nullptr;
1527}
1528
1529/*!
1530 \internal
1531 \since 4.5
1532*/
1533
1534DomButtonGroups *QAbstractFormBuilder::saveButtonGroups(const QWidget *mainContainer)
1535{
1536 // Save fst order buttongroup children of maincontainer
1537 const QObjectList &mchildren = mainContainer->children();
1538 if (mchildren.isEmpty())
1539 return nullptr;
1540 QList<DomButtonGroup *> domGroups;
1541 for (QObject *o : mchildren) {
1542 if (auto bg = qobject_cast<QButtonGroup *>(o))
1543 if (DomButtonGroup* dg = createDom(bg))
1544 domGroups.push_back(dg);
1545 }
1546 if (domGroups.isEmpty())
1547 return nullptr;
1548 DomButtonGroups *rc = new DomButtonGroups;
1549 rc->setElementButtonGroup(domGroups);
1550 return rc;
1551}
1552
1553// VC6 would not find templated members, so we use statics and this utter hack.
1555public:
1556 using QAbstractFormBuilder::saveResource;
1557 using QAbstractFormBuilder::saveText;
1558 using QAbstractFormBuilder::resourceBuilder;
1559 using QAbstractFormBuilder::textBuilder;
1560 using QAbstractFormBuilder::toVariant;
1561};
1562
1563template<class T>
1564static void storeItemFlags(const T *item, QList<DomProperty*> *properties)
1565{
1566 static const Qt::ItemFlags defaultFlags = T().flags();
1567 static const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
1568
1569 if (item->flags() != defaultFlags) {
1570 DomProperty *p = new DomProperty;
1571 p->setAttributeName(QFormBuilderStrings::flagsAttribute);
1572 p->setElementSet(QString::fromLatin1(itemFlags_enum.valueToKeys(item->flags())));
1573 properties->append(p);
1574 }
1575}
1576
1577template<class T>
1578static void storeItemProps(QAbstractFormBuilder *abstractFormBuilder, const T *item,
1579 QList<DomProperty*> *properties,
1580 Qt::Alignment defaultAlign = Qt::AlignLeading | Qt::AlignVCenter)
1581{
1582 static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
1583 FriendlyFB * const formBuilder = static_cast<FriendlyFB *>(abstractFormBuilder);
1584
1585 DomProperty *p;
1586
1587 for (const QFormBuilderStrings::TextRoleNName &it : strings.itemTextRoles)
1588 if ((p = formBuilder->saveText(it.second, item->data(it.first.second))))
1589 properties->append(p);
1590
1591 auto *mo = static_cast<const QMetaObject *>(&QAbstractFormBuilderGadget::staticMetaObject);
1592 for (const QFormBuilderStrings::RoleNName &it : strings.itemRoles) {
1593 const QVariant v = item->data(it.first);
1594 const bool isModified = v.isValid()
1595 && (it.first != Qt::TextAlignmentRole || v.toUInt() != uint(defaultAlign));
1596 if (isModified &&
1597 (p = variantToDomProperty(abstractFormBuilder, mo, it.second, v))) {
1598 properties->append(p);
1599 }
1600 }
1601
1602 if ((p = formBuilder->saveResource(item->data(Qt::DecorationPropertyRole))))
1603 properties->append(p);
1604}
1605
1606template<class T>
1607static void storeItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, const T *item,
1608 QList<DomProperty*> *properties)
1609{
1610 storeItemProps<T>(abstractFormBuilder, item, properties);
1611 storeItemFlags<T>(item, properties);
1612}
1613
1614template<class T>
1615static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item,
1616 const QHash<QString, DomProperty*> &properties)
1617{
1618 static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
1619 FriendlyFB * const formBuilder = static_cast<FriendlyFB *>(abstractFormBuilder);
1620
1621 DomProperty *p;
1622 QVariant v;
1623
1624 for (const QFormBuilderStrings::TextRoleNName &it : strings.itemTextRoles)
1625 if ((p = properties.value(it.second))) {
1626 v = formBuilder->textBuilder()->loadText(p);
1627 QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v);
1628 item->setData(it.first.first, qvariant_cast<QString>(nativeValue));
1629 item->setData(it.first.second, v);
1630 }
1631
1632 for (const QFormBuilderStrings::RoleNName &it : strings.itemRoles)
1633 if ((p = properties.value(it.second)) &&
1634 (v = formBuilder->toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p)).isValid())
1635 item->setData(it.first, v);
1636
1637 if ((p = properties.value(strings.iconAttribute))) {
1638 v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p);
1639 QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v);
1640 item->setIcon(qvariant_cast<QIcon>(nativeValue));
1641 item->setData(Qt::DecorationPropertyRole, v);
1642 }
1643}
1644
1645template<class T>
1646static void loadItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, T *item,
1647 const QHash<QString, DomProperty*> &properties)
1648{
1649 static const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
1650
1651 loadItemProps<T>(abstractFormBuilder, item, properties);
1652
1653 DomProperty *p = properties.value(QFormBuilderStrings::flagsAttribute);
1654 if (p != nullptr && p->kind() == DomProperty::Set)
1655 item->setFlags(enumKeysToValue<Qt::ItemFlags>(itemFlags_enum, p->elementSet().toLatin1()));
1656}
1657
1658/*!
1659 \internal
1660*/
1661void QAbstractFormBuilder::saveTreeWidgetExtraInfo(QTreeWidget *treeWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
1662{
1663 Q_UNUSED(ui_parentWidget);
1664
1665 QList<DomColumn *> columns;
1666 DomProperty *p;
1667 QVariant v;
1668 const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
1669 // save the header
1670 for (int c = 0; c<treeWidget->columnCount(); ++c) {
1671 DomColumn *column = new DomColumn;
1672
1673 QList<DomProperty*> properties;
1674
1675 for (const QFormBuilderStrings::TextRoleNName &it : strings.itemTextRoles) {
1676 p = saveText(it.second, treeWidget->headerItem()->data(c, it.first.second));
1677 // Prevent uic 4.4.X from crashing if it cannot find a column text
1678 if (!p && it.first.first == Qt::EditRole && it.second == "text"_L1) {
1679 DomString *defaultHeader = new DomString;
1680 defaultHeader->setText(QString::number(c + 1));
1681 defaultHeader->setAttributeNotr(u"true"_s);
1682 p = new DomProperty;
1683 p->setAttributeName(it.second);
1684 p->setElementString(defaultHeader);
1685 }
1686 if (p)
1687 properties.append(p);
1688 }
1689
1690 for (const QFormBuilderStrings::RoleNName &it : strings.itemRoles)
1691 if ((v = treeWidget->headerItem()->data(c, it.first)).isValid() &&
1692 (p = variantToDomProperty(this, &QAbstractFormBuilderGadget::staticMetaObject, it.second, v)))
1693 properties.append(p);
1694
1695 if ((p = saveResource(treeWidget->headerItem()->data(c, Qt::DecorationPropertyRole))))
1696 properties.append(p);
1697
1698 column->setElementProperty(properties);
1699 columns.append(column);
1700 }
1701
1702 ui_widget->setElementColumn(columns);
1703
1704 auto items = ui_widget->elementItem();
1705
1706 QQueue<std::pair<QTreeWidgetItem *, DomItem *> > pendingQueue;
1707 for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
1708 pendingQueue.enqueue(std::make_pair(treeWidget->topLevelItem(i), nullptr));
1709
1710 while (!pendingQueue.isEmpty()) {
1711 const std::pair<QTreeWidgetItem *, DomItem *> pair = pendingQueue.dequeue();
1712 QTreeWidgetItem *item = pair.first;
1713 DomItem *parentDomItem = pair.second;
1714
1715 DomItem *currentDomItem = new DomItem;
1716
1717 QList<DomProperty*> properties;
1718 for (int c = 0; c < treeWidget->columnCount(); c++) {
1719 for (const QFormBuilderStrings::TextRoleNName &it : strings.itemTextRoles)
1720 if ((p = saveText(it.second, item->data(c, it.first.second))))
1721 properties.append(p);
1722
1723 for (const QFormBuilderStrings::RoleNName &it : strings.itemRoles)
1724 if ((v = item->data(c, it.first)).isValid() &&
1725 (p = variantToDomProperty(this, &QAbstractFormBuilderGadget::staticMetaObject, it.second, v)))
1726 properties.append(p);
1727
1728 if ((p = saveResource(item->data(c, Qt::DecorationPropertyRole))))
1729 properties.append(p);
1730 }
1731 storeItemFlags(item, &properties);
1732 currentDomItem->setElementProperty(properties);
1733
1734 if (parentDomItem) {
1735 auto childrenItems = parentDomItem->elementItem();
1736 childrenItems.append(currentDomItem);
1737 parentDomItem->setElementItem(childrenItems);
1738 } else
1739 items.append(currentDomItem);
1740
1741 for (int i = 0; i < item->childCount(); i++)
1742 pendingQueue.enqueue(std::make_pair(item->child(i), currentDomItem));
1743 }
1744
1745 ui_widget->setElementItem(items);
1746}
1747
1748/*!
1749 \internal
1750*/
1751void QAbstractFormBuilder::saveTableWidgetExtraInfo(QTableWidget *tableWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
1752{
1753 Q_UNUSED(ui_parentWidget);
1754
1755 // save the horizontal header
1756 QList<DomColumn *> columns;
1757 auto *header = tableWidget->horizontalHeader();
1758 for (int c = 0; c < tableWidget->columnCount(); c++) {
1759 QList<DomProperty*> properties;
1760 QTableWidgetItem *item = tableWidget->horizontalHeaderItem(c);
1761 if (item)
1762 storeItemProps(this, item, &properties, header->defaultAlignment());
1763
1764 DomColumn *column = new DomColumn;
1765 column->setElementProperty(properties);
1766 columns.append(column);
1767 }
1768 ui_widget->setElementColumn(columns);
1769
1770 // save the vertical header
1771 QList<DomRow *> rows;
1772 header = tableWidget->verticalHeader();
1773 for (int r = 0; r < tableWidget->rowCount(); r++) {
1774 QList<DomProperty*> properties;
1775 QTableWidgetItem *item = tableWidget->verticalHeaderItem(r);
1776 if (item)
1777 storeItemProps(this, item, &properties, header->defaultAlignment());
1778
1779 DomRow *row = new DomRow;
1780 row->setElementProperty(properties);
1781 rows.append(row);
1782 }
1783 ui_widget->setElementRow(rows);
1784
1785 auto items = ui_widget->elementItem();
1786 for (int r = 0; r < tableWidget->rowCount(); r++)
1787 for (int c = 0; c < tableWidget->columnCount(); c++) {
1788 QTableWidgetItem *item = tableWidget->item(r, c);
1789 if (item) {
1790 QList<DomProperty*> properties;
1791 storeItemPropsNFlags(this, item, &properties);
1792
1793 DomItem *domItem = new DomItem;
1794 domItem->setAttributeRow(r);
1795 domItem->setAttributeColumn(c);
1796 domItem->setElementProperty(properties);
1797 items.append(domItem);
1798 }
1799 }
1800
1801 ui_widget->setElementItem(items);
1802}
1803
1804/*!
1805 \internal
1806*/
1807void QAbstractFormBuilder::saveListWidgetExtraInfo(QListWidget *listWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
1808{
1809 Q_UNUSED(ui_parentWidget);
1810
1811 auto ui_items = ui_widget->elementItem();
1812 for (int i=0; i<listWidget->count(); ++i) {
1813 QList<DomProperty*> properties;
1814 storeItemPropsNFlags(this, listWidget->item(i), &properties);
1815
1816 DomItem *ui_item = new DomItem();
1817 ui_item->setElementProperty(properties);
1818 ui_items.append(ui_item);
1819 }
1820
1821 ui_widget->setElementItem(ui_items);
1822}
1823
1824/*!
1825 \internal
1826*/
1827void QAbstractFormBuilder::saveComboBoxExtraInfo(QComboBox *comboBox, DomWidget *ui_widget, DomWidget *ui_parentWidget)
1828{
1829 Q_UNUSED(ui_parentWidget);
1830 auto ui_items = ui_widget->elementItem();
1831
1832 const int count = comboBox->count();
1833 for (int i=0; i < count; ++i) {
1834 // We might encounter items for which both builders return 0 in Designer
1835 // (indicating a custom combo adding items in the constructor). Ignore those.
1836 DomProperty *textProperty = saveText(QFormBuilderStrings::textAttribute,
1837 comboBox->itemData(i, Qt::DisplayPropertyRole));
1838 DomProperty *iconProperty = saveResource(comboBox->itemData(i, Qt::DecorationPropertyRole));
1839 if (textProperty || iconProperty) {
1840 QList<DomProperty*> properties;
1841 if (textProperty)
1842 properties.push_back(textProperty);
1843 if (iconProperty)
1844 properties.push_back(iconProperty);
1845
1846 DomItem *ui_item = new DomItem();
1847 ui_item->setElementProperty(properties);
1848 ui_items.push_back(ui_item);
1849 }
1850 }
1851
1852 ui_widget->setElementItem(ui_items);
1853}
1854
1855/*!
1856 \internal
1857 \since 4.5
1858*/
1859
1860void QAbstractFormBuilder::saveButtonExtraInfo(const QAbstractButton *widget, DomWidget *ui_widget, DomWidget *)
1861{
1862 using DomPropertyList = QList<DomProperty *>;
1863 if (const QButtonGroup *buttonGroup = widget->group()) {
1864 DomPropertyList attributes = ui_widget->elementAttribute();
1865 DomString *domString = new DomString();
1866 domString->setText(buttonGroup->objectName());
1867 domString->setAttributeNotr(u"true"_s);
1868 DomProperty *domProperty = new DomProperty();
1869 domProperty->setAttributeName(buttonGroupPropertyC);
1870 domProperty->setElementString(domString);
1871 attributes += domProperty;
1872 ui_widget->setElementAttribute(attributes);
1873 }
1874}
1875
1877 "horizontalHeader"_L1,
1878 "verticalHeader"_L1,
1879};
1880
1882{
1883 // Special handling for qtableview/qtreeview fake header attributes
1884 "visible"_L1,
1885 "cascadingSectionResizes"_L1,
1886 "minimumSectionSize"_L1, // before defaultSectionSize
1887 "defaultSectionSize"_L1,
1888 "highlightSections"_L1,
1889 "showSortIndicator"_L1,
1890 "stretchLastSection"_L1
1891};
1892
1893/*!
1894 \internal
1895 \since 4.5
1896*/
1897void QAbstractFormBuilder::saveItemViewExtraInfo(const QAbstractItemView *itemView,
1898 DomWidget *ui_widget, DomWidget *)
1899{
1900 if (const QTreeView *treeView = qobject_cast<const QTreeView*>(itemView)) {
1901 auto viewProperties = ui_widget->elementAttribute();
1902 const auto &headerProperties = computeProperties(treeView->header());
1903 for (const QLatin1StringView realPropertyName : itemViewHeaderRealPropertyNames) {
1904 const QString upperPropertyName = QChar(realPropertyName.at(0)).toUpper()
1905 + realPropertyName.mid(1);
1906 const QString fakePropertyName = "header"_L1 + upperPropertyName;
1907 for (DomProperty *property : headerProperties) {
1908 if (property->attributeName() == realPropertyName) {
1909 property->setAttributeName(fakePropertyName);
1910 viewProperties << property;
1911 }
1912 }
1913 }
1914 ui_widget->setElementAttribute(viewProperties);
1915 } else if (const QTableView *tableView = qobject_cast<const QTableView*>(itemView)) {
1916 auto viewProperties = ui_widget->elementAttribute();
1917 for (QLatin1StringView headerPrefix : tableHeaderPrefixes) {
1918 const auto &headerProperties = headerPrefix == "horizontalHeader"_L1
1919 ? computeProperties(tableView->horizontalHeader())
1920 : computeProperties(tableView->verticalHeader());
1921 for (const QLatin1StringView realPropertyName : itemViewHeaderRealPropertyNames) {
1922 const QString upperPropertyName = QChar(realPropertyName.at(0)).toUpper()
1923 + realPropertyName.mid(1);
1924 const QString fakePropertyName = headerPrefix + upperPropertyName;
1925 for (DomProperty *property : std::as_const(headerProperties)) {
1926 if (property->attributeName() == realPropertyName) {
1927 property->setAttributeName(fakePropertyName);
1928 viewProperties << property;
1929 }
1930 }
1931 }
1932 }
1933 ui_widget->setElementAttribute(viewProperties);
1934 }
1935}
1936
1937/*!
1938 \internal
1939 \since 4.4
1940*/
1941
1942void QAbstractFormBuilder::setResourceBuilder(QResourceBuilder *builder)
1943{
1944 d->setResourceBuilder(builder);
1945}
1946
1947/*!
1948 \internal
1949 \since 4.4
1950*/
1951
1952QResourceBuilder *QAbstractFormBuilder::resourceBuilder() const
1953{
1954 return d->resourceBuilder();
1955}
1956
1957/*!
1958 \internal
1959 \since 4.5
1960*/
1961
1962void QAbstractFormBuilder::setTextBuilder(QTextBuilder *builder)
1963{
1964 d->setTextBuilder(builder);
1965}
1966
1967/*!
1968 \internal
1969 \since 4.5
1970*/
1971
1972QTextBuilder *QAbstractFormBuilder::textBuilder() const
1973{
1974 return d->textBuilder();
1975}
1976
1977/*!
1978 \internal
1979*/
1980void QAbstractFormBuilder::saveExtraInfo(QWidget *widget, DomWidget *ui_widget,
1981 DomWidget *ui_parentWidget)
1982{
1983 if (QListWidget *listWidget = qobject_cast<QListWidget*>(widget)) {
1984 saveListWidgetExtraInfo(listWidget, ui_widget, ui_parentWidget);
1985 } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(widget)) {
1986 saveTreeWidgetExtraInfo(treeWidget, ui_widget, ui_parentWidget);
1987 } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget*>(widget)) {
1988 saveTableWidgetExtraInfo(tableWidget, ui_widget, ui_parentWidget);
1989 } else if (QComboBox *comboBox = qobject_cast<QComboBox*>(widget)) {
1990 if (!qobject_cast<QFontComboBox*>(widget))
1991 saveComboBoxExtraInfo(comboBox, ui_widget, ui_parentWidget);
1992 } else if(QAbstractButton *ab = qobject_cast<QAbstractButton *>(widget)) {
1993 saveButtonExtraInfo(ab, ui_widget, ui_parentWidget);
1994 }
1995 if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(widget)) {
1996 saveItemViewExtraInfo(itemView, ui_widget, ui_parentWidget);
1997 }
1998}
1999
2000/*!
2001 \internal
2002*/
2003void QAbstractFormBuilder::loadListWidgetExtraInfo(DomWidget *ui_widget, QListWidget *listWidget, QWidget *parentWidget)
2004{
2005 Q_UNUSED(parentWidget);
2006 const auto &elementItem = ui_widget->elementItem();
2007 for (DomItem *ui_item : elementItem) {
2008 const DomPropertyHash properties = propertyMap(ui_item->elementProperty());
2009 QListWidgetItem *item = new QListWidgetItem(listWidget);
2010 loadItemPropsNFlags<QListWidgetItem>(this, item, properties);
2011 }
2012
2013 if (auto *currentRow = QFBE::propertyByName(ui_widget->elementProperty(), "currentRow"))
2014 listWidget->setCurrentRow(currentRow->elementNumber());
2015}
2016
2017/*!
2018 \internal
2019*/
2020void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWidget *treeWidget, QWidget *parentWidget)
2021{
2022 Q_UNUSED(parentWidget);
2023 const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
2024 const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
2025 const auto &columns = ui_widget->elementColumn();
2026 if (!columns.isEmpty())
2027 treeWidget->setColumnCount(columns.size());
2028
2029 for (qsizetype i = 0, size = columns.size(); i < size; ++i) {
2030 const DomColumn *c = columns.at(i);
2031 const DomPropertyHash properties = propertyMap(c->elementProperty());
2032
2033 DomProperty *p;
2034 QVariant v;
2035
2036 for (const QFormBuilderStrings::RoleNName &it : strings.itemRoles)
2037 if ((p = properties.value(it.second)) &&
2038 (v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p)).isValid())
2039 treeWidget->headerItem()->setData(i, it.first, v);
2040
2041 for (const QFormBuilderStrings::TextRoleNName &it : strings.itemTextRoles)
2042 if ((p = properties.value(it.second))) {
2043 v = textBuilder()->loadText(p);
2044 QVariant nativeValue = textBuilder()->toNativeValue(v);
2045 treeWidget->headerItem()->setData(i, it.first.first, qvariant_cast<QString>(nativeValue));
2046 treeWidget->headerItem()->setData(i, it.first.second, v);
2047 }
2048
2049 if ((p = properties.value(QFormBuilderStrings::iconAttribute))) {
2050 v = resourceBuilder()->loadResource(workingDirectory(), p);
2051 QVariant nativeValue = resourceBuilder()->toNativeValue(v);
2052 treeWidget->headerItem()->setIcon(i, qvariant_cast<QIcon>(nativeValue));
2053 treeWidget->headerItem()->setData(i, Qt::DecorationPropertyRole, v);
2054 }
2055 }
2056
2057 QQueue<std::pair<DomItem *, QTreeWidgetItem *> > pendingQueue;
2058 const auto &widgetElementItem = ui_widget->elementItem();
2059 for (DomItem *ui_item : widgetElementItem)
2060 pendingQueue.enqueue(std::make_pair(ui_item, nullptr));
2061
2062 while (!pendingQueue.isEmpty()) {
2063 const std::pair<DomItem *, QTreeWidgetItem *> pair = pendingQueue.dequeue();
2064 const DomItem *domItem = pair.first;
2065 QTreeWidgetItem *parentItem = pair.second;
2066
2067 QTreeWidgetItem *currentItem = nullptr;
2068
2069 if (parentItem)
2070 currentItem = new QTreeWidgetItem(parentItem);
2071 else
2072 currentItem = new QTreeWidgetItem(treeWidget);
2073
2074 const auto &properties = domItem->elementProperty();
2075 int col = -1;
2076 for (DomProperty *property : properties) {
2077 if (property->attributeName() == QFormBuilderStrings::flagsAttribute
2078 && !property->elementSet().isEmpty()) {
2079 currentItem->setFlags(enumKeysToValue<Qt::ItemFlags>(itemFlags_enum, property->elementSet().toLatin1()));
2080 } else if (property->attributeName() == QFormBuilderStrings::textAttribute
2081 && property->elementString()) {
2082 col++;
2083 QVariant textV = textBuilder()->loadText(property);
2084 QVariant nativeValue = textBuilder()->toNativeValue(textV);
2085 currentItem->setText(col, qvariant_cast<QString>(nativeValue));
2086 currentItem->setData(col, Qt::DisplayPropertyRole, textV);
2087 } else if (col >= 0) {
2088 if (property->attributeName() == QFormBuilderStrings::iconAttribute) {
2089 QVariant v = resourceBuilder()->loadResource(workingDirectory(), property);
2090 if (v.isValid()) {
2091 QVariant nativeValue = resourceBuilder()->toNativeValue(v);
2092 currentItem->setIcon(col, qvariant_cast<QIcon>(nativeValue));
2093 currentItem->setData(col, Qt::DecorationPropertyRole, v);
2094 }
2095 } else {
2096 QVariant v;
2097 int role = strings.treeItemRoleHash.value(property->attributeName(), (Qt::ItemDataRole)-1);
2098 if (role >= 0) {
2099 if ((v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, property)).isValid())
2100 currentItem->setData(col, role, v);
2101 } else {
2102 std::pair<Qt::ItemDataRole, Qt::ItemDataRole> rolePair =
2103 strings.treeItemTextRoleHash.value(property->attributeName(),
2104 std::make_pair((Qt::ItemDataRole)-1, (Qt::ItemDataRole)-1));
2105 if (rolePair.first >= 0) {
2106 QVariant textV = textBuilder()->loadText(property);
2107 QVariant nativeValue = textBuilder()->toNativeValue(textV);
2108 currentItem->setData(col, rolePair.first, qvariant_cast<QString>(nativeValue));
2109 currentItem->setData(col, rolePair.second, textV);
2110 }
2111 }
2112 }
2113 }
2114 }
2115
2116 const auto &elementItem = domItem->elementItem();
2117 for (DomItem *childItem : elementItem)
2118 pendingQueue.enqueue(std::make_pair(childItem, currentItem));
2119
2120 }
2121}
2122
2123/*!
2124 \internal
2125*/
2126void QAbstractFormBuilder::loadTableWidgetExtraInfo(DomWidget *ui_widget, QTableWidget *tableWidget, QWidget *parentWidget)
2127{
2128 Q_UNUSED(parentWidget);
2129
2130 const auto &columns = ui_widget->elementColumn();
2131 if (!columns.isEmpty())
2132 tableWidget->setColumnCount(columns.size());
2133 for (qsizetype i = 0, size = columns.size(); i < size; ++i) {
2134 DomColumn *c = columns.at(i);
2135 const DomPropertyHash properties = propertyMap(c->elementProperty());
2136
2137 if (!properties.isEmpty()) {
2138 QTableWidgetItem *item = new QTableWidgetItem;
2139 loadItemProps(this, item, properties);
2140 tableWidget->setHorizontalHeaderItem(i, item);
2141 }
2142 }
2143
2144 const auto &rows = ui_widget->elementRow();
2145 if (!rows.isEmpty())
2146 tableWidget->setRowCount(rows.size());
2147 for (qsizetype i = 0, size = rows.size(); i < size; ++i) {
2148 const DomRow *r = rows.at(i);
2149 const DomPropertyHash properties = propertyMap(r->elementProperty());
2150
2151 if (!properties.isEmpty()) {
2152 QTableWidgetItem *item = new QTableWidgetItem;
2153 loadItemProps(this, item, properties);
2154 tableWidget->setVerticalHeaderItem(i, item);
2155 }
2156 }
2157
2158 const auto &elementItem = ui_widget->elementItem();
2159 for (DomItem *ui_item : elementItem) {
2160 if (ui_item->hasAttributeRow() && ui_item->hasAttributeColumn()) {
2161 const DomPropertyHash properties = propertyMap(ui_item->elementProperty());
2162 QTableWidgetItem *item = new QTableWidgetItem;
2163 loadItemPropsNFlags(this, item, properties);
2164 tableWidget->setItem(ui_item->attributeRow(), ui_item->attributeColumn(), item);
2165 }
2166 }
2167}
2168
2169/*!
2170 \internal
2171*/
2172void QAbstractFormBuilder::loadComboBoxExtraInfo(DomWidget *ui_widget, QComboBox *comboBox, QWidget *parentWidget)
2173{
2174 Q_UNUSED(parentWidget);
2175 const auto &elementItem = ui_widget->elementItem();
2176 for (DomItem *ui_item : elementItem) {
2177 const auto &properties = ui_item->elementProperty();
2178 QString text;
2179 QIcon icon;
2180 QVariant textData;
2181 QVariant iconData;
2182
2183 DomProperty *p = QFBE::propertyByName(properties, QFormBuilderStrings::textAttribute);
2184 if (p && p->elementString()) {
2185 textData = textBuilder()->loadText(p);
2186 text = qvariant_cast<QString>(textBuilder()->toNativeValue(textData));
2187 }
2188
2189 p = QFBE::propertyByName(properties, QFormBuilderStrings::iconAttribute);
2190 if (p) {
2191 iconData = resourceBuilder()->loadResource(workingDirectory(), p);
2192 icon = qvariant_cast<QIcon>(resourceBuilder()->toNativeValue(iconData));
2193 }
2194
2195 comboBox->addItem(icon, text);
2196 comboBox->setItemData((comboBox->count()-1), iconData, Qt::DecorationPropertyRole);
2197 comboBox->setItemData((comboBox->count()-1), textData, Qt::DisplayPropertyRole);
2198 }
2199
2200 if (auto *currentIndex = currentIndexProperty(ui_widget->elementProperty()))
2201 comboBox->setCurrentIndex(currentIndex->elementNumber());
2202}
2203
2204// Get the button group name out of a widget's attribute list
2205static QString buttonGroupName(const DomWidget *ui_widget)
2206{
2207 const auto &attributes = ui_widget->elementAttribute();
2208 if (attributes.isEmpty())
2209 return QString();
2210 const QString buttonGroupProperty = buttonGroupPropertyC;
2211 for (const DomProperty *p : attributes) {
2212 if (p->attributeName() == buttonGroupProperty)
2213 return p->elementString()->text();
2214 }
2215 return QString();
2216}
2217
2218/*!
2219 \internal
2220 \since 4.5
2221*/
2222
2223void QAbstractFormBuilder::loadButtonExtraInfo(const DomWidget *ui_widget, QAbstractButton *button, QWidget *)
2224{
2225 using ButtonGroupHash = QFormBuilderExtra::ButtonGroupHash;
2226
2227 const QString groupName = buttonGroupName(ui_widget);
2228 if (groupName.isEmpty())
2229 return;
2230 // Find entry
2231 ButtonGroupHash &buttonGroups = d->buttonGroups();
2232 const auto it = buttonGroups.find(groupName);
2233 if (it == buttonGroups.end()) {
2234#ifdef QFORMINTERNAL_NAMESPACE // Suppress the warning when copying in Designer
2235 uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Invalid QButtonGroup reference '%1' referenced by '%2'.").arg(groupName, button->objectName()));
2236#endif
2237 return;
2238 }
2239 // Create button group on demand?
2240 QButtonGroup *&group = it.value().second;
2241 if (group == nullptr) {
2242 group = new QButtonGroup;
2243 group->setObjectName(groupName);
2244 applyProperties(group, it.value().first->elementProperty());
2245 }
2246 group->addButton(button);
2247}
2248
2249/*!
2250 \internal
2251 \since 4.5
2252*/
2253void QAbstractFormBuilder::loadItemViewExtraInfo(DomWidget *ui_widget, QAbstractItemView *itemView,
2254 QWidget *)
2255{
2256 if (QTreeView *treeView = qobject_cast<QTreeView*>(itemView)) {
2257 const auto &allAttributes = ui_widget->elementAttribute();
2258 QList<DomProperty *> headerProperties;
2259 for (QLatin1StringView realPropertyName : itemViewHeaderRealPropertyNames) {
2260 const QString upperPropertyName = QChar(realPropertyName.at(0)).toUpper()
2261 + realPropertyName.mid(1);
2262 const QString fakePropertyName = "header"_L1 + upperPropertyName;
2263 for (DomProperty *attr : allAttributes) {
2264 if (attr->attributeName() == fakePropertyName) {
2265 attr->setAttributeName(realPropertyName);
2266 headerProperties << attr;
2267 }
2268 }
2269 }
2270 applyProperties(treeView->header(), headerProperties);
2271 } else if (QTableView *tableView = qobject_cast<QTableView*>(itemView)) {
2272 const auto &allAttributes = ui_widget->elementAttribute();
2273 for (QLatin1StringView headerPrefix : tableHeaderPrefixes) {
2274 QList<DomProperty*> headerProperties;
2275 for (QLatin1StringView realPropertyName : itemViewHeaderRealPropertyNames) {
2276 const QString upperPropertyName = QChar(realPropertyName.at(0)).toUpper()
2277 + realPropertyName.mid(1);
2278 const QString fakePropertyName = headerPrefix + upperPropertyName;
2279 for (DomProperty *attr : allAttributes) {
2280 if (attr->attributeName() == fakePropertyName) {
2281 attr->setAttributeName(realPropertyName);
2282 headerProperties << attr;
2283 }
2284 }
2285 }
2286 if (headerPrefix == "horizontalHeader"_L1)
2287 applyProperties(tableView->horizontalHeader(), headerProperties);
2288 else
2289 applyProperties(tableView->verticalHeader(), headerProperties);
2290 }
2291 }
2292}
2293
2294/*!
2295 \internal
2296*/
2297void QAbstractFormBuilder::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
2298{
2299 if (false) {
2300#if QT_CONFIG(listwidget)
2301 } else if (QListWidget *listWidget = qobject_cast<QListWidget*>(widget)) {
2302 loadListWidgetExtraInfo(ui_widget, listWidget, parentWidget);
2303#endif
2304#if QT_CONFIG(treewidget)
2305 } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(widget)) {
2306 loadTreeWidgetExtraInfo(ui_widget, treeWidget, parentWidget);
2307#endif
2308#if QT_CONFIG(tablewidget)
2309 } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget*>(widget)) {
2310 loadTableWidgetExtraInfo(ui_widget, tableWidget, parentWidget);
2311#endif
2312#if QT_CONFIG(combobox)
2313 } else if (QComboBox *comboBox = qobject_cast<QComboBox*>(widget)) {
2314 if (!qobject_cast<QFontComboBox *>(widget))
2315 loadComboBoxExtraInfo(ui_widget, comboBox, parentWidget);
2316#endif
2317#if QT_CONFIG(tabwidget)
2318 } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget)) {
2319 if (auto *currentIndex = currentIndexProperty(ui_widget->elementProperty()))
2320 tabWidget->setCurrentIndex(currentIndex->elementNumber());
2321#endif
2322#if QT_CONFIG(stackedwidget)
2323 } else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
2324 if (auto *currentIndex = currentIndexProperty(ui_widget->elementProperty()))
2325 stackedWidget->setCurrentIndex(currentIndex->elementNumber());
2326#endif
2327#if QT_CONFIG(toolbox)
2328 } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget)) {
2329 if (auto *currentIndex = currentIndexProperty(ui_widget->elementProperty()))
2330 toolBox->setCurrentIndex(currentIndex->elementNumber());
2331 if (auto *tabSpacing = QFBE::propertyByName(ui_widget->elementProperty(), "tabSpacing"))
2332 toolBox->layout()->setSpacing(tabSpacing->elementNumber());
2333#endif
2334 } else if (QAbstractButton *ab = qobject_cast<QAbstractButton *>(widget)) {
2335 loadButtonExtraInfo(ui_widget, ab, parentWidget);
2336 }
2337 if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(widget)) {
2338 loadItemViewExtraInfo(ui_widget, itemView, parentWidget);
2339 }
2340}
2341
2342/*!
2343 Returns the current working directory of the form builder.
2344
2345 \sa setWorkingDirectory()
2346*/
2347QDir QAbstractFormBuilder::workingDirectory() const
2348{
2349 return d->m_workingDirectory;
2350}
2351
2352/*!
2353 Sets the current working directory of the form builder to the
2354 specified \a directory.
2355
2356 \sa workingDirectory()
2357*/
2358void QAbstractFormBuilder::setWorkingDirectory(const QDir &directory)
2359{
2360 d->m_workingDirectory = directory;
2361}
2362
2363/*!
2364 \internal
2365*/
2366DomAction *QAbstractFormBuilder::createDom(QAction *action)
2367{
2368 if (action->parent() == action->menu() || action->isSeparator())
2369 return nullptr;
2370
2371 DomAction *ui_action = new DomAction;
2372 ui_action->setAttributeName(action->objectName());
2373
2374 ui_action->setElementProperty(computeProperties(action));
2375
2376 return ui_action;
2377}
2378
2379/*!
2380 \internal
2381 \since 4.5
2382*/
2383
2384DomButtonGroup *QAbstractFormBuilder::createDom(QButtonGroup *buttonGroup)
2385{
2386 if (buttonGroup->buttons().isEmpty()) // Empty group left over on form?
2387 return nullptr;
2388 DomButtonGroup *domButtonGroup = new DomButtonGroup;
2389 domButtonGroup->setAttributeName(buttonGroup->objectName());
2390
2391 domButtonGroup->setElementProperty(computeProperties(buttonGroup));
2392 return domButtonGroup;
2393}
2394
2395/*!
2396 \internal
2397*/
2398DomActionGroup *QAbstractFormBuilder::createDom(QActionGroup *actionGroup)
2399{
2400 DomActionGroup *ui_action_group = new DomActionGroup;
2401 ui_action_group->setAttributeName(actionGroup->objectName());
2402
2403 ui_action_group->setElementProperty(computeProperties(actionGroup));
2404
2405 QList<DomAction *> ui_actions;
2406
2407 const auto &actions = actionGroup->actions();
2408 ui_actions.reserve(actions.size());
2409 for (QAction *action : actions) {
2410 if (DomAction *ui_action = createDom(action)) {
2411 ui_actions.append(ui_action);
2412 }
2413 }
2414
2415 ui_action_group->setElementAction(ui_actions);
2416
2417 return ui_action_group;
2418}
2419
2420/*!
2421 \internal
2422*/
2423void QAbstractFormBuilder::addMenuAction(QAction *action)
2424{
2425 Q_UNUSED(action);
2426}
2427
2428/*!
2429 \internal
2430*/
2431void QAbstractFormBuilder::reset()
2432{
2433 d->m_laidout.clear();
2434 d->m_actions.clear();
2435 d->m_actionGroups.clear();
2436 d->m_defaultMargin = INT_MIN;
2437 d->m_defaultSpacing = INT_MIN;
2438 d->m_fullyQualifiedEnums = true;
2439}
2440
2441/*!
2442 \internal
2443 Access meta enumeration for Qt::ToolBarArea
2444*/
2445
2446QMetaEnum QAbstractFormBuilder::toolBarAreaMetaEnum()
2447{
2448 return metaEnum<QAbstractFormBuilderGadget>("toolBarArea");
2449}
2450
2451/*!
2452 \internal
2453 Set up a DOM property with icon.
2454*/
2455
2456void QAbstractFormBuilder::setIconProperty(DomProperty &p, const IconPaths &ip) const
2457{
2458 DomResourceIcon *dpi = new DomResourceIcon;
2459
2460 /* TODO
2461 if (!ip.second.isEmpty())
2462 pix->setAttributeResource(ip.second);
2463*/
2464 dpi->setText(ip.first);
2465
2466 p.setAttributeName(QFormBuilderStrings::iconAttribute);
2467 p.setElementIconSet(dpi);
2468}
2469
2470/*!
2471 \internal
2472 Set up a DOM property with pixmap.
2473*/
2474
2475void QAbstractFormBuilder::setPixmapProperty(DomProperty &p, const IconPaths &ip) const
2476{
2477 QFormBuilderExtra::setPixmapProperty(&p, ip);
2478}
2479
2480/*!
2481 \internal
2482 \since 4.4
2483*/
2484
2485DomProperty *QAbstractFormBuilder::saveResource(const QVariant &v) const
2486{
2487 if (v.isNull())
2488 return nullptr;
2489
2490 DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), v);
2491 if (p)
2492 p->setAttributeName(QFormBuilderStrings::iconAttribute);
2493 return p;
2494}
2495
2496/*!
2497 \internal
2498 \since 4.5
2499*/
2500
2501DomProperty *QAbstractFormBuilder::saveText(const QString &attributeName, const QVariant &v) const
2502{
2503 if (v.isNull())
2504 return nullptr;
2505
2506 DomProperty *p = textBuilder()->saveText(v);
2507 if (p)
2508 p->setAttributeName(attributeName);
2509 return p;
2510}
2511
2512/*!
2513 \internal
2514 Return the appropriate DOM pixmap for an image dom property.
2515 From 4.4 - unused
2516*/
2517
2518const DomResourcePixmap *QAbstractFormBuilder::domPixmap(const DomProperty* p) {
2519 switch (p->kind()) {
2520 case DomProperty::IconSet:
2521 qDebug() << "** WARNING QAbstractFormBuilder::domPixmap() called for icon set!";
2522 break;
2523 case DomProperty::Pixmap:
2524 return p->elementPixmap();
2525 default:
2526 break;
2527 }
2528 return nullptr;
2529}
2530
2531/*!
2532 \fn void QAbstractFormBuilder::createConnections ( DomConnections *, QWidget * )
2533 \internal
2534*/
2535
2536/*!
2537 \fn void QAbstractFormBuilder::createCustomWidgets ( DomCustomWidgets * )
2538 \internal
2539*/
2540
2541/*!
2542 \fn void QAbstractFormBuilder::createResources ( DomResources * )
2543 \internal
2544*/
2545
2546/*!
2547 Returns a human-readable description of the last error occurred in load().
2548
2549 \since 5.0
2550 \sa load()
2551*/
2552
2553QString QAbstractFormBuilder::errorString() const
2554{
2555 return d->m_errorString;
2556}
2557
2558QT_END_NAMESPACE
static QString buttonGroupName(const DomWidget *ui_widget)
static void storeItemProps(QAbstractFormBuilder *abstractFormBuilder, const T *item, QList< DomProperty * > *properties, Qt::Alignment defaultAlign=Qt::AlignLeading|Qt::AlignVCenter)
static Qt::Alignment alignmentFromDom(const QString &in)
static constexpr auto buttonGroupPropertyC
static void storeItemFlags(const T *item, QList< DomProperty * > *properties)
static QList< FormBuilderSaveLayoutEntry > saveGridLayoutEntries(QGridLayout *gridLayout)
static void storeItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, const T *item, QList< DomProperty * > *properties)
static QString alignmentPrefix(bool fullyQualifiedEnums)
static void loadItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, T *item, const QHash< QString, DomProperty * > &properties)
static DomProperty * currentIndexProperty(const QList< DomProperty * > &properties)
static QString alignmentValue(Qt::Alignment a, bool fullyQualifiedEnums)
static constexpr QLatin1StringView itemViewHeaderRealPropertyNames[]
static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item, const QHash< QString, DomProperty * > &properties)
static const QLatin1StringView tableHeaderPrefixes[]
static QList< FormBuilderSaveLayoutEntry > saveLayoutEntries(const QLayout *layout)
Definition qlist.h:76
friend class QWidget
Definition qpainter.h:421
FormBuilderSaveLayoutEntry(QLayoutItem *li=nullptr)
void setAlignment(Qt::Alignment al)