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