| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the Qt Designer of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qsimpleresource_p.h" |
| #include "widgetfactory_p.h" |
| #include "widgetdatabase_p.h" |
| |
| #include <formscriptrunner_p.h> |
| #include <properties_p.h> |
| #include <ui4_p.h> |
| |
| #include <QtDesigner/QDesignerFormEditorInterface> |
| #include <QtDesigner/QDesignerLanguageExtension> |
| #include <script_p.h> |
| #include <QtDesigner/QExtensionManager> |
| #include <QtDesigner/QDesignerCustomWidgetInterface> |
| #include <QtDesigner/extrainfo.h> |
| |
| #include <QtGui/QIcon> |
| #include <QtGui/QWidget> |
| #include <QtGui/QAction> |
| #include <QtCore/QDebug> |
| #include <QtCore/QCoreApplication> |
| |
| |
| QT_BEGIN_NAMESPACE |
| |
| namespace { |
| typedef QList<DomWidgetData*> DomWidgetDataList; |
| typedef QList<DomProperty*> DomPropertyList; |
| typedef QList<QDesignerCustomWidgetInterface *> CustomWidgetInterfaces; |
| } |
| |
| namespace qdesigner_internal { |
| |
| bool QSimpleResource::m_warningsEnabled = true; |
| |
| QSimpleResource::QSimpleResource(QDesignerFormEditorInterface *core) : |
| QAbstractFormBuilder(), |
| m_core(core) |
| { |
| QString workingDirectory = QDir::homePath(); |
| workingDirectory += QDir::separator(); |
| workingDirectory += QLatin1String(".designer"); |
| setWorkingDirectory(QDir(workingDirectory)); |
| #ifndef QT_FORMBUILDER_NO_SCRIPT |
| // Disable scripting in the editors. |
| formScriptRunner()-> setOptions(QFormScriptRunner::DisableScripts); |
| #endif |
| } |
| |
| QSimpleResource::~QSimpleResource() |
| { |
| |
| } |
| |
| QBrush QSimpleResource::setupBrush(DomBrush *brush) |
| { |
| return QAbstractFormBuilder::setupBrush(brush); |
| } |
| |
| DomBrush *QSimpleResource::saveBrush(const QBrush &brush) |
| { |
| return QAbstractFormBuilder::saveBrush(brush); |
| } |
| |
| QIcon QSimpleResource::nameToIcon(const QString &filePath, const QString &qrcPath) |
| { |
| Q_UNUSED(filePath) |
| Q_UNUSED(qrcPath) |
| qWarning() << "QSimpleResource::nameToIcon() is obsoleted"; |
| return QIcon(); |
| } |
| |
| QString QSimpleResource::iconToFilePath(const QIcon &pm) const |
| { |
| Q_UNUSED(pm) |
| qWarning() << "QSimpleResource::iconToFilePath() is obsoleted"; |
| return QString(); |
| } |
| |
| QString QSimpleResource::iconToQrcPath(const QIcon &pm) const |
| { |
| Q_UNUSED(pm) |
| qWarning() << "QSimpleResource::iconToQrcPath() is obsoleted"; |
| return QString(); |
| } |
| |
| QPixmap QSimpleResource::nameToPixmap(const QString &filePath, const QString &qrcPath) |
| { |
| Q_UNUSED(filePath) |
| Q_UNUSED(qrcPath) |
| qWarning() << "QSimpleResource::nameToPixmap() is obsoleted"; |
| return QPixmap(); |
| } |
| |
| QString QSimpleResource::pixmapToFilePath(const QPixmap &pm) const |
| { |
| Q_UNUSED(pm) |
| qWarning() << "QSimpleResource::pixmapToFilePath() is obsoleted"; |
| return QString(); |
| } |
| |
| QString QSimpleResource::pixmapToQrcPath(const QPixmap &pm) const |
| { |
| Q_UNUSED(pm) |
| qWarning() << "QSimpleResource::pixmapToQrcPath() is obsoleted"; |
| return QString(); |
| } |
| |
| DomScript *QSimpleResource::createScript(const QString &script, ScriptSource source) |
| { |
| if (script.isEmpty()) |
| return 0; |
| DomScript *domScript = new DomScript(); |
| switch (source) { |
| case ScriptExtension: |
| domScript->setAttributeSource(QLatin1String("extension")); |
| break; |
| case ScriptDesigner: |
| domScript->setAttributeSource(QLatin1String("designer")); |
| break; |
| case ScriptCustomWidgetPlugin: |
| domScript->setAttributeSource(QLatin1String("customwidgetplugin")); |
| break; |
| } |
| domScript->setAttributeLanguage(QLatin1String("Qt Script")); |
| domScript->setText(script); |
| return domScript; |
| } |
| |
| // Add a script to a list of DomScripts unless empty |
| void QSimpleResource::addScript(const QString &script, ScriptSource source, DomScripts &domScripts) |
| { |
| if (DomScript *domScript = createScript(script, source)) { |
| domScripts += domScript; |
| } |
| } |
| |
| void QSimpleResource::addExtensionDataToDOM(QAbstractFormBuilder *afb, |
| QDesignerFormEditorInterface *core, |
| DomWidget *ui_widget, QWidget *widget) |
| { |
| QExtensionManager *emgr = core->extensionManager(); |
| if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) { |
| extra->saveWidgetExtraInfo(ui_widget); |
| } |
| if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) { |
| // Add internal state |
| const QVariantMap data = scriptExt->data(); |
| if (!data.empty()) { |
| // Convert the map to a DomState. |
| // We pass on the widget for property introspection. Thus, non-designable properties |
| // that have to be converted using QMetaObject (enums and the like) will work. |
| DomPropertyList properties; |
| const QVariantMap::const_iterator vcend = data.constEnd(); |
| for (QVariantMap::const_iterator it = data.constBegin(); it != vcend; ++it) { |
| if (DomProperty *prop = variantToDomProperty(afb, widget->metaObject(), it.key(), it.value())) |
| properties += prop; |
| } |
| if (!properties.empty()) { |
| DomWidgetData *domData = new DomWidgetData; |
| domData->setElementProperty(properties); |
| DomWidgetDataList domDataList; |
| domDataList += domData; |
| ui_widget->setElementWidgetData(domDataList); |
| } |
| |
| } |
| // Add script |
| const QString script = scriptExt->script(); |
| if (!script.isEmpty()) { |
| DomScripts domScripts = ui_widget->elementScript(); |
| addScript(script, ScriptExtension, domScripts); |
| ui_widget->setElementScript(domScripts); |
| } |
| } |
| } |
| |
| void QSimpleResource::applyExtensionDataFromDOM(QAbstractFormBuilder *afb, |
| QDesignerFormEditorInterface *core, |
| DomWidget *ui_widget, QWidget *widget, bool applyState) |
| { |
| QExtensionManager *emgr = core->extensionManager(); |
| if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) { |
| extra->loadWidgetExtraInfo(ui_widget); |
| } |
| if (applyState) { |
| if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) { |
| // Apply the state. |
| // We pass on the widget for property introspection. Thus, non-designable properties |
| // that have to be converted using QMetaObject (enums and the like) will work. |
| QVariantMap data; |
| DomWidgetDataList domDataList = ui_widget->elementWidgetData(); |
| if (!domDataList.empty()) { |
| foreach (const DomWidgetData *domData, domDataList) { |
| const DomPropertyList properties = domData->elementProperty(); |
| foreach(const DomProperty *prop, properties) { |
| const QVariant vprop = domPropertyToVariant(afb, widget->metaObject(), prop); |
| if (vprop.type() != QVariant::Invalid) |
| data.insert(prop->attributeName(), vprop); |
| } |
| } |
| } |
| scriptExt->setData(data); |
| } |
| } |
| } |
| |
| QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *core, QObject *object) |
| { |
| return customWidgetScript(core, qdesigner_internal::WidgetFactory::classNameOf(core, object)); |
| } |
| |
| bool QSimpleResource::hasCustomWidgetScript(QDesignerFormEditorInterface *, QObject *) |
| { |
| return false; |
| } |
| |
| QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *, const QString &) |
| { |
| return QString(); |
| } |
| |
| bool QSimpleResource::setWarningsEnabled(bool warningsEnabled) |
| { |
| const bool rc = m_warningsEnabled; |
| m_warningsEnabled = warningsEnabled; |
| return rc; |
| } |
| |
| bool QSimpleResource::warningsEnabled() |
| { |
| return m_warningsEnabled; |
| } |
| |
| // Custom widgets handling helpers |
| |
| // Add unique fake slots and signals to lists |
| bool QSimpleResource::addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals) |
| { |
| if (!domSlots) |
| return false; |
| |
| bool rc = false; |
| foreach (const QString &fakeSlot, domSlots->elementSlot()) |
| if (fakeSlots.indexOf(fakeSlot) == -1) { |
| fakeSlots += fakeSlot; |
| rc = true; |
| } |
| |
| foreach (const QString &fakeSignal, domSlots->elementSignal()) |
| if (fakeSignals.indexOf(fakeSignal) == -1) { |
| fakeSignals += fakeSignal; |
| rc = true; |
| } |
| return rc; |
| } |
| |
| void QSimpleResource::addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item) |
| { |
| const DomSlots *domSlots = domCustomWidget->elementSlots(); |
| if (!domSlots) |
| return; |
| |
| // Merge in new slots, signals |
| QStringList fakeSlots = item->fakeSlots(); |
| QStringList fakeSignals = item->fakeSignals(); |
| if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) { |
| item->setFakeSlots(fakeSlots); |
| item->setFakeSignals(fakeSignals); |
| } |
| } |
| |
| // Perform one iteration of adding the custom widgets to the database, |
| // looking up the base class and inheriting its data. |
| // Remove the succeeded custom widgets from the list. |
| // Classes whose base class could not be found are left in the list. |
| |
| void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core, |
| QList<DomCustomWidget*>& custom_widget_list) |
| { |
| QDesignerWidgetDataBaseInterface *db = core->widgetDataBase(); |
| for (int i=0; i < custom_widget_list.size(); ) { |
| bool classInserted = false; |
| DomCustomWidget *custom_widget = custom_widget_list[i]; |
| const QString customClassName = custom_widget->elementClass(); |
| const QString base_class = custom_widget->elementExtends(); |
| QString includeFile; |
| IncludeType includeType = IncludeLocal; |
| if (const DomHeader *header = custom_widget->elementHeader()) { |
| includeFile = header->text(); |
| if (header->hasAttributeLocation() && header->attributeLocation() == QLatin1String("global")) |
| includeType = IncludeGlobal; |
| } |
| const bool domIsContainer = custom_widget->elementContainer(); |
| // Append a new item |
| if (base_class.isEmpty()) { |
| WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName); |
| item->setPromoted(false); |
| item->setGroup(QCoreApplication::translate("Designer", "Custom Widgets")); |
| item->setIncludeFile(buildIncludeFile(includeFile, includeType)); |
| item->setContainer(domIsContainer); |
| item->setCustom(true); |
| addFakeMethodsToWidgetDataBase(custom_widget, item); |
| db->append(item); |
| custom_widget_list.removeAt(i); |
| classInserted = true; |
| } else { |
| // Create a new entry cloned from base class. Note that this will ignore existing |
| // classes, eg, plugin custom widgets. |
| QDesignerWidgetDataBaseItemInterface *item = |
| appendDerived(db, customClassName, QCoreApplication::translate("Designer", "Promoted Widgets"), |
| base_class, |
| buildIncludeFile(includeFile, includeType), |
| true,true); |
| // Ok, base class found. |
| if (item) { |
| // Hack to accommodate for old UI-files in which "container" is not set properly: |
| // Apply "container" from DOM only if true (else, eg classes from QFrame might not accept |
| // dropping child widgets on them as container=false). This also allows for |
| // QWidget-derived stacked pages. |
| if (domIsContainer) |
| item->setContainer(domIsContainer); |
| |
| addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item)); |
| custom_widget_list.removeAt(i); |
| classInserted = true; |
| } |
| } |
| // Skip failed item. |
| if (!classInserted) |
| i++; |
| } |
| |
| } |
| |
| void QSimpleResource::handleDomCustomWidgets(const QDesignerFormEditorInterface *core, |
| const DomCustomWidgets *dom_custom_widgets) |
| { |
| if (dom_custom_widgets == 0) |
| return; |
| QList<DomCustomWidget*> custom_widget_list = dom_custom_widgets->elementCustomWidget(); |
| // Attempt to insert each item derived from its base class. |
| // This should at most require two iterations in the event that the classes are out of order |
| // (derived first, max depth: promoted custom plugin = 2) |
| for (int iteration = 0; iteration < 2; iteration++) { |
| addCustomWidgetsToWidgetDatabase(core, custom_widget_list); |
| if (custom_widget_list.empty()) |
| return; |
| } |
| // Oops, there are classes left whose base class could not be found. |
| // Default them to QWidget with warnings. |
| const QString fallBackBaseClass = QLatin1String("QWidget"); |
| for (int i=0; i < custom_widget_list.size(); i++ ) { |
| DomCustomWidget *custom_widget = custom_widget_list[i]; |
| const QString customClassName = custom_widget->elementClass(); |
| const QString base_class = custom_widget->elementExtends(); |
| qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName |
| << " could not be found. Defaulting to " << fallBackBaseClass << '.'; |
| custom_widget->setElementExtends(fallBackBaseClass); |
| } |
| // One more pass. |
| addCustomWidgetsToWidgetDatabase(core, custom_widget_list); |
| } |
| |
| // ------------ FormBuilderClipboard |
| |
| FormBuilderClipboard::FormBuilderClipboard(QWidget *w) |
| { |
| m_widgets += w; |
| } |
| |
| bool FormBuilderClipboard::empty() const |
| { |
| return m_widgets.empty() && m_actions.empty(); |
| } |
| } |
| |
| QT_END_NAMESPACE |