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