1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdesigner_propertysheet_p.h"
43 #include "qdesigner_utils_p.h"
44 #include "formwindowbase_p.h"
45 #include "layoutinfo_p.h"
46 #include "qlayout_widget_p.h"
47 #include "qdesigner_introspection_p.h"
48 
49 #include <formbuilderextra_p.h>
50 
51 #include <QtDesigner/QDesignerFormWindowInterface>
52 #include <QtDesigner/QDesignerFormEditorInterface>
53 #include <QtDesigner/QDesignerWidgetDataBaseInterface>
54 
55 #include <QtCore/QDebug>
56 
57 #include <QtGui/QLayout>
58 #include <QtGui/QDockWidget>
59 #include <QtGui/QDialog>
60 #include <QtGui/QLabel>
61 #include <QtGui/QGroupBox>
62 #include <QtGui/QStyle>
63 #include <QtGui/QApplication>
64 #include <QtGui/QToolBar>
65 #include <QtGui/QMainWindow>
66 #include <QtGui/QMenuBar>
67 
68 QT_BEGIN_NAMESPACE
69 
70 #define USE_LAYOUT_SIZE_CONSTRAINT
71 
propertyIntroducedBy(const QDesignerMetaObjectInterface * meta,int index)72 static const QDesignerMetaObjectInterface *propertyIntroducedBy(const QDesignerMetaObjectInterface *meta, int index)
73 {
74     if (index >= meta->propertyOffset())
75         return meta;
76 
77     if (meta->superClass())
78         return propertyIntroducedBy(meta->superClass(), index);
79 
80     return 0;
81 }
82 
83 // Layout fake properties (prefixed by 'layout' to distinguish them from other 'margins'
84 // that might be around. These are forwarded to the layout sheet (after name transformation).
85 //
86 // 'layoutObjectName' is new for 4.4. It is the name of the actual layout.
87 // Up to 4.3, QLayoutWidget's name was displayed in the objectinspector.
88 // This changes with 4.4; the layout name is displayed. This means that for
89 // old forms, QLayoutWidget will show up as ''; however, the uic code will
90 // still use 'verticalLayout' (in case someone accesses it). New Layouts get autogenerated names,
91 // legacy forms will keep their empty names (unless someone types in a new name).
92 static const char *layoutObjectNameC = "layoutName";
93 static const char *layoutLeftMarginC = "layoutLeftMargin";
94 static const char *layoutTopMarginC = "layoutTopMargin";
95 static const char *layoutRightMarginC = "layoutRightMargin";
96 static const char *layoutBottomMarginC = "layoutBottomMargin";
97 static const char *layoutSpacingC = "layoutSpacing";
98 static const char *layoutHorizontalSpacingC = "layoutHorizontalSpacing";
99 static const char *layoutVerticalSpacingC = "layoutVerticalSpacing";
100 static const char *layoutSizeConstraintC = "layoutSizeConstraint";
101 // form layout
102 static const char *layoutFieldGrowthPolicyC = "layoutFieldGrowthPolicy";
103 static const char *layoutRowWrapPolicyC = "layoutRowWrapPolicy";
104 static const char *layoutLabelAlignmentC = "layoutLabelAlignment";
105 static const char *layoutFormAlignmentC = "layoutFormAlignment";
106 // stretches
107 static const char *layoutboxStretchPropertyC = "layoutStretch";
108 static const char *layoutGridRowStretchPropertyC = "layoutRowStretch";
109 static const char *layoutGridColumnStretchPropertyC = "layoutColumnStretch";
110 static const char *layoutGridRowMinimumHeightC = "layoutRowMinimumHeight";
111 static const char *layoutGridColumnMinimumWidthC = "layoutColumnMinimumWidth";
112 
113 // Find the form editor in the hierarchy.
114 // We know that the parent of the sheet is the extension manager
115 // whose parent is the core.
116 
formEditorForObject(QObject * o)117 static QDesignerFormEditorInterface *formEditorForObject(QObject *o) {
118     do {
119         if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o))
120             return core;
121         o = o->parent();
122     } while(o);
123     Q_ASSERT(o);
124     return 0;
125 }
126 
hasLayoutAttributes(QDesignerFormEditorInterface * core,QObject * object)127 static bool hasLayoutAttributes(QDesignerFormEditorInterface *core, QObject *object)
128 {
129     if (!object->isWidgetType())
130         return false;
131 
132     QWidget *w =  qobject_cast<QWidget *>(object);
133     if (const QDesignerWidgetDataBaseInterface *db = core->widgetDataBase()) {
134         if (db->isContainer(w))
135             return true;
136     }
137     return false;
138 }
139 
140 // Cache DesignerMetaEnum by scope/name of a  QMetaEnum
designerMetaEnumFor(const QDesignerMetaEnumInterface * me)141 static const qdesigner_internal::DesignerMetaEnum &designerMetaEnumFor(const QDesignerMetaEnumInterface *me)
142 {
143     typedef QPair<QString, QString> ScopeNameKey;
144     typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaEnum> DesignerMetaEnumCache;
145     static DesignerMetaEnumCache cache;
146 
147     const QString name = me->name();
148     const QString scope = me->scope();
149 
150     const ScopeNameKey key = ScopeNameKey(scope, name);
151     DesignerMetaEnumCache::iterator it = cache.find(key);
152     if (it == cache.end()) {
153         qdesigner_internal::DesignerMetaEnum dme = qdesigner_internal::DesignerMetaEnum(name, scope, me->separator());
154         const int keyCount = me->keyCount();
155         for (int i=0; i < keyCount; ++i)
156             dme.addKey(me->value(i), me->key(i));
157         it = cache.insert(key, dme);
158     }
159     return it.value();
160 }
161 
162 // Cache DesignerMetaFlags by scope/name of a  QMetaEnum
designerMetaFlagsFor(const QDesignerMetaEnumInterface * me)163 static const qdesigner_internal::DesignerMetaFlags &designerMetaFlagsFor(const QDesignerMetaEnumInterface *me)
164 {
165     typedef QPair<QString, QString> ScopeNameKey;
166     typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaFlags> DesignerMetaFlagsCache;
167     static DesignerMetaFlagsCache cache;
168 
169     const QString name = me->name();
170     const QString scope = me->scope();
171 
172     const ScopeNameKey key = ScopeNameKey(scope, name);
173     DesignerMetaFlagsCache::iterator it = cache.find(key);
174     if (it == cache.end()) {
175         qdesigner_internal::DesignerMetaFlags dme = qdesigner_internal::DesignerMetaFlags(name, scope, me->separator());
176         const int keyCount = me->keyCount();
177         for (int i=0; i < keyCount; ++i)
178             dme.addKey(me->value(i), me->key(i));
179         it = cache.insert(key, dme);
180     }
181     return it.value();
182 }
183 
184 // ------------ QDesignerMemberSheetPrivate
185 class QDesignerPropertySheetPrivate {
186 public:
187     typedef QDesignerPropertySheet::PropertyType PropertyType;
188     typedef QDesignerPropertySheet::ObjectType ObjectType;
189 
190     explicit QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent);
191 
192     bool invalidIndex(const char *functionName, int index) const;
count() const193     inline int count() const { return m_meta->propertyCount() + m_addProperties.count(); }
194 
195     PropertyType propertyType(int index) const;
196     QString transformLayoutPropertyName(int index) const;
197     QLayout* layout(QDesignerPropertySheetExtension **layoutPropertySheet = 0) const;
198     static ObjectType objectType(const QObject *o);
199 
200     bool isReloadableProperty(int index) const;
201     bool isResourceProperty(int index) const;
202     void addResourceProperty(int index, QVariant::Type type);
203     QVariant resourceProperty(int index) const;
204     void setResourceProperty(int index, const QVariant &value);
205     QVariant emptyResourceProperty(int index) const; // of type PropertySheetPixmapValue / PropertySheetIconValue
206     QVariant defaultResourceProperty(int index) const; // of type QPixmap / QIcon (maybe it can be generalized for all types, not resource only)
207 
208     bool isStringProperty(int index) const;
209     void addStringProperty(int index);
210     qdesigner_internal::PropertySheetStringValue stringProperty(int index) const;
211     void setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value);
212 
213     bool isKeySequenceProperty(int index) const;
214     void addKeySequenceProperty(int index);
215     qdesigner_internal::PropertySheetKeySequenceValue keySequenceProperty(int index) const;
216     void setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value);
217 
218     enum PropertyKind { NormalProperty, FakeProperty, DynamicProperty, DefaultDynamicProperty };
219     class Info {
220     public:
221         Info();
222 
223         QString group;
224         QVariant defaultValue;
225         bool changed;
226         bool visible;
227         bool attribute;
228         bool reset;
229         PropertyType propertyType;
230         PropertyKind kind;
231     };
232 
233     Info &ensureInfo(int index);
234 
235     QDesignerPropertySheet *q;
236     QDesignerFormEditorInterface *m_core;
237     const QDesignerMetaObjectInterface *m_meta;
238     const ObjectType m_objectType;
239 
240     typedef QHash<int, Info> InfoHash;
241     InfoHash m_info;
242     QHash<int, QVariant> m_fakeProperties;
243     QHash<int, QVariant> m_addProperties;
244     QHash<QString, int> m_addIndex;
245     QHash<int, QVariant> m_resourceProperties; // only PropertySheetPixmapValue snd PropertySheetIconValue here
246     QHash<int, qdesigner_internal::PropertySheetStringValue> m_stringProperties; // only PropertySheetStringValue
247     QHash<int, qdesigner_internal::PropertySheetKeySequenceValue> m_keySequenceProperties; // only PropertySheetKeySequenceValue
248 
249     const bool m_canHaveLayoutAttributes;
250 
251     // Variables used for caching the layout, access via layout().
252     QPointer<QObject> m_object;
253     mutable QPointer<QLayout> m_lastLayout;
254     mutable QDesignerPropertySheetExtension *m_lastLayoutPropertySheet;
255     mutable bool m_LastLayoutByDesigner;
256 
257     qdesigner_internal::DesignerPixmapCache *m_pixmapCache;
258     qdesigner_internal::DesignerIconCache *m_iconCache;
259     QPointer<qdesigner_internal::FormWindowBase> m_fwb;
260 
261     // Enable Qt's internal properties starting with prefix "_q_"
262     static bool m_internalDynamicPropertiesEnabled;
263 };
264 
265 bool QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = false;
266 
267 /*
268     The property is reloadable if its contents depends on resource.
269 */
isReloadableProperty(int index) const270 bool QDesignerPropertySheetPrivate::isReloadableProperty(int index) const
271 {
272     return isResourceProperty(index)
273            || propertyType(index) == QDesignerPropertySheet::PropertyStyleSheet
274            || propertyType(index) == QDesignerPropertySheet::PropertyText
275            || q->property(index).type() == QVariant::Url;
276 }
277 
278 /*
279     Resource properties are those which:
280         1) are reloadable
281         2) their state is associated with a file which can be taken from resources
282         3) we don't store them in Qt meta object system (because designer keeps different data structure for them)
283 */
284 
isResourceProperty(int index) const285 bool QDesignerPropertySheetPrivate::isResourceProperty(int index) const
286 {
287     return m_resourceProperties.contains(index);
288 }
289 
addResourceProperty(int index,QVariant::Type type)290 void QDesignerPropertySheetPrivate::addResourceProperty(int index, QVariant::Type type)
291 {
292     if (type == QVariant::Pixmap)
293         m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()));
294     else if (type == QVariant::Icon)
295         m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()));
296 }
297 
emptyResourceProperty(int index) const298 QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const
299 {
300     QVariant v = m_resourceProperties.value(index);
301     if (v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
302         return QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
303     if (v.canConvert<qdesigner_internal::PropertySheetIconValue>())
304         return QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
305     return v;
306 }
307 
defaultResourceProperty(int index) const308 QVariant QDesignerPropertySheetPrivate::defaultResourceProperty(int index) const
309 {
310     return m_info.value(index).defaultValue;
311 }
312 
resourceProperty(int index) const313 QVariant QDesignerPropertySheetPrivate::resourceProperty(int index) const
314 {
315     return m_resourceProperties.value(index);
316 }
317 
setResourceProperty(int index,const QVariant & value)318 void QDesignerPropertySheetPrivate::setResourceProperty(int index, const QVariant &value)
319 {
320     Q_ASSERT(isResourceProperty(index));
321 
322     QVariant &v = m_resourceProperties[index];
323     if ((value.canConvert<qdesigner_internal::PropertySheetPixmapValue>() && v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
324         || (value.canConvert<qdesigner_internal::PropertySheetIconValue>() && v.canConvert<qdesigner_internal::PropertySheetIconValue>()))
325         v = value;
326 }
327 
isStringProperty(int index) const328 bool QDesignerPropertySheetPrivate::isStringProperty(int index) const
329 {
330     return m_stringProperties.contains(index);
331 }
332 
addStringProperty(int index)333 void QDesignerPropertySheetPrivate::addStringProperty(int index)
334 {
335     m_stringProperties.insert(index, qdesigner_internal::PropertySheetStringValue());
336 }
337 
stringProperty(int index) const338 qdesigner_internal::PropertySheetStringValue QDesignerPropertySheetPrivate::stringProperty(int index) const
339 {
340     return m_stringProperties.value(index);
341 }
342 
setStringProperty(int index,const qdesigner_internal::PropertySheetStringValue & value)343 void QDesignerPropertySheetPrivate::setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value)
344 {
345     Q_ASSERT(isStringProperty(index));
346 
347     m_stringProperties[index] = value;
348 }
349 
isKeySequenceProperty(int index) const350 bool QDesignerPropertySheetPrivate::isKeySequenceProperty(int index) const
351 {
352     return m_keySequenceProperties.contains(index);
353 }
354 
addKeySequenceProperty(int index)355 void QDesignerPropertySheetPrivate::addKeySequenceProperty(int index)
356 {
357     m_keySequenceProperties.insert(index, qdesigner_internal::PropertySheetKeySequenceValue());
358 }
359 
keySequenceProperty(int index) const360 qdesigner_internal::PropertySheetKeySequenceValue QDesignerPropertySheetPrivate::keySequenceProperty(int index) const
361 {
362     return m_keySequenceProperties.value(index);
363 }
364 
setKeySequenceProperty(int index,const qdesigner_internal::PropertySheetKeySequenceValue & value)365 void QDesignerPropertySheetPrivate::setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value)
366 {
367     Q_ASSERT(isKeySequenceProperty(index));
368 
369     m_keySequenceProperties[index] = value;
370 }
371 
Info()372 QDesignerPropertySheetPrivate::Info::Info() :
373     changed(false),
374     visible(true),
375     attribute(false),
376     reset(true),
377     propertyType(QDesignerPropertySheet::PropertyNone),
378     kind(NormalProperty)
379 {
380 }
381 
QDesignerPropertySheetPrivate(QDesignerPropertySheet * sheetPublic,QObject * object,QObject * sheetParent)382 QDesignerPropertySheetPrivate::QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent) :
383     q(sheetPublic),
384     m_core(formEditorForObject(sheetParent)),
385     m_meta(m_core->introspection()->metaObject(object)),
386     m_objectType(QDesignerPropertySheet::objectTypeFromObject(object)),
387     m_canHaveLayoutAttributes(hasLayoutAttributes(m_core, object)),
388     m_object(object),
389     m_lastLayout(0),
390     m_lastLayoutPropertySheet(0),
391     m_LastLayoutByDesigner(false),
392     m_pixmapCache(0),
393     m_iconCache(0)
394 {
395 }
396 
formWindowBase() const397 qdesigner_internal::FormWindowBase *QDesignerPropertySheet::formWindowBase() const
398 {
399     return d->m_fwb;
400 }
401 
invalidIndex(const char * functionName,int index) const402 bool QDesignerPropertySheetPrivate::invalidIndex(const char *functionName, int index) const
403 {
404     if (index < 0 || index >= count()) {
405         qWarning() <<  "** WARNING " << functionName << " invoked for " << m_object->objectName() << " was  passed an invalid index " << index << '.';
406         return true;
407     }
408     return false;
409 }
410 
layout(QDesignerPropertySheetExtension ** layoutPropertySheet) const411 QLayout* QDesignerPropertySheetPrivate::layout(QDesignerPropertySheetExtension **layoutPropertySheet) const
412 {
413     // Return the layout and its property sheet
414     // only if it is managed by designer and not one created on a custom widget.
415     // (attempt to cache the value as this requires some hoops).
416     if (layoutPropertySheet)
417         *layoutPropertySheet = 0;
418 
419     if (!m_object->isWidgetType() || !m_canHaveLayoutAttributes)
420         return 0;
421 
422     QWidget *widget = qobject_cast<QWidget*>(m_object);
423     QLayout *widgetLayout = qdesigner_internal::LayoutInfo::internalLayout(widget);
424     if (!widgetLayout) {
425         m_lastLayout = 0;
426         m_lastLayoutPropertySheet = 0;
427         return 0;
428     }
429     // Smart logic to avoid retrieving the meta DB from the widget every time.
430     if (widgetLayout != m_lastLayout) {
431         m_lastLayout = widgetLayout;
432         m_LastLayoutByDesigner = false;
433         m_lastLayoutPropertySheet = 0;
434         // Is this a layout managed by designer or some layout on a custom widget?
435         if (qdesigner_internal::LayoutInfo::managedLayout(m_core ,widgetLayout)) {
436             m_LastLayoutByDesigner = true;
437             m_lastLayoutPropertySheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), m_lastLayout);
438         }
439     }
440     if (!m_LastLayoutByDesigner)
441         return 0;
442 
443     if (layoutPropertySheet)
444         *layoutPropertySheet = m_lastLayoutPropertySheet;
445 
446     return  m_lastLayout;
447 }
448 
ensureInfo(int index)449 QDesignerPropertySheetPrivate::Info &QDesignerPropertySheetPrivate::ensureInfo(int index)
450 {
451     InfoHash::iterator it = m_info.find(index);
452     if (it == m_info.end())
453         it = m_info.insert(index, Info());
454     return it.value();
455 }
456 
propertyType(int index) const457 QDesignerPropertySheet::PropertyType QDesignerPropertySheetPrivate::propertyType(int index) const
458 {
459     const InfoHash::const_iterator it = m_info.constFind(index);
460     if (it == m_info.constEnd())
461         return QDesignerPropertySheet::PropertyNone;
462     return it.value().propertyType;
463 }
464 
transformLayoutPropertyName(int index) const465 QString QDesignerPropertySheetPrivate::transformLayoutPropertyName(int index) const
466 {
467     typedef QMap<QDesignerPropertySheet::PropertyType, QString> TypeNameMap;
468     static TypeNameMap typeNameMap;
469     if (typeNameMap.empty()) {
470         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutObjectName, QLatin1String("objectName"));
471         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLeftMargin, QLatin1String("leftMargin"));
472         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutTopMargin, QLatin1String("topMargin"));
473         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRightMargin, QLatin1String("rightMargin"));
474         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBottomMargin, QLatin1String("bottomMargin"));
475         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSpacing, QLatin1String("spacing"));
476         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutHorizontalSpacing, QLatin1String("horizontalSpacing"));
477         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutVerticalSpacing, QLatin1String("verticalSpacing"));
478         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSizeConstraint, QLatin1String("sizeConstraint"));
479         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFieldGrowthPolicy, QLatin1String("fieldGrowthPolicy"));
480         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRowWrapPolicy, QLatin1String("rowWrapPolicy"));
481         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLabelAlignment, QLatin1String("labelAlignment"));
482         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFormAlignment, QLatin1String("formAlignment"));
483         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBoxStretch, QLatin1String("stretch"));
484         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowStretch, QLatin1String("rowStretch"));
485         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnStretch, QLatin1String("columnStretch"));
486         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowMinimumHeight, QLatin1String("rowMinimumHeight"));
487         typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnMinimumWidth, QLatin1String("columnMinimumWidth"));
488     }
489     const TypeNameMap::const_iterator it = typeNameMap.constFind(propertyType(index));
490     if (it != typeNameMap.constEnd())
491         return it.value();
492     return QString();
493 }
494 
495 // ----------- QDesignerPropertySheet
496 
objectTypeFromObject(const QObject * o)497 QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectTypeFromObject(const QObject *o)
498 {
499     if (qobject_cast<const QLayout *>(o))
500         return ObjectLayout;
501 
502     if (!o->isWidgetType())
503         return ObjectNone;
504 
505     if (qobject_cast<const QLayoutWidget *>(o))
506         return ObjectLayoutWidget;
507 
508     if (qobject_cast<const QLabel*>(o))
509         return ObjectLabel;
510 
511     if (o->inherits("Q3GroupBox"))
512         return ObjectQ3GroupBox;
513 
514     return ObjectNone;
515 }
516 
propertyTypeFromName(const QString & name)517 QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyTypeFromName(const QString &name)
518 {
519     typedef QHash<QString, PropertyType> PropertyTypeHash;
520     static PropertyTypeHash propertyTypeHash;
521     if (propertyTypeHash.empty()) {
522         propertyTypeHash.insert(QLatin1String(layoutObjectNameC),         PropertyLayoutObjectName);
523         propertyTypeHash.insert(QLatin1String(layoutLeftMarginC),         PropertyLayoutLeftMargin);
524         propertyTypeHash.insert(QLatin1String(layoutTopMarginC),          PropertyLayoutTopMargin);
525         propertyTypeHash.insert(QLatin1String(layoutRightMarginC),        PropertyLayoutRightMargin);
526         propertyTypeHash.insert(QLatin1String(layoutBottomMarginC),       PropertyLayoutBottomMargin);
527         propertyTypeHash.insert(QLatin1String(layoutSpacingC),            PropertyLayoutSpacing);
528         propertyTypeHash.insert(QLatin1String(layoutHorizontalSpacingC),  PropertyLayoutHorizontalSpacing);
529         propertyTypeHash.insert(QLatin1String(layoutVerticalSpacingC),    PropertyLayoutVerticalSpacing);
530         propertyTypeHash.insert(QLatin1String(layoutSizeConstraintC),     PropertyLayoutSizeConstraint);
531         propertyTypeHash.insert(QLatin1String(layoutFieldGrowthPolicyC),  PropertyLayoutFieldGrowthPolicy);
532         propertyTypeHash.insert(QLatin1String(layoutRowWrapPolicyC),      PropertyLayoutRowWrapPolicy);
533         propertyTypeHash.insert(QLatin1String(layoutLabelAlignmentC),     PropertyLayoutLabelAlignment);
534         propertyTypeHash.insert(QLatin1String(layoutFormAlignmentC),      PropertyLayoutFormAlignment);
535         propertyTypeHash.insert(QLatin1String(layoutboxStretchPropertyC), PropertyLayoutBoxStretch);
536         propertyTypeHash.insert(QLatin1String(layoutGridRowStretchPropertyC),    PropertyLayoutGridRowStretch);
537         propertyTypeHash.insert(QLatin1String(layoutGridColumnStretchPropertyC), PropertyLayoutGridColumnStretch);
538         propertyTypeHash.insert(QLatin1String(layoutGridRowMinimumHeightC),      PropertyLayoutGridRowMinimumHeight);
539         propertyTypeHash.insert(QLatin1String(layoutGridColumnMinimumWidthC),    PropertyLayoutGridColumnMinimumWidth);
540         propertyTypeHash.insert(QLatin1String("buddy"),                   PropertyBuddy);
541         propertyTypeHash.insert(QLatin1String("geometry"),                PropertyGeometry);
542         propertyTypeHash.insert(QLatin1String("checkable"),               PropertyCheckable);
543         propertyTypeHash.insert(QLatin1String("accessibleName"),          PropertyAccessibility);
544         propertyTypeHash.insert(QLatin1String("accessibleDescription"),   PropertyAccessibility);
545         propertyTypeHash.insert(QLatin1String("windowTitle"),             PropertyWindowTitle);
546         propertyTypeHash.insert(QLatin1String("windowIcon"),              PropertyWindowIcon);
547         propertyTypeHash.insert(QLatin1String("windowFilePath"),          PropertyWindowFilePath);
548         propertyTypeHash.insert(QLatin1String("windowOpacity"),           PropertyWindowOpacity);
549         propertyTypeHash.insert(QLatin1String("windowIconText"),          PropertyWindowIconText);
550         propertyTypeHash.insert(QLatin1String("windowModality"),          PropertyWindowModality);
551         propertyTypeHash.insert(QLatin1String("windowModified"),          PropertyWindowModified);
552         propertyTypeHash.insert(QLatin1String("styleSheet"),              PropertyStyleSheet);
553         propertyTypeHash.insert(QLatin1String("text"),                    PropertyText);
554     }
555     return propertyTypeHash.value(name, PropertyNone);
556 }
557 
QDesignerPropertySheet(QObject * object,QObject * parent)558 QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent) :
559     QObject(parent),
560     d(new QDesignerPropertySheetPrivate(this, object, parent))
561 {
562     typedef QDesignerPropertySheetPrivate::Info Info;
563     const QDesignerMetaObjectInterface *baseMeta = d->m_meta;
564 
565     while (baseMeta &&baseMeta->className().startsWith(QLatin1String("QDesigner"))) {
566         baseMeta = baseMeta->superClass();
567     }
568     Q_ASSERT(baseMeta != 0);
569 
570     QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(d->m_object);
571     d->m_fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
572     if (d->m_fwb) {
573         d->m_pixmapCache = d->m_fwb->pixmapCache();
574         d->m_iconCache = d->m_fwb->iconCache();
575         d->m_fwb->addReloadablePropertySheet(this, object);
576     }
577 
578     for (int index=0; index<count(); ++index) {
579         const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
580         const QString name = p->name();
581         if (p->type() == QVariant::KeySequence) {
582             createFakeProperty(name);
583         } else {
584             setVisible(index, false); // use the default for `real' properties
585         }
586 
587         QString pgroup = baseMeta->className();
588 
589         if (const QDesignerMetaObjectInterface *pmeta = propertyIntroducedBy(baseMeta, index)) {
590             pgroup = pmeta->className();
591         }
592 
593         Info &info = d->ensureInfo(index);
594         info.group = pgroup;
595         info.propertyType = propertyTypeFromName(name);
596 
597         if (p->type() == QVariant::Cursor || p->type() == QVariant::Icon || p->type() == QVariant::Pixmap) {
598             info.defaultValue = p->read(d->m_object);
599             if (p->type() == QVariant::Icon || p->type() == QVariant::Pixmap)
600                 d->addResourceProperty(index, p->type());
601         } else if (p->type() == QVariant::String) {
602             d->addStringProperty(index);
603         } else if (p->type() == QVariant::KeySequence) {
604             d->addKeySequenceProperty(index);
605         }
606     }
607 
608     if (object->isWidgetType()) {
609         createFakeProperty(QLatin1String("focusPolicy"));
610         createFakeProperty(QLatin1String("cursor"));
611         createFakeProperty(QLatin1String("toolTip"));
612         createFakeProperty(QLatin1String("whatsThis"));
613         createFakeProperty(QLatin1String("acceptDrops"));
614         createFakeProperty(QLatin1String("dragEnabled"));
615         // windowModality/Opacity is visible only for the main container, in which case the form windows enables it on loading
616         setVisible(createFakeProperty(QLatin1String("windowModality")), false);
617         setVisible(createFakeProperty(QLatin1String("windowOpacity"), double(1.0)), false);
618         if (qobject_cast<const QToolBar *>(d->m_object)) { // prevent toolbars from being dragged off
619             createFakeProperty(QLatin1String("floatable"), QVariant(true));
620         } else {
621             if (qobject_cast<const QMenuBar *>(d->m_object)) {
622                 // Keep the menu bar editable in the form even if a native menu bar is used.
623                 const bool nativeMenuBarDefault = !qApp->testAttribute(Qt::AA_DontUseNativeMenuBar);
624                 createFakeProperty(QLatin1String("nativeMenuBar"), QVariant(nativeMenuBarDefault));
625             }
626         }
627         if (d->m_canHaveLayoutAttributes) {
628             static const QString layoutGroup = QLatin1String("Layout");
629             const char* fakeLayoutProperties[] = {
630                 layoutObjectNameC, layoutLeftMarginC, layoutTopMarginC, layoutRightMarginC, layoutBottomMarginC, layoutSpacingC, layoutHorizontalSpacingC, layoutVerticalSpacingC,
631                 layoutFieldGrowthPolicyC, layoutRowWrapPolicyC, layoutLabelAlignmentC, layoutFormAlignmentC,
632                 layoutboxStretchPropertyC, layoutGridRowStretchPropertyC, layoutGridColumnStretchPropertyC,
633                 layoutGridRowMinimumHeightC, layoutGridColumnMinimumWidthC
634 #ifdef USE_LAYOUT_SIZE_CONSTRAINT
635                 , layoutSizeConstraintC
636 #endif
637             };
638             const int fakeLayoutPropertyCount = sizeof(fakeLayoutProperties)/sizeof(const char*);
639             const int size = count();
640             for (int i = 0; i < fakeLayoutPropertyCount; i++) {
641                 createFakeProperty(QLatin1String(fakeLayoutProperties[i]), 0);
642                 setAttribute(size  + i, true);
643                 setPropertyGroup(size  + i, layoutGroup);
644             }
645         }
646 
647         if (d->m_objectType == ObjectLabel)
648             createFakeProperty(QLatin1String("buddy"), QVariant(QByteArray()));
649         /* We need to create a fake property since the property does not work
650          * for non-toplevel windows or on other systems than Mac and only if
651          * it is above a certain Mac OS version. */
652         if (qobject_cast<const QMainWindow *>(d->m_object))
653             createFakeProperty(QLatin1String("unifiedTitleAndToolBarOnMac"), false);
654     }
655 
656     if (qobject_cast<const QDialog*>(object)) {
657         createFakeProperty(QLatin1String("modal"));
658     }
659     if (qobject_cast<const QDockWidget*>(object)) {
660         createFakeProperty(QLatin1String("floating"));
661     }
662 
663     typedef QList<QByteArray> ByteArrayList;
664     const ByteArrayList names = object->dynamicPropertyNames();
665     if (!names.empty()) {
666         const ByteArrayList::const_iterator cend =  names.constEnd();
667         for (ByteArrayList::const_iterator it = names.constBegin(); it != cend; ++it) {
668             const char* cName = it->constData();
669             const QString name = QString::fromLatin1(cName);
670             const int idx = addDynamicProperty(name, object->property(cName));
671             if (idx != -1)
672                 d->ensureInfo(idx).kind = QDesignerPropertySheetPrivate::DefaultDynamicProperty;
673         }
674     }
675 }
676 
~QDesignerPropertySheet()677 QDesignerPropertySheet::~QDesignerPropertySheet()
678 {
679     if (d->m_fwb)
680         d->m_fwb->removeReloadablePropertySheet(this);
681     delete d;
682 }
683 
object() const684 QObject *QDesignerPropertySheet::object() const
685 {
686     return d->m_object;
687 }
688 
dynamicPropertiesAllowed() const689 bool QDesignerPropertySheet::dynamicPropertiesAllowed() const
690 {
691     return true;
692 }
693 
canAddDynamicProperty(const QString & propName) const694 bool QDesignerPropertySheet::canAddDynamicProperty(const QString &propName) const
695 {
696     // used internally
697     if (propName == QLatin1String("database") ||
698         propName == QLatin1String("buttonGroupId"))
699         return false;
700     const int index = d->m_meta->indexOfProperty(propName);
701     if (index != -1)
702         return false; // property already exists and is not a dynamic one
703     if (d->m_addIndex.contains(propName)) {
704         const int idx = d->m_addIndex.value(propName);
705         if (isVisible(idx))
706             return false; // dynamic property already exists
707         else
708             return true;
709     }
710     if (!QDesignerPropertySheet::internalDynamicPropertiesEnabled() && propName.startsWith(QLatin1String("_q_")))
711         return false;
712     return true;
713 }
714 
addDynamicProperty(const QString & propName,const QVariant & value)715 int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QVariant &value)
716 {
717     typedef QDesignerPropertySheetPrivate::Info Info;
718     if (!value.isValid())
719         return -1; // property has invalid type
720     if (!canAddDynamicProperty(propName))
721         return -1;
722 
723     QVariant v = value;
724     if (value.type() == QVariant::Icon)
725         v = QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
726     else if (value.type() == QVariant::Pixmap)
727         v = QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
728     else if (value.type() == QVariant::String)
729         v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(value.toString()));
730     else if (value.type() == QVariant::KeySequence) {
731         const QKeySequence keySequence = qvariant_cast<QKeySequence>(value);
732         v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
733     }
734 
735     if (d->m_addIndex.contains(propName)) {
736         const int idx = d->m_addIndex.value(propName);
737         // have to be invisible, this was checked in canAddDynamicProperty() method
738         setVisible(idx, true);
739         d->m_addProperties.insert(idx, v);
740         setChanged(idx, false);
741         const int index = d->m_meta->indexOfProperty(propName);
742         Info &info = d->ensureInfo(index);
743         info.defaultValue = value;
744         info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
745         if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
746             d->addResourceProperty(idx, value.type());
747         else if (value.type() == QVariant::String)
748             d->addStringProperty(idx);
749         else if (value.type() == QVariant::KeySequence)
750             d->addKeySequenceProperty(idx);
751         return idx;
752     }
753 
754     const int index = count();
755     d->m_addIndex.insert(propName, index);
756     d->m_addProperties.insert(index, v);
757     Info &info = d->ensureInfo(index);
758     info.visible = true;
759     info.changed = false;
760     info.defaultValue = value;
761     info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
762     setPropertyGroup(index, tr("Dynamic Properties"));
763     if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
764         d->addResourceProperty(index, value.type());
765     else if (value.type() == QVariant::String)
766         d->addStringProperty(index);
767     else if (value.type() == QVariant::KeySequence)
768         d->addKeySequenceProperty(index);
769     return index;
770 }
771 
removeDynamicProperty(int index)772 bool QDesignerPropertySheet::removeDynamicProperty(int index)
773 {
774     if (!d->m_addIndex.contains(propertyName(index)))
775         return false;
776 
777     setVisible(index, false);
778     return true;
779 }
780 
isDynamic(int index) const781 bool QDesignerPropertySheet::isDynamic(int index) const
782 {
783     if (!d->m_addProperties.contains(index))
784         return false;
785 
786     switch (propertyType(index)) {
787     case PropertyBuddy:
788         if (d->m_objectType == ObjectLabel)
789             return false;
790         break;
791     case PropertyLayoutLeftMargin:
792     case PropertyLayoutTopMargin:
793     case PropertyLayoutRightMargin:
794     case PropertyLayoutBottomMargin:
795     case PropertyLayoutSpacing:
796     case PropertyLayoutHorizontalSpacing:
797     case PropertyLayoutVerticalSpacing:
798     case PropertyLayoutObjectName:
799     case PropertyLayoutSizeConstraint:
800     case PropertyLayoutFieldGrowthPolicy:
801     case PropertyLayoutRowWrapPolicy:
802     case PropertyLayoutLabelAlignment:
803     case PropertyLayoutFormAlignment:
804     case PropertyLayoutBoxStretch:
805     case PropertyLayoutGridRowStretch:
806     case PropertyLayoutGridColumnStretch:
807     case PropertyLayoutGridRowMinimumHeight:
808     case PropertyLayoutGridColumnMinimumWidth:
809         if (d->m_object->isWidgetType() && d->m_canHaveLayoutAttributes)
810             return false;
811     default:
812         break;
813     }
814     return true;
815 }
816 
isDynamicProperty(int index) const817 bool QDesignerPropertySheet::isDynamicProperty(int index) const
818 {
819     // Do not complain here, as an invalid index might be encountered
820     // if someone implements a property sheet only, omitting the dynamic sheet.
821     if (index < 0 || index >= count())
822         return false;
823     return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DynamicProperty;
824 }
825 
isDefaultDynamicProperty(int index) const826 bool QDesignerPropertySheet::isDefaultDynamicProperty(int index) const
827 {
828     if (d->invalidIndex(Q_FUNC_INFO, index))
829         return false;
830     return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DefaultDynamicProperty;
831 }
832 
isResourceProperty(int index) const833 bool QDesignerPropertySheet::isResourceProperty(int index) const
834 {
835     return d->isResourceProperty(index);
836 }
837 
defaultResourceProperty(int index) const838 QVariant QDesignerPropertySheet::defaultResourceProperty(int index) const
839 {
840     return d->defaultResourceProperty(index);
841 }
842 
pixmapCache() const843 qdesigner_internal::DesignerPixmapCache *QDesignerPropertySheet::pixmapCache() const
844 {
845     return d->m_pixmapCache;
846 }
847 
setPixmapCache(qdesigner_internal::DesignerPixmapCache * cache)848 void QDesignerPropertySheet::setPixmapCache(qdesigner_internal::DesignerPixmapCache *cache)
849 {
850     d->m_pixmapCache = cache;
851 }
852 
iconCache() const853 qdesigner_internal::DesignerIconCache *QDesignerPropertySheet::iconCache() const
854 {
855     return d->m_iconCache;
856 }
857 
setIconCache(qdesigner_internal::DesignerIconCache * cache)858 void QDesignerPropertySheet::setIconCache(qdesigner_internal::DesignerIconCache *cache)
859 {
860     d->m_iconCache = cache;
861 }
862 
createFakeProperty(const QString & propertyName,const QVariant & value)863 int QDesignerPropertySheet::createFakeProperty(const QString &propertyName, const QVariant &value)
864 {
865     typedef QDesignerPropertySheetPrivate::Info Info;
866     // fake properties
867     const int index = d->m_meta->indexOfProperty(propertyName);
868     if (index != -1) {
869         if (!(d->m_meta->property(index)->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute))
870             return -1;
871         Info &info = d->ensureInfo(index);
872         info.visible = false;
873         info.kind = QDesignerPropertySheetPrivate::FakeProperty;
874         QVariant v = value.isValid() ? value : metaProperty(index);
875         if (v.type() == QVariant::String)
876             v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
877         if (v.type() == QVariant::KeySequence)
878             v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue());
879         d->m_fakeProperties.insert(index, v);
880         return index;
881     }
882     if (!value.isValid())
883         return -1;
884 
885     const int newIndex = count();
886     d->m_addIndex.insert(propertyName, newIndex);
887     d->m_addProperties.insert(newIndex, value);
888     Info &info = d->ensureInfo(newIndex);
889     info.propertyType = propertyTypeFromName(propertyName);
890     info.kind = QDesignerPropertySheetPrivate::FakeProperty;
891     return newIndex;
892 }
893 
isAdditionalProperty(int index) const894 bool QDesignerPropertySheet::isAdditionalProperty(int index) const
895 {
896     if (d->invalidIndex(Q_FUNC_INFO, index))
897         return false;
898     return d->m_addProperties.contains(index);
899 }
900 
isFakeProperty(int index) const901 bool QDesignerPropertySheet::isFakeProperty(int index) const
902 {
903     if (d->invalidIndex(Q_FUNC_INFO, index))
904         return false;
905     // additional properties must be fake
906     return (d->m_fakeProperties.contains(index) || isAdditionalProperty(index));
907 }
908 
count() const909 int QDesignerPropertySheet::count() const
910 {
911     return d->count();
912 }
913 
indexOf(const QString & name) const914 int QDesignerPropertySheet::indexOf(const QString &name) const
915 {
916     int index = d->m_meta->indexOfProperty(name);
917 
918     if (index == -1)
919         index = d->m_addIndex.value(name, -1);
920 
921     return index;
922 }
923 
propertyType(int index) const924 QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyType(int index) const
925 {
926     if (d->invalidIndex(Q_FUNC_INFO, index))
927         return PropertyNone;
928     return d->propertyType(index);
929 }
930 
objectType() const931 QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectType() const
932 {
933     return d->m_objectType;
934 }
935 
propertyName(int index) const936 QString QDesignerPropertySheet::propertyName(int index) const
937 {
938     if (d->invalidIndex(Q_FUNC_INFO, index))
939         return QString();
940     if (isAdditionalProperty(index))
941         return d->m_addIndex.key(index);
942 
943     return d->m_meta->property(index)->name();
944 }
945 
propertyGroup(int index) const946 QString QDesignerPropertySheet::propertyGroup(int index) const
947 {
948     if (d->invalidIndex(Q_FUNC_INFO, index))
949         return QString();
950     const QString g = d->m_info.value(index).group;
951 
952     if (!g.isEmpty())
953         return g;
954 
955     if (propertyType(index) == PropertyAccessibility)
956         return QString::fromUtf8("Accessibility");
957 
958     if (isAdditionalProperty(index))
959         return d->m_meta->className();
960 
961     return g;
962 }
963 
setPropertyGroup(int index,const QString & group)964 void QDesignerPropertySheet::setPropertyGroup(int index, const QString &group)
965 {
966     if (d->invalidIndex(Q_FUNC_INFO, index))
967         return;
968     d->ensureInfo(index).group = group;
969 }
970 
property(int index) const971 QVariant QDesignerPropertySheet::property(int index) const
972 {
973     if (d->invalidIndex(Q_FUNC_INFO, index))
974         return QVariant();
975     if (isAdditionalProperty(index)) {
976         if (isFakeLayoutProperty(index)) {
977             QDesignerPropertySheetExtension *layoutPropertySheet;
978             if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
979                 const QString newPropName = d->transformLayoutPropertyName(index);
980                 if (!newPropName.isEmpty()) {
981                     const int newIndex = layoutPropertySheet->indexOf(newPropName);
982                     if (newIndex != -1)
983                         return layoutPropertySheet->property(newIndex);
984                     return QVariant();
985                 }
986             }
987         }
988         return d->m_addProperties.value(index);
989     }
990 
991     if (isFakeProperty(index)) {
992         return d->m_fakeProperties.value(index);
993     }
994 
995     if (d->isResourceProperty(index))
996         return d->resourceProperty(index);
997 
998     if (d->isStringProperty(index)) {
999         QString strValue = metaProperty(index).toString();
1000         qdesigner_internal::PropertySheetStringValue value = d->stringProperty(index);
1001         if (strValue != value.value()) {
1002             value.setValue(strValue);
1003             d->setStringProperty(index, value); // cache it
1004         }
1005         return QVariant::fromValue(value);
1006     }
1007 
1008     if (d->isKeySequenceProperty(index)) {
1009         QKeySequence keyValue = qvariant_cast<QKeySequence>(metaProperty(index));
1010         qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index);
1011         if (keyValue != value.value()) {
1012             value.setValue(keyValue);
1013             d->setKeySequenceProperty(index, value); // cache it
1014         }
1015         return QVariant::fromValue(value);
1016     }
1017 
1018     return metaProperty(index);
1019 }
1020 
metaProperty(int index) const1021 QVariant QDesignerPropertySheet::metaProperty(int index) const
1022 {
1023     Q_ASSERT(!isFakeProperty(index));
1024 
1025     const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1026     QVariant v = p->read(d->m_object);
1027     switch (p->kind()) {
1028     case QDesignerMetaPropertyInterface::FlagKind: {
1029         qdesigner_internal::PropertySheetFlagValue psflags = qdesigner_internal::PropertySheetFlagValue(v.toInt(), designerMetaFlagsFor(p->enumerator()));
1030         v.setValue(psflags);
1031     }
1032         break;
1033     case QDesignerMetaPropertyInterface::EnumKind: {
1034         qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator()));
1035         v.setValue(pse);
1036     }
1037         break;
1038     case QDesignerMetaPropertyInterface::OtherKind:
1039         break;
1040     }
1041     return v;
1042 }
1043 
resolvePropertyValue(int index,const QVariant & value) const1044 QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const
1045 {
1046     if (value.canConvert<qdesigner_internal::PropertySheetEnumValue>())
1047         return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value;
1048 
1049     if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>())
1050         return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value;
1051 
1052     if (value.canConvert<qdesigner_internal::PropertySheetStringValue>())
1053         return qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value();
1054 
1055     if (value.canConvert<qdesigner_internal::PropertySheetKeySequenceValue>())
1056         return qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value).value();
1057 
1058     if (value.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) {
1059         const QString path = qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value).path();
1060         if (path.isEmpty())
1061             return defaultResourceProperty(index);
1062         if (d->m_pixmapCache) {
1063             return d->m_pixmapCache->pixmap(qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value));
1064         }
1065     }
1066 
1067     if (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) {
1068         const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask();
1069         if (mask == 0)
1070             return defaultResourceProperty(index);
1071         if (d->m_iconCache)
1072             return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value));
1073     }
1074 
1075     return value;
1076 }
1077 
setFakeProperty(int index,const QVariant & value)1078 void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value)
1079 {
1080     Q_ASSERT(isFakeProperty(index));
1081 
1082     QVariant &v = d->m_fakeProperties[index];
1083 
1084     // set resource properties also (if we are going to have fake resource properties)
1085     if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>() || value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
1086         v = value;
1087     } else if (v.canConvert<qdesigner_internal::PropertySheetFlagValue>()) {
1088         qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v);
1089         f.value = value.toInt();
1090         v.setValue(f);
1091         Q_ASSERT(value.type() == QVariant::Int);
1092     } else if (v.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
1093         qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v);
1094         e.value = value.toInt();
1095         v.setValue(e);
1096         Q_ASSERT(value.type() == QVariant::Int);
1097     } else {
1098         v = value;
1099     }
1100 }
1101 
clearFakeProperties()1102 void QDesignerPropertySheet::clearFakeProperties()
1103 {
1104     d->m_fakeProperties.clear();
1105 }
1106 
1107 // Buddy needs to be byte array, else uic won't work
toByteArray(const QVariant & value)1108 static QVariant toByteArray(const QVariant &value) {
1109     if (value.type() == QVariant::ByteArray)
1110         return value;
1111     const QByteArray ba = value.toString().toUtf8();
1112     return QVariant(ba);
1113 }
1114 
setProperty(int index,const QVariant & value)1115 void QDesignerPropertySheet::setProperty(int index, const QVariant &value)
1116 {
1117     if (d->invalidIndex(Q_FUNC_INFO, index))
1118         return;
1119     if (isAdditionalProperty(index)) {
1120         if (d->m_objectType == ObjectLabel && propertyType(index) == PropertyBuddy) {
1121             QFormBuilderExtra::applyBuddy(value.toString(), QFormBuilderExtra::BuddyApplyVisibleOnly, qobject_cast<QLabel *>(d->m_object));
1122             d->m_addProperties[index] = toByteArray(value);
1123             return;
1124         }
1125 
1126         if (isFakeLayoutProperty(index)) {
1127             QDesignerPropertySheetExtension *layoutPropertySheet;
1128             if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
1129                 const QString newPropName = d->transformLayoutPropertyName(index);
1130                 if (!newPropName.isEmpty()) {
1131                     const int newIndex = layoutPropertySheet->indexOf(newPropName);
1132                     if (newIndex != -1)
1133                         layoutPropertySheet->setProperty(newIndex, value);
1134                 }
1135             }
1136         }
1137 
1138         if (isDynamicProperty(index) || isDefaultDynamicProperty(index)) {
1139             if (d->isResourceProperty(index))
1140                 d->setResourceProperty(index, value);
1141             if (d->isStringProperty(index))
1142                 d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
1143             if (d->isKeySequenceProperty(index))
1144                 d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value));
1145             d->m_object->setProperty(propertyName(index).toUtf8(), resolvePropertyValue(index, value));
1146             if (d->m_object->isWidgetType()) {
1147                 QWidget *w = qobject_cast<QWidget *>(d->m_object);
1148                 w->setStyleSheet(w->styleSheet());
1149             }
1150         }
1151         d->m_addProperties[index] = value;
1152     } else if (isFakeProperty(index)) {
1153         setFakeProperty(index, value);
1154     } else {
1155         if (d->isResourceProperty(index))
1156             d->setResourceProperty(index, value);
1157         if (d->isStringProperty(index))
1158             d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
1159         if (d->isKeySequenceProperty(index))
1160             d->setKeySequenceProperty(index, qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value));
1161         const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1162         p->write(d->m_object, resolvePropertyValue(index, value));
1163         if (qobject_cast<QGroupBox *>(d->m_object) && propertyType(index) == PropertyCheckable) {
1164             const int idx = indexOf(QLatin1String("focusPolicy"));
1165             if (!isChanged(idx)) {
1166                 qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(property(idx));
1167                 if (value.toBool()) {
1168                     const QDesignerMetaPropertyInterface *p = d->m_meta->property(idx);
1169                     p->write(d->m_object, Qt::NoFocus);
1170                     e.value = Qt::StrongFocus;
1171                     QVariant v;
1172                     v.setValue(e);
1173                     setFakeProperty(idx, v);
1174                 } else {
1175                     e.value = Qt::NoFocus;
1176                     QVariant v;
1177                     v.setValue(e);
1178                     setFakeProperty(idx, v);
1179                 }
1180             }
1181         }
1182     }
1183 }
1184 
hasReset(int index) const1185 bool QDesignerPropertySheet::hasReset(int index) const
1186 {
1187     if (d->invalidIndex(Q_FUNC_INFO, index))
1188         return false;
1189     if (isAdditionalProperty(index))
1190         return d->m_info.value(index).reset;
1191     return true;
1192 }
1193 
reset(int index)1194 bool QDesignerPropertySheet::reset(int index)
1195 {
1196     if (d->invalidIndex(Q_FUNC_INFO, index))
1197         return false;
1198     if (d->isStringProperty(index)) {
1199         qdesigner_internal::PropertySheetStringValue value;
1200         // Main container: Reset to stored class name as not to change the file names generated by uic.
1201         if (propertyName(index) == QLatin1String("objectName")) {
1202             const QVariant classNameDefaultV = d->m_object->property("_q_classname");
1203             if (classNameDefaultV.isValid())
1204                 value.setValue(classNameDefaultV.toString());
1205         } else if (!isAdditionalProperty(index)) {
1206             const QDesignerMetaPropertyInterface *property = d->m_meta->property(index);
1207             if ((property->accessFlags() & QDesignerMetaPropertyInterface::ResetAccess) && property->reset(d->m_object))
1208                 value.setValue(property->read(d->m_object).toString());
1209             else
1210                 return false;
1211         }
1212         setProperty(index, QVariant::fromValue(value));
1213         return true;
1214     }
1215     if (d->isKeySequenceProperty(index))
1216         setProperty(index, QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue()));
1217     if (d->isResourceProperty(index)) {
1218         setProperty(index, d->emptyResourceProperty(index));
1219         return true;
1220     } else if (isDynamic(index)) {
1221         const QString propName = propertyName(index);
1222         const QVariant oldValue = d->m_addProperties.value(index);
1223         const QVariant defaultValue = d->m_info.value(index).defaultValue;
1224         QVariant newValue = defaultValue;
1225         if (d->isStringProperty(index)) {
1226             newValue = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString()));
1227         } else if (d->isKeySequenceProperty(index)) {
1228             const QKeySequence keySequence = qvariant_cast<QKeySequence>(newValue);
1229             newValue = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
1230         }
1231         if (oldValue == newValue)
1232             return true;
1233         d->m_object->setProperty(propName.toUtf8(), defaultValue);
1234         d->m_addProperties[index] = newValue;
1235         return true;
1236     } else if (!d->m_info.value(index).defaultValue.isNull()) {
1237         setProperty(index, d->m_info.value(index).defaultValue);
1238         return true;
1239     }
1240     if (isAdditionalProperty(index)) {
1241         const PropertyType pType = propertyType(index);
1242         if (d->m_objectType == ObjectLabel && pType == PropertyBuddy) {
1243             setProperty(index, QVariant(QByteArray()));
1244             return true;
1245         }
1246         if (isFakeLayoutProperty(index)) {
1247            // special properties
1248            switch (pType) {
1249            case PropertyLayoutObjectName:
1250               setProperty(index, QString());
1251               return true;
1252            case PropertyLayoutSizeConstraint:
1253               setProperty(index, QVariant(QLayout::SetDefaultConstraint));
1254               return true;
1255            case PropertyLayoutBoxStretch:
1256            case PropertyLayoutGridRowStretch:
1257            case PropertyLayoutGridColumnStretch:
1258            case PropertyLayoutGridRowMinimumHeight:
1259            case PropertyLayoutGridColumnMinimumWidth:
1260            case PropertyLayoutFieldGrowthPolicy:
1261            case PropertyLayoutRowWrapPolicy:
1262            case PropertyLayoutLabelAlignment:
1263            case PropertyLayoutFormAlignment: {
1264                QDesignerPropertySheetExtension *layoutPropertySheet;
1265                if (d->layout(&layoutPropertySheet) && layoutPropertySheet)
1266                    return layoutPropertySheet->reset(layoutPropertySheet->indexOf(d->transformLayoutPropertyName(index)));
1267            }
1268                break;
1269            default:
1270               break;
1271            }
1272            // special margins
1273             int value = -1;
1274             switch (d->m_objectType) {
1275             case ObjectQ3GroupBox: {
1276                 const QWidget *w = qobject_cast<const QWidget *>(d->m_object);
1277                 switch (pType) {
1278                 case PropertyLayoutLeftMargin:
1279                     value = w->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
1280                     break;
1281                 case PropertyLayoutTopMargin:
1282                     value = w->style()->pixelMetric(QStyle::PM_LayoutTopMargin);
1283                     break;
1284                 case PropertyLayoutRightMargin:
1285                     value = w->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
1286                     break;
1287                 case PropertyLayoutBottomMargin:
1288                     value = w->style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
1289                     break;
1290                 case PropertyLayoutSpacing:
1291                 case PropertyLayoutHorizontalSpacing:
1292                 case PropertyLayoutVerticalSpacing:
1293                     value = -1;
1294                     break;
1295                 default:
1296                     break;
1297                 }
1298             }
1299                 break;
1300             case ObjectLayoutWidget:
1301                 if (pType == PropertyLayoutLeftMargin ||
1302                         pType == PropertyLayoutTopMargin ||
1303                         pType == PropertyLayoutRightMargin ||
1304                         pType == PropertyLayoutBottomMargin)
1305                     value = 0;
1306                 break;
1307             default:
1308                 break;
1309             }
1310             setProperty(index, value);
1311             return true;
1312         }
1313         return false;
1314     } else if (isFakeProperty(index)) {
1315         const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1316         const bool result = p->reset(d->m_object);
1317         d->m_fakeProperties[index] = p->read(d->m_object);
1318         return result;
1319     } else if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
1320         if (QWidget *w = qobject_cast<QWidget*>(d->m_object)) {
1321             QWidget *widget = w;
1322             if (qdesigner_internal::Utils::isCentralWidget(d->m_fwb, widget) && d->m_fwb->parentWidget())
1323                 widget = d->m_fwb->parentWidget();
1324 
1325             if (widget != w && widget->parentWidget()) {
1326                 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1327                 widget->parentWidget()->adjustSize();
1328             }
1329             QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1330             widget->adjustSize();
1331             return true;
1332         }
1333     }
1334     // ### TODO: reset for fake properties.
1335 
1336     const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1337     return p->reset(d->m_object);
1338 }
1339 
isChanged(int index) const1340 bool QDesignerPropertySheet::isChanged(int index) const
1341 {
1342     if (d->invalidIndex(Q_FUNC_INFO, index))
1343         return false;
1344     if (isAdditionalProperty(index)) {
1345         if (isFakeLayoutProperty(index)) {
1346             QDesignerPropertySheetExtension *layoutPropertySheet;
1347             if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
1348                 const QString newPropName = d->transformLayoutPropertyName(index);
1349                 if (!newPropName.isEmpty()) {
1350                     const int newIndex = layoutPropertySheet->indexOf(newPropName);
1351                     if (newIndex != -1)
1352                         return layoutPropertySheet->isChanged(newIndex);
1353                     return false;
1354                 }
1355             }
1356         }
1357     }
1358     return d->m_info.value(index).changed;
1359 }
1360 
setChanged(int index,bool changed)1361 void QDesignerPropertySheet::setChanged(int index, bool changed)
1362 {
1363     if (d->invalidIndex(Q_FUNC_INFO, index))
1364         return;
1365     if (isAdditionalProperty(index)) {
1366         if (isFakeLayoutProperty(index)) {
1367             QDesignerPropertySheetExtension *layoutPropertySheet;
1368             if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
1369                 const QString newPropName = d->transformLayoutPropertyName(index);
1370                 if (!newPropName.isEmpty()) {
1371                     const int newIndex = layoutPropertySheet->indexOf(newPropName);
1372                     if (newIndex != -1)
1373                         layoutPropertySheet->setChanged(newIndex, changed);
1374                 }
1375             }
1376         }
1377     }
1378     if (d->isReloadableProperty(index)) {
1379         if (d->m_fwb) {
1380             if (changed)
1381                 d->m_fwb->addReloadableProperty(this, index);
1382             else
1383                 d->m_fwb->removeReloadableProperty(this, index);
1384         }
1385     }
1386     d->ensureInfo(index).changed = changed;
1387 }
1388 
isFakeLayoutProperty(int index) const1389 bool QDesignerPropertySheet::isFakeLayoutProperty(int index) const
1390 {
1391     if (!isAdditionalProperty(index))
1392         return false;
1393 
1394     switch (propertyType(index)) {
1395     case PropertyLayoutObjectName:
1396     case PropertyLayoutSizeConstraint:
1397         return true;
1398     case PropertyLayoutLeftMargin:
1399     case PropertyLayoutTopMargin:
1400     case PropertyLayoutRightMargin:
1401     case PropertyLayoutBottomMargin:
1402     case PropertyLayoutSpacing:
1403     case PropertyLayoutHorizontalSpacing:
1404     case PropertyLayoutVerticalSpacing:
1405     case PropertyLayoutFieldGrowthPolicy:
1406     case PropertyLayoutRowWrapPolicy:
1407     case PropertyLayoutLabelAlignment:
1408     case PropertyLayoutFormAlignment:
1409     case PropertyLayoutBoxStretch:
1410     case PropertyLayoutGridRowStretch:
1411     case PropertyLayoutGridColumnStretch:
1412     case PropertyLayoutGridRowMinimumHeight:
1413     case PropertyLayoutGridColumnMinimumWidth:
1414         return d->m_canHaveLayoutAttributes;
1415     default:
1416         break;
1417     }
1418     return false;
1419 }
1420 
1421 // Determine the "designable" state of a property. Properties, which have
1422 // a per-object boolean test function that returns false are shown in
1423 // disabled state ("checked" depending on "checkable", etc.)
1424 // Properties, which are generally not designable independent
1425 // of the object are not shown at all.
1426 enum DesignableState { PropertyIsDesignable,
1427                        // Object has a Designable test function that returns false.
1428                        PropertyOfObjectNotDesignable,
1429                        PropertyNotDesignable };
1430 
designableState(const QDesignerMetaPropertyInterface * p,const QObject * object)1431 static inline DesignableState designableState(const QDesignerMetaPropertyInterface *p, const QObject *object)
1432 {
1433     if (p->attributes(object) & QDesignerMetaPropertyInterface::DesignableAttribute)
1434         return PropertyIsDesignable;
1435     return (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute) ?
1436             PropertyOfObjectNotDesignable : PropertyNotDesignable;
1437 }
1438 
isVisible(int index) const1439 bool QDesignerPropertySheet::isVisible(int index) const
1440 {
1441     if (d->invalidIndex(Q_FUNC_INFO, index))
1442         return false;
1443 
1444     const PropertyType type = propertyType(index);
1445     if (isAdditionalProperty(index)) {
1446         if (isFakeLayoutProperty(index) && d->m_object->isWidgetType()) {
1447             const QLayout *currentLayout = d->layout();
1448             if (!currentLayout)
1449                 return false;
1450             const int visibleMask = qdesigner_internal::LayoutProperties::visibleProperties(currentLayout);
1451             switch (type) {
1452             case  PropertyLayoutSpacing:
1453                 return visibleMask & qdesigner_internal::LayoutProperties::SpacingProperty;
1454             case PropertyLayoutHorizontalSpacing:
1455             case PropertyLayoutVerticalSpacing:
1456                 return visibleMask & qdesigner_internal::LayoutProperties::HorizSpacingProperty;
1457             case PropertyLayoutFieldGrowthPolicy:
1458                 return visibleMask & qdesigner_internal::LayoutProperties::FieldGrowthPolicyProperty;
1459             case PropertyLayoutRowWrapPolicy:
1460                 return visibleMask & qdesigner_internal::LayoutProperties::RowWrapPolicyProperty;
1461             case PropertyLayoutLabelAlignment:
1462                 return visibleMask & qdesigner_internal::LayoutProperties::LabelAlignmentProperty;
1463             case PropertyLayoutFormAlignment:
1464                 return visibleMask & qdesigner_internal::LayoutProperties::FormAlignmentProperty;
1465             case PropertyLayoutBoxStretch:
1466                 return visibleMask & qdesigner_internal::LayoutProperties::BoxStretchProperty;
1467             case PropertyLayoutGridRowStretch:
1468                 return visibleMask & qdesigner_internal::LayoutProperties::GridRowStretchProperty;
1469             case PropertyLayoutGridColumnStretch:
1470                 return visibleMask & qdesigner_internal::LayoutProperties::GridColumnStretchProperty;
1471             case PropertyLayoutGridRowMinimumHeight:
1472                 return visibleMask & qdesigner_internal::LayoutProperties::GridRowMinimumHeightProperty;
1473             case PropertyLayoutGridColumnMinimumWidth:
1474                 return visibleMask & qdesigner_internal::LayoutProperties::GridColumnMinimumWidthProperty;
1475             default:
1476                 break;
1477             }
1478             return true;
1479         }
1480         return d->m_info.value(index).visible;
1481     }
1482 
1483     if (isFakeProperty(index)) {
1484         switch (type) {
1485         case PropertyWindowModality: // Hidden for child widgets
1486         case PropertyWindowOpacity:
1487             return d->m_info.value(index).visible;
1488         default:
1489             break;
1490         }
1491         return true;
1492     }
1493 
1494     const bool visible = d->m_info.value(index).visible;
1495     switch (type) {
1496     case PropertyWindowTitle:
1497     case PropertyWindowIcon:
1498     case PropertyWindowFilePath:
1499     case PropertyWindowOpacity:
1500     case PropertyWindowIconText:
1501     case PropertyWindowModified:
1502         return visible;
1503     default:
1504         if (visible)
1505             return true;
1506         break;
1507     }
1508 
1509     const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1510     if  (!(p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess))
1511          return false;
1512 
1513     // Enabled handling: Hide only statically not designable properties
1514     return designableState(p, d->m_object) != PropertyNotDesignable;
1515 }
1516 
setVisible(int index,bool visible)1517 void QDesignerPropertySheet::setVisible(int index, bool visible)
1518 {
1519     if (d->invalidIndex(Q_FUNC_INFO, index))
1520         return;
1521     d->ensureInfo(index).visible = visible;
1522 }
1523 
isEnabled(int index) const1524 bool QDesignerPropertySheet::isEnabled(int index) const
1525 {
1526     if (d->invalidIndex(Q_FUNC_INFO, index))
1527         return false;
1528     if (isAdditionalProperty(index))
1529         return true;
1530 
1531     if (isFakeProperty(index))
1532         return true;
1533 
1534     // Grey out geometry of laid-out widgets (including splitter)
1535     if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
1536         bool isManaged;
1537         const qdesigner_internal::LayoutInfo::Type lt = qdesigner_internal::LayoutInfo::laidoutWidgetType(d->m_core, qobject_cast<QWidget *>(d->m_object), &isManaged);
1538         return !isManaged || lt == qdesigner_internal::LayoutInfo::NoLayout;
1539     }
1540 
1541     if (d->m_info.value(index).visible == true) // Sun CC 5.5 oddity, wants true
1542         return true;
1543 
1544     // Enable setting of properties for statically non-designable properties
1545     // as this might be done via TaskMenu/Cursor::setProperty. Note that those
1546     // properties are not visible.
1547     const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
1548     return (p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess) &&
1549            designableState(p, d->m_object) != PropertyOfObjectNotDesignable;
1550 }
1551 
isAttribute(int index) const1552 bool QDesignerPropertySheet::isAttribute(int index) const
1553 {
1554     if (d->invalidIndex(Q_FUNC_INFO, index))
1555         return false;
1556     if (isAdditionalProperty(index))
1557         return d->m_info.value(index).attribute;
1558 
1559     if (isFakeProperty(index))
1560         return false;
1561 
1562     return d->m_info.value(index).attribute;
1563 }
1564 
setAttribute(int index,bool attribute)1565 void QDesignerPropertySheet::setAttribute(int index, bool attribute)
1566 {
1567     if (d->invalidIndex(Q_FUNC_INFO, index))
1568         return;
1569     d->ensureInfo(index).attribute = attribute;
1570 }
1571 
core() const1572 QDesignerFormEditorInterface *QDesignerPropertySheet::core() const
1573 {
1574     return d->m_core;
1575 }
1576 
internalDynamicPropertiesEnabled()1577 bool QDesignerPropertySheet::internalDynamicPropertiesEnabled()
1578 {
1579     return QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled;
1580 }
1581 
setInternalDynamicPropertiesEnabled(bool v)1582 void QDesignerPropertySheet::setInternalDynamicPropertiesEnabled(bool v)
1583 {
1584     QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = v;
1585 }
1586 
1587 // ---------- QDesignerAbstractPropertySheetFactory
1588 
1589 struct QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate {
1590     PropertySheetFactoryPrivate();
1591     const QString m_propertySheetId;
1592     const QString m_dynamicPropertySheetId;
1593 
1594     typedef QMap<QObject*, QObject*> ExtensionMap;
1595     ExtensionMap m_extensions;
1596     typedef QHash<QObject*, bool> ExtendedSet;
1597     ExtendedSet m_extended;
1598 };
1599 
PropertySheetFactoryPrivate()1600 QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate::PropertySheetFactoryPrivate() :
1601     m_propertySheetId(Q_TYPEID(QDesignerPropertySheetExtension)),
1602     m_dynamicPropertySheetId(Q_TYPEID(QDesignerDynamicPropertySheetExtension))
1603 {
1604 }
1605 
1606 // ---------- QDesignerAbstractPropertySheetFactory
1607 
1608 
QDesignerAbstractPropertySheetFactory(QExtensionManager * parent)1609 QDesignerAbstractPropertySheetFactory::QDesignerAbstractPropertySheetFactory(QExtensionManager *parent) :
1610     QExtensionFactory(parent),
1611     m_impl(new PropertySheetFactoryPrivate)
1612 {
1613 }
1614 
~QDesignerAbstractPropertySheetFactory()1615 QDesignerAbstractPropertySheetFactory::~QDesignerAbstractPropertySheetFactory()
1616 {
1617     delete m_impl;
1618 }
1619 
extension(QObject * object,const QString & iid) const1620 QObject *QDesignerAbstractPropertySheetFactory::extension(QObject *object, const QString &iid) const
1621 {
1622     typedef PropertySheetFactoryPrivate::ExtensionMap ExtensionMap;
1623     if (!object)
1624         return 0;
1625 
1626     if (iid != m_impl->m_propertySheetId && iid != m_impl->m_dynamicPropertySheetId)
1627         return 0;
1628 
1629     ExtensionMap::iterator it = m_impl->m_extensions.find(object);
1630     if (it == m_impl->m_extensions.end()) {
1631         if (QObject *ext = createPropertySheet(object, const_cast<QDesignerAbstractPropertySheetFactory*>(this))) {
1632             connect(ext, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
1633             it = m_impl->m_extensions.insert(object, ext);
1634         }
1635     }
1636 
1637     if (!m_impl->m_extended.contains(object)) {
1638         connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
1639         m_impl->m_extended.insert(object, true);
1640     }
1641 
1642     if (it == m_impl->m_extensions.end())
1643         return 0;
1644 
1645     return it.value();
1646 }
1647 
objectDestroyed(QObject * object)1648 void QDesignerAbstractPropertySheetFactory::objectDestroyed(QObject *object)
1649 {
1650     QMutableMapIterator<QObject*, QObject*> it(m_impl->m_extensions);
1651     while (it.hasNext()) {
1652         it.next();
1653 
1654         QObject *o = it.key();
1655         if (o == object || object == it.value()) {
1656             it.remove();
1657         }
1658     }
1659 
1660     m_impl->m_extended.remove(object);
1661 }
1662 
1663 QT_END_NAMESPACE
1664