diff options
Diffstat (limited to 'src/designer/src/lib/shared/qdesigner_formbuilder.cpp')
-rw-r--r-- | src/designer/src/lib/shared/qdesigner_formbuilder.cpp | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/src/designer/src/lib/shared/qdesigner_formbuilder.cpp b/src/designer/src/lib/shared/qdesigner_formbuilder.cpp new file mode 100644 index 000000000..a8054748b --- /dev/null +++ b/src/designer/src/lib/shared/qdesigner_formbuilder.cpp @@ -0,0 +1,498 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdesigner_formbuilder_p.h" +#include "dynamicpropertysheet.h" +#include "qsimpleresource_p.h" +#include "widgetfactory_p.h" +#include "qdesigner_introspection_p.h" + +#include <ui4_p.h> +#include <formbuilderextra_p.h> +// sdk +#include <QtDesigner/container.h> +#include <QtDesigner/customwidget.h> +#include <QtDesigner/propertysheet.h> +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowInterface> +#include <QtDesigner/QDesignerWidgetFactoryInterface> +#include <QtDesigner/QDesignerCustomWidgetInterface> +#include <abstractdialoggui_p.h> + +// shared +#include <qdesigner_propertysheet_p.h> +#include <qdesigner_utils_p.h> +#include <formwindowbase_p.h> +#include <qtresourcemodel_p.h> +#include <scripterrordialog_p.h> + +#include <QtGui/QWidget> +#include <QtGui/QMenu> +#include <QtGui/QToolBar> +#include <QtGui/QMenuBar> +#include <QtGui/QMainWindow> +#include <QtGui/QStyleFactory> +#include <QtGui/QStyle> +#include <QtGui/QApplication> +#include <QtGui/QAbstractScrollArea> +#include <QtGui/QMessageBox> +#include <QtGui/QPixmap> + +#include <QtCore/QBuffer> +#include <QtCore/qdebug.h> +#include <QtCore/QCoreApplication> + +QT_BEGIN_NAMESPACE + +#ifndef QT_FORMBUILDER_NO_SCRIPT +static QString summarizeScriptErrors(const QFormScriptRunner::Errors &errors) +{ + QString rc = QCoreApplication::translate("QDesignerFormBuilder", "Script errors occurred:"); + foreach (QFormScriptRunner::Error error, errors) { + rc += QLatin1Char('\n'); + rc += error.errorMessage; + } + return rc; +} +#endif + +namespace qdesigner_internal { + +QDesignerFormBuilder::QDesignerFormBuilder(QDesignerFormEditorInterface *core, + Mode mode, + const DeviceProfile &deviceProfile) : + m_core(core), + m_mode(mode), + m_deviceProfile(deviceProfile), + m_pixmapCache(0), + m_iconCache(0), + m_ignoreCreateResources(false), + m_tempResourceSet(0), + m_mainWidget(true) +{ + Q_ASSERT(m_core); +#ifndef QT_FORMBUILDER_NO_SCRIPT + // Disable scripting in the editors. + QFormScriptRunner::Options options = formScriptRunner()->options(); + switch (m_mode) { + case DisableScripts: + options |= QFormScriptRunner::DisableScripts; + break; + case EnableScripts: + options |= QFormScriptRunner::DisableWarnings; + options &= ~QFormScriptRunner::DisableScripts; + break; + } + formScriptRunner()-> setOptions(options); +#endif +} + +QString QDesignerFormBuilder::systemStyle() const +{ + return m_deviceProfile.isEmpty() ? + QString::fromUtf8(QApplication::style()->metaObject()->className()) : + m_deviceProfile.style(); +} + +QWidget *QDesignerFormBuilder::createWidgetFromContents(const QString &contents, QWidget *parentWidget) +{ + QByteArray data = contents.toUtf8(); + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + return load(&buffer, parentWidget); +} + +QWidget *QDesignerFormBuilder::create(DomUI *ui, QWidget *parentWidget) +{ + m_mainWidget = true; + QtResourceSet *resourceSet = core()->resourceModel()->currentResourceSet(); + + // reload resource properties; + createResources(ui->elementResources()); + core()->resourceModel()->setCurrentResourceSet(m_tempResourceSet); + + m_ignoreCreateResources = true; + DesignerPixmapCache pixmapCache; + DesignerIconCache iconCache(&pixmapCache); + m_pixmapCache = &pixmapCache; + m_iconCache = &iconCache; + + QWidget *widget = QFormBuilder::create(ui, parentWidget); + + core()->resourceModel()->setCurrentResourceSet(resourceSet); + core()->resourceModel()->removeResourceSet(m_tempResourceSet); + m_tempResourceSet = 0; + m_ignoreCreateResources = false; + m_pixmapCache = 0; + m_iconCache = 0; + + m_customWidgetsWithScript.clear(); + return widget; +} + +QWidget *QDesignerFormBuilder::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name) +{ + QWidget *widget = 0; + + if (widgetName == QLatin1String("QToolBar")) { + widget = new QToolBar(parentWidget); + } else if (widgetName == QLatin1String("QMenu")) { + widget = new QMenu(parentWidget); + } else if (widgetName == QLatin1String("QMenuBar")) { + widget = new QMenuBar(parentWidget); + } else { + widget = core()->widgetFactory()->createWidget(widgetName, parentWidget); + } + + if (widget) { + widget->setObjectName(name); + if (QSimpleResource::hasCustomWidgetScript(m_core, widget)) + m_customWidgetsWithScript.insert(widget); + } + + if (m_mainWidget) { // We need to apply the DPI here to take effect on size hints, etc. + m_deviceProfile.apply(m_core, widget, DeviceProfile::ApplyPreview); + m_mainWidget = false; + } + return widget; +} + +bool QDesignerFormBuilder::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) +{ + // Use container extension or rely on scripts unless main window. + if (QFormBuilder::addItem(ui_widget, widget, parentWidget)) + return true; + + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), parentWidget)) { + container->addWidget(widget); + return true; + } + return false; +} + +bool QDesignerFormBuilder::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout) +{ + return QFormBuilder::addItem(ui_item, item, layout); +} + +QIcon QDesignerFormBuilder::nameToIcon(const QString &filePath, const QString &qrcPath) +{ + Q_UNUSED(filePath) + Q_UNUSED(qrcPath) + qWarning() << "QDesignerFormBuilder::nameToIcon() is obsoleted"; + return QIcon(); +} + +QPixmap QDesignerFormBuilder::nameToPixmap(const QString &filePath, const QString &qrcPath) +{ + Q_UNUSED(filePath) + Q_UNUSED(qrcPath) + qWarning() << "QDesignerFormBuilder::nameToPixmap() is obsoleted"; + return QPixmap(); +} + +/* If the property is a enum or flag value, retrieve + * the existing enum/flag type via property sheet and use it to convert */ + +static bool readDomEnumerationValue(const DomProperty *p, + const QDesignerPropertySheetExtension* sheet, + QVariant &v) +{ + switch (p->kind()) { + case DomProperty::Set: { + const int index = sheet->indexOf(p->attributeName()); + if (index == -1) + return false; + const QVariant sheetValue = sheet->property(index); + if (sheetValue.canConvert<PropertySheetFlagValue>()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); + bool ok = false; + v = f.metaFlags.parseFlags(p->elementSet(), &ok); + if (!ok) + designerWarning(f.metaFlags.messageParseFailed(p->elementSet())); + return true; + } + } + break; + case DomProperty::Enum: { + const int index = sheet->indexOf(p->attributeName()); + if (index == -1) + return false; + const QVariant sheetValue = sheet->property(index); + if (sheetValue.canConvert<PropertySheetEnumValue>()) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); + bool ok = false; + v = e.metaEnum.parseEnum(p->elementEnum(), &ok); + if (!ok) + designerWarning(e.metaEnum.messageParseFailed(p->elementEnum())); + return true; + } + } + break; + default: + break; + } + return false; +} + +void QDesignerFormBuilder::applyProperties(QObject *o, const QList<DomProperty*> &properties) +{ + typedef QList<DomProperty*> DomPropertyList; + + if (properties.empty()) + return; + + QFormBuilderExtra *formBuilderExtra = QFormBuilderExtra::instance(this); + const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), o); + const QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), o); + const bool changingMetaObject = WidgetFactory::classNameOf(core(), o) == QLatin1String("QAxWidget"); + const QDesignerMetaObjectInterface *meta = core()->introspection()->metaObject(o); + const bool dynamicPropertiesAllowed = dynamicSheet && dynamicSheet->dynamicPropertiesAllowed(); + + QDesignerPropertySheet *designerPropertySheet = qobject_cast<QDesignerPropertySheet *>( + core()->extensionManager()->extension(o, Q_TYPEID(QDesignerPropertySheetExtension))); + + if (designerPropertySheet) { + if (designerPropertySheet->pixmapCache()) + designerPropertySheet->setPixmapCache(m_pixmapCache); + if (designerPropertySheet->iconCache()) + designerPropertySheet->setIconCache(m_iconCache); + } + + const DomPropertyList::const_iterator cend = properties.constEnd(); + for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) { + DomProperty *p = *it; + QVariant v; + if (!readDomEnumerationValue(p, sheet, v)) + v = toVariant(o->metaObject(), p); + + if (v.isNull()) + continue; + + const QString attributeName = p->attributeName(); + if (formBuilderExtra->applyPropertyInternally(o, attributeName, v)) + continue; + + // refuse fake properties like current tab name (weak test) + if (!dynamicPropertiesAllowed) { + if (changingMetaObject) // Changes after setting control of QAxWidget + meta = core()->introspection()->metaObject(o); + if (meta->indexOfProperty(attributeName) == -1) + continue; + } + + QObject *obj = o; + QAbstractScrollArea *scroll = qobject_cast<QAbstractScrollArea *>(o); + if (scroll && attributeName == QLatin1String("cursor") && scroll->viewport()) + obj = scroll->viewport(); + + // a real property + obj->setProperty(attributeName.toUtf8(), v); + } +} + +DomWidget *QDesignerFormBuilder::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive) +{ + DomWidget *ui_widget = QFormBuilder::createDom(widget, ui_parentWidget, recursive); + QSimpleResource::addExtensionDataToDOM(this, m_core, ui_widget, widget); + return ui_widget; +} + +QWidget *QDesignerFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidget) +{ + QWidget *widget = QFormBuilder::create(ui_widget, parentWidget); + // Do not apply state if scripts are to be run in preview mode + QSimpleResource::applyExtensionDataFromDOM(this, m_core, ui_widget, widget, m_mode == DisableScripts); + return widget; +} + +void QDesignerFormBuilder::createResources(DomResources *resources) +{ + if (m_ignoreCreateResources) + return; + QStringList paths; + if (resources != 0) { + const QList<DomResource*> dom_include = resources->elementInclude(); + foreach (DomResource *res, dom_include) { + QString path = QDir::cleanPath(workingDirectory().absoluteFilePath(res->attributeLocation())); + paths << path; + } + } + + m_tempResourceSet = core()->resourceModel()->addResourceSet(paths); +} + +QLayout *QDesignerFormBuilder::create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget) +{ + return QFormBuilder::create(ui_layout, layout, parentWidget); +} + +void QDesignerFormBuilder::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) +{ + QFormBuilder::loadExtraInfo(ui_widget, widget, parentWidget); +} + +QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, + const QString &styleName, + const QString &appStyleSheet, + const DeviceProfile &deviceProfile, + ScriptErrors *scriptErrors, + QString *errorMessage) +{ + scriptErrors->clear(); + + // load + QDesignerFormBuilder builder(fw->core(), EnableScripts, deviceProfile); + builder.setWorkingDirectory(fw->absoluteDir()); + + const bool warningsEnabled = QSimpleResource::setWarningsEnabled(false); + QByteArray bytes = fw->contents().toUtf8(); + QSimpleResource::setWarningsEnabled(warningsEnabled); + + QBuffer buffer(&bytes); + buffer.open(QIODevice::ReadOnly); + + QWidget *widget = builder.load(&buffer, 0); + if (!widget) { // Shouldn't happen + *errorMessage = QCoreApplication::translate("QDesignerFormBuilder", "The preview failed to build."); + return 0; + } + // Make sure palette is applied + const QString styleToUse = styleName.isEmpty() ? builder.deviceProfile().style() : styleName; + if (!styleToUse.isEmpty()) { + if (WidgetFactory *wf = qobject_cast<qdesigner_internal::WidgetFactory *>(fw->core()->widgetFactory())) { + if (styleToUse != wf->styleName()) + WidgetFactory::applyStyleToTopLevel(wf->getStyle(styleToUse), widget); + } + } +#ifndef QT_FORMBUILDER_NO_SCRIPT + // Check for script errors + *scriptErrors = builder.formScriptRunner()->errors(); + if (!scriptErrors->empty()) { + *errorMessage = summarizeScriptErrors(*scriptErrors); + delete widget; + return 0; + } +#endif + // Fake application style sheet by prepending. (If this doesn't work, fake by nesting + // into parent widget). + if (!appStyleSheet.isEmpty()) { + QString styleSheet = appStyleSheet; + styleSheet += QLatin1Char('\n'); + styleSheet += widget->styleSheet(); + widget->setStyleSheet(styleSheet); + } + return widget; +} + +QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName) +{ + return createPreview(fw, styleName, QString()); +} + +QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, + const QString &styleName, + const QString &appStyleSheet, + const DeviceProfile &deviceProfile, + QString *errorMessage) +{ + ScriptErrors scriptErrors; + return createPreview(fw, styleName, appStyleSheet, deviceProfile, &scriptErrors, errorMessage); +} + +QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, + const QString &styleName, + const QString &appStyleSheet, + QString *errorMessage) +{ + ScriptErrors scriptErrors; + return createPreview(fw, styleName, appStyleSheet, DeviceProfile(), &scriptErrors, errorMessage); +} + +QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet) +{ + ScriptErrors scriptErrors; + QString errorMessage; + QWidget *widget = createPreview(fw, styleName, appStyleSheet, DeviceProfile(), &scriptErrors, &errorMessage); + if (!widget) { + // Display Script errors or message box + QWidget *dialogParent = fw->core()->topLevel(); + if (scriptErrors.empty()) { + fw->core()->dialogGui()->message(dialogParent, QDesignerDialogGuiInterface::PreviewFailureMessage, + QMessageBox::Warning, QCoreApplication::translate("QDesignerFormBuilder", "Designer"), errorMessage, QMessageBox::Ok); + } else { + ScriptErrorDialog scriptErrorDialog(scriptErrors, dialogParent); + scriptErrorDialog.exec(); + } + return 0; + } + return widget; +} + +QPixmap QDesignerFormBuilder::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet) +{ + QWidget *widget = createPreview(fw, styleName, appStyleSheet); + if (!widget) + return QPixmap(); + + const QPixmap rc = QPixmap::grabWidget (widget); + widget->deleteLater(); + return rc; +} + +// ---------- NewFormWidgetFormBuilder + +NewFormWidgetFormBuilder::NewFormWidgetFormBuilder(QDesignerFormEditorInterface *core, + Mode mode, + const DeviceProfile &deviceProfile) : + QDesignerFormBuilder(core, mode, deviceProfile) +{ +} + +void NewFormWidgetFormBuilder::createCustomWidgets(DomCustomWidgets *dc) +{ + QSimpleResource::handleDomCustomWidgets(core(), dc); +} + +} // namespace qdesigner_internal + +QT_END_NAMESPACE |