1649 lines
65 KiB
C++
1649 lines
65 KiB
C++
|
/****************************************************************************
|
||
|
**
|
||
|
** Copyright (C) 2010 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$
|
||
|
** Commercial Usage
|
||
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
||
|
** accordance with the Qt Commercial License Agreement provided with the
|
||
|
** Software or, alternatively, in accordance with the terms contained in
|
||
|
** a written agreement between you and Nokia.
|
||
|
**
|
||
|
** 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.
|
||
|
**
|
||
|
** 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.
|
||
|
**
|
||
|
** 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, 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
|