1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 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:GPL-EXCEPT$ |
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 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "qdesigner_membersheet_p.h" |
30 | |
31 | #include <QtDesigner/abstractformeditor.h> |
32 | #include <abstractintrospection_p.h> |
33 | |
34 | #include <QtWidgets/qwidget.h> |
35 | QT_BEGIN_NAMESPACE |
36 | |
37 | static QList<QByteArray> stringListToByteArray(const QStringList &l) |
38 | { |
39 | if (l.isEmpty()) |
40 | return QList<QByteArray>(); |
41 | QList<QByteArray> rc; |
42 | const QStringList::const_iterator cend = l.constEnd(); |
43 | for (QStringList::const_iterator it = l.constBegin(); it != cend; ++it) |
44 | rc += it->toUtf8(); |
45 | return rc; |
46 | } |
47 | |
48 | // Find the form editor in the hierarchy. |
49 | // We know that the parent of the sheet is the extension manager |
50 | // whose parent is the core. |
51 | |
52 | static QDesignerFormEditorInterface *formEditorForObject(QObject *o) { |
53 | do { |
54 | if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(object: o)) |
55 | return core; |
56 | o = o->parent(); |
57 | } while(o); |
58 | Q_ASSERT(o); |
59 | return nullptr; |
60 | } |
61 | |
62 | // ------------ QDesignerMemberSheetPrivate |
63 | class QDesignerMemberSheetPrivate { |
64 | public: |
65 | explicit QDesignerMemberSheetPrivate(QObject *object, QObject *sheetParent); |
66 | |
67 | QDesignerFormEditorInterface *m_core; |
68 | const QDesignerMetaObjectInterface *m_meta; |
69 | |
70 | class Info { |
71 | public: |
72 | QString group; |
73 | bool visible{true}; |
74 | }; |
75 | |
76 | using InfoHash = QHash<int, Info>; |
77 | |
78 | Info &ensureInfo(int index); |
79 | |
80 | InfoHash m_info; |
81 | }; |
82 | |
83 | QDesignerMemberSheetPrivate::QDesignerMemberSheetPrivate(QObject *object, QObject *sheetParent) : |
84 | m_core(formEditorForObject(o: sheetParent)), |
85 | m_meta(m_core->introspection()->metaObject(object)) |
86 | { |
87 | } |
88 | |
89 | QDesignerMemberSheetPrivate::Info &QDesignerMemberSheetPrivate::ensureInfo(int index) |
90 | { |
91 | InfoHash::iterator it = m_info.find(akey: index); |
92 | if (it == m_info.end()) { |
93 | it = m_info.insert(akey: index, avalue: Info()); |
94 | } |
95 | return it.value(); |
96 | } |
97 | |
98 | // --------- QDesignerMemberSheet |
99 | |
100 | QDesignerMemberSheet::QDesignerMemberSheet(QObject *object, QObject *parent) : |
101 | QObject(parent), |
102 | d(new QDesignerMemberSheetPrivate(object, parent)) |
103 | { |
104 | } |
105 | |
106 | QDesignerMemberSheet::~QDesignerMemberSheet() |
107 | { |
108 | delete d; |
109 | } |
110 | |
111 | int QDesignerMemberSheet::count() const |
112 | { |
113 | return d->m_meta->methodCount(); |
114 | } |
115 | |
116 | int QDesignerMemberSheet::indexOf(const QString &name) const |
117 | { |
118 | return d->m_meta->indexOfMethod(method: name); |
119 | } |
120 | |
121 | QString QDesignerMemberSheet::memberName(int index) const |
122 | { |
123 | return d->m_meta->method(index)->tag(); |
124 | } |
125 | |
126 | QString QDesignerMemberSheet::declaredInClass(int index) const |
127 | { |
128 | const QString member = d->m_meta->method(index)->signature(); |
129 | |
130 | // Find class whose superclass does not contain the method. |
131 | const QDesignerMetaObjectInterface *meta_obj = d->m_meta; |
132 | |
133 | for (;;) { |
134 | const QDesignerMetaObjectInterface *tmp = meta_obj->superClass(); |
135 | if (tmp == nullptr) |
136 | break; |
137 | if (tmp->indexOfMethod(method: member) == -1) |
138 | break; |
139 | meta_obj = tmp; |
140 | } |
141 | return meta_obj->className(); |
142 | } |
143 | |
144 | QString QDesignerMemberSheet::memberGroup(int index) const |
145 | { |
146 | return d->m_info.value(akey: index).group; |
147 | } |
148 | |
149 | void QDesignerMemberSheet::setMemberGroup(int index, const QString &group) |
150 | { |
151 | d->ensureInfo(index).group = group; |
152 | } |
153 | |
154 | QString QDesignerMemberSheet::signature(int index) const |
155 | { |
156 | return d->m_meta->method(index)->normalizedSignature(); |
157 | } |
158 | |
159 | bool QDesignerMemberSheet::isVisible(int index) const |
160 | { |
161 | const auto it = d->m_info.constFind(akey: index); |
162 | if (it != d->m_info.constEnd()) |
163 | return it.value().visible; |
164 | |
165 | return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Signal |
166 | || d->m_meta->method(index)->access() == QDesignerMetaMethodInterface::Public; |
167 | } |
168 | |
169 | void QDesignerMemberSheet::setVisible(int index, bool visible) |
170 | { |
171 | d->ensureInfo(index).visible = visible; |
172 | } |
173 | |
174 | bool QDesignerMemberSheet::isSignal(int index) const |
175 | { |
176 | return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Signal; |
177 | } |
178 | |
179 | bool QDesignerMemberSheet::isSlot(int index) const |
180 | { |
181 | return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Slot; |
182 | } |
183 | |
184 | bool QDesignerMemberSheet::inheritedFromWidget(int index) const |
185 | { |
186 | return declaredInClass(index) == QStringLiteral("QWidget" ) || declaredInClass(index) == QStringLiteral("QObject" ); |
187 | } |
188 | |
189 | |
190 | QList<QByteArray> QDesignerMemberSheet::parameterTypes(int index) const |
191 | { |
192 | return stringListToByteArray(l: d->m_meta->method(index)->parameterTypes()); |
193 | } |
194 | |
195 | QList<QByteArray> QDesignerMemberSheet::parameterNames(int index) const |
196 | { |
197 | return stringListToByteArray(l: d->m_meta->method(index)->parameterNames()); |
198 | } |
199 | |
200 | bool QDesignerMemberSheet::signalMatchesSlot(const QString &signal, const QString &slot) |
201 | { |
202 | bool result = true; |
203 | |
204 | do { |
205 | int signal_idx = signal.indexOf(c: QLatin1Char('(')); |
206 | int slot_idx = slot.indexOf(c: QLatin1Char('(')); |
207 | if (signal_idx == -1 || slot_idx == -1) |
208 | break; |
209 | |
210 | ++signal_idx; ++slot_idx; |
211 | |
212 | if (slot.at(i: slot_idx) == QLatin1Char(')')) |
213 | break; |
214 | |
215 | while (signal_idx < signal.size() && slot_idx < slot.size()) { |
216 | const QChar signal_c = signal.at(i: signal_idx); |
217 | const QChar slot_c = slot.at(i: slot_idx); |
218 | |
219 | if (signal_c == QLatin1Char(',') && slot_c == QLatin1Char(')')) |
220 | break; |
221 | |
222 | if (signal_c == QLatin1Char(')') && slot_c == QLatin1Char(')')) |
223 | break; |
224 | |
225 | if (signal_c != slot_c) { |
226 | result = false; |
227 | break; |
228 | } |
229 | |
230 | ++signal_idx; ++slot_idx; |
231 | } |
232 | } while (false); |
233 | |
234 | return result; |
235 | } |
236 | |
237 | // ------------ QDesignerMemberSheetFactory |
238 | |
239 | QDesignerMemberSheetFactory::QDesignerMemberSheetFactory(QExtensionManager *parent) |
240 | : QExtensionFactory(parent) |
241 | { |
242 | } |
243 | |
244 | QObject *QDesignerMemberSheetFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const |
245 | { |
246 | if (iid == Q_TYPEID(QDesignerMemberSheetExtension)) { |
247 | return new QDesignerMemberSheet(object, parent); |
248 | } |
249 | |
250 | return nullptr; |
251 | } |
252 | |
253 | QT_END_NAMESPACE |
254 | |