source: trunk/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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