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 "metadatabase_p.h"
30 #include "widgetdatabase_p.h"
31 
32 // sdk
33 #include <QtDesigner/abstractformeditor.h>
34 
35 // Qt
36 #include <QtWidgets/qwidget.h>
37 #include <QtCore/qalgorithms.h>
38 #include <QtCore/qdebug.h>
39 
40 QT_BEGIN_NAMESPACE
41 
42 namespace {
43     const bool debugMetaDatabase = false;
44 }
45 
46 namespace qdesigner_internal {
47 
MetaDataBaseItem(QObject * object)48 MetaDataBaseItem::MetaDataBaseItem(QObject *object)
49     : m_object(object),
50       m_enabled(true)
51 {
52 }
53 
54 MetaDataBaseItem::~MetaDataBaseItem() = default;
55 
name() const56 QString MetaDataBaseItem::name() const
57 {
58     Q_ASSERT(m_object);
59     return m_object->objectName();
60 }
61 
setName(const QString & name)62 void MetaDataBaseItem::setName(const QString &name)
63 {
64     Q_ASSERT(m_object);
65     m_object->setObjectName(name);
66 }
67 
customClassName() const68 QString MetaDataBaseItem::customClassName() const
69 {
70     return m_customClassName;
71 }
setCustomClassName(const QString & customClassName)72 void MetaDataBaseItem::setCustomClassName(const QString &customClassName)
73 {
74     m_customClassName = customClassName;
75 }
76 
77 
tabOrder() const78 QWidgetList MetaDataBaseItem::tabOrder() const
79 {
80     return m_tabOrder;
81 }
82 
setTabOrder(const QWidgetList & tabOrder)83 void MetaDataBaseItem::setTabOrder(const QWidgetList &tabOrder)
84 {
85     m_tabOrder = tabOrder;
86 }
87 
enabled() const88 bool MetaDataBaseItem::enabled() const
89 {
90     return m_enabled;
91 }
92 
setEnabled(bool b)93 void MetaDataBaseItem::setEnabled(bool b)
94 {
95     m_enabled = b;
96 }
97 
fakeSlots() const98 QStringList MetaDataBaseItem::fakeSlots() const
99 {
100     return m_fakeSlots;
101 }
102 
setFakeSlots(const QStringList & fs)103 void MetaDataBaseItem::setFakeSlots(const QStringList &fs)
104 {
105     m_fakeSlots = fs;
106 }
107 
fakeSignals() const108 QStringList MetaDataBaseItem::fakeSignals() const
109 {
110      return m_fakeSignals;
111 }
112 
setFakeSignals(const QStringList & fs)113 void MetaDataBaseItem::setFakeSignals(const QStringList &fs)
114 {
115     m_fakeSignals = fs;
116 }
117 
118 // -----------------------------------------------------
MetaDataBase(QDesignerFormEditorInterface * core,QObject * parent)119 MetaDataBase::MetaDataBase(QDesignerFormEditorInterface *core, QObject *parent)
120     : QDesignerMetaDataBaseInterface(parent),
121       m_core(core)
122 {
123 }
124 
~MetaDataBase()125 MetaDataBase::~MetaDataBase()
126 {
127     qDeleteAll(m_items);
128 }
129 
metaDataBaseItem(QObject * object) const130 MetaDataBaseItem *MetaDataBase::metaDataBaseItem(QObject *object) const
131 {
132     MetaDataBaseItem *i = m_items.value(object);
133     if (i == nullptr || !i->enabled())
134         return nullptr;
135     return i;
136 }
137 
add(QObject * object)138 void MetaDataBase::add(QObject *object)
139 {
140     MetaDataBaseItem *item = m_items.value(object);
141     if (item != nullptr) {
142         item->setEnabled(true);
143         if (debugMetaDatabase) {
144             qDebug() << "MetaDataBase::add: Existing item for " << object->metaObject()->className() << item->name();
145         }
146         return;
147     }
148 
149     item = new MetaDataBaseItem(object);
150     m_items.insert(object, item);
151     if (debugMetaDatabase) {
152         qDebug() << "MetaDataBase::add: New item " << object->metaObject()->className() << item->name();
153     }
154     connect(object, &QObject::destroyed, this, &MetaDataBase::slotDestroyed);
155 
156     emit changed();
157 }
158 
remove(QObject * object)159 void MetaDataBase::remove(QObject *object)
160 {
161     Q_ASSERT(object);
162 
163     if (MetaDataBaseItem *item = m_items.value(object)) {
164         item->setEnabled(false);
165         emit changed();
166     }
167 }
168 
objects() const169 QObjectList MetaDataBase::objects() const
170 {
171     QObjectList result;
172 
173     ItemMap::const_iterator it = m_items.begin();
174     for (; it != m_items.end(); ++it) {
175         if (it.value()->enabled())
176             result.append(it.key());
177     }
178 
179     return result;
180 }
181 
core() const182 QDesignerFormEditorInterface *MetaDataBase::core() const
183 {
184     return m_core;
185 }
186 
slotDestroyed(QObject * object)187 void MetaDataBase::slotDestroyed(QObject *object)
188 {
189     if (m_items.contains(object)) {
190         MetaDataBaseItem *item = m_items.value(object);
191         delete item;
192         m_items.remove(object);
193     }
194 }
195 
196 // promotion convenience
promoteWidget(QDesignerFormEditorInterface * core,QWidget * widget,const QString & customClassName)197 QDESIGNER_SHARED_EXPORT bool promoteWidget(QDesignerFormEditorInterface *core,QWidget *widget,const QString &customClassName)
198 {
199 
200     MetaDataBase *db = qobject_cast<MetaDataBase *>(core->metaDataBase());
201     if (!db)
202         return false;
203     MetaDataBaseItem *item = db->metaDataBaseItem(widget);
204     if (!item) {
205         db ->add(widget);
206         item = db->metaDataBaseItem(widget);
207     }
208     // Recursive promotion occurs if there is a plugin missing.
209     const QString oldCustomClassName = item->customClassName();
210     if (!oldCustomClassName.isEmpty()) {
211         qDebug() << "WARNING: Recursive promotion of " << oldCustomClassName << " to " << customClassName
212             << ". A plugin is missing.";
213     }
214     item->setCustomClassName(customClassName);
215     if (debugMetaDatabase) {
216         qDebug() << "Promoting " << widget->metaObject()->className() << " to " << customClassName;
217     }
218     return true;
219 }
220 
demoteWidget(QDesignerFormEditorInterface * core,QWidget * widget)221 QDESIGNER_SHARED_EXPORT void demoteWidget(QDesignerFormEditorInterface *core,QWidget *widget)
222 {
223     MetaDataBase *db = qobject_cast<MetaDataBase *>(core->metaDataBase());
224     if (!db)
225         return;
226     MetaDataBaseItem *item = db->metaDataBaseItem(widget);
227     item->setCustomClassName(QString());
228     if (debugMetaDatabase) {
229         qDebug() << "Demoting " << widget;
230     }
231 }
232 
isPromoted(QDesignerFormEditorInterface * core,QWidget * widget)233 QDESIGNER_SHARED_EXPORT bool isPromoted(QDesignerFormEditorInterface *core, QWidget* widget)
234 {
235     const MetaDataBase *db = qobject_cast<const MetaDataBase *>(core->metaDataBase());
236     if (!db)
237         return false;
238     const MetaDataBaseItem *item = db->metaDataBaseItem(widget);
239     if (!item)
240         return false;
241     return !item->customClassName().isEmpty();
242 }
243 
promotedCustomClassName(QDesignerFormEditorInterface * core,QWidget * widget)244 QDESIGNER_SHARED_EXPORT QString promotedCustomClassName(QDesignerFormEditorInterface *core, QWidget* widget)
245 {
246     const MetaDataBase *db = qobject_cast<const MetaDataBase *>(core->metaDataBase());
247     if (!db)
248         return QString();
249     const MetaDataBaseItem *item = db->metaDataBaseItem(widget);
250     if (!item)
251         return QString();
252     return item->customClassName();
253 }
254 
promotedExtends(QDesignerFormEditorInterface * core,QWidget * widget)255 QDESIGNER_SHARED_EXPORT QString promotedExtends(QDesignerFormEditorInterface *core, QWidget* widget)
256 {
257     const QString customClassName = promotedCustomClassName(core,widget);
258     if (customClassName.isEmpty())
259         return QString();
260     const int i = core->widgetDataBase()->indexOfClassName(customClassName);
261     if (i == -1)
262         return QString();
263     return core->widgetDataBase()->item(i)->extends();
264 }
265 
266 
267 } // namespace qdesigner_internal
268 
269 QT_END_NAMESPACE
270