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 tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qtpropertybrowser.h"
41#include <QtCore/QSet>
42#include <QtCore/QMap>
43#include <QtGui/QIcon>
44
45#if defined(Q_CC_MSVC)
46# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
47#endif
48
49QT_BEGIN_NAMESPACE
50
51class QtPropertyPrivate
52{
53public:
54 QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {}
55 QtProperty *q_ptr;
56
57 QSet<QtProperty *> m_parentItems;
58 QList<QtProperty *> m_subItems;
59
60 QString m_valueToolTip;
61 QString m_descriptionToolTip;
62 QString m_statusTip;
63 QString m_whatsThis;
64 QString m_name;
65 bool m_enabled;
66 bool m_modified;
67
68 QtAbstractPropertyManager * const m_manager;
69};
70
71class QtAbstractPropertyManagerPrivate
72{
73 QtAbstractPropertyManager *q_ptr;
74 Q_DECLARE_PUBLIC(QtAbstractPropertyManager)
75public:
76 void propertyDestroyed(QtProperty *property);
77 void propertyChanged(QtProperty *property) const;
78 void propertyRemoved(QtProperty *property,
79 QtProperty *parentProperty) const;
80 void propertyInserted(QtProperty *property, QtProperty *parentProperty,
81 QtProperty *afterProperty) const;
82
83 QSet<QtProperty *> m_properties;
84};
85
86/*!
87 \class QtProperty
88 \internal
89 \inmodule QtDesigner
90 \since 4.4
91
92 \brief The QtProperty class encapsulates an instance of a property.
93
94 Properties are created by objects of QtAbstractPropertyManager
95 subclasses; a manager can create properties of a given type, and
96 is used in conjunction with the QtAbstractPropertyBrowser class. A
97 property is always owned by the manager that created it, which can
98 be retrieved using the propertyManager() function.
99
100 QtProperty contains the most common property attributes, and
101 provides functions for retrieving as well as setting their values:
102
103 \table
104 \header \li Getter \li Setter
105 \row
106 \li propertyName() \li setPropertyName()
107 \row
108 \li statusTip() \li setStatusTip()
109 \row
110 \li descriptionToolTip() \li setDescriptionToolTip()
111 \row
112 \li valueToolTip() \li setValueToolTip()
113 \row
114 \li toolTip() \deprecated in 5.6 \li setToolTip() \deprecated in 5.6
115 \row
116 \li whatsThis() \li setWhatsThis()
117 \row
118 \li isEnabled() \li setEnabled()
119 \row
120 \li isModified() \li setModified()
121 \row
122 \li valueText() \li Nop
123 \row
124 \li valueIcon() \li Nop
125 \endtable
126
127 It is also possible to nest properties: QtProperty provides the
128 addSubProperty(), insertSubProperty() and removeSubProperty() functions to
129 manipulate the set of subproperties. Use the subProperties()
130 function to retrieve a property's current set of subproperties.
131 Note that nested properties are not owned by the parent property,
132 i.e. each subproperty is owned by the manager that created it.
133
134 \sa QtAbstractPropertyManager, QtBrowserItem
135*/
136
137/*!
138 Creates a property with the given \a manager.
139
140 This constructor is only useful when creating a custom QtProperty
141 subclass (e.g. QtVariantProperty). To create a regular QtProperty
142 object, use the QtAbstractPropertyManager::addProperty()
143 function instead.
144
145 \sa QtAbstractPropertyManager::addProperty()
146*/
147QtProperty::QtProperty(QtAbstractPropertyManager *manager)
148 : d_ptr(new QtPropertyPrivate(manager))
149{
150 d_ptr->q_ptr = this;
151}
152
153/*!
154 Destroys this property.
155
156 Note that subproperties are detached but not destroyed, i.e. they
157 can still be used in another context.
158
159 \sa QtAbstractPropertyManager::clear()
160
161*/
162QtProperty::~QtProperty()
163{
164 for (QtProperty *property : qAsConst(t&: d_ptr->m_parentItems))
165 property->d_ptr->m_manager->d_ptr->propertyRemoved(property: this, parentProperty: property);
166
167 d_ptr->m_manager->d_ptr->propertyDestroyed(property: this);
168
169 for (QtProperty *property : qAsConst(t&: d_ptr->m_subItems))
170 property->d_ptr->m_parentItems.remove(value: this);
171
172 for (QtProperty *property : qAsConst(t&: d_ptr->m_parentItems))
173 property->d_ptr->m_subItems.removeAll(t: this);
174}
175
176/*!
177 Returns the set of subproperties.
178
179 Note that subproperties are not owned by \e this property, but by
180 the manager that created them.
181
182 \sa insertSubProperty(), removeSubProperty()
183*/
184QList<QtProperty *> QtProperty::subProperties() const
185{
186 return d_ptr->m_subItems;
187}
188
189/*!
190 Returns a pointer to the manager that owns this property.
191*/
192QtAbstractPropertyManager *QtProperty::propertyManager() const
193{
194 return d_ptr->m_manager;
195}
196
197/* Note: As of 17.7.2015 for Qt 5.6, the existing 'toolTip' of the Property
198 * Browser solution was split into valueToolTip() and descriptionToolTip()
199 * to be able to implement custom tool tip for QTBUG-45442. This could
200 * be back-ported to the solution. */
201
202/*!
203 Returns the property value's tool tip.
204
205 This is suitable for tool tips over the value (item delegate).
206
207 \since 5.6
208 \sa setValueToolTip()
209*/
210QString QtProperty::valueToolTip() const
211{
212 return d_ptr->m_valueToolTip;
213}
214
215/*!
216 Returns the property description's tool tip.
217
218 This is suitable for tool tips over the description (label).
219
220 \since 5.6
221 \sa setDescriptionToolTip()
222*/
223QString QtProperty::descriptionToolTip() const
224{
225 return d_ptr->m_descriptionToolTip;
226}
227
228/*!
229 Returns the property's status tip.
230
231 \sa setStatusTip()
232*/
233QString QtProperty::statusTip() const
234{
235 return d_ptr->m_statusTip;
236}
237
238/*!
239 Returns the property's "What's This" help text.
240
241 \sa setWhatsThis()
242*/
243QString QtProperty::whatsThis() const
244{
245 return d_ptr->m_whatsThis;
246}
247
248/*!
249 Returns the property's name.
250
251 \sa setPropertyName()
252*/
253QString QtProperty::propertyName() const
254{
255 return d_ptr->m_name;
256}
257
258/*!
259 Returns whether the property is enabled.
260
261 \sa setEnabled()
262*/
263bool QtProperty::isEnabled() const
264{
265 return d_ptr->m_enabled;
266}
267
268/*!
269 Returns whether the property is modified.
270
271 \sa setModified()
272*/
273bool QtProperty::isModified() const
274{
275 return d_ptr->m_modified;
276}
277
278/*!
279 Returns whether the property has a value.
280
281 \sa QtAbstractPropertyManager::hasValue()
282*/
283bool QtProperty::hasValue() const
284{
285 return d_ptr->m_manager->hasValue(property: this);
286}
287
288/*!
289 Returns an icon representing the current state of this property.
290
291 If the given property type can not generate such an icon, this
292 function returns an invalid icon.
293
294 \sa QtAbstractPropertyManager::valueIcon()
295*/
296QIcon QtProperty::valueIcon() const
297{
298 return d_ptr->m_manager->valueIcon(property: this);
299}
300
301/*!
302 Returns a string representing the current state of this property.
303
304 If the given property type can not generate such a string, this
305 function returns an empty string.
306
307 \sa QtAbstractPropertyManager::valueText()
308*/
309QString QtProperty::valueText() const
310{
311 return d_ptr->m_manager->valueText(property: this);
312}
313
314/*!
315 Sets the property value's tool tip to the given \a text.
316
317 \since 5.6
318 \sa valueToolTip()
319*/
320void QtProperty::setValueToolTip(const QString &text)
321{
322 if (d_ptr->m_valueToolTip == text)
323 return;
324
325 d_ptr->m_valueToolTip = text;
326 propertyChanged();
327}
328
329/*!
330 Sets the property description's tool tip to the given \a text.
331
332 \since 5.6
333 \sa descriptionToolTip()
334*/
335void QtProperty::setDescriptionToolTip(const QString &text)
336{
337 if (d_ptr->m_descriptionToolTip == text)
338 return;
339
340 d_ptr->m_descriptionToolTip = text;
341 propertyChanged();
342}
343
344/*!
345 Sets the property's status tip to the given \a text.
346
347 \sa statusTip()
348*/
349void QtProperty::setStatusTip(const QString &text)
350{
351 if (d_ptr->m_statusTip == text)
352 return;
353
354 d_ptr->m_statusTip = text;
355 propertyChanged();
356}
357
358/*!
359 Sets the property's "What's This" help text to the given \a text.
360
361 \sa whatsThis()
362*/
363void QtProperty::setWhatsThis(const QString &text)
364{
365 if (d_ptr->m_whatsThis == text)
366 return;
367
368 d_ptr->m_whatsThis = text;
369 propertyChanged();
370}
371
372/*!
373 \fn void QtProperty::setPropertyName(const QString &name)
374
375 Sets the property's name to the given \a name.
376
377 \sa propertyName()
378*/
379void QtProperty::setPropertyName(const QString &text)
380{
381 if (d_ptr->m_name == text)
382 return;
383
384 d_ptr->m_name = text;
385 propertyChanged();
386}
387
388/*!
389 Enables or disables the property according to the passed \a enable value.
390
391 \sa isEnabled()
392*/
393void QtProperty::setEnabled(bool enable)
394{
395 if (d_ptr->m_enabled == enable)
396 return;
397
398 d_ptr->m_enabled = enable;
399 propertyChanged();
400}
401
402/*!
403 Sets the property's modified state according to the passed \a modified value.
404
405 \sa isModified()
406*/
407void QtProperty::setModified(bool modified)
408{
409 if (d_ptr->m_modified == modified)
410 return;
411
412 d_ptr->m_modified = modified;
413 propertyChanged();
414}
415
416/*!
417 Appends the given \a property to this property's subproperties.
418
419 If the given \a property already is added, this function does
420 nothing.
421
422 \sa insertSubProperty(), removeSubProperty()
423*/
424void QtProperty::addSubProperty(QtProperty *property)
425{
426 QtProperty *after = 0;
427 if (d_ptr->m_subItems.count() > 0)
428 after = d_ptr->m_subItems.last();
429 insertSubProperty(property, afterProperty: after);
430}
431
432/*!
433 \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty)
434
435 Inserts the given \a property after the specified \a
436 precedingProperty into this property's list of subproperties. If
437 \a precedingProperty is 0, the specified \a property is inserted
438 at the beginning of the list.
439
440 If the given \a property already is inserted, this function does
441 nothing.
442
443 \sa addSubProperty(), removeSubProperty()
444*/
445void QtProperty::insertSubProperty(QtProperty *property,
446 QtProperty *afterProperty)
447{
448 if (!property)
449 return;
450
451 if (property == this)
452 return;
453
454 // traverse all children of item. if this item is a child of item then cannot add.
455 auto pendingList = property->subProperties();
456 QMap<QtProperty *, bool> visited;
457 while (!pendingList.isEmpty()) {
458 QtProperty *i = pendingList.first();
459 if (i == this)
460 return;
461 pendingList.removeFirst();
462 if (visited.contains(akey: i))
463 continue;
464 visited[i] = true;
465 pendingList += i->subProperties();
466 }
467
468 pendingList = subProperties();
469 int pos = 0;
470 int newPos = 0;
471 QtProperty *properAfterProperty = 0;
472 while (pos < pendingList.count()) {
473 QtProperty *i = pendingList.at(i: pos);
474 if (i == property)
475 return; // if item is already inserted in this item then cannot add.
476 if (i == afterProperty) {
477 newPos = pos + 1;
478 properAfterProperty = afterProperty;
479 }
480 pos++;
481 }
482
483 d_ptr->m_subItems.insert(i: newPos, t: property);
484 property->d_ptr->m_parentItems.insert(value: this);
485
486 d_ptr->m_manager->d_ptr->propertyInserted(property, parentProperty: this, afterProperty: properAfterProperty);
487}
488
489/*!
490 Removes the given \a property from the list of subproperties
491 without deleting it.
492
493 \sa addSubProperty(), insertSubProperty()
494*/
495void QtProperty::removeSubProperty(QtProperty *property)
496{
497 if (!property)
498 return;
499
500 d_ptr->m_manager->d_ptr->propertyRemoved(property, parentProperty: this);
501
502 auto pendingList = subProperties();
503 int pos = 0;
504 while (pos < pendingList.count()) {
505 if (pendingList.at(i: pos) == property) {
506 d_ptr->m_subItems.removeAt(i: pos);
507 property->d_ptr->m_parentItems.remove(value: this);
508
509 return;
510 }
511 pos++;
512 }
513}
514
515/*!
516 \internal
517*/
518void QtProperty::propertyChanged()
519{
520 d_ptr->m_manager->d_ptr->propertyChanged(property: this);
521}
522
523////////////////////////////////
524
525void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property)
526{
527 if (m_properties.contains(value: property)) {
528 emit q_ptr->propertyDestroyed(property);
529 q_ptr->uninitializeProperty(property);
530 m_properties.remove(value: property);
531 }
532}
533
534void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const
535{
536 emit q_ptr->propertyChanged(property);
537}
538
539void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property,
540 QtProperty *parentProperty) const
541{
542 emit q_ptr->propertyRemoved(property, parent: parentProperty);
543}
544
545void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property,
546 QtProperty *parentProperty, QtProperty *afterProperty) const
547{
548 emit q_ptr->propertyInserted(property, parent: parentProperty, after: afterProperty);
549}
550
551/*!
552 \class QtAbstractPropertyManager
553 \internal
554 \inmodule QtDesigner
555 \since 4.4
556
557 \brief The QtAbstractPropertyManager provides an interface for
558 property managers.
559
560 A manager can create and manage properties of a given type, and is
561 used in conjunction with the QtAbstractPropertyBrowser class.
562
563 When using a property browser widget, the properties are created
564 and managed by implementations of the QtAbstractPropertyManager
565 class. To ensure that the properties' values will be displayed
566 using suitable editing widgets, the managers are associated with
567 objects of QtAbstractEditorFactory subclasses. The property browser
568 will use these associations to determine which factories it should
569 use to create the preferred editing widgets.
570
571 The QtAbstractPropertyManager class provides common functionality
572 like creating a property using the addProperty() function, and
573 retrieving the properties created by the manager using the
574 properties() function. The class also provides signals that are
575 emitted when the manager's properties change: propertyInserted(),
576 propertyRemoved(), propertyChanged() and propertyDestroyed().
577
578 QtAbstractPropertyManager subclasses are supposed to provide their
579 own type specific API. Note that several ready-made
580 implementations are available:
581
582 \list
583 \li QtBoolPropertyManager
584 \li QtColorPropertyManager
585 \li QtDatePropertyManager
586 \li QtDateTimePropertyManager
587 \li QtDoublePropertyManager
588 \li QtEnumPropertyManager
589 \li QtFlagPropertyManager
590 \li QtFontPropertyManager
591 \li QtGroupPropertyManager
592 \li QtIntPropertyManager
593 \li QtPointPropertyManager
594 \li QtRectPropertyManager
595 \li QtSizePropertyManager
596 \li QtSizePolicyPropertyManager
597 \li QtStringPropertyManager
598 \li QtTimePropertyManager
599 \li QtVariantPropertyManager
600 \endlist
601
602 \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty
603*/
604
605/*!
606 \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty,
607 QtProperty *parentProperty, QtProperty *precedingProperty)
608
609 This signal is emitted when a new subproperty is inserted into an
610 existing property, passing pointers to the \a newProperty, \a
611 parentProperty and \a precedingProperty as parameters.
612
613 If \a precedingProperty is 0, the \a newProperty was inserted at
614 the beginning of the \a parentProperty's subproperties list.
615
616 Note that signal is emitted only if the \a parentProperty is created
617 by this manager.
618
619 \sa QtAbstractPropertyBrowser::itemInserted()
620*/
621
622/*!
623 \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property)
624
625 This signal is emitted whenever a property's data changes, passing
626 a pointer to the \a property as parameter.
627
628 Note that signal is only emitted for properties that are created by
629 this manager.
630
631 \sa QtAbstractPropertyBrowser::itemChanged()
632*/
633
634/*!
635 \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent)
636
637 This signal is emitted when a subproperty is removed, passing
638 pointers to the removed \a property and the \a parent property as
639 parameters.
640
641 Note that signal is emitted only when the \a parent property is
642 created by this manager.
643
644 \sa QtAbstractPropertyBrowser::itemRemoved()
645*/
646
647/*!
648 \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property)
649
650 This signal is emitted when the specified \a property is about to
651 be destroyed.
652
653 Note that signal is only emitted for properties that are created
654 by this manager.
655
656 \sa clear(), uninitializeProperty()
657*/
658
659/*!
660 \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current)
661
662 This signal is emitted when the current item changes. The current item is specified by \a current.
663
664 \sa QtAbstractPropertyBrowser::setCurrentItem()
665*/
666
667/*!
668 Creates an abstract property manager with the given \a parent.
669*/
670QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent)
671 : QObject(parent), d_ptr(new QtAbstractPropertyManagerPrivate)
672{
673 d_ptr->q_ptr = this;
674
675}
676
677/*!
678 Destroys the manager. All properties created by the manager are
679 destroyed.
680*/
681QtAbstractPropertyManager::~QtAbstractPropertyManager()
682{
683 clear();
684}
685
686/*!
687 Destroys all the properties that this manager has created.
688
689 \sa propertyDestroyed(), uninitializeProperty()
690*/
691void QtAbstractPropertyManager::clear() const
692{
693 while (!d_ptr->m_properties.isEmpty())
694 delete *d_ptr->m_properties.cbegin();
695}
696
697/*!
698 Returns the set of properties created by this manager.
699
700 \sa addProperty()
701*/
702QSet<QtProperty *> QtAbstractPropertyManager::properties() const
703{
704 return d_ptr->m_properties;
705}
706
707/*!
708 Returns whether the given \a property has a value.
709
710 The default implementation of this function returns true.
711
712 \sa QtProperty::hasValue()
713*/
714bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const
715{
716 Q_UNUSED(property);
717 return true;
718}
719
720/*!
721 Returns an icon representing the current state of the given \a
722 property.
723
724 The default implementation of this function returns an invalid
725 icon.
726
727 \sa QtProperty::valueIcon()
728*/
729QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const
730{
731 Q_UNUSED(property);
732 return QIcon();
733}
734
735/*!
736 Returns a string representing the current state of the given \a
737 property.
738
739 The default implementation of this function returns an empty
740 string.
741
742 \sa QtProperty::valueText()
743*/
744QString QtAbstractPropertyManager::valueText(const QtProperty *property) const
745{
746 Q_UNUSED(property);
747 return QString();
748}
749
750/*!
751 Creates a property with the given \a name which then is owned by this manager.
752
753 Internally, this function calls the createProperty() and
754 initializeProperty() functions.
755
756 \sa initializeProperty(), properties()
757*/
758QtProperty *QtAbstractPropertyManager::addProperty(const QString &name)
759{
760 QtProperty *property = createProperty();
761 if (property) {
762 property->setPropertyName(name);
763 d_ptr->m_properties.insert(value: property);
764 initializeProperty(property);
765 }
766 return property;
767}
768
769/*!
770 Creates a property.
771
772 The base implementation produce QtProperty instances; Reimplement
773 this function to make this manager produce objects of a QtProperty
774 subclass.
775
776 \sa addProperty(), initializeProperty()
777*/
778QtProperty *QtAbstractPropertyManager::createProperty()
779{
780 return new QtProperty(this);
781}
782
783/*!
784 \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0
785
786 This function is called whenever a new valid property pointer has
787 been created, passing the pointer as parameter.
788
789 The purpose is to let the manager know that the \a property has
790 been created so that it can provide additional attributes for the
791 new property, e.g. QtIntPropertyManager adds \l
792 {QtIntPropertyManager::value()}{value}, \l
793 {QtIntPropertyManager::minimum()}{minimum} and \l
794 {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager
795 subclass adds type specific attributes, this function is pure
796 virtual and must be reimplemented when deriving from the
797 QtAbstractPropertyManager class.
798
799 \sa addProperty(), createProperty()
800*/
801
802/*!
803 This function is called just before the specified \a property is destroyed.
804
805 The purpose is to let the property manager know that the \a
806 property is being destroyed so that it can remove the property's
807 additional attributes.
808
809 \sa clear(), propertyDestroyed()
810*/
811void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property)
812{
813 Q_UNUSED(property);
814}
815
816////////////////////////////////////
817
818/*!
819 \class QtAbstractEditorFactoryBase
820 \internal
821 \inmodule QtDesigner
822 \since 4.4
823
824 \brief The QtAbstractEditorFactoryBase provides an interface for
825 editor factories.
826
827 An editor factory is a class that is able to create an editing
828 widget of a specified type (e.g. line edits or comboboxes) for a
829 given QtProperty object, and it is used in conjunction with the
830 QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
831
832 When using a property browser widget, the properties are created
833 and managed by implementations of the QtAbstractPropertyManager
834 class. To ensure that the properties' values will be displayed
835 using suitable editing widgets, the managers are associated with
836 objects of QtAbstractEditorFactory subclasses. The property browser
837 will use these associations to determine which factories it should
838 use to create the preferred editing widgets.
839
840 Typically, an editor factory is created by subclassing the
841 QtAbstractEditorFactory template class which inherits
842 QtAbstractEditorFactoryBase. But note that several ready-made
843 implementations are available:
844
845 \list
846 \li QtCheckBoxFactory
847 \li QtDateEditFactory
848 \li QtDateTimeEditFactory
849 \li QtDoubleSpinBoxFactory
850 \li QtEnumEditorFactory
851 \li QtLineEditFactory
852 \li QtScrollBarFactory
853 \li QtSliderFactory
854 \li QtSpinBoxFactory
855 \li QtTimeEditFactory
856 \li QtVariantEditorFactory
857 \endlist
858
859 \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser
860*/
861
862/*!
863 \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property,
864 QWidget *parent) = 0
865
866 Creates an editing widget (with the given \a parent) for the given
867 \a property.
868
869 This function is reimplemented in QtAbstractEditorFactory template class
870 which also provides a pure virtual convenience overload of this
871 function enabling access to the property's manager.
872
873 \sa QtAbstractEditorFactory::createEditor()
874*/
875
876/*!
877 \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0)
878
879 Creates an abstract editor factory with the given \a parent.
880*/
881
882/*!
883 \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0
884
885 \internal
886
887 Detaches property manager from factory.
888 This method is reimplemented in QtAbstractEditorFactory template subclass.
889 You don't need to reimplement it in your subclasses. Instead implement more convenient
890 QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass.
891*/
892
893/*!
894 \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0
895
896 \internal
897
898 This method is called when property manager is being destroyed.
899 Basically it notifies factory not to produce editors for properties owned by \a manager.
900 You don't need to reimplement it in your subclass. This method is implemented in
901 QtAbstractEditorFactory template subclass.
902*/
903
904/*!
905 \class QtAbstractEditorFactory
906 \internal
907 \inmodule QtDesigner
908 \since 4.4
909
910 \brief The QtAbstractEditorFactory is the base template class for editor
911 factories.
912
913 An editor factory is a class that is able to create an editing
914 widget of a specified type (e.g. line edits or comboboxes) for a
915 given QtProperty object, and it is used in conjunction with the
916 QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
917
918 Note that the QtAbstractEditorFactory functions are using the
919 PropertyManager template argument class which can be any
920 QtAbstractPropertyManager subclass. For example:
921
922 \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 0
923
924 Note that QtSpinBoxFactory by definition creates editing widgets
925 \e only for properties created by QtIntPropertyManager.
926
927 When using a property browser widget, the properties are created
928 and managed by implementations of the QtAbstractPropertyManager
929 class. To ensure that the properties' values will be displayed
930 using suitable editing widgets, the managers are associated with
931 objects of QtAbstractEditorFactory subclasses. The property browser will
932 use these associations to determine which factories it should use
933 to create the preferred editing widgets.
934
935 A QtAbstractEditorFactory object is capable of producing editors for
936 several property managers at the same time. To create an
937 association between this factory and a given manager, use the
938 addPropertyManager() function. Use the removePropertyManager() function to make
939 this factory stop producing editors for a given property
940 manager. Use the propertyManagers() function to retrieve the set of
941 managers currently associated with this factory.
942
943 Several ready-made implementations of the QtAbstractEditorFactory class
944 are available:
945
946 \list
947 \li QtCheckBoxFactory
948 \li QtDateEditFactory
949 \li QtDateTimeEditFactory
950 \li QtDoubleSpinBoxFactory
951 \li QtEnumEditorFactory
952 \li QtLineEditFactory
953 \li QtScrollBarFactory
954 \li QtSliderFactory
955 \li QtSpinBoxFactory
956 \li QtTimeEditFactory
957 \li QtVariantEditorFactory
958 \endlist
959
960 When deriving from the QtAbstractEditorFactory class, several pure virtual
961 functions must be implemented: the connectPropertyManager() function is
962 used by the factory to connect to the given manager's signals, the
963 createEditor() function is supposed to create an editor for the
964 given property controlled by the given manager, and finally the
965 disconnectPropertyManager() function is used by the factory to disconnect
966 from the specified manager's signals.
967
968 \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager
969*/
970
971/*!
972 \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0)
973
974 Creates an editor factory with the given \a parent.
975
976 \sa addPropertyManager()
977*/
978
979/*!
980 \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent)
981
982 Creates an editing widget (with the given \a parent) for the given
983 \a property.
984*/
985
986/*!
987 \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager)
988
989 Adds the given \a manager to this factory's set of managers,
990 making this factory produce editing widgets for properties created
991 by the given manager.
992
993 The PropertyManager type is a template argument class, and represents the chosen
994 QtAbstractPropertyManager subclass.
995
996 \sa propertyManagers(), removePropertyManager()
997*/
998
999/*!
1000 \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager)
1001
1002 Removes the given \a manager from this factory's set of
1003 managers. The PropertyManager type is a template argument class, and may be
1004 any QtAbstractPropertyManager subclass.
1005
1006 \sa propertyManagers(), addPropertyManager()
1007*/
1008
1009/*!
1010 \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0
1011
1012 Connects this factory to the given \a manager's signals. The
1013 PropertyManager type is a template argument class, and represents
1014 the chosen QtAbstractPropertyManager subclass.
1015
1016 This function is used internally by the addPropertyManager() function, and
1017 makes it possible to update an editing widget when the associated
1018 property's data changes. This is typically done in custom slots
1019 responding to the signals emitted by the property's manager,
1020 e.g. QtIntPropertyManager::valueChanged() and
1021 QtIntPropertyManager::rangeChanged().
1022
1023 \sa propertyManagers(), disconnectPropertyManager()
1024*/
1025
1026/*!
1027 \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property,
1028 QWidget *parent) = 0
1029
1030 Creates an editing widget with the given \a parent for the
1031 specified \a property created by the given \a manager. The
1032 PropertyManager type is a template argument class, and represents
1033 the chosen QtAbstractPropertyManager subclass.
1034
1035 This function must be implemented in derived classes: It is
1036 recommended to store a pointer to the widget and map it to the
1037 given \a property, since the widget must be updated whenever the
1038 associated property's data changes. This is typically done in
1039 custom slots responding to the signals emitted by the property's
1040 manager, e.g. QtIntPropertyManager::valueChanged() and
1041 QtIntPropertyManager::rangeChanged().
1042
1043 \sa connectPropertyManager()
1044*/
1045
1046/*!
1047 \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0
1048
1049 Disconnects this factory from the given \a manager's signals. The
1050 PropertyManager type is a template argument class, and represents
1051 the chosen QtAbstractPropertyManager subclass.
1052
1053 This function is used internally by the removePropertyManager() function.
1054
1055 \sa propertyManagers(), connectPropertyManager()
1056*/
1057
1058/*!
1059 \fn QSet<PropertyManager *> QtAbstractEditorFactory::propertyManagers() const
1060
1061 Returns the factory's set of associated managers. The
1062 PropertyManager type is a template argument class, and represents
1063 the chosen QtAbstractPropertyManager subclass.
1064
1065 \sa addPropertyManager(), removePropertyManager()
1066*/
1067
1068/*!
1069 \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const
1070
1071 Returns the property manager for the given \a property, or 0 if
1072 the given \a property doesn't belong to any of this factory's
1073 registered managers.
1074
1075 The PropertyManager type is a template argument class, and represents the chosen
1076 QtAbstractPropertyManager subclass.
1077
1078 \sa propertyManagers()
1079*/
1080
1081/*!
1082 \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager)
1083
1084 \internal
1085*/
1086
1087////////////////////////////////////
1088class QtBrowserItemPrivate
1089{
1090public:
1091 QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
1092 : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {}
1093
1094 void addChild(QtBrowserItem *index, QtBrowserItem *after);
1095 void removeChild(QtBrowserItem *index);
1096
1097 QtAbstractPropertyBrowser * const m_browser;
1098 QtProperty *m_property;
1099 QtBrowserItem *m_parent;
1100
1101 QtBrowserItem *q_ptr;
1102
1103 QList<QtBrowserItem *> m_children;
1104
1105};
1106
1107void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after)
1108{
1109 if (m_children.contains(t: index))
1110 return;
1111 int idx = m_children.indexOf(t: after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0;
1112 m_children.insert(i: idx, t: index);
1113}
1114
1115void QtBrowserItemPrivate::removeChild(QtBrowserItem *index)
1116{
1117 m_children.removeAll(t: index);
1118}
1119
1120
1121/*!
1122 \class QtBrowserItem
1123 \internal
1124 \inmodule QtDesigner
1125 \since 4.4
1126
1127 \brief The QtBrowserItem class represents a property in
1128 a property browser instance.
1129
1130 Browser items are created whenever a QtProperty is inserted to the
1131 property browser. A QtBrowserItem uniquely identifies a
1132 browser's item. Thus, if the same QtProperty is inserted multiple
1133 times, each occurrence gets its own unique QtBrowserItem. The
1134 items are owned by QtAbstractPropertyBrowser and automatically
1135 deleted when they are removed from the browser.
1136
1137 You can traverse a browser's properties by calling parent() and
1138 children(). The property and the browser associated with an item
1139 are available as property() and browser().
1140
1141 \sa QtAbstractPropertyBrowser, QtProperty
1142*/
1143
1144/*!
1145 Returns the property which is accosiated with this item. Note that
1146 several items can be associated with the same property instance in
1147 the same property browser.
1148
1149 \sa QtAbstractPropertyBrowser::items()
1150*/
1151
1152QtProperty *QtBrowserItem::property() const
1153{
1154 return d_ptr->m_property;
1155}
1156
1157/*!
1158 Returns the parent item of \e this item. Returns 0 if \e this item
1159 is associated with top-level property in item's property browser.
1160
1161 \sa children()
1162*/
1163
1164QtBrowserItem *QtBrowserItem::parent() const
1165{
1166 return d_ptr->m_parent;
1167}
1168
1169/*!
1170 Returns the children items of \e this item. The properties
1171 reproduced from children items are always the same as
1172 reproduced from associated property' children, for example:
1173
1174 \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 1
1175
1176 The \e childrenItems list represents the same list as \e childrenProperties.
1177*/
1178
1179QList<QtBrowserItem *> QtBrowserItem::children() const
1180{
1181 return d_ptr->m_children;
1182}
1183
1184/*!
1185 Returns the property browser which owns \e this item.
1186*/
1187
1188QtAbstractPropertyBrowser *QtBrowserItem::browser() const
1189{
1190 return d_ptr->m_browser;
1191}
1192
1193QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
1194 : d_ptr(new QtBrowserItemPrivate(browser, property, parent))
1195{
1196 d_ptr->q_ptr = this;
1197}
1198
1199QtBrowserItem::~QtBrowserItem()
1200{
1201}
1202
1203
1204////////////////////////////////////
1205
1206typedef QMap<QtAbstractPropertyBrowser *, QMap<QtAbstractPropertyManager *,
1207 QtAbstractEditorFactoryBase *> > Map1;
1208typedef QMap<QtAbstractPropertyManager *, QMap<QtAbstractEditorFactoryBase *,
1209 QList<QtAbstractPropertyBrowser *> > > Map2;
1210Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory)
1211Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews)
1212
1213class QtAbstractPropertyBrowserPrivate
1214{
1215 QtAbstractPropertyBrowser *q_ptr;
1216 Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser)
1217public:
1218 QtAbstractPropertyBrowserPrivate();
1219
1220 void insertSubTree(QtProperty *property,
1221 QtProperty *parentProperty);
1222 void removeSubTree(QtProperty *property,
1223 QtProperty *parentProperty);
1224 void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty);
1225 void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty);
1226 QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex);
1227 void removeBrowserIndex(QtBrowserItem *index);
1228 void clearIndex(QtBrowserItem *index);
1229
1230 void slotPropertyInserted(QtProperty *property,
1231 QtProperty *parentProperty, QtProperty *afterProperty);
1232 void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty);
1233 void slotPropertyDestroyed(QtProperty *property);
1234 void slotPropertyDataChanged(QtProperty *property);
1235
1236 QList<QtProperty *> m_subItems;
1237 QMap<QtAbstractPropertyManager *, QList<QtProperty *> > m_managerToProperties;
1238 QMap<QtProperty *, QList<QtProperty *> > m_propertyToParents;
1239
1240 QMap<QtProperty *, QtBrowserItem *> m_topLevelPropertyToIndex;
1241 QList<QtBrowserItem *> m_topLevelIndexes;
1242 QMap<QtProperty *, QList<QtBrowserItem *> > m_propertyToIndexes;
1243
1244 QtBrowserItem *m_currentItem;
1245};
1246
1247QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() :
1248 m_currentItem(0)
1249{
1250}
1251
1252void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property,
1253 QtProperty *parentProperty)
1254{
1255 if (m_propertyToParents.contains(akey: property)) {
1256 // property was already inserted, so its manager is connected
1257 // and all its children are inserted and theirs managers are connected
1258 // we just register new parent (parent has to be new).
1259 m_propertyToParents[property].append(t: parentProperty);
1260 // don't need to update m_managerToProperties map since
1261 // m_managerToProperties[manager] already contains property.
1262 return;
1263 }
1264 QtAbstractPropertyManager *manager = property->propertyManager();
1265 if (m_managerToProperties[manager].isEmpty()) {
1266 // connect manager's signals
1267 q_ptr->connect(sender: manager, SIGNAL(propertyInserted(QtProperty *,
1268 QtProperty *, QtProperty *)),
1269 receiver: q_ptr, SLOT(slotPropertyInserted(QtProperty *,
1270 QtProperty *, QtProperty *)));
1271 q_ptr->connect(sender: manager, SIGNAL(propertyRemoved(QtProperty *,
1272 QtProperty *)),
1273 receiver: q_ptr, SLOT(slotPropertyRemoved(QtProperty*,QtProperty*)));
1274 q_ptr->connect(sender: manager, SIGNAL(propertyDestroyed(QtProperty*)),
1275 receiver: q_ptr, SLOT(slotPropertyDestroyed(QtProperty*)));
1276 q_ptr->connect(sender: manager, SIGNAL(propertyChanged(QtProperty*)),
1277 receiver: q_ptr, SLOT(slotPropertyDataChanged(QtProperty*)));
1278 }
1279 m_managerToProperties[manager].append(t: property);
1280 m_propertyToParents[property].append(t: parentProperty);
1281
1282 const auto subList = property->subProperties();
1283 for (QtProperty *subProperty : subList)
1284 insertSubTree(property: subProperty, parentProperty: property);
1285}
1286
1287void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property,
1288 QtProperty *parentProperty)
1289{
1290 if (!m_propertyToParents.contains(akey: property)) {
1291 // ASSERT
1292 return;
1293 }
1294
1295 m_propertyToParents[property].removeAll(t: parentProperty);
1296 if (!m_propertyToParents[property].isEmpty())
1297 return;
1298
1299 m_propertyToParents.remove(akey: property);
1300 QtAbstractPropertyManager *manager = property->propertyManager();
1301 m_managerToProperties[manager].removeAll(t: property);
1302 if (m_managerToProperties[manager].isEmpty()) {
1303 // disconnect manager's signals
1304 q_ptr->disconnect(sender: manager, SIGNAL(propertyInserted(QtProperty *,
1305 QtProperty *, QtProperty *)),
1306 receiver: q_ptr, SLOT(slotPropertyInserted(QtProperty *,
1307 QtProperty *, QtProperty *)));
1308 q_ptr->disconnect(sender: manager, SIGNAL(propertyRemoved(QtProperty *,
1309 QtProperty *)),
1310 receiver: q_ptr, SLOT(slotPropertyRemoved(QtProperty*,QtProperty*)));
1311 q_ptr->disconnect(sender: manager, SIGNAL(propertyDestroyed(QtProperty*)),
1312 receiver: q_ptr, SLOT(slotPropertyDestroyed(QtProperty*)));
1313 q_ptr->disconnect(sender: manager, SIGNAL(propertyChanged(QtProperty*)),
1314 receiver: q_ptr, SLOT(slotPropertyDataChanged(QtProperty*)));
1315
1316 m_managerToProperties.remove(akey: manager);
1317 }
1318
1319 const auto subList = property->subProperties();
1320 for (QtProperty *subProperty : subList)
1321 removeSubTree(property: subProperty, parentProperty: property);
1322}
1323
1324void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
1325{
1326 QMap<QtBrowserItem *, QtBrowserItem *> parentToAfter;
1327 if (afterProperty) {
1328 const auto it = m_propertyToIndexes.constFind(akey: afterProperty);
1329 if (it == m_propertyToIndexes.constEnd())
1330 return;
1331
1332 for (QtBrowserItem *idx : it.value()) {
1333 QtBrowserItem *parentIdx = idx->parent();
1334 if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
1335 parentToAfter[idx->parent()] = idx;
1336 }
1337 } else if (parentProperty) {
1338 const auto it = m_propertyToIndexes.find(akey: parentProperty);
1339 if (it == m_propertyToIndexes.constEnd())
1340 return;
1341
1342 for (QtBrowserItem *idx : it.value())
1343 parentToAfter[idx] = 0;
1344 } else {
1345 parentToAfter[0] = 0;
1346 }
1347
1348 const QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator pcend = parentToAfter.constEnd();
1349 for (QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it)
1350 createBrowserIndex(property, parentIndex: it.key(), afterIndex: it.value());
1351}
1352
1353QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property,
1354 QtBrowserItem *parentIndex, QtBrowserItem *afterIndex)
1355{
1356 QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex);
1357 if (parentIndex) {
1358 parentIndex->d_ptr->addChild(index: newIndex, after: afterIndex);
1359 } else {
1360 m_topLevelPropertyToIndex[property] = newIndex;
1361 m_topLevelIndexes.insert(i: m_topLevelIndexes.indexOf(t: afterIndex) + 1, t: newIndex);
1362 }
1363 m_propertyToIndexes[property].append(t: newIndex);
1364
1365 q_ptr->itemInserted(item: newIndex, afterItem: afterIndex);
1366
1367 const auto subItems = property->subProperties();
1368 QtBrowserItem *afterChild = 0;
1369 for (QtProperty *child : subItems)
1370 afterChild = createBrowserIndex(property: child, parentIndex: newIndex, afterIndex: afterChild);
1371 return newIndex;
1372}
1373
1374void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty)
1375{
1376 QList<QtBrowserItem *> toRemove;
1377 const auto it = m_propertyToIndexes.constFind(akey: property);
1378 if (it == m_propertyToIndexes.constEnd())
1379 return;
1380
1381 for (QtBrowserItem *idx : it.value()) {
1382 QtBrowserItem *parentIdx = idx->parent();
1383 if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
1384 toRemove.append(t: idx);
1385 }
1386
1387 for (QtBrowserItem *index : qAsConst(t&: toRemove))
1388 removeBrowserIndex(index);
1389}
1390
1391void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index)
1392{
1393 const auto children = index->children();
1394 for (int i = children.count(); i > 0; i--) {
1395 removeBrowserIndex(index: children.at(i: i - 1));
1396 }
1397
1398 q_ptr->itemRemoved(item: index);
1399
1400 if (index->parent()) {
1401 index->parent()->d_ptr->removeChild(index);
1402 } else {
1403 m_topLevelPropertyToIndex.remove(akey: index->property());
1404 m_topLevelIndexes.removeAll(t: index);
1405 }
1406
1407 QtProperty *property = index->property();
1408
1409 m_propertyToIndexes[property].removeAll(t: index);
1410 if (m_propertyToIndexes[property].isEmpty())
1411 m_propertyToIndexes.remove(akey: property);
1412
1413 delete index;
1414}
1415
1416void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index)
1417{
1418 const auto children = index->children();
1419 for (QtBrowserItem *item : children)
1420 clearIndex(index: item);
1421 delete index;
1422}
1423
1424void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property,
1425 QtProperty *parentProperty, QtProperty *afterProperty)
1426{
1427 if (!m_propertyToParents.contains(akey: parentProperty))
1428 return;
1429 createBrowserIndexes(property, parentProperty, afterProperty);
1430 insertSubTree(property, parentProperty);
1431 //q_ptr->propertyInserted(property, parentProperty, afterProperty);
1432}
1433
1434void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property,
1435 QtProperty *parentProperty)
1436{
1437 if (!m_propertyToParents.contains(akey: parentProperty))
1438 return;
1439 removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call
1440 //q_ptr->propertyRemoved(property, parentProperty);
1441 removeBrowserIndexes(property, parentProperty);
1442}
1443
1444void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property)
1445{
1446 if (!m_subItems.contains(t: property))
1447 return;
1448 q_ptr->removeProperty(property);
1449}
1450
1451void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property)
1452{
1453 if (!m_propertyToParents.contains(akey: property))
1454 return;
1455
1456 const auto it = m_propertyToIndexes.constFind(akey: property);
1457 if (it == m_propertyToIndexes.constEnd())
1458 return;
1459
1460 const auto indexes = it.value();
1461 for (QtBrowserItem *idx : indexes)
1462 q_ptr->itemChanged(item: idx);
1463 //q_ptr->propertyChanged(property);
1464}
1465
1466/*!
1467 \class QtAbstractPropertyBrowser
1468 \internal
1469 \inmodule QtDesigner
1470 \since 4.4
1471
1472 \brief QtAbstractPropertyBrowser provides a base class for
1473 implementing property browsers.
1474
1475 A property browser is a widget that enables the user to edit a
1476 given set of properties. Each property is represented by a label
1477 specifying the property's name, and an editing widget (e.g. a line
1478 edit or a combobox) holding its value. A property can have zero or
1479 more subproperties.
1480
1481 \image qtpropertybrowser.png
1482
1483 The top level properties can be retrieved using the
1484 properties() function. To traverse each property's
1485 subproperties, use the QtProperty::subProperties() function. In
1486 addition, the set of top level properties can be manipulated using
1487 the addProperty(), insertProperty() and removeProperty()
1488 functions. Note that the QtProperty class provides a corresponding
1489 set of functions making it possible to manipulate the set of
1490 subproperties as well.
1491
1492 To remove all the properties from the property browser widget, use
1493 the clear() function. This function will clear the editor, but it
1494 will not delete the properties since they can still be used in
1495 other editors.
1496
1497 The properties themselves are created and managed by
1498 implementations of the QtAbstractPropertyManager class. A manager
1499 can handle (i.e. create and manage) properties of a given type. In
1500 the property browser the managers are associated with
1501 implementations of the QtAbstractEditorFactory: A factory is a
1502 class able to create an editing widget of a specified type.
1503
1504 When using a property browser widget, managers must be created for
1505 each of the required property types before the properties
1506 themselves can be created. To ensure that the properties' values
1507 will be displayed using suitable editing widgets, the managers
1508 must be associated with objects of the preferred factory
1509 implementations using the setFactoryForManager() function. The
1510 property browser will use these associations to determine which
1511 factory it should use to create the preferred editing widget.
1512
1513 Note that a factory can be associated with many managers, but a
1514 manager can only be associated with one single factory within the
1515 context of a single property browser. The associations between
1516 managers and factories can at any time be removed using the
1517 unsetFactoryForManager() function.
1518
1519 Whenever the property data changes or a property is inserted or
1520 removed, the itemChanged(), itemInserted() or
1521 itemRemoved() functions are called, respectively. These
1522 functions must be reimplemented in derived classes in order to
1523 update the property browser widget. Be aware that some property
1524 instances can appear several times in an abstract tree
1525 structure. For example:
1526
1527 \table 100%
1528 \row
1529 \li
1530 \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 2
1531 \li \image qtpropertybrowser-duplicate.png
1532 \endtable
1533
1534 The addProperty() function returns a QtBrowserItem that uniquely
1535 identifies the created item.
1536
1537 To make a property editable in the property browser, the
1538 createEditor() function must be called to provide the
1539 property with a suitable editing widget.
1540
1541 Note that there are two ready-made property browser
1542 implementations:
1543
1544 \list
1545 \li QtGroupBoxPropertyBrowser
1546 \li QtTreePropertyBrowser
1547 \endlist
1548
1549 \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase
1550*/
1551
1552/*!
1553 \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager,
1554 QtAbstractEditorFactory<PropertyManager> *factory)
1555
1556 Connects the given \a manager to the given \a factory, ensuring
1557 that properties of the \a manager's type will be displayed with an
1558 editing widget suitable for their value.
1559
1560 For example:
1561
1562 \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 3
1563
1564 In this example the \c myInteger property's value is displayed
1565 with a QSpinBox widget, while the \c myDouble property's value is
1566 displayed with a QDoubleSpinBox widget.
1567
1568 Note that a factory can be associated with many managers, but a
1569 manager can only be associated with one single factory. If the
1570 given \a manager already is associated with another factory, the
1571 old association is broken before the new one established.
1572
1573 This function ensures that the given \a manager and the given \a
1574 factory are compatible, and it automatically calls the
1575 QtAbstractEditorFactory::addPropertyManager() function if necessary.
1576
1577 \sa unsetFactoryForManager()
1578*/
1579
1580/*!
1581 \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem,
1582 QtBrowserItem *precedingItem) = 0
1583
1584 This function is called to update the widget whenever a property
1585 is inserted or added to the property browser, passing pointers to
1586 the \a insertedItem of property and the specified
1587 \a precedingItem as parameters.
1588
1589 If \a precedingItem is 0, the \a insertedItem was put at
1590 the beginning of its parent item's list of subproperties. If
1591 the parent of \a insertedItem is 0, the \a insertedItem was added as a top
1592 level property of \e this property browser.
1593
1594 This function must be reimplemented in derived classes. Note that
1595 if the \a insertedItem's property has subproperties, this
1596 method will be called for those properties as soon as the current call is finished.
1597
1598 \sa insertProperty(), addProperty()
1599*/
1600
1601/*!
1602 \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0
1603
1604 This function is called to update the widget whenever a property
1605 is removed from the property browser, passing the pointer to the
1606 \a item of the property as parameters. The passed \a item is
1607 deleted just after this call is finished.
1608
1609 If the the parent of \a item is 0, the removed \a item was a
1610 top level property in this editor.
1611
1612 This function must be reimplemented in derived classes. Note that
1613 if the removed \a item's property has subproperties, this
1614 method will be called for those properties just before the current call is started.
1615
1616 \sa removeProperty()
1617*/
1618
1619/*!
1620 \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0
1621
1622 This function is called whenever a property's data changes,
1623 passing a pointer to the \a item of property as parameter.
1624
1625 This function must be reimplemented in derived classes in order to
1626 update the property browser widget whenever a property's name,
1627 tool tip, status tip, "what's this" text, value text or value icon
1628 changes.
1629
1630 Note that if the property browser contains several occurrences of
1631 the same property, this method will be called once for each
1632 occurrence (with a different item each time).
1633
1634 \sa QtProperty, items()
1635*/
1636
1637/*!
1638 Creates an abstract property browser with the given \a parent.
1639*/
1640QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent)
1641 : QWidget(parent), d_ptr(new QtAbstractPropertyBrowserPrivate)
1642{
1643 d_ptr->q_ptr = this;
1644
1645}
1646
1647/*!
1648 Destroys the property browser, and destroys all the items that were
1649 created by this property browser.
1650
1651 Note that the properties that were displayed in the editor are not
1652 deleted since they still can be used in other editors. Neither
1653 does the destructor delete the property managers and editor
1654 factories that were used by this property browser widget unless
1655 this widget was their parent.
1656
1657 \sa QtAbstractPropertyManager::~QtAbstractPropertyManager()
1658*/
1659QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser()
1660{
1661 const auto indexes = topLevelItems();
1662 for (QtBrowserItem *item : indexes)
1663 d_ptr->clearIndex(index: item);
1664}
1665
1666/*!
1667 Returns the property browser's list of top level properties.
1668
1669 To traverse the subproperties, use the QtProperty::subProperties()
1670 function.
1671
1672 \sa addProperty(), insertProperty(), removeProperty()
1673*/
1674QList<QtProperty *> QtAbstractPropertyBrowser::properties() const
1675{
1676 return d_ptr->m_subItems;
1677}
1678
1679/*!
1680 Returns the property browser's list of all items associated
1681 with the given \a property.
1682
1683 There is one item per instance of the property in the browser.
1684
1685 \sa topLevelItem()
1686*/
1687
1688QList<QtBrowserItem *> QtAbstractPropertyBrowser::items(QtProperty *property) const
1689{
1690 return d_ptr->m_propertyToIndexes.value(akey: property);
1691}
1692
1693/*!
1694 Returns the top-level items associated with the given \a property.
1695
1696 Returns 0 if \a property wasn't inserted into this property
1697 browser or isn't a top-level one.
1698
1699 \sa topLevelItems(), items()
1700*/
1701
1702QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const
1703{
1704 return d_ptr->m_topLevelPropertyToIndex.value(akey: property);
1705}
1706
1707/*!
1708 Returns the list of top-level items.
1709
1710 \sa topLevelItem()
1711*/
1712
1713QList<QtBrowserItem *> QtAbstractPropertyBrowser::topLevelItems() const
1714{
1715 return d_ptr->m_topLevelIndexes;
1716}
1717
1718/*!
1719 Removes all the properties from the editor, but does not delete
1720 them since they can still be used in other editors.
1721
1722 \sa removeProperty(), QtAbstractPropertyManager::clear()
1723*/
1724void QtAbstractPropertyBrowser::clear()
1725{
1726 const auto subList = properties();
1727 for (auto rit = subList.crbegin(), rend = subList.crend(); rit != rend; ++rit)
1728 removeProperty(property: *rit);
1729}
1730
1731/*!
1732 Appends the given \a property (and its subproperties) to the
1733 property browser's list of top level properties. Returns the item
1734 created by property browser which is associated with the \a property.
1735 In order to get all children items created by the property
1736 browser in this call, the returned item should be traversed.
1737
1738 If the specified \a property is already added, this function does
1739 nothing and returns 0.
1740
1741 \sa insertProperty(), QtProperty::addSubProperty(), properties()
1742*/
1743QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property)
1744{
1745 QtProperty *afterProperty = 0;
1746 if (d_ptr->m_subItems.count() > 0)
1747 afterProperty = d_ptr->m_subItems.last();
1748 return insertProperty(property, afterProperty);
1749}
1750
1751/*!
1752 \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
1753 QtProperty *afterProperty)
1754
1755 Inserts the given \a property (and its subproperties) after
1756 the specified \a afterProperty in the browser's list of top
1757 level properties. Returns item created by property browser which
1758 is associated with the \a property. In order to get all children items
1759 created by the property browser in this call returned item should be traversed.
1760
1761 If the specified \a afterProperty is 0, the given \a property is
1762 inserted at the beginning of the list. If \a property is
1763 already inserted, this function does nothing and returns 0.
1764
1765 \sa addProperty(), QtProperty::insertSubProperty(), properties()
1766*/
1767QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
1768 QtProperty *afterProperty)
1769{
1770 if (!property)
1771 return 0;
1772
1773 // if item is already inserted in this item then cannot add.
1774 auto pendingList = properties();
1775 int pos = 0;
1776 int newPos = 0;
1777 while (pos < pendingList.count()) {
1778 QtProperty *prop = pendingList.at(i: pos);
1779 if (prop == property)
1780 return 0;
1781 if (prop == afterProperty) {
1782 newPos = pos + 1;
1783 }
1784 pos++;
1785 }
1786 d_ptr->createBrowserIndexes(property, parentProperty: 0, afterProperty);
1787
1788 // traverse inserted subtree and connect to manager's signals
1789 d_ptr->insertSubTree(property, parentProperty: 0);
1790
1791 d_ptr->m_subItems.insert(i: newPos, t: property);
1792 //propertyInserted(property, 0, properAfterProperty);
1793 return topLevelItem(property);
1794}
1795
1796/*!
1797 Removes the specified \a property (and its subproperties) from the
1798 property browser's list of top level properties. All items
1799 that were associated with the given \a property and its children
1800 are deleted.
1801
1802 Note that the properties are \e not deleted since they can still
1803 be used in other editors.
1804
1805 \sa clear(), QtProperty::removeSubProperty(), properties()
1806*/
1807void QtAbstractPropertyBrowser::removeProperty(QtProperty *property)
1808{
1809 if (!property)
1810 return;
1811
1812 auto pendingList = properties();
1813 int pos = 0;
1814 while (pos < pendingList.count()) {
1815 if (pendingList.at(i: pos) == property) {
1816 d_ptr->m_subItems.removeAt(i: pos); //perhaps this two lines
1817 d_ptr->removeSubTree(property, parentProperty: 0); //should be moved down after propertyRemoved call.
1818 //propertyRemoved(property, 0);
1819
1820 d_ptr->removeBrowserIndexes(property, parentProperty: 0);
1821
1822 // when item is deleted, item will call removeItem for top level items,
1823 // and itemRemoved for nested items.
1824
1825 return;
1826 }
1827 pos++;
1828 }
1829}
1830
1831/*!
1832 Creates an editing widget (with the given \a parent) for the given
1833 \a property according to the previously established associations
1834 between property managers and editor factories.
1835
1836 If the property is created by a property manager which was not
1837 associated with any of the existing factories in \e this property
1838 editor, the function returns 0.
1839
1840 To make a property editable in the property browser, the
1841 createEditor() function must be called to provide the
1842 property with a suitable editing widget.
1843
1844 Reimplement this function to provide additional decoration for the
1845 editing widgets created by the installed factories.
1846
1847 \sa setFactoryForManager()
1848*/
1849QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property,
1850 QWidget *parent)
1851{
1852 QtAbstractEditorFactoryBase *factory = 0;
1853 QtAbstractPropertyManager *manager = property->propertyManager();
1854
1855 if (m_viewToManagerToFactory()->contains(akey: this) &&
1856 (*m_viewToManagerToFactory())[this].contains(akey: manager)) {
1857 factory = (*m_viewToManagerToFactory())[this][manager];
1858 }
1859
1860 if (!factory)
1861 return 0;
1862 QWidget *w = factory->createEditor(property, parent);
1863 // Since some editors can be QComboBoxes, and we changed their focus policy in Qt 5
1864 // to make them feel more native on Mac, we need to relax the focus policy to something
1865 // more permissive to keep the combo box from losing focus, allowing it to stay alive,
1866 // when the user clicks on it to show the popup.
1867 if (w)
1868 w->setFocusPolicy(Qt::WheelFocus);
1869 return w;
1870}
1871
1872bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager,
1873 QtAbstractEditorFactoryBase *abstractFactory)
1874{
1875 bool connectNeeded = false;
1876 if (!m_managerToFactoryToViews()->contains(akey: abstractManager) ||
1877 !(*m_managerToFactoryToViews())[abstractManager].contains(akey: abstractFactory)) {
1878 connectNeeded = true;
1879 } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory]
1880 .contains(t: this)) {
1881 return connectNeeded;
1882 }
1883
1884 if (m_viewToManagerToFactory()->contains(akey: this) &&
1885 (*m_viewToManagerToFactory())[this].contains(akey: abstractManager)) {
1886 unsetFactoryForManager(manager: abstractManager);
1887 }
1888
1889 (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(t: this);
1890 (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory;
1891
1892 return connectNeeded;
1893}
1894
1895/*!
1896 Removes the association between the given \a manager and the
1897 factory bound to it, automatically calling the
1898 QtAbstractEditorFactory::removePropertyManager() function if necessary.
1899
1900 \sa setFactoryForManager()
1901*/
1902void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager)
1903{
1904 if (!m_viewToManagerToFactory()->contains(akey: this) ||
1905 !(*m_viewToManagerToFactory())[this].contains(akey: manager)) {
1906 return;
1907 }
1908
1909 QtAbstractEditorFactoryBase *abstractFactory =
1910 (*m_viewToManagerToFactory())[this][manager];
1911 (*m_viewToManagerToFactory())[this].remove(akey: manager);
1912 if ((*m_viewToManagerToFactory())[this].isEmpty()) {
1913 (*m_viewToManagerToFactory()).remove(akey: this);
1914 }
1915
1916 (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(t: this);
1917 if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) {
1918 (*m_managerToFactoryToViews())[manager].remove(akey: abstractFactory);
1919 abstractFactory->breakConnection(manager);
1920 if ((*m_managerToFactoryToViews())[manager].isEmpty()) {
1921 (*m_managerToFactoryToViews()).remove(akey: manager);
1922 }
1923 }
1924}
1925
1926/*!
1927 Returns the current item in the property browser.
1928
1929 \sa setCurrentItem()
1930*/
1931QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const
1932{
1933 return d_ptr->m_currentItem;
1934}
1935
1936/*!
1937 Sets the current item in the property browser to \a item.
1938
1939 \sa currentItem(), currentItemChanged()
1940*/
1941void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item)
1942{
1943 QtBrowserItem *oldItem = d_ptr->m_currentItem;
1944 d_ptr->m_currentItem = item;
1945 if (oldItem != item)
1946 emit currentItemChanged(item);
1947}
1948
1949QT_END_NAMESPACE
1950
1951#include "moc_qtpropertybrowser.cpp"
1952

source code of qttools/src/shared/qtpropertybrowser/qtpropertybrowser.cpp