summaryrefslogtreecommitdiffstats
path: root/src/designer/src/lib/shared/qdesigner_propertysheet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/designer/src/lib/shared/qdesigner_propertysheet.cpp')
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertysheet.cpp1657
1 files changed, 1657 insertions, 0 deletions
diff --git a/src/designer/src/lib/shared/qdesigner_propertysheet.cpp b/src/designer/src/lib/shared/qdesigner_propertysheet.cpp
new file mode 100644
index 000000000..27527da05
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertysheet.cpp
@@ -0,0 +1,1657 @@
+/****************************************************************************
+**
+** 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_propertysheet_p.h"
+#include "qdesigner_utils_p.h"
+#include "formwindowbase_p.h"
+#include "layoutinfo_p.h"
+#include "qlayout_widget_p.h"
+#include "qdesigner_introspection_p.h"
+
+#include <formbuilderextra_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QLayout>
+#include <QtGui/QDockWidget>
+#include <QtGui/QDialog>
+#include <QtGui/QLabel>
+#include <QtGui/QGroupBox>
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+#include <QtGui/QToolBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenuBar>
+
+QT_BEGIN_NAMESPACE
+
+#define USE_LAYOUT_SIZE_CONSTRAINT
+
+static const QDesignerMetaObjectInterface *propertyIntroducedBy(const QDesignerMetaObjectInterface *meta, int index)
+{
+ if (index >= meta->propertyOffset())
+ return meta;
+
+ if (meta->superClass())
+ return propertyIntroducedBy(meta->superClass(), index);
+
+ return 0;
+}
+
+// Layout fake properties (prefixed by 'layout' to distinguish them from other 'margins'
+// that might be around. These are forwarded to the layout sheet (after name transformation).
+//
+// 'layoutObjectName' is new for 4.4. It is the name of the actual layout.
+// Up to 4.3, QLayoutWidget's name was displayed in the objectinspector.
+// This changes with 4.4; the layout name is displayed. This means that for
+// old forms, QLayoutWidget will show up as ''; however, the uic code will
+// still use 'verticalLayout' (in case someone accesses it). New Layouts get autogenerated names,
+// legacy forms will keep their empty names (unless someone types in a new name).
+static const char *layoutObjectNameC = "layoutName";
+static const char *layoutLeftMarginC = "layoutLeftMargin";
+static const char *layoutTopMarginC = "layoutTopMargin";
+static const char *layoutRightMarginC = "layoutRightMargin";
+static const char *layoutBottomMarginC = "layoutBottomMargin";
+static const char *layoutSpacingC = "layoutSpacing";
+static const char *layoutHorizontalSpacingC = "layoutHorizontalSpacing";
+static const char *layoutVerticalSpacingC = "layoutVerticalSpacing";
+static const char *layoutSizeConstraintC = "layoutSizeConstraint";
+// form layout
+static const char *layoutFieldGrowthPolicyC = "layoutFieldGrowthPolicy";
+static const char *layoutRowWrapPolicyC = "layoutRowWrapPolicy";
+static const char *layoutLabelAlignmentC = "layoutLabelAlignment";
+static const char *layoutFormAlignmentC = "layoutFormAlignment";
+// stretches
+static const char *layoutboxStretchPropertyC = "layoutStretch";
+static const char *layoutGridRowStretchPropertyC = "layoutRowStretch";
+static const char *layoutGridColumnStretchPropertyC = "layoutColumnStretch";
+static const char *layoutGridRowMinimumHeightC = "layoutRowMinimumHeight";
+static const char *layoutGridColumnMinimumWidthC = "layoutColumnMinimumWidth";
+
+// Find the form editor in the hierarchy.
+// We know that the parent of the sheet is the extension manager
+// whose parent is the core.
+
+static QDesignerFormEditorInterface *formEditorForObject(QObject *o) {
+ do {
+ if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o))
+ return core;
+ o = o->parent();
+ } while(o);
+ Q_ASSERT(o);
+ return 0;
+}
+
+static bool hasLayoutAttributes(QDesignerFormEditorInterface *core, QObject *object)
+{
+ if (!object->isWidgetType())
+ return false;
+
+ QWidget *w = qobject_cast<QWidget *>(object);
+ if (const QDesignerWidgetDataBaseInterface *db = core->widgetDataBase()) {
+ if (db->isContainer(w))
+ return true;
+ }
+ return false;
+}
+
+// Cache DesignerMetaEnum by scope/name of a QMetaEnum
+static const qdesigner_internal::DesignerMetaEnum &designerMetaEnumFor(const QDesignerMetaEnumInterface *me)
+{
+ typedef QPair<QString, QString> ScopeNameKey;
+ typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaEnum> DesignerMetaEnumCache;
+ static DesignerMetaEnumCache cache;
+
+ const QString name = me->name();
+ const QString scope = me->scope();
+
+ const ScopeNameKey key = ScopeNameKey(scope, name);
+ DesignerMetaEnumCache::iterator it = cache.find(key);
+ if (it == cache.end()) {
+ qdesigner_internal::DesignerMetaEnum dme = qdesigner_internal::DesignerMetaEnum(name, scope, me->separator());
+ const int keyCount = me->keyCount();
+ for (int i=0; i < keyCount; ++i)
+ dme.addKey(me->value(i), me->key(i));
+ it = cache.insert(key, dme);
+ }
+ return it.value();
+}
+
+// Cache DesignerMetaFlags by scope/name of a QMetaEnum
+static const qdesigner_internal::DesignerMetaFlags &designerMetaFlagsFor(const QDesignerMetaEnumInterface *me)
+{
+ typedef QPair<QString, QString> ScopeNameKey;
+ typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaFlags> DesignerMetaFlagsCache;
+ static DesignerMetaFlagsCache cache;
+
+ const QString name = me->name();
+ const QString scope = me->scope();
+
+ const ScopeNameKey key = ScopeNameKey(scope, name);
+ DesignerMetaFlagsCache::iterator it = cache.find(key);
+ if (it == cache.end()) {
+ qdesigner_internal::DesignerMetaFlags dme = qdesigner_internal::DesignerMetaFlags(name, scope, me->separator());
+ const int keyCount = me->keyCount();
+ for (int i=0; i < keyCount; ++i)
+ dme.addKey(me->value(i), me->key(i));
+ it = cache.insert(key, dme);
+ }
+ return it.value();
+}
+
+// ------------ QDesignerMemberSheetPrivate
+class QDesignerPropertySheetPrivate {
+public:
+ typedef QDesignerPropertySheet::PropertyType PropertyType;
+ typedef QDesignerPropertySheet::ObjectType ObjectType;
+
+ explicit QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent);
+
+ bool invalidIndex(const char *functionName, int index) const;
+ inline int count() const { return m_meta->propertyCount() + m_addProperties.count(); }
+
+ PropertyType propertyType(int index) const;
+ QString transformLayoutPropertyName(int index) const;
+ QLayout* layout(QDesignerPropertySheetExtension **layoutPropertySheet = 0) const;
+ static ObjectType objectType(const QObject *o);
+
+ bool isReloadableProperty(int index) const;
+ bool isResourceProperty(int index) const;
+ void addResourceProperty(int index, QVariant::Type type);
+ QVariant resourceProperty(int index) const;
+ void setResourceProperty(int index, const QVariant &value);
+ QVariant emptyResourceProperty(int index) const; // of type PropertySheetPixmapValue / PropertySheetIconValue
+ QVariant defaultResourceProperty(int index) const; // of type QPixmap / QIcon (maybe it can be generalized for all types, not resource only)
+
+ bool isStringProperty(int index) const;
+ void addStringProperty(int index);
+ qdesigner_internal::PropertySheetStringValue stringProperty(int index) const;
+ void setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value);
+
+ bool isKeySequenceProperty(int index) const;
+ void addKeySequenceProperty(int index);
+ qdesigner_internal::PropertySheetKeySequenceValue keySequenceProperty(int index) const;
+ void setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value);
+
+ enum PropertyKind { NormalProperty, FakeProperty, DynamicProperty, DefaultDynamicProperty };
+ class Info {
+ public:
+ Info();
+
+ QString group;
+ QVariant defaultValue;
+ bool changed;
+ bool visible;
+ bool attribute;
+ bool reset;
+ PropertyType propertyType;
+ PropertyKind kind;
+ };
+
+ Info &ensureInfo(int index);
+
+ QDesignerPropertySheet *q;
+ QDesignerFormEditorInterface *m_core;
+ const QDesignerMetaObjectInterface *m_meta;
+ const ObjectType m_objectType;
+
+ typedef QHash<int, Info> InfoHash;
+ InfoHash m_info;
+ QHash<int, QVariant> m_fakeProperties;
+ QHash<int, QVariant> m_addProperties;
+ QHash<QString, int> m_addIndex;
+ QHash<int, QVariant> m_resourceProperties; // only PropertySheetPixmapValue snd PropertySheetIconValue here
+ QHash<int, qdesigner_internal::PropertySheetStringValue> m_stringProperties; // only PropertySheetStringValue
+ QHash<int, qdesigner_internal::PropertySheetKeySequenceValue> m_keySequenceProperties; // only PropertySheetKeySequenceValue
+
+ const bool m_canHaveLayoutAttributes;
+
+ // Variables used for caching the layout, access via layout().
+ QPointer<QObject> m_object;
+ mutable QPointer<QLayout> m_lastLayout;
+ mutable QDesignerPropertySheetExtension *m_lastLayoutPropertySheet;
+ mutable bool m_LastLayoutByDesigner;
+
+ qdesigner_internal::DesignerPixmapCache *m_pixmapCache;
+ qdesigner_internal::DesignerIconCache *m_iconCache;
+ QPointer<qdesigner_internal::FormWindowBase> m_fwb;
+
+ // Enable Qt's internal properties starting with prefix "_q_"
+ static bool m_internalDynamicPropertiesEnabled;
+};
+
+bool QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = false;
+
+/*
+ The property is reloadable if its contents depends on resource.
+*/
+bool QDesignerPropertySheetPrivate::isReloadableProperty(int index) const
+{
+ return isResourceProperty(index)
+ || propertyType(index) == QDesignerPropertySheet::PropertyStyleSheet
+ || propertyType(index) == QDesignerPropertySheet::PropertyText
+ || q->property(index).type() == QVariant::Url;
+}
+
+/*
+ Resource properties are those which:
+ 1) are reloadable
+ 2) their state is associated with a file which can be taken from resources
+ 3) we don't store them in Qt meta object system (because designer keeps different data structure for them)
+*/
+
+bool QDesignerPropertySheetPrivate::isResourceProperty(int index) const
+{
+ return m_resourceProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addResourceProperty(int index, QVariant::Type type)
+{
+ if (type == QVariant::Pixmap)
+ m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()));
+ else if (type == QVariant::Icon)
+ m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()));
+}
+
+QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const
+{
+ QVariant v = m_resourceProperties.value(index);
+ if (v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
+ return QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
+ if (v.canConvert<qdesigner_internal::PropertySheetIconValue>())
+ return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
+ return v;
+}
+
+QVariant QDesignerPropertySheetPrivate::defaultResourceProperty(int index) const
+{
+ return m_info.value(index).defaultValue;
+}
+
+QVariant QDesignerPropertySheetPrivate::resourceProperty(int index) const
+{
+ return m_resourceProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setResourceProperty(int index, const QVariant &value)
+{
+ Q_ASSERT(isResourceProperty(index));
+
+ QVariant &v = m_resourceProperties[index];
+ if ((value.canConvert<qdesigner_internal::PropertySheetPixmapValue>() && v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
+ || (value.canConvert<qdesigner_internal::PropertySheetIconValue>() && v.canConvert<qdesigner_internal::PropertySheetIconValue>()))
+ v = value;
+}
+
+bool QDesignerPropertySheetPrivate::isStringProperty(int index) const
+{
+ return m_stringProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addStringProperty(int index)
+{
+ m_stringProperties.insert(index, qdesigner_internal::PropertySheetStringValue());
+}
+
+qdesigner_internal::PropertySheetStringValue QDesignerPropertySheetPrivate::stringProperty(int index) const
+{
+ return m_stringProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value)
+{
+ Q_ASSERT(isStringProperty(index));
+
+ m_stringProperties[index] = value;
+}
+
+bool QDesignerPropertySheetPrivate::isKeySequenceProperty(int index) const
+{
+ return m_keySequenceProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addKeySequenceProperty(int index)
+{
+ m_keySequenceProperties.insert(index, qdesigner_internal::PropertySheetKeySequenceValue());
+}
+
+qdesigner_internal::PropertySheetKeySequenceValue QDesignerPropertySheetPrivate::keySequenceProperty(int index) const
+{
+ return m_keySequenceProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value)
+{
+ Q_ASSERT(isKeySequenceProperty(index));
+
+ m_keySequenceProperties[index] = value;
+}
+
+QDesignerPropertySheetPrivate::Info::Info() :
+ changed(false),
+ visible(true),
+ attribute(false),
+ reset(true),
+ propertyType(QDesignerPropertySheet::PropertyNone),
+ kind(NormalProperty)
+{
+}
+
+QDesignerPropertySheetPrivate::QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent) :
+ q(sheetPublic),
+ m_core(formEditorForObject(sheetParent)),
+ m_meta(m_core->introspection()->metaObject(object)),
+ m_objectType(QDesignerPropertySheet::objectTypeFromObject(object)),
+ m_canHaveLayoutAttributes(hasLayoutAttributes(m_core, object)),
+ m_object(object),
+ m_lastLayout(0),
+ m_lastLayoutPropertySheet(0),
+ m_LastLayoutByDesigner(false),
+ m_pixmapCache(0),
+ m_iconCache(0)
+{
+}
+
+qdesigner_internal::FormWindowBase *QDesignerPropertySheet::formWindowBase() const
+{
+ return d->m_fwb;
+}
+
+bool QDesignerPropertySheetPrivate::invalidIndex(const char *functionName, int index) const
+{
+ if (index < 0 || index >= count()) {
+ qWarning() << "** WARNING " << functionName << " invoked for " << m_object->objectName() << " was passed an invalid index " << index << '.';
+ return true;
+ }
+ return false;
+}
+
+QLayout* QDesignerPropertySheetPrivate::layout(QDesignerPropertySheetExtension **layoutPropertySheet) const
+{
+ // Return the layout and its property sheet
+ // only if it is managed by designer and not one created on a custom widget.
+ // (attempt to cache the value as this requires some hoops).
+ if (layoutPropertySheet)
+ *layoutPropertySheet = 0;
+
+ if (!m_object->isWidgetType() || !m_canHaveLayoutAttributes)
+ return 0;
+
+ QWidget *widget = qobject_cast<QWidget*>(m_object);
+ QLayout *widgetLayout = qdesigner_internal::LayoutInfo::internalLayout(widget);
+ if (!widgetLayout) {
+ m_lastLayout = 0;
+ m_lastLayoutPropertySheet = 0;
+ return 0;
+ }
+ // Smart logic to avoid retrieving the meta DB from the widget every time.
+ if (widgetLayout != m_lastLayout) {
+ m_lastLayout = widgetLayout;
+ m_LastLayoutByDesigner = false;
+ m_lastLayoutPropertySheet = 0;
+ // Is this a layout managed by designer or some layout on a custom widget?
+ if (qdesigner_internal::LayoutInfo::managedLayout(m_core ,widgetLayout)) {
+ m_LastLayoutByDesigner = true;
+ m_lastLayoutPropertySheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), m_lastLayout);
+ }
+ }
+ if (!m_LastLayoutByDesigner)
+ return 0;
+
+ if (layoutPropertySheet)
+ *layoutPropertySheet = m_lastLayoutPropertySheet;
+
+ return m_lastLayout;
+}
+
+QDesignerPropertySheetPrivate::Info &QDesignerPropertySheetPrivate::ensureInfo(int index)
+{
+ InfoHash::iterator it = m_info.find(index);
+ if (it == m_info.end())
+ it = m_info.insert(index, Info());
+ return it.value();
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheetPrivate::propertyType(int index) const
+{
+ const InfoHash::const_iterator it = m_info.constFind(index);
+ if (it == m_info.constEnd())
+ return QDesignerPropertySheet::PropertyNone;
+ return it.value().propertyType;
+}
+
+QString QDesignerPropertySheetPrivate::transformLayoutPropertyName(int index) const
+{
+ typedef QMap<QDesignerPropertySheet::PropertyType, QString> TypeNameMap;
+ static TypeNameMap typeNameMap;
+ if (typeNameMap.empty()) {
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutObjectName, QLatin1String("objectName"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLeftMargin, QLatin1String("leftMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutTopMargin, QLatin1String("topMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRightMargin, QLatin1String("rightMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBottomMargin, QLatin1String("bottomMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSpacing, QLatin1String("spacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutHorizontalSpacing, QLatin1String("horizontalSpacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutVerticalSpacing, QLatin1String("verticalSpacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSizeConstraint, QLatin1String("sizeConstraint"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFieldGrowthPolicy, QLatin1String("fieldGrowthPolicy"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRowWrapPolicy, QLatin1String("rowWrapPolicy"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLabelAlignment, QLatin1String("labelAlignment"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFormAlignment, QLatin1String("formAlignment"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBoxStretch, QLatin1String("stretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowStretch, QLatin1String("rowStretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnStretch, QLatin1String("columnStretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowMinimumHeight, QLatin1String("rowMinimumHeight"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnMinimumWidth, QLatin1String("columnMinimumWidth"));
+ }
+ const TypeNameMap::const_iterator it = typeNameMap.constFind(propertyType(index));
+ if (it != typeNameMap.constEnd())
+ return it.value();
+ return QString();
+}
+
+// ----------- QDesignerPropertySheet
+
+QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectTypeFromObject(const QObject *o)
+{
+ if (qobject_cast<const QLayout *>(o))
+ return ObjectLayout;
+
+ if (!o->isWidgetType())
+ return ObjectNone;
+
+ if (qobject_cast<const QLayoutWidget *>(o))
+ return ObjectLayoutWidget;
+
+ if (qobject_cast<const QLabel*>(o))
+ return ObjectLabel;
+
+ if (o->inherits("Q3GroupBox"))
+ return ObjectQ3GroupBox;
+
+ return ObjectNone;
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyTypeFromName(const QString &name)
+{
+ typedef QHash<QString, PropertyType> PropertyTypeHash;
+ static PropertyTypeHash propertyTypeHash;
+ if (propertyTypeHash.empty()) {
+ propertyTypeHash.insert(QLatin1String(layoutObjectNameC), PropertyLayoutObjectName);
+ propertyTypeHash.insert(QLatin1String(layoutLeftMarginC), PropertyLayoutLeftMargin);
+ propertyTypeHash.insert(QLatin1String(layoutTopMarginC), PropertyLayoutTopMargin);
+ propertyTypeHash.insert(QLatin1String(layoutRightMarginC), PropertyLayoutRightMargin);
+ propertyTypeHash.insert(QLatin1String(layoutBottomMarginC), PropertyLayoutBottomMargin);
+ propertyTypeHash.insert(QLatin1String(layoutSpacingC), PropertyLayoutSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutHorizontalSpacingC), PropertyLayoutHorizontalSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutVerticalSpacingC), PropertyLayoutVerticalSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutSizeConstraintC), PropertyLayoutSizeConstraint);
+ propertyTypeHash.insert(QLatin1String(layoutFieldGrowthPolicyC), PropertyLayoutFieldGrowthPolicy);
+ propertyTypeHash.insert(QLatin1String(layoutRowWrapPolicyC), PropertyLayoutRowWrapPolicy);
+ propertyTypeHash.insert(QLatin1String(layoutLabelAlignmentC), PropertyLayoutLabelAlignment);
+ propertyTypeHash.insert(QLatin1String(layoutFormAlignmentC), PropertyLayoutFormAlignment);
+ propertyTypeHash.insert(QLatin1String(layoutboxStretchPropertyC), PropertyLayoutBoxStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridRowStretchPropertyC), PropertyLayoutGridRowStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridColumnStretchPropertyC), PropertyLayoutGridColumnStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridRowMinimumHeightC), PropertyLayoutGridRowMinimumHeight);
+ propertyTypeHash.insert(QLatin1String(layoutGridColumnMinimumWidthC), PropertyLayoutGridColumnMinimumWidth);
+ propertyTypeHash.insert(QLatin1String("buddy"), PropertyBuddy);
+ propertyTypeHash.insert(QLatin1String("geometry"), PropertyGeometry);
+ propertyTypeHash.insert(QLatin1String("checkable"), PropertyCheckable);
+ propertyTypeHash.insert(QLatin1String("accessibleName"), PropertyAccessibility);
+ propertyTypeHash.insert(QLatin1String("accessibleDescription"), PropertyAccessibility);
+ propertyTypeHash.insert(QLatin1String("windowTitle"), PropertyWindowTitle);
+ propertyTypeHash.insert(QLatin1String("windowIcon"), PropertyWindowIcon);
+ propertyTypeHash.insert(QLatin1String("windowFilePath"), PropertyWindowFilePath);
+ propertyTypeHash.insert(QLatin1String("windowOpacity"), PropertyWindowOpacity);
+ propertyTypeHash.insert(QLatin1String("windowIconText"), PropertyWindowIconText);
+ propertyTypeHash.insert(QLatin1String("windowModality"), PropertyWindowModality);
+ propertyTypeHash.insert(QLatin1String("windowModified"), PropertyWindowModified);
+ propertyTypeHash.insert(QLatin1String("styleSheet"), PropertyStyleSheet);
+ propertyTypeHash.insert(QLatin1String("text"), PropertyText);
+ }
+ return propertyTypeHash.value(name, PropertyNone);
+}
+
+QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent) :
+ QObject(parent),
+ d(new QDesignerPropertySheetPrivate(this, object, parent))
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ const QDesignerMetaObjectInterface *baseMeta = d->m_meta;
+
+ while (baseMeta &&baseMeta->className().startsWith(QLatin1String("QDesigner"))) {
+ baseMeta = baseMeta->superClass();
+ }
+ Q_ASSERT(baseMeta != 0);
+
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(d->m_object);
+ d->m_fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ if (d->m_fwb) {
+ d->m_pixmapCache = d->m_fwb->pixmapCache();
+ d->m_iconCache = d->m_fwb->iconCache();
+ d->m_fwb->addReloadablePropertySheet(this, object);
+ }
+
+ for (int index=0; index<count(); ++index) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ const QString name = p->name();
+ if (p->type() == QVariant::KeySequence) {
+ createFakeProperty(name);
+ } else {
+ setVisible(index, false); // use the default for `real' properties
+ }
+
+ QString pgroup = baseMeta->className();
+
+ if (const QDesignerMetaObjectInterface *pmeta = propertyIntroducedBy(baseMeta, index)) {
+ pgroup = pmeta->className();
+ }
+
+ Info &info = d->ensureInfo(index);
+ info.group = pgroup;
+ info.propertyType = propertyTypeFromName(name);
+
+ if (p->type() == QVariant::Cursor || p->type() == QVariant::Icon || p->type() == QVariant::Pixmap) {
+ info.defaultValue = p->read(d->m_object);
+ if (p->type() == QVariant::Icon || p->type() == QVariant::Pixmap)
+ d->addResourceProperty(index, p->type());
+ } else if (p->type() == QVariant::String) {
+ d->addStringProperty(index);
+ } else if (p->type() == QVariant::KeySequence) {
+ d->addKeySequenceProperty(index);
+ }
+ }
+
+ if (object->isWidgetType()) {
+ createFakeProperty(QLatin1String("focusPolicy"));
+ createFakeProperty(QLatin1String("cursor"));
+ createFakeProperty(QLatin1String("toolTip"));
+ createFakeProperty(QLatin1String("whatsThis"));
+ createFakeProperty(QLatin1String("acceptDrops"));
+ createFakeProperty(QLatin1String("dragEnabled"));
+ // windowModality/Opacity is visible only for the main container, in which case the form windows enables it on loading
+ setVisible(createFakeProperty(QLatin1String("windowModality")), false);
+ setVisible(createFakeProperty(QLatin1String("windowOpacity"), double(1.0)), false);
+ if (qobject_cast<const QToolBar *>(d->m_object)) { // prevent toolbars from being dragged off
+ createFakeProperty(QLatin1String("floatable"), QVariant(true));
+ } else {
+ if (qobject_cast<const QMenuBar *>(d->m_object)) {
+ // Keep the menu bar editable in the form even if a native menu bar is used.
+ const bool nativeMenuBarDefault = !qApp->testAttribute(Qt::AA_DontUseNativeMenuBar);
+ createFakeProperty(QLatin1String("nativeMenuBar"), QVariant(nativeMenuBarDefault));
+ }
+ }
+ if (d->m_canHaveLayoutAttributes) {
+ static const QString layoutGroup = QLatin1String("Layout");
+ const char* fakeLayoutProperties[] = {
+ layoutObjectNameC, layoutLeftMarginC, layoutTopMarginC, layoutRightMarginC, layoutBottomMarginC, layoutSpacingC, layoutHorizontalSpacingC, layoutVerticalSpacingC,
+ layoutFieldGrowthPolicyC, layoutRowWrapPolicyC, layoutLabelAlignmentC, layoutFormAlignmentC,
+ layoutboxStretchPropertyC, layoutGridRowStretchPropertyC, layoutGridColumnStretchPropertyC,
+ layoutGridRowMinimumHeightC, layoutGridColumnMinimumWidthC
+#ifdef USE_LAYOUT_SIZE_CONSTRAINT
+ , layoutSizeConstraintC
+#endif
+ };
+ const int fakeLayoutPropertyCount = sizeof(fakeLayoutProperties)/sizeof(const char*);
+ const int size = count();
+ for (int i = 0; i < fakeLayoutPropertyCount; i++) {
+ createFakeProperty(QLatin1String(fakeLayoutProperties[i]), 0);
+ setAttribute(size + i, true);
+ setPropertyGroup(size + i, layoutGroup);
+ }
+ }
+
+ if (d->m_objectType == ObjectLabel)
+ createFakeProperty(QLatin1String("buddy"), QVariant(QByteArray()));
+ /* We need to create a fake property since the property does not work
+ * for non-toplevel windows or on other systems than Mac and only if
+ * it is above a certain Mac OS version. */
+ if (qobject_cast<const QMainWindow *>(d->m_object))
+ createFakeProperty(QLatin1String("unifiedTitleAndToolBarOnMac"), false);
+ }
+
+ if (qobject_cast<const QDialog*>(object)) {
+ createFakeProperty(QLatin1String("modal"));
+ }
+ if (qobject_cast<const QDockWidget*>(object)) {
+ createFakeProperty(QLatin1String("floating"));
+ }
+
+ typedef QList<QByteArray> ByteArrayList;
+ const ByteArrayList names = object->dynamicPropertyNames();
+ if (!names.empty()) {
+ const ByteArrayList::const_iterator cend = names.constEnd();
+ for (ByteArrayList::const_iterator it = names.constBegin(); it != cend; ++it) {
+ const char* cName = it->constData();
+ const QString name = QString::fromLatin1(cName);
+ const int idx = addDynamicProperty(name, object->property(cName));
+ if (idx != -1)
+ d->ensureInfo(idx).kind = QDesignerPropertySheetPrivate::DefaultDynamicProperty;
+ }
+ }
+}
+
+QDesignerPropertySheet::~QDesignerPropertySheet()
+{
+ if (d->m_fwb)
+ d->m_fwb->removeReloadablePropertySheet(this);
+ delete d;
+}
+
+QObject *QDesignerPropertySheet::object() const
+{
+ return d->m_object;
+}
+
+bool QDesignerPropertySheet::dynamicPropertiesAllowed() const
+{
+ return true;
+}
+
+bool QDesignerPropertySheet::canAddDynamicProperty(const QString &propName) const
+{
+ // used internally
+ if (propName == QLatin1String("database") ||
+ propName == QLatin1String("buttonGroupId"))
+ return false;
+ const int index = d->m_meta->indexOfProperty(propName);
+ if (index != -1)
+ return false; // property already exists and is not a dynamic one
+ if (d->m_addIndex.contains(propName)) {
+ const int idx = d->m_addIndex.value(propName);
+ if (isVisible(idx))
+ return false; // dynamic property already exists
+ else
+ return true;
+ }
+ if (!QDesignerPropertySheet::internalDynamicPropertiesEnabled() && propName.startsWith(QLatin1String("_q_")))
+ return false;
+ return true;
+}
+
+int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QVariant &value)
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ if (!value.isValid())
+ return -1; // property has invalid type
+ if (!canAddDynamicProperty(propName))
+ return -1;
+
+ QVariant v = value;
+ if (value.type() == QVariant::Icon)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
+ else if (value.type() == QVariant::Pixmap)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
+ else if (value.type() == QVariant::String)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(value.toString()));
+ else if (value.type() == QVariant::KeySequence) {
+ const QKeySequence keySequence = qvariant_cast<QKeySequence>(value);
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
+
+ if (d->m_addIndex.contains(propName)) {
+ const int idx = d->m_addIndex.value(propName);
+ // have to be invisible, this was checked in canAddDynamicProperty() method
+ setVisible(idx, true);
+ d->m_addProperties.insert(idx, v);
+ setChanged(idx, false);
+ const int index = d->m_meta->indexOfProperty(propName);
+ Info &info = d->ensureInfo(index);
+ info.defaultValue = value;
+ info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
+ if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
+ d->addResourceProperty(idx, value.type());
+ else if (value.type() == QVariant::String)
+ d->addStringProperty(idx);
+ else if (value.type() == QVariant::KeySequence)
+ d->addKeySequenceProperty(idx);
+ return idx;
+ }
+
+ const int index = count();
+ d->m_addIndex.insert(propName, index);
+ d->m_addProperties.insert(index, v);
+ Info &info = d->ensureInfo(index);
+ info.visible = true;
+ info.changed = false;
+ info.defaultValue = value;
+ info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
+ setPropertyGroup(index, tr("Dynamic Properties"));
+ if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
+ d->addResourceProperty(index, value.type());
+ else if (value.type() == QVariant::String)
+ d->addStringProperty(index);
+ else if (value.type() == QVariant::KeySequence)
+ d->addKeySequenceProperty(index);
+ return index;
+}
+
+bool QDesignerPropertySheet::removeDynamicProperty(int index)
+{
+ if (!d->m_addIndex.contains(propertyName(index)))
+ return false;
+
+ setVisible(index, false);
+ return true;
+}
+
+bool QDesignerPropertySheet::isDynamic(int index) const
+{
+ if (!d->m_addProperties.contains(index))
+ return false;
+
+ switch (propertyType(index)) {
+ case PropertyBuddy:
+ if (d->m_objectType == ObjectLabel)
+ return false;
+ break;
+ case PropertyLayoutLeftMargin:
+ case PropertyLayoutTopMargin:
+ case PropertyLayoutRightMargin:
+ case PropertyLayoutBottomMargin:
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ case PropertyLayoutObjectName:
+ case PropertyLayoutSizeConstraint:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment:
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ if (d->m_object->isWidgetType() && d->m_canHaveLayoutAttributes)
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool QDesignerPropertySheet::isDynamicProperty(int index) const
+{
+ // Do not complain here, as an invalid index might be encountered
+ // if someone implements a property sheet only, omitting the dynamic sheet.
+ if (index < 0 || index >= count())
+ return false;
+ return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DynamicProperty;
+}
+
+bool QDesignerPropertySheet::isDefaultDynamicProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DefaultDynamicProperty;
+}
+
+bool QDesignerPropertySheet::isResourceProperty(int index) const
+{
+ return d->isResourceProperty(index);
+}
+
+QVariant QDesignerPropertySheet::defaultResourceProperty(int index) const
+{
+ return d->defaultResourceProperty(index);
+}
+
+qdesigner_internal::DesignerPixmapCache *QDesignerPropertySheet::pixmapCache() const
+{
+ return d->m_pixmapCache;
+}
+
+void QDesignerPropertySheet::setPixmapCache(qdesigner_internal::DesignerPixmapCache *cache)
+{
+ d->m_pixmapCache = cache;
+}
+
+qdesigner_internal::DesignerIconCache *QDesignerPropertySheet::iconCache() const
+{
+ return d->m_iconCache;
+}
+
+void QDesignerPropertySheet::setIconCache(qdesigner_internal::DesignerIconCache *cache)
+{
+ d->m_iconCache = cache;
+}
+
+int QDesignerPropertySheet::createFakeProperty(const QString &propertyName, const QVariant &value)
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ // fake properties
+ const int index = d->m_meta->indexOfProperty(propertyName);
+ if (index != -1) {
+ if (!(d->m_meta->property(index)->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute))
+ return -1;
+ Info &info = d->ensureInfo(index);
+ info.visible = false;
+ info.kind = QDesignerPropertySheetPrivate::FakeProperty;
+ QVariant v = value.isValid() ? value : metaProperty(index);
+ if (v.type() == QVariant::String)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ if (v.type() == QVariant::KeySequence)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue());
+ d->m_fakeProperties.insert(index, v);
+ return index;
+ }
+ if (!value.isValid())
+ return -1;
+
+ const int newIndex = count();
+ d->m_addIndex.insert(propertyName, newIndex);
+ d->m_addProperties.insert(newIndex, value);
+ Info &info = d->ensureInfo(newIndex);
+ info.propertyType = propertyTypeFromName(propertyName);
+ info.kind = QDesignerPropertySheetPrivate::FakeProperty;
+ return newIndex;
+}
+
+bool QDesignerPropertySheet::isAdditionalProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ return d->m_addProperties.contains(index);
+}
+
+bool QDesignerPropertySheet::isFakeProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ // additional properties must be fake
+ return (d->m_fakeProperties.contains(index) || isAdditionalProperty(index));
+}
+
+int QDesignerPropertySheet::count() const
+{
+ return d->count();
+}
+
+int QDesignerPropertySheet::indexOf(const QString &name) const
+{
+ int index = d->m_meta->indexOfProperty(name);
+
+ if (index == -1)
+ index = d->m_addIndex.value(name, -1);
+
+ return index;
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyType(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return PropertyNone;
+ return d->propertyType(index);
+}
+
+QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectType() const
+{
+ return d->m_objectType;
+}
+
+QString QDesignerPropertySheet::propertyName(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QString();
+ if (isAdditionalProperty(index))
+ return d->m_addIndex.key(index);
+
+ return d->m_meta->property(index)->name();
+}
+
+QString QDesignerPropertySheet::propertyGroup(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QString();
+ const QString g = d->m_info.value(index).group;
+
+ if (!g.isEmpty())
+ return g;
+
+ if (propertyType(index) == PropertyAccessibility)
+ return QString::fromUtf8("Accessibility");
+
+ if (isAdditionalProperty(index))
+ return d->m_meta->className();
+
+ return g;
+}
+
+void QDesignerPropertySheet::setPropertyGroup(int index, const QString &group)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).group = group;
+}
+
+QVariant QDesignerPropertySheet::property(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QVariant();
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ return layoutPropertySheet->property(newIndex);
+ return QVariant();
+ }
+ }
+ }
+ return d->m_addProperties.value(index);
+ }
+
+ if (isFakeProperty(index)) {
+ return d->m_fakeProperties.value(index);
+ }
+
+ if (d->isResourceProperty(index))
+ return d->resourceProperty(index);
+
+ if (d->isStringProperty(index)) {
+ QString strValue = metaProperty(index).toString();
+ qdesigner_internal::PropertySheetStringValue value = d->stringProperty(index);
+ if (strValue != value.value()) {
+ value.setValue(strValue);
+ d->setStringProperty(index, value); // cache it
+ }
+ return QVariant::fromValue(value);
+ }
+
+ if (d->isKeySequenceProperty(index)) {
+ QKeySequence keyValue = qvariant_cast<QKeySequence>(metaProperty(index));
+ qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index);
+ if (keyValue != value.value()) {
+ value.setValue(keyValue);
+ d->setKeySequenceProperty(index, value); // cache it
+ }
+ return QVariant::fromValue(value);
+ }
+
+ return metaProperty(index);
+}
+
+QVariant QDesignerPropertySheet::metaProperty(int index) const
+{
+ Q_ASSERT(!isFakeProperty(index));
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ QVariant v = p->read(d->m_object);
+ switch (p->kind()) {
+ case QDesignerMetaPropertyInterface::FlagKind: {
+ qdesigner_internal::PropertySheetFlagValue psflags = qdesigner_internal::PropertySheetFlagValue(v.toInt(), designerMetaFlagsFor(p->enumerator()));
+ v.setValue(psflags);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::EnumKind: {
+ qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator()));
+ v.setValue(pse);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::OtherKind:
+ break;
+ }
+ return v;
+}
+
+QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const
+{
+ if (value.canConvert<qdesigner_internal::PropertySheetEnumValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value;
+
+ if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value;
+
+ if (value.canConvert<qdesigner_internal::PropertySheetStringValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value();
+
+ if (value.canConvert<qdesigner_internal::PropertySheetKeySequenceValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value).value();
+
+ if (value.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) {
+ const QString path = qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value).path();
+ if (path.isEmpty())
+ return defaultResourceProperty(index);
+ if (d->m_pixmapCache) {
+ return d->m_pixmapCache->pixmap(qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value));
+ }
+ }
+
+ if (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) {
+ const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask();
+ if (mask == 0)
+ return defaultResourceProperty(index);
+ if (d->m_iconCache)
+ return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value));
+ }
+
+ return value;
+}
+
+void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value)
+{
+ Q_ASSERT(isFakeProperty(index));
+
+ QVariant &v = d->m_fakeProperties[index];
+
+ // set resource properties also (if we are going to have fake resource properties)
+ if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>() || value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
+ v = value;
+ } else if (v.canConvert<qdesigner_internal::PropertySheetFlagValue>()) {
+ qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v);
+ f.value = value.toInt();
+ v.setValue(f);
+ Q_ASSERT(value.type() == QVariant::Int);
+ } else if (v.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
+ qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v);
+ e.value = value.toInt();
+ v.setValue(e);
+ Q_ASSERT(value.type() == QVariant::Int);
+ } else {
+ v = value;
+ }
+}
+
+void QDesignerPropertySheet::clearFakeProperties()
+{
+ d->m_fakeProperties.clear();
+}
+
+// Buddy needs to be byte array, else uic won't work
+static QVariant toByteArray(const QVariant &value) {
+ if (value.type() == QVariant::ByteArray)
+ return value;
+ const QByteArray ba = value.toString().toUtf8();
+ return QVariant(ba);
+}
+
+void QDesignerPropertySheet::setProperty(int index, const QVariant &value)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ if (isAdditionalProperty(index)) {
+ if (d->m_objectType == ObjectLabel && propertyType(index) == PropertyBuddy) {
+ QFormBuilderExtra::applyBuddy(value.toString(), QFormBuilderExtra::BuddyApplyVisibleOnly, qobject_cast<QLabel *>(d->m_object));
+ d->m_addProperties[index] = toByteArray(value);
+ return;
+ }
+
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ layoutPropertySheet->setProperty(newIndex, value);
+ }
+ }
+ }
+
+ if (isDynamicProperty(index) || isDefaultDynamicProperty(index)) {
+ if (d->isResourceProperty(index))
+ d->setResourceProperty(index, value);
+ if (d->isStringProperty(index))
+ d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value));
+ d->m_object->setProperty(propertyName(index).toUtf8(), resolvePropertyValue(index, value));
+ if (d->m_object->isWidgetType()) {
+ QWidget *w = qobject_cast<QWidget *>(d->m_object);
+ w->setStyleSheet(w->styleSheet());
+ }
+ }
+ d->m_addProperties[index] = value;
+ } else if (isFakeProperty(index)) {
+ setFakeProperty(index, value);
+ } else {
+ if (d->isResourceProperty(index))
+ d->setResourceProperty(index, value);
+ if (d->isStringProperty(index))
+ d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value));
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ p->write(d->m_object, resolvePropertyValue(index, value));
+ if (qobject_cast<QGroupBox *>(d->m_object) && propertyType(index) == PropertyCheckable) {
+ const int idx = indexOf(QLatin1String("focusPolicy"));
+ if (!isChanged(idx)) {
+ qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(property(idx));
+ if (value.toBool()) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(idx);
+ p->write(d->m_object, Qt::NoFocus);
+ e.value = Qt::StrongFocus;
+ QVariant v;
+ v.setValue(e);
+ setFakeProperty(idx, v);
+ } else {
+ e.value = Qt::NoFocus;
+ QVariant v;
+ v.setValue(e);
+ setFakeProperty(idx, v);
+ }
+ }
+ }
+ }
+}
+
+bool QDesignerPropertySheet::hasReset(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return d->m_info.value(index).reset;
+ return true;
+}
+
+bool QDesignerPropertySheet::reset(int index)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (d->isStringProperty(index)) {
+ qdesigner_internal::PropertySheetStringValue value;
+ // Main container: Reset to stored class name as not to change the file names generated by uic.
+ if (propertyName(index) == QLatin1String("objectName")) {
+ const QVariant classNameDefaultV = d->m_object->property("_q_classname");
+ if (classNameDefaultV.isValid())
+ value.setValue(classNameDefaultV.toString());
+ }
+ setProperty(index, QVariant::fromValue(value));
+ return true;
+ }
+ if (d->isKeySequenceProperty(index))
+ setProperty(index, QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue()));
+ if (d->isResourceProperty(index)) {
+ setProperty(index, d->emptyResourceProperty(index));
+ return true;
+ } else if (isDynamic(index)) {
+ const QString propName = propertyName(index);
+ const QVariant oldValue = d->m_addProperties.value(index);
+ const QVariant defaultValue = d->m_info.value(index).defaultValue;
+ QVariant newValue = defaultValue;
+ if (d->isStringProperty(index)) {
+ newValue = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString()));
+ } else if (d->isKeySequenceProperty(index)) {
+ const QKeySequence keySequence = qvariant_cast<QKeySequence>(newValue);
+ newValue = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
+ if (oldValue == newValue)
+ return true;
+ d->m_object->setProperty(propName.toUtf8(), defaultValue);
+ d->m_addProperties[index] = newValue;
+ return true;
+ } else if (!d->m_info.value(index).defaultValue.isNull()) {
+ setProperty(index, d->m_info.value(index).defaultValue);
+ return true;
+ }
+ if (isAdditionalProperty(index)) {
+ const PropertyType pType = propertyType(index);
+ if (d->m_objectType == ObjectLabel && pType == PropertyBuddy) {
+ setProperty(index, QVariant(QByteArray()));
+ return true;
+ }
+ if (isFakeLayoutProperty(index)) {
+ // special properties
+ switch (pType) {
+ case PropertyLayoutObjectName:
+ setProperty(index, QString());
+ return true;
+ case PropertyLayoutSizeConstraint:
+ setProperty(index, QVariant(QLayout::SetDefaultConstraint));
+ return true;
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment: {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet)
+ return layoutPropertySheet->reset(layoutPropertySheet->indexOf(d->transformLayoutPropertyName(index)));
+ }
+ break;
+ default:
+ break;
+ }
+ // special margins
+ int value = -1;
+ switch (d->m_objectType) {
+ case ObjectQ3GroupBox: {
+ const QWidget *w = qobject_cast<const QWidget *>(d->m_object);
+ switch (pType) {
+ case PropertyLayoutLeftMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ break;
+ case PropertyLayoutTopMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutTopMargin);
+ break;
+ case PropertyLayoutRightMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+ break;
+ case PropertyLayoutBottomMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
+ break;
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ value = -1;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case ObjectLayoutWidget:
+ if (pType == PropertyLayoutLeftMargin ||
+ pType == PropertyLayoutTopMargin ||
+ pType == PropertyLayoutRightMargin ||
+ pType == PropertyLayoutBottomMargin)
+ value = 0;
+ break;
+ default:
+ break;
+ }
+ setProperty(index, value);
+ return true;
+ }
+ return false;
+ } else if (isFakeProperty(index)) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ const bool result = p->reset(d->m_object);
+ d->m_fakeProperties[index] = p->read(d->m_object);
+ return result;
+ } else if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
+ if (QWidget *w = qobject_cast<QWidget*>(d->m_object)) {
+ QWidget *widget = w;
+ if (qdesigner_internal::Utils::isCentralWidget(d->m_fwb, widget) && d->m_fwb->parentWidget())
+ widget = d->m_fwb->parentWidget();
+
+ if (widget != w && widget->parentWidget()) {
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ widget->parentWidget()->adjustSize();
+ }
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ widget->adjustSize();
+ return true;
+ }
+ }
+ // ### TODO: reset for fake properties.
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ return p->reset(d->m_object);
+}
+
+bool QDesignerPropertySheet::isChanged(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ return layoutPropertySheet->isChanged(newIndex);
+ return false;
+ }
+ }
+ }
+ }
+ return d->m_info.value(index).changed;
+}
+
+void QDesignerPropertySheet::setChanged(int index, bool changed)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ layoutPropertySheet->setChanged(newIndex, changed);
+ }
+ }
+ }
+ }
+ if (d->isReloadableProperty(index)) {
+ if (d->m_fwb) {
+ if (changed)
+ d->m_fwb->addReloadableProperty(this, index);
+ else
+ d->m_fwb->removeReloadableProperty(this, index);
+ }
+ }
+ d->ensureInfo(index).changed = changed;
+}
+
+bool QDesignerPropertySheet::isFakeLayoutProperty(int index) const
+{
+ if (!isAdditionalProperty(index))
+ return false;
+
+ switch (propertyType(index)) {
+ case PropertyLayoutObjectName:
+ case PropertyLayoutSizeConstraint:
+ return true;
+ case PropertyLayoutLeftMargin:
+ case PropertyLayoutTopMargin:
+ case PropertyLayoutRightMargin:
+ case PropertyLayoutBottomMargin:
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment:
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ return d->m_canHaveLayoutAttributes;
+ default:
+ break;
+ }
+ return false;
+}
+
+// Determine the "designable" state of a property. Properties, which have
+// a per-object boolean test function that returns false are shown in
+// disabled state ("checked" depending on "checkable", etc.)
+// Properties, which are generally not designable independent
+// of the object are not shown at all.
+enum DesignableState { PropertyIsDesignable,
+ // Object has a Designable test function that returns false.
+ PropertyOfObjectNotDesignable,
+ PropertyNotDesignable };
+
+static inline DesignableState designableState(const QDesignerMetaPropertyInterface *p, const QObject *object)
+{
+ if (p->attributes(object) & QDesignerMetaPropertyInterface::DesignableAttribute)
+ return PropertyIsDesignable;
+ return (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute) ?
+ PropertyOfObjectNotDesignable : PropertyNotDesignable;
+}
+
+bool QDesignerPropertySheet::isVisible(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+
+ const PropertyType type = propertyType(index);
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index) && d->m_object->isWidgetType()) {
+ const QLayout *currentLayout = d->layout();
+ if (!currentLayout)
+ return false;
+ const int visibleMask = qdesigner_internal::LayoutProperties::visibleProperties(currentLayout);
+ switch (type) {
+ case PropertyLayoutSpacing:
+ return visibleMask & qdesigner_internal::LayoutProperties::SpacingProperty;
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ return visibleMask & qdesigner_internal::LayoutProperties::HorizSpacingProperty;
+ case PropertyLayoutFieldGrowthPolicy:
+ return visibleMask & qdesigner_internal::LayoutProperties::FieldGrowthPolicyProperty;
+ case PropertyLayoutRowWrapPolicy:
+ return visibleMask & qdesigner_internal::LayoutProperties::RowWrapPolicyProperty;
+ case PropertyLayoutLabelAlignment:
+ return visibleMask & qdesigner_internal::LayoutProperties::LabelAlignmentProperty;
+ case PropertyLayoutFormAlignment:
+ return visibleMask & qdesigner_internal::LayoutProperties::FormAlignmentProperty;
+ case PropertyLayoutBoxStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::BoxStretchProperty;
+ case PropertyLayoutGridRowStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridRowStretchProperty;
+ case PropertyLayoutGridColumnStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridColumnStretchProperty;
+ case PropertyLayoutGridRowMinimumHeight:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridRowMinimumHeightProperty;
+ case PropertyLayoutGridColumnMinimumWidth:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridColumnMinimumWidthProperty;
+ default:
+ break;
+ }
+ return true;
+ }
+ return d->m_info.value(index).visible;
+ }
+
+ if (isFakeProperty(index)) {
+ switch (type) {
+ case PropertyWindowModality: // Hidden for child widgets
+ case PropertyWindowOpacity:
+ return d->m_info.value(index).visible;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ const bool visible = d->m_info.value(index).visible;
+ switch (type) {
+ case PropertyWindowTitle:
+ case PropertyWindowIcon:
+ case PropertyWindowFilePath:
+ case PropertyWindowOpacity:
+ case PropertyWindowIconText:
+ case PropertyWindowModified:
+ return visible;
+ default:
+ if (visible)
+ return true;
+ break;
+ }
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ if (!(p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess))
+ return false;
+
+ // Enabled handling: Hide only statically not designable properties
+ return designableState(p, d->m_object) != PropertyNotDesignable;
+}
+
+void QDesignerPropertySheet::setVisible(int index, bool visible)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).visible = visible;
+}
+
+bool QDesignerPropertySheet::isEnabled(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return true;
+
+ if (isFakeProperty(index))
+ return true;
+
+ // Grey out geometry of laid-out widgets (including splitter)
+ if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
+ bool isManaged;
+ const qdesigner_internal::LayoutInfo::Type lt = qdesigner_internal::LayoutInfo::laidoutWidgetType(d->m_core, qobject_cast<QWidget *>(d->m_object), &isManaged);
+ return !isManaged || lt == qdesigner_internal::LayoutInfo::NoLayout;
+ }
+
+ if (d->m_info.value(index).visible == true) // Sun CC 5.5 oddity, wants true
+ return true;
+
+ // Enable setting of properties for statically non-designable properties
+ // as this might be done via TaskMenu/Cursor::setProperty. Note that those
+ // properties are not visible.
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ return (p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess) &&
+ designableState(p, d->m_object) != PropertyOfObjectNotDesignable;
+}
+
+bool QDesignerPropertySheet::isAttribute(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return d->m_info.value(index).attribute;
+
+ if (isFakeProperty(index))
+ return false;
+
+ return d->m_info.value(index).attribute;
+}
+
+void QDesignerPropertySheet::setAttribute(int index, bool attribute)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).attribute = attribute;
+}
+
+QDesignerFormEditorInterface *QDesignerPropertySheet::core() const
+{
+ return d->m_core;
+}
+
+bool QDesignerPropertySheet::internalDynamicPropertiesEnabled()
+{
+ return QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled;
+}
+
+void QDesignerPropertySheet::setInternalDynamicPropertiesEnabled(bool v)
+{
+ QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = v;
+}
+
+// ---------- QDesignerAbstractPropertySheetFactory
+
+struct QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate {
+ PropertySheetFactoryPrivate();
+ const QString m_propertySheetId;
+ const QString m_dynamicPropertySheetId;
+
+ typedef QMap<QObject*, QObject*> ExtensionMap;
+ ExtensionMap m_extensions;
+ typedef QHash<QObject*, bool> ExtendedSet;
+ ExtendedSet m_extended;
+};
+
+QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate::PropertySheetFactoryPrivate() :
+ m_propertySheetId(Q_TYPEID(QDesignerPropertySheetExtension)),
+ m_dynamicPropertySheetId(Q_TYPEID(QDesignerDynamicPropertySheetExtension))
+{
+}
+
+// ---------- QDesignerAbstractPropertySheetFactory
+
+
+QDesignerAbstractPropertySheetFactory::QDesignerAbstractPropertySheetFactory(QExtensionManager *parent) :
+ QExtensionFactory(parent),
+ m_impl(new PropertySheetFactoryPrivate)
+{
+}
+
+QDesignerAbstractPropertySheetFactory::~QDesignerAbstractPropertySheetFactory()
+{
+ delete m_impl;
+}
+
+QObject *QDesignerAbstractPropertySheetFactory::extension(QObject *object, const QString &iid) const
+{
+ typedef PropertySheetFactoryPrivate::ExtensionMap ExtensionMap;
+ if (!object)
+ return 0;
+
+ if (iid != m_impl->m_propertySheetId && iid != m_impl->m_dynamicPropertySheetId)
+ return 0;
+
+ ExtensionMap::iterator it = m_impl->m_extensions.find(object);
+ if (it == m_impl->m_extensions.end()) {
+ if (QObject *ext = createPropertySheet(object, const_cast<QDesignerAbstractPropertySheetFactory*>(this))) {
+ connect(ext, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ it = m_impl->m_extensions.insert(object, ext);
+ }
+ }
+
+ if (!m_impl->m_extended.contains(object)) {
+ connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ m_impl->m_extended.insert(object, true);
+ }
+
+ if (it == m_impl->m_extensions.end())
+ return 0;
+
+ return it.value();
+}
+
+void QDesignerAbstractPropertySheetFactory::objectDestroyed(QObject *object)
+{
+ QMutableMapIterator<QObject*, QObject*> it(m_impl->m_extensions);
+ while (it.hasNext()) {
+ it.next();
+
+ QObject *o = it.key();
+ if (o == object || object == it.value()) {
+ it.remove();
+ }
+ }
+
+ m_impl->m_extended.remove(object);
+}
+
+QT_END_NAMESPACE