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 "qsimpleresource_p.h"
30#include "widgetfactory_p.h"
31#include "widgetdatabase_p.h"
32
33#include <QtDesigner/private/properties_p.h>
34#include <QtDesigner/private/ui4_p.h>
35
36#include <QtDesigner/abstractformeditor.h>
37#include <QtDesigner/abstractlanguage.h>
38#include <QtDesigner/qextensionmanager.h>
39#include <QtDesigner/extrainfo.h>
40
41#include <QtUiPlugin/customwidget.h>
42
43#include <QtGui/qicon.h>
44#include <QtWidgets/qwidget.h>
45#include <QtWidgets/qaction.h>
46#include <QtCore/qdebug.h>
47#include <QtCore/qcoreapplication.h>
48
49
50QT_BEGIN_NAMESPACE
51
52namespace qdesigner_internal {
53
54bool QSimpleResource::m_warningsEnabled = true;
55
56QSimpleResource::QSimpleResource(QDesignerFormEditorInterface *core) :
57 QAbstractFormBuilder(),
58 m_core(core)
59{
60 QString workingDirectory = QDir::homePath();
61 workingDirectory += QDir::separator();
62 workingDirectory += QStringLiteral(".designer");
63 setWorkingDirectory(QDir(workingDirectory));
64}
65
66QSimpleResource::~QSimpleResource() = default;
67
68QBrush QSimpleResource::setupBrush(DomBrush *brush)
69{
70 return QAbstractFormBuilder::setupBrush(brush);
71}
72
73DomBrush *QSimpleResource::saveBrush(const QBrush &brush)
74{
75 return QAbstractFormBuilder::saveBrush(brush);
76}
77
78void QSimpleResource::addExtensionDataToDOM(QAbstractFormBuilder * /* afb */,
79 QDesignerFormEditorInterface *core,
80 DomWidget *ui_widget, QWidget *widget)
81{
82 QExtensionManager *emgr = core->extensionManager();
83 if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(manager: emgr, object: widget)) {
84 extra->saveWidgetExtraInfo(ui_widget);
85 }
86}
87
88void QSimpleResource::applyExtensionDataFromDOM(QAbstractFormBuilder * /* afb */,
89 QDesignerFormEditorInterface *core,
90 DomWidget *ui_widget, QWidget *widget)
91{
92 QExtensionManager *emgr = core->extensionManager();
93 if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(manager: emgr, object: widget)) {
94 extra->loadWidgetExtraInfo(ui_widget);
95 }
96}
97
98QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *core, QObject *object)
99{
100 return customWidgetScript(core, className: qdesigner_internal::WidgetFactory::classNameOf(core, o: object));
101}
102
103bool QSimpleResource::hasCustomWidgetScript(QDesignerFormEditorInterface *, QObject *)
104{
105 return false;
106}
107
108QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *, const QString &)
109{
110 return QString();
111}
112
113// Custom widgets handling helpers
114
115// Add unique fake slots and signals to lists
116bool QSimpleResource::addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals)
117{
118 if (!domSlots)
119 return false;
120
121 bool rc = false;
122 const QStringList &elementSlots = domSlots->elementSlot();
123 for (const QString &fakeSlot : elementSlots)
124 if (fakeSlots.indexOf(t: fakeSlot) == -1) {
125 fakeSlots += fakeSlot;
126 rc = true;
127 }
128
129 const QStringList &elementSignals = domSlots->elementSignal();
130 for (const QString &fakeSignal : elementSignals)
131 if (fakeSignals.indexOf(t: fakeSignal) == -1) {
132 fakeSignals += fakeSignal;
133 rc = true;
134 }
135 return rc;
136}
137
138void QSimpleResource::addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item)
139{
140 const DomSlots *domSlots = domCustomWidget->elementSlots();
141 if (!domSlots)
142 return;
143
144 // Merge in new slots, signals
145 QStringList fakeSlots = item->fakeSlots();
146 QStringList fakeSignals = item->fakeSignals();
147 if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) {
148 item->setFakeSlots(fakeSlots);
149 item->setFakeSignals(fakeSignals);
150 }
151}
152
153// Perform one iteration of adding the custom widgets to the database,
154// looking up the base class and inheriting its data.
155// Remove the succeeded custom widgets from the list.
156// Classes whose base class could not be found are left in the list.
157
158void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core,
159 QVector<DomCustomWidget *> &custom_widget_list)
160{
161 QDesignerWidgetDataBaseInterface *db = core->widgetDataBase();
162 for (int i=0; i < custom_widget_list.size(); ) {
163 bool classInserted = false;
164 DomCustomWidget *custom_widget = custom_widget_list[i];
165 const QString customClassName = custom_widget->elementClass();
166 const QString base_class = custom_widget->elementExtends();
167 QString includeFile;
168 IncludeType includeType = IncludeLocal;
169 if (const DomHeader *header = custom_widget->elementHeader()) {
170 includeFile = header->text();
171 if (header->hasAttributeLocation() && header->attributeLocation() == QStringLiteral("global"))
172 includeType = IncludeGlobal;
173 }
174 const bool domIsContainer = custom_widget->elementContainer();
175 // Append a new item
176 if (base_class.isEmpty()) {
177 WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName);
178 item->setPromoted(false);
179 item->setGroup(QCoreApplication::translate(context: "Designer", key: "Custom Widgets"));
180 item->setIncludeFile(buildIncludeFile(includeFile, includeType));
181 item->setContainer(domIsContainer);
182 item->setCustom(true);
183 addFakeMethodsToWidgetDataBase(domCustomWidget: custom_widget, item);
184 db->append(item);
185 custom_widget_list.removeAt(i);
186 classInserted = true;
187 } else {
188 // Create a new entry cloned from base class. Note that this will ignore existing
189 // classes, eg, plugin custom widgets.
190 QDesignerWidgetDataBaseItemInterface *item =
191 appendDerived(db, className: customClassName, group: QCoreApplication::translate(context: "Designer", key: "Promoted Widgets"),
192 baseClassName: base_class,
193 includeFile: buildIncludeFile(includeFile, includeType),
194 promoted: true,custom: true);
195 // Ok, base class found.
196 if (item) {
197 // Hack to accommodate for old UI-files in which "container" is not set properly:
198 // Apply "container" from DOM only if true (else, eg classes from QFrame might not accept
199 // dropping child widgets on them as container=false). This also allows for
200 // QWidget-derived stacked pages.
201 if (domIsContainer)
202 item->setContainer(domIsContainer);
203
204 addFakeMethodsToWidgetDataBase(domCustomWidget: custom_widget, item: static_cast<WidgetDataBaseItem*>(item));
205 custom_widget_list.removeAt(i);
206 classInserted = true;
207 }
208 }
209 // Skip failed item.
210 if (!classInserted)
211 i++;
212 }
213
214}
215
216void QSimpleResource::handleDomCustomWidgets(const QDesignerFormEditorInterface *core,
217 const DomCustomWidgets *dom_custom_widgets)
218{
219 if (dom_custom_widgets == nullptr)
220 return;
221 auto custom_widget_list = dom_custom_widgets->elementCustomWidget();
222 // Attempt to insert each item derived from its base class.
223 // This should at most require two iterations in the event that the classes are out of order
224 // (derived first, max depth: promoted custom plugin = 2)
225 for (int iteration = 0; iteration < 2; iteration++) {
226 addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
227 if (custom_widget_list.isEmpty())
228 return;
229 }
230 // Oops, there are classes left whose base class could not be found.
231 // Default them to QWidget with warnings.
232 const QString fallBackBaseClass = QStringLiteral("QWidget");
233 for (DomCustomWidget *custom_widget : qAsConst(t&: custom_widget_list)) {
234 const QString customClassName = custom_widget->elementClass();
235 const QString base_class = custom_widget->elementExtends();
236 qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName
237 << " could not be found. Defaulting to " << fallBackBaseClass << '.';
238 custom_widget->setElementExtends(fallBackBaseClass);
239 }
240 // One more pass.
241 addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
242}
243
244// ------------ FormBuilderClipboard
245
246FormBuilderClipboard::FormBuilderClipboard(QWidget *w)
247{
248 m_widgets += w;
249}
250
251bool FormBuilderClipboard::empty() const
252{
253 return m_widgets.isEmpty() && m_actions.isEmpty();
254}
255}
256
257QT_END_NAMESPACE
258

source code of qttools/src/designer/src/lib/shared/qsimpleresource.cpp