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