1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "customwidgetsinfo.h"
5#include "driver.h"
6#include "ui4.h"
7#include "utils.h"
8
9#include <utility>
10
11QT_BEGIN_NAMESPACE
12
13using namespace Qt::StringLiterals;
14
15CustomWidgetsInfo::CustomWidgetsInfo() = default;
16
17void CustomWidgetsInfo::acceptUI(DomUI *node)
18{
19 m_customWidgets.clear();
20
21 if (node->elementCustomWidgets())
22 acceptCustomWidgets(node: node->elementCustomWidgets());
23}
24
25void CustomWidgetsInfo::acceptCustomWidgets(DomCustomWidgets *node)
26{
27 TreeWalker::acceptCustomWidgets(customWidgets: node);
28}
29
30void CustomWidgetsInfo::acceptCustomWidget(DomCustomWidget *node)
31{
32 if (node->elementClass().isEmpty())
33 return;
34
35 m_customWidgets.insert(key: node->elementClass(), value: node);
36}
37
38bool CustomWidgetsInfo::extends(const QString &classNameIn, QAnyStringView baseClassName) const
39{
40 if (classNameIn == baseClassName)
41 return true;
42
43 QString className = classNameIn;
44 while (const DomCustomWidget *c = customWidget(name: className)) {
45 const QString extends = c->elementExtends();
46 if (className == extends) // Faulty legacy custom widget entries exist.
47 return false;
48 if (extends == baseClassName)
49 return true;
50 className = extends;
51 }
52 return false;
53}
54
55bool CustomWidgetsInfo::extendsOneOf(const QString &classNameIn,
56 const QStringList &baseClassNames) const
57{
58 if (baseClassNames.contains(str: classNameIn))
59 return true;
60
61 QString className = classNameIn;
62 while (const DomCustomWidget *c = customWidget(name: className)) {
63 const QString extends = c->elementExtends();
64 if (className == extends) // Faulty legacy custom widget entries exist.
65 return false;
66 if (baseClassNames.contains(str: extends))
67 return true;
68 className = extends;
69 }
70 return false;
71}
72
73bool CustomWidgetsInfo::isCustomWidgetContainer(const QString &className) const
74{
75 if (const DomCustomWidget *dcw = m_customWidgets.value(key: className, defaultValue: nullptr))
76 if (dcw->hasElementContainer())
77 return dcw->elementContainer() != 0;
78 return false;
79}
80
81// Is it ambiguous, resulting in different signals for Python
82// "QAbstractButton::clicked(checked=false)"
83bool CustomWidgetsInfo::isAmbiguousSignal(const QString &className,
84 const QString &signalSignature) const
85{
86 if (signalSignature.startsWith(s: u"triggered") && extends(classNameIn: className, baseClassName: "QAction"))
87 return true;
88 if (signalSignature.startsWith(s: u"clicked(")
89 && extendsOneOf(classNameIn: className, baseClassNames: {u"QCommandLinkButton"_s, u"QCheckBox"_s,
90 u"QPushButton"_s, u"QRadioButton"_s, u"QToolButton"_s})) {
91 return true;
92 }
93 return false;
94}
95
96QString CustomWidgetsInfo::realClassName(const QString &className) const
97{
98 if (className == "Line"_L1)
99 return u"QFrame"_s;
100
101 return className;
102}
103
104QString CustomWidgetsInfo::customWidgetAddPageMethod(const QString &name) const
105{
106 if (DomCustomWidget *dcw = m_customWidgets.value(key: name, defaultValue: nullptr))
107 return dcw->elementAddPageMethod();
108 return QString();
109}
110
111// add page methods for simple containers taking only the widget parameter
112QString CustomWidgetsInfo::simpleContainerAddPageMethod(const QString &name) const
113{
114 using AddPageMethod = std::pair<QString, QString>;
115
116 static const AddPageMethod addPageMethods[] = {
117 {u"QStackedWidget"_s, u"addWidget"_s},
118 {u"QToolBar"_s, u"addWidget"_s},
119 {u"QDockWidget"_s, u"setWidget"_s},
120 {u"QScrollArea"_s, u"setWidget"_s},
121 {u"QSplitter"_s, u"addWidget"_s},
122 {u"QMdiArea"_s, u"addSubWindow"_s}
123 };
124 for (const auto &m : addPageMethods) {
125 if (extends(classNameIn: name, baseClassName: m.first))
126 return m.second;
127 }
128 return QString();
129}
130
131QT_END_NAMESPACE
132

source code of qtbase/src/tools/uic/customwidgetsinfo.cpp