source: trunk/tools/designer/src/lib/shared/qsimpleresource.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 15.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Designer of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qsimpleresource_p.h"
43#include "widgetfactory_p.h"
44#include "widgetdatabase_p.h"
45
46#include <formscriptrunner_p.h>
47#include <properties_p.h>
48#include <ui4_p.h>
49
50#include <QtDesigner/QDesignerFormEditorInterface>
51#include <QtDesigner/QDesignerLanguageExtension>
52#include <script_p.h>
53#include <QtDesigner/QExtensionManager>
54#include <QtDesigner/QDesignerCustomWidgetInterface>
55#include <QtDesigner/extrainfo.h>
56
57#include <QtGui/QIcon>
58#include <QtGui/QWidget>
59#include <QtGui/QAction>
60#include <QtCore/QDebug>
61#include <QtCore/QCoreApplication>
62
63
64QT_BEGIN_NAMESPACE
65
66namespace {
67 typedef QList<DomWidgetData*> DomWidgetDataList;
68 typedef QList<DomProperty*> DomPropertyList;
69 typedef QList<QDesignerCustomWidgetInterface *> CustomWidgetInterfaces;
70}
71
72namespace qdesigner_internal {
73
74bool QSimpleResource::m_warningsEnabled = true;
75
76QSimpleResource::QSimpleResource(QDesignerFormEditorInterface *core) :
77 QAbstractFormBuilder(),
78 m_core(core)
79{
80 QString workingDirectory = QDir::homePath();
81 workingDirectory += QDir::separator();
82 workingDirectory += QLatin1String(".designer");
83 setWorkingDirectory(QDir(workingDirectory));
84#ifndef QT_FORMBUILDER_NO_SCRIPT
85 // Disable scripting in the editors.
86 formScriptRunner()-> setOptions(QFormScriptRunner::DisableScripts);
87#endif
88}
89
90QSimpleResource::~QSimpleResource()
91{
92
93}
94
95QBrush QSimpleResource::setupBrush(DomBrush *brush)
96{
97 return QAbstractFormBuilder::setupBrush(brush);
98}
99
100DomBrush *QSimpleResource::saveBrush(const QBrush &brush)
101{
102 return QAbstractFormBuilder::saveBrush(brush);
103}
104
105QIcon QSimpleResource::nameToIcon(const QString &filePath, const QString &qrcPath)
106{
107 Q_UNUSED(filePath)
108 Q_UNUSED(qrcPath)
109 qWarning() << "QSimpleResource::nameToIcon() is obsoleted";
110 return QIcon();
111}
112
113QString QSimpleResource::iconToFilePath(const QIcon &pm) const
114{
115 Q_UNUSED(pm)
116 qWarning() << "QSimpleResource::iconToFilePath() is obsoleted";
117 return QString();
118}
119
120QString QSimpleResource::iconToQrcPath(const QIcon &pm) const
121{
122 Q_UNUSED(pm)
123 qWarning() << "QSimpleResource::iconToQrcPath() is obsoleted";
124 return QString();
125}
126
127QPixmap QSimpleResource::nameToPixmap(const QString &filePath, const QString &qrcPath)
128{
129 Q_UNUSED(filePath)
130 Q_UNUSED(qrcPath)
131 qWarning() << "QSimpleResource::nameToPixmap() is obsoleted";
132 return QPixmap();
133}
134
135QString QSimpleResource::pixmapToFilePath(const QPixmap &pm) const
136{
137 Q_UNUSED(pm)
138 qWarning() << "QSimpleResource::pixmapToFilePath() is obsoleted";
139 return QString();
140}
141
142QString QSimpleResource::pixmapToQrcPath(const QPixmap &pm) const
143{
144 Q_UNUSED(pm)
145 qWarning() << "QSimpleResource::pixmapToQrcPath() is obsoleted";
146 return QString();
147}
148
149DomScript *QSimpleResource::createScript(const QString &script, ScriptSource source)
150{
151 if (script.isEmpty())
152 return 0;
153 DomScript *domScript = new DomScript();
154 switch (source) {
155 case ScriptExtension:
156 domScript->setAttributeSource(QLatin1String("extension"));
157 break;
158 case ScriptDesigner:
159 domScript->setAttributeSource(QLatin1String("designer"));
160 break;
161 case ScriptCustomWidgetPlugin:
162 domScript->setAttributeSource(QLatin1String("customwidgetplugin"));
163 break;
164 }
165 domScript->setAttributeLanguage(QLatin1String("Qt Script"));
166 domScript->setText(script);
167 return domScript;
168}
169
170// Add a script to a list of DomScripts unless empty
171void QSimpleResource::addScript(const QString &script, ScriptSource source, DomScripts &domScripts)
172{
173 if (DomScript *domScript = createScript(script, source)) {
174 domScripts += domScript;
175 }
176}
177
178void QSimpleResource::addExtensionDataToDOM(QAbstractFormBuilder *afb,
179 QDesignerFormEditorInterface *core,
180 DomWidget *ui_widget, QWidget *widget)
181{
182 QExtensionManager *emgr = core->extensionManager();
183 if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
184 extra->saveWidgetExtraInfo(ui_widget);
185 }
186 if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
187 // Add internal state
188 const QVariantMap data = scriptExt->data();
189 if (!data.empty()) {
190 // Convert the map to a DomState.
191 // We pass on the widget for property introspection. Thus, non-designable properties
192 // that have to be converted using QMetaObject (enums and the like) will work.
193 DomPropertyList properties;
194 const QVariantMap::const_iterator vcend = data.constEnd();
195 for (QVariantMap::const_iterator it = data.constBegin(); it != vcend; ++it) {
196 if (DomProperty *prop = variantToDomProperty(afb, widget->metaObject(), it.key(), it.value()))
197 properties += prop;
198 }
199 if (!properties.empty()) {
200 DomWidgetData *domData = new DomWidgetData;
201 domData->setElementProperty(properties);
202 DomWidgetDataList domDataList;
203 domDataList += domData;
204 ui_widget->setElementWidgetData(domDataList);
205 }
206
207 }
208 // Add script
209 const QString script = scriptExt->script();
210 if (!script.isEmpty()) {
211 DomScripts domScripts = ui_widget->elementScript();
212 addScript(script, ScriptExtension, domScripts);
213 ui_widget->setElementScript(domScripts);
214 }
215 }
216}
217
218void QSimpleResource::applyExtensionDataFromDOM(QAbstractFormBuilder *afb,
219 QDesignerFormEditorInterface *core,
220 DomWidget *ui_widget, QWidget *widget, bool applyState)
221{
222 QExtensionManager *emgr = core->extensionManager();
223 if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
224 extra->loadWidgetExtraInfo(ui_widget);
225 }
226 if (applyState) {
227 if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
228 // Apply the state.
229 // We pass on the widget for property introspection. Thus, non-designable properties
230 // that have to be converted using QMetaObject (enums and the like) will work.
231 QVariantMap data;
232 DomWidgetDataList domDataList = ui_widget->elementWidgetData();
233 if (!domDataList.empty()) {
234 foreach (const DomWidgetData *domData, domDataList) {
235 const DomPropertyList properties = domData->elementProperty();
236 foreach(const DomProperty *prop, properties) {
237 const QVariant vprop = domPropertyToVariant(afb, widget->metaObject(), prop);
238 if (vprop.type() != QVariant::Invalid)
239 data.insert(prop->attributeName(), vprop);
240 }
241 }
242 }
243 scriptExt->setData(data);
244 }
245 }
246}
247
248QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *core, QObject *object)
249{
250 return customWidgetScript(core, qdesigner_internal::WidgetFactory::classNameOf(core, object));
251}
252
253bool QSimpleResource::hasCustomWidgetScript(QDesignerFormEditorInterface *, QObject *)
254{
255 return false;
256}
257
258QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *, const QString &)
259{
260 return QString();
261}
262
263bool QSimpleResource::setWarningsEnabled(bool warningsEnabled)
264{
265 const bool rc = m_warningsEnabled;
266 m_warningsEnabled = warningsEnabled;
267 return rc;
268}
269
270bool QSimpleResource::warningsEnabled()
271{
272 return m_warningsEnabled;
273}
274
275// Custom widgets handling helpers
276
277// Add unique fake slots and signals to lists
278bool QSimpleResource::addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals)
279{
280 if (!domSlots)
281 return false;
282
283 bool rc = false;
284 foreach (const QString &fakeSlot, domSlots->elementSlot())
285 if (fakeSlots.indexOf(fakeSlot) == -1) {
286 fakeSlots += fakeSlot;
287 rc = true;
288 }
289
290 foreach (const QString &fakeSignal, domSlots->elementSignal())
291 if (fakeSignals.indexOf(fakeSignal) == -1) {
292 fakeSignals += fakeSignal;
293 rc = true;
294 }
295 return rc;
296}
297
298void QSimpleResource::addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item)
299{
300 const DomSlots *domSlots = domCustomWidget->elementSlots();
301 if (!domSlots)
302 return;
303
304 // Merge in new slots, signals
305 QStringList fakeSlots = item->fakeSlots();
306 QStringList fakeSignals = item->fakeSignals();
307 if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) {
308 item->setFakeSlots(fakeSlots);
309 item->setFakeSignals(fakeSignals);
310 }
311}
312
313// Perform one iteration of adding the custom widgets to the database,
314// looking up the base class and inheriting its data.
315// Remove the succeeded custom widgets from the list.
316// Classes whose base class could not be found are left in the list.
317
318void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core,
319 QList<DomCustomWidget*>& custom_widget_list)
320{
321 QDesignerWidgetDataBaseInterface *db = core->widgetDataBase();
322 for (int i=0; i < custom_widget_list.size(); ) {
323 bool classInserted = false;
324 DomCustomWidget *custom_widget = custom_widget_list[i];
325 const QString customClassName = custom_widget->elementClass();
326 const QString base_class = custom_widget->elementExtends();
327 QString includeFile;
328 IncludeType includeType = IncludeLocal;
329 if (const DomHeader *header = custom_widget->elementHeader()) {
330 includeFile = header->text();
331 if (header->hasAttributeLocation() && header->attributeLocation() == QLatin1String("global"))
332 includeType = IncludeGlobal;
333 }
334 const bool domIsContainer = custom_widget->elementContainer();
335 // Append a new item
336 if (base_class.isEmpty()) {
337 WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName);
338 item->setPromoted(false);
339 item->setGroup(QCoreApplication::translate("Designer", "Custom Widgets"));
340 item->setIncludeFile(buildIncludeFile(includeFile, includeType));
341 item->setContainer(domIsContainer);
342 item->setCustom(true);
343 addFakeMethodsToWidgetDataBase(custom_widget, item);
344 db->append(item);
345 custom_widget_list.removeAt(i);
346 classInserted = true;
347 } else {
348 // Create a new entry cloned from base class. Note that this will ignore existing
349 // classes, eg, plugin custom widgets.
350 QDesignerWidgetDataBaseItemInterface *item =
351 appendDerived(db, customClassName, QCoreApplication::translate("Designer", "Promoted Widgets"),
352 base_class,
353 buildIncludeFile(includeFile, includeType),
354 true,true);
355 // Ok, base class found.
356 if (item) {
357 // Hack to accommodate for old UI-files in which "container" is not set properly:
358 // Apply "container" from DOM only if true (else, eg classes from QFrame might not accept
359 // dropping child widgets on them as container=false). This also allows for
360 // QWidget-derived stacked pages.
361 if (domIsContainer)
362 item->setContainer(domIsContainer);
363
364 addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item));
365 custom_widget_list.removeAt(i);
366 classInserted = true;
367 }
368 }
369 // Skip failed item.
370 if (!classInserted)
371 i++;
372 }
373
374}
375
376void QSimpleResource::handleDomCustomWidgets(const QDesignerFormEditorInterface *core,
377 const DomCustomWidgets *dom_custom_widgets)
378{
379 if (dom_custom_widgets == 0)
380 return;
381 QList<DomCustomWidget*> custom_widget_list = dom_custom_widgets->elementCustomWidget();
382 // Attempt to insert each item derived from its base class.
383 // This should at most require two iterations in the event that the classes are out of order
384 // (derived first, max depth: promoted custom plugin = 2)
385 for (int iteration = 0; iteration < 2; iteration++) {
386 addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
387 if (custom_widget_list.empty())
388 return;
389 }
390 // Oops, there are classes left whose base class could not be found.
391 // Default them to QWidget with warnings.
392 const QString fallBackBaseClass = QLatin1String("QWidget");
393 for (int i=0; i < custom_widget_list.size(); i++ ) {
394 DomCustomWidget *custom_widget = custom_widget_list[i];
395 const QString customClassName = custom_widget->elementClass();
396 const QString base_class = custom_widget->elementExtends();
397 qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName
398 << " could not be found. Defaulting to " << fallBackBaseClass << '.';
399 custom_widget->setElementExtends(fallBackBaseClass);
400 }
401 // One more pass.
402 addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
403}
404
405// ------------ FormBuilderClipboard
406
407FormBuilderClipboard::FormBuilderClipboard(QWidget *w)
408{
409 m_widgets += w;
410}
411
412bool FormBuilderClipboard::empty() const
413{
414 return m_widgets.empty() && m_actions.empty();
415}
416}
417
418QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.