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