/****************************************************************************
**
** 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 "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, qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()));
    else if (type == QVariant::Icon)
        m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
}

QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const
{
    QVariant v = m_resourceProperties.value(index);
    if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v))
        return qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue());
    if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v))
        return qVariantFromValue(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 ((qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v))
        || (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v)))
        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 = qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
    else if (value.type() == QVariant::Pixmap)
        v = qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue());
    else if (value.type() == QVariant::String)
        v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(value.toString()));
    else if (value.type() == QVariant::KeySequence) {
        const QKeySequence keySequence = qVariantValue<QKeySequence>(value);
        v = qVariantFromValue(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 = qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
        if (v.type() == QVariant::KeySequence)
            v = qVariantFromValue(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 qVariantFromValue(value);
    }

    if (d->isKeySequenceProperty(index)) {
        QKeySequence keyValue = qVariantValue<QKeySequence>(metaProperty(index));
        qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index);
        if (keyValue != value.value()) {
            value.setValue(keyValue);
            d->setKeySequenceProperty(index, value); // cache it
        }
        return qVariantFromValue(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()));
        qVariantSetValue(v, psflags);
    }
        break;
    case QDesignerMetaPropertyInterface::EnumKind: {
        qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator()));
        qVariantSetValue(v, pse);
    }
        break;
    case QDesignerMetaPropertyInterface::OtherKind:
        break;
    }
    return v;
}

QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const
{
    if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value))
        return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value;

    if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value))
        return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value;

    if (qVariantCanConvert<qdesigner_internal::PropertySheetStringValue>(value))
        return qVariantValue<qdesigner_internal::PropertySheetStringValue>(value).value();

    if (qVariantCanConvert<qdesigner_internal::PropertySheetKeySequenceValue>(value))
        return qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value).value();

    if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value)) {
        const QString path = qVariantValue<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 (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value)) {
        const int pathCount = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value).paths().count();
        if (pathCount == 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 (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value) || qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) {
        v = value;
    } else if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(v)) {
        qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v);
        f.value = value.toInt();
        qVariantSetValue(v, f);
        Q_ASSERT(value.type() == QVariant::Int);
    } else if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(v)) {
        qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v);
        e.value = value.toInt();
        qVariantSetValue(v, 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, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value));
            if (d->isKeySequenceProperty(index))
                d->setKeySequenceProperty(index, qVariantValue<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, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value));
        if (d->isKeySequenceProperty(index))
            d->setKeySequenceProperty(index, qVariantValue<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 = qVariantValue<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;
                    qVariantSetValue(v, e);
                    setFakeProperty(idx, v);
                } else {
                    e.value = Qt::NoFocus;
                    QVariant v;
                    qVariantSetValue(v, 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))
        setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
    if (d->isKeySequenceProperty(index))
        setProperty(index, qVariantFromValue(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 = qVariantFromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString()));
        } else if (d->isKeySequenceProperty(index)) {
            const QKeySequence keySequence = qVariantValue<QKeySequence>(newValue);
            newValue = qVariantFromValue(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
