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
stringListToByteArray(const QStringList & l)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
formEditorForObject(QObject * o)52 static QDesignerFormEditorInterface *formEditorForObject(QObject *o) {
53 do {
54 if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(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
QDesignerMemberSheetPrivate(QObject * object,QObject * sheetParent)83 QDesignerMemberSheetPrivate::QDesignerMemberSheetPrivate(QObject *object, QObject *sheetParent) :
84 m_core(formEditorForObject(sheetParent)),
85 m_meta(m_core->introspection()->metaObject(object))
86 {
87 }
88
ensureInfo(int index)89 QDesignerMemberSheetPrivate::Info &QDesignerMemberSheetPrivate::ensureInfo(int index)
90 {
91 InfoHash::iterator it = m_info.find(index);
92 if (it == m_info.end()) {
93 it = m_info.insert(index, Info());
94 }
95 return it.value();
96 }
97
98 // --------- QDesignerMemberSheet
99
QDesignerMemberSheet(QObject * object,QObject * parent)100 QDesignerMemberSheet::QDesignerMemberSheet(QObject *object, QObject *parent) :
101 QObject(parent),
102 d(new QDesignerMemberSheetPrivate(object, parent))
103 {
104 }
105
~QDesignerMemberSheet()106 QDesignerMemberSheet::~QDesignerMemberSheet()
107 {
108 delete d;
109 }
110
count() const111 int QDesignerMemberSheet::count() const
112 {
113 return d->m_meta->methodCount();
114 }
115
indexOf(const QString & name) const116 int QDesignerMemberSheet::indexOf(const QString &name) const
117 {
118 return d->m_meta->indexOfMethod(name);
119 }
120
memberName(int index) const121 QString QDesignerMemberSheet::memberName(int index) const
122 {
123 return d->m_meta->method(index)->tag();
124 }
125
declaredInClass(int index) const126 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(member) == -1)
138 break;
139 meta_obj = tmp;
140 }
141 return meta_obj->className();
142 }
143
memberGroup(int index) const144 QString QDesignerMemberSheet::memberGroup(int index) const
145 {
146 return d->m_info.value(index).group;
147 }
148
setMemberGroup(int index,const QString & group)149 void QDesignerMemberSheet::setMemberGroup(int index, const QString &group)
150 {
151 d->ensureInfo(index).group = group;
152 }
153
signature(int index) const154 QString QDesignerMemberSheet::signature(int index) const
155 {
156 return d->m_meta->method(index)->normalizedSignature();
157 }
158
isVisible(int index) const159 bool QDesignerMemberSheet::isVisible(int index) const
160 {
161 const auto it = d->m_info.constFind(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
setVisible(int index,bool visible)169 void QDesignerMemberSheet::setVisible(int index, bool visible)
170 {
171 d->ensureInfo(index).visible = visible;
172 }
173
isSignal(int index) const174 bool QDesignerMemberSheet::isSignal(int index) const
175 {
176 return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Signal;
177 }
178
isSlot(int index) const179 bool QDesignerMemberSheet::isSlot(int index) const
180 {
181 return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Slot;
182 }
183
inheritedFromWidget(int index) const184 bool QDesignerMemberSheet::inheritedFromWidget(int index) const
185 {
186 return declaredInClass(index) == QStringLiteral("QWidget") || declaredInClass(index) == QStringLiteral("QObject");
187 }
188
189
parameterTypes(int index) const190 QList<QByteArray> QDesignerMemberSheet::parameterTypes(int index) const
191 {
192 return stringListToByteArray(d->m_meta->method(index)->parameterTypes());
193 }
194
parameterNames(int index) const195 QList<QByteArray> QDesignerMemberSheet::parameterNames(int index) const
196 {
197 return stringListToByteArray(d->m_meta->method(index)->parameterNames());
198 }
199
signalMatchesSlot(const QString & signal,const QString & slot)200 bool QDesignerMemberSheet::signalMatchesSlot(const QString &signal, const QString &slot)
201 {
202 bool result = true;
203
204 do {
205 int signal_idx = signal.indexOf(QLatin1Char('('));
206 int slot_idx = slot.indexOf(QLatin1Char('('));
207 if (signal_idx == -1 || slot_idx == -1)
208 break;
209
210 ++signal_idx; ++slot_idx;
211
212 if (slot.at(slot_idx) == QLatin1Char(')'))
213 break;
214
215 while (signal_idx < signal.size() && slot_idx < slot.size()) {
216 const QChar signal_c = signal.at(signal_idx);
217 const QChar slot_c = slot.at(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
QDesignerMemberSheetFactory(QExtensionManager * parent)239 QDesignerMemberSheetFactory::QDesignerMemberSheetFactory(QExtensionManager *parent)
240 : QExtensionFactory(parent)
241 {
242 }
243
createExtension(QObject * object,const QString & iid,QObject * parent) const244 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