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