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