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